Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Oct 2008 16:00:23 +0000 (09:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Oct 2008 16:00:23 +0000 (09:00 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (39 commits)
  [SCSI] sd: fix compile failure with CONFIG_BLK_DEV_INTEGRITY=n
  libiscsi: fix locking in iscsi_eh_device_reset
  libiscsi: check reason why we are stopping iscsi session to determine error value
  [SCSI] iscsi_tcp: return a descriptive error value during connection errors
  [SCSI] libiscsi: rename host reset to target reset
  [SCSI] iscsi class: fix endpoint id handling
  [SCSI] libiscsi: Support drivers initiating session removal
  [SCSI] libiscsi: fix data corruption when target has to resend data-in packets
  [SCSI] sd: Switch kernel printing level for DIF messages
  [SCSI] sd: Correctly handle all combinations of DIF and DIX
  [SCSI] sd: Always print actual protection_type
  [SCSI] sd: Issue correct protection operation
  [SCSI] scsi_error: fix target reset handling
  [SCSI] lpfc 8.2.8 v2 : Add statistical reporting control and additional fc vendor events
  [SCSI] lpfc 8.2.8 v2 : Add sysfs control of target queue depth handling
  [SCSI] lpfc 8.2.8 v2 : Revert target busy in favor of transport disrupted
  [SCSI] scsi_dh_alua: remove REQ_NOMERGE
  [SCSI] lpfc 8.2.8 : update driver version to 8.2.8
  [SCSI] lpfc 8.2.8 : Add MSI-X support
  [SCSI] lpfc 8.2.8 : Update driver to use new Host byte error code DID_TRANSPORT_DISRUPTED
  ...

2670 files changed:
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-class-regulator
Documentation/ABI/testing/sysfs-profiling [new file with mode: 0644]
Documentation/DocBook/Makefile
Documentation/DocBook/procfs-guide.tmpl
Documentation/DocBook/procfs_example.c
Documentation/DocBook/videobook.tmpl [deleted file]
Documentation/HOWTO
Documentation/SAK.txt
Documentation/SubmitChecklist
Documentation/SubmittingDrivers
Documentation/SubmittingPatches
Documentation/blackfin/kgdb.txt [deleted file]
Documentation/block/data-integrity.txt
Documentation/cris/README
Documentation/development-process/1.Intro [new file with mode: 0644]
Documentation/development-process/2.Process [new file with mode: 0644]
Documentation/development-process/3.Early-stage [new file with mode: 0644]
Documentation/development-process/4.Coding [new file with mode: 0644]
Documentation/development-process/5.Posting [new file with mode: 0644]
Documentation/development-process/6.Followthrough [new file with mode: 0644]
Documentation/development-process/7.AdvancedTopics [new file with mode: 0644]
Documentation/development-process/8.Conclusion [new file with mode: 0644]
Documentation/dontdiff
Documentation/fb/intelfb.txt
Documentation/fb/uvesafb.txt
Documentation/fb/viafb.modes [new file with mode: 0644]
Documentation/fb/viafb.txt [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/autofs4-mount-control.txt [new file with mode: 0644]
Documentation/filesystems/ext3.txt
Documentation/filesystems/nfsroot.txt
Documentation/filesystems/ocfs2.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/ramfs-rootfs-initramfs.txt
Documentation/gpio.txt
Documentation/hpet.txt [deleted file]
Documentation/i2c/busses/i2c-viapro
Documentation/i2c/dev-interface
Documentation/i2c/smbus-protocol
Documentation/i2c/writing-clients
Documentation/ia64/kvm.txt
Documentation/kernel-parameters.txt
Documentation/kobject.txt
Documentation/laptops/disk-shock-protection.txt [new file with mode: 0644]
Documentation/networking/cs89x0.txt
Documentation/networking/phonet.txt
Documentation/networking/vortex.txt
Documentation/pcmcia/driver-changes.txt
Documentation/power/regulator/machine.txt
Documentation/power/regulator/regulator.txt
Documentation/power/s2ram.txt
Documentation/powerpc/00-INDEX
Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/fsl/dma.txt
Documentation/powerpc/dts-bindings/fsl/ssi.txt
Documentation/powerpc/ppc_htab.txt [deleted file]
Documentation/powerpc/smp.txt [deleted file]
Documentation/scsi/ChangeLog.megaraid
Documentation/spi/pxa2xx
Documentation/timers/00-INDEX [new file with mode: 0644]
Documentation/timers/hpet.txt [new file with mode: 0644]
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/gspca.txt
Documentation/video4linux/m5602.txt [new file with mode: 0644]
Documentation/video4linux/soc-camera.txt [new file with mode: 0644]
Documentation/w1/00-INDEX
Documentation/w1/masters/ds2490
Documentation/w1/slaves/00-INDEX [new file with mode: 0644]
Documentation/w1/slaves/w1_therm [new file with mode: 0644]
Documentation/w1/w1.generic
MAINTAINERS
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/include/asm/a.out.h
arch/alpha/include/asm/elf.h
arch/alpha/include/asm/statfs.h
arch/alpha/kernel/pci_iommu.c
arch/alpha/kernel/smp.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/configs/omap3_beagle_defconfig [new file with mode: 0644]
arch/arm/configs/omap_ldp_defconfig [new file with mode: 0644]
arch/arm/configs/overo_defconfig [new file with mode: 0644]
arch/arm/include/asm/elf.h
arch/arm/include/asm/statfs.h
arch/arm/kernel/dma.c
arch/arm/mach-integrator/cpu.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap1/clock.h
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap1/serial.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-ldp.c [new file with mode: 0644]
arch/arm/mach-omap2/board-omap3beagle.c [new file with mode: 0644]
arch/arm/mach-omap2/board-overo.c [new file with mode: 0644]
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock24xx.h
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.h
arch/arm/mach-omap2/clockdomain.c [new file with mode: 0644]
arch/arm/mach-omap2/clockdomains.h [new file with mode: 0644]
arch/arm/mach-omap2/cm-regbits-24xx.h
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/memory.c
arch/arm/mach-omap2/memory.h
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/powerdomain.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains.h [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains24xx.h [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains34xx.h [new file with mode: 0644]
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prm-regbits-24xx.h
arch/arm/mach-omap2/prm-regbits-34xx.h
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sleep.S [deleted file]
arch/arm/mach-omap2/sleep24xx.S [new file with mode: 0644]
arch/arm/mach-omap2/sram34xx.S [new file with mode: 0644]
arch/arm/mach-pxa/cm-x270.c
arch/arm/mach-pxa/cpufreq-pxa2xx.c
arch/arm/mach-pxa/cpufreq-pxa3xx.c
arch/arm/mach-pxa/include/mach/camera.h
arch/arm/mach-pxa/viper.c
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/include/mach/debug-macro.S
arch/arm/mach-s3c2410/include/mach/map.h
arch/arm/mach-s3c2410/include/mach/spi.h
arch/arm/mach-s3c2410/include/mach/uncompress.h
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-amlm5900.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-qt2410.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-tct_hammer.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-s3c2412/clock.c
arch/arm/mach-s3c2412/dma.c
arch/arm/mach-s3c2412/irq.c
arch/arm/mach-s3c2412/mach-jive.c
arch/arm/mach-s3c2412/mach-smdk2413.c
arch/arm/mach-s3c2412/mach-vstms.c
arch/arm/mach-s3c2412/pm.c
arch/arm/mach-s3c2412/s3c2412.c
arch/arm/mach-s3c2440/clock.c
arch/arm/mach-s3c2440/dma.c
arch/arm/mach-s3c2440/dsc.c
arch/arm/mach-s3c2440/irq.c
arch/arm/mach-s3c2440/mach-anubis.c
arch/arm/mach-s3c2440/mach-at2440evb.c
arch/arm/mach-s3c2440/mach-nexcoder.c
arch/arm/mach-s3c2440/mach-osiris.c
arch/arm/mach-s3c2440/mach-rx3715.c
arch/arm/mach-s3c2440/mach-smdk2440.c
arch/arm/mach-s3c2440/s3c2440.c
arch/arm/mach-s3c2442/clock.c
arch/arm/mach-s3c2442/s3c2442.c
arch/arm/mach-s3c2443/clock.c
arch/arm/mach-s3c2443/dma.c
arch/arm/mach-s3c2443/irq.c
arch/arm/mach-s3c2443/mach-smdk2443.c
arch/arm/mach-s3c2443/s3c2443.c
arch/arm/mach-sa1100/cpu-sa1100.c
arch/arm/mm/Kconfig
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/common.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/mach/board-2430sdp.h
arch/arm/plat-omap/include/mach/board-apollon.h
arch/arm/plat-omap/include/mach/board-h4.h
arch/arm/plat-omap/include/mach/board-ldp.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/board-omap3beagle.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/board-overo.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/board.h
arch/arm/plat-omap/include/mach/clock.h
arch/arm/plat-omap/include/mach/clockdomain.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/common.h
arch/arm/plat-omap/include/mach/control.h
arch/arm/plat-omap/include/mach/cpu.h
arch/arm/plat-omap/include/mach/debug-macro.S
arch/arm/plat-omap/include/mach/entry-macro.S
arch/arm/plat-omap/include/mach/fpga.h
arch/arm/plat-omap/include/mach/gpio.h
arch/arm/plat-omap/include/mach/gpmc.h
arch/arm/plat-omap/include/mach/hardware.h
arch/arm/plat-omap/include/mach/io.h
arch/arm/plat-omap/include/mach/irqs.h
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/include/mach/memory.h
arch/arm/plat-omap/include/mach/mux.h
arch/arm/plat-omap/include/mach/omap1510.h
arch/arm/plat-omap/include/mach/omap16xx.h
arch/arm/plat-omap/include/mach/omap24xx.h
arch/arm/plat-omap/include/mach/omapfb.h
arch/arm/plat-omap/include/mach/pm.h
arch/arm/plat-omap/include/mach/powerdomain.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/sdrc.h
arch/arm/plat-omap/include/mach/serial.h
arch/arm/plat-omap/include/mach/sram.h
arch/arm/plat-omap/include/mach/system.h
arch/arm/plat-omap/io.c [new file with mode: 0644]
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/sram.c
arch/arm/plat-s3c/Makefile [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/debug-macro.S [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/map.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/regs-adc.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/regs-serial.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/regs-timer.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/uncompress.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/clock.c
arch/arm/plat-s3c24xx/common-smdk.c
arch/arm/plat-s3c24xx/cpu.c
arch/arm/plat-s3c24xx/devs.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-s3c24xx/include/plat/clock.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/common-smdk.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/cpu.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/devs.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/dma.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/irq.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/pm.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2400.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2410.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2412.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2440.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2442.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/include/plat/s3c2443.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/irq.c
arch/arm/plat-s3c24xx/pm-simtec.c
arch/arm/plat-s3c24xx/pm.c
arch/arm/plat-s3c24xx/pwm-clock.c
arch/arm/plat-s3c24xx/pwm.c
arch/arm/plat-s3c24xx/s3c244x-clock.c
arch/arm/plat-s3c24xx/s3c244x-irq.c
arch/arm/plat-s3c24xx/s3c244x.c
arch/arm/plat-s3c24xx/sleep.S
arch/arm/plat-s3c24xx/time.c
arch/avr32/include/asm/a.out.h [deleted file]
arch/avr32/include/asm/elf.h
arch/avr32/mach-at32ap/cpufreq.c
arch/blackfin/Kconfig
arch/blackfin/Kconfig.debug
arch/blackfin/Makefile
arch/blackfin/configs/BF526-EZBRD_defconfig [new file with mode: 0644]
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/configs/CM-BF533_defconfig
arch/blackfin/configs/CM-BF537E_defconfig
arch/blackfin/configs/CM-BF537U_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/blackfin/configs/H8606_defconfig
arch/blackfin/include/asm/a.out.h [deleted file]
arch/blackfin/include/asm/bfin-global.h
arch/blackfin/include/asm/bfrom.h [new file with mode: 0644]
arch/blackfin/include/asm/cacheflush.h
arch/blackfin/include/asm/cplb.h
arch/blackfin/include/asm/cplbinit.h
arch/blackfin/include/asm/cpumask.h [deleted file]
arch/blackfin/include/asm/dma-mapping.h
arch/blackfin/include/asm/elf.h
arch/blackfin/include/asm/io.h
arch/blackfin/include/asm/kgdb.h
arch/blackfin/include/asm/mmu_context.h
arch/blackfin/include/asm/processor.h
arch/blackfin/include/asm/ptrace.h
arch/blackfin/include/asm/timex.h
arch/blackfin/include/asm/traps.h
arch/blackfin/kernel/asm-offsets.c
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-mpu/cplbinit.c
arch/blackfin/kernel/cplb-mpu/cplbmgr.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/early_printk.c
arch/blackfin/kernel/kgdb.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/reboot.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/traps.c
arch/blackfin/mach-bf527/boards/Kconfig
arch/blackfin/mach-bf527/boards/Makefile
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c [new file with mode: 0644]
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/head.S
arch/blackfin/mach-bf527/include/mach/anomaly.h
arch/blackfin/mach-bf527/include/mach/bf527.h
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
arch/blackfin/mach-bf527/include/mach/portmux.h
arch/blackfin/mach-bf533/boards/H8606.c
arch/blackfin/mach-bf533/head.S
arch/blackfin/mach-bf533/include/mach/anomaly.h
arch/blackfin/mach-bf533/include/mach/bf533.h
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/head.S
arch/blackfin/mach-bf537/include/mach/anomaly.h
arch/blackfin/mach-bf537/include/mach/bf537.h
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/head.S
arch/blackfin/mach-bf548/include/mach/anomaly.h
arch/blackfin/mach-bf548/include/mach/bf548.h
arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf548/include/mach/mem_map.h
arch/blackfin/mach-bf561/head.S
arch/blackfin/mach-bf561/include/mach/anomaly.h
arch/blackfin/mach-bf561/include/mach/bf561.h
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf561/include/mach/mem_map.h
arch/blackfin/mach-common/cache.S
arch/blackfin/mach-common/cpufreq.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/head.S
arch/blackfin/mach-common/interrupt.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mm/Makefile
arch/blackfin/mm/blackfin_sram.c [deleted file]
arch/blackfin/mm/isram-driver.c [new file with mode: 0644]
arch/blackfin/mm/sram-alloc.c [new file with mode: 0644]
arch/cris/arch-v10/boot/tools/build.c
arch/cris/arch-v32/mach-a3/cpufreq.c
arch/cris/arch-v32/mach-fs/cpufreq.c
arch/frv/kernel/pm.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/frv/mb93090-mb00/pci-dma.c
arch/frv/mb93090-mb00/pci-frv.c
arch/frv/mb93090-mb00/pci-frv.h
arch/frv/mb93090-mb00/pci-vdk.c
arch/frv/mm/init.c
arch/h8300/Kconfig
arch/h8300/Kconfig.cpu
arch/h8300/include/asm/a.out.h [deleted file]
arch/h8300/include/asm/bug.h
arch/h8300/include/asm/elf.h
arch/h8300/include/asm/io.h
arch/h8300/include/asm/md.h
arch/h8300/include/asm/system.h
arch/h8300/kernel/Makefile
arch/h8300/kernel/module.c
arch/h8300/kernel/process.c
arch/h8300/kernel/time.c
arch/h8300/kernel/timer/Makefile [new file with mode: 0644]
arch/h8300/kernel/timer/itu.c [new file with mode: 0644]
arch/h8300/kernel/timer/timer16.c [new file with mode: 0644]
arch/h8300/kernel/timer/timer8.c [new file with mode: 0644]
arch/h8300/kernel/timer/tpu.c [new file with mode: 0644]
arch/h8300/kernel/traps.c
arch/h8300/mm/fault.c
arch/h8300/platform/h8300h/aki3068net/Makefile
arch/h8300/platform/h8300h/aki3068net/timer.c [deleted file]
arch/h8300/platform/h8300h/generic/Makefile
arch/h8300/platform/h8300h/generic/timer.c [deleted file]
arch/h8300/platform/h8300h/h8max/Makefile
arch/h8300/platform/h8300h/h8max/timer.c [deleted file]
arch/h8300/platform/h8s/edosk2674/Makefile
arch/h8300/platform/h8s/edosk2674/timer.c [deleted file]
arch/h8300/platform/h8s/generic/Makefile
arch/h8300/platform/h8s/generic/timer.c [deleted file]
arch/ia64/Kconfig
arch/ia64/ia32/binfmt_elf32.c
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/ia32priv.h
arch/ia64/ia32/sys_ia32.c
arch/ia64/include/asm/a.out.h [deleted file]
arch/ia64/include/asm/elf.h
arch/ia64/include/asm/kvm_host.h
arch/ia64/include/asm/statfs.h
arch/ia64/kvm/Kconfig
arch/ia64/kvm/Makefile
arch/ia64/kvm/irq.h [new file with mode: 0644]
arch/ia64/kvm/kvm-ia64.c
arch/ia64/kvm/kvm_minstate.h
arch/ia64/kvm/optvfault.S
arch/ia64/kvm/process.c
arch/ia64/kvm/vcpu.h
arch/ia64/kvm/vmm_ivt.S
arch/ia64/kvm/vtlb.c
arch/ia64/mm/init.c
arch/m32r/Kconfig
arch/m32r/kernel/process.c
arch/m32r/mm/discontig.c
arch/m68k/Kconfig
arch/m68k/amiga/config.c
arch/m68k/atari/Makefile
arch/m68k/atari/ataints.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/config.c
arch/m68k/atari/hades-pci.c [deleted file]
arch/m68k/atari/time.c
arch/m68k/bvme6000/config.c
arch/m68k/bvme6000/rtc.c
arch/m68k/kernel/Makefile
arch/m68k/kernel/bios32.c [deleted file]
arch/m68k/kernel/dma.c
arch/m68k/kernel/ints.c
arch/m68k/kernel/process.c
arch/m68k/kernel/traps.c
arch/m68k/kernel/vmlinux-std.lds
arch/m68k/mm/kmap.c
arch/m68k/mvme16x/rtc.c
arch/m68k/q40/config.c
arch/m68k/sun3x/time.c
arch/m68knommu/Kconfig
arch/m68knommu/include/asm/a.out.h [deleted file]
arch/m68knommu/include/asm/elf.h
arch/m68knommu/kernel/process.c
arch/m68knommu/kernel/traps.c
arch/mips/Kconfig
arch/mips/bcm47xx/gpio.c
arch/mips/bcm47xx/setup.c
arch/mips/bcm47xx/wgt634u.c
arch/mips/emma2rh/common/irq.c
arch/mips/emma2rh/common/prom.c
arch/mips/emma2rh/markeins/platform.c
arch/mips/include/asm/a.out.h [deleted file]
arch/mips/include/asm/cevt-r4k.h [new file with mode: 0644]
arch/mips/include/asm/elf.h
arch/mips/include/asm/mach-bcm47xx/gpio.h
arch/mips/include/asm/mach-bcm47xx/war.h
arch/mips/include/asm/mach-generic/ide.h
arch/mips/include/asm/mach-ip22/ds1286.h [deleted file]
arch/mips/include/asm/mach-ip28/ds1286.h [deleted file]
arch/mips/include/asm/spinlock.h
arch/mips/kernel/linux32.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/syscall.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/lasat/sysctl.c
arch/mips/pci/fixup-emma2rh.c
arch/mips/pci/ops-pnx8550.c
arch/mips/pci/pci-emma2rh.c
arch/mips/pci/pci.c
arch/mips/rb532/time.c
arch/mips/sgi-ip22/ip22-platform.c
arch/mips/sgi-ip22/ip22-setup.c
arch/mips/sgi-ip22/ip22-time.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sgi-ip32/ip32-platform.c
arch/mips/sgi-ip32/ip32-setup.c
arch/mips/sibyte/common/sb_tbprof.c
arch/mn10300/Kconfig
arch/parisc/Kconfig
arch/parisc/kernel/binfmt_elf32.c
arch/parisc/kernel/sys_parisc32.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/Makefile
arch/powerpc/boot/addnote.c
arch/powerpc/boot/dtc-src/Makefile.dtc
arch/powerpc/boot/dtc-src/checks.c
arch/powerpc/boot/dtc-src/data.c
arch/powerpc/boot/dtc-src/dtc-lexer.l
arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped
arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped
arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped
arch/powerpc/boot/dtc-src/dtc-parser.y
arch/powerpc/boot/dtc-src/dtc.c
arch/powerpc/boot/dtc-src/dtc.h
arch/powerpc/boot/dtc-src/flattree.c
arch/powerpc/boot/dtc-src/fstree.c
arch/powerpc/boot/dtc-src/libfdt_env.h [new file with mode: 0644]
arch/powerpc/boot/dtc-src/livetree.c
arch/powerpc/boot/dtc-src/srcpos.c
arch/powerpc/boot/dtc-src/srcpos.h
arch/powerpc/boot/dtc-src/treesource.c
arch/powerpc/boot/dtc-src/version_gen.h
arch/powerpc/boot/dts/arches.dts [new file with mode: 0644]
arch/powerpc/boot/dts/asp834x-redboot.dts
arch/powerpc/boot/dts/gef_sbc610.dts [new file with mode: 0644]
arch/powerpc/boot/dts/glacier.dts
arch/powerpc/boot/dts/mgcoge.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mgsuvd.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc5121ads.dts
arch/powerpc/boot/dts/mpc8313erdb.dts
arch/powerpc/boot/dts/mpc8315erdb.dts
arch/powerpc/boot/dts/mpc832x_mds.dts
arch/powerpc/boot/dts/mpc832x_rdb.dts
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/mpc8349emitxgp.dts
arch/powerpc/boot/dts/mpc834x_mds.dts
arch/powerpc/boot/dts/mpc836x_mds.dts
arch/powerpc/boot/dts/mpc836x_rdk.dts
arch/powerpc/boot/dts/mpc8377_mds.dts
arch/powerpc/boot/dts/mpc8377_rdb.dts
arch/powerpc/boot/dts/mpc8378_mds.dts
arch/powerpc/boot/dts/mpc8378_rdb.dts
arch/powerpc/boot/dts/mpc8379_mds.dts
arch/powerpc/boot/dts/mpc8379_rdb.dts
arch/powerpc/boot/dts/mpc8536ds.dts
arch/powerpc/boot/dts/mpc8610_hpcd.dts
arch/powerpc/boot/dts/sbc8349.dts
arch/powerpc/boot/dts/sequoia.dts
arch/powerpc/boot/dts/yosemite.dts
arch/powerpc/boot/elf_util.c
arch/powerpc/boot/libfdt/Makefile.libfdt
arch/powerpc/boot/libfdt/fdt.c
arch/powerpc/boot/libfdt/fdt_ro.c
arch/powerpc/boot/libfdt/fdt_rw.c
arch/powerpc/boot/libfdt/fdt_strerror.c
arch/powerpc/boot/libfdt/fdt_sw.c
arch/powerpc/boot/libfdt/fdt_wip.c
arch/powerpc/boot/libfdt/libfdt.h
arch/powerpc/boot/libfdt/libfdt_internal.h
arch/powerpc/boot/libfdt_env.h
arch/powerpc/boot/wrapper
arch/powerpc/configs/44x/arches_defconfig [new file with mode: 0644]
arch/powerpc/configs/83xx/asp8347_defconfig
arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
arch/powerpc/configs/83xx/mpc832x_mds_defconfig
arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
arch/powerpc/configs/83xx/mpc834x_itx_defconfig
arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
arch/powerpc/configs/83xx/mpc834x_mds_defconfig
arch/powerpc/configs/83xx/mpc836x_mds_defconfig
arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
arch/powerpc/configs/83xx/mpc837x_mds_defconfig
arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
arch/powerpc/configs/83xx/sbc834x_defconfig
arch/powerpc/configs/86xx/gef_sbc610_defconfig [new file with mode: 0644]
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig [new file with mode: 0644]
arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig [new file with mode: 0644]
arch/powerpc/configs/86xx/sbc8641d_defconfig [new file with mode: 0644]
arch/powerpc/configs/ep8248e_defconfig
arch/powerpc/configs/mgcoge_defconfig [new file with mode: 0644]
arch/powerpc/configs/mgsuvd_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc8272_ads_defconfig
arch/powerpc/configs/mpc83xx_defconfig
arch/powerpc/configs/mpc8610_hpcd_defconfig [deleted file]
arch/powerpc/configs/mpc8641_hpcn_defconfig [deleted file]
arch/powerpc/configs/mpc86xx_defconfig [new file with mode: 0644]
arch/powerpc/configs/pq2fads_defconfig
arch/powerpc/configs/sbc8641d_defconfig [deleted file]
arch/powerpc/include/asm/a.out.h [deleted file]
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/dcr-regs.h
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/exception.h
arch/powerpc/include/asm/fsl_lbc.h
arch/powerpc/include/asm/highmem.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mman.h
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/msi_bitmap.h [new file with mode: 0644]
arch/powerpc/include/asm/of_device.h
arch/powerpc/include/asm/of_platform.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/page_32.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/pgtable-ppc32.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/sfp-machine.h [new file with mode: 0644]
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/statfs.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/tlbflush.h
arch/powerpc/include/asm/types.h
arch/powerpc/kernel/.gitignore [new file with mode: 0644]
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/btext.c
arch/powerpc/kernel/cpu_setup_ppc970.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/dma-iommu.c [new file with mode: 0644]
arch/powerpc/kernel/dma.c [new file with mode: 0644]
arch/powerpc/kernel/dma_64.c [deleted file]
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/of_device.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/reloc_64.S [new file with mode: 0644]
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/softemu8xx.c
arch/powerpc/kernel/swsusp_asm64.S
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vio.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/kvm/44x_tlb.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/booke_guest.c
arch/powerpc/kvm/booke_interrupts.S
arch/powerpc/kvm/emulate.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/lib/copypage_64.S
arch/powerpc/lib/dma-noncoherent.c
arch/powerpc/math-emu/Makefile
arch/powerpc/math-emu/double.h [deleted file]
arch/powerpc/math-emu/fadd.c
arch/powerpc/math-emu/fadds.c
arch/powerpc/math-emu/fcmpo.c
arch/powerpc/math-emu/fcmpu.c
arch/powerpc/math-emu/fctiw.c
arch/powerpc/math-emu/fctiwz.c
arch/powerpc/math-emu/fdiv.c
arch/powerpc/math-emu/fdivs.c
arch/powerpc/math-emu/fmadd.c
arch/powerpc/math-emu/fmadds.c
arch/powerpc/math-emu/fmsub.c
arch/powerpc/math-emu/fmsubs.c
arch/powerpc/math-emu/fmul.c
arch/powerpc/math-emu/fmuls.c
arch/powerpc/math-emu/fnmadd.c
arch/powerpc/math-emu/fnmadds.c
arch/powerpc/math-emu/fnmsub.c
arch/powerpc/math-emu/fnmsubs.c
arch/powerpc/math-emu/frsp.c
arch/powerpc/math-emu/fsel.c
arch/powerpc/math-emu/fsqrt.c
arch/powerpc/math-emu/fsqrts.c
arch/powerpc/math-emu/fsub.c
arch/powerpc/math-emu/fsubs.c
arch/powerpc/math-emu/lfd.c
arch/powerpc/math-emu/lfs.c
arch/powerpc/math-emu/math.c
arch/powerpc/math-emu/mcrfs.c
arch/powerpc/math-emu/mffs.c
arch/powerpc/math-emu/mtfsb0.c
arch/powerpc/math-emu/mtfsb1.c
arch/powerpc/math-emu/mtfsf.c
arch/powerpc/math-emu/mtfsfi.c
arch/powerpc/math-emu/op-1.h [deleted file]
arch/powerpc/math-emu/op-2.h [deleted file]
arch/powerpc/math-emu/op-4.h [deleted file]
arch/powerpc/math-emu/op-common.h [deleted file]
arch/powerpc/math-emu/sfp-machine.h [deleted file]
arch/powerpc/math-emu/single.h [deleted file]
arch/powerpc/math-emu/soft-fp.h [deleted file]
arch/powerpc/math-emu/stfs.c
arch/powerpc/math-emu/types.c [deleted file]
arch/powerpc/math-emu/udivmodti4.c
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/gup.c
arch/powerpc/mm/hash_low_32.S
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/tlb_32.c
arch/powerpc/oprofile/cell/vma_map.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/platforms/44x/Kconfig
arch/powerpc/platforms/44x/Makefile
arch/powerpc/platforms/44x/bamboo.c [deleted file]
arch/powerpc/platforms/44x/canyonlands.c [deleted file]
arch/powerpc/platforms/44x/katmai.c [deleted file]
arch/powerpc/platforms/44x/ppc44x_simple.c [new file with mode: 0644]
arch/powerpc/platforms/44x/rainier.c [deleted file]
arch/powerpc/platforms/44x/sequoia.c [deleted file]
arch/powerpc/platforms/44x/taishan.c [deleted file]
arch/powerpc/platforms/512x/Kconfig
arch/powerpc/platforms/512x/mpc5121_ads.c
arch/powerpc/platforms/52xx/mpc52xx_common.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/82xx/Kconfig
arch/powerpc/platforms/82xx/Makefile
arch/powerpc/platforms/82xx/mgcoge.c [new file with mode: 0644]
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/mpc837x_mds.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/mpc85xx_ads.c
arch/powerpc/platforms/85xx/sbc8560.c
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/86xx/Makefile
arch/powerpc/platforms/86xx/gef_pic.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/gef_pic.h [new file with mode: 0644]
arch/powerpc/platforms/86xx/gef_sbc610.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/sbc8641d.c
arch/powerpc/platforms/8xx/Kconfig
arch/powerpc/platforms/8xx/Makefile
arch/powerpc/platforms/8xx/mgsuvd.c [new file with mode: 0644]
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/chrp/time.c
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
arch/powerpc/platforms/iseries/exception.S
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/maple/time.c
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/powermac/time.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/cmm.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/rtasd.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/platforms/pseries/xics.h
arch/powerpc/sysdev/Kconfig
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/cpm1.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_msi.h
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/fsl_soc.h
arch/powerpc/sysdev/mpc8xxx_gpio.c [new file with mode: 0644]
arch/powerpc/sysdev/mpic.h
arch/powerpc/sysdev/mpic_msi.c
arch/powerpc/sysdev/mpic_pasemi_msi.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/msi_bitmap.c [new file with mode: 0644]
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/qe_lib/Kconfig
arch/s390/Kconfig
arch/s390/hypfs/inode.c
arch/s390/include/asm/elf.h
arch/s390/include/asm/statfs.h
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/syscalls.S
arch/s390/kvm/priv.c
arch/sh/include/asm/elf.h
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/elf_32.h
arch/sparc/include/asm/elf_64.h
arch/sparc/include/asm/serial.h [new file with mode: 0644]
arch/sparc/include/asm/statfs.h
arch/sparc/include/asm/statfs_32.h [deleted file]
arch/sparc/include/asm/statfs_64.h [deleted file]
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc64/kernel/chmc.c
arch/sparc64/kernel/iommu.c
arch/sparc64/kernel/iommu_common.h
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/kernel/us3_cpufreq.c
arch/um/Kconfig.i386
arch/um/Kconfig.x86_64
arch/um/drivers/line.c
arch/um/kernel/exec.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/tty_log.c [deleted file]
arch/x86/Kconfig
arch/x86/Kconfig.cpu
arch/x86/Makefile_32.cpu
arch/x86/boot/video-vesa.c
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/ia32/ia32entry.S
arch/x86/ia32/sys_ia32.c
arch/x86/kernel/Makefile
arch/x86/kernel/alternative.c
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/apic_32.c
arch/x86/kernel/apic_64.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpuid.c
arch/x86/kernel/doublefault_32.c
arch/x86/kernel/dumpstack_32.c [new file with mode: 0644]
arch/x86/kernel/dumpstack_64.c [new file with mode: 0644]
arch/x86/kernel/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/es7000_32.c
arch/x86/kernel/genx2apic_uv_x.c
arch/x86/kernel/head.c
arch/x86/kernel/hpet.c
arch/x86/kernel/irqinit_64.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/msr.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/quirks.c
arch/x86/kernel/rtc.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/time_32.c
arch/x86/kernel/time_64.c
arch/x86/kernel/traps.c [new file with mode: 0644]
arch/x86/kernel/traps_32.c [deleted file]
arch/x86/kernel/traps_64.c [deleted file]
arch/x86/kvm/Makefile
arch/x86/kvm/i8254.c
arch/x86/kvm/i8254.h
arch/x86/kvm/i8259.c
arch/x86/kvm/irq.c
arch/x86/kvm/irq.h
arch/x86/kvm/kvm_cache_regs.h [new file with mode: 0644]
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/vmx.h
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h [new file with mode: 0644]
arch/x86/kvm/x86_emulate.c
arch/x86/mach-generic/es7000.c
arch/x86/mm/Makefile
arch/x86/mm/discontig_32.c [deleted file]
arch/x86/mm/fault.c
arch/x86/mm/gup.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa_32.c [new file with mode: 0644]
arch/x86/mm/srat_64.c
arch/x86/oprofile/Makefile
arch/x86/oprofile/nmi_int.c
arch/x86/oprofile/op_model_amd.c [new file with mode: 0644]
arch/x86/oprofile/op_model_athlon.c [deleted file]
arch/x86/oprofile/op_x86_model.h
arch/x86/pci/fixup.c
arch/x86/xen/time.c
arch/xtensa/kernel/setup.c
block/bsg.c
drivers/acpi/Kconfig
drivers/acpi/glue.c
drivers/ata/pata_of_platform.c
drivers/ata/pata_pcmcia.c
drivers/base/Kconfig
drivers/base/bus.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/block/aoe/aoechr.c
drivers/block/ataflop.c
drivers/block/floppy.c
drivers/block/paride/pg.c
drivers/block/paride/pt.c
drivers/block/pktcdvd.c
drivers/block/viodasd.c
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/bluetooth/hci_ldisc.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/intel-agp.c
drivers/char/agp/nvidia-agp.c
drivers/char/amiserial.c
drivers/char/applicom.c
drivers/char/bsr.c
drivers/char/cyclades.c
drivers/char/ds1286.c
drivers/char/dsp56k.c
drivers/char/epca.c
drivers/char/generic_serial.c
drivers/char/hpet.c
drivers/char/hvc_console.c
drivers/char/hw_random/omap-rng.c
drivers/char/ip2/Makefile
drivers/char/ip2/i2ellis.c
drivers/char/ip2/i2ellis.h
drivers/char/ip2/ip2base.c [deleted file]
drivers/char/ip2/ip2main.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/keyboard.c
drivers/char/lp.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/n_hdlc.c
drivers/char/n_r3964.c
drivers/char/n_tty.c
drivers/char/nozomi.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/main.c
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/ppdev.c
drivers/char/pty.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/rtc.c
drivers/char/snsc.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/char/sysrq.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_tis.c
drivers/char/tty_audit.c
drivers/char/tty_buffer.c [new file with mode: 0644]
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/tty_port.c [new file with mode: 0644]
drivers/char/vc_screen.c
drivers/char/viotape.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/char/xilinx_hwicap/xilinx_hwicap.c
drivers/dca/dca-sysfs.c
drivers/edac/i5000_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/mpc85xx_edac.c
drivers/firewire/fw-card.c
drivers/firewire/fw-cdev.c
drivers/firewire/fw-device.c
drivers/firewire/fw-sbp2.c
drivers/firewire/fw-transaction.c
drivers/firewire/fw-transaction.h
drivers/firmware/dmi_scan.c
drivers/firmware/iscsi_ibft.c
drivers/gpio/gpiolib.c
drivers/gpio/max7301.c
drivers/gpio/max732x.c
drivers/gpio/mcp23s08.c
drivers/gpio/pca953x.c
drivers/gpio/pcf857x.c
drivers/gpu/drm/i915/i915_dma.c
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-a4tech.c [new file with mode: 0644]
drivers/hid/hid-apple.c [new file with mode: 0644]
drivers/hid/hid-belkin.c [new file with mode: 0644]
drivers/hid/hid-bright.c [new file with mode: 0644]
drivers/hid/hid-cherry.c [new file with mode: 0644]
drivers/hid/hid-chicony.c [new file with mode: 0644]
drivers/hid/hid-core.c
drivers/hid/hid-cypress.c [new file with mode: 0644]
drivers/hid/hid-dell.c [new file with mode: 0644]
drivers/hid/hid-dummy.c [new file with mode: 0644]
drivers/hid/hid-ezkey.c [new file with mode: 0644]
drivers/hid/hid-gyration.c [new file with mode: 0644]
drivers/hid/hid-ids.h [new file with mode: 0644]
drivers/hid/hid-input-quirks.c [deleted file]
drivers/hid/hid-input.c
drivers/hid/hid-lg.c [new file with mode: 0644]
drivers/hid/hid-lg.h [new file with mode: 0644]
drivers/hid/hid-lg2ff.c [new file with mode: 0644]
drivers/hid/hid-lgff.c [new file with mode: 0644]
drivers/hid/hid-microsoft.c [new file with mode: 0644]
drivers/hid/hid-monterey.c [new file with mode: 0644]
drivers/hid/hid-petalynx.c [new file with mode: 0644]
drivers/hid/hid-pl.c [new file with mode: 0644]
drivers/hid/hid-samsung.c [new file with mode: 0644]
drivers/hid/hid-sony.c [new file with mode: 0644]
drivers/hid/hid-sunplus.c [new file with mode: 0644]
drivers/hid/hid-tmff.c [new file with mode: 0644]
drivers/hid/hid-zpff.c [new file with mode: 0644]
drivers/hid/hidraw.c
drivers/hid/usbhid/Kconfig
drivers/hid/usbhid/Makefile
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-ff.c [deleted file]
drivers/hid/usbhid/hid-lg2ff.c [deleted file]
drivers/hid/usbhid/hid-lgff.c [deleted file]
drivers/hid/usbhid/hid-pidff.c
drivers/hid/usbhid/hid-plff.c [deleted file]
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hid-tmff.c [deleted file]
drivers/hid/usbhid/hid-zpff.c [deleted file]
drivers/hid/usbhid/hiddev.c
drivers/hid/usbhid/usbhid.h
drivers/hid/usbhid/usbkbd.c
drivers/hid/usbhid/usbmouse.c
drivers/hwmon/ams/ams.h
drivers/hwmon/dme1737.c
drivers/hwmon/hwmon.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-highlander.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/mcu_mpc8349emitx.c [new file with mode: 0644]
drivers/i2c/chips/tps65010.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/arm/icside.c
drivers/ide/h8300/ide-h8300.c
drivers/ide/ide-acpi.c
drivers/ide/ide-atapi.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/ide-disk.c
drivers/ide/ide-disk.h [new file with mode: 0644]
drivers/ide/ide-disk_ioctl.c [new file with mode: 0644]
drivers/ide/ide-disk_proc.c [new file with mode: 0644]
drivers/ide/ide-dma-sff.c [new file with mode: 0644]
drivers/ide/ide-dma.c
drivers/ide/ide-floppy.c
drivers/ide/ide-floppy.h
drivers/ide/ide-floppy_ioctl.c
drivers/ide/ide-floppy_proc.c [new file with mode: 0644]
drivers/ide/ide-generic.c
drivers/ide/ide-io.c
drivers/ide/ide-ioctls.c
drivers/ide/ide-iops.c
drivers/ide/ide-lib.c
drivers/ide/ide-park.c [new file with mode: 0644]
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/legacy/ali14xx.c
drivers/ide/legacy/ht6560b.c
drivers/ide/legacy/ide-4drives.c
drivers/ide/legacy/ide-cs.c
drivers/ide/legacy/qd65xx.c
drivers/ide/mips/au1xxx-ide.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/amd74xx.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/cmd640.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/cs5520.c
drivers/ide/pci/cs5530.c
drivers/ide/pci/cs5535.c
drivers/ide/pci/cy82c693.c
drivers/ide/pci/delkin_cb.c
drivers/ide/pci/generic.c
drivers/ide/pci/hpt34x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it8213.c
drivers/ide/pci/it821x.c
drivers/ide/pci/jmicron.c
drivers/ide/pci/ns87415.c
drivers/ide/pci/opti621.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/pdc202xx_old.c
drivers/ide/pci/piix.c
drivers/ide/pci/rz1000.c
drivers/ide/pci/sc1200.c
drivers/ide/pci/scc_pata.c
drivers/ide/pci/serverworks.c
drivers/ide/pci/sgiioc4.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sis5513.c
drivers/ide/pci/sl82c105.c
drivers/ide/pci/slc90e66.c
drivers/ide/pci/tc86c001.c
drivers/ide/pci/triflex.c
drivers/ide/pci/trm290.c
drivers/ide/pci/via82cxxx.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/csr1212.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.h
drivers/ieee1394/raw1394-private.h
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/ieee1394/video1394.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/ipath/ipath_file_ops.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/gameport/gameport.c
drivers/input/joystick/a3d.c
drivers/input/joystick/adi.c
drivers/input/joystick/analog.c
drivers/input/joystick/cobra.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip.c
drivers/input/joystick/grip_mp.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/interact.c
drivers/input/joystick/joydump.c
drivers/input/joystick/sidewinder.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/omap-keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ati_remote2.c
drivers/input/misc/cm109.c [new file with mode: 0644]
drivers/input/misc/hp_sdc_rtc.c
drivers/input/misc/map_to_7segment.h [deleted file]
drivers/input/misc/wistron_btns.c
drivers/input/misc/yealink.c
drivers/input/mouse/Kconfig
drivers/input/mouse/Makefile
drivers/input/mouse/alps.c
drivers/input/mouse/appletouch.c
drivers/input/mouse/hgpk.c [new file with mode: 0644]
drivers/input/mouse/hgpk.h [new file with mode: 0644]
drivers/input/mouse/logips2pp.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/trackpoint.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/i8042-io.h
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/serio_raw.c
drivers/input/tablet/aiptek.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel_tsadcc.c
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/input/touchscreen/wm9705.c
drivers/input/touchscreen/wm9712.c
drivers/input/touchscreen/wm9713.c
drivers/input/touchscreen/wm97xx-core.c
drivers/isdn/capi/capi.c
drivers/isdn/gigaset/ser-gigaset.c
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/mISDN/dsp_cmx.c
drivers/isdn/mISDN/timerdev.c
drivers/leds/led-class.c
drivers/macintosh/adb.c
drivers/md/Kconfig
drivers/md/faulty.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6.h
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_fops.c
drivers/media/common/tuners/mt2060.c
drivers/media/common/tuners/mxl5007t.c
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/tda827x.c
drivers/media/common/tuners/tda827x.h
drivers/media/common/tuners/tda8290.c
drivers/media/common/tuners/tda8290.h
drivers/media/common/tuners/tda9887.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/common/tuners/tuner-types.c
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/tuner-xc2028.h
drivers/media/common/tuners/xc5000.c
drivers/media/common/tuners/xc5000.h
drivers/media/common/tuners/xc5000_priv.h [deleted file]
drivers/media/dvb/Kconfig
drivers/media/dvb/Makefile
drivers/media/dvb/b2c2/flexcop-dma.c
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/cinergyT2/Kconfig [deleted file]
drivers/media/dvb/cinergyT2/Makefile [deleted file]
drivers/media/dvb/cinergyT2/cinergyT2.c [deleted file]
drivers/media/dvb/dm1105/Kconfig [new file with mode: 0644]
drivers/media/dvb/dm1105/Makefile [new file with mode: 0644]
drivers/media/dvb/dm1105/dm1105.c [new file with mode: 0644]
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/af9005-remote.c
drivers/media/dvb/dvb-usb/af9005-script.h
drivers/media/dvb/dvb-usb/af9005.c
drivers/media/dvb/dvb-usb/af9015.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/af9015.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/cinergyT2-core.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/cinergyT2-fe.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/cinergyT2.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dib0700.h
drivers/media/dvb/dvb-usb/dib0700_core.c
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dtv5100.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/dtv5100.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dw2102.c
drivers/media/dvb/dvb-usb/dw2102.h
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/af9013.c [new file with mode: 0644]
drivers/media/dvb/frontends/af9013.h [new file with mode: 0644]
drivers/media/dvb/frontends/af9013_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/au8522.c
drivers/media/dvb/frontends/au8522.h
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24116.c [new file with mode: 0644]
drivers/media/dvb/frontends/cx24116.h [new file with mode: 0644]
drivers/media/dvb/frontends/dib0070.h
drivers/media/dvb/frontends/dib7000m.c
drivers/media/dvb/frontends/dib7000p.c
drivers/media/dvb/frontends/dib7000p.h
drivers/media/dvb/frontends/drx397xD.c
drivers/media/dvb/frontends/drx397xD.h
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/eds1547.h [new file with mode: 0644]
drivers/media/dvb/frontends/lgs8gl5.c [new file with mode: 0644]
drivers/media/dvb/frontends/lgs8gl5.h [new file with mode: 0644]
drivers/media/dvb/frontends/nxt200x.c
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/si21xx.c [new file with mode: 0644]
drivers/media/dvb/frontends/si21xx.h [new file with mode: 0644]
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/stb6000.c [new file with mode: 0644]
drivers/media/dvb/frontends/stb6000.h [new file with mode: 0644]
drivers/media/dvb/frontends/stv0288.c [new file with mode: 0644]
drivers/media/dvb/frontends/stv0288.h [new file with mode: 0644]
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tdhd1.h [new file with mode: 0644]
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttpci/budget.h
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/radio/Kconfig
drivers/media/radio/Makefile
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-mr800.c [new file with mode: 0644]
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/arv.c
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/au0828/au0828.h
drivers/media/video/bt856.c
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/btcx-risc.c
drivers/media/video/bw-qcam.c
drivers/media/video/bw-qcam.h
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cpia.c
drivers/media/video/cpia2/cpia2_core.c
drivers/media/video/cpia2/cpia2_usb.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cx18/Makefile
drivers/media/video/cx18/cx18-audio.c
drivers/media/video/cx18/cx18-av-core.c
drivers/media/video/cx18/cx18-av-core.h
drivers/media/video/cx18/cx18-av-firmware.c
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-firmware.c
drivers/media/video/cx18/cx18-gpio.c
drivers/media/video/cx18/cx18-gpio.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-io.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-io.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-irq.c
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-queue.c
drivers/media/video/cx18/cx18-scb.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-version.h
drivers/media/video/cx18/cx23418.h
drivers/media/video/cx2341x.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-vbi.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/dabusb.c
drivers/media/video/dpc7146.c [deleted file]
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/Kconfig
drivers/media/video/gspca/Makefile
drivers/media/video/gspca/conex.c
drivers/media/video/gspca/etoms.c
drivers/media/video/gspca/finepix.c [new file with mode: 0644]
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/m5602/Kconfig [new file with mode: 0644]
drivers/media/video/gspca/m5602/Makefile [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_bridge.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_core.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_mt9m111.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_mt9m111.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_ov9650.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_ov9650.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_po1030.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_po1030.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_s5k4aa.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_s5k4aa.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_s5k83a.c [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_s5k83a.h [new file with mode: 0644]
drivers/media/video/gspca/m5602/m5602_sensor.h [new file with mode: 0644]
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/pac207.c
drivers/media/video/gspca/pac7311.c
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca500.c
drivers/media/video/gspca/spca501.c
drivers/media/video/gspca/spca505.c
drivers/media/video/gspca/spca506.c
drivers/media/video/gspca/spca508.c
drivers/media/video/gspca/spca561.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/tv8532.c
drivers/media/video/gspca/vc032x.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/ivtv-cards.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-fileops.h
drivers/media/video/ivtv/ivtv-gpio.c
drivers/media/video/ivtv/ivtv-gpio.h
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtv-vbi.c
drivers/media/video/ivtv/ivtv-yuv.c
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/meye.c
drivers/media/video/meye.h
drivers/media/video/mt9m001.c
drivers/media/video/mt9m111.c [new file with mode: 0644]
drivers/media/video/mt9v022.c
drivers/media/video/mxb.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/ovcamchip/ovcamchip_core.c
drivers/media/video/ovcamchip/ovcamchip_priv.h
drivers/media/video/pms.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.h
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-v4l.c
drivers/media/video/pxa_camera.c
drivers/media/video/s2255drv.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5246a.h [deleted file]
drivers/media/video/saa5249.c
drivers/media/video/saa7115.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-ts.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/se401.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/sn9c102/sn9c102_devtable.h
drivers/media/video/sn9c102/sn9c102_hv7131d.c
drivers/media/video/sn9c102/sn9c102_hv7131r.c
drivers/media/video/sn9c102/sn9c102_mi0343.c
drivers/media/video/sn9c102/sn9c102_mi0360.c
drivers/media/video/sn9c102/sn9c102_mt9v111.c
drivers/media/video/sn9c102/sn9c102_ov7630.c
drivers/media/video/sn9c102/sn9c102_ov7660.c
drivers/media/video/sn9c102/sn9c102_pas106b.c
drivers/media/video/sn9c102/sn9c102_pas202bcb.c
drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
drivers/media/video/sn9c102/sn9c102_tas5110d.c
drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
drivers/media/video/stk-webcam.c
drivers/media/video/stk-webcam.h
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tda9840.c
drivers/media/video/tda9840.h
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-3036.c [deleted file]
drivers/media/video/tuner-core.c
drivers/media/video/usbvideo/ibmcam.c
drivers/media/video/usbvideo/konicawc.c
drivers/media/video/usbvideo/quickcam_messenger.c
drivers/media/video/usbvideo/ultracam.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_status.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/videocodec.c [deleted file]
drivers/media/video/videocodec.h [deleted file]
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran.h [deleted file]
drivers/media/video/zoran/Kconfig [new file with mode: 0644]
drivers/media/video/zoran/Makefile [new file with mode: 0644]
drivers/media/video/zoran/videocodec.c [new file with mode: 0644]
drivers/media/video/zoran/videocodec.h [new file with mode: 0644]
drivers/media/video/zoran/zoran.h [new file with mode: 0644]
drivers/media/video/zoran/zoran_card.c [new file with mode: 0644]
drivers/media/video/zoran/zoran_card.h [new file with mode: 0644]
drivers/media/video/zoran/zoran_device.c [new file with mode: 0644]
drivers/media/video/zoran/zoran_device.h [new file with mode: 0644]
drivers/media/video/zoran/zoran_driver.c [new file with mode: 0644]
drivers/media/video/zoran/zoran_procfs.c [new file with mode: 0644]
drivers/media/video/zoran/zoran_procfs.h [new file with mode: 0644]
drivers/media/video/zoran/zr36016.c [new file with mode: 0644]
drivers/media/video/zoran/zr36016.h [new file with mode: 0644]
drivers/media/video/zoran/zr36050.c [new file with mode: 0644]
drivers/media/video/zoran/zr36050.h [new file with mode: 0644]
drivers/media/video/zoran/zr36057.h [new file with mode: 0644]
drivers/media/video/zoran/zr36060.c [new file with mode: 0644]
drivers/media/video/zoran/zr36060.h [new file with mode: 0644]
drivers/media/video/zoran_card.c [deleted file]
drivers/media/video/zoran_card.h [deleted file]
drivers/media/video/zoran_device.c [deleted file]
drivers/media/video/zoran_device.h [deleted file]
drivers/media/video/zoran_driver.c [deleted file]
drivers/media/video/zoran_procfs.c [deleted file]
drivers/media/video/zoran_procfs.h [deleted file]
drivers/media/video/zr36016.c [deleted file]
drivers/media/video/zr36016.h [deleted file]
drivers/media/video/zr36050.c [deleted file]
drivers/media/video/zr36050.h [deleted file]
drivers/media/video/zr36057.h [deleted file]
drivers/media/video/zr36060.c [deleted file]
drivers/media/video/zr36060.h [deleted file]
drivers/media/video/zr364xx.c
drivers/message/i2o/Makefile
drivers/message/i2o/device.c
drivers/message/i2o/exec-osm.c
drivers/message/i2o/i2o_config.c
drivers/message/i2o/iop.c
drivers/message/i2o/memory.c [new file with mode: 0644]
drivers/message/i2o/pci.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/wm8350-core.c [new file with mode: 0644]
drivers/mfd/wm8350-gpio.c [new file with mode: 0644]
drivers/mfd/wm8350-i2c.c [new file with mode: 0644]
drivers/mfd/wm8350-regmap.c [new file with mode: 0644]
drivers/mfd/wm8400-core.c [new file with mode: 0644]
drivers/misc/Kconfig
drivers/misc/hp-wmi.c
drivers/misc/phantom.c
drivers/misc/sgi-gru/gru.h
drivers/misc/sgi-gru/gru_instructions.h
drivers/misc/sgi-gru/grufault.c
drivers/misc/sgi-gru/grufile.c
drivers/misc/sgi-gru/gruhandles.h
drivers/misc/sgi-gru/grukservices.c
drivers/misc/sgi-gru/grumain.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-pci.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/ams-delta.c
drivers/mtd/nand/cafe_nand.c
drivers/net/3c501.c
drivers/net/3c509.c
drivers/net/3c515.c
drivers/net/Kconfig
drivers/net/appletalk/cops.c
drivers/net/au1000_eth.c
drivers/net/bfin_mac.c
drivers/net/cs89x0.c
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/ael1002.c
drivers/net/cxgb3/common.h
drivers/net/cxgb3/cxgb3_ctl_defs.h
drivers/net/cxgb3/cxgb3_defs.h
drivers/net/cxgb3/cxgb3_ioctl.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/cxgb3_offload.c
drivers/net/cxgb3/cxgb3_offload.h
drivers/net/cxgb3/firmware_exports.h
drivers/net/cxgb3/l2t.c
drivers/net/cxgb3/l2t.h
drivers/net/cxgb3/mc5.c
drivers/net/cxgb3/sge.c
drivers/net/cxgb3/t3_cpl.h
drivers/net/cxgb3/t3_hw.c
drivers/net/cxgb3/t3cdev.h
drivers/net/cxgb3/version.h
drivers/net/cxgb3/vsc8211.c
drivers/net/cxgb3/xgmac.c
drivers/net/eexpress.c
drivers/net/enic/enic_main.c
drivers/net/ibm_newemac/Kconfig
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/core.h
drivers/net/ibm_newemac/mal.c
drivers/net/ibm_newemac/mal.h
drivers/net/ibm_newemac/phy.c
drivers/net/ibm_newemac/phy.h
drivers/net/ibmlana.c
drivers/net/irda/sir_dongle.c
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_main.c
drivers/net/jme.c
drivers/net/macmace.c
drivers/net/myri10ge/myri10ge.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/Kconfig
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy_device.c
drivers/net/ppp_generic.c
drivers/net/pppox.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_ethtool.c
drivers/net/qlge/qlge_main.c
drivers/net/r8169.c
drivers/net/sky2.c
drivers/net/smc911x.c
drivers/net/smc911x.h
drivers/net/tc35815.c
drivers/net/tlan.c
drivers/net/tokenring/smctr.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/dmfe.c
drivers/net/via-velocity.c
drivers/net/wan/Kconfig
drivers/net/wan/cosa.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/z85230.c
drivers/net/wan/z85230.h
drivers/net/wireless/airo_cs.c
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/b43/pcmcia.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/if_cs.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rtl8187_dev.c
drivers/net/wireless/spectrum_cs.c
drivers/net/wireless/wavelan.c
drivers/net/wireless/wavelan.p.h
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/net/xen-netfront.c
drivers/nubus/nubus.c
drivers/of/base.c
drivers/of/gpio.c
drivers/oprofile/buffer_sync.c
drivers/oprofile/cpu_buffer.c
drivers/oprofile/cpu_buffer.h
drivers/parport/ChangeLog
drivers/parport/ieee1284.c
drivers/parport/parport_cs.c
drivers/parport/probe.c
drivers/parport/share.c
drivers/pci/dma_remapping.h [deleted file]
drivers/pci/dmar.c
drivers/pci/hotplug/ibmphp_ebda.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/intel-iommu.c
drivers/pci/intel-iommu.h [deleted file]
drivers/pci/intr_remapping.c
drivers/pci/intr_remapping.h
drivers/pci/iova.c
drivers/pci/iova.h [deleted file]
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/pcmcia/Makefile
drivers/pcmcia/au1000_generic.c
drivers/pcmcia/au1000_generic.h
drivers/pcmcia/au1000_pb1x00.c
drivers/pcmcia/au1000_xxs1500.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/ds_internal.h [deleted file]
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/o2micro.h
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/ti113x.h
drivers/pcmcia/yenta_socket.c
drivers/pnp/base.h
drivers/pnp/core.c
drivers/pnp/driver.c
drivers/pnp/interface.c
drivers/pnp/isapnp/core.c
drivers/pnp/pnpbios/core.c
drivers/pnp/quirks.c
drivers/pnp/resource.c
drivers/power/olpc_battery.c
drivers/power/power_supply_core.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/bq24022.c
drivers/regulator/core.c
drivers/regulator/da903x.c [new file with mode: 0644]
drivers/regulator/wm8350-regulator.c [new file with mode: 0644]
drivers/regulator/wm8400-regulator.c [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1286.c [new file with mode: 0644]
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds3234.c [new file with mode: 0644]
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m48t35.c [new file with mode: 0644]
drivers/rtc/rtc-max6900.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pl030.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-stk17ta8.c
drivers/s390/char/fs3270.c
drivers/s390/char/raw3270.c
drivers/s390/char/tape_class.c
drivers/s390/char/vmlogrdr.c
drivers/s390/char/vmur.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_mpc.c
drivers/scsi/Kconfig
drivers/scsi/atari_dma_emul.c [deleted file]
drivers/scsi/atari_scsi.c
drivers/scsi/ch.c
drivers/scsi/dpt_i2o.c
drivers/scsi/ide-scsi.c
drivers/scsi/osst.c
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/scsi/sg.c
drivers/scsi/st.c
drivers/serial/8250.c
drivers/serial/8250_pci.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/bfin_5xx.c
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/cpm_uart/cpm_uart_cpm1.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c
drivers/serial/crisv10.c
drivers/serial/mcfserial.c [deleted file]
drivers/serial/mcfserial.h [deleted file]
drivers/serial/mpc52xx_uart.c
drivers/serial/s3c2400.c
drivers/serial/s3c2410.c
drivers/serial/s3c2412.c
drivers/serial/s3c2440.c
drivers/serial/samsung.c
drivers/serial/serial_core.c
drivers/serial/serial_cs.c
drivers/serial/ucc_uart.c
drivers/spi/mpc52xx_psc_spi.c
drivers/spi/omap2_mcspi.c
drivers/spi/omap_uwire.c
drivers/spi/orion_spi.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi.c
drivers/spi/spi_s3c24xx.c
drivers/spi/spidev.c
drivers/ssb/pcmcia.c
drivers/telephony/ixj.c
drivers/telephony/ixj_pcmcia.c
drivers/uio/Kconfig
drivers/uio/Makefile
drivers/uio/uio.c
drivers/uio/uio_pdrv.c
drivers/uio/uio_sercos3.c [new file with mode: 0644]
drivers/usb/core/devio.c
drivers/usb/core/file.c
drivers/usb/core/hcd.c
drivers/usb/core/inode.c
drivers/usb/gadget/Makefile
drivers/usb/gadget/cdc2.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_loopback.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/gmidi.c
drivers/usb/gadget/printer.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/u_ether.c
drivers/usb/gadget/zero.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/sl811_cs.c
drivers/usb/host/uhci-q.c
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c
drivers/usb/misc/phidgetservo.c
drivers/usb/mon/mon_bin.c
drivers/usb/serial/aircable.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/console.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/navman.c
drivers/usb/serial/omninet.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/safe_serial.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/atmel_lcdfb.c
drivers/video/aty/radeon_accel.c
drivers/video/aty/radeon_backlight.c
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_i2c.c
drivers/video/aty/radeon_pm.c
drivers/video/aty/radeonfb.h
drivers/video/backlight/mbp_nvidia_bl.c
drivers/video/carminefb.c
drivers/video/cirrusfb.c
drivers/video/console/fbcon.c
drivers/video/console/mdacon.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/display/display-sysfs.c
drivers/video/efifb.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/imacfb.c
drivers/video/intelfb/intelfb.h
drivers/video/intelfb/intelfb_i2c.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/intelfb/intelfbhw.c
drivers/video/matrox/matroxfb_base.c
drivers/video/metronomefb.c
drivers/video/neofb.c
drivers/video/omap/dispc.c
drivers/video/omap/dispc.h
drivers/video/omap/lcd_h4.c
drivers/video/omap/lcd_inn1610.c
drivers/video/omap/lcd_osk.c
drivers/video/omap/lcd_sx1.c
drivers/video/omap/lcdc.c
drivers/video/omap/lcdc.h
drivers/video/omap/omapfb_main.c
drivers/video/omap/rfbi.c
drivers/video/omap/sossi.c
drivers/video/s1d13xxxfb.c
drivers/video/tdfxfb.c
drivers/video/tmiofb.c [new file with mode: 0644]
drivers/video/uvesafb.c
drivers/video/vga16fb.c
drivers/video/via/Makefile [new file with mode: 0644]
drivers/video/via/accel.c [new file with mode: 0644]
drivers/video/via/accel.h [new file with mode: 0644]
drivers/video/via/chip.h [new file with mode: 0644]
drivers/video/via/debug.h [new file with mode: 0644]
drivers/video/via/dvi.c [new file with mode: 0644]
drivers/video/via/dvi.h [new file with mode: 0644]
drivers/video/via/global.c [new file with mode: 0644]
drivers/video/via/global.h [new file with mode: 0644]
drivers/video/via/hw.c [new file with mode: 0644]
drivers/video/via/hw.h [new file with mode: 0644]
drivers/video/via/iface.c [new file with mode: 0644]
drivers/video/via/iface.h [new file with mode: 0644]
drivers/video/via/ioctl.c [new file with mode: 0644]
drivers/video/via/ioctl.h [new file with mode: 0644]
drivers/video/via/lcd.c [new file with mode: 0644]
drivers/video/via/lcd.h [new file with mode: 0644]
drivers/video/via/lcdtbl.h [new file with mode: 0644]
drivers/video/via/share.h [new file with mode: 0644]
drivers/video/via/tbl1636.c [new file with mode: 0644]
drivers/video/via/tbl1636.h [new file with mode: 0644]
drivers/video/via/tblDPASetting.c [new file with mode: 0644]
drivers/video/via/tblDPASetting.h [new file with mode: 0644]
drivers/video/via/via_i2c.c [new file with mode: 0644]
drivers/video/via/via_i2c.h [new file with mode: 0644]
drivers/video/via/via_utility.c [new file with mode: 0644]
drivers/video/via/via_utility.h [new file with mode: 0644]
drivers/video/via/viafbdev.c [new file with mode: 0644]
drivers/video/via/viafbdev.h [new file with mode: 0644]
drivers/video/via/viamode.c [new file with mode: 0644]
drivers/video/via/viamode.h [new file with mode: 0644]
drivers/video/via/vt1636.c [new file with mode: 0644]
drivers/video/via/vt1636.h [new file with mode: 0644]
drivers/w1/masters/ds1wm.c
drivers/w1/masters/ds2490.c
drivers/w1/slaves/w1_ds2431.c [new file with mode: 0644]
drivers/w1/slaves/w1_therm.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
fs/9p/v9fs.c
fs/Kconfig
fs/Kconfig.binfmt
fs/Makefile
fs/adfs/super.c
fs/affs/super.c
fs/afs/file.c
fs/afs/internal.h
fs/afs/super.c
fs/afs/write.c
fs/autofs/inode.c
fs/autofs4/Makefile
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c [new file with mode: 0644]
fs/autofs4/expire.c
fs/autofs4/init.c
fs/autofs4/inode.c
fs/autofs4/waitq.c
fs/befs/befs_fs_types.h
fs/befs/linuxvfs.c
fs/befs/super.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_em86.c
fs/binfmt_flat.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/binfmt_som.c
fs/char_dev.c
fs/coda/psdev.c
fs/compat.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/direct-io.c
fs/dquot.c
fs/ecryptfs/Makefile
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/ecryptfs/mmap.c
fs/ecryptfs/netlink.c [deleted file]
fs/efs/super.c
fs/eventpoll.c
fs/exec.c
fs/ext2/balloc.c
fs/ext2/dir.c
fs/ext2/super.c
fs/ext3/super.c
fs/ext4/super.c
fs/fat/inode.c
fs/fs-writeback.c
fs/fuse/inode.c
fs/gfs2/mount.c
fs/hfs/catalog.c
fs/hfs/super.c
fs/hfsplus/bitmap.c
fs/hfsplus/catalog.c
fs/hfsplus/options.c
fs/hfsplus/super.c
fs/hpfs/super.c
fs/hugetlbfs/inode.c
fs/isofs/inode.c
fs/jfs/super.c
fs/lockd/Makefile
fs/lockd/clntlock.c
fs/lockd/grace.c [new file with mode: 0644]
fs/lockd/host.c
fs/lockd/mon.c
fs/lockd/svc.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/lockd/xdr.c
fs/lockd/xdr4.c
fs/mpage.c
fs/nfs/callback.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4namespace.c
fs/nfs/nfsroot.c
fs/nfs/proc.c
fs/nfs/super.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/nfsd/lockd.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/nls/nls_base.c
fs/ocfs2/Makefile
fs/ocfs2/alloc.c
fs/ocfs2/alloc.h
fs/ocfs2/aops.c
fs/ocfs2/buffer_head_io.c
fs/ocfs2/buffer_head_io.h
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dlmglue.c
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/localalloc.c
fs/ocfs2/localalloc.h
fs/ocfs2/locks.c
fs/ocfs2/locks.h
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/ocfs2_jbd_compat.h [new file with mode: 0644]
fs/ocfs2/resize.c
fs/ocfs2/slot_map.c
fs/ocfs2/stack_user.c
fs/ocfs2/stackglue.c
fs/ocfs2/stackglue.h
fs/ocfs2/suballoc.c
fs/ocfs2/suballoc.h
fs/ocfs2/super.c
fs/ocfs2/symlink.c
fs/ocfs2/uptodate.c
fs/ocfs2/uptodate.h
fs/ocfs2/xattr.c [new file with mode: 0644]
fs/ocfs2/xattr.h [new file with mode: 0644]
fs/omfs/inode.c
fs/open.c
fs/partitions/acorn.c
fs/partitions/check.c
fs/proc/Kconfig
fs/proc/array.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/proc_misc.c
fs/proc/proc_sysctl.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/proc/vmcore.c
fs/reiserfs/procfs.c
fs/reiserfs/xattr.c
fs/sysfs/bin.c
fs/sysfs/dir.c
fs/sysfs/file.c
fs/sysfs/mount.c
fs/sysfs/sysfs.h
fs/ubifs/super.c
fs/udf/super.c
fs/ufs/super.c
fs/xfs/linux-2.6/xfs_super.c
include/acpi/acmacros.h
include/acpi/platform/acgcc.h
include/asm-arm/plat-s3c/debug-macro.S [deleted file]
include/asm-arm/plat-s3c/map.h [deleted file]
include/asm-arm/plat-s3c/regs-adc.h [deleted file]
include/asm-arm/plat-s3c/regs-serial.h [deleted file]
include/asm-arm/plat-s3c/regs-timer.h [deleted file]
include/asm-arm/plat-s3c/uncompress.h [deleted file]
include/asm-arm/plat-s3c24xx/clock.h [deleted file]
include/asm-arm/plat-s3c24xx/common-smdk.h [deleted file]
include/asm-arm/plat-s3c24xx/cpu.h [deleted file]
include/asm-arm/plat-s3c24xx/devs.h [deleted file]
include/asm-arm/plat-s3c24xx/dma.h [deleted file]
include/asm-arm/plat-s3c24xx/irq.h [deleted file]
include/asm-arm/plat-s3c24xx/pm.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2400.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2410.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2412.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2440.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2442.h [deleted file]
include/asm-arm/plat-s3c24xx/s3c2443.h [deleted file]
include/asm-cris/a.out.h [deleted file]
include/asm-cris/elf.h
include/asm-frv/elf.h
include/asm-frv/unaligned.h
include/asm-generic/bug.h
include/asm-generic/gpio.h
include/asm-generic/statfs.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/timer.h [new file with mode: 0644]
include/asm-m32r/a.out.h [deleted file]
include/asm-m32r/elf.h
include/asm-m68k/atarihw.h
include/asm-m68k/dma-mapping.h
include/asm-m68k/dma.h
include/asm-m68k/elf.h
include/asm-m68k/entry.h
include/asm-m68k/io.h
include/asm-m68k/pci.h
include/asm-m68k/virtconvert.h
include/asm-mips/cevt-r4k.h [deleted file]
include/asm-mn10300/elf.h
include/asm-parisc/a.out.h [deleted file]
include/asm-parisc/elf.h
include/asm-parisc/statfs.h
include/asm-um/elf-i386.h
include/asm-um/elf-ppc.h
include/asm-um/elf-x86_64.h
include/asm-x86/desc.h
include/asm-x86/elf.h
include/asm-x86/es7000/apic.h
include/asm-x86/es7000/mpparse.h
include/asm-x86/fixmap_32.h
include/asm-x86/fixmap_64.h
include/asm-x86/io.h
include/asm-x86/io_64.h
include/asm-x86/ioctls.h
include/asm-x86/iommu.h
include/asm-x86/irqflags.h
include/asm-x86/kdebug.h
include/asm-x86/kprobes.h
include/asm-x86/kvm.h
include/asm-x86/kvm_host.h
include/asm-x86/mach-default/mach_traps.h
include/asm-x86/module.h
include/asm-x86/msr-index.h
include/asm-x86/nmi.h
include/asm-x86/page.h
include/asm-x86/page_32.h
include/asm-x86/page_64.h
include/asm-x86/pgtable.h
include/asm-x86/ptrace.h
include/asm-x86/pvclock.h
include/asm-x86/segment.h
include/asm-x86/smp.h
include/asm-x86/statfs.h
include/asm-x86/summit/apic.h
include/asm-x86/system.h
include/asm-x86/traps.h
include/asm-x86/xen/page.h
include/asm-xtensa/a.out.h [deleted file]
include/asm-xtensa/elf.h
include/linux/Kbuild
include/linux/aio.h
include/linux/auto_dev-ioctl.h [new file with mode: 0644]
include/linux/auto_fs4.h
include/linux/binfmts.h
include/linux/cgroup.h
include/linux/clk.h
include/linux/compat.h
include/linux/console_struct.h
include/linux/device.h
include/linux/devpts_fs.h
include/linux/dma_remapping.h [new file with mode: 0644]
include/linux/dmi.h
include/linux/ds1286.h
include/linux/dvb/frontend.h
include/linux/dvb/version.h
include/linux/dynamic_printk.h [new file with mode: 0644]
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/ext3_jbd.h
include/linux/firewire-cdev.h
include/linux/fs.h
include/linux/gameport.h
include/linux/gpio.h
include/linux/hid.h
include/linux/hiddev.h
include/linux/hpet.h
include/linux/i2c-id.h
include/linux/i2o.h
include/linux/icmpv6.h
include/linux/ide.h
include/linux/if_ether.h
include/linux/if_fddi.h
include/linux/if_hippi.h
include/linux/igmp.h
include/linux/init.h
include/linux/input.h
include/linux/intel-iommu.h [new file with mode: 0644]
include/linux/interrupt.h
include/linux/iommu-helper.h
include/linux/ioport.h
include/linux/iova.h [new file with mode: 0644]
include/linux/ivtv.h
include/linux/jbd.h
include/linux/jbd2.h
include/linux/journal-head.h
include/linux/kallsyms.h
include/linux/kernel.h
include/linux/kmod.h
include/linux/kvm.h
include/linux/kvm_host.h
include/linux/lockd/bind.h
include/linux/lockd/lockd.h
include/linux/lockd/xdr.h
include/linux/magic.h
include/linux/map_to_7segment.h [new file with mode: 0644]
include/linux/mfd/tmio.h
include/linux/mfd/wm8350/audio.h [new file with mode: 0644]
include/linux/mfd/wm8350/comparator.h [new file with mode: 0644]
include/linux/mfd/wm8350/core.h [new file with mode: 0644]
include/linux/mfd/wm8350/gpio.h [new file with mode: 0644]
include/linux/mfd/wm8350/pmic.h [new file with mode: 0644]
include/linux/mfd/wm8350/rtc.h [new file with mode: 0644]
include/linux/mfd/wm8350/supply.h [new file with mode: 0644]
include/linux/mfd/wm8350/wdt.h [new file with mode: 0644]
include/linux/mfd/wm8400-audio.h [new file with mode: 0644]
include/linux/mfd/wm8400-private.h [new file with mode: 0644]
include/linux/mfd/wm8400.h [new file with mode: 0644]
include/linux/mod_devicetable.h
include/linux/module.h
include/linux/mount.h
include/linux/netdevice.h
include/linux/netfilter/nfnetlink.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_mount.h
include/linux/nfs_xdr.h
include/linux/nfsd/nfsd.h
include/linux/of.h
include/linux/oprofile.h
include/linux/parport.h
include/linux/parser.h
include/linux/pci_ids.h
include/linux/pfn.h
include/linux/pid_namespace.h
include/linux/platform_device.h
include/linux/pm.h
include/linux/pnp.h
include/linux/proc_fs.h
include/linux/profile.h
include/linux/quota.h
include/linux/quotaops.h
include/linux/raid/linear.h
include/linux/raid/md.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h
include/linux/reiserfs_fs.h
include/linux/rtmutex.h
include/linux/serial.h
include/linux/serial_core.h
include/linux/spi/orion_spi.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svc_rdma.h
include/linux/sunrpc/svcsock.h
include/linux/sunrpc/xprtrdma.h
include/linux/swiotlb.h [new file with mode: 0644]
include/linux/sysctl.h
include/linux/sysfs.h
include/linux/task_io_accounting.h
include/linux/telephony.h
include/linux/termios.h
include/linux/time.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/types.h
include/linux/videodev2.h
include/linux/vt_kern.h
include/linux/wait.h
include/math-emu/op-2.h
include/math-emu/op-common.h
include/math-emu/soft-fp.h
include/media/ir-common.h
include/media/saa7115.h
include/media/saa7146.h
include/media/sh_mobile_ceu.h
include/media/soc_camera.h
include/media/tuner.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/media/v4l2-ioctl.h
include/net/9p/9p.h
include/net/bluetooth/bluetooth.h
include/net/cipso_ipv4.h
include/net/ieee80211.h
include/net/ip.h
include/net/ip_vs.h
include/net/irda/irda.h
include/net/mac80211.h
include/net/ndisc.h
include/net/netfilter/nf_nat_core.h
include/net/netlabel.h
include/net/sctp/sctp.h
include/pcmcia/ciscode.h
include/pcmcia/cistpl.h
include/pcmcia/cs.h
include/pcmcia/cs_types.h
include/pcmcia/device_id.h
include/pcmcia/ds.h
include/pcmcia/ss.h
include/sound/soc-dapm.h
include/sound/tea575x-tuner.h
include/video/cyblafb.h
include/video/neomagic.h
include/video/radeon.h
include/video/s1d13xxxfb.h
init/Kconfig
init/do_mounts_md.c
init/do_mounts_rd.c
init/initramfs.c
init/main.c
ipc/ipc_sysctl.c
ipc/sem.c
kernel/acct.c
kernel/auditsc.c
kernel/cgroup.c
kernel/compat.c
kernel/dma.c
kernel/exit.c
kernel/fork.c
kernel/kallsyms.c
kernel/kmod.c
kernel/kprobes.c
kernel/ksysfs.c
kernel/module.c
kernel/panic.c
kernel/power/disk.c
kernel/power/main.c
kernel/power/user.c
kernel/printk.c
kernel/profile.c
kernel/resource.c
kernel/sched_clock.c
kernel/sched_debug.c
kernel/softirq.c
kernel/softlockup.c
kernel/sys.c
kernel/sys_ni.c
kernel/sysctl.c
kernel/time/Kconfig
kernel/time/tick-sched.c
kernel/timer.c
kernel/utsname_sysctl.c
kernel/wait.c
kernel/workqueue.c
lib/Kconfig
lib/Kconfig.debug
lib/Makefile
lib/dynamic_printk.c [new file with mode: 0644]
lib/iommu-helper.c
lib/kobject.c
lib/parser.c
lib/vsprintf.c
mm/Kconfig
mm/bootmem.c
mm/fadvise.c
mm/filemap.c
mm/hugetlb.c
mm/page-writeback.c
mm/page_alloc.c
mm/pdflush.c
mm/readahead.c
mm/shmem.c
mm/truncate.c
net/802/fc.c
net/802/psnap.c
net/9p/client.c
net/9p/trans_fd.c
net/appletalk/ddp.c
net/bluetooth/af_bluetooth.c
net/bluetooth/hidp/core.c
net/bluetooth/hidp/hidp.h
net/bridge/netfilter/Kconfig
net/bridge/netfilter/ebtables.c
net/can/af_can.c
net/core/datagram.c
net/core/dev.c
net/core/dev_mcast.c
net/core/net_namespace.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/skb_dma_map.c
net/core/skbuff.c
net/core/stream.c
net/dccp/ccid.c
net/decnet/dn_dev.c
net/decnet/sysctl_net_decnet.c
net/dsa/Kconfig
net/ipv4/cipso_ipv4.c
net/ipv4/devinet.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/inet_diag.c
net/ipv4/ip_fragment.c
net/ipv4/ip_input.c
net/ipv4/ip_options.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv4/netfilter/nf_nat_core.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_cong.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ndisc.c
net/ipv6/netfilter.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/util.c
net/mac80211/wext.c
net/netfilter/nf_conntrack_acct.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_pptp.c
net/netfilter/nf_tproxy_core.c
net/netfilter/nfnetlink.c
net/netlabel/Makefile
net/netlabel/netlabel_addrlist.c [new file with mode: 0644]
net/netlabel/netlabel_addrlist.h [new file with mode: 0644]
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.h
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_mgmt.h
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/phonet/af_phonet.c
net/rfkill/rfkill-input.c
net/sched/act_api.c
net/sched/cls_api.c
net/sched/ematch.c
net/sched/sch_api.c
net/socket.c
net/sunrpc/auth.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c
net/unix/af_unix.c
net/wireless/core.c
scripts/Makefile.lib
scripts/basic/Makefile
scripts/basic/hash.c [new file with mode: 0644]
scripts/bootgraph.pl [new file with mode: 0644]
scripts/checkpatch.pl
scripts/mod/file2alias.c
security/inode.c
security/selinux/hooks.c
security/selinux/include/netlabel.h
security/selinux/include/objsec.h
security/selinux/netlabel.c
security/selinux/ss/services.c
security/smack/smack_lsm.c
security/smack/smackfs.c
sound/aoa/soundbus/soundbus.h
sound/arm/pxa2xx-ac97-lib.c
sound/core/init.c
sound/core/sound.c
sound/i2c/other/tea575x-tuner.c
sound/oss/ac97_codec.c
sound/oss/soundcard.c
sound/pci/ac97/ac97_patch.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/at91/Kconfig
sound/soc/at91/Makefile
sound/soc/at91/at91-ssc.c
sound/soc/at91/eti_b1_wm8731.c [deleted file]
sound/soc/blackfin/Kconfig
sound/soc/blackfin/Makefile
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ad73311.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-sport.h
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad73311.c [new file with mode: 0644]
sound/soc/codecs/ad73311.h [new file with mode: 0644]
sound/soc/codecs/ak4535.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/tlv320aic23.c [new file with mode: 0644]
sound/soc/codecs/tlv320aic23.h [new file with mode: 0644]
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8510.h
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8753.h
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/omap/osk5912.c [new file with mode: 0644]
sound/soc/pxa/corgi.c
sound/soc/pxa/em-x270.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/sound_core.c
sound/usb/usx2y/us122l.c
virt/kvm/ioapic.c
virt/kvm/ioapic.h
virt/kvm/irq_comm.c [new file with mode: 0644]
virt/kvm/kvm_main.c
virt/kvm/kvm_trace.c
virt/kvm/vtd.c [new file with mode: 0644]

index 73060819ed99c6889c716cf922e1997f37f4a0b0..7286ad090db7b81242b223786d897a4518db2a1d 100644 (file)
@@ -21,6 +21,9 @@ Changes
        - list of changes that break older software packages.
 CodingStyle
        - how the boss likes the C code in the kernel to look.
+development-process/
+       - An extended tutorial on how to work with the kernel development
+         process.
 DMA-API.txt
        - DMA API, pci_ API & extensions for non-consistent memory machines.
 DMA-ISA-LPC.txt
@@ -159,8 +162,6 @@ hayes-esp.txt
        - info on using the Hayes ESP serial driver.
 highuid.txt
        - notes on the change from 16 bit to 32 bit user/group IDs.
-hpet.txt
-       - High Precision Event Timer Driver for Linux.
 timers/
        - info on the timer related topics
 hw_random.txt
index 79a4a75b2d2ceb7af8e07c3efa6289c3722d6342..3731f6f29bcb3f07d5551d7fa41f00f8c0c0ed9a 100644 (file)
@@ -1,7 +1,7 @@
 What:          /sys/class/regulator/.../state
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                state. This holds the regulator output state.
@@ -27,7 +27,7 @@ Description:
 What:          /sys/class/regulator/.../type
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                type. This holds the regulator type.
@@ -51,7 +51,7 @@ Description:
 What:          /sys/class/regulator/.../microvolts
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                microvolts. This holds the regulator output voltage setting
@@ -65,7 +65,7 @@ Description:
 What:          /sys/class/regulator/.../microamps
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                microamps. This holds the regulator output current limit
@@ -79,7 +79,7 @@ Description:
 What:          /sys/class/regulator/.../opmode
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                opmode. This holds the regulator operating mode setting.
@@ -102,7 +102,7 @@ Description:
 What:          /sys/class/regulator/.../min_microvolts
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                min_microvolts. This holds the minimum safe working regulator
@@ -116,7 +116,7 @@ Description:
 What:          /sys/class/regulator/.../max_microvolts
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                max_microvolts. This holds the maximum safe working regulator
@@ -130,7 +130,7 @@ Description:
 What:          /sys/class/regulator/.../min_microamps
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                min_microamps. This holds the minimum safe working regulator
@@ -145,7 +145,7 @@ Description:
 What:          /sys/class/regulator/.../max_microamps
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                max_microamps. This holds the maximum safe working regulator
@@ -157,10 +157,23 @@ Description:
                platform code.
 
 
+What:          /sys/class/regulator/.../name
+Date:          October 2008
+KernelVersion: 2.6.28
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
+Description:
+               Each regulator directory will contain a field called
+               name. This holds a string identifying the regulator for
+               display purposes.
+
+               NOTE: this will be empty if no suitable name is provided
+               by platform or regulator drivers.
+
+
 What:          /sys/class/regulator/.../num_users
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                num_users. This holds the number of consumer devices that
@@ -170,7 +183,7 @@ Description:
 What:          /sys/class/regulator/.../requested_microamps
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                requested_microamps. This holds the total requested load
@@ -181,7 +194,7 @@ Description:
 What:          /sys/class/regulator/.../parent
 Date:          April 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Some regulator directories will contain a link called parent.
                This points to the parent or supply regulator if one exists.
@@ -189,7 +202,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_mem_microvolts
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_mem_microvolts. This holds the regulator output
@@ -203,7 +216,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_disk_microvolts
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_disk_microvolts. This holds the regulator output
@@ -217,7 +230,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_standby_microvolts
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_standby_microvolts. This holds the regulator output
@@ -231,7 +244,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_mem_mode
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_mem_mode. This holds the regulator operating mode
@@ -245,7 +258,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_disk_mode
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_disk_mode. This holds the regulator operating mode
@@ -258,7 +271,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_standby_mode
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_standby_mode. This holds the regulator operating mode
@@ -272,7 +285,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_mem_state
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_mem_state. This holds the regulator operating state
@@ -287,7 +300,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_disk_state
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_disk_state. This holds the regulator operating state
@@ -302,7 +315,7 @@ Description:
 What:          /sys/class/regulator/.../suspend_standby_state
 Date:          May 2008
 KernelVersion: 2.6.26
-Contact:       Liam Girdwood <lg@opensource.wolfsonmicro.com>
+Contact:       Liam Girdwood <lrg@slimlogic.co.uk>
 Description:
                Each regulator directory will contain a field called
                suspend_standby_state. This holds the regulator operating
diff --git a/Documentation/ABI/testing/sysfs-profiling b/Documentation/ABI/testing/sysfs-profiling
new file mode 100644 (file)
index 0000000..b02d8b8
--- /dev/null
@@ -0,0 +1,13 @@
+What:          /sys/kernel/profile
+Date:          September 2008
+Contact:       Dave Hansen <dave@linux.vnet.ibm.com>
+Description:
+               /sys/kernel/profile is the runtime equivalent
+               of the boot-time profile= option.
+
+               You can get the same effect running:
+
+                       echo 2 > /sys/kernel/profile
+
+               as you would by issuing profile=2 on the boot
+               command line.
index 1615350b7b53b4b681ed187e176e896ca0b0845e..fabc06466b93d69a842af47403e7b5f9c5977502 100644 (file)
@@ -6,7 +6,7 @@
 # To add a new book the only step required is to add the book to the
 # list of DOCBOOKS.
 
-DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
+DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml \
            kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
            procfs-guide.xml writing_usb_driver.xml networking.xml \
            kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
index 8a5dc6e021ffa8b16b6dc2f997e115e77b1aaf70..9eba4b7af73de9dd5d6d83086c374c07efb5a1bc 100644 (file)
        <othername>(J.A.K.)</othername>
        <surname>Mouw</surname>
        <affiliation>
-         <orgname>Delft University of Technology</orgname>
-         <orgdiv>Faculty of Information Technology and Systems</orgdiv>
          <address>
-            <email>J.A.K.Mouw@its.tudelft.nl</email>
-            <pob>PO BOX 5031</pob>
-            <postcode>2600 GA</postcode>
-            <city>Delft</city>
-            <country>The Netherlands</country>
+            <email>mouw@nl.linux.org</email>
           </address>
        </affiliation>
       </author>
+      <othercredit>
+       <contrib>
+       This software and documentation were written while working on the
+       LART computing board
+       (<ulink url="http://www.lartmaker.nl/">http://www.lartmaker.nl/</ulink>),
+       which was sponsored by the Delt University of Technology projects
+       Mobile Multi-media Communications and Ubiquitous Communications.
+       </contrib>
+      </othercredit>
     </authorgroup>
 
     <revhistory>
       proofreading.
     </para>
 
-    <para>
-      This documentation was written while working on the LART
-      computing board (<ulink
-      url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>),
-      which is sponsored by the Mobile Multi-media Communications
-      (<ulink
-      url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>)
-      and Ubiquitous Communications (<ulink
-      url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>)
-      projects.
-    </para>
-
     <para>
       Erik
     </para>
index 2f3de0fb83651779e3c849c8ec2c9706c13a2ac4..8c6396e4bf311901a19fd717500c422eeba4869a 100644 (file)
@@ -1,28 +1,16 @@
 /*
  * procfs_example.c: an example proc interface
  *
- * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ * Copyright (C) 2001, Erik Mouw (mouw@nl.linux.org)
  *
  * This file accompanies the procfs-guide in the Linux kernel
  * source. Its main use is to demonstrate the concepts and
  * functions described in the guide.
  *
  * This software has been developed while working on the LART
- * computing board (http://www.lart.tudelft.nl/), which is
- * sponsored by the Mobile Multi-media Communications
- * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications 
- * (http://www.ubicom.tudelft.nl/) projects.
- *
- * The author can be reached at:
- *
- *  Erik Mouw
- *  Information and Communication Theory Group
- *  Faculty of Information Technology and Systems
- *  Delft University of Technology
- *  P.O. Box 5031
- *  2600 GA Delft
- *  The Netherlands
- *
+ * computing board (http://www.lartmaker.nl), which was sponsored
+ * by the Delt University of Technology projects Mobile Multi-media
+ * Communications and Ubiquitous Communications.
  *
  * This program is free software; you can redistribute
  * it and/or modify it under the terms of the GNU General
diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
deleted file mode 100644 (file)
index 0bc2594..0000000
+++ /dev/null
@@ -1,1654 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="V4LGuide">
- <bookinfo>
-  <title>Video4Linux Programming</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Alan</firstname>
-    <surname>Cox</surname>
-    <affiliation>
-     <address>
-      <email>alan@redhat.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2000</year>
-   <holder>Alan Cox</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-      
-   <para>
-     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.
-   </para>
-      
-   <para>
-     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
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-  <chapter id="intro">
-      <title>Introduction</title>
-  <para>
-        Parts of this document first appeared in Linux Magazine under a
-        ninety day exclusivity.
-  </para>
-  <para>
-        Video4Linux is intended to provide a common programming interface
-        for the many TV and capture cards now on the market, as well as
-        parallel port and USB video cameras. Radio, teletext decoders and
-        vertical blanking data interfaces are also provided.
-  </para>
-  </chapter>
-  <chapter id="radio">
-        <title>Radio Devices</title>
-  <para>
-        There are a wide variety of radio interfaces available for PC's, and these
-        are generally very simple to program. The biggest problem with supporting
-        such devices is normally extracting documentation from the vendor.
-  </para>
-  <para>
-        The radio interface supports a simple set of control ioctls standardised
-        across all radio and tv interfaces. It does not support read or write, which
-        are used for video streams. The reason radio cards do not allow you to read
-        the audio stream into an application is that without exception they provide
-        a connection on to a soundcard. Soundcards can be used to read the radio
-        data just fine. 
-  </para>
-  <sect1 id="registerradio">
-  <title>Registering Radio Devices</title>
-  <para>
-        The Video4linux core provides an interface for registering devices. The
-        first step in writing our radio card driver is to register it.
-  </para>
-  <programlisting>
-
-
-static struct video_device my_radio
-{
-        "My radio",
-        VID_TYPE_TUNER,
-        radio_open.
-        radio_close,
-        NULL,                /* no read */
-        NULL,                 /* no write */
-        NULL,                /* no poll */
-        radio_ioctl,
-        NULL,                /* no special init function */
-        NULL                /* no private data */
-};
-
-
-  </programlisting>
-  <para>
-        This declares our video4linux device driver interface. The VID_TYPE_ value
-        defines what kind of an interface we are, and defines basic capabilities.
-  </para>
-  <para>
-        The only defined value relevant for a radio card is VID_TYPE_TUNER which
-        indicates that the device can be tuned. Clearly our radio is going to have some
-        way to change channel so it is tuneable.
-  </para>
-  <para>
-        We declare an open and close routine, but we do not need read or write,
-        which are used to read and write video data to or from the card itself. As
-        we have no read or write there is no poll function.
-  </para>
-  <para>
-        The private initialise function is run when the device is registered. In
-        this driver we've already done all the work needed. The final pointer is a
-        private data pointer that can be used by the device driver to attach and
-        retrieve private data structures. We set this field "priv" to NULL for
-        the moment.
-  </para>
-  <para>
-        Having the structure defined is all very well but we now need to register it
-        with the kernel. 
-  </para>
-  <programlisting>
-
-
-static int io = 0x320;
-
-int __init myradio_init(struct video_init *v)
-{
-        if(!request_region(io, MY_IO_SIZE, "myradio"))
-        {
-                printk(KERN_ERR 
-                    "myradio: port 0x%03X is in use.\n", io);
-                return -EBUSY;
-        }
-
-        if(video_device_register(&amp;my_radio, VFL_TYPE_RADIO)==-1) {
-                release_region(io, MY_IO_SIZE);
-                return -EINVAL;
-        }              
-        return 0;
-}
-
-  </programlisting>
-  <para>
-        The first stage of the initialisation, as is normally the case, is to check 
-        that the I/O space we are about to fiddle with doesn't belong to some other 
-        driver. If it is we leave well alone. If the user gives the address of the 
-        wrong device then we will spot this. These policies will generally avoid 
-        crashing the machine.
-  </para>
-  <para>
-        Now we ask the Video4Linux layer to register the device for us. We hand it
-        our carefully designed video_device structure and also tell it which group
-        of devices we want it registered with. In this case VFL_TYPE_RADIO.
-  </para>
-  <para>
-        The types available are
-  </para>
-   <table frame="all" id="Device_Types"><title>Device Types</title>
-   <tgroup cols="3" align="left">
-   <tbody>
-   <row>
-        <entry>VFL_TYPE_RADIO</entry><entry>/dev/radio{n}</entry><entry>
-
-        Radio devices are assigned in this block. As with all of these
-        selections the actual number assignment is done by the video layer
-        accordijng to what is free.</entry>
-       </row><row>
-        <entry>VFL_TYPE_GRABBER</entry><entry>/dev/video{n}</entry><entry>
-        Video capture devices and also -- counter-intuitively for the name --
-        hardware video playback devices such as MPEG2 cards.</entry>
-       </row><row>
-        <entry>VFL_TYPE_VBI</entry><entry>/dev/vbi{n}</entry><entry>
-        The VBI devices capture the hidden lines on a television picture
-        that carry further information like closed caption data, teletext
-        (primarily in Europe) and now Intercast and the ATVEC internet
-        television encodings.</entry>
-       </row><row>
-        <entry>VFL_TYPE_VTX</entry><entry>/dev/vtx[n}</entry><entry>
-        VTX is 'Videotext' also known as 'Teletext'. This is a system for
-        sending numbered, 40x25, mostly textual page images over the hidden
-        lines. Unlike the /dev/vbi interfaces, this is for 'smart' decoder 
-        chips. (The use of the word smart here has to be taken in context,
-        the smartest teletext chips are fairly dumb pieces of technology).
-       </entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-  <para>
-        We are most definitely a radio.
-  </para>
-  <para>
-        Finally we allocate our I/O space so that nobody treads on us and return 0
-        to signify general happiness with the state of the universe.
-  </para>
-  </sect1>
-  <sect1 id="openradio">
-  <title>Opening And Closing The Radio</title>
-
-  <para>
-        The functions we declared in our video_device are mostly very simple.
-        Firstly we can drop in what is basically standard code for open and close. 
-  </para>
-  <programlisting>
-
-
-static int users = 0;
-
-static int radio_open(struct video_device *dev, int flags)
-{
-        if(users)
-                return -EBUSY;
-        users++;
-        return 0;
-}
-
-  </programlisting>
-  <para>
-        At open time we need to do nothing but check if someone else is also using
-        the radio card. If nobody is using it we make a note that we are using it,
-        then we ensure that nobody unloads our driver on us.
-  </para>
-  <programlisting>
-
-
-static int radio_close(struct video_device *dev)
-{
-        users--;
-}
-
-  </programlisting>
-  <para>
-        At close time we simply need to reduce the user count and allow the module
-        to become unloadable.
-  </para>
-  <para>
-        If you are sharp you will have noticed neither the open nor the close
-        routines attempt to reset or change the radio settings. This is intentional.
-        It allows an application to set up the radio and exit. It avoids a user
-        having to leave an application running all the time just to listen to the
-        radio. 
-  </para>
-  </sect1>
-  <sect1 id="ioctlradio">
-  <title>The Ioctl Interface</title>
-  <para>
-        This leaves the ioctl routine, without which the driver will not be
-        terribly useful to anyone.
-  </para>
-  <programlisting>
-
-
-static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
-        switch(cmd)
-        {
-                case VIDIOCGCAP:
-                {
-                        struct video_capability v;
-                        v.type = VID_TYPE_TUNER;
-                        v.channels = 1;
-                        v.audios = 1;
-                        v.maxwidth = 0;
-                        v.minwidth = 0;
-                        v.maxheight = 0;
-                        v.minheight = 0;
-                        strcpy(v.name, "My Radio");
-                        if(copy_to_user(arg, &amp;v, sizeof(v)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        VIDIOCGCAP is the first ioctl all video4linux devices must support. It
-        allows the applications to find out what sort of a card they have found and
-        to figure out what they want to do about it. The fields in the structure are
-  </para>
-   <table frame="all" id="video_capability_fields"><title>struct video_capability fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-        <entry>name</entry><entry>The device text name. This is intended for the user.</entry>
-       </row><row>
-        <entry>channels</entry><entry>The number of different channels you can tune on
-                        this card. It could even by zero for a card that has
-                        no tuning capability. For our simple FM radio it is 1. 
-                        An AM/FM radio would report 2.</entry>
-       </row><row>
-        <entry>audios</entry><entry>The number of audio inputs on this device. For our
-                        radio there is only one audio input.</entry>
-       </row><row>
-        <entry>minwidth,minheight</entry><entry>The smallest size the card is capable of capturing
-                       images in. We set these to zero. Radios do not
-                        capture pictures</entry>
-       </row><row>
-        <entry>maxwidth,maxheight</entry><entry>The largest image size the card is capable of
-                                      capturing. For our radio we report 0.
-                               </entry>
-       </row><row>
-        <entry>type</entry><entry>This reports the capabilities of the device, and
-                        matches the field we filled in in the struct
-                        video_device when registering.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-  <para>
-        Having filled in the fields, we use copy_to_user to copy the structure into
-        the users buffer. If the copy fails we return an EFAULT to the application
-        so that it knows it tried to feed us garbage.
-  </para>
-  <para>
-        The next pair of ioctl operations select which tuner is to be used and let
-        the application find the tuner properties. We have only a single FM band
-        tuner in our example device.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCGTUNER:
-                {
-                        struct video_tuner v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v))!=0)
-                                return -EFAULT;
-                        if(v.tuner)
-                                return -EINVAL;
-                        v.rangelow=(87*16000);
-                        v.rangehigh=(108*16000);
-                        v.flags = VIDEO_TUNER_LOW;
-                        v.mode = VIDEO_MODE_AUTO;
-                        v.signal = 0xFFFF;
-                        strcpy(v.name, "FM");
-                        if(copy_to_user(&amp;v, arg, sizeof(v))!=0)
-                                return -EFAULT;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        The VIDIOCGTUNER ioctl allows applications to query a tuner. The application
-        sets the tuner field to the tuner number it wishes to query. The query does
-        not change the tuner that is being used, it merely enquires about the tuner
-        in question.
-  </para>
-  <para>
-        We have exactly one tuner so after copying the user buffer to our temporary
-        structure we complain if they asked for a tuner other than tuner 0. 
-  </para>
-  <para>
-        The video_tuner structure has the following fields
-  </para>
-   <table frame="all" id="video_tuner_fields"><title>struct video_tuner fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-        <entry>int tuner</entry><entry>The number of the tuner in question</entry>
-   </row><row>
-        <entry>char name[32]</entry><entry>A text description of this tuner. "FM" will do fine.
-                        This is intended for the application.</entry>
-   </row><row>
-        <entry>u32 flags</entry>
-        <entry>Tuner capability flags</entry>
-   </row>
-   <row>
-        <entry>u16 mode</entry><entry>The current reception mode</entry>
-
-   </row><row>
-        <entry>u16 signal</entry><entry>The signal strength scaled between 0 and 65535. If
-                        a device cannot tell the signal strength it should
-                        report 65535. Many simple cards contain only a 
-                        signal/no signal bit. Such cards will report either
-                        0 or 65535.</entry>
-
-   </row><row>
-        <entry>u32 rangelow, rangehigh</entry><entry>
-                        The range of frequencies supported by the radio
-                        or TV. It is scaled according to the VIDEO_TUNER_LOW
-                        flag.</entry>
-
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-
-   <table frame="all" id="video_tuner_flags"><title>struct video_tuner flags</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-       <entry>VIDEO_TUNER_PAL</entry><entry>A PAL TV tuner</entry>
-       </row><row>
-        <entry>VIDEO_TUNER_NTSC</entry><entry>An NTSC (US) TV tuner</entry>
-       </row><row>
-        <entry>VIDEO_TUNER_SECAM</entry><entry>A SECAM (French) TV tuner</entry>
-       </row><row>
-        <entry>VIDEO_TUNER_LOW</entry><entry>
-             The tuner frequency is scaled in 1/16th of a KHz
-             steps. If not it is in 1/16th of a MHz steps
-       </entry>
-       </row><row>
-        <entry>VIDEO_TUNER_NORM</entry><entry>The tuner can set its format</entry>
-       </row><row>
-        <entry>VIDEO_TUNER_STEREO_ON</entry><entry>The tuner is currently receiving a stereo signal</entry>
-        </row>
-    </tbody>
-    </tgroup>
-    </table>
-
-   <table frame="all" id="video_tuner_modes"><title>struct video_tuner modes</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-                <entry>VIDEO_MODE_PAL</entry><entry>PAL Format</entry>
-   </row><row>
-                <entry>VIDEO_MODE_NTSC</entry><entry>NTSC Format (USA)</entry>
-   </row><row>
-                <entry>VIDEO_MODE_SECAM</entry><entry>French Format</entry>
-   </row><row>
-                <entry>VIDEO_MODE_AUTO</entry><entry>A device that does not need to do
-                                        TV format switching</entry>
-   </row>
-    </tbody>
-    </tgroup>
-    </table>
-  <para>
-        The settings for the radio card are thus fairly simple. We report that we
-        are a tuner called "FM" for FM radio. In order to get the best tuning
-        resolution we report VIDEO_TUNER_LOW and select tuning to 1/16th of KHz. Its
-        unlikely our card can do that resolution but it is a fair bet the card can
-        do better than 1/16th of a MHz. VIDEO_TUNER_LOW is appropriate to almost all
-        radio usage.
-  </para>
-  <para>
-        We report that the tuner automatically handles deciding what format it is
-        receiving - true enough as it only handles FM radio. Our example card is
-        also incapable of detecting stereo or signal strengths so it reports a
-        strength of 0xFFFF (maximum) and no stereo detected.
-  </para>
-  <para>
-        To finish off we set the range that can be tuned to be 87-108Mhz, the normal
-        FM broadcast radio range. It is important to find out what the card is
-        actually capable of tuning. It is easy enough to simply use the FM broadcast
-        range. Unfortunately if you do this you will discover the FM broadcast
-        ranges in the USA, Europe and Japan are all subtly different and some users
-        cannot receive all the stations they wish.
-  </para>
-  <para>
-        The application also needs to be able to set the tuner it wishes to use. In
-        our case, with a single tuner this is rather simple to arrange.
-  </para>
-  <programlisting>
-
-                case VIDIOCSTUNER:
-                {
-                        struct video_tuner v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.tuner != 0)
-                                return -EINVAL;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        We copy the user supplied structure into kernel memory so we can examine it. 
-        If the user has selected a tuner other than zero we reject the request. If 
-        they wanted tuner 0 then, surprisingly enough, that is the current tuner already.
-  </para>
-  <para>
-        The next two ioctls we need to provide are to get and set the frequency of
-        the radio. These both use an unsigned long argument which is the frequency.
-        The scale of the frequency depends on the VIDEO_TUNER_LOW flag as I
-        mentioned earlier on. Since we have VIDEO_TUNER_LOW set this will be in
-        1/16ths of a KHz.
-  </para>
-  <programlisting>
-
-static unsigned long current_freq;
-
-
-
-                case VIDIOCGFREQ:
-                        if(copy_to_user(arg, &amp;current_freq, 
-                                sizeof(unsigned long))
-                                return -EFAULT;
-                        return 0;
-
-  </programlisting>
-  <para>
-        Querying the frequency in our case is relatively simple. Our radio card is
-        too dumb to let us query the signal strength so we remember our setting if 
-        we know it. All we have to do is copy it to the user.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCSFREQ:
-                {
-                        u32 freq;
-                        if(copy_from_user(arg, &amp;freq, 
-                                sizeof(unsigned long))!=0)
-                                return -EFAULT;
-                        if(hardware_set_freq(freq)&lt;0)
-                                return -EINVAL;
-                        current_freq = freq;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        Setting the frequency is a little more complex. We begin by copying the
-        desired frequency into kernel space. Next we call a hardware specific routine
-        to set the radio up. This might be as simple as some scaling and a few
-        writes to an I/O port. For most radio cards it turns out a good deal more
-        complicated and may involve programming things like a phase locked loop on
-        the card. This is what documentation is for. 
-  </para>
-  <para>
-        The final set of operations we need to provide for our radio are the 
-        volume controls. Not all radio cards can even do volume control. After all
-        there is a perfectly good volume control on the sound card. We will assume
-        our radio card has a simple 4 step volume control.
-  </para>
-  <para>
-        There are two ioctls with audio we need to support
-  </para>
-  <programlisting>
-
-static int current_volume=0;
-
-                case VIDIOCGAUDIO:
-                {
-                        struct video_audio v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.audio != 0)
-                                return -EINVAL;
-                        v.volume = 16384*current_volume;
-                        v.step = 16384;
-                        strcpy(v.name, "Radio");
-                        v.mode = VIDEO_SOUND_MONO;
-                        v.balance = 0;
-                        v.base = 0;
-                        v.treble = 0;
-                        
-                        if(copy_to_user(arg. &amp;v, sizeof(v)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        Much like the tuner we start by copying the user structure into kernel
-        space. Again we check if the user has asked for a valid audio input. We have
-        only input 0 and we punt if they ask for another input.
-  </para>
-  <para>
-        Then we fill in the video_audio structure. This has the following format
-  </para>
-   <table frame="all" id="video_audio_fields"><title>struct video_audio fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-   <entry>audio</entry><entry>The input the user wishes to query</entry>
-   </row><row>
-   <entry>volume</entry><entry>The volume setting on a scale of 0-65535</entry>
-   </row><row>
-   <entry>base</entry><entry>The base level on a scale of 0-65535</entry>
-   </row><row>
-   <entry>treble</entry><entry>The treble level on a scale of 0-65535</entry>
-   </row><row>
-   <entry>flags</entry><entry>The features this audio device supports
-   </entry>
-   </row><row>
-   <entry>name</entry><entry>A text name to display to the user. We picked
-                        "Radio" as it explains things quite nicely.</entry>
-   </row><row>
-   <entry>mode</entry><entry>The current reception mode for the audio
-
-                We report MONO because our card is too stupid to know if it is in
-                mono or stereo. 
-   </entry>
-   </row><row>
-   <entry>balance</entry><entry>The stereo balance on a scale of 0-65535, 32768 is
-                        middle.</entry>
-   </row><row>
-   <entry>step</entry><entry>The step by which the volume control jumps. This is
-                        used to help make it easy for applications to set 
-                        slider behaviour.</entry>
-   </row>
-   </tbody>
-   </tgroup>
-   </table>
-
-   <table frame="all" id="video_audio_flags"><title>struct video_audio flags</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-                <entry>VIDEO_AUDIO_MUTE</entry><entry>The audio is currently muted. We
-                                        could fake this in our driver but we
-                                        choose not to bother.</entry>
-   </row><row>
-                <entry>VIDEO_AUDIO_MUTABLE</entry><entry>The input has a mute option</entry>
-   </row><row>
-                <entry>VIDEO_AUDIO_TREBLE</entry><entry>The  input has a treble control</entry>
-   </row><row>
-                <entry>VIDEO_AUDIO_BASS</entry><entry>The input has a base control</entry>
-   </row>
-   </tbody>
-   </tgroup>
-   </table>
-
-   <table frame="all" id="video_audio_modes"><title>struct video_audio modes</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-                <entry>VIDEO_SOUND_MONO</entry><entry>Mono sound</entry>
-   </row><row>
-                <entry>VIDEO_SOUND_STEREO</entry><entry>Stereo sound</entry>
-   </row><row>
-                <entry>VIDEO_SOUND_LANG1</entry><entry>Alternative language 1 (TV specific)</entry>
-   </row><row>
-                <entry>VIDEO_SOUND_LANG2</entry><entry>Alternative language 2 (TV specific)</entry>
-   </row>
-   </tbody>
-   </tgroup>
-   </table>
-  <para>
-        Having filled in the structure we copy it back to user space.
-  </para>
-  <para>
-        The VIDIOCSAUDIO ioctl allows the user to set the audio parameters in the
-        video_audio structure. The driver does its best to honour the request.
-  </para>
-  <programlisting>
-
-                case VIDIOCSAUDIO:
-                {
-                        struct video_audio v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.audio)
-                                return -EINVAL;
-                        current_volume = v/16384;
-                        hardware_set_volume(current_volume);
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        In our case there is very little that the user can set. The volume is
-        basically the limit. Note that we could pretend to have a mute feature
-        by rewriting this to 
-  </para>
-  <programlisting>
-
-                case VIDIOCSAUDIO:
-                {
-                        struct video_audio v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.audio)
-                                return -EINVAL;
-                        current_volume = v/16384;
-                        if(v.flags&amp;VIDEO_AUDIO_MUTE)
-                                hardware_set_volume(0);
-                        else
-                                hardware_set_volume(current_volume);
-                        current_muted = v.flags &amp; 
-                                              VIDEO_AUDIO_MUTE;
-                        return 0;
-                }
-
-  </programlisting>
-  <para>
-        This with the corresponding changes to the VIDIOCGAUDIO code to report the
-        state of the mute flag we save and to report the card has a mute function,
-        will allow applications to use a mute facility with this card. It is
-        questionable whether this is a good idea however. User applications can already
-        fake this themselves and kernel space is precious.
-  </para>
-  <para>
-        We now have a working radio ioctl handler. So we just wrap up the function
-  </para>
-  <programlisting>
-
-
-        }
-        return -ENOIOCTLCMD;
-}
-
-  </programlisting>
-  <para>
-        and pass the Video4Linux layer back an error so that it knows we did not
-        understand the request we got passed.
-  </para>
-  </sect1>
-  <sect1 id="modradio">
-  <title>Module Wrapper</title>
-  <para>
-        Finally we add in the usual module wrapping and the driver is done.
-  </para>
-  <programlisting>
-
-#ifndef MODULE
-
-static int io = 0x300;
-
-#else
-
-static int io = -1;
-
-#endif
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("A driver for an imaginary radio card.");
-module_param(io, int, 0444);
-MODULE_PARM_DESC(io, "I/O address of the card.");
-
-static int __init init(void)
-{
-        if(io==-1)
-        {
-                printk(KERN_ERR 
-         "You must set an I/O address with io=0x???\n");
-                return -EINVAL;
-        }
-        return myradio_init(NULL);
-}
-
-static void __exit cleanup(void)
-{
-        video_unregister_device(&amp;my_radio);
-        release_region(io, MY_IO_SIZE);
-}
-
-module_init(init);
-module_exit(cleanup);
-
-  </programlisting>
-  <para>
-        In this example we set the IO base by default if the driver is compiled into
-        the kernel: you can still set it using "my_radio.irq" if this file is called <filename>my_radio.c</filename>. For the module we require the
-        user sets the parameter. We set io to a nonsense port (-1) so that we can
-        tell if the user supplied an io parameter or not.
-  </para>
-  <para>
-        We use MODULE_ defines to give an author for the card driver and a
-        description. We also use them to declare that io is an integer and it is the
-        address of the card, and can be read by anyone from sysfs.
-  </para>
-  <para>
-        The clean-up routine unregisters the video_device we registered, and frees
-        up the I/O space. Note that the unregister takes the actual video_device
-        structure as its argument. Unlike the file operations structure which can be
-        shared by all instances of a device a video_device structure as an actual
-        instance of the device. If you are registering multiple radio devices you
-        need to fill in one structure per device (most likely by setting up a
-        template and copying it to each of the actual device structures).
-  </para>
-  </sect1>
-  </chapter>
-  <chapter id="Video_Capture_Devices">
-        <title>Video Capture Devices</title>
-  <sect1 id="introvid">
-  <title>Video Capture Device Types</title>
-  <para>
-        The video capture devices share the same interfaces as radio devices. In
-        order to explain the video capture interface I will use the example of a
-        camera that has no tuners or audio input. This keeps the example relatively
-        clean. To get both combine the two driver examples.
-  </para>
-  <para>
-        Video capture devices divide into four categories. A little technology
-        backgrounder. Full motion video even at television resolution (which is
-        actually fairly low) is pretty resource-intensive. You are continually
-        passing megabytes of data every second from the capture card to the display. 
-        several alternative approaches have emerged because copying this through the 
-        processor and the user program is a particularly bad idea .
-  </para>
-  <para>
-        The first is to add the television image onto the video output directly.
-        This is also how some 3D cards work. These basic cards can generally drop the
-        video into any chosen rectangle of the display. Cards like this, which
-        include most mpeg1 cards that used the feature connector,  aren't very
-        friendly in a windowing environment. They don't understand windows or
-        clipping. The video window is always on the top of the display.
-  </para>
-  <para>
-        Chroma keying is a technique used by cards to get around this. It is an old
-        television mixing trick where you mark all the areas you wish to replace
-        with a single clear colour that isn't used in the image - TV people use an
-        incredibly bright blue while computing people often use a particularly
-        virulent purple. Bright blue occurs on the desktop. Anyone with virulent
-        purple windows has another problem besides their TV overlay.
-  </para>
-  <para>
-        The third approach is to copy the data from the capture card to the video
-        card, but to do it directly across the PCI bus. This relieves the processor
-        from doing the work but does require some smartness on the part of the video
-        capture chip, as well as a suitable video card. Programming this kind of
-        card and more so debugging it can be extremely tricky. There are some quite
-        complicated interactions with the display and you may also have to cope with
-        various chipset bugs that show up when PCI cards start talking to each
-        other. 
-  </para>
-  <para>
-        To keep our example fairly simple we will assume a card that supports
-        overlaying a flat rectangular image onto the frame buffer output, and which
-        can also capture stuff into processor memory.
-  </para>
-  </sect1>
-  <sect1 id="regvid">
-  <title>Registering Video Capture Devices</title>
-  <para>
-        This time we need to add more functions for our camera device.
-  </para>
-  <programlisting>
-static struct video_device my_camera
-{
-        "My Camera",
-        VID_TYPE_OVERLAY|VID_TYPE_SCALES|\
-        VID_TYPE_CAPTURE|VID_TYPE_CHROMAKEY,
-        camera_open.
-        camera_close,
-        camera_read,      /* no read */
-        NULL,             /* no write */
-        camera_poll,      /* no poll */
-        camera_ioctl,
-        NULL,             /* no special init function */
-        NULL              /* no private data */
-};
-  </programlisting>
-  <para>
-        We need a read() function which is used for capturing data from
-        the card, and we need a poll function so that a driver can wait for the next
-        frame to be captured.
-  </para>
-  <para>
-        We use the extra video capability flags that did not apply to the
-        radio interface. The video related flags are
-  </para>
-   <table frame="all" id="Capture_Capabilities"><title>Capture Capabilities</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-<entry>VID_TYPE_CAPTURE</entry><entry>We support image capture</entry>
-</row><row>
-<entry>VID_TYPE_TELETEXT</entry><entry>A teletext capture device (vbi{n])</entry>
-</row><row>
-<entry>VID_TYPE_OVERLAY</entry><entry>The image can be directly overlaid onto the
-                                frame buffer</entry>
-</row><row>
-<entry>VID_TYPE_CHROMAKEY</entry><entry>Chromakey can be used to select which parts
-                                of the image to display</entry>
-</row><row>
-<entry>VID_TYPE_CLIPPING</entry><entry>It is possible to give the board a list of
-                                rectangles to draw around. </entry>
-</row><row>
-<entry>VID_TYPE_FRAMERAM</entry><entry>The video capture goes into the video memory
-                                and actually changes it. Applications need
-                                to know this so they can clean up after the
-                                card</entry>
-</row><row>
-<entry>VID_TYPE_SCALES</entry><entry>The image can be scaled to various sizes,
-                                rather than being a single fixed size.</entry>
-</row><row>
-<entry>VID_TYPE_MONOCHROME</entry><entry>The capture will be monochrome. This isn't a
-                                complete answer to the question since a mono
-                                camera on a colour capture card will still
-                                produce mono output.</entry>
-</row><row>
-<entry>VID_TYPE_SUBCAPTURE</entry><entry>The card allows only part of its field of
-                                view to be captured. This enables
-                                applications to avoid copying all of a large
-                                image into memory when only some section is
-                                relevant.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-  <para>
-        We set VID_TYPE_CAPTURE so that we are seen as a capture card,
-        VID_TYPE_CHROMAKEY so the application knows it is time to draw in virulent
-        purple, and VID_TYPE_SCALES because we can be resized.
-  </para>
-  <para>
-        Our setup is fairly similar. This time we also want an interrupt line
-        for the 'frame captured' signal. Not all cards have this so some of them
-        cannot handle poll().
-  </para>
-  <programlisting>
-
-
-static int io = 0x320;
-static int irq = 11;
-
-int __init mycamera_init(struct video_init *v)
-{
-        if(!request_region(io, MY_IO_SIZE, "mycamera"))
-        {
-                printk(KERN_ERR 
-                      "mycamera: port 0x%03X is in use.\n", io);
-                return -EBUSY;
-        }
-
-        if(video_device_register(&amp;my_camera, 
-            VFL_TYPE_GRABBER)==-1) {
-                release_region(io, MY_IO_SIZE);
-                return -EINVAL;
-        }
-        return 0;
-}
-
-  </programlisting>
-  <para>
-        This is little changed from the needs of the radio card. We specify
-        VFL_TYPE_GRABBER this time as we want to be allocated a /dev/video name.
-  </para>
-  </sect1>
-  <sect1 id="opvid">
-  <title>Opening And Closing The Capture Device</title>
-  <programlisting>
-
-
-static int users = 0;
-
-static int camera_open(struct video_device *dev, int flags)
-{
-        if(users)
-                return -EBUSY;
-        if(request_irq(irq, camera_irq, 0, "camera", dev)&lt;0)
-                return -EBUSY;
-        users++;
-        return 0;
-}
-
-
-static int camera_close(struct video_device *dev)
-{
-        users--;
-        free_irq(irq, dev);
-}
-  </programlisting>
-  <para>
-        The open and close routines are also quite similar. The only real change is
-        that we now request an interrupt for the camera device interrupt line. If we
-        cannot get the interrupt we report EBUSY to the application and give up.
-  </para>
-  </sect1>
-  <sect1 id="irqvid">
-  <title>Interrupt Handling</title>
-  <para>
-        Our example handler is for an ISA bus device. If it was PCI you would be
-        able to share the interrupt and would have set IRQF_SHARED to indicate a
-        shared IRQ. We pass the device pointer as the interrupt routine argument. We
-        don't need to since we only support one card but doing this will make it
-        easier to upgrade the driver for multiple devices in the future.
-  </para>
-  <para>
-        Our interrupt routine needs to do little if we assume the card can simply
-        queue one frame to be read after it captures it. 
-  </para>
-  <programlisting>
-
-
-static struct wait_queue *capture_wait;
-static int capture_ready = 0;
-
-static void camera_irq(int irq, void *dev_id, 
-                          struct pt_regs *regs)
-{
-        capture_ready=1;
-        wake_up_interruptible(&amp;capture_wait);
-}
-  </programlisting>
-  <para>
-        The interrupt handler is nice and simple for this card as we are assuming
-        the card is buffering the frame for us. This means we have little to do but
-        wake up        anybody interested. We also set a capture_ready flag, as we may
-        capture a frame before an application needs it. In this case we need to know
-        that a frame is ready. If we had to collect the frame on the interrupt life
-        would be more complex.
-  </para>
-  <para>
-        The two new routines we need to supply are camera_read which returns a
-        frame, and camera_poll which waits for a frame to become ready.
-  </para>
-  <programlisting>
-
-
-static int camera_poll(struct video_device *dev, 
-       struct file *file, struct poll_table *wait)
-{
-        poll_wait(file, &amp;capture_wait, wait);
-        if(capture_read)
-                return POLLIN|POLLRDNORM;
-        return 0;
-}
-
-  </programlisting>
-  <para>
-        Our wait queue for polling is the capture_wait queue. This will cause the
-        task to be woken up by our camera_irq routine. We check capture_read to see
-        if there is an image present and if so report that it is readable.
-  </para>
-  </sect1>
-  <sect1 id="rdvid">
-  <title>Reading The Video Image</title>
-  <programlisting>
-
-
-static long camera_read(struct video_device *dev, char *buf,
-                                unsigned long count)
-{
-        struct wait_queue wait = { current, NULL };
-        u8 *ptr;
-        int len;
-        int i;
-
-        add_wait_queue(&amp;capture_wait, &amp;wait);
-
-        while(!capture_ready)
-        {
-                if(file->flags&amp;O_NDELAY)
-                {
-                        remove_wait_queue(&amp;capture_wait, &amp;wait);
-                        current->state = TASK_RUNNING;
-                        return -EWOULDBLOCK;
-                }
-                if(signal_pending(current))
-                {
-                        remove_wait_queue(&amp;capture_wait, &amp;wait);
-                        current->state = TASK_RUNNING;
-                        return -ERESTARTSYS;
-                }
-                schedule();
-                current->state = TASK_INTERRUPTIBLE;
-        }
-        remove_wait_queue(&amp;capture_wait, &amp;wait);
-        current->state = TASK_RUNNING;
-
-  </programlisting>
-  <para>
-        The first thing we have to do is to ensure that the application waits until
-        the next frame is ready. The code here is almost identical to the mouse code
-        we used earlier in this chapter. It is one of the common building blocks of
-        Linux device driver code and probably one which you will find occurs in any
-        drivers you write.
-  </para>
-  <para>
-        We wait for a frame to be ready, or for a signal to interrupt our waiting. If a
-        signal occurs we need to return from the system call so that the signal can
-        be sent to the application itself. We also check to see if the user actually
-        wanted to avoid waiting - ie  if they are using non-blocking I/O and have other things 
-        to get on with.
-  </para>
-  <para>
-        Next we copy the data from the card to the user application. This is rarely
-        as easy as our example makes out. We will add capture_w, and capture_h here
-        to hold the width and height of the captured image. We assume the card only
-        supports 24bit RGB for now.
-  </para>
-  <programlisting>
-
-
-
-        capture_ready = 0;
-
-        ptr=(u8 *)buf;
-        len = capture_w * 3 * capture_h; /* 24bit RGB */
-
-        if(len>count)
-                len=count;  /* Doesn't all fit */
-
-        for(i=0; i&lt;len; i++)
-        {
-                put_user(inb(io+IMAGE_DATA), ptr);
-                ptr++;
-        }
-
-        hardware_restart_capture();
-                
-        return i;
-}
-
-  </programlisting>
-  <para>
-        For a real hardware device you would try to avoid the loop with put_user().
-        Each call to put_user() has a time overhead checking whether the accesses to user
-        space are allowed. It would be better to read a line into a temporary buffer
-        then copy this to user space in one go.
-  </para>
-  <para>
-        Having captured the image and put it into user space we can kick the card to
-        get the next frame acquired.
-  </para>
-  </sect1>
-  <sect1 id="iocvid">
-  <title>Video Ioctl Handling</title>
-  <para>
-        As with the radio driver the major control interface is via the ioctl()
-        function. Video capture devices support the same tuner calls as a radio
-        device and also support additional calls to control how the video functions
-        are handled. In this simple example the card has no tuners to avoid making
-        the code complex. 
-  </para>
-  <programlisting>
-
-
-
-static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
-        switch(cmd)
-        {
-                case VIDIOCGCAP:
-                {
-                        struct video_capability v;
-                        v.type = VID_TYPE_CAPTURE|\
-                                 VID_TYPE_CHROMAKEY|\
-                                 VID_TYPE_SCALES|\
-                                 VID_TYPE_OVERLAY;
-                        v.channels = 1;
-                        v.audios = 0;
-                        v.maxwidth = 640;
-                        v.minwidth = 16;
-                        v.maxheight = 480;
-                        v.minheight = 16;
-                        strcpy(v.name, "My Camera");
-                        if(copy_to_user(arg, &amp;v, sizeof(v)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        The first ioctl we must support and which all video capture and radio
-        devices are required to support is VIDIOCGCAP. This behaves exactly the same
-        as with a radio device. This time, however, we report the extra capabilities
-        we outlined earlier on when defining our video_dev structure.
-  </para>
-  <para>
-        We now set the video flags saying that we support overlay, capture,
-        scaling and chromakey. We also report size limits - our smallest image is
-        16x16 pixels, our largest is 640x480. 
-  </para>
-  <para>
-        To keep things simple we report no audio and no tuning capabilities at all.
-  </para>
-  <programlisting>        
-
-                case VIDIOCGCHAN:
-                {
-                        struct video_channel v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.channel != 0)
-                                return -EINVAL;
-                        v.flags = 0;
-                        v.tuners = 0;
-                        v.type = VIDEO_TYPE_CAMERA;
-                        v.norm = VIDEO_MODE_AUTO;
-                        strcpy(v.name, "Camera Input");break;
-                        if(copy_to_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        This follows what is very much the standard way an ioctl handler looks
-        in Linux. We copy the data into a kernel space variable and we check that the
-        request is valid (in this case that the input is 0). Finally we copy the
-        camera info back to the user.
-  </para>
-  <para>
-        The VIDIOCGCHAN ioctl allows a user to ask about video channels (that is
-        inputs to the video card). Our example card has a single camera input. The
-        fields in the structure are
-  </para>
-   <table frame="all" id="video_channel_fields"><title>struct video_channel fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-
-   <entry>channel</entry><entry>The channel number we are selecting</entry>
-   </row><row>
-   <entry>name</entry><entry>The name for this channel. This is intended
-                   to describe the port to the user.
-                   Appropriate names are therefore things like
-                   "Camera" "SCART input"</entry>
-   </row><row>
-   <entry>flags</entry><entry>Channel properties</entry>
-   </row><row>
-   <entry>type</entry><entry>Input type</entry>
-   </row><row>
-   <entry>norm</entry><entry>The current television encoding being used
-                   if relevant for this channel.
-    </entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <table frame="all" id="video_channel_flags"><title>struct video_channel flags</title>
-    <tgroup cols="2" align="left">
-    <tbody>
-    <row>
-        <entry>VIDEO_VC_TUNER</entry><entry>Channel has a tuner.</entry>
-   </row><row>
-        <entry>VIDEO_VC_AUDIO</entry><entry>Channel has audio.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <table frame="all" id="video_channel_types"><title>struct video_channel types</title>
-    <tgroup cols="2" align="left">
-    <tbody>
-    <row>
-        <entry>VIDEO_TYPE_TV</entry><entry>Television input.</entry>
-   </row><row>
-        <entry>VIDEO_TYPE_CAMERA</entry><entry>Fixed camera input.</entry>
-   </row><row>
-       <entry>0</entry><entry>Type is unknown.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <table frame="all" id="video_channel_norms"><title>struct video_channel norms</title>
-    <tgroup cols="2" align="left">
-    <tbody>
-    <row>
-        <entry>VIDEO_MODE_PAL</entry><entry>PAL encoded Television</entry>
-   </row><row>
-        <entry>VIDEO_MODE_NTSC</entry><entry>NTSC (US) encoded Television</entry>
-   </row><row>
-        <entry>VIDEO_MODE_SECAM</entry><entry>SECAM (French) Television </entry>
-   </row><row>
-        <entry>VIDEO_MODE_AUTO</entry><entry>Automatic switching, or format does not
-                                matter</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <para>
-        The corresponding VIDIOCSCHAN ioctl allows a user to change channel and to
-        request the norm is changed - for example to switch between a PAL or an NTSC
-        format camera.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCSCHAN:
-                {
-                        struct video_channel v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.channel != 0)
-                                return -EINVAL;
-                        if(v.norm != VIDEO_MODE_AUTO)
-                                return -EINVAL;
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        The implementation of this call in our driver is remarkably easy. Because we
-        are assuming fixed format hardware we need only check that the user has not
-        tried to change anything. 
-  </para>
-  <para>
-        The user also needs to be able to configure and adjust the picture they are
-        seeing. This is much like adjusting a television set. A user application
-        also needs to know the palette being used so that it knows how to display
-        the image that has been captured. The VIDIOCGPICT and VIDIOCSPICT ioctl
-        calls provide this information.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCGPICT
-                {
-                        struct video_picture v;
-                        v.brightness = hardware_brightness();
-                        v.hue = hardware_hue();
-                        v.colour = hardware_saturation();
-                        v.contrast = hardware_brightness();
-                        /* Not settable */
-                        v.whiteness = 32768;
-                        v.depth = 24;           /* 24bit */
-                        v.palette = VIDEO_PALETTE_RGB24;
-                        if(copy_to_user(&amp;v, arg, 
-                             sizeof(v)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        The brightness, hue, color, and contrast provide the picture controls that
-        are akin to a conventional television. Whiteness provides additional
-        control for greyscale images. All of these values are scaled between 0-65535
-        and have 32768 as the mid point setting. The scaling means that applications
-        do not have to worry about the capability range of the hardware but can let
-        it make a best effort attempt.
-  </para>
-  <para>
-        Our depth is 24, as this is in bits. We will be returning RGB24 format. This
-        has one byte of red, then one of green, then one of blue. This then repeats
-        for every other pixel in the image. The other common formats the interface 
-        defines are
-  </para>
-   <table frame="all" id="Framebuffer_Encodings"><title>Framebuffer Encodings</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-   <entry>GREY</entry><entry>Linear greyscale. This is for simple cameras and the
-                        like</entry>
-   </row><row>
-   <entry>RGB565</entry><entry>The top 5 bits hold 32 red levels, the next six bits
-                        hold green and the low 5 bits hold blue. </entry>
-   </row><row>
-   <entry>RGB555</entry><entry>The top bit is clear. The red green and blue levels
-                        each occupy five bits.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-  <para>
-        Additional modes are support for YUV capture formats. These are common for
-        TV and video conferencing applications.
-  </para>
-  <para>
-        The VIDIOCSPICT ioctl allows a user to set some of the picture parameters.
-        Exactly which ones are supported depends heavily on the card itself. It is
-        possible to support many modes and effects in software. In general doing
-        this in the kernel is a bad idea. Video capture is a performance-sensitive
-        application and the programs can often do better if they aren't being
-        'helped' by an overkeen driver writer. Thus for our device we will report
-        RGB24 only and refuse to allow a change.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCSPICT:
-                {
-                        struct video_picture v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.depth!=24 || 
-                           v.palette != VIDEO_PALETTE_RGB24)
-                                return -EINVAL;
-                        set_hardware_brightness(v.brightness);
-                        set_hardware_hue(v.hue);
-                        set_hardware_saturation(v.colour);
-                        set_hardware_brightness(v.contrast);
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        We check the user has not tried to change the palette or the depth. We do
-        not want to carry out some of the changes and then return an error. This may
-        confuse the application which will be assuming no change occurred.
-  </para>
-  <para>
-        In much the same way as you need to be able to set the picture controls to
-        get the right capture images, many cards need to know what they are
-        displaying onto when generating overlay output. In some cases getting this
-        wrong even makes a nasty mess or may crash the computer. For that reason
-        the VIDIOCSBUF ioctl used to set up the frame buffer information may well
-        only be usable by root.
-  </para>
-  <para>
-        We will assume our card is one of the old ISA devices with feature connector
-        and only supports a couple of standard video modes. Very common for older
-        cards although the PCI devices are way smarter than this.
-  </para>
-  <programlisting>
-
-
-static struct video_buffer capture_fb;
-
-                case VIDIOCGFBUF:
-                {
-                        if(copy_to_user(arg, &amp;capture_fb, 
-                             sizeof(capture_fb)))
-                                return -EFAULT;
-                        return 0;
-                        
-                }
-
-
-  </programlisting>
-  <para>
-        We keep the frame buffer information in the format the ioctl uses. This
-        makes it nice and easy to work with in the ioctl calls.
-  </para>
-  <programlisting>
-
-                case VIDIOCSFBUF:
-                {
-                        struct video_buffer v;
-
-                        if(!capable(CAP_SYS_ADMIN))
-                                return -EPERM;
-
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.width!=320 &amp;&amp; v.width!=640)
-                                return -EINVAL;
-                        if(v.height!=200 &amp;&amp; v.height!=240 
-                                &amp;&amp; v.height!=400
-                                &amp;&amp; v.height !=480)
-                                return -EINVAL;
-                        memcpy(&amp;capture_fb, &amp;v, sizeof(v));
-                        hardware_set_fb(&amp;v);
-                        return 0;
-                }
-
-
-
-  </programlisting>
-  <para>
-        The capable() function checks a user has the required capability. The Linux
-        operating system has a set of about 30 capabilities indicating privileged
-        access to services. The default set up gives the superuser (uid 0) all of
-        them and nobody else has any.
-  </para>
-  <para>
-        We check that the user has the SYS_ADMIN capability, that is they are
-        allowed to operate as the machine administrator. We don't want anyone but
-        the administrator making a mess of the display.
-  </para>
-  <para>
-        Next we check for standard PC video modes (320 or 640 wide with either
-        EGA or VGA depths). If the mode is not a standard video mode we reject it as
-        not supported by our card. If the mode is acceptable we save it so that
-        VIDIOCFBUF will give the right answer next time it is called.  The
-        hardware_set_fb() function is some undescribed card specific function to
-        program the card for the desired mode.
-  </para>
-  <para>
-        Before the driver can display an overlay window it needs to know where the
-        window should be placed, and also how large it should be. If the card
-        supports clipping it needs to know which rectangles to omit from the
-        display. The video_window structure is used to describe the way the image 
-        should be displayed. 
-   </para>
-   <table frame="all" id="video_window_fields"><title>struct video_window fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-        <entry>width</entry><entry>The width in pixels of the desired image. The card
-                        may use a smaller size if this size is not available</entry>
-       </row><row>
-        <entry>height</entry><entry>The height of the image. The card may use a smaller
-                        size if this size is not available.</entry>
-       </row><row>
-        <entry>x</entry><entry>   The X position of the top left of the window. This
-                        is in pixels relative to the left hand edge of the
-                        picture. Not all cards can display images aligned on
-                        any pixel boundary. If the position is unsuitable
-                        the card adjusts the image right and reduces the
-                        width.</entry>
-       </row><row>
-        <entry>y</entry><entry>   The Y position of the top left of the window. This
-                        is counted in pixels relative to the top edge of the
-                        picture. As with the width if the card cannot
-                        display  starting on this line it will adjust the
-                        values.</entry>
-       </row><row>
-        <entry>chromakey</entry><entry>The colour (expressed in RGB32 format) for the
-                        chromakey colour if chroma keying is being used. </entry>
-       </row><row>
-        <entry>clips</entry><entry>An array of rectangles that must not be drawn
-                       over.</entry>
-       </row><row>
-        <entry>clipcount</entry><entry>The number of clips in this array.</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <para>
-        Each clip is a struct video_clip which has the following fields
-   </para>
-   <table frame="all" id="video_clip_fields"><title>video_clip fields</title>
-   <tgroup cols="2" align="left">
-   <tbody>
-   <row>
-        <entry>x, y</entry><entry>Co-ordinates relative to the display</entry>
-       </row><row>
-        <entry>width, height</entry><entry>Width and height in pixels</entry>
-       </row><row>
-        <entry>next</entry><entry>A spare field for the application to use</entry>
-    </row>
-    </tbody>
-    </tgroup>
-    </table>
-    <para>
-        The driver is required to ensure it always draws in the area requested or a        smaller area, and that it never draws in any of the areas that are clipped.
-        This may well mean it has to leave alone. small areas the application wished to be
-        drawn.
-  </para>
-  <para>
-        Our example card uses chromakey so does not have to address most of the
-        clipping.  We will add a video_window structure to our global variables to
-        remember our parameters, as we did with the frame buffer.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCGWIN:
-                {
-                        if(copy_to_user(arg, &amp;capture_win, 
-                            sizeof(capture_win)))
-                                return -EFAULT;
-                        return 0;
-                }
-
-
-                case VIDIOCSWIN:
-                {
-                        struct video_window v;
-                        if(copy_from_user(&amp;v, arg, sizeof(v)))
-                                return -EFAULT;
-                        if(v.width &gt; 640 || v.height &gt; 480)
-                                return -EINVAL;
-                        if(v.width &lt; 16 || v.height &lt; 16)
-                                return -EINVAL;
-                        hardware_set_key(v.chromakey);
-                        hardware_set_window(v);
-                        memcpy(&amp;capture_win, &amp;v, sizeof(v));
-                        capture_w = v.width;
-                        capture_h = v.height;
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        Because we are using Chromakey our setup is fairly simple. Mostly we have to
-        check the values are sane and load them into the capture card.
-  </para>
-  <para>
-        With all the setup done we can now turn on the actual capture/overlay. This
-        is done with the VIDIOCCAPTURE ioctl. This takes a single integer argument
-        where 0 is on and 1 is off.
-  </para>
-  <programlisting>
-
-
-                case VIDIOCCAPTURE:
-                {
-                        int v;
-                        if(get_user(v, (int *)arg))
-                                return -EFAULT;
-                        if(v==0)
-                                hardware_capture_off();
-                        else
-                        {
-                                if(capture_fb.width == 0 
-                                    || capture_w == 0)
-                                        return -EINVAL;
-                                hardware_capture_on();
-                        }
-                        return 0;
-                }
-
-
-  </programlisting>
-  <para>
-        We grab the flag from user space and either enable or disable according to
-        its value. There is one small corner case we have to consider here. Suppose
-        that the capture was requested before the video window or the frame buffer
-        had been set up. In those cases there will be unconfigured fields in our
-        card data, as well as unconfigured hardware settings. We check for this case and
-        return an error if the frame buffer or the capture window width is zero.
-  </para>
-  <programlisting>
-
-
-                default:
-                        return -ENOIOCTLCMD;
-        }
-}
-  </programlisting>
-  <para>
-
-        We don't need to support any other ioctls, so if we get this far, it is time
-        to tell the video layer that we don't now what the user is talking about.
-  </para>
-  </sect1>
-  <sect1 id="endvid">
-  <title>Other Functionality</title>
-  <para>
-        The Video4Linux layer supports additional features, including a high
-        performance mmap() based capture mode and capturing part of the image. 
-        These features are out of the scope of the book.  You should however have enough 
-        example code to implement most simple video4linux devices for radio and TV
-        cards.
-  </para>
-  </sect1>
-  </chapter>
-  <chapter id="bugs">
-     <title>Known Bugs And Assumptions</title>
-  <para>
-  <variablelist>
-    <varlistentry><term>Multiple Opens</term>
-    <listitem>
-    <para>
-        The driver assumes multiple opens should not be allowed. A driver
-        can work around this but not cleanly.
-    </para>
-    </listitem></varlistentry>
-
-    <varlistentry><term>API Deficiencies</term>
-    <listitem>
-    <para>
-        The existing API poorly reflects compression capable devices. There
-        are plans afoot to merge V4L, V4L2 and some other ideas into a
-        better interface.
-    </para>
-    </listitem></varlistentry>
-  </variablelist>
-
-  </para>
-  </chapter>
-
-  <chapter id="pubfunctions">
-     <title>Public Functions Provided</title>
-!Edrivers/media/video/v4l2-dev.c
-  </chapter>
-
-</book>
index 48a3955f05fcd9c5f7548aadf7557062f1aabdb1..8495fc970391b7d455455e31515705a1f3d8f0f4 100644 (file)
@@ -112,7 +112,7 @@ required reading:
 
     Other excellent descriptions of how to create patches properly are:
        "The Perfect Patch"
-               http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
+               http://userweb.kernel.org/~akpm/stuff/tpp.txt
        "Linux kernel patch submission format"
                http://linux.yyz.us/patch-format.html
 
@@ -620,7 +620,7 @@ all time.  It should describe the patch completely, containing:
 For more details on what this should all look like, please see the
 ChangeLog section of the document:
   "The Perfect Patch"
-      http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
+      http://userweb.kernel.org/~akpm/stuff/tpp.txt
 
 
 
index b9019ca872eaf6e670481733a2b1393866b51c63..74be14679ed891820cd9c3a7393007f8dd21d07d 100644 (file)
@@ -1,5 +1,5 @@
 Linux 2.4.2 Secure Attention Key (SAK) handling
-18 March 2001, Andrew Morton <akpm@osdl.org>
+18 March 2001, Andrew Morton
 
 An operating system's Secure Attention Key is a security tool which is
 provided as protection against trojan password capturing programs.  It
index 21f0795af20f1a6a3c34569f10ac05d72e8b75b4..ac5e0b2f1097c94333b9b6844bb708980786e028 100644 (file)
@@ -85,3 +85,6 @@ kernel patches.
 23: Tested after it has been merged into the -mm patchset to make sure
     that it still works with all of the other queued patches and various
     changes in the VM, VFS, and other subsystems.
+
+24: All memory barriers {e.g., barrier(), rmb(), wmb()} need a comment in the
+    source code that explains the logic of what they are doing and why.
index 24f2eb40cae5e00491204e11fe8db8afd16b4aef..99e72a81fa2fac5570708ed419e7a89b19040f1c 100644 (file)
@@ -41,7 +41,7 @@ Linux 2.4:
 Linux 2.6:
        The same rules apply as 2.4 except that you should follow linux-kernel
        to track changes in API's. The final contact point for Linux 2.6
-       submissions is Andrew Morton <akpm@osdl.org>.
+       submissions is Andrew Morton.
 
 What Criteria Determine Acceptance
 ----------------------------------
index f79ad9ff6031aa4ee622d9f0be3e0c1604e2d14b..f309d3c6221c3699a0c0b97fbe689faed09e4d2f 100644 (file)
@@ -77,7 +77,7 @@ Quilt:
 http://savannah.nongnu.org/projects/quilt
 
 Andrew Morton's patch scripts:
-http://www.zip.com.au/~akpm/linux/patches/
+http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz
 Instead of these scripts, quilt is the recommended patch management
 tool (see above).
 
@@ -405,7 +405,7 @@ person it names.  This tag documents that potentially interested parties
 have been included in the discussion
 
 
-14) Using Test-by: and Reviewed-by:
+14) Using Tested-by: and Reviewed-by:
 
 A Tested-by: tag indicates that the patch has been successfully tested (in
 some environment) by the person named.  This tag informs maintainers that
@@ -653,7 +653,7 @@ SECTION 3 - REFERENCES
 ----------------------
 
 Andrew Morton, "The perfect patch" (tpp).
-  <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
+  <http://userweb.kernel.org/~akpm/stuff/tpp.txt>
 
 Jeff Garzik, "Linux kernel patch submission format".
   <http://linux.yyz.us/patch-format.html>
@@ -672,4 +672,9 @@ Kernel Documentation/CodingStyle:
 
 Linus Torvalds's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversal changes in.
+  http://halobates.de/on-submitting-patches.pdf
+
 --
diff --git a/Documentation/blackfin/kgdb.txt b/Documentation/blackfin/kgdb.txt
deleted file mode 100644 (file)
index 84f6a48..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-                       A Simple Guide to Configure KGDB
-
-                       Sonic Zhang <sonic.zhang@analog.com>
-                               Aug. 24th 2006
-
-
-This KGDB patch enables the kernel developer to do source level debugging on
-the kernel for the Blackfin architecture.  The debugging works over either the
-ethernet interface or one of the uarts.  Both software breakpoints and
-hardware breakpoints are supported in this version.
-http://docs.blackfin.uclinux.org/doku.php?id=kgdb
-
-
-2 known issues:
-1. This bug:
-       http://blackfin.uclinux.org/tracker/index.php?func=detail&aid=544&group_id=18&atid=145
-   The GDB client for Blackfin uClinux causes incorrect values of local
-   variables to be displayed when the user breaks the running of kernel in GDB.
-2. Because of a hardware bug in Blackfin 533 v1.0.3:
-       05000067 - Watchpoints (Hardware Breakpoints) are not supported
-   Hardware breakpoints cannot be set properly.
-
-
-Debug over Ethernet:
-1. Compile and install the cross platform version of gdb for blackfin, which
-   can be found at $(BINROOT)/bfin-elf-gdb.
-
-2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
-   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
-   With this selected, option "Full Symbolic/Source Debugging support" and 
-   "Compile the kernel with frame pointers" are also selected.
-
-3. Select option "KGDB: connect over (Ethernet)".  Add "kgdboe=@target-IP/,@host-IP/" to
-   the option "Compiled-in Kernel Boot Parameter" under "Kernel hacking".
-
-4. Connect minicom to the serial port and boot the kernel image.
-
-5. Configure the IP "/> ifconfig eth0 target-IP"
-
-6. Start GDB client "bfin-elf-gdb vmlinux".
-
-7. Connect to the target "(gdb) target remote udp:target-IP:6443".
-
-8. Set software breakpoint "(gdb) break sys_open".
-
-9. Continue "(gdb) c".
-
-10. Run ls in the target console "/> ls".
-
-11. Breakpoint hits. "Breakpoint 1: sys_open(..."
-
-12. Display local variables and function paramters.
-    (*) This operation gives wrong results, see known issue 1.
-
-13. Single stepping "(gdb) si".
-
-14. Remove breakpoint 1. "(gdb) del 1"
-
-15. Set hardware breakpoint "(gdb) hbreak sys_open".
-
-16. Continue "(gdb) c".
-
-17. Run ls in the target console "/> ls".
-
-18. Hardware breakpoint hits. "Breakpoint 1: sys_open(...".
-    (*) This hardware breakpoint will not be hit, see known issue 2.
-
-19. Continue "(gdb) c".
-
-20. Interrupt the target in GDB "Ctrl+C".
-
-21. Detach from the target "(gdb) detach".
-
-22. Exit GDB "(gdb) quit".
-
-
-Debug over the UART:
-
-1. Compile and install the cross platform version of gdb for blackfin, which
-   can be found at $(BINROOT)/bfin-elf-gdb.
-
-2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
-   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
-   With this selected, option "Full Symbolic/Source Debugging support" and 
-   "Compile the kernel with frame pointers" are also selected.
-
-3. Select option "KGDB: connect over (UART)".  Set "KGDB: UART port number" to be
-   a different one from the console.  Don't forget to change the mode of
-   blackfin serial driver to PIO.  Otherwise kgdb works incorrectly on UART.
-4. If you want connect to kgdb when the kernel boots, enable
-   "KGDB: Wait for gdb connection early" 
-
-5. Compile kernel.
-
-6. Connect minicom to the serial port of the console and boot the kernel image.
-
-7. Start GDB client "bfin-elf-gdb vmlinux".
-
-8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
-
-9. Connect to the target on the second serial port "(gdb) target remote /dev/ttyS1".
-
-10. Set software breakpoint "(gdb) break sys_open".
-
-11. Continue "(gdb) c". 
-
-12. Run ls in the target console "/> ls". 
-
-13. A breakpoint is hit. "Breakpoint 1: sys_open(..."
-
-14. All other operations are the same as that in KGDB over Ethernet. 
-
-
-Debug over the same UART as console:
-
-1. Compile and install the cross platform version of gdb for blackfin, which
-   can be found at $(BINROOT)/bfin-elf-gdb.
-
-2. Apply this patch to the 2.6.x kernel.  Select the menuconfig option under
-   "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
-   With this selected, option "Full Symbolic/Source Debugging support" and 
-   "Compile the kernel with frame pointers" are also selected.
-
-3. Select option "KGDB: connect over UART".  Set "KGDB: UART port number" to console.
-   Don't forget to change the mode of blackfin serial driver to PIO.
-   Otherwise kgdb works incorrectly on UART.
-4. If you want connect to kgdb when the kernel boots, enable
-   "KGDB: Wait for gdb connection early" 
-
-5. Connect minicom to the serial port and boot the kernel image. 
-
-6. (Optional) Ask target to wait for gdb connection by entering Ctrl+A. In minicom, you should enter Ctrl+A+A.
-
-7. Start GDB client "bfin-elf-gdb vmlinux".
-
-8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
-
-9. Connect to the target "(gdb) target remote /dev/ttyS0".
-
-10. Set software breakpoint "(gdb) break sys_open".
-
-11. Continue "(gdb) c". Then enter Ctrl+C twice to stop GDB connection.
-
-12. Run ls in the target console "/> ls". Dummy string can be seen on the console.
-
-13. Then connect the gdb to target again. "(gdb) target remote /dev/ttyS0".
-    Now you will find a breakpoint is hit. "Breakpoint 1: sys_open(..."
-
-14. All other operations are the same as that in KGDB over Ethernet.  The only
-    difference is that after continue command in GDB, please stop GDB
-    connection by 2 "Ctrl+C"s and connect again after breakpoints are hit or
-    Ctrl+A is entered.
index e9dc8d86adc7c51e4f1f06598a5a2c4b3eb5cabb..e8ca040ba2cff4bb5b938939f75c1bb97f0610af 100644 (file)
@@ -246,7 +246,7 @@ will require extra work due to the application tag.
       retrieve the tag buffer using bio_integrity_get_tag().
 
 
-6.3 PASSING EXISTING INTEGRITY METADATA
+5.3 PASSING EXISTING INTEGRITY METADATA
 
     Filesystems that either generate their own integrity metadata or
     are capable of transferring IMD from user space can use the
@@ -283,7 +283,7 @@ will require extra work due to the application tag.
       integrity upon completion.
 
 
-6.4 REGISTERING A BLOCK DEVICE AS CAPABLE OF EXCHANGING INTEGRITY
+5.4 REGISTERING A BLOCK DEVICE AS CAPABLE OF EXCHANGING INTEGRITY
     METADATA
 
     To enable integrity exchange on a block device the gendisk must be
index 795a1dabe6c78c933fb3ecfe2d16c691c577323d..d9b086869a6054d9687ec51070cfceb51fab6a50 100644 (file)
@@ -27,7 +27,7 @@ operating system.
 The ETRAX 100LX chip
 --------------------
 
-For reference, plase see the press-release:
+For reference, please see the press-release:
 
 http://www.axis.com/news/us/001101_etrax.htm
 
diff --git a/Documentation/development-process/1.Intro b/Documentation/development-process/1.Intro
new file mode 100644 (file)
index 0000000..8cc2cba
--- /dev/null
@@ -0,0 +1,274 @@
+1: A GUIDE TO THE KERNEL DEVELOPMENT PROCESS
+
+The purpose of this document is to help developers (and their managers)
+work with the development community with a minimum of frustration.  It is
+an attempt to document how this community works in a way which is
+accessible to those who are not intimately familiar with Linux kernel
+development (or, indeed, free software development in general).  While
+there is some technical material here, this is very much a process-oriented
+discussion which does not require a deep knowledge of kernel programming to
+understand.
+
+
+1.1: EXECUTIVE SUMMARY
+
+The rest of this section covers the scope of the kernel development process
+and the kinds of frustrations that developers and their employers can
+encounter there.  There are a great many reasons why kernel code should be
+merged into the official ("mainline") kernel, including automatic
+availability to users, community support in many forms, and the ability to
+influence the direction of kernel development.  Code contributed to the
+Linux kernel must be made available under a GPL-compatible license.
+
+Section 2 introduces the development process, the kernel release cycle, and
+the mechanics of the merge window.  The various phases in the patch
+development, review, and merging cycle are covered.  There is some
+discussion of tools and mailing lists.  Developers wanting to get started
+with kernel development are encouraged to track down and fix bugs as an
+initial exercise.
+
+Section 3 covers early-stage project planning, with an emphasis on
+involving the development community as soon as possible.
+
+Section 4 is about the coding process; several pitfalls which have been
+encountered by other developers are discussed.  Some requirements for
+patches are covered, and there is an introduction to some of the tools
+which can help to ensure that kernel patches are correct.
+
+Section 5 talks about the process of posting patches for review.  To be
+taken seriously by the development community, patches must be properly
+formatted and described, and they must be sent to the right place.
+Following the advice in this section should help to ensure the best
+possible reception for your work.
+
+Section 6 covers what happens after posting patches; the job is far from
+done at that point.  Working with reviewers is a crucial part of the
+development process; this section offers a number of tips on how to avoid
+problems at this important stage.  Developers are cautioned against
+assuming that the job is done when a patch is merged into the mainline.
+
+Section 7 introduces a couple of "advanced" topics: managing patches with
+git and reviewing patches posted by others.
+
+Section 8 concludes the document with pointers to sources for more
+information on kernel development.
+
+
+1.2: WHAT THIS DOCUMENT IS ABOUT
+
+The Linux kernel, at over 6 million lines of code and well over 1000 active
+contributors, is one of the largest and most active free software projects
+in existence.  Since its humble beginning in 1991, this kernel has evolved
+into a best-of-breed operating system component which runs on pocket-sized
+digital music players, desktop PCs, the largest supercomputers in
+existence, and all types of systems in between.  It is a robust, efficient,
+and scalable solution for almost any situation.
+
+With the growth of Linux has come an increase in the number of developers
+(and companies) wishing to participate in its development.  Hardware
+vendors want to ensure that Linux supports their products well, making
+those products attractive to Linux users.  Embedded systems vendors, who
+use Linux as a component in an integrated product, want Linux to be as
+capable and well-suited to the task at hand as possible.  Distributors and
+other software vendors who base their products on Linux have a clear
+interest in the capabilities, performance, and reliability of the Linux
+kernel.  And end users, too, will often wish to change Linux to make it
+better suit their needs.
+
+One of the most compelling features of Linux is that it is accessible to
+these developers; anybody with the requisite skills can improve Linux and
+influence the direction of its development.  Proprietary products cannot
+offer this kind of openness, which is a characteristic of the free software
+process.  But, if anything, the kernel is even more open than most other
+free software projects.  A typical three-month kernel development cycle can
+involve over 1000 developers working for more than 100 different companies
+(or for no company at all).
+
+Working with the kernel development community is not especially hard.  But,
+that notwithstanding, many potential contributors have experienced
+difficulties when trying to do kernel work.  The kernel community has
+evolved its own distinct ways of operating which allow it to function
+smoothly (and produce a high-quality product) in an environment where
+thousands of lines of code are being changed every day.  So it is not
+surprising that Linux kernel development process differs greatly from
+proprietary development methods.
+
+The kernel's development process may come across as strange and
+intimidating to new developers, but there are good reasons and solid
+experience behind it.  A developer who does not understand the kernel
+community's ways (or, worse, who tries to flout or circumvent them) will
+have a frustrating experience in store.  The development community, while
+being helpful to those who are trying to learn, has little time for those
+who will not listen or who do not care about the development process.
+
+It is hoped that those who read this document will be able to avoid that
+frustrating experience.  There is a lot of material here, but the effort
+involved in reading it will be repaid in short order.  The development
+community is always in need of developers who will help to make the kernel
+better; the following text should help you - or those who work for you -
+join our community.
+
+
+1.3: CREDITS
+
+This document was written by Jonathan Corbet, corbet@lwn.net.  It has been
+improved by comments from Johannes Berg, James Berry, Alex Chiang, Roland
+Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
+Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and
+Jochen Voß. 
+
+This work was supported by the Linux Foundation; thanks especially to
+Amanda McPherson, who saw the value of this effort and made it all happen.
+
+
+1.4: THE IMPORTANCE OF GETTING CODE INTO THE MAINLINE
+
+Some companies and developers occasionally wonder why they should bother
+learning how to work with the kernel community and get their code into the
+mainline kernel (the "mainline" being the kernel maintained by Linus
+Torvalds and used as a base by Linux distributors).  In the short term,
+contributing code can look like an avoidable expense; it seems easier to
+just keep the code separate and support users directly.  The truth of the
+matter is that keeping code separate ("out of tree") is a false economy.
+
+As a way of illustrating the costs of out-of-tree code, here are a few
+relevant aspects of the kernel development process; most of these will be
+discussed in greater detail later in this document.  Consider:
+
+- Code which has been merged into the mainline kernel is available to all
+  Linux users.  It will automatically be present on all distributions which
+  enable it.  There is no need for driver disks, downloads, or the hassles
+  of supporting multiple versions of multiple distributions; it all just
+  works, for the developer and for the user.  Incorporation into the
+  mainline solves a large number of distribution and support problems.
+
+- While kernel developers strive to maintain a stable interface to user
+  space, the internal kernel API is in constant flux.  The lack of a stable
+  internal interface is a deliberate design decision; it allows fundamental
+  improvements to be made at any time and results in higher-quality code.
+  But one result of that policy is that any out-of-tree code requires
+  constant upkeep if it is to work with new kernels.  Maintaining
+  out-of-tree code requires significant amounts of work just to keep that
+  code working.
+
+  Code which is in the mainline, instead, does not require this work as the
+  result of a simple rule requiring any developer who makes an API change
+  to also fix any code that breaks as the result of that change.  So code
+  which has been merged into the mainline has significantly lower
+  maintenance costs.
+
+- Beyond that, code which is in the kernel will often be improved by other
+  developers.  Surprising results can come from empowering your user
+  community and customers to improve your product.
+
+- Kernel code is subjected to review, both before and after merging into
+  the mainline.  No matter how strong the original developer's skills are,
+  this review process invariably finds ways in which the code can be
+  improved.  Often review finds severe bugs and security problems.  This is
+  especially true for code which has been developed in a closed
+  environment; such code benefits strongly from review by outside
+  developers.  Out-of-tree code is lower-quality code.
+
+- Participation in the development process is your way to influence the
+  direction of kernel development.  Users who complain from the sidelines
+  are heard, but active developers have a stronger voice - and the ability
+  to implement changes which make the kernel work better for their needs.
+
+- When code is maintained separately, the possibility that a third party
+  will contribute a different implementation of a similar feature always
+  exists.  Should that happen, getting your code merged will become much
+  harder - to the point of impossibility.  Then you will be faced with the
+  unpleasant alternatives of either (1) maintaining a nonstandard feature
+  out of tree indefinitely, or (2) abandoning your code and migrating your
+  users over to the in-tree version.
+
+- Contribution of code is the fundamental action which makes the whole
+  process work.  By contributing your code you can add new functionality to
+  the kernel and provide capabilities and examples which are of use to
+  other kernel developers.  If you have developed code for Linux (or are
+  thinking about doing so), you clearly have an interest in the continued
+  success of this platform; contributing code is one of the best ways to
+  help ensure that success.
+
+All of the reasoning above applies to any out-of-tree kernel code,
+including code which is distributed in proprietary, binary-only form.
+There are, however, additional factors which should be taken into account
+before considering any sort of binary-only kernel code distribution.  These
+include:
+
+- The legal issues around the distribution of proprietary kernel modules
+  are cloudy at best; quite a few kernel copyright holders believe that
+  most binary-only modules are derived products of the kernel and that, as
+  a result, their distribution is a violation of the GNU General Public
+  license (about which more will be said below).  Your author is not a
+  lawyer, and nothing in this document can possibly be considered to be
+  legal advice.  The true legal status of closed-source modules can only be
+  determined by the courts.  But the uncertainty which haunts those modules
+  is there regardless.
+
+- Binary modules greatly increase the difficulty of debugging kernel
+  problems, to the point that most kernel developers will not even try.  So
+  the distribution of binary-only modules will make it harder for your
+  users to get support from the community.
+
+- Support is also harder for distributors of binary-only modules, who must
+  provide a version of the module for every distribution and every kernel
+  version they wish to support.  Dozens of builds of a single module can
+  be required to provide reasonably comprehensive coverage, and your users
+  will have to upgrade your module separately every time they upgrade their
+  kernel.
+
+- Everything that was said above about code review applies doubly to
+  closed-source code.  Since this code is not available at all, it cannot
+  have been reviewed by the community and will, beyond doubt, have serious
+  problems. 
+
+Makers of embedded systems, in particular, may be tempted to disregard much
+of what has been said in this section in the belief that they are shipping
+a self-contained product which uses a frozen kernel version and requires no
+more development after its release.  This argument misses the value of
+widespread code review and the value of allowing your users to add
+capabilities to your product.  But these products, too, have a limited
+commercial life, after which a new version must be released.  At that
+point, vendors whose code is in the mainline and well maintained will be
+much better positioned to get the new product ready for market quickly.
+
+
+1.5: LICENSING
+
+Code is contributed to the Linux kernel under a number of licenses, but all
+code must be compatible with version 2 of the GNU General Public License
+(GPLv2), which is the license covering the kernel distribution as a whole.
+In practice, that means that all code contributions are covered either by
+GPLv2 (with, optionally, language allowing distribution under later
+versions of the GPL) or the three-clause BSD license.  Any contributions
+which are not covered by a compatible license will not be accepted into the
+kernel.
+
+Copyright assignments are not required (or requested) for code contributed
+to the kernel.  All code merged into the mainline kernel retains its
+original ownership; as a result, the kernel now has thousands of owners.
+
+One implication of this ownership structure is that any attempt to change
+the licensing of the kernel is doomed to almost certain failure.  There are
+few practical scenarios where the agreement of all copyright holders could
+be obtained (or their code removed from the kernel).  So, in particular,
+there is no prospect of a migration to version 3 of the GPL in the
+foreseeable future.
+
+It is imperative that all code contributed to the kernel be legitimately
+free software.  For that reason, code from anonymous (or pseudonymous)
+contributors will not be accepted.  All contributors are required to "sign
+off" on their code, stating that the code can be distributed with the
+kernel under the GPL.  Code which has not been licensed as free software by
+its owner, or which risks creating copyright-related problems for the
+kernel (such as code which derives from reverse-engineering efforts lacking
+proper safeguards) cannot be contributed.
+
+Questions about copyright-related issues are common on Linux development
+mailing lists.  Such questions will normally receive no shortage of
+answers, but one should bear in mind that the people answering those
+questions are not lawyers and cannot provide legal advice.  If you have
+legal questions relating to Linux source code, there is no substitute for
+talking with a lawyer who understands this field.  Relying on answers
+obtained on technical mailing lists is a risky affair.
diff --git a/Documentation/development-process/2.Process b/Documentation/development-process/2.Process
new file mode 100644 (file)
index 0000000..d750321
--- /dev/null
@@ -0,0 +1,459 @@
+2: HOW THE DEVELOPMENT PROCESS WORKS
+
+Linux kernel development in the early 1990's was a pretty loose affair,
+with relatively small numbers of users and developers involved.  With a
+user base in the millions and with some 2,000 developers involved over the
+course of one year, the kernel has since had to evolve a number of
+processes to keep development happening smoothly.  A solid understanding of
+how the process works is required in order to be an effective part of it.
+
+
+2.1: THE BIG PICTURE
+
+The kernel developers use a loosely time-based release process, with a new
+major kernel release happening every two or three months.  The recent
+release history looks like this:
+
+       2.6.26  July 13, 2008
+       2.6.25  April 16, 2008
+       2.6.24  January 24, 2008
+       2.6.23  October 9, 2007
+       2.6.22  July 8, 2007
+       2.6.21  April 25, 2007
+       2.6.20  February 4, 2007
+
+Every 2.6.x release is a major kernel release with new features, internal
+API changes, and more.  A typical 2.6 release can contain over 10,000
+changesets with changes to several hundred thousand lines of code.  2.6 is
+thus the leading edge of Linux kernel development; the kernel uses a
+rolling development model which is continually integrating major changes.
+
+A relatively straightforward discipline is followed with regard to the
+merging of patches for each release.  At the beginning of each development
+cycle, the "merge window" is said to be open.  At that time, code which is
+deemed to be sufficiently stable (and which is accepted by the development
+community) is merged into the mainline kernel.  The bulk of changes for a
+new development cycle (and all of the major changes) will be merged during
+this time, at a rate approaching 1,000 changes ("patches," or "changesets")
+per day.
+
+(As an aside, it is worth noting that the changes integrated during the
+merge window do not come out of thin air; they have been collected, tested,
+and staged ahead of time.  How that process works will be described in
+detail later on).
+
+The merge window lasts for two weeks.  At the end of this time, Linus
+Torvalds will declare that the window is closed and release the first of
+the "rc" kernels.  For the kernel which is destined to be 2.6.26, for
+example, the release which happens at the end of the merge window will be
+called 2.6.26-rc1.  The -rc1 release is the signal that the time to merge
+new features has passed, and that the time to stabilize the next kernel has
+begun.
+
+Over the next six to ten weeks, only patches which fix problems should be
+submitted to the mainline.  On occasion a more significant change will be
+allowed, but such occasions are rare; developers who try to merge new
+features outside of the merge window tend to get an unfriendly reception.
+As a general rule, if you miss the merge window for a given feature, the
+best thing to do is to wait for the next development cycle.  (An occasional
+exception is made for drivers for previously-unsupported hardware; if they
+touch no in-tree code, they cannot cause regressions and should be safe to
+add at any time).
+
+As fixes make their way into the mainline, the patch rate will slow over
+time.  Linus releases new -rc kernels about once a week; a normal series
+will get up to somewhere between -rc6 and -rc9 before the kernel is
+considered to be sufficiently stable and the final 2.6.x release is made.
+At that point the whole process starts over again.
+
+As an example, here is how the 2.6.25 development cycle went (all dates in
+2008): 
+
+       January 24      2.6.24 stable release
+       February 10     2.6.25-rc1, merge window closes
+       February 15     2.6.25-rc2
+       February 24     2.6.25-rc3
+       March 4         2.6.25-rc4
+       March 9         2.6.25-rc5
+       March 16        2.6.25-rc6
+       March 25        2.6.25-rc7
+       April 1         2.6.25-rc8
+       April 11        2.6.25-rc9
+       April 16        2.6.25 stable release
+
+How do the developers decide when to close the development cycle and create
+the stable release?  The most significant metric used is the list of
+regressions from previous releases.  No bugs are welcome, but those which
+break systems which worked in the past are considered to be especially
+serious.  For this reason, patches which cause regressions are looked upon
+unfavorably and are quite likely to be reverted during the stabilization
+period. 
+
+The developers' goal is to fix all known regressions before the stable
+release is made.  In the real world, this kind of perfection is hard to
+achieve; there are just too many variables in a project of this size.
+There comes a point where delaying the final release just makes the problem
+worse; the pile of changes waiting for the next merge window will grow
+larger, creating even more regressions the next time around.  So most 2.6.x
+kernels go out with a handful of known regressions though, hopefully, none
+of them are serious.
+
+Once a stable release is made, its ongoing maintenance is passed off to the
+"stable team," currently comprised of Greg Kroah-Hartman and Chris Wright.
+The stable team will release occasional updates to the stable release using
+the 2.6.x.y numbering scheme.  To be considered for an update release, a
+patch must (1) fix a significant bug, and (2) already be merged into the
+mainline for the next development kernel.  Continuing our 2.6.25 example,
+the history (as of this writing) is:
+
+       May 1           2.6.25.1
+       May 6           2.6.25.2 
+       May 9           2.6.25.3 
+       May 15          2.6.25.4
+       June 7          2.6.25.5
+       June 9          2.6.25.6
+       June 16         2.6.25.7
+       June 21         2.6.25.8
+       June 24         2.6.25.9
+
+Stable updates for a given kernel are made for approximately six months;
+after that, the maintenance of stable releases is solely the responsibility
+of the distributors which have shipped that particular kernel.
+
+
+2.2: THE LIFECYCLE OF A PATCH
+
+Patches do not go directly from the developer's keyboard into the mainline
+kernel.  There is, instead, a somewhat involved (if somewhat informal)
+process designed to ensure that each patch is reviewed for quality and that
+each patch implements a change which is desirable to have in the mainline.
+This process can happen quickly for minor fixes, or, in the case of large
+and controversial changes, go on for years.  Much developer frustration
+comes from a lack of understanding of this process or from attempts to
+circumvent it.  
+
+In the hopes of reducing that frustration, this document will describe how
+a patch gets into the kernel.  What follows below is an introduction which
+describes the process in a somewhat idealized way.  A much more detailed
+treatment will come in later sections.
+
+The stages that a patch goes through are, generally:
+
+ - Design.  This is where the real requirements for the patch - and the way
+   those requirements will be met - are laid out.  Design work is often
+   done without involving the community, but it is better to do this work
+   in the open if at all possible; it can save a lot of time redesigning
+   things later.
+
+ - Early review.  Patches are posted to the relevant mailing list, and
+   developers on that list reply with any comments they may have.  This
+   process should turn up any major problems with a patch if all goes
+   well.
+
+ - Wider review.  When the patch is getting close to ready for mainline
+   inclusion, it will be accepted by a relevant subsystem maintainer -
+   though this acceptance is not a guarantee that the patch will make it
+   all the way to the mainline.  The patch will show up in the maintainer's
+   subsystem tree and into the staging trees (described below).  When the
+   process works, this step leads to more extensive review of the patch and
+   the discovery of any problems resulting from the integration of this
+   patch with work being done by others.
+
+ - Merging into the mainline.  Eventually, a successful patch will be
+   merged into the mainline repository managed by Linus Torvalds.  More
+   comments and/or problems may surface at this time; it is important that
+   the developer be responsive to these and fix any issues which arise.
+
+ - Stable release.  The number of users potentially affected by the patch
+   is now large, so, once again, new problems may arise.
+
+ - Long-term maintenance.  While it is certainly possible for a developer
+   to forget about code after merging it, that sort of behavior tends to
+   leave a poor impression in the development community.  Merging code
+   eliminates some of the maintenance burden, in that others will fix
+   problems caused by API changes.  But the original developer should
+   continue to take responsibility for the code if it is to remain useful
+   in the longer term.
+
+One of the largest mistakes made by kernel developers (or their employers)
+is to try to cut the process down to a single "merging into the mainline"
+step.  This approach invariably leads to frustration for everybody
+involved.
+
+
+2.3: HOW PATCHES GET INTO THE KERNEL
+
+There is exactly one person who can merge patches into the mainline kernel
+repository: Linus Torvalds.  But, of the over 12,000 patches which went
+into the 2.6.25 kernel, only 250 (around 2%) were directly chosen by Linus
+himself.  The kernel project has long since grown to a size where no single
+developer could possibly inspect and select every patch unassisted.  The
+way the kernel developers have addressed this growth is through the use of
+a lieutenant system built around a chain of trust.
+
+The kernel code base is logically broken down into a set of subsystems:
+networking, specific architecture support, memory management, video
+devices, etc.  Most subsystems have a designated maintainer, a developer
+who has overall responsibility for the code within that subsystem.  These
+subsystem maintainers are the gatekeepers (in a loose way) for the portion
+of the kernel they manage; they are the ones who will (usually) accept a
+patch for inclusion into the mainline kernel.
+
+Subsystem maintainers each manage their own version of the kernel source
+tree, usually (but certainly not always) using the git source management
+tool.  Tools like git (and related tools like quilt or mercurial) allow
+maintainers to track a list of patches, including authorship information
+and other metadata.  At any given time, the maintainer can identify which
+patches in his or her repository are not found in the mainline.
+
+When the merge window opens, top-level maintainers will ask Linus to "pull"
+the patches they have selected for merging from their repositories.  If
+Linus agrees, the stream of patches will flow up into his repository,
+becoming part of the mainline kernel.  The amount of attention that Linus
+pays to specific patches received in a pull operation varies.  It is clear
+that, sometimes, he looks quite closely.  But, as a general rule, Linus
+trusts the subsystem maintainers to not send bad patches upstream.
+
+Subsystem maintainers, in turn, can pull patches from other maintainers.
+For example, the networking tree is built from patches which accumulated
+first in trees dedicated to network device drivers, wireless networking,
+etc.  This chain of repositories can be arbitrarily long, though it rarely
+exceeds two or three links.  Since each maintainer in the chain trusts
+those managing lower-level trees, this process is known as the "chain of
+trust." 
+
+Clearly, in a system like this, getting patches into the kernel depends on
+finding the right maintainer.  Sending patches directly to Linus is not
+normally the right way to go.
+
+
+2.4: STAGING TREES
+
+The chain of subsystem trees guides the flow of patches into the kernel,
+but it also raises an interesting question: what if somebody wants to look
+at all of the patches which are being prepared for the next merge window?
+Developers will be interested in what other changes are pending to see
+whether there are any conflicts to worry about; a patch which changes a
+core kernel function prototype, for example, will conflict with any other
+patches which use the older form of that function.  Reviewers and testers
+want access to the changes in their integrated form before all of those
+changes land in the mainline kernel.  One could pull changes from all of
+the interesting subsystem trees, but that would be a big and error-prone
+job.
+
+The answer comes in the form of staging trees, where subsystem trees are
+collected for testing and review.  The older of these trees, maintained by
+Andrew Morton, is called "-mm" (for memory management, which is how it got
+started).  The -mm tree integrates patches from a long list of subsystem
+trees; it also has some patches aimed at helping with debugging.  
+
+Beyond that, -mm contains a significant collection of patches which have
+been selected by Andrew directly.  These patches may have been posted on a
+mailing list, or they may apply to a part of the kernel for which there is
+no designated subsystem tree.  As a result, -mm operates as a sort of
+subsystem tree of last resort; if there is no other obvious path for a
+patch into the mainline, it is likely to end up in -mm.  Miscellaneous
+patches which accumulate in -mm will eventually either be forwarded on to
+an appropriate subsystem tree or be sent directly to Linus.  In a typical
+development cycle, approximately 10% of the patches going into the mainline
+get there via -mm.
+
+The current -mm patch can always be found from the front page of
+
+       http://kernel.org/
+
+Those who want to see the current state of -mm can get the "-mm of the
+moment" tree, found at:
+
+       http://userweb.kernel.org/~akpm/mmotm/
+
+Use of the MMOTM tree is likely to be a frustrating experience, though;
+there is a definite chance that it will not even compile.
+
+The other staging tree, started more recently, is linux-next, maintained by
+Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
+the mainline is expected to look like after the next merge window closes.
+Linux-next trees are announced on the linux-kernel and linux-next mailing
+lists when they are assembled; they can be downloaded from:
+
+       http://www.kernel.org/pub/linux/kernel/people/sfr/linux-next/
+
+Some information about linux-next has been gathered at:
+
+       http://linux.f-seidel.de/linux-next/pmwiki/
+
+How the linux-next tree will fit into the development process is still
+changing.  As of this writing, the first full development cycle involving
+linux-next (2.6.26) is coming to an end; thus far, it has proved to be a
+valuable resource for finding and fixing integration problems before the
+beginning of the merge window.  See http://lwn.net/Articles/287155/ for
+more information on how linux-next has worked to set up the 2.6.27 merge
+window.
+
+Some developers have begun to suggest that linux-next should be used as the
+target for future development as well.  The linux-next tree does tend to be
+far ahead of the mainline and is more representative of the tree into which
+any new work will be merged.  The downside to this idea is that the
+volatility of linux-next tends to make it a difficult development target.
+See http://lwn.net/Articles/289013/ for more information on this topic, and
+stay tuned; much is still in flux where linux-next is involved.
+
+
+2.5: TOOLS
+
+As can be seen from the above text, the kernel development process depends
+heavily on the ability to herd collections of patches in various
+directions.  The whole thing would not work anywhere near as well as it
+does without suitably powerful tools.  Tutorials on how to use these tools
+are well beyond the scope of this document, but there is space for a few
+pointers.
+
+By far the dominant source code management system used by the kernel
+community is git.  Git is one of a number of distributed version control
+systems being developed in the free software community.  It is well tuned
+for kernel development, in that it performs quite well when dealing with
+large repositories and large numbers of patches.  It also has a reputation
+for being difficult to learn and use, though it has gotten better over
+time.  Some sort of familiarity with git is almost a requirement for kernel
+developers; even if they do not use it for their own work, they'll need git
+to keep up with what other developers (and the mainline) are doing.
+
+Git is now packaged by almost all Linux distributions.  There is a home
+page at 
+
+       http://git.or.cz/
+
+That page has pointers to documentation and tutorials.  One should be
+aware, in particular, of the Kernel Hacker's Guide to git, which has
+information specific to kernel development:
+
+       http://linux.yyz.us/git-howto.html
+
+Among the kernel developers who do not use git, the most popular choice is
+almost certainly Mercurial:
+
+       http://www.selenic.com/mercurial/
+
+Mercurial shares many features with git, but it provides an interface which
+many find easier to use.
+
+The other tool worth knowing about is Quilt:
+
+       http://savannah.nongnu.org/projects/quilt/
+
+Quilt is a patch management system, rather than a source code management
+system.  It does not track history over time; it is, instead, oriented
+toward tracking a specific set of changes against an evolving code base.
+Some major subsystem maintainers use quilt to manage patches intended to go
+upstream.  For the management of certain kinds of trees (-mm, for example),
+quilt is the best tool for the job.
+
+
+2.6: MAILING LISTS
+
+A great deal of Linux kernel development work is done by way of mailing
+lists.  It is hard to be a fully-functioning member of the community
+without joining at least one list somewhere.  But Linux mailing lists also
+represent a potential hazard to developers, who risk getting buried under a
+load of electronic mail, running afoul of the conventions used on the Linux
+lists, or both.
+
+Most kernel mailing lists are run on vger.kernel.org; the master list can
+be found at:
+
+       http://vger.kernel.org/vger-lists.html
+
+There are lists hosted elsewhere, though; a number of them are at
+lists.redhat.com.
+
+The core mailing list for kernel development is, of course, linux-kernel.
+This list is an intimidating place to be; volume can reach 500 messages per
+day, the amount of noise is high, the conversation can be severely
+technical, and participants are not always concerned with showing a high
+degree of politeness.  But there is no other place where the kernel
+development community comes together as a whole; developers who avoid this
+list will miss important information.
+
+There are a few hints which can help with linux-kernel survival:
+
+- Have the list delivered to a separate folder, rather than your main
+  mailbox.  One must be able to ignore the stream for sustained periods of
+  time.
+
+- Do not try to follow every conversation - nobody else does.  It is
+  important to filter on both the topic of interest (though note that
+  long-running conversations can drift away from the original subject
+  without changing the email subject line) and the people who are
+  participating.  
+
+- Do not feed the trolls.  If somebody is trying to stir up an angry
+  response, ignore them.
+
+- When responding to linux-kernel email (or that on other lists) preserve
+  the Cc: header for all involved.  In the absence of a strong reason (such
+  as an explicit request), you should never remove recipients.  Always make
+  sure that the person you are responding to is in the Cc: list.  This
+  convention also makes it unnecessary to explicitly ask to be copied on
+  replies to your postings.
+
+- Search the list archives (and the net as a whole) before asking
+  questions.  Some developers can get impatient with people who clearly
+  have not done their homework.
+
+- Avoid top-posting (the practice of putting your answer above the quoted
+  text you are responding to).  It makes your response harder to read and
+  makes a poor impression.
+
+- Ask on the correct mailing list.  Linux-kernel may be the general meeting
+  point, but it is not the best place to find developers from all
+  subsystems.
+
+The last point - finding the correct mailing list - is a common place for
+beginning developers to go wrong.  Somebody who asks a networking-related
+question on linux-kernel will almost certainly receive a polite suggestion
+to ask on the netdev list instead, as that is the list frequented by most
+networking developers.  Other lists exist for the SCSI, video4linux, IDE,
+filesystem, etc. subsystems.  The best place to look for mailing lists is
+in the MAINTAINERS file packaged with the kernel source.
+
+
+2.7: GETTING STARTED WITH KERNEL DEVELOPMENT
+
+Questions about how to get started with the kernel development process are
+common - from both individuals and companies.  Equally common are missteps
+which make the beginning of the relationship harder than it has to be.
+
+Companies often look to hire well-known developers to get a development
+group started.  This can, in fact, be an effective technique.  But it also
+tends to be expensive and does not do much to grow the pool of experienced
+kernel developers.  It is possible to bring in-house developers up to speed
+on Linux kernel development, given the investment of a bit of time.  Taking
+this time can endow an employer with a group of developers who understand
+the kernel and the company both, and who can help to train others as well.
+Over the medium term, this is often the more profitable approach.
+
+Individual developers are often, understandably, at a loss for a place to
+start.  Beginning with a large project can be intimidating; one often wants
+to test the waters with something smaller first.  This is the point where
+some developers jump into the creation of patches fixing spelling errors or
+minor coding style issues.  Unfortunately, such patches create a level of
+noise which is distracting for the development community as a whole, so,
+increasingly, they are looked down upon.  New developers wishing to
+introduce themselves to the community will not get the sort of reception
+they wish for by these means.
+
+Andrew Morton gives this advice for aspiring kernel developers
+
+       The #1 project for all kernel beginners should surely be "make sure
+       that the kernel runs perfectly at all times on all machines which
+       you can lay your hands on".  Usually the way to do this is to work
+       with others on getting things fixed up (this can require
+       persistence!) but that's fine - it's a part of kernel development.
+
+(http://lwn.net/Articles/283982/).
+
+In the absence of obvious problems to fix, developers are advised to look
+at the current lists of regressions and open bugs in general.  There is
+never any shortage of issues in need of fixing; by addressing these issues,
+developers will gain experience with the process while, at the same time,
+building respect with the rest of the development community.
diff --git a/Documentation/development-process/3.Early-stage b/Documentation/development-process/3.Early-stage
new file mode 100644 (file)
index 0000000..307a159
--- /dev/null
@@ -0,0 +1,195 @@
+3: EARLY-STAGE PLANNING
+
+When contemplating a Linux kernel development project, it can be tempting
+to jump right in and start coding.  As with any significant project,
+though, much of the groundwork for success is best laid before the first
+line of code is written.  Some time spent in early planning and
+communication can save far more time later on.
+
+
+3.1: SPECIFYING THE PROBLEM
+
+Like any engineering project, a successful kernel enhancement starts with a
+clear description of the problem to be solved.  In some cases, this step is
+easy: when a driver is needed for a specific piece of hardware, for
+example.  In others, though, it is tempting to confuse the real problem
+with the proposed solution, and that can lead to difficulties.
+
+Consider an example: some years ago, developers working with Linux audio
+sought a way to run applications without dropouts or other artifacts caused
+by excessive latency in the system.  The solution they arrived at was a
+kernel module intended to hook into the Linux Security Module (LSM)
+framework; this module could be configured to give specific applications
+access to the realtime scheduler.  This module was implemented and sent to
+the linux-kernel mailing list, where it immediately ran into problems.
+
+To the audio developers, this security module was sufficient to solve their
+immediate problem.  To the wider kernel community, though, it was seen as a
+misuse of the LSM framework (which is not intended to confer privileges
+onto processes which they would not otherwise have) and a risk to system
+stability.  Their preferred solutions involved realtime scheduling access
+via the rlimit mechanism for the short term, and ongoing latency reduction
+work in the long term.
+
+The audio community, however, could not see past the particular solution
+they had implemented; they were unwilling to accept alternatives.  The
+resulting disagreement left those developers feeling disillusioned with the
+entire kernel development process; one of them went back to an audio list
+and posted this:
+
+       There are a number of very good Linux kernel developers, but they
+       tend to get outshouted by a large crowd of arrogant fools. Trying
+       to communicate user requirements to these people is a waste of
+       time. They are much too "intelligent" to listen to lesser mortals.
+
+(http://lwn.net/Articles/131776/).
+
+The reality of the situation was different; the kernel developers were far
+more concerned about system stability, long-term maintenance, and finding
+the right solution to the problem than they were with a specific module.
+The moral of the story is to focus on the problem - not a specific solution
+- and to discuss it with the development community before investing in the
+creation of a body of code.
+
+So, when contemplating a kernel development project, one should obtain
+answers to a short set of questions:
+
+ - What, exactly, is the problem which needs to be solved?
+
+ - Who are the users affected by this problem?  Which use cases should the
+   solution address?
+
+ - How does the kernel fall short in addressing that problem now?
+
+Only then does it make sense to start considering possible solutions.
+
+
+3.2: EARLY DISCUSSION
+
+When planning a kernel development project, it makes great sense to hold
+discussions with the community before launching into implementation.  Early
+communication can save time and trouble in a number of ways:
+
+ - It may well be that the problem is addressed by the kernel in ways which
+   you have not understood.  The Linux kernel is large and has a number of
+   features and capabilities which are not immediately obvious.  Not all
+   kernel capabilities are documented as well as one might like, and it is
+   easy to miss things.  Your author has seen the posting of a complete
+   driver which duplicated an existing driver that the new author had been
+   unaware of.  Code which reinvents existing wheels is not only wasteful;
+   it will also not be accepted into the mainline kernel.
+
+ - There may be elements of the proposed solution which will not be
+   acceptable for mainline merging.  It is better to find out about
+   problems like this before writing the code.
+
+ - It's entirely possible that other developers have thought about the
+   problem; they may have ideas for a better solution, and may be willing
+   to help in the creation of that solution.
+
+Years of experience with the kernel development community have taught a
+clear lesson: kernel code which is designed and developed behind closed
+doors invariably has problems which are only revealed when the code is
+released into the community.  Sometimes these problems are severe,
+requiring months or years of effort before the code can be brought up to
+the kernel community's standards.  Some examples include:
+
+ - The Devicescape network stack was designed and implemented for
+   single-processor systems.  It could not be merged into the mainline
+   until it was made suitable for multiprocessor systems.  Retrofitting
+   locking and such into code is a difficult task; as a result, the merging
+   of this code (now called mac80211) was delayed for over a year.
+
+ - The Reiser4 filesystem included a number of capabilities which, in the
+   core kernel developers' opinion, should have been implemented in the
+   virtual filesystem layer instead.  It also included features which could
+   not easily be implemented without exposing the system to user-caused
+   deadlocks.  The late revelation of these problems - and refusal to
+   address some of them - has caused Reiser4 to stay out of the mainline
+   kernel.
+
+ - The AppArmor security module made use of internal virtual filesystem
+   data structures in ways which were considered to be unsafe and
+   unreliable.  This code has since been significantly reworked, but
+   remains outside of the mainline.
+
+In each of these cases, a great deal of pain and extra work could have been
+avoided with some early discussion with the kernel developers.
+
+
+3.3: WHO DO YOU TALK TO?
+
+When developers decide to take their plans public, the next question will
+be: where do we start?  The answer is to find the right mailing list(s) and
+the right maintainer.  For mailing lists, the best approach is to look in
+the MAINTAINERS file for a relevant place to post.  If there is a suitable
+subsystem list, posting there is often preferable to posting on
+linux-kernel; you are more likely to reach developers with expertise in the
+relevant subsystem and the environment may be more supportive.
+
+Finding maintainers can be a bit harder.  Again, the MAINTAINERS file is
+the place to start.  That file tends to not always be up to date, though,
+and not all subsystems are represented there.  The person listed in the
+MAINTAINERS file may, in fact, not be the person who is actually acting in
+that role currently.  So, when there is doubt about who to contact, a
+useful trick is to use git (and "git log" in particular) to see who is
+currently active within the subsystem of interest.  Look at who is writing
+patches, and who, if anybody, is attaching Signed-off-by lines to those
+patches.  Those are the people who will be best placed to help with a new
+development project.
+
+If all else fails, talking to Andrew Morton can be an effective way to
+track down a maintainer for a specific piece of code.
+
+
+3.4: WHEN TO POST?
+
+If possible, posting your plans during the early stages can only be
+helpful.  Describe the problem being solved and any plans that have been
+made on how the implementation will be done.  Any information you can
+provide can help the development community provide useful input on the
+project.
+
+One discouraging thing which can happen at this stage is not a hostile
+reaction, but, instead, little or no reaction at all.  The sad truth of the
+matter is (1) kernel developers tend to be busy, (2) there is no shortage
+of people with grand plans and little code (or even prospect of code) to
+back them up, and (3) nobody is obligated to review or comment on ideas
+posted by others.  If a request-for-comments posting yields little in the
+way of comments, do not assume that it means there is no interest in the
+project.  Unfortunately, you also cannot assume that there are no problems
+with your idea.  The best thing to do in this situation is to proceed,
+keeping the community informed as you go.
+
+
+3.5: GETTING OFFICIAL BUY-IN
+
+If your work is being done in a corporate environment - as most Linux
+kernel work is - you must, obviously, have permission from suitably
+empowered managers before you can post your company's plans or code to a
+public mailing list.  The posting of code which has not been cleared for
+release under a GPL-compatible license can be especially problematic; the
+sooner that a company's management and legal staff can agree on the posting
+of a kernel development project, the better off everybody involved will be.
+
+Some readers may be thinking at this point that their kernel work is
+intended to support a product which does not yet have an officially
+acknowledged existence.  Revealing their employer's plans on a public
+mailing list may not be a viable option.  In cases like this, it is worth
+considering whether the secrecy is really necessary; there is often no real
+need to keep development plans behind closed doors.
+
+That said, there are also cases where a company legitimately cannot
+disclose its plans early in the development process.  Companies with
+experienced kernel developers may choose to proceed in an open-loop manner
+on the assumption that they will be able to avoid serious integration
+problems later.  For companies without that sort of in-house expertise, the
+best option is often to hire an outside developer to review the plans under
+a non-disclosure agreement.  The Linux Foundation operates an NDA program
+designed to help with this sort of situation; more information can be found
+at:
+
+    http://www.linuxfoundation.org/en/NDA_program
+
+This kind of review is often enough to avoid serious problems later on
+without requiring public disclosure of the project.
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding
new file mode 100644 (file)
index 0000000..014aca8
--- /dev/null
@@ -0,0 +1,384 @@
+4: GETTING THE CODE RIGHT
+
+While there is much to be said for a solid and community-oriented design
+process, the proof of any kernel development project is in the resulting
+code.  It is the code which will be examined by other developers and merged
+(or not) into the mainline tree.  So it is the quality of this code which
+will determine the ultimate success of the project.
+
+This section will examine the coding process.  We'll start with a look at a
+number of ways in which kernel developers can go wrong.  Then the focus
+will shift toward doing things right and the tools which can help in that
+quest.
+
+
+4.1: PITFALLS
+
+* Coding style
+
+The kernel has long had a standard coding style, described in
+Documentation/CodingStyle.  For much of that time, the policies described
+in that file were taken as being, at most, advisory.  As a result, there is
+a substantial amount of code in the kernel which does not meet the coding
+style guidelines.  The presence of that code leads to two independent
+hazards for kernel developers.
+
+The first of these is to believe that the kernel coding standards do not
+matter and are not enforced.  The truth of the matter is that adding new
+code to the kernel is very difficult if that code is not coded according to
+the standard; many developers will request that the code be reformatted
+before they will even review it.  A code base as large as the kernel
+requires some uniformity of code to make it possible for developers to
+quickly understand any part of it.  So there is no longer room for
+strangely-formatted code.
+
+Occasionally, the kernel's coding style will run into conflict with an
+employer's mandated style.  In such cases, the kernel's style will have to
+win before the code can be merged.  Putting code into the kernel means
+giving up a degree of control in a number of ways - including control over
+how the code is formatted.
+
+The other trap is to assume that code which is already in the kernel is
+urgently in need of coding style fixes.  Developers may start to generate
+reformatting patches as a way of gaining familiarity with the process, or
+as a way of getting their name into the kernel changelogs - or both.  But
+pure coding style fixes are seen as noise by the development community;
+they tend to get a chilly reception.  So this type of patch is best
+avoided.  It is natural to fix the style of a piece of code while working
+on it for other reasons, but coding style changes should not be made for
+their own sake.
+
+The coding style document also should not be read as an absolute law which
+can never be transgressed.  If there is a good reason to go against the
+style (a line which becomes far less readable if split to fit within the
+80-column limit, for example), just do it.
+
+
+* Abstraction layers
+
+Computer Science professors teach students to make extensive use of
+abstraction layers in the name of flexibility and information hiding.
+Certainly the kernel makes extensive use of abstraction; no project
+involving several million lines of code could do otherwise and survive.
+But experience has shown that excessive or premature abstraction can be
+just as harmful as premature optimization.  Abstraction should be used to
+the level required and no further.
+
+At a simple level, consider a function which has an argument which is
+always passed as zero by all callers.  One could retain that argument just
+in case somebody eventually needs to use the extra flexibility that it
+provides.  By that time, though, chances are good that the code which
+implements this extra argument has been broken in some subtle way which was
+never noticed - because it has never been used.  Or, when the need for
+extra flexibility arises, it does not do so in a way which matches the
+programmer's early expectation.  Kernel developers will routinely submit
+patches to remove unused arguments; they should, in general, not be added
+in the first place.
+
+Abstraction layers which hide access to hardware - often to allow the bulk
+of a driver to be used with multiple operating systems - are especially
+frowned upon.  Such layers obscure the code and may impose a performance
+penalty; they do not belong in the Linux kernel.
+
+On the other hand, if you find yourself copying significant amounts of code
+from another kernel subsystem, it is time to ask whether it would, in fact,
+make sense to pull out some of that code into a separate library or to
+implement that functionality at a higher level.  There is no value in
+replicating the same code throughout the kernel.
+
+
+* #ifdef and preprocessor use in general
+
+The C preprocessor seems to present a powerful temptation to some C
+programmers, who see it as a way to efficiently encode a great deal of
+flexibility into a source file.  But the preprocessor is not C, and heavy
+use of it results in code which is much harder for others to read and
+harder for the compiler to check for correctness.  Heavy preprocessor use
+is almost always a sign of code which needs some cleanup work.
+
+Conditional compilation with #ifdef is, indeed, a powerful feature, and it
+is used within the kernel.  But there is little desire to see code which is
+sprinkled liberally with #ifdef blocks.  As a general rule, #ifdef use
+should be confined to header files whenever possible.
+Conditionally-compiled code can be confined to functions which, if the code
+is not to be present, simply become empty.  The compiler will then quietly
+optimize out the call to the empty function.  The result is far cleaner
+code which is easier to follow.
+
+C preprocessor macros present a number of hazards, including possible
+multiple evaluation of expressions with side effects and no type safety.
+If you are tempted to define a macro, consider creating an inline function
+instead.  The code which results will be the same, but inline functions are
+easier to read, do not evaluate their arguments multiple times, and allow
+the compiler to perform type checking on the arguments and return value.
+
+
+* Inline functions
+
+Inline functions present a hazard of their own, though.  Programmers can
+become enamored of the perceived efficiency inherent in avoiding a function
+call and fill a source file with inline functions.  Those functions,
+however, can actually reduce performance.  Since their code is replicated
+at each call site, they end up bloating the size of the compiled kernel.
+That, in turn, creates pressure on the processor's memory caches, which can
+slow execution dramatically.  Inline functions, as a rule, should be quite
+small and relatively rare.  The cost of a function call, after all, is not
+that high; the creation of large numbers of inline functions is a classic
+example of premature optimization.
+
+In general, kernel programmers ignore cache effects at their peril.  The
+classic time/space tradeoff taught in beginning data structures classes
+often does not apply to contemporary hardware.  Space *is* time, in that a
+larger program will run slower than one which is more compact.
+
+
+* Locking
+
+In May, 2006, the "Devicescape" networking stack was, with great
+fanfare, released under the GPL and made available for inclusion in the
+mainline kernel.  This donation was welcome news; support for wireless
+networking in Linux was considered substandard at best, and the Devicescape
+stack offered the promise of fixing that situation.  Yet, this code did not
+actually make it into the mainline until June, 2007 (2.6.22).  What
+happened?
+
+This code showed a number of signs of having been developed behind
+corporate doors.  But one large problem in particular was that it was not
+designed to work on multiprocessor systems.  Before this networking stack
+(now called mac80211) could be merged, a locking scheme needed to be
+retrofitted onto it.  
+
+Once upon a time, Linux kernel code could be developed without thinking
+about the concurrency issues presented by multiprocessor systems.  Now,
+however, this document is being written on a dual-core laptop.  Even on
+single-processor systems, work being done to improve responsiveness will
+raise the level of concurrency within the kernel.  The days when kernel
+code could be written without thinking about locking are long past.
+
+Any resource (data structures, hardware registers, etc.) which could be
+accessed concurrently by more than one thread must be protected by a lock.
+New code should be written with this requirement in mind; retrofitting
+locking after the fact is a rather more difficult task.  Kernel developers
+should take the time to understand the available locking primitives well
+enough to pick the right tool for the job.  Code which shows a lack of
+attention to concurrency will have a difficult path into the mainline.
+
+
+* Regressions
+
+One final hazard worth mentioning is this: it can be tempting to make a
+change (which may bring big improvements) which causes something to break
+for existing users.  This kind of change is called a "regression," and
+regressions have become most unwelcome in the mainline kernel.  With few
+exceptions, changes which cause regressions will be backed out if the
+regression cannot be fixed in a timely manner.  Far better to avoid the
+regression in the first place.
+
+It is often argued that a regression can be justified if it causes things
+to work for more people than it creates problems for.  Why not make a
+change if it brings new functionality to ten systems for each one it
+breaks?  The best answer to this question was expressed by Linus in July,
+2007:
+
+       So we don't fix bugs by introducing new problems.  That way lies
+       madness, and nobody ever knows if you actually make any real
+       progress at all. Is it two steps forwards, one step back, or one
+       step forward and two steps back?
+
+(http://lwn.net/Articles/243460/).
+
+An especially unwelcome type of regression is any sort of change to the
+user-space ABI.  Once an interface has been exported to user space, it must
+be supported indefinitely.  This fact makes the creation of user-space
+interfaces particularly challenging: since they cannot be changed in
+incompatible ways, they must be done right the first time.  For this
+reason, a great deal of thought, clear documentation, and wide review for
+user-space interfaces is always required.
+
+
+
+4.2: CODE CHECKING TOOLS
+
+For now, at least, the writing of error-free code remains an ideal that few
+of us can reach.  What we can hope to do, though, is to catch and fix as
+many of those errors as possible before our code goes into the mainline
+kernel.  To that end, the kernel developers have put together an impressive
+array of tools which can catch a wide variety of obscure problems in an
+automated way.  Any problem caught by the computer is a problem which will
+not afflict a user later on, so it stands to reason that the automated
+tools should be used whenever possible.
+
+The first step is simply to heed the warnings produced by the compiler.
+Contemporary versions of gcc can detect (and warn about) a large number of
+potential errors.  Quite often, these warnings point to real problems.
+Code submitted for review should, as a rule, not produce any compiler
+warnings.  When silencing warnings, take care to understand the real cause
+and try to avoid "fixes" which make the warning go away without addressing
+its cause.
+
+Note that not all compiler warnings are enabled by default.  Build the
+kernel with "make EXTRA_CFLAGS=-W" to get the full set.
+
+The kernel provides several configuration options which turn on debugging
+features; most of these are found in the "kernel hacking" submenu.  Several
+of these options should be turned on for any kernel used for development or
+testing purposes.  In particular, you should turn on:
+
+ - ENABLE_WARN_DEPRECATED, ENABLE_MUST_CHECK, and FRAME_WARN to get an
+   extra set of warnings for problems like the use of deprecated interfaces
+   or ignoring an important return value from a function.  The output
+   generated by these warnings can be verbose, but one need not worry about
+   warnings from other parts of the kernel.
+
+ - DEBUG_OBJECTS will add code to track the lifetime of various objects
+   created by the kernel and warn when things are done out of order.  If
+   you are adding a subsystem which creates (and exports) complex objects
+   of its own, consider adding support for the object debugging
+   infrastructure.
+
+ - DEBUG_SLAB can find a variety of memory allocation and use errors; it
+   should be used on most development kernels.
+
+ - DEBUG_SPINLOCK, DEBUG_SPINLOCK_SLEEP, and DEBUG_MUTEXES will find a
+   number of common locking errors.
+
+There are quite a few other debugging options, some of which will be
+discussed below.  Some of them have a significant performance impact and
+should not be used all of the time.  But some time spent learning the
+available options will likely be paid back many times over in short order. 
+
+One of the heavier debugging tools is the locking checker, or "lockdep."
+This tool will track the acquisition and release of every lock (spinlock or
+mutex) in the system, the order in which locks are acquired relative to
+each other, the current interrupt environment, and more.  It can then
+ensure that locks are always acquired in the same order, that the same
+interrupt assumptions apply in all situations, and so on.  In other words,
+lockdep can find a number of scenarios in which the system could, on rare
+occasion, deadlock.  This kind of problem can be painful (for both
+developers and users) in a deployed system; lockdep allows them to be found
+in an automated manner ahead of time.  Code with any sort of non-trivial
+locking should be run with lockdep enabled before being submitted for
+inclusion. 
+
+As a diligent kernel programmer, you will, beyond doubt, check the return
+status of any operation (such as a memory allocation) which can fail.  The
+fact of the matter, though, is that the resulting failure recovery paths
+are, probably, completely untested.  Untested code tends to be broken code;
+you could be much more confident of your code if all those error-handling
+paths had been exercised a few times.
+
+The kernel provides a fault injection framework which can do exactly that,
+especially where memory allocations are involved.  With fault injection
+enabled, a configurable percentage of memory allocations will be made to
+fail; these failures can be restricted to a specific range of code.
+Running with fault injection enabled allows the programmer to see how the
+code responds when things go badly.  See
+Documentation/fault-injection/fault-injection.text for more information on
+how to use this facility.
+
+Other kinds of errors can be found with the "sparse" static analysis tool.
+With sparse, the programmer can be warned about confusion between
+user-space and kernel-space addresses, mixture of big-endian and
+small-endian quantities, the passing of integer values where a set of bit
+flags is expected, and so on.  Sparse must be installed separately (it can
+be found at http://www.kernel.org/pub/software/devel/sparse/ if your
+distributor does not package it); it can then be run on the code by adding
+"C=1" to your make command.
+
+Other kinds of portability errors are best found by compiling your code for
+other architectures.  If you do not happen to have an S/390 system or a
+Blackfin development board handy, you can still perform the compilation
+step.  A large set of cross compilers for x86 systems can be found at 
+
+       http://www.kernel.org/pub/tools/crosstool/
+
+Some time spent installing and using these compilers will help avoid
+embarrassment later.
+
+
+4.3: DOCUMENTATION
+
+Documentation has often been more the exception than the rule with kernel
+development.  Even so, adequate documentation will help to ease the merging
+of new code into the kernel, make life easier for other developers, and
+will be helpful for your users.  In many cases, the addition of
+documentation has become essentially mandatory.
+
+The first piece of documentation for any patch is its associated
+changelog.  Log entries should describe the problem being solved, the form
+of the solution, the people who worked on the patch, any relevant
+effects on performance, and anything else that might be needed to
+understand the patch.
+
+Any code which adds a new user-space interface - including new sysfs or
+/proc files - should include documentation of that interface which enables
+user-space developers to know what they are working with.  See
+Documentation/ABI/README for a description of how this documentation should
+be formatted and what information needs to be provided.
+
+The file Documentation/kernel-parameters.txt describes all of the kernel's
+boot-time parameters.  Any patch which adds new parameters should add the
+appropriate entries to this file.
+
+Any new configuration options must be accompanied by help text which
+clearly explains the options and when the user might want to select them. 
+
+Internal API information for many subsystems is documented by way of
+specially-formatted comments; these comments can be extracted and formatted
+in a number of ways by the "kernel-doc" script.  If you are working within
+a subsystem which has kerneldoc comments, you should maintain them and add
+them, as appropriate, for externally-available functions.  Even in areas
+which have not been so documented, there is no harm in adding kerneldoc
+comments for the future; indeed, this can be a useful activity for
+beginning kernel developers.  The format of these comments, along with some
+information on how to create kerneldoc templates can be found in the file
+Documentation/kernel-doc-nano-HOWTO.txt.
+
+Anybody who reads through a significant amount of existing kernel code will
+note that, often, comments are most notable by their absence.  Once again,
+the expectations for new code are higher than they were in the past;
+merging uncommented code will be harder.  That said, there is little desire
+for verbosely-commented code.  The code should, itself, be readable, with
+comments explaining the more subtle aspects.
+
+Certain things should always be commented.  Uses of memory barriers should
+be accompanied by a line explaining why the barrier is necessary.  The
+locking rules for data structures generally need to be explained somewhere.
+Major data structures need comprehensive documentation in general.
+Non-obvious dependencies between separate bits of code should be pointed
+out.  Anything which might tempt a code janitor to make an incorrect
+"cleanup" needs a comment saying why it is done the way it is.  And so on.
+
+
+4.4: INTERNAL API CHANGES
+
+The binary interface provided by the kernel to user space cannot be broken
+except under the most severe circumstances.  The kernel's internal
+programming interfaces, instead, are highly fluid and can be changed when
+the need arises.  If you find yourself having to work around a kernel API,
+or simply not using a specific functionality because it does not meet your
+needs, that may be a sign that the API needs to change.  As a kernel
+developer, you are empowered to make such changes.
+
+There are, of course, some catches.  API changes can be made, but they need
+to be well justified.  So any patch making an internal API change should be
+accompanied by a description of what the change is and why it is
+necessary.  This kind of change should also be broken out into a separate
+patch, rather than buried within a larger patch.
+
+The other catch is that a developer who changes an internal API is
+generally charged with the task of fixing any code within the kernel tree
+which is broken by the change.  For a widely-used function, this duty can
+lead to literally hundreds or thousands of changes - many of which are
+likely to conflict with work being done by other developers.  Needless to
+say, this can be a large job, so it is best to be sure that the
+justification is solid.
+
+When making an incompatible API change, one should, whenever possible,
+ensure that code which has not been updated is caught by the compiler.  
+This will help you to be sure that you have found all in-tree uses of that
+interface.  It will also alert developers of out-of-tree code that there is
+a change that they need to respond to.  Supporting out-of-tree code is not
+something that kernel developers need to be worried about, but we also do
+not have to make life harder for out-of-tree developers than it it needs to
+be. 
diff --git a/Documentation/development-process/5.Posting b/Documentation/development-process/5.Posting
new file mode 100644 (file)
index 0000000..dd48132
--- /dev/null
@@ -0,0 +1,278 @@
+5: POSTING PATCHES
+
+Sooner or later, the time comes when your work is ready to be presented to
+the community for review and, eventually, inclusion into the mainline
+kernel.  Unsurprisingly, the kernel development community has evolved a set
+of conventions and procedures which are used in the posting of patches;
+following them will make life much easier for everybody involved.  This
+document will attempt to cover these expectations in reasonable detail;
+more information can also be found in the files SubmittingPatches,
+SubmittingDrivers, and SubmitChecklist in the kernel documentation
+directory.
+
+
+5.1: WHEN TO POST
+
+There is a constant temptation to avoid posting patches before they are
+completely "ready."  For simple patches, that is not a problem.  If the
+work being done is complex, though, there is a lot to be gained by getting
+feedback from the community before the work is complete.  So you should
+consider posting in-progress work, or even making a git tree available so
+that interested developers can catch up with your work at any time.
+
+When posting code which is not yet considered ready for inclusion, it is a
+good idea to say so in the posting itself.  Also mention any major work
+which remains to be done and any known problems.  Fewer people will look at
+patches which are known to be half-baked, but those who do will come in
+with the idea that they can help you drive the work in the right direction.
+
+
+5.2: BEFORE CREATING PATCHES
+
+There are a number of things which should be done before you consider
+sending patches to the development community.  These include:
+
+ - Test the code to the extent that you can.  Make use of the kernel's
+   debugging tools, ensure that the kernel will build with all reasonable
+   combinations of configuration options, use cross-compilers to build for
+   different architectures, etc.
+
+ - Make sure your code is compliant with the kernel coding style
+   guidelines.
+
+ - Does your change have performance implications?  If so, you should run
+   benchmarks showing what the impact (or benefit) of your change is; a
+   summary of the results should be included with the patch.
+
+ - Be sure that you have the right to post the code.  If this work was done
+   for an employer, the employer likely has a right to the work and must be
+   agreeable with its release under the GPL.
+
+As a general rule, putting in some extra thought before posting code almost
+always pays back the effort in short order.
+
+
+5.3: PATCH PREPARATION
+
+The preparation of patches for posting can be a surprising amount of work,
+but, once again, attempting to save time here is not generally advisable
+even in the short term.
+
+Patches must be prepared against a specific version of the kernel.  As a
+general rule, a patch should be based on the current mainline as found in
+Linus's git tree.  It may become necessary to make versions against -mm,
+linux-next, or a subsystem tree, though, to facilitate wider testing and
+review.  Depending on the area of your patch and what is going on
+elsewhere, basing a patch against these other trees can require a
+significant amount of work resolving conflicts and dealing with API
+changes.
+
+Only the most simple changes should be formatted as a single patch;
+everything else should be made as a logical series of changes.  Splitting
+up patches is a bit of an art; some developers spend a long time figuring
+out how to do it in the way that the community expects.  There are a few
+rules of thumb, however, which can help considerably:
+
+ - The patch series you post will almost certainly not be the series of
+   changes found in your working revision control system.  Instead, the
+   changes you have made need to be considered in their final form, then
+   split apart in ways which make sense.  The developers are interested in
+   discrete, self-contained changes, not the path you took to get to those
+   changes.
+
+ - Each logically independent change should be formatted as a separate
+   patch.  These changes can be small ("add a field to this structure") or
+   large (adding a significant new driver, for example), but they should be
+   conceptually small and amenable to a one-line description.  Each patch
+   should make a specific change which can be reviewed on its own and
+   verified to do what it says it does.
+
+ - As a way of restating the guideline above: do not mix different types of
+   changes in the same patch.  If a single patch fixes a critical security
+   bug, rearranges a few structures, and reformats the code, there is a
+   good chance that it will be passed over and the important fix will be
+   lost.
+
+ - Each patch should yield a kernel which builds and runs properly; if your
+   patch series is interrupted in the middle, the result should still be a
+   working kernel.  Partial application of a patch series is a common
+   scenario when the "git bisect" tool is used to find regressions; if the
+   result is a broken kernel, you will make life harder for developers and
+   users who are engaging in the noble work of tracking down problems.
+
+ - Do not overdo it, though.  One developer recently posted a set of edits
+   to a single file as 500 separate patches - an act which did not make him
+   the most popular person on the kernel mailing list.  A single patch can
+   be reasonably large as long as it still contains a single *logical*
+   change. 
+
+ - It can be tempting to add a whole new infrastructure with a series of
+   patches, but to leave that infrastructure unused until the final patch
+   in the series enables the whole thing.  This temptation should be
+   avoided if possible; if that series adds regressions, bisection will
+   finger the last patch as the one which caused the problem, even though
+   the real bug is elsewhere.  Whenever possible, a patch which adds new
+   code should make that code active immediately.
+
+Working to create the perfect patch series can be a frustrating process
+which takes quite a bit of time and thought after the "real work" has been
+done.  When done properly, though, it is time well spent.
+
+
+5.4: PATCH FORMATTING
+
+So now you have a perfect series of patches for posting, but the work is
+not done quite yet.  Each patch needs to be formatted into a message which
+quickly and clearly communicates its purpose to the rest of the world.  To
+that end, each patch will be composed of the following:
+
+ - An optional "From" line naming the author of the patch.  This line is
+   only necessary if you are passing on somebody else's patch via email,
+   but it never hurts to add it when in doubt.
+
+ - A one-line description of what the patch does.  This message should be
+   enough for a reader who sees it with no other context to figure out the
+   scope of the patch; it is the line that will show up in the "short form"
+   changelogs.  This message is usually formatted with the relevant
+   subsystem name first, followed by the purpose of the patch.  For
+   example:
+
+       gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - A blank line followed by a detailed description of the contents of the
+   patch.  This description can be as long as is required; it should say
+   what the patch does and why it should be applied to the kernel.
+
+ - One or more tag lines, with, at a minimum, one Signed-off-by: line from
+   the author of the patch.  Tags will be described in more detail below.
+
+The above three items should, normally, be the text used when committing
+the change to a revision control system.  They are followed by:
+
+ - The patch itself, in the unified ("-u") patch format.  Using the "-p"
+   option to diff will associate function names with changes, making the
+   resulting patch easier for others to read.
+
+You should avoid including changes to irrelevant files (those generated by
+the build process, for example, or editor backup files) in the patch.  The
+file "dontdiff" in the Documentation directory can help in this regard;
+pass it to diff with the "-X" option.
+
+The tags mentioned above are used to describe how various developers have
+been associated with the development of this patch.  They are described in
+detail in the SubmittingPatches document; what follows here is a brief
+summary.  Each of these lines has the format:
+
+       tag: Full Name <email address>  optional-other-stuff
+
+The tags in common use are:
+
+ - Signed-off-by: this is a developer's certification that he or she has
+   the right to submit the patch for inclusion into the kernel.  It is an
+   agreement to the Developer's Certificate of Origin, the full text of
+   which can be found in Documentation/SubmittingPatches.  Code without a
+   proper signoff cannot be merged into the mainline.
+
+ - Acked-by: indicates an agreement by another developer (often a
+   maintainer of the relevant code) that the patch is appropriate for
+   inclusion into the kernel.
+
+ - Tested-by: states that the named person has tested the patch and found
+   it to work.
+
+ - Reviewed-by: the named developer has reviewed the patch for correctness;
+   see the reviewer's statement in Documentation/SubmittingPatches for more
+   detail.
+
+ - Reported-by: names a user who reported a problem which is fixed by this
+   patch; this tag is used to give credit to the (often underappreciated)
+   people who test our code and let us know when things do not work
+   correctly.
+
+ - Cc: the named person received a copy of the patch and had the
+   opportunity to comment on it.
+
+Be careful in the addition of tags to your patches: only Cc: is appropriate
+for addition without the explicit permission of the person named.
+
+
+5.5: SENDING THE PATCH
+
+Before you mail your patches, there are a couple of other things you should
+take care of:
+
+ - Are you sure that your mailer will not corrupt the patches?  Patches
+   which have had gratuitous white-space changes or line wrapping performed
+   by the mail client will not apply at the other end, and often will not
+   be examined in any detail.  If there is any doubt at all, mail the patch
+   to yourself and convince yourself that it shows up intact.  
+
+   Documentation/email-clients.txt has some helpful hints on making
+   specific mail clients work for sending patches.
+
+ - Are you sure your patch is free of silly mistakes?  You should always
+   run patches through scripts/checkpatch.pl and address the complaints it
+   comes up with.  Please bear in mind that checkpatch.pl, while being the
+   embodiment of a fair amount of thought about what kernel patches should
+   look like, is not smarter than you.  If fixing a checkpatch.pl complaint
+   would make the code worse, don't do it.
+
+Patches should always be sent as plain text.  Please do not send them as
+attachments; that makes it much harder for reviewers to quote sections of
+the patch in their replies.  Instead, just put the patch directly into your
+message.
+
+When mailing patches, it is important to send copies to anybody who might
+be interested in it.  Unlike some other projects, the kernel encourages
+people to err on the side of sending too many copies; don't assume that the
+relevant people will see your posting on the mailing lists.  In particular,
+copies should go to:
+
+ - The maintainer(s) of the affected subsystem(s).  As described earlier,
+   the MAINTAINERS file is the first place to look for these people.
+
+ - Other developers who have been working in the same area - especially
+   those who might be working there now.  Using git to see who else has
+   modified the files you are working on can be helpful.
+
+ - If you are responding to a bug report or a feature request, copy the
+   original poster as well.
+
+ - Send a copy to the relevant mailing list, or, if nothing else applies,
+   the linux-kernel list.
+
+ - If you are fixing a bug, think about whether the fix should go into the
+   next stable update.  If so, stable@kernel.org should get a copy of the
+   patch.  Also add a "Cc: stable@kernel.org" to the tags within the patch
+   itself; that will cause the stable team to get a notification when your
+   fix goes into the mainline.
+
+When selecting recipients for a patch, it is good to have an idea of who
+you think will eventually accept the patch and get it merged.  While it
+is possible to send patches directly to Linus Torvalds and have him merge
+them, things are not normally done that way.  Linus is busy, and there are
+subsystem maintainers who watch over specific parts of the kernel.  Usually
+you will be wanting that maintainer to merge your patches.  If there is no
+obvious maintainer, Andrew Morton is often the patch target of last resort.
+
+Patches need good subject lines.  The canonical format for a patch line is
+something like:
+
+       [PATCH nn/mm] subsys: one-line description of the patch
+
+where "nn" is the ordinal number of the patch, "mm" is the total number of
+patches in the series, and "subsys" is the name of the affected subsystem.
+Clearly, nn/mm can be omitted for a single, standalone patch.  
+
+If you have a significant series of patches, it is customary to send an
+introductory description as part zero.  This convention is not universally
+followed though; if you use it, remember that information in the
+introduction does not make it into the kernel changelogs.  So please ensure
+that the patches, themselves, have complete changelog information.
+
+In general, the second and following parts of a multi-part patch should be
+sent as a reply to the first part so that they all thread together at the
+receiving end.  Tools like git and quilt have commands to mail out a set of
+patches with the proper threading.  If you have a long series, though, and
+are using git, please provide the --no-chain-reply-to option to avoid
+creating exceptionally deep nesting.
diff --git a/Documentation/development-process/6.Followthrough b/Documentation/development-process/6.Followthrough
new file mode 100644 (file)
index 0000000..a8fba3d
--- /dev/null
@@ -0,0 +1,202 @@
+6: FOLLOWTHROUGH
+
+At this point, you have followed the guidelines given so far and, with the
+addition of your own engineering skills, have posted a perfect series of
+patches.  One of the biggest mistakes that even experienced kernel
+developers can make is to conclude that their work is now done.  In truth,
+posting patches indicates a transition into the next stage of the process,
+with, possibly, quite a bit of work yet to be done.
+
+It is a rare patch which is so good at its first posting that there is no
+room for improvement.  The kernel development process recognizes this fact,
+and, as a result, is heavily oriented toward the improvement of posted
+code.  You, as the author of that code, will be expected to work with the
+kernel community to ensure that your code is up to the kernel's quality
+standards.  A failure to participate in this process is quite likely to
+prevent the inclusion of your patches into the mainline.
+
+
+6.1: WORKING WITH REVIEWERS
+
+A patch of any significance will result in a number of comments from other
+developers as they review the code.  Working with reviewers can be, for
+many developers, the most intimidating part of the kernel development
+process.  Life can be made much easier, though, if you keep a few things in
+mind:
+
+ - If you have explained your patch well, reviewers will understand its
+   value and why you went to the trouble of writing it.  But that value
+   will not keep them from asking a fundamental question: what will it be
+   like to maintain a kernel with this code in it five or ten years later?
+   Many of the changes you may be asked to make - from coding style tweaks
+   to substantial rewrites - come from the understanding that Linux will
+   still be around and under development a decade from now.
+
+ - Code review is hard work, and it is a relatively thankless occupation;
+   people remember who wrote kernel code, but there is little lasting fame
+   for those who reviewed it.  So reviewers can get grumpy, especially when
+   they see the same mistakes being made over and over again.  If you get a
+   review which seems angry, insulting, or outright offensive, resist the
+   impulse to respond in kind.  Code review is about the code, not about
+   the people, and code reviewers are not attacking you personally.
+
+ - Similarly, code reviewers are not trying to promote their employers'
+   agendas at the expense of your own.  Kernel developers often expect to
+   be working on the kernel years from now, but they understand that their
+   employer could change.  They truly are, almost without exception,
+   working toward the creation of the best kernel they can; they are not
+   trying to create discomfort for their employers' competitors.
+
+What all of this comes down to is that, when reviewers send you comments,
+you need to pay attention to the technical observations that they are
+making.  Do not let their form of expression or your own pride keep that
+from happening.  When you get review comments on a patch, take the time to
+understand what the reviewer is trying to say.  If possible, fix the things
+that the reviewer is asking you to fix.  And respond back to the reviewer:
+thank them, and describe how you will answer their questions.
+
+Note that you do not have to agree with every change suggested by
+reviewers.  If you believe that the reviewer has misunderstood your code,
+explain what is really going on.  If you have a technical objection to a
+suggested change, describe it and justify your solution to the problem.  If
+your explanations make sense, the reviewer will accept them.  Should your
+explanation not prove persuasive, though, especially if others start to
+agree with the reviewer, take some time to think things over again.  It can
+be easy to become blinded by your own solution to a problem to the point
+that you don't realize that something is fundamentally wrong or, perhaps,
+you're not even solving the right problem.
+
+One fatal mistake is to ignore review comments in the hope that they will
+go away.  They will not go away.  If you repost code without having
+responded to the comments you got the time before, you're likely to find
+that your patches go nowhere.
+
+Speaking of reposting code: please bear in mind that reviewers are not
+going to remember all the details of the code you posted the last time
+around.  So it is always a good idea to remind reviewers of previously
+raised issues and how you dealt with them; the patch changelog is a good
+place for this kind of information.  Reviewers should not have to search
+through list archives to familiarize themselves with what was said last
+time; if you help them get a running start, they will be in a better mood
+when they revisit your code.
+
+What if you've tried to do everything right and things still aren't going
+anywhere?  Most technical disagreements can be resolved through discussion,
+but there are times when somebody simply has to make a decision.  If you
+honestly believe that this decision is going against you wrongly, you can
+always try appealing to a higher power.  As of this writing, that higher
+power tends to be Andrew Morton.  Andrew has a great deal of respect in the
+kernel development community; he can often unjam a situation which seems to
+be hopelessly blocked.  Appealing to Andrew should not be done lightly,
+though, and not before all other alternatives have been explored.  And bear
+in mind, of course, that he may not agree with you either.
+
+
+6.2: WHAT HAPPENS NEXT
+
+If a patch is considered to be a good thing to add to the kernel, and once
+most of the review issues have been resolved, the next step is usually
+entry into a subsystem maintainer's tree.  How that works varies from one
+subsystem to the next; each maintainer has his or her own way of doing
+things.  In particular, there may be more than one tree - one, perhaps,
+dedicated to patches planned for the next merge window, and another for
+longer-term work.  
+
+For patches applying to areas for which there is no obvious subsystem tree
+(memory management patches, for example), the default tree often ends up
+being -mm.  Patches which affect multiple subsystems can also end up going
+through the -mm tree.
+
+Inclusion into a subsystem tree can bring a higher level of visibility to a
+patch.  Now other developers working with that tree will get the patch by
+default.  Subsystem trees typically feed into -mm and linux-next as well,
+making their contents visible to the development community as a whole.  At
+this point, there's a good chance that you will get more comments from a
+new set of reviewers; these comments need to be answered as in the previous
+round.
+
+What may also happen at this point, depending on the nature of your patch,
+is that conflicts with work being done by others turn up.  In the worst
+case, heavy patch conflicts can result in some work being put on the back
+burner so that the remaining patches can be worked into shape and merged.
+Other times, conflict resolution will involve working with the other
+developers and, possibly, moving some patches between trees to ensure that
+everything applies cleanly.  This work can be a pain, but count your
+blessings: before the advent of the linux-next tree, these conflicts often
+only turned up during the merge window and had to be addressed in a hurry.
+Now they can be resolved at leisure, before the merge window opens.
+
+Some day, if all goes well, you'll log on and see that your patch has been
+merged into the mainline kernel.  Congratulations!  Once the celebration is
+complete (and you have added yourself to the MAINTAINERS file), though, it
+is worth remembering an important little fact: the job still is not done.
+Merging into the mainline brings its own challenges.
+
+To begin with, the visibility of your patch has increased yet again.  There
+may be a new round of comments from developers who had not been aware of
+the patch before.  It may be tempting to ignore them, since there is no
+longer any question of your code being merged.  Resist that temptation,
+though; you still need to be responsive to developers who have questions or
+suggestions.
+
+More importantly, though: inclusion into the mainline puts your code into
+the hands of a much larger group of testers.  Even if you have contributed
+a driver for hardware which is not yet available, you will be surprised by
+how many people will build your code into their kernels.  And, of course,
+where there are testers, there will be bug reports.
+
+The worst sort of bug reports are regressions.  If your patch causes a
+regression, you'll find an uncomfortable number of eyes upon you;
+regressions need to be fixed as soon as possible.  If you are unwilling or
+unable to fix the regression (and nobody else does it for you), your patch
+will almost certainly be removed during the stabilization period.  Beyond
+negating all of the work you have done to get your patch into the mainline,
+having a patch pulled as the result of a failure to fix a regression could
+well make it harder for you to get work merged in the future.
+
+After any regressions have been dealt with, there may be other, ordinary
+bugs to deal with.  The stabilization period is your best opportunity to
+fix these bugs and ensure that your code's debut in a mainline kernel
+release is as solid as possible.  So, please, answer bug reports, and fix
+the problems if at all possible.  That's what the stabilization period is
+for; you can start creating cool new patches once any problems with the old
+ones have been taken care of.
+
+And don't forget that there are other milestones which may also create bug
+reports: the next mainline stable release, when prominent distributors pick
+up a version of the kernel containing your patch, etc.  Continuing to
+respond to these reports is a matter of basic pride in your work.  If that
+is insufficient motivation, though, it's also worth considering that the
+development community remembers developers who lose interest in their code
+after it's merged.  The next time you post a patch, they will be evaluating
+it with the assumption that you will not be around to maintain it
+afterward.
+
+
+6.3: OTHER THINGS THAT CAN HAPPEN
+
+One day, you may open your mail client and see that somebody has mailed you
+a patch to your code.  That is one of the advantages of having your code
+out there in the open, after all.  If you agree with the patch, you can
+either forward it on to the subsystem maintainer (be sure to include a
+proper From: line so that the attribution is correct, and add a signoff of
+your own), or send an Acked-by: response back and let the original poster
+send it upward.
+
+If you disagree with the patch, send a polite response explaining why.  If
+possible, tell the author what changes need to be made to make the patch
+acceptable to you.  There is a certain resistance to merging patches which
+are opposed by the author and maintainer of the code, but it only goes so
+far.  If you are seen as needlessly blocking good work, those patches will
+eventually flow around you and get into the mainline anyway.  In the Linux
+kernel, nobody has absolute veto power over any code.  Except maybe Linus.
+
+On very rare occasion, you may see something completely different: another
+developer posts a different solution to your problem.  At that point,
+chances are that one of the two patches will not be merged, and "mine was
+here first" is not considered to be a compelling technical argument.  If
+somebody else's patch displaces yours and gets into the mainline, there is
+really only one way to respond: be pleased that your problem got solved and
+get on with your work.  Having one's work shoved aside in this manner can
+be hurtful and discouraging, but the community will remember your reaction
+long after they have forgotten whose patch actually got merged.
diff --git a/Documentation/development-process/7.AdvancedTopics b/Documentation/development-process/7.AdvancedTopics
new file mode 100644 (file)
index 0000000..a2cf740
--- /dev/null
@@ -0,0 +1,173 @@
+7: ADVANCED TOPICS
+
+At this point, hopefully, you have a handle on how the development process
+works.  There is still more to learn, however!  This section will cover a
+number of topics which can be helpful for developers wanting to become a
+regular part of the Linux kernel development process.
+
+7.1: MANAGING PATCHES WITH GIT
+
+The use of distributed version control for the kernel began in early 2002,
+when Linus first started playing with the proprietary BitKeeper
+application.  While BitKeeper was controversial, the approach to software
+version management it embodied most certainly was not.  Distributed version
+control enabled an immediate acceleration of the kernel development
+project.  In current times, there are several free alternatives to
+BitKeeper.  For better or for worse, the kernel project has settled on git
+as its tool of choice.
+
+Managing patches with git can make life much easier for the developer,
+especially as the volume of those patches grows.  Git also has its rough
+edges and poses certain hazards; it is a young and powerful tool which is
+still being civilized by its developers.  This document will not attempt to
+teach the reader how to use git; that would be sufficient material for a
+long document in its own right.  Instead, the focus here will be on how git
+fits into the kernel development process in particular.  Developers who
+wish to come up to speed with git will find more information at:
+
+       http://git.or.cz/
+
+       http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+and on various tutorials found on the web.
+
+The first order of business is to read the above sites and get a solid
+understanding of how git works before trying to use it to make patches
+available to others.  A git-using developer should be able to obtain a copy
+of the mainline repository, explore the revision history, commit changes to
+the tree, use branches, etc.  An understanding of git's tools for the
+rewriting of history (such as rebase) is also useful.  Git comes with its
+own terminology and concepts; a new user of git should know about refs,
+remote branches, the index, fast-forward merges, pushes and pulls, detached
+heads, etc.  It can all be a little intimidating at the outset, but the
+concepts are not that hard to grasp with a bit of study.
+
+Using git to generate patches for submission by email can be a good
+exercise while coming up to speed.
+
+When you are ready to start putting up git trees for others to look at, you
+will, of course, need a server that can be pulled from.  Setting up such a
+server with git-daemon is relatively straightforward if you have a system
+which is accessible to the Internet.  Otherwise, free, public hosting sites
+(Github, for example) are starting to appear on the net.  Established
+developers can get an account on kernel.org, but those are not easy to come
+by; see http://kernel.org/faq/ for more information.
+
+The normal git workflow involves the use of a lot of branches.  Each line
+of development can be separated into a separate "topic branch" and
+maintained independently.  Branches in git are cheap, there is no reason to
+not make free use of them.  And, in any case, you should not do your
+development in any branch which you intend to ask others to pull from.
+Publicly-available branches should be created with care; merge in patches
+from development branches when they are in complete form and ready to go -
+not before.
+
+Git provides some powerful tools which can allow you to rewrite your
+development history.  An inconvenient patch (one which breaks bisection,
+say, or which has some other sort of obvious bug) can be fixed in place or
+made to disappear from the history entirely.  A patch series can be
+rewritten as if it had been written on top of today's mainline, even though
+you have been working on it for months.  Changes can be transparently
+shifted from one branch to another.  And so on.  Judicious use of git's
+ability to revise history can help in the creation of clean patch sets with
+fewer problems.
+
+Excessive use of this capability can lead to other problems, though, beyond
+a simple obsession for the creation of the perfect project history.
+Rewriting history will rewrite the changes contained in that history,
+turning a tested (hopefully) kernel tree into an untested one.  But, beyond
+that, developers cannot easily collaborate if they do not have a shared
+view of the project history; if you rewrite history which other developers
+have pulled into their repositories, you will make life much more difficult
+for those developers.  So a simple rule of thumb applies here: history
+which has been exported to others should generally be seen as immutable
+thereafter.
+
+So, once you push a set of changes to your publicly-available server, those
+changes should not be rewritten.  Git will attempt to enforce this rule if
+you try to push changes which do not result in a fast-forward merge
+(i.e. changes which do not share the same history).  It is possible to
+override this check, and there may be times when it is necessary to rewrite
+an exported tree.  Moving changesets between trees to avoid conflicts in
+linux-next is one example.  But such actions should be rare.  This is one
+of the reasons why development should be done in private branches (which
+can be rewritten if necessary) and only moved into public branches when
+it's in a reasonably advanced state.
+
+As the mainline (or other tree upon which a set of changes is based)
+advances, it is tempting to merge with that tree to stay on the leading
+edge.  For a private branch, rebasing can be an easy way to keep up with
+another tree, but rebasing is not an option once a tree is exported to the
+world.  Once that happens, a full merge must be done.  Merging occasionally
+makes good sense, but overly frequent merges can clutter the history
+needlessly.  Suggested technique in this case is to merge infrequently, and
+generally only at specific release points (such as a mainline -rc
+release).  If you are nervous about specific changes, you can always
+perform test merges in a private branch.  The git "rerere" tool can be
+useful in such situations; it remembers how merge conflicts were resolved
+so that you don't have to do the same work twice.
+
+One of the biggest recurring complaints about tools like git is this: the
+mass movement of patches from one repository to another makes it easy to
+slip in ill-advised changes which go into the mainline below the review
+radar.  Kernel developers tend to get unhappy when they see that kind of
+thing happening; putting up a git tree with unreviewed or off-topic patches
+can affect your ability to get trees pulled in the future.  Quoting Linus:
+
+       You can send me patches, but for me to pull a git patch from you, I
+       need to know that you know what you're doing, and I need to be able
+       to trust things *without* then having to go and check every
+       individual change by hand.
+
+(http://lwn.net/Articles/224135/).  
+
+To avoid this kind of situation, ensure that all patches within a given
+branch stick closely to the associated topic; a "driver fixes" branch
+should not be making changes to the core memory management code.  And, most
+importantly, do not use a git tree to bypass the review process.  Post an
+occasional summary of the tree to the relevant list, and, when the time is
+right, request that the tree be included in linux-next.
+
+If and when others start to send patches for inclusion into your tree,
+don't forget to review them.  Also ensure that you maintain the correct
+authorship information; the git "am" tool does its best in this regard, but
+you may have to add a "From:" line to the patch if it has been relayed to
+you via a third party.
+
+When requesting a pull, be sure to give all the relevant information: where
+your tree is, what branch to pull, and what changes will result from the
+pull.  The git request-pull command can be helpful in this regard; it will
+format the request as other developers expect, and will also check to be
+sure that you have remembered to push those changes to the public server. 
+
+
+7.2: REVIEWING PATCHES
+
+Some readers will certainly object to putting this section with "advanced
+topics" on the grounds that even beginning kernel developers should be
+reviewing patches.  It is certainly true that there is no better way to
+learn how to program in the kernel environment than by looking at code
+posted by others.  In addition, reviewers are forever in short supply; by
+looking at code you can make a significant contribution to the process as a
+whole.
+
+Reviewing code can be an intimidating prospect, especially for a new kernel
+developer who may well feel nervous about questioning code - in public -
+which has been posted by those with more experience.  Even code written by
+the most experienced developers can be improved, though.  Perhaps the best
+piece of advice for reviewers (all reviewers) is this: phrase review
+comments as questions rather than criticisms.  Asking "how does the lock
+get released in this path?" will always work better than stating "the
+locking here is wrong."
+
+Different developers will review code from different points of view.  Some
+are mostly concerned with coding style and whether code lines have trailing
+white space.  Others will focus primarily on whether the change implemented
+by the patch as a whole is a good thing for the kernel or not.  Yet others
+will check for problematic locking, excessive stack usage, possible
+security issues, duplication of code found elsewhere, adequate
+documentation, adverse effects on performance, user-space ABI changes, etc.
+All types of review, if they lead to better code going into the kernel, are
+welcome and worthwhile.
+
+
diff --git a/Documentation/development-process/8.Conclusion b/Documentation/development-process/8.Conclusion
new file mode 100644 (file)
index 0000000..1990ab4
--- /dev/null
@@ -0,0 +1,74 @@
+8: FOR MORE INFORMATION
+
+There are numerous sources of information on Linux kernel development and
+related topics.  First among those will always be the Documentation
+directory found in the kernel source distribution.  The top-level HOWTO
+file is an important starting point; SubmittingPatches and
+SubmittingDrivers are also something which all kernel developers should
+read.  Many internal kernel APIs are documented using the kerneldoc
+mechanism; "make htmldocs" or "make pdfdocs" can be used to generate those
+documents in HTML or PDF format (though the version of TeX shipped by some
+distributions runs into internal limits and fails to process the documents
+properly).
+
+Various web sites discuss kernel development at all levels of detail.  Your
+author would like to humbly suggest http://lwn.net/ as a source;
+information on many specific kernel topics can be found via the LWN kernel
+index at:
+
+       http://lwn.net/Kernel/Index/
+
+Beyond that, a valuable resource for kernel developers is:
+
+       http://kernelnewbies.org/
+
+Information about the linux-next tree gathers at:
+
+       http://linux.f-seidel.de/linux-next/pmwiki/
+
+And, of course, one should not forget http://kernel.org/, the definitive
+location for kernel release information.
+
+There are a number of books on kernel development:
+
+       Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro
+       Rubini, and Greg Kroah-Hartman).  Online at
+       http://lwn.net/Kernel/LDD3/.
+
+       Linux Kernel Development (Robert Love).
+
+       Understanding the Linux Kernel (Daniel Bovet and Marco Cesati).
+
+All of these books suffer from a common fault, though: they tend to be
+somewhat obsolete by the time they hit the shelves, and they have been on
+the shelves for a while now.  Still, there is quite a bit of good
+information to be found there.
+
+Documentation for git can be found at:
+
+       http://www.kernel.org/pub/software/scm/git/docs/
+
+       http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+
+9: CONCLUSION
+
+Congratulations to anybody who has made it through this long-winded
+document.  Hopefully it has provided a helpful understanding of how the
+Linux kernel is developed and how you can participate in that process.
+
+In the end, it's the participation that matters.  Any open source software
+project is no more than the sum of what its contributors put into it.  The
+Linux kernel has progressed as quickly and as well as it has because it has
+been helped by an impressively large group of developers, all of whom are
+working to make it better.  The kernel is a premier example of what can be
+done when thousands of people work together toward a common goal.
+
+The kernel can always benefit from a larger developer base, though.  There
+is always more work to do.  But, just as importantly, most other
+participants in the Linux ecosystem can benefit through contributing to the
+kernel.  Getting code into the mainline is the key to higher code quality,
+lower maintenance and distribution costs, a higher level of influence over
+the direction of kernel development, and more.  It is a situation where
+everybody involved wins.  Fire up your editor and come join us; you will be
+more than welcome.
index 27809357da58755c4484d711a6bc90534ec07a29..1e89a51ea49b9fa83a8d7cb2d7b61d9eccbfeb25 100644 (file)
@@ -2,11 +2,13 @@
 *.aux
 *.bin
 *.cpio
-*.css
+*.csp
+*.dsp
 *.dvi
+*.elf
 *.eps
-*.fw.gen.S
 *.fw
+*.gen.S
 *.gif
 *.grep
 *.grp
@@ -30,6 +32,7 @@
 *.s
 *.sgml
 *.so
+*.so.dbg
 *.symtypes
 *.tab.c
 *.tab.h
 *.xml
 *_MODULES
 *_vga16.c
-*cscope*
 *~
 *.9
 *.9.gz
 .*
-.cscope
-.gitignore
-.mailmap
 .mm
 53c700_d.h
-53c8xx_d.h*
-COPYING
-CREDITS
 CVS
 ChangeSet
 Image
 Kerntypes
-MODS.txt
+Module.markers
 Module.symvers
 PENDING
 SCCS
@@ -73,7 +69,9 @@ autoconf.h*
 bbootsect
 bin2c
 binkernel.spec
+binoffset
 bootsect
+bounds.h
 bsetup
 btfixupprep
 build
@@ -89,39 +87,36 @@ config_data.h*
 config_data.gz*
 conmakehash
 consolemap_deftbl.c*
+cpustr.h
 crc32table.h*
 cscope.*
-defkeymap.c*
+defkeymap.c
 devlist.h*
 docproc
-dummy_sym.c*
 elf2ecoff
 elfconfig.h*
-filelist
 fixdep
 fore200e_mkfirm
 fore200e_pca_fw.c*
 gconf
 gen-devlist
-gen-kdb_cmds.c*
 gen_crc32table
 gen_init_cpio
 genksyms
-gentbl
 *_gray256.c
+ihex2fw
 ikconfig.h*
 initramfs_data.cpio
 initramfs_data.cpio.gz
 initramfs_list
 kallsyms
 kconfig
-kconfig.tk
-keywords.c*
+keywords.c
 ksym.c*
 ksym.h*
 kxgettext
 lkc_defs.h
-lex.c*
+lex.c
 lex.*.c
 logo_*.c
 logo_*_clut224.c
@@ -130,7 +125,6 @@ lxdialog
 mach-types
 mach-types.h
 machtypes.h
-make_times_h
 map
 maui_boot.h
 mconf
@@ -138,6 +132,7 @@ miboot*
 mk_elfconfig
 mkboot
 mkbugboot
+mkcpustr
 mkdep
 mkprep
 mktables
@@ -145,11 +140,12 @@ mktree
 modpost
 modules.order
 modversions.h*
+ncscope.*
 offset.h
 offsets.h
 oui.c*
-parse.c*
-parse.h*
+parse.c
+parse.h
 patches*
 pca200e.bin
 pca200e_ecd.bin2
@@ -157,7 +153,7 @@ piggy.gz
 piggyback
 pnmtologo
 ppc_defs.h*
-promcon_tbl.c*
+promcon_tbl.c
 pss_boot.h
 qconf
 raid6altivec*.c
@@ -168,27 +164,38 @@ series
 setup
 setup.bin
 setup.elf
-sim710_d.h*
 sImage
 sm_tbl*
 split-include
+syscalltab.h
 tags
 tftpboot.img
 timeconst.h
 times.h*
-tkparse
 trix_boot.h
 utsrelease.h*
+vdso-syms.lds
 vdso.lds
+vdso32-int80-syms.lds
+vdso32-syms.lds
+vdso32-syscall-syms.lds
+vdso32-sysenter-syms.lds
+vdso32.lds
+vdso32.so.dbg
+vdso64.lds
+vdso64.so.dbg
 version.h*
 vmlinux
 vmlinux-*
 vmlinux.aout
-vmlinux*.lds*
-vmlinux*.scr
+vmlinux.lds
 vsyscall.lds
+vsyscall_32.lds
 wanxlfw.inc
 uImage
 unifdef
+wakeup.bin
+wakeup.elf
+wakeup.lds
 zImage*
 zconf.hash.c
index 27a3160650a468bed78a1483d485e1ccbf51bd6d..dd9e944ea6283c7e7e1f321458f94affedfdbdd2 100644 (file)
@@ -14,6 +14,7 @@ graphics devices.  These would include:
        Intel 915GM
        Intel 945G
        Intel 945GM
+       Intel 945GME
        Intel 965G
        Intel 965GM
 
index bcfc233a0080d53146c77f57ee1c96eac7e5e6a4..7ac3c4078ff956985254535c4cc9177519bec05e 100644 (file)
@@ -52,7 +52,7 @@ are either given on the kernel command line or as module parameters, e.g.:
 
  video=uvesafb:1024x768-32,mtrr:3,ywrap (compiled into the kernel)
 
- # modprobe uvesafb mode=1024x768-32 mtrr=3 scroll=ywrap  (module)
+ # modprobe uvesafb mode_option=1024x768-32 mtrr=3 scroll=ywrap  (module)
 
 Accepted options:
 
@@ -105,7 +105,7 @@ vtotal:n
 <mode>  The mode you want to set, in the standard modedb format.  Refer to
         modedb.txt for a detailed description.  When uvesafb is compiled as
         a module, the mode string should be provided as a value of the
-        'mode' option.
+        'mode_option' option.
 
 vbemode:x
         Force the use of VBE mode x.  The mode will only be set if it's
diff --git a/Documentation/fb/viafb.modes b/Documentation/fb/viafb.modes
new file mode 100644 (file)
index 0000000..02e5b48
--- /dev/null
@@ -0,0 +1,870 @@
+#
+#
+#   These data are based on the CRTC parameters in
+#
+#       VIA Integration Graphics Chip
+#       (C) 2004 VIA Technologies Inc.
+#
+
+#
+#   640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      640     480
+#   Scan Frequency      31.469 kHz  59.94 Hz
+#   Sync Width      3.813 us    0.064 ms
+#               12 chars    2 lines
+#   Front Porch     0.636 us    0.318  ms
+#               2 chars     10 lines
+#   Back Porch      1.907 us    1.048  ms
+#               6 chars     33 lines
+#   Active Time     25.422 us   15.253 ms
+#               80 chars    480 lines
+#   Blank Time      6.356 us    1.430 ms
+#               20 chars    45 lines
+#   Polarity        negative    negative
+#
+
+mode "640x480-60"
+# D: 25.175 MHz, H: 31.469 kHz, V: 59.94 Hz
+    geometry 640 480 640 480 32
+    timings 39722 48 16 33 10 96 2 endmode mode "480x640-60"
+# D: 24.823 MHz, H: 39.780 kHz, V: 60.00 Hz
+    geometry 480 640 480 640 32 timings 39722 72 24 19 1 48 3 endmode
+#
+#   640x480, 75 Hz, Non-Interlaced (31.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      640     480
+#   Scan Frequency      37.500 kHz  75.00 Hz
+#   Sync Width      2.032 us    0.080 ms
+#               8 chars     3 lines
+#   Front Porch     0.508 us    0.027 ms
+#               2 chars     1 lines
+#   Back Porch      3.810 us    0.427 ms
+#               15 chars    16 lines
+#   Active Time     20.317 us   12.800 ms
+#               80 chars    480 lines
+#   Blank Time      6.349 us    0.533 ms
+#               25 chars    20 lines
+#   Polarity        negative    negative
+#
+    mode "640x480-75"
+# D: 31.50 MHz, H: 37.500 kHz, V: 75.00 Hz
+    geometry 640 480 640 480 32 timings 31747 120 16 16 1 64 3 endmode
+#
+#   640x480, 85 Hz, Non-Interlaced (36.000 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      640     480
+#   Scan Frequency  43.269 kHz  85.00 Hz
+#   Sync Width      1.556 us    0.069 ms
+#               7 chars     3 lines
+#   Front Porch     1.556 us    0.023 ms
+#               7 chars     1 lines
+#   Back Porch      2.222 us    0.578 ms
+#               10 chars    25 lines
+#   Active Time     17.778 us   11.093 ms
+#               80 chars    480 lines
+#   Blank Time      5.333 us    0.670 ms
+#               24 chars    29 lines
+#   Polarity        negative    negative
+#
+    mode "640x480-85"
+# D: 36.000 MHz, H: 43.269 kHz, V: 85.00 Hz
+    geometry 640 480 640 480 32 timings 27777 80 56 25 1 56 3 endmode
+#
+#   640x480, 100 Hz, Non-Interlaced (43.163 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      640     480
+#   Scan Frequency      50.900 kHz  100.00 Hz
+#   Sync Width      1.483 us    0.058 ms
+#               8 chars     3 lines
+#   Front Porch     0.927 us    0.019 ms
+#               5 chars     1 lines
+#   Back Porch      2.409 us    0.475 ms
+#               13 chars    25 lines
+#   Active Time     14.827 us   9.430 ms
+#               80 chars    480 lines
+#   Blank Time      4.819 us    0.570 ms
+#               26 chars    29 lines
+#   Polarity        positive    positive
+#
+    mode "640x480-100"
+# D: 43.163 MHz, H: 50.900 kHz, V: 100.00 Hz
+    geometry 640 480 640 480 32 timings 23168 104 40 25 1 64 3 endmode
+#
+#   640x480, 120 Hz, Non-Interlaced (52.406 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      640     480
+#   Scan Frequency      61.800 kHz  120.00 Hz
+#   Sync Width      1.221 us    0.048 ms
+#               8 chars         3 lines
+#   Front Porch     0.763 us    0.016 ms
+#               5 chars     1 lines
+#   Back Porch      1.984 us    0.496 ms
+#               13 chars    31 lines
+#   Active Time     12.212 us   7.767 ms
+#               80 chars    480 lines
+#   Blank Time      3.969 us    0.566 ms
+#               26 chars    35 lines
+#   Polarity        positive    positive
+#
+    mode "640x480-120"
+# D: 52.406 MHz, H: 61.800 kHz, V: 120.00 Hz
+    geometry 640 480 640 480 32 timings 19081 104 40 31 1 64 3 endmode
+#
+#   720x480, 60 Hz, Non-Interlaced (26.880 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      720     480
+#   Scan Frequency      30.000 kHz  60.241 Hz
+#   Sync Width      2.679 us    0.099 ms
+#               9 chars     3 lines
+#   Front Porch     0.595 us    0.033 ms
+#               2 chars     1 lines
+#   Back Porch      3.274 us    0.462 ms
+#               11 chars    14 lines
+#   Active Time     26.786 us   16.000 ms
+#               90 chars    480 lines
+#   Blank Time      6.548 us    0.600 ms
+#               22 chars    18 lines
+#   Polarity        positive    positive
+#
+    mode "720x480-60"
+# D: 26.880 MHz, H: 30.000 kHz, V: 60.24 Hz
+    geometry 720 480 720 480 32 timings 37202 88 16 14 1 72 3 endmode
+#
+#   800x480, 60 Hz, Non-Interlaced (29.581 MHz dotclock)
+#
+#               Horizontal    Vertical
+#   Resolution      800         480
+#   Scan Frequency  29.892 kHz  60.00 Hz
+#   Sync Width      2.704 us    100.604 us
+#                   10 chars    3 lines
+#   Front Porch     0.541 us    33.535 us
+#                   2 chars     1 lines
+#   Back Porch      3.245 us    435.949 us
+#                   12 chars    13 lines
+#   Active Time     27.044 us   16.097 ms
+#                   100 chars   480 lines
+#   Blank Time      6.491 us    0.570 ms
+#                   24 chars    17 lines
+#   Polarity        positive    positive
+#
+    mode "800x480-60"
+# D: 29.500 MHz, H: 29.738 kHz, V: 60.00 Hz
+    geometry 800 480 800 480 32 timings 33805 96 24 10 3 72 7 endmode
+#
+#   720x576, 60 Hz, Non-Interlaced (32.668 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      720     576
+#   Scan Frequency      35.820 kHz  60.00 Hz
+#   Sync Width      2.204 us    0.083 ms
+#               9 chars     3 lines
+#   Front Porch     0.735 us    0.027 ms
+#               3 chars     1 lines
+#   Back Porch      2.939 us    0.459 ms
+#               12 chars    17 lines
+#   Active Time     22.040 us   16.080 ms
+#               90 chars    476 lines
+#   Blank Time      5.877 us    0.586 ms
+#               24 chars    21 lines
+#   Polarity        positive    positive
+#
+    mode "720x576-60"
+# D: 32.668 MHz, H: 35.820 kHz, V: 60.00 Hz
+    geometry 720 576 720 576 32 timings 30611 96 24 17 1 72 3 endmode
+#
+#   800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      800     600
+#   Scan Frequency      37.879 kHz  60.32 Hz
+#   Sync Width      3.200 us    0.106 ms
+#               16 chars    4 lines
+#   Front Porch     1.000 us    0.026 ms
+#               5 chars     1 lines
+#   Back Porch      2.200 us    0.607 ms
+#               11 chars    23 lines
+#   Active Time     20.000 us   15.840 ms
+#               100 chars   600 lines
+#   Blank Time      6.400 us    0.739 ms
+#               32 chars    28 lines
+#   Polarity        positive    positive
+#
+    mode "800x600-60"
+# D: 40.00 MHz, H: 37.879 kHz, V: 60.32 Hz
+    geometry 800 600 800 600 32
+    timings 25000 88 40 23 1 128 4 hsync high vsync high endmode
+#
+#   800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      800     600
+#   Scan Frequency      46.875 kHz  75.00 Hz
+#   Sync Width      1.616 us    0.064 ms
+#               10 chars    3 lines
+#   Front Porch     0.323 us    0.021 ms
+#               2 chars     1 lines
+#   Back Porch      3.232 us    0.448 ms
+#               20 chars    21 lines
+#   Active Time     16.162 us   12.800 ms
+#               100 chars   600 lines
+#   Blank Time      5.172 us    0.533 ms
+#               32 chars    25 lines
+#   Polarity        positive    positive
+#
+    mode "800x600-75"
+# D: 49.50 MHz, H: 46.875 kHz, V: 75.00 Hz
+    geometry 800 600 800 600 32
+    timings 20203 160 16 21 1 80 3 hsync high vsync high endmode
+#
+#   800x600, 85 Hz, Non-Interlaced (56.25 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      800     600
+#   Scan Frequency      53.674 kHz  85.061 Hz
+#   Sync Width      1.138 us    0.056 ms
+#               8 chars     3 lines
+#   Front Porch     0.569 us    0.019 ms
+#               4 chars     1 lines
+#   Back Porch      2.702 us    0.503 ms
+#               19 chars    27 lines
+#   Active Time     14.222 us   11.179 ms
+#               100 chars   600 lines
+#   Blank Time      4.409 us    0.578 ms
+#               31 chars    31 lines
+#   Polarity        positive    positive
+#
+    mode "800x600-85"
+# D: 56.25 MHz, H: 53.674 kHz, V: 85.061 Hz
+    geometry 800 600 800 600 32
+    timings 17777 152 32 27 1 64 3 hsync high vsync high endmode
+#
+#   800x600, 100 Hz, Non-Interlaced (67.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      800     600
+#   Scan Frequency      62.500 kHz  100.00 Hz
+#   Sync Width      0.948 us    0.064 ms
+#               8 chars     4 lines
+#   Front Porch     0.000 us    0.112 ms
+#               0 chars     7 lines
+#   Back Porch      3.200 us    0.224 ms
+#               27 chars    14 lines
+#   Active Time     11.852 us   9.600 ms
+#               100 chars   600 lines
+#   Blank Time      4.148 us    0.400 ms
+#               35 chars    25 lines
+#   Polarity        positive    positive
+#
+    mode "800x600-100"
+# D: 67.50 MHz, H: 62.500 kHz, V: 100.00 Hz
+    geometry 800 600 800 600 32
+    timings 14667 216 0 14 7 64 4 hsync high vsync high endmode
+#
+#   800x600, 120 Hz, Non-Interlaced (83.950 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      800     600
+#   Scan Frequency  77.160 kHz  120.00 Hz
+#   Sync Width      1.048 us    0.039 ms
+#               11 chars    3 lines
+#   Front Porch     0.667 us    0.013 ms
+#               7 chars     1 lines
+#   Back Porch      1.715 us    0.507 ms
+#               18 chars    39 lines
+#   Active Time     9.529 us    7.776 ms
+#               100 chars   600 lines
+#   Blank Time      3.431 us    0.557 ms
+#               36 chars    43 lines
+#   Polarity        positive    positive
+#
+    mode "800x600-120"
+# D: 83.950 MHz, H: 77.160 kHz, V: 120.00 Hz
+    geometry 800 600 800 600 32
+    timings 11912 144 56 39 1 88 3 hsync high vsync high endmode
+#
+#   848x480, 60 Hz, Non-Interlaced (31.490 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      848     480
+#   Scan Frequency  29.820 kHz  60.00 Hz
+#   Sync Width      2.795 us    0.099 ms
+#               11 chars    3 lines
+#   Front Porch     0.508 us    0.033 ms
+#               2 chars     1 lines
+#   Back Porch      3.303 us    0.429 ms
+#               13 chars    13 lines
+#   Active Time     26.929 us   16.097 ms
+#               106 chars   480 lines
+#   Blank Time      6.605 us    0.570 ms
+#               26 chars    17 lines
+#   Polarity        positive    positive
+#
+    mode "848x480-60"
+# D: 31.500 MHz, H: 29.830 kHz, V: 60.00 Hz
+    geometry 848 480 848 480 32
+    timings 31746 104 24 12 3 80 5 hsync high vsync high endmode
+#
+#   856x480, 60 Hz, Non-Interlaced (31.728 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      856     480
+#   Scan Frequency  29.820 kHz  60.00 Hz
+#   Sync Width      2.774 us    0.099 ms
+#               11 chars    3 lines
+#   Front Porch     0.504 us    0.033 ms
+#               2 chars     1 lines
+#   Back Porch      3.728 us    0.429 ms
+#               13 chars    13 lines
+#   Active Time     26.979 us   16.097 ms
+#               107 chars   480 lines
+#   Blank Time      6.556 us    0.570 ms
+#               26 chars    17 lines
+#   Polarity        positive    positive
+#
+    mode "856x480-60"
+# D: 31.728 MHz, H: 29.820 kHz, V: 60.00 Hz
+    geometry 856 480 856 480 32
+    timings 31518 104 16 13 1 88 3
+    hsync high vsync high endmode mode "960x600-60"
+# D: 45.250 MHz, H: 37.212 kHz, V: 60.00 Hz
+    geometry 960 600 960 600 32 timings 22099 128 32 15 3 96 6 endmode
+#
+#   1000x600, 60 Hz, Non-Interlaced (48.068 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1000     600
+#   Scan Frequency  37.320 kHz  60.00 Hz
+#   Sync Width      2.164 us    0.080 ms
+#               13 chars    3 lines
+#   Front Porch     0.832 us    0.027 ms
+#               5 chars     1 lines
+#   Back Porch      2.996 us    0.483 ms
+#               18 chars    18 lines
+#   Active Time     20.804 us   16.077 ms
+#               125 chars   600 lines
+#   Blank Time      5.991 us    0.589 ms
+#               36 chars    22 lines
+#   Polarity        negative    positive
+#
+    mode "1000x600-60"
+# D: 48.068 MHz, H: 37.320 kHz, V: 60.00 Hz
+    geometry 1000 600 1000 600 32
+    timings 20834 144 40 18 1 104 3 endmode mode "1024x576-60"
+# D: 46.996 MHz, H: 35.820 kHz, V: 60.00 Hz
+    geometry 1024 576 1024 576 32
+    timings 21278 144 40 17 1 104 3 endmode mode "1024x600-60"
+# D: 48.964 MHz, H: 37.320 kHz, V: 60.00 Hz
+    geometry 1024 600 1024 600 32
+    timings 20461 144 40 18 1 104 3 endmode mode "1088x612-60"
+# D: 52.952 MHz, H: 38.040 kHz, V: 60.00 Hz
+    geometry 1088 612 1088 612 32 timings 18877 152 48 16 3 104 5 endmode
+#
+#   1024x512, 60 Hz, Non-Interlaced (41.291 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1024    512
+#   Scan Frequency  31.860 kHz  60.00 Hz
+#   Sync Width      2.519 us    0.094 ms
+#               13 chars    3 lines
+#   Front Porch     0.775 us    0.031 ms
+#               4 chars     1 lines
+#   Back Porch      3.294 us    0.465 ms
+#               17 chars    15 lines
+#   Active Time     24.800 us   16.070 ms
+#               128 chars   512 lines
+#   Blank Time      6.587 us    0.596 ms
+#               34 chars    19 lines
+#   Polarity        positive    positive
+#
+    mode "1024x512-60"
+# D: 41.291 MHz, H: 31.860 kHz, V: 60.00 Hz
+    geometry 1024 512 1024 512 32
+    timings 24218 126 32 15 1 104 3 hsync high vsync high endmode
+#
+#   1024x600, 60 Hz, Non-Interlaced (48.875 MHz dotclock)
+#
+#                     Horizontal  Vertical
+#   Resolution          1024        768
+#   Scan Frequency      37.252 kHz  60.00 Hz
+#   Sync Width          2.128 us    80.532us
+#                       13 chars    3 lines
+#   Front Porch        0.818 us     26.844 us
+#                       5 chars     1 lines
+#   Back Porch          2.946 us    483.192 us
+#                       18 chars    18 lines
+#   Active Time         20.951 us   16.697 ms
+#                       128 chars   622 lines
+#   Blank Time          5.893 us    0.591 ms
+#                       36 chars    22 lines
+#   Polarity            negative    positive
+#
+#mode "1024x600-60"
+#     # D: 48.875 MHz, H: 37.252 kHz, V: 60.00 Hz
+#     geometry 1024 600 1024 600 32
+#    timings 20460  144 40 18 1 104  3
+# endmode
+#
+#   1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1024        768
+#   Scan Frequency      48.363 kHz  60.00 Hz
+#   Sync Width      2.092 us    0.124 ms
+#               17 chars    6 lines
+#   Front Porch     0.369 us    0.062 ms
+#               3 chars     3 lines
+#   Back Porch      2.462 us    0.601 ms
+#               20 chars    29 lines
+#   Active Time     15.754 us   15.880 ms
+#               128 chars   768 lines
+#   Blank Time      4.923 us    0.786 ms
+#               40 chars    38 lines
+#   Polarity        negative    negative
+#
+    mode "1024x768-60"
+# D: 65.00 MHz, H: 48.363 kHz, V: 60.00 Hz
+    geometry 1024 768 1024 768 32 timings 15385 160 24 29 3 136 6 endmode
+#
+#   1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1024        768
+#   Scan Frequency      60.023 kHz  75.03 Hz
+#   Sync Width      1.219 us    0.050 ms
+#               12 chars    3 lines
+#   Front Porch     0.203 us    0.017 ms
+#               2 chars     1 lines
+#   Back Porch      2.235 us    0.466 ms
+#               22 chars    28 lines
+#   Active Time     13.003 us   12.795 ms
+#               128 chars   768 lines
+#   Blank Time      3.657 us    0.533 ms
+#               36 chars    32 lines
+#   Polarity        positive    positive
+#
+    mode "1024x768-75"
+# D: 78.75 MHz, H: 60.023 kHz, V: 75.03 Hz
+    geometry 1024 768 1024 768 32
+    timings 12699 176 16 28 1 96 3 hsync high vsync high endmode
+#
+#   1024x768, 85 Hz, Non-Interlaced (94.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1024        768
+#   Scan Frequency  68.677 kHz  85.00 Hz
+#   Sync Width      1.016 us    0.044 ms
+#               12 chars    3 lines
+#   Front Porch     0.508 us    0.015 ms
+#               6 chars     1 lines
+#   Back Porch      2.201 us    0.524 ms
+#               26 chars    36 lines
+#   Active Time     10.836 us   11.183 ms
+#               128 chars   768 lines
+#   Blank Time      3.725 us    0.582 ms
+#               44 chars    40 lines
+#   Polarity        positive    positive
+#
+    mode "1024x768-85"
+# D: 94.50 MHz, H: 68.677 kHz, V: 85.00 Hz
+    geometry 1024 768 1024 768 32
+    timings 10582 208 48 36 1 96 3 hsync high vsync high endmode
+#
+#   1024x768, 100 Hz, Non-Interlaced (110.0 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1024        768
+#   Scan Frequency      79.023 kHz  99.78 Hz
+#   Sync Width      0.800 us    0.101 ms
+#               11 chars    8 lines
+#   Front Porch     0.000 us    0.000 ms
+#               0 chars     0 lines
+#   Back Porch      2.545 us    0.202 ms
+#               35 chars    16 lines
+#   Active Time     9.309 us    9.719 ms
+#               128 chars   768 lines
+#   Blank Time      3.345 us    0.304 ms
+#               46 chars    24 lines
+#   Polarity        negative    negative
+#
+    mode "1024x768-100"
+# D: 113.3 MHz, H: 79.023 kHz, V: 99.78 Hz
+    geometry 1024 768 1024 768 32
+    timings 8825 280 0 16 0 88 8 endmode mode "1152x720-60"
+# D: 66.750 MHz, H: 44.859 kHz, V: 60.00 Hz
+    geometry 1152 720 1152 720 32 timings 14981 168 56 19 3 112 6 endmode
+#
+#   1152x864, 75 Hz, Non-Interlaced (110.0 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1152        864
+#   Scan Frequency      75.137 kHz  74.99 Hz
+#   Sync Width      1.309 us    0.106 ms
+#               18 chars    8 lines
+#   Front Porch     0.245 us    0.599 ms
+#               3 chars     45 lines
+#   Back Porch      1.282 us    1.132 ms
+#               18 chars    85 lines
+#   Active Time     10.473 us   11.499 ms
+#               144 chars   864 lines
+#   Blank Time      2.836 us    1.837 ms
+#               39 chars    138 lines
+#   Polarity        positive    positive
+#
+    mode "1152x864-75"
+# D: 110.0 MHz, H: 75.137 kHz, V: 74.99 Hz
+    geometry 1152 864 1152 864 32
+    timings 9259 144 24 85 45 144 8
+    hsync high vsync high endmode mode "1200x720-60"
+# D: 70.184 MHz, H: 44.760 kHz, V: 60.00 Hz
+    geometry 1200 720 1200 720 32
+    timings 14253 184 28 22 1 128 3 endmode mode "1280x600-60"
+# D: 61.503 MHz, H: 37.320 kHz, V: 60.00 Hz
+    geometry 1280 600 1280 600 32
+    timings 16260 184 28 18 1 128 3 endmode mode "1280x720-50"
+# D: 60.466 MHz, H: 37.050 kHz, V: 50.00 Hz
+    geometry 1280 720 1280 720 32
+    timings 16538 176 48 17 1 128 3 endmode mode "1280x768-50"
+# D: 65.178 MHz, H: 39.550 kHz, V: 50.00 Hz
+    geometry 1280 768 1280 768 32 timings 15342 184 28 19 1 128 3 endmode
+#
+#   1280x768, 60 Hz, Non-Interlaced (80.136 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280    768
+#   Scan Frequency  47.700 kHz  60.00 Hz
+#   Sync Width      1.697 us    0.063 ms
+#               17 chars    3 lines
+#   Front Porch     0.799 us    0.021 ms
+#               8 chars     1 lines
+#   Back Porch      2.496 us    0.483 ms
+#               25 chars    23 lines
+#   Active Time     15.973 us   16.101 ms
+#               160 chars   768 lines
+#   Blank Time      4.992 us    0.566 ms
+#               50 chars    27 lines
+#   Polarity        positive    positive
+#
+    mode "1280x768-60"
+# D: 80.13 MHz, H: 47.700 kHz, V: 60.00 Hz
+    geometry 1280 768 1280 768 32
+    timings 12480 200 48 23 1 126 3 hsync high vsync high endmode
+#
+#   1280x800, 60 Hz, Non-Interlaced (83.375 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280    800
+#   Scan Frequency  49.628 kHz  60.00 Hz
+#   Sync Width      1.631 us    60.450 us
+#                   17 chars    3 lines
+#   Front Porch     0.768 us    20.15 us
+#                   8 chars     1 lines
+#   Back Porch      2.399 us    0.483 ms
+#                   25 chars    24 lines
+#   Active Time     15.352 us   16.120 ms
+#                   160 chars   800 lines
+#   Blank Time      4.798 us    0.564 ms
+#                   50 chars    28 lines
+#   Polarity        negtive    positive
+#
+    mode "1280x800-60"
+# D: 83.500 MHz, H: 49.702 kHz, V: 60.00 Hz
+    geometry 1280 800 1280 800 32 timings 11994 200 72 22 3 128 6 endmode
+#
+#   1280x960, 60 Hz, Non-Interlaced (108.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280    960
+#   Scan Frequency  60.000 kHz  60.00 Hz
+#   Sync Width      1.037 us    0.050 ms
+#               14 chars    3 lines
+#   Front Porch     0.889 us    0.017 ms
+#               12 chars    1 lines
+#   Back Porch      2.889 us    0.600 ms
+#               39 chars    36 lines
+#   Active Time     11.852 us   16.000 ms
+#               160 chars   960 lines
+#   Blank Time      4.815 us    0.667 ms
+#               65 chars    40 lines
+#   Polarity        positive    positive
+#
+    mode "1280x960-60"
+# D: 108.00 MHz, H: 60.000 kHz, V: 60.00 Hz
+    geometry 1280 960 1280 960 32
+    timings 9259 312 96 36 1 112 3 hsync high vsync high endmode
+#
+#   1280x1024, 60 Hz, Non-Interlaced (108.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280        1024
+#   Scan Frequency      63.981 kHz  60.02 Hz
+#   Sync Width      1.037 us    0.047 ms
+#               14 chars    3 lines
+#   Front Porch     0.444 us    0.015 ms
+#               6 chars     1 lines
+#   Back Porch      2.297 us    0.594 ms
+#               31 chars    38 lines
+#   Active Time     11.852 us   16.005 ms
+#               160 chars   1024 lines
+#   Blank Time      3.778 us    0.656 ms
+#               51 chars    42 lines
+#   Polarity        positive    positive
+#
+    mode "1280x1024-60"
+# D: 108.00 MHz, H: 63.981 kHz, V: 60.02 Hz
+    geometry 1280 1024 1280 1024 32
+    timings 9260 248 48 38 1 112 3 hsync high vsync high endmode
+#
+#   1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280        1024
+#   Scan Frequency      79.976 kHz  75.02 Hz
+#   Sync Width      1.067 us    0.038 ms
+#               18 chars    3 lines
+#   Front Porch     0.119 us    0.012 ms
+#               2 chars     1 lines
+#   Back Porch      1.837 us    0.475 ms
+#               31 chars    38 lines
+#   Active Time     9.481 us    12.804 ms
+#               160 chars   1024 lines
+#   Blank Time      3.022 us    0.525 ms
+#               51 chars    42 lines
+#   Polarity        positive    positive
+#
+    mode "1280x1024-75"
+# D: 135.00 MHz, H: 79.976 kHz, V: 75.02 Hz
+    geometry 1280 1024 1280 1024 32
+    timings 7408 248 16 38 1 144 3 hsync high vsync high endmode
+#
+#   1280x1024, 85 Hz, Non-Interlaced (157.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280        1024
+#   Scan Frequency  91.146 kHz  85.02 Hz
+#   Sync Width      1.016 us    0.033 ms
+#               20 chars    3 lines
+#   Front Porch     0.406 us    0.011 ms
+#               8 chars     1 lines
+#   Back Porch      1.422 us    0.483 ms
+#               28 chars    44 lines
+#   Active Time     8.127 us    11.235 ms
+#               160 chars   1024 lines
+#   Blank Time      2.844 us    0.527 ms
+#               56 chars    48 lines
+#   Polarity        positive    positive
+#
+    mode "1280x1024-85"
+# D: 157.50 MHz, H: 91.146 kHz, V: 85.02 Hz
+    geometry 1280 1024 1280 1024 32
+    timings 6349 224 64 44 1 160 3
+    hsync high vsync high endmode mode "1440x900-60"
+# D: 106.500 MHz, H: 55.935 kHz, V: 60.00 Hz
+    geometry 1440 900 1440 900 32
+    timings 9390 232 80 25 3 152 6
+    hsync high vsync high endmode mode "1440x900-75"
+# D: 136.750 MHz, H: 70.635 kHz, V: 75.00 Hz
+    geometry 1440 900 1440 900 32
+    timings 7315 248 96 33 3 152 6 hsync high vsync high endmode
+#
+#   1440x1050, 60 Hz, Non-Interlaced (125.10 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1440        1050
+#   Scan Frequency      65.220 kHz  60.00 Hz
+#   Sync Width      1.204 us    0.046 ms
+#               19 chars    3 lines
+#   Front Porch     0.760 us    0.015 ms
+#               12 chars    1 lines
+#   Back Porch      1.964 us    0.495 ms
+#               31 chars    33 lines
+#   Active Time     11.405 us   16.099 ms
+#               180 chars   1050 lines
+#   Blank Time      3.928 us    0.567 ms
+#               62 chars    37 lines
+#   Polarity        positive    positive
+#
+    mode "1440x1050-60"
+# D: 125.10 MHz, H: 65.220 kHz, V: 60.00 Hz
+    geometry 1440 1050 1440 1050 32
+    timings 7993 248 96 33 1 152 3
+    hsync high vsync high endmode mode "1600x900-60"
+# D: 118.250 MHz, H: 55.990 kHz, V: 60.00 Hz
+    geometry 1600 900 1600 900 32
+    timings 8415 256 88 26 3 168 5 endmode mode "1600x1024-60"
+# D: 136.358 MHz, H: 63.600 kHz, V: 60.00 Hz
+    geometry 1600 1024 1600 1024 32 timings 7315 272 104 32 1 168 3 endmode
+#
+#   1600x1200, 60 Hz, Non-Interlaced (156.00 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1600        1200
+#   Scan Frequency      76.200 kHz  60.00 Hz
+#   Sync Width      1.026 us    0.105 ms
+#               20 chars    8 lines
+#   Front Porch     0.205 us    0.131 ms
+#               4 chars     10 lines
+#   Back Porch      1.636 us    0.682 ms
+#               32 chars    52 lines
+#   Active Time     10.256 us   15.748 ms
+#               200 chars   1200 lines
+#   Blank Time      2.872 us    0.866 ms
+#               56 chars    66 lines
+#   Polarity        negative    negative
+#
+    mode "1600x1200-60"
+# D: 156.00 MHz, H: 76.200 kHz, V: 60.00 Hz
+    geometry 1600 1200 1600 1200 32 timings 6172 256 32 52 10 160 8 endmode
+#
+#   1600x1200, 75 Hz, Non-Interlaced (202.50 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1600        1200
+#   Scan Frequency  93.750 kHz  75.00 Hz
+#   Sync Width      0.948 us    0.032 ms
+#               24 chars    3 lines
+#   Front Porch     0.316 us    0.011 ms
+#               8 chars     1 lines
+#   Back Porch      1.501 us    0.491 ms
+#               38 chars    46 lines
+#   Active Time     7.901 us    12.800 ms
+#               200 chars   1200 lines
+#   Blank Time      2.765 us    0.533 ms
+#               70 chars    50 lines
+#   Polarity    positive    positive
+#
+    mode "1600x1200-75"
+# D: 202.50 MHz, H: 93.750 kHz, V: 75.00 Hz
+    geometry 1600 1200 1600 1200 32
+    timings 4938 304 64 46 1 192 3
+    hsync high vsync high endmode mode "1680x1050-60"
+# D: 146.250 MHz, H: 65.290 kHz, V: 59.954 Hz
+    geometry 1680 1050 1680 1050 32
+    timings 6814 280 104 30 3 176 6
+    hsync high vsync high endmode mode "1680x1050-75"
+# D: 187.000 MHz, H: 82.306 kHz, V: 74.892 Hz
+    geometry 1680 1050 1680 1050 32
+    timings 5348 296 120 40 3 176 6
+    hsync high vsync high endmode mode "1792x1344-60"
+# D: 202.975 MHz, H: 83.460 kHz, V: 60.00 Hz
+    geometry 1792 1344 1792 1344 32
+    timings 4902 320 128 43 1 192 3
+    hsync high vsync high endmode mode "1856x1392-60"
+# D: 218.571 MHz, H: 86.460 kHz, V: 60.00 Hz
+    geometry 1856 1392 1856 1392 32
+    timings 4577 336 136 45 1 200 3
+    hsync high vsync high endmode mode "1920x1200-60"
+# D: 193.250 MHz, H: 74.556 kHz, V: 60.00 Hz
+    geometry 1920 1200 1920 1200 32
+    timings 5173 336 136 36 3 200 6
+    hsync high vsync high endmode mode "1920x1440-60"
+# D: 234.000 MHz, H:90.000 kHz, V: 60.00 Hz
+    geometry 1920 1440 1920 1440 32
+    timings 4274 344 128 56 1 208 3
+    hsync high vsync high endmode mode "1920x1440-75"
+# D: 297.000 MHz, H:112.500 kHz, V: 75.00 Hz
+    geometry 1920 1440 1920 1440 32
+    timings 3367 352 144 56 1 224 3
+    hsync high vsync high endmode mode "2048x1536-60"
+# D: 267.250 MHz, H: 95.446 kHz, V: 60.00 Hz
+    geometry 2048 1536 2048 1536 32
+    timings 3742 376 152 49 3 224 4 hsync high vsync high endmode
+#
+#   1280x720, 60 Hz, Non-Interlaced (74.481 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1280        720
+#   Scan Frequency      44.760 kHz  60.00 Hz
+#   Sync Width      1.826 us    67.024 ms
+#               17 chars    3 lines
+#   Front Porch     0.752 us    22.341 ms
+#               7 chars     1 lines
+#   Back Porch      2.578 us    491.510 ms
+#               24 chars    22 lines
+#   Active Time     17.186 us   16.086 ms
+#               160 chars   720 lines
+#   Blank Time      5.156 us    0.581 ms
+#               48 chars    26 lines
+#   Polarity        negative    negative
+#
+    mode "1280x720-60"
+# D: 74.481 MHz, H: 44.760 kHz, V: 60.00 Hz
+    geometry 1280 720 1280 720 32 timings 13426 192 64 22 1 136 3 endmode
+#
+#   1920x1080, 60 Hz, Non-Interlaced (172.798 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1920        1080
+#   Scan Frequency      67.080 kHz  60.00 Hz
+#   Sync Width      1.204 us    44.723 ms
+#               26 chars    3 lines
+#   Front Porch     0.694 us    14.908 ms
+#               15 chars     1 lines
+#   Back Porch      1.898 us    506.857 ms
+#               41 chars    34 lines
+#   Active Time     11.111 us   16.100 ms
+#               240 chars   1080 lines
+#   Blank Time      3.796 us    0.566 ms
+#               82 chars    38 lines
+#   Polarity        negative    negative
+#
+    mode "1920x1080-60"
+# D: 74.481 MHz, H: 67.080 kHz, V: 60.00 Hz
+    geometry 1920 1080 1920 1080 32 timings 5787 328 120 34 1 208 3 endmode
+#
+#   1400x1050, 60 Hz, Non-Interlaced (122.61 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1400        1050
+#   Scan Frequency      65.218 kHz  59.99 Hz
+#   Sync Width      1.037 us    0.047 ms
+#               19 chars    3 lines
+#   Front Porch     0.444 us    0.015 ms
+#               11 chars     1 lines
+#   Back Porch      1.185 us    0.188 ms
+#               30 chars    33 lines
+#   Active Time     12.963 us   16.411 ms
+#               175 chars   1050 lines
+#   Blank Time      2.667 us    0.250 ms
+#               60 chars    37 lines
+#   Polarity        negative    positive
+#
+    mode "1400x1050-60"
+# D: 122.750 MHz, H: 65.317 kHz, V: 59.99 Hz
+    geometry 1400 1050 1408 1050 32
+    timings 8214 232 88 32 3 144 4 endmode mode "1400x1050-75"
+# D: 156.000 MHz, H: 82.278 kHz, V: 74.867 Hz
+    geometry 1400 1050 1408 1050 32 timings 6410 248 104 42 3 144 4 endmode
+#
+#   1366x768, 60 Hz, Non-Interlaced (85.86 MHz dotclock)
+#
+#               Horizontal  Vertical
+#   Resolution      1366        768
+#   Scan Frequency      47.700 kHz  60.00 Hz
+#   Sync Width      1.677 us    0.063 ms
+#               18 chars    3 lines
+#   Front Porch     0.839 us    0.021 ms
+#               9 chars     1 lines
+#   Back Porch      2.516 us    0.482 ms
+#               27 chars    23 lines
+#   Active Time     15.933 us   16.101 ms
+#               171 chars   768 lines
+#   Blank Time      5.031 us    0.566 ms
+#               54 chars    27 lines
+#   Polarity        negative    positive
+#
+    mode "1360x768-60"
+# D: 84.750 MHz, H: 47.720 kHz, V: 60.00 Hz
+    geometry 1360 768 1360 768 32
+    timings 11799 208 72 22 3 136 5 endmode mode "1366x768-60"
+# D: 85.86 MHz, H: 47.700 kHz, V: 60.00 Hz
+    geometry 1366 768 1366 768 32
+    timings 11647 216 72 23 1 144 3 endmode mode "1366x768-50"
+# D: 69,924 MHz, H: 39.550 kHz, V: 50.00 Hz
+    geometry 1366 768 1366 768 32 timings 14301 200 56 19 1 144 3 endmode
diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt
new file mode 100644 (file)
index 0000000..67dbf44
--- /dev/null
@@ -0,0 +1,214 @@
+
+        VIA Integration Graphic Chip Console Framebuffer Driver
+
+[Platform]
+-----------------------
+    The console framebuffer driver is for graphics chips of
+    VIA UniChrome Family(CLE266, PM800 / CN400 / CN300,
+                        P4M800CE / P4M800Pro / CN700 / VN800,
+                        CX700 / VX700, K8M890, P4M890,
+                        CN896 / P4M900, VX800)
+
+[Driver features]
+------------------------
+    Device: CRT, LCD, DVI
+
+    Support viafb_mode:
+        CRT:
+            640x480(60, 75, 85, 100, 120 Hz), 720x480(60 Hz),
+            720x576(60 Hz), 800x600(60, 75, 85, 100, 120 Hz),
+            848x480(60 Hz), 856x480(60 Hz), 1024x512(60 Hz),
+            1024x768(60, 75, 85, 100 Hz), 1152x864(75 Hz),
+            1280x768(60 Hz), 1280x960(60 Hz), 1280x1024(60, 75, 85 Hz),
+            1440x1050(60 Hz), 1600x1200(60, 75 Hz), 1280x720(60 Hz),
+            1920x1080(60 Hz), 1400x1050(60 Hz), 800x480(60 Hz)
+
+    color depth: 8 bpp, 16 bpp, 32 bpp supports.
+
+    Support 2D hardware accelerator.
+
+[Using the viafb module]
+-- -- --------------------
+    Start viafb with default settings:
+        #modprobe viafb
+
+    Start viafb with with user options:
+        #modprobe viafb viafb_mode=800x600 viafb_bpp=16 viafb_refresh=60
+                  viafb_active_dev=CRT+DVI viafb_dvi_port=DVP1
+                  viafb_mode1=1024x768 viafb_bpp=16 viafb_refresh1=60
+                  viafb_SAMM_ON=1
+
+    viafb_mode:
+        640x480 (default)
+        720x480
+        800x600
+        1024x768
+        ......
+
+    viafb_bpp:
+        8, 16, 32 (default:32)
+
+    viafb_refresh:
+        60, 75, 85, 100, 120 (default:60)
+
+    viafb_lcd_dsp_method:
+        0 : expansion (default)
+        1 : centering
+
+    viafb_lcd_mode:
+        0 : LCD panel with LSB data format input (default)
+        1 : LCD panel with MSB data format input
+
+    viafb_lcd_panel_id:
+        0 : Resolution: 640x480, Channel: single, Dithering: Enable
+        1 : Resolution: 800x600, Channel: single, Dithering: Enable
+        2 : Resolution: 1024x768, Channel: single, Dithering: Enable (default)
+        3 : Resolution: 1280x768, Channel: single, Dithering: Enable
+        4 : Resolution: 1280x1024, Channel: dual, Dithering: Enable
+        5 : Resolution: 1400x1050, Channel: dual, Dithering: Enable
+        6 : Resolution: 1600x1200, Channel: dual, Dithering: Enable
+
+        8 : Resolution: 800x480, Channel: single, Dithering: Enable
+        9 : Resolution: 1024x768, Channel: dual, Dithering: Enable
+        10: Resolution: 1024x768, Channel: single, Dithering: Disable
+        11: Resolution: 1024x768, Channel: dual, Dithering: Disable
+        12: Resolution: 1280x768, Channel: single, Dithering: Disable
+        13: Resolution: 1280x1024, Channel: dual, Dithering: Disable
+        14: Resolution: 1400x1050, Channel: dual, Dithering: Disable
+        15: Resolution: 1600x1200, Channel: dual, Dithering: Disable
+        16: Resolution: 1366x768, Channel: single, Dithering: Disable
+        17: Resolution: 1024x600, Channel: single, Dithering: Enable
+        18: Resolution: 1280x768, Channel: dual, Dithering: Enable
+        19: Resolution: 1280x800, Channel: single, Dithering: Enable
+
+    viafb_accel:
+        0 : No 2D Hardware Acceleration
+        1 : 2D Hardware Acceleration (default)
+
+    viafb_SAMM_ON:
+        0 : viafb_SAMM_ON disable (default)
+        1 : viafb_SAMM_ON enable
+
+    viafb_mode1: (secondary display device)
+        640x480 (default)
+        720x480
+        800x600
+        1024x768
+        ... ...
+
+    viafb_bpp1: (secondary display device)
+        8, 16, 32 (default:32)
+
+    viafb_refresh1: (secondary display device)
+        60, 75, 85, 100, 120 (default:60)
+
+    viafb_active_dev:
+        This option is used to specify active devices.(CRT, DVI, CRT+LCD...)
+        DVI stands for DVI or HDMI, E.g., If you want to enable HDMI,
+        set viafb_active_dev=DVI. In SAMM case, the previous of
+        viafb_active_dev is primary device, and the following is
+        secondary device.
+
+        For example:
+        To enable one device, such as DVI only, we can use:
+            modprobe viafb viafb_active_dev=DVI
+        To enable two devices, such as CRT+DVI:
+            modprobe viafb viafb_active_dev=CRT+DVI;
+
+        For DuoView case, we can use:
+            modprobe viafb viafb_active_dev=CRT+DVI
+            OR
+            modprobe viafb viafb_active_dev=DVI+CRT...
+
+        For SAMM case:
+        If CRT is primary and DVI is secondary, we should use:
+            modprobe viafb viafb_active_dev=CRT+DVI viafb_SAMM_ON=1...
+        If DVI is primary and CRT is secondary, we should use:
+            modprobe viafb viafb_active_dev=DVI+CRT viafb_SAMM_ON=1...
+
+    viafb_display_hardware_layout:
+        This option is used to specify display hardware layout for CX700 chip.
+        1 : LCD only
+        2 : DVI only
+        3 : LCD+DVI (default)
+        4 : LCD1+LCD2 (internal + internal)
+        16: LCD1+ExternalLCD2 (internal + external)
+
+    viafb_second_size:
+        This option is used to set second device memory size(MB) in SAMM case.
+        The minimal size is 16.
+
+    viafb_platform_epia_dvi:
+        This option is used to enable DVI on EPIA - M
+        0 : No DVI on EPIA - M (default)
+        1 : DVI on EPIA - M
+
+    viafb_bus_width:
+        When using 24 - Bit Bus Width Digital Interface,
+        this option should be set.
+        12: 12-Bit LVDS or 12-Bit TMDS (default)
+        24: 24-Bit LVDS or 24-Bit TMDS
+
+    viafb_device_lcd_dualedge:
+        When using Dual Edge Panel, this option should be set.
+        0 : No Dual Edge Panel (default)
+        1 : Dual Edge Panel
+
+    viafb_video_dev:
+        This option is used to specify video output devices(CRT, DVI, LCD) for
+        duoview case.
+        For example:
+        To output video on DVI, we should use:
+            modprobe viafb viafb_video_dev=DVI...
+
+    viafb_lcd_port:
+        This option is used to specify LCD output port,
+        available values are "DVP0" "DVP1" "DFP_HIGHLOW" "DFP_HIGH" "DFP_LOW".
+        for external LCD + external DVI on CX700(External LCD is on DVP0),
+        we should use:
+            modprobe viafb viafb_lcd_port=DVP0...
+
+Notes:
+    1. CRT may not display properly for DuoView CRT & DVI display at
+       the "640x480" PAL mode with DVI overscan enabled.
+    2. SAMM stands for single adapter multi monitors. It is different from
+       multi-head since SAMM support multi monitor at driver layers, thus fbcon
+       layer doesn't even know about it; SAMM's second screen doesn't have a
+       device node file, thus a user mode application can't access it directly.
+       When SAMM is enabled, viafb_mode and viafb_mode1, viafb_bpp and
+       viafb_bpp1, viafb_refresh and viafb_refresh1 can be different.
+    3. When console is depending on viafbinfo1, dynamically change resolution
+       and bpp, need to call VIAFB specified ioctl interface VIAFB_SET_DEVICE
+       instead of calling common ioctl function FBIOPUT_VSCREENINFO since
+       viafb doesn't support multi-head well, or it will cause screen crush.
+    4. VX800 2D accelerator hasn't been supported in this driver yet. When
+       using driver on VX800, the driver will disable the acceleration
+       function as default.
+
+
+[Configure viafb with "fbset" tool]
+-----------------------------------
+    "fbset" is an inbox utility of Linux.
+    1. Inquire current viafb information, type,
+           # fbset -i
+
+    2. Set various resolutions and viafb_refresh rates,
+           # fbset <resolution-vertical_sync>
+
+       example,
+           # fbset "1024x768-75"
+       or
+           # fbset -g 1024 768 1024 768 32
+       Check the file "/etc/fb.modes" to find display modes available.
+
+    3. Set the color depth,
+           # fbset -depth <value>
+
+       example,
+           # fbset -depth 16
+
+[Bootup with viafb]:
+--------------------
+    Add the following line to your grub.conf:
+    append = "video=viafb:viafb_mode=1024x768,viafb_bpp=32,viafb_refresh=85"
+
index 3d2d0c29f02735e01e1acbc3bf3d1c97440352f2..f5f812daf9f439658bcc710164b2912dc2430e75 100644 (file)
@@ -287,11 +287,19 @@ Who:      Glauber Costa <gcosta@redhat.com>
 
 ---------------------------
 
-What:  old style serial driver for ColdFire (CONFIG_SERIAL_COLDFIRE)
-When:  2.6.28
-Why:   This driver still uses the old interface and has been replaced
-       by CONFIG_SERIAL_MCF.
-Who:   Sebastian Siewior <sebastian@breakpoint.cc>
+What:  remove HID compat support
+When:  2.6.29
+Why:   needed only as a temporary solution until distros fix themselves up
+Who:   Jiri Slaby <jirislaby@gmail.com>
+
+---------------------------
+
+What: print_fn_descriptor_symbol()
+When: October 2009
+Why:  The %pF vsprintf format provides the same functionality in a
+      simpler way.  print_fn_descriptor_symbol() is deprecated but
+      still present to give out-of-tree modules time to change.
+Who:  Bjorn Helgaas <bjorn.helgaas@hp.com>
 
 ---------------------------
 
diff --git a/Documentation/filesystems/autofs4-mount-control.txt b/Documentation/filesystems/autofs4-mount-control.txt
new file mode 100644 (file)
index 0000000..c634174
--- /dev/null
@@ -0,0 +1,393 @@
+
+Miscellaneous Device control operations for the autofs4 kernel module
+====================================================================
+
+The problem
+===========
+
+There is a problem with active restarts in autofs (that is to say
+restarting autofs when there are busy mounts).
+
+During normal operation autofs uses a file descriptor opened on the
+directory that is being managed in order to be able to issue control
+operations. Using a file descriptor gives ioctl operations access to
+autofs specific information stored in the super block. The operations
+are things such as setting an autofs mount catatonic, setting the
+expire timeout and requesting expire checks. As is explained below,
+certain types of autofs triggered mounts can end up covering an autofs
+mount itself which prevents us being able to use open(2) to obtain a
+file descriptor for these operations if we don't already have one open.
+
+Currently autofs uses "umount -l" (lazy umount) to clear active mounts
+at restart. While using lazy umount works for most cases, anything that
+needs to walk back up the mount tree to construct a path, such as
+getcwd(2) and the proc file system /proc/<pid>/cwd, no longer works
+because the point from which the path is constructed has been detached
+from the mount tree.
+
+The actual problem with autofs is that it can't reconnect to existing
+mounts. Immediately one thinks of just adding the ability to remount
+autofs file systems would solve it, but alas, that can't work. This is
+because autofs direct mounts and the implementation of "on demand mount
+and expire" of nested mount trees have the file system mounted directly
+on top of the mount trigger directory dentry.
+
+For example, there are two types of automount maps, direct (in the kernel
+module source you will see a third type called an offset, which is just
+a direct mount in disguise) and indirect.
+
+Here is a master map with direct and indirect map entries:
+
+/-      /etc/auto.direct
+/test   /etc/auto.indirect
+
+and the corresponding map files:
+
+/etc/auto.direct:
+
+/automount/dparse/g6  budgie:/autofs/export1
+/automount/dparse/g1  shark:/autofs/export1
+and so on.
+
+/etc/auto.indirect:
+
+g1    shark:/autofs/export1
+g6    budgie:/autofs/export1
+and so on.
+
+For the above indirect map an autofs file system is mounted on /test and
+mounts are triggered for each sub-directory key by the inode lookup
+operation. So we see a mount of shark:/autofs/export1 on /test/g1, for
+example.
+
+The way that direct mounts are handled is by making an autofs mount on
+each full path, such as /automount/dparse/g1, and using it as a mount
+trigger. So when we walk on the path we mount shark:/autofs/export1 "on
+top of this mount point". Since these are always directories we can
+use the follow_link inode operation to trigger the mount.
+
+But, each entry in direct and indirect maps can have offsets (making
+them multi-mount map entries).
+
+For example, an indirect mount map entry could also be:
+
+g1  \
+   /        shark:/autofs/export5/testing/test \
+   /s1      shark:/autofs/export/testing/test/s1 \
+   /s2      shark:/autofs/export5/testing/test/s2 \
+   /s1/ss1  shark:/autofs/export1 \
+   /s2/ss2  shark:/autofs/export2
+
+and a similarly a direct mount map entry could also be:
+
+/automount/dparse/g1 \
+    /       shark:/autofs/export5/testing/test \
+    /s1     shark:/autofs/export/testing/test/s1 \
+    /s2     shark:/autofs/export5/testing/test/s2 \
+    /s1/ss1 shark:/autofs/export2 \
+    /s2/ss2 shark:/autofs/export2
+
+One of the issues with version 4 of autofs was that, when mounting an
+entry with a large number of offsets, possibly with nesting, we needed
+to mount and umount all of the offsets as a single unit. Not really a
+problem, except for people with a large number of offsets in map entries.
+This mechanism is used for the well known "hosts" map and we have seen
+cases (in 2.4) where the available number of mounts are exhausted or
+where the number of privileged ports available is exhausted.
+
+In version 5 we mount only as we go down the tree of offsets and
+similarly for expiring them which resolves the above problem. There is
+somewhat more detail to the implementation but it isn't needed for the
+sake of the problem explanation. The one important detail is that these
+offsets are implemented using the same mechanism as the direct mounts
+above and so the mount points can be covered by a mount.
+
+The current autofs implementation uses an ioctl file descriptor opened
+on the mount point for control operations. The references held by the
+descriptor are accounted for in checks made to determine if a mount is
+in use and is also used to access autofs file system information held
+in the mount super block. So the use of a file handle needs to be
+retained.
+
+
+The Solution
+============
+
+To be able to restart autofs leaving existing direct, indirect and
+offset mounts in place we need to be able to obtain a file handle
+for these potentially covered autofs mount points. Rather than just
+implement an isolated operation it was decided to re-implement the
+existing ioctl interface and add new operations to provide this
+functionality.
+
+In addition, to be able to reconstruct a mount tree that has busy mounts,
+the uid and gid of the last user that triggered the mount needs to be
+available because these can be used as macro substitution variables in
+autofs maps. They are recorded at mount request time and an operation
+has been added to retrieve them.
+
+Since we're re-implementing the control interface, a couple of other
+problems with the existing interface have been addressed. First, when
+a mount or expire operation completes a status is returned to the
+kernel by either a "send ready" or a "send fail" operation. The
+"send fail" operation of the ioctl interface could only ever send
+ENOENT so the re-implementation allows user space to send an actual
+status. Another expensive operation in user space, for those using
+very large maps, is discovering if a mount is present. Usually this
+involves scanning /proc/mounts and since it needs to be done quite
+often it can introduce significant overhead when there are many entries
+in the mount table. An operation to lookup the mount status of a mount
+point dentry (covered or not) has also been added.
+
+Current kernel development policy recommends avoiding the use of the
+ioctl mechanism in favor of systems such as Netlink. An implementation
+using this system was attempted to evaluate its suitability and it was
+found to be inadequate, in this case. The Generic Netlink system was
+used for this as raw Netlink would lead to a significant increase in
+complexity. There's no question that the Generic Netlink system is an
+elegant solution for common case ioctl functions but it's not a complete
+replacement probably because it's primary purpose in life is to be a
+message bus implementation rather than specifically an ioctl replacement.
+While it would be possible to work around this there is one concern
+that lead to the decision to not use it. This is that the autofs
+expire in the daemon has become far to complex because umount
+candidates are enumerated, almost for no other reason than to "count"
+the number of times to call the expire ioctl. This involves scanning
+the mount table which has proved to be a big overhead for users with
+large maps. The best way to improve this is try and get back to the
+way the expire was done long ago. That is, when an expire request is
+issued for a mount (file handle) we should continually call back to
+the daemon until we can't umount any more mounts, then return the
+appropriate status to the daemon. At the moment we just expire one
+mount at a time. A Generic Netlink implementation would exclude this
+possibility for future development due to the requirements of the
+message bus architecture.
+
+
+autofs4 Miscellaneous Device mount control interface
+====================================================
+
+The control interface is opening a device node, typically /dev/autofs.
+
+All the ioctls use a common structure to pass the needed parameter
+information and return operation results:
+
+struct autofs_dev_ioctl {
+       __u32 ver_major;
+       __u32 ver_minor;
+       __u32 size;             /* total size of data passed in
+                                * including this struct */
+       __s32 ioctlfd;          /* automount command fd */
+
+       __u32 arg1;             /* Command parameters */
+       __u32 arg2;
+
+       char path[0];
+};
+
+The ioctlfd field is a mount point file descriptor of an autofs mount
+point. It is returned by the open call and is used by all calls except
+the check for whether a given path is a mount point, where it may
+optionally be used to check a specific mount corresponding to a given
+mount point file descriptor, and when requesting the uid and gid of the
+last successful mount on a directory within the autofs file system.
+
+The fields arg1 and arg2 are used to communicate parameters and results of
+calls made as described below.
+
+The path field is used to pass a path where it is needed and the size field
+is used account for the increased structure length when translating the
+structure sent from user space.
+
+This structure can be initialized before setting specific fields by using
+the void function call init_autofs_dev_ioctl(struct autofs_dev_ioctl *).
+
+All of the ioctls perform a copy of this structure from user space to
+kernel space and return -EINVAL if the size parameter is smaller than
+the structure size itself, -ENOMEM if the kernel memory allocation fails
+or -EFAULT if the copy itself fails. Other checks include a version check
+of the compiled in user space version against the module version and a
+mismatch results in a -EINVAL return. If the size field is greater than
+the structure size then a path is assumed to be present and is checked to
+ensure it begins with a "/" and is NULL terminated, otherwise -EINVAL is
+returned. Following these checks, for all ioctl commands except
+AUTOFS_DEV_IOCTL_VERSION_CMD, AUTOFS_DEV_IOCTL_OPENMOUNT_CMD and
+AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD the ioctlfd is validated and if it is
+not a valid descriptor or doesn't correspond to an autofs mount point
+an error of -EBADF, -ENOTTY or -EINVAL (not an autofs descriptor) is
+returned.
+
+
+The ioctls
+==========
+
+An example of an implementation which uses this interface can be seen
+in autofs version 5.0.4 and later in file lib/dev-ioctl-lib.c of the
+distribution tar available for download from kernel.org in directory
+/pub/linux/daemons/autofs/v5.
+
+The device node ioctl operations implemented by this interface are:
+
+
+AUTOFS_DEV_IOCTL_VERSION
+------------------------
+
+Get the major and minor version of the autofs4 device ioctl kernel module
+implementation. It requires an initialized struct autofs_dev_ioctl as an
+input parameter and sets the version information in the passed in structure.
+It returns 0 on success or the error -EINVAL if a version mismatch is
+detected.
+
+
+AUTOFS_DEV_IOCTL_PROTOVER_CMD and AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD
+------------------------------------------------------------------
+
+Get the major and minor version of the autofs4 protocol version understood
+by loaded module. This call requires an initialized struct autofs_dev_ioctl
+with the ioctlfd field set to a valid autofs mount point descriptor
+and sets the requested version number in structure field arg1. These
+commands return 0 on success or one of the negative error codes if
+validation fails.
+
+
+AUTOFS_DEV_IOCTL_OPENMOUNT and AUTOFS_DEV_IOCTL_CLOSEMOUNT
+----------------------------------------------------------
+
+Obtain and release a file descriptor for an autofs managed mount point
+path. The open call requires an initialized struct autofs_dev_ioctl with
+the the path field set and the size field adjusted appropriately as well
+as the arg1 field set to the device number of the autofs mount. The
+device number can be obtained from the mount options shown in
+/proc/mounts. The close call requires an initialized struct
+autofs_dev_ioct with the ioctlfd field set to the descriptor obtained
+from the open call. The release of the file descriptor can also be done
+with close(2) so any open descriptors will also be closed at process exit.
+The close call is included in the implemented operations largely for
+completeness and to provide for a consistent user space implementation.
+
+
+AUTOFS_DEV_IOCTL_READY_CMD and AUTOFS_DEV_IOCTL_FAIL_CMD
+--------------------------------------------------------
+
+Return mount and expire result status from user space to the kernel.
+Both of these calls require an initialized struct autofs_dev_ioctl
+with the ioctlfd field set to the descriptor obtained from the open
+call and the arg1 field set to the wait queue token number, received
+by user space in the foregoing mount or expire request. The arg2 field
+is set to the status to be returned. For the ready call this is always
+0 and for the fail call it is set to the errno of the operation.
+
+
+AUTOFS_DEV_IOCTL_SETPIPEFD_CMD
+------------------------------
+
+Set the pipe file descriptor used for kernel communication to the daemon.
+Normally this is set at mount time using an option but when reconnecting
+to a existing mount we need to use this to tell the autofs mount about
+the new kernel pipe descriptor. In order to protect mounts against
+incorrectly setting the pipe descriptor we also require that the autofs
+mount be catatonic (see next call).
+
+The call requires an initialized struct autofs_dev_ioctl with the
+ioctlfd field set to the descriptor obtained from the open call and
+the arg1 field set to descriptor of the pipe. On success the call
+also sets the process group id used to identify the controlling process
+(eg. the owning automount(8) daemon) to the process group of the caller.
+
+
+AUTOFS_DEV_IOCTL_CATATONIC_CMD
+------------------------------
+
+Make the autofs mount point catatonic. The autofs mount will no longer
+issue mount requests, the kernel communication pipe descriptor is released
+and any remaining waits in the queue released.
+
+The call requires an initialized struct autofs_dev_ioctl with the
+ioctlfd field set to the descriptor obtained from the open call.
+
+
+AUTOFS_DEV_IOCTL_TIMEOUT_CMD
+----------------------------
+
+Set the expire timeout for mounts withing an autofs mount point.
+
+The call requires an initialized struct autofs_dev_ioctl with the
+ioctlfd field set to the descriptor obtained from the open call.
+
+
+AUTOFS_DEV_IOCTL_REQUESTER_CMD
+------------------------------
+
+Return the uid and gid of the last process to successfully trigger a the
+mount on the given path dentry.
+
+The call requires an initialized struct autofs_dev_ioctl with the path
+field set to the mount point in question and the size field adjusted
+appropriately as well as the arg1 field set to the device number of the
+containing autofs mount. Upon return the struct field arg1 contains the
+uid and arg2 the gid.
+
+When reconstructing an autofs mount tree with active mounts we need to
+re-connect to mounts that may have used the original process uid and
+gid (or string variations of them) for mount lookups within the map entry.
+This call provides the ability to obtain this uid and gid so they may be
+used by user space for the mount map lookups.
+
+
+AUTOFS_DEV_IOCTL_EXPIRE_CMD
+---------------------------
+
+Issue an expire request to the kernel for an autofs mount. Typically
+this ioctl is called until no further expire candidates are found.
+
+The call requires an initialized struct autofs_dev_ioctl with the
+ioctlfd field set to the descriptor obtained from the open call. In
+addition an immediate expire, independent of the mount timeout, can be
+requested by setting the arg1 field to 1. If no expire candidates can
+be found the ioctl returns -1 with errno set to EAGAIN.
+
+This call causes the kernel module to check the mount corresponding
+to the given ioctlfd for mounts that can be expired, issues an expire
+request back to the daemon and waits for completion.
+
+AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD
+------------------------------
+
+Checks if an autofs mount point is in use.
+
+The call requires an initialized struct autofs_dev_ioctl with the
+ioctlfd field set to the descriptor obtained from the open call and
+it returns the result in the arg1 field, 1 for busy and 0 otherwise.
+
+
+AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD
+---------------------------------
+
+Check if the given path is a mountpoint.
+
+The call requires an initialized struct autofs_dev_ioctl. There are two
+possible variations. Both use the path field set to the path of the mount
+point to check and the size field adjusted appropriately. One uses the
+ioctlfd field to identify a specific mount point to check while the other
+variation uses the path and optionaly arg1 set to an autofs mount type.
+The call returns 1 if this is a mount point and sets arg1 to the device
+number of the mount and field arg2 to the relevant super block magic
+number (described below) or 0 if it isn't a mountpoint. In both cases
+the the device number (as returned by new_encode_dev()) is returned
+in field arg1.
+
+If supplied with a file descriptor we're looking for a specific mount,
+not necessarily at the top of the mounted stack. In this case the path
+the descriptor corresponds to is considered a mountpoint if it is itself
+a mountpoint or contains a mount, such as a multi-mount without a root
+mount. In this case we return 1 if the descriptor corresponds to a mount
+point and and also returns the super magic of the covering mount if there
+is one or 0 if it isn't a mountpoint.
+
+If a path is supplied (and the ioctlfd field is set to -1) then the path
+is looked up and is checked to see if it is the root of a mount. If a
+type is also given we are looking for a particular autofs mount and if
+a match isn't found a fail is returned. If the the located path is the
+root of a mount 1 is returned along with the super magic of the mount
+or 0 otherwise.
+
index b45f3c1b8b431655f500b0a8842553ea21a5d6a0..295f26cd895a0d5cd460267a84ebbb687978fa69 100644 (file)
@@ -193,6 +193,5 @@ kernel source:      <file:fs/ext3/>
 programs:      http://e2fsprogs.sourceforge.net/
                http://ext2resize.sourceforge.net
 
-useful links:  http://www.zip.com.au/~akpm/linux/ext3/ext3-usage.html
-               http://www-106.ibm.com/developerworks/linux/library/l-fs7/
+useful links:  http://www-106.ibm.com/developerworks/linux/library/l-fs7/
                http://www-106.ibm.com/developerworks/linux/library/l-fs8/
index 31b329172343546e8f1e1fb4a30549298d45ee68..68baddf3c3e04f0c75e03dcf58a83dc926d57644 100644 (file)
@@ -169,7 +169,7 @@ They depend on various facilities being available:
 3.1)  Booting from a floppy using syslinux
 
        When building kernels, an easy way to create a boot floppy that uses
-       syslinux is to use the zdisk or bzdisk make targets which use
+       syslinux is to use the zdisk or bzdisk make targets which use zimage
        and bzimage images respectively. Both targets accept the
        FDARGS parameter which can be used to set the kernel command line.
 
index c318a8bbb1ef1efdbd68930ed687595f3c397121..4340cc825796e87d0af97df690ef4ae13fd4e320 100644 (file)
@@ -76,3 +76,9 @@ localalloc=8(*)               Allows custom localalloc size in MB. If the value is too
                        large, the fs will silently revert it to the default.
                        Localalloc is not enabled for local mounts.
 localflocks            This disables cluster aware flock.
+inode64                        Indicates that Ocfs2 is allowed to create inodes at
+                       any location in the filesystem, including those which
+                       will result in inode numbers occupying more than 32
+                       bits of significance.
+user_xattr     (*)     Enables Extended User Attributes.
+nouser_xattr           Disables Extended User Attributes.
index d831d24d2a6c133214ad3663f1d7762138e3dbe4..c032bf39e8b9b581b6ada65f7a99b97b2dae7019 100644 (file)
@@ -1321,6 +1321,18 @@ debugging information is displayed on console.
 NMI switch that most IA32 servers have fires unknown NMI up, for example.
 If a system hangs up, try pressing the NMI switch.
 
+panic_on_unrecovered_nmi
+------------------------
+
+The default Linux behaviour on an NMI of either memory or unknown is to continue
+operation. For many environments such as scientific computing it is preferable
+that the box is taken out and the error dealt with than an uncorrected
+parity/ECC error get propogated.
+
+A small number of systems do generate NMI's for bizarre random reasons such as
+power management so the default is off. That sysctl works like the existing
+panic controls already in that directory.
+
 nmi_watchdog
 ------------
 
@@ -1331,13 +1343,6 @@ determine whether or not they are still functioning properly.
 Because the NMI watchdog shares registers with oprofile, by disabling the NMI
 watchdog, oprofile may have more registers to utilize.
 
-maps_protect
-------------
-
-Enables/Disables the protection of the per-process proc entries "maps" and
-"smaps".  When enabled, the contents of these files are visible only to
-readers that are allowed to ptrace() the given process.
-
 msgmni
 ------
 
index 7be232b44ee4602f74dc0b75ed66d150c23a6aaf..62fe9b1e089031c2e30153e9dc1be6f15d30aa6c 100644 (file)
@@ -263,7 +263,7 @@ User Mode Linux, like so:
     sleep(999999999);
   }
   EOF
-  gcc -static hello2.c -o init
+  gcc -static hello.c -o init
   echo init | cpio -o -H newc | gzip > test.cpio.gz
   # Testing external initramfs using the initrd loading mechanism.
   qemu -kernel /boot/vmlinuz -initrd test.cpio.gz /dev/zero
index 18022e249c53dc1ad991d74d160551fa32f32070..b1b9887012478f9b654edaa90bcdd13e72a9f20e 100644 (file)
@@ -240,6 +240,10 @@ signal, or (b) something wrongly believes it's safe to remove drivers
 needed to manage a signal that's in active use.  That is, requesting a
 GPIO can serve as a kind of lock.
 
+Some platforms may also use knowledge about what GPIOs are active for
+power management, such as by powering down unused chip sectors and, more
+easily, gating off unused clocks.
+
 These two calls are optional because not not all current Linux platforms
 offer such functionality in their GPIO support; a valid implementation
 could return success for all gpio_request() calls.  Unlike the other calls,
@@ -264,7 +268,7 @@ map between them using calls like:
        /* map GPIO numbers to IRQ numbers */
        int gpio_to_irq(unsigned gpio);
 
-       /* map IRQ numbers to GPIO numbers */
+       /* map IRQ numbers to GPIO numbers (avoid using this) */
        int irq_to_gpio(unsigned irq);
 
 Those return either the corresponding number in the other namespace, or
@@ -284,7 +288,8 @@ system wakeup capabilities.
 
 Non-error values returned from irq_to_gpio() would most commonly be used
 with gpio_get_value(), for example to initialize or update driver state
-when the IRQ is edge-triggered.
+when the IRQ is edge-triggered.  Note that some platforms don't support
+this reverse mapping, so you should avoid using it.
 
 
 Emulating Open Drain Signals
diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt
deleted file mode 100644 (file)
index 6ad52d9..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-               High Precision Event Timer Driver for Linux
-
-The High Precision Event Timer (HPET) hardware is the future replacement
-for the 8254 and Real Time Clock (RTC) periodic timer functionality.
-Each HPET can have up to 32 timers.  It is possible to configure the
-first two timers as legacy replacements for 8254 and RTC periodic timers.
-A specification done by Intel and Microsoft can be found at
-<http://www.intel.com/technology/architecture/hpetspec.htm>.
-
-The driver supports detection of HPET driver allocation and initialization
-of the HPET before the driver module_init routine is called.  This enables
-platform code which uses timer 0 or 1 as the main timer to intercept HPET
-initialization.  An example of this initialization can be found in
-arch/i386/kernel/time_hpet.c.
-
-The driver provides two APIs which are very similar to the API found in
-the rtc.c driver.  There is a user space API and a kernel space API.
-An example user space program is provided below.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <memory.h>
-#include <malloc.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <linux/hpet.h>
-
-
-extern void hpet_open_close(int, const char **);
-extern void hpet_info(int, const char **);
-extern void hpet_poll(int, const char **);
-extern void hpet_fasync(int, const char **);
-extern void hpet_read(int, const char **);
-
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-
-struct hpet_command {
-       char            *command;
-       void            (*func)(int argc, const char ** argv);
-} hpet_command[] = {
-       {
-               "open-close",
-               hpet_open_close
-       },
-       {
-               "info",
-               hpet_info
-       },
-       {
-               "poll",
-               hpet_poll
-       },
-       {
-               "fasync",
-               hpet_fasync
-       },
-};
-
-int
-main(int argc, const char ** argv)
-{
-       int     i;
-
-       argc--;
-       argv++;
-
-       if (!argc) {
-               fprintf(stderr, "-hpet: requires command\n");
-               return -1;
-       }
-
-
-       for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
-               if (!strcmp(argv[0], hpet_command[i].command)) {
-                       argc--;
-                       argv++;
-                       fprintf(stderr, "-hpet: executing %s\n",
-                               hpet_command[i].command);
-                       hpet_command[i].func(argc, argv);
-                       return 0;
-               }
-
-       fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
-
-       return -1;
-}
-
-void
-hpet_open_close(int argc, const char **argv)
-{
-       int     fd;
-
-       if (argc != 1) {
-               fprintf(stderr, "hpet_open_close: device-name\n");
-               return;
-       }
-
-       fd = open(argv[0], O_RDONLY);
-       if (fd < 0)
-               fprintf(stderr, "hpet_open_close: open failed\n");
-       else
-               close(fd);
-
-       return;
-}
-
-void
-hpet_info(int argc, const char **argv)
-{
-}
-
-void
-hpet_poll(int argc, const char **argv)
-{
-       unsigned long           freq;
-       int                     iterations, i, fd;
-       struct pollfd           pfd;
-       struct hpet_info        info;
-       struct timeval          stv, etv;
-       struct timezone         tz;
-       long                    usec;
-
-       if (argc != 3) {
-               fprintf(stderr, "hpet_poll: device-name freq iterations\n");
-               return;
-       }
-
-       freq = atoi(argv[1]);
-       iterations = atoi(argv[2]);
-
-       fd = open(argv[0], O_RDONLY);
-
-       if (fd < 0) {
-               fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
-               return;
-       }
-
-       if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
-               fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
-               goto out;
-       }
-
-       if (ioctl(fd, HPET_INFO, &info) < 0) {
-               fprintf(stderr, "hpet_poll: failed to get info\n");
-               goto out;
-       }
-
-       fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
-
-       if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
-               fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
-               goto out;
-       }
-
-       if (ioctl(fd, HPET_IE_ON, 0) < 0) {
-               fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
-               goto out;
-       }
-
-       pfd.fd = fd;
-       pfd.events = POLLIN;
-
-       for (i = 0; i < iterations; i++) {
-               pfd.revents = 0;
-               gettimeofday(&stv, &tz);
-               if (poll(&pfd, 1, -1) < 0)
-                       fprintf(stderr, "hpet_poll: poll failed\n");
-               else {
-                       long    data;
-
-                       gettimeofday(&etv, &tz);
-                       usec = stv.tv_sec * 1000000 + stv.tv_usec;
-                       usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
-
-                       fprintf(stderr,
-                               "hpet_poll: expired time = 0x%lx\n", usec);
-
-                       fprintf(stderr, "hpet_poll: revents = 0x%x\n",
-                               pfd.revents);
-
-                       if (read(fd, &data, sizeof(data)) != sizeof(data)) {
-                               fprintf(stderr, "hpet_poll: read failed\n");
-                       }
-                       else
-                               fprintf(stderr, "hpet_poll: data 0x%lx\n",
-                                       data);
-               }
-       }
-
-out:
-       close(fd);
-       return;
-}
-
-static int hpet_sigio_count;
-
-static void
-hpet_sigio(int val)
-{
-       fprintf(stderr, "hpet_sigio: called\n");
-       hpet_sigio_count++;
-}
-
-void
-hpet_fasync(int argc, const char **argv)
-{
-       unsigned long           freq;
-       int                     iterations, i, fd, value;
-       sig_t                   oldsig;
-       struct hpet_info        info;
-
-       hpet_sigio_count = 0;
-       fd = -1;
-
-       if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
-               fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
-               return;
-       }
-
-       if (argc != 3) {
-               fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
-               goto out;
-       }
-
-       fd = open(argv[0], O_RDONLY);
-
-       if (fd < 0) {
-               fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
-               return;
-       }
-
-
-       if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
-               ((value = fcntl(fd, F_GETFL)) == 1) ||
-               (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
-               fprintf(stderr, "hpet_fasync: fcntl failed\n");
-               goto out;
-       }
-
-       freq = atoi(argv[1]);
-       iterations = atoi(argv[2]);
-
-       if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
-               fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
-               goto out;
-       }
-
-       if (ioctl(fd, HPET_INFO, &info) < 0) {
-               fprintf(stderr, "hpet_fasync: failed to get info\n");
-               goto out;
-       }
-
-       fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
-
-       if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
-               fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
-               goto out;
-       }
-
-       if (ioctl(fd, HPET_IE_ON, 0) < 0) {
-               fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
-               goto out;
-       }
-
-       for (i = 0; i < iterations; i++) {
-               (void) pause();
-               fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
-       }
-
-out:
-       signal(SIGIO, oldsig);
-
-       if (fd >= 0)
-               close(fd);
-
-       return;
-}
-
-The kernel API has three interfaces exported from the driver:
-
-       hpet_register(struct hpet_task *tp, int periodic)
-       hpet_unregister(struct hpet_task *tp)
-       hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
-
-The kernel module using this interface fills in the ht_func and ht_data
-members of the hpet_task structure before calling hpet_register.
-hpet_control simply vectors to the hpet_ioctl routine and has the same
-commands and respective arguments as the user API.  hpet_unregister
-is used to terminate usage of the HPET timer reserved by hpet_register.
index 1405fb69984c7533c22030226698866fead7569f..22efedf60c872869e5230eb5ccf66c166634e22c 100644 (file)
@@ -16,6 +16,9 @@ Supported adapters:
   * VIA Technologies, Inc. CX700
     Datasheet: available on request and under NDA from VIA
 
+  * VIA Technologies, Inc. VX800/VX820
+    Datasheet: available on http://linux.via.com.tw
+
 Authors:
        Kyösti Mälkki <kmalkki@cc.hut.fi>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -49,6 +52,7 @@ Your lspci -n listing must show one of these :
  device 1106:3372   (VT8237S)
  device 1106:3287   (VT8251)
  device 1106:8324   (CX700)
+ device 1106:8353   (VX800/VX820)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
@@ -57,5 +61,5 @@ Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
 VT8231), this driver supports I2C block transactions. Such transactions
 are mainly useful to read from and write to EEPROMs.
 
-The CX700 additionally appears to support SMBus PEC, although this driver
-doesn't implement it yet.
+The CX700/VX800/VX820 additionally appears to support SMBus PEC, although
+this driver doesn't implement it yet.
index 9dd79123ddd9949de863a0c2c20e98f99269a8c4..3e742ba25536123dc4108c6eb2db860584d9b442 100644 (file)
@@ -4,6 +4,10 @@ the /dev interface. You need to load module i2c-dev for this.
 
 Each registered i2c adapter gets a number, counting from 0. You can
 examine /sys/class/i2c-dev/ to see what number corresponds to which adapter.
+Alternatively, you can run "i2cdetect -l" to obtain a formated list of all
+i2c adapters present on your system at a given time. i2cdetect is part of
+the i2c-tools package.
+
 I2C device files are character device files with major device number 89
 and a minor device number corresponding to the number assigned as 
 explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., 
@@ -17,30 +21,34 @@ So let's say you want to access an i2c adapter from a C program. The
 first thing to do is "#include <linux/i2c-dev.h>". Please note that
 there are two files named "i2c-dev.h" out there, one is distributed
 with the Linux kernel and is meant to be included from kernel
-driver code, the other one is distributed with lm_sensors and is
+driver code, the other one is distributed with i2c-tools and is
 meant to be included from user-space programs. You obviously want
 the second one here.
 
 Now, you have to decide which adapter you want to access. You should
-inspect /sys/class/i2c-dev/ to decide this. Adapter numbers are assigned
-somewhat dynamically, so you can not even assume /dev/i2c-0 is the
-first adapter.
+inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this.
+Adapter numbers are assigned somewhat dynamically, so you can not
+assume much about them. They can even change from one boot to the next.
 
 Next thing, open the device file, as follows:
+
   int file;
   int adapter_nr = 2; /* probably dynamically determined */
   char filename[20];
   
-  sprintf(filename,"/dev/i2c-%d",adapter_nr);
-  if ((file = open(filename,O_RDWR)) < 0) {
+  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
+  file = open(filename, O_RDWR);
+  if (file < 0) {
     /* ERROR HANDLING; you can check errno to see what went wrong */
     exit(1);
   }
 
 When you have opened the device, you must specify with what device
 address you want to communicate:
+
   int addr = 0x40; /* The I2C address */
-  if (ioctl(file,I2C_SLAVE,addr) < 0) {
+
+  if (ioctl(file, I2C_SLAVE, addr) < 0) {
     /* ERROR HANDLING; you can check errno to see what went wrong */
     exit(1);
   }
@@ -48,31 +56,41 @@ address you want to communicate:
 Well, you are all set up now. You can now use SMBus commands or plain
 I2C to communicate with your device. SMBus commands are preferred if
 the device supports them. Both are illustrated below.
+
   __u8 register = 0x10; /* Device register to access */
   __s32 res;
   char buf[10];
+
   /* Using SMBus commands */
-  res = i2c_smbus_read_word_data(file,register);
+  res = i2c_smbus_read_word_data(file, register);
   if (res < 0) {
     /* ERROR HANDLING: i2c transaction failed */
   } else {
     /* res contains the read word */
   }
+
   /* Using I2C Write, equivalent of 
-           i2c_smbus_write_word_data(file,register,0x6543) */
+     i2c_smbus_write_word_data(file, register, 0x6543) */
   buf[0] = register;
   buf[1] = 0x43;
   buf[2] = 0x65;
-  if ( write(file,buf,3) != 3) {
+  if (write(file, buf, 3) ! =3) {
     /* ERROR HANDLING: i2c transaction failed */
   }
+
   /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */
-  if (read(file,buf,1) != 1) {
+  if (read(file, buf, 1) != 1) {
     /* ERROR HANDLING: i2c transaction failed */
   } else {
     /* buf[0] contains the read byte */
   }
 
+Note that only a subset of the I2C and SMBus protocols can be achieved by
+the means of read() and write() calls. In particular, so-called combined
+transactions (mixing read and write messages in the same transaction)
+aren't supported. For this reason, this interface is almost never used by
+user-space programs.
+
 IMPORTANT: because of the use of inline functions, you *have* to use
 '-O' or some variation when you compile your program!
 
@@ -80,31 +98,29 @@ IMPORTANT: because of the use of inline functions, you *have* to use
 Full interface description
 ==========================
 
-The following IOCTLs are defined and fully supported 
-(see also i2c-dev.h):
+The following IOCTLs are defined:
 
-ioctl(file,I2C_SLAVE,long addr)
+ioctl(file, I2C_SLAVE, long addr)
   Change slave address. The address is passed in the 7 lower bits of the
   argument (except for 10 bit addresses, passed in the 10 lower bits in this
   case).
 
-ioctl(file,I2C_TENBIT,long select)
+ioctl(file, I2C_TENBIT, long select)
   Selects ten bit addresses if select not equals 0, selects normal 7 bit
   addresses if select equals 0. Default 0.  This request is only valid
   if the adapter has I2C_FUNC_10BIT_ADDR.
 
-ioctl(file,I2C_PEC,long select)
+ioctl(file, I2C_PEC, long select)
   Selects SMBus PEC (packet error checking) generation and verification
   if select not equals 0, disables if select equals 0. Default 0.
   Used only for SMBus transactions.  This request only has an effect if the
   the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just
   doesn't have any effect.
 
-ioctl(file,I2C_FUNCS,unsigned long *funcs)
+ioctl(file, I2C_FUNCS, unsigned long *funcs)
   Gets the adapter functionality and puts it in *funcs.
 
-ioctl(file,I2C_RDWR,struct i2c_rdwr_ioctl_data *msgset)
-
+ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset)
   Do combined read/write transaction without stop in between.
   Only valid if the adapter has I2C_FUNC_I2C.  The argument is
   a pointer to a
@@ -120,10 +136,9 @@ ioctl(file,I2C_RDWR,struct i2c_rdwr_ioctl_data *msgset)
   The slave address and whether to use ten bit address mode has to be
   set in each message, overriding the values set with the above ioctl's.
 
-
-Other values are NOT supported at this moment, except for I2C_SMBUS,
-which you should never directly call; instead, use the access functions
-below.
+ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args)
+  Not meant to be called  directly; instead, use the access functions
+  below.
 
 You can do plain i2c transactions by using read(2) and write(2) calls.
 You do not need to pass the address byte; instead, set it through
@@ -148,7 +163,52 @@ what happened. The 'write' transactions return 0 on success; the
 returns the number of values read. The block buffers need not be longer
 than 32 bytes.
 
-The above functions are all macros, that resolve to calls to the
-i2c_smbus_access function, that on its turn calls a specific ioctl
+The above functions are all inline functions, that resolve to calls to
+the i2c_smbus_access function, that on its turn calls a specific ioctl
 with the data in a specific format. Read the source code if you
 want to know what happens behind the screens.
+
+
+Implementation details
+======================
+
+For the interested, here's the code flow which happens inside the kernel
+when you use the /dev interface to I2C:
+
+1* Your program opens /dev/i2c-N and calls ioctl() on it, as described in
+section "C example" above.
+
+2* These open() and ioctl() calls are handled by the i2c-dev kernel
+driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(),
+respectively. You can think of i2c-dev as a generic I2C chip driver
+that can be programmed from user-space.
+
+3* Some ioctl() calls are for administrative tasks and are handled by
+i2c-dev directly. Examples include I2C_SLAVE (set the address of the
+device you want to access) and I2C_PEC (enable or disable SMBus error
+checking on future transactions.)
+
+4* Other ioctl() calls are converted to in-kernel function calls by
+i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter
+functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which
+performs an SMBus transaction using i2c-core.c:i2c_smbus_xfer().
+
+The i2c-dev driver is responsible for checking all the parameters that
+come from user-space for validity. After this point, there is no
+difference between these calls that came from user-space through i2c-dev
+and calls that would have been performed by kernel I2C chip drivers
+directly. This means that I2C bus drivers don't need to implement
+anything special to support access from user-space.
+
+5* These i2c-core.c/i2c.h functions are wrappers to the actual
+implementation of your I2C bus driver. Each adapter must declare
+callback functions implementing these standard calls.
+i2c.h:i2c_get_functionality() calls i2c_adapter.algo->functionality(),
+while i2c-core.c:i2c_smbus_xfer() calls either
+adapter.algo->smbus_xfer() if it is implemented, or if not,
+i2c-core.c:i2c_smbus_xfer_emulated() which in turn calls
+i2c_adapter.algo->master_xfer().
+
+After your I2C bus driver has processed these requests, execution runs
+up the call chain, with almost no processing done, except by i2c-dev to
+package the returned data, if any, in suitable format for the ioctl.
index 24bfb65da17dbe53db1d6f8c98562ff9c85ce5ea..9df47441f0e73063c39f39fe22acc1fb3a753416 100644 (file)
@@ -109,8 +109,8 @@ specified through the Comm byte.
 S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
 
 
-SMBus Process Call
-==================
+SMBus Process Call:  i2c_smbus_process_call()
+=============================================
 
 This command selects a device register (through the Comm byte), sends
 16 bits of data to it, and reads 16 bits of data in return.
index 6b61b3a2e90bee2b7cbed065160bd029db89ba08..d73ee117a8caecfaf0585aeb4239c27828a7b5df 100644 (file)
@@ -606,6 +606,8 @@ SMBus communication
   extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
   extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                        u8 command, u16 value);
+  extern s32 i2c_smbus_process_call(struct i2c_client *client,
+                                    u8 command, u16 value);
   extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
                                        u8 command, u8 *values);
   extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
@@ -621,8 +623,6 @@ These ones were removed from i2c-core because they had no users, but could
 be added back later if needed:
 
   extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
-  extern s32 i2c_smbus_process_call(struct i2c_client * client,
-                                    u8 command, u16 value);
   extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
                                           u8 command, u8 length,
                                           u8 *values)
index 914d07f49268b728ab5c1d8a6e7b23b59cef0128..84f7cb3d5bec43499965cb683d966f22ee15f85b 100644 (file)
@@ -1,7 +1,8 @@
-Currently, kvm module in EXPERIMENTAL stage on IA64. This means that
-interfaces are not stable enough to use. So, plase had better don't run
-critical applications in virtual machine. We will try our best to make it
-strong in future versions!
+Currently, kvm module is in EXPERIMENTAL stage on IA64. This means that
+interfaces are not stable enough to use. So, please don't run critical
+applications in virtual machine.
+We will try our best to improve it in future versions!
+
                                Guide: How to boot up guests on kvm/ia64
 
 This guide is to describe how to enable kvm support for IA-64 systems.
index 2443f5bb43648e5a2c50bc94d33703f88360880a..dd28a0d56981e4e0376fb5010086c817633a6a3b 100644 (file)
@@ -796,6 +796,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        Defaults to the default architecture's huge page size
                        if not specified.
 
+       i8042.debug     [HW] Toggle i8042 debug mode
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
                             keyboard and cannot control its state
@@ -1713,6 +1714,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        autoconfiguration.
                        Ranges are in pairs (memory base and size).
 
+       dynamic_printk
+                       Enables pr_debug()/dev_dbg() calls if
+                       CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
+                       be switched on/off via <debugfs>/dynamic_printk/modules
+
        print-fatal-signals=
                        [KNL] debug: print fatal signals
                        print-fatal-signals=1: print segfault info to
index 51a8021ee532bc03e4e530dd724f3e42ae737bc4..f5d2aad65a672ce65082769b835d621bac11e59a 100644 (file)
@@ -118,6 +118,10 @@ the name of the kobject, call kobject_rename():
 
     int kobject_rename(struct kobject *kobj, const char *new_name);
 
+Note kobject_rename does perform any locking or have a solid notion of
+what names are valid so the provide must provide their own sanity checking
+and serialization.
+
 There is a function called kobject_set_name() but that is legacy cruft and
 is being removed.  If your code needs to call this function, it is
 incorrect and needs to be fixed.
diff --git a/Documentation/laptops/disk-shock-protection.txt b/Documentation/laptops/disk-shock-protection.txt
new file mode 100644 (file)
index 0000000..0e6ba26
--- /dev/null
@@ -0,0 +1,149 @@
+Hard disk shock protection
+==========================
+
+Author: Elias Oltmanns <eo@nebensachen.de>
+Last modified: 2008-10-03
+
+
+0. Contents
+-----------
+
+1. Intro
+2. The interface
+3. References
+4. CREDITS
+
+
+1. Intro
+--------
+
+ATA/ATAPI-7 specifies the IDLE IMMEDIATE command with unload feature.
+Issuing this command should cause the drive to switch to idle mode and
+unload disk heads. This feature is being used in modern laptops in
+conjunction with accelerometers and appropriate software to implement
+a shock protection facility. The idea is to stop all I/O operations on
+the internal hard drive and park its heads on the ramp when critical
+situations are anticipated. The desire to have such a feature
+available on GNU/Linux systems has been the original motivation to
+implement a generic disk head parking interface in the Linux kernel.
+Please note, however, that other components have to be set up on your
+system in order to get disk shock protection working (see
+section 3. References below for pointers to more information about
+that).
+
+
+2. The interface
+----------------
+
+For each ATA device, the kernel exports the file
+block/*/device/unload_heads in sysfs (here assumed to be mounted under
+/sys). Access to /sys/block/*/device/unload_heads is denied with
+-EOPNOTSUPP if the device does not support the unload feature.
+Otherwise, writing an integer value to this file will take the heads
+of the respective drive off the platter and block all I/O operations
+for the specified number of milliseconds. When the timeout expires and
+no further disk head park request has been issued in the meantime,
+normal operation will be resumed. The maximal value accepted for a
+timeout is 30000 milliseconds. Exceeding this limit will return
+-EOVERFLOW, but heads will be parked anyway and the timeout will be
+set to 30 seconds. However, you can always change a timeout to any
+value between 0 and 30000 by issuing a subsequent head park request
+before the timeout of the previous one has expired. In particular, the
+total timeout can exceed 30 seconds and, more importantly, you can
+cancel a previously set timeout and resume normal operation
+immediately by specifying a timeout of 0. Values below -2 are rejected
+with -EINVAL (see below for the special meaning of -1 and -2). If the
+timeout specified for a recent head park request has not yet expired,
+reading from /sys/block/*/device/unload_heads will report the number
+of milliseconds remaining until normal operation will be resumed;
+otherwise, reading the unload_heads attribute will return 0.
+
+For example, do the following in order to park the heads of drive
+/dev/sda and stop all I/O operations for five seconds:
+
+# echo 5000 > /sys/block/sda/device/unload_heads
+
+A simple
+
+# cat /sys/block/sda/device/unload_heads
+
+will show you how many milliseconds are left before normal operation
+will be resumed.
+
+A word of caution: The fact that the interface operates on a basis of
+milliseconds may raise expectations that cannot be satisfied in
+reality. In fact, the ATA specs clearly state that the time for an
+unload operation to complete is vendor specific. The hint in ATA-7
+that this will typically be within 500 milliseconds apparently has
+been dropped in ATA-8.
+
+There is a technical detail of this implementation that may cause some
+confusion and should be discussed here. When a head park request has
+been issued to a device successfully, all I/O operations on the
+controller port this device is attached to will be deferred. That is
+to say, any other device that may be connected to the same port will
+be affected too. The only exception is that a subsequent head unload
+request to that other device will be executed immediately. Further
+operations on that port will be deferred until the timeout specified
+for either device on the port has expired. As far as PATA (old style
+IDE) configurations are concerned, there can only be two devices
+attached to any single port. In SATA world we have port multipliers
+which means that a user-issued head parking request to one device may
+actually result in stopping I/O to a whole bunch of devices. However,
+since this feature is supposed to be used on laptops and does not seem
+to be very useful in any other environment, there will be mostly one
+device per port. Even if the CD/DVD writer happens to be connected to
+the same port as the hard drive, it generally *should* recover just
+fine from the occasional buffer under-run incurred by a head park
+request to the HD. Actually, when you are using an ide driver rather
+than its libata counterpart (i.e. your disk is called /dev/hda
+instead of /dev/sda), then parking the heads of one drive (drive X)
+will generally not affect the mode of operation of another drive
+(drive Y) on the same port as described above. It is only when a port
+reset is required to recover from an exception on drive Y that further
+I/O operations on that drive (and the reset itself) will be delayed
+until drive X is no longer in the parked state.
+
+Finally, there are some hard drives that only comply with an earlier
+version of the ATA standard than ATA-7, but do support the unload
+feature nonetheless. Unfortunately, there is no safe way Linux can
+detect these devices, so you won't be able to write to the
+unload_heads attribute. If you know that your device really does
+support the unload feature (for instance, because the vendor of your
+laptop or the hard drive itself told you so), then you can tell the
+kernel to enable the usage of this feature for that drive by writing
+the special value -1 to the unload_heads attribute:
+
+# echo -1 > /sys/block/sda/device/unload_heads
+
+will enable the feature for /dev/sda, and giving -2 instead of -1 will
+disable it again.
+
+
+3. References
+-------------
+
+There are several laptops from different vendors featuring shock
+protection capabilities. As manufacturers have refused to support open
+source development of the required software components so far, Linux
+support for shock protection varies considerably between different
+hardware implementations. Ideally, this section should contain a list
+of pointers at different projects aiming at an implementation of shock
+protection on different systems. Unfortunately, I only know of a
+single project which, although still considered experimental, is fit
+for use. Please feel free to add projects that have been the victims
+of my ignorance.
+
+- http://www.thinkwiki.org/wiki/HDAPS
+  See this page for information about Linux support of the hard disk
+  active protection system as implemented in IBM/Lenovo Thinkpads.
+
+
+4. CREDITS
+----------
+
+This implementation of disk head parking has been inspired by a patch
+originally published by Jon Escombe <lists@dresco.co.uk>. My efforts
+to develop an implementation of this feature that is fit to be merged
+into mainline have been aided by various kernel developers, in
+particular by Tejun Heo and Bartlomiej Zolnierkiewicz.
index 6387d3decf858a7c83d2ae65f06c6eccdfa7dfae..c725d33b316fbadebb0d93d1fb70c193318ac1a2 100644 (file)
@@ -3,7 +3,7 @@ NOTE
 ----
 
 This document was contributed by Cirrus Logic for kernel 2.2.5.  This version
-has been updated for 2.3.48 by Andrew Morton <andrewm@uow.edu.au>
+has been updated for 2.3.48 by Andrew Morton.
 
 Cirrus make a copy of this driver available at their website, as
 described below.  In general, you should use the driver version which
@@ -690,7 +690,7 @@ latest drivers and technical publications.
 6.4 Current maintainer
 
 In February 2000 the maintenance of this driver was assumed by Andrew
-Morton <akpm@zip.com.au>
+Morton.
 
 6.5 Kernel module parameters
 
index 0e6e592f4f55b876c06b48ceae531b3cfdd6b421..6a07e45d4a9307aa208b88ae84cd97ab490fd0ac 100644 (file)
@@ -146,8 +146,8 @@ WARNING:
 When polling a connected pipe socket for writability, there is an
 intrinsic race condition whereby writability might be lost between the
 polling and the writing system calls. In this case, the socket will
-block until write because possible again, unless non-blocking mode
-becomes enabled.
+block until write becomes possible again, unless non-blocking mode
+is enabled.
 
 
 The pipe protocol provides two socket options at the SOL_PNPIPE level:
index 6356d3faed365634bbbe85172b28abdf472c600b..bd70976b816039e6e06c34e5f6924f0ee0130469 100644 (file)
@@ -1,5 +1,5 @@
 Documentation/networking/vortex.txt
-Andrew Morton <andrewm@uow.edu.au>
+Andrew Morton
 30 April 2000
 
 
@@ -11,7 +11,7 @@ The driver was written by Donald Becker <becker@scyld.com>
 Don is no longer the prime maintainer of this version of the driver. 
 Please report problems to one or more of:
 
-  Andrew Morton <akpm@osdl.org>
+  Andrew Morton
   Netdev mailing list <netdev@vger.kernel.org>
   Linux kernel mailing list <linux-kernel@vger.kernel.org>
 
@@ -305,11 +305,6 @@ Donald's wake-on-LAN page:
 
        ftp://ftp.3com.com/pub/nic/3c90x/3c90xx2.exe
 
-Driver updates and a detailed changelog for the modifications which
-were made for the 2.3/2,4 series kernel is available at
-
-     http://www.zip.com.au/~akpm/linux/#3c59x-bc
-
 
 Autonegotiation notes
 ---------------------
index 96f155e687506096e0f694591aa3b9fd722e4a48..059934363cafaf18a15ebff592e167f8c84ee539 100644 (file)
@@ -1,5 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* New configuration loop helper (as of 2.6.28)
+   By calling pcmcia_loop_config(), a driver can iterate over all available
+   configuration options. During a driver's probe() phase, one doesn't need
+   to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data and
+   pcmcia_parse_tuple directly in most if not all cases.
+
 * New release helper (as of 2.6.17)
    Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
    necessary now is calling pcmcia_disable_device. As there is no valid
index c9a35665cf7072c52c92027a715e980c9479a3b7..ce3487d99abedef8b3616740bc3a980d3607bdd3 100644 (file)
@@ -2,17 +2,8 @@ Regulator Machine Driver Interface
 ===================================
 
 The regulator machine driver interface is intended for board/machine specific
-initialisation code to configure the regulator subsystem. Typical things that
-machine drivers would do are :-
+initialisation code to configure the regulator subsystem.
 
- 1. Regulator -> Device mapping.
- 2. Regulator supply configuration.
- 3. Power Domain constraint setting.
-
-
-
-1. Regulator -> device mapping
-==============================
 Consider the following machine :-
 
   Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
@@ -21,81 +12,82 @@ Consider the following machine :-
 
 The drivers for consumers A & B must be mapped to the correct regulator in
 order to control their power supply. This mapping can be achieved in machine
-initialisation code by calling :-
+initialisation code by creating a struct regulator_consumer_supply for
+each regulator.
+
+struct regulator_consumer_supply {
+       struct device *dev;     /* consumer */
+       const char *supply;     /* consumer supply - e.g. "vcc" */
+};
 
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-                               const char *supply);
+e.g. for the machine above
 
-and is shown with the following code :-
+static struct regulator_consumer_supply regulator1_consumers[] = {
+{
+       .dev    = &platform_consumerB_device.dev,
+       .supply = "Vcc",
+},};
 
-regulator_set_device_supply("Regulator-1", devB, "Vcc");
-regulator_set_device_supply("Regulator-2", devA, "Vcc");
+static struct regulator_consumer_supply regulator2_consumers[] = {
+{
+       .dev    = &platform_consumerA_device.dev,
+       .supply = "Vcc",
+},};
 
 This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2
 to the 'Vcc' supply for Consumer A.
 
-
-2. Regulator supply configuration.
-==================================
-Consider the following machine (again) :-
-
-  Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
-               |
-               +-> [Consumer B @ 3.3V]
+Constraints can now be registered by defining a struct regulator_init_data
+for each regulator power domain. This structure also maps the consumers
+to their supply regulator :-
+
+static struct regulator_init_data regulator1_data = {
+       .constraints = {
+               .min_uV = 3300000,
+               .max_uV = 3300000,
+               .valid_modes_mask = REGULATOR_MODE_NORMAL,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(regulator1_consumers),
+       .consumer_supplies = regulator1_consumers,
+};
 
 Regulator-1 supplies power to Regulator-2. This relationship must be registered
 with the core so that Regulator-1 is also enabled when Consumer A enables it's
-supply (Regulator-2).
-
-This relationship can be register with the core via :-
-
-int regulator_set_supply(const char *regulator, const char *regulator_supply);
-
-In this example we would use the following code :-
-
-regulator_set_supply("Regulator-2", "Regulator-1");
-
-Relationships can be queried by calling :-
-
-const char *regulator_get_supply(const char *regulator);
-
-
-3. Power Domain constraint setting.
-===================================
-Each power domain within a system has physical constraints on voltage and
-current. This must be defined in software so that the power domain is always
-operated within specifications.
-
-Consider the following machine (again) :-
-
-  Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
-               |
-               +-> [Consumer B @ 3.3V]
-
-This gives us two regulators and two power domains:
-
-                   Domain 1: Regulator-2, Consumer B.
-                   Domain 2: Consumer A.
-
-Constraints can be registered by calling :-
-
-int regulator_set_platform_constraints(const char *regulator,
-       struct regulation_constraints *constraints);
-
-The example is defined as follows :-
-
-struct regulation_constraints domain_1 = {
-       .min_uV = 3300000,
-       .max_uV = 3300000,
-       .valid_modes_mask = REGULATOR_MODE_NORMAL,
+supply (Regulator-2). The supply regulator is set by the supply_regulator_dev
+field below:-
+
+static struct regulator_init_data regulator2_data = {
+       .supply_regulator_dev = &platform_regulator1_device.dev,
+       .constraints = {
+               .min_uV = 1800000,
+               .max_uV = 2000000,
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+               .valid_modes_mask = REGULATOR_MODE_NORMAL,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(regulator2_consumers),
+       .consumer_supplies = regulator2_consumers,
 };
 
-struct regulation_constraints domain_2 = {
-       .min_uV = 1800000,
-       .max_uV = 2000000,
-       .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-       .valid_modes_mask = REGULATOR_MODE_NORMAL,
+Finally the regulator devices must be registered in the usual manner.
+
+static struct platform_device regulator_devices[] = {
+{
+       .name = "regulator",
+       .id = DCDC_1,
+       .dev = {
+               .platform_data = &regulator1_data,
+       },
+},
+{
+       .name = "regulator",
+       .id = DCDC_2,
+       .dev = {
+               .platform_data = &regulator2_data,
+       },
+},
 };
+/* register regulator 1 device */
+platform_device_register(&wm8350_regulator_devices[0]);
 
-regulator_set_platform_constraints("Regulator-1", &domain_1);
-regulator_set_platform_constraints("Regulator-2", &domain_2);
+/* register regulator 2 device */
+platform_device_register(&wm8350_regulator_devices[1]);
index a69050143592236cdcf39655027c30bb8aeccb47..4200accb9bba981b0c582c6089a6a07fcc215fae 100644 (file)
@@ -10,11 +10,11 @@ Registration
 
 Drivers can register a regulator by calling :-
 
-struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-                                         void *reg_data);
+struct regulator_dev *regulator_register(struct device *dev,
+       struct regulator_desc *regulator_desc);
 
-This will register the regulators capabilities and operations the regulator
-core. The core does not touch reg_data (private to regulator driver).
+This will register the regulators capabilities and operations to the regulator
+core.
 
 Regulators can be unregistered by calling :-
 
index b05f512130eaa1cb3f75da9414cf65d80cfe5b62..2ebdc6091ce17ff6464aeb4cec35939983045de6 100644 (file)
@@ -54,3 +54,21 @@ used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out
 that "radeonfb" simply cannot resume that device - it tries to set the
 PLL's, and it just _hangs_. Using the regular VGA console and letting X
 resume it instead works fine.
+
+NOTE
+====
+pm_trace uses the system's Real Time Clock (RTC) to save the magic number.
+Reason for this is that the RTC is the only reliably available piece of
+hardware during resume operations where a value can be set that will
+survive a reboot.
+
+Consequence is that after a resume (even if it is successful) your system
+clock will have a value corresponding to the magic mumber instead of the
+correct date/time! It is therefore advisable to use a program like ntp-date
+or rdate to reset the correct date/time from an external time source when
+using this trace option.
+
+As the clock keeps ticking it is also essential that the reboot is done
+quickly after the resume failure. The trace option does not use the seconds
+or the low order bits of the minutes of the RTC, but a too long delay will
+corrupt the magic value.
index 29d839ce7327a01ad8ba24437b8840dcf9b70919..e3960b8c868940ebf6f39ec14e21735d023abf07 100644 (file)
@@ -18,10 +18,6 @@ mpc52xx.txt
        - Linux 2.6.x on MPC52xx family
 mpc52xx-device-tree-bindings.txt
        - MPC5200 Device Tree Bindings
-ppc_htab.txt
-       - info about the Linux/PPC /proc/ppc_htab entry
-smp.txt
-       - use and state info about Linux/PPC on MP machines
 sound.txt
        - info on sound support under Linux/PPC
 zImage_layout.txt
diff --git a/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt b/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt
new file mode 100644 (file)
index 0000000..35a4653
--- /dev/null
@@ -0,0 +1,40 @@
+* Freescale 83xx and 512x PCI bridges
+
+Freescale 83xx and 512x SOCs include the same pci bridge core.
+
+83xx/512x specific notes:
+- reg: should contain two address length tuples
+    The first is for the internal pci bridge registers
+    The second is for the pci config space access registers
+
+Example (MPC8313ERDB)
+       pci0: pci@e0008500 {
+               cell-index = <1>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+                               /* IDSEL 0x0E -mini PCI */
+                                0x7000 0x0 0x0 0x1 &ipic 18 0x8
+                                0x7000 0x0 0x0 0x2 &ipic 18 0x8
+                                0x7000 0x0 0x0 0x3 &ipic 18 0x8
+                                0x7000 0x0 0x0 0x4 &ipic 18 0x8
+
+                               /* IDSEL 0x0F - PCI slot */
+                                0x7800 0x0 0x0 0x1 &ipic 17 0x8
+                                0x7800 0x0 0x0 0x2 &ipic 18 0x8
+                                0x7800 0x0 0x0 0x3 &ipic 17 0x8
+                                0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
+               interrupt-parent = <&ipic>;
+               interrupts = <66 0x8>;
+               bus-range = <0x0 0x0>;
+               ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
+                         0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
+                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+               clock-frequency = <66666666>;
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
+               compatible = "fsl,mpc8349-pci";
+               device_type = "pci";
+       };
diff --git a/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt b/Documentation/powerpc/dts-bindings/fsl/8xxx_gpio.txt
new file mode 100644 (file)
index 0000000..d015dce
--- /dev/null
@@ -0,0 +1,40 @@
+GPIO controllers on MPC8xxx SoCs
+
+This is for the non-QE/CPM/GUTs GPIO controllers as found on
+8349, 8572, 8610 and compatible.
+
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+Required properties:
+- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
+  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters (currently unused).
+ - interrupts : Interrupt mapping for GPIO IRQ (currently unused).
+ - interrupt-parent : Phandle for the interrupt controller that
+   services interrupts for this device.
+- gpio-controller : Marks the port as GPIO controller.
+
+Example of gpio-controller nodes for a MPC8347 SoC:
+
+       gpio1: gpio-controller@c00 {
+               #gpio-cells = <2>;
+               compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
+               reg = <0xc00 0x100>;
+               interrupts = <74 0x8>;
+               interrupt-parent = <&ipic>;
+               gpio-controller;
+       };
+
+       gpio2: gpio-controller@d00 {
+               #gpio-cells = <2>;
+               compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
+               reg = <0xd00 0x100>;
+               interrupts = <75 0x8>;
+               interrupt-parent = <&ipic>;
+               gpio-controller;
+       };
+
+See booting-without-of.txt for details of how to specify GPIO
+information for devices.
index 86826df00e64ea66085c387d7fd68db46211963c..cc453110fc4651bcbc135e2dfc163e45776eb574 100644 (file)
@@ -20,7 +20,7 @@ Required properties:
         - compatible        : compatible list, contains 2 entries, first is
                         "fsl,CHIP-dma-channel", where CHIP is the processor
                         (mpc8349, mpc8350, etc.) and the second is
-                        "fsl,elo-dma-channel"
+                        "fsl,elo-dma-channel". However, see note below.
         - reg               : <registers mapping for channel>
         - cell-index        : dma channel index starts at 0.
 
@@ -82,7 +82,7 @@ Required properties:
         - compatible        : compatible list, contains 2 entries, first is
                         "fsl,CHIP-dma-channel", where CHIP is the processor
                         (mpc8540, mpc8560, etc.) and the second is
-                        "fsl,eloplus-dma-channel"
+                        "fsl,eloplus-dma-channel". However, see note below.
         - cell-index        : dma channel index starts at 0.
         - reg               : <registers mapping for channel>
         - interrupts        : <interrupt mapping for DMA channel IRQ>
@@ -125,3 +125,12 @@ Example:
                        interrupts = <17 2>;
                };
        };
+
+Note on DMA channel compatible properties: The compatible property must say
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
+driver (fsldma).  Any DMA channel used by fsldma cannot be used by another
+DMA driver, such as the SSI sound drivers for the MPC8610.  Therefore, any DMA
+channel that should be used for another driver should not use
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel".  For the SSI drivers, for
+example, the compatible property should be "fsl,ssi-dma-channel".  See ssi.txt
+for more information.
index d100555d488a32e722cf4ae3f6640159018e9a83..a2d963998a654ab5042d67b24130dbf33dc12f71 100644 (file)
@@ -24,6 +24,12 @@ Required properties:
                    "rj-master" - r.j., SSI is clock master
                    "ac97-slave" - AC97 mode, SSI is clock slave
                    "ac97-master" - AC97 mode, SSI is clock master
+- fsl,playback-dma: phandle to a node for the DMA channel to use for
+                    playback of audio.  This is typically dictated by SOC
+                    design.  See the notes below.
+- fsl,capture-dma:  phandle to a node for the DMA channel to use for
+                    capture (recording) of audio.  This is typically dictated
+                    by SOC design.  See the notes below.
 
 Optional properties:
 - codec-handle   : phandle to a 'codec' node that defines an audio
@@ -36,3 +42,20 @@ Child 'codec' node required properties:
 Child 'codec' node optional properties:
 - clock-frequency  : The frequency of the input clock, which typically
                      comes from an on-board dedicated oscillator.
+
+Notes on fsl,playback-dma and fsl,capture-dma:
+
+On SOCs that have an SSI, specific DMA channels are hard-wired for playback
+and capture.  On the MPC8610, for example, SSI1 must use DMA channel 0 for
+playback and DMA channel 1 for capture.  SSI2 must use DMA channel 2 for
+playback and DMA channel 3 for capture.  The developer can choose which
+DMA controller to use, but the channels themselves are hard-wired.  The
+purpose of these two properties is to represent this hardware design.
+
+The device tree nodes for the DMA channels that are referenced by
+"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with
+"fsl,ssi-dma-channel".  The SOC-specific compatible string (e.g.
+"fsl,mpc8610-dma-channel") can remain.  If these nodes are left as
+"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA
+drivers (fsldma) will attempt to use them, and it will conflict with the
+sound drivers.
diff --git a/Documentation/powerpc/ppc_htab.txt b/Documentation/powerpc/ppc_htab.txt
deleted file mode 100644 (file)
index 8b8c7df..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-                 Information about /proc/ppc_htab
-=====================================================================
-
-This document and the related code was written by me (Cort Dougan), please
-email me (cort@fsmlabs.com) if you have questions, comments or corrections.
-
-Last Change: 2.16.98
-
-This entry in the proc directory is readable by all users but only
-writable by root.
-
-The ppc_htab interface is a user level way of accessing the
-performance monitoring registers as well as providing information
-about the PTE hash table.
-
-1. Reading
-
-  Reading this file will give you information about the memory management
-  hash table that serves as an extended tlb for page translation on the
-  powerpc.  It will also give you information about performance measurement
-  specific to the cpu that you are using.
-
-  Explanation of the 604 Performance Monitoring Fields:
-    MMCR0 - the current value of the MMCR0 register
-    PMC1
-    PMC2 - the value of the performance counters and a
-           description of what events they are counting
-           which are based on MMCR0 bit settings.
-  Explanation of the PTE Hash Table fields:
-
-    Size - hash table size in Kb.
-    Buckets -  number of buckets in the table.
-    Address - the virtual kernel address of the hash table base.
-    Entries - the number of ptes that can be stored in the hash table.
-    User/Kernel - how many pte's are in use by the kernel or user at that time.
-    Overflows - How many of the entries are in their secondary hash location.
-    Percent full - ratio of free pte entries to in use entries.
-    Reloads - Count of how many hash table misses have occurred
-              that were fixed with a reload from the linux tables.
-              Should always be 0 on 603 based machines.
-    Non-error Misses - Count of how many hash table misses have occurred
-              that were completed with the creation of a pte in the linux
-              tables with a call to do_page_fault().
-    Error Misses - Number of misses due to errors such as bad address
-              and permission violations.  This includes kernel access of
-              bad user addresses that are fixed up by the trap handler.
-
-  Note that calculation of the data displayed from /proc/ppc_htab takes
-  a long time and spends a great deal of time in the kernel.  It would
-  be quite hard on performance to read this file constantly.  In time
-  there may be a counter in the kernel that allows successive reads from
-  this file only after a given amount of time has passed to reduce the
-  possibility of a user slowing the system by reading this file.
-
-2. Writing
-
-  Writing to the ppc_htab allows you to change the characteristics of
-  the powerpc PTE hash table and setup performance monitoring.
-
-  Resizing the PTE hash table is not enabled right now due to many
-  complications with moving the hash table, rehashing the entries
-  and many many SMP issues that would have to be dealt with.
-
-  Write options to ppc_htab:
-  
-   - To set the size of the hash table to 64Kb:
-
-      echo 'size 64' > /proc/ppc_htab
-
-     The size must be a multiple of 64 and must be greater than or equal to
-     64.
-
-   - To turn off performance monitoring:
-
-      echo 'off' > /proc/ppc_htab
-
-   - To reset the counters without changing what they're counting:
-
-      echo 'reset' > /proc/ppc_htab
-
-     Note that counting will continue after the reset if it is enabled.
-
-   - To count only events in user mode or only in kernel mode:
-
-      echo 'user' > /proc/ppc_htab
-       ...or...
-      echo 'kernel' > /proc/ppc_htab
-
-     Note that these two options are exclusive of one another and the
-     lack of either of these options counts user and kernel.
-     Using 'reset' and 'off' reset these flags.
-
-   - The 604 has 2 performance counters which can each count events from
-     a specific set of events.  These sets are disjoint so it is not
-     possible to count _any_ combination of 2 events.  One event can
-     be counted by PMC1 and one by PMC2.
-
-     To start counting a particular event use:
-
-      echo 'event' > /proc/ppc_htab
-
-     and choose from these events:
-
-     PMC1
-     ----
-      'ic miss' - instruction cache misses
-      'dtlb' - data tlb misses (not hash table misses)
-
-     PMC2
-     ----
-      'dc miss' - data cache misses
-      'itlb' - instruction tlb misses (not hash table misses)
-      'load miss time' - cycles to complete a load miss
-
-3. Bugs
-
-  The PMC1 and PMC2 counters can overflow and give no indication of that
-  in /proc/ppc_htab.
diff --git a/Documentation/powerpc/smp.txt b/Documentation/powerpc/smp.txt
deleted file mode 100644 (file)
index 5b581b8..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-                 Information about Linux/PPC SMP mode
-=====================================================================
-
-This document and the related code was written by me
-(Cort Dougan, cort@fsmlabs.com) please email me if you have questions,
-comments or corrections.
-
-Last Change: 3.31.99
-
-If you want to help by writing code or testing different hardware please
-email me!
-
-1. State of Supported Hardware
-
-  PowerSurge Architecture - tested on UMAX s900, Apple 9600
-    The second processor on this machine boots up just fine and
-    enters its idle loop.  Hopefully a completely working SMP kernel
-    on this machine will be done shortly.
-
-    The code makes the assumption of only two processors.  The changes
-    necessary to work with any number would not be overly difficult but
-    I don't have any machines with >2 processors so it's not high on my
-    list of priorities.  If anyone else would like do to the work email
-    me and I can point out the places that need changed.  If you have >2
-    processors and don't want to add support yourself let me know and I
-    can take a look into it.
-
-  BeBox
-    BeBox support hasn't been added to the 2.1.X kernels from 2.0.X
-    but work is being done and SMP support for BeBox is in the works.
-
-  CHRP
-    CHRP SMP works and is fairly solid.  It's been tested on the IBM F50
-    with 4 processors for quite some time now.
index 37796fe45bd00a0a31fa9bc4a3a6a12decbe1606..eaa4801f2ce6aecfb0f7c1b3ca5f91ceb58341fd 100644 (file)
@@ -409,7 +409,7 @@ i.  Function reordering so that inline functions are defined before they
        megaraid_mbox_prepare_pthru, megaraid_mbox_prepare_epthru,
        megaraid_busywait_mbox
 
-               - Andrew Morton <akpm@osdl.org>, 08.19.2004
+               - Andrew Morton, 08.19.2004
                linux-scsi mailing list
 
        "Something else to clean up after inclusion: every instance of an
@@ -471,13 +471,13 @@ vi.       Add support for 64-bit applications. Current drivers assume only
 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
+               - Andrew Morton, 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
+               - Andrew Morton, 08.19.2004
                linux-scsi mailing list
 
 ix.    replace udelay with msleep
index bbe8dee681a5d2b9a503d7f59b22e79d7a3e9014..6bb916d57c957754fd9b4915c4d1a42e3a4cc8ac 100644 (file)
@@ -96,7 +96,7 @@ Each slave device attached to the PXA must provide slave specific configuration
 information via the structure "pxa2xx_spi_chip" found in
 "arch/arm/mach-pxa/include/mach/pxa2xx_spi.h".  The pxa2xx_spi master controller driver
 will uses the configuration whenever the driver communicates with the slave
-device.
+device. All fields are optional.
 
 struct pxa2xx_spi_chip {
        u8 tx_threshold;
@@ -112,14 +112,17 @@ used to configure the SSP hardware fifo.  These fields are critical to the
 performance of pxa2xx_spi driver and misconfiguration will result in rx
 fifo overruns (especially in PIO mode transfers). Good default values are
 
-       .tx_threshold = 12,
-       .rx_threshold = 4,
+       .tx_threshold = 8,
+       .rx_threshold = 8,
+
+The range is 1 to 16 where zero indicates "use default".
 
 The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA
 engine and is related the "spi_device.bits_per_word" field.  Read and understand
 the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
 to determine the correct value. An SSP configured for byte-wide transfers would
-use a value of 8.
+use a value of 8. The driver will determine a reasonable default if
+dma_burst_size == 0.
 
 The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle
 trailing bytes in the SSP receiver fifo.  The correct value for this field is
@@ -137,7 +140,13 @@ function for asserting/deasserting a slave device chip select.  If the field is
 NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
 configured to use SSPFRM instead.
 
-NSSP SALVE SAMPLE
+NOTE: the SPI driver cannot control the chip select if SSPFRM is used, so the
+chipselect is dropped after each spi_transfer.  Most devices need chip select
+asserted around the complete message.  Use SSPFRM as a GPIO (through cs_control)
+to accomodate these chips.
+
+
+NSSP SLAVE SAMPLE
 -----------------
 The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the
 "spi_board_info.controller_data" field. Below is a sample configuration using
@@ -206,18 +215,21 @@ static void __init streetracer_init(void)
 
 DMA and PIO I/O Support
 -----------------------
-The pxa2xx_spi driver support both DMA and interrupt driven PIO message
-transfers.  The driver defaults to PIO mode and DMA transfers must enabled by
-setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and
-ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero.  The DMA
-mode support both coherent and stream based DMA mappings.
+The pxa2xx_spi driver supports both DMA and interrupt driven PIO message
+transfers.  The driver defaults to PIO mode and DMA transfers must be enabled
+by setting the "enable_dma" flag in the "pxa2xx_spi_master" structure.  The DMA
+mode supports both coherent and stream based DMA mappings.
 
 The following logic is used to determine the type of I/O to be used on
 a per "spi_transfer" basis:
 
-if !enable_dma or dma_burst_size == 0 then
+if !enable_dma then
        always use PIO transfers
 
+if spi_message.len > 8191 then
+       print "rate limited" warning
+       use PIO transfers
+
 if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then
        use coherent DMA mode
 
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX
new file mode 100644 (file)
index 0000000..397dc35
--- /dev/null
@@ -0,0 +1,10 @@
+00-INDEX
+       - this file
+highres.txt
+       - High resolution timers and dynamic ticks design notes
+hpet.txt
+       - High Precision Event Timer Driver for Linux
+hrtimers.txt
+       - subsystem for high-resolution kernel timers
+timer_stats.txt
+       - timer usage statistics
diff --git a/Documentation/timers/hpet.txt b/Documentation/timers/hpet.txt
new file mode 100644 (file)
index 0000000..e7c09ab
--- /dev/null
@@ -0,0 +1,299 @@
+               High Precision Event Timer Driver for Linux
+
+The High Precision Event Timer (HPET) hardware follows a specification
+by Intel and Microsoft which can be found at
+
+       http://www.intel.com/technology/architecture/hpetspec.htm
+
+Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision")
+and up to 32 comparators.  Normally three or more comparators are provided,
+each of which can generate oneshot interupts and at least one of which has
+additional hardware to support periodic interrupts.  The comparators are
+also called "timers", which can be misleading since usually timers are
+independent of each other ... these share a counter, complicating resets.
+
+HPET devices can support two interrupt routing modes.  In one mode, the
+comparators are additional interrupt sources with no particular system
+role.  Many x86 BIOS writers don't route HPET interrupts at all, which
+prevents use of that mode.  They support the other "legacy replacement"
+mode where the first two comparators block interrupts from 8254 timers
+and from the RTC.
+
+The driver supports detection of HPET driver allocation and initialization
+of the HPET before the driver module_init routine is called.  This enables
+platform code which uses timer 0 or 1 as the main timer to intercept HPET
+initialization.  An example of this initialization can be found in
+arch/x86/kernel/hpet.c.
+
+The driver provides a userspace API which resembles the API found in the
+RTC driver framework.  An example user space program is provided below.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <memory.h>
+#include <malloc.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <linux/hpet.h>
+
+
+extern void hpet_open_close(int, const char **);
+extern void hpet_info(int, const char **);
+extern void hpet_poll(int, const char **);
+extern void hpet_fasync(int, const char **);
+extern void hpet_read(int, const char **);
+
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+struct hpet_command {
+       char            *command;
+       void            (*func)(int argc, const char ** argv);
+} hpet_command[] = {
+       {
+               "open-close",
+               hpet_open_close
+       },
+       {
+               "info",
+               hpet_info
+       },
+       {
+               "poll",
+               hpet_poll
+       },
+       {
+               "fasync",
+               hpet_fasync
+       },
+};
+
+int
+main(int argc, const char ** argv)
+{
+       int     i;
+
+       argc--;
+       argv++;
+
+       if (!argc) {
+               fprintf(stderr, "-hpet: requires command\n");
+               return -1;
+       }
+
+
+       for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
+               if (!strcmp(argv[0], hpet_command[i].command)) {
+                       argc--;
+                       argv++;
+                       fprintf(stderr, "-hpet: executing %s\n",
+                               hpet_command[i].command);
+                       hpet_command[i].func(argc, argv);
+                       return 0;
+               }
+
+       fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
+
+       return -1;
+}
+
+void
+hpet_open_close(int argc, const char **argv)
+{
+       int     fd;
+
+       if (argc != 1) {
+               fprintf(stderr, "hpet_open_close: device-name\n");
+               return;
+       }
+
+       fd = open(argv[0], O_RDONLY);
+       if (fd < 0)
+               fprintf(stderr, "hpet_open_close: open failed\n");
+       else
+               close(fd);
+
+       return;
+}
+
+void
+hpet_info(int argc, const char **argv)
+{
+}
+
+void
+hpet_poll(int argc, const char **argv)
+{
+       unsigned long           freq;
+       int                     iterations, i, fd;
+       struct pollfd           pfd;
+       struct hpet_info        info;
+       struct timeval          stv, etv;
+       struct timezone         tz;
+       long                    usec;
+
+       if (argc != 3) {
+               fprintf(stderr, "hpet_poll: device-name freq iterations\n");
+               return;
+       }
+
+       freq = atoi(argv[1]);
+       iterations = atoi(argv[2]);
+
+       fd = open(argv[0], O_RDONLY);
+
+       if (fd < 0) {
+               fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
+               return;
+       }
+
+       if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+               fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
+               goto out;
+       }
+
+       if (ioctl(fd, HPET_INFO, &info) < 0) {
+               fprintf(stderr, "hpet_poll: failed to get info\n");
+               goto out;
+       }
+
+       fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
+
+       if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+               fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
+               goto out;
+       }
+
+       if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+               fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
+               goto out;
+       }
+
+       pfd.fd = fd;
+       pfd.events = POLLIN;
+
+       for (i = 0; i < iterations; i++) {
+               pfd.revents = 0;
+               gettimeofday(&stv, &tz);
+               if (poll(&pfd, 1, -1) < 0)
+                       fprintf(stderr, "hpet_poll: poll failed\n");
+               else {
+                       long    data;
+
+                       gettimeofday(&etv, &tz);
+                       usec = stv.tv_sec * 1000000 + stv.tv_usec;
+                       usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
+
+                       fprintf(stderr,
+                               "hpet_poll: expired time = 0x%lx\n", usec);
+
+                       fprintf(stderr, "hpet_poll: revents = 0x%x\n",
+                               pfd.revents);
+
+                       if (read(fd, &data, sizeof(data)) != sizeof(data)) {
+                               fprintf(stderr, "hpet_poll: read failed\n");
+                       }
+                       else
+                               fprintf(stderr, "hpet_poll: data 0x%lx\n",
+                                       data);
+               }
+       }
+
+out:
+       close(fd);
+       return;
+}
+
+static int hpet_sigio_count;
+
+static void
+hpet_sigio(int val)
+{
+       fprintf(stderr, "hpet_sigio: called\n");
+       hpet_sigio_count++;
+}
+
+void
+hpet_fasync(int argc, const char **argv)
+{
+       unsigned long           freq;
+       int                     iterations, i, fd, value;
+       sig_t                   oldsig;
+       struct hpet_info        info;
+
+       hpet_sigio_count = 0;
+       fd = -1;
+
+       if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
+               fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
+               return;
+       }
+
+       if (argc != 3) {
+               fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
+               goto out;
+       }
+
+       fd = open(argv[0], O_RDONLY);
+
+       if (fd < 0) {
+               fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
+               return;
+       }
+
+
+       if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
+               ((value = fcntl(fd, F_GETFL)) == 1) ||
+               (fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
+               fprintf(stderr, "hpet_fasync: fcntl failed\n");
+               goto out;
+       }
+
+       freq = atoi(argv[1]);
+       iterations = atoi(argv[2]);
+
+       if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+               fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
+               goto out;
+       }
+
+       if (ioctl(fd, HPET_INFO, &info) < 0) {
+               fprintf(stderr, "hpet_fasync: failed to get info\n");
+               goto out;
+       }
+
+       fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
+
+       if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+               fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
+               goto out;
+       }
+
+       if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+               fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
+               goto out;
+       }
+
+       for (i = 0; i < iterations; i++) {
+               (void) pause();
+               fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
+       }
+
+out:
+       signal(SIGIO, oldsig);
+
+       if (fd >= 0)
+               close(fd);
+
+       return;
+}
index f32efb6fb12c5111de62f875ec8361af5152e091..60ba66836038215952c9be46dcbff58edb19b319 100644 (file)
 149 -> Typhoon TV-Tuner PCI (50684)
 150 -> Geovision GV-600                                    [008a:763c]
 151 -> Kozumi KTV-01C
+152 -> Encore ENL TV-FM-2                                  [1000:1801]
index f0e613ba55b8bd2f1ed0f39b7e93699ec3b9d5bc..64823ccacd69013ae48401705e7704a39ce38136 100644 (file)
@@ -9,3 +9,5 @@
   8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
   9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
  10 -> DViCO FusionHDTV7 Dual Express                      [18ac:d618]
+ 11 -> DViCO FusionHDTV DVB-T Dual Express                 [18ac:db78]
+ 12 -> Leadtek Winfast PxDVR3200 H                         [107d:6681]
index 7cf5685d36452f64216a0f304e69f7b71ed43703..a5227e308f4ab91146dc2426a2bd694d95d63043 100644 (file)
  65 -> DViCO FusionHDTV 7 Gold                             [18ac:d610]
  66 -> Prolink Pixelview MPEG 8000GT                       [1554:4935]
  67 -> Kworld PlusTV HD PCI 120 (ATSC 120)                 [17de:08c1]
+ 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid           [0070:6900,0070:6904,0070:6902]
+ 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2              [0070:6905,0070:6906]
+ 70 -> TeVii S460 DVB-S/S2                                 [d460:9022]
+ 71 -> Omicom SS4 DVB-S/S2 PCI                             [A044:2011]
+ 72 -> TBS 8920 DVB-S/S2                                   [8920:8888]
+ 73 -> TeVii S420 DVB-S                                    [d420:9022]
+ 74 -> Prolink Pixelview Global Extreme                    [1554:4976]
+ 75 -> PROF 7300 DVB-S/S2                                  [B033:3033]
index 53449cb99b17c71e3714949b090fd2252e7e4492..187cc48d092469a045ccd52fb16d4239bf6c447e 100644 (file)
@@ -1,5 +1,5 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
@@ -12,7 +12,7 @@
  11 -> Terratec Hybrid XS                       (em2880)        [0ccd:0042]
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
- 14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840)
+ 14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840) [eb1a:2821]
  15 -> V-Gear PocketTV                          (em2800)
  16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b,2040:651f]
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
index 39868af9cf9fe665a6bbd991a4927e55061232d3..dc67eef38ff92071995b9c0d12f901ef4e3837b9 100644 (file)
@@ -76,7 +76,7 @@
  75 -> AVerMedia AVerTVHD MCE A180              [1461:1044]
  76 -> SKNet MonsterTV Mobile                   [1131:4ee9]
  77 -> Pinnacle PCTV 40i/50i/110i (saa7133)     [11bd:002e]
- 78 -> ASUSTeK P7131 Dual                       [1043:4862,1043:4857]
+ 78 -> ASUSTeK P7131 Dual                       [1043:4862]
  79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
  80 -> ASUS Digimatrix TV                       [1043:0210]
  81 -> Philips Tiger reference design           [1131:2018]
 144 -> Beholder BeholdTV M6 Extra               [5ace:6193]
 145 -> AVerMedia MiniPCI DVB-T Hybrid M103      [1461:f636]
 146 -> ASUSTeK P7131 Analog
+147 -> Asus Tiger 3in1                          [1043:4878]
+148 -> Encore ENLTV-FM v5.3                     [1a7f:2008]
+149 -> Avermedia PCI pure analog (M135A)        [1461:f11d]
+150 -> Zogis Real Angel 220
+151 -> ADS Tech Instant HDTV                    [1421:0380]
+152 -> Asus Tiger Rev:1.00                      [1043:4857]
index 0e2394695bb86843fb89a166eaa83727a2d9a37e..30bbdda68d03bc17dd91b215764ef3aa71f5e614 100644 (file)
@@ -74,3 +74,4 @@ tuner=72 - Thomson FE6600
 tuner=73 - Samsung TCPG 6121P30A
 tuner=75 - Philips TEA5761 FM Radio
 tuner=76 - Xceive 5000 tuner
+tuner=77 - TCL tuner MF02GIP-5N-E
index 9a3e4d797fa858d0925e30d64be6c381fe6bae24..004818fab040ab0bb04078be639c5346a688f772 100644 (file)
@@ -7,6 +7,7 @@ The modules are:
 xxxx           vend:prod
 ----
 spca501                0000:0000       MystFromOri Unknow Camera
+m5602          0402:5602       ALi Video Camera Controller
 spca501                040a:0002       Kodak DVC-325
 spca500                040a:0300       Kodak EZ200
 zc3xx          041e:041e       Creative WebCam Live!
@@ -42,6 +43,7 @@ zc3xx         0458:7007       Genius VideoCam V2
 zc3xx          0458:700c       Genius VideoCam V3
 zc3xx          0458:700f       Genius VideoCam Web V2
 sonixj         0458:7025       Genius Eye 311Q
+sonixj         0458:702e       Genius Slim 310 NB
 sonixj         045e:00f5       MicroSoft VX3000
 sonixj         045e:00f7       MicroSoft VX1000
 ov519          045e:028c       Micro$oft xbox cam
@@ -81,7 +83,7 @@ spca561               046d:092b       Labtec Webcam Plus
 spca561                046d:092c       Logitech QC chat Elch2
 spca561                046d:092d       Logitech QC Elch2
 spca561                046d:092e       Logitech QC Elch2
-spca561                046d:092f       Logitech QC Elch2
+spca561                046d:092f       Logitech  QuickCam Express Plus
 sunplus                046d:0960       Logitech ClickSmart 420
 sunplus                0471:0322       Philips DMVC1300K
 zc3xx          0471:0325       Philips SPC 200 NC
@@ -96,6 +98,29 @@ sunplus              04a5:3003       Benq DC 1300
 sunplus                04a5:3008       Benq DC 1500
 sunplus                04a5:300a       Benq DC 3410
 spca500                04a5:300c       Benq DC 1016
+finepix                04cb:0104       Fujifilm FinePix 4800
+finepix                04cb:0109       Fujifilm FinePix A202
+finepix                04cb:010b       Fujifilm FinePix A203
+finepix                04cb:010f       Fujifilm FinePix A204
+finepix                04cb:0111       Fujifilm FinePix A205
+finepix                04cb:0113       Fujifilm FinePix A210
+finepix                04cb:0115       Fujifilm FinePix A303
+finepix                04cb:0117       Fujifilm FinePix A310
+finepix                04cb:0119       Fujifilm FinePix F401
+finepix                04cb:011b       Fujifilm FinePix F402
+finepix                04cb:011d       Fujifilm FinePix F410
+finepix                04cb:0121       Fujifilm FinePix F601
+finepix                04cb:0123       Fujifilm FinePix F700
+finepix                04cb:0125       Fujifilm FinePix M603
+finepix                04cb:0127       Fujifilm FinePix S300
+finepix                04cb:0129       Fujifilm FinePix S304
+finepix                04cb:012b       Fujifilm FinePix S500
+finepix                04cb:012d       Fujifilm FinePix S602
+finepix                04cb:012f       Fujifilm FinePix S700
+finepix                04cb:0131       Fujifilm FinePix unknown model
+finepix                04cb:013b       Fujifilm FinePix unknown model
+finepix                04cb:013d       Fujifilm FinePix unknown model
+finepix                04cb:013f       Fujifilm FinePix F420
 sunplus                04f1:1001       JVC GC A50
 spca561                04fc:0561       Flexcam 100
 sunplus                04fc:500c       Sunplus CA500C
@@ -181,6 +206,7 @@ pac207              093a:2468       PAC207
 pac207         093a:2470       Genius GF112
 pac207         093a:2471       Genius VideoCam ge111
 pac207         093a:2472       Genius VideoCam ge110
+pac207         093a:2476       Genius e-Messenger 112
 pac7311                093a:2600       PAC7311 Typhoon
 pac7311                093a:2601       Philips SPC 610 NC
 pac7311                093a:2603       PAC7312
diff --git a/Documentation/video4linux/m5602.txt b/Documentation/video4linux/m5602.txt
new file mode 100644 (file)
index 0000000..4450ab1
--- /dev/null
@@ -0,0 +1,12 @@
+This document describes the ALi m5602 bridge connected
+to the following supported sensors:
+OmniVision OV9650,
+Samsung s5k83a,
+Samsung s5k4aa,
+Micron mt9m111,
+Pixel plus PO1030
+
+This driver mimics the windows drivers, which have a braindead implementation sending bayer-encoded frames at VGA resolution.
+In a perfect world we should be able to reprogram the m5602 and the connected sensor in hardware instead, supporting a range of resolutions and pixelformats
+
+Anyway, have fun and please report any bugs to m560x-driver-devel@lists.sourceforge.net
diff --git a/Documentation/video4linux/soc-camera.txt b/Documentation/video4linux/soc-camera.txt
new file mode 100644 (file)
index 0000000..178ef3c
--- /dev/null
@@ -0,0 +1,120 @@
+                       Soc-Camera Subsystem
+                       ====================
+
+Terminology
+-----------
+
+The following terms are used in this document:
+ - camera / camera device / camera sensor - a video-camera sensor chip, capable
+   of connecting to a variety of systems and interfaces, typically uses i2c for
+   control and configuration, and a parallel or a serial bus for data.
+ - camera host - an interface, to which a camera is connected. Typically a
+   specialised interface, present on many SoCs, e.g., PXA27x and PXA3xx, SuperH,
+   AVR32, i.MX27, i.MX31.
+ - camera host bus - a connection between a camera host and a camera. Can be
+   parallel or serial, consists of data and control lines, e.g., clock, vertical
+   and horizontal synchronization signals.
+
+Purpose of the soc-camera subsystem
+-----------------------------------
+
+The soc-camera subsystem provides a unified API between camera host drivers and
+camera sensor drivers. It implements a V4L2 interface to the user, currently
+only the mmap method is supported.
+
+This subsystem has been written to connect drivers for System-on-Chip (SoC)
+video capture interfaces with drivers for CMOS camera sensor chips to enable
+the reuse of sensor drivers with various hosts. The subsystem has been designed
+to support multiple camera host interfaces and multiple cameras per interface,
+although most applications have only one camera sensor.
+
+Existing drivers
+----------------
+
+As of 2.6.27-rc4 there are two host drivers in the mainline: pxa_camera.c for
+PXA27x SoCs and sh_mobile_ceu_camera.c for SuperH SoCs, and four sensor drivers:
+mt9m001.c, mt9m111.c, mt9v022.c and a generic soc_camera_platform.c driver. This
+list is not supposed to be updated, look for more examples in your tree.
+
+Camera host API
+---------------
+
+A host camera driver is registered using the
+
+soc_camera_host_register(struct soc_camera_host *);
+
+function. The host object can be initialized as follows:
+
+static struct soc_camera_host pxa_soc_camera_host = {
+       .drv_name       = PXA_CAM_DRV_NAME,
+       .ops            = &pxa_soc_camera_host_ops,
+};
+
+All camera host methods are passed in a struct soc_camera_host_ops:
+
+static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
+       .owner          = THIS_MODULE,
+       .add            = pxa_camera_add_device,
+       .remove         = pxa_camera_remove_device,
+       .suspend        = pxa_camera_suspend,
+       .resume         = pxa_camera_resume,
+       .set_fmt_cap    = pxa_camera_set_fmt_cap,
+       .try_fmt_cap    = pxa_camera_try_fmt_cap,
+       .init_videobuf  = pxa_camera_init_videobuf,
+       .reqbufs        = pxa_camera_reqbufs,
+       .poll           = pxa_camera_poll,
+       .querycap       = pxa_camera_querycap,
+       .try_bus_param  = pxa_camera_try_bus_param,
+       .set_bus_param  = pxa_camera_set_bus_param,
+};
+
+.add and .remove methods are called when a sensor is attached to or detached
+from the host, apart from performing host-internal tasks they shall also call
+sensor driver's .init and .release methods respectively. .suspend and .resume
+methods implement host's power-management functionality and its their
+responsibility to call respective sensor's methods. .try_bus_param and
+.set_bus_param are used to negotiate physical connection parameters between the
+host and the sensor. .init_videobuf is called by soc-camera core when a
+video-device is opened, further video-buffer management is implemented completely
+by the specific camera host driver. The rest of the methods are called from
+respective V4L2 operations.
+
+Camera API
+----------
+
+Sensor drivers can use struct soc_camera_link, typically provided by the
+platform, and used to specify to which camera host bus the sensor is connected,
+and arbitrarily provide platform .power and .reset methods for the camera.
+soc_camera_device_register() and soc_camera_device_unregister() functions are
+used to add a sensor driver to or remove one from the system. The registration
+function takes a pointer to struct soc_camera_device as the only parameter.
+This struct can be initialized as follows:
+
+       /* link to driver operations */
+       icd->ops        = &mt9m001_ops;
+       /* link to the underlying physical (e.g., i2c) device */
+       icd->control    = &client->dev;
+       /* window geometry */
+       icd->x_min      = 20;
+       icd->y_min      = 12;
+       icd->x_current  = 20;
+       icd->y_current  = 12;
+       icd->width_min  = 48;
+       icd->width_max  = 1280;
+       icd->height_min = 32;
+       icd->height_max = 1024;
+       icd->y_skip_top = 1;
+       /* camera bus ID, typically obtained from platform data */
+       icd->iface      = icl->bus_id;
+
+struct soc_camera_ops provides .probe and .remove methods, which are called by
+the soc-camera core, when a camera is matched against or removed from a camera
+host bus, .init, .release, .suspend, and .resume are called from the camera host
+driver as discussed above. Other members of this struct provide respective V4L2
+functionality.
+
+struct soc_camera_device also links to an array of struct soc_camera_data_format,
+listing pixel formats, supported by the camera.
+
+--
+Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
index 5270cf4cb109f93a1505e4185f318a60f1fcd252..cb49802745dcb1c7838223b77d59c11e8e108b6b 100644 (file)
@@ -1,5 +1,7 @@
 00-INDEX
        - This file
+slaves/
+       - Drivers that provide support for specific family codes.
 masters/
        - Individual chips providing 1-wire busses.
 w1.generic
index 239f9ae018432c0ad23a33603bf429e062a40866..28176def3d6f3430c0b2c71c6be9d6b180914cf9 100644 (file)
@@ -16,3 +16,55 @@ which allows to build USB <-> W1 bridges.
 DS9490(R) is a USB <-> W1 bus master device
 which has 0x81 family ID integrated chip and DS2490
 low-level operational chip.
+
+Notes and limitations.
+- The weak pullup current is a minimum of 0.9mA and maximum of 6.0mA.
+- The 5V strong pullup is supported with a minimum of 5.9mA and a
+  maximum of 30.4 mA.  (From DS2490.pdf)
+- While the ds2490 supports a hardware search the code doesn't take
+  advantage of it (in tested case it only returned first device).
+- The hardware will detect when devices are attached to the bus on the
+  next bus (reset?) operation, however only a message is printed as
+  the core w1 code doesn't make use of the information.  Connecting
+  one device tends to give multiple new device notifications.
+- The number of USB bus transactions could be reduced if w1_reset_send
+  was added to the API.  The name is just a suggestion.  It would take
+  a write buffer and a read buffer (along with sizes) as arguments.
+  The ds2490 block I/O command supports reset, write buffer, read
+  buffer, and strong pullup all in one command, instead of the current
+  1 reset bus, 2 write the match rom command and slave rom id, 3 block
+  write and read data.  The write buffer needs to have the match rom
+  command and slave rom id prepended to the front of the requested
+  write buffer, both of which are known to the driver.
+- The hardware supports normal, flexible, and overdrive bus
+  communication speeds, but only the normal is supported.
+- The registered w1_bus_master functions don't define error
+  conditions.  If a bus search is in progress and the ds2490 is
+  removed it can produce a good amount of error output before the bus
+  search finishes.
+- The hardware supports detecting some error conditions, such as
+  short, alarming presence on reset, and no presence on reset, but the
+  driver doesn't query those values.
+- The ds2490 specification doesn't cover short bulk in reads in
+  detail, but my observation is if fewer bytes are requested than are
+  available, the bulk read will return an error and the hardware will
+  clear the entire bulk in buffer.  It would be possible to read the
+  maximum buffer size to not run into this error condition, only extra
+  bytes in the buffer is a logic error in the driver.  The code should
+  should match reads and writes as well as data sizes.  Reads and
+  writes are serialized and the status verifies that the chip is idle
+  (and data is available) before the read is executed, so it should
+  not happen.
+- Running x86_64 2.6.24 UHCI under qemu 0.9.0 under x86_64 2.6.22-rc6
+  with a OHCI controller, ds2490 running in the guest would operate
+  normally the first time the module was loaded after qemu attached
+  the ds2490 hardware, but if the module was unloaded, then reloaded
+  most of the time one of the bulk out or in, and usually the bulk in
+  would fail.  qemu sets a 50ms timeout and the bulk in would timeout
+  even when the status shows data available.  A bulk out write would
+  show a successful completion, but the ds2490 status register would
+  show 0 bytes written.  Detaching qemu from the ds2490 hardware and
+  reattaching would clear the problem.  usbmon output in the guest and
+  host did not explain the problem.  My guess is a bug in either qemu
+  or the host OS and more likely the host OS.
+-- 03-06-2008 David Fries <David@Fries.net>
diff --git a/Documentation/w1/slaves/00-INDEX b/Documentation/w1/slaves/00-INDEX
new file mode 100644 (file)
index 0000000..f8101d6
--- /dev/null
@@ -0,0 +1,4 @@
+00-INDEX
+       - This file
+w1_therm
+       - The Maxim/Dallas Semiconductor ds18*20 temperature sensor.
diff --git a/Documentation/w1/slaves/w1_therm b/Documentation/w1/slaves/w1_therm
new file mode 100644 (file)
index 0000000..0403aaa
--- /dev/null
@@ -0,0 +1,41 @@
+Kernel driver w1_therm
+====================
+
+Supported chips:
+  * Maxim ds18*20 based temperature sensors.
+
+Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Description
+-----------
+
+w1_therm provides basic temperature conversion for ds18*20 devices.
+supported family codes:
+W1_THERM_DS18S20       0x10
+W1_THERM_DS1822                0x22
+W1_THERM_DS18B20       0x28
+
+Support is provided through the sysfs w1_slave file.  Each open and
+read sequence will initiate a temperature conversion then provide two
+lines of ASCII output.  The first line contains the nine hex bytes
+read along with a calculated crc value and YES or NO if it matched.
+If the crc matched the returned values are retained.  The second line
+displays the retained values along with a temperature in millidegrees
+Centigrade after t=.
+
+Parasite powered devices are limited to one slave performing a
+temperature conversion at a time.  If none of the devices are parasite
+powered it would be possible to convert all the devices at the same
+time and then go back to read individual sensors.  That isn't
+currently supported.  The driver also doesn't support reduced
+precision (which would also reduce the conversion time).
+
+The module parameter strong_pullup can be set to 0 to disable the
+strong pullup or 1 to enable.  If enabled the 5V strong pullup will be
+enabled when the conversion is taking place provided the master driver
+must support the strong pullup (or it falls back to a pullup
+resistor).  The DS18b20 temperature sensor specification lists a
+maximum current draw of 1.5mA and that a 5k pullup resistor is not
+sufficient.  The strong pullup is designed to provide the additional
+current required.
index 4c6509dd478923285bc883867635fe8365faa77b..e3333eec4320c2a4d679a111a19539523781f428 100644 (file)
@@ -79,10 +79,13 @@ w1 master sysfs interface
 <xx-xxxxxxxxxxxxx> - a directory for a found device. The format is family-serial
 bus                - (standard) symlink to the w1 bus
 driver             - (standard) symlink to the w1 driver
+w1_master_add      - Manually register a slave device
 w1_master_attempts - the number of times a search was attempted
 w1_master_max_slave_count
                    - the maximum slaves that may be attached to a master
 w1_master_name     - the name of the device (w1_bus_masterX)
+w1_master_pullup   - 5V strong pullup 0 enabled, 1 disabled
+w1_master_remove   - Manually remove a slave device
 w1_master_search   - the number of searches left to do, -1=continual (default)
 w1_master_slave_count
                    - the number of slaves found
@@ -90,7 +93,13 @@ w1_master_slaves   - the names of the slaves, one per line
 w1_master_timeout  - the delay in seconds between searches
 
 If you have a w1 bus that never changes (you don't add or remove devices),
-you can set w1_master_search to a positive value to disable searches.
+you can set the module parameter search_count to a small positive number
+for an initially small number of bus searches.  Alternatively it could be
+set to zero, then manually add the slave device serial numbers by
+w1_master_add device file.  The w1_master_add and w1_master_remove files
+generally only make sense when searching is disabled, as a search will
+redetect manually removed devices that are present and timeout manually
+added devices that aren't on the bus.
 
 
 w1 slave sysfs interface
index 6ba3ee822838cea89be914acb2333424ec644c9d..52702b057c022fa6a3d3b4ee7f2c5984482286f9 100644 (file)
@@ -72,8 +72,8 @@ M: Mail patches to
 L: Mailing list that is relevant to this area
 W: Web-page with status/info
 T: SCM tree type and location.  Type is one of: git, hg, quilt.
-S: Status, one of the following:
 F: Applicable files and/or directories
+S: Status, one of the following:
 
        Supported:      Someone is actually paid to look after this.
        Maintained:     Someone actually looks after it.
@@ -1629,6 +1629,11 @@ P:       Christopher Hoover
 M:     ch@murgatroid.com, ch@hpl.hp.com
 S:     Maintained
 
+EPSON S1D13XXX FRAMEBUFFER DRIVER
+P:     Kristoffer Ericson
+M:     kristoffer.ericson@gmail.com
+S:     Maintained
+
 ETHEREXPRESS-16 NETWORK DRIVER
 P:     Philip Blundell
 M:     philb@gnu.org
@@ -2443,7 +2448,14 @@ S:       Supported
 
 KERNEL VIRTUAL MACHINE (KVM)
 P:     Avi Kivity
-M:     avi@qumranet.com
+M:     avi@redhat.com
+L:     kvm@vger.kernel.org
+W:     http://kvm.qumranet.com
+S:     Supported
+
+KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
+P:     Joerg Roedel
+M:     joerg.roedel@amd.com
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -2797,15 +2809,6 @@ L:       linux-mtd@lists.infradead.org
 T:     git git://git.infradead.org/mtd-2.6.git
 S:     Maintained
 
-MEI MN10300/AM33 PORT
-P:     David Howells
-M:     dhowells@redhat.com
-P:     Koichi Yasutake
-M:     yasutake.koichi@jp.panasonic.com
-L:     linux-am33-list@redhat.com (moderated for non-subscribers)
-W:     ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
-S:     Maintained
-
 MICROTEK X6 SCANNER
 P:     Oliver Neukum
 M:     oliver@neukum.name
@@ -3170,6 +3173,15 @@ M:       olof@lixom.net
 L:     i2c@lm-sensors.org
 S:     Maintained
 
+PANASONIC MN10300/AM33 PORT
+P:     David Howells
+M:     dhowells@redhat.com
+P:     Koichi Yasutake
+M:     yasutake.koichi@jp.panasonic.com
+L:     linux-am33-list@redhat.com (moderated for non-subscribers)
+W:     ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
+S:     Maintained
+
 PARALLEL PORT SUPPORT
 L:     linux-parport@lists.infradead.org (subscribers-only)
 S:     Orphan
@@ -4089,7 +4101,7 @@ W:        http://tpmdd.sourceforge.net
 P:     Marcel Selhorst
 M:     tpm@selhorst.net
 W:     http://www.prosec.rub.de/tpm/
-L:     tpmdd-devel@lists.sourceforge.net
+L:     tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 
 TRIVIAL PATCHES
@@ -4480,6 +4492,13 @@ W:       http://kernel.org/~kzak/util-linux-ng/
 T:     git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git
 S:     Maintained
 
+UVESAFB DRIVER
+P:     Michal Januszewski
+M:     spock@gentoo.org
+L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+W:     http://dev.gentoo.org/~spock/projects/uvesafb/
+S:     Maintained
+
 VFAT/FAT/MSDOS FILESYSTEM
 P:     OGAWA Hirofumi
 M:     hirofumi@mail.parknet.co.jp
@@ -4497,6 +4516,14 @@ M:       khali@linux-fr.org
 L:     i2c@lm-sensors.org
 S:     Maintained
 
+VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
+P:     Joseph Chan
+M:     JosephChan@via.com.tw
+P:     Scott Fang
+M:     ScottFang@viatech.com.cn
+L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
+S:     Maintained
+
 VIA VELOCITY NETWORK DRIVER
 P:     Francois Romieu
 M:     romieu@fr.zoreil.com
@@ -4520,10 +4547,11 @@ S:      Maintained
 
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 P:     Liam Girdwood
-M:     lg@opensource.wolfsonmicro.com
+M:     lrg@slimlogic.co.uk
 P:     Mark Brown
 M:     broonie@opensource.wolfsonmicro.com
 W:     http://opensource.wolfsonmicro.com/node/15
+W:     http://www.slimlogic.co.uk/?page_id=5
 T:     git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
 S:     Supported
 
@@ -4597,7 +4625,7 @@ WM97XX TOUCHSCREEN DRIVERS
 P:     Mark Brown
 M:     broonie@opensource.wolfsonmicro.com
 P:     Liam Girdwood
-M:     liam.girdwood@wolfsonmicro.com
+M:     lrg@slimlogic.co.uk
 L:     linux-input@vger.kernel.org
 T:     git git://opensource.wolfsonmicro.com/linux-2.6-touch
 W:     http://opensource.wolfsonmicro.com/node/7
index 364c6dadde0a6b6ed988f15294f799240b292a68..e6ab550bceb3fda92cf1ad1e67d1e3cee1af9005 100644 (file)
@@ -13,8 +13,22 @@ config OPROFILE
 
          If unsure, say N.
 
+config OPROFILE_IBS
+       bool "OProfile AMD IBS support (EXPERIMENTAL)"
+       default n
+       depends on OPROFILE && SMP && X86
+       help
+          Instruction-Based Sampling (IBS) is a new profiling
+          technique that provides rich, precise program performance
+          information. IBS is introduced by AMD Family10h processors
+          (AMD Opteron Quad-Core processor “Barcelona”) to overcome
+          the limitations of conventional performance counter
+          sampling.
+
+         If unsure, say N.
+
 config HAVE_OPROFILE
-       def_bool n
+       bool
 
 config KPROBES
        bool "Kprobes"
@@ -28,7 +42,7 @@ config KPROBES
          If in doubt, say "N".
 
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
-       def_bool n
+       bool
        help
          Some architectures are unable to perform unaligned accesses
          without the use of get_unaligned/put_unaligned. Others are
@@ -51,13 +65,13 @@ config KRETPROBES
        depends on KPROBES && HAVE_KRETPROBES
 
 config HAVE_IOREMAP_PROT
-       def_bool n
+       bool
 
 config HAVE_KPROBES
-       def_bool n
+       bool
 
 config HAVE_KRETPROBES
-       def_bool n
+       bool
 
 #
 # An arch should select this if it provides all these things:
@@ -75,16 +89,16 @@ config HAVE_KRETPROBES
 #      signal delivery         calls tracehook_signal_handler()
 #
 config HAVE_ARCH_TRACEHOOK
-       def_bool n
+       bool
 
 config HAVE_DMA_ATTRS
-       def_bool n
+       bool
 
 config USE_GENERIC_SMP_HELPERS
-       def_bool n
+       bool
 
 config HAVE_CLK
-       def_bool n
+       bool
        help
          The <linux/clk.h> calls support software clock gating and
          thus are a key power management tool on many systems.
index 1bec55d63ef6241fb9451c821a09960657503acb..a0f642b6a4b92b556e08c8c1d1e357979cd48322 100644 (file)
@@ -5,6 +5,7 @@
 config ALPHA
        bool
        default y
+       select HAVE_AOUT
        select HAVE_IDE
        select HAVE_OPROFILE
        help
@@ -68,9 +69,6 @@ config AUTO_IRQ_AFFINITY
        depends on SMP
        default y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 source "init/Kconfig"
 
 
@@ -224,8 +222,7 @@ config ALPHA_MIATA
        bool "Miata"
        help
          The Digital PersonalWorkStation (PWS 433a, 433au, 500a, 500au, 600a,
-         or 600au).  There is an Installation HOWTO for this hardware at
-         <http://eijk.homelinux.org/~stefan/miata.html>.
+         or 600au).
 
 config ALPHA_MIKASA
        bool "Mikasa"
index 02ce8473870a96c326b91fe8a8f321b0c734dc0f..acdc681231cb49c2c11b8e47564bf02542bd3742 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 < 0x100000000L \
+       set_personality (((BFPM->taso || EX.ah.entry < 0x100000000L \
                           ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
 
 #endif /* __KERNEL__ */
index fc1002ea1e0c766c5150e633d1a83dfa7700a17f..5c75c1b2352a9cacf7c47de5c04d57b1bab7211b 100644 (file)
@@ -144,9 +144,9 @@ extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task);
        : amask (AMASK_CIX) ? "ev6" : "ev67");  \
 })
 
-#define SET_PERSONALITY(EX, IBCS2)                             \
+#define SET_PERSONALITY(EX)                                    \
        set_personality(((EX).e_flags & EF_ALPHA_32BIT)         \
-          ? PER_LINUX_32BIT : (IBCS2) ? PER_SVR4 : PER_LINUX)
+          ? PER_LINUX_32BIT : PER_LINUX)
 
 extern int alpha_l1i_cacheshape;
 extern int alpha_l1d_cacheshape;
index ad15830baefe43199b00d5fc88e445b96b59031b..de35cd438a1023a57f3c5dfb4a49230d8ff69aee 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _ALPHA_STATFS_H
 #define _ALPHA_STATFS_H
 
+/* Alpha is the only 64-bit platform with 32-bit statfs. And doesn't
+   even seem to implement statfs64 */
+#define __statfs_word __u32
+
 #include <asm-generic/statfs.h>
 
 #endif
index 2179c602032a6e5a7a4d55ec59bca02e2a745334..b9094da05d7a136a5dff6bf7a6a0751e25af5316 100644 (file)
@@ -41,13 +41,6 @@ mk_iommu_pte(unsigned long paddr)
        return (paddr >> (PAGE_SHIFT-1)) | 1;
 }
 
-static inline long
-calc_npages(long bytes)
-{
-       return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
-}
-\f
-
 /* Return the minimum of MAX or the first power of two larger
    than main memory.  */
 
@@ -287,7 +280,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
        if (!arena || arena->dma_base + arena->size - 1 > max_dma)
                arena = hose->sg_isa;
 
-       npages = calc_npages((paddr & ~PAGE_MASK) + size);
+       npages = iommu_num_pages(paddr, size, PAGE_SIZE);
 
        /* Force allocation to 64KB boundary for ISA bridges. */
        if (pdev && pdev == isa_bridge)
@@ -387,7 +380,7 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
                BUG();
        }
 
-       npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
+       npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
 
        spin_lock_irqsave(&arena->lock, flags);
 
@@ -580,7 +573,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
           contiguous.  */
 
        paddr &= ~PAGE_MASK;
-       npages = calc_npages(paddr + size);
+       npages = iommu_num_pages(paddr, size, PAGE_SIZE);
        dma_ofs = iommu_arena_alloc(dev, arena, npages, 0);
        if (dma_ofs < 0) {
                /* If we attempted a direct map above but failed, die.  */
@@ -616,7 +609,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
                        sg++;
                }
 
-               npages = calc_npages((paddr & ~PAGE_MASK) + size);
+               npages = iommu_num_pages(paddr, size, PAGE_SIZE);
 
                paddr &= PAGE_MASK;
                for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
@@ -775,7 +768,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
                DBGA("    (%ld) sg [%lx,%lx]\n",
                     sg - end + nents, addr, size);
 
-               npages = calc_npages((addr & ~PAGE_MASK) + size);
+               npages = iommu_num_pages(addr, size, PAGE_SIZE);
                ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
                iommu_arena_free(arena, ofs, npages);
 
index 06b6fdab639f879d56529611381f94627ee5e52f..e657c45d91d27c5a62f7d542ab9d36f3adcb9109 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/cache.h>
 #include <linux/profile.h>
 #include <linux/bitops.h>
+#include <linux/cpu.h>
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
index efeed65b4a66616d5fae54b35fbd0947735359ac..4853f9df37bd22a037f122bd7d78a9a6600cc474 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration"
 config ARM
        bool
        default y
+       select HAVE_AOUT
        select HAVE_IDE
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
@@ -140,9 +141,6 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
index e2274bc0b5441d249c225a0a49eb5474b490e14e..7d5121260fda0370fe85303120544af07689cf79 100644 (file)
@@ -118,9 +118,10 @@ endif
  machine-$(CONFIG_ARCH_IXP23XX)    := ixp23xx
  machine-$(CONFIG_ARCH_OMAP1)     := omap1
  machine-$(CONFIG_ARCH_OMAP2)     := omap2
+ machine-$(CONFIG_ARCH_OMAP3)     := omap2
     plat-$(CONFIG_ARCH_OMAP)      := omap
  machine-$(CONFIG_ARCH_S3C2410)           := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
-    plat-$(CONFIG_PLAT_S3C24XX)           := s3c24xx
+    plat-$(CONFIG_PLAT_S3C24XX)           := s3c24xx s3c
  machine-$(CONFIG_ARCH_LH7A40X)           := lh7a40x
  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
  machine-$(CONFIG_ARCH_IMX)       := imx
diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig
new file mode 100644 (file)
index 0000000..e042d27
--- /dev/null
@@ -0,0 +1,1321 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc8
+# Wed Oct  1 17:14:22 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_MUX is not set
+# CONFIG_OMAP_MCBSP is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP3_BEAGLE=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# 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
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_M66592=y
+CONFIG_USB_M66592=y
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/omap_ldp_defconfig b/arch/arm/configs/omap_ldp_defconfig
new file mode 100644 (file)
index 0000000..948a212
--- /dev/null
@@ -0,0 +1,1044 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc5
+# Fri Oct 10 11:49:41 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_OMAP_SERIAL_WAKE=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+CONFIG_MACH_OMAP_LDP=y
+# CONFIG_MACH_OVERO is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+# CONFIG_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/overo_defconfig b/arch/arm/configs/overo_defconfig
new file mode 100644 (file)
index 0000000..4920096
--- /dev/null
@@ -0,0 +1,1885 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc8
+# Fri Oct  3 11:50:34 2008
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+# CONFIG_OMAP_RESET_CLOCKS is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+CONFIG_MACH_OVERO=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_LL is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+CONFIG_CFG80211=y
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_93CX6=m
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+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_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+CONFIG_LIBERTAS_SDIO=y
+CONFIG_LIBERTAS_DEBUG=y
+CONFIG_USB_ZD1201=m
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+CONFIG_RTL8187=m
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_WAN 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_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# 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_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_AU0828 is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+# CONFIG_VIDEO_EM28XX is not set
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+# CONFIG_USB_ET61X251 is not set
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+# CONFIG_USB_ZC0301 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_ANYSEE is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+# CONFIG_DVB_CINERGYT2_TUNING is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+# CONFIG_DVB_DRX397XD is not set
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# 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
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+# CONFIG_USB_BERRY_CHARGE is not set
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_OMAP is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+
+#
+# Voltage and Current regulators
+#
+# CONFIG_REGULATOR is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_AUTHENC is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 5be016980c193ddef8b7cdcb5ffa0be32d55d1fe..a58378c343b9d3143f5e0116808b2bd1f690ba41 100644 (file)
@@ -107,6 +107,6 @@ extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define ELF_PLAT_INIT(_r, load_addr)   (_r)->ARM_r0 = 0
 
 extern void elf_set_personality(const struct elf32_hdr *);
-#define SET_PERSONALITY(ex, ibcs2)     elf_set_personality(&(ex))
+#define SET_PERSONALITY(ex)    elf_set_personality(&(ex))
 
 #endif
index a02e6a8c3d70ac2d681ef9dd35a426426f1b0ae4..079447c05ba7ea9ea970fee600f03a863e7eaebd 100644 (file)
@@ -1,42 +1,12 @@
 #ifndef _ASMARM_STATFS_H
 #define _ASMARM_STATFS_H
 
-#ifndef __KERNEL_STRICT_NAMES
-# include <linux/types.h>
-typedef __kernel_fsid_t        fsid_t;
-#endif
-
-struct statfs {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u32 f_blocks;
-       __u32 f_bfree;
-       __u32 f_bavail;
-       __u32 f_files;
-       __u32 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-};
-
 /*
  * With EABI there is 4 bytes of padding added to this structure.
  * Let's pack it so the padding goes away to simplify dual ABI support.
  * Note that user space does NOT have to pack this structure.
  */
-struct statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-} __attribute__ ((packed,aligned(4)));
+#define ARCH_PACK_STATFS64 __attribute__((packed,aligned(4)))
 
+#include <asm-generic/statfs.h>
 #endif
index ba99a20355236a06491922a63e0ef745f0bcfcc5..d006085ed7e7b882966510d09695fbb4b1a6091a 100644 (file)
@@ -25,23 +25,6 @@ EXPORT_SYMBOL(dma_spin_lock);
 
 static dma_t dma_chan[MAX_DMA_CHANNELS];
 
-/*
- * Get dma list for /proc/dma
- */
-int get_dma_list(char *buf)
-{
-       dma_t *dma;
-       char *p = buf;
-       int i;
-
-       for (i = 0, dma = dma_chan; i < MAX_DMA_CHANNELS; i++, dma++)
-               if (dma->lock)
-                       p += sprintf(p, "%2d: %14s %s\n", i,
-                                    dma->d_ops->type, dma->device_id);
-
-       return p - buf;
-}
-
 /*
  * Request DMA channel
  *
index e4f72d202cc04acc6b9e3e60261457052434871f..44d4c2e8207b1b06a368fbe30b99ecc75f726302 100644 (file)
@@ -184,7 +184,6 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
 {
 
        /* set default policy and cpuinfo */
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.max_freq = 160000;
        policy->cpuinfo.min_freq = 12000;
        policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
index 2ced6d9984d27802844a448aa37720f54889d62a..adfcd7b513930cdaa677aa835e7e3d24f9d1171d 100644 (file)
@@ -476,6 +476,10 @@ static struct i2c_board_info __initdata h3_i2c_board_info[] = {
                I2C_BOARD_INFO("tps65013", 0x48),
                /* .irq         = OMAP_GPIO_IRQ(??), */
        },
+       {
+               I2C_BOARD_INFO("isp1301_omap", 0x2d),
+               .irq            = OMAP_GPIO_IRQ(14),
+       },
 };
 
 static struct omap_gpio_switch h3_gpio_switches[] __initdata = {
index 478c2c9a22cb02cfda5bb3472f6b911f0790483b..5fba207317100f4ed3cacb9361e134a4e75ee926 100644 (file)
@@ -201,7 +201,7 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate)
                return -EINVAL;
 
        parent = clk->parent;
-       if (unlikely(parent == 0))
+       if (unlikely(parent == NULL))
                return -EIO;
 
        realrate = parent->rate;
@@ -499,7 +499,7 @@ static int omap1_clk_enable_generic(struct clk *clk)
        if (clk->flags & ALWAYS_ENABLED)
                return 0;
 
-       if (unlikely(clk->enable_reg == 0)) {
+       if (unlikely(clk->enable_reg == NULL)) {
                printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
                       clk->name);
                return -EINVAL;
@@ -535,7 +535,7 @@ static void omap1_clk_disable_generic(struct clk *clk)
        __u16 regval16;
        __u32 regval32;
 
-       if (clk->enable_reg == 0)
+       if (clk->enable_reg == NULL)
                return;
 
        if (clk->flags & ENABLE_REG_32BIT) {
@@ -577,7 +577,7 @@ static long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
                return clk->parent->rate / (1 << dsor_exp);
        }
 
-       if(clk->round_rate != 0)
+       if (clk->round_rate != NULL)
                return clk->round_rate(clk, rate);
 
        return clk->rate;
@@ -625,7 +625,7 @@ static void __init omap1_clk_disable_unused(struct clk *clk)
 
        /* Clocks in the DSP domain need api_ck. Just assume bootloader
         * has not enabled any DSP clocks */
-       if ((u32)clk->enable_reg == DSP_IDLECT2) {
+       if (clk->enable_reg == DSP_IDLECT2) {
                printk(KERN_INFO "Skipping reset check for DSP domain "
                       "clock \"%s\"\n", clk->name);
                return;
index 6eadf72828d8900ebbfbff69894b380cc5b80114..5635b511ab6f0b5d1546fef5dec6ed52d70e3c96 100644 (file)
@@ -324,7 +324,7 @@ static struct clk dspper_ck = {
        .parent         = &ck_dpll1,
        .flags          = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
                          RATE_CKCTL | VIRTUAL_IO_ADDRESS,
-       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_reg     = DSP_IDLECT2,
        .enable_bit     = EN_PERCK,
        .rate_offset    = CKCTL_PERDIV_OFFSET,
        .recalc         = &omap1_ckctl_recalc_dsp_domain,
@@ -338,7 +338,7 @@ static struct clk dspxor_ck = {
        .parent         = &ck_ref,
        .flags          = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
                          VIRTUAL_IO_ADDRESS,
-       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_reg     = DSP_IDLECT2,
        .enable_bit     = EN_XORPCK,
        .recalc         = &followparent_recalc,
        .enable         = &omap1_clk_enable_dsp_domain,
@@ -350,7 +350,7 @@ static struct clk dsptim_ck = {
        .parent         = &ck_ref,
        .flags          = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
                          VIRTUAL_IO_ADDRESS,
-       .enable_reg     = (void __iomem *)DSP_IDLECT2,
+       .enable_reg     = DSP_IDLECT2,
        .enable_bit     = EN_DSPTIMCK,
        .recalc         = &followparent_recalc,
        .enable         = &omap1_clk_enable_dsp_domain,
index 99982d3380c96d27f522a7b970d463e6cc53f454..e382b438c64ed5d42d49f05e1586ab03c3218aa5 100644 (file)
@@ -101,7 +101,7 @@ static inline void omap_init_mbox(void) { }
 
 #if defined(CONFIG_OMAP_STI)
 
-#define OMAP1_STI_BASE         IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_BASE         0xfffea000
 #define OMAP1_STI_CHANNEL_BASE (OMAP1_STI_BASE + 0x400)
 
 static struct resource sti_resources[] = {
index 2baeaeb0c9004d2038a7c1fde8b398068de77810..7de7c69155840f2e84fddc23574bb9d74546afe5 100644 (file)
@@ -103,30 +103,6 @@ static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
 { }
 #endif
 
-static int omap1_mcbsp_check(unsigned int id)
-{
-       /* REVISIT: Check correctly for number of registered McBSPs */
-       if (cpu_is_omap730()) {
-               if (id > OMAP_MAX_MCBSP_COUNT - 2) {
-                      printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",
-                               id + 1);
-                      return -ENODEV;
-               }
-               return 0;
-       }
-
-       if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
-               if (id > OMAP_MAX_MCBSP_COUNT - 1) {
-                       printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",
-                               id + 1);
-                       return -ENODEV;
-               }
-               return 0;
-       }
-
-       return -ENODEV;
-}
-
 static void omap1_mcbsp_request(unsigned int id)
 {
        /*
@@ -151,7 +127,6 @@ static void omap1_mcbsp_free(unsigned int id)
 }
 
 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
-       .check          = omap1_mcbsp_check,
        .request        = omap1_mcbsp_request,
        .free           = omap1_mcbsp_free,
 };
@@ -160,7 +135,6 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
        {
                .phys_base      = OMAP730_MCBSP1_BASE,
-               .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,
@@ -169,7 +143,6 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP730_MCBSP2_BASE,
-               .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,
@@ -187,7 +160,6 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
        {
                .phys_base      = OMAP1510_MCBSP1_BASE,
-               .virt_base      = OMAP1510_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
                .rx_irq         = INT_McBSP1RX,
@@ -197,7 +169,6 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
                },
        {
                .phys_base      = OMAP1510_MCBSP2_BASE,
-               .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,
@@ -206,7 +177,6 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP1510_MCBSP3_BASE,
-               .virt_base      = OMAP1510_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
                .rx_irq         = INT_McBSP3RX,
@@ -225,7 +195,6 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
        {
                .phys_base      = OMAP1610_MCBSP1_BASE,
-               .virt_base      = OMAP1610_MCBSP1_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP1_TX,
                .rx_irq         = INT_McBSP1RX,
@@ -235,7 +204,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP1610_MCBSP2_BASE,
-               .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,
@@ -244,7 +212,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP1610_MCBSP3_BASE,
-               .virt_base      = OMAP1610_MCBSP3_BASE,
                .dma_rx_sync    = OMAP_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP_DMA_MCBSP3_TX,
                .rx_irq         = INT_McBSP3RX,
@@ -270,6 +237,18 @@ int __init omap1_mcbsp_init(void)
                }
        }
 
+       if (cpu_is_omap730())
+               omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
+       if (cpu_is_omap15xx())
+               omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
+       if (cpu_is_omap16xx())
+               omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
+
+       mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
+                                                               GFP_KERNEL);
+       if (!mcbsp_ptr)
+               return -ENOMEM;
+
        if (cpu_is_omap730())
                omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata,
                                                OMAP730_MCBSP_PDATA_SZ);
index aefc967fc003fe2e19e1244fb9fb40ef70589ae0..528691d5cb51ed76899041c6285774ae2d608bd6 100644 (file)
@@ -67,8 +67,8 @@ static void __init omap_serial_reset(struct plat_serial8250_port *p)
 
 static struct plat_serial8250_port serial_platform_data[] = {
        {
-               .membase        = (char*)IO_ADDRESS(OMAP_UART1_BASE),
-               .mapbase        = (unsigned long)OMAP_UART1_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART1_BASE),
+               .mapbase        = OMAP_UART1_BASE,
                .irq            = INT_UART1,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
@@ -76,8 +76,8 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .uartclk        = OMAP16XX_BASE_BAUD * 16,
        },
        {
-               .membase        = (char*)IO_ADDRESS(OMAP_UART2_BASE),
-               .mapbase        = (unsigned long)OMAP_UART2_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART2_BASE),
+               .mapbase        = OMAP_UART2_BASE,
                .irq            = INT_UART2,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
@@ -85,8 +85,8 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .uartclk        = OMAP16XX_BASE_BAUD * 16,
        },
        {
-               .membase        = (char*)IO_ADDRESS(OMAP_UART3_BASE),
-               .mapbase        = (unsigned long)OMAP_UART3_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART3_BASE),
+               .mapbase        = OMAP_UART3_BASE,
                .irq            = INT_UART3,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
index 7069c9d536f1b07ad07460a9909cb050be8d013c..4832fcc7d04a14be864b663590aaf6b2b1258abb 100644 (file)
@@ -15,8 +15,17 @@ config ARCH_OMAP2430
        bool "OMAP2430 support"
        depends on ARCH_OMAP24XX
 
+config ARCH_OMAP34XX
+       bool "OMAP34xx Based System"
+       depends on ARCH_OMAP3
+
+config ARCH_OMAP3430
+       bool "OMAP3430 support"
+       depends on ARCH_OMAP3 && ARCH_OMAP34XX
+       select ARCH_OMAP_OTG
+
 comment "OMAP Board Type"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2 || ARCH_OMAP3
 
 config MACH_OMAP_GENERIC
        bool "Generic OMAP board"
@@ -35,3 +44,14 @@ config MACH_OMAP_2430SDP
        bool "OMAP 2430 SDP board"
        depends on ARCH_OMAP2 && ARCH_OMAP24XX
 
+config MACH_OMAP3_BEAGLE
+       bool "OMAP3 BEAGLE board"
+       depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OMAP_LDP
+       bool "OMAP3 LDP board"
+       depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OVERO
+       bool "Gumstix Overo board"
+       depends on ARCH_OMAP3 && ARCH_OMAP34XX
index 93ee990618ef32b0905dd5de7bc515aa5a70c14d..c69392372c99890f9c50f96e5c7a556b5bef98a6 100644 (file)
@@ -4,16 +4,21 @@
 
 # Common support
 obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \
-               devices.o serial.o gpmc.o timer-gp.o
+               devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
+               clockdomain.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
 # Functions loaded to SRAM
 obj-$(CONFIG_ARCH_OMAP2420)            += sram242x.o
 obj-$(CONFIG_ARCH_OMAP2430)            += sram243x.o
+obj-$(CONFIG_ARCH_OMAP3)               += sram34xx.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
+ifeq ($(CONFIG_PM),y)
+obj-y                                  += pm.o
+obj-$(CONFIG_ARCH_OMAP24XX)            += sleep24xx.o
+endif
 
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)               += clock24xx.o
@@ -24,4 +29,7 @@ obj-$(CONFIG_MACH_OMAP_GENERIC)               += board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)             += board-h4.o
 obj-$(CONFIG_MACH_OMAP_2430SDP)                += board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)                += board-apollon.o
+obj-$(CONFIG_MACH_OMAP3_BEAGLE)                += board-omap3beagle.o
+obj-$(CONFIG_MACH_OMAP_LDP)            += board-ldp.o
+obj-$(CONFIG_MACH_OVERO)               += board-overo.o
 
index d4e3b6fc4705fe9335835911a13828ecc5fbfae7..2fef2c84508390daa193ef4e9c189872c44d91aa 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -391,6 +392,13 @@ static struct omap_board_config_kernel h4_config[] = {
        { OMAP_TAG_LCD,         &h4_lcd_config },
 };
 
+static struct i2c_board_info __initdata h4_i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("isp1301_omap", 0x2d),
+               .irq            = OMAP_GPIO_IRQ(125),
+       },
+};
+
 static void __init omap_h4_init(void)
 {
        /*
@@ -411,6 +419,9 @@ static void __init omap_h4_init(void)
        }
 #endif
 
+       i2c_register_board_info(1, h4_i2c_board_info,
+                       ARRAY_SIZE(h4_i2c_board_info));
+
        platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
        omap_board_config = h4_config;
        omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
new file mode 100644 (file)
index 0000000..1ea5998
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * linux/arch/arm/mach-omap2/board-ldp.c
+ *
+ * Copyright (C) 2008 Texas Instruments Inc.
+ * Nishant Kamat <nskamat@ti.com>
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * This program is free software; you can 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/board-ldp.h>
+#include <mach/mcspi.h>
+#include <mach/gpio.h>
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/gpmc.h>
+
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <mach/control.h>
+
+static void __init omap_ldp_init_irq(void)
+{
+       omap2_init_common_hw();
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct omap_uart_config ldp_uart_config __initdata = {
+       .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel ldp_config[] __initdata = {
+       { OMAP_TAG_UART,        &ldp_uart_config },
+};
+
+static int __init omap_i2c_init(void)
+{
+       omap_register_i2c_bus(1, 2600, NULL, 0);
+       omap_register_i2c_bus(2, 400, NULL, 0);
+       omap_register_i2c_bus(3, 400, NULL, 0);
+       return 0;
+}
+
+static void __init omap_ldp_init(void)
+{
+       omap_i2c_init();
+       omap_board_config = ldp_config;
+       omap_board_config_size = ARRAY_SIZE(ldp_config);
+       omap_serial_init();
+}
+
+static void __init omap_ldp_map_io(void)
+{
+       omap2_set_globals_343x();
+       omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_LDP, "OMAP LDP board")
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = omap_ldp_map_io,
+       .init_irq       = omap_ldp_init_irq,
+       .init_machine   = omap_ldp_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
new file mode 100644 (file)
index 0000000..baa7967
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3beagle.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/gpmc.h>
+#include <mach/nand.h>
+
+
+#define GPMC_CS0_BASE  0x60
+#define GPMC_CS_SIZE   0x30
+
+#define NAND_BLOCK_SIZE                SZ_128K
+
+static struct mtd_partition omap3beagle_nand_partitions[] = {
+       /* All the partition sizes are listed in terms of NAND block size */
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 4 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
+               .size           = 15 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "U-Boot Env",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
+               .size           = 1 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .size           = 32 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "File System",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_nand_platform_data omap3beagle_nand_data = {
+       .options        = NAND_BUSWIDTH_16,
+       .parts          = omap3beagle_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(omap3beagle_nand_partitions),
+       .dma_channel    = -1,           /* disable DMA in OMAP NAND driver */
+       .nand_setup     = NULL,
+       .dev_ready      = NULL,
+};
+
+static struct resource omap3beagle_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device omap3beagle_nand_device = {
+       .name           = "omap2-nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &omap3beagle_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &omap3beagle_nand_resource,
+};
+
+static struct omap_uart_config omap3_beagle_uart_config __initdata = {
+       .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static void __init omap3_beagle_init_irq(void)
+{
+       omap2_init_common_hw();
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct platform_device omap3_beagle_lcd_device = {
+       .name           = "omap3beagle_lcd",
+       .id             = -1,
+};
+
+static struct omap_lcd_config omap3_beagle_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct gpio_led gpio_leds[] = {
+       {
+               .name                   = "beagleboard::usr0",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 150,
+       },
+       {
+               .name                   = "beagleboard::usr1",
+               .default_trigger        = "mmc0",
+               .gpio                   = 149,
+       },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_led_info,
+       },
+};
+
+static struct gpio_keys_button gpio_buttons[] = {
+       {
+               .code                   = BTN_EXTRA,
+               .gpio                   = 7,
+               .desc                   = "user",
+               .wakeup                 = 1,
+       },
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+       .buttons        = gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device keys_gpio = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_key_info,
+       },
+};
+
+static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+       { OMAP_TAG_UART,        &omap3_beagle_uart_config },
+       { OMAP_TAG_LCD,         &omap3_beagle_lcd_config },
+};
+
+static struct platform_device *omap3_beagle_devices[] __initdata = {
+       &omap3_beagle_lcd_device,
+       &leds_gpio,
+       &keys_gpio,
+};
+
+static void __init omap3beagle_flash_init(void)
+{
+       u8 cs = 0;
+       u8 nandcs = GPMC_CS_NUM + 1;
+
+       u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+       /* find out the chip-select on which NAND exists */
+       while (cs < GPMC_CS_NUM) {
+               u32 ret = 0;
+               ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               if ((ret & 0xC00) == 0x800) {
+                       printk(KERN_INFO "Found NAND on CS%d\n", cs);
+                       if (nandcs > GPMC_CS_NUM)
+                               nandcs = cs;
+               }
+               cs++;
+       }
+
+       if (nandcs > GPMC_CS_NUM) {
+               printk(KERN_INFO "NAND: Unable to find configuration "
+                                "in GPMC\n ");
+               return;
+       }
+
+       if (nandcs < GPMC_CS_NUM) {
+               omap3beagle_nand_data.cs = nandcs;
+               omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
+                       (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
+               omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
+
+               printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+               if (platform_device_register(&omap3beagle_nand_device) < 0)
+                       printk(KERN_ERR "Unable to register NAND device\n");
+       }
+}
+
+static void __init omap3_beagle_init(void)
+{
+       platform_add_devices(omap3_beagle_devices,
+                       ARRAY_SIZE(omap3_beagle_devices));
+       omap_board_config = omap3_beagle_config;
+       omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+       omap_serial_init();
+       omap3beagle_flash_init();
+}
+
+static void __init omap3_beagle_map_io(void)
+{
+       omap2_set_globals_343x();
+       omap2_map_common_io();
+}
+
+MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+       /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_beagle_map_io,
+       .init_irq       = omap3_beagle_init_irq,
+       .init_machine   = omap3_beagle_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
new file mode 100644 (file)
index 0000000..e09aa59
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * board-overo.c (Gumstix Overo)
+ *
+ * Initial code: Steve Sakoman <steve@sakoman.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+
+#include <mach/board-overo.h>
+#include <mach/board.h>
+#include <mach/common.h>
+#include <mach/gpio.h>
+#include <mach/gpmc.h>
+#include <mach/hardware.h>
+#include <mach/nand.h>
+
+#define NAND_BLOCK_SIZE SZ_128K
+#define GPMC_CS0_BASE  0x60
+#define GPMC_CS_SIZE   0x30
+
+static struct mtd_partition overo_nand_partitions[] = {
+       {
+               .name           = "xloader",
+               .offset         = 0,                    /* Offset = 0x00000 */
+               .size           = 4 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "uboot",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
+               .size           = 14 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "uboot environment",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x240000 */
+               .size           = 2 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "linux",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .size           = 32 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "rootfs",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_nand_platform_data overo_nand_data = {
+       .parts = overo_nand_partitions,
+       .nr_parts = ARRAY_SIZE(overo_nand_partitions),
+       .dma_channel = -1,      /* disable DMA in OMAP NAND driver */
+};
+
+static struct resource overo_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device overo_nand_device = {
+       .name           = "omap2-nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &overo_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &overo_nand_resource,
+};
+
+
+static void __init overo_flash_init(void)
+{
+       u8 cs = 0;
+       u8 nandcs = GPMC_CS_NUM + 1;
+
+       u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+       /* find out the chip-select on which NAND exists */
+       while (cs < GPMC_CS_NUM) {
+               u32 ret = 0;
+               ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               if ((ret & 0xC00) == 0x800) {
+                       printk(KERN_INFO "Found NAND on CS%d\n", cs);
+                       if (nandcs > GPMC_CS_NUM)
+                               nandcs = cs;
+               }
+               cs++;
+       }
+
+       if (nandcs > GPMC_CS_NUM) {
+               printk(KERN_INFO "NAND: Unable to find configuration "
+                                "in GPMC\n ");
+               return;
+       }
+
+       if (nandcs < GPMC_CS_NUM) {
+               overo_nand_data.cs = nandcs;
+               overo_nand_data.gpmc_cs_baseaddr = (void *)
+                       (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
+               overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
+
+               printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+               if (platform_device_register(&overo_nand_device) < 0)
+                       printk(KERN_ERR "Unable to register NAND device\n");
+       }
+}
+static struct omap_uart_config overo_uart_config __initdata = {
+       .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static int __init overo_i2c_init(void)
+{
+       /* i2c2 pins are used for gpio */
+       omap_register_i2c_bus(3, 400, NULL, 0);
+       return 0;
+}
+
+static void __init overo_init_irq(void)
+{
+       omap2_init_common_hw();
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct platform_device overo_lcd_device = {
+       .name           = "overo_lcd",
+       .id             = -1,
+};
+
+static struct omap_lcd_config overo_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel overo_config[] __initdata = {
+       { OMAP_TAG_UART,        &overo_uart_config },
+       { OMAP_TAG_LCD,         &overo_lcd_config },
+};
+
+static struct platform_device *overo_devices[] __initdata = {
+       &overo_lcd_device,
+};
+
+static void __init overo_init(void)
+{
+       overo_i2c_init();
+       platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
+       omap_board_config = overo_config;
+       omap_board_config_size = ARRAY_SIZE(overo_config);
+       omap_serial_init();
+       overo_flash_init();
+
+       if ((gpio_request(OVERO_GPIO_W2W_NRESET,
+                         "OVERO_GPIO_W2W_NRESET") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_W2W_NRESET, 1) == 0)) {
+               gpio_export(OVERO_GPIO_W2W_NRESET, 0);
+               gpio_set_value(OVERO_GPIO_W2W_NRESET, 0);
+               udelay(10);
+               gpio_set_value(OVERO_GPIO_W2W_NRESET, 1);
+       } else {
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_W2W_NRESET\n");
+       }
+
+       if ((gpio_request(OVERO_GPIO_BT_XGATE, "OVERO_GPIO_BT_XGATE") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_BT_XGATE, 0) == 0))
+               gpio_export(OVERO_GPIO_BT_XGATE, 0);
+       else
+               printk(KERN_ERR "could not obtain gpio for OVERO_GPIO_BT_XGATE\n");
+
+       if ((gpio_request(OVERO_GPIO_BT_NRESET, "OVERO_GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_BT_NRESET, 1) == 0)) {
+               gpio_export(OVERO_GPIO_BT_NRESET, 0);
+               gpio_set_value(OVERO_GPIO_BT_NRESET, 0);
+               mdelay(6);
+               gpio_set_value(OVERO_GPIO_BT_NRESET, 1);
+       } else {
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_BT_NRESET\n");
+       }
+
+       if ((gpio_request(OVERO_GPIO_USBH_CPEN, "OVERO_GPIO_USBH_CPEN") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_USBH_CPEN, 1) == 0))
+               gpio_export(OVERO_GPIO_USBH_CPEN, 0);
+       else
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_USBH_CPEN\n");
+
+       if ((gpio_request(OVERO_GPIO_USBH_NRESET,
+                         "OVERO_GPIO_USBH_NRESET") == 0) &&
+           (gpio_direction_output(OVERO_GPIO_USBH_NRESET, 1) == 0))
+               gpio_export(OVERO_GPIO_USBH_NRESET, 0);
+       else
+               printk(KERN_ERR "could not obtain gpio for "
+                                       "OVERO_GPIO_USBH_NRESET\n");
+}
+
+static void __init overo_map_io(void)
+{
+       omap2_set_globals_343x();
+       omap2_map_common_io();
+}
+
+MACHINE_START(OVERO, "Gumstix Overo")
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = overo_map_io,
+       .init_irq       = overo_init_irq,
+       .init_machine   = overo_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 97cde3d3611dede6c2f67b0091f8a0c4ce76db55..ad721e0cbf7a1ded6c54ab2212efb4a5da1f281e 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/bitops.h>
 
 #include <mach/clock.h>
+#include <mach/clockdomain.h>
 #include <mach/sram.h>
 #include <mach/cpu.h>
 #include <asm/div64.h>
 u8 cpu_mask;
 
 /*-------------------------------------------------------------------------
- * Omap2 specific clock functions
+ * OMAP2/3 specific clock functions
  *-------------------------------------------------------------------------*/
 
+/**
+ * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
+ * @clk: OMAP clock struct ptr to use
+ *
+ * Convert a clockdomain name stored in a struct clk 'clk' into a
+ * clockdomain pointer, and save it into the struct clk.  Intended to be
+ * called during clk_register().  No return value.
+ */
+void omap2_init_clk_clkdm(struct clk *clk)
+{
+       struct clockdomain *clkdm;
+
+       if (!clk->clkdm_name)
+               return;
+
+       clkdm = clkdm_lookup(clk->clkdm_name);
+       if (clkdm) {
+               pr_debug("clock: associated clk %s to clkdm %s\n",
+                        clk->name, clk->clkdm_name);
+               clk->clkdm = clkdm;
+       } else {
+               pr_debug("clock: could not associate clk %s to "
+                        "clkdm %s\n", clk->name, clk->clkdm_name);
+       }
+}
+
 /**
  * omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
  * @clk: OMAP clock struct ptr to use
@@ -250,7 +277,7 @@ int _omap2_clk_enable(struct clk *clk)
        if (clk->enable)
                return clk->enable(clk);
 
-       if (unlikely(clk->enable_reg == 0)) {
+       if (unlikely(clk->enable_reg == NULL)) {
                printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
                       clk->name);
                return 0; /* REVISIT: -EINVAL */
@@ -282,7 +309,7 @@ void _omap2_clk_disable(struct clk *clk)
                return;
        }
 
-       if (clk->enable_reg == 0) {
+       if (clk->enable_reg == NULL) {
                /*
                 * 'Independent' here refers to a clock which is not
                 * controlled by its parent.
@@ -307,6 +334,9 @@ void omap2_clk_disable(struct clk *clk)
                _omap2_clk_disable(clk);
                if (likely((u32)clk->parent))
                        omap2_clk_disable(clk->parent);
+               if (clk->clkdm)
+                       omap2_clkdm_clk_disable(clk->clkdm, clk);
+
        }
 }
 
@@ -323,11 +353,19 @@ int omap2_clk_enable(struct clk *clk)
                        return ret;
                }
 
+               if (clk->clkdm)
+                       omap2_clkdm_clk_enable(clk->clkdm, clk);
+
                ret = _omap2_clk_enable(clk);
 
-               if (unlikely(ret != 0) && clk->parent) {
-                       omap2_clk_disable(clk->parent);
-                       clk->usecount--;
+               if (unlikely(ret != 0)) {
+                       if (clk->clkdm)
+                               omap2_clkdm_clk_disable(clk->clkdm, clk);
+
+                       if (clk->parent) {
+                               omap2_clk_disable(clk->parent);
+                               clk->usecount--;
+                       }
                }
        }
 
@@ -476,7 +514,7 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
 /* Given a clock and a rate apply a clock specific rounding function */
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       if (clk->round_rate != 0)
+       if (clk->round_rate != NULL)
                return clk->round_rate(clk, rate);
 
        if (clk->flags & RATE_FIXED)
@@ -565,7 +603,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
  */
 void __iomem *omap2_get_clksel(struct clk *clk, u32 *field_mask)
 {
-       if (unlikely((clk->clksel_reg == 0) || (clk->clksel_mask == 0)))
+       if (unlikely((clk->clksel_reg == NULL) || (clk->clksel_mask == NULL)))
                return NULL;
 
        *field_mask = clk->clksel_mask;
@@ -585,7 +623,7 @@ u32 omap2_clksel_get_divisor(struct clk *clk)
        void __iomem *div_addr;
 
        div_addr = omap2_get_clksel(clk, &field_mask);
-       if (div_addr == 0)
+       if (div_addr == NULL)
                return 0;
 
        field_val = __raw_readl(div_addr) & field_mask;
@@ -604,7 +642,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
                return -EINVAL;
 
        div_addr = omap2_get_clksel(clk, &field_mask);
-       if (div_addr == 0)
+       if (div_addr == NULL)
                return -EINVAL;
 
        field_val = omap2_divisor_to_clksel(clk, new_div);
@@ -642,7 +680,7 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
                return -EINVAL;
 
        /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
-       if (clk->set_rate != 0)
+       if (clk->set_rate != NULL)
                ret = clk->set_rate(clk, rate);
 
        if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
@@ -663,7 +701,7 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
        const struct clksel_rate *clkr;
 
        *parent_div = 0;
-       *src_addr = 0;
+       *src_addr = NULL;
 
        clks = omap2_get_clksel_by_parent(clk, src_clk);
        if (clks == NULL)
@@ -704,7 +742,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 
        field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
                                               &field_mask, clk, &parent_div);
-       if (src_addr == 0)
+       if (src_addr == NULL)
                return -EINVAL;
 
        if (clk->usecount > 0)
index 626e5fa93b6ad3a9fd6e79164d9092dc29c4935d..1fb330e0847d868bb6ac76fb6de806c1b20a93b7 100644 (file)
@@ -21,6 +21,7 @@
 /* The maximum error between a target DPLL rate and the rounded rate in Hz */
 #define DEFAULT_DPLL_RATE_TOLERANCE    50000
 
+int omap2_clk_init(void);
 int omap2_clk_enable(struct clk *clk);
 void omap2_clk_disable(struct clk *clk);
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
@@ -36,6 +37,7 @@ void omap2_clk_disable_unused(struct clk *clk);
 #endif
 
 void omap2_clksel_recalc(struct clk *clk);
+void omap2_init_clk_clkdm(struct clk *clk);
 void omap2_init_clksel_parent(struct clk *clk);
 u32 omap2_clksel_get_divisor(struct clk *clk);
 u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
index be4e25554e05dfe0ad608a837f763164bf3275df..242a19d86ccd025f1a36d6baede741e0a7b5d03c 100644 (file)
@@ -626,6 +626,7 @@ static struct clk func_32k_ck = {
        .rate           = 32000,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &propagate_rate,
 };
 
@@ -634,17 +635,19 @@ static struct clk osc_ck = {              /* (*12, *13, 19.2, *26, 38.4)MHz */
        .name           = "osc_ck",
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .enable         = &omap2_enable_osc_ck,
        .disable        = &omap2_disable_osc_ck,
        .recalc         = &omap2_osc_clk_recalc,
 };
 
-/* With out modem likely 12MHz, with modem likely 13MHz */
+/* Without modem likely 12MHz, with modem likely 13MHz */
 static struct clk sys_ck = {           /* (*12, *13, 19.2, 26, 38.4)MHz */
        .name           = "sys_ck",             /* ~ ref_clk also */
        .parent         = &osc_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                ALWAYS_ENABLED | RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &omap2_sys_clk_recalc,
 };
 
@@ -653,6 +656,7 @@ static struct clk alt_ck = {                /* Typical 54M or 48M, may not exist */
        .rate           = 54000000,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &propagate_rate,
 };
 
@@ -684,6 +688,7 @@ static struct clk dpll_ck = {
        .dpll_data      = &dpll_dd,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &omap2_dpllcore_recalc,
        .set_rate       = &omap2_reprogram_dpllcore,
 };
@@ -694,6 +699,7 @@ static struct clk apll96_ck = {
        .rate           = 96000000,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_bit     = OMAP24XX_EN_96M_PLL_SHIFT,
        .enable         = &omap2_clk_fixed_enable,
@@ -707,6 +713,7 @@ static struct clk apll54_ck = {
        .rate           = 54000000,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_FIXED | RATE_PROPAGATES | ENABLE_ON_INIT,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_bit     = OMAP24XX_EN_54M_PLL_SHIFT,
        .enable         = &omap2_clk_fixed_enable,
@@ -741,6 +748,7 @@ static struct clk func_54m_ck = {
        .parent         = &apll54_ck,   /* can also be alt_clk */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
        .clksel_mask    = OMAP24XX_54M_SOURCE,
@@ -753,6 +761,7 @@ static struct clk core_ck = {
        .parent         = &dpll_ck,             /* can also be 32k */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                ALWAYS_ENABLED | RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -779,6 +788,7 @@ static struct clk func_96m_ck = {
        .parent         = &apll96_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
        .clksel_mask    = OMAP2430_96M_SOURCE,
@@ -811,6 +821,7 @@ static struct clk func_48m_ck = {
        .parent         = &apll96_ck,    /* 96M or Alt */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
        .clksel_mask    = OMAP24XX_48M_SOURCE,
@@ -826,6 +837,7 @@ static struct clk func_12m_ck = {
        .fixed_div      = 4,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &omap2_fixed_divisor_recalc,
 };
 
@@ -878,6 +890,7 @@ static struct clk sys_clkout_src = {
        .parent         = &func_54m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP24XX_PRCM_CLKOUT_CTRL,
        .enable_bit     = OMAP24XX_CLKOUT_EN_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -908,6 +921,7 @@ static struct clk sys_clkout = {
        .parent         = &sys_clkout_src,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .clksel_reg     = OMAP24XX_PRCM_CLKOUT_CTRL,
        .clksel_mask    = OMAP24XX_CLKOUT_DIV_MASK,
        .clksel         = sys_clkout_clksel,
@@ -921,6 +935,7 @@ static struct clk sys_clkout2_src = {
        .name           = "sys_clkout2_src",
        .parent         = &func_54m_ck,
        .flags          = CLOCK_IN_OMAP242X | RATE_PROPAGATES,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP24XX_PRCM_CLKOUT_CTRL,
        .enable_bit     = OMAP2420_CLKOUT2_EN_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -942,6 +957,7 @@ static struct clk sys_clkout2 = {
        .name           = "sys_clkout2",
        .parent         = &sys_clkout2_src,
        .flags          = CLOCK_IN_OMAP242X | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "wkup_clkdm",
        .clksel_reg     = OMAP24XX_PRCM_CLKOUT_CTRL,
        .clksel_mask    = OMAP2420_CLKOUT2_DIV_MASK,
        .clksel         = sys_clkout2_clksel,
@@ -954,6 +970,7 @@ static struct clk emul_ck = {
        .name           = "emul_ck",
        .parent         = &func_54m_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP24XX_PRCM_CLKEMUL_CTRL,
        .enable_bit     = OMAP24XX_EMULATION_EN_SHIFT,
        .recalc         = &followparent_recalc,
@@ -990,12 +1007,13 @@ static struct clk mpu_ck = {     /* Control cpu */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                ALWAYS_ENABLED | DELAYED_APP |
                                CONFIG_PARTICIPANT | RATE_PROPAGATES,
+       .clkdm_name     = "mpu_clkdm",
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL),
        .clksel_mask    = OMAP24XX_CLKSEL_MPU_MASK,
        .clksel         = mpu_clksel,
        .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
+       .round_rate     = &omap2_clksel_round_rate,
        .set_rate       = &omap2_clksel_set_rate
 };
 
@@ -1031,6 +1049,7 @@ static struct clk dsp_fck = {
        .parent         = &core_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | DELAYED_APP |
                                CONFIG_PARTICIPANT | RATE_PROPAGATES,
+       .clkdm_name     = "dsp_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1054,10 +1073,7 @@ static const struct clksel dsp_irate_ick_clksel[] = {
        { .parent = NULL }
 };
 
-/*
- * This clock does not exist as such in the TRM, but is added to
- * separate source selection from  XXX
- */
+/* This clock does not exist as such in the TRM. */
 static struct clk dsp_irate_ick = {
        .name           = "dsp_irate_ick",
        .parent         = &dsp_fck,
@@ -1089,11 +1105,17 @@ static struct clk iva2_1_ick = {
        .enable_bit     = OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
 };
 
+/*
+ * The IVA1 is an ARM7 core on the 2420 that has nothing to do with
+ * the C54x, but which is contained in the DSP powerdomain.  Does not
+ * exist on later OMAPs.
+ */
 static struct clk iva1_ifck = {
        .name           = "iva1_ifck",
        .parent         = &core_ck,
        .flags          = CLOCK_IN_OMAP242X | CONFIG_PARTICIPANT |
                                RATE_PROPAGATES | DELAYED_APP,
+       .clkdm_name     = "iva1_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP2420_EN_IVA_COP_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
@@ -1109,6 +1131,7 @@ static struct clk iva1_mpu_int_ifck = {
        .name           = "iva1_mpu_int_ifck",
        .parent         = &iva1_ifck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "iva1_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP2420_EN_IVA_MPU_SHIFT,
        .fixed_div      = 2,
@@ -1156,6 +1179,7 @@ static struct clk core_l3_ck = {  /* Used for ick and fck, interconnect */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                ALWAYS_ENABLED | DELAYED_APP |
                                CONFIG_PARTICIPANT | RATE_PROPAGATES,
+       .clkdm_name     = "core_l3_clkdm",
        .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
        .clksel_mask    = OMAP24XX_CLKSEL_L3_MASK,
        .clksel         = core_l3_clksel,
@@ -1177,11 +1201,13 @@ static const struct clksel usb_l4_ick_clksel[] = {
        { .parent = NULL },
 };
 
+/* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {       /* FS-USB interface clock */
        .name           = "usb_l4_ick",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                DELAYED_APP | CONFIG_PARTICIPANT,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP24XX_EN_USB_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1192,11 +1218,43 @@ static struct clk usb_l4_ick = {        /* FS-USB interface clock */
        .set_rate       = &omap2_clksel_set_rate
 };
 
+/*
+ * L4 clock management domain
+ *
+ * This domain contains lots of interface clocks from the L4 interface, some
+ * functional clocks.  Fixed APLL functional source clocks are managed in
+ * this domain.
+ */
+static const struct clksel_rate l4_core_l3_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
+       { .div = 2, .val = 2, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel l4_clksel[] = {
+       { .parent = &core_l3_ck, .rates = l4_core_l3_rates },
+       { .parent = NULL }
+};
+
+static struct clk l4_ck = {            /* used both as an ick and fck */
+       .name           = "l4_ck",
+       .parent         = &core_l3_ck,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
+       .clkdm_name     = "core_l4_clkdm",
+       .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
+       .clksel_mask    = OMAP24XX_CLKSEL_L4_MASK,
+       .clksel         = l4_clksel,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate
+};
+
 /*
  * SSI is in L3 management domain, its direct parent is core not l3,
  * many core power domain entities are grouped into the L3 clock
  * domain.
- * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_CLIK
+ * SSI_SSR_FCLK, SSI_SST_FCLK, SSI_L4_ICLK
  *
  * ssr = core/1/2/3/4/5, sst = 1/2 ssr.
  */
@@ -1221,6 +1279,7 @@ static struct clk ssi_ssr_sst_fck = {
        .parent         = &core_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                DELAYED_APP,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP24XX_EN_SSI_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
@@ -1231,6 +1290,7 @@ static struct clk ssi_ssr_sst_fck = {
        .set_rate       = &omap2_clksel_set_rate
 };
 
+
 /*
  * GFX clock domain
  *     Clocks:
@@ -1254,6 +1314,7 @@ static struct clk gfx_3d_fck = {
        .name           = "gfx_3d_fck",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "gfx_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_EN_3D_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1268,6 +1329,7 @@ static struct clk gfx_2d_fck = {
        .name           = "gfx_2d_fck",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "gfx_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_EN_2D_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
@@ -1282,6 +1344,7 @@ static struct clk gfx_ick = {
        .name           = "gfx_ick",            /* From l3 */
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "gfx_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
        .enable_bit     = OMAP_EN_GFX_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1311,6 +1374,7 @@ static struct clk mdm_ick = {             /* used both as a ick and fck */
        .name           = "mdm_ick",
        .parent         = &core_ck,
        .flags          = CLOCK_IN_OMAP243X | DELAYED_APP | CONFIG_PARTICIPANT,
+       .clkdm_name     = "mdm_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
        .enable_bit     = OMAP2430_CM_ICLKEN_MDM_EN_MDM_SHIFT,
        .clksel_reg     = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_CLKSEL),
@@ -1325,51 +1389,12 @@ static struct clk mdm_osc_ck = {
        .name           = "mdm_osc_ck",
        .parent         = &osc_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "mdm_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
        .enable_bit     = OMAP2430_EN_OSC_SHIFT,
        .recalc         = &followparent_recalc,
 };
 
-/*
- * L4 clock management domain
- *
- * This domain contains lots of interface clocks from the L4 interface, some
- * functional clocks.  Fixed APLL functional source clocks are managed in
- * this domain.
- */
-static const struct clksel_rate l4_core_l3_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_24XX | DEFAULT_RATE },
-       { .div = 2, .val = 2, .flags = RATE_IN_24XX },
-       { .div = 0 }
-};
-
-static const struct clksel l4_clksel[] = {
-       { .parent = &core_l3_ck, .rates = l4_core_l3_rates },
-       { .parent = NULL }
-};
-
-static struct clk l4_ck = {            /* used both as an ick and fck */
-       .name           = "l4_ck",
-       .parent         = &core_l3_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
-                               ALWAYS_ENABLED | DELAYED_APP | RATE_PROPAGATES,
-       .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1),
-       .clksel_mask    = OMAP24XX_CLKSEL_L4_MASK,
-       .clksel         = l4_clksel,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate
-};
-
-static struct clk ssi_l4_ick = {
-       .name           = "ssi_l4_ick",
-       .parent         = &l4_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
-       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
-       .enable_bit     = OMAP24XX_EN_SSI_SHIFT,
-       .recalc         = &followparent_recalc,
-};
-
 /*
  * DSS clock domain
  * CLOCKs:
@@ -1409,6 +1434,7 @@ static struct clk dss_ick = {             /* Enables both L3,L4 ICLK's */
        .name           = "dss_ick",
        .parent         = &l4_ck,       /* really both l3 and l4 */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "dss_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_DSS1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1419,6 +1445,7 @@ static struct clk dss1_fck = {
        .parent         = &core_ck,             /* Core or sys */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                DELAYED_APP,
+       .clkdm_name     = "dss_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_DSS1_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1451,6 +1478,7 @@ static struct clk dss2_fck = {            /* Alt clk used in power management */
        .parent         = &sys_ck,              /* fixed at sys_ck or 48MHz */
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
                                DELAYED_APP,
+       .clkdm_name     = "dss_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_DSS2_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1464,6 +1492,7 @@ static struct clk dss_54m_fck = { /* Alt clk used in power management */
        .name           = "dss_54m_fck",        /* 54m tv clk */
        .parent         = &func_54m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "dss_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_TV_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1491,6 +1520,7 @@ static struct clk gpt1_ick = {
        .name           = "gpt1_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_GPT1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1500,6 +1530,7 @@ static struct clk gpt1_fck = {
        .name           = "gpt1_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_EN_GPT1_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1515,6 +1546,7 @@ static struct clk gpt2_ick = {
        .name           = "gpt2_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1524,6 +1556,7 @@ static struct clk gpt2_fck = {
        .name           = "gpt2_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT2_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1537,6 +1570,7 @@ static struct clk gpt3_ick = {
        .name           = "gpt3_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1546,6 +1580,7 @@ static struct clk gpt3_fck = {
        .name           = "gpt3_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT3_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1559,6 +1594,7 @@ static struct clk gpt4_ick = {
        .name           = "gpt4_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT4_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1568,6 +1604,7 @@ static struct clk gpt4_fck = {
        .name           = "gpt4_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT4_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1581,6 +1618,7 @@ static struct clk gpt5_ick = {
        .name           = "gpt5_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT5_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1590,6 +1628,7 @@ static struct clk gpt5_fck = {
        .name           = "gpt5_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT5_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1603,6 +1642,7 @@ static struct clk gpt6_ick = {
        .name           = "gpt6_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT6_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1612,6 +1652,7 @@ static struct clk gpt6_fck = {
        .name           = "gpt6_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT6_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1634,6 +1675,7 @@ static struct clk gpt7_fck = {
        .name           = "gpt7_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT7_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1647,6 +1689,7 @@ static struct clk gpt8_ick = {
        .name           = "gpt8_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT8_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1656,6 +1699,7 @@ static struct clk gpt8_fck = {
        .name           = "gpt8_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT8_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1669,6 +1713,7 @@ static struct clk gpt9_ick = {
        .name           = "gpt9_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT9_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1678,6 +1723,7 @@ static struct clk gpt9_fck = {
        .name           = "gpt9_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT9_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1691,6 +1737,7 @@ static struct clk gpt10_ick = {
        .name           = "gpt10_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT10_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1700,6 +1747,7 @@ static struct clk gpt10_fck = {
        .name           = "gpt10_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT10_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1713,6 +1761,7 @@ static struct clk gpt11_ick = {
        .name           = "gpt11_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT11_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1722,6 +1771,7 @@ static struct clk gpt11_fck = {
        .name           = "gpt11_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT11_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1735,6 +1785,7 @@ static struct clk gpt12_ick = {
        .name           = "gpt12_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT12_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1744,6 +1795,7 @@ static struct clk gpt12_fck = {
        .name           = "gpt12_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_GPT12_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -1758,6 +1810,7 @@ static struct clk mcbsp1_ick = {
        .id             = 1,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1768,6 +1821,7 @@ static struct clk mcbsp1_fck = {
        .id             = 1,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1778,6 +1832,7 @@ static struct clk mcbsp2_ick = {
        .id             = 2,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1788,6 +1843,7 @@ static struct clk mcbsp2_fck = {
        .id             = 2,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1798,6 +1854,7 @@ static struct clk mcbsp3_ick = {
        .id             = 3,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1808,6 +1865,7 @@ static struct clk mcbsp3_fck = {
        .id             = 3,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1818,6 +1876,7 @@ static struct clk mcbsp4_ick = {
        .id             = 4,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP4_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1828,6 +1887,7 @@ static struct clk mcbsp4_fck = {
        .id             = 4,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP4_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1838,6 +1898,7 @@ static struct clk mcbsp5_ick = {
        .id             = 5,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP5_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1848,6 +1909,7 @@ static struct clk mcbsp5_fck = {
        .id             = 5,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP5_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1857,6 +1919,7 @@ static struct clk mcspi1_ick = {
        .name           = "mcspi_ick",
        .id             = 1,
        .parent         = &l4_ck,
+       .clkdm_name     = "core_l4_clkdm",
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MCSPI1_SHIFT,
@@ -1868,6 +1931,7 @@ static struct clk mcspi1_fck = {
        .id             = 1,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCSPI1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1878,6 +1942,7 @@ static struct clk mcspi2_ick = {
        .id             = 2,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MCSPI2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1888,6 +1953,7 @@ static struct clk mcspi2_fck = {
        .id             = 2,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCSPI2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1898,6 +1964,7 @@ static struct clk mcspi3_ick = {
        .id             = 3,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MCSPI3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1908,6 +1975,7 @@ static struct clk mcspi3_fck = {
        .id             = 3,
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCSPI3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1917,6 +1985,7 @@ static struct clk uart1_ick = {
        .name           = "uart1_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_UART1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1926,6 +1995,7 @@ static struct clk uart1_fck = {
        .name           = "uart1_fck",
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_UART1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1935,6 +2005,7 @@ static struct clk uart2_ick = {
        .name           = "uart2_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_UART2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1944,6 +2015,7 @@ static struct clk uart2_fck = {
        .name           = "uart2_fck",
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_UART2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1953,6 +2025,7 @@ static struct clk uart3_ick = {
        .name           = "uart3_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP24XX_EN_UART3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1962,6 +2035,7 @@ static struct clk uart3_fck = {
        .name           = "uart3_fck",
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP24XX_EN_UART3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1971,6 +2045,7 @@ static struct clk gpios_ick = {
        .name           = "gpios_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_GPIOS_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1980,6 +2055,7 @@ static struct clk gpios_fck = {
        .name           = "gpios_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_EN_GPIOS_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1989,6 +2065,7 @@ static struct clk mpu_wdt_ick = {
        .name           = "mpu_wdt_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_MPU_WDT_SHIFT,
        .recalc         = &followparent_recalc,
@@ -1998,6 +2075,7 @@ static struct clk mpu_wdt_fck = {
        .name           = "mpu_wdt_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "wkup_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP24XX_EN_MPU_WDT_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2006,31 +2084,40 @@ static struct clk mpu_wdt_fck = {
 static struct clk sync_32k_ick = {
        .name           = "sync_32k_ick",
        .parent         = &l4_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               ENABLE_ON_INIT,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_32KSYNC_SHIFT,
        .recalc         = &followparent_recalc,
 };
+
 static struct clk wdt1_ick = {
        .name           = "wdt1_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_WDT1_SHIFT,
        .recalc         = &followparent_recalc,
 };
+
 static struct clk omapctrl_ick = {
        .name           = "omapctrl_ick",
        .parent         = &l4_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               ENABLE_ON_INIT,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP24XX_EN_OMAPCTRL_SHIFT,
        .recalc         = &followparent_recalc,
 };
+
 static struct clk icr_ick = {
        .name           = "icr_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP2430_EN_ICR_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2040,15 +2127,22 @@ static struct clk cam_ick = {
        .name           = "cam_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_CAM_SHIFT,
        .recalc         = &followparent_recalc,
 };
 
+/*
+ * cam_fck controls both CAM_MCLK and CAM_FCLK.  It should probably be
+ * split into two separate clocks, since the parent clocks are different
+ * and the clockdomains are also different.
+ */
 static struct clk cam_fck = {
        .name           = "cam_fck",
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_CAM_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2058,6 +2152,7 @@ static struct clk mailboxes_ick = {
        .name           = "mailboxes_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MAILBOXES_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2067,6 +2162,7 @@ static struct clk wdt4_ick = {
        .name           = "wdt4_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_WDT4_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2076,6 +2172,7 @@ static struct clk wdt4_fck = {
        .name           = "wdt4_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_WDT4_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2085,6 +2182,7 @@ static struct clk wdt3_ick = {
        .name           = "wdt3_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_WDT3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2094,6 +2192,7 @@ static struct clk wdt3_fck = {
        .name           = "wdt3_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_WDT3_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2103,6 +2202,7 @@ static struct clk mspro_ick = {
        .name           = "mspro_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_MSPRO_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2112,6 +2212,7 @@ static struct clk mspro_fck = {
        .name           = "mspro_fck",
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MSPRO_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2121,6 +2222,7 @@ static struct clk mmc_ick = {
        .name           = "mmc_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_MMC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2130,6 +2232,7 @@ static struct clk mmc_fck = {
        .name           = "mmc_fck",
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_MMC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2139,6 +2242,7 @@ static struct clk fac_ick = {
        .name           = "fac_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_FAC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2148,6 +2252,7 @@ static struct clk fac_fck = {
        .name           = "fac_fck",
        .parent         = &func_12m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_FAC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2157,6 +2262,7 @@ static struct clk eac_ick = {
        .name           = "eac_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_EAC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2166,6 +2272,7 @@ static struct clk eac_fck = {
        .name           = "eac_fck",
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_EAC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2175,6 +2282,7 @@ static struct clk hdq_ick = {
        .name           = "hdq_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP24XX_EN_HDQ_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2184,6 +2292,7 @@ static struct clk hdq_fck = {
        .name           = "hdq_fck",
        .parent         = &func_12m_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_HDQ_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2194,6 +2303,7 @@ static struct clk i2c2_ick = {
        .id             = 2,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_I2C2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2204,6 +2314,7 @@ static struct clk i2c2_fck = {
        .id             = 2,
        .parent         = &func_12m_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_I2C2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2214,6 +2325,7 @@ static struct clk i2chs2_fck = {
        .id             = 2,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_I2CHS2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2224,6 +2336,7 @@ static struct clk i2c1_ick = {
        .id             = 1,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_I2C1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2234,6 +2347,7 @@ static struct clk i2c1_fck = {
        .id             = 1,
        .parent         = &func_12m_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_I2C1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2244,6 +2358,7 @@ static struct clk i2chs1_fck = {
        .id             = 1,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_I2CHS1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2252,7 +2367,9 @@ static struct clk i2chs1_fck = {
 static struct clk gpmc_fck = {
        .name           = "gpmc_fck",
        .parent         = &core_l3_ck,
-       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
+       .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
+                               ENABLE_ON_INIT,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2260,6 +2377,7 @@ static struct clk sdma_fck = {
        .name           = "sdma_fck",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2267,6 +2385,7 @@ static struct clk sdma_ick = {
        .name           = "sdma_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2274,6 +2393,7 @@ static struct clk vlynq_ick = {
        .name           = "vlynq_ick",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP2420_EN_VLYNQ_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2308,6 +2428,7 @@ static struct clk vlynq_fck = {
        .name           = "vlynq_fck",
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP242X | DELAYED_APP,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP2420_EN_VLYNQ_SHIFT,
        .init           = &omap2_init_clksel_parent,
@@ -2323,6 +2444,7 @@ static struct clk sdrc_ick = {
        .name           = "sdrc_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | ENABLE_ON_INIT,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
        .enable_bit     = OMAP2430_EN_SDRC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2332,6 +2454,7 @@ static struct clk des_ick = {
        .name           = "des_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
        .enable_bit     = OMAP24XX_EN_DES_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2341,6 +2464,7 @@ static struct clk sha_ick = {
        .name           = "sha_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
        .enable_bit     = OMAP24XX_EN_SHA_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2350,6 +2474,7 @@ static struct clk rng_ick = {
        .name           = "rng_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
        .enable_bit     = OMAP24XX_EN_RNG_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2359,6 +2484,7 @@ static struct clk aes_ick = {
        .name           = "aes_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
        .enable_bit     = OMAP24XX_EN_AES_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2368,6 +2494,7 @@ static struct clk pka_ick = {
        .name           = "pka_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
        .enable_bit     = OMAP24XX_EN_PKA_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2377,6 +2504,7 @@ static struct clk usb_fck = {
        .name           = "usb_fck",
        .parent         = &func_48m_ck,
        .flags          = CLOCK_IN_OMAP243X | CLOCK_IN_OMAP242X,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP24XX_EN_USB_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2386,6 +2514,7 @@ static struct clk usbhs_ick = {
        .name           = "usbhs_ick",
        .parent         = &core_l3_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_USBHS_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2396,6 +2525,7 @@ static struct clk mmchs1_ick = {
        .id             = 1,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MMCHS1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2406,6 +2536,7 @@ static struct clk mmchs1_fck = {
        .id             = 1,
        .parent         = &func_96m_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l3_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MMCHS1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2416,6 +2547,7 @@ static struct clk mmchs2_ick = {
        .id             = 2,
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MMCHS2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2435,6 +2567,7 @@ static struct clk gpio5_ick = {
        .name           = "gpio5_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_GPIO5_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2444,6 +2577,7 @@ static struct clk gpio5_fck = {
        .name           = "gpio5_fck",
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_GPIO5_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2453,6 +2587,7 @@ static struct clk mdm_intc_ick = {
        .name           = "mdm_intc_ick",
        .parent         = &l4_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
        .enable_bit     = OMAP2430_EN_MDM_INTC_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2463,6 +2598,7 @@ static struct clk mmchsdb1_fck = {
        .id             = 1,
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MMCHSDB1_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2473,6 +2609,7 @@ static struct clk mmchsdb2_fck = {
        .id             = 2,
        .parent         = &func_32k_ck,
        .flags          = CLOCK_IN_OMAP243X,
+       .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MMCHSDB2_SHIFT,
        .recalc         = &followparent_recalc,
@@ -2551,7 +2688,6 @@ static struct clk *onchip_24xx_clks[] __initdata = {
        &usb_l4_ick,
        /* L4 domain clocks */
        &l4_ck,                 /* used as both core_l4 and wu_l4 */
-       &ssi_l4_ick,
        /* virtual meta-group clock */
        &virt_prcm_set,
        /* general l4 interface ck, multi-parent functional clk */
index e5b475f21081d8848741114a61200a177787e6d7..084e11082f80c872ada5955a4e4a687a9fefdc0a 100644 (file)
@@ -62,11 +62,14 @@ static void omap3_dpll_recalc(struct clk *clk)
 static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
 {
        const struct dpll_data *dd;
+       u32 v;
 
        dd = clk->dpll_data;
 
-       cm_rmw_reg_bits(dd->enable_mask, clken_bits << __ffs(dd->enable_mask),
-                       dd->control_reg);
+       v = __raw_readl(dd->control_reg);
+       v &= ~dd->enable_mask;
+       v |= clken_bits << __ffs(dd->enable_mask);
+       __raw_writel(v, dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -82,7 +85,7 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
        state <<= dd->idlest_bit;
        idlest_mask = 1 << dd->idlest_bit;
 
-       while (((cm_read_reg(dd->idlest_reg) & idlest_mask) != state) &&
+       while (((__raw_readl(dd->idlest_reg) & idlest_mask) != state) &&
               i < MAX_DPLL_WAIT_TRIES) {
                i++;
                udelay(1);
@@ -285,7 +288,7 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk)
 
        dd = clk->dpll_data;
 
-       v = cm_read_reg(dd->autoidle_reg);
+       v = __raw_readl(dd->autoidle_reg);
        v &= dd->autoidle_mask;
        v >>= __ffs(dd->autoidle_mask);
 
@@ -304,6 +307,7 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk)
 static void omap3_dpll_allow_idle(struct clk *clk)
 {
        const struct dpll_data *dd;
+       u32 v;
 
        if (!clk || !clk->dpll_data)
                return;
@@ -315,9 +319,10 @@ static void omap3_dpll_allow_idle(struct clk *clk)
         * by writing 0x5 instead of 0x1.  Add some mechanism to
         * optionally enter this mode.
         */
-       cm_rmw_reg_bits(dd->autoidle_mask,
-                       DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask),
-                       dd->autoidle_reg);
+       v = __raw_readl(dd->autoidle_reg);
+       v &= ~dd->autoidle_mask;
+       v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
+       __raw_writel(v, dd->autoidle_reg);
 }
 
 /**
@@ -329,15 +334,17 @@ static void omap3_dpll_allow_idle(struct clk *clk)
 static void omap3_dpll_deny_idle(struct clk *clk)
 {
        const struct dpll_data *dd;
+       u32 v;
 
        if (!clk || !clk->dpll_data)
                return;
 
        dd = clk->dpll_data;
 
-       cm_rmw_reg_bits(dd->autoidle_mask,
-                       DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask),
-                       dd->autoidle_reg);
+       v = __raw_readl(dd->autoidle_reg);
+       v &= ~dd->autoidle_mask;
+       v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
+       __raw_writel(v, dd->autoidle_reg);
 }
 
 /* Clock control for DPLL outputs */
@@ -482,8 +489,10 @@ int __init omap2_clk_init(void)
        for (clkp = onchip_34xx_clks;
             clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
             clkp++) {
-               if ((*clkp)->flags & cpu_clkflg)
+               if ((*clkp)->flags & cpu_clkflg) {
                        clk_register(*clkp);
+                       omap2_init_clk_clkdm(*clkp);
+               }
        }
 
        /* REVISIT: Not yet ready for OMAP3 */
index ec664457a11a964b88b5f7cf8dd10d882f082588..c38a8a09692ff3748d24208eca1ee492fe967020 100644 (file)
@@ -478,7 +478,7 @@ static struct clk dpll3_m2_ck = {
 };
 
 static const struct clksel core_ck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
        { .parent = &dpll3_m2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -495,7 +495,7 @@ static struct clk core_ck = {
 };
 
 static const struct clksel dpll3_m2x2_ck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
        { .parent = &dpll3_x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -541,7 +541,7 @@ static struct clk dpll3_m3x2_ck = {
 };
 
 static const struct clksel emu_core_alwon_ck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -633,7 +633,7 @@ static struct clk dpll4_m2x2_ck = {
 };
 
 static const struct clksel omap_96m_alwon_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -659,7 +659,7 @@ static struct clk omap_96m_fck = {
 };
 
 static const struct clksel cm_96m_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -701,7 +701,7 @@ static struct clk dpll4_m3x2_ck = {
 };
 
 static const struct clksel virt_omap_54m_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -911,7 +911,7 @@ static struct clk dpll5_m2_ck = {
 };
 
 static const struct clksel omap_120m_fck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
        { .parent = &dpll5_m2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -919,13 +919,13 @@ static const struct clksel omap_120m_fck_clksel[] = {
 static struct clk omap_120m_fck = {
        .name           = "omap_120m_fck",
        .parent         = &dpll5_m2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
-       .clksel_mask    = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
-       .clksel         = omap_120m_fck_clksel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
+       .clksel_mask    = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
+       .clksel         = omap_120m_fck_clksel,
        .flags          = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 /* CM EXTERNAL CLOCK OUTPUTS */
@@ -1034,7 +1034,7 @@ static struct clk dpll1_fck = {
  * called 'dpll1_fck'
  */
 static const struct clksel mpu_clksel[] = {
-       { .parent = &dpll1_fck,     .rates = dpll_bypass_rates },
+       { .parent = &dpll1_fck,     .rates = dpll_bypass_rates },
        { .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -1048,6 +1048,7 @@ static struct clk mpu_ck = {
        .clksel         = mpu_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "mpu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1075,6 +1076,8 @@ static struct clk arm_fck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
+/* XXX What about neon_clkdm ? */
+
 /*
  * REVISIT: This clock is never specifically defined in the 3430 TRM,
  * although it is referenced - so this is a guess
@@ -1107,7 +1110,7 @@ static struct clk dpll2_fck = {
  */
 
 static const struct clksel iva2_clksel[] = {
-       { .parent = &dpll2_fck,   .rates = dpll_bypass_rates },
+       { .parent = &dpll2_fck,   .rates = dpll_bypass_rates },
        { .parent = &dpll2_m2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -1123,6 +1126,7 @@ static struct clk iva2_ck = {
        .clksel_mask    = OMAP3430_ST_IVA2_CLK_MASK,
        .clksel         = iva2_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+       .clkdm_name     = "iva2_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1137,6 +1141,7 @@ static struct clk l3_ick = {
        .clksel         = div2_core_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1154,6 +1159,7 @@ static struct clk l4_ick = {
        .clksel         = div2_l3_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 
 };
@@ -1183,43 +1189,57 @@ static const struct clksel gfx_l3_clksel[] = {
        { .parent = NULL }
 };
 
-static struct clk gfx_l3_fck = {
-       .name           = "gfx_l3_fck",
+/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */
+static struct clk gfx_l3_ck = {
+       .name           = "gfx_l3_ck",
        .parent         = &l3_ick,
        .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
        .enable_bit     = OMAP_EN_GFX_SHIFT,
+       .flags          = CLOCK_IN_OMAP3430ES1,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk gfx_l3_fck = {
+       .name           = "gfx_l3_fck",
+       .parent         = &gfx_l3_ck,
+       .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
        .clksel_mask    = OMAP_CLKSEL_GFX_MASK,
        .clksel         = gfx_l3_clksel,
-       .flags          = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES,
+       .flags          = CLOCK_IN_OMAP3430ES1 | RATE_PROPAGATES |
+                               PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "gfx_3430es1_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk gfx_l3_ick = {
        .name           = "gfx_l3_ick",
-       .parent         = &l3_ick,
-       .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_ICLKEN),
-       .enable_bit     = OMAP_EN_GFX_SHIFT,
-       .flags          = CLOCK_IN_OMAP3430ES1,
+       .parent         = &gfx_l3_ck,
+       .flags          = CLOCK_IN_OMAP3430ES1 | PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "gfx_3430es1_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk gfx_cg1_ck = {
        .name           = "gfx_cg1_ck",
        .parent         = &gfx_l3_fck, /* REVISIT: correct? */
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430ES1_EN_2D_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES1,
+       .clkdm_name     = "gfx_3430es1_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk gfx_cg2_ck = {
        .name           = "gfx_cg2_ck",
        .parent         = &gfx_l3_fck, /* REVISIT: correct? */
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(GFX_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430ES1_EN_3D_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES1,
+       .clkdm_name     = "gfx_3430es1_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1252,15 +1272,18 @@ static struct clk sgx_fck = {
        .clksel_mask    = OMAP3430ES2_CLKSEL_SGX_MASK,
        .clksel         = sgx_clksel,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "sgx_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk sgx_ick = {
        .name           = "sgx_ick",
        .parent         = &l3_ick,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_SGX_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430ES2_EN_SGX_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "sgx_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1269,9 +1292,11 @@ static struct clk sgx_ick = {
 static struct clk d2d_26m_fck = {
        .name           = "d2d_26m_fck",
        .parent         = &sys_ck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430ES1_EN_D2D_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES1,
+       .clkdm_name     = "d2d_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1291,6 +1316,7 @@ static struct clk gpt10_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT10_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1304,6 +1330,7 @@ static struct clk gpt11_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT11_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1341,6 +1368,7 @@ static struct clk core_96m_fck = {
        .parent         = &omap_96m_fck,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1351,6 +1379,7 @@ static struct clk mmchs3_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430ES2_EN_MMC3_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1361,6 +1390,7 @@ static struct clk mmchs2_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_MMC2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1370,6 +1400,7 @@ static struct clk mspro_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_MSPRO_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1380,6 +1411,7 @@ static struct clk mmchs1_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_MMC1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1390,16 +1422,18 @@ static struct clk i2c3_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_I2C3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk i2c2_fck = {
        .name           = "i2c_fck",
-       .id             = 2,
+       .id             = 2,
        .parent         = &core_96m_fck,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_I2C2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1410,6 +1444,7 @@ static struct clk i2c1_fck = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP3430_EN_I2C1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1443,6 +1478,7 @@ static struct clk mcbsp5_fck = {
        .clksel_mask    = OMAP2_MCBSP5_CLKS_MASK,
        .clksel         = mcbsp_15_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1456,6 +1492,7 @@ static struct clk mcbsp1_fck = {
        .clksel_mask    = OMAP2_MCBSP1_CLKS_MASK,
        .clksel         = mcbsp_15_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1466,6 +1503,7 @@ static struct clk core_48m_fck = {
        .parent         = &omap_48m_fck,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1543,6 +1581,7 @@ static struct clk core_12m_fck = {
        .parent         = &omap_12m_fck,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1581,6 +1620,7 @@ static struct clk ssi_ssr_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_SSI_MASK,
        .clksel         = ssi_ssr_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -1596,11 +1636,17 @@ static struct clk ssi_sst_fck = {
 
 /* CORE_L3_ICK based clocks */
 
+/*
+ * XXX must add clk_enable/clk_disable for these if standard code won't
+ * handle it
+ */
 static struct clk core_l3_ick = {
        .name           = "core_l3_ick",
        .parent         = &l3_ick,
+       .init           = &omap2_init_clk_clkdm,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1610,6 +1656,7 @@ static struct clk hsotgusb_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_HSOTGUSB_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1619,6 +1666,7 @@ static struct clk sdrc_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_SDRC_SHIFT,
        .flags          = CLOCK_IN_OMAP343X | ENABLE_ON_INIT,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1627,6 +1675,7 @@ static struct clk gpmc_fck = {
        .parent         = &core_l3_ick,
        .flags          = CLOCK_IN_OMAP343X | PARENT_CONTROLS_CLOCK |
                                ENABLE_ON_INIT,
+       .clkdm_name     = "core_l3_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1654,8 +1703,10 @@ static struct clk pka_ick = {
 static struct clk core_l4_ick = {
        .name           = "core_l4_ick",
        .parent         = &l4_ick,
+       .init           = &omap2_init_clk_clkdm,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1665,6 +1716,7 @@ static struct clk usbtll_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
        .enable_bit     = OMAP3430ES2_EN_USBTLL_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1675,6 +1727,7 @@ static struct clk mmchs3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430ES2_EN_MMC3_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1685,6 +1738,7 @@ static struct clk icr_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_ICR_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1694,6 +1748,7 @@ static struct clk aes2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_AES2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1703,6 +1758,7 @@ static struct clk sha12_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_SHA12_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1712,6 +1768,7 @@ static struct clk des2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_DES2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1722,6 +1779,7 @@ static struct clk mmchs2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MMC2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1732,6 +1790,7 @@ static struct clk mmchs1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MMC1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1741,6 +1800,7 @@ static struct clk mspro_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MSPRO_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1750,6 +1810,7 @@ static struct clk hdq_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_HDQ_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1760,6 +1821,7 @@ static struct clk mcspi4_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCSPI4_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1770,6 +1832,7 @@ static struct clk mcspi3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCSPI3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1780,6 +1843,7 @@ static struct clk mcspi2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCSPI2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1790,6 +1854,7 @@ static struct clk mcspi1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCSPI1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1800,6 +1865,7 @@ static struct clk i2c3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_I2C3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1810,6 +1876,7 @@ static struct clk i2c2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_I2C2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1820,6 +1887,7 @@ static struct clk i2c1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_I2C1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1829,6 +1897,7 @@ static struct clk uart2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_UART2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1838,6 +1907,7 @@ static struct clk uart1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_UART1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1847,6 +1917,7 @@ static struct clk gpt11_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_GPT11_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1856,6 +1927,7 @@ static struct clk gpt10_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_GPT10_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1866,6 +1938,7 @@ static struct clk mcbsp5_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCBSP5_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1876,6 +1949,7 @@ static struct clk mcbsp1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MCBSP1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1885,6 +1959,7 @@ static struct clk fac_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430ES1_EN_FAC_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES1,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1894,6 +1969,7 @@ static struct clk mailboxes_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_MAILBOXES_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1913,6 +1989,7 @@ static struct clk ssi_l4_ick = {
        .parent         = &l4_ick,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1922,6 +1999,7 @@ static struct clk ssi_ick = {
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_SSI_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -1996,7 +2074,7 @@ static struct clk des1_ick = {
 
 /* DSS */
 static const struct clksel dss1_alwon_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -2011,33 +2089,40 @@ static struct clk dss1_alwon_fck = {
        .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
        .clksel         = dss1_alwon_fck_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "dss_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk dss_tv_fck = {
        .name           = "dss_tv_fck",
        .parent         = &omap_54m_fck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_TV_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "dss_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk dss_96m_fck = {
        .name           = "dss_96m_fck",
        .parent         = &omap_96m_fck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_TV_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "dss_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk dss2_alwon_fck = {
        .name           = "dss2_alwon_fck",
        .parent         = &sys_ck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_DSS2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "dss_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2045,16 +2130,18 @@ static struct clk dss_ick = {
        /* Handles both L3 and L4 clocks */
        .name           = "dss_ick",
        .parent         = &l4_ick,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "dss_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 /* CAM */
 
 static const struct clksel cam_mclk_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
+       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
        { .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates },
        { .parent = NULL }
 };
@@ -2069,24 +2156,19 @@ static struct clk cam_mclk = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_CAM_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "cam_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
-static struct clk cam_l3_ick = {
-       .name           = "cam_l3_ick",
-       .parent         = &l3_ick,
-       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
-       .enable_bit     = OMAP3430_EN_CAM_SHIFT,
-       .flags          = CLOCK_IN_OMAP343X,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk cam_l4_ick = {
-       .name           = "cam_l4_ick",
+static struct clk cam_ick = {
+       /* Handles both L3 and L4 clocks */
+       .name           = "cam_ick",
        .parent         = &l4_ick,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_CAM_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "cam_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2095,45 +2177,45 @@ static struct clk cam_l4_ick = {
 static struct clk usbhost_120m_fck = {
        .name           = "usbhost_120m_fck",
        .parent         = &omap_120m_fck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430ES2_EN_USBHOST2_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "usbhost_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk usbhost_48m_fck = {
        .name           = "usbhost_48m_fck",
        .parent         = &omap_48m_fck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430ES2_EN_USBHOST1_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "usbhost_clkdm",
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usbhost_l3_ick = {
-       .name           = "usbhost_l3_ick",
-       .parent         = &l3_ick,
-       .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
-       .enable_bit     = OMAP3430ES2_EN_USBHOST_SHIFT,
-       .flags          = CLOCK_IN_OMAP3430ES2,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk usbhost_l4_ick = {
-       .name           = "usbhost_l4_ick",
+static struct clk usbhost_ick = {
+       /* Handles both L3 and L4 clocks */
+       .name           = "usbhost_ick",
        .parent         = &l4_ick,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430ES2_EN_USBHOST_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "usbhost_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk usbhost_sar_fck = {
        .name           = "usbhost_sar_fck",
        .parent         = &osc_sys_ck,
+       .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_PRM_REGADDR(OMAP3430ES2_USBHOST_MOD, PM_PWSTCTRL),
        .enable_bit     = OMAP3430ES2_SAVEANDRESTORE_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "usbhost_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2175,6 +2257,7 @@ static struct clk usim_fck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
+/* XXX should gpt1's clksel have wkup_32k_fck as the 32k opt? */
 static struct clk gpt1_fck = {
        .name           = "gpt1_fck",
        .init           = &omap2_init_clksel_parent,
@@ -2184,13 +2267,16 @@ static struct clk gpt1_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT1_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk wkup_32k_fck = {
        .name           = "wkup_32k_fck",
+       .init           = &omap2_init_clk_clkdm,
        .parent         = &omap_32k_fck,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2200,6 +2286,7 @@ static struct clk gpio1_fck = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2209,6 +2296,7 @@ static struct clk wdt2_fck = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_WDT2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2216,6 +2304,7 @@ static struct clk wkup_l4_ick = {
        .name           = "wkup_l4_ick",
        .parent         = &sys_ck,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2227,6 +2316,7 @@ static struct clk usim_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430ES2_EN_USIMOCP_SHIFT,
        .flags          = CLOCK_IN_OMAP3430ES2,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2236,6 +2326,7 @@ static struct clk wdt2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_WDT2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2245,6 +2336,7 @@ static struct clk wdt1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_WDT1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2254,6 +2346,7 @@ static struct clk gpio1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2263,15 +2356,18 @@ static struct clk omap_32ksync_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_32KSYNC_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
+/* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_ick = {
        .name           = "gpt12_ick",
        .parent         = &wkup_l4_ick,
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT12_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2281,6 +2377,7 @@ static struct clk gpt1_ick = {
        .enable_reg     = OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT1_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "wkup_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2291,16 +2388,20 @@ static struct clk gpt1_ick = {
 static struct clk per_96m_fck = {
        .name           = "per_96m_fck",
        .parent         = &omap_96m_alwon_fck,
+       .init           = &omap2_init_clk_clkdm,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static struct clk per_48m_fck = {
        .name           = "per_48m_fck",
        .parent         = &omap_48m_fck,
+       .init           = &omap2_init_clk_clkdm,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2310,6 +2411,7 @@ static struct clk uart3_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_UART3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2322,6 +2424,7 @@ static struct clk gpt2_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT2_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2334,6 +2437,7 @@ static struct clk gpt3_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT3_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2346,6 +2450,7 @@ static struct clk gpt4_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT4_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2358,6 +2463,7 @@ static struct clk gpt5_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT5_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2370,6 +2476,7 @@ static struct clk gpt6_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT6_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2382,6 +2489,7 @@ static struct clk gpt7_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT7_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2394,6 +2502,7 @@ static struct clk gpt8_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT8_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2406,12 +2515,14 @@ static struct clk gpt9_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_GPT9_MASK,
        .clksel         = omap343x_gpt_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk per_32k_alwon_fck = {
        .name           = "per_32k_alwon_fck",
        .parent         = &omap_32k_fck,
+       .clkdm_name     = "per_clkdm",
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
        .recalc         = &followparent_recalc,
 };
@@ -2422,6 +2533,7 @@ static struct clk gpio6_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO6_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2431,6 +2543,7 @@ static struct clk gpio5_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO5_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2440,6 +2553,7 @@ static struct clk gpio4_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO4_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2449,6 +2563,7 @@ static struct clk gpio3_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2458,6 +2573,7 @@ static struct clk gpio2_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_GPIO2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2467,6 +2583,7 @@ static struct clk wdt3_fck = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_WDT3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2475,6 +2592,7 @@ static struct clk per_l4_ick = {
        .parent         = &l4_ick,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
                                PARENT_CONTROLS_CLOCK,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2484,6 +2602,7 @@ static struct clk gpio6_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO6_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2493,6 +2612,7 @@ static struct clk gpio5_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO5_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2502,6 +2622,7 @@ static struct clk gpio4_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO4_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2511,6 +2632,7 @@ static struct clk gpio3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2520,6 +2642,7 @@ static struct clk gpio2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPIO2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2529,6 +2652,7 @@ static struct clk wdt3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_WDT3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2538,6 +2662,7 @@ static struct clk uart3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_UART3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2547,6 +2672,7 @@ static struct clk gpt9_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT9_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2556,6 +2682,7 @@ static struct clk gpt8_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT8_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2565,6 +2692,7 @@ static struct clk gpt7_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT7_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2574,6 +2702,7 @@ static struct clk gpt6_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT6_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2583,6 +2712,7 @@ static struct clk gpt5_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT5_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2592,6 +2722,7 @@ static struct clk gpt4_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT4_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2601,6 +2732,7 @@ static struct clk gpt3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2610,6 +2742,7 @@ static struct clk gpt2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_GPT2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2620,6 +2753,7 @@ static struct clk mcbsp2_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_MCBSP2_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2630,6 +2764,7 @@ static struct clk mcbsp3_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_MCBSP3_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
@@ -2640,12 +2775,13 @@ static struct clk mcbsp4_ick = {
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
        .enable_bit     = OMAP3430_EN_MCBSP4_SHIFT,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 static const struct clksel mcbsp_234_clksel[] = {
        { .parent = &per_96m_fck, .rates = common_mcbsp_96m_rates },
-       { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+       { .parent = &mcbsp_clks,  .rates = common_mcbsp_mcbsp_rates },
        { .parent = NULL }
 };
 
@@ -2659,6 +2795,7 @@ static struct clk mcbsp2_fck = {
        .clksel_mask    = OMAP2_MCBSP2_CLKS_MASK,
        .clksel         = mcbsp_234_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2672,6 +2809,7 @@ static struct clk mcbsp3_fck = {
        .clksel_mask    = OMAP2_MCBSP3_CLKS_MASK,
        .clksel         = mcbsp_234_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2685,6 +2823,7 @@ static struct clk mcbsp4_fck = {
        .clksel_mask    = OMAP2_MCBSP4_CLKS_MASK,
        .clksel         = mcbsp_234_clksel,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "per_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2732,6 +2871,7 @@ static struct clk emu_src_ck = {
        .clksel_mask    = OMAP3430_MUX_CTRL_MASK,
        .clksel         = emu_src_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2755,6 +2895,7 @@ static struct clk pclk_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_PCLK_MASK,
        .clksel         = pclk_emu_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2777,6 +2918,7 @@ static struct clk pclkx2_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_PCLKX2_MASK,
        .clksel         = pclkx2_emu_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2792,6 +2934,7 @@ static struct clk atclk_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_ATCLK_MASK,
        .clksel         = atclk_emu_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2802,6 +2945,7 @@ static struct clk traceclk_src_fck = {
        .clksel_mask    = OMAP3430_TRACE_MUX_CTRL_MASK,
        .clksel         = emu_src_clksel,
        .flags          = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2824,6 +2968,7 @@ static struct clk traceclk_fck = {
        .clksel_mask    = OMAP3430_CLKSEL_TRACECLK_MASK,
        .clksel         = traceclk_clksel,
        .flags          = CLOCK_IN_OMAP343X | ALWAYS_ENABLED,
+       .clkdm_name     = "emu_clkdm",
        .recalc         = &omap2_clksel_recalc,
 };
 
@@ -2853,11 +2998,13 @@ static struct clk sr_l4_ick = {
        .name           = "sr_l4_ick",
        .parent         = &l4_ick,
        .flags          = CLOCK_IN_OMAP343X,
+       .clkdm_name     = "core_l4_clkdm",
        .recalc         = &followparent_recalc,
 };
 
 /* SECURE_32K_FCK clocks */
 
+/* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_fck = {
        .name           = "gpt12_fck",
        .parent         = &secure_32k_fck,
@@ -2933,6 +3080,7 @@ static struct clk *onchip_34xx_clks[] __initdata = {
        &l3_ick,
        &l4_ick,
        &rm_ick,
+       &gfx_l3_ck,
        &gfx_l3_fck,
        &gfx_l3_ick,
        &gfx_cg1_ck,
@@ -3014,12 +3162,10 @@ static struct clk *onchip_34xx_clks[] __initdata = {
        &dss2_alwon_fck,
        &dss_ick,
        &cam_mclk,
-       &cam_l3_ick,
-       &cam_l4_ick,
+       &cam_ick,
        &usbhost_120m_fck,
        &usbhost_48m_fck,
-       &usbhost_l3_ick,
-       &usbhost_l4_ick,
+       &usbhost_ick,
        &usbhost_sar_fck,
        &usim_fck,
        &gpt1_fck,
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
new file mode 100644 (file)
index 0000000..4c3ce9c
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ * OMAP2/3 clockdomain framework functions
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley and Jouni Högander
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifdef CONFIG_OMAP_DEBUG_CLOCKDOMAIN
+#  define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/limits.h>
+
+#include <linux/io.h>
+
+#include <linux/bitops.h>
+
+#include <mach/clock.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "cm.h"
+
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
+
+/* clkdm_list contains all registered struct clockdomains */
+static LIST_HEAD(clkdm_list);
+
+/* clkdm_mutex protects clkdm_list add and del ops */
+static DEFINE_MUTEX(clkdm_mutex);
+
+/* array of powerdomain deps to be added/removed when clkdm in hwsup mode */
+static struct clkdm_pwrdm_autodep *autodeps;
+
+
+/* Private functions */
+
+/*
+ * _autodep_lookup - resolve autodep pwrdm names to pwrdm pointers; store
+ * @autodep: struct clkdm_pwrdm_autodep * to resolve
+ *
+ * Resolve autodep powerdomain names to powerdomain pointers via
+ * pwrdm_lookup() and store the pointers in the autodep structure.  An
+ * "autodep" is a powerdomain sleep/wakeup dependency that is
+ * automatically added and removed whenever clocks in the associated
+ * clockdomain are enabled or disabled (respectively) when the
+ * clockdomain is in hardware-supervised mode. Meant to be called
+ * once at clockdomain layer initialization, since these should remain
+ * fixed for a particular architecture.  No return value.
+ */
+static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
+{
+       struct powerdomain *pwrdm;
+
+       if (!autodep)
+               return;
+
+       if (!omap_chip_is(autodep->omap_chip))
+               return;
+
+       pwrdm = pwrdm_lookup(autodep->pwrdm_name);
+       if (!pwrdm) {
+               pr_debug("clockdomain: _autodep_lookup: powerdomain %s "
+                        "does not exist\n", autodep->pwrdm_name);
+               WARN_ON(1);
+               return;
+       }
+       autodep->pwrdm = pwrdm;
+
+       return;
+}
+
+/*
+ * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
+ * @clkdm: struct clockdomain *
+ *
+ * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is enabled. No return value.
+ */
+static void _clkdm_add_autodeps(struct clockdomain *clkdm)
+{
+       struct clkdm_pwrdm_autodep *autodep;
+
+       for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
+               if (!autodep->pwrdm)
+                       continue;
+
+               pr_debug("clockdomain: adding %s sleepdep/wkdep for "
+                        "pwrdm %s\n", autodep->pwrdm_name,
+                        clkdm->pwrdm->name);
+
+               pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm);
+               pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm);
+       }
+}
+
+/*
+ * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ */
+static void _clkdm_del_autodeps(struct clockdomain *clkdm)
+{
+       struct clkdm_pwrdm_autodep *autodep;
+
+       for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
+               if (!autodep->pwrdm)
+                       continue;
+
+               pr_debug("clockdomain: removing %s sleepdep/wkdep for "
+                        "pwrdm %s\n", autodep->pwrdm_name,
+                        clkdm->pwrdm->name);
+
+               pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm);
+               pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm);
+       }
+}
+
+
+static struct clockdomain *_clkdm_lookup(const char *name)
+{
+       struct clockdomain *clkdm, *temp_clkdm;
+
+       if (!name)
+               return NULL;
+
+       clkdm = NULL;
+
+       list_for_each_entry(temp_clkdm, &clkdm_list, node) {
+               if (!strcmp(name, temp_clkdm->name)) {
+                       clkdm = temp_clkdm;
+                       break;
+               }
+       }
+
+       return clkdm;
+}
+
+
+/* Public functions */
+
+/**
+ * clkdm_init - set up the clockdomain layer
+ * @clkdms: optional pointer to an array of clockdomains to register
+ * @init_autodeps: optional pointer to an array of autodeps to register
+ *
+ * Set up internal state.  If a pointer to an array of clockdomains
+ * was supplied, loop through the list of clockdomains, register all
+ * that are available on the current platform. Similarly, if a
+ * pointer to an array of clockdomain-powerdomain autodependencies was
+ * provided, register those.  No return value.
+ */
+void clkdm_init(struct clockdomain **clkdms,
+               struct clkdm_pwrdm_autodep *init_autodeps)
+{
+       struct clockdomain **c = NULL;
+       struct clkdm_pwrdm_autodep *autodep = NULL;
+
+       if (clkdms)
+               for (c = clkdms; *c; c++)
+                       clkdm_register(*c);
+
+       autodeps = init_autodeps;
+       if (autodeps)
+               for (autodep = autodeps; autodep->pwrdm_name; autodep++)
+                       _autodep_lookup(autodep);
+}
+
+/**
+ * clkdm_register - register a clockdomain
+ * @clkdm: struct clockdomain * to register
+ *
+ * Adds a clockdomain to the internal clockdomain list.
+ * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
+ * already registered by the provided name, or 0 upon success.
+ */
+int clkdm_register(struct clockdomain *clkdm)
+{
+       int ret = -EINVAL;
+       struct powerdomain *pwrdm;
+
+       if (!clkdm || !clkdm->name)
+               return -EINVAL;
+
+       if (!omap_chip_is(clkdm->omap_chip))
+               return -EINVAL;
+
+       pwrdm = pwrdm_lookup(clkdm->pwrdm_name);
+       if (!pwrdm) {
+               pr_debug("clockdomain: clkdm_register %s: powerdomain %s "
+                        "does not exist\n", clkdm->name, clkdm->pwrdm_name);
+               return -EINVAL;
+       }
+       clkdm->pwrdm = pwrdm;
+
+       mutex_lock(&clkdm_mutex);
+       /* Verify that the clockdomain is not already registered */
+       if (_clkdm_lookup(clkdm->name)) {
+               ret = -EEXIST;
+               goto cr_unlock;
+       };
+
+       list_add(&clkdm->node, &clkdm_list);
+
+       pwrdm_add_clkdm(pwrdm, clkdm);
+
+       pr_debug("clockdomain: registered %s\n", clkdm->name);
+       ret = 0;
+
+cr_unlock:
+       mutex_unlock(&clkdm_mutex);
+
+       return ret;
+}
+
+/**
+ * clkdm_unregister - unregister a clockdomain
+ * @clkdm: struct clockdomain * to unregister
+ *
+ * Removes a clockdomain from the internal clockdomain list.  Returns
+ * -EINVAL if clkdm argument is NULL.
+ */
+int clkdm_unregister(struct clockdomain *clkdm)
+{
+       if (!clkdm)
+               return -EINVAL;
+
+       pwrdm_del_clkdm(clkdm->pwrdm, clkdm);
+
+       mutex_lock(&clkdm_mutex);
+       list_del(&clkdm->node);
+       mutex_unlock(&clkdm_mutex);
+
+       pr_debug("clockdomain: unregistered %s\n", clkdm->name);
+
+       return 0;
+}
+
+/**
+ * clkdm_lookup - look up a clockdomain by name, return a pointer
+ * @name: name of clockdomain
+ *
+ * Find a registered clockdomain by its name.  Returns a pointer to the
+ * struct clockdomain if found, or NULL otherwise.
+ */
+struct clockdomain *clkdm_lookup(const char *name)
+{
+       struct clockdomain *clkdm, *temp_clkdm;
+
+       if (!name)
+               return NULL;
+
+       clkdm = NULL;
+
+       mutex_lock(&clkdm_mutex);
+       list_for_each_entry(temp_clkdm, &clkdm_list, node) {
+               if (!strcmp(name, temp_clkdm->name)) {
+                       clkdm = temp_clkdm;
+                       break;
+               }
+       }
+       mutex_unlock(&clkdm_mutex);
+
+       return clkdm;
+}
+
+/**
+ * clkdm_for_each - call function on each registered clockdomain
+ * @fn: callback function *
+ *
+ * Call the supplied function for each registered clockdomain.
+ * The callback function can return anything but 0 to bail
+ * out early from the iterator.  The callback function is called with
+ * the clkdm_mutex held, so no clockdomain structure manipulation
+ * functions should be called from the callback, although hardware
+ * clockdomain control functions are fine.  Returns the last return
+ * value of the callback function, which should be 0 for success or
+ * anything else to indicate failure; or -EINVAL if the function pointer
+ * is null.
+ */
+int clkdm_for_each(int (*fn)(struct clockdomain *clkdm))
+{
+       struct clockdomain *clkdm;
+       int ret = 0;
+
+       if (!fn)
+               return -EINVAL;
+
+       mutex_lock(&clkdm_mutex);
+       list_for_each_entry(clkdm, &clkdm_list, node) {
+               ret = (*fn)(clkdm);
+               if (ret)
+                       break;
+       }
+       mutex_unlock(&clkdm_mutex);
+
+       return ret;
+}
+
+
+/**
+ * clkdm_get_pwrdm - return a ptr to the pwrdm that this clkdm resides in
+ * @clkdm: struct clockdomain *
+ *
+ * Return a pointer to the struct powerdomain that the specified clockdomain
+ * 'clkdm' exists in, or returns NULL if clkdm argument is NULL.
+ */
+struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
+{
+       if (!clkdm)
+               return NULL;
+
+       return clkdm->pwrdm;
+}
+
+
+/* Hardware clockdomain control */
+
+/**
+ * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
+ * @clk: struct clk * of a clockdomain
+ *
+ * Return the clockdomain's current state transition mode from the
+ * corresponding domain CM_CLKSTCTRL register. Returns -EINVAL if clk
+ * is NULL or the current mode upon success.
+ */
+static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
+{
+       u32 v;
+
+       if (!clkdm)
+               return -EINVAL;
+
+       v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+       v &= clkdm->clktrctrl_mask;
+       v >>= __ffs(clkdm->clktrctrl_mask);
+
+       return v;
+}
+
+/**
+ * omap2_clkdm_sleep - force clockdomain sleep transition
+ * @clkdm: struct clockdomain *
+ *
+ * Instruct the CM to force a sleep transition on the specified
+ * clockdomain 'clkdm'.  Returns -EINVAL if clk is NULL or if
+ * clockdomain does not support software-initiated sleep; 0 upon
+ * success.
+ */
+int omap2_clkdm_sleep(struct clockdomain *clkdm)
+{
+       if (!clkdm)
+               return -EINVAL;
+
+       if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
+               pr_debug("clockdomain: %s does not support forcing "
+                        "sleep via software\n", clkdm->name);
+               return -EINVAL;
+       }
+
+       pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
+
+       if (cpu_is_omap24xx()) {
+
+               cm_set_mod_reg_bits(OMAP24XX_FORCESTATE,
+                                   clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       } else if (cpu_is_omap34xx()) {
+
+               u32 v = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
+                        __ffs(clkdm->clktrctrl_mask));
+
+               cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
+                                   clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+
+       } else {
+               BUG();
+       };
+
+       return 0;
+}
+
+/**
+ * omap2_clkdm_wakeup - force clockdomain wakeup transition
+ * @clkdm: struct clockdomain *
+ *
+ * Instruct the CM to force a wakeup transition on the specified
+ * clockdomain 'clkdm'.  Returns -EINVAL if clkdm is NULL or if the
+ * clockdomain does not support software-controlled wakeup; 0 upon
+ * success.
+ */
+int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+{
+       if (!clkdm)
+               return -EINVAL;
+
+       if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
+               pr_debug("clockdomain: %s does not support forcing "
+                        "wakeup via software\n", clkdm->name);
+               return -EINVAL;
+       }
+
+       pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
+
+       if (cpu_is_omap24xx()) {
+
+               cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE,
+                                     clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       } else if (cpu_is_omap34xx()) {
+
+               u32 v = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
+                        __ffs(clkdm->clktrctrl_mask));
+
+               cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
+                                   clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+
+       } else {
+               BUG();
+       };
+
+       return 0;
+}
+
+/**
+ * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Allow the hardware to automatically switch the clockdomain into
+ * active or idle states, as needed by downstream clocks.  If the
+ * clockdomain has any downstream clocks enabled in the clock
+ * framework, wkdep/sleepdep autodependencies are added; this is so
+ * device drivers can read and write to the device.  No return value.
+ */
+void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+       u32 v;
+
+       if (!clkdm)
+               return;
+
+       if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
+               pr_debug("clock: automatic idle transitions cannot be enabled "
+                        "on clockdomain %s\n", clkdm->name);
+               return;
+       }
+
+       pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
+                clkdm->name);
+
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_add_autodeps(clkdm);
+
+       if (cpu_is_omap24xx())
+               v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
+       else if (cpu_is_omap34xx())
+               v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
+       else
+               BUG();
+
+
+       cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+                           v << __ffs(clkdm->clktrctrl_mask),
+                           clkdm->pwrdm->prcm_offs,
+                           CM_CLKSTCTRL);
+}
+
+/**
+ * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Prevent the hardware from automatically switching the clockdomain
+ * into inactive or idle states.  If the clockdomain has downstream
+ * clocks enabled in the clock framework, wkdep/sleepdep
+ * autodependencies are removed.  No return value.
+ */
+void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+       u32 v;
+
+       if (!clkdm)
+               return;
+
+       if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
+               pr_debug("clockdomain: automatic idle transitions cannot be "
+                        "disabled on %s\n", clkdm->name);
+               return;
+       }
+
+       pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
+                clkdm->name);
+
+       if (cpu_is_omap24xx())
+               v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
+       else if (cpu_is_omap34xx())
+               v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
+       else
+               BUG();
+
+       cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
+                           v << __ffs(clkdm->clktrctrl_mask),
+                           clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
+
+       if (atomic_read(&clkdm->usecount) > 0)
+               _clkdm_del_autodeps(clkdm);
+}
+
+
+/* Clockdomain-to-clock framework interface code */
+
+/**
+ * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
+ * @clkdm: struct clockdomain *
+ * @clk: struct clk * of the enabled downstream clock
+ *
+ * Increment the usecount of this clockdomain 'clkdm' and ensure that
+ * it is awake.  Intended to be called by clk_enable() code.  If the
+ * clockdomain is in software-supervised idle mode, force the
+ * clockdomain to wake.  If the clockdomain is in hardware-supervised
+ * idle mode, add clkdm-pwrdm autodependencies, to ensure that devices
+ * in the clockdomain can be read from/written to by on-chip processors.
+ * Returns -EINVAL if passed null pointers; returns 0 upon success or
+ * if the clockdomain is in hwsup idle mode.
+ */
+int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
+{
+       int v;
+
+       /*
+        * XXX Rewrite this code to maintain a list of enabled
+        * downstream clocks for debugging purposes?
+        */
+
+       if (!clkdm || !clk)
+               return -EINVAL;
+
+       if (atomic_inc_return(&clkdm->usecount) > 1)
+               return 0;
+
+       /* Clockdomain now has one enabled downstream clock */
+
+       pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
+                clk->name);
+
+       v = omap2_clkdm_clktrctrl_read(clkdm);
+
+       if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
+           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
+               _clkdm_add_autodeps(clkdm);
+       else
+               omap2_clkdm_wakeup(clkdm);
+
+       return 0;
+}
+
+/**
+ * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
+ * @clkdm: struct clockdomain *
+ * @clk: struct clk * of the disabled downstream clock
+ *
+ * Decrement the usecount of this clockdomain 'clkdm'. Intended to be
+ * called by clk_disable() code.  If the usecount goes to 0, put the
+ * clockdomain to sleep (software-supervised mode) or remove the
+ * clkdm-pwrdm autodependencies (hardware-supervised mode).  Returns
+ * -EINVAL if passed null pointers; -ERANGE if the clkdm usecount
+ * underflows and debugging is enabled; or returns 0 upon success or
+ * if the clockdomain is in hwsup idle mode.
+ */
+int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
+{
+       int v;
+
+       /*
+        * XXX Rewrite this code to maintain a list of enabled
+        * downstream clocks for debugging purposes?
+        */
+
+       if (!clkdm || !clk)
+               return -EINVAL;
+
+#ifdef DEBUG
+       if (atomic_read(&clkdm->usecount) == 0) {
+               WARN_ON(1); /* underflow */
+               return -ERANGE;
+       }
+#endif
+
+       if (atomic_dec_return(&clkdm->usecount) > 0)
+               return 0;
+
+       /* All downstream clocks of this clockdomain are now disabled */
+
+       pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
+                clk->name);
+
+       v = omap2_clkdm_clktrctrl_read(clkdm);
+
+       if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
+           (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
+               _clkdm_del_autodeps(clkdm);
+       else
+               omap2_clkdm_sleep(clkdm);
+
+       return 0;
+}
+
diff --git a/arch/arm/mach-omap2/clockdomains.h b/arch/arm/mach-omap2/clockdomains.h
new file mode 100644 (file)
index 0000000..cd86dcc
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * OMAP2/3 clockdomains
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
+#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
+
+#include <mach/clockdomain.h>
+
+/*
+ * OMAP2/3-common clockdomains
+ */
+
+/* This is an implicit clockdomain - it is never defined as such in TRM */
+static struct clockdomain wkup_clkdm = {
+       .name           = "wkup_clkdm",
+       .pwrdm_name     = "wkup_pwrdm",
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+};
+
+/*
+ * 2420-only clockdomains
+ */
+
+#if defined(CONFIG_ARCH_OMAP2420)
+
+static struct clockdomain mpu_2420_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm_name     = "mpu_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+static struct clockdomain iva1_2420_clkdm = {
+       .name           = "iva1_clkdm",
+       .pwrdm_name     = "dsp_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+#endif  /* CONFIG_ARCH_OMAP2420 */
+
+
+/*
+ * 2430-only clockdomains
+ */
+
+#if defined(CONFIG_ARCH_OMAP2430)
+
+static struct clockdomain mpu_2430_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm_name     = "mpu_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+static struct clockdomain mdm_clkdm = {
+       .name           = "mdm_clkdm",
+       .pwrdm_name     = "mdm_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+#endif    /* CONFIG_ARCH_OMAP2430 */
+
+
+/*
+ * 24XX-only clockdomains
+ */
+
+#if defined(CONFIG_ARCH_OMAP24XX)
+
+static struct clockdomain dsp_clkdm = {
+       .name           = "dsp_clkdm",
+       .pwrdm_name     = "dsp_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
+static struct clockdomain gfx_24xx_clkdm = {
+       .name           = "gfx_clkdm",
+       .pwrdm_name     = "gfx_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
+static struct clockdomain core_l3_24xx_clkdm = {
+       .name           = "core_l3_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
+static struct clockdomain core_l4_24xx_clkdm = {
+       .name           = "core_l4_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
+static struct clockdomain dss_24xx_clkdm = {
+       .name           = "dss_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+};
+
+#endif   /* CONFIG_ARCH_OMAP24XX */
+
+
+/*
+ * 34xx clockdomains
+ */
+
+#if defined(CONFIG_ARCH_OMAP34XX)
+
+static struct clockdomain mpu_34xx_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm_name     = "mpu_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain neon_clkdm = {
+       .name           = "neon_clkdm",
+       .pwrdm_name     = "neon_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain iva2_clkdm = {
+       .name           = "iva2_clkdm",
+       .pwrdm_name     = "iva2_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain gfx_3430es1_clkdm = {
+       .name           = "gfx_clkdm",
+       .pwrdm_name     = "gfx_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
+};
+
+static struct clockdomain sgx_clkdm = {
+       .name           = "sgx_clkdm",
+       .pwrdm_name     = "sgx_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+};
+
+/*
+ * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
+ * then that information was removed from the 34xx ES2+ TRM.  It is
+ * unclear whether the core is still there, but the clockdomain logic
+ * is there, and must be programmed to an appropriate state if the
+ * CORE clockdomain is to become inactive.
+ */
+static struct clockdomain d2d_clkdm = {
+       .name           = "d2d_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain core_l3_34xx_clkdm = {
+       .name           = "core_l3_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain core_l4_34xx_clkdm = {
+       .name           = "core_l4_clkdm",
+       .pwrdm_name     = "core_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain dss_34xx_clkdm = {
+       .name           = "dss_clkdm",
+       .pwrdm_name     = "dss_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain cam_clkdm = {
+       .name           = "cam_clkdm",
+       .pwrdm_name     = "cam_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain usbhost_clkdm = {
+       .name           = "usbhost_clkdm",
+       .pwrdm_name     = "usbhost_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+};
+
+static struct clockdomain per_clkdm = {
+       .name           = "per_clkdm",
+       .pwrdm_name     = "per_pwrdm",
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct clockdomain emu_clkdm = {
+       .name           = "emu_clkdm",
+       .pwrdm_name     = "emu_pwrdm",
+       .flags          = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_SWSUP,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+#endif   /* CONFIG_ARCH_OMAP34XX */
+
+/*
+ * Clockdomain-powerdomain hwsup dependencies (34XX only)
+ */
+
+static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL }
+};
+
+/*
+ *
+ */
+
+static struct clockdomain *clockdomains_omap[] = {
+
+       &wkup_clkdm,
+
+#ifdef CONFIG_ARCH_OMAP2420
+       &mpu_2420_clkdm,
+       &iva1_2420_clkdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+       &mpu_2430_clkdm,
+       &mdm_clkdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP24XX
+       &dsp_clkdm,
+       &gfx_24xx_clkdm,
+       &core_l3_24xx_clkdm,
+       &core_l4_24xx_clkdm,
+       &dss_24xx_clkdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+       &mpu_34xx_clkdm,
+       &neon_clkdm,
+       &iva2_clkdm,
+       &gfx_3430es1_clkdm,
+       &sgx_clkdm,
+       &d2d_clkdm,
+       &core_l3_34xx_clkdm,
+       &core_l4_34xx_clkdm,
+       &dss_34xx_clkdm,
+       &cam_clkdm,
+       &usbhost_clkdm,
+       &per_clkdm,
+       &emu_clkdm,
+#endif
+
+       NULL,
+};
+
+#endif
index 20ac38100678a1eb2c82d5b7e76aaddd7bb9be2b..1098ecfab861e2b42a0a6130fbe0b2d55ceb0004 100644 (file)
@@ -63,7 +63,8 @@
 #define OMAP24XX_CLKSEL_MPU_MASK                       (0x1f << 0)
 
 /* CM_CLKSTCTRL_MPU */
-#define OMAP24XX_AUTOSTATE_MPU                         (1 << 0)
+#define OMAP24XX_AUTOSTATE_MPU_SHIFT                   0
+#define OMAP24XX_AUTOSTATE_MPU_MASK                    (1 << 0)
 
 /* CM_FCLKEN1_CORE specific bits*/
 #define OMAP24XX_EN_TV_SHIFT                           2
 #define OMAP24XX_CLKSEL_GPT2_MASK                      (0x3 << 2)
 
 /* CM_CLKSTCTRL_CORE */
-#define OMAP24XX_AUTOSTATE_DSS                         (1 << 2)
-#define OMAP24XX_AUTOSTATE_L4                          (1 << 1)
-#define OMAP24XX_AUTOSTATE_L3                          (1 << 0)
+#define OMAP24XX_AUTOSTATE_DSS_SHIFT                   2
+#define OMAP24XX_AUTOSTATE_DSS_MASK                    (1 << 2)
+#define OMAP24XX_AUTOSTATE_L4_SHIFT                    1
+#define OMAP24XX_AUTOSTATE_L4_MASK                     (1 << 1)
+#define OMAP24XX_AUTOSTATE_L3_SHIFT                    0
+#define OMAP24XX_AUTOSTATE_L3_MASK                     (1 << 0)
 
 /* CM_FCLKEN_GFX */
 #define OMAP24XX_EN_3D_SHIFT                           2
 /* CM_CLKSEL_GFX specific bits */
 
 /* CM_CLKSTCTRL_GFX */
-#define OMAP24XX_AUTOSTATE_GFX                         (1 << 0)
+#define OMAP24XX_AUTOSTATE_GFX_SHIFT                   0
+#define OMAP24XX_AUTOSTATE_GFX_MASK                    (1 << 0)
 
 /* CM_FCLKEN_WKUP specific bits */
 
 #define OMAP24XX_CLKSEL_DSP_MASK                       (0x1f << 0)
 
 /* CM_CLKSTCTRL_DSP */
-#define OMAP2420_AUTOSTATE_IVA                         (1 << 8)
-#define OMAP24XX_AUTOSTATE_DSP                         (1 << 0)
+#define OMAP2420_AUTOSTATE_IVA_SHIFT                   8
+#define OMAP2420_AUTOSTATE_IVA_MASK                    (1 << 8)
+#define OMAP24XX_AUTOSTATE_DSP_SHIFT                   0
+#define OMAP24XX_AUTOSTATE_DSP_MASK                    (1 << 0)
 
 /* CM_FCLKEN_MDM */
 /* 2430 only */
 
 /* CM_CLKSTCTRL_MDM */
 /* 2430 only */
-#define OMAP2430_AUTOSTATE_MDM                         (1 << 0)
+#define OMAP2430_AUTOSTATE_MDM_SHIFT                   0
+#define OMAP2430_AUTOSTATE_MDM_MASK                    (1 << 0)
 
 #endif
index ee4c0ca1a7087af06ad8bb45498accbeb67f2cea..219f5c8d9659413146dc3f72c257280cd33e67e6 100644 (file)
@@ -96,7 +96,8 @@
 #define OMAP3430_CLKTRCTRL_IVA2_MASK                   (0x3 << 0)
 
 /* CM_CLKSTST_IVA2 */
-#define OMAP3430_CLKACTIVITY_IVA2                      (1 << 0)
+#define OMAP3430_CLKACTIVITY_IVA2_SHIFT                        0
+#define OMAP3430_CLKACTIVITY_IVA2_MASK                 (1 << 0)
 
 /* CM_REVISION specific bits */
 
 #define OMAP3430_CLKTRCTRL_MPU_MASK                    (0x3 << 0)
 
 /* CM_CLKSTST_MPU */
-#define OMAP3430_CLKACTIVITY_MPU                       (1 << 0)
+#define OMAP3430_CLKACTIVITY_MPU_SHIFT                 0
+#define OMAP3430_CLKACTIVITY_MPU_MASK                  (1 << 0)
 
 /* CM_FCLKEN1_CORE specific bits */
 
 #define OMAP3430_CLKTRCTRL_L3_MASK                     (0x3 << 0)
 
 /* CM_CLKSTST_CORE */
-#define OMAP3430ES1_CLKACTIVITY_D2D                    (1 << 2)
-#define OMAP3430_CLKACTIVITY_L4                                (1 << 1)
-#define OMAP3430_CLKACTIVITY_L3                                (1 << 0)
+#define OMAP3430ES1_CLKACTIVITY_D2D_SHIFT              2
+#define OMAP3430ES1_CLKACTIVITY_D2D_MASK               (1 << 2)
+#define OMAP3430_CLKACTIVITY_L4_SHIFT                  1
+#define OMAP3430_CLKACTIVITY_L4_MASK                   (1 << 1)
+#define OMAP3430_CLKACTIVITY_L3_SHIFT                  0
+#define OMAP3430_CLKACTIVITY_L3_MASK                   (1 << 0)
 
 /* CM_FCLKEN_GFX */
 #define OMAP3430ES1_EN_3D                              (1 << 2)
 #define OMAP3430ES1_CLKTRCTRL_GFX_MASK                 (0x3 << 0)
 
 /* CM_CLKSTST_GFX */
-#define OMAP3430ES1_CLKACTIVITY_GFX                    (1 << 0)
+#define OMAP3430ES1_CLKACTIVITY_GFX_SHIFT              0
+#define OMAP3430ES1_CLKACTIVITY_GFX_MASK               (1 << 0)
 
 /* CM_FCLKEN_SGX */
 #define OMAP3430ES2_EN_SGX_SHIFT                       1
 #define OMAP3430ES2_CLKSEL_SGX_SHIFT                   0
 #define OMAP3430ES2_CLKSEL_SGX_MASK                    (0x7 << 0)
 
+/* CM_CLKSTCTRL_SGX */
+#define OMAP3430ES2_CLKTRCTRL_SGX_SHIFT                        0
+#define OMAP3430ES2_CLKTRCTRL_SGX_MASK                 (0x3 << 0)
+
+/* CM_CLKSTST_SGX */
+#define OMAP3430ES2_CLKACTIVITY_SGX_SHIFT              0
+#define OMAP3430ES2_CLKACTIVITY_SGX_MASK               (1 << 0)
+
 /* CM_FCLKEN_WKUP specific bits */
 #define OMAP3430ES2_EN_USIMOCP_SHIFT                   9
 
 #define OMAP3430_CLKTRCTRL_DSS_MASK                    (0x3 << 0)
 
 /* CM_CLKSTST_DSS */
-#define OMAP3430_CLKACTIVITY_DSS                       (1 << 0)
+#define OMAP3430_CLKACTIVITY_DSS_SHIFT                 0
+#define OMAP3430_CLKACTIVITY_DSS_MASK                  (1 << 0)
 
 /* CM_FCLKEN_CAM specific bits */
 
 #define OMAP3430_CLKTRCTRL_CAM_MASK                    (0x3 << 0)
 
 /* CM_CLKSTST_CAM */
-#define OMAP3430_CLKACTIVITY_CAM                       (1 << 0)
+#define OMAP3430_CLKACTIVITY_CAM_SHIFT                 0
+#define OMAP3430_CLKACTIVITY_CAM_MASK                  (1 << 0)
 
 /* CM_FCLKEN_PER specific bits */
 
 #define OMAP3430_CLKTRCTRL_PER_MASK                    (0x3 << 0)
 
 /* CM_CLKSTST_PER */
-#define OMAP3430_CLKACTIVITY_PER                       (1 << 0)
+#define OMAP3430_CLKACTIVITY_PER_SHIFT                 0
+#define OMAP3430_CLKACTIVITY_PER_MASK                  (1 << 0)
 
 /* CM_CLKSEL1_EMU */
 #define OMAP3430_DIV_DPLL4_SHIFT                       24
 #define OMAP3430_CLKTRCTRL_EMU_MASK                    (0x3 << 0)
 
 /* CM_CLKSTST_EMU */
-#define OMAP3430_CLKACTIVITY_EMU                       (1 << 0)
+#define OMAP3430_CLKACTIVITY_EMU_SHIFT                 0
+#define OMAP3430_CLKACTIVITY_EMU_MASK                  (1 << 0)
 
 /* CM_CLKSEL2_EMU specific bits */
 #define OMAP3430_CORE_DPLL_EMU_MULT_SHIFT              8
 #define OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT            0
 #define OMAP3430ES2_CLKTRCTRL_USBHOST_MASK             (3 << 0)
 
-
+/* CM_CLKSTST_USBHOST */
+#define OMAP3430ES2_CLKACTIVITY_USBHOST_SHIFT          0
+#define OMAP3430ES2_CLKACTIVITY_USBHOST_MASK           (1 << 0)
 
 #endif
index 87a44c715aa4dd1b0604f4f81874c15df9de5d7b..65fdf78c91e1b1d03c62f006d0937e35b16f3d28 100644 (file)
@@ -18,7 +18,7 @@
 
 #ifndef __ASSEMBLER__
 #define OMAP_CM_REGADDR(module, reg)                                   \
-       (void __iomem *)IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg))
+                       IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg))
 #else
 #define OMAP2420_CM_REGADDR(module, reg)                               \
                        IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
index 2ee954a0bc7c23733fc186b27ece2dc8e755e64d..90af2ac469aaccc74401ceea7fe5487e63a7dd6b 100644 (file)
 #include <mach/board.h>
 #include <mach/mux.h>
 #include <mach/gpio.h>
-
-#if    defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
-
-#define OMAP2_I2C_BASE2                0x48072000
-#define OMAP2_I2C_INT2         57
-
-static struct resource i2c_resources2[] = {
-       {
-               .start          = OMAP2_I2C_BASE2,
-               .end            = OMAP2_I2C_BASE2 + 0x3f,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP2_I2C_INT2,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device omap_i2c_device2 = {
-       .name           = "i2c_omap",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(i2c_resources2),
-       .resource       = i2c_resources2,
-};
-
-/* See also arch/arm/plat-omap/devices.c for first I2C on 24xx */
-static void omap_init_i2c(void)
-{
-       /* REVISIT: Second I2C not in use on H4? */
-       if (machine_is_omap_h4())
-               return;
-
-       if (!cpu_is_omap2430()) {
-               omap_cfg_reg(J15_24XX_I2C2_SCL);
-               omap_cfg_reg(H19_24XX_I2C2_SDA);
-       }
-       (void) platform_device_register(&omap_i2c_device2);
-}
-
-#else
-
-static void omap_init_i2c(void) {}
-
-#endif
+#include <mach/eac.h>
 
 #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
 #define OMAP2_MBOX_BASE                IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
@@ -104,7 +61,9 @@ static inline void omap_init_mbox(void) { }
 
 #if defined(CONFIG_OMAP_STI)
 
-#define OMAP2_STI_BASE         IO_ADDRESS(0x48068000)
+#if defined(CONFIG_ARCH_OMAP2)
+
+#define OMAP2_STI_BASE         0x48068000
 #define OMAP2_STI_CHANNEL_BASE 0x54000000
 #define OMAP2_STI_IRQ          4
 
@@ -124,6 +83,25 @@ static struct resource sti_resources[] = {
                .flags          = IORESOURCE_IRQ,
        }
 };
+#elif defined(CONFIG_ARCH_OMAP3)
+
+#define OMAP3_SDTI_BASE                0x54500000
+#define OMAP3_SDTI_CHANNEL_BASE        0x54600000
+
+static struct resource sti_resources[] = {
+       {
+               .start          = OMAP3_SDTI_BASE,
+               .end            = OMAP3_SDTI_BASE + 0xFFF,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = OMAP3_SDTI_CHANNEL_BASE,
+               .end            = OMAP3_SDTI_CHANNEL_BASE + SZ_1M - 1,
+               .flags          = IORESOURCE_MEM,
+       }
+};
+
+#endif
 
 static struct platform_device sti_device = {
        .name           = "sti",
@@ -140,12 +118,14 @@ static inline void omap_init_sti(void)
 static inline void omap_init_sti(void) {}
 #endif
 
-#if defined(CONFIG_SPI_OMAP24XX)
+#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <mach/mcspi.h>
 
 #define OMAP2_MCSPI1_BASE              0x48098000
 #define OMAP2_MCSPI2_BASE              0x4809a000
+#define OMAP2_MCSPI3_BASE              0x480b8000
+#define OMAP2_MCSPI4_BASE              0x480ba000
 
 static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
        .num_cs         = 4,
@@ -159,7 +139,7 @@ static struct resource omap2_mcspi1_resources[] = {
        },
 };
 
-struct platform_device omap2_mcspi1 = {
+static struct platform_device omap2_mcspi1 = {
        .name           = "omap2_mcspi",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(omap2_mcspi1_resources),
@@ -181,7 +161,7 @@ static struct resource omap2_mcspi2_resources[] = {
        },
 };
 
-struct platform_device omap2_mcspi2 = {
+static struct platform_device omap2_mcspi2 = {
        .name           = "omap2_mcspi",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(omap2_mcspi2_resources),
@@ -191,16 +171,162 @@ struct platform_device omap2_mcspi2 = {
        },
 };
 
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
+       .num_cs         = 2,
+};
+
+static struct resource omap2_mcspi3_resources[] = {
+       {
+       .start          = OMAP2_MCSPI3_BASE,
+       .end            = OMAP2_MCSPI3_BASE + 0xff,
+       .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap2_mcspi3 = {
+       .name           = "omap2_mcspi",
+       .id             = 3,
+       .num_resources  = ARRAY_SIZE(omap2_mcspi3_resources),
+       .resource       = omap2_mcspi3_resources,
+       .dev            = {
+               .platform_data = &omap2_mcspi3_config,
+       },
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
+       .num_cs         = 1,
+};
+
+static struct resource omap2_mcspi4_resources[] = {
+       {
+               .start          = OMAP2_MCSPI4_BASE,
+               .end            = OMAP2_MCSPI4_BASE + 0xff,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap2_mcspi4 = {
+       .name           = "omap2_mcspi",
+       .id             = 4,
+       .num_resources  = ARRAY_SIZE(omap2_mcspi4_resources),
+       .resource       = omap2_mcspi4_resources,
+       .dev            = {
+               .platform_data = &omap2_mcspi4_config,
+       },
+};
+#endif
+
 static void omap_init_mcspi(void)
 {
        platform_device_register(&omap2_mcspi1);
        platform_device_register(&omap2_mcspi2);
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+       platform_device_register(&omap2_mcspi3);
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+       platform_device_register(&omap2_mcspi4);
+#endif
 }
 
 #else
 static inline void omap_init_mcspi(void) {}
 #endif
 
+#ifdef CONFIG_SND_OMAP24XX_EAC
+
+#define OMAP2_EAC_BASE                 0x48090000
+
+static struct resource omap2_eac_resources[] = {
+       {
+               .start          = OMAP2_EAC_BASE,
+               .end            = OMAP2_EAC_BASE + 0x109,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap2_eac_device = {
+       .name           = "omap24xx-eac",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(omap2_eac_resources),
+       .resource       = omap2_eac_resources,
+       .dev = {
+               .platform_data = NULL,
+       },
+};
+
+void omap_init_eac(struct eac_platform_data *pdata)
+{
+       omap2_eac_device.dev.platform_data = pdata;
+       platform_device_register(&omap2_eac_device);
+}
+
+#else
+void omap_init_eac(struct eac_platform_data *pdata) {}
+#endif
+
+#ifdef CONFIG_OMAP_SHA1_MD5
+static struct resource sha1_md5_resources[] = {
+       {
+               .start  = OMAP24XX_SEC_SHA1MD5_BASE,
+               .end    = OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = INT_24XX_SHA1MD5,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device sha1_md5_device = {
+       .name           = "OMAP SHA1/MD5",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(sha1_md5_resources),
+       .resource       = sha1_md5_resources,
+};
+
+static void omap_init_sha1_md5(void)
+{
+       platform_device_register(&sha1_md5_device);
+}
+#else
+static inline void omap_init_sha1_md5(void) { }
+#endif
+
+#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#define OMAP_HDQ_BASE  0x480B2000
+#endif
+static struct resource omap_hdq_resources[] = {
+       {
+               .start          = OMAP_HDQ_BASE,
+               .end            = OMAP_HDQ_BASE + 0x1C,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = INT_24XX_HDQ_IRQ,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+static struct platform_device omap_hdq_dev = {
+       .name = "omap_hdq",
+       .id = 0,
+       .dev = {
+               .platform_data = NULL,
+       },
+       .num_resources  = ARRAY_SIZE(omap_hdq_resources),
+       .resource       = omap_hdq_resources,
+};
+static inline void omap_hdq_init(void)
+{
+       (void) platform_device_register(&omap_hdq_dev);
+}
+#else
+static inline void omap_hdq_init(void) {}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -208,10 +334,11 @@ static int __init omap2_init_devices(void)
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
-       omap_init_i2c();
        omap_init_mbox();
        omap_init_mcspi();
+       omap_hdq_init();
        omap_init_sti();
+       omap_init_sha1_md5();
 
        return 0;
 }
index af1081a0b27c9549b0dedecaac107991afb553b2..763bdbeaf68182c87389d36a3ed4a53db09e59ed 100644 (file)
@@ -9,6 +9,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <asm/mach-types.h>
 #include <mach/gpmc.h>
 
-#undef DEBUG
-
-#ifdef CONFIG_ARCH_OMAP2420
-#define GPMC_BASE              0x6800a000
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2430
-#define GPMC_BASE              0x6E000000
-#endif
+#include <mach/sdrc.h>
 
+/* GPMC register offsets */
 #define GPMC_REVISION          0x00
 #define GPMC_SYSCONFIG         0x10
 #define GPMC_SYSSTATUS         0x14
@@ -51,7 +47,6 @@
 #define GPMC_CS0               0x60
 #define GPMC_CS_SIZE           0x30
 
-#define GPMC_CS_NUM            8
 #define GPMC_MEM_START         0x00000000
 #define GPMC_MEM_END           0x3FFFFFFF
 #define BOOT_ROM_SPACE         0x100000        /* 1MB */
@@ -64,12 +59,9 @@ static struct resource       gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 static unsigned                gpmc_cs_map;
 
-static void __iomem *gpmc_base =
-       (void __iomem *) IO_ADDRESS(GPMC_BASE);
-static void __iomem *gpmc_cs_base =
-       (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0;
+static void __iomem *gpmc_base;
 
-static struct clk *gpmc_fck;
+static struct clk *gpmc_l3_clk;
 
 static void gpmc_write_reg(int idx, u32 val)
 {
@@ -85,19 +77,32 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
        void __iomem *reg_addr;
 
-       reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx;
+       reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
        __raw_writel(val, reg_addr);
 }
 
 u32 gpmc_cs_read_reg(int cs, int idx)
 {
-       return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx);
+       void __iomem *reg_addr;
+
+       reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
+       return __raw_readl(reg_addr);
 }
 
+/* TODO: Add support for gpmc_fck to clock framework and use it */
 unsigned long gpmc_get_fclk_period(void)
 {
-       /* In picoseconds */
-       return 1000000000 / ((clk_get_rate(gpmc_fck)) / 1000);
+       unsigned long rate = clk_get_rate(gpmc_l3_clk);
+
+       if (rate == 0) {
+               printk(KERN_WARNING "gpmc_l3_clk not enabled\n");
+               return 0;
+       }
+
+       rate /= 1000;
+       rate = 1000000000 / rate;       /* In picoseconds */
+
+       return rate;
 }
 
 unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
@@ -110,6 +115,11 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
        return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
+unsigned int gpmc_ticks_to_ns(unsigned int ticks)
+{
+       return ticks * gpmc_get_fclk_period() / 1000;
+}
+
 unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 {
        unsigned long ticks = gpmc_ns_to_ticks(time_ns);
@@ -210,6 +220,11 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
        GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
+       if (cpu_is_omap34xx()) {
+               GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
+               GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
+       }
+
        /* caller is expected to have initialized CONFIG1 to cover
         * at least sync vs async
         */
@@ -350,6 +365,7 @@ out:
        spin_unlock(&gpmc_mem_lock);
        return r;
 }
+EXPORT_SYMBOL(gpmc_cs_request);
 
 void gpmc_cs_free(int cs)
 {
@@ -365,8 +381,9 @@ void gpmc_cs_free(int cs)
        gpmc_cs_set_reserved(cs, 0);
        spin_unlock(&gpmc_mem_lock);
 }
+EXPORT_SYMBOL(gpmc_cs_free);
 
-void __init gpmc_mem_init(void)
+static void __init gpmc_mem_init(void)
 {
        int cs;
        unsigned long boot_rom_space = 0;
@@ -396,12 +413,33 @@ void __init gpmc_mem_init(void)
 void __init gpmc_init(void)
 {
        u32 l;
+       char *ck;
+
+       if (cpu_is_omap24xx()) {
+               ck = "core_l3_ck";
+               if (cpu_is_omap2420())
+                       l = OMAP2420_GPMC_BASE;
+               else
+                       l = OMAP34XX_GPMC_BASE;
+       } else if (cpu_is_omap34xx()) {
+               ck = "gpmc_fck";
+               l = OMAP34XX_GPMC_BASE;
+       }
 
-       gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */
-       if (IS_ERR(gpmc_fck))
-               WARN_ON(1);
-       else
-               clk_enable(gpmc_fck);
+       gpmc_l3_clk = clk_get(NULL, ck);
+       if (IS_ERR(gpmc_l3_clk)) {
+               printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
+               return -ENODEV;
+       }
+
+       gpmc_base = ioremap(l, SZ_4K);
+       if (!gpmc_base) {
+               clk_put(gpmc_l3_clk);
+               printk(KERN_ERR "Could not get GPMC register memory\n");
+               return -ENOMEM;
+       }
+
+       BUG_ON(IS_ERR(gpmc_l3_clk));
 
        l = gpmc_read_reg(GPMC_REVISION);
        printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
index 209177c7f22fe434a442359dd8f54f68d243348e..bf45ff39a7b5fbe9d651fbc81c6ec6f2caeb7e32 100644 (file)
 
 #include <asm/cputype.h>
 
+#include <mach/common.h>
 #include <mach/control.h>
 #include <mach/cpu.h>
 
-#if defined(CONFIG_ARCH_OMAP2420)
-#define TAP_BASE       io_p2v(0x48014000)
-#elif defined(CONFIG_ARCH_OMAP2430)
-#define TAP_BASE       io_p2v(0x4900A000)
-#elif defined(CONFIG_ARCH_OMAP34XX)
-#define TAP_BASE       io_p2v(0x4830A000)
-#endif
+static u32 class;
+static void __iomem *tap_base;
+static u16 tap_prod_id;
 
 #define OMAP_TAP_IDCODE                0x0204
-#if defined(CONFIG_ARCH_OMAP34XX)
-#define OMAP_TAP_PROD_ID       0x0210
-#else
-#define OMAP_TAP_PROD_ID       0x0208
-#endif
-
 #define OMAP_TAP_DIE_ID_0      0x0218
 #define OMAP_TAP_DIE_ID_1      0x021C
 #define OMAP_TAP_DIE_ID_2      0x0220
@@ -94,18 +85,24 @@ static u32 __init read_tap_reg(int reg)
         * it means its Cortex r0p0 which is 3430 ES1
         */
        if ((((cpuid >> 4) & 0xFFF) == 0xC08) && ((cpuid & 0xF) == 0x0)) {
+
+               if (reg == tap_prod_id) {
+                       regval = 0x000F00F0;
+                       goto out;
+               }
+
                switch (reg) {
                case OMAP_TAP_IDCODE  : regval = 0x0B7AE02F; break;
                /* Making DevType as 0xF in ES1 to differ from ES2 */
-               case OMAP_TAP_PROD_ID : regval = 0x000F00F0; break;
                case OMAP_TAP_DIE_ID_0: regval = 0x01000000; break;
                case OMAP_TAP_DIE_ID_1: regval = 0x1012d687; break;
                case OMAP_TAP_DIE_ID_2: regval = 0x00000000; break;
                case OMAP_TAP_DIE_ID_3: regval = 0x2d2c0000; break;
                }
        } else
-               regval = __raw_readl(TAP_BASE + reg);
+               regval = __raw_readl(tap_base + reg);
 
+out:
        return regval;
 
 }
@@ -204,7 +201,7 @@ void __init omap2_check_revision(void)
        u8  rev;
 
        idcode = read_tap_reg(OMAP_TAP_IDCODE);
-       prod_id = read_tap_reg(OMAP_TAP_PROD_ID);
+       prod_id = read_tap_reg(tap_prod_id);
        hawkeye = (idcode >> 12) & 0xffff;
        rev = (idcode >> 28) & 0x0f;
        dev_type = (prod_id >> 16) & 0x0f;
@@ -269,3 +266,13 @@ void __init omap2_check_revision(void)
 
 }
 
+void __init omap2_set_globals_tap(struct omap_globals *omap2_globals)
+{
+       class = omap2_globals->class;
+       tap_base = omap2_globals->tap;
+
+       if (class == 0x3430)
+               tap_prod_id = 0x0210;
+       else
+               tap_prod_id = 0x0208;
+}
index 7c3d6289c05ff50412b2e4ad75b50ba1ff8c4212..5ea64f926ed592e9348581080ee0bac061ab31a5 100644 (file)
@@ -4,8 +4,11 @@
  * OMAP2 I/O mapping code
  *
  * Copyright (C) 2005 Nokia Corporation
- * Author: Juha Yrjölä <juha.yrjola@nokia.com>
- * Updated map desc to add 2430 support : <x0khasim@ti.com>
+ * Copyright (C) 2007 Texas Instruments
+ *
+ * Author:
+ *     Juha Yrjola <juha.yrjola@nokia.com>
+ *     Syed Khasim <x0khasim@ti.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
 
 #include <mach/mux.h>
 #include <mach/omapfb.h>
+#include <mach/sram.h>
+
+#include "memory.h"
+
+#include "clock.h"
+
+#include <mach/powerdomain.h>
+
+#include "powerdomains.h"
 
-extern void omap_sram_init(void);
-extern int omap2_clk_init(void);
-extern void omap2_check_revision(void);
-extern void omap2_init_memory(void);
-extern void gpmc_init(void);
-extern void omapfb_reserve_sdram(void);
+#include <mach/clockdomain.h>
+#include "clockdomains.h"
 
 /*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
  */
-static struct map_desc omap2_io_desc[] __initdata = {
+
+#ifdef CONFIG_ARCH_OMAP24XX
+static struct map_desc omap24xx_io_desc[] __initdata = {
        {
                .virtual        = L3_24XX_VIRT,
                .pfn            = __phys_to_pfn(L3_24XX_PHYS),
@@ -43,12 +53,39 @@ static struct map_desc omap2_io_desc[] __initdata = {
                .type           = MT_DEVICE
        },
        {
-               .virtual        = L4_24XX_VIRT,
-               .pfn            = __phys_to_pfn(L4_24XX_PHYS),
-               .length         = L4_24XX_SIZE,
-               .type           = MT_DEVICE
+               .virtual        = L4_24XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_24XX_PHYS),
+               .length         = L4_24XX_SIZE,
+               .type           = MT_DEVICE
        },
+};
+
+#ifdef CONFIG_ARCH_OMAP2420
+static struct map_desc omap242x_io_desc[] __initdata = {
+       {
+               .virtual        = DSP_MEM_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MEM_24XX_PHYS),
+               .length         = DSP_MEM_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_IPI_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_IPI_24XX_PHYS),
+               .length         = DSP_IPI_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = DSP_MMU_24XX_VIRT,
+               .pfn            = __phys_to_pfn(DSP_MMU_24XX_PHYS),
+               .length         = DSP_MMU_24XX_SIZE,
+               .type           = MT_DEVICE
+       },
+};
+
+#endif
+
 #ifdef CONFIG_ARCH_OMAP2430
+static struct map_desc omap243x_io_desc[] __initdata = {
        {
                .virtual        = L4_WK_243X_VIRT,
                .pfn            = __phys_to_pfn(L4_WK_243X_PHYS),
@@ -61,30 +98,90 @@ static struct map_desc omap2_io_desc[] __initdata = {
                .length         = OMAP243X_GPMC_SIZE,
                .type           = MT_DEVICE
        },
+       {
+               .virtual        = OMAP243X_SDRC_VIRT,
+               .pfn            = __phys_to_pfn(OMAP243X_SDRC_PHYS),
+               .length         = OMAP243X_SDRC_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = OMAP243X_SMS_VIRT,
+               .pfn            = __phys_to_pfn(OMAP243X_SMS_PHYS),
+               .length         = OMAP243X_SMS_SIZE,
+               .type           = MT_DEVICE
+       },
+};
+#endif
 #endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+static struct map_desc omap34xx_io_desc[] __initdata = {
        {
-               .virtual        = DSP_MEM_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_MEM_24XX_PHYS),
-               .length         = DSP_MEM_24XX_SIZE,
+               .virtual        = L3_34XX_VIRT,
+               .pfn            = __phys_to_pfn(L3_34XX_PHYS),
+               .length         = L3_34XX_SIZE,
                .type           = MT_DEVICE
        },
        {
-               .virtual        = DSP_IPI_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_IPI_24XX_PHYS),
-               .length         = DSP_IPI_24XX_SIZE,
+               .virtual        = L4_34XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_34XX_PHYS),
+               .length         = L4_34XX_SIZE,
                .type           = MT_DEVICE
        },
        {
-               .virtual        = DSP_MMU_24XX_VIRT,
-               .pfn            = __phys_to_pfn(DSP_MMU_24XX_PHYS),
-               .length         = DSP_MMU_24XX_SIZE,
+               .virtual        = L4_WK_34XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_WK_34XX_PHYS),
+               .length         = L4_WK_34XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = OMAP34XX_GPMC_VIRT,
+               .pfn            = __phys_to_pfn(OMAP34XX_GPMC_PHYS),
+               .length         = OMAP34XX_GPMC_SIZE,
                .type           = MT_DEVICE
-       }
+       },
+       {
+               .virtual        = OMAP343X_SMS_VIRT,
+               .pfn            = __phys_to_pfn(OMAP343X_SMS_PHYS),
+               .length         = OMAP343X_SMS_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = OMAP343X_SDRC_VIRT,
+               .pfn            = __phys_to_pfn(OMAP343X_SDRC_PHYS),
+               .length         = OMAP343X_SDRC_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = L4_PER_34XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_PER_34XX_PHYS),
+               .length         = L4_PER_34XX_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = L4_EMU_34XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_EMU_34XX_PHYS),
+               .length         = L4_EMU_34XX_SIZE,
+               .type           = MT_DEVICE
+       },
 };
+#endif
 
 void __init omap2_map_common_io(void)
 {
-       iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+#if defined(CONFIG_ARCH_OMAP2420)
+       iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
+       iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2430)
+       iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
+       iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
+#endif
+
+#if defined(CONFIG_ARCH_OMAP34XX)
+       iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
+#endif
 
        /* Normally devicemaps_init() would flush caches and tlb after
         * mdesc->map_io(), but we must also do it here because of the CPU
@@ -101,12 +198,9 @@ void __init omap2_map_common_io(void)
 void __init omap2_init_common_hw(void)
 {
        omap2_mux_init();
+       pwrdm_init(powerdomains_omap);
+       clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
        omap2_clk_init();
-/*
- * Need to Fix this for 2430
- */
-#ifndef CONFIG_ARCH_OMAP2430
        omap2_init_memory();
-#endif
        gpmc_init();
 }
index 196a9565a8dc206ddcbd567673ba1a5323244b42..d354e0fe4477ad450668b16e462258e26b2b4853 100644 (file)
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <asm/mach/irq.h>
-#include <asm/irq.h>
 
-#define INTC_REVISION  0x0000
-#define INTC_SYSCONFIG 0x0010
-#define INTC_SYSSTATUS 0x0014
-#define INTC_CONTROL   0x0048
-#define INTC_MIR_CLEAR0        0x0088
-#define INTC_MIR_SET0  0x008c
+
+/* selected INTC register offsets */
+
+#define INTC_REVISION          0x0000
+#define INTC_SYSCONFIG         0x0010
+#define INTC_SYSSTATUS         0x0014
+#define INTC_CONTROL           0x0048
+#define INTC_MIR_CLEAR0                0x0088
+#define INTC_MIR_SET0          0x008c
+#define INTC_PENDING_IRQ0      0x0098
+
+/* Number of IRQ state bits in each MIR register */
+#define IRQ_BITS_PER_REG       32
 
 /*
  * OMAP2 has a number of different interrupt controllers, each interrupt
  * for each bank.. when in doubt, consult the TRM.
  */
 static struct omap_irq_bank {
-       unsigned long base_reg;
+       void __iomem *base_reg;
        unsigned int nr_irqs;
 } __attribute__ ((aligned(4))) irq_banks[] = {
        {
                /* MPU INTC */
-               .base_reg       = IO_ADDRESS(OMAP24XX_IC_BASE),
+               .base_reg       = 0,
                .nr_irqs        = 96,
-       }, {
-               /* XXX: DSP INTC */
-       }
+       },
 };
 
+/* INTC bank register get/set */
+
+static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
+{
+       __raw_writel(val, bank->base_reg + reg);
+}
+
+static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg)
+{
+       return __raw_readl(bank->base_reg + reg);
+}
+
 /* XXX: FIQ and additional INTC support (only MPU at the moment) */
 static void omap_ack_irq(unsigned int irq)
 {
-       __raw_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL);
+       intc_bank_write_reg(0x1, &irq_banks[0], INTC_CONTROL);
 }
 
 static void omap_mask_irq(unsigned int irq)
 {
-       int offset = (irq >> 5) << 5;
+       int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
-       if (irq >= 64) {
-               irq %= 64;
-       } else if (irq >= 32) {
-               irq %= 32;
-       }
+       irq &= (IRQ_BITS_PER_REG - 1);
 
-       __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
+       intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);
 }
 
 static void omap_unmask_irq(unsigned int irq)
 {
-       int offset = (irq >> 5) << 5;
+       int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
-       if (irq >= 64) {
-               irq %= 64;
-       } else if (irq >= 32) {
-               irq %= 32;
-       }
+       irq &= (IRQ_BITS_PER_REG - 1);
 
-       __raw_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset);
+       intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset);
 }
 
 static void omap_mask_ack_irq(unsigned int irq)
@@ -93,20 +101,20 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
 {
        unsigned long tmp;
 
-       tmp = __raw_readl(bank->base_reg + INTC_REVISION) & 0xff;
-       printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx "
+       tmp = intc_bank_read_reg(bank, INTC_REVISION) & 0xff;
+       printk(KERN_INFO "IRQ: Found an INTC at 0x%p "
                         "(revision %ld.%ld) with %d interrupts\n",
                         bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
 
-       tmp = __raw_readl(bank->base_reg + INTC_SYSCONFIG);
+       tmp = intc_bank_read_reg(bank, INTC_SYSCONFIG);
        tmp |= 1 << 1;  /* soft reset */
-       __raw_writel(tmp, bank->base_reg + INTC_SYSCONFIG);
+       intc_bank_write_reg(tmp, bank, INTC_SYSCONFIG);
 
-       while (!(__raw_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1))
+       while (!(intc_bank_read_reg(bank, INTC_SYSSTATUS) & 0x1))
                /* Wait for reset to complete */;
 
        /* Enable autoidle */
-       __raw_writel(1 << 0, bank->base_reg + INTC_SYSCONFIG);
+       intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
 }
 
 void __init omap_init_irq(void)
@@ -118,9 +126,10 @@ void __init omap_init_irq(void)
        for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
                struct omap_irq_bank *bank = irq_banks + i;
 
-               /* XXX */
-               if (!bank->base_reg)
-                       continue;
+               if (cpu_is_omap24xx())
+                       bank->base_reg = OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE);
+               else if (cpu_is_omap34xx())
+                       bank->base_reg = OMAP2_IO_ADDRESS(OMAP34XX_IC_BASE);
 
                omap_irq_bank_init_one(bank);
 
index b261f1f80b5e0fd7131a5586ca04bb6d9796a3ea..cae3ebe249b3cdbacb18ece2b34e06aba82d17d5 100644 (file)
@@ -89,6 +89,30 @@ static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
                        .disable        = omap_mcbsp_clk_disable,
                },
        },
+       {
+               .clk = {
+                       .name           = "mcbsp_clk",
+                       .id             = 3,
+                       .enable         = omap_mcbsp_clk_enable,
+                       .disable        = omap_mcbsp_clk_disable,
+               },
+       },
+       {
+               .clk = {
+                       .name           = "mcbsp_clk",
+                       .id             = 4,
+                       .enable         = omap_mcbsp_clk_enable,
+                       .disable        = omap_mcbsp_clk_disable,
+               },
+       },
+       {
+               .clk = {
+                       .name           = "mcbsp_clk",
+                       .id             = 5,
+                       .enable         = omap_mcbsp_clk_enable,
+                       .disable        = omap_mcbsp_clk_disable,
+               },
+       },
 };
 
 #define omap_mcbsp_clks_size   ARRAY_SIZE(omap_mcbsp_clks)
@@ -117,25 +141,14 @@ static void omap2_mcbsp_request(unsigned int id)
                omap2_mcbsp2_mux_setup();
 }
 
-static int omap2_mcbsp_check(unsigned int id)
-{
-       if (id > OMAP_MAX_MCBSP_COUNT - 1) {
-               printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
-               return -ENODEV;
-       }
-       return 0;
-}
-
 static struct omap_mcbsp_ops omap2_mcbsp_ops = {
        .request        = omap2_mcbsp_request,
-       .check          = omap2_mcbsp_check,
 };
 
-#ifdef CONFIG_ARCH_OMAP24XX
-static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
+#ifdef CONFIG_ARCH_OMAP2420
+static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
        {
                .phys_base      = OMAP24XX_MCBSP1_BASE,
-               .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
@@ -145,7 +158,6 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
-               .virt_base      = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
@@ -154,17 +166,70 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
                .clk_name       = "mcbsp_clk",
        },
 };
-#define OMAP24XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap24xx_mcbsp_pdata)
+#define OMAP2420_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2420_mcbsp_pdata)
 #else
-#define omap24xx_mcbsp_pdata           NULL
-#define OMAP24XX_MCBSP_PDATA_SZ                0
+#define omap2420_mcbsp_pdata           NULL
+#define OMAP2420_MCBSP_PDATA_SZ                0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
+       {
+               .phys_base      = OMAP24XX_MCBSP1_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
+               .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP24XX_MCBSP2_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
+               .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP2430_MCBSP3_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
+               .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP2430_MCBSP4_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
+               .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP2430_MCBSP5_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
+               .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+};
+#define OMAP2430_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2430_mcbsp_pdata)
+#else
+#define omap2430_mcbsp_pdata           NULL
+#define OMAP2430_MCBSP_PDATA_SZ                0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP34XX
 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
        {
                .phys_base      = OMAP34XX_MCBSP1_BASE,
-               .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
@@ -174,7 +239,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
        },
        {
                .phys_base      = OMAP34XX_MCBSP2_BASE,
-               .virt_base      = IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
                .dma_rx_sync    = OMAP24XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
@@ -182,6 +246,33 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .ops            = &omap2_mcbsp_ops,
                .clk_name       = "mcbsp_clk",
        },
+       {
+               .phys_base      = OMAP34XX_MCBSP3_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP3_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
+               .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP34XX_MCBSP4_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP4_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
+               .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
+       {
+               .phys_base      = OMAP34XX_MCBSP5_BASE,
+               .dma_rx_sync    = OMAP24XX_DMA_MCBSP5_RX,
+               .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
+               .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
+               .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
+               .ops            = &omap2_mcbsp_ops,
+               .clk_name       = "mcbsp_clk",
+       },
 };
 #define OMAP34XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap34xx_mcbsp_pdata)
 #else
@@ -189,7 +280,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
 #define OMAP34XX_MCBSP_PDATA_SZ                0
 #endif
 
-int __init omap2_mcbsp_init(void)
+static int __init omap2_mcbsp_init(void)
 {
        int i;
 
@@ -199,10 +290,24 @@ int __init omap2_mcbsp_init(void)
                clk_register(&omap_mcbsp_clks[i].clk);
        }
 
-       if (cpu_is_omap24xx())
-               omap_mcbsp_register_board_cfg(omap24xx_mcbsp_pdata,
-                                               OMAP24XX_MCBSP_PDATA_SZ);
+       if (cpu_is_omap2420())
+               omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
+       if (cpu_is_omap2430())
+               omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
+       if (cpu_is_omap34xx())
+               omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
+
+       mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
+                                                               GFP_KERNEL);
+       if (!mcbsp_ptr)
+               return -ENOMEM;
 
+       if (cpu_is_omap2420())
+               omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
+                                               OMAP2420_MCBSP_PDATA_SZ);
+       if (cpu_is_omap2430())
+               omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
+                                               OMAP2430_MCBSP_PDATA_SZ);
        if (cpu_is_omap34xx())
                omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
                                                OMAP34XX_MCBSP_PDATA_SZ);
index ab1462b02e6e97f9ce306bc878a5b7782ebf38f0..882c7022429260a291b60221b2ee587098608a22 100644 (file)
@@ -101,6 +101,17 @@ u32 omap2_reprogram_sdrc(u32 level, u32 force)
        return prev;
 }
 
+#if !defined(CONFIG_ARCH_OMAP2)
+void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
+                               u32 base_cs, u32 force_unlock)
+{
+}
+void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
+                                     u32 mem_type)
+{
+}
+#endif
+
 void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
 {
        unsigned long dll_cnt;
@@ -165,6 +176,9 @@ void __init omap2_init_memory(void)
 {
        u32 l;
 
+       if (!cpu_is_omap2420())
+               return;
+
        l = sms_read_reg(SMS_SYSCONFIG);
        l &= ~(0x3 << 3);
        l |= (0x2 << 3);
index 9a280b50a89306e977771e55dc3c0793d58980f2..bb3db80a7c46105861fe7f908139d740802dcac4 100644 (file)
@@ -14,6 +14,9 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef ARCH_ARM_MACH_OMAP2_MEMORY_H
+#define ARCH_ARM_MACH_OMAP2_MEMORY_H
+
 /* Memory timings */
 #define M_DDR          1
 #define M_LOCK_CTRL    (1 << 2)
@@ -34,3 +37,7 @@ extern u32 omap2_memory_get_fast_dll_ctrl(void);
 extern u32 omap2_memory_get_type(void);
 u32 omap2_dll_force_needed(void);
 u32 omap2_reprogram_sdrc(u32 level, u32 force);
+void __init omap2_init_memory(void);
+void __init gpmc_init(void);
+
+#endif
index 6b7d672058b9b360ff1b4034c070f3ab64091e00..b1393673d95d802b97f2a24494cddad16340de0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-omap2/mux.c
  *
- * OMAP2 pin multiplexing configurations
+ * OMAP2 and OMAP3 pin multiplexing configurations
  *
  * Copyright (C) 2004 - 2008 Texas Instruments Inc.
  * Copyright (C) 2003 - 2008 Nokia Corporation
@@ -220,16 +220,222 @@ MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF",  0x0131, 0,      0,      0,      1)
 #define OMAP24XX_PINS_SZ       0
 #endif /* CONFIG_ARCH_OMAP24XX */
 
-#define OMAP24XX_PULL_ENA      (1 << 3)
-#define OMAP24XX_PULL_UP       (1 << 4)
+#ifdef CONFIG_ARCH_OMAP34XX
+static struct pin_config __initdata_or_module omap34xx_pins[] = {
+/*
+ *             Name, reg-offset,
+ *             mux-mode | [active-mode | off-mode]
+ */
+
+/* 34xx I2C */
+MUX_CFG_34XX("K21_34XX_I2C1_SCL", 0x1ba,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("J21_34XX_I2C1_SDA", 0x1bc,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AF15_34XX_I2C2_SCL", 0x1be,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AE15_34XX_I2C2_SDA", 0x1c0,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AF14_34XX_I2C3_SCL", 0x1c2,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AG14_34XX_I2C3_SDA", 0x1c4,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AD26_34XX_I2C4_SCL", 0xa00,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AE26_34XX_I2C4_SDA", 0xa02,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_INPUT_PULLUP)
+
+/* PHY - HSUSB: 12-pin ULPI PHY: Port 1*/
+MUX_CFG_34XX("Y8_3430_USB1HS_PHY_CLK", 0x5da,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("Y9_3430_USB1HS_PHY_STP", 0x5d8,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AA14_3430_USB1HS_PHY_DIR", 0x5ec,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA11_3430_USB1HS_PHY_NXT", 0x5ee,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W13_3430_USB1HS_PHY_D0", 0x5dc,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W12_3430_USB1HS_PHY_D1", 0x5de,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W11_3430_USB1HS_PHY_D2", 0x5e0,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y11_3430_USB1HS_PHY_D3", 0x5ea,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W9_3430_USB1HS_PHY_D4", 0x5e4,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y12_3430_USB1HS_PHY_D5", 0x5e6,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W8_3430_USB1HS_PHY_D6", 0x5e8,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y13_3430_USB1HS_PHY_D7", 0x5e2,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+
+/* PHY - HSUSB: 12-pin ULPI PHY: Port 2*/
+MUX_CFG_34XX("AA8_3430_USB2HS_PHY_CLK", 0x5f0,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AA10_3430_USB2HS_PHY_STP", 0x5f2,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AA9_3430_USB2HS_PHY_DIR", 0x5f4,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB11_3430_USB2HS_PHY_NXT", 0x5f6,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB10_3430_USB2HS_PHY_D0", 0x5f8,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB9_3430_USB2HS_PHY_D1", 0x5fa,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W3_3430_USB2HS_PHY_D2", 0x1d4,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T4_3430_USB2HS_PHY_D3", 0x1de,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T3_3430_USB2HS_PHY_D4", 0x1d8,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("R3_3430_USB2HS_PHY_D5", 0x1da,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("R4_3430_USB2HS_PHY_D6", 0x1dc,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T2_3430_USB2HS_PHY_D7", 0x1d6,
+               OMAP34XX_MUX_MODE3 | OMAP34XX_PIN_INPUT_PULLDOWN)
+
+/* TLL - HSUSB: 12-pin TLL Port 1*/
+MUX_CFG_34XX("Y8_3430_USB1HS_TLL_CLK", 0x5da,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y9_3430_USB1HS_TLL_STP", 0x5d8,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AA14_3430_USB1HS_TLL_DIR", 0x5ec,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA11_3430_USB1HS_TLL_NXT", 0x5ee,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W13_3430_USB1HS_TLL_D0", 0x5dc,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W12_3430_USB1HS_TLL_D1", 0x5de,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W11_3430_USB1HS_TLL_D2", 0x5e0,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y11_3430_USB1HS_TLL_D3", 0x5ea,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W9_3430_USB1HS_TLL_D4", 0x5e4,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y12_3430_USB1HS_TLL_D5", 0x5e6,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W8_3430_USB1HS_TLL_D6", 0x5e8,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y13_3430_USB1HS_TLL_D7", 0x5e2,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+
+/* TLL - HSUSB: 12-pin TLL Port 2*/
+MUX_CFG_34XX("AA8_3430_USB2HS_TLL_CLK", 0x5f0,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA10_3430_USB2HS_TLL_STP", 0x5f2,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AA9_3430_USB2HS_TLL_DIR", 0x5f4,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB11_3430_USB2HS_TLL_NXT", 0x5f6,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB10_3430_USB2HS_TLL_D0", 0x5f8,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB9_3430_USB2HS_TLL_D1", 0x5fa,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W3_3430_USB2HS_TLL_D2", 0x1d4,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T4_3430_USB2HS_TLL_D3", 0x1de,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T3_3430_USB2HS_TLL_D4", 0x1d8,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("R3_3430_USB2HS_TLL_D5", 0x1da,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("R4_3430_USB2HS_TLL_D6", 0x1dc,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T2_3430_USB2HS_TLL_D7", 0x1d6,
+               OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLDOWN)
+
+/* TLL - HSUSB: 12-pin TLL Port 3*/
+MUX_CFG_34XX("AA6_3430_USB3HS_TLL_CLK", 0x180,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB3_3430_USB3HS_TLL_STP", 0x166,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLUP)
+MUX_CFG_34XX("AA3_3430_USB3HS_TLL_DIR", 0x168,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y3_3430_USB3HS_TLL_NXT", 0x16a,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA5_3430_USB3HS_TLL_D0", 0x186,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y4_3430_USB3HS_TLL_D1", 0x184,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y5_3430_USB3HS_TLL_D2", 0x188,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W5_3430_USB3HS_TLL_D3", 0x18a,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB12_3430_USB3HS_TLL_D4", 0x16c,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB13_3430_USB3HS_TLL_D5", 0x16e,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA13_3430_USB3HS_TLL_D6", 0x170,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AA12_3430_USB3HS_TLL_D7", 0x172,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+
+/* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */
+MUX_CFG_34XX("AF10_3430_USB1FS_PHY_MM1_RXDP", 0x5d8,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AG9_3430_USB1FS_PHY_MM1_RXDM", 0x5ee,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W13_3430_USB1FS_PHY_MM1_RXRCV", 0x5dc,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W12_3430_USB1FS_PHY_MM1_TXSE0", 0x5de,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W11_3430_USB1FS_PHY_MM1_TXDAT", 0x5e0,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("Y11_3430_USB1FS_PHY_MM1_TXEN_N", 0x5ea,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT)
+
+/* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */
+MUX_CFG_34XX("AF7_3430_USB2FS_PHY_MM2_RXDP", 0x5f2,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AH7_3430_USB2FS_PHY_MM2_RXDM", 0x5f6,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB10_3430_USB2FS_PHY_MM2_RXRCV", 0x5f8,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AB9_3430_USB2FS_PHY_MM2_TXSE0", 0x5fa,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("W3_3430_USB2FS_PHY_MM2_TXDAT", 0x1d4,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("T4_3430_USB2FS_PHY_MM2_TXEN_N", 0x1de,
+               OMAP34XX_MUX_MODE5 | OMAP34XX_PIN_OUTPUT)
+
+/* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */
+MUX_CFG_34XX("AH3_3430_USB3FS_PHY_MM3_RXDP", 0x166,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AE3_3430_USB3FS_PHY_MM3_RXDM", 0x16a,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AD1_3430_USB3FS_PHY_MM3_RXRCV", 0x186,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AE1_3430_USB3FS_PHY_MM3_TXSE0", 0x184,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AD2_3430_USB3FS_PHY_MM3_TXDAT", 0x188,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_INPUT_PULLDOWN)
+MUX_CFG_34XX("AC1_3430_USB3FS_PHY_MM3_TXEN_N", 0x18a,
+               OMAP34XX_MUX_MODE6 | OMAP34XX_PIN_OUTPUT)
+
+};
+
+#define OMAP34XX_PINS_SZ       ARRAY_SIZE(omap34xx_pins)
+
+#else
+#define omap34xx_pins          NULL
+#define OMAP34XX_PINS_SZ       0
+#endif /* CONFIG_ARCH_OMAP34XX */
 
 #if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
-void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u8 reg)
+static void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u16 reg)
 {
        u16 orig;
        u8 warn = 0, debug = 0;
 
-       orig = omap_ctrl_readb(cfg->mux_reg);
+       if (cpu_is_omap24xx())
+               orig = omap_ctrl_readb(cfg->mux_reg);
+       else
+               orig = omap_ctrl_readw(cfg->mux_reg);
 
 #ifdef CONFIG_OMAP_MUX_DEBUG
        debug = cfg->debug;
@@ -255,9 +461,9 @@ int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg)
        spin_lock_irqsave(&mux_spin_lock, flags);
        reg |= cfg->mask & 0x7;
        if (cfg->pull_val)
-               reg |= OMAP24XX_PULL_ENA;
+               reg |= OMAP2_PULL_ENA;
        if (cfg->pu_pd_val)
-               reg |= OMAP24XX_PULL_UP;
+               reg |= OMAP2_PULL_UP;
        omap2_cfg_debug(cfg, reg);
        omap_ctrl_writeb(reg, cfg->mux_reg);
        spin_unlock_irqrestore(&mux_spin_lock, flags);
@@ -265,7 +471,26 @@ int __init_or_module omap24xx_cfg_reg(const struct pin_config *cfg)
        return 0;
 }
 #else
-#define omap24xx_cfg_reg       0
+#define omap24xx_cfg_reg       NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+static int __init_or_module omap34xx_cfg_reg(const struct pin_config *cfg)
+{
+       static DEFINE_SPINLOCK(mux_spin_lock);
+       unsigned long flags;
+       u16 reg = 0;
+
+       spin_lock_irqsave(&mux_spin_lock, flags);
+       reg |= cfg->mux_val;
+       omap2_cfg_debug(cfg, reg);
+       omap_ctrl_writew(reg, cfg->mux_reg);
+       spin_unlock_irqrestore(&mux_spin_lock, flags);
+
+       return 0;
+}
+#else
+#define omap34xx_cfg_reg       NULL
 #endif
 
 int __init omap2_mux_init(void)
@@ -274,6 +499,10 @@ int __init omap2_mux_init(void)
                arch_mux_cfg.pins       = omap24xx_pins;
                arch_mux_cfg.size       = OMAP24XX_PINS_SZ;
                arch_mux_cfg.cfg_reg    = omap24xx_cfg_reg;
+       } else if (cpu_is_omap34xx()) {
+               arch_mux_cfg.pins       = omap34xx_pins;
+               arch_mux_cfg.size       = OMAP34XX_PINS_SZ;
+               arch_mux_cfg.cfg_reg    = omap34xx_cfg_reg;
        }
 
        return omap_mux_register(&arch_mux_cfg);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
new file mode 100644 (file)
index 0000000..73e2971
--- /dev/null
@@ -0,0 +1,1113 @@
+/*
+ * OMAP powerdomain control
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifdef CONFIG_OMAP_DEBUG_POWERDOMAIN
+# define DEBUG
+#endif
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/atomic.h>
+
+#include "cm.h"
+#include "cm-regbits-34xx.h"
+#include "prm.h"
+#include "prm-regbits-34xx.h"
+
+#include <mach/cpu.h>
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
+
+/* pwrdm_list contains all registered struct powerdomains */
+static LIST_HEAD(pwrdm_list);
+
+/*
+ * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
+ * protect pwrdm_clkdms[] during clkdm add/del ops
+ */
+static DEFINE_RWLOCK(pwrdm_rwlock);
+
+
+/* Private functions */
+
+static u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+       u32 v;
+
+       v = prm_read_mod_reg(domain, idx);
+       v &= mask;
+       v >>= __ffs(mask);
+
+       return v;
+}
+
+static struct powerdomain *_pwrdm_lookup(const char *name)
+{
+       struct powerdomain *pwrdm, *temp_pwrdm;
+
+       pwrdm = NULL;
+
+       list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
+               if (!strcmp(name, temp_pwrdm->name)) {
+                       pwrdm = temp_pwrdm;
+                       break;
+               }
+       }
+
+       return pwrdm;
+}
+
+/* _pwrdm_deps_lookup - look up the specified powerdomain in a pwrdm list */
+static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
+                                             struct pwrdm_dep *deps)
+{
+       struct pwrdm_dep *pd;
+
+       if (!pwrdm || !deps || !omap_chip_is(pwrdm->omap_chip))
+               return ERR_PTR(-EINVAL);
+
+       for (pd = deps; pd; pd++) {
+
+               if (!omap_chip_is(pd->omap_chip))
+                       continue;
+
+               if (!pd->pwrdm && pd->pwrdm_name)
+                       pd->pwrdm = pwrdm_lookup(pd->pwrdm_name);
+
+               if (pd->pwrdm == pwrdm)
+                       break;
+
+       }
+
+       if (!pd)
+               return ERR_PTR(-ENOENT);
+
+       return pd->pwrdm;
+}
+
+
+/* Public functions */
+
+/**
+ * pwrdm_init - set up the powerdomain layer
+ *
+ * Loop through the list of powerdomains, registering all that are
+ * available on the current CPU. If pwrdm_list is supplied and not
+ * null, all of the referenced powerdomains will be registered.  No
+ * return value.
+ */
+void pwrdm_init(struct powerdomain **pwrdm_list)
+{
+       struct powerdomain **p = NULL;
+
+       if (pwrdm_list)
+               for (p = pwrdm_list; *p; p++)
+                       pwrdm_register(*p);
+}
+
+/**
+ * pwrdm_register - register a powerdomain
+ * @pwrdm: struct powerdomain * to register
+ *
+ * Adds a powerdomain to the internal powerdomain list.  Returns
+ * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
+ * already registered by the provided name, or 0 upon success.
+ */
+int pwrdm_register(struct powerdomain *pwrdm)
+{
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (!omap_chip_is(pwrdm->omap_chip))
+               return -EINVAL;
+
+       write_lock_irqsave(&pwrdm_rwlock, flags);
+       if (_pwrdm_lookup(pwrdm->name)) {
+               ret = -EEXIST;
+               goto pr_unlock;
+       }
+
+       list_add(&pwrdm->node, &pwrdm_list);
+
+       pr_debug("powerdomain: registered %s\n", pwrdm->name);
+       ret = 0;
+
+pr_unlock:
+       write_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return ret;
+}
+
+/**
+ * pwrdm_unregister - unregister a powerdomain
+ * @pwrdm: struct powerdomain * to unregister
+ *
+ * Removes a powerdomain from the internal powerdomain list.  Returns
+ * -EINVAL if pwrdm argument is NULL.
+ */
+int pwrdm_unregister(struct powerdomain *pwrdm)
+{
+       unsigned long flags;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       write_lock_irqsave(&pwrdm_rwlock, flags);
+       list_del(&pwrdm->node);
+       write_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       pr_debug("powerdomain: unregistered %s\n", pwrdm->name);
+
+       return 0;
+}
+
+/**
+ * pwrdm_lookup - look up a powerdomain by name, return a pointer
+ * @name: name of powerdomain
+ *
+ * Find a registered powerdomain by its name.  Returns a pointer to the
+ * struct powerdomain if found, or NULL otherwise.
+ */
+struct powerdomain *pwrdm_lookup(const char *name)
+{
+       struct powerdomain *pwrdm;
+       unsigned long flags;
+
+       if (!name)
+               return NULL;
+
+       read_lock_irqsave(&pwrdm_rwlock, flags);
+       pwrdm = _pwrdm_lookup(name);
+       read_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return pwrdm;
+}
+
+/**
+ * pwrdm_for_each - call function on each registered clockdomain
+ * @fn: callback function *
+ *
+ * Call the supplied function for each registered powerdomain.  The
+ * callback function can return anything but 0 to bail out early from
+ * the iterator.  The callback function is called with the pwrdm_rwlock
+ * held for reading, so no powerdomain structure manipulation
+ * functions should be called from the callback, although hardware
+ * powerdomain control functions are fine.  Returns the last return
+ * value of the callback function, which should be 0 for success or
+ * anything else to indicate failure; or -EINVAL if the function
+ * pointer is null.
+ */
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
+{
+       struct powerdomain *temp_pwrdm;
+       unsigned long flags;
+       int ret = 0;
+
+       if (!fn)
+               return -EINVAL;
+
+       read_lock_irqsave(&pwrdm_rwlock, flags);
+       list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
+               ret = (*fn)(temp_pwrdm);
+               if (ret)
+                       break;
+       }
+       read_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return ret;
+}
+
+/**
+ * pwrdm_add_clkdm - add a clockdomain to a powerdomain
+ * @pwrdm: struct powerdomain * to add the clockdomain to
+ * @clkdm: struct clockdomain * to associate with a powerdomain
+ *
+ * Associate the clockdomain 'clkdm' with a powerdomain 'pwrdm'.  This
+ * enables the use of pwrdm_for_each_clkdm().  Returns -EINVAL if
+ * presented with invalid pointers; -ENOMEM if memory could not be allocated;
+ * or 0 upon success.
+ */
+int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
+{
+       unsigned long flags;
+       int i;
+       int ret = -EINVAL;
+
+       if (!pwrdm || !clkdm)
+               return -EINVAL;
+
+       pr_debug("powerdomain: associating clockdomain %s with powerdomain "
+                "%s\n", clkdm->name, pwrdm->name);
+
+       write_lock_irqsave(&pwrdm_rwlock, flags);
+
+       for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
+               if (!pwrdm->pwrdm_clkdms[i])
+                       break;
+#ifdef DEBUG
+               if (pwrdm->pwrdm_clkdms[i] == clkdm) {
+                       ret = -EINVAL;
+                       goto pac_exit;
+               }
+#endif
+       }
+
+       if (i == PWRDM_MAX_CLKDMS) {
+               pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
+                        "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
+               WARN_ON(1);
+               ret = -ENOMEM;
+               goto pac_exit;
+       }
+
+       pwrdm->pwrdm_clkdms[i] = clkdm;
+
+       ret = 0;
+
+pac_exit:
+       write_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return ret;
+}
+
+/**
+ * pwrdm_del_clkdm - remove a clockdomain from a powerdomain
+ * @pwrdm: struct powerdomain * to add the clockdomain to
+ * @clkdm: struct clockdomain * to associate with a powerdomain
+ *
+ * Dissociate the clockdomain 'clkdm' from the powerdomain
+ * 'pwrdm'. Returns -EINVAL if presented with invalid pointers;
+ * -ENOENT if the clkdm was not associated with the powerdomain, or 0
+ * upon success.
+ */
+int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
+{
+       unsigned long flags;
+       int ret = -EINVAL;
+       int i;
+
+       if (!pwrdm || !clkdm)
+               return -EINVAL;
+
+       pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
+                "%s\n", clkdm->name, pwrdm->name);
+
+       write_lock_irqsave(&pwrdm_rwlock, flags);
+
+       for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
+               if (pwrdm->pwrdm_clkdms[i] == clkdm)
+                       break;
+
+       if (i == PWRDM_MAX_CLKDMS) {
+               pr_debug("powerdomain: clkdm %s not associated with pwrdm "
+                        "%s ?!\n", clkdm->name, pwrdm->name);
+               ret = -ENOENT;
+               goto pdc_exit;
+       }
+
+       pwrdm->pwrdm_clkdms[i] = NULL;
+
+       ret = 0;
+
+pdc_exit:
+       write_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return ret;
+}
+
+/**
+ * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm
+ * @pwrdm: struct powerdomain * to iterate over
+ * @fn: callback function *
+ *
+ * Call the supplied function for each clockdomain in the powerdomain
+ * 'pwrdm'.  The callback function can return anything but 0 to bail
+ * out early from the iterator.  The callback function is called with
+ * the pwrdm_rwlock held for reading, so no powerdomain structure
+ * manipulation functions should be called from the callback, although
+ * hardware powerdomain control functions are fine.  Returns -EINVAL
+ * if presented with invalid pointers; or passes along the last return
+ * value of the callback function, which should be 0 for success or
+ * anything else to indicate failure.
+ */
+int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
+                        int (*fn)(struct powerdomain *pwrdm,
+                                  struct clockdomain *clkdm))
+{
+       unsigned long flags;
+       int ret = 0;
+       int i;
+
+       if (!fn)
+               return -EINVAL;
+
+       read_lock_irqsave(&pwrdm_rwlock, flags);
+
+       for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
+               ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);
+
+       read_unlock_irqrestore(&pwrdm_rwlock, flags);
+
+       return ret;
+}
+
+
+/**
+ * pwrdm_add_wkdep - add a wakeup dependency from pwrdm2 to pwrdm1
+ * @pwrdm1: wake this struct powerdomain * up (dependent)
+ * @pwrdm2: when this struct powerdomain * wakes up (source)
+ *
+ * When the powerdomain represented by pwrdm2 wakes up (due to an
+ * interrupt), wake up pwrdm1. Implemented in hardware on the OMAP,
+ * this feature is designed to reduce wakeup latency of the dependent
+ * powerdomain.  Returns -EINVAL if presented with invalid powerdomain
+ * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
+ * 0 upon success.
+ */
+int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear wake up of "
+                        "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       pr_debug("powerdomain: hardware will wake up %s when %s wakes up\n",
+                pwrdm1->name, pwrdm2->name);
+
+       prm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
+                            pwrdm1->prcm_offs, PM_WKDEP);
+
+       return 0;
+}
+
+/**
+ * pwrdm_del_wkdep - remove a wakeup dependency from pwrdm2 to pwrdm1
+ * @pwrdm1: wake this struct powerdomain * up (dependent)
+ * @pwrdm2: when this struct powerdomain * wakes up (source)
+ *
+ * Remove a wakeup dependency that causes pwrdm1 to wake up when pwrdm2
+ * wakes up.  Returns -EINVAL if presented with invalid powerdomain
+ * pointers, -ENOENT if pwrdm2 cannot wake up pwrdm1 in hardware, or
+ * 0 upon success.
+ */
+int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear wake up of "
+                        "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       pr_debug("powerdomain: hardware will no longer wake up %s after %s "
+                "wakes up\n", pwrdm1->name, pwrdm2->name);
+
+       prm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
+                              pwrdm1->prcm_offs, PM_WKDEP);
+
+       return 0;
+}
+
+/**
+ * pwrdm_read_wkdep - read wakeup dependency state from pwrdm2 to pwrdm1
+ * @pwrdm1: wake this struct powerdomain * up (dependent)
+ * @pwrdm2: when this struct powerdomain * wakes up (source)
+ *
+ * Return 1 if a hardware wakeup dependency exists wherein pwrdm1 will be
+ * awoken when pwrdm2 wakes up; 0 if dependency is not set; -EINVAL
+ * if either powerdomain pointer is invalid; or -ENOENT if the hardware
+ * is incapable.
+ *
+ * REVISIT: Currently this function only represents software-controllable
+ * wakeup dependencies.  Wakeup dependencies fixed in hardware are not
+ * yet handled here.
+ */
+int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->wkdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear wake up of "
+                        "%s when %s wakes up\n", pwrdm1->name, pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       return prm_read_mod_bits_shift(pwrdm1->prcm_offs, PM_WKDEP,
+                                       (1 << pwrdm2->dep_bit));
+}
+
+/**
+ * pwrdm_add_sleepdep - add a sleep dependency from pwrdm2 to pwrdm1
+ * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
+ * @pwrdm2: when this struct powerdomain * is active (source)
+ *
+ * Prevent pwrdm1 from automatically going inactive (and then to
+ * retention or off) if pwrdm2 is still active.         Returns -EINVAL if
+ * presented with invalid powerdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep dependencies,
+ * -ENOENT if the specified dependency cannot be set in hardware, or
+ * 0 upon success.
+ */
+int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       if (!cpu_is_omap34xx())
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear sleep "
+                        "dependency affecting %s from %s\n", pwrdm1->name,
+                        pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       pr_debug("powerdomain: will prevent %s from sleeping if %s is active\n",
+                pwrdm1->name, pwrdm2->name);
+
+       cm_set_mod_reg_bits((1 << pwrdm2->dep_bit),
+                           pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
+
+       return 0;
+}
+
+/**
+ * pwrdm_del_sleepdep - remove a sleep dependency from pwrdm2 to pwrdm1
+ * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
+ * @pwrdm2: when this struct powerdomain * is active (source)
+ *
+ * Allow pwrdm1 to automatically go inactive (and then to retention or
+ * off), independent of the activity state of pwrdm2.  Returns -EINVAL
+ * if presented with invalid powerdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep dependencies,
+ * -ENOENT if the specified dependency cannot be cleared in hardware, or
+ * 0 upon success.
+ */
+int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       if (!cpu_is_omap34xx())
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear sleep "
+                        "dependency affecting %s from %s\n", pwrdm1->name,
+                        pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       pr_debug("powerdomain: will no longer prevent %s from sleeping if "
+                "%s is active\n", pwrdm1->name, pwrdm2->name);
+
+       cm_clear_mod_reg_bits((1 << pwrdm2->dep_bit),
+                             pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP);
+
+       return 0;
+}
+
+/**
+ * pwrdm_read_sleepdep - read sleep dependency state from pwrdm2 to pwrdm1
+ * @pwrdm1: prevent this struct powerdomain * from sleeping (dependent)
+ * @pwrdm2: when this struct powerdomain * is active (source)
+ *
+ * Return 1 if a hardware sleep dependency exists wherein pwrdm1 will
+ * not be allowed to automatically go inactive if pwrdm2 is active;
+ * 0 if pwrdm1's automatic power state inactivity transition is independent
+ * of pwrdm2's; -EINVAL if either powerdomain pointer is invalid or called
+ * on a machine that does not support software-configurable hardware sleep
+ * dependencies; or -ENOENT if the hardware is incapable.
+ *
+ * REVISIT: Currently this function only represents software-controllable
+ * sleep dependencies. Sleep dependencies fixed in hardware are not
+ * yet handled here.
+ */
+int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2)
+{
+       struct powerdomain *p;
+
+       if (!pwrdm1)
+               return -EINVAL;
+
+       if (!cpu_is_omap34xx())
+               return -EINVAL;
+
+       p = _pwrdm_deps_lookup(pwrdm2, pwrdm1->sleepdep_srcs);
+       if (IS_ERR(p)) {
+               pr_debug("powerdomain: hardware cannot set/clear sleep "
+                        "dependency affecting %s from %s\n", pwrdm1->name,
+                        pwrdm2->name);
+               return IS_ERR(p);
+       }
+
+       return prm_read_mod_bits_shift(pwrdm1->prcm_offs, OMAP3430_CM_SLEEPDEP,
+                                       (1 << pwrdm2->dep_bit));
+}
+
+/**
+ * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain
+ * @pwrdm: struct powerdomain *
+ *
+ * Return the number of controllable memory banks in powerdomain pwrdm,
+ * starting with 1.  Returns -EINVAL if the powerdomain pointer is null.
+ */
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       return pwrdm->banks;
+}
+
+/**
+ * pwrdm_set_next_pwrst - set next powerdomain power state
+ * @pwrdm: struct powerdomain * to set
+ * @pwrst: one of the PWRDM_POWER_* macros
+ *
+ * Set the powerdomain pwrdm's next power state to pwrst.  The powerdomain
+ * may not enter this state immediately if the preconditions for this state
+ * have not been satisfied.  Returns -EINVAL if the powerdomain pointer is
+ * null or if the power state is invalid for the powerdomin, or returns 0
+ * upon success.
+ */
+int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (!(pwrdm->pwrsts & (1 << pwrst)))
+               return -EINVAL;
+
+       pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
+                pwrdm->name, pwrst);
+
+       prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
+                            (pwrst << OMAP_POWERSTATE_SHIFT),
+                            pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_read_next_pwrst - get next powerdomain power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain pwrdm's next power state.  Returns -EINVAL
+ * if the powerdomain pointer is null or returns the next power state
+ * upon success.
+ */
+int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTCTRL,
+                                       OMAP_POWERSTATE_MASK);
+}
+
+/**
+ * pwrdm_read_pwrst - get current powerdomain power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain pwrdm's current power state. Returns -EINVAL
+ * if the powerdomain pointer is null or returns the current power state
+ * upon success.
+ */
+int pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
+                                       OMAP_POWERSTATEST_MASK);
+}
+
+/**
+ * pwrdm_read_prev_pwrst - get previous powerdomain power state
+ * @pwrdm: struct powerdomain * to get previous power state
+ *
+ * Return the powerdomain pwrdm's previous power state.  Returns -EINVAL
+ * if the powerdomain pointer is null or returns the previous power state
+ * upon success.
+ */
+int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
+                                       OMAP3430_LASTPOWERSTATEENTERED_MASK);
+}
+
+/**
+ * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
+ * @pwrdm: struct powerdomain * to set
+ * @pwrst: one of the PWRDM_POWER_* macros
+ *
+ * Set the next power state that the logic portion of the powerdomain
+ * pwrdm will enter when the powerdomain enters retention.  This will
+ * be either RETENTION or OFF, if supported.  Returns -EINVAL if the
+ * powerdomain pointer is null or the target power state is not not
+ * supported, or returns 0 upon success.
+ */
+int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
+               return -EINVAL;
+
+       pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
+                pwrdm->name, pwrst);
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE,
+                            (pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE)),
+                            pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_set_mem_onst - set memory power state while powerdomain ON
+ * @pwrdm: struct powerdomain * to set
+ * @bank: memory bank number to set (0-3)
+ * @pwrst: one of the PWRDM_POWER_* macros
+ *
+ * Set the next power state that memory bank x of the powerdomain
+ * pwrdm will enter when the powerdomain enters the ON state.  Bank
+ * will be a number from 0 to 3, and represents different types of
+ * memory, depending on the powerdomain.  Returns -EINVAL if the
+ * powerdomain pointer is null or the target power state is not not
+ * supported for this memory bank, -EEXIST if the target memory bank
+ * does not exist or is not controllable, or returns 0 upon success.
+ */
+int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
+{
+       u32 m;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (pwrdm->banks < (bank + 1))
+               return -EEXIST;
+
+       if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
+               return -EINVAL;
+
+       pr_debug("powerdomain: setting next memory powerstate for domain %s "
+                "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       switch (bank) {
+       case 0:
+               m = OMAP3430_SHAREDL1CACHEFLATONSTATE_MASK;
+               break;
+       case 1:
+               m = OMAP3430_L1FLATMEMONSTATE_MASK;
+               break;
+       case 2:
+               m = OMAP3430_SHAREDL2CACHEFLATONSTATE_MASK;
+               break;
+       case 3:
+               m = OMAP3430_L2FLATMEMONSTATE_MASK;
+               break;
+       default:
+               WARN_ON(1); /* should never happen */
+               return -EEXIST;
+       }
+
+       prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)),
+                            pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
+ * @pwrdm: struct powerdomain * to set
+ * @bank: memory bank number to set (0-3)
+ * @pwrst: one of the PWRDM_POWER_* macros
+ *
+ * Set the next power state that memory bank x of the powerdomain
+ * pwrdm will enter when the powerdomain enters the RETENTION state.
+ * Bank will be a number from 0 to 3, and represents different types
+ * of memory, depending on the powerdomain.  pwrst will be either
+ * RETENTION or OFF, if supported. Returns -EINVAL if the powerdomain
+ * pointer is null or the target power state is not not supported for
+ * this memory bank, -EEXIST if the target memory bank does not exist
+ * or is not controllable, or returns 0 upon success.
+ */
+int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
+{
+       u32 m;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (pwrdm->banks < (bank + 1))
+               return -EEXIST;
+
+       if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
+               return -EINVAL;
+
+       pr_debug("powerdomain: setting next memory powerstate for domain %s "
+                "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       switch (bank) {
+       case 0:
+               m = OMAP3430_SHAREDL1CACHEFLATRETSTATE;
+               break;
+       case 1:
+               m = OMAP3430_L1FLATMEMRETSTATE;
+               break;
+       case 2:
+               m = OMAP3430_SHAREDL2CACHEFLATRETSTATE;
+               break;
+       case 3:
+               m = OMAP3430_L2FLATMEMRETSTATE;
+               break;
+       default:
+               WARN_ON(1); /* should never happen */
+               return -EEXIST;
+       }
+
+       prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
+                            PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_read_logic_pwrst - get current powerdomain logic retention power state
+ * @pwrdm: struct powerdomain * to get current logic retention power state
+ *
+ * Return the current power state that the logic portion of
+ * powerdomain pwrdm will enter
+ * Returns -EINVAL if the powerdomain pointer is null or returns the
+ * current logic retention power state upon success.
+ */
+int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST,
+                                       OMAP3430_LOGICSTATEST);
+}
+
+/**
+ * pwrdm_read_prev_logic_pwrst - get previous powerdomain logic power state
+ * @pwrdm: struct powerdomain * to get previous logic power state
+ *
+ * Return the powerdomain pwrdm's logic power state.  Returns -EINVAL
+ * if the powerdomain pointer is null or returns the previous logic
+ * power state upon success.
+ */
+int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
+                                       OMAP3430_LASTLOGICSTATEENTERED);
+}
+
+/**
+ * pwrdm_read_mem_pwrst - get current memory bank power state
+ * @pwrdm: struct powerdomain * to get current memory bank power state
+ * @bank: memory bank number (0-3)
+ *
+ * Return the powerdomain pwrdm's current memory power state for bank
+ * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
+ * the target memory bank does not exist or is not controllable, or
+ * returns the current memory power state upon success.
+ */
+int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (pwrdm->banks < (bank + 1))
+               return -EEXIST;
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       switch (bank) {
+       case 0:
+               m = OMAP3430_SHAREDL1CACHEFLATSTATEST_MASK;
+               break;
+       case 1:
+               m = OMAP3430_L1FLATMEMSTATEST_MASK;
+               break;
+       case 2:
+               m = OMAP3430_SHAREDL2CACHEFLATSTATEST_MASK;
+               break;
+       case 3:
+               m = OMAP3430_L2FLATMEMSTATEST_MASK;
+               break;
+       default:
+               WARN_ON(1); /* should never happen */
+               return -EEXIST;
+       }
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs, PM_PWSTST, m);
+}
+
+/**
+ * pwrdm_read_prev_mem_pwrst - get previous memory bank power state
+ * @pwrdm: struct powerdomain * to get previous memory bank power state
+ * @bank: memory bank number (0-3)
+ *
+ * Return the powerdomain pwrdm's previous memory power state for bank
+ * x.  Returns -EINVAL if the powerdomain pointer is null, -EEXIST if
+ * the target memory bank does not exist or is not controllable, or
+ * returns the previous memory power state upon success.
+ */
+int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (pwrdm->banks < (bank + 1))
+               return -EEXIST;
+
+       /*
+        * The register bit names below may not correspond to the
+        * actual names of the bits in each powerdomain's register,
+        * but the type of value returned is the same for each
+        * powerdomain.
+        */
+       switch (bank) {
+       case 0:
+               m = OMAP3430_LASTMEM1STATEENTERED_MASK;
+               break;
+       case 1:
+               m = OMAP3430_LASTMEM2STATEENTERED_MASK;
+               break;
+       case 2:
+               m = OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
+               break;
+       case 3:
+               m = OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
+               break;
+       default:
+               WARN_ON(1); /* should never happen */
+               return -EEXIST;
+       }
+
+       return prm_read_mod_bits_shift(pwrdm->prcm_offs,
+                                       OMAP3430_PM_PREPWSTST, m);
+}
+
+/**
+ * pwrdm_clear_all_prev_pwrst - clear previous powerstate register for a pwrdm
+ * @pwrdm: struct powerdomain * to clear
+ *
+ * Clear the powerdomain's previous power state register.  Clears the
+ * entire register, including logic and memory bank previous power states.
+ * Returns -EINVAL if the powerdomain pointer is null, or returns 0 upon
+ * success.
+ */
+int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       /*
+        * XXX should get the powerdomain's current state here;
+        * warn & fail if it is not ON.
+        */
+
+       pr_debug("powerdomain: clearing previous power state reg for %s\n",
+                pwrdm->name);
+
+       prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
+
+       return 0;
+}
+
+/**
+ * pwrdm_enable_hdwr_sar - enable automatic hardware SAR for a pwrdm
+ * @pwrdm: struct powerdomain *
+ *
+ * Enable automatic context save-and-restore upon power state change
+ * for some devices in a powerdomain.  Warning: this only affects a
+ * subset of devices in a powerdomain; check the TRM closely.  Returns
+ * -EINVAL if the powerdomain pointer is null or if the powerdomain
+ * does not support automatic save-and-restore, or returns 0 upon
+ * success.
+ */
+int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
+               return -EINVAL;
+
+       pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
+                pwrdm->name);
+
+       prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
+                            pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_disable_hdwr_sar - disable automatic hardware SAR for a pwrdm
+ * @pwrdm: struct powerdomain *
+ *
+ * Disable automatic context save-and-restore upon power state change
+ * for some devices in a powerdomain.  Warning: this only affects a
+ * subset of devices in a powerdomain; check the TRM closely.  Returns
+ * -EINVAL if the powerdomain pointer is null or if the powerdomain
+ * does not support automatic save-and-restore, or returns 0 upon
+ * success.
+ */
+int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
+               return -EINVAL;
+
+       pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
+                pwrdm->name);
+
+       prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
+                            pwrdm->prcm_offs, PM_PWSTCTRL);
+
+       return 0;
+}
+
+/**
+ * pwrdm_has_hdwr_sar - test whether powerdomain supports hardware SAR
+ * @pwrdm: struct powerdomain *
+ *
+ * Returns 1 if powerdomain 'pwrdm' supports hardware save-and-restore
+ * for some devices, or 0 if it does not.
+ */
+bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm)
+{
+       return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
+}
+
+/**
+ * pwrdm_wait_transition - wait for powerdomain power transition to finish
+ * @pwrdm: struct powerdomain * to wait for
+ *
+ * If the powerdomain pwrdm is in the process of a state transition,
+ * spin until it completes the power transition, or until an iteration
+ * bailout value is reached. Returns -EINVAL if the powerdomain
+ * pointer is null, -EAGAIN if the bailout value was reached, or
+ * returns 0 upon success.
+ */
+int pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+       u32 c = 0;
+
+       if (!pwrdm)
+               return -EINVAL;
+
+       /*
+        * REVISIT: pwrdm_wait_transition() may be better implemented
+        * via a callback and a periodic timer check -- how long do we expect
+        * powerdomain transitions to take?
+        */
+
+       /* XXX Is this udelay() value meaningful? */
+       while ((prm_read_mod_reg(pwrdm->prcm_offs, PM_PWSTST) &
+               OMAP_INTRANSITION) &&
+              (c++ < PWRDM_TRANSITION_BAILOUT))
+               udelay(1);
+
+       if (c >= PWRDM_TRANSITION_BAILOUT) {
+               printk(KERN_ERR "powerdomain: waited too long for "
+                      "powerdomain %s to complete transition\n", pwrdm->name);
+               return -EAGAIN;
+       }
+
+       pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+       return 0;
+}
+
+
diff --git a/arch/arm/mach-omap2/powerdomains.h b/arch/arm/mach-omap2/powerdomains.h
new file mode 100644 (file)
index 0000000..1e151fa
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * OMAP2/3 common powerdomain definitions
+ *
+ * Copyright (C) 2007-8 Texas Instruments, Inc.
+ * Copyright (C) 2007-8 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Debugging and integration fixes by Jouni Högander
+ *
+ * This program is free software; you can 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 ARCH_ARM_MACH_OMAP2_POWERDOMAINS
+#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS
+
+/*
+ * This file contains all of the powerdomains that have some element
+ * of software control for the OMAP24xx and OMAP34XX chips.
+ *
+ * A few notes:
+ *
+ * This is not an exhaustive listing of powerdomains on the chips; only
+ * powerdomains that can be controlled in software.
+ *
+ * A useful validation rule for struct powerdomain:
+ * Any powerdomain referenced by a wkdep_srcs or sleepdep_srcs array
+ * must have a dep_bit assigned.  So wkdep_srcs/sleepdep_srcs are really
+ * just software-controllable dependencies.  Non-software-controllable
+ * dependencies do exist, but they are not encoded below (yet).
+ *
+ * 24xx does not support programmable sleep dependencies (SLEEPDEP)
+ *
+ */
+
+/*
+ * The names for the DSP/IVA2 powerdomains are confusing.
+ *
+ * Most OMAP chips have an on-board DSP.
+ *
+ * On the 2420, this is a 'C55 DSP called, simply, the DSP.  Its
+ * powerdomain is called the "DSP power domain."  On the 2430, the
+ * on-board DSP is a 'C64 DSP, now called the IVA2 or IVA2.1.  Its
+ * powerdomain is still called the "DSP power domain." On the 3430,
+ * the DSP is a 'C64 DSP like the 2430, also known as the IVA2; but
+ * its powerdomain is now called the "IVA2 power domain."
+ *
+ * The 2420 also has something called the IVA, which is a separate ARM
+ * core, and has nothing to do with the DSP/IVA2.
+ *
+ * Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
+ * address offset is different between the C55 and C64 DSPs.
+ *
+ * The overly-specific dep_bit names are due to a bit name collision
+ * with CM_FCLKEN_{DSP,IVA2}.  The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
+ * value are the same for all powerdomains: 2
+ */
+
+/*
+ * XXX should dep_bit be a mask, so we can test to see if it is 0 as a
+ * sanity check?
+ * XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
+ */
+
+#include <mach/powerdomain.h>
+
+#include "prcm-common.h"
+#include "prm.h"
+#include "cm.h"
+
+/* OMAP2/3-common powerdomains and wakeup dependencies */
+
+/*
+ * 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
+ * 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
+ * 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
+ */
+static struct pwrdm_dep gfx_sgx_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
+                                           CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
+                                           CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+/*
+ * 3430: CM_SLEEPDEP_CAM: MPU
+ * 3430ES1: CM_SLEEPDEP_GFX: MPU
+ * 3430ES2: CM_SLEEPDEP_SGX: MPU
+ */
+static struct pwrdm_dep cam_gfx_sleepdeps[] = {
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+
+#include "powerdomains24xx.h"
+#include "powerdomains34xx.h"
+
+
+/*
+ * OMAP2/3 common powerdomains
+ */
+
+/*
+ * The GFX powerdomain is not present on 3430ES2, but currently we do not
+ * have a macro to filter it out at compile-time.
+ */
+static struct powerdomain gfx_pwrdm = {
+       .name             = "gfx_pwrdm",
+       .prcm_offs        = GFX_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
+                                          CHIP_IS_OMAP3430ES1),
+       .wkdep_srcs       = gfx_sgx_wkdeps,
+       .sleepdep_srcs    = cam_gfx_sleepdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+static struct powerdomain wkup_pwrdm = {
+       .name           = "wkup_pwrdm",
+       .prcm_offs      = WKUP_MOD,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+       .dep_bit        = OMAP_EN_WKUP_SHIFT,
+};
+
+
+
+/* As powerdomains are added or removed above, this list must also be changed */
+static struct powerdomain *powerdomains_omap[] __initdata = {
+
+       &gfx_pwrdm,
+       &wkup_pwrdm,
+
+#ifdef CONFIG_ARCH_OMAP24XX
+       &dsp_pwrdm,
+       &mpu_24xx_pwrdm,
+       &core_24xx_pwrdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+       &mdm_pwrdm,
+#endif
+
+#ifdef CONFIG_ARCH_OMAP34XX
+       &iva2_pwrdm,
+       &mpu_34xx_pwrdm,
+       &neon_pwrdm,
+       &core_34xx_pwrdm,
+       &cam_pwrdm,
+       &dss_pwrdm,
+       &per_pwrdm,
+       &emu_pwrdm,
+       &sgx_pwrdm,
+       &usbhost_pwrdm,
+#endif
+
+       NULL
+};
+
+
+#endif
diff --git a/arch/arm/mach-omap2/powerdomains24xx.h b/arch/arm/mach-omap2/powerdomains24xx.h
new file mode 100644 (file)
index 0000000..9f08dc3
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * OMAP24XX powerdomain definitions
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Debugging and integration fixes by Jouni Högander
+ *
+ * This program is free software; you can 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 ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX
+#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS24XX
+
+/*
+ * N.B. If powerdomains are added or removed from this file, update
+ * the array in mach-omap2/powerdomains.h.
+ */
+
+#include <mach/powerdomain.h>
+
+#include "prcm-common.h"
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "cm.h"
+#include "cm-regbits-24xx.h"
+
+/* 24XX powerdomains and dependencies */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+
+
+/* Wakeup dependency source arrays */
+
+/*
+ * 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
+ * 2430 PM_WKDEP_MDM: same as above
+ */
+static struct pwrdm_dep dsp_mdm_24xx_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       { NULL },
+};
+
+/*
+ * 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
+ * 2430 adds MDM
+ */
+static struct pwrdm_dep mpu_24xx_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "dsp_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "mdm_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+       },
+       { NULL },
+};
+
+/*
+ * 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
+ * 2430 adds MDM
+ */
+static struct pwrdm_dep core_24xx_wkdeps[] = {
+       {
+               .pwrdm_name = "dsp_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "gfx_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
+       },
+       {
+               .pwrdm_name = "mdm_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+       },
+       { NULL },
+};
+
+
+/* Powerdomains */
+
+static struct powerdomain dsp_pwrdm = {
+       .name             = "dsp_pwrdm",
+       .prcm_offs        = OMAP24XX_DSP_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+       .dep_bit          = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
+       .wkdep_srcs       = dsp_mdm_24xx_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,
+       },
+};
+
+static struct powerdomain mpu_24xx_pwrdm = {
+       .name             = "mpu_pwrdm",
+       .prcm_offs        = MPU_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+       .dep_bit          = OMAP24XX_EN_MPU_SHIFT,
+       .wkdep_srcs       = mpu_24xx_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,
+       },
+};
+
+static struct powerdomain core_24xx_pwrdm = {
+       .name             = "core_pwrdm",
+       .prcm_offs        = CORE_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
+       .wkdep_srcs       = core_24xx_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .dep_bit          = OMAP24XX_EN_CORE_SHIFT,
+       .banks            = 3,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_OFF_RET,    /* MEM1RETSTATE */
+               [1] = PWRSTS_OFF_RET,    /* MEM2RETSTATE */
+               [2] = PWRSTS_OFF_RET,    /* MEM3RETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+               [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+               [2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
+       },
+};
+
+#endif    /* CONFIG_ARCH_OMAP24XX */
+
+
+
+/*
+ * 2430-specific powerdomains
+ */
+
+#ifdef CONFIG_ARCH_OMAP2430
+
+/* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
+
+/* Another case of bit name collisions between several registers: EN_MDM */
+static struct powerdomain mdm_pwrdm = {
+       .name             = "mdm_pwrdm",
+       .prcm_offs        = OMAP2430_MDM_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+       .dep_bit          = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
+       .wkdep_srcs       = dsp_mdm_24xx_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+#endif     /* CONFIG_ARCH_OMAP2430 */
+
+
+#endif
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h
new file mode 100644 (file)
index 0000000..f573f71
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * OMAP34XX powerdomain definitions
+ *
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ * Debugging and integration fixes by Jouni Högander
+ *
+ * This program is free software; you can 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 ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX
+#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS34XX
+
+/*
+ * N.B. If powerdomains are added or removed from this file, update
+ * the array in mach-omap2/powerdomains.h.
+ */
+
+#include <mach/powerdomain.h>
+
+#include "prcm-common.h"
+#include "prm.h"
+#include "prm-regbits-34xx.h"
+#include "cm.h"
+#include "cm-regbits-34xx.h"
+
+/*
+ * 34XX-specific powerdomains, dependencies
+ */
+
+#ifdef CONFIG_ARCH_OMAP34XX
+
+/*
+ * 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
+ * (USBHOST is ES2 only)
+ */
+static struct pwrdm_dep per_usbhost_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+/*
+ * 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
+ */
+static struct pwrdm_dep mpu_34xx_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "dss_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "per_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+/*
+ * 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
+ */
+static struct pwrdm_dep iva2_wkdeps[] = {
+       {
+               .pwrdm_name = "core_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "dss_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "per_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+
+/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
+static struct pwrdm_dep cam_dss_wkdeps[] = {
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "wkup_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+/* 3430: PM_WKDEP_NEON: MPU */
+static struct pwrdm_dep neon_wkdeps[] = {
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+
+/* Sleep dependency source arrays for 34xx-specific pwrdms - 34XX only */
+
+/*
+ * 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
+ * 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
+ */
+static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = {
+       {
+               .pwrdm_name = "mpu_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       {
+               .pwrdm_name = "iva2_pwrdm",
+               .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+       },
+       { NULL },
+};
+
+
+/*
+ * Powerdomains
+ */
+
+static struct powerdomain iva2_pwrdm = {
+       .name             = "iva2_pwrdm",
+       .prcm_offs        = OMAP3430_IVA2_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .dep_bit          = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
+       .wkdep_srcs       = iva2_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .banks            = 4,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_OFF_RET,
+               [1] = PWRSTS_OFF_RET,
+               [2] = PWRSTS_OFF_RET,
+               [3] = PWRSTS_OFF_RET,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,
+               [1] = PWRDM_POWER_ON,
+               [2] = PWRSTS_OFF_ON,
+               [3] = PWRDM_POWER_ON,
+       },
+};
+
+static struct powerdomain mpu_34xx_pwrdm = {
+       .name             = "mpu_pwrdm",
+       .prcm_offs        = MPU_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .dep_bit          = OMAP3430_EN_MPU_SHIFT,
+       .wkdep_srcs       = mpu_34xx_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_OFF_RET,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_OFF_ON,
+       },
+};
+
+/* No wkdeps or sleepdeps for 34xx core apparently */
+static struct powerdomain core_34xx_pwrdm = {
+       .name             = "core_pwrdm",
+       .prcm_offs        = CORE_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .dep_bit          = OMAP3430_EN_CORE_SHIFT,
+       .banks            = 2,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_OFF_RET,    /* MEM1RETSTATE */
+               [1] = PWRSTS_OFF_RET,    /* MEM2RETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
+               [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+       },
+};
+
+/* Another case of bit name collisions between several registers: EN_DSS */
+static struct powerdomain dss_pwrdm = {
+       .name             = "dss_pwrdm",
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .prcm_offs        = OMAP3430_DSS_MOD,
+       .dep_bit          = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+       .wkdep_srcs       = cam_dss_wkdeps,
+       .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+static struct powerdomain sgx_pwrdm = {
+       .name             = "sgx_pwrdm",
+       .prcm_offs        = OMAP3430ES2_SGX_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+       .wkdep_srcs       = gfx_sgx_wkdeps,
+       .sleepdep_srcs    = cam_gfx_sleepdeps,
+       /* XXX This is accurate for 3430 SGX, but what about GFX? */
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+static struct powerdomain cam_pwrdm = {
+       .name             = "cam_pwrdm",
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .prcm_offs        = OMAP3430_CAM_MOD,
+       .wkdep_srcs       = cam_dss_wkdeps,
+       .sleepdep_srcs    = cam_gfx_sleepdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+static struct powerdomain per_pwrdm = {
+       .name             = "per_pwrdm",
+       .prcm_offs        = OMAP3430_PER_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .dep_bit          = OMAP3430_EN_PER_SHIFT,
+       .wkdep_srcs       = per_usbhost_wkdeps,
+       .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+static struct powerdomain emu_pwrdm = {
+       .name           = "emu_pwrdm",
+       .prcm_offs      = OMAP3430_EMU_MOD,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+static struct powerdomain neon_pwrdm = {
+       .name             = "neon_pwrdm",
+       .prcm_offs        = OMAP3430_NEON_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+       .wkdep_srcs       = neon_wkdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+};
+
+static struct powerdomain usbhost_pwrdm = {
+       .name             = "usbhost_pwrdm",
+       .prcm_offs        = OMAP3430ES2_USBHOST_MOD,
+       .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
+       .wkdep_srcs       = per_usbhost_wkdeps,
+       .sleepdep_srcs    = dss_per_usbhost_sleepdeps,
+       .pwrsts           = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret = PWRDM_POWER_RET,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+       },
+};
+
+#endif    /* CONFIG_ARCH_OMAP34XX */
+
+
+#endif
index 54c32f482131819666dc81c79a2b5661ae43d515..4a32822ff3fca38834ca4c267c85fa6a5334ce28 100644 (file)
 #define OMAP3430_ST_GPT2                               (1 << 3)
 
 /* CM_SLEEPDEP_PER, PM_WKDEP_IVA2, PM_WKDEP_MPU, PM_WKDEP_PER shared bits */
-#define OMAP3430_EN_CORE                               (1 << 0)
+#define OMAP3430_EN_CORE_SHIFT                         0
+#define OMAP3430_EN_CORE_MASK                          (1 << 0)
 
 #endif
 
index c6d17a3378ec3035c683920136f49f3395053829..4002051c20b98457bdc12142e8d328d33fedc4a4 100644 (file)
 #define OMAP24XX_WKUP1_EN                              (1 << 0)
 
 /* PM_WKDEP_GFX, PM_WKDEP_MPU, PM_WKDEP_DSP, PM_WKDEP_MDM shared bits */
-#define OMAP24XX_EN_MPU                                        (1 << 1)
-#define OMAP24XX_EN_CORE                               (1 << 0)
+#define OMAP24XX_EN_MPU_SHIFT                          1
+#define OMAP24XX_EN_MPU_MASK                           (1 << 1)
+#define OMAP24XX_EN_CORE_SHIFT                                 0
+#define OMAP24XX_EN_CORE_MASK                          (1 << 0)
 
 /*
  * PM_PWSTCTRL_MPU, PM_PWSTCTRL_GFX, PM_PWSTCTRL_DSP, PM_PWSTCTRL_MDM
 /* 2430 calls GLOBALWMPU_RST "GLOBALWARM_RST" instead */
 
 /* PM_WKDEP_MPU specific bits */
-#define OMAP2430_PM_WKDEP_MPU_EN_MDM                   (1 << 5)
-#define OMAP24XX_PM_WKDEP_MPU_EN_DSP                   (1 << 2)
+#define OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT             5
+#define OMAP2430_PM_WKDEP_MPU_EN_MDM_MASK              (1 << 5)
+#define OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT             2
+#define OMAP24XX_PM_WKDEP_MPU_EN_DSP_MASK              (1 << 2)
 
 /* PM_EVGENCTRL_MPU specific bits */
 
index b4686bc345ca661bbe58c07d7d6ac4469f9b427c..5b5ecfe6c99916847b88b50db7235f3b8c51fedc 100644 (file)
@@ -68,7 +68,8 @@
 #define OMAP3430_VPINIDLE                              (1 << 0)
 
 /* PM_WKDEP_IVA2, PM_WKDEP_MPU shared bits */
-#define OMAP3430_EN_PER                                        (1 << 7)
+#define OMAP3430_EN_PER_SHIFT                          7
+#define OMAP3430_EN_PER_MASK                           (1 << 7)
 
 /* PM_PWSTCTRL_IVA2, PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE shared bits */
 #define OMAP3430_MEMORYCHANGE                          (1 << 3)
@@ -77,7 +78,7 @@
 #define OMAP3430_LOGICSTATEST                          (1 << 2)
 
 /* PM_PREPWSTST_IVA2, PM_PREPWSTST_CORE shared bits */
-#define OMAP3430_LASTLOGICSTATEENTERED                         (1 << 2)
+#define OMAP3430_LASTLOGICSTATEENTERED                 (1 << 2)
 
 /*
  * PM_PREPWSTST_IVA2, PM_PREPWSTST_MPU, PM_PREPWSTST_CORE,
 #define OMAP3430_EMULATION_MPU_RST                     (1 << 11)
 
 /* PM_WKDEP_MPU specific bits */
-#define OMAP3430_PM_WKDEP_MPU_EN_DSS                   (1 << 5)
-#define OMAP3430_PM_WKDEP_MPU_EN_IVA2                  (1 << 2)
+#define OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT             5
+#define OMAP3430_PM_WKDEP_MPU_EN_DSS_MASK              (1 << 5)
+#define OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT            2
+#define OMAP3430_PM_WKDEP_MPU_EN_IVA2_MASK             (1 << 2)
 
 /* PM_EVGENCTRL_MPU */
 #define OMAP3430_OFFLOADMODE_SHIFT                     3
index bbf41fc8e9a9102cd70003b59fb7c85615f4339e..e4dc4b17881d2e9cbc198aefb7bf148ac4e50688 100644 (file)
@@ -18,7 +18,7 @@
 
 #ifndef __ASSEMBLER__
 #define OMAP_PRM_REGADDR(module, reg)                                  \
-       (void __iomem *)IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg))
+                       IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg))
 #else
 #define OMAP2420_PRM_REGADDR(module, reg)                              \
                        IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
@@ -305,7 +305,8 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
  * 3430: PM_WKDEP_IVA2, PM_WKDEP_GFX, PM_WKDEP_DSS, PM_WKDEP_CAM,
  *      PM_WKDEP_PER
  */
-#define OMAP_EN_WKUP                                   (1 << 4)
+#define OMAP_EN_WKUP_SHIFT                             4
+#define OMAP_EN_WKUP_MASK                              (1 << 4)
 
 /*
  * 24XX: PM_PWSTCTRL_MPU, PM_PWSTCTRL_CORE, PM_PWSTCTRL_GFX,
index 7d9444adc5df6c94deb0189cb35fbba2d74d9512..4dcf39c285b94bac5e1e6292469299c633fcd0bf 100644 (file)
@@ -3,7 +3,7 @@
  *
  * OMAP2 serial support.
  *
- * Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2005-2008 Nokia Corporation
  * Author: Paul Mundt <paul.mundt@nokia.com>
  *
  * Based off of arch/arm/mach-omap/omap1/serial.c
 #include <mach/common.h>
 #include <mach/board.h>
 
-static struct clk * uart1_ick = NULL;
-static struct clk * uart1_fck = NULL;
-static struct clk * uart2_ick = NULL;
-static struct clk * uart2_fck = NULL;
-static struct clk * uart3_ick = NULL;
-static struct clk * uart3_fck = NULL;
+static struct clk *uart_ick[OMAP_MAX_NR_PORTS];
+static struct clk *uart_fck[OMAP_MAX_NR_PORTS];
 
 static struct plat_serial8250_port serial_platform_data[] = {
        {
-               .membase        = (char *)IO_ADDRESS(OMAP_UART1_BASE),
-               .mapbase        = (unsigned long)OMAP_UART1_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART1_BASE),
+               .mapbase        = OMAP_UART1_BASE,
                .irq            = 72,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+               .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
-               .membase        = (char *)IO_ADDRESS(OMAP_UART2_BASE),
-               .mapbase        = (unsigned long)OMAP_UART2_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART2_BASE),
+               .mapbase        = OMAP_UART2_BASE,
                .irq            = 73,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+               .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
-               .membase        = (char *)IO_ADDRESS(OMAP_UART3_BASE),
-               .mapbase        = (unsigned long)OMAP_UART3_BASE,
+               .membase        = IO_ADDRESS(OMAP_UART3_BASE),
+               .mapbase        = OMAP_UART3_BASE,
                .irq            = 74,
                .flags          = UPF_BOOT_AUTOCONF,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = OMAP16XX_BASE_BAUD * 16,
+               .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
                .flags          = 0
        }
@@ -70,7 +66,7 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
                                    int value)
 {
        offset <<= p->regshift;
-       __raw_writeb(value, (unsigned long)(p->membase + offset));
+       __raw_writeb(value, p->membase + offset);
 }
 
 /*
@@ -86,10 +82,27 @@ static inline void __init omap_serial_reset(struct plat_serial8250_port *p)
        serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
 }
 
-void __init omap_serial_init()
+void omap_serial_enable_clocks(int enable)
+{
+       int i;
+       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+               if (uart_ick[i] && uart_fck[i]) {
+                       if (enable) {
+                               clk_enable(uart_ick[i]);
+                               clk_enable(uart_fck[i]);
+                       } else {
+                               clk_disable(uart_ick[i]);
+                               clk_disable(uart_fck[i]);
+                       }
+               }
+       }
+}
+
+void __init omap_serial_init(void)
 {
        int i;
        const struct omap_uart_config *info;
+       char name[16];
 
        /*
         * Make sure the serial ports are muxed on at this point.
@@ -97,8 +110,7 @@ void __init omap_serial_init()
         * if not needed.
         */
 
-       info = omap_get_config(OMAP_TAG_UART,
-                              struct omap_uart_config);
+       info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
 
        if (info == NULL)
                return;
@@ -107,58 +119,26 @@ void __init omap_serial_init()
                struct plat_serial8250_port *p = serial_platform_data + i;
 
                if (!(info->enabled_uarts & (1 << i))) {
-                       p->membase = 0;
+                       p->membase = NULL;
                        p->mapbase = 0;
                        continue;
                }
 
-               switch (i) {
-               case 0:
-                       uart1_ick = clk_get(NULL, "uart1_ick");
-                       if (IS_ERR(uart1_ick))
-                               printk("Could not get uart1_ick\n");
-                       else {
-                               clk_enable(uart1_ick);
-                       }
-
-                       uart1_fck = clk_get(NULL, "uart1_fck");
-                       if (IS_ERR(uart1_fck))
-                               printk("Could not get uart1_fck\n");
-                       else {
-                               clk_enable(uart1_fck);
-                       }
-                       break;
-               case 1:
-                       uart2_ick = clk_get(NULL, "uart2_ick");
-                       if (IS_ERR(uart2_ick))
-                               printk("Could not get uart2_ick\n");
-                       else {
-                               clk_enable(uart2_ick);
-                       }
-
-                       uart2_fck = clk_get(NULL, "uart2_fck");
-                       if (IS_ERR(uart2_fck))
-                               printk("Could not get uart2_fck\n");
-                       else {
-                               clk_enable(uart2_fck);
-                       }
-                       break;
-               case 2:
-                       uart3_ick = clk_get(NULL, "uart3_ick");
-                       if (IS_ERR(uart3_ick))
-                               printk("Could not get uart3_ick\n");
-                       else {
-                               clk_enable(uart3_ick);
-                       }
-
-                       uart3_fck = clk_get(NULL, "uart3_fck");
-                       if (IS_ERR(uart3_fck))
-                               printk("Could not get uart3_fck\n");
-                       else {
-                               clk_enable(uart3_fck);
-                       }
-                       break;
-               }
+               sprintf(name, "uart%d_ick", i+1);
+               uart_ick[i] = clk_get(NULL, name);
+               if (IS_ERR(uart_ick[i])) {
+                       printk(KERN_ERR "Could not get uart%d_ick\n", i+1);
+                       uart_ick[i] = NULL;
+               } else
+                       clk_enable(uart_ick[i]);
+
+               sprintf(name, "uart%d_fck", i+1);
+               uart_fck[i] = clk_get(NULL, name);
+               if (IS_ERR(uart_fck[i])) {
+                       printk(KERN_ERR "Could not get uart%d_fck\n", i+1);
+                       uart_fck[i] = NULL;
+               } else
+                       clk_enable(uart_fck[i]);
 
                omap_serial_reset(p);
        }
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
deleted file mode 100644 (file)
index 87a706f..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/sleep.S
- *
- * (C) Copyright 2004
- * Texas Instruments, <www.ti.com>
- * Richard Woodruff <r-woodruff2@ti.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
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <mach/io.h>
-#include <mach/pm.h>
-
-#include "sdrc.h"
-
-/* First address of reserved address space?  apparently valid for OMAP2 & 3 */
-#define A_SDRC0_V              (0xC0000000)
-
-       .text
-
-/*
- * Forces OMAP into idle state
- *
- * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
- * for normal idles.
- *
- * Note: This code get's copied to internal SRAM at boot. When the OMAP
- *      wakes up it continues execution at the point it went to sleep.
- */
-ENTRY(omap24xx_idle_loop_suspend)
-       stmfd   sp!, {r0, lr}           @ save registers on stack
-       mov     r0, #0                  @ clear for mcr setup
-       mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
-       ldmfd   sp!, {r0, pc}           @ restore regs and return
-
-ENTRY(omap24xx_idle_loop_suspend_sz)
-       .word   . - omap24xx_idle_loop_suspend
-
-/*
- * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
- * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
- * SDRC.
- *
- * Input:
- * R0 :        DLL ctrl value pre-Sleep
- * R1 : Processor+Revision
- *     2420: 0x21 = 242xES1, 0x26 = 242xES2.2
- *     2430: 0x31 = 2430ES1, 0x32 = 2430ES2
- *
- * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
- * when we get called, but the DLL probably isn't.  We will wait a bit more in
- * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
- * if in unlocked mode.
- *
- * For less than 242x-ES2.2 upon wake from a sleep mode where the external
- * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
- * clock can pass into the PRCM can cause problems at DSP and IVA.
- * To work around this the code will switch to the 32kHz source prior to sleep.
- * Post sleep we will shift back to using the DPLL.  Apparently,
- * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
- * 3x12MHz + 3x32kHz clocks for a full switch.
- *
- * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
- * at wake
- */
-ENTRY(omap24xx_cpu_suspend)
-       stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
-       mov     r3, #0x0                @ clear for mrc call
-       mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
-       nop
-       nop
-       ldr     r3, A_SDRC_POWER        @ addr of sdrc power
-       ldr     r4, [r3]                @ value of sdrc power
-       orr     r4, r4, #0x40           @ enable self refresh on idle req
-       mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
-       str     r4, [r3]                @ make it so
-       mov     r2, #0
-       nop
-       mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
-       nop
-loop:
-       subs    r5, r5, #0x1            @ awake, wait just a bit
-       bne     loop
-
-       /* The DPLL has on before we take the DDR out of self refresh */
-       bic     r4, r4, #0x40           @ now clear self refresh bit.
-       str     r4, [r3]                @ put vlaue back.
-       ldr     r4, A_SDRC0             @ make a clock happen
-       ldr     r4, [r4]
-       nop                             @ start auto refresh only after clk ok
-       movs    r0, r0                  @ see if DDR or SDR
-       ldrne   r1, A_SDRC_DLLA_CTRL_S  @ get addr of DLL ctrl
-       strne   r0, [r1]                @ rewrite DLLA to force DLL reload
-       addne   r1, r1, #0x8            @ move to DLLB
-       strne   r0, [r1]                @ rewrite DLLB to force DLL reload
-
-       mov     r5, #0x1000
-loop2:
-       subs    r5, r5, #0x1
-       bne     loop2
-       /* resume*/
-       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
-
-A_SDRC_POWER:
-       .word OMAP242X_SDRC_REGADDR(SDRC_POWER)
-A_SDRC0:
-       .word A_SDRC0_V
-A_SDRC_DLLA_CTRL_S:
-       .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
-
-ENTRY(omap24xx_cpu_suspend_sz)
-       .word   . - omap24xx_cpu_suspend
-
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
new file mode 100644 (file)
index 0000000..43336b9
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * (C) Copyright 2006 Nokia Corporation
+ * Fixed idle loop sleep
+ * Igor Stoppa <igor.stoppa@nokia.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
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/io.h>
+#include <mach/pm.h>
+
+#include <mach/omap24xx.h>
+
+#include "sdrc.h"
+
+/* First address of reserved address space?  apparently valid for OMAP2 & 3 */
+#define A_SDRC0_V              (0xC0000000)
+
+       .text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *      wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+       stmfd   sp!, {r0, lr}           @ save registers on stack
+       mov     r0, #0                  @ clear for mcr setup
+       mcr     p15, 0, r0, c7, c0, 4   @ wait for interrupt
+       ldmfd   sp!, {r0, pc}           @ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+       .word   . - omap24xx_idle_loop_suspend
+
+/*
+ * omap24xx_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 :        DLL ctrl value pre-Sleep
+ * R1 : SDRC_DLLA_CTRL
+ * R2 : SDRC_POWER
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't.  We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL.  Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+       stmfd   sp!, {r0 - r12, lr}     @ save registers on stack
+       mov     r3, #0x0                @ clear for mcr call
+       mcr     p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
+       nop
+       nop
+       ldr     r4, [r2]                @ read SDRC_POWER
+       orr     r4, r4, #0x40           @ enable self refresh on idle req
+       mov     r5, #0x2000             @ set delay (DPLL relock + DLL relock)
+       str     r4, [r2]                @ make it so
+       mov     r2, #0
+       nop
+       mcr     p15, 0, r2, c7, c0, 4   @ wait for interrupt
+       nop
+loop:
+       subs    r5, r5, #0x1            @ awake, wait just a bit
+       bne     loop
+
+       /* The DPLL has to be on before we take the DDR out of self refresh */
+       bic     r4, r4, #0x40           @ now clear self refresh bit.
+       str     r4, [r2]                @ write to SDRC_POWER
+       ldr     r4, A_SDRC0             @ make a clock happen
+       ldr     r4, [r4]                @ read A_SDRC0
+       nop                             @ start auto refresh only after clk ok
+       movs    r0, r0                  @ see if DDR or SDR
+       strne   r0, [r1]                @ rewrite DLLA to force DLL reload
+       addne   r1, r1, #0x8            @ move to DLLB
+       strne   r0, [r1]                @ rewrite DLLB to force DLL reload
+
+       mov     r5, #0x1000
+loop2:
+       subs    r5, r5, #0x1
+       bne     loop2
+       /* resume*/
+       ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+
+A_SDRC0:
+       .word A_SDRC0_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+       .word   . - omap24xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
new file mode 100644 (file)
index 0000000..2c71461
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * linux/arch/arm/mach-omap3/sram.S
+ *
+ * Omap3 specific functions that need to be run in internal SRAM
+ *
+ * (C) Copyright 2007
+ * Texas Instruments Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.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
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+
+#include <mach/io.h>
+
+#include "sdrc.h"
+#include "cm.h"
+
+       .text
+
+/*
+ * Change frequency of core dpll
+ * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
+ */
+ENTRY(omap3_sram_configure_core_dpll)
+       stmfd   sp!, {r1-r12, lr}       @ store regs to stack
+       cmp     r3, #0x2
+       blne    configure_sdrc
+       cmp     r3, #0x2
+       blne    lock_dll
+       cmp     r3, #0x1
+       blne    unlock_dll
+       bl      sdram_in_selfrefresh    @ put the SDRAM in self refresh
+       bl      configure_core_dpll
+       bl      enable_sdrc
+       cmp     r3, #0x1
+       blne    wait_dll_unlock
+       cmp     r3, #0x2
+       blne    wait_dll_lock
+       cmp     r3, #0x1
+       blne    configure_sdrc
+       mov     r0, #0                  @ return value
+       ldmfd   sp!, {r1-r12, pc}       @ restore regs and return
+unlock_dll:
+       ldr     r4, omap3_sdrc_dlla_ctrl
+       ldr     r5, [r4]
+       orr     r5, r5, #0x4
+       str     r5, [r4]
+       bx      lr
+lock_dll:
+       ldr     r4, omap3_sdrc_dlla_ctrl
+       ldr     r5, [r4]
+       bic     r5, r5, #0x4
+       str     r5, [r4]
+       bx      lr
+sdram_in_selfrefresh:
+       mov     r5, #0x0                @ Move 0 to R5
+       mcr     p15, 0, r5, c7, c10, 5  @ memory barrier
+       ldr     r4, omap3_sdrc_power    @ read the SDRC_POWER register
+       ldr     r5, [r4]                @ read the contents of SDRC_POWER
+       orr     r5, r5, #0x40           @ enable self refresh on idle req
+       str     r5, [r4]                @ write back to SDRC_POWER register
+       ldr     r4, omap3_cm_iclken1_core       @ read the CM_ICLKEN1_CORE reg
+       ldr     r5, [r4]
+       bic     r5, r5, #0x2            @ disable iclk bit for SRDC
+       str     r5, [r4]
+wait_sdrc_idle:
+       ldr     r4, omap3_cm_idlest1_core
+       ldr     r5, [r4]
+       and     r5, r5, #0x2            @ check for SDRC idle
+       cmp     r5, #2
+       bne     wait_sdrc_idle
+       bx      lr
+configure_core_dpll:
+       ldr     r4, omap3_cm_clksel1_pll
+       ldr     r5, [r4]
+       ldr     r6, core_m2_mask_val    @ modify m2 for core dpll
+       and     r5, r5, r6
+       orr     r5, r5, r3, lsl #0x1B   @ r3 contains the M2 val
+       str     r5, [r4]
+       mov     r5, #0x800              @ wait for the clock to stabilise
+       cmp     r3, #2
+       bne     wait_clk_stable
+       bx      lr
+wait_clk_stable:
+       subs    r5, r5, #1
+       bne     wait_clk_stable
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       bx      lr
+enable_sdrc:
+       ldr     r4, omap3_cm_iclken1_core
+       ldr     r5, [r4]
+       orr     r5, r5, #0x2            @ enable iclk bit for SDRC
+       str     r5, [r4]
+wait_sdrc_idle1:
+       ldr     r4, omap3_cm_idlest1_core
+       ldr     r5, [r4]
+       and     r5, r5, #0x2
+       cmp     r5, #0
+       bne     wait_sdrc_idle1
+       ldr     r4, omap3_sdrc_power
+       ldr     r5, [r4]
+       bic     r5, r5, #0x40
+       str     r5, [r4]
+       bx      lr
+wait_dll_lock:
+       ldr     r4, omap3_sdrc_dlla_status
+       ldr     r5, [r4]
+       and     r5, r5, #0x4
+       cmp     r5, #0x4
+       bne     wait_dll_lock
+       bx      lr
+wait_dll_unlock:
+       ldr     r4, omap3_sdrc_dlla_status
+       ldr     r5, [r4]
+       and     r5, r5, #0x4
+       cmp     r5, #0x0
+       bne     wait_dll_unlock
+       bx      lr
+configure_sdrc:
+       ldr     r4, omap3_sdrc_rfr_ctrl
+       str     r0, [r4]
+       ldr     r4, omap3_sdrc_actim_ctrla
+       str     r1, [r4]
+       ldr     r4, omap3_sdrc_actim_ctrlb
+       str     r2, [r4]
+       bx      lr
+
+omap3_sdrc_power:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_POWER)
+omap3_cm_clksel1_pll:
+       .word OMAP34XX_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
+omap3_cm_idlest1_core:
+       .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST)
+omap3_cm_iclken1_core:
+       .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
+omap3_sdrc_rfr_ctrl:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0)
+omap3_sdrc_actim_ctrla:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_0)
+omap3_sdrc_actim_ctrlb:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_0)
+omap3_sdrc_dlla_status:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
+omap3_sdrc_dlla_ctrl:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
+core_m2_mask_val:
+       .word 0x07FFFFFF
+
+ENTRY(omap3_sram_configure_core_dpll_sz)
+       .word   . - omap3_sram_configure_core_dpll
index a82dad1a8cc86c76cef9fa50619695903b03d138..df83b97f303fd989c0df1795cea48c98ea82ecf6 100644 (file)
@@ -162,7 +162,7 @@ static void __init cmx270_init_rtc(void)
        platform_device_register(&cmx270_rtc_device);
 }
 #else
-static inline void cmx2xx_init_rtc(void) {}
+static inline void cmx270_init_rtc(void) {}
 #endif
 
 /* 2700G graphics */
index d82528e74bd0e3d27359169246da5e14e56828c9..1f272ea83f36e63c824822acc98ec388018d71ae 100644 (file)
@@ -335,9 +335,6 @@ static __init int pxa_cpufreq_init(struct cpufreq_policy *policy)
                pxa27x_guess_max_freq();
 
        /* set default policy and cpuinfo */
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-       if (cpu_is_pxa25x())
-               policy->policy = CPUFREQ_POLICY_PERFORMANCE;
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
        policy->cur = get_clk_frequency_khz(0);    /* current freq */
        policy->min = policy->max = policy->cur;
index 1ea0c9c0adaf5a6b2825a8d2042ed93435dc216a..968c8309ec37226247d8c2604a332c2048f4225d 100644 (file)
@@ -210,7 +210,6 @@ static __init int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
        int ret = -EINVAL;
 
        /* set default policy and cpuinfo */
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.min_freq = 104000;
        policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
index 39516ced8b1f5470c24463e05211b3faafe3f270..31abe6d514b896b259224cbf48ae01d0213b4893 100644 (file)
@@ -36,8 +36,6 @@
 
 struct pxacamera_platform_data {
        int (*init)(struct device *);
-       int (*power)(struct device *, int);
-       int (*reset)(struct device *, int);
 
        unsigned long flags;
        unsigned long mclk_10khz;
index d7632f63603c2967f2098a4df5d0792249603631..4b3120dbc049946b75f05b94b8f6479ca40ecdd9 100644 (file)
@@ -204,25 +204,54 @@ static void viper_set_core_cpu_voltage(unsigned long khz, int force)
 
 /* Interrupt handling */
 static unsigned long viper_irq_enabled_mask;
+static const int viper_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 };
+static const int viper_isa_irq_map[] = {
+       0,              /* ISA irq #0, invalid */
+       0,              /* ISA irq #1, invalid */
+       0,              /* ISA irq #2, invalid */
+       1 << 0,         /* ISA irq #3 */
+       1 << 1,         /* ISA irq #4 */
+       1 << 2,         /* ISA irq #5 */
+       1 << 3,         /* ISA irq #6 */
+       1 << 4,         /* ISA irq #7 */
+       0,              /* ISA irq #8, invalid */
+       1 << 8,         /* ISA irq #9 */
+       1 << 5,         /* ISA irq #10 */
+       1 << 6,         /* ISA irq #11 */
+       1 << 7,         /* ISA irq #12 */
+       0,              /* ISA irq #13, invalid */
+       1 << 9,         /* ISA irq #14 */
+       1 << 10,        /* ISA irq #15 */
+};
+
+static inline int viper_irq_to_bitmask(unsigned int irq)
+{
+       return viper_isa_irq_map[irq - PXA_ISA_IRQ(0)];
+}
+
+static inline int viper_bit_to_irq(int bit)
+{
+       return viper_isa_irqs[bit] + PXA_ISA_IRQ(0);
+}
 
 static void viper_ack_irq(unsigned int irq)
 {
-       int viper_irq = irq - PXA_ISA_IRQ(0);
+       int viper_irq = viper_irq_to_bitmask(irq);
 
-       if (viper_irq < 8)
-               VIPER_LO_IRQ_STATUS = 1 << viper_irq;
+       if (viper_irq & 0xff)
+               VIPER_LO_IRQ_STATUS = viper_irq;
        else
-               VIPER_HI_IRQ_STATUS = 1 << (viper_irq - 8);
+               VIPER_HI_IRQ_STATUS = (viper_irq >> 8);
 }
 
 static void viper_mask_irq(unsigned int irq)
 {
-       viper_irq_enabled_mask &= ~(1 << (irq - PXA_ISA_IRQ(0)));
+       viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(irq));
 }
 
 static void viper_unmask_irq(unsigned int irq)
 {
-       viper_irq_enabled_mask |= (1 << (irq - PXA_ISA_IRQ(0)));
+       viper_irq_enabled_mask |= viper_irq_to_bitmask(irq);
 }
 
 static inline unsigned long viper_irq_pending(void)
@@ -237,8 +266,12 @@ static void viper_irq_handler(unsigned int irq, struct irq_desc *desc)
 
        pending = viper_irq_pending();
        do {
+               /* we're in a chained irq handler,
+                * so ack the interrupt by hand */
+               GEDR(VIPER_CPLD_GPIO) = GPIO_bit(VIPER_CPLD_GPIO);
+
                if (likely(pending)) {
-                       irq = PXA_ISA_IRQ(0) + __ffs(pending);
+                       irq = viper_bit_to_irq(__ffs(pending));
                        generic_handle_irq(irq);
                }
                pending = viper_irq_pending();
@@ -254,15 +287,14 @@ static struct irq_chip viper_irq_chip = {
 
 static void __init viper_init_irq(void)
 {
-       const int isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 };
-       int irq;
+       int level;
        int isa_irq;
 
        pxa25x_init_irq();
 
        /* setup ISA IRQs */
-       for (irq = 0; irq < ARRAY_SIZE(isa_irqs); irq++) {
-               isa_irq = isa_irqs[irq];
+       for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) {
+               isa_irq = viper_bit_to_irq(level);
                set_irq_chip(isa_irq, &viper_irq_chip);
                set_irq_handler(isa_irq, handle_edge_irq);
                set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
index 75738000272be89f69c3e4fd8b6c725a97e0644f..9a37c87152b0074a0da7d47a0c2cd2f914b829df 100644 (file)
@@ -38,7 +38,7 @@
 #include <mach/bast-map.h>
 #include <mach/bast-irq.h>
 
-#include <asm/plat-s3c24xx/irq.h>
+#include <plat/irq.h>
 
 #if 0
 #include <asm/debug-ll.h>
index fef646c36b540600576e83f4e982e2983302099b..4e07943c1e29116603aef7427ec41410084949ed 100644 (file)
 
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 int s3c2410_clkcon_enable(struct clk *clk, int enable)
 {
index 8730797749e3a8ee65ea7daed665d32a828a14e3..7d914a470b6c7d228d8bf841380524b6fd65a56f 100644 (file)
 #include <asm/dma.h>
 #include <mach/dma.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/dma.h>
+#include <plat/cpu.h>
+#include <plat/dma.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <asm/plat-s3c/regs-ac97.h>
 #include <mach/regs-mem.h>
index 682df23087ab43134dd043cda3a83dcc85da0125..4c29a89ad0770566b4969a84354af3d2e4f76b14 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
 #define S3C2410_UART1_OFF (0x4000)
 #define SHIFT_2440TXF (14-9)
@@ -99,4 +99,4 @@
 
 /* include the reset of the code which will do the work */
 
-#include <asm/plat-s3c/debug-macro.S>
+#include <plat/debug-macro.S>
index 64bf7e94a5bf0baac8a68008c9ed23bebef28a5d..23c470c2e5b13cf1420a542875c80ab07547cc4a 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MAP_H
 #define __ASM_ARCH_MAP_H
 
-#include <asm/plat-s3c/map.h>
+#include <plat/map.h>
 
 #define S3C2410_ADDR(x)                S3C_ADDR(x)
 
index 921b13b4f0a055dc3c036138149e6ca14db8fc89..46d46f5b99f2817b92c43729928371f0d3a8fb08 100644 (file)
@@ -18,6 +18,7 @@ struct s3c2410_spi_info {
        unsigned int             num_cs;        /* total chipselects */
        int                      bus_num;       /* bus number to use. */
 
+       void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
        void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
 
index 708e47459ffc91f331804a63d08c32890a3cb41b..ab39491beee209328854aef56651b4e829d30171 100644 (file)
@@ -21,7 +21,7 @@
 #undef S3C2410_GPIOREG
 #define S3C2410_GPIOREG(x) ((S3C24XX_PA_GPIO + (x)))
 
-#include <asm/plat-s3c/uncompress.h>
+#include <plat/uncompress.h>
 
 static inline int is_arm926(void)
 {
index f5c5c53e1cc18f6b3f663f41c9f5b26380360b0d..92150399563bdddabab2cd7ec3ca2da4fc2514b7 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/ioport.h>
 #include <linux/sysdev.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 static int s3c2410_irq_add(struct sys_device *sysdev)
 {
index 527f88a288ec4ea094ffb4dc63e2a27e5c606b46..d061fea01900138879c776af78150e2966942db3 100644 (file)
 #include <asm/mach-types.h>
 #include <mach/fb.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
index e4368e6e7e6c9ac6b70c735c770bb747b2f65b2b..8db9c700e3c24cbf621a2403960e6fe159ac4fb3 100644 (file)
@@ -39,7 +39,7 @@
 #include <asm/mach-types.h>
 
 //#include <asm/debug-ll.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
@@ -55,9 +55,9 @@
 
 #include <linux/serial_8250.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 #include "usb-simtec.h"
 #include "nor-simtec.h"
index 85e710f2863b37ec9a3edf21df100741f96c1f4a..98716d0108e9d670747c56b45598fb78253961b2 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/fb.h>
 #include <asm/plat-s3c24xx/udc.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 static struct map_desc h1940_iodesc[] __initdata = {
        [0] = {
index 3ece2d04934e20ce90ec6c2b4ac7bc67846e03fa..82505517846c532f32e87db5e927e0da18e541fa 100644 (file)
 #include <asm/mach/map.h>
 
 #include <asm/plat-s3c/iic.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/s3c2410.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s3c2410.h>
 #include <asm/plat-s3c24xx/udc.h>
 
 static struct map_desc n30_iodesc[] __initdata = {
index c4dfe3eabe1d87a21e0bc741284a707e0495b031..d8255cf87e446ef07f8f719d2413bf2957ab6b1a 100644 (file)
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 static struct map_desc otom11_iodesc[] __initdata = {
   /* Device area */
index 97c13192315ba8ae60140250e7648ab8b66ef0be..661807e14e8a56f8b2c1eb304bc15543a5b05d31 100644 (file)
 
 #include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/fb.h>
 #include <asm/plat-s3c/nand.h>
 #include <asm/plat-s3c24xx/udc.h>
 #include <mach/spi.h>
 #include <mach/spi-gpio.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/common-smdk.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 static struct map_desc qt2410_iodesc[] __initdata = {
        { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
index d49e58acb03b033eaaacaf15accb8bd75c88ee14..152527bb287290e28522c581fbff65368eab4b08 100644 (file)
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
+#include <plat/common-smdk.h>
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
index cc2e79fe4f9f6a3e7abca47fccd91f8ae6c6c4cb..309dcf4c870af92c8603276d0b7f1e3ccfa83939 100644 (file)
@@ -44,9 +44,9 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/regs-serial.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
index ed3acb05c8553253a1598ef52c50c5907cb043a7..941353af16dc85f546107e222f5a5c5bec3649a9 100644 (file)
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 #include "usb-simtec.h"
 #include "nor-simtec.h"
index 733f8a22777536c43339cf9cb2d3ae2b0ccf42c9..a6970f6131926cdb3550e90fec3ed72a95377cc1 100644 (file)
@@ -34,8 +34,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/h1940.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 #ifdef CONFIG_S3C2410_PM_DEBUG
 extern void pm_dbg(const char *fmt, ...);
index b1e658c917a07840171c85601a120a420bb0a941..ac79b536c4c3d5510f84e969e5cb4cfe5faecb9e 100644 (file)
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/clock.h>
+#include <plat/s3c2410.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
 
 /* Initial IO mappings */
 
index be37f221a177b529b9da67aba5a4104a6d4b474d..dd5b6388a5a555826e80eab1eae0710040d954f6 100644 (file)
@@ -32,7 +32,7 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-mem.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
        /* s3c2410_cpu_suspend
         *
index eb6fc0bfd47ecd8f1e28f7b4e49fc0d31dedcb86..6078f09b7df5d9311cc42ab7796e9b16271cb10c 100644 (file)
@@ -35,7 +35,7 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
-#include <asm/plat-s3c24xx/devs.h>
+#include <plat/devs.h>
 #include "usb-simtec.h"
 
 /* control power and monitor over-current events on various Simtec
index 5fbaac6054f8a0ce3fb9f94163308a42074f9d4a..96d9eb15424f38087ec3b2a210add4ab7ea4d842 100644 (file)
 
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/s3c2412.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2412.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 /* We currently have to assume that the system is running
  * from the XTPll input, and that all ***REFCLKs are being
index dcfff6b8b95854c173211b70d2babfb740cc75ea..ba0591e71f329aff73ae383c3549f22d17390507 100644 (file)
 #include <asm/dma.h>
 #include <mach/dma.h>
 
-#include <asm/plat-s3c24xx/dma.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/dma.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <asm/plat-s3c/regs-ac97.h>
 #include <mach/regs-mem.h>
index 41720f2c1fea8eb3d1ccb52ac181a4540c76061d..6000ca9d18156d6d0c48736e0c3e82bc1905b3a3 100644 (file)
@@ -35,9 +35,9 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-power.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/irq.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/cpu.h>
+#include <plat/irq.h>
+#include <plat/pm.h>
 
 #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
 #define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0))))
index ad980a1690c261b7ea8386616418993b10faf911..b08f18c8c47a0144868763d46c44eb844b93eb6b 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <asm/plat-s3c/nand.h>
 #include <asm/plat-s3c/iic.h>
 
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 #include <asm/plat-s3c24xx/udc.h>
 
 static struct map_desc jive_iodesc[] __initdata = {
index 8f8d9117b968d0d77635da2e4a563783c001d5dc..c719b5a740a914cc2a5d75e8f9bec7d02b2fb3e5 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/mach-types.h>
 
 //#include <asm/debug-ll.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
 #include <asm/plat-s3c24xx/udc.h>
 #include <mach/fb.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2412.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2412.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
+#include <plat/common-smdk.h>
 
 static struct map_desc smdk2413_iodesc[] __initdata = {
 };
index bb9bf63b2e02d0564fffbbe2cf86a15cb52ee60f..4cfa19ad9be015947c8b9f538a29f76715c3a388 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
 
 #include <asm/plat-s3c/nand.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2412.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2412.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 
 static struct map_desc vstms_iodesc[] __initdata = {
index 9540ef752f73c2da727a7b74b096981d4b450031..217e9e4ed45f20a9d5b0c1ce678ab752f8b4f2e5 100644 (file)
 #include <mach/regs-gpio.h>
 #include <mach/regs-dsc.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
-#include <asm/plat-s3c24xx/s3c2412.h>
+#include <plat/s3c2412.h>
 
 extern void s3c2412_sleep_enter(void);
 
index 42440fc5568192e225a8a5aa46b8d7e6c260251a..313759c3da69fcc0ba4f357342f2191475a9ed4b 100644 (file)
@@ -34,7 +34,7 @@
 #include <mach/idle.h>
 
 #include <mach/regs-clock.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-power.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpioj.h>
 #include <asm/plat-s3c24xx/regs-spi.h>
 #include <mach/regs-s3c2412.h>
 
-#include <asm/plat-s3c24xx/s3c2412.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/s3c2412.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/pm.h>
 
 #ifndef CONFIG_CPU_S3C2412_ONLY
 void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
index 40503a65bacfffa51b5199a14eac13868f31ef9e..d1c29b2537cda76a79ff40ee45ac6c030110e8cb 100644 (file)
@@ -41,8 +41,8 @@
 
 #include <mach/regs-clock.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 /* S3C2440 extended clock support */
 
index cdd4e6e79ac0277859c37b9a051a09b127e9060c..32303f6a83219dc5f2a3b6b263610ae77121d40a 100644 (file)
 #include <asm/dma.h>
 #include <mach/dma.h>
 
-#include <asm/plat-s3c24xx/dma.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/dma.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <asm/plat-s3c/regs-ac97.h>
 #include <mach/regs-mem.h>
index 4f7d06baf0d377a7c1427820c413c6cb574dc6e0..55404427277134300c12cf81359d040faddda67a 100644 (file)
@@ -27,8 +27,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-dsc.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/s3c2440.h>
+#include <plat/cpu.h>
+#include <plat/s3c2440.h>
 
 int s3c2440_set_dsc(unsigned int pin, unsigned int value)
 {
index 33e3ede0a2b32d3623c31ec06390b29e51c5b99c..63c5ab65727f60a2f54877c6899f8b50e6b8edb6 100644 (file)
@@ -34,9 +34,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
-#include <asm/plat-s3c24xx/irq.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
 
 /* WDT/AC97 */
 
index 19eb0e5269ac3bf7e458563a1fe92ae2decd3c02..e2beca4704847daee81d643f0870a65c81eca5f6 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
@@ -48,9 +48,9 @@
 
 #include <net/ax88796.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
index f0f0cc6afcf469cc32e1a259ee01c0ac95092549..66876c6f2f1c593f643cbdd9be679a7949597a27 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
@@ -42,9 +42,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 static struct map_desc at2440evb_iodesc[] __initdata = {
        /* Nothing here */
index 49e828d1d4d852e33a425424481938e572b08975..a546307fd53d8abb2ff39d84bc2a72b401c893ea 100644 (file)
 
 //#include <asm/debug-ll.h>
 #include <mach/regs-gpio.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2440.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2440.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 static struct map_desc nexcoder_iodesc[] __initdata = {
        /* nothing here yet */
index 85144aa52c276e7449dee5266e48a4fc36170a27..2361d606abc50fdd85ddd84c7ac54473d61a9145 100644 (file)
@@ -33,7 +33,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
@@ -44,9 +44,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 /* onboard perihperal map */
 
index a4c690456d19a40f3ffcb72a08905f2292cb429c..4d14c7cff89214eaab3357ec5b138fa27b64b41b 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
 #include <asm/plat-s3c/nand.h>
 #include <mach/fb.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 static struct map_desc rx3715_iodesc[] __initdata = {
        /* dump ISA space somewhere unused */
index 7ac60b869e7fde7dfe708b1972072102b9359ee6..fefeaaa4155fff74bb21d9320b38063342b54acd 100644 (file)
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
 #include <mach/idle.h>
 #include <mach/fb.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2440.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2440.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
+#include <plat/common-smdk.h>
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
index c81cdb330712cdb3bc16ac708fe4fba4b6b255cd..ac1f7ea5f405ff342a3b1fd550eb940e43df0486 100644 (file)
@@ -29,9 +29,9 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
-#include <asm/plat-s3c24xx/s3c2440.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2440.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 static struct sys_device s3c2440_sysdev = {
        .cls            = &s3c2440_sysclass,
index 18f2ce4d7b23b7667b6748627fe0daa1cf25092a..ea1aa1f5157a7959b5080a42743a9ed2e2abe99b 100644 (file)
@@ -41,8 +41,8 @@
 
 #include <mach/regs-clock.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 /* S3C2442 extended clock support */
 
index fbf8264249da376879221f29e82b08a4138657e3..4663bdc7fff6f26bad2cf161186d805e8a8690c7 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
 
-#include <asm/plat-s3c24xx/s3c2442.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2442.h>
+#include <plat/cpu.h>
 
 static struct sys_device s3c2442_sysdev = {
        .cls            = &s3c2442_sysclass,
index 603b5ea1deab4b96b0a267a816ccfc7c89f6953a..2f60bf6b8d4395e49bc49fcc3dfc072386c17656 100644 (file)
@@ -39,9 +39,9 @@
 
 #include <mach/regs-s3c2443-clock.h>
 
-#include <asm/plat-s3c24xx/s3c2443.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2443.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 /* We currently have to assume that the system is running
  * from the XTPll input, and that all ***REFCLKs are being
index 5d9ee772659bd73ca696415d205522e6a31fac1c..f73ccb25ff9488136cbcbae50e16a1a03f5b384d 100644 (file)
 #include <asm/dma.h>
 #include <mach/dma.h>
 
-#include <asm/plat-s3c24xx/dma.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/dma.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <asm/plat-s3c/regs-ac97.h>
 #include <mach/regs-mem.h>
index e44341d7dfef91189ad960cbcc8264357879eecd..0e0d693f397449139f8fd9e790a1f4693e3f661b 100644 (file)
@@ -34,9 +34,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
-#include <asm/plat-s3c24xx/irq.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
 
 #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
 
index f0d119dc040906838fadedcc73d940e2946450da..a7fe65f3dcc16a08b0212adfd4abd373174d7435 100644 (file)
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
 #include <mach/idle.h>
 #include <mach/fb.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2440.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2440.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
+#include <plat/common-smdk.h>
 
 static struct map_desc smdk2443_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
index c973b68cc7358c4c01f57b18ad41bd063ae2947b..bbeddf9ddcb1a68c99835f039f10a150c66f64f2 100644 (file)
@@ -32,9 +32,9 @@
 #include <mach/regs-s3c2443-clock.h>
 #include <mach/reset.h>
 
-#include <asm/plat-s3c24xx/s3c2443.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/s3c2443.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
index f7fa03478efd9e7c203c72363696e8651209499d..244d5956312cfb106cf90e39a4863ba082943ac0 100644 (file)
@@ -224,7 +224,6 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
        if (policy->cpu != 0)
                return -EINVAL;
        policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.min_freq = 59000;
        policy->cpuinfo.max_freq = 287000;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
index 330814d1ee2536e65dc23273ea01d225088688fe..d1193884d76d9ce4540b5d2a9d11e94e0233536b 100644 (file)
@@ -428,7 +428,7 @@ config CPU_32v6K
 # ARMv7
 config CPU_V7
        bool "Support ARM V7 processor"
-       depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB
+       depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP3
        select CPU_32v6K
        select CPU_32v7
        select CPU_ABRT_EV7
index b917206ee9068036f6e17570162595a16afbdf38..a94f0c44ebc8286b042f39a8de172c7d80eb4238 100644 (file)
@@ -15,6 +15,9 @@ config ARCH_OMAP1
 config ARCH_OMAP2
        bool "TI OMAP2"
 
+config ARCH_OMAP3
+       bool "TI OMAP3"
+
 endchoice
 
 comment "OMAP Feature Selections"
@@ -29,6 +32,30 @@ config OMAP_DEBUG_LEDS
        depends on OMAP_DEBUG_DEVICES
        default y if LEDS || LEDS_OMAP_DEBUG
 
+config OMAP_DEBUG_POWERDOMAIN
+       bool "Emit debug messages from powerdomain layer"
+       depends on ARCH_OMAP2 || ARCH_OMAP3
+       default n
+       help
+         Say Y here if you want to compile in powerdomain layer
+         debugging messages for OMAP2/3.   These messages can
+         provide more detail as to why some powerdomain calls
+         may be failing, and will also emit a descriptive message
+         for every powerdomain register write.  However, the
+         extra detail costs some memory.
+
+config OMAP_DEBUG_CLOCKDOMAIN
+       bool "Emit debug messages from clockdomain layer"
+       depends on ARCH_OMAP2 || ARCH_OMAP3
+       default n
+       help
+         Say Y here if you want to compile in clockdomain layer
+         debugging messages for OMAP2/3.   These messages can
+         provide more detail as to why some clockdomain calls
+         may be failing, and will also emit a descriptive message
+         for every clockdomain register write.  However, the
+         extra detail costs some memory.
+
 config OMAP_RESET_CLOCKS
        bool "Reset unused clocks during boot"
        depends on ARCH_OMAP
@@ -88,13 +115,13 @@ config OMAP_MPU_TIMER
 
 config OMAP_32K_TIMER
        bool "Use 32KHz timer"
-       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+       depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
        help
          Select this option if you want to enable the OMAP 32KHz timer.
          This timer saves power compared to the OMAP_MPU_TIMER, and has
          support for no tick during idle. The 32KHz timer provides less
          intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-         currently only available for OMAP16XX and 24XX.
+         currently only available for OMAP16XX, 24XX and 34XX.
 
 endchoice
 
@@ -109,7 +136,7 @@ config OMAP_32K_TIMER_HZ
 
 config OMAP_DM_TIMER
        bool "Use dual-mode timer"
-       depends on ARCH_OMAP16XX || ARCH_OMAP24XX
+       depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
        help
         Select this option if you want to use OMAP Dual-Mode timers.
 
index 2c4051cc79a13f249e32d4cb6abf31841ee1c258..deaff58878a2fe7cfd1324cf2afc6653eaf7ec99 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
-        usb.o fb.o
+        usb.o fb.o io.o
 obj-m :=
 obj-n :=
 obj-  :=
index 8bdf0ead0cf36ec58316a5a49bc26813a92450ae..0843b8882f9311aa38dd972537dd5f5f757e86e7 100644 (file)
@@ -248,6 +248,7 @@ static struct omap_globals *omap2_globals;
 
 static void __init __omap2_set_globals(void)
 {
+       omap2_set_globals_tap(omap2_globals);
        omap2_set_globals_memory(omap2_globals);
        omap2_set_globals_control(omap2_globals);
        omap2_set_globals_prcm(omap2_globals);
@@ -258,12 +259,13 @@ static void __init __omap2_set_globals(void)
 #if defined(CONFIG_ARCH_OMAP2420)
 
 static struct omap_globals omap242x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x48014000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CM_BASE),
+       .class  = OMAP242X_CLASS,
+       .tap    = OMAP2_IO_ADDRESS(0x48014000),
+       .sdrc   = OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE),
+       .sms    = OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE),
+       .ctrl   = OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE),
+       .prm    = OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE),
+       .cm     = OMAP2_IO_ADDRESS(OMAP2420_CM_BASE),
 };
 
 void __init omap2_set_globals_242x(void)
@@ -276,12 +278,13 @@ void __init omap2_set_globals_242x(void)
 #if defined(CONFIG_ARCH_OMAP2430)
 
 static struct omap_globals omap243x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4900a000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_CM_BASE),
+       .class  = OMAP243X_CLASS,
+       .tap    = OMAP2_IO_ADDRESS(0x4900a000),
+       .sdrc   = OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE),
+       .sms    = OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE),
+       .ctrl   = OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE),
+       .prm    = OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE),
+       .cm     = OMAP2_IO_ADDRESS(OMAP2430_CM_BASE),
 };
 
 void __init omap2_set_globals_243x(void)
@@ -294,12 +297,13 @@ void __init omap2_set_globals_243x(void)
 #if defined(CONFIG_ARCH_OMAP3430)
 
 static struct omap_globals omap343x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4830A000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_CM_BASE),
+       .class  = OMAP343X_CLASS,
+       .tap    = OMAP2_IO_ADDRESS(0x4830A000),
+       .sdrc   = OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE),
+       .sms    = OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE),
+       .ctrl   = OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE),
+       .prm    = OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE),
+       .cm     = OMAP2_IO_ADDRESS(OMAP3430_CM_BASE),
 };
 
 void __init omap2_set_globals_343x(void)
index 97187fa0ae52b529a1f51453a29d2f2577c0605a..0cb2b22388e93454a7fe78b69e465fee6a519379 100644 (file)
 #include <asm/mach/map.h>
 
 #include <mach/tc.h>
+#include <mach/control.h>
 #include <mach/board.h>
 #include <mach/mmc.h>
 #include <mach/mux.h>
 #include <mach/gpio.h>
 #include <mach/menelaus.h>
 #include <mach/mcbsp.h>
+#include <mach/dsp_common.h>
 
 #if    defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
 
-#include "../plat-omap/dsp/dsp_common.h"
-
 static struct dsp_platform_data dsp_pdata = {
        .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list),
 };
@@ -76,7 +76,7 @@ int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev)
 {
        static DEFINE_MUTEX(dsp_pdata_lock);
 
-       mutex_init(&kdev->lock);
+       spin_lock_init(&kdev->lock);
 
        mutex_lock(&dsp_pdata_lock);
        list_add_tail(&kdev->entry, &dsp_pdata.kdev_list);
@@ -95,6 +95,10 @@ static inline void omap_init_dsp(void) { }
 
 static void omap_init_kp(void)
 {
+       /* 2430 and 34xx keypad is on TWL4030 */
+       if (cpu_is_omap2430() || cpu_is_omap34xx())
+               return;
+
        if (machine_is_omap_h2() || machine_is_omap_h3()) {
                omap_cfg_reg(F18_1610_KBC0);
                omap_cfg_reg(D20_1610_KBC1);
@@ -156,13 +160,6 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 {
        int i;
 
-       if (size > OMAP_MAX_MCBSP_COUNT) {
-               printk(KERN_WARNING "Registered too many McBSPs platform_data."
-                       " Using maximum (%d) available.\n",
-                       OMAP_MAX_MCBSP_COUNT);
-               size = OMAP_MAX_MCBSP_COUNT;
-       }
-
        omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
                                     GFP_KERNEL);
        if (!omap_mcbsp_devices) {
@@ -530,10 +527,6 @@ static inline void omap_init_rng(void) {}
  */
 static int __init omap_init_devices(void)
 {
-/*
- * Need to enable relevant once for 2430 SDP
- */
-#ifndef CONFIG_MACH_OMAP_2430SDP
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
@@ -543,7 +536,6 @@ static int __init omap_init_devices(void)
        omap_init_uwire();
        omap_init_wdt();
        omap_init_rng();
-#endif
        return 0;
 }
 arch_initcall(omap_init_devices);
index a63b644ad30574b024f4ff60146f9233b7fa17db..50f8b4ad9a0942a0e818a746dff055d17b8be139 100644 (file)
@@ -1233,7 +1233,7 @@ int omap_request_dma_chain(int dev_id, const char *dev_name,
        /* request and reserve DMA channels for the chain */
        for (i = 0; i < no_of_chans; i++) {
                err = omap_request_dma(dev_id, dev_name,
-                                       callback, 0, &channels[i]);
+                                       callback, NULL, &channels[i]);
                if (err < 0) {
                        int j;
                        for (j = 0; j < i; j++)
@@ -2297,13 +2297,13 @@ static int __init omap_init_dma(void)
        int ch, r;
 
        if (cpu_class_is_omap1()) {
-               omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP1_DMA_BASE);
+               omap_dma_base = IO_ADDRESS(OMAP1_DMA_BASE);
                dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
        } else if (cpu_is_omap24xx()) {
-               omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP24XX_DMA4_BASE);
+               omap_dma_base = IO_ADDRESS(OMAP24XX_DMA4_BASE);
                dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
        } else if (cpu_is_omap34xx()) {
-               omap_dma_base = (void __iomem *)IO_ADDRESS(OMAP34XX_DMA4_BASE);
+               omap_dma_base = IO_ADDRESS(OMAP34XX_DMA4_BASE);
                dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT;
        } else {
                pr_err("DMA init failed for unsupported omap\n");
index 606fcffdcefcc98cd69f02c0f4f6225e72df8929..963c31cd15416b69aacd5ae253e393f641de0e8a 100644 (file)
@@ -693,7 +693,7 @@ int __init omap_dm_timer_init(void)
 
        for (i = 0; i < dm_timer_count; i++) {
                timer = &dm_timers[i];
-               timer->io_base = (void __iomem *)io_p2v(timer->phys_base);
+               timer->io_base = IO_ADDRESS(timer->phys_base);
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
                if (cpu_class_is_omap2()) {
                        char clk_name[16];
index 5935ae4e550b4f5514a211d897827f933e592295..8679fbca6bbec4ec3d5e5561b92c633cf1e6f298 100644 (file)
@@ -28,7 +28,7 @@
 /*
  * OMAP1510 GPIO registers
  */
-#define OMAP1510_GPIO_BASE             (void __iomem *)0xfffce000
+#define OMAP1510_GPIO_BASE             IO_ADDRESS(0xfffce000)
 #define OMAP1510_GPIO_DATA_INPUT       0x00
 #define OMAP1510_GPIO_DATA_OUTPUT      0x04
 #define OMAP1510_GPIO_DIR_CONTROL      0x08
 /*
  * OMAP1610 specific GPIO registers
  */
-#define OMAP1610_GPIO1_BASE            (void __iomem *)0xfffbe400
-#define OMAP1610_GPIO2_BASE            (void __iomem *)0xfffbec00
-#define OMAP1610_GPIO3_BASE            (void __iomem *)0xfffbb400
-#define OMAP1610_GPIO4_BASE            (void __iomem *)0xfffbbc00
+#define OMAP1610_GPIO1_BASE            IO_ADDRESS(0xfffbe400)
+#define OMAP1610_GPIO2_BASE            IO_ADDRESS(0xfffbec00)
+#define OMAP1610_GPIO3_BASE            IO_ADDRESS(0xfffbb400)
+#define OMAP1610_GPIO4_BASE            IO_ADDRESS(0xfffbbc00)
 #define OMAP1610_GPIO_REVISION         0x0000
 #define OMAP1610_GPIO_SYSCONFIG                0x0010
 #define OMAP1610_GPIO_SYSSTATUS                0x0014
 /*
  * OMAP730 specific GPIO registers
  */
-#define OMAP730_GPIO1_BASE             (void __iomem *)0xfffbc000
-#define OMAP730_GPIO2_BASE             (void __iomem *)0xfffbc800
-#define OMAP730_GPIO3_BASE             (void __iomem *)0xfffbd000
-#define OMAP730_GPIO4_BASE             (void __iomem *)0xfffbd800
-#define OMAP730_GPIO5_BASE             (void __iomem *)0xfffbe000
-#define OMAP730_GPIO6_BASE             (void __iomem *)0xfffbe800
+#define OMAP730_GPIO1_BASE             IO_ADDRESS(0xfffbc000)
+#define OMAP730_GPIO2_BASE             IO_ADDRESS(0xfffbc800)
+#define OMAP730_GPIO3_BASE             IO_ADDRESS(0xfffbd000)
+#define OMAP730_GPIO4_BASE             IO_ADDRESS(0xfffbd800)
+#define OMAP730_GPIO5_BASE             IO_ADDRESS(0xfffbe000)
+#define OMAP730_GPIO6_BASE             IO_ADDRESS(0xfffbe800)
 #define OMAP730_GPIO_DATA_INPUT                0x00
 #define OMAP730_GPIO_DATA_OUTPUT       0x04
 #define OMAP730_GPIO_DIR_CONTROL       0x08
 /*
  * omap24xx specific GPIO registers
  */
-#define OMAP242X_GPIO1_BASE            (void __iomem *)0x48018000
-#define OMAP242X_GPIO2_BASE            (void __iomem *)0x4801a000
-#define OMAP242X_GPIO3_BASE            (void __iomem *)0x4801c000
-#define OMAP242X_GPIO4_BASE            (void __iomem *)0x4801e000
+#define OMAP242X_GPIO1_BASE            IO_ADDRESS(0x48018000)
+#define OMAP242X_GPIO2_BASE            IO_ADDRESS(0x4801a000)
+#define OMAP242X_GPIO3_BASE            IO_ADDRESS(0x4801c000)
+#define OMAP242X_GPIO4_BASE            IO_ADDRESS(0x4801e000)
 
-#define OMAP243X_GPIO1_BASE            (void __iomem *)0x4900C000
-#define OMAP243X_GPIO2_BASE            (void __iomem *)0x4900E000
-#define OMAP243X_GPIO3_BASE            (void __iomem *)0x49010000
-#define OMAP243X_GPIO4_BASE            (void __iomem *)0x49012000
-#define OMAP243X_GPIO5_BASE            (void __iomem *)0x480B6000
+#define OMAP243X_GPIO1_BASE            IO_ADDRESS(0x4900C000)
+#define OMAP243X_GPIO2_BASE            IO_ADDRESS(0x4900E000)
+#define OMAP243X_GPIO3_BASE            IO_ADDRESS(0x49010000)
+#define OMAP243X_GPIO4_BASE            IO_ADDRESS(0x49012000)
+#define OMAP243X_GPIO5_BASE            IO_ADDRESS(0x480B6000)
 
 #define OMAP24XX_GPIO_REVISION         0x0000
 #define OMAP24XX_GPIO_SYSCONFIG                0x0010
  * omap34xx specific GPIO registers
  */
 
-#define OMAP34XX_GPIO1_BASE            (void __iomem *)0x48310000
-#define OMAP34XX_GPIO2_BASE            (void __iomem *)0x49050000
-#define OMAP34XX_GPIO3_BASE            (void __iomem *)0x49052000
-#define OMAP34XX_GPIO4_BASE            (void __iomem *)0x49054000
-#define OMAP34XX_GPIO5_BASE            (void __iomem *)0x49056000
-#define OMAP34XX_GPIO6_BASE            (void __iomem *)0x49058000
+#define OMAP34XX_GPIO1_BASE            IO_ADDRESS(0x48310000)
+#define OMAP34XX_GPIO2_BASE            IO_ADDRESS(0x49050000)
+#define OMAP34XX_GPIO3_BASE            IO_ADDRESS(0x49052000)
+#define OMAP34XX_GPIO4_BASE            IO_ADDRESS(0x49054000)
+#define OMAP34XX_GPIO5_BASE            IO_ADDRESS(0x49056000)
+#define OMAP34XX_GPIO6_BASE            IO_ADDRESS(0x49058000)
 
+#define OMAP_MPUIO_VBASE               IO_ADDRESS(OMAP_MPUIO_BASE)
 
 struct gpio_bank {
        void __iomem *base;
@@ -160,7 +161,7 @@ struct gpio_bank {
 
 #ifdef CONFIG_ARCH_OMAP16XX
 static struct gpio_bank gpio_bank_1610[5] = {
-       { OMAP_MPUIO_BASE,     INT_MPUIO,           IH_MPUIO_BASE,     METHOD_MPUIO},
+       { OMAP_MPUIO_VBASE,    INT_MPUIO,           IH_MPUIO_BASE,     METHOD_MPUIO},
        { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,      IH_GPIO_BASE,      METHOD_GPIO_1610 },
        { OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 },
        { OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 },
@@ -170,14 +171,14 @@ static struct gpio_bank gpio_bank_1610[5] = {
 
 #ifdef CONFIG_ARCH_OMAP15XX
 static struct gpio_bank gpio_bank_1510[2] = {
-       { OMAP_MPUIO_BASE,    INT_MPUIO,      IH_MPUIO_BASE, METHOD_MPUIO },
+       { OMAP_MPUIO_VBASE,   INT_MPUIO,      IH_MPUIO_BASE, METHOD_MPUIO },
        { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE,  METHOD_GPIO_1510 }
 };
 #endif
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct gpio_bank gpio_bank_730[7] = {
-       { OMAP_MPUIO_BASE,     INT_730_MPUIO,       IH_MPUIO_BASE,      METHOD_MPUIO },
+       { OMAP_MPUIO_VBASE,    INT_730_MPUIO,       IH_MPUIO_BASE,      METHOD_MPUIO },
        { OMAP730_GPIO1_BASE,  INT_730_GPIO_BANK1,  IH_GPIO_BASE,       METHOD_GPIO_730 },
        { OMAP730_GPIO2_BASE,  INT_730_GPIO_BANK2,  IH_GPIO_BASE + 32,  METHOD_GPIO_730 },
        { OMAP730_GPIO3_BASE,  INT_730_GPIO_BANK3,  IH_GPIO_BASE + 64,  METHOD_GPIO_730 },
@@ -1389,7 +1390,7 @@ static int __init _omap_gpio_init(void)
 
                gpio_bank_count = 5;
                gpio_bank = gpio_bank_1610;
-               rev = omap_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION);
+               rev = __raw_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION);
                printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
                       (rev >> 4) & 0x0f, rev & 0x0f);
        }
@@ -1408,7 +1409,7 @@ static int __init _omap_gpio_init(void)
 
                gpio_bank_count = 4;
                gpio_bank = gpio_bank_242x;
-               rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+               rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
                printk(KERN_INFO "OMAP242x GPIO hardware version %d.%d\n",
                        (rev >> 4) & 0x0f, rev & 0x0f);
        }
@@ -1417,7 +1418,7 @@ static int __init _omap_gpio_init(void)
 
                gpio_bank_count = 5;
                gpio_bank = gpio_bank_243x;
-               rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+               rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
                printk(KERN_INFO "OMAP243x GPIO hardware version %d.%d\n",
                        (rev >> 4) & 0x0f, rev & 0x0f);
        }
@@ -1428,7 +1429,7 @@ static int __init _omap_gpio_init(void)
 
                gpio_bank_count = OMAP34XX_NR_GPIOS;
                gpio_bank = gpio_bank_34xx;
-               rev = omap_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
+               rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION);
                printk(KERN_INFO "OMAP34xx GPIO hardware version %d.%d\n",
                        (rev >> 4) & 0x0f, rev & 0x0f);
        }
@@ -1437,10 +1438,9 @@ static int __init _omap_gpio_init(void)
                int j, gpio_count = 16;
 
                bank = &gpio_bank[i];
-               bank->base = IO_ADDRESS(bank->base);
                spin_lock_init(&bank->lock);
                if (bank_is_mpuio(bank))
-                       omap_writew(0xFFFF, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_MASKIT);
+                       __raw_writew(0xffff, bank->base + OMAP_MPUIO_GPIO_MASKIT);
                if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
                        __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK);
                        __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
index cf1dc02239495a8a1f2762d4eba8290c01f4d856..10d449ea7ed0d728106117d9c9ee64cd3580c875 100644 (file)
 #define __ASM_ARCH_OMAP_2430SDP_H
 
 /* Placeholder for 2430SDP specific defines */
-#define OMAP24XX_ETHR_START             0x08000300
+#define OMAP24XX_ETHR_START            0x08000300
 #define OMAP24XX_ETHR_GPIO_IRQ         149
 #define SDP2430_CS0_BASE               0x04000000
 
-#define TWL4030_IRQNUM                 INT_24XX_SYS_NIRQ
+/* Function prototypes */
+extern void sdp2430_flash_init(void);
+extern void sdp2430_usb_init(void);
 
 #endif /* __ASM_ARCH_OMAP_2430SDP_H */
index d6f2a8e963d5c86340bec27d604217699341de04..731c858cf3fe70e836a9fbead02bee5ed7bfb5fa 100644 (file)
 
 extern void apollon_mmc_init(void);
 
+static inline int apollon_plus(void)
+{
+       /* The apollon plus has IDCODE revision 5 */
+       return system_rev & 0xc0;
+}
+
 /* Placeholder for APOLLON specific defines */
 #define APOLLON_ETHR_GPIO_IRQ          74
 
index 1470cd3e519b80d746388cb0414b0fa59f596d43..7c3fa0f0a65e1512b2efe9e55debfe199d87a789 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/arm/plat-omap/include/mach/board-h4.h
  *
- * Hardware definitions for TI OMAP1610 H4 board.
+ * Hardware definitions for TI OMAP2420 H4 board.
  *
  * Initial creation by Dirk Behme <dirk.behme@de.bosch.com>
  *
@@ -29,6 +29,9 @@
 #ifndef __ASM_ARCH_OMAP_H4_H
 #define __ASM_ARCH_OMAP_H4_H
 
+/* MMC Prototypes */
+extern void h4_mmc_init(void);
+
 /* Placeholder for H4 specific defines */
 #define OMAP24XX_ETHR_GPIO_IRQ         92
 #endif /*  __ASM_ARCH_OMAP_H4_H */
diff --git a/arch/arm/plat-omap/include/mach/board-ldp.h b/arch/arm/plat-omap/include/mach/board-ldp.h
new file mode 100644 (file)
index 0000000..66e2746
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/plat-omap/include/mach/board-ldp.h
+ *
+ * Hardware definitions for TI OMAP3 LDP.
+ *
+ * Copyright (C) 2008 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 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_OMAP_LDP_H
+#define __ASM_ARCH_OMAP_LDP_H
+
+extern void twl4030_bci_battery_init(void);
+
+#define TWL4030_IRQNUM         INT_34XX_SYS_NIRQ
+
+#endif /* __ASM_ARCH_OMAP_LDP_H */
diff --git a/arch/arm/plat-omap/include/mach/board-omap3beagle.h b/arch/arm/plat-omap/include/mach/board-omap3beagle.h
new file mode 100644 (file)
index 0000000..3080d52
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * arch/arm/plat-omap/include/mach/board-omap3beagle.h
+ *
+ * Hardware definitions for TI OMAP3 BEAGLE.
+ *
+ * Initial creation by Syed Mohammed Khasim <khasim@ti.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_OMAP3_BEAGLE_H
+#define __ASM_ARCH_OMAP3_BEAGLE_H
+
+#endif /* __ASM_ARCH_OMAP3_BEAGLE_H */
+
diff --git a/arch/arm/plat-omap/include/mach/board-overo.h b/arch/arm/plat-omap/include/mach/board-overo.h
new file mode 100644 (file)
index 0000000..7ecae66
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * board-overo.h (Gumstix Overo)
+ *
+ * Initial code: Steve Sakoman <steve@sakoman.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.
+ *
+ * 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_OVERO_H
+#define __ASM_ARCH_OVERO_H
+
+#define OVERO_GPIO_BT_XGATE    15
+#define OVERO_GPIO_W2W_NRESET  16
+#define OVERO_GPIO_BT_NRESET   164
+#define OVERO_GPIO_USBH_CPEN   168
+#define OVERO_GPIO_USBH_NRESET 183
+
+#endif /* ____ASM_ARCH_OVERO_H */
+
index 54445642f35d4ff4fd54e137fdcf845acdfb9238..c23c12ccb3532c912285a70ef012dd6b030ff5b1 100644 (file)
@@ -45,6 +45,8 @@ struct omap_mmc_conf {
        unsigned cover:1;
        /* 4 wire signaling is optional, and is only used for SD/SDIO */
        unsigned wire4:1;
+       /* use the internal clock */
+       unsigned internal_clock:1;
        s16 power_pin;
        s16 switch_pin;
        s16 wp_pin;
index 92f7c7238fcd9b94d019287dc1ea7ddd07fca472..719298554ed7ebc9647c931db05106e2b6c0e290 100644 (file)
@@ -15,6 +15,7 @@
 
 struct module;
 struct clk;
+struct clockdomain;
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 
@@ -79,6 +80,8 @@ struct clk {
        u32                     clksel_mask;
        const struct clksel     *clksel;
        struct dpll_data        *dpll_data;
+       const char              *clkdm_name;
+       struct clockdomain      *clkdm;
 #else
        __u8                    rate_offset;
        __u8                    src_offset;
diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h
new file mode 100644 (file)
index 0000000..1f51f01
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * linux/include/asm-arm/arch-omap/clockdomain.h
+ *
+ * OMAP2/3 clockdomain framework functions
+ *
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ *
+ * This program is free software; you can 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_OMAP_CLOCKDOMAIN_H
+#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
+
+#include <mach/powerdomain.h>
+#include <mach/clock.h>
+#include <mach/cpu.h>
+
+/* Clockdomain capability flags */
+#define CLKDM_CAN_FORCE_SLEEP                  (1 << 0)
+#define CLKDM_CAN_FORCE_WAKEUP                 (1 << 1)
+#define CLKDM_CAN_ENABLE_AUTO                  (1 << 2)
+#define CLKDM_CAN_DISABLE_AUTO                 (1 << 3)
+
+#define CLKDM_CAN_HWSUP                (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
+#define CLKDM_CAN_SWSUP                (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
+#define CLKDM_CAN_HWSUP_SWSUP  (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
+
+/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
+#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO                0x0
+#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO         0x1
+
+/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
+#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO                0x0
+#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP         0x1
+#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP                0x2
+#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO         0x3
+
+/*
+ * struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps
+ * and sleepdeps added when a powerdomain should stay active in hwsup mode;
+ * and conversely, removed when the powerdomain should be allowed to go
+ * inactive in hwsup mode.
+ */
+struct clkdm_pwrdm_autodep {
+
+       /* Name of the powerdomain to add a wkdep/sleepdep on */
+       const char *pwrdm_name;
+
+       /* Powerdomain pointer (looked up at clkdm_init() time) */
+       struct powerdomain *pwrdm;
+
+       /* OMAP chip types that this clockdomain dep is valid on */
+       const struct omap_chip_id omap_chip;
+
+};
+
+struct clockdomain {
+
+       /* Clockdomain name */
+       const char *name;
+
+       /* Powerdomain enclosing this clockdomain */
+       const char *pwrdm_name;
+
+       /* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
+       const u16 clktrctrl_mask;
+
+       /* Clockdomain capability flags */
+       const u8 flags;
+
+       /* OMAP chip types that this clockdomain is valid on */
+       const struct omap_chip_id omap_chip;
+
+       /* Usecount tracking */
+       atomic_t usecount;
+
+       /* Powerdomain pointer assigned at clkdm_register() */
+       struct powerdomain *pwrdm;
+
+       struct list_head node;
+
+};
+
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps);
+int clkdm_register(struct clockdomain *clkdm);
+int clkdm_unregister(struct clockdomain *clkdm);
+struct clockdomain *clkdm_lookup(const char *name);
+
+int clkdm_for_each(int (*fn)(struct clockdomain *clkdm));
+struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
+
+void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
+void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
+
+int omap2_clkdm_wakeup(struct clockdomain *clkdm);
+int omap2_clkdm_sleep(struct clockdomain *clkdm);
+
+int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
+int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+
+#endif
index 06093112b665c6b2b77330647f11938cfe898825..ef70e2b0f05413d78e246b27e17ab3602d690cea 100644 (file)
@@ -34,6 +34,7 @@ struct sys_timer;
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
 extern void omap_serial_init(void);
+extern void omap_serial_enable_clocks(int enable);
 #ifdef CONFIG_I2C_OMAP
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
                                 struct i2c_board_info const *info,
@@ -49,6 +50,7 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
 
 /* IO bases for various OMAP processors */
 struct omap_globals {
+       u32             class;          /* OMAP class to detect */
        void __iomem    *tap;           /* Control module ID code */
        void __iomem    *sdrc;          /* SDRAM Controller */
        void __iomem    *sms;           /* SDRAM Memory Scheduler */
@@ -62,6 +64,7 @@ void omap2_set_globals_243x(void);
 void omap2_set_globals_343x(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
+void omap2_set_globals_tap(struct omap_globals *);
 void omap2_set_globals_memory(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
index e3fd62d9a995115bc2514807a8203f52dfe31684..dc9886760577b4be3510571863f38cf03ba0e04c 100644 (file)
@@ -1,13 +1,10 @@
-#ifndef __ASM_ARCH_CONTROL_H
-#define __ASM_ARCH_CONTROL_H
-
 /*
  * arch/arm/plat-omap/include/mach/control.h
  *
  * OMAP2/3 System Control Module definitions
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Copyright (C) 2007 Nokia Corporation
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
  * the Free Software Foundation.
  */
 
+#ifndef __ASM_ARCH_CONTROL_H
+#define __ASM_ARCH_CONTROL_H
+
 #include <mach/io.h>
 
+#ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)                                     \
-       (void __iomem *)IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
+       IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
 #define OMAP243X_CTRL_REGADDR(reg)                                     \
-       (void __iomem *)IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
+       IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
 #define OMAP343X_CTRL_REGADDR(reg)                                     \
-       (void __iomem *)IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+       IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#else
+#define OMAP242X_CTRL_REGADDR(reg)     IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
+#define OMAP243X_CTRL_REGADDR(reg)     IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
+#define OMAP343X_CTRL_REGADDR(reg)     IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#endif /* __ASSEMBLY__ */
 
 /*
  * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
 #define OMAP343X_CONTROL_TEST_KEY_13   (OMAP2_CONTROL_GENERAL + 0x00fc)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
+#define OMAP343X_CONTROL_TEMP_SENSOR   (OMAP2_CONTROL_GENERAL + 0x02b4)
 
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
index 05aee0eda34fb9de569e630bc966e59c4f1a8928..e0464187209dcc9d4227267e251944b1e7cd7337 100644 (file)
@@ -346,9 +346,14 @@ IS_OMAP_TYPE(3430, 0x3430)
                get_sil_revision(system_rev)
 
 /* Various silicon macros defined here */
+#define OMAP242X_CLASS         0x24200000
 #define OMAP2420_REV_ES1_0     0x24200000
 #define OMAP2420_REV_ES2_0     0x24201000
+
+#define OMAP243X_CLASS         0x24300000
 #define OMAP2430_REV_ES1_0     0x24300000
+
+#define OMAP343X_CLASS         0x34300000
 #define OMAP3430_REV_ES1_0     0x34300000
 #define OMAP3430_REV_ES2_0     0x34301000
 #define OMAP3430_REV_ES2_1     0x34302000
index 1b0039bdeb4ee28c0501e94d9c15afe9c060858e..1b11f5c6a2d9769d4acdc543a5fba4bd1a03636d 100644 (file)
 #ifdef CONFIG_OMAP_LL_DEBUG_UART3
                add     \rx, \rx, #0x00004000   @ UART 3
 #endif
+
+#elif  CONFIG_ARCH_OMAP3
+               moveq   \rx, #0x48000000        @ physical base address
+               movne   \rx, #0xd8000000        @ virtual base
+               orr     \rx, \rx, #0x0006a000
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
+               add     \rx, \rx, #0x00002000   @ UART 2
+#endif
+#ifdef CONFIG_OMAP_LL_DEBUG_UART3
+               add     \rx, \rx, #0x00fb0000   @ UART 3
+               add     \rx, \rx, #0x00006000
+#endif
 #endif
                .endm
 
index d4e9043bf2013c23b08f34c9eefcba9322059c45..030118ee204a655065e733508f1feee26c7aa3f2 100644 (file)
 1510:
                .endm
 
-#elif defined(CONFIG_ARCH_OMAP24XX)
+#endif
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 
+#if defined(CONFIG_ARCH_OMAP24XX)
 #include <mach/omap24xx.h>
+#endif
+#if defined(CONFIG_ARCH_OMAP34XX)
+#include <mach/omap34xx.h>
+#endif
+
+#define INTCPS_SIR_IRQ_OFFSET  0x0040          /* Active interrupt number */
 
                .macro  disable_fiq
                .endm
@@ -79,7 +87,7 @@
                ldr     \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
                cmp     \irqnr, #0x0
 2222:
-               ldrne   \irqnr, [\base, #IRQ_SIR_IRQ]
+               ldrne   \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
 
                .endm
 
index c92e4b42b2899cc0e6fdad376813815734cd5341..f1864a652f7a9adde718fc646062db39a0941ceb 100644 (file)
@@ -34,9 +34,9 @@ extern void omap1510_fpga_init_irq(void);
  * ---------------------------------------------------------------------------
  */
 /* 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_BASE             IOMEM(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 + 0x300)
 #define H2P2_DBG_FPGA_FPGA_REV         (H2P2_DBG_FPGA_BASE + 0x10)     /* FPGA Revision */
@@ -85,9 +85,9 @@ struct h2p2_dbg_fpga {
  *  OMAP-1510 FPGA
  * ---------------------------------------------------------------------------
  */
-#define OMAP1510_FPGA_BASE                     0xE8000000      /* Virtual */
-#define OMAP1510_FPGA_SIZE                     SZ_4K
-#define OMAP1510_FPGA_START                    0x08000000      /* Physical */
+#define OMAP1510_FPGA_BASE             IOMEM(0xE8000000)       /* VA */
+#define OMAP1510_FPGA_SIZE             SZ_4K
+#define OMAP1510_FPGA_START            0x08000000              /* PA */
 
 /* Revision */
 #define OMAP1510_FPGA_REV_LOW                  (OMAP1510_FPGA_BASE + 0x0)
index 8c71e288860fcec75a16f98ff0d0bbcc3b8fde34..98e9008b7e9d172ad06eb50a000cca0ef5443bb0 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/io.h>
 #include <mach/irqs.h>
 
-#define OMAP_MPUIO_BASE                        (void __iomem *)0xfffb5000
+#define OMAP_MPUIO_BASE                        0xfffb5000
 
 #ifdef CONFIG_ARCH_OMAP730
 #define OMAP_MPUIO_INPUT_LATCH         0x00
@@ -76,6 +76,8 @@ extern void omap_free_gpio(int gpio);
 extern void omap_set_gpio_direction(int gpio, int is_input);
 extern void omap_set_gpio_dataout(int gpio, int enable);
 extern int omap_get_gpio_datain(int gpio);
+extern void omap2_gpio_prepare_for_retention(void);
+extern void omap2_gpio_resume_after_retention(void);
 extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
 
index 6a8e07ffc2d03431b5da8b43b6a67122a212c071..45b678439bb70704b141dc823d0af33ec7237658 100644 (file)
@@ -11,6 +11,9 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM            8
+
 #define GPMC_CS_CONFIG1                0x00
 #define GPMC_CS_CONFIG2                0x04
 #define GPMC_CS_CONFIG3                0x08
@@ -22,6 +25,9 @@
 #define GPMC_CS_NAND_ADDRESS   0x20
 #define GPMC_CS_NAND_DATA      0x24
 
+#define GPMC_CONFIG            0x50
+#define GPMC_STATUS            0x54
+
 #define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
 #define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
 #define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
@@ -78,9 +84,14 @@ struct gpmc_timings {
        u16 access;             /* Start-cycle to first data valid delay */
        u16 rd_cycle;           /* Total read cycle time */
        u16 wr_cycle;           /* Total write cycle time */
+
+       /* The following are only on OMAP3430 */
+       u16 wr_access;          /* WRACCESSTIME */
+       u16 wr_data_mux_bus;    /* WRDATAONADMUXBUS */
 };
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
 extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
 extern unsigned long gpmc_get_fclk_period(void);
 
@@ -92,5 +103,6 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
+extern void gpmc_init(void);
 
 #endif
index 07f5d7f21528874c11091d7ec982c87465a051d6..6589ddbb63b2a4c17ea5b91965c7895cdc4c1b33 100644 (file)
@@ -89,7 +89,7 @@
 #define DPLL_CTL               (0xfffecf00)
 
 /* DSP clock control. Must use __raw_readw() and __raw_writew() with these */
-#define DSP_CONFIG_REG_BASE     (0xe1008000)
+#define DSP_CONFIG_REG_BASE     IOMEM(0xe1008000)
 #define DSP_CKCTL              (DSP_CONFIG_REG_BASE + 0x0)
 #define DSP_IDLECT1            (DSP_CONFIG_REG_BASE + 0x4)
 #define DSP_IDLECT2            (DSP_CONFIG_REG_BASE + 0x8)
 
 #include "omap730.h"
 #include "omap1510.h"
-#include "omap24xx.h"
 #include "omap16xx.h"
+#include "omap24xx.h"
 #include "omap34xx.h"
 
 #ifndef __ASSEMBLER__
 #include "board-2430sdp.h"
 #endif
 
+#ifdef CONFIG_MACH_OMAP3_BEAGLE
+#include "board-omap3beagle.h"
+#endif
+
+#ifdef CONFIG_MACH_OMAP_LDP
+#include "board-ldp.h"
+#endif
+
 #ifdef CONFIG_MACH_OMAP_APOLLON
 #include "board-apollon.h"
 #endif
index 2a30b7d88cdeae71cff778ae13c90bbb65d950f7..adc83b7b82052f296dae128af5597084ed1c1e45 100644 (file)
 
 #if defined(CONFIG_ARCH_OMAP1)
 
-#define IO_PHYS                0xFFFB0000
-#define IO_OFFSET      0x01000000      /* Virtual IO = 0xfefb0000 */
-#define IO_SIZE                0x40000
-#define IO_VIRT                (IO_PHYS - IO_OFFSET)
-#define IO_ADDRESS(pa) ((pa) - IO_OFFSET)
-#define OMAP1_IO_ADDRESS(pa)   ((pa) - IO_OFFSET)
-#define io_p2v(pa)     ((pa) - IO_OFFSET)
-#define io_v2p(va)     ((va) + IO_OFFSET)
+#define IO_PHYS                        0xFFFB0000
+#define IO_OFFSET              0x01000000      /* Virtual IO = 0xfefb0000 */
+#define IO_SIZE                        0x40000
+#define IO_VIRT                        (IO_PHYS - IO_OFFSET)
+#define __IO_ADDRESS(pa)       ((pa) - IO_OFFSET)
+#define __OMAP1_IO_ADDRESS(pa) ((pa) - IO_OFFSET)
+#define io_v2p(va)             ((va) + IO_OFFSET)
 
 #elif defined(CONFIG_ARCH_OMAP2)
 
@@ -74,7 +73,6 @@
 #define L4_24XX_VIRT   0xd8000000
 #define L4_24XX_SIZE   SZ_1M           /* 1MB of 128MB used, want 1MB sect */
 
-#ifdef CONFIG_ARCH_OMAP2430
 #define L4_WK_243X_PHYS                L4_WK_243X_BASE         /* 0x49000000 */
 #define L4_WK_243X_VIRT                0xd9000000
 #define L4_WK_243X_SIZE                SZ_1M
 #define OMAP243X_SMS_VIRT      0xFC000000
 #define OMAP243X_SMS_SIZE      SZ_1M
 
-#endif
-
-#define IO_OFFSET      0x90000000
-#define IO_ADDRESS(pa) ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
-#define OMAP2_IO_ADDRESS(pa)   ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
-#define io_p2v(pa)     ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
-#define io_v2p(va)     ((va) - IO_OFFSET)      /* Works for L3 and L4 */
+#define IO_OFFSET              0x90000000
+#define __IO_ADDRESS(pa)       ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
+#define __OMAP2_IO_ADDRESS(pa) ((pa) + IO_OFFSET)      /* Works for L3 and L4 */
+#define io_v2p(va)             ((va) - IO_OFFSET)      /* Works for L3 and L4 */
 
 /* DSP */
 #define DSP_MEM_24XX_PHYS      OMAP2420_DSP_MEM_BASE   /* 0x58000000 */
 
 
 #define IO_OFFSET              0x90000000
-#define IO_ADDRESS(pa)         ((pa) + IO_OFFSET)/* Works for L3 and L4 */
-#define OMAP2_IO_ADDRESS(pa)   ((pa) + IO_OFFSET)/* Works for L3 and L4 */
-#define io_p2v(pa)             ((pa) + IO_OFFSET)/* Works for L3 and L4 */
+#define __IO_ADDRESS(pa)       ((pa) + IO_OFFSET)/* Works for L3 and L4 */
+#define __OMAP2_IO_ADDRESS(pa) ((pa) + IO_OFFSET)/* Works for L3 and L4 */
 #define io_v2p(va)             ((va) - IO_OFFSET)/* Works for L3 and L4 */
 
 /* DSP */
 
 #endif
 
-#ifndef __ASSEMBLER__
+#define IO_ADDRESS(pa)         IOMEM(__IO_ADDRESS(pa))
+#define OMAP1_IO_ADDRESS(pa)   IOMEM(__OMAP1_IO_ADDRESS(pa))
+#define OMAP2_IO_ADDRESS(pa)   IOMEM(__OMAP2_IO_ADDRESS(pa))
+
+#ifdef __ASSEMBLER__
+#define IOMEM(x)               x
+#else
+#define IOMEM(x)               ((void __force __iomem *)(x))
 
 /*
  * Functions to access the OMAP IO region
  *      - DO NOT use hardcoded virtual addresses to allow changing the
  *        IO address space again if needed
  */
-#define omap_readb(a)          (*(volatile unsigned char  *)IO_ADDRESS(a))
-#define omap_readw(a)          (*(volatile unsigned short *)IO_ADDRESS(a))
-#define omap_readl(a)          (*(volatile unsigned int   *)IO_ADDRESS(a))
+#define omap_readb(a)          __raw_readb(IO_ADDRESS(a))
+#define omap_readw(a)          __raw_readw(IO_ADDRESS(a))
+#define omap_readl(a)          __raw_readl(IO_ADDRESS(a))
 
-#define omap_writeb(v,a)       (*(volatile unsigned char  *)IO_ADDRESS(a) = (v))
-#define omap_writew(v,a)       (*(volatile unsigned short *)IO_ADDRESS(a) = (v))
-#define omap_writel(v,a)       (*(volatile unsigned int   *)IO_ADDRESS(a) = (v))
+#define omap_writeb(v,a)       __raw_writeb(v, IO_ADDRESS(a))
+#define omap_writew(v,a)       __raw_writew(v, IO_ADDRESS(a))
+#define omap_writel(v,a)       __raw_writel(v, IO_ADDRESS(a))
 
 extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
@@ -192,6 +193,12 @@ extern void omap1_init_common_hw(void);
 extern void omap2_map_common_io(void);
 extern void omap2_init_common_hw(void);
 
+#define __arch_ioremap(p,s,t)  omap_ioremap(p,s,t)
+#define __arch_iounmap(v)      omap_iounmap(v)
+
+void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
+void omap_iounmap(volatile void __iomem *addr);
+
 #endif
 
 #endif
index 62aa7dfb9464c9ef375acc6d2ac1283413f4486e..a2929ac8c68733a6e4b606d5737a01a9fafb3fb8 100644 (file)
 #define INT_UART2              (15 + IH2_BASE)
 #define INT_BT_MCSI1TX         (16 + IH2_BASE)
 #define INT_BT_MCSI1RX         (17 + IH2_BASE)
+#define INT_SOSSI_MATCH                (19 + IH2_BASE)
 #define INT_USB_W2FC           (20 + IH2_BASE)
 #define INT_1WIRE              (21 + IH2_BASE)
 #define INT_OS_TIMER           (22 + IH2_BASE)
 #define INT_1610_DMA_CH14      (61 + IH2_BASE)
 #define INT_1610_DMA_CH15      (62 + IH2_BASE)
 #define INT_1610_NAND          (63 + IH2_BASE)
+#define INT_1610_SHA1MD5       (91 + IH2_BASE)
 
 /*
  * OMAP-730 specific IRQ numbers for interrupt handler 2
 #define INT_24XX_GPTIMER10     46
 #define INT_24XX_GPTIMER11     47
 #define INT_24XX_GPTIMER12     48
+#define INT_24XX_SHA1MD5       51
+#define INT_24XX_MCBSP4_IRQ_TX 54
+#define INT_24XX_MCBSP4_IRQ_RX 55
 #define INT_24XX_I2C1_IRQ      56
 #define INT_24XX_I2C2_IRQ      57
+#define INT_24XX_HDQ_IRQ       58
 #define INT_24XX_MCBSP1_IRQ_TX 59
 #define INT_24XX_MCBSP1_IRQ_RX 60
 #define INT_24XX_MCBSP2_IRQ_TX 62
 #define INT_24XX_MCBSP2_IRQ_RX 63
+#define INT_24XX_SPI1_IRQ      65
+#define INT_24XX_SPI2_IRQ      66
 #define INT_24XX_UART1_IRQ     72
 #define INT_24XX_UART2_IRQ     73
 #define INT_24XX_UART3_IRQ     74
 #define INT_24XX_USB_IRQ_HGEN  78
 #define INT_24XX_USB_IRQ_HSOF  79
 #define INT_24XX_USB_IRQ_OTG   80
+#define INT_24XX_MCBSP5_IRQ_TX 81
+#define INT_24XX_MCBSP5_IRQ_RX 82
 #define INT_24XX_MMC_IRQ       83
+#define INT_24XX_MMC2_IRQ      86
+#define INT_24XX_MCBSP3_IRQ_TX 89
+#define INT_24XX_MCBSP3_IRQ_RX 90
+#define INT_24XX_SPI3_IRQ      91
+
+#define INT_243X_MCBSP2_IRQ    16
+#define INT_243X_MCBSP3_IRQ    17
+#define INT_243X_MCBSP4_IRQ    18
+#define INT_243X_MCBSP5_IRQ    19
+#define INT_243X_MCBSP1_IRQ    64
+#define INT_243X_HS_USB_MC     92
+#define INT_243X_HS_USB_DMA    93
+#define INT_243X_CARKIT_IRQ    94
+
+#define INT_34XX_BENCH_MPU_EMUL        3
+#define INT_34XX_ST_MCBSP2_IRQ 4
+#define INT_34XX_ST_MCBSP3_IRQ 5
+#define INT_34XX_SSM_ABORT_IRQ 6
+#define INT_34XX_SYS_NIRQ      7
+#define INT_34XX_D2D_FW_IRQ    8
+#define INT_34XX_PRCM_MPU_IRQ  11
+#define INT_34XX_MCBSP1_IRQ    16
+#define INT_34XX_MCBSP2_IRQ    17
+#define INT_34XX_MCBSP3_IRQ    22
+#define INT_34XX_MCBSP4_IRQ    23
+#define INT_34XX_CAM_IRQ       24
+#define INT_34XX_MCBSP5_IRQ    27
+#define INT_34XX_GPIO_BANK1    29
+#define INT_34XX_GPIO_BANK2    30
+#define INT_34XX_GPIO_BANK3    31
+#define INT_34XX_GPIO_BANK4    32
+#define INT_34XX_GPIO_BANK5    33
+#define INT_34XX_GPIO_BANK6    34
+#define INT_34XX_USIM_IRQ      35
+#define INT_34XX_WDT3_IRQ      36
+#define INT_34XX_SPI4_IRQ      48
+#define INT_34XX_SHA1MD52_IRQ  49
+#define INT_34XX_FPKA_READY_IRQ        50
+#define INT_34XX_SHA1MD51_IRQ  51
+#define INT_34XX_RNG_IRQ       52
+#define INT_34XX_I2C3_IRQ      61
+#define INT_34XX_FPKA_ERROR_IRQ        64
+#define INT_34XX_PBIAS_IRQ     75
+#define INT_34XX_OHCI_IRQ      76
+#define INT_34XX_EHCI_IRQ      77
+#define INT_34XX_TLL_IRQ       78
+#define INT_34XX_PARTHASH_IRQ  79
+#define INT_34XX_MMC3_IRQ      94
+#define INT_34XX_GPT12_IRQ     95
 
 #define        INT_34XX_BENCH_MPU_EMUL 3
 
index 8fdb95e26fcd86775fe4fd494139e381b17f76e5..6a0d1a0a24a7d86f2f767130de8ed9ea95073e3c 100644 (file)
 
 #define OMAP24XX_MCBSP1_BASE   0x48074000
 #define OMAP24XX_MCBSP2_BASE   0x48076000
+#define OMAP2430_MCBSP3_BASE   0x4808c000
+#define OMAP2430_MCBSP4_BASE   0x4808e000
+#define OMAP2430_MCBSP5_BASE   0x48096000
 
 #define OMAP34XX_MCBSP1_BASE   0x48074000
 #define OMAP34XX_MCBSP2_BASE   0x49022000
+#define OMAP34XX_MCBSP3_BASE   0x49024000
+#define OMAP34XX_MCBSP4_BASE   0x49026000
+#define OMAP34XX_MCBSP5_BASE   0x48096000
 
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730)
 
@@ -81,9 +87,6 @@
 #define OMAP_MCBSP_REG_XCERG   0x3A
 #define OMAP_MCBSP_REG_XCERH   0x3C
 
-#define OMAP_MAX_MCBSP_COUNT   3
-#define MAX_MCBSP_CLOCKS       3
-
 #define AUDIO_MCBSP_DATAWRITE  (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
 #define AUDIO_MCBSP_DATAREAD   (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
 
 #define AUDIO_DMA_TX           OMAP_DMA_MCBSP1_TX
 #define AUDIO_DMA_RX           OMAP_DMA_MCBSP1_RX
 
-#elif defined(CONFIG_ARCH_OMAP24XX)
+#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
 
 #define OMAP_MCBSP_REG_DRR2    0x00
 #define OMAP_MCBSP_REG_DRR1    0x04
 #define OMAP_MCBSP_REG_DXR2    0x08
 #define OMAP_MCBSP_REG_DXR1    0x0C
+#define OMAP_MCBSP_REG_DRR     0x00
+#define OMAP_MCBSP_REG_DXR     0x08
 #define OMAP_MCBSP_REG_SPCR2   0x10
 #define OMAP_MCBSP_REG_SPCR1   0x14
 #define OMAP_MCBSP_REG_RCR2    0x18
 #define OMAP_MCBSP_REG_RCERH   0x70
 #define OMAP_MCBSP_REG_XCERG   0x74
 #define OMAP_MCBSP_REG_XCERH   0x78
-
-#define OMAP_MAX_MCBSP_COUNT   2
-#define MAX_MCBSP_CLOCKS       2
+#define OMAP_MCBSP_REG_SYSCON  0x8C
+#define OMAP_MCBSP_REG_XCCR    0xAC
+#define OMAP_MCBSP_REG_RCCR    0xB0
 
 #define AUDIO_MCBSP_DATAWRITE  (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
 #define AUDIO_MCBSP_DATAREAD   (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
 
 #endif
 
-#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 DXENA                  0x0080
 #define CLKSTP(value)          ((value)<<11)   /* bits 11:12 */
 #define RJUST(value)           ((value)<<13)   /* bits 13:14 */
+#define ALB                    0x8000
 #define DLB                    0x8000
 
 /************************** McBSP SPCR2 bit definitions ***********************/
 #define XPABLK(value)          ((value)<<5)    /* Bits 5:6 */
 #define XPBBLK(value)          ((value)<<7)    /* Bits 7:8 */
 
+/*********************** McBSP XCCR bit definitions *************************/
+#define DILB                   0x0020
+#define XDMAEN                 0x0008
+#define XDISABLE               0x0001
+
+/********************** McBSP RCCR bit definitions *************************/
+#define RDMAEN                 0x0008
+#define RDISABLE               0x0001
+
+/********************** McBSP SYSCONFIG bit definitions ********************/
+#define SOFTRST                        0x0002
 
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
@@ -260,6 +273,8 @@ typedef enum {
        OMAP_MCBSP1 = 0,
        OMAP_MCBSP2,
        OMAP_MCBSP3,
+       OMAP_MCBSP4,
+       OMAP_MCBSP5
 } omap_mcbsp_id;
 
 typedef int __bitwise omap_mcbsp_io_type_t;
@@ -311,12 +326,10 @@ struct omap_mcbsp_spi_cfg {
 struct omap_mcbsp_ops {
        void (*request)(unsigned int);
        void (*free)(unsigned int);
-       int (*check)(unsigned int);
 };
 
 struct omap_mcbsp_platform_data {
        unsigned long phys_base;
-       u32 virt_base;
        u8 dma_rx_sync, dma_tx_sync;
        u16 rx_irq, tx_irq;
        struct omap_mcbsp_ops *ops;
@@ -326,7 +339,7 @@ struct omap_mcbsp_platform_data {
 struct omap_mcbsp {
        struct device *dev;
        unsigned long phys_base;
-       u32 io_base;
+       void __iomem *io_base;
        u8 id;
        u8 free;
        omap_mcbsp_word_length rx_word_length;
@@ -354,6 +367,8 @@ struct omap_mcbsp {
        struct omap_mcbsp_platform_data *pdata;
        struct clk *clk;
 };
+extern struct omap_mcbsp **mcbsp_ptr;
+extern int omap_mcbsp_count;
 
 int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
@@ -378,5 +393,6 @@ void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg *
 /* Polled read/write functions */
 int omap_mcbsp_pollread(unsigned int id, u16 * buf);
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 
 #endif
index a325caf80d04b9a18928a7b6478a64ab4f5338e3..d40cac60b95986043e4ff9bb4fce21bea5a6b1fa 100644 (file)
@@ -38,7 +38,7 @@
  */
 #if defined(CONFIG_ARCH_OMAP1)
 #define PHYS_OFFSET            UL(0x10000000)
-#elif defined(CONFIG_ARCH_OMAP2)
+#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 #define PHYS_OFFSET            UL(0x80000000)
 #endif
 
index 614b2c1327c747b77b5c693979babc566bd66d02..6bbf1789bed5debac64e2f9a7bc4ab0b19c0a834 100644 (file)
        .pu_pd_val      = pull_mode,                            \
 },
 
-
-#define PULL_DISABLED  0
-#define PULL_ENABLED   1
-
-#define PULL_DOWN      0
-#define PULL_UP                1
+/* 24xx/34xx mux bit defines */
+#define OMAP2_PULL_ENA         (1 << 3)
+#define OMAP2_PULL_UP          (1 << 4)
+#define OMAP2_ALTELECTRICALSEL (1 << 5)
+
+/* 34xx specific mux bit defines */
+#define OMAP3_INPUT_EN         (1 << 8)
+#define OMAP3_OFF_EN           (1 << 9)
+#define OMAP3_OFFOUT_EN                (1 << 10)
+#define OMAP3_OFFOUT_VAL       (1 << 11)
+#define OMAP3_OFF_PULL_EN      (1 << 12)
+#define OMAP3_OFF_PULL_UP      (1 << 13)
+#define OMAP3_WAKEUP_EN                (1 << 14)
+
+/* 34xx mux mode options for each pin. See TRM for options */
+#define        OMAP34XX_MUX_MODE0      0
+#define        OMAP34XX_MUX_MODE1      1
+#define        OMAP34XX_MUX_MODE2      2
+#define        OMAP34XX_MUX_MODE3      3
+#define        OMAP34XX_MUX_MODE4      4
+#define        OMAP34XX_MUX_MODE5      5
+#define        OMAP34XX_MUX_MODE6      6
+#define        OMAP34XX_MUX_MODE7      7
+
+/* 34xx active pin states */
+#define OMAP34XX_PIN_OUTPUT            0
+#define OMAP34XX_PIN_INPUT             OMAP3_INPUT_EN
+#define OMAP34XX_PIN_INPUT_PULLUP      (OMAP2_PULL_ENA | OMAP3_INPUT_EN \
+                                               | OMAP2_PULL_UP)
+#define OMAP34XX_PIN_INPUT_PULLDOWN    (OMAP2_PULL_ENA | OMAP3_INPUT_EN)
+
+/* 34xx off mode states */
+#define OMAP34XX_PIN_OFF_NONE           0
+#define OMAP34XX_PIN_OFF_OUTPUT_HIGH   (OMAP3_OFF_EN | OMAP3_OFFOUT_EN \
+                                               | OMAP3_OFFOUT_VAL)
+#define OMAP34XX_PIN_OFF_OUTPUT_LOW    (OMAP3_OFF_EN | OMAP3_OFFOUT_EN)
+#define OMAP34XX_PIN_OFF_INPUT_PULLUP  (OMAP3_OFF_EN | OMAP3_OFF_PULL_EN \
+                                               | OMAP3_OFF_PULL_UP)
+#define OMAP34XX_PIN_OFF_INPUT_PULLDOWN        (OMAP3_OFF_EN | OMAP3_OFF_PULL_EN)
+#define OMAP34XX_PIN_OFF_WAKEUPENABLE  OMAP3_WAKEUP_EN
+
+#define MUX_CFG_34XX(desc, reg_offset, mux_value) {            \
+       .name           = desc,                                 \
+       .debug          = 0,                                    \
+       .mux_reg        = reg_offset,                           \
+       .mux_val        = mux_value                             \
+},
 
 struct pin_config {
-       char *name;
-       unsigned char busy;
-       unsigned char debug;
+       char                    *name;
+       const unsigned int      mux_reg;
+       unsigned char           debug;
 
-       const char *mux_reg_name;
-       const unsigned int mux_reg;
+#if    defined(CONFIG_ARCH_OMAP34XX)
+       u16                     mux_val; /* Wake-up, off mode, pull, mux mode */
+#endif
+
+#if    defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP24XX)
        const unsigned char mask_offset;
        const unsigned char mask;
 
@@ -150,6 +194,12 @@ struct pin_config {
        const char *pu_pd_name;
        const unsigned int pu_pd_reg;
        const unsigned char pu_pd_val;
+#endif
+
+#if    defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
+       const char *mux_reg_name;
+#endif
+
 };
 
 enum omap730_index {
@@ -593,6 +643,114 @@ enum omap24xx_index {
 
 };
 
+enum omap34xx_index {
+       /* 34xx I2C */
+       K21_34XX_I2C1_SCL,
+       J21_34XX_I2C1_SDA,
+       AF15_34XX_I2C2_SCL,
+       AE15_34XX_I2C2_SDA,
+       AF14_34XX_I2C3_SCL,
+       AG14_34XX_I2C3_SDA,
+       AD26_34XX_I2C4_SCL,
+       AE26_34XX_I2C4_SDA,
+
+       /* PHY - HSUSB: 12-pin ULPI PHY: Port 1*/
+       Y8_3430_USB1HS_PHY_CLK,
+       Y9_3430_USB1HS_PHY_STP,
+       AA14_3430_USB1HS_PHY_DIR,
+       AA11_3430_USB1HS_PHY_NXT,
+       W13_3430_USB1HS_PHY_DATA0,
+       W12_3430_USB1HS_PHY_DATA1,
+       W11_3430_USB1HS_PHY_DATA2,
+       Y11_3430_USB1HS_PHY_DATA3,
+       W9_3430_USB1HS_PHY_DATA4,
+       Y12_3430_USB1HS_PHY_DATA5,
+       W8_3430_USB1HS_PHY_DATA6,
+       Y13_3430_USB1HS_PHY_DATA7,
+
+       /* PHY - HSUSB: 12-pin ULPI PHY: Port 2*/
+       AA8_3430_USB2HS_PHY_CLK,
+       AA10_3430_USB2HS_PHY_STP,
+       AA9_3430_USB2HS_PHY_DIR,
+       AB11_3430_USB2HS_PHY_NXT,
+       AB10_3430_USB2HS_PHY_DATA0,
+       AB9_3430_USB2HS_PHY_DATA1,
+       W3_3430_USB2HS_PHY_DATA2,
+       T4_3430_USB2HS_PHY_DATA3,
+       T3_3430_USB2HS_PHY_DATA4,
+       R3_3430_USB2HS_PHY_DATA5,
+       R4_3430_USB2HS_PHY_DATA6,
+       T2_3430_USB2HS_PHY_DATA7,
+
+
+       /* TLL - HSUSB: 12-pin TLL Port 1*/
+       Y8_3430_USB1HS_TLL_CLK,
+       Y9_3430_USB1HS_TLL_STP,
+       AA14_3430_USB1HS_TLL_DIR,
+       AA11_3430_USB1HS_TLL_NXT,
+       W13_3430_USB1HS_TLL_DATA0,
+       W12_3430_USB1HS_TLL_DATA1,
+       W11_3430_USB1HS_TLL_DATA2,
+       Y11_3430_USB1HS_TLL_DATA3,
+       W9_3430_USB1HS_TLL_DATA4,
+       Y12_3430_USB1HS_TLL_DATA5,
+       W8_3430_USB1HS_TLL_DATA6,
+       Y13_3430_USB1HS_TLL_DATA7,
+
+       /* TLL - HSUSB: 12-pin TLL Port 2*/
+       AA8_3430_USB2HS_TLL_CLK,
+       AA10_3430_USB2HS_TLL_STP,
+       AA9_3430_USB2HS_TLL_DIR,
+       AB11_3430_USB2HS_TLL_NXT,
+       AB10_3430_USB2HS_TLL_DATA0,
+       AB9_3430_USB2HS_TLL_DATA1,
+       W3_3430_USB2HS_TLL_DATA2,
+       T4_3430_USB2HS_TLL_DATA3,
+       T3_3430_USB2HS_TLL_DATA4,
+       R3_3430_USB2HS_TLL_DATA5,
+       R4_3430_USB2HS_TLL_DATA6,
+       T2_3430_USB2HS_TLL_DATA7,
+
+       /* TLL - HSUSB: 12-pin TLL Port 3*/
+       AA6_3430_USB3HS_TLL_CLK,
+       AB3_3430_USB3HS_TLL_STP,
+       AA3_3430_USB3HS_TLL_DIR,
+       Y3_3430_USB3HS_TLL_NXT,
+       AA5_3430_USB3HS_TLL_DATA0,
+       Y4_3430_USB3HS_TLL_DATA1,
+       Y5_3430_USB3HS_TLL_DATA2,
+       W5_3430_USB3HS_TLL_DATA3,
+       AB12_3430_USB3HS_TLL_DATA4,
+       AB13_3430_USB3HS_TLL_DATA5,
+       AA13_3430_USB3HS_TLL_DATA6,
+       AA12_3430_USB3HS_TLL_DATA7,
+
+       /* PHY FSUSB: FS Serial for Port 1 (multiple PHY modes supported) */
+       AF10_3430_USB1FS_PHY_MM1_RXDP,
+       AG9_3430_USB1FS_PHY_MM1_RXDM,
+       W13_3430_USB1FS_PHY_MM1_RXRCV,
+       W12_3430_USB1FS_PHY_MM1_TXSE0,
+       W11_3430_USB1FS_PHY_MM1_TXDAT,
+       Y11_3430_USB1FS_PHY_MM1_TXEN_N,
+
+       /* PHY FSUSB: FS Serial for Port 2 (multiple PHY modes supported) */
+       AF7_3430_USB2FS_PHY_MM2_RXDP,
+       AH7_3430_USB2FS_PHY_MM2_RXDM,
+       AB10_3430_USB2FS_PHY_MM2_RXRCV,
+       AB9_3430_USB2FS_PHY_MM2_TXSE0,
+       W3_3430_USB2FS_PHY_MM2_TXDAT,
+       T4_3430_USB2FS_PHY_MM2_TXEN_N,
+
+       /* PHY FSUSB: FS Serial for Port 3 (multiple PHY modes supported) */
+       AH3_3430_USB3FS_PHY_MM3_RXDP,
+       AE3_3430_USB3FS_PHY_MM3_RXDM,
+       AD1_3430_USB3FS_PHY_MM3_RXRCV,
+       AE1_3430_USB3FS_PHY_MM3_TXSE0,
+       AD2_3430_USB3FS_PHY_MM3_TXDAT,
+       AC1_3430_USB3FS_PHY_MM3_TXEN_N,
+
+};
+
 struct omap_mux_cfg {
        struct pin_config       *pins;
        unsigned long           size;
index 505a38af8b22a36376c65e2374cf7b13d8f42361..d240046681381e071f98f1187d425b119e7b7594 100644 (file)
@@ -44,5 +44,7 @@
 #define OMAP1510_DSPREG_SIZE   SZ_128K
 #define OMAP1510_DSPREG_START  0xE1000000
 
+#define OMAP1510_DSP_MMU_BASE  (0xfffed200)
+
 #endif /*  __ASM_ARCH_OMAP15XX_H */
 
index c6c93afb2788f4b00911a67ec6d538570ec4a7ca..0e69b504c25fa1231a0fc1bd0f800432b50c57c2 100644 (file)
 #define OMAP16XX_DSPREG_SIZE   SZ_128K
 #define OMAP16XX_DSPREG_START  0xE1000000
 
+#define OMAP16XX_SEC_BASE      0xFFFE4000
+#define OMAP16XX_SEC_DES       (OMAP16XX_SEC_BASE + 0x0000)
+#define OMAP16XX_SEC_SHA1MD5   (OMAP16XX_SEC_BASE + 0x0800)
+#define OMAP16XX_SEC_RNG       (OMAP16XX_SEC_BASE + 0x1000)
+
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
 #define WSPR_DISABLE_0         (0x0000aaaa)
 #define WSPR_DISABLE_1         (0x00005555)
 
-/* Mailbox */
+#define OMAP16XX_DSP_MMU_BASE  (0xfffed200)
 #define OMAP16XX_MAILBOX_BASE  (0xfffcf000)
 
 #endif /*  __ASM_ARCH_OMAP16XX_H */
index bb8319d66e9f5afa64a2798ccaca93ee98e76d57..24335d4932f5c725a13583197633bcd08fced549 100644 (file)
@@ -39,7 +39,6 @@
 /* interrupt controller */
 #define OMAP24XX_IC_BASE       (L4_24XX_BASE + 0xfe000)
 #define OMAP24XX_IVA_INTC_BASE 0x40000000
-#define IRQ_SIR_IRQ            0x0040
 
 #define OMAP2420_CTRL_BASE     L4_24XX_BASE
 #define OMAP2420_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
@@ -48,6 +47,7 @@
 #define OMAP2420_PRM_BASE      OMAP2420_CM_BASE
 #define OMAP2420_SDRC_BASE     (L3_24XX_BASE + 0x9000)
 #define OMAP2420_SMS_BASE      0x68008000
+#define OMAP2420_GPMC_BASE     0x6800a000
 
 #define OMAP2430_32KSYNCT_BASE (L4_WK_243X_BASE + 0x20000)
 #define OMAP2430_PRCM_BASE     (L4_WK_243X_BASE + 0x6000)
index cae037d130792a7c466a697d079b475c2f756e8b..ec67fb428607c55ba7d4e452db241cd048e7028c 100644 (file)
@@ -62,6 +62,7 @@
 #define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE        0x00010000
 #define OMAPFB_CAPS_WINDOW_SCALE       0x00020000
 #define OMAPFB_CAPS_WINDOW_OVERLAY     0x00040000
+#define OMAPFB_CAPS_WINDOW_ROTATE      0x00080000
 #define OMAPFB_CAPS_SET_BACKLIGHT      0x01000000
 
 /* Values from DSP must map to lower 16-bits */
@@ -305,6 +306,7 @@ struct lcd_ctrl {
                                           int screen_width,
                                           int pos_x, int pos_y, int width,
                                           int height, int color_mode);
+       int             (*set_rotate)     (int angle);
        int             (*setup_mem)      (int plane, size_t size,
                                           int mem_type, unsigned long *paddr);
        int             (*mmap)           (struct fb_info *info,
@@ -374,6 +376,7 @@ extern struct lcd_ctrl omap1_lcd_ctrl;
 extern struct lcd_ctrl omap2_disp_ctrl;
 #endif
 
+extern void omapfb_reserve_sdram(void);
 extern void omapfb_register_panel(struct lcd_panel *panel);
 extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval);
 extern void omapfb_notify_clients(struct omapfb_device *fbdev,
index bfa09325a5ffad992a7c2aadd05b84d899ccf36d..768eb6e7abcfb719e83a3f085e3955e4b65d07fb 100644 (file)
  * Register and offset definitions to be used in PM assembler code
  * ----------------------------------------------------------------------------
  */
-#define CLKGEN_REG_ASM_BASE            io_p2v(0xfffece00)
+#define CLKGEN_REG_ASM_BASE            IO_ADDRESS(0xfffece00)
 #define ARM_IDLECT1_ASM_OFFSET         0x04
 #define ARM_IDLECT2_ASM_OFFSET         0x08
 
-#define TCMIF_ASM_BASE                 io_p2v(0xfffecc00)
+#define TCMIF_ASM_BASE                 IO_ADDRESS(0xfffecc00)
 #define EMIFS_CONFIG_ASM_OFFSET                0x0c
 #define EMIFF_SDRAM_CONFIG_ASM_OFFSET  0x20
 
@@ -135,7 +135,8 @@ extern void omap_pm_suspend(void);
 extern void omap730_cpu_suspend(unsigned short, unsigned short);
 extern void omap1510_cpu_suspend(unsigned short, unsigned short);
 extern void omap1610_cpu_suspend(unsigned short, unsigned short);
-extern void omap24xx_cpu_suspend(u32 dll_ctrl, u32 cpu_revision);
+extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
+                                       void __iomem *sdrc_power);
 extern void omap730_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h
new file mode 100644 (file)
index 0000000..2806a9c
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * OMAP2/3 powerdomain control
+ *
+ * Copyright (C) 2007-8 Texas Instruments, Inc.
+ * Copyright (C) 2007-8 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ *
+ * This program is free software; you can 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_OMAP_POWERDOMAIN
+#define ASM_ARM_ARCH_OMAP_POWERDOMAIN
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include <asm/atomic.h>
+
+#include <mach/cpu.h>
+
+
+/* Powerdomain basic power states */
+#define PWRDM_POWER_OFF                0x0
+#define PWRDM_POWER_RET                0x1
+#define PWRDM_POWER_INACTIVE   0x2
+#define PWRDM_POWER_ON         0x3
+
+/* Powerdomain allowable state bitfields */
+#define PWRSTS_OFF_ON          ((1 << PWRDM_POWER_OFF) | \
+                                (1 << PWRDM_POWER_ON))
+
+#define PWRSTS_OFF_RET         ((1 << PWRDM_POWER_OFF) | \
+                                (1 << PWRDM_POWER_RET))
+
+#define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
+
+
+/* Powerdomain flags */
+#define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
+
+
+/*
+ * Number of memory banks that are power-controllable. On OMAP3430, the
+ * maximum is 4.
+ */
+#define PWRDM_MAX_MEM_BANKS    4
+
+/*
+ * Maximum number of clockdomains that can be associated with a powerdomain.
+ * CORE powerdomain is probably the worst case.
+ */
+#define PWRDM_MAX_CLKDMS       3
+
+/* XXX A completely arbitrary number. What is reasonable here? */
+#define PWRDM_TRANSITION_BAILOUT 100000
+
+struct clockdomain;
+struct powerdomain;
+
+/* Encodes dependencies between powerdomains - statically defined */
+struct pwrdm_dep {
+
+       /* Powerdomain name */
+       const char *pwrdm_name;
+
+       /* Powerdomain pointer - resolved by the powerdomain code */
+       struct powerdomain *pwrdm;
+
+       /* Flags to mark OMAP chip restrictions, etc. */
+       const struct omap_chip_id omap_chip;
+
+};
+
+struct powerdomain {
+
+       /* Powerdomain name */
+       const char *name;
+
+       /* the address offset from CM_BASE/PRM_BASE */
+       const s16 prcm_offs;
+
+       /* Used to represent the OMAP chip types containing this pwrdm */
+       const struct omap_chip_id omap_chip;
+
+       /* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */
+       const u8 dep_bit;
+
+       /* Powerdomains that can be told to wake this powerdomain up */
+       struct pwrdm_dep *wkdep_srcs;
+
+       /* Powerdomains that can be told to keep this pwrdm from inactivity */
+       struct pwrdm_dep *sleepdep_srcs;
+
+       /* Possible powerdomain power states */
+       const u8 pwrsts;
+
+       /* Possible logic power states when pwrdm in RETENTION */
+       const u8 pwrsts_logic_ret;
+
+       /* Powerdomain flags */
+       const u8 flags;
+
+       /* Number of software-controllable memory banks in this powerdomain */
+       const u8 banks;
+
+       /* Possible memory bank pwrstates when pwrdm in RETENTION */
+       const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
+
+       /* Possible memory bank pwrstates when pwrdm is ON */
+       const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
+
+       /* Clockdomains in this powerdomain */
+       struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
+
+       struct list_head node;
+
+};
+
+
+void pwrdm_init(struct powerdomain **pwrdm_list);
+
+int pwrdm_register(struct powerdomain *pwrdm);
+int pwrdm_unregister(struct powerdomain *pwrdm);
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm));
+
+int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
+int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
+int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
+                        int (*fn)(struct powerdomain *pwrdm,
+                                  struct clockdomain *clkdm));
+
+int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
+int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
+int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
+
+int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
+int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+
+int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
+int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
+
+int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm);
+int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
+bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
+
+int pwrdm_wait_transition(struct powerdomain *pwrdm);
+
+#endif
index 787b7acec546eeaf7330be8e8e834b83e5b22d61..a98c6c3beb2ce1a8d02a6f302a5323989381fe5d 100644 (file)
@@ -25,6 +25,8 @@
 #define SDRC_DLLB_STATUS       0x06C
 #define SDRC_POWER             0x070
 #define SDRC_MR_0              0x084
+#define SDRC_ACTIM_CTRL_A_0    0x09c
+#define SDRC_ACTIM_CTRL_B_0    0x0a0
 #define SDRC_RFR_CTRL_0                0x0a4
 
 /*
@@ -63,9 +65,9 @@
  */
 
 
-#define OMAP242X_SMS_REGADDR(reg)      (void __iomem *)IO_ADDRESS(OMAP2420_SMS_BASE + reg)
-#define OMAP243X_SMS_REGADDR(reg)      (void __iomem *)IO_ADDRESS(OMAP243X_SMS_BASE + reg)
-#define OMAP343X_SMS_REGADDR(reg)      (void __iomem *)IO_ADDRESS(OMAP343X_SMS_BASE + reg)
+#define OMAP242X_SMS_REGADDR(reg)      IO_ADDRESS(OMAP2420_SMS_BASE + reg)
+#define OMAP243X_SMS_REGADDR(reg)      IO_ADDRESS(OMAP243X_SMS_BASE + reg)
+#define OMAP343X_SMS_REGADDR(reg)      IO_ADDRESS(OMAP343X_SMS_BASE + reg)
 
 /* SMS register offsets - read/write with sms_{read,write}_reg() */
 
index cc6bfa51ccb54022498cd8f02f1d68aa433467f0..8a676a04be481b1630cb7d0fa61cc87b00498aa4 100644 (file)
 #define OMAP_UART1_BASE                0x4806a000
 #define OMAP_UART2_BASE                0x4806c000
 #define OMAP_UART3_BASE                0x4806e000
+#elif defined(CONFIG_ARCH_OMAP3)
+/* OMAP3 serial ports */
+#define OMAP_UART1_BASE                0x4806a000
+#define OMAP_UART2_BASE                0x4806c000
+#define OMAP_UART3_BASE                0x49020000
 #endif
 
 #define OMAP_MAX_NR_PORTS      3
 #define OMAP1510_BASE_BAUD     (12000000/16)
 #define OMAP16XX_BASE_BAUD     (48000000/16)
+#define OMAP24XX_BASE_BAUD     (48000000/16)
 
-#define is_omap_port(p       ({int __ret = 0;                        \
-                       if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
-                           p == IO_ADDRESS(OMAP_UART2_BASE) || \
-                           p == IO_ADDRESS(OMAP_UART3_BASE))   \
-                               __ret = 1;                      \
-                       __ret;                                  \
+#define is_omap_port(pt)       ({int __ret = 0;                        \
+                       if ((pt)->port.mapbase == OMAP_UART1_BASE ||    \
+                           (pt)->port.mapbase == OMAP_UART2_BASE ||    \
+                           (pt)->port.mapbase == OMAP_UART3_BASE)      \
+                               __ret = 1;                              \
+                       __ret;                                          \
                        })
 
 #endif
index e09323449981aa230f4b1a6e309d2117878cd548..ab35d622dcf5c4553c6340da777146c89f3b974b 100644 (file)
@@ -21,6 +21,10 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
                                      u32 mem_type);
 extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
 
+extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl,
+                                    u32 sdrc_actim_ctrla,
+                                    u32 sdrc_actim_ctrlb, u32 m2);
+
 /* Do not use these */
 extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
 extern unsigned long omap1_sram_reprogram_clock_sz;
@@ -53,4 +57,10 @@ extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
                                                u32 mem_type);
 extern unsigned long omap243x_sram_reprogram_sdrc_sz;
 
+
+extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl,
+                                         u32 sdrc_actim_ctrla,
+                                         u32 sdrc_actim_ctrlb, u32 m2);
+extern unsigned long omap3_sram_configure_core_dpll_sz;
+
 #endif
index 06a28c7b98de7020054497fbfcb4714dec9ac321..06923f261545c268852f308ae73cb30b4546aa32 100644 (file)
@@ -40,7 +40,7 @@ static inline void omap1_arch_reset(char mode)
 
 static inline void arch_reset(char mode)
 {
-       if (!cpu_is_omap24xx())
+       if (!cpu_class_is_omap2())
                omap1_arch_reset(mode);
        else
                omap_prcm_arch_reset(mode);
diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c
new file mode 100644 (file)
index 0000000..af326ef
--- /dev/null
@@ -0,0 +1,107 @@
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+
+#include <mach/omap730.h>
+#include <mach/omap1510.h>
+#include <mach/omap16xx.h>
+#include <mach/omap24xx.h>
+#include <mach/omap34xx.h>
+
+#define BETWEEN(p,st,sz)       ((p) >= (st) && (p) < ((st) + (sz)))
+#define XLATE(p,pst,vst)       ((void __iomem *)((p) - (pst) + (vst)))
+
+/*
+ * Intercept ioremap() requests for addresses in our fixed mapping regions.
+ */
+void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+#ifdef CONFIG_ARCH_OMAP1
+       if (cpu_class_is_omap1()) {
+               if (BETWEEN(p, IO_PHYS, IO_SIZE))
+                       return XLATE(p, IO_PHYS, IO_VIRT);
+       }
+       if (cpu_is_omap730()) {
+               if (BETWEEN(p, OMAP730_DSP_BASE, OMAP730_DSP_SIZE))
+                       return XLATE(p, OMAP730_DSP_BASE, OMAP730_DSP_START);
+
+               if (BETWEEN(p, OMAP730_DSPREG_BASE, OMAP730_DSPREG_SIZE))
+                       return XLATE(p, OMAP730_DSPREG_BASE,
+                                       OMAP730_DSPREG_START);
+       }
+       if (cpu_is_omap15xx()) {
+               if (BETWEEN(p, OMAP1510_DSP_BASE, OMAP1510_DSP_SIZE))
+                       return XLATE(p, OMAP1510_DSP_BASE, OMAP1510_DSP_START);
+
+               if (BETWEEN(p, OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_SIZE))
+                       return XLATE(p, OMAP1510_DSPREG_BASE,
+                                       OMAP1510_DSPREG_START);
+       }
+       if (cpu_is_omap16xx()) {
+               if (BETWEEN(p, OMAP16XX_DSP_BASE, OMAP16XX_DSP_SIZE))
+                       return XLATE(p, OMAP16XX_DSP_BASE, OMAP16XX_DSP_START);
+
+               if (BETWEEN(p, OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_SIZE))
+                       return XLATE(p, OMAP16XX_DSPREG_BASE,
+                                       OMAP16XX_DSPREG_START);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+       if (cpu_is_omap24xx()) {
+               if (BETWEEN(p, L3_24XX_PHYS, L3_24XX_SIZE))
+                       return XLATE(p, L3_24XX_PHYS, L3_24XX_VIRT);
+               if (BETWEEN(p, L4_24XX_PHYS, L4_24XX_SIZE))
+                       return XLATE(p, L4_24XX_PHYS, L4_24XX_VIRT);
+       }
+       if (cpu_is_omap2420()) {
+               if (BETWEEN(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_SIZE))
+                       return XLATE(p, DSP_MEM_24XX_PHYS, DSP_MEM_24XX_VIRT);
+               if (BETWEEN(p, DSP_IPI_24XX_PHYS, DSP_IPI_24XX_SIZE))
+                       return XLATE(p, DSP_IPI_24XX_PHYS, DSP_IPI_24XX_SIZE);
+               if (BETWEEN(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_SIZE))
+                       return XLATE(p, DSP_MMU_24XX_PHYS, DSP_MMU_24XX_VIRT);
+       }
+       if (cpu_is_omap2430()) {
+               if (BETWEEN(p, L4_WK_243X_PHYS, L4_WK_243X_SIZE))
+                       return XLATE(p, L4_WK_243X_PHYS, L4_WK_243X_VIRT);
+               if (BETWEEN(p, OMAP243X_GPMC_PHYS, OMAP243X_GPMC_SIZE))
+                       return XLATE(p, OMAP243X_GPMC_PHYS, OMAP243X_GPMC_VIRT);
+               if (BETWEEN(p, OMAP243X_SDRC_PHYS, OMAP243X_SDRC_SIZE))
+                       return XLATE(p, OMAP243X_SDRC_PHYS, OMAP243X_SDRC_VIRT);
+               if (BETWEEN(p, OMAP243X_SMS_PHYS, OMAP243X_SMS_SIZE))
+                       return XLATE(p, OMAP243X_SMS_PHYS, OMAP243X_SMS_VIRT);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+       if (cpu_is_omap34xx()) {
+               if (BETWEEN(p, L3_34XX_PHYS, L3_34XX_SIZE))
+                       return XLATE(p, L3_34XX_PHYS, L3_34XX_VIRT);
+               if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE))
+                       return XLATE(p, L4_34XX_PHYS, L4_34XX_VIRT);
+               if (BETWEEN(p, L4_WK_34XX_PHYS, L4_WK_34XX_SIZE))
+                       return XLATE(p, L4_WK_34XX_PHYS, L4_WK_34XX_VIRT);
+               if (BETWEEN(p, OMAP34XX_GPMC_PHYS, OMAP34XX_GPMC_SIZE))
+                       return XLATE(p, OMAP34XX_GPMC_PHYS, OMAP34XX_GPMC_VIRT);
+               if (BETWEEN(p, OMAP343X_SMS_PHYS, OMAP343X_SMS_SIZE))
+                       return XLATE(p, OMAP343X_SMS_PHYS, OMAP343X_SMS_VIRT);
+               if (BETWEEN(p, OMAP343X_SDRC_PHYS, OMAP343X_SDRC_SIZE))
+                       return XLATE(p, OMAP343X_SDRC_PHYS, OMAP343X_SDRC_VIRT);
+               if (BETWEEN(p, L4_PER_34XX_PHYS, L4_PER_34XX_SIZE))
+                       return XLATE(p, L4_PER_34XX_PHYS, L4_PER_34XX_VIRT);
+               if (BETWEEN(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_SIZE))
+                       return XLATE(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_VIRT);
+       }
+#endif
+
+       return __arm_ioremap(p, size, type);
+}
+EXPORT_SYMBOL(omap_ioremap);
+
+void omap_iounmap(volatile void __iomem *addr)
+{
+       unsigned long virt = (unsigned long)addr;
+
+       if (virt >= VMALLOC_START && virt < VMALLOC_END)
+               __iounmap(addr);
+}
+EXPORT_SYMBOL(omap_iounmap);
index 014d26574bb61cd52267db7edfff9ad439e0c4bd..af33fc713e1a325d7e5179d8fa20921ebc1e152d 100644 (file)
 #include <mach/dma.h>
 #include <mach/mcbsp.h>
 
-static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+struct omap_mcbsp **mcbsp_ptr;
+int omap_mcbsp_count;
 
-#define omap_mcbsp_check_valid_id(id)  (mcbsp[id].pdata && \
-                                       mcbsp[id].pdata->ops && \
-                                       mcbsp[id].pdata->ops->check && \
-                                       (mcbsp[id].pdata->ops->check(id) == 0))
+void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val)
+{
+       if (cpu_class_is_omap1() || cpu_is_omap2420())
+               __raw_writew((u16)val, io_base + reg);
+       else
+               __raw_writel(val, io_base + reg);
+}
+
+int omap_mcbsp_read(void __iomem *io_base, u16 reg)
+{
+       if (cpu_class_is_omap1() || cpu_is_omap2420())
+               return __raw_readw(io_base + reg);
+       else
+               return __raw_readl(io_base + reg);
+}
+
+#define OMAP_MCBSP_READ(base, reg) \
+                       omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg)
+#define OMAP_MCBSP_WRITE(base, reg, val) \
+                       omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val)
+
+#define omap_mcbsp_check_valid_id(id)  (id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)            mcbsp_ptr[id];
 
 static void omap_mcbsp_dump_reg(u8 id)
 {
-       dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id);
-       dev_dbg(mcbsp[id].dev, "DRR2:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
-       dev_dbg(mcbsp[id].dev, "DRR1:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
-       dev_dbg(mcbsp[id].dev, "DXR2:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
-       dev_dbg(mcbsp[id].dev, "DXR1:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
-       dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
-       dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
-       dev_dbg(mcbsp[id].dev, "RCR2:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
-       dev_dbg(mcbsp[id].dev, "RCR1:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
-       dev_dbg(mcbsp[id].dev, "XCR2:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
-       dev_dbg(mcbsp[id].dev, "XCR1:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
-       dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
-       dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
-       dev_dbg(mcbsp[id].dev, "PCR0:  0x%04x\n",
-                       OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
-       dev_dbg(mcbsp[id].dev, "***********************\n");
+       struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id);
+
+       dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
+       dev_dbg(mcbsp->dev, "DRR2:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, DRR2));
+       dev_dbg(mcbsp->dev, "DRR1:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, DRR1));
+       dev_dbg(mcbsp->dev, "DXR2:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, DXR2));
+       dev_dbg(mcbsp->dev, "DXR1:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, DXR1));
+       dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, SPCR2));
+       dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, SPCR1));
+       dev_dbg(mcbsp->dev, "RCR2:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, RCR2));
+       dev_dbg(mcbsp->dev, "RCR1:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, RCR1));
+       dev_dbg(mcbsp->dev, "XCR2:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, XCR2));
+       dev_dbg(mcbsp->dev, "XCR1:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, XCR1));
+       dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, SRGR2));
+       dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, SRGR1));
+       dev_dbg(mcbsp->dev, "PCR0:  0x%04x\n",
+                       OMAP_MCBSP_READ(mcbsp->io_base, PCR0));
+       dev_dbg(mcbsp->dev, "***********************\n");
 }
 
 static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
@@ -126,16 +148,18 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
  */
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       io_base = mcbsp[id].io_base;
-       dev_dbg(mcbsp[id].dev, "Configuring McBSP%d  io_base: 0x%8x\n",
-                       mcbsp[id].id, io_base);
+       io_base = mcbsp->io_base;
+       dev_dbg(mcbsp->dev, "Configuring McBSP%d  phys_base: 0x%08lx\n",
+                       mcbsp->id, mcbsp->phys_base);
 
        /* We write the given config */
        OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
@@ -158,23 +182,26 @@ EXPORT_SYMBOL(omap_mcbsp_config);
  */
 int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
 {
+       struct omap_mcbsp *mcbsp;
+
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       spin_lock(&mcbsp[id].lock);
+       spin_lock(&mcbsp->lock);
 
-       if (!mcbsp[id].free) {
-               dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n",
-                       mcbsp[id].id);
-               spin_unlock(&mcbsp[id].lock);
+       if (!mcbsp->free) {
+               dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
+                       mcbsp->id);
+               spin_unlock(&mcbsp->lock);
                return -EINVAL;
        }
 
-       mcbsp[id].io_type = io_type;
+       mcbsp->io_type = io_type;
 
-       spin_unlock(&mcbsp[id].lock);
+       spin_unlock(&mcbsp->lock);
 
        return 0;
 }
@@ -182,53 +209,60 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type);
 
 int omap_mcbsp_request(unsigned int id)
 {
+       struct omap_mcbsp *mcbsp;
        int err;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       if (mcbsp[id].pdata->ops->request)
-               mcbsp[id].pdata->ops->request(id);
+       if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
+               mcbsp->pdata->ops->request(id);
 
-       clk_enable(mcbsp[id].clk);
+       clk_enable(mcbsp->clk);
 
-       spin_lock(&mcbsp[id].lock);
-       if (!mcbsp[id].free) {
-               dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n",
-                       mcbsp[id].id);
-               spin_unlock(&mcbsp[id].lock);
+       spin_lock(&mcbsp->lock);
+       if (!mcbsp->free) {
+               dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
+                       mcbsp->id);
+               spin_unlock(&mcbsp->lock);
                return -1;
        }
 
-       mcbsp[id].free = 0;
-       spin_unlock(&mcbsp[id].lock);
+       mcbsp->free = 0;
+       spin_unlock(&mcbsp->lock);
+
+       /*
+        * Make sure that transmitter, receiver and sample-rate generator are
+        * not running before activating IRQs.
+        */
+       OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR1, 0);
+       OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR2, 0);
 
-       if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+       if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
                /* We need to get IRQs here */
-               err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler,
-                                       0, "McBSP", (void *) (&mcbsp[id]));
+               init_completion(&mcbsp->tx_irq_completion);
+               err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+                                       0, "McBSP", (void *)mcbsp);
                if (err != 0) {
-                       dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d "
-                                       "for McBSP%d\n", mcbsp[id].tx_irq,
-                                       mcbsp[id].id);
+                       dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+                                       "for McBSP%d\n", mcbsp->tx_irq,
+                                       mcbsp->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]));
+               init_completion(&mcbsp->rx_irq_completion);
+               err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler,
+                                       0, "McBSP", (void *)mcbsp);
                if (err != 0) {
-                       dev_err(mcbsp[id].dev, "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]));
+                       dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+                                       "for McBSP%d\n", mcbsp->rx_irq,
+                                       mcbsp->id);
+                       free_irq(mcbsp->tx_irq, (void *)mcbsp);
                        return err;
                }
-
-               init_completion(&(mcbsp[id].rx_irq_completion));
        }
 
        return 0;
@@ -237,31 +271,34 @@ EXPORT_SYMBOL(omap_mcbsp_request);
 
 void omap_mcbsp_free(unsigned int id)
 {
+       struct omap_mcbsp *mcbsp;
+
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       if (mcbsp[id].pdata->ops->free)
-               mcbsp[id].pdata->ops->free(id);
+       if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+               mcbsp->pdata->ops->free(id);
 
-       clk_disable(mcbsp[id].clk);
+       clk_disable(mcbsp->clk);
 
-       spin_lock(&mcbsp[id].lock);
-       if (mcbsp[id].free) {
-               dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n",
-                       mcbsp[id].id);
-               spin_unlock(&mcbsp[id].lock);
+       spin_lock(&mcbsp->lock);
+       if (mcbsp->free) {
+               dev_err(mcbsp->dev, "McBSP%d was not reserved\n",
+                       mcbsp->id);
+               spin_unlock(&mcbsp->lock);
                return;
        }
 
-       mcbsp[id].free = 1;
-       spin_unlock(&mcbsp[id].lock);
+       mcbsp->free = 1;
+       spin_unlock(&mcbsp->lock);
 
-       if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+       if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
                /* Free IRQs */
-               free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
-               free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+               free_irq(mcbsp->rx_irq, (void *)mcbsp);
+               free_irq(mcbsp->tx_irq, (void *)mcbsp);
        }
 }
 EXPORT_SYMBOL(omap_mcbsp_free);
@@ -273,18 +310,19 @@ EXPORT_SYMBOL(omap_mcbsp_free);
  */
 void omap_mcbsp_start(unsigned int id)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
 
-       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;
+       mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7;
+       mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7;
 
        /* Start the sample generator */
        w = OMAP_MCBSP_READ(io_base, SPCR2);
@@ -310,7 +348,8 @@ EXPORT_SYMBOL(omap_mcbsp_start);
 
 void omap_mcbsp_stop(unsigned int id)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -318,7 +357,8 @@ void omap_mcbsp_stop(unsigned int id)
                return;
        }
 
-       io_base = mcbsp[id].io_base;
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
 
        /* Reset transmitter */
        w = OMAP_MCBSP_READ(io_base, SPCR2);
@@ -337,14 +377,17 @@ EXPORT_SYMBOL(omap_mcbsp_stop);
 /* polled mcbsp i/o operations */
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
 {
-       u32 base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *base;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
 
-       base = mcbsp[id].io_base;
+       mcbsp = id_to_mcbsp_ptr(id);
+       base = mcbsp->io_base;
+
        writew(buf, base + OMAP_MCBSP_REG_DXR1);
        /* if frame sync error - clear the error */
        if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {
@@ -366,8 +409,8 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
                                       (XRST),
                                       base + OMAP_MCBSP_REG_SPCR2);
                                udelay(10);
-                               dev_err(mcbsp[id].dev, "Could not write to"
-                                       " McBSP%d Register\n", mcbsp[id].id);
+                               dev_err(mcbsp->dev, "Could not write to"
+                                       " McBSP%d Register\n", mcbsp->id);
                                return -2;
                        }
                }
@@ -379,14 +422,16 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite);
 
 int omap_mcbsp_pollread(unsigned int id, u16 *buf)
 {
-       u32 base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *base;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       base = mcbsp[id].io_base;
+       base = mcbsp->io_base;
        /* if frame sync error - clear the error */
        if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {
                /* clear error */
@@ -407,8 +452,8 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)
                                       (RRST),
                                       base + OMAP_MCBSP_REG_SPCR1);
                                udelay(10);
-                               dev_err(mcbsp[id].dev, "Could not read from"
-                                       " McBSP%d Register\n", mcbsp[id].id);
+                               dev_err(mcbsp->dev, "Could not read from"
+                                       " McBSP%d Register\n", mcbsp->id);
                                return -2;
                        }
                }
@@ -424,7 +469,8 @@ EXPORT_SYMBOL(omap_mcbsp_pollread);
  */
 void omap_mcbsp_xmit_word(unsigned int id, u32 word)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
        omap_mcbsp_word_length word_length;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -432,10 +478,11 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word)
                return;
        }
 
-       io_base = mcbsp[id].io_base;
-       word_length = mcbsp[id].tx_word_length;
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
+       word_length = mcbsp->tx_word_length;
 
-       wait_for_completion(&(mcbsp[id].tx_irq_completion));
+       wait_for_completion(&mcbsp->tx_irq_completion);
 
        if (word_length > OMAP_MCBSP_WORD_16)
                OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
@@ -445,7 +492,8 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word);
 
 u32 omap_mcbsp_recv_word(unsigned int id)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
        u16 word_lsb, word_msb = 0;
        omap_mcbsp_word_length word_length;
 
@@ -453,11 +501,12 @@ u32 omap_mcbsp_recv_word(unsigned int id)
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       word_length = mcbsp[id].rx_word_length;
-       io_base = mcbsp[id].io_base;
+       word_length = mcbsp->rx_word_length;
+       io_base = mcbsp->io_base;
 
-       wait_for_completion(&(mcbsp[id].rx_irq_completion));
+       wait_for_completion(&mcbsp->rx_irq_completion);
 
        if (word_length > OMAP_MCBSP_WORD_16)
                word_msb = OMAP_MCBSP_READ(io_base, DRR2);
@@ -469,7 +518,8 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word);
 
 int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
 {
-       u32 io_base;
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
        omap_mcbsp_word_length tx_word_length;
        omap_mcbsp_word_length rx_word_length;
        u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
@@ -478,10 +528,10 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
-
-       io_base = mcbsp[id].io_base;
-       tx_word_length = mcbsp[id].tx_word_length;
-       rx_word_length = mcbsp[id].rx_word_length;
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
+       tx_word_length = mcbsp->tx_word_length;
+       rx_word_length = mcbsp->rx_word_length;
 
        if (tx_word_length != rx_word_length)
                return -EINVAL;
@@ -496,8 +546,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
                        udelay(10);
                        OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
                        udelay(10);
-                       dev_err(mcbsp[id].dev, "McBSP%d transmitter not "
-                               "ready\n", mcbsp[id].id);
+                       dev_err(mcbsp->dev, "McBSP%d transmitter not "
+                               "ready\n", mcbsp->id);
                        return -EAGAIN;
                }
        }
@@ -517,8 +567,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
                        udelay(10);
                        OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
                        udelay(10);
-                       dev_err(mcbsp[id].dev, "McBSP%d receiver not "
-                               "ready\n", mcbsp[id].id);
+                       dev_err(mcbsp->dev, "McBSP%d receiver not "
+                               "ready\n", mcbsp->id);
                        return -EAGAIN;
                }
        }
@@ -534,7 +584,9 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
 
 int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
 {
-       u32 io_base, clock_word = 0;
+       struct omap_mcbsp *mcbsp;
+       u32 clock_word = 0;
+       void __iomem *io_base;
        omap_mcbsp_word_length tx_word_length;
        omap_mcbsp_word_length rx_word_length;
        u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
@@ -544,9 +596,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
                return -ENODEV;
        }
 
-       io_base = mcbsp[id].io_base;
-       tx_word_length = mcbsp[id].tx_word_length;
-       rx_word_length = mcbsp[id].rx_word_length;
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
+
+       tx_word_length = mcbsp->tx_word_length;
+       rx_word_length = mcbsp->rx_word_length;
 
        if (tx_word_length != rx_word_length)
                return -EINVAL;
@@ -561,8 +615,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
                        udelay(10);
                        OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
                        udelay(10);
-                       dev_err(mcbsp[id].dev, "McBSP%d transmitter not "
-                               "ready\n", mcbsp[id].id);
+                       dev_err(mcbsp->dev, "McBSP%d transmitter not "
+                               "ready\n", mcbsp->id);
                        return -EAGAIN;
                }
        }
@@ -582,8 +636,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
                        udelay(10);
                        OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
                        udelay(10);
-                       dev_err(mcbsp[id].dev, "McBSP%d receiver not "
-                               "ready\n", mcbsp[id].id);
+                       dev_err(mcbsp->dev, "McBSP%d receiver not "
+                               "ready\n", mcbsp->id);
                        return -EAGAIN;
                }
        }
@@ -609,6 +663,7 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
 int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
                                unsigned int length)
 {
+       struct omap_mcbsp *mcbsp;
        int dma_tx_ch;
        int src_port = 0;
        int dest_port = 0;
@@ -618,50 +673,51 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX",
+       if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX",
                                omap_mcbsp_tx_dma_callback,
-                               &mcbsp[id],
+                               mcbsp,
                                &dma_tx_ch)) {
-               dev_err(mcbsp[id].dev, " Unable to request DMA channel for "
+               dev_err(mcbsp->dev, " Unable to request DMA channel for "
                                "McBSP%d TX. Trying IRQ based TX\n",
-                               mcbsp[id].id);
+                               mcbsp->id);
                return -EAGAIN;
        }
-       mcbsp[id].dma_tx_lch = dma_tx_ch;
+       mcbsp->dma_tx_lch = dma_tx_ch;
 
-       dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id,
+       dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id,
                dma_tx_ch);
 
-       init_completion(&(mcbsp[id].tx_dma_completion));
+       init_completion(&mcbsp->tx_dma_completion);
 
        if (cpu_class_is_omap1()) {
                src_port = OMAP_DMA_PORT_TIPB;
                dest_port = OMAP_DMA_PORT_EMIFF;
        }
        if (cpu_class_is_omap2())
-               sync_dev = mcbsp[id].dma_tx_sync;
+               sync_dev = mcbsp->dma_tx_sync;
 
-       omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
+       omap_set_dma_transfer_params(mcbsp->dma_tx_lch,
                                     OMAP_DMA_DATA_TYPE_S16,
                                     length >> 1, 1,
                                     OMAP_DMA_SYNC_ELEMENT,
         sync_dev, 0);
 
-       omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
+       omap_set_dma_dest_params(mcbsp->dma_tx_lch,
                                 src_port,
                                 OMAP_DMA_AMODE_CONSTANT,
-                                mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1,
+                                mcbsp->phys_base + OMAP_MCBSP_REG_DXR1,
                                 0, 0);
 
-       omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
+       omap_set_dma_src_params(mcbsp->dma_tx_lch,
                                dest_port,
                                OMAP_DMA_AMODE_POST_INC,
                                buffer,
                                0, 0);
 
-       omap_start_dma(mcbsp[id].dma_tx_lch);
-       wait_for_completion(&(mcbsp[id].tx_dma_completion));
+       omap_start_dma(mcbsp->dma_tx_lch);
+       wait_for_completion(&mcbsp->tx_dma_completion);
 
        return 0;
 }
@@ -670,6 +726,7 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
 int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
                                unsigned int length)
 {
+       struct omap_mcbsp *mcbsp;
        int dma_rx_ch;
        int src_port = 0;
        int dest_port = 0;
@@ -679,50 +736,51 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return -ENODEV;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
-       if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX",
+       if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX",
                                omap_mcbsp_rx_dma_callback,
-                               &mcbsp[id],
+                               mcbsp,
                                &dma_rx_ch)) {
-               dev_err(mcbsp[id].dev, "Unable to request DMA channel for "
+               dev_err(mcbsp->dev, "Unable to request DMA channel for "
                                "McBSP%d RX. Trying IRQ based RX\n",
-                               mcbsp[id].id);
+                               mcbsp->id);
                return -EAGAIN;
        }
-       mcbsp[id].dma_rx_lch = dma_rx_ch;
+       mcbsp->dma_rx_lch = dma_rx_ch;
 
-       dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id,
+       dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id,
                dma_rx_ch);
 
-       init_completion(&(mcbsp[id].rx_dma_completion));
+       init_completion(&mcbsp->rx_dma_completion);
 
        if (cpu_class_is_omap1()) {
                src_port = OMAP_DMA_PORT_TIPB;
                dest_port = OMAP_DMA_PORT_EMIFF;
        }
        if (cpu_class_is_omap2())
-               sync_dev = mcbsp[id].dma_rx_sync;
+               sync_dev = mcbsp->dma_rx_sync;
 
-       omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
+       omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
                                        OMAP_DMA_DATA_TYPE_S16,
                                        length >> 1, 1,
                                        OMAP_DMA_SYNC_ELEMENT,
                                        sync_dev, 0);
 
-       omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
+       omap_set_dma_src_params(mcbsp->dma_rx_lch,
                                src_port,
                                OMAP_DMA_AMODE_CONSTANT,
-                               mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1,
+                               mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
                                0, 0);
 
-       omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
+       omap_set_dma_dest_params(mcbsp->dma_rx_lch,
                                        dest_port,
                                        OMAP_DMA_AMODE_POST_INC,
                                        buffer,
                                        0, 0);
 
-       omap_start_dma(mcbsp[id].dma_rx_lch);
-       wait_for_completion(&(mcbsp[id].rx_dma_completion));
+       omap_start_dma(mcbsp->dma_rx_lch);
+       wait_for_completion(&mcbsp->rx_dma_completion);
 
        return 0;
 }
@@ -737,12 +795,14 @@ EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
 void omap_mcbsp_set_spi_mode(unsigned int id,
                                const struct omap_mcbsp_spi_cfg *spi_cfg)
 {
+       struct omap_mcbsp *mcbsp;
        struct omap_mcbsp_reg_cfg mcbsp_cfg;
 
        if (!omap_mcbsp_check_valid_id(id)) {
                printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
                return;
        }
+       mcbsp = id_to_mcbsp_ptr(id);
 
        memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
 
@@ -803,9 +863,10 @@ EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  * 730 has only 2 McBSP, and both of them are MPU peripherals.
  */
-static int __init omap_mcbsp_probe(struct platform_device *pdev)
+static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 {
        struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_mcbsp *mcbsp;
        int id = pdev->id - 1;
        int ret = 0;
 
@@ -818,47 +879,63 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id);
 
-       if (id >= OMAP_MAX_MCBSP_COUNT) {
+       if (id >= omap_mcbsp_count) {
                dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id);
                ret = -EINVAL;
                goto exit;
        }
 
-       spin_lock_init(&mcbsp[id].lock);
-       mcbsp[id].id = id + 1;
-       mcbsp[id].free = 1;
-       mcbsp[id].dma_tx_lch = -1;
-       mcbsp[id].dma_rx_lch = -1;
+       mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL);
+       if (!mcbsp) {
+               ret = -ENOMEM;
+               goto exit;
+       }
+       mcbsp_ptr[id] = mcbsp;
+
+       spin_lock_init(&mcbsp->lock);
+       mcbsp->id = id + 1;
+       mcbsp->free = 1;
+       mcbsp->dma_tx_lch = -1;
+       mcbsp->dma_rx_lch = -1;
+
+       mcbsp->phys_base = pdata->phys_base;
+       mcbsp->io_base = ioremap(pdata->phys_base, SZ_4K);
+       if (!mcbsp->io_base) {
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
 
-       mcbsp[id].phys_base = pdata->phys_base;
-       mcbsp[id].io_base = pdata->virt_base;
        /* Default I/O is IRQ based */
-       mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO;
-       mcbsp[id].tx_irq = pdata->tx_irq;
-       mcbsp[id].rx_irq = pdata->rx_irq;
-       mcbsp[id].dma_rx_sync = pdata->dma_rx_sync;
-       mcbsp[id].dma_tx_sync = pdata->dma_tx_sync;
+       mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
+       mcbsp->tx_irq = pdata->tx_irq;
+       mcbsp->rx_irq = pdata->rx_irq;
+       mcbsp->dma_rx_sync = pdata->dma_rx_sync;
+       mcbsp->dma_tx_sync = pdata->dma_tx_sync;
 
        if (pdata->clk_name)
-               mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name);
-       if (IS_ERR(mcbsp[id].clk)) {
-               mcbsp[id].free = 0;
+               mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name);
+       if (IS_ERR(mcbsp->clk)) {
                dev_err(&pdev->dev,
                        "Invalid clock configuration for McBSP%d.\n",
-                       mcbsp[id].id);
-               ret = -EINVAL;
-               goto exit;
+                       mcbsp->id);
+               ret = PTR_ERR(mcbsp->clk);
+               goto err_clk;
        }
 
-       mcbsp[id].pdata = pdata;
-       mcbsp[id].dev = &pdev->dev;
-       platform_set_drvdata(pdev, &mcbsp[id]);
+       mcbsp->pdata = pdata;
+       mcbsp->dev = &pdev->dev;
+       platform_set_drvdata(pdev, mcbsp);
+       return 0;
 
+err_clk:
+       iounmap(mcbsp->io_base);
+err_ioremap:
+       mcbsp->free = 0;
 exit:
        return ret;
 }
 
-static int omap_mcbsp_remove(struct platform_device *pdev)
+static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
 {
        struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
 
@@ -872,6 +949,8 @@ static int omap_mcbsp_remove(struct platform_device *pdev)
                clk_disable(mcbsp->clk);
                clk_put(mcbsp->clk);
 
+               iounmap(mcbsp->io_base);
+
                mcbsp->clk = NULL;
                mcbsp->free = 0;
                mcbsp->dev = NULL;
@@ -882,7 +961,7 @@ static int omap_mcbsp_remove(struct platform_device *pdev)
 
 static struct platform_driver omap_mcbsp_driver = {
        .probe          = omap_mcbsp_probe,
-       .remove         = omap_mcbsp_remove,
+       .remove         = __devexit_p(omap_mcbsp_remove),
        .driver         = {
                .name   = "omap-mcbsp",
        },
index e0003e0746e748076c47ca95e0bf9ec775b1d87d..9f9a921829c00686f5b8a658c89bef8e084558d0 100644 (file)
@@ -271,7 +271,7 @@ int __init omap1_sram_init(void)
 #define omap1_sram_init()      do {} while (0)
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2)
 
 static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
                              u32 base_cs, u32 force_unlock);
@@ -352,23 +352,19 @@ static inline int omap243x_sram_init(void)
 
 #ifdef CONFIG_ARCH_OMAP3
 
-static u32 (*_omap2_sram_reprogram_gpmc)(u32 perf_level);
-u32 omap2_sram_reprogram_gpmc(u32 perf_level)
-{
-       if (!_omap2_sram_reprogram_gpmc)
-               omap_sram_error();
-
-       return _omap2_sram_reprogram_gpmc(perf_level);
-}
-
-static u32 (*_omap2_sram_configure_core_dpll)(u32 m, u32 n,
-                                               u32 freqsel, u32 m2);
-u32 omap2_sram_configure_core_dpll(u32 m, u32 n, u32 freqsel, u32 m2)
+static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl,
+                                             u32 sdrc_actim_ctrla,
+                                             u32 sdrc_actim_ctrlb,
+                                             u32 m2);
+u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla,
+                             u32 sdrc_actim_ctrlb, u32 m2)
 {
-       if (!_omap2_sram_configure_core_dpll)
+       if (!_omap3_sram_configure_core_dpll)
                omap_sram_error();
 
-       return _omap2_sram_configure_core_dpll(m, n, freqsel, m2);
+       return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl,
+                                              sdrc_actim_ctrla,
+                                              sdrc_actim_ctrlb, m2);
 }
 
 /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */
@@ -376,31 +372,16 @@ void restore_sram_functions(void)
 {
        omap_sram_ceil = omap_sram_base + omap_sram_size;
 
-       _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc,
-               omap34xx_sram_reprogram_gpmc_sz);
-
-       _omap2_sram_configure_core_dpll =
-                       omap_sram_push(omap34xx_sram_configure_core_dpll,
-                                       omap34xx_sram_configure_core_dpll_sz);
+       _omap3_sram_configure_core_dpll =
+               omap_sram_push(omap3_sram_configure_core_dpll,
+                              omap3_sram_configure_core_dpll_sz);
 }
 
 int __init omap34xx_sram_init(void)
 {
-       _omap2_sram_ddr_init = omap_sram_push(omap34xx_sram_ddr_init,
-                                       omap34xx_sram_ddr_init_sz);
-
-       _omap2_sram_reprogram_sdrc = omap_sram_push(omap34xx_sram_reprogram_sdrc,
-                                       omap34xx_sram_reprogram_sdrc_sz);
-
-       _omap2_set_prcm = omap_sram_push(omap34xx_sram_set_prcm,
-                                       omap34xx_sram_set_prcm_sz);
-
-       _omap2_sram_reprogram_gpmc = omap_sram_push(omap34xx_sram_reprogram_gpmc,
-                                       omap34xx_sram_reprogram_gpmc_sz);
-
-       _omap2_sram_configure_core_dpll =
-                               omap_sram_push(omap34xx_sram_configure_core_dpll,
-                                       omap34xx_sram_configure_core_dpll_sz);
+       _omap3_sram_configure_core_dpll =
+               omap_sram_push(omap3_sram_configure_core_dpll,
+                              omap3_sram_configure_core_dpll_sz);
 
        return 0;
 }
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
new file mode 100644 (file)
index 0000000..f03d7b3
--- /dev/null
@@ -0,0 +1,3 @@
+# dummy makefile, currently just including asm/arm/plat-s3c/include/plat
+
+obj-n  := dummy.o
diff --git a/arch/arm/plat-s3c/include/plat/debug-macro.S b/arch/arm/plat-s3c/include/plat/debug-macro.S
new file mode 100644 (file)
index 0000000..4aa7e2e
--- /dev/null
@@ -0,0 +1,75 @@
+/* linux/include/asm-arm/plat-s3c/debug-macro.S
+ *
+ * Copyright 2005, 2007 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     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 <plat/regs-serial.h>
+
+/* The S3C2440 implementations are used by default as they are the
+ * most widely re-used */
+
+       .macro fifo_level_s3c2440 rd, rx
+               ldr     \rd, [ \rx, # S3C2410_UFSTAT ]
+               and     \rd, \rd, #S3C2440_UFSTAT_TXMASK
+       .endm
+
+#ifndef fifo_level
+#define fifo_level fifo_level_s3c2410
+#endif
+
+       .macro  fifo_full_s3c2440 rd, rx
+               ldr     \rd, [ \rx, # S3C2410_UFSTAT ]
+               tst     \rd, #S3C2440_UFSTAT_TXFULL
+       .endm
+
+#ifndef fifo_full
+#define fifo_full fifo_full_s3c2440
+#endif
+
+       .macro  senduart,rd,rx
+               strb    \rd, [\rx, # S3C2410_UTXH ]
+       .endm
+
+       .macro  busyuart, rd, rx
+               ldr     \rd, [ \rx, # S3C2410_UFCON ]
+               tst     \rd, #S3C2410_UFCON_FIFOMODE    @ fifo enabled?
+               beq     1001f                           @
+               @ FIFO enabled...
+1003:
+               fifo_full \rd, \rx
+               bne     1003b
+               b       1002f
+
+1001:
+               @ busy waiting for non fifo
+               ldr     \rd, [ \rx, # S3C2410_UTRSTAT ]
+               tst     \rd, #S3C2410_UTRSTAT_TXFE
+               beq     1001b
+
+1002:          @ exit busyuart
+       .endm
+
+       .macro  waituart,rd,rx
+               ldr     \rd, [ \rx, # S3C2410_UFCON ]
+               tst     \rd, #S3C2410_UFCON_FIFOMODE    @ fifo enabled?
+               beq     1001f                           @
+               @ FIFO enabled...
+1003:
+               fifo_level \rd, \rx
+               teq     \rd, #0
+               bne     1003b
+               b       1002f
+1001:
+               @ idle waiting for non fifo
+               ldr     \rd, [ \rx, # S3C2410_UTRSTAT ]
+               tst     \rd, #S3C2410_UTRSTAT_TXFE
+               beq     1001b
+
+1002:          @ exit busyuart
+       .endm
diff --git a/arch/arm/plat-s3c/include/plat/map.h b/arch/arm/plat-s3c/include/plat/map.h
new file mode 100644 (file)
index 0000000..b84289d
--- /dev/null
@@ -0,0 +1,40 @@
+/* linux/include/asm-arm/plat-s3c/map.h
+ *
+ * Copyright 2003, 2007 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - Memory map definitions (virtual addresses)
+ *
+ * This program is free software; you can 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_PLAT_MAP_H
+#define __ASM_PLAT_MAP_H __FILE__
+
+/* Fit all our registers in at 0xF4000000 upwards, trying to use as
+ * little of the VA space as possible so vmalloc and friends have a
+ * better chance of getting memory.
+ *
+ * we try to ensure stuff like the IRQ registers are available for
+ * an single MOVS instruction (ie, only 8 bits of set data)
+ */
+
+#define S3C_ADDR_BASE  (0xF4000000)
+
+#ifndef __ASSEMBLY__
+#define S3C_ADDR(x)    ((void __iomem __force *)S3C_ADDR_BASE + (x))
+#else
+#define S3C_ADDR(x)    (S3C_ADDR_BASE + (x))
+#endif
+
+#define S3C_VA_IRQ     S3C_ADDR(0x00000000)    /* irq controller(s) */
+#define S3C_VA_SYS     S3C_ADDR(0x00100000)    /* system control */
+#define S3C_VA_MEM     S3C_ADDR(0x00200000)    /* system control */
+#define S3C_VA_TIMER   S3C_ADDR(0x00300000)    /* timer block */
+#define S3C_VA_WATCHDOG        S3C_ADDR(0x00400000)    /* watchdog */
+#define S3C_VA_UART    S3C_ADDR(0x01000000)    /* UART */
+
+#endif /* __ASM_PLAT_MAP_H */
diff --git a/arch/arm/plat-s3c/include/plat/regs-adc.h b/arch/arm/plat-s3c/include/plat/regs-adc.h
new file mode 100644 (file)
index 0000000..4323ccc
--- /dev/null
@@ -0,0 +1,60 @@
+/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
+ *
+ * Copyright (c) 2004 Shannon Holland <holland@loser.net>
+ *
+ * This program is free software; yosu can 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 ADC registers
+*/
+
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
+
+#define S3C2410_ADCREG(x) (x)
+
+#define S3C2410_ADCCON    S3C2410_ADCREG(0x00)
+#define S3C2410_ADCTSC    S3C2410_ADCREG(0x04)
+#define S3C2410_ADCDLY    S3C2410_ADCREG(0x08)
+#define S3C2410_ADCDAT0           S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1           S3C2410_ADCREG(0x10)
+
+
+/* ADCCON Register Bits */
+#define S3C2410_ADCCON_ECFLG           (1<<15)
+#define S3C2410_ADCCON_PRSCEN          (1<<14)
+#define S3C2410_ADCCON_PRSCVL(x)       (((x)&0xFF)<<6)
+#define S3C2410_ADCCON_PRSCVLMASK      (0xFF<<6)
+#define S3C2410_ADCCON_SELMUX(x)       (((x)&0x7)<<3)
+#define S3C2410_ADCCON_MUXMASK         (0x7<<3)
+#define S3C2410_ADCCON_STDBM           (1<<2)
+#define S3C2410_ADCCON_READ_START      (1<<1)
+#define S3C2410_ADCCON_ENABLE_START    (1<<0)
+#define S3C2410_ADCCON_STARTMASK       (0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C2410_ADCTSC_YM_SEN          (1<<7)
+#define S3C2410_ADCTSC_YP_SEN          (1<<6)
+#define S3C2410_ADCTSC_XM_SEN          (1<<5)
+#define S3C2410_ADCTSC_XP_SEN          (1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
+#define S3C2410_ADCTSC_AUTO_PST                (1<<2)
+#define S3C2410_ADCTSC_XY_PST(x)       (((x)&0x3)<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN         (1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST       (1<<14)
+#define S3C2410_ADCDAT0_XY_PST         (0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK    (0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN         (1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST       (1<<14)
+#define S3C2410_ADCDAT1_XY_PST         (0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK    (0x03FF)
+
+#endif /* __ASM_ARCH_REGS_ADC_H */
+
+
diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h
new file mode 100644 (file)
index 0000000..a0daa64
--- /dev/null
@@ -0,0 +1,232 @@
+/* arch/arm/mach-s3c2410/include/mach/regs-serial.h
+ *
+ *  From linux/include/asm-arm/hardware/serial_s3c2410.h
+ *
+ *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
+ *
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *
+ *  Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
+ *
+ *  Adapted from:
+ *
+ *  Internal header file for MX1ADS serial ports (UART1 & 2)
+ *
+ *  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_ARM_REGS_SERIAL_H
+#define __ASM_ARM_REGS_SERIAL_H
+
+#define S3C24XX_VA_UART0      (S3C_VA_UART)
+#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
+
+#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
+#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
+#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
+
+#define S3C2410_URXH     (0x24)
+#define S3C2410_UTXH     (0x20)
+#define S3C2410_ULCON    (0x00)
+#define S3C2410_UCON     (0x04)
+#define S3C2410_UFCON    (0x08)
+#define S3C2410_UMCON    (0x0C)
+#define S3C2410_UBRDIV   (0x28)
+#define S3C2410_UTRSTAT          (0x10)
+#define S3C2410_UERSTAT          (0x14)
+#define S3C2410_UFSTAT   (0x18)
+#define S3C2410_UMSTAT   (0x1C)
+
+#define S3C2410_LCON_CFGMASK     ((0xF<<3)|(0x3))
+
+#define S3C2410_LCON_CS5         (0x0)
+#define S3C2410_LCON_CS6         (0x1)
+#define S3C2410_LCON_CS7         (0x2)
+#define S3C2410_LCON_CS8         (0x3)
+#define S3C2410_LCON_CSMASK      (0x3)
+
+#define S3C2410_LCON_PNONE       (0x0)
+#define S3C2410_LCON_PEVEN       (0x5 << 3)
+#define S3C2410_LCON_PODD        (0x4 << 3)
+#define S3C2410_LCON_PMASK       (0x7 << 3)
+
+#define S3C2410_LCON_STOPB       (1<<2)
+#define S3C2410_LCON_IRM          (1<<6)
+
+#define S3C2440_UCON_CLKMASK     (3<<10)
+#define S3C2440_UCON_PCLK        (0<<10)
+#define S3C2440_UCON_UCLK        (1<<10)
+#define S3C2440_UCON_PCLK2       (2<<10)
+#define S3C2440_UCON_FCLK        (3<<10)
+#define S3C2443_UCON_EPLL        (3<<10)
+
+#define S3C2440_UCON2_FCLK_EN    (1<<15)
+#define S3C2440_UCON0_DIVMASK    (15 << 12)
+#define S3C2440_UCON1_DIVMASK    (15 << 12)
+#define S3C2440_UCON2_DIVMASK    (7 << 12)
+#define S3C2440_UCON_DIVSHIFT    (12)
+
+#define S3C2412_UCON_CLKMASK   (3<<10)
+#define S3C2412_UCON_UCLK      (1<<10)
+#define S3C2412_UCON_USYSCLK   (3<<10)
+#define S3C2412_UCON_PCLK      (0<<10)
+#define S3C2412_UCON_PCLK2     (2<<10)
+
+#define S3C2410_UCON_UCLK        (1<<10)
+#define S3C2410_UCON_SBREAK      (1<<4)
+
+#define S3C2410_UCON_TXILEVEL    (1<<9)
+#define S3C2410_UCON_RXILEVEL    (1<<8)
+#define S3C2410_UCON_TXIRQMODE   (1<<2)
+#define S3C2410_UCON_RXIRQMODE   (1<<0)
+#define S3C2410_UCON_RXFIFO_TOI          (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
+#define S3C2443_UCON_LOOPBACK    (1<<5)
+
+#define S3C2410_UCON_DEFAULT     (S3C2410_UCON_TXILEVEL  | \
+                                  S3C2410_UCON_RXILEVEL  | \
+                                  S3C2410_UCON_TXIRQMODE | \
+                                  S3C2410_UCON_RXIRQMODE | \
+                                  S3C2410_UCON_RXFIFO_TOI)
+
+#define S3C2410_UFCON_FIFOMODE   (1<<0)
+#define S3C2410_UFCON_TXTRIG0    (0<<6)
+#define S3C2410_UFCON_RXTRIG8    (1<<4)
+#define S3C2410_UFCON_RXTRIG12   (2<<4)
+
+/* S3C2440 FIFO trigger levels */
+#define S3C2440_UFCON_RXTRIG1    (0<<4)
+#define S3C2440_UFCON_RXTRIG8    (1<<4)
+#define S3C2440_UFCON_RXTRIG16   (2<<4)
+#define S3C2440_UFCON_RXTRIG32   (3<<4)
+
+#define S3C2440_UFCON_TXTRIG0    (0<<6)
+#define S3C2440_UFCON_TXTRIG16   (1<<6)
+#define S3C2440_UFCON_TXTRIG32   (2<<6)
+#define S3C2440_UFCON_TXTRIG48   (3<<6)
+
+#define S3C2410_UFCON_RESETBOTH          (3<<1)
+#define S3C2410_UFCON_RESETTX    (1<<2)
+#define S3C2410_UFCON_RESETRX    (1<<1)
+
+#define S3C2410_UFCON_DEFAULT    (S3C2410_UFCON_FIFOMODE | \
+                                  S3C2410_UFCON_TXTRIG0  | \
+                                  S3C2410_UFCON_RXTRIG8 )
+
+#define        S3C2410_UMCOM_AFC         (1<<4)
+#define        S3C2410_UMCOM_RTS_LOW     (1<<0)
+
+#define S3C2412_UMCON_AFC_63   (0<<5)          /* same as s3c2443 */
+#define S3C2412_UMCON_AFC_56   (1<<5)
+#define S3C2412_UMCON_AFC_48   (2<<5)
+#define S3C2412_UMCON_AFC_40   (3<<5)
+#define S3C2412_UMCON_AFC_32   (4<<5)
+#define S3C2412_UMCON_AFC_24   (5<<5)
+#define S3C2412_UMCON_AFC_16   (6<<5)
+#define S3C2412_UMCON_AFC_8    (7<<5)
+
+#define S3C2410_UFSTAT_TXFULL    (1<<9)
+#define S3C2410_UFSTAT_RXFULL    (1<<8)
+#define S3C2410_UFSTAT_TXMASK    (15<<4)
+#define S3C2410_UFSTAT_TXSHIFT   (4)
+#define S3C2410_UFSTAT_RXMASK    (15<<0)
+#define S3C2410_UFSTAT_RXSHIFT   (0)
+
+/* UFSTAT S3C2443 same as S3C2440 */
+#define S3C2440_UFSTAT_TXFULL    (1<<14)
+#define S3C2440_UFSTAT_RXFULL    (1<<6)
+#define S3C2440_UFSTAT_TXSHIFT   (8)
+#define S3C2440_UFSTAT_RXSHIFT   (0)
+#define S3C2440_UFSTAT_TXMASK    (63<<8)
+#define S3C2440_UFSTAT_RXMASK    (63)
+
+#define S3C2410_UTRSTAT_TXE      (1<<2)
+#define S3C2410_UTRSTAT_TXFE     (1<<1)
+#define S3C2410_UTRSTAT_RXDR     (1<<0)
+
+#define S3C2410_UERSTAT_OVERRUN          (1<<0)
+#define S3C2410_UERSTAT_FRAME    (1<<2)
+#define S3C2410_UERSTAT_BREAK    (1<<3)
+#define S3C2443_UERSTAT_PARITY   (1<<1)
+
+#define S3C2410_UERSTAT_ANY      (S3C2410_UERSTAT_OVERRUN | \
+                                  S3C2410_UERSTAT_FRAME | \
+                                  S3C2410_UERSTAT_BREAK)
+
+#define S3C2410_UMSTAT_CTS       (1<<0)
+#define S3C2410_UMSTAT_DeltaCTS          (1<<2)
+
+#define S3C2443_DIVSLOT                  (0x2C)
+
+#ifndef __ASSEMBLY__
+
+/* struct s3c24xx_uart_clksrc
+ *
+ * this structure defines a named clock source that can be used for the
+ * uart, so that the best clock can be selected for the requested baud
+ * rate.
+ *
+ * min_baud and max_baud define the range of baud-rates this clock is
+ * acceptable for, if they are both zero, it is assumed any baud rate that
+ * can be generated from this clock will be used.
+ *
+ * divisor gives the divisor from the clock to the one seen by the uart
+*/
+
+struct s3c24xx_uart_clksrc {
+       const char      *name;
+       unsigned int     divisor;
+       unsigned int     min_baud;
+       unsigned int     max_baud;
+};
+
+/* configuration structure for per-machine configurations for the
+ * serial port
+ *
+ * the pointer is setup by the machine specific initialisation from the
+ * arch/arm/mach-s3c2410/ directory.
+*/
+
+struct s3c2410_uartcfg {
+       unsigned char      hwport;       /* hardware port number */
+       unsigned char      unused;
+       unsigned short     flags;
+       upf_t              uart_flags;   /* default uart flags */
+
+       unsigned long      ucon;         /* value of ucon for port */
+       unsigned long      ulcon;        /* value of ulcon for port */
+       unsigned long      ufcon;        /* value of ufcon for port */
+
+       struct s3c24xx_uart_clksrc *clocks;
+       unsigned int                clocks_size;
+};
+
+/* s3c24xx_uart_devs
+ *
+ * this is exported from the core as we cannot use driver_register(),
+ * or platform_add_device() before the console_initcall()
+*/
+
+extern struct platform_device *s3c24xx_uart_devs[3];
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_REGS_SERIAL_H */
+
diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-s3c/include/plat/regs-timer.h
new file mode 100644 (file)
index 0000000..cc0eedd
--- /dev/null
@@ -0,0 +1,115 @@
+/* arch/arm/mach-s3c2410/include/mach/regs-timer.h
+ *
+ * Copyright (c) 2003 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 Timer configuration
+*/
+
+
+#ifndef __ASM_ARCH_REGS_TIMER_H
+#define __ASM_ARCH_REGS_TIMER_H
+
+#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
+#define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
+
+#define S3C2410_TCFG0        S3C_TIMERREG(0x00)
+#define S3C2410_TCFG1        S3C_TIMERREG(0x04)
+#define S3C2410_TCON         S3C_TIMERREG(0x08)
+
+#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)
+#define S3C2410_TCFG1_MUX4_DIV8          (2<<16)
+#define S3C2410_TCFG1_MUX4_DIV16  (3<<16)
+#define S3C2410_TCFG1_MUX4_TCLK1  (4<<16)
+#define S3C2410_TCFG1_MUX4_MASK          (15<<16)
+#define S3C2410_TCFG1_MUX4_SHIFT  (16)
+
+#define S3C2410_TCFG1_MUX3_DIV2          (0<<12)
+#define S3C2410_TCFG1_MUX3_DIV4          (1<<12)
+#define S3C2410_TCFG1_MUX3_DIV8          (2<<12)
+#define S3C2410_TCFG1_MUX3_DIV16  (3<<12)
+#define S3C2410_TCFG1_MUX3_TCLK1  (4<<12)
+#define S3C2410_TCFG1_MUX3_MASK          (15<<12)
+
+
+#define S3C2410_TCFG1_MUX2_DIV2          (0<<8)
+#define S3C2410_TCFG1_MUX2_DIV4          (1<<8)
+#define S3C2410_TCFG1_MUX2_DIV8          (2<<8)
+#define S3C2410_TCFG1_MUX2_DIV16  (3<<8)
+#define S3C2410_TCFG1_MUX2_TCLK1  (4<<8)
+#define S3C2410_TCFG1_MUX2_MASK          (15<<8)
+
+
+#define S3C2410_TCFG1_MUX1_DIV2          (0<<4)
+#define S3C2410_TCFG1_MUX1_DIV4          (1<<4)
+#define S3C2410_TCFG1_MUX1_DIV8          (2<<4)
+#define S3C2410_TCFG1_MUX1_DIV16  (3<<4)
+#define S3C2410_TCFG1_MUX1_TCLK0  (4<<4)
+#define S3C2410_TCFG1_MUX1_MASK          (15<<4)
+
+#define S3C2410_TCFG1_MUX0_DIV2          (0<<0)
+#define S3C2410_TCFG1_MUX0_DIV4          (1<<0)
+#define S3C2410_TCFG1_MUX0_DIV8          (2<<0)
+#define S3C2410_TCFG1_MUX0_DIV16  (3<<0)
+#define S3C2410_TCFG1_MUX0_TCLK0  (4<<0)
+#define S3C2410_TCFG1_MUX0_MASK          (15<<0)
+
+#define S3C2410_TCFG1_MUX_DIV2   (0<<0)
+#define S3C2410_TCFG1_MUX_DIV4   (1<<0)
+#define S3C2410_TCFG1_MUX_DIV8   (2<<0)
+#define S3C2410_TCFG1_MUX_DIV16   (3<<0)
+#define S3C2410_TCFG1_MUX_TCLK    (4<<0)
+#define S3C2410_TCFG1_MUX_MASK   (15<<0)
+
+#define S3C2410_TCFG1_SHIFT(x)   ((x) * 4)
+
+/* for each timer, we have an count buffer, an compare buffer and
+ * an observation buffer
+*/
+
+/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
+
+#define S3C2410_TCNTB(tmr)    S3C_TIMERREG2(tmr, 0x00)
+#define S3C2410_TCMPB(tmr)    S3C_TIMERREG2(tmr, 0x04)
+#define S3C2410_TCNTO(tmr)    S3C_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
+
+#define S3C2410_TCON_T4RELOAD    (1<<22)
+#define S3C2410_TCON_T4MANUALUPD  (1<<21)
+#define S3C2410_TCON_T4START     (1<<20)
+
+#define S3C2410_TCON_T3RELOAD    (1<<19)
+#define S3C2410_TCON_T3INVERT    (1<<18)
+#define S3C2410_TCON_T3MANUALUPD  (1<<17)
+#define S3C2410_TCON_T3START     (1<<16)
+
+#define S3C2410_TCON_T2RELOAD    (1<<15)
+#define S3C2410_TCON_T2INVERT    (1<<14)
+#define S3C2410_TCON_T2MANUALUPD  (1<<13)
+#define S3C2410_TCON_T2START     (1<<12)
+
+#define S3C2410_TCON_T1RELOAD    (1<<11)
+#define S3C2410_TCON_T1INVERT    (1<<10)
+#define S3C2410_TCON_T1MANUALUPD  (1<<9)
+#define S3C2410_TCON_T1START     (1<<8)
+
+#define S3C2410_TCON_T0DEADZONE          (1<<4)
+#define S3C2410_TCON_T0RELOAD    (1<<3)
+#define S3C2410_TCON_T0INVERT    (1<<2)
+#define S3C2410_TCON_T0MANUALUPD  (1<<1)
+#define S3C2410_TCON_T0START     (1<<0)
+
+#endif /*  __ASM_ARCH_REGS_TIMER_H */
+
+
+
diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h
new file mode 100644 (file)
index 0000000..4df006b
--- /dev/null
@@ -0,0 +1,155 @@
+/* linux/include/asm-arm/plat-s3c/uncompress.h
+ *
+ * Copyright 2003, 2007 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - uncompress code
+ *
+ * This program is free software; you can 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_PLAT_UNCOMPRESS_H
+#define __ASM_PLAT_UNCOMPRESS_H
+
+typedef unsigned int upf_t;    /* cannot include linux/serial_core.h */
+
+/* uart setup */
+
+static unsigned int fifo_mask;
+static unsigned int fifo_max;
+
+/* forward declerations */
+
+static void arch_detect_cpu(void);
+
+/* defines for UART registers */
+
+#include <plat/regs-serial.h>
+#include <asm/plat-s3c/regs-watchdog.h>
+
+/* working in physical space... */
+#undef S3C2410_WDOGREG
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
+
+/* how many bytes we allow into the FIFO at a time in FIFO mode */
+#define FIFO_MAX        (14)
+
+#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT)
+
+static __inline__ void
+uart_wr(unsigned int reg, unsigned int val)
+{
+       volatile unsigned int *ptr;
+
+       ptr = (volatile unsigned int *)(reg + uart_base);
+       *ptr = val;
+}
+
+static __inline__ unsigned int
+uart_rd(unsigned int reg)
+{
+       volatile unsigned int *ptr;
+
+       ptr = (volatile unsigned int *)(reg + uart_base);
+       return *ptr;
+}
+
+/* we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+*/
+
+static void putc(int ch)
+{
+       if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+               int level;
+
+               while (1) {
+                       level = uart_rd(S3C2410_UFSTAT);
+                       level &= fifo_mask;
+
+                       if (level < fifo_max)
+                               break;
+               }
+
+       } else {
+               /* not using fifos */
+
+               while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+                       barrier();
+       }
+
+       /* write byte to transmission register */
+       uart_wr(S3C2410_UTXH, ch);
+}
+
+static inline void flush(void)
+{
+}
+
+#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
+
+/* CONFIG_S3C_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+*/
+
+#ifdef CONFIG_S3C_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+static inline void arch_decomp_wdog(void)
+{
+       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+       __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+#ifdef CONFIG_S3C_BOOT_ERROR_RESET
+
+static void arch_decomp_error(const char *x)
+{
+       putstr("\n\n");
+       putstr(x);
+       putstr("\n\n -- System resetting\n");
+
+       __raw_writel(0x4000, S3C2410_WTDAT);
+       __raw_writel(0x4000, S3C2410_WTCNT);
+       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+
+       while(1);
+}
+
+#define arch_error arch_decomp_error
+#endif
+
+static void error(char *err);
+
+static void
+arch_decomp_setup(void)
+{
+       /* we may need to setup the uart(s) here if we are not running
+        * on an BAST... the BAST will have left the uarts configured
+        * after calling linux.
+        */
+
+       arch_detect_cpu();
+       arch_decomp_wdog_start();
+}
+
+
+#endif /* __ASM_PLAT_UNCOMPRESS_H */
index 400541359bfbc617d0b569c8197c6fdfc2e76b90..a005ddbd9ef3b00f16ac1a5668bc19889c4614ea 100644 (file)
@@ -47,8 +47,8 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 /* clock information */
 
index d528f460f6bc48027a6155a4084adb9d079ff63e..3098736c65d99d3bdc90ec83f1ff0c49cd5afd41 100644 (file)
@@ -40,9 +40,9 @@
 
 #include <asm/plat-s3c/nand.h>
 
-#include <asm/plat-s3c24xx/common-smdk.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/common-smdk.h>
+#include <plat/devs.h>
+#include <plat/pm.h>
 
 /* LED devices */
 
index 9c607bbc9343bc34712536a66cd2a30b9d4ce556..22a329513c0f3ff0149791066ae4d6a5c64515c1 100644 (file)
 #include <mach/system-reset.h>
 
 #include <mach/regs-gpio.h>
-#include <asm/plat-s3c/regs-serial.h>
-
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/s3c2400.h>
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2412.h>
+#include <plat/regs-serial.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s3c2400.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2412.h>
 #include "s3c244x.h"
-#include <asm/plat-s3c24xx/s3c2440.h>
-#include <asm/plat-s3c24xx/s3c2442.h>
-#include <asm/plat-s3c24xx/s3c2443.h>
+#include <plat/s3c2440.h>
+#include <plat/s3c2442.h>
+#include <plat/s3c2443.h>
 
 struct cpu_table {
        unsigned long   idcode;
index 6b13b5455dfc6b32935da3d3bcac491a9e284f2e..e93f8bf6d3386659e175e1248adfea8178982bf4 100644 (file)
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <asm/plat-s3c24xx/udc.h>
 
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
 #include <asm/plat-s3c24xx/regs-spi.h>
 
 /* Serial port registrations */
index d6344461a83bb13494e41c72f9667de66ee3a47b..1baf941d1930b76e94b58b23464e5d71da00ab8d 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/mach/dma.h>
 #include <mach/map.h>
 
-#include <asm/plat-s3c24xx/dma.h>
+#include <plat/dma.h>
 
 /* io map for dma */
 static void __iomem *dma_base;
diff --git a/arch/arm/plat-s3c24xx/include/plat/clock.h b/arch/arm/plat-s3c24xx/include/plat/clock.h
new file mode 100644 (file)
index 0000000..235b753
--- /dev/null
@@ -0,0 +1,64 @@
+/* linux/include/asm-arm/plat-s3c24xx/clock.h
+ * linux/arch/arm/mach-s3c2410/clock.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     http://www.simtec.co.uk/products/SWLINUX/
+ *     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;
+       int                   id;
+       int                   usage;
+       unsigned long         rate;
+       unsigned long         ctrlbit;
+
+       int                 (*enable)(struct clk *, int enable);
+       int                 (*set_rate)(struct clk *c, unsigned long rate);
+       unsigned long       (*get_rate)(struct clk *c);
+       unsigned long       (*round_rate)(struct clk *c, unsigned long rate);
+       int                 (*set_parent)(struct clk *c, struct clk *parent);
+};
+
+/* other clocks which may be registered by board support */
+
+extern struct clk s3c24xx_dclk0;
+extern struct clk s3c24xx_dclk1;
+extern struct clk s3c24xx_clkout0;
+extern struct clk s3c24xx_clkout1;
+extern struct clk s3c24xx_uclk;
+
+extern struct clk clk_usb_bus;
+
+/* core clock support */
+
+extern struct clk clk_f;
+extern struct clk clk_h;
+extern struct clk clk_p;
+extern struct clk clk_mpll;
+extern struct clk clk_upll;
+extern struct clk clk_xtal;
+
+/* exports for arch/arm/mach-s3c2410
+ *
+ * Please DO NOT use these outside of arch/arm/mach-s3c2410
+*/
+
+extern struct mutex clocks_mutex;
+
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+
+extern int s3c24xx_register_clock(struct clk *clk);
+extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
+
+extern int s3c24xx_setup_clocks(unsigned long xtal,
+                               unsigned long fclk,
+                               unsigned long hclk,
+                               unsigned long pclk);
diff --git a/arch/arm/plat-s3c24xx/include/plat/common-smdk.h b/arch/arm/plat-s3c24xx/include/plat/common-smdk.h
new file mode 100644 (file)
index 0000000..58d9094
--- /dev/null
@@ -0,0 +1,15 @@
+/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can 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 smdk_machine_init(void);
diff --git a/arch/arm/plat-s3c24xx/include/plat/cpu.h b/arch/arm/plat-s3c24xx/include/plat/cpu.h
new file mode 100644 (file)
index 0000000..23e420e
--- /dev/null
@@ -0,0 +1,54 @@
+/* linux/include/asm-arm/plat-s3c24xx/cpu.h
+ *
+ * Copyright (c) 2004-2005 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.
+*/
+
+/* todo - fix when rmk changes iodescs to use `void __iomem *` */
+
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
+
+/* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
+struct s3c2410_uartcfg;
+struct map_desc;
+
+/* core initialisation functions */
+
+extern void s3c24xx_init_irq(void);
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
+extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c24xx_init_clocks(int xtal);
+
+extern void s3c24xx_init_uartdevs(char *name,
+                                 struct s3c24xx_uart_resources *res,
+                                 struct s3c2410_uartcfg *cfg, int no);
+
+/* timer for 2410/2440 */
+
+struct sys_timer;
+extern struct sys_timer s3c24xx_timer;
+
+/* system device classes */
+
+extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
+extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
+extern struct sysdev_class s3c2443_sysclass;
diff --git a/arch/arm/plat-s3c24xx/include/plat/devs.h b/arch/arm/plat-s3c24xx/include/plat/devs.h
new file mode 100644 (file)
index 0000000..badaac9
--- /dev/null
@@ -0,0 +1,49 @@
+/* linux/include/asm-arm/plat-s3c24xx/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.
+*/
+#include <linux/platform_device.h>
+
+struct s3c24xx_uart_resources {
+       struct resource         *resources;
+       unsigned long            nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+
+extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
+
+extern struct platform_device s3c_device_timer[];
+
+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_hsmmc;
+
+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_usbgadget;
+
+/* s3c2440 specific devices */
+
+#ifdef CONFIG_CPU_S3C2440
+
+extern struct platform_device s3c_device_camif;
+
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/dma.h b/arch/arm/plat-s3c24xx/include/plat/dma.h
new file mode 100644 (file)
index 0000000..c78efe3
--- /dev/null
@@ -0,0 +1,82 @@
+/* linux/include/asm-arm/plat-s3c24xx/dma.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA 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.
+*/
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+#define DMA_CH_VALID           (1<<31)
+#define DMA_CH_NEVER           (1<<30)
+
+struct s3c24xx_dma_addr {
+       unsigned long           from;
+       unsigned long           to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+       const char              *name;
+       struct s3c24xx_dma_addr  hw_addr;
+
+       unsigned long            channels[S3C2410_DMA_CHANNELS];
+       unsigned long            channels_rx[S3C2410_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+       struct s3c24xx_dma_map  *map;
+       unsigned long            map_size;
+       unsigned long            dcon_mask;
+
+       void    (*select)(struct s3c2410_dma_chan *chan,
+                         struct s3c24xx_dma_map *map);
+
+       void    (*direction)(struct s3c2410_dma_chan *chan,
+                            struct s3c24xx_dma_map *map,
+                            enum s3c2410_dmasrc dir);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+       unsigned int    list[S3C2410_DMA_CHANNELS];     /* list of channels */
+       unsigned int    flags;                          /* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+       struct s3c24xx_dma_order_ch     channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+                           unsigned int stride);
diff --git a/arch/arm/plat-s3c24xx/include/plat/irq.h b/arch/arm/plat-s3c24xx/include/plat/irq.h
new file mode 100644 (file)
index 0000000..45746a9
--- /dev/null
@@ -0,0 +1,109 @@
+/* linux/include/asm-arm/plat-s3c24xx/irq.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU IRQ 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.
+*/
+
+#define irqdbf(x...)
+#define irqdbf2(x...)
+
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+/* these are exported for arch/arm/mach-* usage */
+extern struct irq_chip s3c_irq_level_chip;
+extern struct irq_chip s3c_irq_chip;
+
+static inline void
+s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
+               int subcheck)
+{
+       unsigned long mask;
+       unsigned long submask;
+
+       submask = __raw_readl(S3C2410_INTSUBMSK);
+       mask = __raw_readl(S3C2410_INTMSK);
+
+       submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
+
+       /* check to see if we need to mask the parent IRQ */
+
+       if ((submask  & subcheck) == subcheck) {
+               __raw_writel(mask | parentbit, S3C2410_INTMSK);
+       }
+
+       /* write back masks */
+       __raw_writel(submask, S3C2410_INTSUBMSK);
+
+}
+
+static inline void
+s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
+{
+       unsigned long mask;
+       unsigned long submask;
+
+       submask = __raw_readl(S3C2410_INTSUBMSK);
+       mask = __raw_readl(S3C2410_INTMSK);
+
+       submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
+       mask &= ~parentbit;
+
+       /* write back masks */
+       __raw_writel(submask, S3C2410_INTSUBMSK);
+       __raw_writel(mask, S3C2410_INTMSK);
+}
+
+
+static inline void
+s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+       unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+       s3c_irqsub_mask(irqno, parentmask, group);
+
+       __raw_writel(bit, S3C2410_SUBSRCPND);
+
+       /* only ack parent if we've got all the irqs (seems we must
+        * ack, all and hope that the irq system retriggers ok when
+        * the interrupt goes off again)
+        */
+
+       if (1) {
+               __raw_writel(parentmask, S3C2410_SRCPND);
+               __raw_writel(parentmask, S3C2410_INTPND);
+       }
+}
+
+static inline void
+s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+       unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+       __raw_writel(bit, S3C2410_SUBSRCPND);
+
+       /* only ack parent if we've got all the irqs (seems we must
+        * ack, all and hope that the irq system retriggers ok when
+        * the interrupt goes off again)
+        */
+
+       if (1) {
+               __raw_writel(parentmask, S3C2410_SRCPND);
+               __raw_writel(parentmask, S3C2410_INTPND);
+       }
+}
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+#ifdef CONFIG_PM
+extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
+#else
+#define s3c_irq_wake NULL
+#endif
+
+extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm.h b/arch/arm/plat-s3c24xx/include/plat/pm.h
new file mode 100644 (file)
index 0000000..cc62366
--- /dev/null
@@ -0,0 +1,73 @@
+/* linux/include/asm-arm/plat-s3c24xx/pm.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.
+*/
+
+/* s3c2410_pm_init
+ *
+ * called from board at initialisation time to setup the power
+ * management
+*/
+
+#ifdef CONFIG_PM
+
+extern __init int s3c2410_pm_init(void);
+
+#else
+
+static inline int s3c2410_pm_init(void)
+{
+       return 0;
+}
+#endif
+
+/* configuration for the IRQ mask over sleep */
+extern unsigned long s3c_irqwake_intmask;
+extern unsigned long s3c_irqwake_eintmask;
+
+/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
+extern unsigned long s3c_irqwake_intallow;
+extern unsigned long s3c_irqwake_eintallow;
+
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
+/* Flags for PM Control */
+
+extern unsigned long s3c_pm_flags;
+
+/* from sleep.S */
+
+extern int  s3c2410_cpu_save(unsigned long *saveblk);
+extern void s3c2410_cpu_suspend(void);
+extern void s3c2410_cpu_resume(void);
+
+extern unsigned long s3c2410_sleep_save_phys;
+
+/* sleep save info */
+
+struct sleep_save {
+       void __iomem    *reg;
+       unsigned long   val;
+};
+
+#define SAVE_ITEM(x) \
+       { .reg = (x) }
+
+extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
+extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2400.h b/arch/arm/plat-s3c24xx/include/plat/s3c2400.h
new file mode 100644 (file)
index 0000000..3a5a168
--- /dev/null
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2400 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:
+ *     09-Fev-2006 LCVR  First version, based on s3c2410.h
+*/
+
+#ifdef CONFIG_CPU_S3C2400
+
+extern  int s3c2400_init(void);
+
+extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2400_init_clocks(int xtal);
+
+#else
+#define s3c2400_init_clocks NULL
+#define s3c2400_init_uarts NULL
+#define s3c2400_map_io NULL
+#define s3c2400_init NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2410.h b/arch/arm/plat-s3c24xx/include/plat/s3c2410.h
new file mode 100644 (file)
index 0000000..3cd1ec6
--- /dev/null
@@ -0,0 +1,31 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifdef CONFIG_CPU_S3C2410
+
+extern  int s3c2410_init(void);
+
+extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2410_init_clocks(int xtal);
+
+#else
+#define s3c2410_init_clocks NULL
+#define s3c2410_init_uarts NULL
+#define s3c2410_map_io NULL
+#define s3c2410_init NULL
+#endif
+
+extern int s3c2410_baseclk_add(void);
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2412.h b/arch/arm/plat-s3c24xx/include/plat/s3c2412.h
new file mode 100644 (file)
index 0000000..3ec9768
--- /dev/null
@@ -0,0 +1,29 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2440.h b/arch/arm/plat-s3c24xx/include/plat/s3c2440.h
new file mode 100644 (file)
index 0000000..107853b
--- /dev/null
@@ -0,0 +1,17 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+#else
+#define s3c2440_init NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2442.h b/arch/arm/plat-s3c24xx/include/plat/s3c2442.h
new file mode 100644 (file)
index 0000000..451a23a
--- /dev/null
@@ -0,0 +1,17 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2442 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2443.h b/arch/arm/plat-s3c24xx/include/plat/s3c2443.h
new file mode 100644 (file)
index 0000000..11d83b5
--- /dev/null
@@ -0,0 +1,32 @@
+/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2443 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.
+*/
+
+#ifdef CONFIG_CPU_S3C2443
+
+struct s3c2410_uartcfg;
+
+extern  int s3c2443_init(void);
+
+extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2443_init_clocks(int xtal);
+
+extern  int s3c2443_baseclk_add(void);
+
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
index 590fc5a3ab06e8710b295a7cc5cdc80959654c98..963f7a4f26f23042611426f4e9245337764b566a 100644 (file)
@@ -65,9 +65,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
-#include <asm/plat-s3c24xx/irq.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
 
 /* wakeup irq control */
 
index 0a074d35890aa5eebc76eb9d1bf6fea4ef537700..21dfa74773d17ec0d61109fbd47ce1a4477f9211 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <asm/mach-types.h>
 
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/pm.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
index d3934b1119a9e0c855f3e16153c6bad696f26144..8efb57ad501948974b0400c3f5ed75910506575d 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
@@ -48,7 +48,7 @@
 
 #include <asm/mach/time.h>
 
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/pm.h>
 
 /* for external use */
 
index 306cc9c6f9efebf44258a24d956197fd9f63b3a7..b8e854f1b1d50dbc4f7524b2b9843ed614f51a4b 100644 (file)
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
-#include <asm/plat-s3c/regs-timer.h>
+#include <plat/regs-timer.h>
 
 /* Each of the timers 0 through 5 go through the following
  * clock tree, with the inputs depending on the timers.
index 7a92c938542a6e4e59b652eca8d2f3287164a37e..feb770f2e84e1a470bcd3cc1b4e57686e10f0171 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/io.h>
 #include <linux/pwm.h>
 
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c/regs-timer.h>
+#include <plat/devs.h>
+#include <plat/regs-timer.h>
 
 struct pwm_device {
        struct list_head         list;
index 119647a5eaa63e8db78eff5c8f2a2dccf9ddd99d..7c09773ff9fcdfe93b48c64707035206f9b48f2f 100644 (file)
@@ -41,8 +41,8 @@
 
 #include <mach/regs-clock.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
 {
index 0601c5f3230bdd84700aa3b4b4e93568afb71422..0902afd227cadf8b690285cb9d7e5c1ac0eec912 100644 (file)
@@ -34,9 +34,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
 
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
-#include <asm/plat-s3c24xx/irq.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
 
 /* camera irq */
 
index 146863a69aeb3fae4a611c2abbfc1ab6d43aa96d..c0344fac4a9492706609ed7ef5a2a42a4b27c9b0 100644 (file)
 #include <asm/irq.h>
 
 #include <mach/regs-clock.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-gpioj.h>
 #include <mach/regs-dsc.h>
 
-#include <asm/plat-s3c24xx/s3c2410.h>
-#include <asm/plat-s3c24xx/s3c2440.h>
+#include <plat/s3c2410.h>
+#include <plat/s3c2440.h>
 #include "s3c244x.h"
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/devs.h>
-#include <asm/plat-s3c24xx/cpu.h>
-#include <asm/plat-s3c24xx/pm.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
 
 static struct map_desc s3c244x_iodesc[] __initdata = {
        IODESC_ENT(CLKPWR),
index 4981a08b6ebbcb9fa6eb5e604b2f453b1ec18699..76594b21280258e4fa05d21190030599f27dd8a4 100644 (file)
@@ -32,7 +32,7 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-mem.h>
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 
 /* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
  * reset the UART configuration, only enable if you really need this!
index 64bfa19ae951c1444d8741835ef49d12f1f27432..c51916236ac082bfad855f9ecc6d93588a9fbdc1 100644 (file)
 
 #include <asm/irq.h>
 #include <mach/map.h>
-#include <asm/plat-s3c/regs-timer.h>
+#include <plat/regs-timer.h>
 #include <mach/regs-irq.h>
 #include <asm/mach/time.h>
 
-#include <asm/plat-s3c24xx/clock.h>
-#include <asm/plat-s3c24xx/cpu.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_usec_ticks;
diff --git a/arch/avr32/include/asm/a.out.h b/arch/avr32/include/asm/a.out.h
deleted file mode 100644 (file)
index e46375a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __ASM_AVR32_A_OUT_H
-#define __ASM_AVR32_A_OUT_H
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* __ASM_AVR32_A_OUT_H */
index 64ce40ee1d585d052e437d4f8ada3026e200bcfb..d5d1d41c600a81e6eea29bd07967fa2412ffce14 100644 (file)
@@ -103,6 +103,6 @@ typedef struct user_fpu_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
 
 #endif /* __ASM_AVR32_ELF_H */
index 5dd8d25428bfb7d6a48a084eee1d114d83efaeeb..d84efe4984ab82da6aaae2a6ca2c09d700016c80 100644 (file)
@@ -87,7 +87,6 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
        policy->cur = at32_get_speed(0);
        policy->min = policy->cpuinfo.min_freq;
        policy->max = policy->cpuinfo.max_freq;
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
        printk("cpufreq: AT32AP CPU frequency driver\n");
 
index 4154ff1101fa1aa53f9f4941941e3f7b47f01064..8102c79aaa94044369612ab3a8dc3bb6e33aa807 100644 (file)
@@ -162,16 +162,28 @@ config BF549
 config BF561
        bool "BF561"
        help
-         Not Supported Yet - Work in progress - BF561 Processor Support.
+         BF561 Processor Support.
 
 endchoice
 
+config BF_REV_MIN
+       int
+       default 0 if (BF52x || BF54x)
+       default 2 if (BF537 || BF536 || BF534)
+       default 3 if (BF561 ||BF533 || BF532 || BF531)
+
+config BF_REV_MAX
+       int
+       default 2 if (BF52x || BF54x)
+       default 3 if (BF537 || BF536 || BF534)
+       default 5 if (BF561)
+       default 6 if (BF533 || BF532 || BF531)
+
 choice
        prompt "Silicon Rev"
-       default BF_REV_0_1 if BF527
-       default BF_REV_0_2 if BF537
-       default BF_REV_0_3 if BF533
-       default BF_REV_0_0 if BF549
+       default BF_REV_0_1 if (BF52x || BF54x)
+       default BF_REV_0_2 if (BF534 || BF536 || BF537)
+       default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561)
 
 config BF_REV_0_0
        bool "0.0"
@@ -183,7 +195,7 @@ config BF_REV_0_1
 
 config BF_REV_0_2
        bool "0.2"
-       depends on (BF537 || BF536 || BF534)
+       depends on (BF52x || BF537 || BF536 || BF534 || BF54x)
 
 config BF_REV_0_3
        bool "0.3"
@@ -197,6 +209,10 @@ config BF_REV_0_5
        bool "0.5"
        depends on (BF561 || BF533 || BF532 || BF531)
 
+config BF_REV_0_6
+       bool "0.6"
+       depends on (BF533 || BF532 || BF531)
+
 config BF_REV_ANY
        bool "any"
 
@@ -249,7 +265,7 @@ config MEM_MT48LC8M32B2B5_7
 
 config MEM_MT48LC32M16A2TG_75
        bool
-       depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP)
+       depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP || BFIN526_EZBRD)
        default y
 
 source "arch/blackfin/mach-bf527/Kconfig"
@@ -286,13 +302,20 @@ config BOOT_LOAD
          memory region is used to capture NULL pointer references as well
          as some core kernel functions.
 
+config ROM_BASE
+       hex "Kernel ROM Base"
+       default "0x20040000"
+       range 0x20000000 0x20400000 if !(BF54x || BF561)
+       range 0x20000000 0x30000000 if (BF54x || BF561)
+       help
+
 comment "Clock/PLL Setup"
 
 config CLKIN_HZ
        int "Frequency of the crystal on the board in Hz"
        default "11059200" if BFIN533_STAMP
        default "27000000" if BFIN533_EZKIT
-       default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP)
+       default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD)
        default "30000000" if BFIN561_EZKIT
        default "24576000" if PNAV10
        default "10000000" if BFIN532_IP0X
@@ -332,7 +355,7 @@ config VCO_MULT
        default "22" if BFIN533_BLUETECHNIX_CM
        default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
        default "20" if BFIN561_EZKIT
-       default "16" if (H8606_HVSISTEMAS || BLACKSTAMP)
+       default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD)
        help
          This controls the frequency of the on-chip PLL. This can be between 1 and 64.
          PLL Frequency = (Crystal Frequency) * (this setting)
@@ -368,14 +391,6 @@ config SCLK_DIV
          This can be between 1 and 15
          System Clock = (PLL frequency) / (this setting)
 
-config MAX_MEM_SIZE
-       int "Max SDRAM Memory Size in MBytes"
-       depends on !MPU
-       default 512
-       help
-         This is the max memory size that the kernel will create CPLB
-         tables for.  Your system will not be able to handle any more.
-
 choice
        prompt "DDR SDRAM Chip Type"
        depends on BFIN_KERNEL_CLOCK
@@ -389,6 +404,14 @@ config MEM_MT46V32M16_5B
        bool "MT46V32M16_5B"
 endchoice
 
+config MAX_MEM_SIZE
+       int "Max SDRAM Memory Size in MBytes"
+       depends on !MPU
+       default 512
+       help
+         This is the max memory size that the kernel will create CPLB
+         tables for.  Your system will not be able to handle any more.
+
 #
 # Max & Min Speeds for various Chips
 #
@@ -455,8 +478,6 @@ config CYCLES_CLOCKSOURCE
 
 source kernel/time/Kconfig
 
-comment "Memory Setup"
-
 comment "Misc"
 
 choice
@@ -622,6 +643,15 @@ config CPLB_SWITCH_TAB_L1
          If enabled, the CPLB Switch Tables are linked
          into L1 data memory. (less latency)
 
+config APP_STACK_L1
+       bool "Support locating application stack in L1 Scratch Memory"
+       default y
+       help
+         If enabled the application stack can be located in L1
+         scratch memory (less latency).
+
+         Currently only works with FLAT binaries.
+
 comment "Speed Optimizations"
 config BFIN_INS_LOWOVERHEAD
        bool "ins[bwl] low overhead, higher interrupt latency"
@@ -755,6 +785,13 @@ config BFIN_WT
 
 endchoice
 
+config BFIN_L2_CACHEABLE
+       bool "Cache L2 SRAM"
+       depends on (BFIN_DCACHE || BFIN_ICACHE) && (BF54x || BF561)
+       default n
+       help
+         Select to make L2 SRAM cacheable in L1 data and instruction cache.
+
 config MPU
        bool "Enable the memory protection unit (EXPERIMENTAL)"
        default n
index c468624d55f00614f627814f72e609a3565b34df..3ad25983ec9777c97478745652217812a2674202 100644 (file)
@@ -2,6 +2,22 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
+config HAVE_ARCH_KGDB
+       def_bool y
+
+config DEBUG_VERBOSE
+       bool "Verbose fault messages"
+       default y
+       select PRINTK
+       help
+         When a program crashes due to an exception, or the kernel detects
+         an internal error, the kernel can print a not so brief message
+         explaining what the problem was. This debugging information is
+         useful to developers and kernel hackers when tracking down problems,
+         but mostly meaningless to other people. This is always helpful for
+         debugging but serves no purpose on a production system.
+         Most people should say N here.
+
 config DEBUG_MMRS
        bool "Generate Blackfin MMR tree"
        select DEBUG_FS
@@ -22,6 +38,44 @@ config DEBUG_HWERR
          hardware error interrupts and need to know where they are coming
          from.
 
+config DEBUG_DOUBLEFAULT
+       bool "Debug Double Faults"
+       default n
+       help
+         If an exception is caused while executing code within the exception
+         handler, the NMI handler, the reset vector, or in emulator mode,
+         a double fault occurs. On the Blackfin, this is a unrecoverable
+         event. You have two options:
+         - RESET exactly when double fault occurs. The excepting
+           instruction address is stored in RETX, where the next kernel
+           boot will print it out.
+         - Print debug message. This is much more error prone, although
+           easier to handle. It is error prone since:
+           - The excepting instruction is not committed.
+           - All writebacks from the instruction are prevented.
+           - The generated exception is not taken.
+           - The EXCAUSE field is updated with an unrecoverable event
+           The only way to check this is to see if EXCAUSE contains the
+           unrecoverable event value at every exception return. By selecting
+           this option, you are skipping over the faulting instruction, and 
+           hoping things stay together enough to print out a debug message.
+
+         This does add a little kernel code, but is the only method to debug
+         double faults - if unsure say "Y"
+
+choice
+       prompt "Double Fault Failure Method"
+       default DEBUG_DOUBLEFAULT_PRINT
+       depends on DEBUG_DOUBLEFAULT
+
+config DEBUG_DOUBLEFAULT_PRINT
+       bool "Print"
+
+config DEBUG_DOUBLEFAULT_RESET
+       bool "Reset"
+
+endchoice
+
 config DEBUG_ICACHE_CHECK
        bool "Check Instruction cache coherency"
        depends on DEBUG_KERNEL
@@ -143,6 +197,7 @@ config DEBUG_BFIN_NO_KERN_HWTRACE
 config EARLY_PRINTK
        bool "Early printk" 
        default n
+       select SERIAL_CORE_CONSOLE
        help
          This option enables special console drivers which allow the kernel
          to print messages very early in the bootup process.
index eac0533d6e4fcf11c92dd6236f3d09bdb774d88f..6bf50977850ca486db832cfb41bd2e627aa9aaf1 100644 (file)
@@ -67,6 +67,7 @@ rev-$(CONFIG_BF_REV_0_2)  := 0.2
 rev-$(CONFIG_BF_REV_0_3)  := 0.3
 rev-$(CONFIG_BF_REV_0_4)  := 0.4
 rev-$(CONFIG_BF_REV_0_5)  := 0.5
+rev-$(CONFIG_BF_REV_0_6)  := 0.6
 rev-$(CONFIG_BF_REV_NONE) := none
 rev-$(CONFIG_BF_REV_ANY)  := any
 
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
new file mode 100644 (file)
index 0000000..4443a47
--- /dev/null
@@ -0,0 +1,1427 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26.3
+# Thu Aug 28 16:49:53 2008
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+CONFIG_BF526=y
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF52x=y
+CONFIG_MEM_MT48LC32M16A2TG_75=y
+# CONFIG_BFIN527_EZKIT is not set
+# CONFIG_BFIN527_BLUETECHNIX_CM is not set
+CONFIG_BFIN526_EZBRD=y
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA0_ERROR=7
+CONFIG_IRQ_DMAR0_BLK=7
+CONFIG_IRQ_DMAR1_BLK=7
+CONFIG_IRQ_DMAR0_OVR=7
+CONFIG_IRQ_DMAR1_OVR=7
+CONFIG_IRQ_PPI_ERROR=7
+CONFIG_IRQ_MAC_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_UART0_ERROR=7
+CONFIG_IRQ_UART1_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_OPTSEC=11
+CONFIG_IRQ_CNT=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_PORTH_INTA=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_PORTH_INTB=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PORTG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_PORTF_INTA=13
+CONFIG_IRQ_PORTF_INTB=13
+CONFIG_IRQ_SPI_ERROR=7
+CONFIG_IRQ_NFC_ERROR=7
+CONFIG_IRQ_HDMA_ERROR=7
+CONFIG_IRQ_HDMA=7
+CONFIG_IRQ_USB_EINT=10
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_MEM_SIZE=512
+CONFIG_MAX_VCO_HZ=400000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Memory Setup
+#
+
+#
+# Misc
+#
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+# CONFIG_SCHEDULE_L1 is not set
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_4M is not set
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC0
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_BF5XX is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# 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
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_TWI_KEYPAD is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+CONFIG_SIMPLE_GPIO=m
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+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_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SPI devices
+#
+
+#
+# ALSA Blackfin devices
+#
+# CONFIG_SND_BLACKFIN_AD1836 is not set
+# CONFIG_SND_BFIN_AD73311 is not set
+# CONFIG_SND_BFIN_AD73322 is not set
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=m
+CONFIG_SND_BF5XX_I2S=m
+CONFIG_SND_BF5XX_SOC_SSM2602=m
+# CONFIG_SND_BF5XX_AC97 is not set
+CONFIG_SND_BF5XX_SOC_SPORT=m
+CONFIG_SND_BF5XX_SOC_I2S=m
+CONFIG_SND_BF5XX_SPORT_NUM=0
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# SoC Audio for the Texas Instruments OMAP
+#
+CONFIG_SND_SOC_SSM2602=m
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_OTG_BLACKLIST_HUB=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# Blackfin high speed USB support
+#
+CONFIG_USB_MUSB_HOST=y
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_MUSB_LOGLEVEL=0
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_DEBUG_MMRS=y
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index 66854a83c0de648c8b7ad6cf6a36801d9f38d666..4a2a660a6b3578260f579234e23521377182a52d 100644 (file)
@@ -772,7 +772,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
index 6bc11db12690b49077dc5b359dbd99d528494263..deeb5e45effbdda40dfc6682c9c6d60ffa7b4657 100644 (file)
@@ -674,7 +674,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
@@ -740,7 +740,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index d77d991a1f619877e1ea25ddf32ebad9f10fcf8e..c23267ed880bde1514e5f00b325f40b1bb794d90 100644 (file)
@@ -681,7 +681,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
index 5fd7c4b143df56bfd3f7bb8b3fed4a75e025ab1c..63a0f854745cc740ce8f76ece096e5f52b8a86ee 100644 (file)
@@ -731,7 +731,7 @@ CONFIG_CAN4LINUX=y
 # CONFIG_CAN_UNCTWINCAN is not set
 CONFIG_CAN_BLACKFIN=m
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
@@ -871,7 +871,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index 390669e8668e0695fb41da67baf77bcbe205410d..bf63660815b927de3a2a496a131d1ac1d7bac43f 100644 (file)
@@ -855,7 +855,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
@@ -1001,7 +1001,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 # CONFIG_USB_DABUSB is not set
 
 #
index 976a4d7ba175ee955270d9170023d02525d3a19b..3c70d6230a12fe28ff25383ec174041fb2eef942 100644 (file)
@@ -719,7 +719,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
@@ -785,7 +785,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index 0799aa9bba9d430187cffc1b850758928540273d..b6a14635fb91f844867e01bc3dad3feac327cc31 100644 (file)
@@ -679,7 +679,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
index 09deea44480b43d6d830d19d2c8c317625a7b40f..c3ba9066b935a651662bb346090d135e789eef61 100644 (file)
@@ -672,7 +672,7 @@ CONFIG_HWMON=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index 219fc345a5f5bdc7f2a25273cc4ace45c25e29c9..cdc6b7feb59eb14e67540b2dd6f0d3f4f0e74fe9 100644 (file)
@@ -703,7 +703,7 @@ CONFIG_HWMON=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index 9873d586fc7753240a01d774b9d9e165f9a3b146..f074bdcd1ce589b6852a8352dea2491cf708fb9b 100644 (file)
@@ -683,7 +683,7 @@ CONFIG_HWMON=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index 0e3605fdb7b040f8c8be5038fa43a3d5ade884f5..5c44fdb8e6e363bdf65fb3daf89581662438c498 100644 (file)
@@ -762,7 +762,7 @@ CONFIG_UNIX98_PTYS=y
 #
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
@@ -909,7 +909,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 # CONFIG_USB_DABUSB is not set
 
 #
index 59c7cdbee904f0206755731174193799d1130ef2..086fe5dda4950e8296ddf2ed972ef9238d6fa70b 100644 (file)
@@ -684,7 +684,7 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_DAB is not set
 
 #
 # Graphics support
index ba0bee90b7e1e46965a145d975c0ce4242b3b0be..1fc31f1b762be85f46ef49fa93ea6186cfbb7078 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.12
+# Linux kernel version: 2.6.22.14
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
@@ -192,7 +192,7 @@ CONFIG_CLKIN_HZ=25000000
 # CONFIG_BFIN_KERNEL_CLOCK is not set
 CONFIG_MAX_VCO_HZ=400000000
 CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
 CONFIG_MIN_SCLK_HZ=27000000
 
 #
@@ -516,7 +516,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 #
 # CONFIG_MTD_DATAFLASH is not set
 CONFIG_MTD_M25P80=y
-CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -635,25 +635,25 @@ CONFIG_INPUT=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
 # Input Device Drivers
 #
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_ATI_REMOTE is not set
-# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
-# CONFIG_INPUT_YEALINK is not set
-# CONFIG_INPUT_UINPUT is not set
-# CONFIG_BF53X_PFBUTTONS is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Hardware I/O ports
@@ -681,7 +681,15 @@ CONFIG_BFIN_TIMER_LATENCY=y
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
 
 #
 # Non-8250 serial port support
diff --git a/arch/blackfin/include/asm/a.out.h b/arch/blackfin/include/asm/a.out.h
deleted file mode 100644 (file)
index 6c3d652..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __BFIN_A_OUT_H__
-#define __BFIN_A_OUT_H__
-
-struct exec {
-       unsigned long a_info;   /* Use macros N_MAGIC, etc for access */
-       unsigned a_text;        /* length of text, in bytes */
-       unsigned a_data;        /* length of data, in bytes */
-       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
-       unsigned a_syms;        /* length of symbol table data in file, in bytes */
-       unsigned a_entry;       /* start address */
-       unsigned a_trsize;      /* length of relocation info for text, in bytes */
-       unsigned a_drsize;      /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif                         /* __BFIN_A_OUT_H__ */
index 7ba70de66f2b4077d40de98039bc02b3667a4fc2..56dcb0a2d2449ced3d11097a889be0cde31d3017 100644 (file)
@@ -63,7 +63,6 @@ extern void bfin_dcache_init(void);
 extern void init_exception_vectors(void);
 extern void program_IAR(void);
 
-extern void bfin_reset(void);
 extern asmlinkage void lower_to_irq14(void);
 extern asmlinkage void bfin_return_from_exception(void);
 extern asmlinkage void evt14_softirq(void);
@@ -92,6 +91,8 @@ extern int sram_free(const void*);
 extern void *sram_alloc_with_lsl(size_t, unsigned long);
 extern int sram_free_with_lsl(const void*);
 
+extern void *isram_memcpy(void *dest, const void *src, size_t n);
+
 extern const char bfin_board_name[];
 
 extern unsigned long bfin_sic_iwr[];
@@ -104,7 +105,7 @@ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
        _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
        _ebss_l2[], _l2_lma_start[];
 
-/* only used when CONFIG_MTD_UCLINUX */
+/* only used when MTD_UCLINUX */
 extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
 
 #ifdef CONFIG_BFIN_ICACHE_LOCK
diff --git a/arch/blackfin/include/asm/bfrom.h b/arch/blackfin/include/asm/bfrom.h
new file mode 100644 (file)
index 0000000..cfe8024
--- /dev/null
@@ -0,0 +1,85 @@
+/* Blackfin on-chip ROM API
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFROM_H__
+#define __BFROM_H__
+
+#include <linux/types.h>
+
+/* Possible syscontrol action flags */
+#define SYSCTRL_READ        0x00000000    /* read registers */
+#define SYSCTRL_WRITE       0x00000001    /* write registers */
+#define SYSCTRL_SYSRESET    0x00000002    /* perform system reset */
+#define SYSCTRL_CORERESET   0x00000004    /* perform core reset */
+#define SYSCTRL_SOFTRESET   0x00000006    /* perform core and system reset */
+#define SYSCTRL_VRCTL       0x00000010    /* read/write VR_CTL register */
+#define SYSCTRL_EXTVOLTAGE  0x00000020    /* VDDINT supplied externally */
+#define SYSCTRL_INTVOLTAGE  0x00000000    /* VDDINT generated by on-chip regulator */
+#define SYSCTRL_OTPVOLTAGE  0x00000040    /* For Factory Purposes Only */
+#define SYSCTRL_PLLCTL      0x00000100    /* read/write PLL_CTL register */
+#define SYSCTRL_PLLDIV      0x00000200    /* read/write PLL_DIV register */
+#define SYSCTRL_LOCKCNT     0x00000400    /* read/write PLL_LOCKCNT register */
+#define SYSCTRL_PLLSTAT     0x00000800    /* read/write PLL_STAT register */
+
+typedef struct ADI_SYSCTRL_VALUES {
+       uint16_t uwVrCtl;
+       uint16_t uwPllCtl;
+       uint16_t uwPllDiv;
+       uint16_t uwPllLockCnt;
+       uint16_t uwPllStat;
+} ADI_SYSCTRL_VALUES;
+
+static uint32_t (* const bfrom_SysControl)(uint32_t action_flags, ADI_SYSCTRL_VALUES *power_settings, void *reserved) = (void *)0xEF000038;
+
+/* We need a dedicated function since we need to screw with the stack pointer
+ * when resetting.  The on-chip ROM will save/restore registers on the stack
+ * when doing a system reset, so the stack cannot be outside of the chip.
+ */
+__attribute__((__noreturn__))
+static inline void bfrom_SoftReset(void *new_stack)
+{
+       while (1)
+               __asm__ __volatile__(
+                       "sp = %[stack];"
+                       "jump (%[bfrom_syscontrol]);"
+                       : : [bfrom_syscontrol] "p"(bfrom_SysControl),
+                               "q0"(SYSCTRL_SOFTRESET),
+                               "q1"(0),
+                               "q2"(NULL),
+                               [stack] "p"(new_stack)
+               );
+}
+
+/* OTP Functions */
+static uint32_t (* const bfrom_OtpCommand)(uint32_t command, uint32_t value) = (void *)0xEF000018;
+static uint32_t (* const bfrom_OtpRead)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001A;
+static uint32_t (* const bfrom_OtpWrite)(uint32_t page, uint32_t flags, uint64_t *page_content) = (void *)0xEF00001C;
+
+/* otp command: defines for "command" */
+#define OTP_INIT                 0x00000001
+#define OTP_CLOSE                0x00000002
+
+/* otp read/write: defines for "flags" */
+#define OTP_LOWER_HALF           0x00000000 /* select upper/lower 64-bit half (bit 0) */
+#define OTP_UPPER_HALF           0x00000001
+#define OTP_NO_ECC               0x00000010 /* do not use ECC */
+#define OTP_LOCK                 0x00000020 /* sets page protection bit for page */
+#define OTP_CHECK_FOR_PREV_WRITE 0x00000080
+
+/* Return values for all functions */
+#define OTP_SUCCESS          0x00000000
+#define OTP_MASTER_ERROR     0x001
+#define OTP_WRITE_ERROR      0x003
+#define OTP_READ_ERROR       0x005
+#define OTP_ACC_VIO_ERROR    0x009
+#define OTP_DATA_MULT_ERROR  0x011
+#define OTP_ECC_MULT_ERROR   0x021
+#define OTP_PREV_WR_ERROR    0x041
+#define OTP_DATA_SB_WARN     0x100
+#define OTP_ECC_SB_WARN      0x200
+
+#endif
index d81a77545a04a6a88414d11ec6e9e00604475d23..4403415583fa67f8809e3e14399e8c648b72562a 100644 (file)
 #ifndef _BLACKFIN_CACHEFLUSH_H
 #define _BLACKFIN_CACHEFLUSH_H
 
-#include <asm/cplb.h>
-
-extern void blackfin_icache_dcache_flush_range(unsigned int, unsigned int);
-extern void blackfin_icache_flush_range(unsigned int, unsigned int);
-extern void blackfin_dcache_flush_range(unsigned int, unsigned int);
-extern void blackfin_dcache_invalidate_range(unsigned int, unsigned int);
-extern void blackfin_dflush_page(void *);
+extern void blackfin_icache_dcache_flush_range(unsigned long start_address, unsigned long end_address);
+extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address);
+extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
+extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
+extern void blackfin_dflush_page(void *page);
 
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
@@ -87,4 +85,21 @@ do { memcpy(dst, src, len); \
 # define flush_dcache_page(page)                       do { } while (0)
 #endif
 
+extern unsigned long reserved_mem_dcache_on;
+extern unsigned long reserved_mem_icache_on;
+
+static inline int bfin_addr_dcachable(unsigned long addr)
+{
+#ifdef CONFIG_BFIN_DCACHE
+       if (addr < (_ramend - DMA_UNCACHED_REGION))
+               return 1;
+#endif
+
+       if (reserved_mem_dcache_on &&
+               addr >= _ramend && addr < physical_mem_end)
+               return 1;
+
+       return 0;
+}
+
 #endif                         /* _BLACKFIN_ICACHEFLUSH_H */
index 05d6f05fb7482ccc5ac6e12a9627a405c08666de..9e8b4035fcec5732ea375fe02c92d48f336aa9e2 100644 (file)
 #endif
 
 #define L1_DMEMORY       (CPLB_LOCK | CPLB_COMMON)
-#define L2_MEMORY        (CPLB_COMMON)
+#ifdef CONFIG_BFIN_L2_CACHEABLE
+#define L2_IMEMORY        (SDRAM_IGENERIC)
+#define L2_DMEMORY        (SDRAM_DGENERIC)
+#else
+#define L2_IMEMORY        (CPLB_COMMON)
+#define L2_DMEMORY        (CPLB_COMMON)
+#endif
 #define SDRAM_DNON_CHBL  (CPLB_COMMON)
 #define SDRAM_EBIU       (CPLB_COMMON)
 #define SDRAM_OOPS       (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
index 0eb1c1b685a7db84630614b4dce858beb4a3f182..f845b41147ba209184182a79194383465cc20fb6 100644 (file)
@@ -87,9 +87,6 @@ extern u_long dpdt_swapcount_table[];
 
 #endif /* CONFIG_MPU */
 
-extern unsigned long reserved_mem_dcache_on;
-extern unsigned long reserved_mem_icache_on;
-
-extern void generate_cpl_tables(void);
+extern void generate_cplb_tables(void);
 
 #endif
diff --git a/arch/blackfin/include/asm/cpumask.h b/arch/blackfin/include/asm/cpumask.h
deleted file mode 100644 (file)
index b20a8e9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_BLACKFIN_CPUMASK_H
-#define _ASM_BLACKFIN_CPUMASK_H
-
-#include <asm-generic/cpumask.h>
-
-#endif                         /* _ASM_BLACKFIN_CPUMASK_H */
index 1a13c2fc3667326a78b7267cf27fb71de75922f5..ede748d67efdc6bed10051a746a9fa53499e7469 100644 (file)
@@ -80,4 +80,15 @@ extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
                      int nhwentries, enum dma_data_direction direction);
 
+static inline void dma_sync_single_for_cpu(struct device *dev,
+                                       dma_addr_t handle, size_t size,
+                                       enum dma_data_direction dir)
+{
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+                                       dma_addr_t handle, size_t size,
+                                       enum dma_data_direction dir)
+{
+}
 #endif                         /* _BLACKFIN_DMA_MAPPING_H */
index 67a03a8a353e019a28a1c86918ee6367eb978d69..cdbfcfc30f6a693c170d6db57e80a3af04c5cf50 100644 (file)
@@ -122,6 +122,6 @@ do {                                                                                        \
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif
index cbbf7ffdbbff1d4450e29ef0b68c5d1cde99c168..7dc77a21fdf33aeb2f94fc42ad97db7c1f9447a0 100644 (file)
@@ -134,6 +134,36 @@ extern void dma_insb(unsigned long port, void *addr, unsigned short count);
 extern void dma_insw(unsigned long port, void *addr, unsigned short count);
 extern void dma_insl(unsigned long port, void *addr, unsigned short count);
 
+static inline void readsl(const void __iomem *addr, void *buf, int len)
+{
+       insl((unsigned long)addr, buf, len);
+}
+
+static inline void readsw(const void __iomem *addr, void *buf, int len)
+{
+       insw((unsigned long)addr, buf, len);
+}
+
+static inline void readsb(const void __iomem *addr, void *buf, int len)
+{
+       insb((unsigned long)addr, buf, len);
+}
+
+static inline void writesl(const void __iomem *addr, const void *buf, int len)
+{
+       outsl((unsigned long)addr, buf, len);
+}
+
+static inline void writesw(const void __iomem *addr, const void *buf, int len)
+{
+       outsw((unsigned long)addr, buf, len);
+}
+
+static inline void writesb(const void __iomem *addr, const void *buf, int len)
+{
+       outsb((unsigned long)addr, buf, len);
+}
+
 /*
  * Map some physical address range into the kernel address space.
  */
index 0f73847fd6bc53f4d90538477c814d632d777ab2..26ebac6646d879b61e7acb1759a81f4328d484c4 100644 (file)
@@ -124,9 +124,16 @@ enum regnames {
 /* Number of bytes of registers.  */
 #define NUMREGBYTES BFIN_NUM_REGS*4
 
-#define BREAKPOINT() asm("   EXCPT 2;");
-#define BREAK_INSTR_SIZE       2
-#define HW_BREAKPOINT_NUM              6
+static inline void arch_kgdb_breakpoint(void)
+{
+       asm("   EXCPT 2;");
+}
+#define BREAK_INSTR_SIZE       2
+#define CACHE_FLUSH_IS_SAFE    1
+#define HW_INST_WATCHPOINT_NUM 6
+#define HW_WATCHPOINT_NUM      8
+#define TYPE_INST_WATCHPOINT   0
+#define TYPE_DATA_WATCHPOINT   1
 
 /* Instruction watchpoint address control register bits mask */
 #define WPPWR          0x1
@@ -163,10 +170,11 @@ enum regnames {
 #define WPDAEN1                0x8
 #define WPDCNTEN0      0x10
 #define WPDCNTEN1      0x20
+
 #define WPDSRC0                0xc0
-#define WPDACC0                0x300
+#define WPDACC0_OFFSET 8
 #define WPDSRC1                0xc00
-#define WPDACC1                0x3000
+#define WPDACC1_OFFSET 12
 
 /* Watchpoint status register bits mask */
 #define STATIA0                0x1
@@ -178,7 +186,4 @@ enum regnames {
 #define STATDA0                0x40
 #define STATDA1                0x80
 
-extern void kgdb_print(const char *fmt, ...);
-extern void init_kgdb_uart(void);
-
 #endif
index 8529552a981ff39ee42a6b8b60205a08edbbe57f..35593dda2a4d396d0bcbbaed982c2b2c5888812b 100644 (file)
@@ -45,49 +45,12 @@ extern unsigned long l1_stack_len;
 extern int l1sram_free(const void*);
 extern void *l1sram_alloc_max(void*);
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-/* Called when creating a new context during fork() or execve().  */
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
-#ifdef CONFIG_MPU
-       unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order);
-       mm->context.page_rwx_mask = (unsigned long *)p;
-       memset(mm->context.page_rwx_mask, 0,
-              page_mask_nelts * 3 * sizeof(long));
-#endif
-       return 0;
-}
-
 static inline void free_l1stack(void)
 {
        nr_l1stack_tasks--;
        if (nr_l1stack_tasks == 0)
                l1sram_free(l1_stack_base);
 }
-static inline void destroy_context(struct mm_struct *mm)
-{
-       struct sram_list_struct *tmp;
-
-       if (current_l1_stack_save == mm->context.l1_stack_save)
-               current_l1_stack_save = NULL;
-       if (mm->context.l1_stack_save)
-               free_l1stack();
-
-       while ((tmp = mm->context.sram_list)) {
-               mm->context.sram_list = tmp->next;
-               sram_free(tmp->addr);
-               kfree(tmp);
-       }
-#ifdef CONFIG_MPU
-       if (current_rwx_mask == mm->context.page_rwx_mask)
-               current_rwx_mask = NULL;
-       free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
-#endif
-}
 
 static inline unsigned long
 alloc_l1stack(unsigned long length, unsigned long *stack_base)
@@ -134,6 +97,7 @@ static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_m
        }
 #endif
 
+#ifdef CONFIG_APP_STACK_L1
        /* L1 stack switching.  */
        if (!next_mm->context.l1_stack_save)
                return;
@@ -144,6 +108,7 @@ static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_m
        }
        current_l1_stack_save = next_mm->context.l1_stack_save;
        memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
+#endif
 }
 
 #ifdef CONFIG_MPU
@@ -180,4 +145,44 @@ static inline void update_protections(struct mm_struct *mm)
 }
 #endif
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/* Called when creating a new context during fork() or execve().  */
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+#ifdef CONFIG_MPU
+       unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order);
+       mm->context.page_rwx_mask = (unsigned long *)p;
+       memset(mm->context.page_rwx_mask, 0,
+              page_mask_nelts * 3 * sizeof(long));
+#endif
+       return 0;
+}
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+       struct sram_list_struct *tmp;
+
+#ifdef CONFIG_APP_STACK_L1
+       if (current_l1_stack_save == mm->context.l1_stack_save)
+               current_l1_stack_save = 0;
+       if (mm->context.l1_stack_save)
+               free_l1stack();
+#endif
+
+       while ((tmp = mm->context.sram_list)) {
+               mm->context.sram_list = tmp->next;
+               sram_free(tmp->addr);
+               kfree(tmp);
+       }
+#ifdef CONFIG_MPU
+       if (current_rwx_mask == mm->context.page_rwx_mask)
+               current_rwx_mask = NULL;
+       free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
+#endif
+}
+
 #endif
index 6f3995b119d8e78658abd9c5ca448deaa2026435..e3e9b41fa8dbd59e698bbd7deba58b008e218f42 100644 (file)
@@ -134,6 +134,12 @@ static inline uint32_t __pure bfin_revid(void)
        return revid;
 }
 
+static inline uint16_t __pure bfin_cpuid(void)
+{
+       return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12;
+
+}
+
 static inline uint32_t __pure bfin_compiled_revid(void)
 {
 #if defined(CONFIG_BF_REV_0_0)
index a45a80e54adcbe75a774df805d881c03a8da7015..e3f086dc7268eca47b1d7c4c72d57fa13a2d0f40 100644 (file)
@@ -158,6 +158,8 @@ extern void show_regs(struct pt_regs *);
 #define PT_SEQSTAT 8
 #define PT_IPEND 4
 
+#define PT_ORIG_R0 208
+#define PT_ORIG_P0 212
 #define PT_SYSCFG 216
 #define PT_TEXT_ADDR 220
 #define PT_TEXT_END_ADDR 224
index 22b0806161bb614b2179c7ec1eee002a0255779e..248aeb06680527f49dd24d3e559295ac9fdf78ed 100644 (file)
@@ -16,7 +16,7 @@ typedef unsigned long long cycles_t;
 static inline cycles_t get_cycles(void)
 {
        unsigned long tmp, tmp2;
-       __asm__("%0 = cycles; %1 = cycles2;" : "=d"(tmp), "=d"(tmp2));
+       __asm__ __volatile__("%0 = cycles; %1 = cycles2;" : "=d"(tmp), "=d"(tmp2));
        return tmp | ((cycles_t)tmp2 << 32);
 }
 
index f0e5f940d9cae503d55be15fb74982c15be47a2a..34f7295fb0708c71f8823fd8fc709535629da42d 100644 (file)
@@ -59,6 +59,9 @@
        level "   or a 16-bit register is accessed with a 32-bit instruction.\n"
 #define HWC_x3(level) \
        "External Memory Addressing Error\n"
+#define EXC_0x04(level) \
+       "Unimplmented exception occured\n" \
+       level " - Maybe you forgot to install a custom exception handler?\n"
 #define HWC_x12(level) \
        "Performance Monitor Overflow\n"
 #define HWC_x18(level) \
@@ -84,7 +87,7 @@
        level "   a particular processor implementation.\n"
 #define EXC_0x22(level) \
        "Illegal instruction combination\n" \
-       level " - See section for multi-issue rules in the ADSP-BF53x Blackfin\n" \
+       level " - See section for multi-issue rules in the Blackfin\n" \
        level "   Processor Instruction Set Reference.\n"
 #define EXC_0x23(level) \
        "Data access CPLB protection violation\n" \
index 881afe9082c76744bd9bdb01cc0bcd564a50f973..9bb85dd5ccb39a65d0926dcf27c019f6fa44df34 100644 (file)
@@ -60,6 +60,7 @@ int main(void)
        DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
 
        /* offsets into the pt_regs */
+       DEFINE(PT_ORIG_R0, offsetof(struct pt_regs, orig_r0));
        DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0));
        DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc));
        DEFINE(PT_R0, offsetof(struct pt_regs, r0));
index 93229b3d6e3e30da6bc17dd760bd48ddbacda0af..339293d677cc33608970e912476dad1040ab7ade 100644 (file)
@@ -117,15 +117,14 @@ int request_dma(unsigned int channel, char *device_id)
 
 #ifdef CONFIG_BF54x
        if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
-               if (strncmp(device_id, "BFIN_UART", 9) == 0) {
-                       dma_ch[channel].regs->peripheral_map &= 0x0FFF;
-                       dma_ch[channel].regs->peripheral_map |=
+               unsigned int per_map;
+               per_map = dma_ch[channel].regs->peripheral_map & 0xFFF;
+               if (strncmp(device_id, "BFIN_UART", 9) == 0)
+                       dma_ch[channel].regs->peripheral_map = per_map |
                                ((channel - CH_UART2_RX + 0xC)<<12);
-               } else {
-                       dma_ch[channel].regs->peripheral_map &= 0x0FFF;
-                       dma_ch[channel].regs->peripheral_map |=
+               else
+                       dma_ch[channel].regs->peripheral_map = per_map |
                                ((channel - CH_UART2_RX + 0x6)<<12);
-               }
        }
 #endif
 
index ecbd141e0ef2b1d60a4ae71af6655aabd16019b3..6e08f425bb44076fa39443e23ab75d1db429afa1 100644 (file)
@@ -231,14 +231,14 @@ inline int check_gpio(unsigned gpio)
 }
 #endif
 
-void gpio_error(unsigned gpio)
+static void gpio_error(unsigned gpio)
 {
        printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio);
 }
 
 static void set_label(unsigned short ident, const char *label)
 {
-       if (label && str_ident) {
+       if (label) {
                strncpy(str_ident[ident].name, label,
                         RESOURCE_LABEL_SIZE);
                str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
@@ -247,9 +247,6 @@ static void set_label(unsigned short ident, const char *label)
 
 static char *get_label(unsigned short ident)
 {
-       if (!str_ident)
-               return "UNKNOWN";
-
        return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
 }
 
@@ -260,7 +257,7 @@ static int cmp_label(unsigned short ident, const char *label)
                printk(KERN_ERR "Please provide none-null label\n");
        }
 
-       if (label && str_ident)
+       if (label)
                return strncmp(str_ident[ident].name,
                                 label, strlen(label));
        else
index 48060105346adab6481be7119b534a717f475fe2..55af729f8495725129e8cbfd7e41d40e083427f3 100644 (file)
@@ -36,7 +36,7 @@ struct cplb_entry dcplb_tbl[MAX_CPLBS];
 int first_switched_icplb, first_switched_dcplb;
 int first_mask_dcplb;
 
-void __init generate_cpl_tables(void)
+void __init generate_cplb_tables(void)
 {
        int i_d, i_i;
        unsigned long addr;
@@ -83,8 +83,18 @@ void __init generate_cpl_tables(void)
        dcplb_tbl[i_d].addr = L1_DATA_A_START;
        dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
 #endif
+#if L1_CODE_LENGTH > 0
        icplb_tbl[i_i].addr = L1_CODE_START;
        icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+#endif
+
+       /* Cover L2 memory */
+#if L2_LENGTH > 0
+       dcplb_tbl[i_d].addr = L2_START;
+       dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
+       icplb_tbl[i_i].addr = L2_START;
+       icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
+#endif
 
        first_mask_dcplb = i_d;
        first_switched_dcplb = i_d + (1 << page_mask_order);
index 99f2831e2964949a052fc3d5f1e788b69a9c6f8f..baa52e261f0d501dab0206a4edaebdc678f9b33f 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 
 #include <asm/blackfin.h>
+#include <asm/cacheflush.h>
 #include <asm/cplbinit.h>
 #include <asm/mmu_context.h>
 
@@ -144,9 +145,7 @@ static noinline int dcplb_miss(void)
 
        d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
 #ifdef CONFIG_BFIN_DCACHE
-       if (addr < _ramend - DMA_UNCACHED_REGION ||
-           (reserved_mem_dcache_on && addr >= _ramend &&
-            addr < physical_mem_end)) {
+       if (bfin_addr_dcachable(addr)) {
                d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
 #ifdef CONFIG_BFIN_WT
                d_data |= CPLB_L1_AOW | CPLB_WT;
@@ -322,9 +321,11 @@ int cplb_hdr(int seqstat, struct pt_regs *regs)
 void flush_switched_cplbs(void)
 {
        int i;
+       unsigned long flags;
 
        nr_cplb_flush++;
 
+       local_irq_save(flags);
        disable_icplb();
        for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
                icplb_tbl[i].data = 0;
@@ -338,6 +339,8 @@ void flush_switched_cplbs(void)
                bfin_write32(DCPLB_DATA0 + i * 4, 0);
        }
        enable_dcplb();
+       local_irq_restore(flags);
+
 }
 
 void set_mask_dcplbs(unsigned long *masks)
@@ -345,10 +348,15 @@ void set_mask_dcplbs(unsigned long *masks)
        int i;
        unsigned long addr = (unsigned long)masks;
        unsigned long d_data;
-       current_rwx_mask = masks;
+       unsigned long flags;
 
-       if (!masks)
+       if (!masks) {
+               current_rwx_mask = masks;
                return;
+       }
+
+       local_irq_save(flags);
+       current_rwx_mask = masks;
 
        d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
 #ifdef CONFIG_BFIN_DCACHE
@@ -367,4 +375,5 @@ void set_mask_dcplbs(unsigned long *masks)
                addr += PAGE_SIZE;
        }
        enable_dcplb();
+       local_irq_restore(flags);
 }
index 728f708d3981008d0f4bdc459054da549a03d84e..512f8c92ead511f2286a4a9f688763becd9ca8ed 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 
 #include <asm/blackfin.h>
+#include <asm/cacheflush.h>
 #include <asm/cplb.h>
 #include <asm/cplbinit.h>
 
@@ -168,8 +169,8 @@ static struct cplb_desc cplb_data[] = {
                .end = L2_START + L2_LENGTH,
                .psize = SIZE_1M,
                .attr = SWITCH_T | I_CPLB | D_CPLB,
-               .i_conf = L2_MEMORY,
-               .d_conf = L2_MEMORY,
+               .i_conf = L2_IMEMORY,
+               .d_conf = L2_DMEMORY,
                .valid = (L2_LENGTH > 0),
                .name = "L2 Memory",
        },
@@ -308,7 +309,7 @@ __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
        }
 }
 
-void __init generate_cpl_tables(void)
+void __init generate_cplb_tables(void)
 {
 
        u16 i, j, process;
index 60f67f90fe35e7b81c2b349d2733c78c9ed16fd0..1f4e3d2e09014533cc929b53627ead66333030f4 100644 (file)
@@ -35,6 +35,9 @@
 extern struct console *bfin_earlyserial_init(unsigned int port,
                                                unsigned int cflag);
 #endif
+#ifdef CONFIG_BFIN_JTAG_COMM
+extern struct console *bfin_jc_early_init(void);
+#endif
 
 static struct console *early_console;
 
@@ -142,6 +145,15 @@ int __init setup_early_printk(char *buf)
                early_console = earlyserial_init(buf);
        }
 #endif
+
+#ifdef CONFIG_BFIN_JTAG_COMM
+       /* Check for Blackfin JTAG */
+       if (!strncmp(buf, "jtag", 4)) {
+               buf += 4;
+               early_console = bfin_jc_early_init();
+       }
+#endif
+
 #ifdef CONFIG_FB
                /* TODO: add framebuffer console support */
 #endif
index a1f9641a6425d6158ebf21f4a71f4df867fd44ea..b795a207742cd4ff557cc6b06a154a083b62bfd9 100644 (file)
@@ -1,32 +1,9 @@
 /*
- * File:         arch/blackfin/kernel/kgdb.c
- * Based on:
- * Author:       Sonic Zhang
+ * arch/blackfin/kernel/kgdb.c - Blackfin kgdb pieces
  *
- * Created:
- * Description:
+ * Copyright 2005-2008 Analog Devices Inc.
  *
- * Rev:          $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
- *
- * Modified:
- *               Copyright 2005-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/string.h>
 #include <linux/kgdb.h>
 #include <linux/console.h>
 #include <linux/init.h>
-#include <linux/debugger.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
+#include <linux/uaccess.h>
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/blackfin.h>
+#include <asm/dma.h>
 
 /* Put the error code here just in case the user cares.  */
-int gdb_bf533errcode;
+int gdb_bfin_errcode;
 /* Likewise, the vector number here (since GDB only gets the signal
    number through the usual means, and that's not very specific).  */
-int gdb_bf533vector = -1;
+int gdb_bfin_vector = -1;
 
 #if KGDB_MAX_NO_CPUS != 8
 #error change the definition of slavecpulocks
 #endif
 
-void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+#ifdef CONFIG_BFIN_WDT
+# error "Please unselect blackfin watchdog driver before build KGDB."
+#endif
+
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
        gdb_regs[BFIN_R0] = regs->r0;
        gdb_regs[BFIN_R1] = regs->r1;
@@ -133,7 +115,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
        gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat;
 }
 
-void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
        regs->r0 = gdb_regs[BFIN_R0];
        regs->r1 = gdb_regs[BFIN_R1];
@@ -199,171 +181,208 @@ struct hw_breakpoint {
        unsigned int dataacc:2;
        unsigned short count;
        unsigned int addr;
-} breakinfo[HW_BREAKPOINT_NUM];
+} breakinfo[HW_WATCHPOINT_NUM];
 
-int kgdb_arch_init(void)
-{
-       debugger_step = 0;
-
-       kgdb_remove_all_hw_break();
-       return 0;
-}
-
-int kgdb_set_hw_break(unsigned long addr)
+int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
 {
        int breakno;
-       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
-               if (!breakinfo[breakno].occupied) {
+       int bfin_type;
+       int dataacc = 0;
+
+       switch (type) {
+       case BP_HARDWARE_BREAKPOINT:
+               bfin_type = TYPE_INST_WATCHPOINT;
+               break;
+       case BP_WRITE_WATCHPOINT:
+               dataacc = 1;
+               bfin_type = TYPE_DATA_WATCHPOINT;
+               break;
+       case BP_READ_WATCHPOINT:
+               dataacc = 2;
+               bfin_type = TYPE_DATA_WATCHPOINT;
+               break;
+       case BP_ACCESS_WATCHPOINT:
+               dataacc = 3;
+               bfin_type = TYPE_DATA_WATCHPOINT;
+               break;
+       default:
+               return -ENOSPC;
+       }
+
+       /* Becasue hardware data watchpoint impelemented in current
+        * Blackfin can not trigger an exception event as the hardware
+        * instrction watchpoint does, we ignaore all data watch point here.
+        * They can be turned on easily after future blackfin design
+        * supports this feature.
+        */
+       for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++)
+               if (bfin_type == breakinfo[breakno].type
+                       && !breakinfo[breakno].occupied) {
                        breakinfo[breakno].occupied = 1;
                        breakinfo[breakno].enabled = 1;
-                       breakinfo[breakno].type = 1;
                        breakinfo[breakno].addr = addr;
+                       breakinfo[breakno].dataacc = dataacc;
+                       breakinfo[breakno].count = 0;
                        return 0;
                }
 
        return -ENOSPC;
 }
 
-int kgdb_remove_hw_break(unsigned long addr)
+int bfin_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
 {
        int breakno;
-       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
-               if (breakinfo[breakno].addr == addr)
-                       memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint));
+       int bfin_type;
+
+       switch (type) {
+       case BP_HARDWARE_BREAKPOINT:
+               bfin_type = TYPE_INST_WATCHPOINT;
+               break;
+       case BP_WRITE_WATCHPOINT:
+       case BP_READ_WATCHPOINT:
+       case BP_ACCESS_WATCHPOINT:
+               bfin_type = TYPE_DATA_WATCHPOINT;
+               break;
+       default:
+               return 0;
+       }
+       for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
+               if (bfin_type == breakinfo[breakno].type
+                       && breakinfo[breakno].occupied
+                       && breakinfo[breakno].addr == addr) {
+                       breakinfo[breakno].occupied = 0;
+                       breakinfo[breakno].enabled = 0;
+               }
 
        return 0;
 }
 
-void kgdb_remove_all_hw_break(void)
+void bfin_remove_all_hw_break(void)
 {
-       memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8);
-}
+       int breakno;
 
-/*
-void kgdb_show_info(void)
-{
-       printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n",
-               bfin_read_WPIA0(), bfin_read_WPIACNT0(),
-               bfin_read_WPIACTL(), bfin_read_WPSTAT());
+       memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_WATCHPOINT_NUM);
+
+       for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++)
+               breakinfo[breakno].type = TYPE_INST_WATCHPOINT;
+       for (; breakno < HW_WATCHPOINT_NUM; breakno++)
+               breakinfo[breakno].type = TYPE_DATA_WATCHPOINT;
 }
-*/
 
-void kgdb_correct_hw_break(void)
+void bfin_correct_hw_break(void)
 {
        int breakno;
-       int correctit;
-       uint32_t wpdactl = bfin_read_WPDACTL();
+       unsigned int wpiactl = 0;
+       unsigned int wpdactl = 0;
+       int enable_wp = 0;
+
+       for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
+               if (breakinfo[breakno].enabled) {
+                       enable_wp = 1;
 
-       correctit = 0;
-       for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) {
-               if (breakinfo[breakno].type == 1) {
                        switch (breakno) {
                        case 0:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN01|EMUSW0);
-                                       wpdactl |= WPIAEN0|WPICNTEN0;
-                                       bfin_write_WPIA0(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT0(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN0;
-                               }
+                               wpiactl |= WPIAEN0|WPICNTEN0;
+                               bfin_write_WPIA0(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT0(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
-
                        case 1:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN01|EMUSW1);
-                                       wpdactl |= WPIAEN1|WPICNTEN1;
-                                       bfin_write_WPIA1(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT1(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN1;
-                               }
+                               wpiactl |= WPIAEN1|WPICNTEN1;
+                               bfin_write_WPIA1(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT1(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
-
                        case 2:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN23|EMUSW2);
-                                       wpdactl |= WPIAEN2|WPICNTEN2;
-                                       bfin_write_WPIA2(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT2(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN2;
-                               }
+                               wpiactl |= WPIAEN2|WPICNTEN2;
+                               bfin_write_WPIA2(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT2(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
-
                        case 3:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN23|EMUSW3);
-                                       wpdactl |= WPIAEN3|WPICNTEN3;
-                                       bfin_write_WPIA3(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT3(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN3;
-                               }
+                               wpiactl |= WPIAEN3|WPICNTEN3;
+                               bfin_write_WPIA3(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT3(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
                        case 4:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN45|EMUSW4);
-                                       wpdactl |= WPIAEN4|WPICNTEN4;
-                                       bfin_write_WPIA4(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT4(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN4;
-                               }
+                               wpiactl |= WPIAEN4|WPICNTEN4;
+                               bfin_write_WPIA4(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT4(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
                        case 5:
-                               if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) {
-                                       correctit = 1;
-                                       wpdactl &= ~(WPIREN45|EMUSW5);
-                                       wpdactl |= WPIAEN5|WPICNTEN5;
-                                       bfin_write_WPIA5(breakinfo[breakno].addr);
-                                       bfin_write_WPIACNT5(breakinfo[breakno].skip);
-                               } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) {
-                                       correctit = 1;
-                                       wpdactl &= ~WPIAEN5;
-                               }
+                               wpiactl |= WPIAEN5|WPICNTEN5;
+                               bfin_write_WPIA5(breakinfo[breakno].addr);
+                               bfin_write_WPIACNT5(breakinfo[breakno].count
+                                       + breakinfo->skip);
+                               break;
+                       case 6:
+                               wpdactl |= WPDAEN0|WPDCNTEN0|WPDSRC0;
+                               wpdactl |= breakinfo[breakno].dataacc
+                                       << WPDACC0_OFFSET;
+                               bfin_write_WPDA0(breakinfo[breakno].addr);
+                               bfin_write_WPDACNT0(breakinfo[breakno].count
+                                       + breakinfo->skip);
+                               break;
+                       case 7:
+                               wpdactl |= WPDAEN1|WPDCNTEN1|WPDSRC1;
+                               wpdactl |= breakinfo[breakno].dataacc
+                                       << WPDACC1_OFFSET;
+                               bfin_write_WPDA1(breakinfo[breakno].addr);
+                               bfin_write_WPDACNT1(breakinfo[breakno].count
+                                       + breakinfo->skip);
                                break;
                        }
                }
-       }
-       if (correctit) {
-               wpdactl &= ~WPAND;
-               wpdactl |= WPPWR;
-               /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
+
+       /* Should enable WPPWR bit first before set any other
+        * WPIACTL and WPDACTL bits */
+       if (enable_wp) {
+               bfin_write_WPIACTL(WPPWR);
+               CSYNC();
+               bfin_write_WPIACTL(wpiactl|WPPWR);
                bfin_write_WPDACTL(wpdactl);
                CSYNC();
-               /*kgdb_show_info();*/
        }
 }
 
 void kgdb_disable_hw_debug(struct pt_regs *regs)
 {
        /* Disable hardware debugging while we are in kgdb */
-       bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
+       bfin_write_WPIACTL(0);
+       bfin_write_WPDACTL(0);
        CSYNC();
 }
 
-void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code)
+#ifdef CONFIG_SMP
+void kgdb_passive_cpu_callback(void *info)
+{
+       kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+       smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0);
+}
+
+void kgdb_roundup_cpu(int cpu, unsigned long flags)
+{
+       smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0);
+}
+#endif
+
+void kgdb_post_primary_code(struct pt_regs *regs, int eVector, int err_code)
 {
        /* Master processor is completely in the debugger */
-       gdb_bf533vector = eVector;
-       gdb_bf533errcode = err_code;
+       gdb_bfin_vector = eVector;
+       gdb_bfin_errcode = err_code;
 }
 
-int kgdb_arch_handle_exception(int exceptionVector, int signo,
+int kgdb_arch_handle_exception(int vector, int signo,
                               int err_code, char *remcom_in_buffer,
                               char *remcom_out_buffer,
-                              struct pt_regs *linux_regs)
+                              struct pt_regs *regs)
 {
        long addr;
        long breakno;
@@ -385,44 +404,40 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
                /* try to read optional parameter, pc unchanged if no parm */
                ptr = &remcom_in_buffer[1];
                if (kgdb_hex2long(&ptr, &addr)) {
-                       linux_regs->retx = addr;
+                       regs->retx = addr;
                }
-               newPC = linux_regs->retx;
+               newPC = regs->retx;
 
                /* clear the trace bit */
-               linux_regs->syscfg &= 0xfffffffe;
+               regs->syscfg &= 0xfffffffe;
 
                /* set the trace bit if we're stepping */
                if (remcom_in_buffer[0] == 's') {
-                       linux_regs->syscfg |= 0x1;
-                       debugger_step = linux_regs->ipend;
-                       debugger_step >>= 6;
-                       for (i = 10; i > 0; i--, debugger_step >>= 1)
-                               if (debugger_step & 1)
+                       regs->syscfg |= 0x1;
+                       kgdb_single_step = regs->ipend;
+                       kgdb_single_step >>= 6;
+                       for (i = 10; i > 0; i--, kgdb_single_step >>= 1)
+                               if (kgdb_single_step & 1)
                                        break;
                        /* i indicate event priority of current stopped instruction
                         * user space instruction is 0, IVG15 is 1, IVTMR is 10.
-                        * debugger_step > 0 means in single step mode
+                        * kgdb_single_step > 0 means in single step mode
                         */
-                       debugger_step = i + 1;
-               } else {
-                       debugger_step = 0;
+                       kgdb_single_step = i + 1;
                }
 
-               wp_status = bfin_read_WPSTAT();
-               CSYNC();
-
-               if (exceptionVector == VEC_WATCH) {
-                       for (breakno = 0; breakno < 6; ++breakno) {
+               if (vector == VEC_WATCH) {
+                       wp_status = bfin_read_WPSTAT();
+                       for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) {
                                if (wp_status & (1 << breakno)) {
                                        breakinfo->skip = 1;
                                        break;
                                }
                        }
+                       bfin_write_WPSTAT(0);
                }
-               kgdb_correct_hw_break();
 
-               bfin_write_WPSTAT(0);
+               bfin_correct_hw_break();
 
                return 0;
        }                       /* switch */
@@ -431,5 +446,385 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo,
 
 struct kgdb_arch arch_kgdb_ops = {
        .gdb_bpt_instr = {0xa1},
+#ifdef CONFIG_SMP
+       .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
+#else
        .flags = KGDB_HW_BREAKPOINT,
+#endif
+       .set_hw_breakpoint = bfin_set_hw_break,
+       .remove_hw_breakpoint = bfin_remove_hw_break,
+       .remove_all_hw_break = bfin_remove_all_hw_break,
+       .correct_hw_break = bfin_correct_hw_break,
 };
+
+static int hex(char ch)
+{
+       if ((ch >= 'a') && (ch <= 'f'))
+               return ch - 'a' + 10;
+       if ((ch >= '0') && (ch <= '9'))
+               return ch - '0';
+       if ((ch >= 'A') && (ch <= 'F'))
+               return ch - 'A' + 10;
+       return -1;
+}
+
+static int validate_memory_access_address(unsigned long addr, int size)
+{
+       int cpu = raw_smp_processor_id();
+
+       if (size < 0)
+               return EFAULT;
+       if (addr >= 0x1000 && (addr + size) <= physical_mem_end)
+               return 0;
+       if (addr >= SYSMMR_BASE)
+               return 0;
+       if (addr >= ASYNC_BANK0_BASE
+          && addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
+               return 0;
+       if (cpu == 0) {
+               if (addr >= L1_SCRATCH_START
+                  && (addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH))
+                       return 0;
+#if L1_CODE_LENGTH != 0
+               if (addr >= L1_CODE_START
+                  && (addr + size <= L1_CODE_START + L1_CODE_LENGTH))
+                       return 0;
+#endif
+#if L1_DATA_A_LENGTH != 0
+               if (addr >= L1_DATA_A_START
+                  && (addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH))
+                       return 0;
+#endif
+#if L1_DATA_B_LENGTH != 0
+               if (addr >= L1_DATA_B_START
+                  && (addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH))
+                       return 0;
+#endif
+#ifdef CONFIG_SMP
+       } else if (cpu == 1) {
+               if (addr >= COREB_L1_SCRATCH_START
+                  && (addr + size <= COREB_L1_SCRATCH_START
+                  + L1_SCRATCH_LENGTH))
+                       return 0;
+# if L1_CODE_LENGTH != 0
+               if (addr >= COREB_L1_CODE_START
+                  && (addr + size <= COREB_L1_CODE_START + L1_CODE_LENGTH))
+                       return 0;
+# endif
+# if L1_DATA_A_LENGTH != 0
+               if (addr >= COREB_L1_DATA_A_START
+                  && (addr + size <= COREB_L1_DATA_A_START + L1_DATA_A_LENGTH))
+                       return 0;
+# endif
+# if L1_DATA_B_LENGTH != 0
+               if (addr >= COREB_L1_DATA_B_START
+                  && (addr + size <= COREB_L1_DATA_B_START + L1_DATA_B_LENGTH))
+                       return 0;
+# endif
+#endif
+       }
+
+#if L2_LENGTH != 0
+       if (addr >= L2_START
+          && addr + size <= L2_START + L2_LENGTH)
+               return 0;
+#endif
+
+       return EFAULT;
+}
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null). May return an error.
+ */
+int kgdb_mem2hex(char *mem, char *buf, int count)
+{
+       char *tmp;
+       int err = 0;
+       unsigned char *pch;
+       unsigned short mmr16;
+       unsigned long mmr32;
+       int cpu = raw_smp_processor_id();
+
+       if (validate_memory_access_address((unsigned long)mem, count))
+               return EFAULT;
+
+       /*
+        * We use the upper half of buf as an intermediate buffer for the
+        * raw memory copy.  Hex conversion will work against this one.
+        */
+       tmp = buf + count;
+
+       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
+               switch (count) {
+               case 2:
+                       if ((unsigned int)mem % 2 == 0) {
+                               mmr16 = *(unsigned short *)mem;
+                               pch = (unsigned char *)&mmr16;
+                               *tmp++ = *pch++;
+                               *tmp++ = *pch++;
+                               tmp -= 2;
+                       } else
+                               err = EFAULT;
+                       break;
+               case 4:
+                       if ((unsigned int)mem % 4 == 0) {
+                               mmr32 = *(unsigned long *)mem;
+                               pch = (unsigned char *)&mmr32;
+                               *tmp++ = *pch++;
+                               *tmp++ = *pch++;
+                               *tmp++ = *pch++;
+                               *tmp++ = *pch++;
+                               tmp -= 4;
+                       } else
+                               err = EFAULT;
+                       break;
+               default:
+                       err = EFAULT;
+               }
+       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
+               (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
+#ifdef CONFIG_SMP
+               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
+               (unsigned int)(mem + count) <=
+               COREB_L1_CODE_START + L1_CODE_LENGTH
+#endif
+               ) {
+               /* access L1 instruction SRAM*/
+               if (dma_memcpy(tmp, mem, count) == NULL)
+                       err = EFAULT;
+       } else
+               err = probe_kernel_read(tmp, mem, count);
+
+       if (!err) {
+               while (count > 0) {
+                       buf = pack_hex_byte(buf, *tmp);
+                       tmp++;
+                       count--;
+               }
+
+               *buf = 0;
+       }
+
+       return err;
+}
+
+/*
+ * Copy the binary array pointed to by buf into mem.  Fix $, #, and
+ * 0x7d escaped with 0x7d.  Return a pointer to the character after
+ * the last byte written.
+ */
+int kgdb_ebin2mem(char *buf, char *mem, int count)
+{
+       char *tmp_old;
+       char *tmp_new;
+       unsigned short *mmr16;
+       unsigned long *mmr32;
+       int err = 0;
+       int size = 0;
+       int cpu = raw_smp_processor_id();
+
+       tmp_old = tmp_new = buf;
+
+       while (count-- > 0) {
+               if (*tmp_old == 0x7d)
+                       *tmp_new = *(++tmp_old) ^ 0x20;
+               else
+                       *tmp_new = *tmp_old;
+               tmp_new++;
+               tmp_old++;
+               size++;
+       }
+
+       if (validate_memory_access_address((unsigned long)mem, size))
+               return EFAULT;
+
+       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
+               switch (size) {
+               case 2:
+                       if ((unsigned int)mem % 2 == 0) {
+                               mmr16 = (unsigned short *)buf;
+                               *(unsigned short *)mem = *mmr16;
+                       } else
+                               return EFAULT;
+                       break;
+               case 4:
+                       if ((unsigned int)mem % 4 == 0) {
+                               mmr32 = (unsigned long *)buf;
+                               *(unsigned long *)mem = *mmr32;
+                       } else
+                               return EFAULT;
+                       break;
+               default:
+                       return EFAULT;
+               }
+       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
+               (unsigned int)(mem + count) < L1_CODE_START + L1_CODE_LENGTH
+#ifdef CONFIG_SMP
+               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
+               (unsigned int)(mem + count) <=
+               COREB_L1_CODE_START + L1_CODE_LENGTH
+#endif
+               ) {
+               /* access L1 instruction SRAM */
+               if (dma_memcpy(mem, buf, size) == NULL)
+                       err = EFAULT;
+       } else
+               err = probe_kernel_write(mem, buf, size);
+
+       return err;
+}
+
+/*
+ * Convert the hex array pointed to by buf into binary to be placed in mem.
+ * Return a pointer to the character AFTER the last byte written.
+ * May return an error.
+ */
+int kgdb_hex2mem(char *buf, char *mem, int count)
+{
+       char *tmp_raw;
+       char *tmp_hex;
+       unsigned short *mmr16;
+       unsigned long *mmr32;
+       int cpu = raw_smp_processor_id();
+
+       if (validate_memory_access_address((unsigned long)mem, count))
+               return EFAULT;
+
+       /*
+        * We use the upper half of buf as an intermediate buffer for the
+        * raw memory that is converted from hex.
+        */
+       tmp_raw = buf + count * 2;
+
+       tmp_hex = tmp_raw - 1;
+       while (tmp_hex >= buf) {
+               tmp_raw--;
+               *tmp_raw = hex(*tmp_hex--);
+               *tmp_raw |= hex(*tmp_hex--) << 4;
+       }
+
+       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
+               switch (count) {
+               case 2:
+                       if ((unsigned int)mem % 2 == 0) {
+                               mmr16 = (unsigned short *)tmp_raw;
+                               *(unsigned short *)mem = *mmr16;
+                       } else
+                               return EFAULT;
+                       break;
+               case 4:
+                       if ((unsigned int)mem % 4 == 0) {
+                               mmr32 = (unsigned long *)tmp_raw;
+                               *(unsigned long *)mem = *mmr32;
+                       } else
+                               return EFAULT;
+                       break;
+               default:
+                       return EFAULT;
+               }
+       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
+               (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
+#ifdef CONFIG_SMP
+               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
+               (unsigned int)(mem + count) <=
+               COREB_L1_CODE_START + L1_CODE_LENGTH
+#endif
+               ) {
+               /* access L1 instruction SRAM */
+               if (dma_memcpy(mem, tmp_raw, count) == NULL)
+                       return EFAULT;
+       } else
+               return probe_kernel_write(mem, tmp_raw, count);
+       return 0;
+}
+
+int kgdb_validate_break_address(unsigned long addr)
+{
+       int cpu = raw_smp_processor_id();
+
+       if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end)
+               return 0;
+       if (addr >= ASYNC_BANK0_BASE
+          && addr + BREAK_INSTR_SIZE <= ASYNC_BANK3_BASE + ASYNC_BANK3_BASE)
+               return 0;
+#if L1_CODE_LENGTH != 0
+       if (cpu == 0 && addr >= L1_CODE_START
+          && addr + BREAK_INSTR_SIZE <= L1_CODE_START + L1_CODE_LENGTH)
+               return 0;
+# ifdef CONFIG_SMP
+       else if (cpu == 1 && addr >= COREB_L1_CODE_START
+          && addr + BREAK_INSTR_SIZE <= COREB_L1_CODE_START + L1_CODE_LENGTH)
+               return 0;
+# endif
+#endif
+#if L2_LENGTH != 0
+       if (addr >= L2_START
+          && addr + BREAK_INSTR_SIZE <= L2_START + L2_LENGTH)
+               return 0;
+#endif
+
+       return EFAULT;
+}
+
+int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+{
+       int err;
+       int cpu = raw_smp_processor_id();
+
+       if ((cpu == 0 && (unsigned int)addr >= L1_CODE_START
+               && (unsigned int)(addr + BREAK_INSTR_SIZE)
+               < L1_CODE_START + L1_CODE_LENGTH)
+#ifdef CONFIG_SMP
+               || (cpu == 1 && (unsigned int)addr >= COREB_L1_CODE_START
+               && (unsigned int)(addr + BREAK_INSTR_SIZE)
+               < COREB_L1_CODE_START + L1_CODE_LENGTH)
+#endif
+               ) {
+               /* access L1 instruction SRAM */
+               if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE)
+                       == NULL)
+                       return -EFAULT;
+
+               if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr,
+                       BREAK_INSTR_SIZE) == NULL)
+                       return -EFAULT;
+
+               return 0;
+       } else {
+               err = probe_kernel_read(saved_instr, (char *)addr,
+                       BREAK_INSTR_SIZE);
+               if (err)
+                       return err;
+
+               return probe_kernel_write((char *)addr,
+                       arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+       }
+}
+
+int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+{
+       if ((unsigned int)addr >= L1_CODE_START &&
+               (unsigned int)(addr + BREAK_INSTR_SIZE) <
+                       L1_CODE_START + L1_CODE_LENGTH) {
+               /* access L1 instruction SRAM */
+               if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL)
+                       return -EFAULT;
+
+               return 0;
+       } else
+               return probe_kernel_write((char *)addr,
+                               (char *)bundle, BREAK_INSTR_SIZE);
+}
+
+int kgdb_arch_init(void)
+{
+       kgdb_single_step = 0;
+
+       bfin_remove_all_hw_break();
+       return 0;
+}
+
+void kgdb_arch_exit(void)
+{
+}
index bf1a51d8e608a39305ef8d03295060bec5416138..140bf00e99749f6fee7e9aec85149f9872c1d03f 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/dma.h>
 #include <asm/fixed_code.h>
 
-#define MAX_SHARED_LIBS 3
 #define TEXT_OFFSET 0
 /*
  * does not yet catch signals sent when the child dies.
@@ -161,21 +160,32 @@ static inline int is_user_addr_valid(struct task_struct *child,
        struct vm_list_struct *vml;
        struct sram_list_struct *sraml;
 
+       /* overflow */
+       if (start + len < start)
+               return -EIO;
+
        for (vml = child->mm->context.vmlist; vml; vml = vml->next)
-               if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
+               if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end)
                        return 0;
 
        for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
                if (start >= (unsigned long)sraml->addr
-                   && start + len <= (unsigned long)sraml->addr + sraml->length)
+                   && start + len < (unsigned long)sraml->addr + sraml->length)
                        return 0;
 
-       if (start >= FIXED_CODE_START && start + len <= FIXED_CODE_END)
+       if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END)
                return 0;
 
        return -EIO;
 }
 
+void ptrace_enable(struct task_struct *child)
+{
+       unsigned long tmp;
+       tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS);
+       put_reg(child, PT_SYSCFG, tmp);
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -192,14 +202,12 @@ void ptrace_disable(struct task_struct *child)
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        int ret;
-       int add = 0;
        unsigned long __user *datap = (unsigned long __user *)data;
 
        switch (request) {
                /* when I and D space are separate, these will need to be fixed. */
        case PTRACE_PEEKDATA:
                pr_debug("ptrace: PEEKDATA\n");
-               add = MAX_SHARED_LIBS * 4;      /* space between text and data */
                /* fall through */
        case PTRACE_PEEKTEXT:   /* read word at location addr. */
                {
@@ -207,40 +215,35 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        int copied;
 
                        ret = -EIO;
-                       pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add,
-                                sizeof(data));
-                       if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0)
+                       pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data));
+                       if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0)
                                break;
                        pr_debug("ptrace: user address is valid\n");
 
-#if L1_CODE_LENGTH != 0
-                       if (addr + add >= L1_CODE_START
-                           && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
-                               safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp));
+                       if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
+                           && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
+                               safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
                                copied = sizeof(tmp);
-                       } else
-#endif
-#if L1_DATA_A_LENGTH != 0
-                       if (addr + add >= L1_DATA_A_START
-                           && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
-                               memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
+
+                       } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
+                           && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
+                               memcpy(&tmp, (const void *)(addr), sizeof(tmp));
                                copied = sizeof(tmp);
-                       } else
-#endif
-#if L1_DATA_B_LENGTH != 0
-                       if (addr + add >= L1_DATA_B_START
-                           && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
-                               memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
+
+                       } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
+                           && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
+                               memcpy(&tmp, (const void *)(addr), sizeof(tmp));
                                copied = sizeof(tmp);
-                       } else
-#endif
-                       if (addr + add >= FIXED_CODE_START
-                           && addr + add + sizeof(tmp) <= FIXED_CODE_END) {
-                               memcpy(&tmp, (const void *)(addr + add), sizeof(tmp));
+
+                       } else if (addr >= FIXED_CODE_START
+                           && addr + sizeof(tmp) <= FIXED_CODE_END) {
+                               memcpy(&tmp, (const void *)(addr), sizeof(tmp));
                                copied = sizeof(tmp);
+
                        } else
-                               copied = access_process_vm(child, addr + add, &tmp,
+                               copied = access_process_vm(child, addr, &tmp,
                                                           sizeof(tmp), 0);
+
                        pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
                        if (copied != sizeof(tmp))
                                break;
@@ -284,47 +287,43 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
                /* when I and D space are separate, this will have to be fixed. */
        case PTRACE_POKEDATA:
-               printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n");
+               pr_debug("ptrace: PTRACE_PEEKDATA\n");
                /* fall through */
        case PTRACE_POKETEXT:   /* write the word at location addr. */
                {
                        int copied;
 
                        ret = -EIO;
-                       pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n",
-                                addr, add, sizeof(data), data);
-                       if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0)
+                       pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n",
+                                addr, sizeof(data), data);
+                       if (is_user_addr_valid(child, addr, sizeof(data)) < 0)
                                break;
                        pr_debug("ptrace: user address is valid\n");
 
-#if L1_CODE_LENGTH != 0
-                       if (addr + add >= L1_CODE_START
-                           && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
-                               safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data));
+                       if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
+                           && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
+                               safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
                                copied = sizeof(data);
-                       } else
-#endif
-#if L1_DATA_A_LENGTH != 0
-                       if (addr + add >= L1_DATA_A_START
-                           && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
-                               memcpy((void *)(addr + add), &data, sizeof(data));
+
+                       } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START
+                           && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) {
+                               memcpy((void *)(addr), &data, sizeof(data));
                                copied = sizeof(data);
-                       } else
-#endif
-#if L1_DATA_B_LENGTH != 0
-                       if (addr + add >= L1_DATA_B_START
-                           && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
-                               memcpy((void *)(addr + add), &data, sizeof(data));
+
+                       } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START
+                           && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) {
+                               memcpy((void *)(addr), &data, sizeof(data));
                                copied = sizeof(data);
-                       } else
-#endif
-                       if (addr + add >= FIXED_CODE_START
-                           && addr + add + sizeof(data) <= FIXED_CODE_END) {
-                               memcpy((void *)(addr + add), &data, sizeof(data));
+
+                       } else if (addr >= FIXED_CODE_START
+                           && addr + sizeof(data) <= FIXED_CODE_END) {
+                               memcpy((void *)(addr), &data, sizeof(data));
                                copied = sizeof(data);
+
                        } else
-                               copied = access_process_vm(child, addr + add, &data,
+                               copied = access_process_vm(child, addr, &data,
                                                           sizeof(data), 1);
+
                        pr_debug("ptrace: copied size %d\n", copied);
                        if (copied != sizeof(data))
                                break;
@@ -351,29 +350,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                break;
 
        case PTRACE_SYSCALL:    /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT:
-               {               /* restart after signal. */
-                       long tmp;
+       case PTRACE_CONT:       /* restart after signal. */
+               pr_debug("ptrace: syscall/cont\n");
 
-                       pr_debug("ptrace_cont\n");
-
-                       ret = -EIO;
-                       if (!valid_signal(data))
-                               break;
-                       if (request == PTRACE_SYSCALL)
-                               set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-                       else
-                               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-                       child->exit_code = data;
-                       /* make sure the single step bit is not set. */
-                       tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
-                       put_reg(child, PT_SYSCFG, tmp);
-                       pr_debug("before wake_up_process\n");
-                       wake_up_process(child);
-                       ret = 0;
+               ret = -EIO;
+               if (!valid_signal(data))
                        break;
-               }
+               if (request == PTRACE_SYSCALL)
+                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               else
+                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               child->exit_code = data;
+               ptrace_disable(child);
+               pr_debug("ptrace: before wake_up_process\n");
+               wake_up_process(child);
+               ret = 0;
+               break;
 
        /*
         * make the child exit.  Best I can do is send it a sigkill.
@@ -381,55 +373,37 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
         * exit.
         */
        case PTRACE_KILL:
-               {
-                       long tmp;
-                       ret = 0;
-                       if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
-                               break;
-                       child->exit_code = SIGKILL;
-                       /* make sure the single step bit is not set. */
-                       tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
-                       put_reg(child, PT_SYSCFG, tmp);
-                       wake_up_process(child);
+               ret = 0;
+               if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
                        break;
-               }
-
-       case PTRACE_SINGLESTEP:
-               {               /* set the trap flag. */
-                       long tmp;
-
-                       pr_debug("single step\n");
-                       ret = -EIO;
-                       if (!valid_signal(data))
-                               break;
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-                       tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS);
-                       put_reg(child, PT_SYSCFG, tmp);
+               child->exit_code = SIGKILL;
+               ptrace_disable(child);
+               wake_up_process(child);
+               break;
 
-                       child->exit_code = data;
-                       /* give it a chance to run. */
-                       wake_up_process(child);
-                       ret = 0;
+       case PTRACE_SINGLESTEP: /* set the trap flag. */
+               pr_debug("ptrace: single step\n");
+               ret = -EIO;
+               if (!valid_signal(data))
                        break;
-               }
+               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               ptrace_enable(child);
+               child->exit_code = data;
+               wake_up_process(child);
+               ret = 0;
+               break;
 
        case PTRACE_GETREGS:
-               {
-
-                       /* Get all gp regs from the child. */
-                       ret = ptrace_getregs(child, datap);
-                       break;
-               }
+               /* Get all gp regs from the child. */
+               ret = ptrace_getregs(child, datap);
+               break;
 
        case PTRACE_SETREGS:
-               {
-                       printk(KERN_NOTICE
-                              "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n");
-                       /* Set all gp regs in the child. */
-                       ret = 0;
-                       break;
-               }
+               printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n");
+               /* Set all gp regs in the child. */
+               ret = 0;
+               break;
+
        default:
                ret = ptrace_request(child, request, addr, data);
                break;
@@ -440,7 +414,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
 asmlinkage void syscall_trace(void)
 {
-
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
                return;
 
index 367e2dc0988195a9ed6d41e5acda35a00cc088f4..ae97ca407b0dfe0a2e17809e0d2d542c65376677 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/bfin-global.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
+#include <asm/bfrom.h>
 
 /* A system soft reset makes external memory unusable so force
  * this function into L1.  We use the compiler ssync here rather
@@ -20,7 +21,7 @@
  * the core reset.
  */
 __attribute__((l1_text))
-void bfin_reset(void)
+static void bfin_reset(void)
 {
        /* Wait for completion of "system" events such as cache line
         * line fills so that we avoid infinite stalls later on as
@@ -34,15 +35,15 @@ void bfin_reset(void)
                bfin_write_SWRST(0x7);
 
                /* Due to the way reset is handled in the hardware, we need
-                * to delay for 7 SCLKS.  The only reliable way to do this is
-                * to calculate the CCLK/SCLK ratio and multiply 7.  For now,
+                * to delay for 10 SCLKS.  The only reliable way to do this is
+                * to calculate the CCLK/SCLK ratio and multiply 10.  For now,
                 * we'll assume worse case which is a 1:15 ratio.
                 */
                asm(
                        "LSETUP (1f, 1f) LC0 = %0\n"
                        "1: nop;"
                        :
-                       : "a" (15 * 7)
+                       : "a" (15 * 10)
                        : "LC0", "LB0", "LT0"
                );
 
@@ -74,7 +75,14 @@ void machine_restart(char *cmd)
 {
        native_machine_restart(cmd);
        local_irq_disable();
-       bfin_reset();
+       if (ANOMALY_05000353 || ANOMALY_05000386)
+               bfin_reset();
+       else
+               /* the bootrom checks to see how it was reset and will
+                * automatically perform a software reset for us when
+                * it starts executing boot
+                */
+               asm("raise 1;");
 }
 
 __attribute__((weak))
index 7a82d10b4ebf70aff56268ab83ff77966dbe69cb..7f35d1046cd87d1062df7520b577b72eac4bcdf7 100644 (file)
@@ -42,6 +42,7 @@ EXPORT_SYMBOL(memory_start);
 EXPORT_SYMBOL(memory_end);
 EXPORT_SYMBOL(physical_mem_end);
 EXPORT_SYMBOL(_ramend);
+EXPORT_SYMBOL(reserved_mem_dcache_on);
 
 #ifdef CONFIG_MTD_UCLINUX
 unsigned long memory_mtd_end, memory_mtd_start, mtd_size;
@@ -52,7 +53,8 @@ EXPORT_SYMBOL(mtd_size);
 #endif
 
 char __initdata command_line[COMMAND_LINE_SIZE];
-unsigned int __initdata *__retx;
+void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat,
+       *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr;
 
 /* boot memmap, for parsing "memmap=" */
 #define BFIN_MEMMAP_MAX                128 /* number of entries in bfin_memmap */
@@ -77,10 +79,10 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata;
 static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata;
 static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata;
 
-void __init bf53x_cache_init(void)
+void __init bfin_cache_init(void)
 {
 #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
-       generate_cpl_tables();
+       generate_cplb_tables();
 #endif
 
 #ifdef CONFIG_BFIN_ICACHE
@@ -100,7 +102,7 @@ void __init bf53x_cache_init(void)
 #endif
 }
 
-void __init bf53x_relocate_l1_mem(void)
+void __init bfin_relocate_l1_mem(void)
 {
        unsigned long l1_code_length;
        unsigned long l1_data_a_length;
@@ -410,7 +412,7 @@ static __init void parse_cmdline_early(char *cmdline_p)
  *  [_rambase, _ramstart]:             kernel image
  *  [memory_start, memory_end]:                dynamic memory managed by kernel
  *  [memory_end, _ramend]:             reserved memory
- *     [meory_mtd_start(memory_end),
+ *     [memory_mtd_start(memory_end),
  *             memory_mtd_start + mtd_size]:   rootfs (if any)
  *     [_ramend - DMA_UNCACHED_REGION,
  *             _ramend]:                       uncached DMA region
@@ -782,16 +784,25 @@ void __init setup_arch(char **cmdline_p)
 
        _bfin_swrst = bfin_read_SWRST();
 
-       /* If we double fault, reset the system - otherwise we hang forever */
-       bfin_write_SWRST(DOUBLE_FAULT);
+#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
+       bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT);
+#endif
+#ifdef CONFIG_DEBUG_DOUBLEFAULT_RESET
+       bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT);
+#endif
 
-       if (_bfin_swrst & RESET_DOUBLE)
-               /*
-                * don't decode the address, since you don't know if this
-                * kernel's symbol map is the same as the crashing kernel
-                */
-               printk(KERN_INFO "Recovering from Double Fault event at %pF\n", __retx);
-       else if (_bfin_swrst & RESET_WDOG)
+       if (_bfin_swrst & RESET_DOUBLE) {
+               printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n");
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+               /* We assume the crashing kernel, and the current symbol table match */
+               printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
+                       (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx);
+               printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr);
+               printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr);
+#endif
+               printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
+                       init_retx);
+       } else if (_bfin_swrst & RESET_WDOG)
                printk(KERN_INFO "Recovering from Watchdog event\n");
        else if (_bfin_swrst & RESET_SOFTWARE)
                printk(KERN_NOTICE "Reset caused by Software reset\n");
@@ -803,17 +814,24 @@ void __init setup_arch(char **cmdline_p)
                printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU);
        else
                printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
-       if (bfin_revid() != bfin_compiled_revid()) {
-               if (bfin_compiled_revid() == -1)
-                       printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
-                              bfin_revid());
-               else if (bfin_compiled_revid() != 0xffff)
-                       printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
-                              bfin_compiled_revid(), bfin_revid());
+
+       if (unlikely(CPUID != bfin_cpuid()))
+               printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
+                       CPU, bfin_cpuid(), bfin_revid());
+       else {
+               if (bfin_revid() != bfin_compiled_revid()) {
+                       if (bfin_compiled_revid() == -1)
+                               printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
+                                      bfin_revid());
+                       else if (bfin_compiled_revid() != 0xffff)
+                               printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
+                                      bfin_compiled_revid(), bfin_revid());
+               }
+               if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
+                       printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
+                              CPU, bfin_revid());
        }
-       if (bfin_revid() < SUPPORTED_REVID)
-               printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
-                      CPU, bfin_revid());
+
        printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
 
        printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
@@ -850,7 +868,7 @@ void __init setup_arch(char **cmdline_p)
                != SAFE_USER_INSTRUCTION - FIXED_CODE_START);
 
        init_exception_vectors();
-       bf53x_cache_init();
+       bfin_cache_init();
 }
 
 static int __init topology_init(void)
@@ -986,13 +1004,18 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        }
 
        seq_printf(m, "processor\t: %d\n"
-               "vendor_id\t: %s\n"
-               "cpu family\t: 0x%x\n"
-               "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
+               "vendor_id\t: %s\n",
+               *(unsigned int *)v,
+               vendor);
+
+       if (CPUID == bfin_cpuid())
+               seq_printf(m, "cpu family\t: 0x%04x\n", CPUID);
+       else
+               seq_printf(m, "cpu family\t: Compiled for:0x%04x, running on:0x%04x\n",
+                       CPUID, bfin_cpuid());
+
+       seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
                "stepping\t: %d\n",
-               0,
-               vendor,
-               (bfin_read_CHIPID() & CHIPID_FAMILY),
                cpu, cclk/1000000, sclk/1000000,
 #ifdef CONFIG_MPU
                "mpu on",
@@ -1038,7 +1061,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
                dcache_size = 0;
 
-       if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB))
+       if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB))
                icache_size = 0;
 
        seq_printf(m, "cache size\t: %d KB(L1 icache) "
@@ -1127,12 +1150,18 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-       return *pos < NR_CPUS ? ((void *)0x12345678) : NULL;
+       if (*pos == 0)
+               *pos = first_cpu(cpu_online_map);
+       if (*pos >= num_online_cpus())
+               return NULL;
+
+       return pos;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       ++*pos;
+       *pos = next_cpu(*pos, cpu_online_map);
+
        return c_start(m, pos);
 }
 
index 9a9d5083acfdde5e2cae73830c79b9dcdf478030..1aa2c788e228399f3ab00912fc50296e052cbf71 100644 (file)
 #include <linux/fs.h>
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
+#include <asm/cplb.h>
 #include <asm/blackfin.h>
 #include <asm/irq_handler.h>
 #include <linux/irq.h>
 #include <asm/trace.h>
 #include <asm/fixed_code.h>
-#include <asm/dma.h>
 
 #ifdef CONFIG_KGDB
-# include <linux/debugger.h>
 # include <linux/kgdb.h>
 
 # define CHK_DEBUGGER_TRAP() \
        do { \
-               CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \
+               kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
        } while (0)
 # define CHK_DEBUGGER_TRAP_MAYBE() \
        do { \
 # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
 #endif
 
+
+#ifdef CONFIG_VERBOSE_DEBUG
+#define verbose_printk(fmt, arg...) \
+       printk(fmt, ##arg)
+#else
+#define verbose_printk(fmt, arg...) \
+       ({ if (0) printk(fmt, ##arg); 0; })
+#endif
+
 /* Initiate the event table handler */
 void __init trap_init(void)
 {
@@ -67,10 +75,19 @@ void __init trap_init(void)
        CSYNC();
 }
 
-unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr;
+/*
+ * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
+ * values across the transition from exception to IRQ5.
+ * We put these in L1, so they are going to be in a valid
+ * location during exception context
+ */
+__attribute__((l1_data))
+unsigned long saved_retx, saved_seqstat,
+       saved_icplb_fault_addr, saved_dcplb_fault_addr;
 
 static void decode_address(char *buf, unsigned long address)
 {
+#ifdef CONFIG_DEBUG_VERBOSE
        struct vm_list_struct *vml;
        struct task_struct *p;
        struct mm_struct *mm;
@@ -178,16 +195,39 @@ static void decode_address(char *buf, unsigned long address)
 
 done:
        write_unlock_irqrestore(&tasklist_lock, flags);
+#else
+       sprintf(buf, " ");
+#endif
 }
 
 asmlinkage void double_fault_c(struct pt_regs *fp)
 {
        console_verbose();
        oops_in_progress = 1;
+#ifdef CONFIG_DEBUG_VERBOSE
        printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
-       dump_bfin_process(fp);
-       dump_bfin_mem(fp);
-       show_regs(fp);
+#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
+       if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
+               char buf[150];
+               decode_address(buf, saved_retx);
+               printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
+                       (int)saved_seqstat & SEQSTAT_EXCAUSE, buf);
+               decode_address(buf, saved_dcplb_fault_addr);
+               printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
+               decode_address(buf, saved_icplb_fault_addr);
+               printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);
+
+               decode_address(buf, fp->retx);
+               printk(KERN_NOTICE "The instruction at %s caused a double exception\n",
+                       buf);
+       } else
+#endif
+       {
+               dump_bfin_process(fp);
+               dump_bfin_mem(fp);
+               show_regs(fp);
+       }
+#endif
        panic("Double Fault - unrecoverable event\n");
 
 }
@@ -259,34 +299,42 @@ asmlinkage void trap_c(struct pt_regs *fp)
                        return;
                else
                        break;
+       /* 0x03 - User Defined, userspace stack overflow */
+       case VEC_EXCPT03:
+               info.si_code = SEGV_STACKFLOW;
+               sig = SIGSEGV;
+               verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
+               break;
+       /* 0x02 - KGDB initial connection and break signal trap */
+       case VEC_EXCPT02:
 #ifdef CONFIG_KGDB
-       case VEC_EXCPT02 :               /* gdb connection */
                info.si_code = TRAP_ILLTRAP;
                sig = SIGTRAP;
                CHK_DEBUGGER_TRAP();
                return;
-#else
-       /* 0x02 - User Defined, Caught by default */
 #endif
-       /* 0x03 - User Defined, userspace stack overflow */
-       case VEC_EXCPT03:
-               info.si_code = SEGV_STACKFLOW;
-               sig = SIGSEGV;
-               printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+       /* 0x04 - User Defined */
+       /* 0x05 - User Defined */
+       /* 0x06 - User Defined */
+       /* 0x07 - User Defined */
+       /* 0x08 - User Defined */
+       /* 0x09 - User Defined */
+       /* 0x0A - User Defined */
+       /* 0x0B - User Defined */
+       /* 0x0C - User Defined */
+       /* 0x0D - User Defined */
+       /* 0x0E - User Defined */
+       /* 0x0F - User Defined */
+       /* If we got here, it is most likely that someone was trying to use a
+        * custom exception handler, and it is not actually installed properly
+        */
+       case VEC_EXCPT04 ... VEC_EXCPT15:
+               info.si_code = ILL_ILLPARAOP;
+               sig = SIGILL;
+               verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
-       /* 0x04 - User Defined, Caught by default */
-       /* 0x05 - User Defined, Caught by default */
-       /* 0x06 - User Defined, Caught by default */
-       /* 0x07 - User Defined, Caught by default */
-       /* 0x08 - User Defined, Caught by default */
-       /* 0x09 - User Defined, Caught by default */
-       /* 0x0A - User Defined, Caught by default */
-       /* 0x0B - User Defined, Caught by default */
-       /* 0x0C - User Defined, Caught by default */
-       /* 0x0D - User Defined, Caught by default */
-       /* 0x0E - User Defined, Caught by default */
-       /* 0x0F - User Defined, Caught by default */
        /* 0x10 HW Single step, handled here */
        case VEC_STEP:
                info.si_code = TRAP_STEP;
@@ -301,8 +349,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
        case VEC_OVFLOW:
                info.si_code = TRAP_TRACEFLOW;
                sig = SIGTRAP;
-               printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x12 - Reserved, Caught by default */
        /* 0x13 - Reserved, Caught by default */
@@ -323,44 +371,43 @@ asmlinkage void trap_c(struct pt_regs *fp)
        case VEC_UNDEF_I:
                info.si_code = ILL_ILLOPC;
                sig = SIGILL;
-               printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x22 - Illegal Instruction Combination, handled here */
        case VEC_ILGAL_I:
                info.si_code = ILL_ILLPARAOP;
                sig = SIGILL;
-               printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x23 - Data CPLB protection violation, handled here */
        case VEC_CPLB_VL:
                info.si_code = ILL_CPLB_VI;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x24 - Data access misaligned, handled here */
        case VEC_MISALI_D:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x25 - Unrecoverable Event, handled here */
        case VEC_UNCOV:
                info.si_code = ILL_ILLEXCPT;
                sig = SIGILL;
-               printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
                error case is handled here */
        case VEC_CPLB_M:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
                break;
        /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
        case VEC_CPLB_MHIT:
@@ -368,11 +415,11 @@ asmlinkage void trap_c(struct pt_regs *fp)
                sig = SIGSEGV;
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
                if (saved_dcplb_fault_addr < FIXED_CODE_START)
-                       printk(KERN_NOTICE "NULL pointer access\n");
+                       verbose_printk(KERN_NOTICE "NULL pointer access\n");
                else
 #endif
-                       printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+                       verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x28 - Emulation Watchpoint, handled here */
        case VEC_WATCH:
@@ -390,8 +437,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
        case VEC_ISTRU_VL:      /* ADSP-BF535 only (MH) */
                info.si_code = BUS_OPFETCH;
                sig = SIGBUS;
-               printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
 #else
        /* 0x29 - Reserved, Caught by default */
@@ -400,22 +447,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
        case VEC_MISALI_I:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2B - Instruction CPLB protection violation, handled here */
        case VEC_CPLB_I_VL:
                info.si_code = ILL_CPLB_VI;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
        case VEC_CPLB_I_M:
                info.si_code = ILL_CPLB_MISS;
                sig = SIGBUS;
-               printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
                break;
        /* 0x2D - Instruction CPLB Multiple Hits, handled here */
        case VEC_CPLB_I_MHIT:
@@ -423,18 +469,18 @@ asmlinkage void trap_c(struct pt_regs *fp)
                sig = SIGSEGV;
 #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
                if (saved_icplb_fault_addr < FIXED_CODE_START)
-                       printk(KERN_NOTICE "Jump to NULL address\n");
+                       verbose_printk(KERN_NOTICE "Jump to NULL address\n");
                else
 #endif
-                       printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+                       verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2E - Illegal use of Supervisor Resource, handled here */
        case VEC_ILL_RES:
                info.si_code = ILL_PRVOPC;
                sig = SIGILL;
-               printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2F - Reserved, Caught by default */
        /* 0x30 - Reserved, Caught by default */
@@ -461,17 +507,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
                case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
                        info.si_code = BUS_ADRALN;
                        sig = SIGBUS;
-                       printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
+                       verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
                        break;
                /* External Memory Addressing Error */
                case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
                        info.si_code = BUS_ADRERR;
                        sig = SIGBUS;
-                       printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
+                       verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
                        break;
                /* Performance Monitor Overflow */
                case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
-                       printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
+                       verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
                        break;
                /* RAISE 5 instruction */
                case (SEQSTAT_HWERRCAUSE_RAISE_5):
@@ -481,21 +527,25 @@ asmlinkage void trap_c(struct pt_regs *fp)
                        printk(KERN_NOTICE HWC_default(KERN_NOTICE));
                        break;
                }
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
+       /*
+        * We should be handling all known exception types above,
+        * if we get here we hit a reserved one, so panic
+        */
        default:
-               info.si_code = TRAP_ILLTRAP;
-               sig = SIGTRAP;
-               printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
+               oops_in_progress = 1;
+               info.si_code = ILL_ILLPARAOP;
+               sig = SIGILL;
+               verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
                        (fp->seqstat & SEQSTAT_EXCAUSE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        }
 
        BUG_ON(sig == 0);
 
        if (sig != SIGTRAP) {
-               unsigned long *stack;
                dump_bfin_process(fp);
                dump_bfin_mem(fp);
                show_regs(fp);
@@ -503,7 +553,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
                /* Print out the trace buffer if it makes sense */
 #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
                if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
-                       printk(KERN_NOTICE "No trace since you do not have "
+                       verbose_printk(KERN_NOTICE "No trace since you do not have "
                                "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
                                KERN_NOTICE "\n");
                else
@@ -512,20 +562,22 @@ asmlinkage void trap_c(struct pt_regs *fp)
 
                if (oops_in_progress) {
                        /* Dump the current kernel stack */
-                       printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
+                       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
                        show_stack(current, NULL);
-
                        print_modules();
 #ifndef CONFIG_ACCESS_CHECK
-                       printk(KERN_EMERG "Please turn on "
+                       verbose_printk(KERN_EMERG "Please turn on "
                               "CONFIG_ACCESS_CHECK\n");
 #endif
                        panic("Kernel exception");
                } else {
+#ifdef CONFIG_VERBOSE_DEBUG
+                       unsigned long *stack;
                        /* Dump the user space stack */
                        stack = (unsigned long *)rdusp();
-                       printk(KERN_NOTICE "Userspace Stack\n");
+                       verbose_printk(KERN_NOTICE "Userspace Stack\n");
                        show_stack(NULL, stack);
+#endif
                }
        }
 
@@ -546,7 +598,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
  * Similar to get_user, do some address checking, then dereference
  * Return true on sucess, false on bad address
  */
-bool get_instruction(unsigned short *val, unsigned short *address)
+static bool get_instruction(unsigned short *val, unsigned short *address)
 {
 
        unsigned long addr;
@@ -592,7 +644,7 @@ bool get_instruction(unsigned short *val, unsigned short *address)
 
 #if L1_CODE_LENGTH != 0
        if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
-               dma_memcpy(val, address, 2);
+               isram_memcpy(val, address, 2);
                return true;
        }
 #endif
@@ -607,45 +659,48 @@ bool get_instruction(unsigned short *val, unsigned short *address)
  * These are the normal instructions which cause change of flow, which
  * would be at the source of the trace buffer
  */
-void decode_instruction(unsigned short *address)
+#ifdef CONFIG_DEBUG_VERBOSE
+static void decode_instruction(unsigned short *address)
 {
        unsigned short opcode;
 
        if (get_instruction(&opcode, address)) {
                if (opcode == 0x0010)
-                       printk("RTS");
+                       verbose_printk("RTS");
                else if (opcode == 0x0011)
-                       printk("RTI");
+                       verbose_printk("RTI");
                else if (opcode == 0x0012)
-                       printk("RTX");
+                       verbose_printk("RTX");
                else if (opcode >= 0x0050 && opcode <= 0x0057)
-                       printk("JUMP (P%i)", opcode & 7);
+                       verbose_printk("JUMP (P%i)", opcode & 7);
                else if (opcode >= 0x0060 && opcode <= 0x0067)
-                       printk("CALL (P%i)", opcode & 7);
+                       verbose_printk("CALL (P%i)", opcode & 7);
                else if (opcode >= 0x0070 && opcode <= 0x0077)
-                       printk("CALL (PC+P%i)", opcode & 7);
+                       verbose_printk("CALL (PC+P%i)", opcode & 7);
                else if (opcode >= 0x0080 && opcode <= 0x0087)
-                       printk("JUMP (PC+P%i)", opcode & 7);
+                       verbose_printk("JUMP (PC+P%i)", opcode & 7);
                else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
-                       printk("IF !CC JUMP");
+                       verbose_printk("IF !CC JUMP");
                else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
-                       printk("IF CC JUMP");
+                       verbose_printk("IF CC JUMP");
                else if (opcode >= 0x2000 && opcode <= 0x2fff)
-                       printk("JUMP.S");
+                       verbose_printk("JUMP.S");
                else if (opcode >= 0xe080 && opcode <= 0xe0ff)
-                       printk("LSETUP");
+                       verbose_printk("LSETUP");
                else if (opcode >= 0xe200 && opcode <= 0xe2ff)
-                       printk("JUMP.L");
+                       verbose_printk("JUMP.L");
                else if (opcode >= 0xe300 && opcode <= 0xe3ff)
-                       printk("CALL pcrel");
+                       verbose_printk("CALL pcrel");
                else
-                       printk("0x%04x", opcode);
+                       verbose_printk("0x%04x", opcode);
        }
 
 }
+#endif
 
 void dump_bfin_trace_buffer(void)
 {
+#ifdef CONFIG_DEBUG_VERBOSE
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
        int tflags, i = 0;
        char buf[150];
@@ -701,6 +756,7 @@ void dump_bfin_trace_buffer(void)
 
        trace_buffer_restore(tflags);
 #endif
+#endif
 }
 EXPORT_SYMBOL(dump_bfin_trace_buffer);
 
@@ -708,7 +764,7 @@ EXPORT_SYMBOL(dump_bfin_trace_buffer);
  * Checks to see if the address pointed to is either a
  * 16-bit CALL instruction, or a 32-bit CALL instruction
  */
-bool is_bfin_call(unsigned short *addr)
+static bool is_bfin_call(unsigned short *addr)
 {
        unsigned short opcode = 0, *ins_addr;
        ins_addr = (unsigned short *)addr;
@@ -730,8 +786,10 @@ bool is_bfin_call(unsigned short *addr)
        return false;
 
 }
+
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
+#ifdef CONFIG_PRINTK
        unsigned int *addr, *endstack, *fp = 0, *frame;
        unsigned short *ins_addr;
        char buf[150];
@@ -756,8 +814,10 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        } else
                endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
 
+       printk(KERN_NOTICE "Stack info:\n");
        decode_address(buf, (unsigned int)stack);
-       printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
+       printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
+
        addr = (unsigned int *)((unsigned int)stack & ~0x3F);
 
        /* First thing is to look for a frame pointer */
@@ -848,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (!j)
                        printk("\n");
        }
-
+#endif
 }
 
 void dump_stack(void)
@@ -866,38 +926,39 @@ EXPORT_SYMBOL(dump_stack);
 
 void dump_bfin_process(struct pt_regs *fp)
 {
+#ifdef CONFIG_DEBUG_VERBOSE
        /* We should be able to look at fp->ipend, but we don't push it on the
         * stack all the time, so do this until we fix that */
        unsigned int context = bfin_read_IPEND();
 
        if (oops_in_progress)
-               printk(KERN_EMERG "Kernel OOPS in progress\n");
+               verbose_printk(KERN_EMERG "Kernel OOPS in progress\n");
 
        if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
-               printk(KERN_NOTICE "HW Error context\n");
+               verbose_printk(KERN_NOTICE "HW Error context\n");
        else if (context & 0x0020)
-               printk(KERN_NOTICE "Deferred Exception context\n");
+               verbose_printk(KERN_NOTICE "Deferred Exception context\n");
        else if (context & 0x3FC0)
-               printk(KERN_NOTICE "Interrupt context\n");
+               verbose_printk(KERN_NOTICE "Interrupt context\n");
        else if (context & 0x4000)
-               printk(KERN_NOTICE "Deferred Interrupt context\n");
+               verbose_printk(KERN_NOTICE "Deferred Interrupt context\n");
        else if (context & 0x8000)
-               printk(KERN_NOTICE "Kernel process context\n");
+               verbose_printk(KERN_NOTICE "Kernel process context\n");
 
        /* Because we are crashing, and pointers could be bad, we check things
         * pretty closely before we use them
         */
        if ((unsigned long)current >= FIXED_CODE_START &&
            !((unsigned long)current & 0x3) && current->pid) {
-               printk(KERN_NOTICE "CURRENT PROCESS:\n");
+               verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
                if (current->comm >= (char *)FIXED_CODE_START)
-                       printk(KERN_NOTICE "COMM=%s PID=%d\n",
+                       verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
                                current->comm, current->pid);
                else
-                       printk(KERN_NOTICE "COMM= invalid\n");
+                       verbose_printk(KERN_NOTICE "COMM= invalid\n");
 
                if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
-                       printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
+                       verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
                                KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
                                KERN_NOTICE "\n",
                                (void *)current->mm->start_code,
@@ -908,38 +969,40 @@ void dump_bfin_process(struct pt_regs *fp)
                                (void *)current->mm->brk,
                                (void *)current->mm->start_stack);
                else
-                       printk(KERN_NOTICE "invalid mm\n");
+                       verbose_printk(KERN_NOTICE "invalid mm\n");
        } else
-               printk(KERN_NOTICE "\n" KERN_NOTICE
+               verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
                     "No Valid process in current context\n");
+#endif
 }
 
 void dump_bfin_mem(struct pt_regs *fp)
 {
+#ifdef CONFIG_DEBUG_VERBOSE
        unsigned short *addr, *erraddr, val = 0, err = 0;
        char sti = 0, buf[6];
 
        erraddr = (void *)fp->pc;
 
-       printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
+       verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
 
        for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
             addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
             addr++) {
                if (!((unsigned long)addr & 0xF))
-                       printk("\n" KERN_NOTICE "0x%p: ", addr);
+                       verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
 
-               if (get_instruction(&val, addr)) {
+               if (!get_instruction(&val, addr)) {
                                val = 0;
                                sprintf(buf, "????");
                } else
                        sprintf(buf, "%04x", val);
 
                if (addr == erraddr) {
-                       printk("[%s]", buf);
+                       verbose_printk("[%s]", buf);
                        err = val;
                } else
-                       printk(" %s ", buf);
+                       verbose_printk(" %s ", buf);
 
                /* Do any previous instructions turn on interrupts? */
                if (addr <= erraddr &&                          /* in the past */
@@ -948,14 +1011,14 @@ void dump_bfin_mem(struct pt_regs *fp)
                        sti = 1;
        }
 
-       printk("\n");
+       verbose_printk("\n");
 
        /* Hardware error interrupts can be deferred */
        if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
            oops_in_progress)){
-               printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
+               verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
 #ifndef CONFIG_DEBUG_HWERR
-               printk(KERN_NOTICE "The remaining message may be meaningless\n"
+               verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
                        KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
                         " better idea where it came from\n");
 #else
@@ -969,34 +1032,47 @@ void dump_bfin_mem(struct pt_regs *fp)
                        /* And the last RETI points to the current userspace context */
                        if ((fp + 1)->pc >= current->mm->start_code &&
                            (fp + 1)->pc <= current->mm->end_code) {
-                               printk(KERN_NOTICE "It might be better to look around here : \n");
-                               printk(KERN_NOTICE "-------------------------------------------\n");
+                               verbose_printk(KERN_NOTICE "It might be better to look around here : \n");
+                               verbose_printk(KERN_NOTICE "-------------------------------------------\n");
                                show_regs(fp + 1);
-                               printk(KERN_NOTICE "-------------------------------------------\n");
+                               verbose_printk(KERN_NOTICE "-------------------------------------------\n");
                        }
                }
 #endif
        }
+#endif
 }
 
 void show_regs(struct pt_regs *fp)
 {
+#ifdef CONFIG_DEBUG_VERBOSE
        char buf [150];
        struct irqaction *action;
        unsigned int i;
        unsigned long flags;
 
-       printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
-       printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
+       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
+       verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
                (long)fp->seqstat, fp->ipend, fp->syscfg);
-       printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
-               (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
-       printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
+       if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
+               verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
+                       (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
+#ifdef EBIU_ERRMST
+               /* If the error was from the EBIU, print it out */
+               if (bfin_read_EBIU_ERRMST() & CORE_ERROR) {
+                       verbose_printk(KERN_NOTICE "  EBIU Error Reason  : 0x%04x\n",
+                               bfin_read_EBIU_ERRMST());
+                       verbose_printk(KERN_NOTICE "  EBIU Error Address : 0x%08x\n",
+                               bfin_read_EBIU_ERRADD());
+               }
+#endif
+       }
+       verbose_printk(KERN_NOTICE "  EXCAUSE   : 0x%lx\n",
                fp->seqstat & SEQSTAT_EXCAUSE);
        for (i = 6; i <= 15 ; i++) {
                if (fp->ipend & (1 << i)) {
                        decode_address(buf, bfin_read32(EVT0 + 4*i));
-                       printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
+                       verbose_printk(KERN_NOTICE "  physical IVG%i asserted : %s\n", i, buf);
                }
        }
 
@@ -1009,64 +1085,65 @@ void show_regs(struct pt_regs *fp)
                                goto unlock;
 
                        decode_address(buf, (unsigned int)action->handler);
-                       printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
+                       verbose_printk(KERN_NOTICE "  logical irq %3d mapped  : %s", i, buf);
                        for (action = action->next; action; action = action->next) {
                                decode_address(buf, (unsigned int)action->handler);
-                               printk(", %s", buf);
+                               verbose_printk(", %s", buf);
                        }
-                       printk("\n");
+                       verbose_printk("\n");
 unlock:
                        spin_unlock_irqrestore(&irq_desc[i].lock, flags);
                }
        }
 
        decode_address(buf, fp->rete);
-       printk(KERN_NOTICE " RETE: %s\n", buf);
+       verbose_printk(KERN_NOTICE " RETE: %s\n", buf);
        decode_address(buf, fp->retn);
-       printk(KERN_NOTICE " RETN: %s\n", buf);
+       verbose_printk(KERN_NOTICE " RETN: %s\n", buf);
        decode_address(buf, fp->retx);
-       printk(KERN_NOTICE " RETX: %s\n", buf);
+       verbose_printk(KERN_NOTICE " RETX: %s\n", buf);
        decode_address(buf, fp->rets);
-       printk(KERN_NOTICE " RETS: %s\n", buf);
+       verbose_printk(KERN_NOTICE " RETS: %s\n", buf);
        decode_address(buf, fp->pc);
-       printk(KERN_NOTICE " PC  : %s\n", buf);
+       verbose_printk(KERN_NOTICE " PC  : %s\n", buf);
 
        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) &&
            (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
                decode_address(buf, saved_dcplb_fault_addr);
-               printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
+               verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
                decode_address(buf, saved_icplb_fault_addr);
-               printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
+               verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
        }
 
-       printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
-       printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
+       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
+       verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
                fp->r0, fp->r1, fp->r2, fp->r3);
-       printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
+       verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
                fp->r4, fp->r5, fp->r6, fp->r7);
-       printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
+       verbose_printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",
                fp->p0, fp->p1, fp->p2, fp->p3);
-       printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
+       verbose_printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",
                fp->p4, fp->p5, fp->fp, (long)fp);
-       printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
+       verbose_printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",
                fp->lb0, fp->lt0, fp->lc0);
-       printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
+       verbose_printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",
                fp->lb1, fp->lt1, fp->lc1);
-       printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
+       verbose_printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",
                fp->b0, fp->l0, fp->m0, fp->i0);
-       printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
+       verbose_printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",
                fp->b1, fp->l1, fp->m1, fp->i1);
-       printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
+       verbose_printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",
                fp->b2, fp->l2, fp->m2, fp->i2);
-       printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
+       verbose_printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",
                fp->b3, fp->l3, fp->m3, fp->i3);
-       printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
+       verbose_printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",
                fp->a0w, fp->a0x, fp->a1w, fp->a1x);
 
-       printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
+       verbose_printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",
                rdusp(), fp->astat);
 
-       printk(KERN_NOTICE "\n");
+       verbose_printk(KERN_NOTICE "\n");
+#endif
 }
 
 #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1
index 8bf9e58f01480f3ae1530550933f36cdf3b33dc4..df224d04e1677bb5b7f4d0d0bf631e7797c3943f 100644 (file)
@@ -14,4 +14,9 @@ config BFIN527_BLUETECHNIX_CM
        help
          CM-BF527 support for EVAL- and DEV-Board.
 
+config BFIN526_EZBRD
+       bool "BF526-EZBRD"
+       help
+         BF526-EZBRD/EZKIT Lite board support.
+
 endchoice
index 7ba7d256bbb8601b6cf5da9136ff21e435753a81..eb6ed3362f9f413adc63bc698eaa82b00ecdf104 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_BFIN527_EZKIT)            += ezkit.o
 obj-$(CONFIG_BFIN527_BLUETECHNIX_CM)   += cm_bf527.o
+obj-$(CONFIG_BFIN526_EZBRD)            += ezbrd.o
index d22bc7773717411e200c1968e885413a0d74031f..9ea440bbb13de36ddc6f0059aaa92f7db9e8eb19 100644 (file)
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/sl811.h>
-#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
 #include <linux/usb/musb.h>
-#endif
-#include <asm/cplb.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -130,6 +127,16 @@ static struct resource musb_resources[] = {
        },
 };
 
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 0,
+       .dyn_fifo       = 0,
+       .soft_con       = 1,
+       .dma            = 1,
+       .num_eps        = 7,
+       .dma_channels   = 7,
+       .gpio_vrsel     = GPIO_PF11,
+};
+
 static struct musb_hdrc_platform_data musb_plat = {
 #if defined(CONFIG_USB_MUSB_OTG)
        .mode           = MUSB_OTG,
@@ -138,7 +145,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
 #endif
-       .multipoint     = 0,
+       .config         = &musb_config,
 };
 
 static u64 musb_dmamask = ~(u32)0;
@@ -201,7 +208,7 @@ static struct mtd_partition partition_info[] = {
        {
                .name = "linux kernel(nand)",
                .offset = 0,
-               .size = 4 * SIZE_1M,
+               .size = 4 * 1024 * 1024,
        },
        {
                .name = "file system(nand)",
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
new file mode 100644 (file)
index 0000000..36c87b6
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * File:         arch/blackfin/mach-bf527/boards/ezbrd.c
+ * Based on:     arch/blackfin/mach-bf537/boards/stamp.c
+ * Author:       Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2005 National ICT Australia (NICTA)
+ *               Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/usb/musb.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+#include <linux/spi/ad7877.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "BF526-EZBRD";
+
+/*
+ *  Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+static struct resource musb_resources[] = {
+       [0] = {
+               .start  = 0xffc03800,
+               .end    = 0xffc03cff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = { /* general IRQ */
+               .start  = IRQ_USB_INT0,
+               .end    = IRQ_USB_INT0,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+       [2] = { /* DMA IRQ */
+               .start  = IRQ_USB_DMA,
+               .end    = IRQ_USB_DMA,
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 0,
+       .dyn_fifo       = 0,
+       .soft_con       = 1,
+       .dma            = 1,
+       .num_eps        = 7,
+       .dma_channels   = 7,
+       .gpio_vrsel     = GPIO_PG13,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_USB_MUSB_OTG)
+       .mode           = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+       .mode           = MUSB_HOST,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+       .mode           = MUSB_PERIPHERAL,
+#endif
+       .config         = &musb_config,
+};
+
+static u64 musb_dmamask = ~(u32)0;
+
+static struct platform_device musb_device = {
+       .name           = "musb_hdrc",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = &musb_dmamask,
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &musb_plat,
+       },
+       .num_resources  = ARRAY_SIZE(musb_resources),
+       .resource       = musb_resources,
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ezbrd_partitions[] = {
+       {
+               .name       = "bootloader(nor)",
+               .size       = 0x40000,
+               .offset     = 0,
+       }, {
+               .name       = "linux kernel(nor)",
+               .size       = 0x1C0000,
+               .offset     = MTDPART_OFS_APPEND,
+       }, {
+               .name       = "file system(nor)",
+               .size       = MTDPART_SIZ_FULL,
+               .offset     = MTDPART_OFS_APPEND,
+       }
+};
+
+static struct physmap_flash_data ezbrd_flash_data = {
+       .width      = 2,
+       .parts      = ezbrd_partitions,
+       .nr_parts   = ARRAY_SIZE(ezbrd_partitions),
+};
+
+static struct resource ezbrd_flash_resource = {
+       .start = 0x20000000,
+       .end   = 0x203fffff,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ezbrd_flash_device = {
+       .name          = "physmap-flash",
+       .id            = 0,
+       .dev = {
+               .platform_data = &ezbrd_flash_data,
+       },
+       .num_resources = 1,
+       .resource      = &ezbrd_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+static struct mtd_partition partition_info[] = {
+       {
+               .name = "linux kernel(nand)",
+               .offset = 0,
+               .size = 4 * 1024 * 1024,
+       },
+       {
+               .name = "file system(nand)",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct bf5xx_nand_platform bf5xx_nand_platform = {
+       .page_size = NFC_PG_SIZE_256,
+       .data_width = NFC_NWIDTH_8,
+       .partitions = partition_info,
+       .nr_partitions = ARRAY_SIZE(partition_info),
+       .rd_dly = 3,
+       .wr_dly = 3,
+};
+
+static struct resource bf5xx_nand_resources[] = {
+       {
+               .start = NFC_CTL,
+               .end = NFC_DATA_RD + 2,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = CH_NFC,
+               .end = CH_NFC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bf5xx_nand_device = {
+       .name = "bf5xx-nand",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bf5xx_nand_resources),
+       .resource = bf5xx_nand_resources,
+       .dev = {
+               .platform_data = &bf5xx_nand_platform,
+       },
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+       .name = "rtc-bfin",
+       .id   = -1,
+};
+#endif
+
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mac_device = {
+       .name = "bfin_mac",
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+       {
+               .name = "bootloader(spi)",
+               .size = 0x00040000,
+               .offset = 0,
+               .mask_flags = MTD_CAP_ROM
+       }, {
+               .name = "linux kernel(spi)",
+               .size = MTDPART_SIZ_FULL,
+               .offset = MTDPART_OFS_APPEND,
+       }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+       .name = "m25p80",
+       .parts = bfin_spi_flash_partitions,
+       .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+       .type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+       .enable_dma = 0,         /* use dma transfer with this chip*/
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+       .enable_dma = 1,         /* use dma transfer with this chip*/
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+       .enable_dma = 1,
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+       .ctl_reg        = 0x4, /* send zero */
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+       .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+       .model                  = 7877,
+       .vref_delay_usecs       = 50,   /* internal, no capacitor */
+       .x_plate_ohms           = 419,
+       .y_plate_ohms           = 486,
+       .pressure_max           = 1000,
+       .pressure_min           = 0,
+       .stopacq_polarity       = 1,
+       .first_conversion_delay = 3,
+       .acquisition_time       = 1,
+       .averaging              = 1,
+       .pen_down_acc_interval  = 1,
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+        && defined(CONFIG_SND_SOC_WM8731_SPI)
+static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+       || defined(CONFIG_MTD_M25P80_MODULE)
+       {
+               /* the modalias must be the same as spi device driver name */
+               .modalias = "m25p80", /* Name of spi_driver for this device */
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+               .platform_data = &bfin_spi_flash_data,
+               .controller_data = &spi_flash_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+       || defined(CONFIG_SPI_ADC_BF533_MODULE)
+       {
+               .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+               .max_speed_hz = 6250000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0, /* Framework bus number */
+               .chip_select = 1, /* Framework chip select. */
+               .platform_data = NULL, /* No spi_driver specific config */
+               .controller_data = &spi_adc_chip_info,
+       },
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+       {
+               .modalias = "spi_mmc_dummy",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 0,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "spi_mmc",
+               .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+               .platform_data = NULL,
+               .controller_data = &spi_mmc_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_PBX)
+       {
+               .modalias = "fxs-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 8 - CONFIG_J11_JUMPER,
+               .controller_data = &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+       {
+               .modalias = "fxo-spi",
+               .max_speed_hz = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 8 - CONFIG_J19_JUMPER,
+               .controller_data = &spi_si3xxx_chip_info,
+               .mode = SPI_MODE_3,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+       {
+               .modalias               = "ad7877",
+               .platform_data          = &bfin_ad7877_ts_info,
+               .irq                    = IRQ_PF8,
+               .max_speed_hz   = 12500000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 0,
+               .chip_select  = 2,
+               .controller_data = &spi_ad7877_chip_info,
+       },
+#endif
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+        && defined(CONFIG_SND_SOC_WM8731_SPI)
+       {
+               .modalias       = "wm8731",
+               .max_speed_hz   = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num        = 0,
+               .chip_select    = 5,
+               .controller_data = &spi_wm8731_chip_info,
+               .mode = SPI_MODE_0,
+       },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+       {
+               .modalias = "spidev",
+               .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &spidev_chip_info,
+       },
+#endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+       {
+               .modalias = "bfin-lq035q1-spi",
+               .max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &lq035q1_spi_chip_info,
+               .mode = SPI_CPHA | SPI_CPOL,
+       },
+#endif
+};
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+       .num_chipselect = 8,
+       .enable_dma = 1,  /* master has the ability to do dma transfer */
+       .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+       [0] = {
+               .start = SPI0_REGBASE,
+               .end   = SPI0_REGBASE + 0xFF,
+               .flags = IORESOURCE_MEM,
+               },
+       [1] = {
+               .start = CH_SPI,
+               .end   = CH_SPI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_spi0_device = {
+       .name = "bfin-spi",
+       .id = 0, /* Bus number */
+       .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+       .resource = bfin_spi0_resource,
+       .dev = {
+               .platform_data = &bfin_spi0_info, /* Passed to driver */
+       },
+};
+#endif  /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+       .name = "bfin-uart",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(bfin_uart_resources),
+       .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+static struct resource bfin_sir_resources[] = {
+#ifdef CONFIG_BFIN_SIR0
+       {
+               .start = 0xFFC00400,
+               .end = 0xFFC004FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+#ifdef CONFIG_BFIN_SIR1
+       {
+               .start = 0xFFC02000,
+               .end = 0xFFC020FF,
+               .flags = IORESOURCE_MEM,
+       },
+#endif
+};
+
+static struct platform_device bfin_sir_device = {
+       .name = "bfin_sir",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_sir_resources),
+       .resource = bfin_sir_resources,
+};
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+       [0] = {
+               .start = TWI0_REGBASE,
+               .end   = TWI0_REGBASE,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_TWI,
+               .end   = IRQ_TWI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+       .name = "i2c-bfin-twi",
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+       .resource = bfin_twi0_resource,
+};
+#endif
+
+#ifdef CONFIG_I2C_BOARDINFO
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+       },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+       {
+               I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+               .irq = IRQ_PF8,
+       },
+#endif
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+       .name = "bfin-sport-uart",
+       .id = 1,
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+       {BTN_0, GPIO_PG0, 1, "gpio-keys: BTN0"},
+       {BTN_1, GPIO_PG13, 1, "gpio-keys: BTN1"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+       .buttons        = bfin_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+       .name      = "gpio-keys",
+       .dev = {
+               .platform_data = &bfin_gpio_keys_data,
+       },
+};
+#endif
+
+static struct resource bfin_gpios_resources = {
+       .start = 0,
+       .end   = MAX_BLACKFIN_GPIOS - 1,
+       .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+       .name = "simple-gpio",
+       .id = -1,
+       .num_resources = 1,
+       .resource = &bfin_gpios_resources,
+};
+
+static const unsigned int cclk_vlev_datasheet[] =
+{
+       VRPAIR(VLEV_100, 400000000),
+       VRPAIR(VLEV_105, 426000000),
+       VRPAIR(VLEV_110, 500000000),
+       VRPAIR(VLEV_115, 533000000),
+       VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+       .tuple_tab = cclk_vlev_datasheet,
+       .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+       .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+       .name = "bfin dpmc",
+       .dev = {
+               .platform_data = &bfin_dmpc_vreg_data,
+       },
+};
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+#include <asm/bfin-lq035q1.h>
+
+static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = {
+       .mode =         LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB,
+       .use_bl =       1,
+       .gpio_bl =      GPIO_PG12,
+};
+
+static struct resource bfin_lq035q1_resources[] = {
+       {
+               .start = IRQ_PPI_ERROR,
+               .end = IRQ_PPI_ERROR,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_lq035q1_device = {
+       .name           = "bfin-lq035q1",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bfin_lq035q1_resources),
+       .resource       = bfin_lq035q1_resources,
+       .dev            = {
+               .platform_data = &bfin_lq035q1_data,
+       },
+};
+#endif
+
+static struct platform_device *stamp_devices[] __initdata = {
+
+       &bfin_dpmc,
+
+#if defined(CONFIG_MTD_NAND_BF5XX) || defined(CONFIG_MTD_NAND_BF5XX_MODULE)
+       &bf5xx_nand_device,
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+       &rtc_device,
+#endif
+
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+       &musb_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+       &bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+       &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+       &bfin_lq035q1_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+       &bfin_sir_device,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+       &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+       &bfin_sport0_uart_device,
+       &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+       &bfin_device_gpiokeys,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+       &ezbrd_flash_device,
+#endif
+
+       &bfin_gpios_device,
+};
+
+static int __init stamp_init(void)
+{
+       printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+#ifdef CONFIG_I2C_BOARDINFO
+       i2c_register_board_info(0, bfin_i2c_board_info,
+                               ARRAY_SIZE(bfin_i2c_board_info));
+#endif
+
+       platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+       spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+       return 0;
+}
+
+arch_initcall(stamp_init);
+
+void native_machine_restart(char *cmd)
+{
+       /* workaround reboot hang when booting from SPI */
+       if ((bfin_read_SYSCR() & 0x7) == 0x3)
+               bfin_gpio_reset_spi0_ssel1();
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+       /* the MAC is stored in OTP memory page 0xDF */
+       u32 ret;
+       u64 otp_mac;
+       u32 (*otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)0xEF00001A;
+
+       ret = otp_read(0xDF, 0x00, &otp_mac);
+       if (!(ret & 0x1)) {
+               char *otp_mac_p = (char *)&otp_mac;
+               for (ret = 0; ret < 6; ++ret)
+                       addr[ret] = otp_mac_p[5 - ret];
+       }
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
index 762f754c06ccdcfedae5a8416750cf5d7940195e..8ee2b744e23492c024916009749ae1014774017f 100644 (file)
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/sl811.h>
-#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
 #include <linux/usb/musb.h>
-#endif
-#include <asm/cplb.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -129,6 +126,16 @@ static struct resource musb_resources[] = {
        },
 };
 
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 0,
+       .dyn_fifo       = 0,
+       .soft_con       = 1,
+       .dma            = 1,
+       .num_eps        = 7,
+       .dma_channels   = 7,
+       .gpio_vrsel     = GPIO_PG13,
+};
+
 static struct musb_hdrc_platform_data musb_plat = {
 #if defined(CONFIG_USB_MUSB_OTG)
        .mode           = MUSB_OTG,
@@ -137,7 +144,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
 #endif
-       .multipoint     = 0,
+       .config         = &musb_config,
 };
 
 static u64 musb_dmamask = ~(u32)0;
@@ -218,7 +225,7 @@ static struct mtd_partition partition_info[] = {
        {
                .name = "linux kernel(nand)",
                .offset = 0,
-               .size = 4 * SIZE_1M,
+               .size = 4 * 1024 * 1024,
        },
        {
                .name = "file system(nand)",
@@ -846,6 +853,38 @@ static struct platform_device bfin_device_gpiokeys = {
 };
 #endif
 
+#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#include <linux/input.h>
+#include <asm/bfin_rotary.h>
+
+static struct bfin_rotary_platform_data bfin_rotary_data = {
+       /*.rotary_up_key     = KEY_UP,*/
+       /*.rotary_down_key   = KEY_DOWN,*/
+       .rotary_rel_code   = REL_WHEEL,
+       .rotary_button_key = KEY_ENTER,
+       .debounce          = 10,        /* 0..17 */
+       .mode              = ROT_QUAD_ENC | ROT_DEBE,
+};
+
+static struct resource bfin_rotary_resources[] = {
+       {
+               .start = IRQ_CNT,
+               .end = IRQ_CNT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_rotary_device = {
+       .name           = "bfin-rotary",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bfin_rotary_resources),
+       .resource       = bfin_rotary_resources,
+       .dev            = {
+               .platform_data = &bfin_rotary_data,
+       },
+};
+#endif
+
 static struct resource bfin_gpios_resources = {
        .start = 0,
        .end   = MAX_BLACKFIN_GPIOS - 1,
@@ -962,6 +1001,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_device_gpiokeys,
 #endif
 
+#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+       &bfin_rotary_device,
+#endif
+
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
index 28c486191209669f1bc2cd48f82fe8930d8e3c09..0eb1da85db730e60c9a7e0e0373695650613268e 100644 (file)
@@ -87,6 +87,9 @@ ENTRY(_start_dma_code)
        r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
        r1 = r1 << 8;                    /* Shift it over                   */
        r0 = r1 | r0;                    /* add them all together           */
+#ifdef ANOMALY_05000265
+       BITSET(r0, 15);                  /* Add 250 mV of hysteresis to SPORT input pins */
+#endif
 
        p0.h = hi(PLL_CTL);
        p0.l = lo(PLL_CTL);              /* Load the address                */
index b7b166f4f064d8abe4bee22bb5c566e78e0b683a..62373e61c585f5b463c2ad80cc9df4abd0eacc43 100644 (file)
@@ -7,12 +7,24 @@
  */
 
 /* This file shoule be up to date with:
- *  - Revision C, 01/25/2008; ADSP-BF527 Blackfin Processor Anomaly List
+ *  - Revision B, 08/12/2008; ADSP-BF526 Blackfin Processor Anomaly List
+ *  - Revision E, 08/18/2008; ADSP-BF527 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
+#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
+# define ANOMALY_BF526 1
+#else
+# define ANOMALY_BF526 0
+#endif
+#if defined(__ADSPBF523__) || defined(__ADSPBF525__) || defined(__ADSPBF527__)
+# define ANOMALY_BF527 1
+#else
+# define ANOMALY_BF527 0
+#endif
+
 /* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000245 (1)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
 #define ANOMALY_05000265 (1)
-/* New Feature: EMAC TX DMA Word Alignment */
-#define ANOMALY_05000285 (1)
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
+#define ANOMALY_05000310 (1)
 /* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (1)
+#define ANOMALY_05000312 (ANOMALY_BF527)
+/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
+#define ANOMALY_05000313 (__SILICON_REVISION__ < 2)
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
-#define ANOMALY_05000328 (1)
+#define ANOMALY_05000328 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Disallowed Configuration Prevents Subsequent Allowed Configuration on Host DMA Port */
-#define ANOMALY_05000337 (1)
+#define ANOMALY_05000337 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Ethernet MAC MDIO Reads Do Not Meet IEEE Specification */
-#define ANOMALY_05000341 (1)
+#define ANOMALY_05000341 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* TWI May Not Operate Correctly Under Certain Signal Termination Conditions */
-#define ANOMALY_05000342 (1)
+#define ANOMALY_05000342 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* USB Calibration Value Is Not Initialized */
-#define ANOMALY_05000346 (1)
+#define ANOMALY_05000346 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* USB Calibration Value to use */
+#define ANOMALY_05000346_value 0xE510
 /* Preboot Routine Incorrectly Alters Reset Value of USB Register */
-#define ANOMALY_05000347 (1)
+#define ANOMALY_05000347 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Security Features Are Not Functional */
-#define ANOMALY_05000348 (__SILICON_REVISION__ < 1)
+#define ANOMALY_05000348 (ANOMALY_BF527 && __SILICON_REVISION__ < 1)
+/* bfrom_SysControl() Firmware Function Performs Improper System Reset */
+#define ANOMALY_05000353 (ANOMALY_BF526)
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
-#define ANOMALY_05000355 (1)
+#define ANOMALY_05000355 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
-#define ANOMALY_05000357 (1)
+#define ANOMALY_05000357 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Incorrect Revision Number in DSPID Register */
-#define ANOMALY_05000364 (__SILICON_REVISION__ > 0)
+#define ANOMALY_05000364 (ANOMALY_BF527 && __SILICON_REVISION__ == 1)
 /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
 #define ANOMALY_05000366 (1)
-/* New Feature: Higher Default CCLK Rate */
-#define ANOMALY_05000368 (1)
+/* Incorrect Default CSEL Value in PLL_DIV */
+#define ANOMALY_05000368 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
-#define ANOMALY_05000371 (1)
+#define ANOMALY_05000371 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Authentication Fails To Initiate */
-#define ANOMALY_05000376 (__SILICON_REVISION__ > 0)
+#define ANOMALY_05000376 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* Data Read From L3 Memory by USB DMA May be Corrupted */
-#define ANOMALY_05000380 (1)
-/* USB Full-speed Mode not Fully Tested */
-#define ANOMALY_05000381 (1)
-/* New Feature: Boot from OTP Memory */
-#define ANOMALY_05000385 (1)
-/* New Feature: bfrom_SysControl() Routine */
-#define ANOMALY_05000386 (1)
-/* New Feature: Programmable Preboot Settings */
-#define ANOMALY_05000387 (1)
+#define ANOMALY_05000380 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* 8-Bit NAND Flash Boot Mode Not Functional */
+#define ANOMALY_05000382 (__SILICON_REVISION__ < 2)
+/* Host Must Not Read Back During Host DMA Boot */
+#define ANOMALY_05000384 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Boot from OTP Memory Not Functional */
+#define ANOMALY_05000385 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* bfrom_SysControl() Firmware Routine Not Functional */
+#define ANOMALY_05000386 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Programmable Preboot Settings Not Functional */
+#define ANOMALY_05000387 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* CRC32 Checksum Support Not Functional */
+#define ANOMALY_05000388 (__SILICON_REVISION__ < 2)
 /* Reset Vector Must Not Be in SDRAM Memory Space */
-#define ANOMALY_05000389 (1)
-/* New Feature: pTempCurrent Added to ADI_BOOT_DATA Structure */
-#define ANOMALY_05000392 (1)
-/* New Feature: dTempByteCount Value Increased in ADI_BOOT_DATA Structure */
-#define ANOMALY_05000393 (1)
-/* New Feature: Log Buffer Functionality */
-#define ANOMALY_05000394 (1)
-/* New Feature: Hook Routine Functionality */
-#define ANOMALY_05000395 (1)
-/* New Feature: Header Indirect Bit */
-#define ANOMALY_05000396 (1)
-/* New Feature: BK_ONES, BK_ZEROS, and BK_DATECODE Constants */
-#define ANOMALY_05000397 (1)
-/* New Feature: SWRESET, DFRESET and WDRESET Bits Added to SYSCR Register */
-#define ANOMALY_05000398 (1)
-/* New Feature: BCODE_NOBOOT Added to BCODE Field of SYSCR Register */
-#define ANOMALY_05000399 (1)
+#define ANOMALY_05000389 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000392 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000393 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Log Buffer Not Functional */
+#define ANOMALY_05000394 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Hook Routine Not Functional */
+#define ANOMALY_05000395 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Header Indirect Bit Not Functional */
+#define ANOMALY_05000396 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
+#define ANOMALY_05000397 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* SWRESET, DFRESET and WDRESET Bits in the SYSCR Register Not Functional */
+#define ANOMALY_05000398 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* BCODE_NOBOOT in BCODE Field of SYSCR Register Not Functional */
+#define ANOMALY_05000399 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
 /* PPI Data Signals D0 and D8 do not Tristate After Disabling PPI */
-#define ANOMALY_05000401 (1)
+#define ANOMALY_05000401 (__SILICON_REVISION__ < 2)
+/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
+#define ANOMALY_05000403 (__SILICON_REVISION__ < 2)
+/* Lockbox SESR Disallows Certain User Interrupts */
+#define ANOMALY_05000404 (__SILICON_REVISION__ < 2)
+/* Lockbox SESR Firmware Does Not Save/Restore Full Context */
+#define ANOMALY_05000405 (1)
+/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */
+#define ANOMALY_05000407 (__SILICON_REVISION__ < 2)
+/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */
+#define ANOMALY_05000408 (1)
+/* Lockbox firmware leaves MDMA0 channel enabled */
+#define ANOMALY_05000409 (__SILICON_REVISION__ < 2)
+/* Incorrect Default Internal Voltage Regulator Setting */
+#define ANOMALY_05000410 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */
+#define ANOMALY_05000411 (__SILICON_REVISION__ < 2)
+/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */
+#define ANOMALY_05000414 (__SILICON_REVISION__ < 2)
+/* DEB2_URGENT Bit Not Functional */
+#define ANOMALY_05000415 (__SILICON_REVISION__ < 2)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* SPORT0 Ignores External TSCLK0 on PG14 When TMR6 is an Output */
+#define ANOMALY_05000417 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* tSFSPE and tHFSPE Do Not Meet Data Sheet Specifications */
+#define ANOMALY_05000418 (__SILICON_REVISION__ < 2)
+/* USB PLL_STABLE Bit May Not Accurately Reflect the USB PLL's Status */
+#define ANOMALY_05000420 (__SILICON_REVISION__ < 2)
+/* TWI Fall Time (Tof) May Violate the Minimum I2C Specification */
+#define ANOMALY_05000421 (1)
+/* TWI Input Capacitance (Ci) May Violate the Maximum I2C Specification */
+#define ANOMALY_05000422 (ANOMALY_BF527 && __SILICON_REVISION__ > 1)
+/* Certain Ethernet Frames With Errors are Misclassified in RMII Mode */
+#define ANOMALY_05000423 (__SILICON_REVISION__ < 2)
+/* Internal Voltage Regulator Not Trimmed */
+#define ANOMALY_05000424 (ANOMALY_BF527 && __SILICON_REVISION__ < 2)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (__SILICON_REVISION__ < 2)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Reflects Buffer Status Instead of IRQ Status */
+#define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
+/* Software System Reset Corrupts PLL_LOCKCNT Register */
+#define ANOMALY_05000430 (ANOMALY_BF527 && __SILICON_REVISION__ > 1)
+/* bfrom_SysControl() Does Not Clear SIC_IWR1 Before Executing PLL Programming Sequence */
+#define ANOMALY_05000432 (ANOMALY_BF526)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000125 (0)
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000285 (0)
+#define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000363 (0)
index 056eb4b9cd25fcb0f8adb61d43ca3eae34fbd7e6..144f08d3f8ea4511d7b0c80eddcfe128991f1783 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef __MACH_BF527_H__
 #define __MACH_BF527_H__
 
-#define SUPPORTED_REVID 2
-
 #define OFFSET_(x) ((x) & 0x0000FFFF)
 
 /*some misc defines*/
 
 #ifdef CONFIG_BF527
 #define CPU "BF527"
+#define CPUID 0x27e4
+#endif
+#ifdef CONFIG_BF526
+#define CPU "BF526"
+#define CPUID 0x27e4
 #endif
 #ifdef CONFIG_BF525
 #define CPU "BF525"
+#define CPUID 0x27e4
+#endif
+#ifdef CONFIG_BF524
+#define CPU "BF524"
+#define CPUID 0x27e4
+#endif
+#ifdef CONFIG_BF523
+#define CPU "BF523"
+#define CPUID 0x27e4
 #endif
 #ifdef CONFIG_BF522
 #define CPU "BF522"
+#define CPUID 0x27e4
 #endif
+
 #ifndef CPU
-#define        CPU "UNKNOWN"
-#define CPUID 0x0
+#error Unknown CPU type - This kernel doesn't seem to be configured properly
 #endif
 
 #endif                         /* __MACH_BF527_H__  */
index 2526b6ed6faa78ce72d45d9e210743c589850f8e..75722d6008b0cade6651e72911d7bfdb3543cbf6 100644 (file)
@@ -78,6 +78,9 @@
 #  define CONFIG_UART1_RTS_PIN -1
 # endif
 #endif
+
+#define BFIN_UART_TX_FIFO_SIZE 2
+
 /*
  * The pin configuration is different from schematic
  */
@@ -119,7 +122,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long uart_base_addr;
        int uart_irq;
@@ -164,8 +166,6 @@ struct bfin_serial_res bfin_serial_resource[] = {
 #endif
 };
 
-int nr_ports = ARRAY_SIZE(bfin_serial_resource);
-
 #define DRIVER_NAME "bfin-uart"
 
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
index 6ac2ed7026eb86c39b91e163339bd06bc3f58337..68b55d03fedf58f0e87b76b6d85d7912fd9e78ec 100644 (file)
 
 #define                 DPRESCALE  0xf        /* Load Counter Register */
 
+/* CNT_COMMAND bit field options */
+
+#define W1LCNT_ZERO   0x0001   /* write 1 to load CNT_COUNTER with zero */
+#define W1LCNT_MIN    0x0004   /* write 1 to load CNT_COUNTER from CNT_MIN */
+#define W1LCNT_MAX    0x0008   /* write 1 to load CNT_COUNTER from CNT_MAX */
+
+#define W1LMIN_ZERO   0x0010   /* write 1 to load CNT_MIN with zero */
+#define W1LMIN_CNT    0x0020   /* write 1 to load CNT_MIN from CNT_COUNTER */
+#define W1LMIN_MAX    0x0080   /* write 1 to load CNT_MIN from CNT_MAX */
+
+#define W1LMAX_ZERO   0x0100   /* write 1 to load CNT_MAX with zero */
+#define W1LMAX_CNT    0x0200   /* write 1 to load CNT_MAX from CNT_COUNTER */
+#define W1LMAX_MIN    0x0400   /* write 1 to load CNT_MAX from CNT_MIN */
+
+/* CNT_CONFIG bit field options */
+
+#define CNTMODE_QUADENC  0x0000  /* quadrature encoder mode */
+#define CNTMODE_BINENC   0x0100  /* binary encoder mode */
+#define CNTMODE_UDCNT    0x0200  /* up/down counter mode */
+#define CNTMODE_DIRCNT   0x0400  /* direction counter mode */
+#define CNTMODE_DIRTMR   0x0500  /* direction timer mode */
+
+#define BNDMODE_COMP     0x0000  /* boundary compare mode */
+#define BNDMODE_ZERO     0x1000  /* boundary compare and zero mode */
+#define BNDMODE_CAPT     0x2000  /* boundary capture mode */
+#define BNDMODE_AEXT     0x3000  /* boundary auto-extend mode */
+
 /* Bit masks for OTP_CONTROL */
 
 #define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
index ae4d205bfcf5bb764b87d35e8879536399e82457..7f6da2c386bb80c3072fc8bf4ba1176b4a0e0c40 100644 (file)
 #define P_UART1_RX     (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
 #endif
 
+#define P_CNT_CZM      (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(3))
+#define P_CNT_CDG      (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(3))
+#define P_CNT_CUD      (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(3))
+
 #define P_HWAIT                (P_DONTCARE)
 
 #define P_SPI0_SS      (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
index c66a68f30239644be1ab52863f667855a670242e..72ac3ac8ef766cd87d353dc7e6b53a12e3b64ff6 100644 (file)
@@ -9,7 +9,7 @@
  * Modified:
  *               Copyright 2005 National ICT Australia (NICTA)
  *               Copyright 2004-2006 Analog Devices Inc
- *              Copyright 2007 HV Sistemas S.L.
+ *              Copyright 2007,2008 HV Sistemas S.L.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -64,18 +64,18 @@ static struct platform_device rtc_device = {
 static struct resource dm9000_resources[] = {
        [0] = {
                .start  = 0x20300000,
-               .end    = 0x20300000 + 1,
+               .end    = 0x20300002,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = 0x20300000 + 4,
-               .end    = 0x20300000 + 5,
+               .start  = 0x20300004,
+               .end    = 0x20300006,
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
                .start  = IRQ_PF10,
                .end    = IRQ_PF10,
-               .flags  = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+               .flags  = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IRQF_SHARED | IRQF_TRIGGER_HIGH),
        },
 };
 
@@ -140,18 +140,22 @@ static struct platform_device net2272_bfin_device = {
 #if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
 static struct mtd_partition bfin_spi_flash_partitions[] = {
        {
-               .name = "bootloader(spi)",
-               .size = 0x00060000,
+               .name = "bootloader (spi)",
+               .size = 0x40000,
                .offset = 0,
                .mask_flags = MTD_CAP_ROM
        }, {
-               .name = "linux kernel(spi)",
-               .size = 0x100000,
-               .offset = 0x60000
+               .name = "fpga (spi)",
+               .size =   0x30000,
+               .offset = 0x40000
        }, {
-               .name = "file system(spi)",
-               .size = 0x6a0000,
-               .offset = 0x00160000,
+               .name = "linux kernel (spi)",
+               .size =   0x150000,
+               .offset =  0x70000
+       }, {
+               .name = "jffs2 root file system (spi)",
+               .size =   0x640000,
+               .offset = 0x1c0000,
        }
 };
 
@@ -340,7 +344,7 @@ static struct platform_device bfin_sir_device = {
 
 static struct plat_serial8250_port serial8250_platform_data [] = {
        {
-               .membase = 0x20200000,
+               .membase = (void *)0x20200000,
                .mapbase = 0x20200000,
                .irq = IRQ_PF8,
                .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
@@ -348,7 +352,7 @@ static struct plat_serial8250_port serial8250_platform_data [] = {
                .regshift = 1,
                .uartclk = 66666667,
        }, {
-               .membase = 0x20200010,
+               .membase = (void *)0x20200010,
                .mapbase = 0x20200010,
                .irq = IRQ_PF8,
                .flags = UPF_BOOT_AUTOCONF | UART_CONFIG_TYPE,
index 01b2b7ead5abf24aa4d0aaa45b6ad2d0f6315fd2..9fc95aaca439c26371577172026824e320fddd14 100644 (file)
@@ -78,6 +78,9 @@ ENTRY(_start_dma_code)
        r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
        r1 = r1 << 8;                    /* Shift it over                   */
        r0 = r1 | r0;                    /* add them all together           */
+#ifdef ANOMALY_05000265
+       BITSET(r0, 15);                  /* Add 250 mV of hysteresis to SPORT input pins */
+#endif
 
        p0.h = hi(PLL_CTL);
        p0.l = lo(PLL_CTL);              /* Load the address                */
index 8f7ea112fd3a0cf9c2e428dafa4cf7aada5d8f2d..f544fc56959ac4d8b19ec4501e65a8a23bf9e57d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 /* This file shoule be up to date with:
- *  - Revision C, 02/08/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ *  - Revision D, 06/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 /* UART STB Bit Incorrectly Affects Receiver Setting */
 #define ANOMALY_05000231 (__SILICON_REVISION__ < 5)
 /* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */
-#define ANOMALY_05000233 (__SILICON_REVISION__ < 4)
+#define ANOMALY_05000233 (__SILICON_REVISION__ < 6)
 /* Incorrect Revision Number in DSPID Register */
 #define ANOMALY_05000234 (__SILICON_REVISION__ == 4)
 /* DF Bit in PLL_CTL Register Does Not Respond to Hardware Reset */
-#define ANOMALY_05000242 (__SILICON_REVISION__ < 4)
+#define ANOMALY_05000242 (__SILICON_REVISION__ < 5)
 /* If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control Causes Failures */
 #define ANOMALY_05000244 (__SILICON_REVISION__ < 5)
 /* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
 /* CSYNC/SSYNC/IDLE Causes Infinite Stall in Penultimate Instruction in Hardware Loop */
 #define ANOMALY_05000264 (__SILICON_REVISION__ < 5)
 /* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
-#define ANOMALY_05000265 (__SILICON_REVISION__ < 5)
+#define ANOMALY_05000265 (1)
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Increase */
 #define ANOMALY_05000269 (__SILICON_REVISION__ < 5)
 /* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
 /* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
 #define ANOMALY_05000272 (1)
 /* Writes to Synchronous SDRAM Memory May Be Lost */
-#define ANOMALY_05000273 (1)
+#define ANOMALY_05000273 (__SILICON_REVISION__ < 6)
 /* Timing Requirements Change for External Frame Sync PPI Modes with Non-Zero PPI_DELAY */
 #define ANOMALY_05000276 (1)
 /* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
-#define ANOMALY_05000277 (1)
+#define ANOMALY_05000277 (__SILICON_REVISION__ < 6)
 /* Disabling Peripherals with DMA Running May Cause DMA System Instability */
-#define ANOMALY_05000278 (1)
+#define ANOMALY_05000278 (__SILICON_REVISION__ < 6)
 /* False Hardware Error Exception When ISR Context Is Not Restored */
-#define ANOMALY_05000281 (1)
+#define ANOMALY_05000281 (__SILICON_REVISION__ < 6)
 /* Memory DMA Corruption with 32-Bit Data and Traffic Control */
-#define ANOMALY_05000282 (1)
+#define ANOMALY_05000282 (__SILICON_REVISION__ < 6)
 /* System MMR Write Is Stalled Indefinitely When Killed in a Particular Stage */
-#define ANOMALY_05000283 (1)
+#define ANOMALY_05000283 (__SILICON_REVISION__ < 6)
 /* SPORTs May Receive Bad Data If FIFOs Fill Up */
-#define ANOMALY_05000288 (1)
+#define ANOMALY_05000288 (__SILICON_REVISION__ < 6)
 /* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
-#define ANOMALY_05000301 (1)
+#define ANOMALY_05000301 (__SILICON_REVISION__ < 6)
 /* SSYNCs After Writes To DMA MMR Registers May Not Be Handled Correctly */
 #define ANOMALY_05000302 (__SILICON_REVISION__ < 5)
 /* New Feature: Additional Hysteresis on SPORT Input Pins (Not Available On Older Silicon) */
 #define ANOMALY_05000305 (__SILICON_REVISION__ < 5)
 /* New Feature: Additional PPI Frame Sync Sampling Options (Not Available On Older Silicon) */
 #define ANOMALY_05000306 (__SILICON_REVISION__ < 5)
+/* SCKELOW Bit Does Not Maintain State Through Hibernate */
+#define ANOMALY_05000307 (1)
 /* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
 #define ANOMALY_05000310 (1)
 /* Erroneous Flag (GPIO) Pin Operations under Specific Sequences */
-#define ANOMALY_05000311 (1)
+#define ANOMALY_05000311 (__SILICON_REVISION__ < 6)
 /* Errors When SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (1)
+#define ANOMALY_05000312 (__SILICON_REVISION__ < 6)
 /* PPI Is Level-Sensitive on First Transfer */
-#define ANOMALY_05000313 (1)
+#define ANOMALY_05000313 (__SILICON_REVISION__ < 6)
 /* Killed System MMR Write Completes Erroneously On Next System MMR Access */
-#define ANOMALY_05000315 (1)
+#define ANOMALY_05000315 (__SILICON_REVISION__ < 6)
 /* Internal Voltage Regulator Values of 1.05V, 1.10V and 1.15V Not Allowed for LQFP Packages */
-#define ANOMALY_05000319 (ANOMALY_BF531 || ANOMALY_BF532)
+#define ANOMALY_05000319 ((ANOMALY_BF531 || ANOMALY_BF532) && __SILICON_REVISION__ < 6)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
-#define ANOMALY_05000357 (1)
+#define ANOMALY_05000357 (__SILICON_REVISION__ < 6)
 /* UART Break Signal Issues */
 #define ANOMALY_05000363 (__SILICON_REVISION__ < 5)
 /* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
 #define ANOMALY_05000366 (1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
-#define ANOMALY_05000371 (1)
+#define ANOMALY_05000371 (__SILICON_REVISION__ < 6)
 /* PPI Does Not Start Properly In Specific Mode */
-#define ANOMALY_05000400 (__SILICON_REVISION__ >= 5)
+#define ANOMALY_05000400 (__SILICON_REVISION__ == 5)
 /* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
-#define ANOMALY_05000402 (__SILICON_REVISION__ >= 5)
+#define ANOMALY_05000402 (__SILICON_REVISION__ == 5)
 /* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
 #define ANOMALY_05000403 (1)
-
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
 
 /* These anomalies have been "phased" out of analog.com anomaly sheets and are
  * here to show running on older silicon just isn't feasible.
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000353 (1)
+#define ANOMALY_05000386 (1)
 
 #endif
index 12a4169319916ae58cecedcebea0f6f783e08438..dfc8c1ad2d7a48dc52990ff8cad34c0bff7a3396 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef __MACH_BF533_H__
 #define __MACH_BF533_H__
 
-#define SUPPORTED_REVID 2
-
 #define OFFSET_(x) ((x) & 0x0000FFFF)
 
 /*some misc defines*/
 
 #ifdef CONFIG_BF533
 #define CPU "BF533"
-#define CPUID 0x027a5000
+#define CPUID 0x27a5
 #endif
 #ifdef CONFIG_BF532
 #define CPU "BF532"
-#define CPUID 0x0275A000
+#define CPUID 0x275A
 #endif
 #ifdef CONFIG_BF531
 #define CPU "BF531"
-#define CPUID 0x027a5000
+#define CPUID 0x27a5
 #endif
+
 #ifndef CPU
-#define        CPU "UNKNOWN"
-#define CPUID 0x0
+#error Unknown CPU type - This kernel doesn't seem to be configured properly
 #endif
 
 #endif                         /* __MACH_BF533_H__  */
index ebf592b59aab4b88a1d790f013f86535d55ccfeb..f3d9e495230c04439357b1499874c918092a817e 100644 (file)
@@ -69,6 +69,8 @@
 # endif
 #endif
 
+#define BFIN_UART_TX_FIFO_SIZE 2
+
 struct bfin_serial_port {
         struct uart_port        port;
         unsigned int            old_status;
@@ -83,7 +85,7 @@ struct bfin_serial_port {
        unsigned int            rx_dma_channel;
        struct work_struct      tx_dma_workqueue;
 #else
-# if ANOMALY_05000230
+# if ANOMALY_05000363
        unsigned int anomaly_threshold;
 # endif
 #endif
@@ -111,7 +113,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -142,7 +143,6 @@ struct bfin_serial_res bfin_serial_resource[] = {
 
 #define DRIVER_NAME "bfin-uart"
 
-int nr_ports = BFIN_UART_NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
@@ -158,7 +158,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
        }
        if (uart->rts_pin >= 0) {
                gpio_request(uart->rts_pin, DRIVER_NAME);
-               gpio_direction_input(uart->rts_pin, 0);
+               gpio_direction_output(uart->rts_pin, 0);
        }
 #endif
 }
index 8482d22321f33058370924c30c864f455c0383f8..8d394393201fd74d13ab5a13fbac6bf9d420bd57 100644 (file)
@@ -51,7 +51,6 @@
 #include <asm/reboot.h>
 #include <asm/portmux.h>
 #include <asm/dpmc.h>
-#include <linux/spi/ad7877.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -555,6 +554,7 @@ static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
 #endif
 
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+#include <linux/spi/ad7877.h>
 static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
        .enable_dma = 0,
        .bits_per_word = 16,
@@ -575,6 +575,30 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
+#if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+       .model                  = 7879, /* Model = AD7879 */
+       .x_plate_ohms           = 620,  /* 620 Ohm from the touch datasheet */
+       .pressure_max           = 10000,
+       .pressure_min           = 0,
+       .first_conversion_delay = 3,    /* wait 512us before do a first conversion */
+       .acquisition_time       = 1,    /* 4us acquisition time per sample */
+       .median                 = 2,    /* do 8 measurements */
+       .averaging              = 1,    /* take the average of 4 middle samples */
+       .pen_down_acc_interval  = 255,  /* 9.4 ms */
+       .gpio_output            = 1,    /* configure AUX/VBAT/GPIO as GPIO output */
+       .gpio_default           = 1,    /* During initialization set GPIO = HIGH */
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+       .enable_dma = 0,
+       .bits_per_word = 16,
+};
+#endif
+
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
 static struct bfin5xx_spi_chip spidev_chip_info = {
        .enable_dma = 0,
@@ -582,6 +606,13 @@ static struct bfin5xx_spi_chip spidev_chip_info = {
 };
 #endif
 
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
+       .enable_dma     = 0,
+       .bits_per_word  = 8,
+};
+#endif
+
 #if defined(CONFIG_MTD_DATAFLASH) \
        || defined(CONFIG_MTD_DATAFLASH_MODULE)
 
@@ -721,6 +752,18 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .controller_data = &spi_ad7877_chip_info,
        },
 #endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+       {
+               .modalias = "ad7879",
+               .platform_data = &bfin_ad7879_ts_info,
+               .irq = IRQ_PF7,
+               .max_speed_hz = 5000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 1,
+               .controller_data = &spi_ad7879_chip_info,
+               .mode = SPI_CPHA | SPI_CPOL,
+       },
+#endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
        {
                .modalias = "spidev",
@@ -730,6 +773,16 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
                .controller_data = &spidev_chip_info,
        },
 #endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+       {
+               .modalias = "bfin-lq035q1-spi",
+               .max_speed_hz = 20000000,     /* max spi clock (SCK) speed in HZ */
+               .bus_num = 0,
+               .chip_select = 2,
+               .controller_data = &lq035q1_spi_chip_info,
+               .mode = SPI_CPHA | SPI_CPOL,
+       },
+#endif
 };
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
@@ -777,6 +830,34 @@ static struct platform_device bfin_fb_adv7393_device = {
 };
 #endif
 
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+#include <asm/bfin-lq035q1.h>
+
+static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = {
+       .mode =         LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB,
+       .use_bl =       0,      /* let something else control the LCD Blacklight */
+       .gpio_bl =      GPIO_PF7,
+};
+
+static struct resource bfin_lq035q1_resources[] = {
+       {
+               .start = IRQ_PPI_ERROR,
+               .end = IRQ_PPI_ERROR,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_lq035q1_device = {
+       .name           = "bfin-lq035q1",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bfin_lq035q1_resources),
+       .resource       = bfin_lq035q1_resources,
+       .dev            = {
+               .platform_data = &bfin_lq035q1_data,
+       },
+};
+#endif
+
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 #ifdef CONFIG_SERIAL_BFIN_UART0
@@ -856,7 +937,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
                I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-               .irq = 55,
+               .irq = IRQ_PF5,
        },
 #endif
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
@@ -867,7 +948,14 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-               .irq = 72,
+               .irq = IRQ_PG6,
+       },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_I2C) || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE)
+       {
+               I2C_BOARD_INFO("ad7879", 0x2F),
+               .irq = IRQ_PG5,
+               .platform_data = (void *)&bfin_ad7879_ts_info,
        },
 #endif
 };
@@ -997,6 +1085,10 @@ static struct platform_device *stamp_devices[] __initdata = {
        &bfin_fb_device,
 #endif
 
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+       &bfin_lq035q1_device,
+#endif
+
 #if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE)
        &bfin_fb_adv7393_device,
 #endif
index 12eb5cc571d082c80181da8401dff77cb4c1a50c..f5c94bf80e3bbec8c61451a5e035bc868b66aec6 100644 (file)
@@ -87,6 +87,9 @@ ENTRY(_start_dma_code)
        r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
        r1 = r1 << 8;                    /* Shift it over                   */
        r0 = r1 | r0;                    /* add them all together           */
+#ifdef ANOMALY_05000265
+       BITSET(r0, 15);                  /* Add 250 mV of hysteresis to SPORT input pins */
+#endif
 
        p0.h = hi(PLL_CTL);
        p0.l = lo(PLL_CTL);              /* Load the address                */
index 8460ab9c324f59c7b74c58b984671dfce7c7f40c..c68992494f9e7d0ad5fcd610dcc8a0b06d51b040 100644 (file)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
+#define ANOMALY_05000353 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000386 (1)
 
 #endif
index cfe2a221112ef12ec97a8fbda0790310e55cb016..24d5c9d42323228619dd0ac966ce32b2f1bb8b68 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef __MACH_BF537_H__
 #define __MACH_BF537_H__
 
-#define SUPPORTED_REVID 2
-
 /* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */
 
 #define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE)       /* SPI_STAT */
 
 #ifdef CONFIG_BF537
 #define CPU "BF537"
-#define CPUID 0x027c8000
+#define CPUID 0x27c8
 #endif
 #ifdef CONFIG_BF536
 #define CPU "BF536"
-#define CPUID 0x027c8000
+#define CPUID 0x27c8
 #endif
 #ifdef CONFIG_BF534
 #define CPU "BF534"
-#define CPUID 0x027c6000
+#define CPUID 0x27c6
 #endif
+
 #ifndef CPU
-#define        CPU "UNKNOWN"
-#define CPUID 0x0
+#error Unknown CPU type - This kernel doesn't seem to be configured properly
 #endif
 
 #endif                         /* __MACH_BF537_H__  */
index 1bf56ffa22f946236dfcfad9d14b27db6e26d090..b3f87e1d16a2f5ffa18156b35e76edc01c451870 100644 (file)
@@ -78,6 +78,9 @@
 #  define CONFIG_UART1_RTS_PIN -1
 # endif
 #endif
+
+#define BFIN_UART_TX_FIFO_SIZE 2
+
 /*
  * The pin configuration is different from schematic
  */
@@ -119,7 +122,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -164,8 +166,6 @@ struct bfin_serial_res bfin_serial_resource[] = {
 #endif
 };
 
-int nr_ports = ARRAY_SIZE(bfin_serial_resource);
-
 #define DRIVER_NAME "bfin-uart"
 
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
index ce934ee174e070e8375f8a2b5d1ff61644c1de0c..24192aaa92757423dd6a3fa76137cc96b87a6804 100644 (file)
 #include <linux/spi/flash.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
 #include <linux/usb/musb.h>
-#endif
 #include <asm/bfin5xx_spi.h>
-#include <asm/cplb.h>
 #include <asm/dma.h>
 #include <asm/gpio.h>
 #include <asm/nand.h>
@@ -175,6 +172,7 @@ static struct resource bfin_uart_resources[] = {
        {
                .start = 0xFFC03100,
                .end = 0xFFC031FF,
+               .flags = IORESOURCE_MEM,
        },
 #endif
 };
@@ -268,6 +266,16 @@ static struct resource musb_resources[] = {
        },
 };
 
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 0,
+       .dyn_fifo       = 0,
+       .soft_con       = 1,
+       .dma            = 1,
+       .num_eps        = 7,
+       .dma_channels   = 7,
+       .gpio_vrsel     = GPIO_PH6,
+};
+
 static struct musb_hdrc_platform_data musb_plat = {
 #if defined(CONFIG_USB_MUSB_OTG)
        .mode           = MUSB_OTG,
@@ -276,7 +284,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
 #endif
-       .multipoint     = 0,
+       .config         = &musb_config,
 };
 
 static u64 musb_dmamask = ~(u32)0;
@@ -321,12 +329,12 @@ static struct mtd_partition partition_info[] = {
        {
                .name = "linux kernel(nand)",
                .offset = 0,
-               .size = 4 * SIZE_1M,
+               .size = 4 * 1024 * 1024,
        },
        {
                .name = "file system(nand)",
-               .offset = 4 * SIZE_1M,
-               .size = (256 - 4) * SIZE_1M,
+               .offset = 4 * 1024 * 1024,
+               .size = (256 - 4) * 1024 * 1024,
        },
 };
 
index 39357693046d158f4a3097556099a66f3b930675..5288187a3acebfe2eec6cd3b384099b202e2b174 100644 (file)
 #include <linux/irq.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
-#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
 #include <linux/usb/musb.h>
-#endif
 #include <asm/bfin5xx_spi.h>
-#include <asm/cplb.h>
 #include <asm/dma.h>
 #include <asm/gpio.h>
 #include <asm/nand.h>
@@ -186,6 +183,37 @@ static struct platform_device bf54x_kpad_device = {
 };
 #endif
 
+#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#include <asm/bfin_rotary.h>
+
+static struct bfin_rotary_platform_data bfin_rotary_data = {
+       /*.rotary_up_key     = KEY_UP,*/
+       /*.rotary_down_key   = KEY_DOWN,*/
+       .rotary_rel_code   = REL_WHEEL,
+       .rotary_button_key = KEY_ENTER,
+       .debounce          = 10,        /* 0..17 */
+       .mode              = ROT_QUAD_ENC | ROT_DEBE,
+};
+
+static struct resource bfin_rotary_resources[] = {
+       {
+               .start = IRQ_CNT,
+               .end = IRQ_CNT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device bfin_rotary_device = {
+       .name           = "bfin-rotary",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(bfin_rotary_resources),
+       .resource       = bfin_rotary_resources,
+       .dev            = {
+               .platform_data = &bfin_rotary_data,
+       },
+};
+#endif
+
 #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
 static struct platform_device rtc_device = {
        .name = "rtc-bfin",
@@ -314,6 +342,16 @@ static struct resource musb_resources[] = {
        },
 };
 
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 0,
+       .dyn_fifo       = 0,
+       .soft_con       = 1,
+       .dma            = 1,
+       .num_eps        = 7,
+       .dma_channels   = 7,
+       .gpio_vrsel     = GPIO_PE7,
+};
+
 static struct musb_hdrc_platform_data musb_plat = {
 #if defined(CONFIG_USB_MUSB_OTG)
        .mode           = MUSB_OTG,
@@ -322,7 +360,7 @@ static struct musb_hdrc_platform_data musb_plat = {
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
 #endif
-       .multipoint     = 0,
+       .config         = &musb_config,
 };
 
 static u64 musb_dmamask = ~(u32)0;
@@ -367,7 +405,7 @@ static struct mtd_partition partition_info[] = {
        {
                .name = "linux kernel(nand)",
                .offset = 0,
-               .size = 4 * SIZE_1M,
+               .size = 4 * 1024 * 1024,
        },
        {
                .name = "file system(nand)",
@@ -424,7 +462,7 @@ static struct mtd_partition ezkit_partitions[] = {
                .offset     = 0,
        }, {
                .name       = "linux kernel(nor)",
-               .size       = 0x1C0000,
+               .size       = 0x400000,
                .offset     = MTDPART_OFS_APPEND,
        }, {
                .name       = "file system(nor)",
@@ -441,7 +479,7 @@ static struct physmap_flash_data ezkit_flash_data = {
 
 static struct resource ezkit_flash_resource = {
        .start = 0x20000000,
-       .end   = 0x20ffffff,
+       .end   = 0x21ffffff,
        .flags = IORESOURCE_MEM,
 };
 
@@ -551,7 +589,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 {
        .modalias               = "ad7877",
        .platform_data          = &bfin_ad7877_ts_info,
-       .irq                    = IRQ_PJ11,
+       .irq                    = IRQ_PJ11,     /* newer boards (Rev 1.4+) use IRQ_PB4 */
        .max_speed_hz           = 12500000,     /* max spi clock (SCK) speed in HZ */
        .bus_num                = 0,
        .chip_select            = 2,
@@ -810,6 +848,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bf54x_kpad_device,
 #endif
 
+#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+       &bfin_rotary_device,
+#endif
+
 #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
        &i2c_bfin_twi0_device,
 #if !defined(CONFIG_BF542)
index 4d5cfeacb123c1ca49095102e06abb3195308ae0..93b361dff27ba23bab6f471e154f2c69d1028eb3 100644 (file)
@@ -73,25 +73,19 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-#if defined(CONFIG_BF54x)
+       /* enable self refresh via SRREQ */
        P2.H = hi(EBIU_RSTCTL);
        P2.L = lo(EBIU_RSTCTL);
        R0 = [P2];
        BITSET (R0, 3);
-#else
-       P2.H = hi(EBIU_SDGCTL);
-       P2.L = lo(EBIU_SDGCTL);
-       R0 = [P2];
-       BITSET (R0, 24);
-#endif
        [P2] = R0;
        SSYNC;
-#if defined(CONFIG_BF54x)
+
+       /* wait for SRACK bit to be set */
 .LSRR_MODE:
        R0 = [P2];
        CC = BITTST(R0, 4);
        if !CC JUMP .LSRR_MODE;
-#endif
 
        r0 = CONFIG_VCO_MULT & 63;       /* Load the VCO multiplier         */
        r0 = r0 << 9;                    /* Shift it over,                  */
@@ -100,6 +94,9 @@ ENTRY(_start_dma_code)
        r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
        r1 = r1 << 8;                    /* Shift it over                   */
        r0 = r1 | r0;                    /* add them all together           */
+#ifdef ANOMALY_05000265
+       BITSET(r0, 15);                  /* Add 250 mV of hysteresis to SPORT input pins */
+#endif
 
        p0.h = hi(PLL_CTL);
        p0.l = lo(PLL_CTL);              /* Load the address                */
@@ -123,7 +120,7 @@ ENTRY(_start_dma_code)
        w[p0] = r0.l;
        ssync;
 
-#if defined(CONFIG_BF54x)
+       /* disable self refresh by clearing SRREQ */
        P2.H = hi(EBIU_RSTCTL);
        P2.L = lo(EBIU_RSTCTL);
        R0 = [P2];
@@ -155,41 +152,6 @@ ENTRY(_start_dma_code)
        r0.h = hi(mem_DDRCTL2);
        [p0] = r0;
        ssync;
-#else
-       p0.l = lo(EBIU_SDRRC);
-       p0.h = hi(EBIU_SDRRC);
-       r0 = mem_SDRRC;
-       w[p0] = r0.l;
-       ssync;
-
-       p0.l = LO(EBIU_SDBCTL);
-       p0.h = HI(EBIU_SDBCTL);     /* SDRAM Memory Bank Control Register */
-       r0 = mem_SDBCTL;
-       w[p0] = r0.l;
-       ssync;
-
-       P2.H = hi(EBIU_SDGCTL);
-       P2.L = lo(EBIU_SDGCTL);
-       R0 = [P2];
-       BITCLR (R0, 24);
-       p0.h = hi(EBIU_SDSTAT);
-       p0.l = lo(EBIU_SDSTAT);
-       r2.l = w[p0];
-       cc = bittst(r2,3);
-       if !cc jump .Lskip;
-       NOP;
-       BITSET (R0, 23);
-.Lskip:
-       [P2] = R0;
-       SSYNC;
-
-       R0.L = lo(mem_SDGCTL);
-       R0.H = hi(mem_SDGCTL);
-       R1 = [p2];
-       R1 = R1 | R0;
-       [P2] = R1;
-       SSYNC;
-#endif
 
        RTS;
 ENDPROC(_start_dma_code)
index 3ad59655881a863b0529a4cef8af5ce9c839e579..816b09278f62ecec05cd0876fc2700a8ef8587fa 100644 (file)
@@ -2,18 +2,18 @@
  * File: include/asm-blackfin/mach-bf548/anomaly.h
  * Bugs: Enter bugs at http://blackfin.uclinux.org/
  *
- * Copyright (C) 2004-2007 Analog Devices Inc.
+ * Copyright (C) 2004-2008 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
 /* This file shoule be up to date with:
- *  - Revision E, 11/28/2007; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
+ *  - Revision G, 08/07/2008; ADSP-BF542/BF544/BF547/BF548/BF549 Blackfin Processor Anomaly List
  */
 
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
-/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot 2 Not Supported */
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
 #define ANOMALY_05000074 (1)
 /* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
 #define ANOMALY_05000119 (1)
 /* TWI Slave Boot Mode Is Not Functional */
 #define ANOMALY_05000324 (__SILICON_REVISION__ < 1)
 /* External FIFO Boot Mode Is Not Functional */
-#define ANOMALY_05000325 (__SILICON_REVISION__ < 1)
+#define ANOMALY_05000325 (__SILICON_REVISION__ < 2)
 /* Data Lost When Core and DMA Accesses Are Made to the USB FIFO Simultaneously */
 #define ANOMALY_05000327 (__SILICON_REVISION__ < 1)
 /* Incorrect Access of OTP_STATUS During otp_write() Function */
 #define ANOMALY_05000328 (__SILICON_REVISION__ < 1)
 /* Synchronous Burst Flash Boot Mode Is Not Functional */
 #define ANOMALY_05000329 (__SILICON_REVISION__ < 1)
-/* Host DMA Boot Mode Is Not Functional */
+/* Host DMA Boot Modes Are Not Functional */
 #define ANOMALY_05000330 (__SILICON_REVISION__ < 1)
 /* Inadequate Timing Margins on DDR DQS to DQ and DQM Skew */
 #define ANOMALY_05000334 (__SILICON_REVISION__ < 1)
 #define ANOMALY_05000344 (__SILICON_REVISION__ < 1)
 /* USB Calibration Value Is Not Intialized */
 #define ANOMALY_05000346 (__SILICON_REVISION__ < 1)
-/* Boot ROM Kernel Incorrectly Alters Reset Value of USB Register */
+/* USB Calibration Value to use */
+#define ANOMALY_05000346_value 0x5411
+/* Preboot Routine Incorrectly Alters Reset Value of USB Register */
 #define ANOMALY_05000347 (__SILICON_REVISION__ < 1)
 /* Data Lost when Core Reads SDH Data FIFO */
 #define ANOMALY_05000349 (__SILICON_REVISION__ < 1)
 /* PLL Status Register Is Inaccurate */
 #define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
+/* bfrom_SysControl() Firmware Function Performs Improper System Reset */
+#define ANOMALY_05000353 (__SILICON_REVISION__ < 2)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
+/* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
+#define ANOMALY_05000356 (__SILICON_REVISION__ < 1)
 /* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
 #define ANOMALY_05000357 (1)
 /* External Memory Read Access Hangs Core With PLL Bypass */
 #define ANOMALY_05000360 (1)
 /* DMAs that Go Urgent during Tight Core Writes to External Memory Are Blocked */
 #define ANOMALY_05000365 (1)
+/* WURESET Bit In SYSCR Register Does Not Properly Indicate Hibernate Wake-Up */
+#define ANOMALY_05000367 (__SILICON_REVISION__ < 1)
 /* Addressing Conflict between Boot ROM and Asynchronous Memory */
 #define ANOMALY_05000369 (1)
+/* Default PLL MSEL and SSEL Settings Can Cause 400MHz Product To Violate Specifications */
+#define ANOMALY_05000370 (__SILICON_REVISION__ < 1)
 /* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
-#define ANOMALY_05000371 (1)
+#define ANOMALY_05000371 (__SILICON_REVISION__ < 2)
+/* USB DP/DM Data Pins May Lose State When Entering Hibernate */
+#define ANOMALY_05000372 (__SILICON_REVISION__ < 1)
 /* Mobile DDR Operation Not Functional */
 #define ANOMALY_05000377 (1)
 /* Security/Authentication Speedpath Causes Authentication To Fail To Initiate */
-#define ANOMALY_05000378 (1)
+#define ANOMALY_05000378 (__SILICON_REVISION__ < 2)
+/* 16-Bit NAND FLASH Boot Mode Is Not Functional */
+#define ANOMALY_05000379 (1)
+/* 8-Bit NAND Flash Boot Mode Not Functional */
+#define ANOMALY_05000382 (__SILICON_REVISION__ < 1)
+/* Some ATAPI Modes Are Not Functional */
+#define ANOMALY_05000383 (1)
+/* Boot from OTP Memory Not Functional */
+#define ANOMALY_05000385 (__SILICON_REVISION__ < 1)
+/* bfrom_SysControl() Firmware Routine Not Functional */
+#define ANOMALY_05000386 (__SILICON_REVISION__ < 1)
+/* Programmable Preboot Settings Not Functional */
+#define ANOMALY_05000387 (__SILICON_REVISION__ < 1)
+/* CRC32 Checksum Support Not Functional */
+#define ANOMALY_05000388 (__SILICON_REVISION__ < 1)
+/* Reset Vector Must Not Be in SDRAM Memory Space */
+#define ANOMALY_05000389 (__SILICON_REVISION__ < 1)
+/* Changed Meaning of BCODE Field in SYSCR Register */
+#define ANOMALY_05000390 (__SILICON_REVISION__ < 1)
+/* Repeated Boot from Page-Mode or Burst-Mode Flash Memory May Fail */
+#define ANOMALY_05000391 (__SILICON_REVISION__ < 1)
+/* pTempCurrent Not Present in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000392 (__SILICON_REVISION__ < 1)
+/* Deprecated Value of dTempByteCount in ADI_BOOT_DATA Structure */
+#define ANOMALY_05000393 (__SILICON_REVISION__ < 1)
+/* Log Buffer Not Functional */
+#define ANOMALY_05000394 (__SILICON_REVISION__ < 1)
+/* Hook Routine Not Functional */
+#define ANOMALY_05000395 (__SILICON_REVISION__ < 1)
+/* Header Indirect Bit Not Functional */
+#define ANOMALY_05000396 (__SILICON_REVISION__ < 1)
+/* BK_ONES, BK_ZEROS, and BK_DATECODE Constants Not Functional */
+#define ANOMALY_05000397 (__SILICON_REVISION__ < 1)
+/* Lockbox SESR Disallows Certain User Interrupts */
+#define ANOMALY_05000404 (__SILICON_REVISION__ < 2)
+/* Lockbox SESR Firmware Does Not Save/Restore Full Context */
+#define ANOMALY_05000405 (1)
+/* Lockbox SESR Argument Checking Does Not Check L2 Memory Protection Range */
+#define ANOMALY_05000406 (__SILICON_REVISION__ < 2)
+/* Lockbox SESR Firmware Arguments Are Not Retained After First Initialization */
+#define ANOMALY_05000407 (__SILICON_REVISION__ < 2)
+/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */
+#define ANOMALY_05000408 (1)
+/* Lockbox firmware leaves MDMA0 channel enabled */
+#define ANOMALY_05000409 (__SILICON_REVISION__ < 2)
+/* bfrom_SysControl() Firmware Function Cannot be Used to Enter Power Saving Modes */
+#define ANOMALY_05000411 (__SILICON_REVISION__ < 2)
+/* NAND Boot Mode Not Compatible With Some NAND Flash Devices */
+#define ANOMALY_05000413 (__SILICON_REVISION__ < 2)
+/* OTP_CHECK_FOR_PREV_WRITE Bit is Not Functional in bfrom_OtpWrite() API */
+#define ANOMALY_05000414 (__SILICON_REVISION__ < 2)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause Spurious Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* CORE_EPPI_PRIO bit and SYS_EPPI_PRIO bit in the HMDMA1_CONTROL register are not functional */
+#define ANOMALY_05000427 (__SILICON_REVISION__ < 2)
+/* WB_EDGE Bit in NFC_IRQSTAT Incorrectly Behaves as a Buffer Status Bit Instead of an IRQ Status Bit */
+#define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
+/* Software System Reset Corrupts PLL_LOCKCNT Register */
+#define ANOMALY_05000430 (__SILICON_REVISION__ >= 2)
 
 /* Anomalies that don't exist on this proc */
 #define ANOMALY_05000125 (0)
 #define ANOMALY_05000263 (0)
 #define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
+#define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000363 (0)
index e748588e8930c2976d270bc03f8e88d1ff969551..49f9b403d45846c65a96458117c99253021bc866 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef __MACH_BF548_H__
 #define __MACH_BF548_H__
 
-#define SUPPORTED_REVID 0
-
 #define OFFSET_(x) ((x) & 0x0000FFFF)
 
 /*some misc defines*/
 
 #if defined(CONFIG_BF542)
 # define CPU   "BF542"
-# define CPUID 0x027c8000
+# define CPUID 0x27de
 #elif defined(CONFIG_BF544)
-# define CPU "BF544"
-# define CPUID 0x027c8000
+# define CPU   "BF544"
+# define CPUID 0x27de
 #elif defined(CONFIG_BF547)
-# define CPU "BF547"
+# define CPU   "BF547"
+# define CPUID 0x27de
 #elif defined(CONFIG_BF548)
-# define CPU "BF548"
-# define CPUID 0x027c6000
+# define CPU   "BF548"
+# define CPUID 0x27de
 #elif defined(CONFIG_BF549)
-# define CPU "BF549"
-#else
-# define CPU "UNKNOWN"
-# define CPUID 0x0
+# define CPU   "BF549"
+# define CPUID 0x27de
+#endif
+
+#ifndef CPU
+#error Unknown CPU type - This kernel doesn't seem to be configured properly
 #endif
 
 #endif /* __MACH_BF48_H__  */
index 5e29446a8e03dde1acbf65bcc136a8cb83f5f60a..e4cf35e7ab9fd6c8a4adf80d10090e821a266ba3 100644 (file)
@@ -82,6 +82,9 @@
 #  define CONFIG_UART1_RTS_PIN -1
 # endif
 #endif
+
+#define BFIN_UART_TX_FIFO_SIZE 2
+
 /*
  * The pin configuration is different from schematic
  */
@@ -105,7 +108,6 @@ struct bfin_serial_port {
 #endif
 };
 
-struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -170,8 +172,6 @@ struct bfin_serial_res bfin_serial_resource[] = {
 #endif
 };
 
-int nr_ports = ARRAY_SIZE(bfin_serial_resource);
-
 #define DRIVER_NAME "bfin-uart"
 
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
index f99f47bc3a0796162796c75470497742a80d992c..a2228428dc065e11cc5fc6df3674fadbb5933147 100644 (file)
 #endif /*CONFIG_BFIN_DCACHE*/
 
 /* Level 2 Memory */
-#if !defined(CONFIG_BF542)
-# define L2_START          0xFEB00000
-# if defined(CONFIG_BF544)
-#  define L2_LENGTH        0x10000
-# else
-#  define L2_LENGTH        0x20000
-# endif
+#define L2_START            0xFEB00000
+#if defined(CONFIG_BF542)
+# define L2_LENGTH          0
+#elif defined(CONFIG_BF544)
+# define L2_LENGTH          0x10000
+#else
+# define L2_LENGTH          0x20000
 #endif
 
 /* Scratch Pad Memory */
index 75ea6a9058296fd62c4386e9b9ebec2a1e5c3342..31a777a9e69996d51d0947de84c33883a23b8e1f 100644 (file)
@@ -77,6 +77,9 @@ ENTRY(_start_dma_code)
        r1 = PLL_BYPASS;                 /* Bypass the PLL?                 */
        r1 = r1 << 8;                    /* Shift it over                   */
        r0 = r1 | r0;                    /* add them all together           */
+#ifdef ANOMALY_05000265
+       BITSET(r0, 15);                  /* Add 250 mV of hysteresis to SPORT input pins */
+#endif
 
        p0.h = hi(PLL_CTL);
        p0.l = lo(PLL_CTL);              /* Load the address                */
index 5c5d7d7d695fdc0b663c27f019f6d2c7900a9c3f..22990df04ae1b5024bee767ed3f4d46730cdcbad 100644 (file)
 #define ANOMALY_05000183 (0)
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
+#define ANOMALY_05000353 (1)
+#define ANOMALY_05000386 (1)
 
 #endif
index 3ef9e5f36136d09f3f385142589b8b92b7301e93..18b1b3a223abdf2b6c40a6eae0a1810b18eb886c 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef __MACH_BF561_H__
 #define __MACH_BF561_H__
 
-#define SUPPORTED_REVID                0x3
-
 #define OFFSET_(x) ((x) & 0x0000FFFF)
 
 /*some misc defines*/
 
 #ifdef CONFIG_BF561
 #define CPU "BF561"
-#define CPUID 0x027bb000
+#define CPUID 0x27bb
 #endif
+
 #ifndef CPU
-#define CPU "UNKNOWN"
-#define CPUID 0x0
+#error Unknown CPU type - This kernel doesn't seem to be configured properly
 #endif
 
 #endif                         /* __MACH_BF561_H__  */
index 8aa02780e642ccde6deee3e79b4fe401d481902d..043bfcf26c52a2250c4399a484904e0e0906e9af 100644 (file)
@@ -69,6 +69,8 @@
 # endif
 #endif
 
+#define BFIN_UART_TX_FIFO_SIZE 2
+
 struct bfin_serial_port {
         struct uart_port        port;
         unsigned int            old_status;
@@ -83,7 +85,7 @@ struct bfin_serial_port {
        unsigned int            rx_dma_channel;
        struct work_struct      tx_dma_workqueue;
 #else
-# if ANOMALY_05000230
+# if ANOMALY_05000363
        unsigned int anomaly_threshold;
 # endif
 #endif
@@ -111,7 +113,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
        bfin_write16(uart->port.membase + OFFSET_LSR, -1);
 }
 
-struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
 struct bfin_serial_res {
        unsigned long   uart_base_addr;
        int             uart_irq;
@@ -142,7 +143,6 @@ struct bfin_serial_res bfin_serial_resource[] = {
 
 #define DRIVER_NAME "bfin-uart"
 
-int nr_ports = BFIN_UART_NR_PORTS;
 static void bfin_serial_hw_init(struct bfin_serial_port *uart)
 {
 
@@ -158,7 +158,7 @@ static void bfin_serial_hw_init(struct bfin_serial_port *uart)
        }
        if (uart->rts_pin >= 0) {
                gpio_request(uart->rts_pin, DRIVER_NAME);
-               gpio_direction_input(uart->rts_pin, 0);
+               gpio_direction_output(uart->rts_pin, 0);
        }
 #endif
 }
index c26d8486cc4b833d85ed36204f5642c2c2608dce..f1d4c0637bd2f7fb762ae981b08e2577243fd5fd 100644 (file)
 /* Memory Map for ADSP-BF561 processors */
 
 #ifdef CONFIG_BF561
-#define L1_CODE_START     0xFFA00000
-#define L1_DATA_A_START     0xFF800000
-#define L1_DATA_B_START     0xFF900000
+#define COREA_L1_CODE_START       0xFFA00000
+#define COREA_L1_DATA_A_START     0xFF800000
+#define COREA_L1_DATA_B_START     0xFF900000
+#define COREB_L1_CODE_START       0xFF600000
+#define COREB_L1_DATA_A_START     0xFF400000
+#define COREB_L1_DATA_B_START     0xFF500000
+
+#define L1_CODE_START       COREA_L1_CODE_START
+#define L1_DATA_A_START     COREA_L1_DATA_A_START
+#define L1_DATA_B_START     COREA_L1_DATA_B_START
 
 #define L1_CODE_LENGTH      0x4000
 
 
 /* Scratch Pad Memory */
 
-#define L1_SCRATCH_START       0xFFB00000
+#define COREA_L1_SCRATCH_START 0xFFB00000
+#define COREB_L1_SCRATCH_START 0xFF700000
+
+#define L1_SCRATCH_START       COREA_L1_SCRATCH_START
 #define L1_SCRATCH_LENGTH      0x1000
 
 #endif                         /* _MEM_MAP_533_H_ */
index 85f8c79b3c377b1c2a9e0d4f01fc370a4e4bce6e..db532181fbdeb9200a6d445b6f7fd940cd088830 100644 (file)
 /*
- * File:         arch/blackfin/mach-common/cache.S
- * Based on:
- * Author:       LG Soft India
+ * Blackfin cache control code
  *
- * Created:
- * Description:  cache control support
+ * Copyright 2004-2008 Analog Devices Inc.
  *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
  *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/linkage.h>
-#include <asm/cplb.h>
-#include <asm/entry.h>
 #include <asm/blackfin.h>
 #include <asm/cache.h>
+#include <asm/page.h>
 
 .text
 
-/*
- * blackfin_cache_flush_range(start, end)
- * Invalidate all cache lines assocoiated with this
- * area of memory.
+/* Since all L1 caches work the same way, we use the same method for flushing
+ * them.  Only the actual flush instruction differs.  We write this in asm as
+ * GCC can be hard to coax into writing nice hardware loops.
  *
- * start:      Start address
- * end:                End address
+ * Also, we assume the following register setup:
+ * R0 = start address
+ * R1 = end address
  */
-ENTRY(_blackfin_icache_flush_range)
+.macro do_flush flushins:req optflushins optnopins label
+
+       /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */
+       R1 += -1;
        R2 = -L1_CACHE_BYTES;
-       R2 = R0 & R2;
-       P0 = R2;
-       P1 = R1;
-       CSYNC(R3);
-       IFLUSH [P0];
+       R1 = R1 & R2;
+       R1 += L1_CACHE_BYTES;
+
+       /* count = (end - start) >> L1_CACHE_SHIFT */
+       R2 = R1 - R0;
+       R2 >>= L1_CACHE_SHIFT;
+       P1 = R2;
+
+.ifnb \label
+\label :
+.endif
+       P0 = R0;
+       LSETUP (1f, 2f) LC1 = P1;
 1:
-       IFLUSH [P0++];
-       CC = P0 < P1 (iu);
-       IF CC JUMP 1b (bp);
-       IFLUSH [P0];
-       SSYNC(R3);
+.ifnb \optflushins
+       \optflushins [P0];
+.endif
+.ifb \optnopins
+2:
+.endif
+       \flushins [P0++];
+.ifnb \optnopins
+2: \optnopins;
+.endif
+
        RTS;
-ENDPROC(_blackfin_icache_flush_range)
+.endm
 
-/*
- * blackfin_icache_dcache_flush_range(start, end)
- * FLUSH all cache lines assocoiated with this
- * area of memory.
- *
- * start:      Start address
- * end:                End address
- */
+/* Invalidate all instruction cache lines assocoiated with this memory area */
+ENTRY(_blackfin_icache_flush_range)
+       do_flush IFLUSH, , nop
+ENDPROC(_blackfin_icache_flush_range)
 
+/* Flush all cache lines assocoiated with this area of memory. */
 ENTRY(_blackfin_icache_dcache_flush_range)
-       R2 = -L1_CACHE_BYTES;
-       R2 = R0 & R2;
-       P0 = R2;
-       P1 = R1;
-       CSYNC(R3);
-       IFLUSH [P0];
-1:
-       FLUSH [P0];
-       IFLUSH [P0++];
-       CC = P0 < P1 (iu);
-       IF CC JUMP 1b (bp);
-       IFLUSH [P0];
-       FLUSH [P0];
-       SSYNC(R3);
-       RTS;
+       do_flush IFLUSH, FLUSH
 ENDPROC(_blackfin_icache_dcache_flush_range)
 
 /* Throw away all D-cached data in specified region without any obligation to
- * write them back. However, we must clean the D-cached entries around the
- * boundaries of the start and/or end address is not cache aligned.
- *
- * Start: start address,
- * end  : end address.
+ * write them back.  Since the Blackfin ISA does not have an "invalidate"
+ * instruction, we use flush/invalidate.  Perhaps as a speed optimization we
+ * could bang on the DTEST MMRs ...
  */
-
 ENTRY(_blackfin_dcache_invalidate_range)
-       R2 = -L1_CACHE_BYTES;
-       R2 = R0 & R2;
-       P0 = R2;
-       P1 = R1;
-       CSYNC(R3);
-       FLUSHINV[P0];
-1:
-       FLUSHINV[P0++];
-       CC = P0 < P1 (iu);
-       IF CC JUMP 1b (bp);
-
-       /* If the data crosses a cache line, then we'll be pointing to
-        * the last cache line, but won't have flushed/invalidated it yet,
-        * so do one more.
-        */
-       FLUSHINV[P0];
-       SSYNC(R3);
-       RTS;
+       do_flush FLUSHINV
 ENDPROC(_blackfin_dcache_invalidate_range)
 
+/* Flush all data cache lines assocoiated with this memory area */
 ENTRY(_blackfin_dcache_flush_range)
-       R2 = -L1_CACHE_BYTES;
-       R2 = R0 & R2;
-       P0 = R2;
-       P1 = R1;
-       CSYNC(R3);
-       FLUSH[P0];
-1:
-       FLUSH[P0++];
-       CC = P0 < P1 (iu);
-       IF CC JUMP 1b (bp);
-
-       /* If the data crosses a cache line, then we'll be pointing to
-        * the last cache line, but won't have flushed it yet, so do
-        * one more.
-        */
-       FLUSH[P0];
-       SSYNC(R3);
-       RTS;
+       do_flush FLUSH, , , .Ldfr
 ENDPROC(_blackfin_dcache_flush_range)
 
+/* Our headers convert the page structure to an address, so just need to flush
+ * its contents like normal.  We know the start address is page aligned (which
+ * greater than our cache alignment), as is the end address.  So just jump into
+ * the middle of the dcache flush function.
+ */
 ENTRY(_blackfin_dflush_page)
        P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
-       P0 = R0;
-       CSYNC(R3);
-       FLUSH[P0];
-       LSETUP (.Lfl1, .Lfl1) LC0 = P1;
-.Lfl1: FLUSH [P0++];
-       SSYNC(R3);
-       RTS;
+       jump .Ldfr;
 ENDPROC(_blackfin_dflush_page)
index 75cdad291e889be2b3b1a761c6304d9308d46118..c22c47b601273771d71306bbfbb264a6c66b8605 100644 (file)
@@ -158,8 +158,6 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
                                                 dpm_state_table[index].tscale);
        }
 
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
        policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000;
        /*Now ,only support one cpu */
        policy->cur = cclk;
index 847c172a99ebcd9a31c0940718077fe6556dbe92..c13fa8da28c7fbbd7aae0377358e9e10f9babff5 100644 (file)
@@ -129,6 +129,18 @@ ENTRY(_ex_icplb_miss)
 #else
        call __cplb_hdr;
 #endif
+
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+       /* While we were processing this, did we double fault? */
+       r7 = SEQSTAT;           /* reason code is in bit 5:0 */
+       r6.l = lo(SEQSTAT_EXCAUSE);
+       r6.h = hi(SEQSTAT_EXCAUSE);
+       r7 = r7 & r6;
+       r6 = 0x25;
+       CC = R7 == R6;
+       if CC JUMP _double_fault;
+#endif
+
        DEBUG_HWTRACE_RESTORE(p5, r7)
        RESTORE_ALL_SYS
        SP = EX_SCRATCH_REG;
@@ -136,11 +148,8 @@ ENTRY(_ex_icplb_miss)
 ENDPROC(_ex_icplb_miss)
 
 ENTRY(_ex_syscall)
-       (R7:6,P5:4) = [sp++];
-       ASTAT = [sp++];
        raise 15;               /* invoked by TRAP #0, for sys call */
-       sp = EX_SCRATCH_REG;
-       rtx
+       jump.s _bfin_return_from_exception;
 ENDPROC(_ex_syscall)
 
 ENTRY(_ex_soft_bp)
@@ -181,8 +190,8 @@ ENTRY(_ex_single_step)
        if cc jump .Lfind_priority_done;
        jump.s .Lfind_priority_start;
 .Lfind_priority_done:
-       p4.l = _debugger_step;
-       p4.h = _debugger_step;
+       p4.l = _kgdb_single_step;
+       p4.h = _kgdb_single_step;
        r6 = [p4];
        cc = r6 == 0;
        if cc jump .Ldo_single_step;
@@ -250,6 +259,29 @@ ENTRY(_bfin_return_from_exception)
        R7=LC1;
        LC1=R7;
 #endif
+
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+       /* While we were processing the current exception,
+        * did we cause another, and double fault?
+        */
+       r7 = SEQSTAT;           /* reason code is in bit 5:0 */
+       r6.l = lo(SEQSTAT_EXCAUSE);
+       r6.h = hi(SEQSTAT_EXCAUSE);
+       r7 = r7 & r6;
+       r6 = 0x25;
+       CC = R7 == R6;
+       if CC JUMP _double_fault;
+
+       /* Did we cause a HW error? */
+       p5.l = lo(ILAT);
+       p5.h = hi(ILAT);
+       r6 = [p5];
+       r7 = 0x20;              /* Did I just cause anther HW error? */
+       r7 = r7 & r1;
+       CC = R7 == R6;
+       if CC JUMP _double_fault;
+#endif
+
        (R7:6,P5:4) = [sp++];
        ASTAT = [sp++];
        sp = EX_SCRATCH_REG;
@@ -292,6 +324,14 @@ ENTRY(_ex_trap_c)
        [p4] = p5;
        csync;
 
+#ifndef CONFIG_DEBUG_DOUBLEFAULT
+       /*
+        * Save these registers, as they are only valid in exception context
+        *  (where we are now - as soon as we defer to IRQ5, they can change)
+        * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3,
+        * but they are not very interesting, so don't save them
+        */
+
        p4.l = lo(DCPLB_FAULT_ADDR);
        p4.h = hi(DCPLB_FAULT_ADDR);
        r7 = [p4];
@@ -304,12 +344,11 @@ ENTRY(_ex_trap_c)
        p5.l = _saved_icplb_fault_addr;
        [p5] = r7;
 
-       p4.l = _excpt_saved_stuff;
-       p4.h = _excpt_saved_stuff;
-
        r6 = retx;
+       p4.l = _saved_retx;
+       p4.h = _saved_retx;
        [p4] = r6;
-
+#endif
        r6 = SYSCFG;
        [p4 + 4] = r6;
        BITCLR(r6, 0);
@@ -327,59 +366,56 @@ ENTRY(_ex_trap_c)
        r6 = 0x3f;
        sti r6;
 
-       (R7:6,P5:4) = [sp++];
-       ASTAT = [sp++];
-       SP = EX_SCRATCH_REG;
        raise 5;
-       rtx;
+       jump.s _bfin_return_from_exception;
 ENDPROC(_ex_trap_c)
 
 /* We just realized we got an exception, while we were processing a different
  * exception. This is a unrecoverable event, so crash
  */
 ENTRY(_double_fault)
-        /* Turn caches & protection off, to ensure we don't get any more
-         * double exceptions
-         */
-
-        P4.L = LO(IMEM_CONTROL);
-        P4.H = HI(IMEM_CONTROL);
-
-        R5 = [P4];              /* Control Register*/
-        BITCLR(R5,ENICPLB_P);
-        SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
-        .align 8;
-        [P4] = R5;
-        SSYNC;
-
-        P4.L = LO(DMEM_CONTROL);
-        P4.H = HI(DMEM_CONTROL);
-        R5 = [P4];
-        BITCLR(R5,ENDCPLB_P);
-        SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
-        .align 8;
-        [P4] = R5;
-        SSYNC;
-
-        /* Fix up the stack */
-        (R7:6,P5:4) = [sp++];
-        ASTAT = [sp++];
-        SP = EX_SCRATCH_REG;
-
-        /* We should be out of the exception stack, and back down into
-         * kernel or user space stack
-         */
-        SAVE_ALL_SYS
+       /* Turn caches & protection off, to ensure we don't get any more
+        * double exceptions
+        */
+
+       P4.L = LO(IMEM_CONTROL);
+       P4.H = HI(IMEM_CONTROL);
+
+       R5 = [P4];              /* Control Register*/
+       BITCLR(R5,ENICPLB_P);
+       SSYNC;          /* SSYNC required before writing to IMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+
+       P4.L = LO(DMEM_CONTROL);
+       P4.H = HI(DMEM_CONTROL);
+       R5 = [P4];
+       BITCLR(R5,ENDCPLB_P);
+       SSYNC;          /* SSYNC required before writing to DMEM_CONTROL. */
+       .align 8;
+       [P4] = R5;
+       SSYNC;
+
+       /* Fix up the stack */
+       (R7:6,P5:4) = [sp++];
+       ASTAT = [sp++];
+       SP = EX_SCRATCH_REG;
+
+       /* We should be out of the exception stack, and back down into
+        * kernel or user space stack
+        */
+       SAVE_ALL_SYS
 
        /* The dumping functions expect the return address in the RETI
         * slot.  */
        r6 = retx;
        [sp + PT_PC] = r6;
 
-        r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
-        SP += -12;
-        call _double_fault_c;
-        SP += 12;
+       r0 = sp;        /* stack frame pt_regs pointer argument ==> r0 */
+       SP += -12;
+       call _double_fault_c;
+       SP += 12;
 .L_double_fault_panic:
         JUMP .L_double_fault_panic
 
@@ -388,8 +424,8 @@ ENDPROC(_double_fault)
 ENTRY(_exception_to_level5)
        SAVE_ALL_SYS
 
-       p4.l = _excpt_saved_stuff;
-       p4.h = _excpt_saved_stuff;
+       p4.l = _saved_retx;
+       p4.h = _saved_retx;
        r6 = [p4];
        [sp + PT_PC] = r6;
 
@@ -420,6 +456,17 @@ ENTRY(_exception_to_level5)
        call _trap_c;
        SP += 12;
 
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+       /* Grab ILAT */
+       p2.l = lo(ILAT);
+       p2.h = hi(ILAT);
+       r0 = [p2];
+       r1 = 0x20;  /* Did I just cause anther HW error? */
+       r0 = r0 & r1;
+       CC = R0 == R1;
+       if CC JUMP _double_fault;
+#endif
+
        call _ret_from_exception;
        RESTORE_ALL_SYS
        rti;
@@ -436,7 +483,48 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
        /* Try to deal with syscalls quickly.  */
        [--sp] = ASTAT;
        [--sp] = (R7:6,P5:4);
+
+#if ANOMALY_05000283 || ANOMALY_05000315
+       cc = r7 == r7;
+       p5.h = HI(CHIPID);
+       p5.l = LO(CHIPID);
+       if cc jump 1f;
+       r7.l = W[p5];
+1:
+#endif
+
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+       /*
+        * Save these registers, as they are only valid in exception context
+        * (where we are now - as soon as we defer to IRQ5, they can change)
+        * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3,
+        * but they are not very interesting, so don't save them
+        */
+
+       p4.l = lo(DCPLB_FAULT_ADDR);
+       p4.h = hi(DCPLB_FAULT_ADDR);
+       r7 = [p4];
+       p5.h = _saved_dcplb_fault_addr;
+       p5.l = _saved_dcplb_fault_addr;
+       [p5] = r7;
+
+       r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
+       p5.h = _saved_icplb_fault_addr;
+       p5.l = _saved_icplb_fault_addr;
+       [p5] = r7;
+
+       p4.l = _saved_retx;
+       p4.h = _saved_retx;
+       r6 = retx;
+       [p4] = r6;
+
        r7 = SEQSTAT;           /* reason code is in bit 5:0 */
+       p4.l = _saved_seqstat;
+       p4.h = _saved_seqstat;
+       [p4] = r7;
+#else
+       r7 = SEQSTAT;           /* reason code is in bit 5:0 */
+#endif
        r6.l = lo(SEQSTAT_EXCAUSE);
        r6.h = hi(SEQSTAT_EXCAUSE);
        r7 = r7 & r6;
@@ -616,6 +704,9 @@ ENTRY(_system_call)
        rts;
 ENDPROC(_system_call)
 
+/* Do not mark as ENTRY() to avoid error in assembler ...
+ * this symbol need not be global anyways, so ...
+ */
 _sys_trace:
        call _syscall_trace;
 
@@ -941,6 +1032,15 @@ ENTRY(_early_trap)
        SAVE_ALL_SYS
        trace_buffer_stop(p0,r0);
 
+#if ANOMALY_05000283 || ANOMALY_05000315
+       cc = r5 == r5;
+       p4.h = HI(CHIPID);
+       p4.l = LO(CHIPID);
+       if cc jump 1f;
+       r5.l = W[p4];
+1:
+#endif
+
        /* Turn caches off, to ensure we don't get double exceptions */
 
        P4.L = LO(IMEM_CONTROL);
@@ -992,7 +1092,12 @@ ENTRY(_ex_table)
         */
        .long _ex_syscall       /* 0x00 - User Defined - Linux Syscall */
        .long _ex_soft_bp       /* 0x01 - User Defined - Software breakpoint */
+#ifdef CONFIG_KGDB
+       .long _ex_trap_c        /* 0x02 - User Defined - KGDB initial connection
+                                                        and break signal trap */
+#else
        .long _ex_replaceable   /* 0x02 - User Defined */
+#endif
        .long _ex_trap_c        /* 0x03 - User Defined - userspace stack overflow */
        .long _ex_trap_c        /* 0x04 - User Defined - dump trace buffer */
        .long _ex_replaceable   /* 0x05 - User Defined */
@@ -1432,15 +1537,7 @@ ENTRY(_sys_call_table)
        .rept NR_syscalls-(.-_sys_call_table)/4
        .long _sys_ni_syscall
        .endr
-
-       /*
-        * Used to save the real RETX, IMASK and SYSCFG when temporarily
-        * storing safe values across the transition from exception to IRQ5.
-        */
-_excpt_saved_stuff:
-       .long 0;
-       .long 0;
-       .long 0;
+END(_sys_call_table)
 
 _exception_stack:
        .rept 1024
index 191b4e974c4b6288047e3d74ef507fb69b5119f4..f123a62e2451ca5acaabbd866030118267a93e35 100644 (file)
@@ -68,6 +68,16 @@ ENTRY(__start)
        M2 = r0;
        M3 = r0;
 
+       /*
+        * Clear ITEST_COMMAND and DTEST_COMMAND registers,
+        * Leaving these as non-zero can confuse the emulator
+        */
+       p0.L = LO(DTEST_COMMAND);
+       p0.H = HI(DTEST_COMMAND);
+       [p0] = R0;
+       [p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0;
+       CSYNC;
+
        trace_buffer_init(p0,r0);
        P0 = R1;
        R0 = R1;
@@ -90,12 +100,46 @@ ENTRY(__start)
        [p0] = R0;
        SSYNC;
 
-       /* Save RETX, in case of doublefault */
-       p0.l = ___retx;
-       p0.h = ___retx;
+       /* in case of double faults, save a few things */
+       p0.l = _init_retx;
+       p0.h = _init_retx;
        R0 = RETX;
        [P0] = R0;
 
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+       /* Only save these if we are storing them,
+        * This happens here, since L1 gets clobbered
+        * below
+        */
+       p0.l = _saved_retx;
+       p0.h = _saved_retx;
+       p1.l = _init_saved_retx;
+       p1.h = _init_saved_retx;
+       r0 = [p0];
+       [p1] = r0;
+
+       p0.l = _saved_dcplb_fault_addr;
+       p0.h = _saved_dcplb_fault_addr;
+       p1.l = _init_saved_dcplb_fault_addr;
+       p1.h = _init_saved_dcplb_fault_addr;
+       r0 = [p0];
+       [p1] = r0;
+
+       p0.l = _saved_icplb_fault_addr;
+       p0.h = _saved_icplb_fault_addr;
+       p1.l = _init_saved_icplb_fault_addr;
+       p1.h = _init_saved_icplb_fault_addr;
+       r0 = [p0];
+       [p1] = r0;
+
+       p0.l = _saved_seqstat;
+       p0.h = _saved_seqstat;
+       p1.l = _init_saved_seqstat;
+       p1.h = _init_saved_seqstat;
+       r0 = [p0];
+       [p1] = r0;
+#endif
+
        /* Initialize stack pointer */
        sp.l = lo(INITIAL_STACK);
        sp.h = hi(INITIAL_STACK);
@@ -107,7 +151,7 @@ ENTRY(__start)
 #endif
 
        /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
-       call _bf53x_relocate_l1_mem;
+       call _bfin_relocate_l1_mem;
 #ifdef CONFIG_BFIN_KERNEL_CLOCK
        call _start_dma_code;
 #endif
@@ -162,6 +206,60 @@ ENTRY(_real_start)
        w[p0] = r0;
        ssync;
 
+#if L1_DATA_A_LENGTH > 0
+       r1.l = __sbss_l1;
+       r1.h = __sbss_l1;
+       r2.l = __ebss_l1;
+       r2.h = __ebss_l1;
+       r0 = 0 (z);
+       r2 = r2 - r1;
+       cc = r2 == 0;
+       if cc jump .L_a_l1_done;
+       r2 >>= 2;
+       p1 = r1;
+       p2 = r2;
+       lsetup (.L_clear_a_l1, .L_clear_a_l1 ) lc0 = p2;
+.L_clear_a_l1:
+       [p1++] = r0;
+.L_a_l1_done:
+#endif
+
+#if L1_DATA_B_LENGTH > 0
+       r1.l = __sbss_b_l1;
+       r1.h = __sbss_b_l1;
+       r2.l = __ebss_b_l1;
+       r2.h = __ebss_b_l1;
+       r0 = 0 (z);
+       r2 = r2 - r1;
+       cc = r2 == 0;
+       if cc jump .L_b_l1_done;
+       r2 >>= 2;
+       p1 = r1;
+       p2 = r2;
+       lsetup (.L_clear_b_l1, .L_clear_b_l1 ) lc0 = p2;
+.L_clear_b_l1:
+       [p1++] = r0;
+.L_b_l1_done:
+#endif
+
+#if L2_LENGTH > 0
+       r1.l = __sbss_l2;
+       r1.h = __sbss_l2;
+       r2.l = __ebss_l2;
+       r2.h = __ebss_l2;
+       r0 = 0 (z);
+       r2 = r2 - r1;
+       cc = r2 == 0;
+       if cc jump .L_l2_done;
+       r2 >>= 2;
+       p1 = r1;
+       p2 = r2;
+       lsetup (.L_clear_l2, .L_clear_l2 ) lc0 = p2;
+.L_clear_l2:
+       [p1++] = r0;
+.L_l2_done:
+#endif
+
        /* Zero out the bss region
         * Note: this will fail if bss is 0 bytes ...
         */
index b27e59d32401ac1143d1cc1f6676f8b8eb9dc512..4a2ec7a9675a95698638d6b942c59c6de6fc6cfc 100644 (file)
@@ -143,7 +143,7 @@ ENTRY(_evt_ivhw)
        fp = 0;
 #endif
 
-#if ANOMALY_05000283
+#if ANOMALY_05000283 || ANOMALY_05000315
        cc = r7 == r7;
        p5.h = HI(CHIPID);
        p5.l = LO(CHIPID);
@@ -179,7 +179,16 @@ ENTRY(_evt_ivhw)
        call _trap_c;
        SP += 12;
 
+#ifdef EBIU_ERRMST
+       /* make sure EBIU_ERRMST is clear */
+       p0.l = LO(EBIU_ERRMST);
+       p0.h = HI(EBIU_ERRMST);
+       r0.l = (CORE_ERROR | CORE_MERROR);
+       w[p0] = r0.l;
+#endif
+
        call _ret_from_exception;
+
 .Lcommon_restore_all_sys:
        RESTORE_ALL_SYS
        rti;
index 5fa536727c61b574b6d35671aec7299b9696a415..34e8a726ffda2fd4d8796f83b4cd285264791f77 100644 (file)
@@ -243,12 +243,14 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
 #endif
 
 static struct irq_chip bfin_core_irqchip = {
+       .name = "CORE",
        .ack = bfin_ack_noop,
        .mask = bfin_core_mask_irq,
        .unmask = bfin_core_unmask_irq,
 };
 
 static struct irq_chip bfin_internal_irqchip = {
+       .name = "INTN",
        .ack = bfin_ack_noop,
        .mask = bfin_internal_mask_irq,
        .unmask = bfin_internal_unmask_irq,
@@ -278,6 +280,7 @@ static void bfin_generic_error_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip bfin_generic_error_irqchip = {
+       .name = "ERROR",
        .ack = bfin_ack_noop,
        .mask_ack = bfin_generic_error_mask_irq,
        .mask = bfin_generic_error_mask_irq,
@@ -361,6 +364,14 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
 }
 #endif                         /* BF537_GENERIC_ERROR_INT_DEMUX */
 
+static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
+{
+       struct irq_desc *desc = irq_desc + irq;
+       /* May not call generic set_irq_handler() due to spinlock
+          recursion. */
+       desc->handle_irq = handle;
+}
+
 #if !defined(CONFIG_BF54x)
 
 static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -473,9 +484,9 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
        SSYNC();
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
-               set_irq_handler(irq, handle_edge_irq);
+               bfin_set_irq_handler(irq, handle_edge_irq);
        else
-               set_irq_handler(irq, handle_level_irq);
+               bfin_set_irq_handler(irq, handle_level_irq);
 
        return 0;
 }
@@ -495,6 +506,7 @@ int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
 #endif
 
 static struct irq_chip bfin_gpio_irqchip = {
+       .name = "GPIO",
        .ack = bfin_gpio_ack_irq,
        .mask = bfin_gpio_mask_irq,
        .mask_ack = bfin_gpio_mask_ack_irq,
@@ -804,10 +816,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
                pint[bank]->edge_set = pintbit;
-               set_irq_handler(irq, handle_edge_irq);
+               bfin_set_irq_handler(irq, handle_edge_irq);
        } else {
                pint[bank]->edge_clear = pintbit;
-               set_irq_handler(irq, handle_level_irq);
+               bfin_set_irq_handler(irq, handle_level_irq);
        }
 
        SSYNC();
@@ -884,6 +896,7 @@ void bfin_pm_restore(void)
 #endif
 
 static struct irq_chip bfin_gpio_irqchip = {
+       .name = "GPIO",
        .ack = bfin_gpio_ack_irq,
        .mask = bfin_gpio_mask_irq,
        .mask_ack = bfin_gpio_mask_ack_irq,
@@ -1136,8 +1149,4 @@ void do_irq(int vec, struct pt_regs *fp)
                vec = ivg->irqno;
        }
        asm_do_IRQ(vec, fp);
-
-#ifdef CONFIG_KGDB
-       kgdb_process_breakpoint();
-#endif
 }
index 2a7202ce01fd4166bece9317da237f78d107c349..d489f894f4b1d7451fc7cdedb8cf1ce9049b371b 100644 (file)
@@ -2,4 +2,4 @@
 # arch/blackfin/mm/Makefile
 #
 
-obj-y := blackfin_sram.o init.o
+obj-y := sram-alloc.o isram-driver.o init.o
diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
deleted file mode 100644 (file)
index 4f5e887..0000000
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- * File:         arch/blackfin/mm/blackfin_sram.c
- * Based on:
- * Author:
- *
- * Created:
- * Description:  SRAM driver for Blackfin ADSP-BF5xx
- *
- * Modified:
- *               Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/rtc.h>
-#include <asm/blackfin.h>
-#include "blackfin_sram.h"
-
-static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
-static spinlock_t l2_sram_lock;
-
-/* the data structure for L1 scratchpad and DATA SRAM */
-struct sram_piece {
-       void *paddr;
-       int size;
-       pid_t pid;
-       struct sram_piece *next;
-};
-
-static struct sram_piece free_l1_ssram_head, used_l1_ssram_head;
-
-#if L1_DATA_A_LENGTH != 0
-static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head;
-#endif
-
-#if L1_DATA_B_LENGTH != 0
-static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head;
-#endif
-
-#if L1_CODE_LENGTH != 0
-static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head;
-#endif
-
-#if L2_LENGTH != 0
-static struct sram_piece free_l2_sram_head, used_l2_sram_head;
-#endif
-
-static struct kmem_cache *sram_piece_cache;
-
-/* L1 Scratchpad SRAM initialization function */
-static void __init l1sram_init(void)
-{
-       free_l1_ssram_head.next =
-               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-       if (!free_l1_ssram_head.next) {
-               printk(KERN_INFO"Fail to initialize Scratchpad data SRAM.\n");
-               return;
-       }
-
-       free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START;
-       free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH;
-       free_l1_ssram_head.next->pid = 0;
-       free_l1_ssram_head.next->next = NULL;
-
-       used_l1_ssram_head.next = NULL;
-
-       /* mutex initialize */
-       spin_lock_init(&l1sram_lock);
-
-       printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
-              L1_SCRATCH_LENGTH >> 10);
-}
-
-static void __init l1_data_sram_init(void)
-{
-#if L1_DATA_A_LENGTH != 0
-       free_l1_data_A_sram_head.next =
-               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-       if (!free_l1_data_A_sram_head.next) {
-               printk(KERN_INFO"Fail to initialize L1 Data A SRAM.\n");
-               return;
-       }
-
-       free_l1_data_A_sram_head.next->paddr =
-               (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1);
-       free_l1_data_A_sram_head.next->size =
-               L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
-       free_l1_data_A_sram_head.next->pid = 0;
-       free_l1_data_A_sram_head.next->next = NULL;
-
-       used_l1_data_A_sram_head.next = NULL;
-
-       printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
-               L1_DATA_A_LENGTH >> 10,
-               free_l1_data_A_sram_head.next->size >> 10);
-#endif
-#if L1_DATA_B_LENGTH != 0
-       free_l1_data_B_sram_head.next =
-               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-       if (!free_l1_data_B_sram_head.next) {
-               printk(KERN_INFO"Fail to initialize L1 Data B SRAM.\n");
-               return;
-       }
-
-       free_l1_data_B_sram_head.next->paddr =
-               (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1);
-       free_l1_data_B_sram_head.next->size =
-               L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
-       free_l1_data_B_sram_head.next->pid = 0;
-       free_l1_data_B_sram_head.next->next = NULL;
-
-       used_l1_data_B_sram_head.next = NULL;
-
-       printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
-               L1_DATA_B_LENGTH >> 10,
-               free_l1_data_B_sram_head.next->size >> 10);
-#endif
-
-       /* mutex initialize */
-       spin_lock_init(&l1_data_sram_lock);
-}
-
-static void __init l1_inst_sram_init(void)
-{
-#if L1_CODE_LENGTH != 0
-       free_l1_inst_sram_head.next =
-               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-       if (!free_l1_inst_sram_head.next) {
-               printk(KERN_INFO"Fail to initialize L1 Instruction SRAM.\n");
-               return;
-       }
-
-       free_l1_inst_sram_head.next->paddr =
-               (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
-       free_l1_inst_sram_head.next->size =
-               L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
-       free_l1_inst_sram_head.next->pid = 0;
-       free_l1_inst_sram_head.next->next = NULL;
-
-       used_l1_inst_sram_head.next = NULL;
-
-       printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
-               L1_CODE_LENGTH >> 10,
-               free_l1_inst_sram_head.next->size >> 10);
-#endif
-
-       /* mutex initialize */
-       spin_lock_init(&l1_inst_sram_lock);
-}
-
-static void __init l2_sram_init(void)
-{
-#if L2_LENGTH != 0
-       free_l2_sram_head.next =
-               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-       if (!free_l2_sram_head.next) {
-               printk(KERN_INFO"Fail to initialize L2 SRAM.\n");
-               return;
-       }
-
-       free_l2_sram_head.next->paddr = (void *)L2_START +
-               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
-       free_l2_sram_head.next->size = L2_LENGTH -
-               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
-       free_l2_sram_head.next->pid = 0;
-       free_l2_sram_head.next->next = NULL;
-
-       used_l2_sram_head.next = NULL;
-
-       printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n",
-               L2_LENGTH >> 10,
-               free_l2_sram_head.next->size >> 10);
-#endif
-
-       /* mutex initialize */
-       spin_lock_init(&l2_sram_lock);
-}
-void __init bfin_sram_init(void)
-{
-       sram_piece_cache = kmem_cache_create("sram_piece_cache",
-                               sizeof(struct sram_piece),
-                               0, SLAB_PANIC, NULL);
-
-       l1sram_init();
-       l1_data_sram_init();
-       l1_inst_sram_init();
-       l2_sram_init();
-}
-
-/* SRAM allocate function */
-static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
-               struct sram_piece *pused_head)
-{
-       struct sram_piece *pslot, *plast, *pavail;
-
-       if (size <= 0 || !pfree_head || !pused_head)
-               return NULL;
-
-       /* Align the size */
-       size = (size + 3) & ~3;
-
-       pslot = pfree_head->next;
-       plast = pfree_head;
-
-       /* search an available piece slot */
-       while (pslot != NULL && size > pslot->size) {
-               plast = pslot;
-               pslot = pslot->next;
-       }
-
-       if (!pslot)
-               return NULL;
-
-       if (pslot->size == size) {
-               plast->next = pslot->next;
-               pavail = pslot;
-       } else {
-               pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
-
-               if (!pavail)
-                       return NULL;
-
-               pavail->paddr = pslot->paddr;
-               pavail->size = size;
-               pslot->paddr += size;
-               pslot->size -= size;
-       }
-
-       pavail->pid = current->pid;
-
-       pslot = pused_head->next;
-       plast = pused_head;
-
-       /* insert new piece into used piece list !!! */
-       while (pslot != NULL && pavail->paddr < pslot->paddr) {
-               plast = pslot;
-               pslot = pslot->next;
-       }
-
-       pavail->next = pslot;
-       plast->next = pavail;
-
-       return pavail->paddr;
-}
-
-/* Allocate the largest available block.  */
-static void *_sram_alloc_max(struct sram_piece *pfree_head,
-                               struct sram_piece *pused_head,
-                               unsigned long *psize)
-{
-       struct sram_piece *pslot, *pmax;
-
-       if (!pfree_head || !pused_head)
-               return NULL;
-
-       pmax = pslot = pfree_head->next;
-
-       /* search an available piece slot */
-       while (pslot != NULL) {
-               if (pslot->size > pmax->size)
-                       pmax = pslot;
-               pslot = pslot->next;
-       }
-
-       if (!pmax)
-               return NULL;
-
-       *psize = pmax->size;
-
-       return _sram_alloc(*psize, pfree_head, pused_head);
-}
-
-/* SRAM free function */
-static int _sram_free(const void *addr,
-                       struct sram_piece *pfree_head,
-                       struct sram_piece *pused_head)
-{
-       struct sram_piece *pslot, *plast, *pavail;
-
-       if (!pfree_head || !pused_head)
-               return -1;
-
-       /* search the relevant memory slot */
-       pslot = pused_head->next;
-       plast = pused_head;
-
-       /* search an available piece slot */
-       while (pslot != NULL && pslot->paddr != addr) {
-               plast = pslot;
-               pslot = pslot->next;
-       }
-
-       if (!pslot)
-               return -1;
-
-       plast->next = pslot->next;
-       pavail = pslot;
-       pavail->pid = 0;
-
-       /* insert free pieces back to the free list */
-       pslot = pfree_head->next;
-       plast = pfree_head;
-
-       while (pslot != NULL && addr > pslot->paddr) {
-               plast = pslot;
-               pslot = pslot->next;
-       }
-
-       if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) {
-               plast->size += pavail->size;
-               kmem_cache_free(sram_piece_cache, pavail);
-       } else {
-               pavail->next = plast->next;
-               plast->next = pavail;
-               plast = pavail;
-       }
-
-       if (pslot && plast->paddr + plast->size == pslot->paddr) {
-               plast->size += pslot->size;
-               plast->next = pslot->next;
-               kmem_cache_free(sram_piece_cache, pslot);
-       }
-
-       return 0;
-}
-
-int sram_free(const void *addr)
-{
-       if (0) {}
-#if L1_CODE_LENGTH != 0
-       else if (addr >= (void *)L1_CODE_START
-                && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
-               return l1_inst_sram_free(addr);
-#endif
-#if L1_DATA_A_LENGTH != 0
-       else if (addr >= (void *)L1_DATA_A_START
-                && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
-               return l1_data_A_sram_free(addr);
-#endif
-#if L1_DATA_B_LENGTH != 0
-       else if (addr >= (void *)L1_DATA_B_START
-                && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
-               return l1_data_B_sram_free(addr);
-#endif
-#if L2_LENGTH != 0
-       else if (addr >= (void *)L2_START
-                && addr < (void *)(L2_START + L2_LENGTH))
-               return l2_sram_free(addr);
-#endif
-       else
-               return -1;
-}
-EXPORT_SYMBOL(sram_free);
-
-void *l1_data_A_sram_alloc(size_t size)
-{
-       unsigned long flags;
-       void *addr = NULL;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_data_sram_lock, flags);
-
-#if L1_DATA_A_LENGTH != 0
-       addr = _sram_alloc(size, &free_l1_data_A_sram_head,
-                       &used_l1_data_A_sram_head);
-#endif
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
-
-       pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
-                (long unsigned int)addr, size);
-
-       return addr;
-}
-EXPORT_SYMBOL(l1_data_A_sram_alloc);
-
-int l1_data_A_sram_free(const void *addr)
-{
-       unsigned long flags;
-       int ret;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_data_sram_lock, flags);
-
-#if L1_DATA_A_LENGTH != 0
-       ret = _sram_free(addr, &free_l1_data_A_sram_head,
-                       &used_l1_data_A_sram_head);
-#else
-       ret = -1;
-#endif
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(l1_data_A_sram_free);
-
-void *l1_data_B_sram_alloc(size_t size)
-{
-#if L1_DATA_B_LENGTH != 0
-       unsigned long flags;
-       void *addr;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_data_sram_lock, flags);
-
-       addr = _sram_alloc(size, &free_l1_data_B_sram_head,
-                       &used_l1_data_B_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
-
-       pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
-                (long unsigned int)addr, size);
-
-       return addr;
-#else
-       return NULL;
-#endif
-}
-EXPORT_SYMBOL(l1_data_B_sram_alloc);
-
-int l1_data_B_sram_free(const void *addr)
-{
-#if L1_DATA_B_LENGTH != 0
-       unsigned long flags;
-       int ret;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_data_sram_lock, flags);
-
-       ret = _sram_free(addr, &free_l1_data_B_sram_head,
-                       &used_l1_data_B_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
-
-       return ret;
-#else
-       return -1;
-#endif
-}
-EXPORT_SYMBOL(l1_data_B_sram_free);
-
-void *l1_data_sram_alloc(size_t size)
-{
-       void *addr = l1_data_A_sram_alloc(size);
-
-       if (!addr)
-               addr = l1_data_B_sram_alloc(size);
-
-       return addr;
-}
-EXPORT_SYMBOL(l1_data_sram_alloc);
-
-void *l1_data_sram_zalloc(size_t size)
-{
-       void *addr = l1_data_sram_alloc(size);
-
-       if (addr)
-               memset(addr, 0x00, size);
-
-       return addr;
-}
-EXPORT_SYMBOL(l1_data_sram_zalloc);
-
-int l1_data_sram_free(const void *addr)
-{
-       int ret;
-       ret = l1_data_A_sram_free(addr);
-       if (ret == -1)
-               ret = l1_data_B_sram_free(addr);
-       return ret;
-}
-EXPORT_SYMBOL(l1_data_sram_free);
-
-void *l1_inst_sram_alloc(size_t size)
-{
-#if L1_CODE_LENGTH != 0
-       unsigned long flags;
-       void *addr;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_inst_sram_lock, flags);
-
-       addr = _sram_alloc(size, &free_l1_inst_sram_head,
-                       &used_l1_inst_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
-
-       pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
-                (long unsigned int)addr, size);
-
-       return addr;
-#else
-       return NULL;
-#endif
-}
-EXPORT_SYMBOL(l1_inst_sram_alloc);
-
-int l1_inst_sram_free(const void *addr)
-{
-#if L1_CODE_LENGTH != 0
-       unsigned long flags;
-       int ret;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1_inst_sram_lock, flags);
-
-       ret = _sram_free(addr, &free_l1_inst_sram_head,
-                       &used_l1_inst_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
-
-       return ret;
-#else
-       return -1;
-#endif
-}
-EXPORT_SYMBOL(l1_inst_sram_free);
-
-/* L1 Scratchpad memory allocate function */
-void *l1sram_alloc(size_t size)
-{
-       unsigned long flags;
-       void *addr;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1sram_lock, flags);
-
-       addr = _sram_alloc(size, &free_l1_ssram_head,
-                       &used_l1_ssram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1sram_lock, flags);
-
-       return addr;
-}
-
-/* L1 Scratchpad memory allocate function */
-void *l1sram_alloc_max(size_t *psize)
-{
-       unsigned long flags;
-       void *addr;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1sram_lock, flags);
-
-       addr = _sram_alloc_max(&free_l1_ssram_head,
-                       &used_l1_ssram_head, psize);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1sram_lock, flags);
-
-       return addr;
-}
-
-/* L1 Scratchpad memory free function */
-int l1sram_free(const void *addr)
-{
-       unsigned long flags;
-       int ret;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l1sram_lock, flags);
-
-       ret = _sram_free(addr, &free_l1_ssram_head,
-                       &used_l1_ssram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l1sram_lock, flags);
-
-       return ret;
-}
-
-void *l2_sram_alloc(size_t size)
-{
-#if L2_LENGTH != 0
-       unsigned long flags;
-       void *addr;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l2_sram_lock, flags);
-
-       addr = _sram_alloc(size, &free_l2_sram_head,
-                       &used_l2_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l2_sram_lock, flags);
-
-       pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n",
-                (long unsigned int)addr, size);
-
-       return addr;
-#else
-       return NULL;
-#endif
-}
-EXPORT_SYMBOL(l2_sram_alloc);
-
-void *l2_sram_zalloc(size_t size)
-{
-       void *addr = l2_sram_alloc(size);
-
-       if (addr)
-               memset(addr, 0x00, size);
-
-       return addr;
-}
-EXPORT_SYMBOL(l2_sram_zalloc);
-
-int l2_sram_free(const void *addr)
-{
-#if L2_LENGTH != 0
-       unsigned long flags;
-       int ret;
-
-       /* add mutex operation */
-       spin_lock_irqsave(&l2_sram_lock, flags);
-
-       ret = _sram_free(addr, &free_l2_sram_head,
-                       &used_l2_sram_head);
-
-       /* add mutex operation */
-       spin_unlock_irqrestore(&l2_sram_lock, flags);
-
-       return ret;
-#else
-       return -1;
-#endif
-}
-EXPORT_SYMBOL(l2_sram_free);
-
-int sram_free_with_lsl(const void *addr)
-{
-       struct sram_list_struct *lsl, **tmp;
-       struct mm_struct *mm = current->mm;
-
-       for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
-               if ((*tmp)->addr == addr)
-                       goto found;
-       return -1;
-found:
-       lsl = *tmp;
-       sram_free(addr);
-       *tmp = lsl->next;
-       kfree(lsl);
-
-       return 0;
-}
-EXPORT_SYMBOL(sram_free_with_lsl);
-
-void *sram_alloc_with_lsl(size_t size, unsigned long flags)
-{
-       void *addr = NULL;
-       struct sram_list_struct *lsl = NULL;
-       struct mm_struct *mm = current->mm;
-
-       lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL);
-       if (!lsl)
-               return NULL;
-
-       if (flags & L1_INST_SRAM)
-               addr = l1_inst_sram_alloc(size);
-
-       if (addr == NULL && (flags & L1_DATA_A_SRAM))
-               addr = l1_data_A_sram_alloc(size);
-
-       if (addr == NULL && (flags & L1_DATA_B_SRAM))
-               addr = l1_data_B_sram_alloc(size);
-
-       if (addr == NULL && (flags & L2_SRAM))
-               addr = l2_sram_alloc(size);
-
-       if (addr == NULL) {
-               kfree(lsl);
-               return NULL;
-       }
-       lsl->addr = addr;
-       lsl->length = size;
-       lsl->next = mm->context.sram_list;
-       mm->context.sram_list = lsl;
-       return addr;
-}
-EXPORT_SYMBOL(sram_alloc_with_lsl);
-
-#ifdef CONFIG_PROC_FS
-/* Once we get a real allocator, we'll throw all of this away.
- * Until then, we need some sort of visibility into the L1 alloc.
- */
-/* Need to keep line of output the same.  Currently, that is 44 bytes
- * (including newline).
- */
-static int _sram_proc_read(char *buf, int *len, int count, const char *desc,
-               struct sram_piece *pfree_head,
-               struct sram_piece *pused_head)
-{
-       struct sram_piece *pslot;
-
-       if (!pfree_head || !pused_head)
-               return -1;
-
-       *len += sprintf(&buf[*len], "--- SRAM %-14s Size   PID State     \n", desc);
-
-       /* search the relevant memory slot */
-       pslot = pused_head->next;
-
-       while (pslot != NULL) {
-               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
-                       pslot->paddr, pslot->paddr + pslot->size,
-                       pslot->size, pslot->pid, "ALLOCATED");
-
-               pslot = pslot->next;
-       }
-
-       pslot = pfree_head->next;
-
-       while (pslot != NULL) {
-               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
-                       pslot->paddr, pslot->paddr + pslot->size,
-                       pslot->size, pslot->pid, "FREE");
-
-               pslot = pslot->next;
-       }
-
-       return 0;
-}
-static int sram_proc_read(char *buf, char **start, off_t offset, int count,
-               int *eof, void *data)
-{
-       int len = 0;
-
-       if (_sram_proc_read(buf, &len, count, "Scratchpad",
-                       &free_l1_ssram_head, &used_l1_ssram_head))
-               goto not_done;
-#if L1_DATA_A_LENGTH != 0
-       if (_sram_proc_read(buf, &len, count, "L1 Data A",
-                       &free_l1_data_A_sram_head,
-                       &used_l1_data_A_sram_head))
-               goto not_done;
-#endif
-#if L1_DATA_B_LENGTH != 0
-       if (_sram_proc_read(buf, &len, count, "L1 Data B",
-                       &free_l1_data_B_sram_head,
-                       &used_l1_data_B_sram_head))
-               goto not_done;
-#endif
-#if L1_CODE_LENGTH != 0
-       if (_sram_proc_read(buf, &len, count, "L1 Instruction",
-                       &free_l1_inst_sram_head, &used_l1_inst_sram_head))
-               goto not_done;
-#endif
-#if L2_LENGTH != 0
-       if (_sram_proc_read(buf, &len, count, "L2",
-                       &free_l2_sram_head, &used_l2_sram_head))
-               goto not_done;
-#endif
-
-       *eof = 1;
- not_done:
-       return len;
-}
-
-static int __init sram_proc_init(void)
-{
-       struct proc_dir_entry *ptr;
-       ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
-       if (!ptr) {
-               printk(KERN_WARNING "unable to create /proc/sram\n");
-               return -1;
-       }
-       ptr->owner = THIS_MODULE;
-       ptr->read_proc = sram_proc_read;
-       return 0;
-}
-late_initcall(sram_proc_init);
-#endif
diff --git a/arch/blackfin/mm/isram-driver.c b/arch/blackfin/mm/isram-driver.c
new file mode 100644 (file)
index 0000000..22913e7
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Description: Instruction SRAM accessor functions for the Blackfin
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+
+#include <asm/blackfin.h>
+
+/*
+ * IMPORTANT WARNING ABOUT THESE FUNCTIONS
+ *
+ * The emulator will not function correctly if a write command is left in
+ * ITEST_COMMAND or DTEST_COMMAND AND access to cache memory is needed by
+ * the emulator. To avoid such problems, ensure that both ITEST_COMMAND
+ * and DTEST_COMMAND are zero when exiting these functions.
+ */
+
+
+/*
+ * On the Blackfin, L1 instruction sram (which operates at core speeds) can not
+ * be accessed by a normal core load, so we need to go through a few hoops to
+ * read/write it.
+ * To try to make it easier - we export a memcpy interface, where either src or
+ * dest can be in this special L1 memory area.
+ * The low level read/write functions should not be exposed to the rest of the
+ * kernel, since they operate on 64-bit data, and need specific address alignment
+ */
+
+static DEFINE_SPINLOCK(dtest_lock);
+
+/* Takes a void pointer */
+#define IADDR2DTEST(x) \
+       ({ unsigned long __addr = (unsigned long)(x); \
+               (__addr & 0x47F8)        | /* address bits 14 & 10:3 */ \
+               (__addr & 0x0800) << 15  | /* address bit  11        */ \
+               (__addr  & 0x3000) << 4  | /* address bits 13:12     */ \
+               (__addr  & 0x8000) << 8  | /* address bit  15        */ \
+               (0x1000004);               /* isram access           */ \
+       })
+
+/* Takes a pointer, and returns the offset (in bits) which things should be shifted */
+#define ADDR2OFFSET(x) ((((unsigned long)(x)) & 0x7) * 8)
+
+/* Takes a pointer, determines if it is the last byte in the isram 64-bit data type */
+#define ADDR2LAST(x) ((((unsigned long)x) & 0x7) == 0x7)
+
+static void isram_write(const void *addr, uint64_t data)
+{
+       uint32_t cmd;
+       unsigned long flags;
+
+       if (addr >= (void *)(L1_CODE_START + L1_CODE_LENGTH))
+               return;
+
+       cmd = IADDR2DTEST(addr) | 1;             /* write */
+
+       /*
+        * Writes to DTEST_DATA[0:1] need to be atomic with write to DTEST_COMMAND
+        * While in exception context - atomicity is guaranteed or double fault
+        */
+       spin_lock_irqsave(&dtest_lock, flags);
+
+       bfin_write_DTEST_DATA0(data & 0xFFFFFFFF);
+       bfin_write_DTEST_DATA1(data >> 32);
+
+       /* use the builtin, since interrupts are already turned off */
+       __builtin_bfin_csync();
+       bfin_write_DTEST_COMMAND(cmd);
+       __builtin_bfin_csync();
+
+       bfin_write_DTEST_COMMAND(0);
+       __builtin_bfin_csync();
+
+       spin_unlock_irqrestore(&dtest_lock, flags);
+}
+
+static uint64_t isram_read(const void *addr)
+{
+       uint32_t cmd;
+       unsigned long flags;
+       uint64_t ret;
+
+       if (addr > (void *)(L1_CODE_START + L1_CODE_LENGTH))
+               return 0;
+
+       cmd = IADDR2DTEST(addr) | 0;              /* read */
+
+       /*
+        * Reads of DTEST_DATA[0:1] need to be atomic with write to DTEST_COMMAND
+        * While in exception context - atomicity is guaranteed or double fault
+        */
+       spin_lock_irqsave(&dtest_lock, flags);
+       /* use the builtin, since interrupts are already turned off */
+       __builtin_bfin_csync();
+       bfin_write_DTEST_COMMAND(cmd);
+       __builtin_bfin_csync();
+       ret = bfin_read_DTEST_DATA0() | ((uint64_t)bfin_read_DTEST_DATA1() << 32);
+
+       bfin_write_DTEST_COMMAND(0);
+       __builtin_bfin_csync();
+       spin_unlock_irqrestore(&dtest_lock, flags);
+
+       return ret;
+}
+
+static bool isram_check_addr(const void *addr, size_t n)
+{
+       if ((addr >= (void *)L1_CODE_START) &&
+           (addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))) {
+               if ((addr + n) >= (void *)(L1_CODE_START + L1_CODE_LENGTH)) {
+                       show_stack(NULL, NULL);
+                       printk(KERN_ERR "isram_memcpy: copy involving %p length "
+                                       "(%zu) too long\n", addr, n);
+               }
+               return true;
+       }
+       return false;
+}
+
+/*
+ * The isram_memcpy() function copies n bytes from memory area src to memory area dest.
+ * The isram_memcpy() function returns a pointer to dest.
+ * Either dest or src can be in L1 instruction sram.
+ */
+void *isram_memcpy(void *dest, const void *src, size_t n)
+{
+       uint64_t data_in = 0, data_out = 0;
+       size_t count;
+       bool dest_in_l1, src_in_l1, need_data, put_data;
+       unsigned char byte, *src_byte, *dest_byte;
+
+       src_byte = (unsigned char *)src;
+       dest_byte = (unsigned char *)dest;
+
+       dest_in_l1 = isram_check_addr(dest, n);
+       src_in_l1 = isram_check_addr(src, n);
+
+       need_data = true;
+       put_data = true;
+       for (count = 0; count < n; count++) {
+               if (src_in_l1) {
+                       if (need_data) {
+                               data_in = isram_read(src + count);
+                               need_data = false;
+                       }
+
+                       if (ADDR2LAST(src + count))
+                               need_data = true;
+
+                       byte = (unsigned char)((data_in >> ADDR2OFFSET(src + count)) & 0xff);
+
+               } else {
+                       /* src is in L2 or L3 - so just dereference*/
+                       byte = src_byte[count];
+               }
+
+               if (dest_in_l1) {
+                       if (put_data) {
+                               data_out = isram_read(dest + count);
+                               put_data = false;
+                       }
+
+                       data_out &= ~((uint64_t)0xff << ADDR2OFFSET(dest + count));
+                       data_out |= ((uint64_t)byte << ADDR2OFFSET(dest + count));
+
+                       if (ADDR2LAST(dest + count)) {
+                               put_data = true;
+                               isram_write(dest + count, data_out);
+                       }
+               } else {
+                       /* dest in L2 or L3 - so just dereference */
+                       dest_byte[count] = byte;
+               }
+       }
+
+       /* make sure we dump the last byte if necessary */
+       if (dest_in_l1 && !put_data)
+               isram_write(dest + count, data_out);
+
+       return dest;
+}
+EXPORT_SYMBOL(isram_memcpy);
+
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
new file mode 100644 (file)
index 0000000..0f1ca69
--- /dev/null
@@ -0,0 +1,809 @@
+/*
+ * File:         arch/blackfin/mm/sram-alloc.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:  SRAM allocator for Blackfin L1 and L2 memory
+ *
+ * Modified:
+ *               Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/rtc.h>
+#include <asm/blackfin.h>
+#include "blackfin_sram.h"
+
+static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
+static spinlock_t l2_sram_lock;
+
+/* the data structure for L1 scratchpad and DATA SRAM */
+struct sram_piece {
+       void *paddr;
+       int size;
+       pid_t pid;
+       struct sram_piece *next;
+};
+
+static struct sram_piece free_l1_ssram_head, used_l1_ssram_head;
+
+#if L1_DATA_A_LENGTH != 0
+static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head;
+#endif
+
+#if L1_DATA_B_LENGTH != 0
+static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head;
+#endif
+
+#if L1_CODE_LENGTH != 0
+static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head;
+#endif
+
+#if L2_LENGTH != 0
+static struct sram_piece free_l2_sram_head, used_l2_sram_head;
+#endif
+
+static struct kmem_cache *sram_piece_cache;
+
+/* L1 Scratchpad SRAM initialization function */
+static void __init l1sram_init(void)
+{
+       free_l1_ssram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_ssram_head.next) {
+               printk(KERN_INFO "Failed to initialize Scratchpad data SRAM\n");
+               return;
+       }
+
+       free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START;
+       free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH;
+       free_l1_ssram_head.next->pid = 0;
+       free_l1_ssram_head.next->next = NULL;
+
+       used_l1_ssram_head.next = NULL;
+
+       /* mutex initialize */
+       spin_lock_init(&l1sram_lock);
+
+       printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
+              L1_SCRATCH_LENGTH >> 10);
+}
+
+static void __init l1_data_sram_init(void)
+{
+#if L1_DATA_A_LENGTH != 0
+       free_l1_data_A_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_data_A_sram_head.next) {
+               printk(KERN_INFO "Failed to initialize L1 Data A SRAM\n");
+               return;
+       }
+
+       free_l1_data_A_sram_head.next->paddr =
+               (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1);
+       free_l1_data_A_sram_head.next->size =
+               L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
+       free_l1_data_A_sram_head.next->pid = 0;
+       free_l1_data_A_sram_head.next->next = NULL;
+
+       used_l1_data_A_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
+               L1_DATA_A_LENGTH >> 10,
+               free_l1_data_A_sram_head.next->size >> 10);
+#endif
+#if L1_DATA_B_LENGTH != 0
+       free_l1_data_B_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_data_B_sram_head.next) {
+               printk(KERN_INFO "Failed to initialize L1 Data B SRAM\n");
+               return;
+       }
+
+       free_l1_data_B_sram_head.next->paddr =
+               (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1);
+       free_l1_data_B_sram_head.next->size =
+               L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
+       free_l1_data_B_sram_head.next->pid = 0;
+       free_l1_data_B_sram_head.next->next = NULL;
+
+       used_l1_data_B_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
+               L1_DATA_B_LENGTH >> 10,
+               free_l1_data_B_sram_head.next->size >> 10);
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l1_data_sram_lock);
+}
+
+static void __init l1_inst_sram_init(void)
+{
+#if L1_CODE_LENGTH != 0
+       free_l1_inst_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l1_inst_sram_head.next) {
+               printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n");
+               return;
+       }
+
+       free_l1_inst_sram_head.next->paddr =
+               (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
+       free_l1_inst_sram_head.next->size =
+               L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
+       free_l1_inst_sram_head.next->pid = 0;
+       free_l1_inst_sram_head.next->next = NULL;
+
+       used_l1_inst_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
+               L1_CODE_LENGTH >> 10,
+               free_l1_inst_sram_head.next->size >> 10);
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l1_inst_sram_lock);
+}
+
+static void __init l2_sram_init(void)
+{
+#if L2_LENGTH != 0
+       free_l2_sram_head.next =
+               kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+       if (!free_l2_sram_head.next) {
+               printk(KERN_INFO "Failed to initialize L2 SRAM\n");
+               return;
+       }
+
+       free_l2_sram_head.next->paddr = (void *)L2_START +
+               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+       free_l2_sram_head.next->size = L2_LENGTH -
+               (_etext_l2 - _stext_l2) + (_edata_l2 - _sdata_l2);
+       free_l2_sram_head.next->pid = 0;
+       free_l2_sram_head.next->next = NULL;
+
+       used_l2_sram_head.next = NULL;
+
+       printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n",
+               L2_LENGTH >> 10,
+               free_l2_sram_head.next->size >> 10);
+#endif
+
+       /* mutex initialize */
+       spin_lock_init(&l2_sram_lock);
+}
+void __init bfin_sram_init(void)
+{
+       sram_piece_cache = kmem_cache_create("sram_piece_cache",
+                               sizeof(struct sram_piece),
+                               0, SLAB_PANIC, NULL);
+
+       l1sram_init();
+       l1_data_sram_init();
+       l1_inst_sram_init();
+       l2_sram_init();
+}
+
+/* SRAM allocate function */
+static void *_sram_alloc(size_t size, struct sram_piece *pfree_head,
+               struct sram_piece *pused_head)
+{
+       struct sram_piece *pslot, *plast, *pavail;
+
+       if (size <= 0 || !pfree_head || !pused_head)
+               return NULL;
+
+       /* Align the size */
+       size = (size + 3) & ~3;
+
+       pslot = pfree_head->next;
+       plast = pfree_head;
+
+       /* search an available piece slot */
+       while (pslot != NULL && size > pslot->size) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       if (!pslot)
+               return NULL;
+
+       if (pslot->size == size) {
+               plast->next = pslot->next;
+               pavail = pslot;
+       } else {
+               pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+
+               if (!pavail)
+                       return NULL;
+
+               pavail->paddr = pslot->paddr;
+               pavail->size = size;
+               pslot->paddr += size;
+               pslot->size -= size;
+       }
+
+       pavail->pid = current->pid;
+
+       pslot = pused_head->next;
+       plast = pused_head;
+
+       /* insert new piece into used piece list !!! */
+       while (pslot != NULL && pavail->paddr < pslot->paddr) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       pavail->next = pslot;
+       plast->next = pavail;
+
+       return pavail->paddr;
+}
+
+/* Allocate the largest available block.  */
+static void *_sram_alloc_max(struct sram_piece *pfree_head,
+                               struct sram_piece *pused_head,
+                               unsigned long *psize)
+{
+       struct sram_piece *pslot, *pmax;
+
+       if (!pfree_head || !pused_head)
+               return NULL;
+
+       pmax = pslot = pfree_head->next;
+
+       /* search an available piece slot */
+       while (pslot != NULL) {
+               if (pslot->size > pmax->size)
+                       pmax = pslot;
+               pslot = pslot->next;
+       }
+
+       if (!pmax)
+               return NULL;
+
+       *psize = pmax->size;
+
+       return _sram_alloc(*psize, pfree_head, pused_head);
+}
+
+/* SRAM free function */
+static int _sram_free(const void *addr,
+                       struct sram_piece *pfree_head,
+                       struct sram_piece *pused_head)
+{
+       struct sram_piece *pslot, *plast, *pavail;
+
+       if (!pfree_head || !pused_head)
+               return -1;
+
+       /* search the relevant memory slot */
+       pslot = pused_head->next;
+       plast = pused_head;
+
+       /* search an available piece slot */
+       while (pslot != NULL && pslot->paddr != addr) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       if (!pslot)
+               return -1;
+
+       plast->next = pslot->next;
+       pavail = pslot;
+       pavail->pid = 0;
+
+       /* insert free pieces back to the free list */
+       pslot = pfree_head->next;
+       plast = pfree_head;
+
+       while (pslot != NULL && addr > pslot->paddr) {
+               plast = pslot;
+               pslot = pslot->next;
+       }
+
+       if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) {
+               plast->size += pavail->size;
+               kmem_cache_free(sram_piece_cache, pavail);
+       } else {
+               pavail->next = plast->next;
+               plast->next = pavail;
+               plast = pavail;
+       }
+
+       if (pslot && plast->paddr + plast->size == pslot->paddr) {
+               plast->size += pslot->size;
+               plast->next = pslot->next;
+               kmem_cache_free(sram_piece_cache, pslot);
+       }
+
+       return 0;
+}
+
+int sram_free(const void *addr)
+{
+
+#if L1_CODE_LENGTH != 0
+       if (addr >= (void *)L1_CODE_START
+                && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
+               return l1_inst_sram_free(addr);
+       else
+#endif
+#if L1_DATA_A_LENGTH != 0
+       if (addr >= (void *)L1_DATA_A_START
+                && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
+               return l1_data_A_sram_free(addr);
+       else
+#endif
+#if L1_DATA_B_LENGTH != 0
+       if (addr >= (void *)L1_DATA_B_START
+                && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
+               return l1_data_B_sram_free(addr);
+       else
+#endif
+#if L2_LENGTH != 0
+       if (addr >= (void *)L2_START
+                && addr < (void *)(L2_START + L2_LENGTH))
+               return l2_sram_free(addr);
+       else
+#endif
+               return -1;
+}
+EXPORT_SYMBOL(sram_free);
+
+void *l1_data_A_sram_alloc(size_t size)
+{
+       unsigned long flags;
+       void *addr = NULL;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+#if L1_DATA_A_LENGTH != 0
+       addr = _sram_alloc(size, &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head);
+#endif
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_A_sram_alloc);
+
+int l1_data_A_sram_free(const void *addr)
+{
+       unsigned long flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+#if L1_DATA_A_LENGTH != 0
+       ret = _sram_free(addr, &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head);
+#else
+       ret = -1;
+#endif
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(l1_data_A_sram_free);
+
+void *l1_data_B_sram_alloc(size_t size)
+{
+#if L1_DATA_B_LENGTH != 0
+       unsigned long flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+       addr = _sram_alloc(size, &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l1_data_B_sram_alloc);
+
+int l1_data_B_sram_free(const void *addr)
+{
+#if L1_DATA_B_LENGTH != 0
+       unsigned long flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_data_sram_lock, flags);
+
+       ret = _sram_free(addr, &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l1_data_B_sram_free);
+
+void *l1_data_sram_alloc(size_t size)
+{
+       void *addr = l1_data_A_sram_alloc(size);
+
+       if (!addr)
+               addr = l1_data_B_sram_alloc(size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_sram_alloc);
+
+void *l1_data_sram_zalloc(size_t size)
+{
+       void *addr = l1_data_sram_alloc(size);
+
+       if (addr)
+               memset(addr, 0x00, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l1_data_sram_zalloc);
+
+int l1_data_sram_free(const void *addr)
+{
+       int ret;
+       ret = l1_data_A_sram_free(addr);
+       if (ret == -1)
+               ret = l1_data_B_sram_free(addr);
+       return ret;
+}
+EXPORT_SYMBOL(l1_data_sram_free);
+
+void *l1_inst_sram_alloc(size_t size)
+{
+#if L1_CODE_LENGTH != 0
+       unsigned long flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_inst_sram_lock, flags);
+
+       addr = _sram_alloc(size, &free_l1_inst_sram_head,
+                       &used_l1_inst_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+
+       pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l1_inst_sram_alloc);
+
+int l1_inst_sram_free(const void *addr)
+{
+#if L1_CODE_LENGTH != 0
+       unsigned long flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1_inst_sram_lock, flags);
+
+       ret = _sram_free(addr, &free_l1_inst_sram_head,
+                       &used_l1_inst_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l1_inst_sram_free);
+
+/* L1 Scratchpad memory allocate function */
+void *l1sram_alloc(size_t size)
+{
+       unsigned long flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       addr = _sram_alloc(size, &free_l1_ssram_head,
+                       &used_l1_ssram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return addr;
+}
+
+/* L1 Scratchpad memory allocate function */
+void *l1sram_alloc_max(size_t *psize)
+{
+       unsigned long flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       addr = _sram_alloc_max(&free_l1_ssram_head,
+                       &used_l1_ssram_head, psize);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return addr;
+}
+
+/* L1 Scratchpad memory free function */
+int l1sram_free(const void *addr)
+{
+       unsigned long flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l1sram_lock, flags);
+
+       ret = _sram_free(addr, &free_l1_ssram_head,
+                       &used_l1_ssram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l1sram_lock, flags);
+
+       return ret;
+}
+
+void *l2_sram_alloc(size_t size)
+{
+#if L2_LENGTH != 0
+       unsigned long flags;
+       void *addr;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l2_sram_lock, flags);
+
+       addr = _sram_alloc(size, &free_l2_sram_head,
+                       &used_l2_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l2_sram_lock, flags);
+
+       pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n",
+                (long unsigned int)addr, size);
+
+       return addr;
+#else
+       return NULL;
+#endif
+}
+EXPORT_SYMBOL(l2_sram_alloc);
+
+void *l2_sram_zalloc(size_t size)
+{
+       void *addr = l2_sram_alloc(size);
+
+       if (addr)
+               memset(addr, 0x00, size);
+
+       return addr;
+}
+EXPORT_SYMBOL(l2_sram_zalloc);
+
+int l2_sram_free(const void *addr)
+{
+#if L2_LENGTH != 0
+       unsigned long flags;
+       int ret;
+
+       /* add mutex operation */
+       spin_lock_irqsave(&l2_sram_lock, flags);
+
+       ret = _sram_free(addr, &free_l2_sram_head,
+                       &used_l2_sram_head);
+
+       /* add mutex operation */
+       spin_unlock_irqrestore(&l2_sram_lock, flags);
+
+       return ret;
+#else
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(l2_sram_free);
+
+int sram_free_with_lsl(const void *addr)
+{
+       struct sram_list_struct *lsl, **tmp;
+       struct mm_struct *mm = current->mm;
+
+       for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
+               if ((*tmp)->addr == addr)
+                       goto found;
+       return -1;
+found:
+       lsl = *tmp;
+       sram_free(addr);
+       *tmp = lsl->next;
+       kfree(lsl);
+
+       return 0;
+}
+EXPORT_SYMBOL(sram_free_with_lsl);
+
+void *sram_alloc_with_lsl(size_t size, unsigned long flags)
+{
+       void *addr = NULL;
+       struct sram_list_struct *lsl = NULL;
+       struct mm_struct *mm = current->mm;
+
+       lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL);
+       if (!lsl)
+               return NULL;
+
+       if (flags & L1_INST_SRAM)
+               addr = l1_inst_sram_alloc(size);
+
+       if (addr == NULL && (flags & L1_DATA_A_SRAM))
+               addr = l1_data_A_sram_alloc(size);
+
+       if (addr == NULL && (flags & L1_DATA_B_SRAM))
+               addr = l1_data_B_sram_alloc(size);
+
+       if (addr == NULL && (flags & L2_SRAM))
+               addr = l2_sram_alloc(size);
+
+       if (addr == NULL) {
+               kfree(lsl);
+               return NULL;
+       }
+       lsl->addr = addr;
+       lsl->length = size;
+       lsl->next = mm->context.sram_list;
+       mm->context.sram_list = lsl;
+       return addr;
+}
+EXPORT_SYMBOL(sram_alloc_with_lsl);
+
+#ifdef CONFIG_PROC_FS
+/* Once we get a real allocator, we'll throw all of this away.
+ * Until then, we need some sort of visibility into the L1 alloc.
+ */
+/* Need to keep line of output the same.  Currently, that is 44 bytes
+ * (including newline).
+ */
+static int _sram_proc_read(char *buf, int *len, int count, const char *desc,
+               struct sram_piece *pfree_head,
+               struct sram_piece *pused_head)
+{
+       struct sram_piece *pslot;
+
+       if (!pfree_head || !pused_head)
+               return -1;
+
+       *len += sprintf(&buf[*len], "--- SRAM %-14s Size   PID State     \n", desc);
+
+       /* search the relevant memory slot */
+       pslot = pused_head->next;
+
+       while (pslot != NULL) {
+               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
+                       pslot->paddr, pslot->paddr + pslot->size,
+                       pslot->size, pslot->pid, "ALLOCATED");
+
+               pslot = pslot->next;
+       }
+
+       pslot = pfree_head->next;
+
+       while (pslot != NULL) {
+               *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
+                       pslot->paddr, pslot->paddr + pslot->size,
+                       pslot->size, pslot->pid, "FREE");
+
+               pslot = pslot->next;
+       }
+
+       return 0;
+}
+static int sram_proc_read(char *buf, char **start, off_t offset, int count,
+               int *eof, void *data)
+{
+       int len = 0;
+
+       if (_sram_proc_read(buf, &len, count, "Scratchpad",
+                       &free_l1_ssram_head, &used_l1_ssram_head))
+               goto not_done;
+#if L1_DATA_A_LENGTH != 0
+       if (_sram_proc_read(buf, &len, count, "L1 Data A",
+                       &free_l1_data_A_sram_head,
+                       &used_l1_data_A_sram_head))
+               goto not_done;
+#endif
+#if L1_DATA_B_LENGTH != 0
+       if (_sram_proc_read(buf, &len, count, "L1 Data B",
+                       &free_l1_data_B_sram_head,
+                       &used_l1_data_B_sram_head))
+               goto not_done;
+#endif
+#if L1_CODE_LENGTH != 0
+       if (_sram_proc_read(buf, &len, count, "L1 Instruction",
+                       &free_l1_inst_sram_head, &used_l1_inst_sram_head))
+               goto not_done;
+#endif
+#if L2_LENGTH != 0
+       if (_sram_proc_read(buf, &len, count, "L2",
+                       &free_l2_sram_head, &used_l2_sram_head))
+               goto not_done;
+#endif
+
+       *eof = 1;
+ not_done:
+       return len;
+}
+
+static int __init sram_proc_init(void)
+{
+       struct proc_dir_entry *ptr;
+       ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
+       if (!ptr) {
+               printk(KERN_WARNING "unable to create /proc/sram\n");
+               return -1;
+       }
+       ptr->owner = THIS_MODULE;
+       ptr->read_proc = sram_proc_read;
+       return 0;
+}
+late_initcall(sram_proc_init);
+#endif
index 2f9bbb26d6036960cc4be90a2bccfc50bb0330fd..c8adef364160daa8fedb6ac4af2049df263d6a87 100644 (file)
@@ -30,7 +30,6 @@
 #include <sys/sysmacros.h>
 #include <unistd.h>    /* contains read/write */
 #include <fcntl.h>
-#include <linux/a.out.h>
 #include <errno.h>
 
 #define MINIX_HEADER 32
index 8e5a3cab8ad7f3dcfd3e48a3b5e48c98deab61d0..ee391ecb5bc9bb6e67f216ba265304ba791f6b13 100644 (file)
@@ -85,7 +85,6 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy)
        int result;
 
        /* cpuinfo and default policy values */
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.transition_latency = 1000000; /* 1ms */
        policy->cur = cris_freq_get_cpu_frequency(0);
 
index d57631c0d8d1c09bc35393cfa7b18019dd00116b..58bd71e5bda95415621819222665ba24a74e658e 100644 (file)
@@ -81,7 +81,6 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy)
        int result;
 
        /* cpuinfo and default policy values */
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.transition_latency = 1000000;   /* 1ms */
        policy->cur = cris_freq_get_cpu_frequency(0);
 
index d1113c5031f5f4f19a16314378e63ab3a9889301..be722fc1acff523986182dcef23da7b15a3c2534 100644 (file)
@@ -211,7 +211,7 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
        return try_set_cmode(new_cmode)?:*lenp;
 }
 
-static int cmode_sysctl(ctl_table *table, int __user *name, int nlen,
+static int cmode_sysctl(ctl_table *table,
                        void __user *oldval, size_t __user *oldlenp,
                        void __user *newval, size_t newlen)
 {
@@ -314,7 +314,7 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
        return try_set_p0(new_p0)?:*lenp;
 }
 
-static int p0_sysctl(ctl_table *table, int __user *name, int nlen,
+static int p0_sysctl(ctl_table *table,
                     void __user *oldval, size_t __user *oldlenp,
                     void __user *newval, size_t newlen)
 {
@@ -358,7 +358,7 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
        return try_set_cm(new_cm)?:*lenp;
 }
 
-static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
+static int cm_sysctl(ctl_table *table,
                     void __user *oldval, size_t __user *oldlenp,
                     void __user *newval, size_t newlen)
 {
index 64ee58d748be807131c2188d659ec1dc0bceba8a..52ff9aec799d29c84a649aa128ccb985b60cd68c 100644 (file)
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(dma_free_coherent);
  * The 32-bit bus address to use is returned.
  *
  * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single is performed.
+ * until either dma_unmap_single or pci_dma_sync_single is performed.
  */
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
                          enum dma_data_direction direction)
@@ -129,7 +129,7 @@ EXPORT_SYMBOL(dma_map_single);
 /*
  * Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
+ * above dma_map_single interface.  Here the scatter gather list
  * elements are each tagged with the appropriate dma address
  * and length.  They are obtained via sg_dma_{address,length}(SG).
  *
@@ -139,7 +139,7 @@ EXPORT_SYMBOL(dma_map_single);
  *       The routine returns the number of addr/length pairs actually
  *       used, at most nents.
  *
- * Device ownership issues as mentioned above for pci_map_single are
+ * Device ownership issues as mentioned above for dma_map_single are
  * the same here.
  */
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
@@ -158,3 +158,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 }
 
 EXPORT_SYMBOL(dma_map_sg);
+
+/*
+ * Map a single page of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Device ownership issues as mentioned above for dma_map_single are
+ * the same here.
+ */
+dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+                       size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(direction == DMA_NONE);
+       flush_dcache_page(page);
+       return (dma_addr_t) page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
index 662f7b12d005fa532b834ec06838cf5ae56bc264..3ddedebc4eb3db1a1bbc25a7a10dd2e1fd1e66e5 100644 (file)
@@ -61,7 +61,7 @@ EXPORT_SYMBOL(dma_map_single);
 /*
  * Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
+ * above dma_map_single interface.  Here the scatter gather list
  * elements are each tagged with the appropriate dma address
  * and length.  They are obtained via sg_dma_{address,length}(SG).
  *
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(dma_map_single);
  *       The routine returns the number of addr/length pairs actually
  *       used, at most nents.
  *
- * Device ownership issues as mentioned above for pci_map_single are
+ * Device ownership issues as mentioned above for dma_map_single are
  * the same here.
  */
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
@@ -105,6 +105,13 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 EXPORT_SYMBOL(dma_map_sg);
 
+/*
+ * Map a single page of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Device ownership issues as mentioned above for dma_map_single are
+ * the same here.
+ */
 dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset,
                        size_t size, enum dma_data_direction direction)
 {
index edae117fcc2bcc93ef81a8d1d8a167e6a2050a68..43d67534c7122f44e5787ccb36a3faed12489412 100644 (file)
@@ -201,38 +201,6 @@ void __init pcibios_resource_survey(void)
        pcibios_assign_resources();
 }
 
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for(idx=0; idx<6; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1<<idx)))
-                       continue;
-
-               r = &dev->resource[idx];
-               if (!r->start && r->end) {
-                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (dev->resource[PCI_ROM_RESOURCE].start)
-               cmd |= PCI_COMMAND_MEMORY;
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-}
-
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain crappy BIOSes forget to set it properly.
index 0c7bf39dc7298cb781c0b2b7ecf6c2a1be451b0c..f3fe5591479388ba6c2b3d7b6320740dfd392701 100644 (file)
@@ -29,7 +29,6 @@ extern unsigned int __nongpreldata pci_probe;
 extern unsigned int pcibios_max_latency;
 
 void pcibios_resource_survey(void);
-int pcibios_enable_resources(struct pci_dev *, int);
 
 /* pci-vdk.c */
 
index f003cfa68b7a0cbe78ee1ca3444dd6deb7884e18..0f41c3a72da5f5cf042052554a3add718c238946 100644 (file)
@@ -412,7 +412,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
        int err;
 
-       if ((err = pcibios_enable_resources(dev, mask)) < 0)
+       if ((err = pci_enable_resources(dev, mask)) < 0)
                return err;
        if (!dev->msi_enabled)
                pcibios_enable_irq(dev);
index 1b851db341865420257f388a9fc9e31828a1d0e8..0708284f85fb3d690d4e649366ea056282a171b8 100644 (file)
@@ -87,8 +87,6 @@ void __init paging_init(void)
 
                pkmap_page_table = alloc_bootmem_pages(PAGE_SIZE);
 
-               memset(pkmap_page_table, 0, PAGE_SIZE);
-
                pge = swapper_pg_dir + pgd_index_k(PKMAP_BASE);
                pue = pud_offset(pge, PKMAP_BASE);
                pme = pmd_offset(pue, PKMAP_BASE);
index 396ab059efa35a9fa1d2e8258aff56cd0f8f0ab4..c7966746fbfec582938b77a37baaed384d1b0ec2 100644 (file)
@@ -62,13 +62,14 @@ config GENERIC_TIME
        bool
        default y
 
+config GENERIC_BUG
+        bool
+        depends on BUG
+
 config TIME_LOW_RES
        bool
        default y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 config NO_IOPORT
        def_bool y
 
index 582797db9603f1fa19b3a0d2fae692bf1510efb2..b65dcfe51d9ca2ae26b890de5f1f070620b8b033 100644 (file)
@@ -1,5 +1,7 @@
 menu "Processor type and features"
 
+source "kernel/time/Kconfig"
+
 choice
        prompt "H8/300 platform"
        default H8300H_GENERIC
@@ -11,6 +13,7 @@ config H8300H_GENERIC
 
 config H8300H_AKI3068NET
        bool "AE-3068/69"
+       select CONFIG_H83068
        help
          AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support
          More Information. (Japanese Only)
@@ -21,6 +24,7 @@ config H8300H_AKI3068NET
 
 config H8300H_H8MAX
        bool "H8MAX"
+       select CONFIG_H83068
        help
          H8MAX Evaluation Board Support
          More Information. (Japanese Only)
@@ -28,6 +32,7 @@ config H8300H_H8MAX
 
 config H8300H_SIM
        bool "H8/300H Simulator"
+       select CONFIG_H83007
        help
          GDB Simulator Support
          More Information.
@@ -40,6 +45,7 @@ config H8S_GENERIC
 
 config H8S_EDOSK2674
        bool "EDOSK-2674"
+       select CONFIG_H8S2768
        help
          Renesas EDOSK-2674 Evaluation Board Support
          More Information.
@@ -55,44 +61,37 @@ config H8S_SIM
 
 endchoice
 
-if (H8300H_GENERIC || H8S_GENERIC)
-menu "Detail Selection"
-if (H8300H_GENERIC)
 choice
        prompt "CPU Selection"
 
 config H83002
        bool "H8/3001,3002,3003"
+       select CPU_H8300H
 
 config H83007
        bool "H8/3006,3007"
+       select CPU_H8300H
 
 config H83048
        bool "H8/3044,3045,3046,3047,3048,3052"
+       select CPU_H8300H
 
 config H83068
        bool "H8/3065,3066,3067,3068,3069"
-endchoice
-endif
-
-if (H8S_GENERIC)
-choice
-       prompt "CPU Selection"
+       select CPU_H8300H
 
 config H8S2678
        bool "H8S/2670,2673,2674R,2675,2676"
+       select CPU_H8S
+
 endchoice
-endif
 
 config CPU_CLOCK
        int "CPU Clock Frequency (/1KHz)"
        default "20000"
        help
          CPU Clock Frequency divide to 1000
-endmenu
-endif
 
-if (H8300H_GENERIC || H8S_GENERIC || H8300H_SIM || H8S_SIM || H8S_EDOSK2674)
 choice
        prompt "Kernel executes from"
        ---help---
@@ -107,75 +106,61 @@ config ROMKERNEL
        bool "ROM"
        help
          The kernel will be resident in FLASH/ROM when running.
-
 endchoice
-endif
 
-if (H8300H_AKI3068NET)
-config H83068
-       bool
-       default y
 
-config CPU_CLOCK
-       int
-       default "20000"
-
-config RAMKERNEL
+config CPU_H8300H
        bool
+       depends on (H83002 || H83007 || H83048 || H83068)
        default y
-endif
 
-if (H8300H_H8MAX)
-config H83068
+config CPU_H8S
        bool
+       depends on H8S2678
        default y
 
-config CPU_CLOCK
-       int
-       default 25000
+choice
+       prompt "Timer"
+config H8300_TIMER8
+       bool "8bit timer (2ch cascade)"
+       depends on (H83007 || H83068 || H8S2678)
 
-config RAMKERNEL
-       bool
-       default y
-endif
+config H8300_TIMER16
+       bool "16bit timer"
+       depends on (H83007 || H83068)
 
-if (H8300H_SIM)
-config H83007
-       bool
-       default y
+config H8300_ITU
+       bool "ITU"
+       depends on (H83002 || H83048)
 
-config CPU_CLOCK
-       int
-       default "16000"
-endif
+config H8300_TPU
+       bool "TPU"
+       depends on H8S2678
+endchoice
 
-if (H8S_EDOSK2674)
-config H8S2678
-       bool
-       default y
-config CPU_CLOCK
-       int
-       default 33000
+if H8300_TIMER8
+choice
+       prompt "Timer Channel"
+config H8300_TIMER8_CH0
+       bool "Channel 0"
+config H8300_TIMER8_CH2
+       bool "Channel 2"
+       depends on CPU_H8300H
+endchoice
 endif
 
-if (H8S_SIM)
-config H8S2678
-       bool
-       default y
-config CPU_CLOCK
-       int
-       default 33000
-endif
+config H8300_TIMER16_CH
+       int "16bit timer channel (0 - 2)"
+       depends on H8300_TIMER16
+       range 0 2
 
-config CPU_H8300H
-       bool
-       depends on (H83002 || H83007 || H83048 || H83068)
-       default y
+config H8300_ITU_CH
+       int "ITU channel"
+       depends on H8300_ITU
 
-config CPU_H8S
-       bool
-       depends on H8S2678
-       default y
+config H8300_TPU_CH
+       int "TPU channel"
+       depends on H8300_TPU
 
 config PREEMPT
        bool "Preemptible Kernel"
diff --git a/arch/h8300/include/asm/a.out.h b/arch/h8300/include/asm/a.out.h
deleted file mode 100644 (file)
index ded780f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __H8300_A_OUT_H__
-#define __H8300_A_OUT_H__
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* __H8300_A_OUT_H__ */
index edddf5b086e5f447fa2117103015e6714d8a3786..887c19773185d2da7442fb81b5090a0742de571b 100644 (file)
@@ -1,4 +1,8 @@
 #ifndef _H8300_BUG_H
 #define _H8300_BUG_H
+
+/* always true */
+#define is_valid_bugaddr(addr) (1)
+
 #include <asm-generic/bug.h>
 #endif
index a8b57d1f41286261434957bc408057b487628408..94e2284c88168fba8a42afc0008aa8cb1c53944e 100644 (file)
@@ -55,7 +55,7 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #define R_H8_NONE       0
 #define R_H8_DIR32      1
index 26dc6ccd9441a2237ada1f7168131f07402949a9..33e842f3284bf7cdec4b0a3aec59835cbe0b20b0 100644 (file)
@@ -295,6 +295,40 @@ static __inline__ void ctrl_outl(unsigned long b, unsigned long addr)
         *(volatile unsigned long*)addr = b;
 }
 
+static __inline__ void ctrl_bclr(int b, unsigned long addr)
+{
+       if (__builtin_constant_p(b))
+               switch (b) {
+               case 0: __asm__("bclr #0,@%0"::"r"(addr)); break;
+               case 1: __asm__("bclr #1,@%0"::"r"(addr)); break;
+               case 2: __asm__("bclr #2,@%0"::"r"(addr)); break;
+               case 3: __asm__("bclr #3,@%0"::"r"(addr)); break;
+               case 4: __asm__("bclr #4,@%0"::"r"(addr)); break;
+               case 5: __asm__("bclr #5,@%0"::"r"(addr)); break;
+               case 6: __asm__("bclr #6,@%0"::"r"(addr)); break;
+               case 7: __asm__("bclr #7,@%0"::"r"(addr)); break;
+               }
+       else
+               __asm__("bclr %w0,@%1"::"r"(b), "r"(addr));
+}
+
+static __inline__ void ctrl_bset(int b, unsigned long addr)
+{
+       if (__builtin_constant_p(b))
+               switch (b) {
+               case 0: __asm__("bset #0,@%0"::"r"(addr)); break;
+               case 1: __asm__("bset #1,@%0"::"r"(addr)); break;
+               case 2: __asm__("bset #2,@%0"::"r"(addr)); break;
+               case 3: __asm__("bset #3,@%0"::"r"(addr)); break;
+               case 4: __asm__("bset #4,@%0"::"r"(addr)); break;
+               case 5: __asm__("bset #5,@%0"::"r"(addr)); break;
+               case 6: __asm__("bset #6,@%0"::"r"(addr)); break;
+               case 7: __asm__("bset #7,@%0"::"r"(addr)); break;
+               }
+       else
+               __asm__("bset %w0,@%1"::"r"(b), "r"(addr));
+}
+
 /* Pages to physical address... */
 #define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
 #define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
index 1a47dc6691fb34b7532266b94ee9fe3faee0a199..1b7300e0a175b3214ca0368217afb88a50a37c53 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: md.h,v 1.1 2002/11/19 02:09:26 gerg Exp $
+/*
  * md.h: High speed xor_block operation for RAID4/5 
  *
  */
index 4b8e475908ae0c9eab94c5ac55cb7e2c36216000..d98d97685f068da986c8639bd29953d94a8ceb8d 100644 (file)
@@ -155,4 +155,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
 
 #define arch_align_stack(x) (x)
 
+void die(char *str, struct pt_regs *fp, unsigned long err);
+
 #endif /* _H8300_SYSTEM_H */
index 6c248c3c5c3b92cf9084da1b3542440b4b920b49..8d4d2a54be9efd83afc94935b359a59288504911 100644 (file)
@@ -7,6 +7,6 @@ extra-y := vmlinux.lds
 obj-y := process.o traps.o ptrace.o irq.o \
         sys_h8300.o time.o signal.o \
          setup.o gpio.o init_task.o syscalls.o \
-        entry.o
+        entry.o timer/
 
 obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
index 4fd7138a6e03d01217d92517d83fb58f531cd9d1..cfc9127d2cede26312fcaef364a35d6be0c95080 100644 (file)
@@ -114,9 +114,10 @@ int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
 {
-       return 0;
+       return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
+       module_bug_cleanup(mod);
 }
index dfbe7ab9ffe2e2fa632260ccb2111d3a9e9a87df..a8ef654a5a0b8403af3a52c709478956140d2690 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
index e37c835e67cf2bee6538e07a50913d08cb7a6eca..7f2d6cfbb4b6091b2f6c7523ca004582b766349e 100644 (file)
 #include <linux/profile.h>
 
 #include <asm/io.h>
-#include <asm/target_time.h>
+#include <asm/timer.h>
 
 #define        TICK_SIZE (tick_nsec / 1000)
 
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
+void h8300_timer_tick(void)
 {
-       /* may need to kick the hardware timer */
-       platform_timer_eoi();
-
+       if (current->pid)
+               profile_tick(CPU_PROFILING);
+       write_seqlock(&xtime_lock);
        do_timer(1);
-#ifndef CONFIG_SMP
-       update_process_times(user_mode(regs));
-#endif
-       profile_tick(CPU_PROFILING);
+       write_sequnlock(&xtime_lock);
+       update_process_times(user_mode(get_irq_regs()));
 }
 
-void time_init(void)
+void __init time_init(void)
 {
        unsigned int year, mon, day, hour, min, sec;
 
@@ -57,12 +51,13 @@ void time_init(void)
        year = 1980;
        mon = day = 1;
        hour = min = sec = 0;
-       platform_gettod (&year, &mon, &day, &hour, &min, &sec);
-
+#ifdef CONFIG_H8300_GETTOD
+       h8300_gettod (&year, &mon, &day, &hour, &min, &sec);
+#endif
        if ((year += 1900) < 1970)
                year += 100;
        xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
        xtime.tv_nsec = 0;
 
-       platform_timer_setup(timer_interrupt);
+       h8300_timer_setup();
 }
diff --git a/arch/h8300/kernel/timer/Makefile b/arch/h8300/kernel/timer/Makefile
new file mode 100644 (file)
index 0000000..bef0510
--- /dev/null
@@ -0,0 +1,6 @@
+# h8300 internal timer handler
+
+obj-$(CONFIG_H8300_TIMER8)  := timer8.o
+obj-$(CONFIG_H8300_TIMER16) := timer16.o
+obj-$(CONFIG_H8300_ITU)     := itu.o
+obj-$(CONFIG_H8300_TPU)     := tpu.o
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c
new file mode 100644 (file)
index 0000000..d1c9265
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  linux/arch/h8300/kernel/timer/itu.c
+ *
+ *  Yoshinori Sato <ysato@users.sourcefoge.jp>
+ *
+ *  ITU Timer Handler
+ *
+ */
+
+#include <linux/errno.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/init.h>
+#include <linux/timex.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/regs306x.h>
+
+#if CONFIG_H8300_ITU_CH == 0
+#define ITUBASE        0xffff64
+#define ITUIRQ 24
+#elif CONFIG_H8300_ITU_CH == 1
+#define ITUBASE        0xffff6e
+#define ITUIRQ 28
+#elif CONFIG_H8300_ITU_CH == 2
+#define ITUBASE        0xffff78
+#define ITUIRQ 32
+#elif CONFIG_H8300_ITU_CH == 3
+#define ITUBASE        0xffff82
+#define ITUIRQ 36
+#elif CONFIG_H8300_ITU_CH == 4
+#define ITUBASE        0xffff92
+#define ITUIRQ 40
+#else
+#error Unknown timer channel.
+#endif
+
+#define TCR    0
+#define TIOR   1
+#define TIER   2
+#define TSR    3
+#define TCNT   4
+#define GRA    6
+#define GRB    8
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       h8300_timer_tick();
+       ctrl_bclr(IMFA, ITUBASE + TSR);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction itu_irq = {
+       .name           = "itu",
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+static const int __initdata divide_rate[] = {1, 2, 4, 8};
+
+void __init h8300_timer_setup(void)
+{
+       unsigned int div;
+       unsigned int cnt;
+
+       calc_param(cnt, div, divide_rate, 0x10000);
+
+       setup_irq(ITUIRQ, &itu_irq);
+
+       /* initalize timer */
+       ctrl_outb(0, TSTR);
+       ctrl_outb(CCLR0 | div, ITUBASE + TCR);
+       ctrl_outb(0x01, ITUBASE + TIER);
+       ctrl_outw(cnt, ITUBASE + GRA);
+       ctrl_bset(CONFIG_H8300_ITU_CH, TSTR);
+}
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c
new file mode 100644 (file)
index 0000000..e14271b
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *  linux/arch/h8300/kernel/timer/timer16.c
+ *
+ *  Yoshinori Sato <ysato@users.sourcefoge.jp>
+ *
+ *  16bit Timer Handler
+ *
+ */
+
+#include <linux/errno.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/init.h>
+#include <linux/timex.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/regs306x.h>
+
+/* 16bit timer */
+#if CONFIG_H8300_TIMER16_CH == 0
+#define _16BASE        0xffff78
+#define _16IRQ 24
+#elif CONFIG_H8300_TIMER16_CH == 1
+#define _16BASE        0xffff80
+#define _16IRQ 28
+#elif CONFIG_H8300_TIMER16_CH == 2
+#define _16BASE        0xffff88
+#define _16IRQ 32
+#else
+#error Unknown timer channel.
+#endif
+
+#define TCR    0
+#define TIOR   1
+#define TCNT   2
+#define GRA    4
+#define GRB    6
+
+#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*10000 /* Timer input freq. */
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       h8300_timer_tick();
+       ctrl_bclr(CONFIG_H8300_TIMER16_CH, TISRA);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction timer16_irq = {
+       .name           = "timer-16",
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+static const int __initdata divide_rate[] = {1, 2, 4, 8};
+
+void __init h8300_timer_setup(void)
+{
+       unsigned int div;
+       unsigned int cnt;
+
+       calc_param(cnt, div, divide_rate, 0x10000);
+
+       setup_irq(_16IRQ, &timer16_irq);
+
+       /* initalize timer */
+       ctrl_outb(0, TSTR);
+       ctrl_outb(CCLR0 | div, _16BASE + TCR);
+       ctrl_outw(cnt, _16BASE + GRA);
+       ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA);
+       ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR);
+}
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
new file mode 100644 (file)
index 0000000..0556d7c
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  linux/arch/h8300/kernel/cpu/timer/timer8.c
+ *
+ *  Yoshinori Sato <ysato@users.sourcefoge.jp>
+ *
+ *  8bit Timer Handler
+ *
+ */
+
+#include <linux/errno.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/init.h>
+#include <linux/profile.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/timer.h>
+#if defined(CONFIG_CPU_H8300H)
+#include <asm/regs306x.h>
+#endif
+#if defined(CONFIG_CPU_H8S)
+#include <asm/regs267x.h>
+#endif
+
+/* 8bit timer x2 */
+#define CMFA   6
+
+#if defined(CONFIG_H8300_TIMER8_CH0)
+#define _8BASE _8TCR0
+#ifdef CONFIG_CPU_H8300H
+#define _8IRQ  36
+#endif
+#ifdef CONFIG_CPU_H8S
+#define _8IRQ  72
+#endif
+#elif defined(CONFIG_H8300_TIMER8_CH2)
+#ifdef CONFIG_CPU_H8300H
+#define _8BASE _8TCR2
+#define _8IRQ  40
+#endif
+#endif
+
+#ifndef _8BASE
+#error Unknown timer channel.
+#endif
+
+#define _8TCR  0
+#define _8TCSR 2
+#define TCORA  4
+#define TCORB  6
+#define _8TCNT 8
+
+#define CMIEA  0x40
+#define CCLR_CMA 0x08
+#define CKS2   0x04
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       h8300_timer_tick();
+       ctrl_bclr(CMFA, _8BASE + _8TCSR);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction timer8_irq = {
+       .name           = "timer-8",
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+static const int __initdata divide_rate[] = {8, 64, 8192};
+
+void __init h8300_timer_setup(void)
+{
+       unsigned int div;
+       unsigned int cnt;
+
+       calc_param(cnt, div, divide_rate, 0x10000);
+       div++;
+
+       setup_irq(_8IRQ, &timer8_irq);
+
+#if defined(CONFIG_CPU_H8S)
+       /* Timer module enable */
+       ctrl_bclr(0, MSTPCRL)
+#endif
+
+       /* initalize timer */
+       ctrl_outw(cnt, _8BASE + TCORA);
+       ctrl_outw(0x0000, _8BASE + _8TCSR);
+       ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div,
+                 _8BASE + _8TCR);
+}
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c
new file mode 100644 (file)
index 0000000..df7f453
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  linux/arch/h8300/kernel/timer/tpu.c
+ *
+ *  Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ *  TPU Timer Handler
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/errno.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/init.h>
+#include <linux/timex.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/regs267x.h>
+
+/* TPU */
+#if CONFIG_H8300_TPU_CH == 0
+#define TPUBASE        0xffffd0
+#define TPUIRQ 40
+#elif CONFIG_H8300_TPU_CH == 1
+#define TPUBASE        0xffffe0
+#define TPUIRQ 48
+#elif CONFIG_H8300_TPU_CH == 2
+#define TPUBASE        0xfffff0
+#define TPUIRQ 52
+#elif CONFIG_H8300_TPU_CH == 3
+#define TPUBASE        0xfffe80
+#define TPUIRQ 56
+#elif CONFIG_H8300_TPU_CH == 4
+#define TPUBASE        0xfffe90
+#define TPUIRQ 64
+#else
+#error Unknown timer channel.
+#endif
+
+#define _TCR   0
+#define _TMDR  1
+#define _TIOR  2
+#define _TIER  4
+#define _TSR   5
+#define _TCNT  6
+#define _GRA   8
+#define _GRB   10
+
+#define CCLR0  0x20
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       h8300_timer_tick();
+       ctrl_bclr(0, TPUBASE + _TSR);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction tpu_irq = {
+       .name           = "tpu",
+       .handler        = timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .mask           = CPU_MASK_NONE,
+};
+
+const static int __initdata divide_rate[] = {
+#if CONFIG_H8300_TPU_CH == 0
+       1,4,16,64,0,0,0,0,
+#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
+       1,4,16,64,0,0,256,0,
+#elif (CONFIG_H8300_TPU_CH == 2) || (CONFIG_H8300_TPU_CH == 4)
+       1,4,16,64,0,0,0,1024,
+#elif CONFIG_H8300_TPU_CH == 3
+       1,4,16,64,0,1024,256,4096,
+#endif
+};
+
+void __init h8300_timer_setup(void)
+{
+       unsigned int cnt;
+       unsigned int div;
+
+       calc_param(cnt, div, divide_rate, 0x10000);
+
+       setup_irq(TPUIRQ, &tpu_irq);
+
+       /* TPU module enabled */
+       ctrl_bclr(3, MSTPCRH);
+
+       ctrl_outb(0, TSTR);
+       ctrl_outb(CCLR0 | div, TPUBASE + _TCR);
+       ctrl_outb(0, TPUBASE + _TMDR);
+       ctrl_outw(0, TPUBASE + _TIOR);
+       ctrl_outb(0x01, TPUBASE + _TIER);
+       ctrl_outw(cnt, TPUBASE + _GRA);
+       ctrl_bset(CONFIG_H8300_TPU_CH, TSTR);
+}
index f8f7d7ea97f17298522e599d22ce4e388cc5009a..3c0b66bc669eca40ced007cccb5d2ce5d6695904 100644 (file)
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/bug.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/page.h>
-#include <asm/gpio.h>
+
+static DEFINE_SPINLOCK(die_lock);
 
 /*
  * this must be called very early as the kernel might
@@ -94,16 +96,19 @@ static void dump(struct pt_regs *fp)
        printk("\n\n");
 }
 
-void die_if_kernel (char *str, struct pt_regs *fp, int nr)
+void die(char *str, struct pt_regs *fp, unsigned long err)
 {
-       extern int console_loglevel;
+       static int diecount;
 
-       if (!(fp->ccr & PS_S))
-               return;
+       oops_enter();
 
-       console_loglevel = 15;
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       report_bug(fp->pc, fp);
+       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++diecount);
        dump(fp);
 
+       spin_unlock_irq(&die_lock);
        do_exit(SIGSEGV);
 }
 
index 29e9af9f0e6a71942178bb9daff5f997e733060a..1d092abebf03bcfbeabfbe41f67b99cb1260e58e 100644 (file)
@@ -20,8 +20,6 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
-extern void die_if_kernel(char *, struct pt_regs *, long);
-
 /*
  * This routine handles page faults.  It determines the problem, and
  * then passes it off to one of the appropriate routines.
@@ -50,7 +48,8 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
        } else
                printk(KERN_ALERT "Unable to handle kernel access");
        printk(" at virtual address %08lx\n",address);
-       die_if_kernel("Oops", regs, error_code);
+       if (!user_mode(regs))
+               die("Oops", regs, error_code);
        do_exit(SIGKILL);
 
        return 1;
index b03c328f8c703ac578faf82eb7a3a2fb929a5a18..b7ff78050b7f7237d9b9566b0d1eba4f4fac44eb 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 extra-y := crt0_ram.o
-obj-y := timer.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/timer.c b/arch/h8300/platform/h8300h/aki3068net/timer.c
deleted file mode 100644 (file)
index 27cd85d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/aki3068net/timer.c
- *
- *  Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- *  Platform depend Timer Handler
- *
- */
-
-#include <linux/errno.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/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-#define CMFA 6
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CLK_DIV8192 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       /* setup 8bit timer ch2 */
-       ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2);      /* set interval */
-       ctrl_outb(0x00, _8TCSR2);                      /* no output */
-       request_irq(40, timer_int, 0, "timer", 0);
-       ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
-}
-
-void platform_timer_eoi(void)
-{
-       *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
-}
-
-void platform_gettod(int *year, int *mon, int *day, int *hour,
-                int *min, int *sec)
-{
-       *year = *mon = *day = *hour = *min = *sec = 0;
-}
index 32b964a9010e25a43720e5d39d3942a868e4ae42..2b12a170209e0086693aa2dcf71a3397857c21af 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 extra-y :=  crt0_$(MODEL).o
-obj-y := timer.o
diff --git a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c
deleted file mode 100644 (file)
index 6f5cefe..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/generic/timer.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend Timer Handler
- *
- */
-
-#include <linux/errno.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 <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <linux/timex.h>
-
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#define CMFA 6
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CLK_DIV8192 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       /* setup 8bit timer ch2 */
-       ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2);      /* set interval */
-       ctrl_outb(0x00, _8TCSR2);                      /* no output */
-       request_irq(40, timer_int, 0, "timer", 0);
-       ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
-}
-
-void platform_timer_eoi(void)
-{
-       *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
-}
-#endif
-
-#if defined(CONFIG_H83002) || defined(CONFIG_H83048)
-/* FIXME! */
-#define TSTR 0x00ffff60
-#define TSNC 0x00ffff61
-#define TMDR 0x00ffff62
-#define TFCR 0x00ffff63
-#define TOER 0x00ffff90
-#define TOCR 0x00ffff91
-/* ITU0 */
-#define TCR  0x00ffff64
-#define TIOR 0x00ffff65
-#define TIER 0x00ffff66
-#define TSR  0x00ffff67
-#define TCNT 0x00ffff68
-#define GRA  0x00ffff6a
-#define GRB  0x00ffff6c
-
-#define CCLR_CMGRA 0x20
-#define CLK_DIV8 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       *(unsigned short *)GRA= H8300_TIMER_FREQ / HZ;  /* set interval */
-       *(unsigned short *)TCNT=0;                      /* clear counter */
-       ctrl_outb(0x80|CCLR_CMGRA|CLK_DIV8, TCR);       /* set ITU0 clock */
-       ctrl_outb(0x88, TIOR);                          /* no output */
-       request_irq(26, timer_int, 0, "timer", 0);
-       ctrl_outb(0xf9, TIER);                          /* compare match GRA interrupt */
-       ctrl_outb(ctrl_inb(TSNC) & ~0x01, TSNC);        /* ITU0 async */
-       ctrl_outb(ctrl_inb(TMDR) & ~0x01, TMDR);        /* ITU0 normal mode */
-       ctrl_outb(ctrl_inb(TSTR) | 0x01, TSTR);         /* ITU0 Start */
-       return 0;
-}
-
-void platform_timer_eoi(void)
-{
-       ctrl_outb(ctrl_inb(TSR) & ~0x01,TSR);
-}
-#endif
-
-void platform_gettod(int *year, int *mon, int *day, int *hour,
-                int *min, int *sec)
-{
-       *year = *mon = *day = *hour = *min = *sec = 0;
-}
index b03c328f8c703ac578faf82eb7a3a2fb929a5a18..b7ff78050b7f7237d9b9566b0d1eba4f4fac44eb 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 extra-y := crt0_ram.o
-obj-y := timer.o
diff --git a/arch/h8300/platform/h8300h/h8max/timer.c b/arch/h8300/platform/h8300h/h8max/timer.c
deleted file mode 100644 (file)
index 85a574a..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/h8max/timer.c
- *
- *  Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- *  Platform depend Timer Handler
- *
- */
-
-#include <linux/errno.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/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-#define CMFA 6
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CLK_DIV8192 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       /* setup 8bit timer ch2 */
-       ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2);      /* set interval */
-       ctrl_outb(0x00, _8TCSR2);                      /* no output */
-       request_irq(40, timer_int, 0, "timer", 0);
-       ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
-}
-
-void platform_timer_eoi(void)
-{
-       *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
-}
-
-void platform_gettod(int *year, int *mon, int *day, int *hour,
-                int *min, int *sec)
-{
-       *year = *mon = *day = *hour = *min = *sec = 0;
-}
-
index f763654ac6fefc177b92bb6211dae9d2a6b34677..8e349723bb4f618b283da45e1e5797838ca7e0ea 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 extra-y := crt0_$(MODEL).o
-obj-y := timer.o
diff --git a/arch/h8300/platform/h8s/edosk2674/timer.c b/arch/h8300/platform/h8s/edosk2674/timer.c
deleted file mode 100644 (file)
index bfb1424..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/edosk2674/timer.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend Timer Handler
- *
- */
-
-#include <linux/errno.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/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs267x.h>
-
-#define CMFA 6
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CLK_DIV8192 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       /* 8bit timer module enabled */
-       ctrl_outb(ctrl_inb(MSTPCRL) & ~0x01, MSTPCRL);
-       /* setup 8bit timer ch1 */
-       ctrl_outb(H8300_TIMER_FREQ / HZ, _8TCORA1);      /* set interval */
-       ctrl_outb(0x00, _8TCSR1);                        /* no output */
-       request_irq(76, timer_int, 0, "timer" ,0);
-       ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR1);   /* start count */
-}
-
-void platform_timer_eoi(void)
-{
-       *(volatile unsigned char *)_8TCSR1 &= ~(1 << CMFA);
-}
-
-void platform_gettod(int *year, int *mon, int *day, int *hour,
-                int *min, int *sec)
-{
-/* FIXME! not RTC support */
-       *year = *mon = *day = *hour = *min = *sec = 0;
-}
index 055d53a9811ba70dc41eb48050ee686486dbd0ae..44b4685c664c8bf7b52e7bfb6fd54d8655a165f3 100644 (file)
@@ -3,4 +3,3 @@
 #
 
 extra-y =  crt0_$(MODEL).o
-obj-y := timer.o
diff --git a/arch/h8300/platform/h8s/generic/timer.c b/arch/h8300/platform/h8s/generic/timer.c
deleted file mode 100644 (file)
index c2211c6..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/generic/timer.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend Timer Handler
- *
- */
-
-#include <linux/errno.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/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs267x.h>
-
-#define CMFA 6
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CLK_DIV8192 0x03
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
-
-void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
-{
-       /* 8bit timer module enabled */
-       ctrl_outb(ctrl_inb(MSTPCRL) & ~0x01, MSTPCRL);
-       /* setup 8bit timer ch1 */
-       ctrl_outb(H8300_TIMER_FREQ / HZ, _8TCORA1);      /* set interval */
-       ctrl_outb(0x00, _8TCSR1);                        /* no output */
-       request_irq(76, timer_int, 0, "timer" ,0);
-       ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR1);   /* start count */
-}
-
-void platform_timer_eoi(void)
-{
-       *(volatile unsigned char *)_8TCSR1 &= ~(1 << CMFA);
-}
-
-void platform_gettod(int *year, int *mon, int *day, int *hour,
-                int *min, int *sec)
-{
-       *year = *mon = *day = *hour = *min = *sec = 0;
-}
index 48e496fe1e753102811cb4064f4da6d8f0060c4f..3b7aa38254a8408b5564a260eb7a2ef30cf8d5f8 100644 (file)
@@ -60,14 +60,6 @@ config RWSEM_XCHGADD_ALGORITHM
        bool
        default y
 
-config ARCH_HAS_ILOG2_U32
-       bool
-       default n
-
-config ARCH_HAS_ILOG2_U64
-       bool
-       default n
-
 config HUGETLB_PAGE_SIZE_VARIABLE
        bool
        depends on HUGETLB_PAGE
index 4f0c30c38e994c1ea188f811232ecc27f7b81be1..f92bdaac8976ecff13c9639743d8411289f5581f 100644 (file)
@@ -41,7 +41,7 @@ randomize_stack_top(unsigned long stack_top);
 #define elf_map                                elf32_map
 
 #undef SET_PERSONALITY
-#define SET_PERSONALITY(ex, ibcs2)     elf32_set_personality()
+#define SET_PERSONALITY(ex)    elf32_set_personality()
 
 #define elf_read_implies_exec(ex, have_pt_gnu_stack)   (!(have_pt_gnu_stack))
 
index ff88c48c5d19a9ba07d047b784f05dfe89e55d2f..53505bb04771811b42a74fc7d15bebb8cb25e0e4 100644 (file)
@@ -251,8 +251,8 @@ ia32_syscall_table:
        data8 compat_sys_setrlimit        /* 75 */
        data8 compat_sys_old_getrlimit
        data8 compat_sys_getrusage
-       data8 sys32_gettimeofday
-       data8 sys32_settimeofday
+       data8 compat_sys_gettimeofday
+       data8 compat_sys_settimeofday
        data8 sys32_getgroups16   /* 80 */
        data8 sys32_setgroups16
        data8 sys32_old_select
index dd0c53687a96d9f022b7a119d7f6310168c9a25c..0f15349c3c6b4ee6d56d4a22de3da87e8e7b0c69 100644 (file)
@@ -332,8 +332,8 @@ void ia64_elf32_init(struct pt_regs *regs);
 #define ELF_PLATFORM   NULL
 
 #ifdef __KERNEL__
-# define SET_PERSONALITY(EX,IBCS2)                             \
-       (current->personality = (IBCS2) ? PER_SVR4 : PER_LINUX)
+# define SET_PERSONALITY(EX)                           \
+       (current->personality = PER_LINUX)
 #endif
 
 #define IA32_EFLAG     0x200
index bf196cbb37969ca5016b937e2074e71b48a03fff..f4430bb4bbdcc46335cf4f21579f77cd26e6afd9 100644 (file)
@@ -118,41 +118,6 @@ sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __use
        return error;
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if ((u64) stat->size > MAX_NON_LFS ||
-           !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       if (clear_user(ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
-       err |= __put_user(ino, &ubuf->st_ino);
-       err |= __put_user(stat->mode, &ubuf->st_mode);
-       err |= __put_user(stat->nlink, &ubuf->st_nlink);
-       err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid);
-       err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid);
-       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
-       err |= __put_user(stat->size, &ubuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &ubuf->st_blksize);
-       err |= __put_user(stat->blocks, &ubuf->st_blocks);
-       return err;
-}
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
 
@@ -1148,68 +1113,12 @@ sys32_pipe (int __user *fd)
        return retval;
 }
 
-static inline long
-get_tv32 (struct timeval *o, struct compat_timeval __user *i)
-{
-       return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-               (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
-}
-
-static inline long
-put_tv32 (struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
-}
-
 asmlinkage unsigned long
 sys32_alarm (unsigned int seconds)
 {
        return alarm_setitimer(seconds);
 }
 
-/* Translations due to time_t size differences.  Which affects all
-   sorts of things, like timeval and itimerval.  */
-
-extern struct timezone sys_tz;
-
-asmlinkage long
-sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-asmlinkage long
-sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timeval ktv;
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_tv32(&ktv, tv))
-                       return -EFAULT;
-               kts.tv_sec = ktv.tv_sec;
-               kts.tv_nsec = ktv.tv_usec * 1000;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 struct sel_arg_struct {
        unsigned int n;
        unsigned int inp;
diff --git a/arch/ia64/include/asm/a.out.h b/arch/ia64/include/asm/a.out.h
deleted file mode 100644 (file)
index 193dcfb..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _ASM_IA64_A_OUT_H
-#define _ASM_IA64_A_OUT_H
-
-/*
- * No a.out format has been (or should be) defined so this file is
- * just a dummy that allows us to get binfmt_elf compiled.  It
- * probably would be better to clean up binfmt_elf.c so it does not
- * necessarily depend on there being a.out support.
- *
- * Modified 1998-2002
- *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
- */
-
-#include <linux/types.h>
-
-struct exec {
-       unsigned long a_info;
-       unsigned long a_text;
-       unsigned long a_data;
-       unsigned long a_bss;
-       unsigned long a_entry;
-};
-
-#define N_TXTADDR(x)   0
-#define N_DATADDR(x)   0
-#define N_BSSADDR(x)   0
-#define N_DRSIZE(x)    0
-#define N_TRSIZE(x)    0
-#define N_SYMSIZE(x)   0
-#define N_TXTOFF(x)    0
-
-#endif /* _ASM_IA64_A_OUT_H */
index 2acb6b6543c914c6293331623ed77a956918340a..86eddee029cb5238c00d4de2ef1c432f37e97e6d 100644 (file)
@@ -202,7 +202,7 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
    relevant until we have real hardware to play with... */
 #define ELF_PLATFORM   NULL
 
-#define SET_PERSONALITY(ex, ibcs2)     set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex)    set_personality(PER_LINUX)
 #define elf_read_implies_exec(ex, executable_stack)                                    \
        ((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0)
 
index 1efe513a99415c6b0557ae6e00486ac5bd50c327..85db124d37f6a91498a02821f320138106bbc4fc 100644 (file)
 #define GPFN_IOSAPIC        (4UL << 60) /* IOSAPIC base */
 #define GPFN_LEGACY_IO      (5UL << 60) /* Legacy I/O base */
 #define GPFN_GFW        (6UL << 60) /* Guest Firmware */
-#define GPFN_HIGH_MMIO      (7UL << 60) /* High MMIO range */
+#define GPFN_PHYS_MMIO      (7UL << 60) /* Directed MMIO Range */
 
 #define GPFN_IO_MASK        (7UL << 60) /* Guest pfn is I/O type */
 #define GPFN_INV_MASK       (1UL << 63) /* Guest pfn is invalid */
@@ -413,6 +413,10 @@ struct kvm_arch {
        struct kvm_ioapic *vioapic;
        struct kvm_vm_stat stat;
        struct kvm_sal_data rdv_sal_data;
+
+       struct list_head assigned_dev_head;
+       struct dmar_domain *intel_iommu_domain;
+       struct hlist_head irq_ack_notifier_list;
 };
 
 union cpuid3_t {
index 811097974f31ed54d281564134c648fb62e7ea59..1e589669de56fee4f2dd1c718efd2191776c5770 100644 (file)
@@ -8,55 +8,13 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
-#ifndef __KERNEL_STRICT_NAMES
-# include <linux/types.h>
-typedef __kernel_fsid_t        fsid_t;
-#endif
-
 /*
- * This is ugly --- we're already 64-bit, so just duplicate the definitions
+ * We need compat_statfs64 to be packed, because the i386 ABI won't
+ * add padding at the end to bring it to a multiple of 8 bytes, but
+ * the IA64 ABI will.
  */
-struct statfs {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-
-struct statfs64 {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
+#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
 
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-} __attribute__((packed));
+#include <asm-generic/statfs.h>
 
 #endif /* _ASM_IA64_STATFS_H */
index 7914e4828504595c161aee52025ed9e5f0cdaba0..8e99fed6b3fd932a61b8d2de2537710748717b2d 100644 (file)
@@ -46,4 +46,6 @@ config KVM_INTEL
 config KVM_TRACE
        bool
 
+source drivers/virtio/Kconfig
+
 endif # VIRTUALIZATION
index bf22fb9e6dcf8f04f5a289dad646ec7b8229511e..cf37f8f490c030a02fb458df21c376af4a051bdb 100644 (file)
@@ -44,7 +44,11 @@ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
 EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
-               coalesced_mmio.o)
+               coalesced_mmio.o irq_comm.o)
+
+ifeq ($(CONFIG_DMAR),y)
+common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+endif
 
 kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/ia64/kvm/irq.h b/arch/ia64/kvm/irq.h
new file mode 100644 (file)
index 0000000..c6786e8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * irq.h: In-kernel interrupt controller related definitions
+ * Copyright (c) 2008, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Xiantao Zhang <xiantao.zhang@intel.com>
+ *
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+static inline int irqchip_in_kernel(struct kvm *kvm)
+{
+       return 1;
+}
+
+#endif
index cd0d1a7284b78afbe673424b4463d3f6463621de..c0699f0e35a926936113e42d925b4fd08318c1c3 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/bitops.h>
 #include <linux/hrtimer.h>
 #include <linux/uaccess.h>
+#include <linux/intel-iommu.h>
 
 #include <asm/pgtable.h>
 #include <asm/gcc_intrin.h>
@@ -45,6 +46,7 @@
 #include "iodev.h"
 #include "ioapic.h"
 #include "lapic.h"
+#include "irq.h"
 
 static unsigned long kvm_vmm_base;
 static unsigned long kvm_vsa_base;
@@ -179,12 +181,16 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
        case KVM_CAP_IRQCHIP:
        case KVM_CAP_USER_MEMORY:
+       case KVM_CAP_MP_STATE:
 
                r = 1;
                break;
        case KVM_CAP_COALESCED_MMIO:
                r = KVM_COALESCED_MMIO_PAGE_OFFSET;
                break;
+       case KVM_CAP_IOMMU:
+               r = intel_iommu_found();
+               break;
        default:
                r = 0;
        }
@@ -771,6 +777,7 @@ static void kvm_init_vm(struct kvm *kvm)
         */
        kvm_build_io_pmt(kvm);
 
+       INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 }
 
 struct  kvm *kvm_arch_create_vm(void)
@@ -1334,6 +1341,10 @@ static void kvm_release_vm_pages(struct kvm *kvm)
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+       kvm_iommu_unmap_guest(kvm);
+#ifdef  KVM_CAP_DEVICE_ASSIGNMENT
+       kvm_free_all_assigned_devices(kvm);
+#endif
        kfree(kvm->arch.vioapic);
        kvm_release_vm_pages(kvm);
        kvm_free_physmem(kvm);
@@ -1435,17 +1446,24 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
                int user_alloc)
 {
        unsigned long i;
-       struct page *page;
+       unsigned long pfn;
        int npages = mem->memory_size >> PAGE_SHIFT;
        struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
        unsigned long base_gfn = memslot->base_gfn;
 
        for (i = 0; i < npages; i++) {
-               page = gfn_to_page(kvm, base_gfn + i);
-               kvm_set_pmt_entry(kvm, base_gfn + i,
-                               page_to_pfn(page) << PAGE_SHIFT,
-                               _PAGE_AR_RWX|_PAGE_MA_WB);
-               memslot->rmap[i] = (unsigned long)page;
+               pfn = gfn_to_pfn(kvm, base_gfn + i);
+               if (!kvm_is_mmio_pfn(pfn)) {
+                       kvm_set_pmt_entry(kvm, base_gfn + i,
+                                       pfn << PAGE_SHIFT,
+                               _PAGE_AR_RWX | _PAGE_MA_WB);
+                       memslot->rmap[i] = (unsigned long)pfn_to_page(pfn);
+               } else {
+                       kvm_set_pmt_entry(kvm, base_gfn + i,
+                                       GPFN_PHYS_MMIO | (pfn << PAGE_SHIFT),
+                                       _PAGE_MA_UC);
+                       memslot->rmap[i] = 0;
+                       }
        }
 
        return 0;
@@ -1789,11 +1807,43 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       vcpu_load(vcpu);
+       mp_state->mp_state = vcpu->arch.mp_state;
+       vcpu_put(vcpu);
+       return 0;
+}
+
+static int vcpu_reset(struct kvm_vcpu *vcpu)
+{
+       int r;
+       long psr;
+       local_irq_save(psr);
+       r = kvm_insert_vmm_mapping(vcpu);
+       if (r)
+               goto fail;
+
+       vcpu->arch.launched = 0;
+       kvm_arch_vcpu_uninit(vcpu);
+       r = kvm_arch_vcpu_init(vcpu);
+       if (r)
+               goto fail;
+
+       kvm_purge_vmm_mapping(vcpu);
+       r = 0;
+fail:
+       local_irq_restore(psr);
+       return r;
 }
 
 int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
-       return -EINVAL;
+       int r = 0;
+
+       vcpu_load(vcpu);
+       vcpu->arch.mp_state = mp_state->mp_state;
+       if (vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)
+               r = vcpu_reset(vcpu);
+       vcpu_put(vcpu);
+       return r;
 }
index 13980d9b8bcf1542ea29756990e2ce4a3b941d9e..2cc41d17cf991855d31460c1025137589e037461 100644 (file)
 
 #define PAL_VSA_SYNC_READ                                              \
        /* begin to call pal vps sync_read */                           \
+{.mii;                                                                 \
        add r25 = VMM_VPD_BASE_OFFSET, r21;                             \
-       adds r20 = VMM_VCPU_VSA_BASE_OFFSET, r21;  /* entry point */    \
+       nop 0x0;                                                        \
+       mov r24=ip;                                                     \
        ;;                                                              \
+}                                                                      \
+{.mmb                                                                  \
+       add r24=0x20, r24;                                              \
        ld8 r25 = [r25];      /* read vpd base */                       \
-       ld8 r20 = [r20];                                                \
-       ;;                                                              \
-       add r20 = PAL_VPS_SYNC_READ,r20;                                \
-       ;;                                                              \
-{ .mii;                                                                        \
-       nop 0x0;                                                        \
-       mov r24 = ip;                                                   \
-       mov b0 = r20;                                                   \
+       br.cond.sptk kvm_vps_sync_read;         /*call the service*/    \
        ;;                                                              \
 };                                                                     \
-{ .mmb;                                                                        \
-       add r24 = 0x20, r24;                                            \
-       nop 0x0;                                                        \
-       br.cond.sptk b0;        /*  call the service */                 \
-       ;;                                                              \
-};
-
 
 
 #define KVM_MINSTATE_GET_CURRENT(reg)   mov reg=r21
index e4f15d641b22dfbc5c21ea85f4c2e2db1d54a36b..634abad979b5143953e6eae5191eff3b4a673bc1 100644 (file)
@@ -1,9 +1,12 @@
 /*
- * arch/ia64/vmx/optvfault.S
+ * arch/ia64/kvm/optvfault.S
  * optimize virtualization fault handler
  *
  * Copyright (C) 2006 Intel Co
  *     Xuefei Xu (Anthony Xu) <anthony.xu@intel.com>
+ * Copyright (C) 2008 Intel Co
+ *      Add the support for Tukwila processors.
+ *     Xiantao Zhang <xiantao.zhang@intel.com>
  */
 
 #include <asm/asmmacro.h>
 #define ACCE_MOV_TO_PSR
 #define ACCE_THASH
 
+#define VMX_VPS_SYNC_READ                      \
+       add r16=VMM_VPD_BASE_OFFSET,r21;        \
+       mov r17 = b0;                           \
+       mov r18 = r24;                          \
+       mov r19 = r25;                          \
+       mov r20 = r31;                          \
+       ;;                                      \
+{.mii;                                         \
+       ld8 r16 = [r16];                        \
+       nop 0x0;                                \
+       mov r24 = ip;                           \
+       ;;                                      \
+};                                             \
+{.mmb;                                         \
+       add r24=0x20, r24;                      \
+       mov r25 =r16;                           \
+       br.sptk.many kvm_vps_sync_read;         \
+};                                             \
+       mov b0 = r17;                           \
+       mov r24 = r18;                          \
+       mov r25 = r19;                          \
+       mov r31 = r20
+
+ENTRY(kvm_vps_entry)
+       adds r29 = VMM_VCPU_VSA_BASE_OFFSET,r21
+       ;;
+       ld8 r29 = [r29]
+       ;;
+       add r29 = r29, r30
+       ;;
+       mov b0 = r29
+       br.sptk.many b0
+END(kvm_vps_entry)
+
+/*
+ *     Inputs:
+ *     r24 : return address
+ *     r25 : vpd
+ *     r29 : scratch
+ *
+ */
+GLOBAL_ENTRY(kvm_vps_sync_read)
+       movl r30 = PAL_VPS_SYNC_READ
+       ;;
+       br.sptk.many kvm_vps_entry
+END(kvm_vps_sync_read)
+
+/*
+ *     Inputs:
+ *     r24 : return address
+ *     r25 : vpd
+ *     r29 : scratch
+ *
+ */
+GLOBAL_ENTRY(kvm_vps_sync_write)
+       movl r30 = PAL_VPS_SYNC_WRITE
+       ;;
+       br.sptk.many kvm_vps_entry
+END(kvm_vps_sync_write)
+
+/*
+ *     Inputs:
+ *     r23 : pr
+ *     r24 : guest b0
+ *     r25 : vpd
+ *
+ */
+GLOBAL_ENTRY(kvm_vps_resume_normal)
+       movl r30 = PAL_VPS_RESUME_NORMAL
+       ;;
+       mov pr=r23,-2
+       br.sptk.many kvm_vps_entry
+END(kvm_vps_resume_normal)
+
+/*
+ *     Inputs:
+ *     r23 : pr
+ *     r24 : guest b0
+ *     r25 : vpd
+ *     r17 : isr
+ */
+GLOBAL_ENTRY(kvm_vps_resume_handler)
+       movl r30 = PAL_VPS_RESUME_HANDLER
+       ;;
+       ld8 r27=[r25]
+       shr r17=r17,IA64_ISR_IR_BIT
+       ;;
+       dep r27=r17,r27,63,1   // bit 63 of r27 indicate whether enable CFLE
+       mov pr=r23,-2
+       br.sptk.many kvm_vps_entry
+END(kvm_vps_resume_handler)
+
 //mov r1=ar3
 GLOBAL_ENTRY(kvm_asm_mov_from_ar)
 #ifndef ACCE_MOV_FROM_AR
@@ -157,11 +252,11 @@ GLOBAL_ENTRY(kvm_asm_rsm)
 #ifndef ACCE_RSM
        br.many kvm_virtualization_fault_back
 #endif
-       add r16=VMM_VPD_BASE_OFFSET,r21
+       VMX_VPS_SYNC_READ
+       ;;
        extr.u r26=r25,6,21
        extr.u r27=r25,31,2
        ;;
-       ld8 r16=[r16]
        extr.u r28=r25,36,1
        dep r26=r27,r26,21,2
        ;;
@@ -196,7 +291,7 @@ GLOBAL_ENTRY(kvm_asm_rsm)
        tbit.nz p6,p0=r23,0
        ;;
        tbit.z.or p6,p0=r26,IA64_PSR_DT_BIT
-       (p6) br.dptk kvm_resume_to_guest
+       (p6) br.dptk kvm_resume_to_guest_with_sync
        ;;
        add r26=VMM_VCPU_META_RR0_OFFSET,r21
        add r27=VMM_VCPU_META_RR0_OFFSET+8,r21
@@ -212,7 +307,7 @@ GLOBAL_ENTRY(kvm_asm_rsm)
        mov rr[r28]=r27
        ;;
        srlz.d
-       br.many kvm_resume_to_guest
+       br.many kvm_resume_to_guest_with_sync
 END(kvm_asm_rsm)
 
 
@@ -221,11 +316,11 @@ GLOBAL_ENTRY(kvm_asm_ssm)
 #ifndef ACCE_SSM
        br.many kvm_virtualization_fault_back
 #endif
-       add r16=VMM_VPD_BASE_OFFSET,r21
+       VMX_VPS_SYNC_READ
+       ;;
        extr.u r26=r25,6,21
        extr.u r27=r25,31,2
        ;;
-       ld8 r16=[r16]
        extr.u r28=r25,36,1
        dep r26=r27,r26,21,2
        ;;  //r26 is imm24
@@ -271,7 +366,7 @@ kvm_asm_ssm_1:
        tbit.nz p6,p0=r29,IA64_PSR_I_BIT
        ;;
        tbit.z.or p6,p0=r19,IA64_PSR_I_BIT
-       (p6) br.dptk kvm_resume_to_guest
+       (p6) br.dptk kvm_resume_to_guest_with_sync
        ;;
        add r29=VPD_VTPR_START_OFFSET,r16
        add r30=VPD_VHPI_START_OFFSET,r16
@@ -286,7 +381,7 @@ kvm_asm_ssm_1:
        ;;
        cmp.gt p6,p0=r30,r17
        (p6) br.dpnt.few kvm_asm_dispatch_vexirq
-       br.many kvm_resume_to_guest
+       br.many kvm_resume_to_guest_with_sync
 END(kvm_asm_ssm)
 
 
@@ -295,10 +390,9 @@ GLOBAL_ENTRY(kvm_asm_mov_to_psr)
 #ifndef ACCE_MOV_TO_PSR
        br.many kvm_virtualization_fault_back
 #endif
-       add r16=VMM_VPD_BASE_OFFSET,r21
-       extr.u r26=r25,13,7 //r2
+       VMX_VPS_SYNC_READ
        ;;
-       ld8 r16=[r16]
+       extr.u r26=r25,13,7 //r2
        addl r20=@gprel(asm_mov_from_reg),gp
        ;;
        adds r30=kvm_asm_mov_to_psr_back-asm_mov_from_reg,r20
@@ -374,7 +468,7 @@ kvm_asm_mov_to_psr_1:
        ;;
        tbit.nz.or p6,p0=r17,IA64_PSR_I_BIT
        tbit.z.or p6,p0=r30,IA64_PSR_I_BIT
-       (p6) br.dpnt.few kvm_resume_to_guest
+       (p6) br.dpnt.few kvm_resume_to_guest_with_sync
        ;;
        add r29=VPD_VTPR_START_OFFSET,r16
        add r30=VPD_VHPI_START_OFFSET,r16
@@ -389,13 +483,29 @@ kvm_asm_mov_to_psr_1:
        ;;
        cmp.gt p6,p0=r30,r17
        (p6) br.dpnt.few kvm_asm_dispatch_vexirq
-       br.many kvm_resume_to_guest
+       br.many kvm_resume_to_guest_with_sync
 END(kvm_asm_mov_to_psr)
 
 
 ENTRY(kvm_asm_dispatch_vexirq)
 //increment iip
+       mov r17 = b0
+       mov r18 = r31
+{.mii
+       add r25=VMM_VPD_BASE_OFFSET,r21
+       nop 0x0
+       mov r24 = ip
+       ;;
+}
+{.mmb
+       add r24 = 0x20, r24
+       ld8 r25 = [r25]
+       br.sptk.many kvm_vps_sync_write
+}
+       mov b0 =r17
        mov r16=cr.ipsr
+       mov r31 = r18
+       mov r19 = 37
        ;;
        extr.u r17=r16,IA64_PSR_RI_BIT,2
        tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
@@ -435,25 +545,31 @@ GLOBAL_ENTRY(kvm_asm_thash)
        ;;
 kvm_asm_thash_back1:
        shr.u r23=r19,61                // get RR number
-       adds r25=VMM_VCPU_VRR0_OFFSET,r21       // get vcpu->arch.vrr[0]'s addr
+       adds r28=VMM_VCPU_VRR0_OFFSET,r21       // get vcpu->arch.vrr[0]'s addr
        adds r16=VMM_VPD_VPTA_OFFSET,r16        // get vpta
        ;;
-       shladd r27=r23,3,r25    // get vcpu->arch.vrr[r23]'s addr
+       shladd r27=r23,3,r28    // get vcpu->arch.vrr[r23]'s addr
        ld8 r17=[r16]           // get PTA
        mov r26=1
        ;;
-       extr.u r29=r17,2,6              // get pta.size
-       ld8 r25=[r27]           // get vcpu->arch.vrr[r23]'s value
+       extr.u r29=r17,2,6      // get pta.size
+       ld8 r28=[r27]           // get vcpu->arch.vrr[r23]'s value
        ;;
-       extr.u r25=r25,2,6              // get rr.ps
+       mov b0=r24
+       //Fallback to C if pta.vf is set
+       tbit.nz p6,p0=r17, 8
+       ;;
+       (p6) mov r24=EVENT_THASH
+       (p6) br.cond.dpnt.many kvm_virtualization_fault_back
+       extr.u r28=r28,2,6      // get rr.ps
        shl r22=r26,r29         // 1UL << pta.size
        ;;
-       shr.u r23=r19,r25               // vaddr >> rr.ps
+       shr.u r23=r19,r28       // vaddr >> rr.ps
        adds r26=3,r29          // pta.size + 3
        shl r27=r17,3           // pta << 3
        ;;
        shl r23=r23,3           // (vaddr >> rr.ps) << 3
-       shr.u r27=r27,r26               // (pta << 3) >> (pta.size+3)
+       shr.u r27=r27,r26       // (pta << 3) >> (pta.size+3)
        movl r16=7<<61
        ;;
        adds r22=-1,r22         // (1UL << pta.size) - 1
@@ -724,6 +840,29 @@ END(asm_mov_from_reg)
  * r31: pr
  * r24: b0
  */
+ENTRY(kvm_resume_to_guest_with_sync)
+       adds r19=VMM_VPD_BASE_OFFSET,r21
+       mov r16 = r31
+       mov r17 = r24
+       ;;
+{.mii
+       ld8 r25 =[r19]
+       nop 0x0
+       mov r24 = ip
+       ;;
+}
+{.mmb
+       add r24 =0x20, r24
+       nop 0x0
+       br.sptk.many kvm_vps_sync_write
+}
+
+       mov r31 = r16
+       mov r24 =r17
+       ;;
+       br.sptk.many kvm_resume_to_guest
+END(kvm_resume_to_guest_with_sync)
+
 ENTRY(kvm_resume_to_guest)
        adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
        ;;
index 5a33f7ed29a0af4b3410f9fa1259b839f657eefa..3417783ae16446f8f7b4347afe6e801b0b473191 100644 (file)
@@ -962,9 +962,9 @@ static void kvm_do_resume_op(struct kvm_vcpu *vcpu)
 void vmm_transition(struct kvm_vcpu *vcpu)
 {
        ia64_call_vsa(PAL_VPS_SAVE, (unsigned long)vcpu->arch.vpd,
-                       0, 0, 0, 0, 0, 0);
+                       1, 0, 0, 0, 0, 0);
        vmm_trampoline(&vcpu->arch.guest, &vcpu->arch.host);
        ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)vcpu->arch.vpd,
-                                               0, 0, 0, 0, 0, 0);
+                                               1, 0, 0, 0, 0, 0);
        kvm_do_resume_op(vcpu);
 }
index b0fcfb62c49e8a660464be9fca38c2e555ab20cc..341e3fee280cd502cbb270aaea00218548fcdbff 100644 (file)
@@ -313,21 +313,21 @@ static inline void vcpu_set_tr(struct thash_data *trp, u64 pte, u64 itir,
        trp->rid = rid;
 }
 
-extern u64 kvm_lookup_mpa(u64 gpfn);
-extern u64 kvm_gpa_to_mpa(u64 gpa);
-
-/* Return I/O type if trye */
-#define __gpfn_is_io(gpfn)                     \
-       ({                                              \
-        u64 pte, ret = 0;                      \
-        pte = kvm_lookup_mpa(gpfn);            \
-        if (!(pte & GPFN_INV_MASK))            \
-        ret = pte & GPFN_IO_MASK;      \
-        ret;                                   \
-        })
+extern u64 kvm_get_mpt_entry(u64 gpfn);
 
+/* Return I/ */
+static inline u64 __gpfn_is_io(u64 gpfn)
+{
+       u64  pte;
+       pte = kvm_get_mpt_entry(gpfn);
+       if (!(pte & GPFN_INV_MASK)) {
+               pte = pte & GPFN_IO_MASK;
+               if (pte != GPFN_PHYS_MMIO)
+                       return pte;
+       }
+       return 0;
+}
 #endif
-
 #define IA64_NO_FAULT  0
 #define IA64_FAULT     1
 
index 3ee5f481c06dccbd62f88940cacb8f2662567c71..c1d7251a148008bcbdcb57b9b0611ab9dc6a52ee 100644 (file)
@@ -1261,11 +1261,6 @@ kvm_rse_clear_invalid:
     adds r19=VMM_VPD_VPSR_OFFSET,r18
     ;;
     ld8 r19=[r19]        //vpsr
-    adds r20=VMM_VCPU_VSA_BASE_OFFSET,r21
-    ;;
-    ld8 r20=[r20]
-    ;;
-//vsa_sync_write_start
     mov r25=r18
     adds r16= VMM_VCPU_GP_OFFSET,r21
     ;;
@@ -1274,10 +1269,7 @@ kvm_rse_clear_invalid:
     ;;
     add  r24=r24,r16
     ;;
-    add r16=PAL_VPS_SYNC_WRITE,r20
-    ;;
-    mov b0=r16
-    br.cond.sptk b0         // call the service
+    br.sptk.many  kvm_vps_sync_write       // call the service
     ;;
 END(ia64_leave_hypervisor)
 // fall through
@@ -1288,28 +1280,15 @@ GLOBAL_ENTRY(ia64_vmm_entry)
  *  r17:cr.isr
  *  r18:vpd
  *  r19:vpsr
- *  r20:__vsa_base
  *  r22:b0
  *  r23:predicate
  */
     mov r24=r22
     mov r25=r18
     tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT        // p1=vpsr.ic
+    (p1) br.cond.sptk.few kvm_vps_resume_normal
+    (p2) br.cond.sptk.many kvm_vps_resume_handler
     ;;
-    (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
-    (p1) br.sptk.many ia64_vmm_entry_out
-    ;;
-    tbit.nz p1,p2 = r17,IA64_ISR_IR_BIT                //p1=cr.isr.ir
-    ;;
-    (p1) add r29=PAL_VPS_RESUME_NORMAL,r20
-    (p2) add r29=PAL_VPS_RESUME_HANDLER,r20
-    (p2) ld8 r26=[r25]
-    ;;
-ia64_vmm_entry_out:
-    mov pr=r23,-2
-    mov b0=r29
-    ;;
-    br.cond.sptk b0             // call pal service
 END(ia64_vmm_entry)
 
 
@@ -1376,6 +1355,9 @@ GLOBAL_ENTRY(vmm_reset_entry)
     //set up ipsr, iip, vpd.vpsr, dcr
     // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1
     // For DCR: all bits 0
+    bsw.0
+    ;;
+    mov r21 =r13
     adds r14=-VMM_PT_REGS_SIZE, r12
     ;;
     movl r6=0x501008826000      // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1
@@ -1387,12 +1369,6 @@ GLOBAL_ENTRY(vmm_reset_entry)
     ;;
     srlz.i
     ;;
-    bsw.0
-    ;;
-    mov r21 =r13
-    ;;
-    bsw.1
-    ;;
     mov ar.rsc = 0
     ;;
     flushrs
@@ -1406,12 +1382,9 @@ GLOBAL_ENTRY(vmm_reset_entry)
     ld8 r1 = [r20]
     ;;
     mov cr.iip=r4
-    ;;
     adds r16=VMM_VPD_BASE_OFFSET,r13
-    adds r20=VMM_VCPU_VSA_BASE_OFFSET,r13
     ;;
     ld8 r18=[r16]
-    ld8 r20=[r20]
     ;;
     adds r19=VMM_VPD_VPSR_OFFSET,r18
     ;;
index def4576d22b1b9d3524319d5c7dffe0fa43c24ba..e22b93361e082528812b2d56c1e2bd628f21f584 100644 (file)
@@ -390,7 +390,7 @@ void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps)
 
 u64 translate_phy_pte(u64 *pte, u64 itir, u64 va)
 {
-       u64 ps, ps_mask, paddr, maddr;
+       u64 ps, ps_mask, paddr, maddr, io_mask;
        union pte_flags phy_pte;
 
        ps = itir_ps(itir);
@@ -398,8 +398,9 @@ u64 translate_phy_pte(u64 *pte, u64 itir, u64 va)
        phy_pte.val = *pte;
        paddr = *pte;
        paddr = ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask);
-       maddr = kvm_lookup_mpa(paddr >> PAGE_SHIFT);
-       if (maddr & GPFN_IO_MASK) {
+       maddr = kvm_get_mpt_entry(paddr >> PAGE_SHIFT);
+       io_mask = maddr & GPFN_IO_MASK;
+       if (io_mask && (io_mask != GPFN_PHYS_MMIO)) {
                *pte |= VTLB_PTE_IO;
                return -1;
        }
@@ -418,7 +419,7 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir,
                                                u64 ifa, int type)
 {
        u64 ps;
-       u64 phy_pte;
+       u64 phy_pte, io_mask, index;
        union ia64_rr vrr, mrr;
        int ret = 0;
 
@@ -426,13 +427,16 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir,
        vrr.val = vcpu_get_rr(v, ifa);
        mrr.val = ia64_get_rr(ifa);
 
+       index = (pte & _PAGE_PPN_MASK) >> PAGE_SHIFT;
+       io_mask = kvm_get_mpt_entry(index) & GPFN_IO_MASK;
        phy_pte = translate_phy_pte(&pte, itir, ifa);
 
        /* Ensure WB attribute if pte is related to a normal mem page,
         * which is required by vga acceleration since qemu maps shared
         * vram buffer with WB.
         */
-       if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT)) {
+       if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT) &&
+                       io_mask != GPFN_PHYS_MMIO) {
                pte &= ~_PAGE_MA_MASK;
                phy_pte &= ~_PAGE_MA_MASK;
        }
@@ -566,12 +570,19 @@ void thash_init(struct thash_cb *hcb, u64 sz)
        }
 }
 
-u64 kvm_lookup_mpa(u64 gpfn)
+u64 kvm_get_mpt_entry(u64 gpfn)
 {
        u64 *base = (u64 *) KVM_P2M_BASE;
        return *(base + gpfn);
 }
 
+u64 kvm_lookup_mpa(u64 gpfn)
+{
+       u64 maddr;
+       maddr = kvm_get_mpt_entry(gpfn);
+       return maddr&_PAGE_PPN_MASK;
+}
+
 u64 kvm_gpa_to_mpa(u64 gpa)
 {
        u64 pte = kvm_lookup_mpa(gpa >> PAGE_SHIFT);
index 200100ea7610883ae8fc90768a64ba185aa68d3c..f482a9098e32aadec0fc194befc4906a6be7f6b2 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/bitops.h>
 #include <linux/kexec.h>
 
-#include <asm/a.out.h>
 #include <asm/dma.h>
 #include <asm/ia32.h>
 #include <asm/io.h>
index f57113f1f892b091e7439ee18448459b6df25678..00289c178f895a6ad62a7fb34603af08d52bc961 100644 (file)
@@ -36,9 +36,6 @@ config NO_IOPORT
 config NO_DMA
        def_bool y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 config HZ
        int
        default 100
index 5be4faaf5b1c49c03391bb298e6f83122d6d88ab..7103d91e1a2f92ee3db9a4d060336ee29c08d347 100644 (file)
@@ -11,7 +11,7 @@
 #undef DEBUG_PROCESS
 #ifdef DEBUG_PROCESS
 #define DPRINTK(fmt, args...)  printk("%s:%d:%s: " fmt, __FILE__, __LINE__, \
-  __FUNCTION__, ##args)
+  __func__, ##args)
 #else
 #define DPRINTK(fmt, args...)
 #endif
index cbc3c4c54566bbfb3f7fb418968e5798798ec740..7daf897292cf65c2ec12832265f26035cda399af 100644 (file)
@@ -111,9 +111,9 @@ unsigned long __init setup_memory(void)
                                initrd_start, INITRD_SIZE);
                } else {
                        printk("initrd extends beyond end of memory "
-                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                               "(0x%08lx > 0x%08llx)\ndisabling initrd\n",
                                INITRD_START + INITRD_SIZE,
-                               PFN_PHYS(max_low_pfn));
+                               (unsigned long long)PFN_PHYS(max_low_pfn));
 
                        initrd_start = 0;
                }
index 8c5e1de68fcb6737bbfb1995b21736ac379fa7cc..677c93a490f6f49501e4c7d2e375fd42bb4dabc5 100644 (file)
@@ -5,6 +5,7 @@
 config M68K
        bool
        default y
+       select HAVE_AOUT
        select HAVE_IDE
 
 config MMU
@@ -53,9 +54,6 @@ config NO_IOPORT
 config NO_DMA
        def_bool SUN3
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 config HZ
        int
        default 100
@@ -107,21 +105,9 @@ config PCMCIA
          To compile this driver as modules, choose M here: the
          modules will be called pcmcia_core and ds.
 
-config SUN3
-       bool "Sun3 support"
-       select M68020
-       select MMU_SUN3 if MMU
-       help
-         This option enables support for the Sun 3 series of workstations
-         (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
-         that all other hardware types must be disabled, as Sun 3 kernels
-         are incompatible with all other m68k targets (including Sun 3x!).
-
-         If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
 config AMIGA
        bool "Amiga support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          This option enables support for the Amiga series of computers. If
          you plan to use this kernel on an Amiga, say Y here and browse the
@@ -129,33 +115,16 @@ config AMIGA
 
 config ATARI
        bool "Atari support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          This option enables support for the 68000-based Atari series of
          computers (including the TT, Falcon and Medusa). If you plan to use
          this kernel on an Atari, say Y here and browse the material
          available in <file:Documentation/m68k>; otherwise say N.
 
-config HADES
-       bool "Hades support"
-       depends on ATARI && BROKEN
-       help
-         This option enables support for the Hades Atari clone. If you plan
-         to use this kernel on a Hades, say Y here; otherwise say N.
-
-config PCI
-       bool
-       depends on HADES
-       default y
-       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.
-
 config MAC
        bool "Macintosh support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          This option enables support for the Apple Macintosh series of
          computers (yes, there is experimental support now, at least for part
@@ -176,14 +145,14 @@ config M68K_L2_CACHE
 
 config APOLLO
        bool "Apollo support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          Say Y here if you want to run Linux on an MC680x0-based Apollo
          Domain workstation such as the DN3500.
 
 config VME
        bool "VME (Motorola and BVM) support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          Say Y here if you want to build a kernel for a 680x0 based VME
          board.  Boards currently supported include Motorola boards MVME147,
@@ -220,7 +189,7 @@ config BVME6000
 
 config HP300
        bool "HP9000/300 and HP9000/400 support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          This option enables support for the HP9000/300 and HP9000/400 series
          of workstations. Support for these machines is still somewhat
@@ -239,7 +208,7 @@ config DIO
 
 config SUN3X
        bool "Sun3x support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        select M68030
        help
          This option enables support for the Sun 3x series of workstations.
@@ -252,7 +221,7 @@ config SUN3X
 
 config Q40
        bool "Q40/Q60 support"
-       depends on !MMU_SUN3
+       select MMU_MOTOROLA if MMU
        help
          The Q40 is a Motorola 68040-based successor to the Sinclair QL
          manufactured in Germany.  There is an official Q40 home page at
@@ -260,6 +229,19 @@ config Q40
          Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
          emulation.
 
+config SUN3
+       bool "Sun3 support"
+       depends on !MMU_MOTOROLA
+       select MMU_SUN3 if MMU
+       select M68020
+       help
+         This option enables support for the Sun 3 series of workstations
+         (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
+         that all other hardware types must be disabled, as Sun 3 kernels
+         are incompatible with all other m68k targets (including Sun 3x!).
+
+         If you don't want to compile a kernel exclusively for a Sun 3, say N.
+
 comment "Processor type"
 
 config M68020
@@ -297,10 +279,10 @@ config M68060
 config MMU_MOTOROLA
        bool
        depends on MMU && !MMU_SUN3
-       default y
 
 config MMU_SUN3
        bool
+       depends on MMU && !MMU_MOTOROLA
 
 config M68KFPU_EMU
        bool "Math emulation support (EXPERIMENTAL)"
index df679d96b1cb790de2b64478cd46306d407f9451..0a3f9e8ebde0db468365abf2a429a11a04c1e934 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/zorro.h>
 #include <linux/module.h>
+#include <linux/keyboard.h>
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -984,3 +985,11 @@ static int amiga_get_hardware_list(char *buffer)
 
        return len;
 }
+
+/*
+ * The Amiga keyboard driver needs key_maps, but we cannot export it in
+ * drivers/char/defkeymap.c, as it is autogenerated
+ */
+#ifdef CONFIG_HW_CONSOLE
+EXPORT_SYMBOL_GPL(key_maps);
+#endif
index 2cd905efe63abb15572d653fd6ee71b485c952b3..0cac723306f936befae82e5e21dc673a36507c5f 100644 (file)
@@ -5,7 +5,4 @@
 obj-y          := config.o time.o debug.o ataints.o stdma.o \
                        atasound.o stram.o
 
-ifeq ($(CONFIG_PCI),y)
-obj-$(CONFIG_HADES)    += hades-pci.o
-endif
 obj-$(CONFIG_ATARI_KBD_CORE)   += atakeyb.o
index b45593a60bddf67bfdb57e611ded063f3b386993..dba4afabb444a41bb7c294475825726e607f1881 100644 (file)
@@ -407,10 +407,8 @@ void __init atari_init_IRQ(void)
                 * gets overruns)
                 */
 
-               if (!MACH_IS_HADES) {
-                       vectors[VEC_INT2] = falcon_hblhandler;
-                       vectors[VEC_INT4] = falcon_hblhandler;
-               }
+               vectors[VEC_INT2] = falcon_hblhandler;
+               vectors[VEC_INT4] = falcon_hblhandler;
        }
 
        if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
index bb959fbab2dc2b74805052b409142ffd2c43b965..c038b7c7eff0e8ea20f009b83eb4b1658040a229 100644 (file)
@@ -635,15 +635,3 @@ int atari_keyb_init(void)
        return 0;
 }
 EXPORT_SYMBOL_GPL(atari_keyb_init);
-
-int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
-{
-#ifdef CONFIG_MAGIC_SYSRQ
-       /* ALT+HELP pressed? */
-       if ((keycode == 98) && ((shift_state & 0xff) == 8))
-               *keycodep = 0xff;
-       else
-#endif
-               *keycodep = keycode;
-       return 1;
-}
index 5945e15055582821ee0b1adcab4d640c8d3b1b56..af031855f796f4b61bd716f092d5065c97d1bc12 100644 (file)
@@ -231,7 +231,7 @@ void __init config_atari(void)
         */
 
        printk("Atari hardware found: ");
-       if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+       if (MACH_IS_MEDUSA) {
                /* There's no Atari video hardware on the Medusa, but all the
                 * addresses below generate a DTACK so no bus error occurs! */
        } else if (hwreg_present(f030_xreg)) {
@@ -269,10 +269,6 @@ void __init config_atari(void)
                ATARIHW_SET(SCSI_DMA);
                printk("TT_SCSI_DMA ");
        }
-       if (!MACH_IS_HADES && hwreg_present(&st_dma.dma_hi)) {
-               ATARIHW_SET(STND_DMA);
-               printk("STND_DMA ");
-       }
        /*
         * The ST-DMA address registers aren't readable
         * on all Medusas, so the test below may fail
@@ -294,12 +290,11 @@ void __init config_atari(void)
                ATARIHW_SET(YM_2149);
                printk("YM2149 ");
        }
-       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-               hwreg_present(&tt_dmasnd.ctrl)) {
+       if (!MACH_IS_MEDUSA && hwreg_present(&tt_dmasnd.ctrl)) {
                ATARIHW_SET(PCM_8BIT);
                printk("PCM ");
        }
-       if (!MACH_IS_HADES && hwreg_present(&falcon_codec.unused5)) {
+       if (hwreg_present(&falcon_codec.unused5)) {
                ATARIHW_SET(CODEC);
                printk("CODEC ");
        }
@@ -313,7 +308,7 @@ void __init config_atari(void)
            (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
            (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
 #else
-           !MACH_IS_MEDUSA && !MACH_IS_HADES
+           !MACH_IS_MEDUSA
 #endif
            ) {
                ATARIHW_SET(SCC_DMA);
@@ -327,10 +322,7 @@ void __init config_atari(void)
                ATARIHW_SET(ST_ESCC);
                printk("ST_ESCC ");
        }
-       if (MACH_IS_HADES) {
-               ATARIHW_SET(VME);
-               printk("VME ");
-       } else if (hwreg_present(&tt_scu.sys_mask)) {
+       if (hwreg_present(&tt_scu.sys_mask)) {
                ATARIHW_SET(SCU);
                /* Assume a VME bus if there's a SCU */
                ATARIHW_SET(VME);
@@ -340,7 +332,7 @@ void __init config_atari(void)
                ATARIHW_SET(ANALOG_JOY);
                printk("ANALOG_JOY ");
        }
-       if (!MACH_IS_HADES && hwreg_present(blitter.halftone)) {
+       if (hwreg_present(blitter.halftone)) {
                ATARIHW_SET(BLITTER);
                printk("BLITTER ");
        }
@@ -349,8 +341,7 @@ void __init config_atari(void)
                printk("IDE ");
        }
 #if 1 /* This maybe wrong */
-       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-           hwreg_present(&tt_microwire.data) &&
+       if (!MACH_IS_MEDUSA && hwreg_present(&tt_microwire.data) &&
            hwreg_present(&tt_microwire.mask) &&
            (tt_microwire.mask = 0x7ff,
             udelay(1),
@@ -369,19 +360,18 @@ void __init config_atari(void)
                mach_hwclk = atari_tt_hwclk;
                mach_set_clock_mmss = atari_tt_set_clock_mmss;
        }
-       if (!MACH_IS_HADES && hwreg_present(&mste_rtc.sec_ones)) {
+       if (hwreg_present(&mste_rtc.sec_ones)) {
                ATARIHW_SET(MSTE_CLK);
                printk("MSTE_CLK ");
                mach_hwclk = atari_mste_hwclk;
                mach_set_clock_mmss = atari_mste_set_clock_mmss;
        }
-       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-           hwreg_present(&dma_wd.fdc_speed) &&
+       if (!MACH_IS_MEDUSA && hwreg_present(&dma_wd.fdc_speed) &&
            hwreg_write(&dma_wd.fdc_speed, 0)) {
                ATARIHW_SET(FDCSPEED);
                printk("FDC_SPEED ");
        }
-       if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
+       if (!ATARIHW_PRESENT(ST_SCSI)) {
                ATARIHW_SET(ACSI);
                printk("ACSI ");
        }
@@ -449,7 +439,7 @@ void __init config_atari(void)
         * 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
         * in the last 16MB of the address space.
         */
-       tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
+       tos_version = (MACH_IS_MEDUSA) ?
                        0xfff : *(unsigned short *)0xff000002;
        atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
 }
@@ -511,8 +501,7 @@ static void atari_reset(void)
         * On the Medusa, phys. 0x4 may contain garbage because it's no
         * ROM.  See above for explanation why we cannot use PTOV(4).
         */
-       reset_addr = MACH_IS_HADES ? 0x7fe00030 :
-                    MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
+       reset_addr = MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
                     *(unsigned long *) 0xff000004;
 
        /* reset ACIA for switch off OverScan, if it's active */
@@ -606,8 +595,6 @@ static void atari_get_model(char *model)
                if (MACH_IS_MEDUSA)
                        /* Medusa has TT _MCH cookie */
                        strcat(model, "Medusa");
-               else if (MACH_IS_HADES)
-                       strcat(model, "Hades");
                else
                        strcat(model, "TT");
                break;
diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
deleted file mode 100644 (file)
index 2bbabc0..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone.
- *
- * Written by Wout Klaren.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-
-#if 0
-# define DBG_DEVS(args)                printk args
-#else
-# define DBG_DEVS(args)
-#endif
-
-#if defined(CONFIG_PCI) && defined(CONFIG_HADES)
-
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/byteorder.h>
-#include <asm/pci.h>
-
-#define HADES_MEM_BASE         0x80000000
-#define HADES_MEM_SIZE         0x20000000
-#define HADES_CONFIG_BASE      0xA0000000
-#define HADES_CONFIG_SIZE      0x10000000
-#define HADES_IO_BASE          0xB0000000
-#define HADES_IO_SIZE          0x10000000
-#define HADES_VIRT_IO_SIZE     0x00010000      /* Only 64k is remapped and actually used. */
-
-#define N_SLOTS                                4                       /* Number of PCI slots. */
-
-static const char pci_mem_name[] = "PCI memory space";
-static const char pci_io_name[] = "PCI I/O space";
-static const char pci_config_name[] = "PCI config space";
-
-static struct resource config_space = {
-    .name = pci_config_name,
-    .start = HADES_CONFIG_BASE,
-    .end = HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1
-};
-static struct resource io_space = {
-    .name = pci_io_name,
-    .start = HADES_IO_BASE,
-    .end = HADES_IO_BASE + HADES_IO_SIZE - 1
-};
-
-static const unsigned long pci_conf_base_phys[] = {
-    0xA0080000, 0xA0040000, 0xA0020000, 0xA0010000
-};
-static unsigned long pci_conf_base_virt[N_SLOTS];
-static unsigned long pci_io_base_virt;
-
-/*
- * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
- *                          unsigned char where)
- *
- * Calculate the address of the PCI configuration area of the given
- * device.
- *
- * BUG: boards with multiple functions are probably not correctly
- * supported.
- */
-
-static void *mk_conf_addr(struct pci_dev *dev, int where)
-{
-       int device = dev->devfn >> 3, function = dev->devfn & 7;
-       void *result;
-
-       DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
-                 dev->bus->number, dev->devfn, where, pci_addr));
-
-       if (device > 3)
-       {
-               DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULL\n", device));
-               return NULL;
-       }
-
-       if (dev->bus->number != 0)
-       {
-               DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULL\n", device));
-               return NULL;
-       }
-
-       result = (void *) (pci_conf_base_virt[device] | (function << 8) | (where));
-       DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", (unsigned long) result));
-       return result;
-}
-
-static int hades_read_config_byte(struct pci_dev *dev, int where, u8 *value)
-{
-       volatile unsigned char *pci_addr;
-
-       *value = 0xff;
-
-       if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       *value = *pci_addr;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
-       volatile unsigned short *pci_addr;
-
-       *value = 0xffff;
-
-       if (where & 0x1)
-               return PCIBIOS_BAD_REGISTER_NUMBER;
-
-       if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       *value = le16_to_cpu(*pci_addr);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
-       volatile unsigned int *pci_addr;
-       unsigned char header_type;
-       int result;
-
-       *value = 0xffffffff;
-
-       if (where & 0x3)
-               return PCIBIOS_BAD_REGISTER_NUMBER;
-
-       if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       *value = le32_to_cpu(*pci_addr);
-
-       /*
-        * Check if the value is an address on the bus. If true, add the
-        * base address of the PCI memory or PCI I/O area on the Hades.
-        */
-
-       if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
-                                            &header_type)) != PCIBIOS_SUCCESSFUL)
-               return result;
-
-       if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
-           ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
-                                                        (where <= PCI_BASE_ADDRESS_5))))
-       {
-               if ((*value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-               {
-                       /*
-                        * Base address register that contains an I/O address. If the
-                        * address is valid on the Hades (0 <= *value < HADES_VIRT_IO_SIZE),
-                        * add 'pci_io_base_virt' to the value.
-                        */
-
-                       if (*value < HADES_VIRT_IO_SIZE)
-                               *value += pci_io_base_virt;
-               }
-               else
-               {
-                       /*
-                        * Base address register that contains an memory address. If the
-                        * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE),
-                        * add HADES_MEM_BASE to the value.
-                        */
-
-                       if (*value == 0)
-                       {
-                               /*
-                                * Base address is 0. Test if this base
-                                * address register is used.
-                                */
-
-                               *pci_addr = 0xffffffff;
-                               if (*pci_addr != 0)
-                               {
-                                       *pci_addr = *value;
-                                       if (*value < HADES_MEM_SIZE)
-                                               *value += HADES_MEM_BASE;
-                               }
-                       }
-                       else
-                       {
-                               if (*value < HADES_MEM_SIZE)
-                                       *value += HADES_MEM_BASE;
-                       }
-               }
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
-       volatile unsigned char *pci_addr;
-
-       if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       *pci_addr = value;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
-       volatile unsigned short *pci_addr;
-
-       if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       *pci_addr = cpu_to_le16(value);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int hades_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-       volatile unsigned int *pci_addr;
-       unsigned char header_type;
-       int result;
-
-       if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /*
-        * Check if the value is an address on the bus. If true, subtract the
-        * base address of the PCI memory or PCI I/O area on the Hades.
-        */
-
-       if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
-                                            &header_type)) != PCIBIOS_SUCCESSFUL)
-               return result;
-
-       if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
-           ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
-                                                        (where <= PCI_BASE_ADDRESS_5))))
-       {
-               if ((value & PCI_BASE_ADDRESS_SPACE) ==
-                   PCI_BASE_ADDRESS_SPACE_IO)
-               {
-                       /*
-                        * I/O address. Check if the address is valid address on
-                        * the Hades (pci_io_base_virt <= value < pci_io_base_virt +
-                        * HADES_VIRT_IO_SIZE) or if the value is 0xffffffff. If not
-                        * true do not write the base address register. If it is a
-                        * valid base address subtract 'pci_io_base_virt' from the value.
-                        */
-
-                       if ((value >= pci_io_base_virt) && (value < (pci_io_base_virt +
-                                                                                                                HADES_VIRT_IO_SIZE)))
-                               value -= pci_io_base_virt;
-                       else
-                       {
-                               if (value != 0xffffffff)
-                                       return PCIBIOS_SET_FAILED;
-                       }
-               }
-               else
-               {
-                       /*
-                        * Memory address. Check if the address is valid address on
-                        * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or
-                        * if the value is 0xffffffff. If not true do not write
-                        * the base address register. If it is a valid base address
-                        * subtract HADES_MEM_BASE from the value.
-                        */
-
-                       if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE)))
-                               value -= HADES_MEM_BASE;
-                       else
-                       {
-                               if (value != 0xffffffff)
-                                       return PCIBIOS_SET_FAILED;
-                       }
-               }
-       }
-
-       *pci_addr = cpu_to_le32(value);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-/*
- * static inline void hades_fixup(void)
- *
- * Assign IRQ numbers as used by Linux to the interrupt pins
- * of the PCI cards.
- */
-
-static void __init hades_fixup(int pci_modify)
-{
-       char irq_tab[4] = {
-               [0] = IRQ_TT_MFP_IO0,           /* Slot 0. */
-               [1] = IRQ_TT_MFP_IO1,           /* Slot 1. */
-               [2] = IRQ_TT_MFP_SCC,           /* Slot 2. */
-               [3] = IRQ_TT_MFP_SCSIDMA        /* Slot 3. */
-       };
-       struct pci_dev *dev = NULL;
-       unsigned char slot;
-
-       /*
-        * Go through all devices, fixing up irqs as we see fit:
-        */
-
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
-       {
-               if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
-               {
-                       slot = PCI_SLOT(dev->devfn);    /* Determine slot number. */
-                       dev->irq = irq_tab[slot];
-                       if (pci_modify)
-                               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-               }
-       }
-}
-
-/*
- * static void hades_conf_device(struct pci_dev *dev)
- *
- * Machine dependent Configure the given device.
- *
- * Parameters:
- *
- * dev         - the pci device.
- */
-
-static void __init hades_conf_device(struct pci_dev *dev)
-{
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0);
-}
-
-static struct pci_ops hades_pci_ops = {
-       .read_byte =    hades_read_config_byte,
-       .read_word =    hades_read_config_word,
-       .read_dword =   hades_read_config_dword,
-       .write_byte =   hades_write_config_byte,
-       .write_word =   hades_write_config_word,
-       .write_dword =  hades_write_config_dword
-};
-
-/*
- * struct pci_bus_info *init_hades_pci(void)
- *
- * Machine specific initialisation:
- *
- * - Allocate and initialise a 'pci_bus_info' structure
- * - Initialise hardware
- *
- * Result: pointer to 'pci_bus_info' structure.
- */
-
-struct pci_bus_info * __init init_hades_pci(void)
-{
-       struct pci_bus_info *bus;
-       int i;
-
-       /*
-        * Remap I/O and configuration space.
-        */
-
-       pci_io_base_virt = (unsigned long) ioremap(HADES_IO_BASE, HADES_VIRT_IO_SIZE);
-
-       for (i = 0; i < N_SLOTS; i++)
-               pci_conf_base_virt[i] = (unsigned long) ioremap(pci_conf_base_phys[i], 0x10000);
-
-       /*
-        * Allocate memory for bus info structure.
-        */
-
-       bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
-       if (unlikely(!bus))
-               goto iounmap_base_virt;
-
-       /*
-        * Claim resources. The m68k has no separate I/O space, both
-        * PCI memory space and PCI I/O space are in memory space. Therefore
-        * the I/O resources are requested in memory space as well.
-        */
-
-       if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
-               goto free_bus;
-
-       if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
-               goto release_config_space;
-
-       bus->mem_space.start = HADES_MEM_BASE;
-       bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
-       bus->mem_space.name = pci_mem_name;
-#if 1
-       if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
-               goto release_io_space;
-#endif
-       bus->io_space.start = pci_io_base_virt;
-       bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
-       bus->io_space.name = pci_io_name;
-#if 1
-       if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
-               goto release_bus_mem_space;
-#endif
-       /*
-        * Set hardware dependent functions.
-        */
-
-       bus->m68k_pci_ops = &hades_pci_ops;
-       bus->fixup = hades_fixup;
-       bus->conf_device = hades_conf_device;
-
-       /*
-        * Select high to low edge for PCI interrupts.
-        */
-
-       tt_mfp.active_edge &= ~0x27;
-
-       return bus;
-
-release_bus_mem_space:
-       release_resource(&bus->mem_space);
-release_io_space:
-       release_resource(&io_space);
-release_config_space:
-       release_resource(&config_space);
-free_bus:
-       kfree(bus);
-iounmap_base_virt:
-       iounmap((void *)pci_io_base_virt);
-
-       for (i = 0; i < N_SLOTS; i++)
-               iounmap((void *)pci_conf_base_virt[i]);
-
-       return NULL;
-}
-#endif
index e0d3c8bfb40864791b6c333e3926be8212ba7bc5..1edde27fa32dbb600dd5d07822cfd0bb5281b992 100644 (file)
@@ -20,6 +20,9 @@
 
 #include <asm/atariints.h>
 
+DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL_GPL(rtc_lock);
+
 void __init
 atari_sched_init(irq_handler_t timer_routine)
 {
@@ -191,13 +194,14 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
         }
 
         if (!(ctrl & RTC_DM_BINARY)) {
-            BIN_TO_BCD(sec);
-            BIN_TO_BCD(min);
-            BIN_TO_BCD(hour);
-            BIN_TO_BCD(day);
-            BIN_TO_BCD(mon);
-            BIN_TO_BCD(year);
-            if (wday >= 0) BIN_TO_BCD(wday);
+           sec = bin2bcd(sec);
+           min = bin2bcd(min);
+           hour = bin2bcd(hour);
+           day = bin2bcd(day);
+           mon = bin2bcd(mon);
+           year = bin2bcd(year);
+           if (wday >= 0)
+               wday = bin2bcd(wday);
         }
     }
 
@@ -252,13 +256,13 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
        }
 
        if (!(ctrl & RTC_DM_BINARY)) {
-            BCD_TO_BIN(sec);
-            BCD_TO_BIN(min);
-            BCD_TO_BIN(hour);
-            BCD_TO_BIN(day);
-            BCD_TO_BIN(mon);
-            BCD_TO_BIN(year);
-            BCD_TO_BIN(wday);
+           sec = bcd2bin(sec);
+           min = bcd2bin(min);
+           hour = bcd2bin(hour);
+           day = bcd2bin(day);
+           mon = bcd2bin(mon);
+           year = bcd2bin(year);
+           wday = bcd2bin(wday);
         }
 
         if (!(ctrl & RTC_24H)) {
@@ -318,7 +322,7 @@ int atari_tt_set_clock_mmss (unsigned long nowtime)
 
     rtc_minutes = RTC_READ (RTC_MINUTES);
     if (!(save_control & RTC_DM_BINARY))
-        BCD_TO_BIN (rtc_minutes);
+       rtc_minutes = bcd2bin(rtc_minutes);
 
     /* Since we're only adjusting minutes and seconds, don't interfere
        with hour overflow.  This avoids messing with unknown time zones
@@ -329,8 +333,8 @@ int atari_tt_set_clock_mmss (unsigned long nowtime)
         {
             if (!(save_control & RTC_DM_BINARY))
                 {
-                    BIN_TO_BCD (real_seconds);
-                    BIN_TO_BCD (real_minutes);
+                   real_seconds = bin2bcd(real_seconds);
+                   real_minutes = bin2bcd(real_minutes);
                 }
             RTC_WRITE (RTC_SECONDS, real_seconds);
             RTC_WRITE (RTC_MINUTES, real_minutes);
index 9433a88a33c4093866e6ea603182f0975e6b0e54..65c9204ab9ac626aaec3066967bdce9b1792ea60 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/genhd.h>
 #include <linux/rtc.h>
 #include <linux/interrupt.h>
+#include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
@@ -46,9 +47,6 @@ extern void bvme6000_reset (void);
 extern void bvme6000_waitbut(void);
 void bvme6000_set_vectors (void);
 
-static unsigned char bcd2bin (unsigned char b);
-static unsigned char bin2bcd (unsigned char b);
-
 /* Save tick handler routine pointer, will point to do_timer() in
  * kernel/sched.c, called via bvme6000_process_int() */
 
@@ -264,17 +262,6 @@ unsigned long bvme6000_gettimeoffset (void)
     return v;
 }
 
-static unsigned char bcd2bin (unsigned char b)
-{
-       return ((b>>4)*10 + (b&15));
-}
-
-static unsigned char bin2bcd (unsigned char b)
-{
-       return (((b/10)*16) + (b%10));
-}
-
-
 /*
  * Looks like op is non-zero for setting the clock, and zero for
  * reading the clock.
index e8ac3f7d72df6dd457aded95444e69655d16f7c1..808c9018b115022dd2ba8dee88a070fc003448ce 100644 (file)
@@ -57,16 +57,16 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                rtc->msr = 0x40;
                memset(&wtime, 0, sizeof(struct rtc_time));
                do {
-                       wtime.tm_sec =  BCD2BIN(rtc->bcd_sec);
-                       wtime.tm_min =  BCD2BIN(rtc->bcd_min);
-                       wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
-                       wtime.tm_mday =  BCD2BIN(rtc->bcd_dom);
-                       wtime.tm_mon =  BCD2BIN(rtc->bcd_mth)-1;
-                       wtime.tm_year = BCD2BIN(rtc->bcd_year);
+                       wtime.tm_sec =  bcd2bin(rtc->bcd_sec);
+                       wtime.tm_min =  bcd2bin(rtc->bcd_min);
+                       wtime.tm_hour = bcd2bin(rtc->bcd_hr);
+                       wtime.tm_mday =  bcd2bin(rtc->bcd_dom);
+                       wtime.tm_mon =  bcd2bin(rtc->bcd_mth)-1;
+                       wtime.tm_year = bcd2bin(rtc->bcd_year);
                        if (wtime.tm_year < 70)
                                wtime.tm_year += 100;
-                       wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
-               } while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec));
+                       wtime.tm_wday = bcd2bin(rtc->bcd_dow)-1;
+               } while (wtime.tm_sec != bcd2bin(rtc->bcd_sec));
                rtc->msr = msr;
                local_irq_restore(flags);
                return copy_to_user(argp, &wtime, sizeof wtime) ?
@@ -114,14 +114,14 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                rtc->t0cr_rtmr = yrs%4;
                rtc->bcd_tenms = 0;
-               rtc->bcd_sec   = BIN2BCD(sec);
-               rtc->bcd_min   = BIN2BCD(min);
-               rtc->bcd_hr    = BIN2BCD(hrs);
-               rtc->bcd_dom   = BIN2BCD(day);
-               rtc->bcd_mth   = BIN2BCD(mon);
-               rtc->bcd_year  = BIN2BCD(yrs%100);
+               rtc->bcd_sec   = bin2bcd(sec);
+               rtc->bcd_min   = bin2bcd(min);
+               rtc->bcd_hr    = bin2bcd(hrs);
+               rtc->bcd_dom   = bin2bcd(day);
+               rtc->bcd_mth   = bin2bcd(mon);
+               rtc->bcd_year  = bin2bcd(yrs%100);
                if (rtc_tm.tm_wday >= 0)
-                       rtc->bcd_dow = BIN2BCD(rtc_tm.tm_wday+1);
+                       rtc->bcd_dow = bin2bcd(rtc_tm.tm_wday+1);
                rtc->t0cr_rtmr = yrs%4 | 0x08;
 
                rtc->msr = msr;
index 3a7f622255045e958a1d4f733978b06eb89f1950..55d5d6b680a211376390499ee2aee7d2e5d41b61 100644 (file)
@@ -14,5 +14,4 @@ obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
 
 devres-y = ../../../kernel/irq/devres.o
 
-obj-$(CONFIG_PCI)      += bios32.o
 obj-y$(CONFIG_MMU_SUN3) += dma.o       # no, it's not a typo
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
deleted file mode 100644 (file)
index af170c2..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * bios32.c - PCI BIOS functions for m68k systems.
- *
- * Written by Wout Klaren.
- *
- * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#if 0
-# define DBG_DEVS(args)                printk args
-#else
-# define DBG_DEVS(args)
-#endif
-
-#ifdef CONFIG_PCI
-
-/*
- * PCI support for Linux/m68k. Currently only the Hades is supported.
- *
- * The support for PCI bridges in the DEC Alpha version has
- * been removed in this version.
- */
-
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/pci.h>
-#include <asm/uaccess.h>
-
-#define KB             1024
-#define MB             (1024*KB)
-#define GB             (1024*MB)
-
-#define MAJOR_REV      0
-#define MINOR_REV      5
-
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-
-#define ALIGN(val,align)       (((val) + ((align) - 1)) & ~((align) - 1))
-
-/*
- * Offsets relative to the I/O and memory base addresses from where resources
- * are allocated.
- */
-
-#define IO_ALLOC_OFFSET                0x00004000
-#define MEM_ALLOC_OFFSET       0x04000000
-
-/*
- * Declarations of hardware specific initialisation functions.
- */
-
-extern struct pci_bus_info *init_hades_pci(void);
-
-/*
- * Bus info structure of the PCI bus. A pointer to this structure is
- * put in the sysdata member of the pci_bus structure.
- */
-
-static struct pci_bus_info *bus_info;
-
-static int pci_modify = 1;             /* If set, layout the PCI bus ourself. */
-static int skip_vga;                   /* If set do not modify base addresses
-                                          of vga cards.*/
-static int disable_pci_burst;          /* If set do not allow PCI bursts. */
-
-static unsigned int io_base;
-static unsigned int mem_base;
-
-/*
- * static void disable_dev(struct pci_dev *dev)
- *
- * Disable PCI device DEV so that it does not respond to I/O or memory
- * accesses.
- *
- * Parameters:
- *
- * dev - device to disable.
- */
-
-static void __init disable_dev(struct pci_dev *dev)
-{
-       unsigned short cmd;
-
-       if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
-            (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
-            (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
-               return;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
-       cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
-       pci_write_config_word(dev, PCI_COMMAND, cmd);
-}
-
-/*
- * static void layout_dev(struct pci_dev *dev)
- *
- * Layout memory and I/O for a device.
- *
- * Parameters:
- *
- * device      - device to layout memory and I/O for.
- */
-
-static void __init layout_dev(struct pci_dev *dev)
-{
-       unsigned short cmd;
-       unsigned int base, mask, size, reg;
-       unsigned int alignto;
-       int i;
-
-       /*
-        * Skip video cards if requested.
-        */
-
-       if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
-            (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
-            (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
-               return;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
-       for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++)
-       {
-               /*
-                * Figure out how much space and of what type this
-                * device wants.
-                */
-
-               pci_write_config_dword(dev, reg, 0xffffffff);
-               pci_read_config_dword(dev, reg, &base);
-
-               if (!base)
-               {
-                       /* this base-address register is unused */
-                       dev->resource[i].start = 0;
-                       dev->resource[i].end = 0;
-                       dev->resource[i].flags = 0;
-                       continue;
-               }
-
-               /*
-                * We've read the base address register back after
-                * writing all ones and so now we must decode it.
-                */
-
-               if (base & PCI_BASE_ADDRESS_SPACE_IO)
-               {
-                       /*
-                        * I/O space base address register.
-                        */
-
-                       cmd |= PCI_COMMAND_IO;
-
-                       base &= PCI_BASE_ADDRESS_IO_MASK;
-                       mask = (~base << 1) | 0x1;
-                       size = (mask & base) & 0xffffffff;
-
-                       /*
-                        * Align to multiple of size of minimum base.
-                        */
-
-                       alignto = max_t(unsigned int, 0x040, size);
-                       base = ALIGN(io_base, alignto);
-                       io_base = base + size;
-                       pci_write_config_dword(dev, reg, base | PCI_BASE_ADDRESS_SPACE_IO);
-
-                       dev->resource[i].start = base;
-                       dev->resource[i].end = dev->resource[i].start + size - 1;
-                       dev->resource[i].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
-
-                       DBG_DEVS(("layout_dev: IO address: %lX\n", base));
-               }
-               else
-               {
-                       unsigned int type;
-
-                       /*
-                        * Memory space base address register.
-                        */
-
-                       cmd |= PCI_COMMAND_MEMORY;
-                       type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
-                       base &= PCI_BASE_ADDRESS_MEM_MASK;
-                       mask = (~base << 1) | 0x1;
-                       size = (mask & base) & 0xffffffff;
-                       switch (type)
-                       {
-                       case PCI_BASE_ADDRESS_MEM_TYPE_32:
-                       case PCI_BASE_ADDRESS_MEM_TYPE_64:
-                               break;
-
-                       case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-                               printk("bios32 WARNING: slot %d, function %d "
-                                      "requests memory below 1MB---don't "
-                                      "know how to do that.\n",
-                                      PCI_SLOT(dev->devfn),
-                                      PCI_FUNC(dev->devfn));
-                               continue;
-                       }
-
-                       /*
-                        * Align to multiple of size of minimum base.
-                        */
-
-                       alignto = max_t(unsigned int, 0x1000, size);
-                       base = ALIGN(mem_base, alignto);
-                       mem_base = base + size;
-                       pci_write_config_dword(dev, reg, base);
-
-                       dev->resource[i].start = base;
-                       dev->resource[i].end = dev->resource[i].start + size - 1;
-                       dev->resource[i].flags = IORESOURCE_MEM;
-
-                       if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
-                       {
-                               /*
-                                * 64-bit address, set the highest 32 bits
-                                * to zero.
-                                */
-
-                               reg += 4;
-                               pci_write_config_dword(dev, reg, 0);
-
-                               i++;
-                               dev->resource[i].start = 0;
-                               dev->resource[i].end = 0;
-                               dev->resource[i].flags = 0;
-                       }
-               }
-       }
-
-       /*
-        * Enable device:
-        */
-
-       if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
-           dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
-           dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
-           dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
-       {
-               /*
-                * All of these (may) have I/O scattered all around
-                * and may not use i/o-base address registers at all.
-                * So we just have to always enable I/O to these
-                * devices.
-                */
-               cmd |= PCI_COMMAND_IO;
-       }
-
-       pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
-
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, (disable_pci_burst) ? 0 : 32);
-
-       if (bus_info != NULL)
-               bus_info->conf_device(dev);     /* Machine dependent configuration. */
-
-       DBG_DEVS(("layout_dev: bus %d  slot 0x%x  VID 0x%x  DID 0x%x  class 0x%x\n",
-                 dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
-}
-
-/*
- * static void layout_bus(struct pci_bus *bus)
- *
- * Layout memory and I/O for all devices on the given bus.
- *
- * Parameters:
- *
- * bus - bus.
- */
-
-static void __init layout_bus(struct pci_bus *bus)
-{
-       unsigned int bio, bmem;
-       struct pci_dev *dev;
-
-       DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
-
-       if (!bus->devices && !bus->children)
-               return;
-
-       /*
-        * Align the current bases on appropriate boundaries (4K for
-        * IO and 1MB for memory).
-        */
-
-       bio = io_base = ALIGN(io_base, 4*KB);
-       bmem = mem_base = ALIGN(mem_base, 1*MB);
-
-       /*
-        * PCI devices might have been setup by a PCI BIOS emulation
-        * running under TOS. In these cases there is a
-        * window during which two devices may have an overlapping
-        * address range. To avoid this causing trouble, we first
-        * turn off the I/O and memory address decoders for all PCI
-        * devices.  They'll be re-enabled only once all address
-        * decoders are programmed consistently.
-        */
-
-       DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
-
-       for (dev = bus->devices; dev; dev = dev->sibling)
-       {
-               if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
-                   (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
-                       disable_dev(dev);
-       }
-
-       /*
-        * Allocate space to each device:
-        */
-
-       DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
-
-       for (dev = bus->devices; dev; dev = dev->sibling)
-       {
-               if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
-                   (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
-                       layout_dev(dev);
-       }
-
-       DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
-}
-
-/*
- * static void pcibios_fixup(void)
- *
- * Layout memory and I/O of all devices on the PCI bus if 'pci_modify' is
- * true. This might be necessary because not every m68k machine with a PCI
- * bus has a PCI BIOS. This function should be called right after
- * pci_scan_bus() in pcibios_init().
- */
-
-static void __init pcibios_fixup(void)
-{
-       if (pci_modify)
-       {
-               /*
-                * Set base addresses for allocation of I/O and memory space.
-                */
-
-               io_base = bus_info->io_space.start + IO_ALLOC_OFFSET;
-               mem_base = bus_info->mem_space.start + MEM_ALLOC_OFFSET;
-
-               /*
-                * Scan the tree, allocating PCI memory and I/O space.
-                */
-
-               layout_bus(pci_bus_b(pci_root.next));
-       }
-
-       /*
-        * Fix interrupt assignments, etc.
-        */
-
-       bus_info->fixup(pci_modify);
-}
-
-/*
- * static void pcibios_claim_resources(struct pci_bus *bus)
- *
- * Claim all resources that are assigned to devices on the given bus.
- *
- * Parameters:
- *
- * bus - bus.
- */
-
-static void __init pcibios_claim_resources(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-       int i;
-
-       while (bus)
-       {
-               for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
-               {
-                       for (i = 0; i < PCI_NUM_RESOURCES; i++)
-                       {
-                               struct resource *r = &dev->resource[i];
-                               struct resource *pr;
-                               struct pci_bus_info *bus_info = (struct pci_bus_info *) dev->sysdata;
-
-                               if ((r->start == 0) || (r->parent != NULL))
-                                       continue;
-#if 1
-                               if (r->flags & IORESOURCE_IO)
-                                       pr = &bus_info->io_space;
-                               else
-                                       pr = &bus_info->mem_space;
-#else
-                               if (r->flags & IORESOURCE_IO)
-                                       pr = &ioport_resource;
-                               else
-                                       pr = &iomem_resource;
-#endif
-                               if (request_resource(pr, r) < 0)
-                               {
-                                       printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", i, dev->name);
-                               }
-                       }
-               }
-
-               if (bus->children)
-                       pcibios_claim_resources(bus->children);
-
-               bus = bus->next;
-       }
-}
-
-/*
- * int pcibios_assign_resource(struct pci_dev *dev, int i)
- *
- * Assign a new address to a PCI resource.
- *
- * Parameters:
- *
- * dev - device.
- * i   - resource.
- *
- * Result: 0 if successful.
- */
-
-int __init pcibios_assign_resource(struct pci_dev *dev, int i)
-{
-       struct resource *r = &dev->resource[i];
-       struct resource *pr = pci_find_parent_resource(dev, r);
-       unsigned long size = r->end + 1;
-
-       if (!pr)
-               return -EINVAL;
-
-       if (r->flags & IORESOURCE_IO)
-       {
-               if (size > 0x100)
-                       return -EFBIG;
-
-               if (allocate_resource(pr, r, size, bus_info->io_space.start +
-                                     IO_ALLOC_OFFSET,  bus_info->io_space.end, 1024))
-                       return -EBUSY;
-       }
-       else
-       {
-               if (allocate_resource(pr, r, size, bus_info->mem_space.start +
-                                     MEM_ALLOC_OFFSET, bus_info->mem_space.end, size))
-                       return -EBUSY;
-       }
-
-       if (i < 6)
-               pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, r->start);
-
-       return 0;
-}
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-       void *sysdata;
-
-       sysdata = (bus->parent) ? bus->parent->sysdata : bus->sysdata;
-
-       for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
-               dev->sysdata = sysdata;
-}
-
-void __init pcibios_init(void)
-{
-       printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
-
-       bus_info = NULL;
-#ifdef CONFIG_HADES
-       if (MACH_IS_HADES)
-               bus_info = init_hades_pci();
-#endif
-       if (bus_info != NULL)
-       {
-               printk("PCI: Probing PCI hardware\n");
-               pci_scan_bus(0, bus_info->m68k_pci_ops, bus_info);
-               pcibios_fixup();
-               pcibios_claim_resources(pci_root);
-       }
-       else
-               printk("PCI: No PCI bus detected\n");
-}
-
-char * __init pcibios_setup(char *str)
-{
-       if (!strcmp(str, "nomodify"))
-       {
-               pci_modify = 0;
-               return NULL;
-       }
-       else if (!strcmp(str, "skipvga"))
-       {
-               skip_vga = 1;
-               return NULL;
-       }
-       else if (!strcmp(str, "noburst"))
-       {
-               disable_pci_burst = 1;
-               return NULL;
-       }
-
-       return str;
-}
-#endif /* CONFIG_PCI */
index 6f8c080dd9f9d24979f23adefb086810b7c2ae65..2bb4245404d836ca73e770ed24146f7c6c78e9b4 100644 (file)
@@ -66,8 +66,8 @@ void dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
-inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
-                                      enum dma_data_direction dir)
+void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+                               size_t size, enum dma_data_direction dir)
 {
        switch (dir) {
        case DMA_TO_DEVICE:
index ded7dd2f67b2803688965a49f0abb72faf1e0463..7e8a0d394e6184cbf63a5fb257befa4082ce0148 100644 (file)
@@ -429,8 +429,9 @@ int show_interrupts(struct seq_file *p, void *v)
        return 0;
 }
 
+#ifdef CONFIG_PROC_FS
 void init_irq_proc(void)
 {
        /* Insert /proc/irq driver here */
 }
-
+#endif
index 7888cdf91f5dafba1d157547d8ddb4b1a7f268a9..3042c2bc8c58490083ef4a2718c6a839c4e7e978 100644 (file)
@@ -78,7 +78,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 static void default_idle(void)
 {
        if (!need_resched())
-#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
+#if defined(MACH_ATARI_ONLY)
                /* block out HSYNC on the atari (falcon) */
                __asm__("stop #0x2200" : : : "cc");
 #else
index 75b8340b254be08caa07f9e29eac3cbb5e5f0161..6d813de2baf183472f9a95379505e602508845c7 100644 (file)
@@ -883,8 +883,7 @@ void show_trace(unsigned long *stack)
                        if (i % 5 == 0)
                                printk("\n       ");
 #endif
-                       printk(" [<%08lx>]", addr);
-                       print_symbol(" %s\n", addr);
+                       printk(" [<%08lx>] %pS\n", addr, (void *)addr);
                        i++;
                }
        }
@@ -900,10 +899,8 @@ void show_registers(struct pt_regs *regs)
        int i;
 
        print_modules();
-       printk("PC: [<%08lx>]",regs->pc);
-       print_symbol(" %s", regs->pc);
-       printk("\nSR: %04x  SP: %p  a2: %08lx\n",
-              regs->sr, regs, regs->a2);
+       printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
+       printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
        printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
               regs->d0, regs->d1, regs->d2, regs->d3);
        printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
index 99b0784c0552a094cb629f26ae3827e469d17a36..f846d4e3e5e1f23a179ec47e69bbb09488a0c3c8 100644 (file)
@@ -34,10 +34,10 @@ SECTIONS
        CONSTRUCTORS
        }
 
-  .bss : { *(.bss) }           /* BSS */
-
   . = ALIGN(16);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) } :data
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .bss : { *(.bss) }           /* BSS */
 
   _edata = .;                  /* End of data section */
 
@@ -48,7 +48,7 @@ SECTIONS
        _sinittext = .;
        INIT_TEXT
        _einittext = .;
-  }
+  } :data
   .init.data : { INIT_DATA }
   . = ALIGN(16);
   __setup_start = .;
@@ -74,6 +74,7 @@ SECTIONS
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
 #endif
+  NOTES
   . = ALIGN(8192);
   __init_end = .;
 
index 46b7d6035aabaab6a299f5c2cef9fee411c96bb4..df620ac2a296b7a7da77a87cf9e00c06ee0786e5 100644 (file)
@@ -66,8 +66,10 @@ static struct vm_struct *get_io_area(unsigned long size)
        for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
                if (size + addr < (unsigned long)tmp->addr)
                        break;
-               if (addr > KMAP_END-size)
+               if (addr > KMAP_END-size) {
+                       kfree(area);
                        return NULL;
+               }
                addr = tmp->size + (unsigned long)tmp->addr;
        }
        area->addr = (void *)addr;
index 432a9f13b2ed6bc6955908096740c1154e3d4ee5..cea5e3e4e63646abf411aeb34be8172493214a34 100644 (file)
@@ -52,15 +52,15 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                /* Ensure clock and real-time-mode-register are accessible */
                rtc->ctrl = RTC_READ;
                memset(&wtime, 0, sizeof(struct rtc_time));
-               wtime.tm_sec =  BCD2BIN(rtc->bcd_sec);
-               wtime.tm_min =  BCD2BIN(rtc->bcd_min);
-               wtime.tm_hour = BCD2BIN(rtc->bcd_hr);
-               wtime.tm_mday =  BCD2BIN(rtc->bcd_dom);
-               wtime.tm_mon =  BCD2BIN(rtc->bcd_mth)-1;
-               wtime.tm_year = BCD2BIN(rtc->bcd_year);
+               wtime.tm_sec =  bcd2bin(rtc->bcd_sec);
+               wtime.tm_min =  bcd2bin(rtc->bcd_min);
+               wtime.tm_hour = bcd2bin(rtc->bcd_hr);
+               wtime.tm_mday =  bcd2bin(rtc->bcd_dom);
+               wtime.tm_mon =  bcd2bin(rtc->bcd_mth)-1;
+               wtime.tm_year = bcd2bin(rtc->bcd_year);
                if (wtime.tm_year < 70)
                        wtime.tm_year += 100;
-               wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
+               wtime.tm_wday = bcd2bin(rtc->bcd_dow)-1;
                rtc->ctrl = 0;
                local_irq_restore(flags);
                return copy_to_user(argp, &wtime, sizeof wtime) ?
@@ -104,12 +104,12 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                local_irq_save(flags);
                rtc->ctrl     = RTC_WRITE;
 
-               rtc->bcd_sec  = BIN2BCD(sec);
-               rtc->bcd_min  = BIN2BCD(min);
-               rtc->bcd_hr   = BIN2BCD(hrs);
-               rtc->bcd_dom  = BIN2BCD(day);
-               rtc->bcd_mth  = BIN2BCD(mon);
-               rtc->bcd_year = BIN2BCD(yrs%100);
+               rtc->bcd_sec  = bin2bcd(sec);
+               rtc->bcd_min  = bin2bcd(min);
+               rtc->bcd_hr   = bin2bcd(hrs);
+               rtc->bcd_dom  = bin2bcd(day);
+               rtc->bcd_mth  = bin2bcd(mon);
+               rtc->bcd_year = bin2bcd(yrs%100);
 
                rtc->ctrl     = 0;
                local_irq_restore(flags);
index be9de2f3dc48ee1da88283072e49a28890329122..9c7eefa3f98a133bd53d767b0edbf3f622993416 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/serial_reg.h>
 #include <linux/rtc.h>
 #include <linux/vt_kern.h>
+#include <linux/bcd.h>
 
 #include <asm/io.h>
 #include <asm/rtc.h>
@@ -216,17 +217,6 @@ int q40_parse_bootinfo(const struct bi_record *rec)
 }
 
 
-static inline unsigned char bcd2bin(unsigned char b)
-{
-       return (b >> 4) * 10 + (b & 15);
-}
-
-static inline unsigned char bin2bcd(unsigned char b)
-{
-       return (b / 10) * 16 + (b % 10);
-}
-
-
 static unsigned long q40_gettimeoffset(void)
 {
        return 5000 * (ql_ticks != 0);
index f5eaafb00d218ce9519545b3ddb1c2600bac9532..536a04aaf22f28b9de07fda6dd9420b1b31e3b3d 100644 (file)
@@ -47,23 +47,23 @@ int sun3x_hwclk(int set, struct rtc_time *t)
 
        if(set) {
                h->csr |= C_WRITE;
-               h->sec = BIN2BCD(t->tm_sec);
-               h->min = BIN2BCD(t->tm_min);
-               h->hour = BIN2BCD(t->tm_hour);
-               h->wday = BIN2BCD(t->tm_wday);
-               h->mday = BIN2BCD(t->tm_mday);
-               h->month = BIN2BCD(t->tm_mon);
-               h->year = BIN2BCD(t->tm_year);
+               h->sec = bin2bcd(t->tm_sec);
+               h->min = bin2bcd(t->tm_min);
+               h->hour = bin2bcd(t->tm_hour);
+               h->wday = bin2bcd(t->tm_wday);
+               h->mday = bin2bcd(t->tm_mday);
+               h->month = bin2bcd(t->tm_mon);
+               h->year = bin2bcd(t->tm_year);
                h->csr &= ~C_WRITE;
        } else {
                h->csr |= C_READ;
-               t->tm_sec = BCD2BIN(h->sec);
-               t->tm_min = BCD2BIN(h->min);
-               t->tm_hour = BCD2BIN(h->hour);
-               t->tm_wday = BCD2BIN(h->wday);
-               t->tm_mday = BCD2BIN(h->mday);
-               t->tm_mon = BCD2BIN(h->month);
-               t->tm_year = BCD2BIN(h->year);
+               t->tm_sec = bcd2bin(h->sec);
+               t->tm_min = bcd2bin(h->min);
+               t->tm_hour = bcd2bin(h->hour);
+               t->tm_wday = bcd2bin(h->wday);
+               t->tm_mday = bcd2bin(h->mday);
+               t->tm_mon = bcd2bin(h->month);
+               t->tm_year = bcd2bin(h->year);
                h->csr &= ~C_READ;
        }
 
index 2e7515e8db985a9f4b50820edae74a643cf0f325..0a8998315e5ed9fcdada66d87c5ee1127e35b9ac 100644 (file)
@@ -73,9 +73,6 @@ config GENERIC_CLOCKEVENTS
 config NO_IOPORT
        def_bool y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 source "init/Kconfig"
 
 menu "Processor type and features"
diff --git a/arch/m68knommu/include/asm/a.out.h b/arch/m68knommu/include/asm/a.out.h
deleted file mode 100644 (file)
index ce18ef9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/a.out.h>
index 27f0ec70fba8d6f54f58677092c5318d7cee8ac0..b8046837f38496fe42c9a9645dd3fa140e975ee2 100644 (file)
@@ -105,6 +105,6 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif
index 47502d5ec19fa18873ca85fcebeae7ff42e9ed16..3f2d7745f31e8321f629b80dd1eceacced2a52e2 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
index 46f8f9d0c4089085c2c3888e0c63afa2cbbb0e09..5d5d56bcd0efd5121ff2965f83a6e200b4726866 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/a.out.h>
 #include <linux/user.h>
 #include <linux/string.h>
 #include <linux/linkage.h>
index cd5fbf6f07848c3c9778aae1e8be265a92f426c4..b905744d79153be3d3170e9f81ce4e0805974d71 100644 (file)
@@ -52,6 +52,7 @@ config BCM47XX
        select SSB
        select SSB_DRIVER_MIPS
        select SSB_DRIVER_EXTIF
+       select SSB_EMBEDDED
        select SSB_PCICORE_HOSTMODE if PCI
        select GENERIC_GPIO
        select SYS_HAS_EARLY_PRINTK
index f5a53acf995a67eb7b8af311e755efc0d2db2922..9b798800258c3db159cb8ea78718d47feefe2836 100644 (file)
 #include <asm/mach-bcm47xx/bcm47xx.h>
 #include <asm/mach-bcm47xx/gpio.h>
 
-int bcm47xx_gpio_to_irq(unsigned gpio)
+#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
+static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
+#else
+static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
+#endif
+
+int gpio_request(unsigned gpio, const char *tag)
 {
-       if (ssb_bcm47xx.chipco.dev)
-               return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
-       else if (ssb_bcm47xx.extif.dev)
-               return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
-       else
+       if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
+           ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
                return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(bcm47xx_gpio_to_irq);
 
-int bcm47xx_gpio_get_value(unsigned gpio)
-{
-       if (ssb_bcm47xx.chipco.dev)
-               return ssb_chipco_gpio_in(&ssb_bcm47xx.chipco, 1 << gpio);
-       else if (ssb_bcm47xx.extif.dev)
-               return ssb_extif_gpio_in(&ssb_bcm47xx.extif, 1 << gpio);
-       else
-               return 0;
-}
-EXPORT_SYMBOL_GPL(bcm47xx_gpio_get_value);
+       if (ssb_extif_available(&ssb_bcm47xx.extif) &&
+           ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+               return -EINVAL;
 
-void bcm47xx_gpio_set_value(unsigned gpio, int value)
-{
-       if (ssb_bcm47xx.chipco.dev)
-               ssb_chipco_gpio_out(&ssb_bcm47xx.chipco,
-                                   1 << gpio,
-                                   value ? 1 << gpio : 0);
-       else if (ssb_bcm47xx.extif.dev)
-               ssb_extif_gpio_out(&ssb_bcm47xx.extif,
-                                  1 << gpio,
-                                  value ? 1 << gpio : 0);
-}
-EXPORT_SYMBOL_GPL(bcm47xx_gpio_set_value);
+       if (test_and_set_bit(gpio, gpio_in_use))
+               return -EBUSY;
 
-int bcm47xx_gpio_direction_input(unsigned gpio)
-{
-       if (ssb_bcm47xx.chipco.dev && (gpio < BCM47XX_CHIPCO_GPIO_LINES))
-               ssb_chipco_gpio_outen(&ssb_bcm47xx.chipco,
-                                     1 << gpio, 0);
-       else if (ssb_bcm47xx.extif.dev && (gpio < BCM47XX_EXTIF_GPIO_LINES))
-               ssb_extif_gpio_outen(&ssb_bcm47xx.extif,
-                                    1 << gpio, 0);
-       else
-               return -EINVAL;
        return 0;
 }
-EXPORT_SYMBOL_GPL(bcm47xx_gpio_direction_input);
+EXPORT_SYMBOL(gpio_request);
 
-int bcm47xx_gpio_direction_output(unsigned gpio, int value)
+void gpio_free(unsigned gpio)
 {
-       bcm47xx_gpio_set_value(gpio, value);
+       if (ssb_chipco_available(&ssb_bcm47xx.chipco) &&
+           ((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
+               return;
+
+       if (ssb_extif_available(&ssb_bcm47xx.extif) &&
+           ((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
+               return;
+
+       clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
 
-       if (ssb_bcm47xx.chipco.dev && (gpio < BCM47XX_CHIPCO_GPIO_LINES))
-               ssb_chipco_gpio_outen(&ssb_bcm47xx.chipco,
-                                     1 << gpio, 1 << gpio);
-       else if (ssb_bcm47xx.extif.dev && (gpio < BCM47XX_EXTIF_GPIO_LINES))
-               ssb_extif_gpio_outen(&ssb_bcm47xx.extif,
-                                    1 << gpio, 1 << gpio);
+int gpio_to_irq(unsigned gpio)
+{
+       if (ssb_chipco_available(&ssb_bcm47xx.chipco))
+               return ssb_mips_irq(ssb_bcm47xx.chipco.dev) + 2;
+       else if (ssb_extif_available(&ssb_bcm47xx.extif))
+               return ssb_mips_irq(ssb_bcm47xx.extif.dev) + 2;
        else
                return -EINVAL;
-       return 0;
 }
-EXPORT_SYMBOL_GPL(bcm47xx_gpio_direction_output);
+EXPORT_SYMBOL_GPL(gpio_to_irq);
 
index 8d36f186890eaf5e4271c31ea967c0efbe18608e..2f580fa160c9f2ca33de248385ce743c8cf58365 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/types.h>
 #include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_embedded.h>
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
 #include <asm/time.h>
@@ -41,7 +42,7 @@ static void bcm47xx_machine_restart(char *command)
        printk(KERN_ALERT "Please stand by while rebooting the system...\n");
        local_irq_disable();
        /* Set the watchdog timer to reset immediately */
-       ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 1);
+       ssb_watchdog_timer_set(&ssb_bcm47xx, 1);
        while (1)
                cpu_relax();
 }
@@ -50,7 +51,7 @@ static void bcm47xx_machine_halt(void)
 {
        /* Disable interrupts and watchdog and spin forever */
        local_irq_disable();
-       ssb_chipco_watchdog_timer_set(&ssb_bcm47xx.chipco, 0);
+       ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
        while (1)
                cpu_relax();
 }
index d1d90c9ef2fa7382fa6b65fe3e34778ad843e3c1..ef00e7f58c24f16d998430b04c899aaf4d364775 100644 (file)
@@ -11,6 +11,9 @@
 #include <linux/leds.h>
 #include <linux/mtd/physmap.h>
 #include <linux/ssb/ssb.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/gpio.h>
 #include <asm/mach-bcm47xx/bcm47xx.h>
 
 /* GPIO definitions for the WGT634U */
@@ -99,6 +102,30 @@ static struct platform_device *wgt634u_devices[] __initdata = {
        &wgt634u_gpio_leds,
 };
 
+static irqreturn_t gpio_interrupt(int irq, void *ignored)
+{
+       int state;
+
+       /* Interrupts are shared, check if the current one is
+          a GPIO interrupt. */
+       if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
+                                  SSB_CHIPCO_IRQ_GPIO))
+               return IRQ_NONE;
+
+       state = gpio_get_value(WGT634U_GPIO_RESET);
+
+       /* Interrupt are level triggered, revert the interrupt polarity
+          to clear the interrupt. */
+       gpio_polarity(WGT634U_GPIO_RESET, state);
+
+       if (!state) {
+               printk(KERN_INFO "Reset button pressed");
+               ctrl_alt_del();
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int __init wgt634u_init(void)
 {
        /* There is no easy way to detect that we are running on a WGT634U
@@ -112,6 +139,19 @@ static int __init wgt634u_init(void)
            ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
             (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
                struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+
+               printk(KERN_INFO "WGT634U machine detected.\n");
+
+               if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
+                                gpio_interrupt, IRQF_SHARED,
+                                "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
+                       gpio_direction_input(WGT634U_GPIO_RESET);
+                       gpio_intmask(WGT634U_GPIO_RESET, 1);
+                       ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
+                                           SSB_CHIPCO_IRQ_GPIO,
+                                           SSB_CHIPCO_IRQ_GPIO);
+               }
+
                wgt634u_flash_data.width = mcore->flash_buswidth;
                wgt634u_flash_resource.start = mcore->flash_window;
                wgt634u_flash_resource.end = mcore->flash_window
index d956047736675db99cbe5453ce1016570ee5142b..91cbd959ab671f49782dddaee4d692a4de40371a 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/system.h>
 #include <asm/mipsregs.h>
-#include <asm/debug.h>
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
index 5e92b3a9c5b894227ffe91c0b78351650c1d3a2a..e14a2e3d8842e0a2704fb4a548a12b522cf15c49 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/emma2rh/emma2rh.h>
-#include <asm/debug.h>
 
 const char *get_system_type(void)
 {
index d70627de7cfe953764ae786304d0e89b73c1e178..fb9cda253ab0806f67ad6a0245c406e3d1608737 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/irq.h>
 #include <asm/reboot.h>
 #include <asm/traps.h>
-#include <asm/debug.h>
 
 #include <asm/emma2rh/emma2rh.h>
 
diff --git a/arch/mips/include/asm/a.out.h b/arch/mips/include/asm/a.out.h
deleted file mode 100644 (file)
index cad8371..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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) 1994 - 1999, 2003 by Ralf Baechle
- */
-#ifndef _ASM_A_OUT_H
-#define _ASM_A_OUT_H
-
-#ifdef __KERNEL__
-
-
-#endif
-
-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)
-
-#endif /* _ASM_A_OUT_H */
diff --git a/arch/mips/include/asm/cevt-r4k.h b/arch/mips/include/asm/cevt-r4k.h
new file mode 100644 (file)
index 0000000..fa4328f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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) 2008 Kevin D. Kissell
+ */
+
+/*
+ * Definitions used for common event timer implementation
+ * for MIPS 4K-type processors and their MIPS MT variants.
+ * Avoids unsightly extern declarations in C files.
+ */
+#ifndef __ASM_CEVT_R4K_H
+#define __ASM_CEVT_R4K_H
+
+DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
+
+void mips_event_handler(struct clock_event_device *dev);
+int c0_compare_int_usable(void);
+void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *);
+irqreturn_t c0_compare_interrupt(int, void *);
+
+extern struct irqaction c0_compare_irqaction;
+extern int cp0_timer_irq_installed;
+
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+
+static inline int handle_perf_irq(int r2)
+{
+       /*
+        * The performance counter overflow interrupt may be shared with the
+        * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+        * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+        * and we can't reliably determine if a counter interrupt has also
+        * happened (!r2) then don't check for a timer interrupt.
+        */
+       return (cp0_perfcount_irq < 0) &&
+               perf_irq() == IRQ_HANDLED &&
+               !r2;
+}
+
+#endif /* __ASM_CEVT_R4K_H */
index f69f7acba6378542b606bed125bd409a3ec90cbf..a8eac1697b3ddcf05dccc71d42267c549cc40904 100644 (file)
@@ -247,10 +247,8 @@ extern struct mips_abi mips_abi_n32;
 
 #ifdef CONFIG_32BIT
 
-#define SET_PERSONALITY(ex, ibcs2)                                     \
+#define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
-       if (ibcs2)                                                      \
-               set_personality(PER_SVR4);                              \
        set_personality(PER_LINUX);                                     \
                                                                        \
        current->thread.abi = &mips_abi;                                \
@@ -296,7 +294,7 @@ do {                                                                        \
 #define __SET_PERSONALITY32(ex)        do { } while (0)
 #endif
 
-#define SET_PERSONALITY(ex, ibcs2)                                     \
+#define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
        clear_thread_flag(TIF_32BIT_REGS);                              \
        clear_thread_flag(TIF_32BIT_ADDR);                              \
@@ -306,9 +304,7 @@ do {                                                                        \
        else                                                            \
                current->thread.abi = &mips_abi;                        \
                                                                        \
-       if (ibcs2)                                                      \
-               set_personality(PER_SVR4);                              \
-       else if (current->personality != PER_LINUX32)                   \
+       if (current->personality != PER_LINUX32)                        \
                set_personality(PER_LINUX);                             \
 } while (0)
 
index cfc8f4d618ce517e137b7c0f57c0a65ce068bc75..d8ff4cd89ab50731d68f360f04bf5b08d9b779be 100644 (file)
@@ -9,47 +9,46 @@
 #ifndef __BCM47XX_GPIO_H
 #define __BCM47XX_GPIO_H
 
+#include <linux/ssb/ssb_embedded.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+
 #define BCM47XX_EXTIF_GPIO_LINES       5
 #define BCM47XX_CHIPCO_GPIO_LINES      16
 
-extern int bcm47xx_gpio_to_irq(unsigned gpio);
-extern int bcm47xx_gpio_get_value(unsigned gpio);
-extern void bcm47xx_gpio_set_value(unsigned gpio, int value);
-extern int bcm47xx_gpio_direction_input(unsigned gpio);
-extern int bcm47xx_gpio_direction_output(unsigned gpio, int value);
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-       return 0;
-}
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+extern int gpio_to_irq(unsigned gpio);
 
-static inline void gpio_free(unsigned gpio)
+static inline int gpio_get_value(unsigned gpio)
 {
+       return ssb_gpio_in(&ssb_bcm47xx, 1 << gpio);
 }
 
-static inline int gpio_to_irq(unsigned gpio)
+static inline void gpio_set_value(unsigned gpio, int value)
 {
-       return bcm47xx_gpio_to_irq(gpio);
+       ssb_gpio_out(&ssb_bcm47xx, 1 << gpio, value ? 1 << gpio : 0);
 }
 
-static inline int gpio_get_value(unsigned gpio)
+static inline int gpio_direction_input(unsigned gpio)
 {
-       return bcm47xx_gpio_get_value(gpio);
+       return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
 }
 
-static inline void gpio_set_value(unsigned gpio, int value)
+static inline int gpio_direction_output(unsigned gpio, int value)
 {
-       bcm47xx_gpio_set_value(gpio, value);
+       return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
 }
 
-static inline int gpio_direction_input(unsigned gpio)
+static int gpio_intmask(unsigned gpio, int value)
 {
-       return bcm47xx_gpio_direction_input(gpio);
+       return ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
+                               value ? 1 << gpio : 0);
 }
 
-static inline int gpio_direction_output(unsigned gpio, int value)
+static int gpio_polarity(unsigned gpio, int value)
 {
-       return bcm47xx_gpio_direction_output(gpio, value);
+       return ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
+                                value ? 1 << gpio : 0);
 }
 
 
index 4a2b7986b5824913bd6f990a0e03a1ee638336e7..87cd4651dda380a9438564f5b76cbd94dc9767c0 100644 (file)
@@ -5,8 +5,8 @@
  *
  * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
  */
-#ifndef __ASM_MIPS_MACH_BCM947XX_WAR_H
-#define __ASM_MIPS_MACH_BCM947XX_WAR_H
+#ifndef __ASM_MIPS_MACH_BCM47XX_WAR_H
+#define __ASM_MIPS_MACH_BCM47XX_WAR_H
 
 #define R4600_V1_INDEX_ICACHEOP_WAR    0
 #define R4600_V1_HIT_CACHEOP_WAR       0
@@ -22,4 +22,4 @@
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
 
-#endif /* __ASM_MIPS_MACH_BCM947XX_WAR_H */
+#endif /* __ASM_MIPS_MACH_BCM47XX_WAR_H */
index 73008f7bdc93708281e647889a7e3d6c6be87c41..9c93a5b36f2a2dfd14a84fcfea813fb8ed3634e8 100644 (file)
 #include <linux/stddef.h>
 #include <asm/processor.h>
 
-static __inline__ int ide_probe_legacy(void)
-{
-#ifdef CONFIG_PCI
-       struct pci_dev *dev;
-       /*
-        * This can be called on the ide_setup() path, super-early in
-        * boot.  But the down_read() will enable local interrupts,
-        * which can cause some machines to crash.  So here we detect
-        * and flag that situation and bail out early.
-        */
-       if (no_pci_devices())
-               return 0;
-       dev = pci_get_class(PCI_CLASS_BRIDGE_EISA << 8, NULL);
-       if (dev)
-               goto found;
-       dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
-       if (dev)
-               goto found;
-       return 0;
-found:
-       pci_dev_put(dev);
-       return 1;
-#elif defined(CONFIG_EISA) || defined(CONFIG_ISA)
-       return 1;
-#else
-       return 0;
-#endif
-}
-
 /* MIPS port and memory-mapped I/O string operations.  */
 static inline void __ide_flush_prologue(void)
 {
diff --git a/arch/mips/include/asm/mach-ip22/ds1286.h b/arch/mips/include/asm/mach-ip22/ds1286.h
deleted file mode 100644 (file)
index f19f1ea..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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) 1998, 2001, 03 by Ralf Baechle
- *
- * RTC routines for PC style attached Dallas chip.
- */
-#ifndef __ASM_MACH_IP22_DS1286_H
-#define __ASM_MACH_IP22_DS1286_H
-
-#include <asm/sgi/hpc3.h>
-
-#define rtc_read(reg)          (hpc3c0->rtcregs[(reg)] & 0xff)
-#define rtc_write(data, reg)   do { hpc3c0->rtcregs[(reg)] = (data); } while(0)
-
-#endif /* __ASM_MACH_IP22_DS1286_H */
diff --git a/arch/mips/include/asm/mach-ip28/ds1286.h b/arch/mips/include/asm/mach-ip28/ds1286.h
deleted file mode 100644 (file)
index 471bb9a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASM_MACH_IP28_DS1286_H
-#define __ASM_MACH_IP28_DS1286_H
-#include <asm/mach-ip22/ds1286.h>
-#endif /* __ASM_MACH_IP28_DS1286_H */
index 5d98a3cb85b711f6b9f8a0f1ff7cf8a82b920778..1a1f320c30d8286cff6d8d16374c9a41fa318ac3 100644 (file)
@@ -147,7 +147,7 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
                "       ori     %[ticket], %[ticket], 0x2000            \n"
                "       xori    %[ticket], %[ticket], 0x2000            \n"
                "       sc      %[ticket], %[ticket_ptr]                \n"
-               "       beqzl   %[ticket], 2f                           \n"
+               "       beqzl   %[ticket], 1b                           \n"
                : [ticket_ptr] "+m" (lock->lock),
                  [ticket] "=&r" (tmp));
        } else {
index 2fefb14414b7db6db1dbfd4b58719082197439ba..aa2c55e3b55ffda84dff352114a6bf904aa07580 100644 (file)
 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
 #endif
 
-/*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       struct compat_stat tmp;
-
-       if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.st_dev = new_encode_dev(stat->dev);
-       tmp.st_ino = stat->ino;
-       if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
-               return -EOVERFLOW;
-       tmp.st_mode = stat->mode;
-       tmp.st_nlink = stat->nlink;
-       SET_UID(tmp.st_uid, stat->uid);
-       SET_GID(tmp.st_gid, stat->gid);
-       tmp.st_rdev = new_encode_dev(stat->rdev);
-       tmp.st_size = stat->size;
-       tmp.st_atime = stat->atime.tv_sec;
-       tmp.st_mtime = stat->mtime.tv_sec;
-       tmp.st_ctime = stat->ctime.tv_sec;
-#ifdef STAT_HAVE_NSEC
-       tmp.st_atime_nsec = stat->atime.tv_nsec;
-       tmp.st_mtime_nsec = stat->mtime.tv_nsec;
-       tmp.st_ctime_nsec = stat->ctime.tv_nsec;
-#endif
-       tmp.st_blocks = stat->blocks;
-       tmp.st_blksize = stat->blksize;
-       return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
-}
-
 asmlinkage unsigned long
 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
          unsigned long flags, unsigned long fd, unsigned long pgoff)
@@ -168,72 +133,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
        return sys_ftruncate(fd, merge_64(a2, a3));
 }
 
-static inline long
-get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
-       return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-               (__get_user(o->tv_sec, &i->tv_sec) |
-                __get_user(o->tv_usec, &i->tv_usec)));
-}
-
-static inline long
-put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) |
-                __put_user(i->tv_usec, &o->tv_usec)));
-}
-
-extern struct timezone sys_tz;
-
-asmlinkage int
-sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (!access_ok(VERIFY_READ, i, sizeof(*i)))
-               return -EFAULT;
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-               return 0;
-}
-
-asmlinkage int
-sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
                            unsigned int offset_low, loff_t __user * result,
                            unsigned int origin)
index 75bb1300dd7aa0c12f7985a3986a69e9d49904f6..26760cad8b6972c4ad956a8cad81355c9d15ade7 100644 (file)
@@ -39,7 +39,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "processor\t\t: %ld\n", n);
        sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
                cpu_data[n].options & MIPS_CPU_FPU ? "  FPU V%d.%d" : "");
-       seq_printf(m, fmt, __cpu_name[smp_processor_id()],
+       seq_printf(m, fmt, __cpu_name[n],
                                   (version >> 4) & 0x0f, version & 0x0f,
                                   (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
        seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n",
index 22fc19bbe87f3744ee24ef7dbc81a315b293fc1d..ca2e4026ad20b3c00365d0dc3b85904bbd2e273a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/personality.h>
 #include <linux/sys.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
index dfd868b683640634f7d128f883f53165b73595fb..4ce93aa7b37259f24299791a7a793230de5a79a6 100644 (file)
@@ -522,8 +522,8 @@ static int __init rtlx_module_init(void)
                atomic_set(&channel_wqs[i].in_open, 0);
                mutex_init(&channel_wqs[i].mutex);
 
-               dev = device_create_drvdata(mt_class, NULL, MKDEV(major, i),
-                                           NULL, "%s%d", module_name, i);
+               dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,
+                                   "%s%d", module_name, i);
                if (IS_ERR(dev)) {
                        err = PTR_ERR(dev);
                        goto out_chrdev;
index 324c5499dec28c4b29cb529a9bc5032c71ba9aa1..e266b3aa6560fa8de6e3b0fd607bee6a714685a8 100644 (file)
@@ -214,7 +214,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_fchown
        PTR     sys_lchown
        PTR     sys_umask
-       PTR     sys32_gettimeofday
+       PTR     compat_sys_gettimeofday
        PTR     compat_sys_getrlimit            /* 6095 */
        PTR     compat_sys_getrusage
        PTR     compat_sys_sysinfo
@@ -279,7 +279,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_chroot
        PTR     sys_sync
        PTR     sys_acct
-       PTR     sys32_settimeofday
+       PTR     compat_sys_settimeofday
        PTR     compat_sys_mount                /* 6160 */
        PTR     sys_umount
        PTR     sys_swapon
index 85fedac99a578eb67e732b8762856eda3ca766c1..6c7ef8313ebd702dde4997d225f06189fdb560a0 100644 (file)
@@ -283,8 +283,8 @@ sys_call_table:
        PTR     compat_sys_setrlimit            /* 4075 */
        PTR     compat_sys_getrlimit
        PTR     compat_sys_getrusage
-       PTR     sys32_gettimeofday
-       PTR     sys32_settimeofday
+       PTR     compat_sys_gettimeofday
+       PTR     compat_sys_settimeofday
        PTR     sys_getgroups                   /* 4080 */
        PTR     sys_setgroups
        PTR     sys_ni_syscall                  /* old_select */
index 343015a2f418fd9fb741ef6ae7b8821008e1af19..37970d9b2186eed4f26d8b736d731f35fb5d7b72 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  * Copyright (C) 2001 MIPS Technologies, Inc.
  */
-#include <linux/a.out.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
index afb119f35682680c2eb5eeddb20137aab7e64aa9..58738c8d754feb09bf525fe6862c62e1f6bda39a 100644 (file)
@@ -104,7 +104,7 @@ SECTIONS
        . = ALIGN(_PAGE_SIZE);
        __nosave_end = .;
 
-       . = ALIGN(32);
+       . = ALIGN(1 << CONFIG_MIPS_L1_CACHE_SHIFT);
        .data.cacheline_aligned : {
                *(.data.cacheline_aligned)
        }
index 866881ec0cf81ed603705f8c01cebab3147def2f..8f88886feb12e147167fa7bcf61a5961bd6430cf 100644 (file)
 #endif
 
 /* Strategy function to write EEPROM after changing string entry */
-int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
+int sysctl_lasatstring(ctl_table *table,
                void *oldval, size_t *oldlenp,
                void *newval, size_t newlen)
 {
        int r;
 
-       r = sysctl_string(table, name,
-                         nlen, oldval, oldlenp, newval, newlen);
+       r = sysctl_string(table, oldval, oldlenp, newval, newlen);
        if (r < 0)
                return r;
 
@@ -113,13 +112,13 @@ int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
 #endif
 
 /* Sysctl for setting the IP addresses */
-int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
+int sysctl_lasat_intvec(ctl_table *table,
                    void *oldval, size_t *oldlenp,
                    void *newval, size_t newlen)
 {
        int r;
 
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
+       r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
        if (r < 0)
                return r;
 
@@ -131,7 +130,7 @@ int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
 
 #ifdef CONFIG_DS1603
 /* Same for RTC */
-int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
+int sysctl_lasat_rtc(ctl_table *table,
                    void *oldval, size_t *oldlenp,
                    void *newval, size_t newlen)
 {
@@ -140,7 +139,7 @@ int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
        rtctmp = read_persistent_clock();
        if (rtctmp < 0)
                rtctmp = 0;
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
+       r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
        if (r < 0)
                return r;
        if (newval && newlen)
@@ -211,13 +210,13 @@ int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
 }
 #endif
 
-static int sysctl_lasat_prid(ctl_table *table, int *name, int nlen,
+static int sysctl_lasat_prid(ctl_table *table,
                                     void *oldval, size_t *oldlenp,
                                     void *newval, size_t newlen)
 {
        int r;
 
-       r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
+       r = sysctl_intvec(table, oldval, oldlenp, newval, newlen);
        if (r < 0)
                return r;
        if (newval && newlen) {
index a2705895561d983f54e48f52594f1594e4166cd3..846eae9cdd051cbc2fbf6f9d007ca4fc217d152d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci.h>
 
 #include <asm/bootinfo.h>
-#include <asm/debug.h>
 
 #include <asm/emma2rh/emma2rh.h>
 
index 0e160d9f07c39ae5aafd5df33dd605b6365118f7..1e6213fa7bdbc2de327b5923e95649aa0fda86e1 100644 (file)
@@ -29,8 +29,6 @@
 
 #include <asm/mach-pnx8550/pci.h>
 #include <asm/mach-pnx8550/glb.h>
-#include <asm/debug.h>
-
 
 static inline void clear_status(void)
 {
index d99591a0cdfe7abdfdeaf99a5a7218395edbfb82..772e283daa63c5115b7ca429f86164f49e87bf19 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/pci.h>
 
 #include <asm/bootinfo.h>
-#include <asm/debug.h>
 
 #include <asm/emma2rh/emma2rh.h>
 
index c7fe6ec621e68524b0e4ef5d391e7e47d43e472a..a377e9d2d029be681072a265908ba7f0f9a2dd17 100644 (file)
@@ -34,6 +34,8 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head;
 unsigned long PCIBIOS_MIN_IO   = 0x0000;
 unsigned long PCIBIOS_MIN_MEM  = 0;
 
+static int pci_initialized;
+
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
@@ -74,6 +76,42 @@ pcibios_align_resource(void *data, struct resource *res,
        res->start = start;
 }
 
+static void __devinit pcibios_scanbus(struct pci_controller *hose)
+{
+       static int next_busno;
+       static int need_domain_info;
+       struct pci_bus *bus;
+
+       if (!hose->iommu)
+               PCI_DMA_BUS_IS_PHYS = 1;
+
+       if (hose->get_busno && pci_probe_only)
+               next_busno = (*hose->get_busno)();
+
+       bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+       hose->bus = bus;
+
+       need_domain_info = need_domain_info || hose->index;
+       hose->need_domain_info = need_domain_info;
+       if (bus) {
+               next_busno = bus->subordinate + 1;
+               /* Don't allow 8-bit bus number overflow inside the hose -
+                  reserve some space for bridges. */
+               if (next_busno > 224) {
+                       next_busno = 0;
+                       need_domain_info = 1;
+               }
+
+               if (!pci_probe_only) {
+                       pci_bus_size_bridges(bus);
+                       pci_bus_assign_resources(bus);
+                       pci_enable_bridges(bus);
+               }
+       }
+}
+
+static DEFINE_MUTEX(pci_scan_mutex);
+
 void __devinit register_pci_controller(struct pci_controller *hose)
 {
        if (request_resource(&iomem_resource, hose->mem_resource) < 0)
@@ -93,6 +131,17 @@ void __devinit register_pci_controller(struct pci_controller *hose)
                printk(KERN_WARNING
                       "registering PCI controller with io_map_base unset\n");
        }
+
+       /*
+        * Scan the bus if it is register after the PCI subsystem
+        * initialization.
+        */
+       if (pci_initialized) {
+               mutex_lock(&pci_scan_mutex);
+               pcibios_scanbus(hose);
+               mutex_unlock(&pci_scan_mutex);
+       }
+
        return;
 
 out:
@@ -125,38 +174,15 @@ static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
 static int __init pcibios_init(void)
 {
        struct pci_controller *hose;
-       struct pci_bus *bus;
-       int next_busno;
-       int need_domain_info = 0;
 
        /* Scan all of the recorded PCI controllers.  */
-       for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
-
-               if (!hose->iommu)
-                       PCI_DMA_BUS_IS_PHYS = 1;
-
-               if (hose->get_busno && pci_probe_only)
-                       next_busno = (*hose->get_busno)();
-
-               bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
-               hose->bus = bus;
-               need_domain_info = need_domain_info || hose->index;
-               hose->need_domain_info = need_domain_info;
-               if (bus) {
-                       next_busno = bus->subordinate + 1;
-                       /* Don't allow 8-bit bus number overflow inside the hose -
-                          reserve some space for bridges. */
-                       if (next_busno > 224) {
-                               next_busno = 0;
-                               need_domain_info = 1;
-                       }
-               }
-       }
+       for (hose = hose_head; hose; hose = hose->next)
+               pcibios_scanbus(hose);
 
-       if (!pci_probe_only)
-               pci_assign_unassigned_resources();
        pci_fixup_irqs(common_swizzle, pcibios_map_irq);
 
+       pci_initialized = 1;
+
        return 0;
 }
 
index 8e7a46855b50ad8fc5afe81e528d2e301c833a31..1377d599f0e33ff9dcf60680aea7ff8ed07a2a5d 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/timex.h>
 
 #include <asm/mipsregs.h>
-#include <asm/debug.h>
 #include <asm/time.h>
 #include <asm/mach-rc32434/rc32434.h>
 
index 52486c4d2b019739be2db360e3cbc8b7dd1fd847..deddbf0ebe5c839175353b3f7f8cce68a594106c 100644 (file)
@@ -192,3 +192,18 @@ static int __init sgi_button_devinit(void)
 }
 
 device_initcall(sgi_button_devinit);
+
+static int __init sgi_ds1286_devinit(void)
+{
+       struct resource res;
+
+       memset(&res, 0, sizeof(res));
+       res.start = HPC3_CHIP0_BASE + offsetof(struct hpc3_regs, rtcregs);
+       res.end = res.start + sizeof(hpc3c0->rtcregs) - 1;
+       res.flags = IORESOURCE_MEM;
+
+       return IS_ERR(platform_device_register_simple("rtc-ds1286", -1,
+                                                     &res, 1));
+}
+
+device_initcall(sgi_ds1286_devinit);
index 896a1ef8482962e5376a37487693f5b87183f053..b9a931358e2391801aa0e2704ecbb8f83b991be4 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
  */
-#include <linux/ds1286.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kdev_t.h>
index 10e50549165588b13cfc5a63e17a57539f7812ba..3dcb27ec0c530b7aa4238bc4eb2cd568cd9fc794 100644 (file)
@@ -10,7 +10,6 @@
  * Copyright (C) 2003, 06 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/bcd.h>
-#include <linux/ds1286.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ip22.h>
 
-/*
- * Note that mktime uses month from 1 to 12 while rtc_time_to_tm
- * uses 0 to 11.
- */
-unsigned long read_persistent_clock(void)
-{
-       unsigned int yrs, mon, day, hrs, min, sec;
-       unsigned int save_control;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
-       hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
-
-       sec = BCD2BIN(hpc3c0->rtcregs[RTC_SECONDS] & 0xff);
-       min = BCD2BIN(hpc3c0->rtcregs[RTC_MINUTES] & 0xff);
-       hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x3f);
-       day = BCD2BIN(hpc3c0->rtcregs[RTC_DATE] & 0xff);
-       mon = BCD2BIN(hpc3c0->rtcregs[RTC_MONTH] & 0x1f);
-       yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff);
-
-       hpc3c0->rtcregs[RTC_CMD] = save_control;
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       if (yrs < 45)
-               yrs += 30;
-       if ((yrs += 40) < 70)
-               yrs += 100;
-
-       return mktime(yrs + 1900, mon, day, hrs, min, sec);
-}
-
-int rtc_mips_set_time(unsigned long tim)
-{
-       struct rtc_time tm;
-       unsigned int save_control;
-       unsigned long flags;
-
-       rtc_time_to_tm(tim, &tm);
-
-       tm.tm_mon += 1;         /* tm_mon starts at zero */
-       tm.tm_year -= 40;
-       if (tm.tm_year >= 100)
-               tm.tm_year -= 100;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
-       hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
-
-       hpc3c0->rtcregs[RTC_YEAR] = BIN2BCD(tm.tm_year);
-       hpc3c0->rtcregs[RTC_MONTH] = BIN2BCD(tm.tm_mon);
-       hpc3c0->rtcregs[RTC_DATE] = BIN2BCD(tm.tm_mday);
-       hpc3c0->rtcregs[RTC_HOURS] = BIN2BCD(tm.tm_hour);
-       hpc3c0->rtcregs[RTC_MINUTES] = BIN2BCD(tm.tm_min);
-       hpc3c0->rtcregs[RTC_SECONDS] = BIN2BCD(tm.tm_sec);
-       hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0;
-
-       hpc3c0->rtcregs[RTC_CMD] = save_control;
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       return 0;
-}
-
 static unsigned long dosample(void)
 {
        u32 ct0, ct1;
index 8b4e854af925b4b832dff234c0a0bcd64e2f5a42..1327c2746fb73be5cedc9484df1bfdb8ab16ce1c 100644 (file)
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
+#include <linux/platform_device.h>
 
 #include <asm/time.h>
 #include <asm/pgtable.h>
 #include <asm/sgialib.h>
 #include <asm/sn/ioc3.h>
-#include <asm/m48t35.h>
 #include <asm/sn/klconfig.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
 
 #define TICK_SIZE (tick_nsec / 1000)
 
-#if 0
-static int set_rtc_mmss(unsigned long nowtime)
-{
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-       struct m48t35_rtc *rtc;
-       nasid_t nid;
-
-       nid = get_nasid();
-       rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
-                                                       IOC3_BYTEBUS_DEV0);
-
-       rtc->control |= M48T35_RTC_READ;
-       cmos_minutes = BCD2BIN(rtc->min);
-       rtc->control &= ~M48T35_RTC_READ;
-
-       /*
-        * Since we're only adjusting minutes and seconds, don't interfere with
-        * hour overflow. This avoids messing with unknown time zones but
-        * requires your RTC not to be off by more than 15 minutes
-        */
-       real_seconds = nowtime % 60;
-       real_minutes = nowtime / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-               real_minutes += 30;     /* correct for half hour time zone */
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               real_seconds = BIN2BCD(real_seconds);
-               real_minutes = BIN2BCD(real_minutes);
-               rtc->control |= M48T35_RTC_SET;
-               rtc->sec = real_seconds;
-               rtc->min = real_minutes;
-               rtc->control &= ~M48T35_RTC_SET;
-       } else {
-               printk(KERN_WARNING
-                      "set_rtc_mmss: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       return retval;
-}
-#endif
-
 /* Includes for ioc3_init().  */
 #include <asm/sn/types.h>
 #include <asm/sn/sn0/addrs.h>
@@ -80,37 +35,6 @@ static int set_rtc_mmss(unsigned long nowtime)
 #include <asm/sn/sn0/hubio.h>
 #include <asm/pci/bridge.h>
 
-unsigned long read_persistent_clock(void)
-{
-        unsigned int year, month, date, hour, min, sec;
-       struct m48t35_rtc *rtc;
-       nasid_t nid;
-
-       nid = get_nasid();
-       rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
-                                                       IOC3_BYTEBUS_DEV0);
-
-       rtc->control |= M48T35_RTC_READ;
-       sec = rtc->sec;
-       min = rtc->min;
-       hour = rtc->hour;
-       date = rtc->date;
-       month = rtc->month;
-       year = rtc->year;
-       rtc->control &= ~M48T35_RTC_READ;
-
-        sec = BCD2BIN(sec);
-        min = BCD2BIN(min);
-        hour = BCD2BIN(hour);
-        date = BCD2BIN(date);
-        month = BCD2BIN(month);
-        year = BCD2BIN(year);
-
-        year += 1970;
-
-        return mktime(year, month, date, hour, min, sec);
-}
-
 static void enable_rt_irq(unsigned int irq)
 {
 }
@@ -286,6 +210,7 @@ void __cpuinit cpu_time_init(void)
 
 void __cpuinit hub_rtc_init(cnodeid_t cnode)
 {
+
        /*
         * We only need to initialize the current node.
         * If this is not the current node then it is a cpuless
@@ -301,3 +226,23 @@ void __cpuinit hub_rtc_init(cnodeid_t cnode)
                LOCAL_HUB_S(PI_RT_PEND_B, 0);
        }
 }
+
+static int __init sgi_ip27_rtc_devinit(void)
+{
+       struct resource res;
+
+       memset(&res, 0, sizeof(res));
+       res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base +
+                             IOC3_BYTEBUS_DEV0);
+       res.end = res.start + 32767;
+       res.flags = IORESOURCE_MEM;
+
+       return IS_ERR(platform_device_register_simple("rtc-m48t35", -1,
+                                                     &res, 1));
+}
+
+/*
+ * kludge make this a device_initcall after ioc3 resource conflicts
+ * are resolved
+ */
+late_initcall(sgi_ip27_rtc_devinit);
index 3d63721e0e804e117cb0580837014c016856f66c..511e9ff2acfd997751d1b86b80e7165e262052a9 100644 (file)
@@ -90,6 +90,22 @@ static __init int sgio2btns_devinit(void)
 
 device_initcall(sgio2btns_devinit);
 
+static struct resource sgio2_cmos_rsrc[] = {
+       {
+               .start = 0x70,
+               .end   = 0x71,
+               .flags = IORESOURCE_IO
+       }
+};
+
+static __init int sgio2_cmos_devinit(void)
+{
+       return IS_ERR(platform_device_register_simple("rtc_cmos", -1,
+                                                     sgio2_cmos_rsrc, 1));
+}
+
+device_initcall(sgio2_cmos_devinit);
+
 MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2");
index 1024bf40bd9e79f1c63dd79f7be8289371e89caf..c5a5d4a31b4b42f1c7d3c9a2f45cbbe88e16bf01 100644 (file)
@@ -62,11 +62,6 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
 }
 #endif
 
-unsigned long read_persistent_clock(void)
-{
-       return mc146818_get_cmos_time();
-}
-
 /* An arbitrary time; this can be decreased if reliability looks good */
 #define WAIT_MS 10
 
index 66e3e3fb311f9a413ffb3dbc58aa9174fe101fe5..637a194e5cd5f95e0ee2de2687ddbab05ac45cec 100644 (file)
@@ -576,8 +576,7 @@ static int __init sbprof_tb_init(void)
 
        tb_class = tbc;
 
-       dev = device_create_drvdata(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0),
-                                   NULL, "tb");
+       dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), NULL, "tb");
        if (IS_ERR(dev)) {
                err = PTR_ERR(dev);
                goto out_class;
index e856218da90d36098e719602be9ffaa78c28f606..dd557c9cf001be6226441b78cb84753f5e50cb15 100644 (file)
@@ -53,9 +53,6 @@ config QUICKLIST
 config ARCH_HAS_ILOG2_U32
        def_bool y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool n
-
 # Use the generic interrupt handling code in kernel/irq/
 config GENERIC_HARDIRQS
        def_bool y
index a7d4fd353c2b06fcaa8c7d6e1306e71b14ad440f..8313fccced5e1553f6f3d7ff484d897d2d20b812 100644 (file)
@@ -76,9 +76,6 @@ config IRQ_PER_CPU
        bool
        default y
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 # unless you want to implement ACPI on PA-RISC ... ;-)
 config PM
        bool
index ecb10a4f63c6af15324cb7343951701b04aaba1f..f61692d2b557edcc51691148182b3750b373ccb9 100644 (file)
@@ -85,7 +85,7 @@ struct elf_prpsinfo32
  * could set a processor dependent flag in the thread_struct.
  */
 
-#define SET_PERSONALITY(ex, ibcs2) \
+#define SET_PERSONALITY(ex) \
        set_thread_flag(TIF_32BIT); \
        current->thread.map_base = DEFAULT_MAP_BASE32; \
        current->thread.task_size = DEFAULT_TASK_SIZE32 \
index 71efd6a28e2a39b60a3151836d50facd9594984f..0838155b7a88229df24188a9f0dc74b2facf1162 100644 (file)
@@ -179,111 +179,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
        return ret;
 }
 
-static int
-put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
-{
-       struct compat_timeval t32;
-       t32.tv_sec = t->tv_sec;
-       t32.tv_usec = t->tv_usec;
-       return copy_to_user(u, &t32, sizeof t32);
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-       return 0;
-}
-
-asmlinkage int
-sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-    extern void do_gettimeofday(struct timeval *tv);
-
-    if (tv) {
-           struct timeval ktv;
-           do_gettimeofday(&ktv);
-           if (put_compat_timeval(tv, &ktv))
-                   return -EFAULT;
-    }
-    if (tz) {
-           extern struct timezone sys_tz;
-           if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                   return -EFAULT;
-    }
-    return 0;
-}
-
-asmlinkage 
-int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
-           !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(0, &statbuf->st_reserved1);
-       err |= put_user(0, &statbuf->st_reserved2);
-       err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-       err |= put_user(0, &statbuf->__unused1);
-       err |= put_user(0, &statbuf->__unused2);
-       err |= put_user(0, &statbuf->__unused3);
-       err |= put_user(0, &statbuf->__unused4);
-       err |= put_user(0, &statbuf->__unused5);
-       err |= put_user(0, &statbuf->st_fstype); /* not avail */
-       err |= put_user(0, &statbuf->st_realdev); /* not avail */
-       err |= put_user(0, &statbuf->st_basemode); /* not avail */
-       err |= put_user(0, &statbuf->st_spareshort);
-       err |= put_user(stat->uid, &statbuf->st_uid);
-       err |= put_user(stat->gid, &statbuf->st_gid);
-       err |= put_user(0, &statbuf->st_spare4[0]);
-       err |= put_user(0, &statbuf->st_spare4[1]);
-       err |= put_user(0, &statbuf->st_spare4[2]);
-
-       return err;
-}
-
 /*** copied from mips64 ***/
 /*
  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
index 6b5ac38f5a9916017473d3174bb6f3d047f72cb8..c7e59f548817fb36554954d663bfedcdf5e3b2f6 100644 (file)
        ENTRY_COMP(getrlimit)
        ENTRY_COMP(getrusage)
        /* struct timeval and timezone are maybe?? consistent wide and narrow */
-       ENTRY_DIFF(gettimeofday)
-       ENTRY_DIFF(settimeofday)
+       ENTRY_COMP(gettimeofday)
+       ENTRY_COMP(settimeofday)
        ENTRY_SAME(getgroups)           /* 80 */
        ENTRY_SAME(setgroups)
        /* struct socketaddr... */
index 587da5e0990f9504979f9357b2783305e6a23d02..380baa1780e9197b060ce1594aa098340d4da538 100644 (file)
@@ -22,6 +22,9 @@ config WORD_SIZE
 config PPC_MERGE
        def_bool y
 
+config ARCH_PHYS_ADDR_T_64BIT
+       def_bool PPC64 || PHYS_64BIT
+
 config MMU
        bool
        default y
@@ -415,8 +418,11 @@ config PPC_64K_PAGES
 
 config FORCE_MAX_ZONEORDER
        int "Maximum zone order"
+       range 9 64 if PPC_64K_PAGES
        default "9" if PPC_64K_PAGES
+       range 13 64 if PPC64 && !PPC_64K_PAGES
        default "13" if PPC64 && !PPC_64K_PAGES
+       range 11 64
        default "11"
        help
          The kernel memory allocator divides physically contiguous memory
@@ -806,6 +812,19 @@ config PIN_TLB
 endmenu
 
 if PPC64
+config RELOCATABLE
+       bool "Build a relocatable kernel"
+       help
+         This builds a kernel image that is capable of running anywhere
+         in the RMA (real memory area) at any 16k-aligned base address.
+         The kernel is linked as a position-independent executable (PIE)
+         and contains dynamic relocations which are processed early
+         in the bootup process.
+
+         One use is for the kexec on panic case where the recovery kernel
+         must live at a different physical address than the primary
+         kernel.
+
 config PAGE_OFFSET
        hex
        default "0xc000000000000000"
index 4ebc52a19f0ab4e9883a3621882744d5f69e0dcc..15eb27861fc713c1b02995fd030bc139652b24d2 100644 (file)
@@ -51,6 +51,11 @@ config FTR_FIXUP_SELFTEST
        depends on DEBUG_KERNEL
        default n
 
+config MSI_BITMAP_SELFTEST
+       bool "Run self-tests of the MSI bitmap code."
+       depends on DEBUG_KERNEL
+       default n
+
 config XMON
        bool "Include xmon kernel debugger"
        depends on DEBUG_KERNEL
index c6be19e9ceae99dd6f0d6a47f66e44634a71e3bb..24dd1a37f8fb93268b120ac844bd62880eb2a7de 100644 (file)
@@ -63,7 +63,9 @@ override CC   += -m$(CONFIG_WORD_SIZE)
 override AR    := GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR)
 endif
 
-LDFLAGS_vmlinux        := -Bstatic
+LDFLAGS_vmlinux-yy := -Bstatic
+LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie
+LDFLAGS_vmlinux        := $(LDFLAGS_vmlinux-yy)
 
 CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none  -mcall-aixdesc
 CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
@@ -102,7 +104,10 @@ endif
 KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
 
 # No SPE instruction when building kernel
+# (We use all available options to help semi-broken compilers)
 KBUILD_CFLAGS += $(call cc-option,-mno-spe)
+KBUILD_CFLAGS += $(call cc-option,-mspe=no)
+KBUILD_CFLAGS += $(call cc-option,-mabi=no-spe)
 
 # Enable unit-at-a-time mode when possible. It shrinks the
 # kernel considerably.
index 65d1a8454d2cfb11e54ffa3082c16bc3316bd4da..aac1406ccba5cb6394cdacf4837d846e4d35e56a 100644 (file)
@@ -310,8 +310,11 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
 $(obj)/vmlinux.strip: vmlinux
        $(STRIP) -s -R .comment $< -o $@
 
+# The iseries hypervisor won't take an ET_DYN executable, so this
+# changes the type (byte 17) in the file to ET_EXEC (2).
 $(obj)/zImage.iseries: vmlinux
        $(STRIP) -s -R .comment $< -o $@
+       printf "\x02" | dd of=$@ conv=notrunc bs=1 seek=17
 
 $(obj)/uImage: vmlinux $(wrapperbits)
        $(call if_changed,wrap,uboot)
index b1e5611b2ab1d639edd67346ca50f88d625b9629..dcc9ab2ca823fff000dccf638c3c7caab421500e 100644 (file)
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * Usage: addnote zImage
+ * Usage: addnote zImage [note.elf]
+ *
+ * If note.elf is supplied, it is the name of an ELF file that contains
+ * an RPA note to use instead of the built-in one.  Alternatively, the
+ * note.elf file may be empty, in which case the built-in RPA note is
+ * used (this is to simplify how this is invoked from the wrapper script).
  */
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,27 +48,29 @@ char rpaname[] = "IBM,RPA-Client-Config";
  */
 #define N_RPA_DESCR    8
 unsigned int rpanote[N_RPA_DESCR] = {
-       0,                      /* lparaffinity */
-       64,                     /* min_rmo_size */
+       1,                      /* lparaffinity */
+       128,                    /* min_rmo_size */
        0,                      /* min_rmo_percent */
-       40,                     /* max_pft_size */
+       46,                     /* max_pft_size */
        1,                      /* splpar */
        -1,                     /* min_load */
-       0,                      /* new_mem_def */
-       1,                      /* ignore_my_client_config */
+       1,                      /* new_mem_def */
+       0,                      /* ignore_my_client_config */
 };
 
 #define ROUNDUP(len)   (((len) + 3) & ~3)
 
 unsigned char buf[512];
+unsigned char notebuf[512];
 
-#define GET_16BE(off)  ((buf[off] << 8) + (buf[(off)+1]))
-#define GET_32BE(off)  ((GET_16BE(off) << 16) + GET_16BE((off)+2))
+#define GET_16BE(b, off)       (((b)[off] << 8) + ((b)[(off)+1]))
+#define GET_32BE(b, off)       ((GET_16BE((b), (off)) << 16) + \
+                                GET_16BE((b), (off)+2))
 
-#define PUT_16BE(off, v)       (buf[off] = ((v) >> 8) & 0xff, \
-                                buf[(off) + 1] = (v) & 0xff)
-#define PUT_32BE(off, v)       (PUT_16BE((off), (v) >> 16), \
-                                PUT_16BE((off) + 2, (v)))
+#define PUT_16BE(b, off, v)    ((b)[off] = ((v) >> 8) & 0xff, \
+                                (b)[(off) + 1] = (v) & 0xff)
+#define PUT_32BE(b, off, v)    (PUT_16BE((b), (off), (v) >> 16), \
+                                PUT_16BE((b), (off) + 2, (v)))
 
 /* Structure of an ELF file */
 #define E_IDENT                0       /* ELF header */
@@ -88,15 +95,71 @@ unsigned char buf[512];
 
 unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
 
+unsigned char *read_rpanote(const char *fname, int *nnp)
+{
+       int notefd, nr, i;
+       int ph, ps, np;
+       int note, notesize;
+
+       notefd = open(fname, O_RDONLY);
+       if (notefd < 0) {
+               perror(fname);
+               exit(1);
+       }
+       nr = read(notefd, notebuf, sizeof(notebuf));
+       if (nr < 0) {
+               perror("read note");
+               exit(1);
+       }
+       if (nr == 0)            /* empty file */
+               return NULL;
+       if (nr < E_HSIZE ||
+           memcmp(&notebuf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0 ||
+           notebuf[E_IDENT+EI_CLASS] != ELFCLASS32 ||
+           notebuf[E_IDENT+EI_DATA] != ELFDATA2MSB)
+               goto notelf;
+       close(notefd);
+
+       /* now look for the RPA-note */
+       ph = GET_32BE(notebuf, E_PHOFF);
+       ps = GET_16BE(notebuf, E_PHENTSIZE);
+       np = GET_16BE(notebuf, E_PHNUM);
+       if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
+               goto notelf;
+
+       for (i = 0; i < np; ++i, ph += ps) {
+               if (GET_32BE(notebuf, ph + PH_TYPE) != PT_NOTE)
+                       continue;
+               note = GET_32BE(notebuf, ph + PH_OFFSET);
+               notesize = GET_32BE(notebuf, ph + PH_FILESZ);
+               if (notesize < 34 || note + notesize > nr)
+                       continue;
+               if (GET_32BE(notebuf, note) != strlen(rpaname) + 1 ||
+                   GET_32BE(notebuf, note + 8) != 0x12759999 ||
+                   strcmp((char *)&notebuf[note + 12], rpaname) != 0)
+                       continue;
+               /* looks like an RPA note, return it */
+               *nnp = notesize;
+               return &notebuf[note];
+       }
+       /* no RPA note found */
+       return NULL;
+
+ notelf:
+       fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", fname);
+       exit(1);
+}
+
 int
 main(int ac, char **av)
 {
        int fd, n, i;
        int ph, ps, np;
        int nnote, nnote2, ns;
+       unsigned char *rpap;
 
-       if (ac != 2) {
-               fprintf(stderr, "Usage: %s elf-file\n", av[0]);
+       if (ac != 2 && ac != 3) {
+               fprintf(stderr, "Usage: %s elf-file [rpanote.elf]\n", av[0]);
                exit(1);
        }
        fd = open(av[1], O_RDWR);
@@ -107,6 +170,7 @@ main(int ac, char **av)
 
        nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
        nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
+       rpap = NULL;
 
        n = read(fd, buf, sizeof(buf));
        if (n < 0) {
@@ -124,16 +188,19 @@ main(int ac, char **av)
                exit(1);
        }
 
-       ph = GET_32BE(E_PHOFF);
-       ps = GET_16BE(E_PHENTSIZE);
-       np = GET_16BE(E_PHNUM);
+       if (ac == 3)
+               rpap = read_rpanote(av[2], &nnote2);
+
+       ph = GET_32BE(buf, E_PHOFF);
+       ps = GET_16BE(buf, E_PHENTSIZE);
+       np = GET_16BE(buf, E_PHNUM);
        if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
                goto notelf;
        if (ph + (np + 2) * ps + nnote + nnote2 > n)
                goto nospace;
 
        for (i = 0; i < np; ++i) {
-               if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
+               if (GET_32BE(buf, ph + PH_TYPE) == PT_NOTE) {
                        fprintf(stderr, "%s already has a note entry\n",
                                av[1]);
                        exit(0);
@@ -148,37 +215,42 @@ main(int ac, char **av)
 
        /* fill in the program header entry */
        ns = ph + 2 * ps;
-       PUT_32BE(ph + PH_TYPE, PT_NOTE);
-       PUT_32BE(ph + PH_OFFSET, ns);
-       PUT_32BE(ph + PH_FILESZ, nnote);
+       PUT_32BE(buf, ph + PH_TYPE, PT_NOTE);
+       PUT_32BE(buf, ph + PH_OFFSET, ns);
+       PUT_32BE(buf, ph + PH_FILESZ, nnote);
 
        /* fill in the note area we point to */
        /* XXX we should probably make this a proper section */
-       PUT_32BE(ns, strlen(arch) + 1);
-       PUT_32BE(ns + 4, N_DESCR * 4);
-       PUT_32BE(ns + 8, 0x1275);
+       PUT_32BE(buf, ns, strlen(arch) + 1);
+       PUT_32BE(buf, ns + 4, N_DESCR * 4);
+       PUT_32BE(buf, ns + 8, 0x1275);
        strcpy((char *) &buf[ns + 12], arch);
        ns += 12 + strlen(arch) + 1;
        for (i = 0; i < N_DESCR; ++i, ns += 4)
-               PUT_32BE(ns, descr[i]);
+               PUT_32BE(buf, ns, descr[i]);
 
        /* fill in the second program header entry and the RPA note area */
        ph += ps;
-       PUT_32BE(ph + PH_TYPE, PT_NOTE);
-       PUT_32BE(ph + PH_OFFSET, ns);
-       PUT_32BE(ph + PH_FILESZ, nnote2);
+       PUT_32BE(buf, ph + PH_TYPE, PT_NOTE);
+       PUT_32BE(buf, ph + PH_OFFSET, ns);
+       PUT_32BE(buf, ph + PH_FILESZ, nnote2);
 
        /* fill in the note area we point to */
-       PUT_32BE(ns, strlen(rpaname) + 1);
-       PUT_32BE(ns + 4, sizeof(rpanote));
-       PUT_32BE(ns + 8, 0x12759999);
-       strcpy((char *) &buf[ns + 12], rpaname);
-       ns += 12 + ROUNDUP(strlen(rpaname) + 1);
-       for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
-               PUT_32BE(ns, rpanote[i]);
+       if (rpap) {
+               /* RPA note supplied in file, just copy the whole thing over */
+               memcpy(buf + ns, rpap, nnote2);
+       } else {
+               PUT_32BE(buf, ns, strlen(rpaname) + 1);
+               PUT_32BE(buf, ns + 4, sizeof(rpanote));
+               PUT_32BE(buf, ns + 8, 0x12759999);
+               strcpy((char *) &buf[ns + 12], rpaname);
+               ns += 12 + ROUNDUP(strlen(rpaname) + 1);
+               for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
+                       PUT_32BE(buf, ns, rpanote[i]);
+       }
 
        /* Update the number of program headers */
-       PUT_16BE(E_PHNUM, np + 2);
+       PUT_16BE(buf, E_PHNUM, np + 2);
 
        /* write back */
        lseek(fd, (long) 0, SEEK_SET);
index d607fdb8df8df8a2df1ecaef98b665e4355063b2..6ddf9ecac669861511d9dbbeed7b4b7b831d1883 100644 (file)
@@ -5,21 +5,5 @@
 #
 DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
        checks.c
-DTC_EXTRA = dtc.h srcpos.h
-DTC_LEXFILES = dtc-lexer.l
-DTC_BISONFILES = dtc-parser.y
-
-DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c)
-DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c)
-DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h)
-
-DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS)
-DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES)
+DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
 DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
-
-DTC_CLEANFILES = $(DTC_GEN_ALL)
-
-# We assume the containing Makefile system can do auto-dependencies for most
-# things, but we supply the dependencies on generated header files explicitly
-
-$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES))
index 2ce961cd414d71f71993b5a15fd3931cc69833a4..95485796f253ffb0d2c413e50acf650fe397aece 100644 (file)
@@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
 }
 NODE_CHECK(duplicate_property_names, NULL, ERROR);
 
+#define LOWERCASE      "abcdefghijklmnopqrstuvwxyz"
+#define UPPERCASE      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define DIGITS         "0123456789"
+#define PROPNODECHARS  LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+
+static void check_node_name_chars(struct check *c, struct node *dt,
+                                 struct node *node)
+{
+       int n = strspn(node->name, c->data);
+
+       if (n < strlen(node->name))
+               FAIL(c, "Bad character '%c' in node %s",
+                    node->name[n], node->fullpath);
+}
+NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+
+static void check_node_name_format(struct check *c, struct node *dt,
+                                  struct node *node)
+{
+       if (strchr(get_unitname(node), '@'))
+               FAIL(c, "Node %s has multiple '@' characters in name",
+                    node->fullpath);
+}
+NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+
+static void check_property_name_chars(struct check *c, struct node *dt,
+                                     struct node *node, struct property *prop)
+{
+       int n = strspn(prop->name, c->data);
+
+       if (n < strlen(prop->name))
+               FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
+                    prop->name[n], prop->name, node->fullpath);
+}
+PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+
 static void check_explicit_phandles(struct check *c, struct node *root,
                                          struct node *node)
 {
@@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR);
 static void check_name_properties(struct check *c, struct node *root,
                                  struct node *node)
 {
-       struct property *prop;
+       struct property **pp, *prop = NULL;
+
+       for (pp = &node->proplist; *pp; pp = &((*pp)->next))
+               if (streq((*pp)->name, "name")) {
+                       prop = *pp;
+                       break;
+               }
 
-       prop = get_property(node, "name");
        if (!prop)
                return; /* No name property, that's fine */
 
        if ((prop->val.len != node->basenamelen+1)
-           || (memcmp(prop->val.val, node->name, node->basenamelen) != 0))
+           || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
                FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
                     " of base node name)", node->fullpath, prop->val.val);
+       } else {
+               /* The name property is correct, and therefore redundant.
+                * Delete it */
+               *pp = prop->next;
+               free(prop->name);
+               data_free(prop->val);
+               free(prop);
+       }
 }
 CHECK_IS_STRING(name_is_string, "name", ERROR);
 NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
@@ -301,23 +350,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
 static void fixup_phandle_references(struct check *c, struct node *dt,
                                     struct node *node, struct property *prop)
 {
-      struct marker *m = prop->val.markers;
-      struct node *refnode;
-      cell_t phandle;
-
-      for_each_marker_of_type(m, REF_PHANDLE) {
-             assert(m->offset + sizeof(cell_t) <= prop->val.len);
-
-             refnode = get_node_by_ref(dt, m->ref);
-             if (! refnode) {
-                     FAIL(c, "Reference to non-existent node or label \"%s\"\n",
-                          m->ref);
-                     continue;
-             }
-
-             phandle = get_node_phandle(dt, refnode);
-             *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle);
-      }
+       struct marker *m = prop->val.markers;
+       struct node *refnode;
+       cell_t phandle;
+
+       for_each_marker_of_type(m, REF_PHANDLE) {
+               assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+               refnode = get_node_by_ref(dt, m->ref);
+               if (! refnode) {
+                       FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+                            m->ref);
+                       continue;
+               }
+
+               phandle = get_node_phandle(dt, refnode);
+               *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+       }
 }
 CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
       &duplicate_node_names, &explicit_phandles);
@@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
 
 static struct check *check_table[] = {
        &duplicate_node_names, &duplicate_property_names,
+       &node_name_chars, &node_name_format, &property_name_chars,
        &name_is_string, &name_properties,
        &explicit_phandles,
        &phandle_references, &path_references,
@@ -511,10 +561,7 @@ static struct check *check_table[] = {
        &obsolete_chosen_interrupt_controller,
 };
 
-int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
-
-void process_checks(int force, struct boot_info *bi,
-                   int checkflag, int outversion, int boot_cpuid_phys)
+void process_checks(int force, struct boot_info *bi)
 {
        struct node *dt = bi->dt;
        int i;
@@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi,
                                "output forced\n");
                }
        }
-
-       if (checkflag) {
-               if (error) {
-                       fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
-               } else {
-                       if (!check_semantics(bi->dt, outversion,
-                                            boot_cpuid_phys))
-                               fprintf(stderr, "Warning: Input tree has semantic errors\n");
-               }
-       }
-}
-
-/*
- * Semantic check functions
- */
-
-#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
-#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
-
-#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
-
-#define CHECK_HAVE(node, propname) \
-       do { \
-               if (! (prop = get_property((node), (propname)))) \
-                       DO_ERR("Missing \"%s\" property in %s\n", (propname), \
-                               (node)->fullpath); \
-       } while (0);
-
-#define CHECK_HAVE_WARN(node, propname) \
-       do { \
-               if (! (prop  = get_property((node), (propname)))) \
-                       WARNMSG("%s has no \"%s\" property\n", \
-                               (node)->fullpath, (propname)); \
-       } while (0)
-
-#define CHECK_HAVE_STRING(node, propname) \
-       do { \
-               CHECK_HAVE((node), (propname)); \
-               if (prop && !data_is_one_string(prop->val)) \
-                       DO_ERR("\"%s\" property in %s is not a string\n", \
-                               (propname), (node)->fullpath); \
-       } while (0)
-
-#define CHECK_HAVE_STREQ(node, propname, value) \
-       do { \
-               CHECK_HAVE_STRING((node), (propname)); \
-               if (prop && !streq(prop->val.val, (value))) \
-                       DO_ERR("%s has wrong %s, %s (should be %s\n", \
-                               (node)->fullpath, (propname), \
-                               prop->val.val, (value)); \
-       } while (0)
-
-#define CHECK_HAVE_ONECELL(node, propname) \
-       do { \
-               CHECK_HAVE((node), (propname)); \
-               if (prop && (prop->val.len != sizeof(cell_t))) \
-                       DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
-       } while (0)
-
-#define CHECK_HAVE_WARN_ONECELL(node, propname) \
-       do { \
-               CHECK_HAVE_WARN((node), (propname)); \
-               if (prop && (prop->val.len != sizeof(cell_t))) \
-                       DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
-       } while (0)
-
-#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
-       do { \
-               struct node *ref; \
-               CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
-               if (prop) {\
-                       cell_t phandle = propval_cell(prop); \
-                       if ((phandle == 0) || (phandle == -1)) { \
-                               DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
-                       } else { \
-                               ref = get_node_by_phandle((root), propval_cell(prop)); \
-                               if (! ref) \
-                                       DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
-                       } \
-               } \
-       } while (0)
-
-#define CHECK_HAVE_WARN_STRING(node, propname) \
-       do { \
-               CHECK_HAVE_WARN((node), (propname)); \
-               if (prop && !data_is_one_string(prop->val)) \
-                       DO_ERR("\"%s\" property in %s is not a string\n", \
-                               (propname), (node)->fullpath); \
-       } while (0)
-
-static int check_root(struct node *root)
-{
-       struct property *prop;
-       int ok = 1;
-
-       CHECK_HAVE_STRING(root, "model");
-       CHECK_HAVE_WARN(root, "compatible");
-
-       return ok;
-}
-
-static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
-{
-       struct node *cpus, *cpu;
-       struct property *prop;
-       struct node *bootcpu = NULL;
-       int ok = 1;
-
-       cpus = get_subnode(root, "cpus");
-       if (! cpus) {
-               ERRMSG("Missing /cpus node\n");
-               return 0;
-       }
-
-       if (cpus->addr_cells != 1)
-               DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
-                      cpus->fullpath, cpus->addr_cells);
-       if (cpus->size_cells != 0)
-               DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
-                      cpus->fullpath, cpus->size_cells);
-
-       for_each_child(cpus, cpu) {
-               CHECK_HAVE_STREQ(cpu, "device_type", "cpu");
-
-               CHECK_HAVE_ONECELL(cpu, "reg");
-               if (prop) {
-                       cell_t unitnum;
-                       char *eptr;
-
-                       unitnum = strtol(get_unitname(cpu), &eptr, 16);
-                       if (*eptr) {
-                               WARNMSG("%s has bad format unit name %s (should be CPU number\n",
-                                       cpu->fullpath, get_unitname(cpu));
-                       } else if (unitnum != propval_cell(prop)) {
-                               WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
-                                      cpu->fullpath, get_unitname(cpu),
-                                      propval_cell(prop));
-                       }
-               }
-
-/*             CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
-/*             CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
-               CHECK_HAVE_ONECELL(cpu, "d-cache-size");
-               CHECK_HAVE_ONECELL(cpu, "i-cache-size");
-
-               CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
-               CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");
-
-               prop = get_property(cpu, "linux,boot-cpu");
-               if (prop) {
-                       if (prop->val.len)
-                               WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
-                                       cpu->fullpath);
-                       if (bootcpu)
-                               DO_ERR("Multiple boot cpus (%s and %s)\n",
-                                      bootcpu->fullpath, cpu->fullpath);
-                       else
-                               bootcpu = cpu;
-               }
-       }
-
-       if (outversion < 2) {
-               if (! bootcpu)
-                       WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
-       } else {
-               if (bootcpu)
-                       WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
-               if (boot_cpuid_phys == 0xfeedbeef)
-                       WARNMSG("physical boot CPU not set.  Use -b option to set\n");
-       }
-
-       return ok;
-}
-
-static int check_memory(struct node *root)
-{
-       struct node *mem;
-       struct property *prop;
-       int nnodes = 0;
-       int ok = 1;
-
-       for_each_child(root, mem) {
-               if (! strneq(mem->name, "memory", mem->basenamelen))
-                       continue;
-
-               nnodes++;
-
-               CHECK_HAVE_STREQ(mem, "device_type", "memory");
-               CHECK_HAVE(mem, "reg");
-       }
-
-       if (nnodes == 0) {
-               ERRMSG("No memory nodes\n");
-               return 0;
-       }
-
-       return ok;
-}
-
-int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
-{
-       int ok = 1;
-
-       ok = ok && check_root(dt);
-       ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
-       ok = ok && check_memory(dt);
-       if (! ok)
-               return 0;
-
-       return 1;
 }
index a94718c731a95256d92e3ea1fbf63077aebd917a..dd2e3d39d4c1ba941f58c0e676cb52fc6bac93a4 100644 (file)
@@ -32,8 +32,6 @@ void data_free(struct data d)
                m = nm;
        }
 
-       assert(!d.val || d.asize);
-
        if (d.val)
                free(d.val);
 }
@@ -43,9 +41,6 @@ struct data data_grow_for(struct data d, int xlen)
        struct data nd;
        int newsize;
 
-       /* we must start with an allocated datum */
-       assert(!d.val || d.asize);
-
        if (xlen == 0)
                return d;
 
@@ -56,11 +51,8 @@ struct data data_grow_for(struct data d, int xlen)
        while ((d.len + xlen) > newsize)
                newsize *= 2;
 
-       nd.asize = newsize;
        nd.val = xrealloc(d.val, newsize);
 
-       assert(nd.asize >= (d.len + xlen));
-
        return nd;
 }
 
@@ -83,16 +75,11 @@ static char get_oct_char(const char *s, int *i)
        long val;
 
        x[3] = '\0';
-       x[0] = s[(*i)];
-       if (x[0]) {
-               x[1] = s[(*i)+1];
-               if (x[1])
-                       x[2] = s[(*i)+2];
-       }
+       strncpy(x, s + *i, 3);
 
        val = strtol(x, &endx, 8);
-       if ((endx - x) == 0)
-               fprintf(stderr, "Empty \\nnn escape\n");
+
+       assert(endx > x);
 
        (*i) += endx - x;
        return val;
@@ -105,13 +92,11 @@ static char get_hex_char(const char *s, int *i)
        long val;
 
        x[2] = '\0';
-       x[0] = s[(*i)];
-       if (x[0])
-               x[1] = s[(*i)+1];
+       strncpy(x, s + *i, 2);
 
        val = strtol(x, &endx, 16);
-       if ((endx - x) == 0)
-               fprintf(stderr, "Empty \\x escape\n");
+       if (!(endx  > x))
+               die("\\x used with no following hex digits\n");
 
        (*i) += endx - x;
        return val;
@@ -182,14 +167,29 @@ struct data data_copy_escape_string(const char *s, int len)
        return d;
 }
 
-struct data data_copy_file(FILE *f, size_t len)
+struct data data_copy_file(FILE *f, size_t maxlen)
 {
-       struct data d;
+       struct data d = empty_data;
 
-       d = data_grow_for(empty_data, len);
+       while (!feof(f) && (d.len < maxlen)) {
+               size_t chunksize, ret;
 
-       d.len = len;
-       fread(d.val, len, 1, f);
+               if (maxlen == -1)
+                       chunksize = 4096;
+               else
+                       chunksize = maxlen - d.len;
+
+               d = data_grow_for(d, chunksize);
+               ret = fread(d.val + d.len, 1, chunksize, f);
+
+               if (ferror(f))
+                       die("Error reading file into data: %s", strerror(errno));
+
+               if (d.len + ret < d.len)
+                       die("Overflow reading file into data\n");
+
+               d.len += ret;
+       }
 
        return d;
 }
@@ -247,7 +247,7 @@ struct data data_merge(struct data d1, struct data d2)
 
 struct data data_append_cell(struct data d, cell_t word)
 {
-       cell_t beword = cpu_to_be32(word);
+       cell_t beword = cpu_to_fdt32(word);
 
        return data_append_data(d, &beword, sizeof(beword));
 }
@@ -256,15 +256,15 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
 {
        struct fdt_reserve_entry bere;
 
-       bere.address = cpu_to_be64(re->address);
-       bere.size = cpu_to_be64(re->size);
+       bere.address = cpu_to_fdt64(re->address);
+       bere.size = cpu_to_fdt64(re->size);
 
        return data_append_data(d, &bere, sizeof(bere));
 }
 
-struct data data_append_addr(struct data d, u64 addr)
+struct data data_append_addr(struct data d, uint64_t addr)
 {
-       u64 beaddr = cpu_to_be64(addr);
+       uint64_t beaddr = cpu_to_fdt64(addr);
 
        return data_append_data(d, &beaddr, sizeof(beaddr));
 }
index c811b221b31e26ac827955918d53000ccf9e8ea6..44dbfd3f097650c139476571348655066a1006c2 100644 (file)
 PROPNODECHAR   [a-zA-Z0-9,._+*#?@-]
 PATHCHAR       ({PROPNODECHAR}|[/])
 LABEL          [a-zA-Z_][a-zA-Z0-9_]*
+STRING         \"([^\\"]|\\.)*\"
+WS             [[:space:]]
+COMMENT                "/*"([^*]|\*+[^*/])*\*+"/"
+LINECOMMENT    "//".*\n
 
 %{
 #include "dtc.h"
@@ -52,29 +56,26 @@ static int dts_version; /* = 0 */
                                DPRINT("<V1>\n"); \
                                BEGIN(V1); \
                        }
+
+static void push_input_file(const char *filename);
+static int pop_input_file(void);
 %}
 
 %%
-<*>"/include/"         BEGIN(INCLUDE);
-
-<INCLUDE>\"[^"\n]*\"   {
-                       yytext[strlen(yytext) - 1] = 0;
-                       if (!push_input_file(yytext + 1)) {
-                               /* Some unrecoverable error.*/
-                               exit(1);
-                       }
-                       BEGIN_DEFAULT();
+<*>"/include/"{WS}*{STRING} {
+                       char *name = strchr(yytext, '\"') + 1;
+                       yytext[yyleng-1] = '\0';
+                       push_input_file(name);
                }
 
-
 <*><<EOF>>             {
                        if (!pop_input_file()) {
                                yyterminate();
                        }
                }
 
-<*>\"([^\\"]|\\.)*\"   {
-                       yylloc.filenum = srcpos_filenum;
+<*>{STRING}    {
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -84,7 +85,7 @@ static int dts_version; /* = 0 */
                }
 
 <*>"/dts-v1/"  {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -93,7 +94,7 @@ static int dts_version; /* = 0 */
                }
 
 <*>"/memreserve/"      {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
@@ -101,7 +102,7 @@ static int dts_version; /* = 0 */
                }
 
 <*>{LABEL}:    {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = strdup(yytext);
@@ -110,7 +111,7 @@ static int dts_version; /* = 0 */
                }
 
 <INITIAL>[bodh]# {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        if (*yytext == 'b')
                                yylval.cbase = 2;
@@ -125,7 +126,7 @@ static int dts_version; /* = 0 */
                }
 
 <INITIAL>[0-9a-fA-F]+  {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.literal = strdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
@@ -133,7 +134,7 @@ static int dts_version; /* = 0 */
                }
 
 <V1>[0-9]+|0[xX][0-9a-fA-F]+      {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.literal = strdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
@@ -141,7 +142,7 @@ static int dts_version; /* = 0 */
                }
 
 \&{LABEL}      {       /* label reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = strdup(yytext+1);
@@ -149,7 +150,7 @@ static int dts_version; /* = 0 */
                }
 
 "&{/"{PATHCHAR}+\}     {       /* new-style path reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -158,7 +159,7 @@ static int dts_version; /* = 0 */
                }
 
 <INITIAL>"&/"{PATHCHAR}+ {     /* old-style path reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = strdup(yytext+1);
@@ -166,7 +167,7 @@ static int dts_version; /* = 0 */
                }
 
 <BYTESTRING>[0-9a-fA-F]{2} {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -174,7 +175,7 @@ static int dts_version; /* = 0 */
                }
 
 <BYTESTRING>"]"        {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
@@ -182,7 +183,7 @@ static int dts_version; /* = 0 */
                }
 
 <PROPNODENAME>{PROPNODECHAR}+ {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("PropNodeName: %s\n", yytext);
                        yylval.propnodename = strdup(yytext);
@@ -190,20 +191,19 @@ static int dts_version; /* = 0 */
                        return DT_PROPNODENAME;
                }
 
-
-<*>[[:space:]]+        /* eat whitespace */
-
-<*>"/*"([^*]|\*+[^*/])*\*+"/"  {
-                       yylloc.filenum = srcpos_filenum;
+"/incbin/"     {
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
-                       DPRINT("Comment: %s\n", yytext);
-                       /* eat comments */
+                       DPRINT("Binary Include\n");
+                       return DT_INCBIN;
                }
 
-<*>"//".*\n    /* eat line comments */
+<*>{WS}+       /* eat whitespace */
+<*>{COMMENT}+  /* eat C-style comments */
+<*>{LINECOMMENT}+ /* eat C++-style comments */
 
 <*>.           {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -227,14 +227,13 @@ static int dts_version; /* = 0 */
  */
 
 struct incl_file {
-       int filenum;
-       FILE *file;
+       struct dtc_file *file;
        YY_BUFFER_STATE yy_prev_buf;
        int yy_prev_lineno;
        struct incl_file *prev;
 };
 
-struct incl_file *incl_file_stack;
+static struct incl_file *incl_file_stack;
 
 
 /*
@@ -245,36 +244,34 @@ struct incl_file *incl_file_stack;
 static int incl_depth = 0;
 
 
-int push_input_file(const char *filename)
+static void push_input_file(const char *filename)
 {
-       FILE *f;
        struct incl_file *incl_file;
+       struct dtc_file *newfile;
+       struct search_path search, *searchptr = NULL;
 
-       if (!filename) {
-               yyerror("No include file name given.");
-               return 0;
-       }
+       assert(filename);
 
-       if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
-               yyerror("Includes nested too deeply");
-               return 0;
+       if (incl_depth++ >= MAX_INCLUDE_DEPTH)
+               die("Includes nested too deeply");
+
+       if (srcpos_file) {
+               search.dir = srcpos_file->dir;
+               search.next = NULL;
+               search.prev = NULL;
+               searchptr = &search;
        }
 
-       f = dtc_open_file(filename);
+       newfile = dtc_open_file(filename, searchptr);
 
-       incl_file = malloc(sizeof(struct incl_file));
-       if (!incl_file) {
-               yyerror("Can not allocate include file space.");
-               return 0;
-       }
+       incl_file = xmalloc(sizeof(struct incl_file));
 
        /*
         * Save current context.
         */
        incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
        incl_file->yy_prev_lineno = yylineno;
-       incl_file->filenum = srcpos_filenum;
-       incl_file->file = yyin;
+       incl_file->file = srcpos_file;
        incl_file->prev = incl_file_stack;
 
        incl_file_stack = incl_file;
@@ -282,23 +279,21 @@ int push_input_file(const char *filename)
        /*
         * Establish new context.
         */
-       srcpos_filenum = lookup_file_name(filename, 0);
+       srcpos_file = newfile;
        yylineno = 1;
-       yyin = f;
+       yyin = newfile->file;
        yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
-
-       return 1;
 }
 
 
-int pop_input_file(void)
+static int pop_input_file(void)
 {
        struct incl_file *incl_file;
 
        if (incl_file_stack == 0)
                return 0;
 
-       fclose(yyin);
+       dtc_close_file(srcpos_file);
 
        /*
         * Pop.
@@ -313,16 +308,13 @@ int pop_input_file(void)
        yy_delete_buffer(YY_CURRENT_BUFFER);
        yy_switch_to_buffer(incl_file->yy_prev_buf);
        yylineno = incl_file->yy_prev_lineno;
-       srcpos_filenum = incl_file->filenum;
-       yyin = incl_file->file;
+       srcpos_file = incl_file->file;
+       yyin = incl_file->file ? incl_file->file->file : NULL;
 
        /*
         * Free old state.
         */
        free(incl_file);
 
-       if (YY_CURRENT_BUFFER == 0)
-               return 0;
-
        return 1;
 }
index d0f742460f920ca503e938808d1dc129637a1ee6..ac392cb040f613bb62b508ea27e712283459c40f 100644 (file)
@@ -9,7 +9,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 33
+#define YY_FLEX_SUBMINOR_VERSION 34
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -31,7 +31,7 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
 /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
  * if you want the limit (max/min) macros for int types. 
@@ -94,11 +94,12 @@ typedef unsigned int flex_uint32_t;
 
 #else  /* ! __cplusplus */
 
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
 
 #define YY_USE_CONST
 
-#endif /* __STDC__ */
+#endif /* defined (__STDC__) */
 #endif /* ! __cplusplus */
 
 #ifdef YY_USE_CONST
@@ -194,11 +195,13 @@ extern FILE *yyin, *yyout;
 /* The following is because we cannot portably get our hands on size_t
  * (without autoconf's help, which isn't available because we want
  * flex-generated scanners to compile on their own).
+ * Given that the standard has decreed that size_t exists since 1989,
+ * I guess we can afford to depend on it. Manoj.
  */
 
 #ifndef YY_TYPEDEF_YY_SIZE_T
 #define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
+typedef size_t yy_size_t;
 #endif
 
 #ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -349,7 +352,7 @@ void yyfree (void *  );
 
 /* Begin user sect3 */
 
-#define yywrap() 1
+#define yywrap(n) 1
 #define YY_SKIP_YYWRAP
 
 typedef unsigned char YY_CHAR;
@@ -389,19 +392,20 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[94] =
+static yyconst flex_int16_t yy_accept[104] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       21,   19,   16,   16,   19,   19,   19,    8,    8,   19,
-        8,   19,   19,   19,   19,   14,   15,   15,   19,    9,
-        9,   16,    0,    3,    0,    0,   10,    0,    0,    0,
-        0,    0,    0,    8,    8,    6,    0,    7,    0,    2,
-        0,   13,   13,   15,   15,    9,    0,   12,   10,    0,
-        0,    0,    0,   18,    0,    0,    0,    2,    9,    0,
-       17,    0,    0,    0,   11,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    4,    0,    0,    1,    0,    0,
-        0,    5,    0
-
+       21,   19,   16,   16,   19,   19,   19,    7,    7,   19,
+        7,   19,   19,   19,   19,   13,   14,   14,   19,    8,
+        8,   16,    0,    2,    0,    0,    9,    0,    0,    0,
+        0,    0,    0,    7,    7,    5,    0,    6,    0,   12,
+       12,   14,   14,    8,    0,   11,    9,    0,    0,    0,
+        0,   18,    0,    0,    0,    0,    8,    0,   17,    0,
+        0,    0,    0,    0,   10,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    3,   15,
+        0,    0,    0,    0,    0,    0,    0,    0,    1,    0,
+
+        0,    4,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -444,122 +448,126 @@ static yyconst flex_int32_t yy_meta[36] =
         7,    7,    7,    8,    1
     } ;
 
-static yyconst flex_int16_t yy_base[107] =
+static yyconst flex_int16_t yy_base[117] =
     {   0,
-        0,    0,   32,    0,   53,    0,   76,    0,  108,  111,
-      280,  288,   37,   39,   33,   36,  106,    0,  123,  146,
-      255,  251,   45,    0,  159,  288,    0,   53,  108,  172,
-      114,  127,  158,  288,  245,    0,    0,  234,  235,  236,
-      197,  195,  199,    0,    0,  288,    0,  288,  160,  288,
-      183,  288,    0,    0,  183,  182,    0,    0,    0,    0,
-      204,  189,  207,  288,  179,  187,  180,  194,    0,  171,
-      288,  196,  178,  174,  288,  169,  169,  177,  165,  153,
-      143,  155,  137,  118,  288,  122,   42,  288,   36,   36,
-       40,  288,  288,  212,  218,  223,  229,  234,  239,  245,
-
-      251,  255,  262,  270,  275,  280
+        0,    0,   30,    0,   44,    0,   67,    0,   97,  105,
+      302,  303,   35,   44,   40,   94,  112,    0,  129,  152,
+      296,  295,  159,    0,  176,  303,    0,  116,   95,  165,
+       49,   46,  102,  303,  296,    0,    0,  288,  290,  293,
+      264,  266,  270,    0,    0,  303,    0,  303,  264,  303,
+        0,    0,  195,  101,    0,    0,    0,    0,  284,  125,
+      277,  265,  225,  230,  216,  218,    0,  202,  224,  221,
+      217,  107,  196,  188,  303,  206,  179,  186,  178,  185,
+      183,  162,  161,  150,  169,  160,  145,  125,  303,  303,
+      137,  109,  190,  103,  203,  167,  108,  197,  303,  123,
+
+       29,  303,  303,  215,  221,  226,  229,  234,  240,  246,
+      250,  257,  265,  270,  275,  282
     } ;
 
-static yyconst flex_int16_t yy_def[107] =
+static yyconst flex_int16_t yy_def[117] =
     {   0,
-       93,    1,    1,    3,    3,    5,   93,    7,    3,    3,
-       93,   93,   93,   93,   94,   95,   93,   96,   93,   19,
-       19,   20,   97,   98,   20,   93,   99,  100,   95,   93,
-       93,   93,   94,   93,   94,  101,  102,   93,  103,  104,
-       93,   93,   93,   96,   19,   93,   20,   93,   97,   93,
-       97,   93,   20,   99,  100,   93,  105,  101,  102,  106,
-      103,  103,  104,   93,   93,   93,   93,   94,  105,  106,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,    0,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   93
+      103,    1,    1,    3,    3,    5,  103,    7,    3,    3,
+      103,  103,  103,  103,  104,  105,  103,  106,  103,   19,
+       19,   20,  103,  107,   20,  103,  108,  109,  105,  103,
+      103,  103,  104,  103,  104,  110,  111,  103,  112,  113,
+      103,  103,  103,  106,   19,  103,   20,  103,  103,  103,
+       20,  108,  109,  103,  114,  110,  111,  115,  112,  112,
+      113,  103,  103,  103,  103,  103,  114,  115,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  116,  103,  116,  103,  116,
+
+      103,  103,    0,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103
     } ;
 
-static yyconst flex_int16_t yy_nxt[324] =
+static yyconst flex_int16_t yy_nxt[339] =
     {   0,
        12,   13,   14,   15,   12,   16,   12,   12,   12,   17,
        18,   18,   18,   12,   19,   20,   20,   12,   12,   21,
        19,   21,   19,   22,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   12,   12,   23,   34,   12,   32,   32,
-       32,   32,   12,   12,   12,   36,   20,   33,   50,   92,
-       35,   20,   20,   20,   20,   20,   15,   54,   91,   54,
-       54,   54,   51,   24,   24,   24,   46,   25,   90,   38,
-       89,   26,   25,   25,   25,   25,   12,   13,   14,   15,
-       27,   12,   27,   27,   27,   17,   27,   27,   27,   12,
-       28,   28,   28,   12,   12,   28,   28,   28,   28,   28,
-
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   12,
-       12,   15,   39,   29,   15,   40,   29,   93,   30,   31,
-       31,   30,   31,   31,   56,   56,   56,   41,   32,   32,
-       42,   88,   43,   45,   45,   45,   46,   45,   47,   47,
-       87,   38,   45,   45,   45,   45,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,   47,   47,   47,   47,   86,
-       47,   34,   33,   50,   85,   47,   47,   47,   47,   53,
-       53,   53,   84,   53,   83,   35,   82,   51,   53,   53,
-       53,   53,   56,   56,   56,   93,   68,   54,   57,   54,
-       54,   54,   56,   56,   56,   62,   46,   34,   71,   81,
-
-       80,   79,   78,   77,   76,   75,   74,   73,   72,   64,
-       62,   35,   33,   33,   33,   33,   33,   33,   33,   33,
-       37,   67,   66,   37,   37,   37,   44,   65,   44,   49,
-       49,   49,   49,   49,   49,   49,   49,   52,   64,   52,
-       54,   62,   54,   60,   54,   54,   55,   93,   55,   55,
-       55,   55,   58,   58,   58,   48,   58,   58,   59,   48,
-       59,   59,   61,   61,   61,   61,   61,   61,   61,   61,
-       63,   63,   63,   63,   63,   63,   63,   63,   69,   93,
-       69,   70,   70,   70,   93,   70,   70,   11,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93
+       20,   20,   20,   12,   12,   12,   32,   32,  102,   23,
+       12,   12,   12,   34,   20,   32,   32,   32,   32,   20,
+       20,   20,   20,   20,   24,   24,   24,   35,   25,   54,
+       54,   54,   26,   25,   25,   25,   25,   12,   13,   14,
+       15,   27,   12,   27,   27,   27,   23,   27,   27,   27,
+       12,   28,   28,   28,   12,   12,   28,   28,   28,   28,
+       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
+
+       12,   12,   29,   36,  103,   34,   17,   30,   31,   31,
+       29,   54,   54,   54,   17,   30,   31,   31,   39,   35,
+       52,   40,   52,   52,   52,  103,   78,   38,   38,   46,
+      101,   60,   79,   41,   69,   97,   42,   94,   43,   45,
+       45,   45,   46,   45,   47,   47,   93,   92,   45,   45,
+       45,   45,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   39,   47,   91,   40,   90,
+       99,   47,   47,   47,   47,   54,   54,   54,   89,   88,
+       41,   55,   87,   49,  100,   43,   51,   51,   51,   86,
+       51,   95,   95,   96,   85,   51,   51,   51,   51,   52,
+
+       99,   52,   52,   52,   95,   95,   96,   84,   46,   83,
+       82,   81,   39,   79,  100,   33,   33,   33,   33,   33,
+       33,   33,   33,   37,   80,   77,   37,   37,   37,   44,
+       40,   44,   50,   76,   50,   52,   75,   52,   74,   52,
+       52,   53,   73,   53,   53,   53,   53,   56,   56,   56,
+       72,   56,   56,   57,   71,   57,   57,   59,   59,   59,
+       59,   59,   59,   59,   59,   61,   61,   61,   61,   61,
+       61,   61,   61,   67,   70,   67,   68,   68,   68,   62,
+       68,   68,   98,   98,   98,   98,   98,   98,   98,   98,
+       60,   66,   65,   64,   63,   62,   60,   58,  103,   48,
+
+       48,  103,   11,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103
     } ;
 
-static yyconst flex_int16_t yy_chk[324] =
+static yyconst flex_int16_t yy_chk[339] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    3,   15,    3,   13,   13,
-       14,   14,    3,    3,    3,   16,    3,   23,   23,   91,
-       15,    3,    3,    3,    3,    3,    5,   28,   90,   28,
-       28,   28,   23,    5,    5,    5,   28,    5,   89,   16,
-       87,    5,    5,    5,    5,    5,    7,    7,    7,    7,
+        1,    1,    1,    1,    1,    3,   13,   13,  101,    3,
+        3,    3,    3,   15,    3,   14,   14,   32,   32,    3,
+        3,    3,    3,    3,    5,    5,    5,   15,    5,   31,
+       31,   31,    5,    5,    5,    5,    5,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    9,   17,    9,   10,   17,   10,   29,    9,    9,
-        9,   10,   10,   10,   31,   31,   31,   17,   32,   32,
-       17,   86,   17,   19,   19,   19,   19,   19,   19,   19,
-       84,   29,   19,   19,   19,   19,   19,   19,   19,   19,
-       19,   19,   19,   19,   19,   19,   20,   20,   20,   83,
-       20,   33,   49,   49,   82,   20,   20,   20,   20,   25,
-       25,   25,   81,   25,   80,   33,   79,   49,   25,   25,
-       25,   25,   30,   30,   30,   51,   51,   55,   30,   55,
-       55,   55,   56,   56,   56,   62,   55,   68,   62,   78,
-
-       77,   76,   74,   73,   72,   70,   67,   66,   65,   63,
-       61,   68,   94,   94,   94,   94,   94,   94,   94,   94,
-       95,   43,   42,   95,   95,   95,   96,   41,   96,   97,
-       97,   97,   97,   97,   97,   97,   97,   98,   40,   98,
-       99,   39,   99,   38,   99,   99,  100,   35,  100,  100,
-      100,  100,  101,  101,  101,   22,  101,  101,  102,   21,
-      102,  102,  103,  103,  103,  103,  103,  103,  103,  103,
-      104,  104,  104,  104,  104,  104,  104,  104,  105,   11,
-      105,  106,  106,  106,    0,  106,  106,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
-       93,   93,   93
+
+        7,    7,    9,   16,   29,   33,    9,    9,    9,    9,
+       10,   54,   54,   54,   10,   10,   10,   10,   17,   33,
+       28,   17,   28,   28,   28,  100,   72,   16,   29,   28,
+       97,   60,   72,   17,   60,   94,   17,   92,   17,   19,
+       19,   19,   19,   19,   19,   19,   91,   88,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   20,   20,   20,   23,   20,   87,   23,   86,
+       96,   20,   20,   20,   20,   30,   30,   30,   85,   84,
+       23,   30,   83,   23,   96,   23,   25,   25,   25,   82,
+       25,   93,   93,   93,   81,   25,   25,   25,   25,   53,
+
+       98,   53,   53,   53,   95,   95,   95,   80,   53,   79,
+       78,   77,   76,   74,   98,  104,  104,  104,  104,  104,
+      104,  104,  104,  105,   73,   71,  105,  105,  105,  106,
+       70,  106,  107,   69,  107,  108,   68,  108,   66,  108,
+      108,  109,   65,  109,  109,  109,  109,  110,  110,  110,
+       64,  110,  110,  111,   63,  111,  111,  112,  112,  112,
+      112,  112,  112,  112,  112,  113,  113,  113,  113,  113,
+      113,  113,  113,  114,   62,  114,  115,  115,  115,   61,
+      115,  115,  116,  116,  116,  116,  116,  116,  116,  116,
+       59,   49,   43,   42,   41,   40,   39,   38,   35,   22,
+
+       21,   11,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103
     } ;
 
 /* Table of booleans, true if rule could match eol. */
 static yyconst flex_int32_t yy_rule_can_match_eol[21] =
     {   0,
-0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 
+1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 
     0,     };
 
 static yy_state_type yy_last_accepting_state;
@@ -600,7 +608,7 @@ char *yytext;
 
 
 
-#line 33 "dtc-lexer.l"
+#line 37 "dtc-lexer.l"
 #include "dtc.h"
 #include "srcpos.h"
 #include "dtc-parser.tab.h"
@@ -623,7 +631,10 @@ static int dts_version; /* = 0 */
                                DPRINT("<V1>\n"); \
                                BEGIN(V1); \
                        }
-#line 627 "dtc-lexer.lex.c"
+
+static void push_input_file(const char *filename);
+static int pop_input_file(void);
+#line 638 "dtc-lexer.lex.c"
 
 #define INITIAL 0
 #define INCLUDE 1
@@ -685,7 +696,7 @@ static int input (void );
 /* This used to be an fputs(), but since the string might contain NUL's,
  * we now use fwrite().
  */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
 #endif
 
 /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
@@ -696,7 +707,7 @@ static int input (void );
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
                { \
                int c = '*'; \
-               size_t n; \
+               int n; \
                for ( n = 0; n < max_size && \
                             (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
                        buf[n] = (char) c; \
@@ -778,9 +789,9 @@ YY_DECL
        register char *yy_cp, *yy_bp;
        register int yy_act;
     
-#line 57 "dtc-lexer.l"
+#line 64 "dtc-lexer.l"
 
-#line 784 "dtc-lexer.lex.c"
+#line 795 "dtc-lexer.lex.c"
 
        if ( !(yy_init) )
                {
@@ -833,13 +844,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 94 )
+                               if ( yy_current_state >= 104 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 288 );
+               while ( yy_base[yy_current_state] != 303 );
 
 yy_find_action:
                yy_act = yy_accept[yy_current_state];
@@ -874,20 +885,13 @@ do_action:        /* This label is used only to access EOF actions. */
                        goto yy_find_action;
 
 case 1:
+/* rule 1 can match eol */
 YY_RULE_SETUP
-#line 58 "dtc-lexer.l"
-BEGIN(INCLUDE);
-       YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 60 "dtc-lexer.l"
+#line 65 "dtc-lexer.l"
 {
-                       yytext[strlen(yytext) - 1] = 0;
-                       if (!push_input_file(yytext + 1)) {
-                               /* Some unrecoverable error.*/
-                               exit(1);
-                       }
-                       BEGIN_DEFAULT();
+                       char *name = strchr(yytext, '\"') + 1;
+                       yytext[yyleng-1] = '\0';
+                       push_input_file(name);
                }
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
@@ -895,19 +899,19 @@ case YY_STATE_EOF(INCLUDE):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 70 "dtc-lexer.l"
+#line 71 "dtc-lexer.l"
 {
                        if (!pop_input_file()) {
                                yyterminate();
                        }
                }
        YY_BREAK
-case 3:
-/* rule 3 can match eol */
+case 2:
+/* rule 2 can match eol */
 YY_RULE_SETUP
-#line 76 "dtc-lexer.l"
+#line 77 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -916,11 +920,11 @@ YY_RULE_SETUP
                        return DT_STRING;
                }
        YY_BREAK
-case 4:
+case 3:
 YY_RULE_SETUP
-#line 86 "dtc-lexer.l"
+#line 87 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -928,22 +932,22 @@ YY_RULE_SETUP
                        return DT_V1;
                }
        YY_BREAK
-case 5:
+case 4:
 YY_RULE_SETUP
-#line 95 "dtc-lexer.l"
+#line 96 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
                        return DT_MEMRESERVE;
                }
        YY_BREAK
-case 6:
+case 5:
 YY_RULE_SETUP
-#line 103 "dtc-lexer.l"
+#line 104 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = strdup(yytext);
@@ -951,11 +955,11 @@ YY_RULE_SETUP
                        return DT_LABEL;
                }
        YY_BREAK
-case 7:
+case 6:
 YY_RULE_SETUP
-#line 112 "dtc-lexer.l"
+#line 113 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        if (*yytext == 'b')
                                yylval.cbase = 2;
@@ -969,44 +973,44 @@ YY_RULE_SETUP
                        return DT_BASE;
                }
        YY_BREAK
-case 8:
+case 7:
 YY_RULE_SETUP
-#line 127 "dtc-lexer.l"
+#line 128 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.literal = strdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
                        return DT_LEGACYLITERAL;
                }
        YY_BREAK
-case 9:
+case 8:
 YY_RULE_SETUP
-#line 135 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.literal = strdup(yytext);
                        DPRINT("Literal: '%s'\n", yylval.literal);
                        return DT_LITERAL;
                }
        YY_BREAK
-case 10:
+case 9:
 YY_RULE_SETUP
-#line 143 "dtc-lexer.l"
+#line 144 "dtc-lexer.l"
 {      /* label reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = strdup(yytext+1);
                        return DT_REF;
                }
        YY_BREAK
-case 11:
+case 10:
 YY_RULE_SETUP
-#line 151 "dtc-lexer.l"
+#line 152 "dtc-lexer.l"
 {      /* new-style path reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -1014,44 +1018,44 @@ YY_RULE_SETUP
                        return DT_REF;
                }
        YY_BREAK
-case 12:
+case 11:
 YY_RULE_SETUP
-#line 160 "dtc-lexer.l"
+#line 161 "dtc-lexer.l"
 {      /* old-style path reference */
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = strdup(yytext+1);
                        return DT_REF;
                }
        YY_BREAK
-case 13:
+case 12:
 YY_RULE_SETUP
-#line 168 "dtc-lexer.l"
+#line 169 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
                        return DT_BYTE;
                }
        YY_BREAK
-case 14:
+case 13:
 YY_RULE_SETUP
-#line 176 "dtc-lexer.l"
+#line 177 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
                        return ']';
                }
        YY_BREAK
-case 15:
+case 14:
 YY_RULE_SETUP
-#line 184 "dtc-lexer.l"
+#line 185 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("PropNodeName: %s\n", yytext);
                        yylval.propnodename = strdup(yytext);
@@ -1059,34 +1063,39 @@ YY_RULE_SETUP
                        return DT_PROPNODENAME;
                }
        YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
+{
+                       yylloc.file = srcpos_file;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Binary Include\n");
+                       return DT_INCBIN;
+               }
+       YY_BREAK
 case 16:
 /* rule 16 can match eol */
 YY_RULE_SETUP
-#line 194 "dtc-lexer.l"
+#line 201 "dtc-lexer.l"
 /* eat whitespace */
        YY_BREAK
 case 17:
 /* rule 17 can match eol */
 YY_RULE_SETUP
-#line 196 "dtc-lexer.l"
-{
-                       yylloc.filenum = srcpos_filenum;
-                       yylloc.first_line = yylineno;
-                       DPRINT("Comment: %s\n", yytext);
-                       /* eat comments */
-               }
+#line 202 "dtc-lexer.l"
+/* eat C-style comments */
        YY_BREAK
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
 #line 203 "dtc-lexer.l"
-/* eat line comments */
+/* eat C++-style comments */
        YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 205 "dtc-lexer.l"
 {
-                       yylloc.filenum = srcpos_filenum;
+                       yylloc.file = srcpos_file;
                        yylloc.first_line = yylineno;
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -1107,7 +1116,7 @@ YY_RULE_SETUP
 #line 222 "dtc-lexer.l"
 ECHO;
        YY_BREAK
-#line 1111 "dtc-lexer.lex.c"
+#line 1120 "dtc-lexer.lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -1360,6 +1369,14 @@ static int yy_get_next_buffer (void)
        else
                ret_val = EOB_ACT_CONTINUE_SCAN;
 
+       if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+       }
+
        (yy_n_chars) += number_to_move;
        YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
        YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1389,7 +1406,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 94 )
+                       if ( yy_current_state >= 104 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1417,11 +1434,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 94 )
+               if ( yy_current_state >= 104 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 93);
+       yy_is_jam = (yy_current_state == 103);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -1743,7 +1760,9 @@ static void yyensure_buffer_stack (void)
                (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
                                                                (num_to_alloc * sizeof(struct yy_buffer_state*)
                                                                );
-               
+               if ( ! (yy_buffer_stack) )
+                       YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+                                                                 
                memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
                                
                (yy_buffer_stack_max) = num_to_alloc;
@@ -1761,6 +1780,8 @@ static void yyensure_buffer_stack (void)
                                                                ((yy_buffer_stack),
                                                                num_to_alloc * sizeof(struct yy_buffer_state*)
                                                                );
+               if ( ! (yy_buffer_stack) )
+                       YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
                /* zero only the new slots.*/
                memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -2072,14 +2093,13 @@ void yyfree (void * ptr )
  */
 
 struct incl_file {
-       int filenum;
-       FILE *file;
+       struct dtc_file *file;
        YY_BUFFER_STATE yy_prev_buf;
        int yy_prev_lineno;
        struct incl_file *prev;
 };
 
-struct incl_file *incl_file_stack;
+static struct incl_file *incl_file_stack;
 
 
 /*
@@ -2090,36 +2110,34 @@ struct incl_file *incl_file_stack;
 static int incl_depth = 0;
 
 
-int push_input_file(const char *filename)
+static void push_input_file(const char *filename)
 {
-       FILE *f;
        struct incl_file *incl_file;
+       struct dtc_file *newfile;
+       struct search_path search, *searchptr = NULL;
 
-       if (!filename) {
-               yyerror("No include file name given.");
-               return 0;
-       }
+       assert(filename);
 
-       if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
-               yyerror("Includes nested too deeply");
-               return 0;
+       if (incl_depth++ >= MAX_INCLUDE_DEPTH)
+               die("Includes nested too deeply");
+
+       if (srcpos_file) {
+               search.dir = srcpos_file->dir;
+               search.next = NULL;
+               search.prev = NULL;
+               searchptr = &search;
        }
 
-       f = dtc_open_file(filename);
+       newfile = dtc_open_file(filename, searchptr);
 
-       incl_file = malloc(sizeof(struct incl_file));
-       if (!incl_file) {
-               yyerror("Can not allocate include file space.");
-               return 0;
-       }
+       incl_file = xmalloc(sizeof(struct incl_file));
 
        /*
         * Save current context.
         */
        incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
        incl_file->yy_prev_lineno = yylineno;
-       incl_file->filenum = srcpos_filenum;
-       incl_file->file = yyin;
+       incl_file->file = srcpos_file;
        incl_file->prev = incl_file_stack;
 
        incl_file_stack = incl_file;
@@ -2127,23 +2145,21 @@ int push_input_file(const char *filename)
        /*
         * Establish new context.
         */
-       srcpos_filenum = lookup_file_name(filename, 0);
+       srcpos_file = newfile;
        yylineno = 1;
-       yyin = f;
+       yyin = newfile->file;
        yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
-
-       return 1;
 }
 
 
-int pop_input_file(void)
+static int pop_input_file(void)
 {
        struct incl_file *incl_file;
 
        if (incl_file_stack == 0)
                return 0;
 
-       fclose(yyin);
+       dtc_close_file(srcpos_file);
 
        /*
         * Pop.
@@ -2158,17 +2174,14 @@ int pop_input_file(void)
        yy_delete_buffer(YY_CURRENT_BUFFER);
        yy_switch_to_buffer(incl_file->yy_prev_buf);
        yylineno = incl_file->yy_prev_lineno;
-       srcpos_filenum = incl_file->filenum;
-       yyin = incl_file->file;
+       srcpos_file = incl_file->file;
+       yyin = incl_file->file ? incl_file->file->file : NULL;
 
        /*
         * Free old state.
         */
        free(incl_file);
 
-       if (YY_CURRENT_BUFFER == 0)
-               return 0;
-
        return 1;
 }
 
index 28e6ec0296a1598cea08fba484fbbc022158f6ad..27129377e5d217dce3ca2a4501f9c36a6b181071 100644 (file)
@@ -75,7 +75,8 @@
      DT_BYTE = 264,
      DT_STRING = 265,
      DT_LABEL = 266,
-     DT_REF = 267
+     DT_REF = 267,
+     DT_INCBIN = 268
    };
 #endif
 /* Tokens.  */
@@ -89,6 +90,7 @@
 #define DT_STRING 265
 #define DT_LABEL 266
 #define DT_REF 267
+#define DT_INCBIN 268
 
 
 
 /* Copy the first part of user declarations.  */
 #line 23 "dtc-parser.y"
 
+#include <stdio.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
-int yylex(void);
-unsigned long long eval_literal(const char *s, int base, int bits);
+extern int yylex(void);
 
 extern struct boot_info *the_boot_info;
+extern int treesource_error;
 
+static unsigned long long eval_literal(const char *s, int base, int bits);
 
 
 /* Enabling traces.  */
@@ -126,16 +131,16 @@ extern struct boot_info *the_boot_info;
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 34 "dtc-parser.y"
+#line 37 "dtc-parser.y"
 {
        char *propnodename;
        char *literal;
        char *labelref;
        unsigned int cbase;
-       u8 byte;
+       uint8_t byte;
        struct data data;
 
-       u64 addr;
+       uint64_t addr;
        cell_t cell;
        struct property *prop;
        struct property *proplist;
@@ -144,7 +149,7 @@ typedef union YYSTYPE
        struct reserve_info *re;
 }
 /* Line 187 of yacc.c.  */
-#line 148 "dtc-parser.tab.c"
+#line 153 "dtc-parser.tab.c"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -169,7 +174,7 @@ typedef struct YYLTYPE
 
 
 /* Line 216 of yacc.c.  */
-#line 173 "dtc-parser.tab.c"
+#line 178 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -386,20 +391,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  9
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   60
+#define YYLAST   73
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  24
+#define YYNTOKENS  27
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  20
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  43
+#define YYNRULES  45
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  67
+#define YYNSTATES  76
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   267
+#define YYMAXUTOK   268
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -411,15 +416,15 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,    23,    14,     2,    15,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
-      19,    18,    20,     2,     2,     2,     2,     2,     2,     2,
+      24,    26,     2,     2,    25,    15,     2,    16,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    14,
+      20,    19,    21,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    21,     2,    22,     2,     2,     2,     2,     2,     2,
+       2,    22,     2,    23,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    16,     2,    17,     2,     2,     2,     2,
+       2,     2,     2,    17,     2,    18,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -433,7 +438,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12
+       5,     6,     7,     8,     9,    10,    11,    12,    13
 };
 
 #if YYDEBUG
@@ -443,37 +448,39 @@ static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     8,    11,    12,    15,    21,    22,    25,
       27,    34,    36,    38,    41,    47,    48,    51,    57,    61,
-      64,    69,    74,    77,    80,    81,    84,    87,    88,    91,
-      94,    97,    98,   100,   102,   105,   106,   109,   112,   113,
-     116,   119,   123,   124
+      64,    69,    74,    77,    87,    93,    96,    97,   100,   103,
+     104,   107,   110,   113,   114,   116,   118,   121,   122,   125,
+     128,   129,   132,   135,   139,   140
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      25,     0,    -1,     3,    13,    26,    31,    -1,    28,    31,
-      -1,    -1,    27,    26,    -1,    43,     4,    30,    30,    13,
-      -1,    -1,    29,    28,    -1,    27,    -1,    43,     4,    30,
-      14,    30,    13,    -1,     6,    -1,     7,    -1,    15,    32,
-      -1,    16,    33,    41,    17,    13,    -1,    -1,    33,    34,
-      -1,    43,     5,    18,    35,    13,    -1,    43,     5,    13,
-      -1,    36,    10,    -1,    36,    19,    37,    20,    -1,    36,
-      21,    40,    22,    -1,    36,    12,    -1,    35,    11,    -1,
-      -1,    35,    23,    -1,    36,    11,    -1,    -1,    37,    39,
-      -1,    37,    12,    -1,    37,    11,    -1,    -1,     8,    -1,
-       6,    -1,    38,     7,    -1,    -1,    40,     9,    -1,    40,
-      11,    -1,    -1,    42,    41,    -1,    42,    34,    -1,    43,
-       5,    32,    -1,    -1,    11,    -1
+      28,     0,    -1,     3,    14,    29,    34,    -1,    31,    34,
+      -1,    -1,    30,    29,    -1,    46,     4,    33,    33,    14,
+      -1,    -1,    32,    31,    -1,    30,    -1,    46,     4,    33,
+      15,    33,    14,    -1,     6,    -1,     7,    -1,    16,    35,
+      -1,    17,    36,    44,    18,    14,    -1,    -1,    36,    37,
+      -1,    46,     5,    19,    38,    14,    -1,    46,     5,    14,
+      -1,    39,    10,    -1,    39,    20,    40,    21,    -1,    39,
+      22,    43,    23,    -1,    39,    12,    -1,    39,    13,    24,
+      10,    25,    33,    25,    33,    26,    -1,    39,    13,    24,
+      10,    26,    -1,    38,    11,    -1,    -1,    38,    25,    -1,
+      39,    11,    -1,    -1,    40,    42,    -1,    40,    12,    -1,
+      40,    11,    -1,    -1,     8,    -1,     6,    -1,    41,     7,
+      -1,    -1,    43,     9,    -1,    43,    11,    -1,    -1,    45,
+      44,    -1,    45,    37,    -1,    46,     5,    35,    -1,    -1,
+      11,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    85,    85,    89,    97,   100,   107,   115,   118,   125,
-     129,   136,   140,   147,   154,   162,   165,   172,   176,   183,
-     187,   191,   195,   199,   207,   210,   214,   222,   225,   229,
-     234,   242,   245,   249,   253,   261,   264,   268,   276,   279,
-     283,   291,   299,   302
+       0,    89,    89,    93,   101,   104,   111,   119,   122,   129,
+     133,   140,   144,   151,   158,   166,   169,   176,   180,   187,
+     191,   195,   199,   203,   220,   231,   239,   242,   246,   254,
+     257,   261,   266,   274,   277,   281,   285,   293,   296,   300,
+     308,   311,   315,   323,   331,   334
 };
 #endif
 
@@ -484,12 +491,12 @@ static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
   "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
-  "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "';'", "'-'", "'/'", "'{'",
-  "'}'", "'='", "'<'", "'>'", "'['", "']'", "','", "$accept", "sourcefile",
-  "memreserves", "memreserve", "v0_memreserves", "v0_memreserve", "addr",
-  "devicetree", "nodedef", "proplist", "propdef", "propdata",
-  "propdataprefix", "celllist", "cellbase", "cellval", "bytestring",
-  "subnodes", "subnode", "label", 0
+  "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'-'",
+  "'/'", "'{'", "'}'", "'='", "'<'", "'>'", "'['", "']'", "'('", "','",
+  "')'", "$accept", "sourcefile", "memreserves", "memreserve",
+  "v0_memreserves", "v0_memreserve", "addr", "devicetree", "nodedef",
+  "proplist", "propdef", "propdata", "propdataprefix", "celllist",
+  "cellbase", "cellval", "bytestring", "subnodes", "subnode", "label", 0
 };
 #endif
 
@@ -499,19 +506,19 @@ static const char *const yytname[] =
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,    59,    45,    47,   123,   125,    61,    60,
-      62,    91,    93,    44
+     265,   266,   267,   268,    59,    45,    47,   123,   125,    61,
+      60,    62,    91,    93,    40,    44,    41
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    24,    25,    25,    26,    26,    27,    28,    28,    29,
-      29,    30,    30,    31,    32,    33,    33,    34,    34,    35,
-      35,    35,    35,    35,    36,    36,    36,    37,    37,    37,
-      37,    38,    38,    39,    39,    40,    40,    40,    41,    41,
-      41,    42,    43,    43
+       0,    27,    28,    28,    29,    29,    30,    31,    31,    32,
+      32,    33,    33,    34,    35,    36,    36,    37,    37,    38,
+      38,    38,    38,    38,    38,    38,    39,    39,    39,    40,
+      40,    40,    40,    41,    41,    42,    42,    43,    43,    43,
+      44,    44,    44,    45,    46,    46
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -519,9 +526,9 @@ static const yytype_uint8 yyr2[] =
 {
        0,     2,     4,     2,     0,     2,     5,     0,     2,     1,
        6,     1,     1,     2,     5,     0,     2,     5,     3,     2,
-       4,     4,     2,     2,     0,     2,     2,     0,     2,     2,
-       2,     0,     1,     1,     2,     0,     2,     2,     0,     2,
-       2,     3,     0,     1
+       4,     4,     2,     9,     5,     2,     0,     2,     2,     0,
+       2,     2,     2,     0,     1,     1,     2,     0,     2,     2,
+       0,     2,     2,     3,     0,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -529,81 +536,86 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       7,     0,    43,     0,     9,     0,     7,     0,     4,     1,
+       7,     0,    45,     0,     9,     0,     7,     0,     4,     1,
        0,     3,     8,     0,     0,     4,     0,    15,    13,    11,
-      12,     0,     2,     5,     0,    38,     0,     0,     0,    16,
-       0,    38,     0,     0,     6,     0,    40,    39,     0,    10,
-      14,    18,    24,    41,     0,     0,    23,    17,    25,    19,
-      26,    22,    27,    35,    31,     0,    33,    32,    30,    29,
-      20,     0,    28,    36,    37,    21,    34
+      12,     0,     2,     5,     0,    40,     0,     0,     0,    16,
+       0,    40,     0,     0,     6,     0,    42,    41,     0,    10,
+      14,    18,    26,    43,     0,     0,    25,    17,    27,    19,
+      28,    22,     0,    29,    37,     0,    33,     0,     0,    35,
+      34,    32,    31,    20,     0,    30,    38,    39,    21,     0,
+      24,    36,     0,     0,     0,    23
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
       -1,     3,    14,     4,     5,     6,    27,    11,    18,    25,
-      29,    44,    45,    54,    61,    62,    55,    30,    31,     7
+      29,    44,    45,    56,    64,    65,    57,    30,    31,     7
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -13
+#define YYPACT_NINF -14
 static const yytype_int8 yypact[] =
 {
-      23,    11,   -13,    37,   -13,    -4,    18,    39,    18,   -13,
-      28,   -13,   -13,    34,    -4,    18,    41,   -13,   -13,   -13,
-     -13,    25,   -13,   -13,    34,    -3,    34,    33,    34,   -13,
-      30,    -3,    43,    36,   -13,    38,   -13,   -13,    20,   -13,
-     -13,   -13,   -13,   -13,     2,     9,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,    -2,    -6,   -13,   -13,   -13,   -13,
-     -13,    45,   -13,   -13,   -13,   -13,   -13
+      30,   -11,   -14,     7,   -14,    -1,    27,    13,    27,   -14,
+       8,   -14,   -14,    40,    -1,    27,    35,   -14,   -14,   -14,
+     -14,    21,   -14,   -14,    40,    24,    40,    28,    40,   -14,
+      32,    24,    46,    38,   -14,    39,   -14,   -14,    26,   -14,
+     -14,   -14,   -14,   -14,    -9,    10,   -14,   -14,   -14,   -14,
+     -14,   -14,    31,   -14,   -14,    44,    -2,     3,    23,   -14,
+     -14,   -14,   -14,   -14,    50,   -14,   -14,   -14,   -14,    40,
+     -14,   -14,    33,    40,    36,   -14
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -13,   -13,    35,    27,    47,   -13,   -12,    40,    17,   -13,
-      26,   -13,   -13,   -13,   -13,   -13,   -13,    29,   -13,    -8
+     -14,   -14,    48,    29,    53,   -14,   -13,    47,    34,   -14,
+      37,   -14,   -14,   -14,   -14,   -14,   -14,    42,   -14,    -7
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -43
+#define YYTABLE_NINF -45
 static const yytype_int8 yytable[] =
 {
-      16,    21,   -42,    63,    56,    64,    57,    16,     2,    58,
-      59,    10,    28,    46,    33,    47,    65,    32,    60,    49,
-      50,    51,   -42,    32,     8,    48,     1,   -42,    52,     2,
-      53,    19,    20,    41,     2,    15,    17,     9,    42,    26,
-      19,    20,    15,    13,    17,    24,    34,    35,    38,    39,
-      23,    40,    66,    12,    22,    43,     0,    36,     0,     0,
-      37
+      21,    16,    46,     8,    59,    47,    60,     9,    16,    61,
+      62,    28,    66,    33,    67,    10,    48,    13,    32,    63,
+      49,    50,    51,    52,    32,    17,    68,    19,    20,   -44,
+      53,   -44,    54,     1,   -44,     2,    26,    15,     2,    24,
+      41,     2,    34,    17,    15,    42,    19,    20,    69,    70,
+      35,    38,    39,    40,    58,    55,    72,    71,    73,    12,
+      74,    22,    75,    23,     0,     0,     0,     0,    36,     0,
+       0,     0,    43,    37
 };
 
 static const yytype_int8 yycheck[] =
 {
-       8,    13,     5,     9,     6,    11,     8,    15,    11,    11,
-      12,    15,    24,    11,    26,    13,    22,    25,    20,    10,
-      11,    12,     4,    31,    13,    23,     3,     4,    19,    11,
-      21,     6,     7,    13,    11,     8,    16,     0,    18,    14,
-       6,     7,    15,     4,    16,     4,    13,    17,     5,    13,
-      15,    13,     7,     6,    14,    38,    -1,    31,    -1,    -1,
-      31
+      13,     8,    11,    14,     6,    14,     8,     0,    15,    11,
+      12,    24,     9,    26,    11,    16,    25,     4,    25,    21,
+      10,    11,    12,    13,    31,    17,    23,     6,     7,     5,
+      20,     4,    22,     3,     4,    11,    15,     8,    11,     4,
+      14,    11,    14,    17,    15,    19,     6,     7,    25,    26,
+      18,     5,    14,    14,    10,    24,    69,     7,    25,     6,
+      73,    14,    26,    15,    -1,    -1,    -1,    -1,    31,    -1,
+      -1,    -1,    38,    31
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    11,    25,    27,    28,    29,    43,    13,     0,
-      15,    31,    28,     4,    26,    27,    43,    16,    32,     6,
-       7,    30,    31,    26,     4,    33,    14,    30,    30,    34,
-      41,    42,    43,    30,    13,    17,    34,    41,     5,    13,
-      13,    13,    18,    32,    35,    36,    11,    13,    23,    10,
-      11,    12,    19,    21,    37,    40,     6,     8,    11,    12,
-      20,    38,    39,     9,    11,    22,     7
+       0,     3,    11,    28,    30,    31,    32,    46,    14,     0,
+      16,    34,    31,     4,    29,    30,    46,    17,    35,     6,
+       7,    33,    34,    29,     4,    36,    15,    33,    33,    37,
+      44,    45,    46,    33,    14,    18,    37,    44,     5,    14,
+      14,    14,    19,    35,    38,    39,    11,    14,    25,    10,
+      11,    12,    13,    20,    22,    24,    40,    43,    10,     6,
+       8,    11,    12,    21,    41,    42,     9,    11,    23,    25,
+      26,     7,    33,    25,    33,    26
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1440,289 +1452,323 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 86 "dtc-parser.y"
+#line 90 "dtc-parser.y"
     {
-                       the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node));
+                       the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), 0);
                ;}
     break;
 
   case 3:
-#line 90 "dtc-parser.y"
+#line 94 "dtc-parser.y"
     {
-                       the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node));
+                       the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node), 0);
                ;}
     break;
 
   case 4:
-#line 97 "dtc-parser.y"
+#line 101 "dtc-parser.y"
     {
                        (yyval.re) = NULL;
                ;}
     break;
 
   case 5:
-#line 101 "dtc-parser.y"
+#line 105 "dtc-parser.y"
     {
                        (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
                ;}
     break;
 
   case 6:
-#line 108 "dtc-parser.y"
+#line 112 "dtc-parser.y"
     {
                        (yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
                ;}
     break;
 
   case 7:
-#line 115 "dtc-parser.y"
+#line 119 "dtc-parser.y"
     {
                        (yyval.re) = NULL;
                ;}
     break;
 
   case 8:
-#line 119 "dtc-parser.y"
+#line 123 "dtc-parser.y"
     {
                        (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
                ;}
     break;
 
   case 9:
-#line 126 "dtc-parser.y"
+#line 130 "dtc-parser.y"
     {
                        (yyval.re) = (yyvsp[(1) - (1)].re);
                ;}
     break;
 
   case 10:
-#line 130 "dtc-parser.y"
+#line 134 "dtc-parser.y"
     {
                        (yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
                ;}
     break;
 
   case 11:
-#line 137 "dtc-parser.y"
+#line 141 "dtc-parser.y"
     {
                        (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
                ;}
     break;
 
   case 12:
-#line 141 "dtc-parser.y"
+#line 145 "dtc-parser.y"
     {
                        (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
                ;}
     break;
 
   case 13:
-#line 148 "dtc-parser.y"
+#line 152 "dtc-parser.y"
     {
                        (yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
                ;}
     break;
 
   case 14:
-#line 155 "dtc-parser.y"
+#line 159 "dtc-parser.y"
     {
                        (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
                ;}
     break;
 
   case 15:
-#line 162 "dtc-parser.y"
+#line 166 "dtc-parser.y"
     {
                        (yyval.proplist) = NULL;
                ;}
     break;
 
   case 16:
-#line 166 "dtc-parser.y"
+#line 170 "dtc-parser.y"
     {
                        (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
                ;}
     break;
 
   case 17:
-#line 173 "dtc-parser.y"
+#line 177 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
                ;}
     break;
 
   case 18:
-#line 177 "dtc-parser.y"
+#line 181 "dtc-parser.y"
     {
                        (yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
                ;}
     break;
 
   case 19:
-#line 184 "dtc-parser.y"
+#line 188 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
                ;}
     break;
 
   case 20:
-#line 188 "dtc-parser.y"
+#line 192 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
                ;}
     break;
 
   case 21:
-#line 192 "dtc-parser.y"
+#line 196 "dtc-parser.y"
     {
                        (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
                ;}
     break;
 
   case 22:
-#line 196 "dtc-parser.y"
+#line 200 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 23:
-#line 200 "dtc-parser.y"
+#line 204 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+                       struct search_path path = { srcpos_file->dir, NULL, NULL };
+                       struct dtc_file *file = dtc_open_file((yyvsp[(4) - (9)].data).val, &path);
+                       struct data d = empty_data;
+
+                       if ((yyvsp[(6) - (9)].addr) != 0)
+                               if (fseek(file->file, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+                                       yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+                                                (unsigned long long)(yyvsp[(6) - (9)].addr),
+                                                (yyvsp[(4) - (9)].data).val, strerror(errno));
+
+                       d = data_copy_file(file->file, (yyvsp[(8) - (9)].addr));
+
+                       (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
+                       dtc_close_file(file);
                ;}
     break;
 
   case 24:
-#line 207 "dtc-parser.y"
+#line 221 "dtc-parser.y"
     {
-                       (yyval.data) = empty_data;
+                       struct search_path path = { srcpos_file->dir, NULL, NULL };
+                       struct dtc_file *file = dtc_open_file((yyvsp[(4) - (5)].data).val, &path);
+                       struct data d = empty_data;
+
+                       d = data_copy_file(file->file, -1);
+
+                       (yyval.data) = data_merge((yyvsp[(1) - (5)].data), d);
+                       dtc_close_file(file);
                ;}
     break;
 
   case 25:
-#line 211 "dtc-parser.y"
+#line 232 "dtc-parser.y"
     {
-                       (yyval.data) = (yyvsp[(1) - (2)].data);
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 26:
-#line 215 "dtc-parser.y"
+#line 239 "dtc-parser.y"
     {
-                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+                       (yyval.data) = empty_data;
                ;}
     break;
 
   case 27:
-#line 222 "dtc-parser.y"
+#line 243 "dtc-parser.y"
     {
-                       (yyval.data) = empty_data;
+                       (yyval.data) = (yyvsp[(1) - (2)].data);
                ;}
     break;
 
   case 28:
-#line 226 "dtc-parser.y"
+#line 247 "dtc-parser.y"
     {
-                       (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
   case 29:
-#line 230 "dtc-parser.y"
+#line 254 "dtc-parser.y"
+    {
+                       (yyval.data) = empty_data;
+               ;}
+    break;
+
+  case 30:
+#line 258 "dtc-parser.y"
+    {
+                       (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+               ;}
+    break;
+
+  case 31:
+#line 262 "dtc-parser.y"
     {
                        (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
                                                              (yyvsp[(2) - (2)].labelref)), -1);
                ;}
     break;
 
-  case 30:
-#line 235 "dtc-parser.y"
+  case 32:
+#line 267 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
-  case 31:
-#line 242 "dtc-parser.y"
+  case 33:
+#line 274 "dtc-parser.y"
     {
                        (yyval.cbase) = 16;
                ;}
     break;
 
-  case 33:
-#line 250 "dtc-parser.y"
+  case 35:
+#line 282 "dtc-parser.y"
     {
                        (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
                ;}
     break;
 
-  case 34:
-#line 254 "dtc-parser.y"
+  case 36:
+#line 286 "dtc-parser.y"
     {
                        (yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
                ;}
     break;
 
-  case 35:
-#line 261 "dtc-parser.y"
+  case 37:
+#line 293 "dtc-parser.y"
     {
                        (yyval.data) = empty_data;
                ;}
     break;
 
-  case 36:
-#line 265 "dtc-parser.y"
+  case 38:
+#line 297 "dtc-parser.y"
     {
                        (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
                ;}
     break;
 
-  case 37:
-#line 269 "dtc-parser.y"
+  case 39:
+#line 301 "dtc-parser.y"
     {
                        (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
                ;}
     break;
 
-  case 38:
-#line 276 "dtc-parser.y"
+  case 40:
+#line 308 "dtc-parser.y"
     {
                        (yyval.nodelist) = NULL;
                ;}
     break;
 
-  case 39:
-#line 280 "dtc-parser.y"
+  case 41:
+#line 312 "dtc-parser.y"
     {
                        (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
                ;}
     break;
 
-  case 40:
-#line 284 "dtc-parser.y"
+  case 42:
+#line 316 "dtc-parser.y"
     {
-                       yyerror("syntax error: properties must precede subnodes\n");
+                       yyerror("syntax error: properties must precede subnodes");
                        YYERROR;
                ;}
     break;
 
-  case 41:
-#line 292 "dtc-parser.y"
+  case 43:
+#line 324 "dtc-parser.y"
     {
                        (yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
                ;}
     break;
 
-  case 42:
-#line 299 "dtc-parser.y"
+  case 44:
+#line 331 "dtc-parser.y"
     {
                        (yyval.labelref) = NULL;
                ;}
     break;
 
-  case 43:
-#line 303 "dtc-parser.y"
+  case 45:
+#line 335 "dtc-parser.y"
     {
                        (yyval.labelref) = (yyvsp[(1) - (1)].labelref);
                ;}
@@ -1730,7 +1776,7 @@ yyreduce:
 
 
 /* Line 1267 of yacc.c.  */
-#line 1734 "dtc-parser.tab.c"
+#line 1780 "dtc-parser.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1950,21 +1996,32 @@ yyreturn:
 }
 
 
-#line 308 "dtc-parser.y"
+#line 340 "dtc-parser.y"
 
 
-void yyerror (char const *s)
+void yyerrorf(char const *s, ...)
 {
-       const char *fname = srcpos_filename_for_num(yylloc.filenum);
+       const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
+       va_list va;
+       va_start(va, s);
 
        if (strcmp(fname, "-") == 0)
                fname = "stdin";
 
-       fprintf(stderr, "%s:%d %s\n",
-               fname, yylloc.first_line, s);
+       fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
+       vfprintf(stderr, s, va);
+       fprintf(stderr, "\n");
+
+       treesource_error = 1;
+       va_end(va);
+}
+
+void yyerror (char const *s)
+{
+       yyerrorf("%s", s);
 }
 
-unsigned long long eval_literal(const char *s, int base, int bits)
+static unsigned long long eval_literal(const char *s, int base, int bits)
 {
        unsigned long long val;
        char *e;
index 4707b029ed25853dfb107c84c99ec4a1b551837b..ba99100d55c980e4281976df0ebbe4de31bdc541 100644 (file)
@@ -48,7 +48,8 @@
      DT_BYTE = 264,
      DT_STRING = 265,
      DT_LABEL = 266,
-     DT_REF = 267
+     DT_REF = 267,
+     DT_INCBIN = 268
    };
 #endif
 /* Tokens.  */
 #define DT_STRING 265
 #define DT_LABEL 266
 #define DT_REF 267
+#define DT_INCBIN 268
 
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 34 "dtc-parser.y"
+#line 37 "dtc-parser.y"
 {
        char *propnodename;
        char *literal;
        char *labelref;
        unsigned int cbase;
-       u8 byte;
+       uint8_t byte;
        struct data data;
 
-       u64 addr;
+       uint64_t addr;
        cell_t cell;
        struct property *prop;
        struct property *proplist;
@@ -86,7 +88,7 @@ typedef union YYSTYPE
        struct reserve_info *re;
 }
 /* Line 1489 of yacc.c.  */
-#line 90 "dtc-parser.tab.h"
+#line 92 "dtc-parser.tab.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index 002ea7fef184ee5b9cc1aec663f262c7e5bd2bdf..b2ab562420ead9815ac83adf4372bece16e10f23 100644 (file)
 %locations
 
 %{
+#include <stdio.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
-int yylex(void);
-unsigned long long eval_literal(const char *s, int base, int bits);
+extern int yylex(void);
 
 extern struct boot_info *the_boot_info;
+extern int treesource_error;
 
+static unsigned long long eval_literal(const char *s, int base, int bits);
 %}
 
 %union {
@@ -36,10 +39,10 @@ extern struct boot_info *the_boot_info;
        char *literal;
        char *labelref;
        unsigned int cbase;
-       u8 byte;
+       uint8_t byte;
        struct data data;
 
-       u64 addr;
+       uint64_t addr;
        cell_t cell;
        struct property *prop;
        struct property *proplist;
@@ -58,6 +61,7 @@ extern struct boot_info *the_boot_info;
 %token <data> DT_STRING
 %token <labelref> DT_LABEL
 %token <labelref> DT_REF
+%token DT_INCBIN
 
 %type <data> propdata
 %type <data> propdataprefix
@@ -84,11 +88,11 @@ extern struct boot_info *the_boot_info;
 sourcefile:
          DT_V1 ';' memreserves devicetree
                {
-                       the_boot_info = build_boot_info($3, $4);
+                       the_boot_info = build_boot_info($3, $4, 0);
                }
        | v0_memreserves devicetree
                {
-                       the_boot_info = build_boot_info($1, $2);
+                       the_boot_info = build_boot_info($1, $2, 0);
                }
        ;
 
@@ -196,6 +200,34 @@ propdata:
                {
                        $$ = data_add_marker($1, REF_PATH, $2);
                }
+       | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+               {
+                       struct search_path path = { srcpos_file->dir, NULL, NULL };
+                       struct dtc_file *file = dtc_open_file($4.val, &path);
+                       struct data d = empty_data;
+
+                       if ($6 != 0)
+                               if (fseek(file->file, $6, SEEK_SET) != 0)
+                                       yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+                                                (unsigned long long)$6,
+                                                $4.val, strerror(errno));
+
+                       d = data_copy_file(file->file, $8);
+
+                       $$ = data_merge($1, d);
+                       dtc_close_file(file);
+               }
+       | propdataprefix DT_INCBIN '(' DT_STRING ')'
+               {
+                       struct search_path path = { srcpos_file->dir, NULL, NULL };
+                       struct dtc_file *file = dtc_open_file($4.val, &path);
+                       struct data d = empty_data;
+
+                       d = data_copy_file(file->file, -1);
+
+                       $$ = data_merge($1, d);
+                       dtc_close_file(file);
+               }
        | propdata DT_LABEL
                {
                        $$ = data_add_marker($1, LABEL, $2);
@@ -282,7 +314,7 @@ subnodes:
                }
        | subnode propdef
                {
-                       yyerror("syntax error: properties must precede subnodes\n");
+                       yyerror("syntax error: properties must precede subnodes");
                        YYERROR;
                }
        ;
@@ -307,18 +339,29 @@ label:
 
 %%
 
-void yyerror (char const *s)
+void yyerrorf(char const *s, ...)
 {
-       const char *fname = srcpos_filename_for_num(yylloc.filenum);
+       const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
+       va_list va;
+       va_start(va, s);
 
        if (strcmp(fname, "-") == 0)
                fname = "stdin";
 
-       fprintf(stderr, "%s:%d %s\n",
-               fname, yylloc.first_line, s);
+       fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
+       vfprintf(stderr, s, va);
+       fprintf(stderr, "\n");
+
+       treesource_error = 1;
+       va_end(va);
+}
+
+void yyerror (char const *s)
+{
+       yyerrorf("%s", s);
 }
 
-unsigned long long eval_literal(const char *s, int base, int bits)
+static unsigned long long eval_literal(const char *s, int base, int bits)
 {
        unsigned long long val;
        char *e;
index 01131d7c2d5ef95c528b087d8e495ccc005a8cb6..d8fd43b4ac1a517a339e30e095f2a28544a1b906 100644 (file)
@@ -55,7 +55,7 @@ char *join_path(const char *path, const char *name)
        return str;
 }
 
-void fill_fullpaths(struct node *tree, const char *prefix)
+static void fill_fullpaths(struct node *tree, const char *prefix)
 {
        struct node *child;
        const char *unit;
@@ -106,7 +106,7 @@ static void  __attribute__ ((noreturn)) usage(void)
        fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
        fprintf(stderr, "\t-v\n");
        fprintf(stderr, "\t\tPrint DTC version and exit\n");
-       exit(2);
+       exit(3);
 }
 
 int main(int argc, char *argv[])
@@ -118,10 +118,9 @@ int main(int argc, char *argv[])
        int force = 0, check = 0;
        const char *arg;
        int opt;
-       FILE *inf = NULL;
        FILE *outf = NULL;
        int outversion = DEFAULT_FDT_VERSION;
-       int boot_cpuid_phys = 0xfeedbeef;
+       long long cmdline_boot_cpuid = -1;
 
        quiet      = 0;
        reservenum = 0;
@@ -161,11 +160,11 @@ int main(int argc, char *argv[])
                        quiet++;
                        break;
                case 'b':
-                       boot_cpuid_phys = strtol(optarg, NULL, 0);
+                       cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
                        break;
                case 'v':
-                   printf("Version: %s\n", DTC_VERSION);
-                   exit(0);
+                       printf("Version: %s\n", DTC_VERSION);
+                       exit(0);
                case 'h':
                default:
                        usage();
@@ -180,31 +179,27 @@ int main(int argc, char *argv[])
                arg = argv[optind];
 
        /* minsize and padsize are mutually exclusive */
-       if ((minsize) && (padsize)) {
+       if (minsize && padsize)
                die("Can't set both -p and -S\n");
-       }
 
        fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
                inform, outform, arg);
 
-       if (streq(inform, "dts")) {
+       if (streq(inform, "dts"))
                bi = dt_from_source(arg);
-       } else if (streq(inform, "fs")) {
+       else if (streq(inform, "fs"))
                bi = dt_from_fs(arg);
-       } else if(streq(inform, "dtb")) {
-               inf = dtc_open_file(arg);
-               bi = dt_from_blob(inf);
-       } else {
+       else if(streq(inform, "dtb"))
+               bi = dt_from_blob(arg);
+       else
                die("Unknown input format \"%s\"\n", inform);
-       }
 
-       if (inf && (inf != stdin))
-               fclose(inf);
+       if (cmdline_boot_cpuid != -1)
+               bi->boot_cpuid_phys = cmdline_boot_cpuid;
 
-       if (! bi || ! bi->dt)
-               die("Couldn't read input tree\n");
+       fill_fullpaths(bi->dt, "");
+       process_checks(force, bi);
 
-       process_checks(force, bi, check, outversion, boot_cpuid_phys);
 
        if (streq(outname, "-")) {
                outf = stdout;
@@ -218,9 +213,9 @@ int main(int argc, char *argv[])
        if (streq(outform, "dts")) {
                dt_to_source(outf, bi);
        } else if (streq(outform, "dtb")) {
-               dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
+               dt_to_blob(outf, bi, outversion);
        } else if (streq(outform, "asm")) {
-               dt_to_asm(outf, bi, outversion, boot_cpuid_phys);
+               dt_to_asm(outf, bi, outversion);
        } else if (streq(outform, "null")) {
                /* do nothing */
        } else {
index 65281777a167294e7385391efe751876f4d05001..08d54c8700863a84ab08c26ef699af4bce99c431 100644 (file)
 #include <ctype.h>
 #include <errno.h>
 #include <unistd.h>
-#include <netinet/in.h>
-#include <endian.h>
-#include <byteswap.h>
 
+#include <libfdt_env.h>
 #include <fdt.h>
 
 #define DEFAULT_FDT_VERSION    17
@@ -75,25 +73,8 @@ static inline void *xrealloc(void *p, size_t len)
        return new;
 }
 
-typedef uint8_t u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-typedef u32 cell_t;
+typedef uint32_t cell_t;
 
-#define cpu_to_be16(x) htons(x)
-#define be16_to_cpu(x) ntohs(x)
-
-#define cpu_to_be32(x) htonl(x)
-#define be32_to_cpu(x) ntohl(x)
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define cpu_to_be64(x) (x)
-#define be64_to_cpu(x) (x)
-#else
-#define cpu_to_be64(x) bswap_64(x)
-#define be64_to_cpu(x) bswap_64(x)
-#endif
 
 #define streq(a, b)    (strcmp((a), (b)) == 0)
 #define strneq(a, b, n)        (strncmp((a), (b), (n)) == 0)
@@ -118,7 +99,6 @@ struct  marker {
 struct data {
        int len;
        char *val;
-       int asize;
        struct marker *markers;
 };
 
@@ -145,7 +125,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
 struct data data_merge(struct data d1, struct data d2);
 struct data data_append_cell(struct data d, cell_t word);
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
-struct data data_append_addr(struct data d, u64 addr);
+struct data data_append_addr(struct data d, uint64_t addr);
 struct data data_append_byte(struct data d, uint8_t byte);
 struct data data_append_zeroes(struct data d, int len);
 struct data data_append_align(struct data d, int align);
@@ -223,7 +203,7 @@ struct reserve_info {
        char *label;
 };
 
-struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label);
+struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
                                         struct reserve_info *list);
 struct reserve_info *add_reserve_entry(struct reserve_info *list,
@@ -233,24 +213,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
 struct boot_info {
        struct reserve_info *reservelist;
        struct node *dt;                /* the device tree */
+       uint32_t boot_cpuid_phys;
 };
 
 struct boot_info *build_boot_info(struct reserve_info *reservelist,
-                                 struct node *tree);
+                                 struct node *tree, uint32_t boot_cpuid_phys);
 
 /* Checks */
 
-void process_checks(int force, struct boot_info *bi,
-                   int checkflag, int outversion, int boot_cpuid_phys);
+void process_checks(int force, struct boot_info *bi);
 
 /* Flattened trees */
 
-void dt_to_blob(FILE *f, struct boot_info *bi, int version,
-               int boot_cpuid_phys);
-void dt_to_asm(FILE *f, struct boot_info *bi, int version,
-              int boot_cpuid_phys);
+void dt_to_blob(FILE *f, struct boot_info *bi, int version);
+void dt_to_asm(FILE *f, struct boot_info *bi, int version);
 
-struct boot_info *dt_from_blob(FILE *f);
+struct boot_info *dt_from_blob(const char *fname);
 
 /* Tree source */
 
@@ -264,6 +242,5 @@ struct boot_info *dt_from_fs(const char *dirname);
 /* misc */
 
 char *join_path(const char *path, const char *name);
-void fill_fullpaths(struct node *tree, const char *prefix);
 
 #endif /* _DTC_H */
index a7cfb843d3342413882a5d3583b725bdfc30e0cd..76acd28c068db81195548369019b577d4aee5ddb 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "dtc.h"
+#include "srcpos.h"
 
 #define FTF_FULLPATH   0x1
 #define FTF_VARALIGN   0x2
@@ -162,28 +163,18 @@ static void asm_emit_data(void *e, struct data d)
 {
        FILE *f = e;
        int off = 0;
-       struct marker *m;
+       struct marker *m = d.markers;
 
-       m = d.markers;
-       while (m) {
-               if (m->type == LABEL)
-                       emit_offset_label(f, m->ref, m->offset);
-               m = m->next;
-       }
+       for_each_marker_of_type(m, LABEL)
+               emit_offset_label(f, m->ref, m->offset);
 
-       while ((d.len - off) >= sizeof(u32)) {
+       while ((d.len - off) >= sizeof(uint32_t)) {
                fprintf(f, "\t.long\t0x%x\n",
-                       be32_to_cpu(*((u32 *)(d.val+off))));
-               off += sizeof(u32);
-       }
-
-       if ((d.len - off) >= sizeof(u16)) {
-               fprintf(f, "\t.short\t0x%hx\n",
-                       be16_to_cpu(*((u16 *)(d.val+off))));
-               off += sizeof(u16);
+                       fdt32_to_cpu(*((uint32_t *)(d.val+off))));
+               off += sizeof(uint32_t);
        }
 
-       if ((d.len - off) >= 1) {
+       while ((d.len - off) >= 1) {
                fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
                off += 1;
        }
@@ -336,29 +327,28 @@ static void make_fdt_header(struct fdt_header *fdt,
 
        memset(fdt, 0xff, sizeof(*fdt));
 
-       fdt->magic = cpu_to_be32(FDT_MAGIC);
-       fdt->version = cpu_to_be32(vi->version);
-       fdt->last_comp_version = cpu_to_be32(vi->last_comp_version);
+       fdt->magic = cpu_to_fdt32(FDT_MAGIC);
+       fdt->version = cpu_to_fdt32(vi->version);
+       fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
 
        /* Reserve map should be doubleword aligned */
        reserve_off = ALIGN(vi->hdr_size, 8);
 
-       fdt->off_mem_rsvmap = cpu_to_be32(reserve_off);
-       fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize);
-       fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize
+       fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
+       fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
+       fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
                                          + dtsize);
-       fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize);
+       fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
 
        if (vi->flags & FTF_BOOTCPUID)
-               fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys);
+               fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
        if (vi->flags & FTF_STRTABSIZE)
-               fdt->size_dt_strings = cpu_to_be32(strsize);
+               fdt->size_dt_strings = cpu_to_fdt32(strsize);
        if (vi->flags & FTF_STRUCTSIZE)
-               fdt->size_dt_struct = cpu_to_be32(dtsize);
+               fdt->size_dt_struct = cpu_to_fdt32(dtsize);
 }
 
-void dt_to_blob(FILE *f, struct boot_info *bi, int version,
-               int boot_cpuid_phys)
+void dt_to_blob(FILE *f, struct boot_info *bi, int version)
 {
        struct version_info *vi = NULL;
        int i;
@@ -383,26 +373,26 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
 
        /* Make header */
        make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
-                       boot_cpuid_phys);
+                       bi->boot_cpuid_phys);
 
        /*
         * If the user asked for more space than is used, adjust the totalsize.
         */
        if (minsize > 0) {
-               padlen = minsize - be32_to_cpu(fdt.totalsize);
+               padlen = minsize - fdt32_to_cpu(fdt.totalsize);
                if ((padlen < 0) && (quiet < 1))
                        fprintf(stderr,
                                "Warning: blob size %d >= minimum size %d\n",
-                               be32_to_cpu(fdt.totalsize), minsize);
+                               fdt32_to_cpu(fdt.totalsize), minsize);
        }
 
        if (padsize > 0)
                padlen = padsize;
 
        if (padlen > 0) {
-               int tsize = be32_to_cpu(fdt.totalsize);
+               int tsize = fdt32_to_cpu(fdt.totalsize);
                tsize += padlen;
-               fdt.totalsize = cpu_to_be32(tsize);
+               fdt.totalsize = cpu_to_fdt32(tsize);
        }
 
        /*
@@ -410,7 +400,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version,
         * the reserve buffer, add the reserve map terminating zeroes,
         * the device tree itself, and finally the strings.
         */
-       blob = data_append_data(blob, &fdt, sizeof(fdt));
+       blob = data_append_data(blob, &fdt, vi->hdr_size);
        blob = data_append_align(blob, 8);
        blob = data_merge(blob, reservebuf);
        blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
@@ -449,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
        }
 }
 
-void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
+void dt_to_asm(FILE *f, struct boot_info *bi, int version)
 {
        struct version_info *vi = NULL;
        int i;
@@ -489,7 +479,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
 
        if (vi->flags & FTF_BOOTCPUID)
                fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
-                       boot_cpuid_phys);
+                       bi->boot_cpuid_phys);
 
        if (vi->flags & FTF_STRTABSIZE)
                fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
@@ -579,15 +569,15 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
        inb->ptr += len;
 }
 
-static u32 flat_read_word(struct inbuf *inb)
+static uint32_t flat_read_word(struct inbuf *inb)
 {
-       u32 val;
+       uint32_t val;
 
        assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
 
        flat_read_chunk(inb, &val, sizeof(val));
 
-       return be32_to_cpu(val);
+       return fdt32_to_cpu(val);
 }
 
 static void flat_realign(struct inbuf *inb, int align)
@@ -615,7 +605,7 @@ static char *flat_read_string(struct inbuf *inb)
 
        inb->ptr += len;
 
-       flat_realign(inb, sizeof(u32));
+       flat_realign(inb, sizeof(uint32_t));
 
        return str;
 }
@@ -632,7 +622,7 @@ static struct data flat_read_data(struct inbuf *inb, int len)
 
        flat_read_chunk(inb, d.val, len);
 
-       flat_realign(inb, sizeof(u32));
+       flat_realign(inb, sizeof(uint32_t));
 
        return d;
 }
@@ -659,7 +649,7 @@ static char *flat_read_stringtable(struct inbuf *inb, int offset)
 static struct property *flat_read_property(struct inbuf *dtbuf,
                                           struct inbuf *strbuf, int flags)
 {
-       u32 proplen, stroff;
+       uint32_t proplen, stroff;
        char *name;
        struct data val;
 
@@ -693,8 +683,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
        p = inb->ptr;
        while (1) {
                flat_read_chunk(inb, &re, sizeof(re));
-               re.address  = be64_to_cpu(re.address);
-               re.size = be64_to_cpu(re.size);
+               re.address  = fdt64_to_cpu(re.address);
+               re.size = fdt64_to_cpu(re.size);
                if (re.size == 0)
                        break;
 
@@ -708,77 +698,37 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
 
 static char *nodename_from_path(const char *ppath, const char *cpath)
 {
-       const char *lslash;
        int plen;
 
-       lslash = strrchr(cpath, '/');
-       if (! lslash)
-               return NULL;
-
-       plen = lslash - cpath;
-
-       if (streq(cpath, "/") && streq(ppath, ""))
-               return "";
-
-       if ((plen == 0) && streq(ppath, "/"))
-               return strdup(lslash+1);
-
-       if (! strneq(ppath, cpath, plen))
-               return NULL;
-
-       return strdup(lslash+1);
-}
-
-static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-";
-static const char UNITCHAR[] = "0123456789abcdef,";
-
-static int check_node_name(const char *name)
-{
-       const char *atpos;
-       int basenamelen;
+       plen = strlen(ppath);
 
-       atpos = strrchr(name, '@');
+       if (!strneq(ppath, cpath, plen))
+               die("Path \"%s\" is not valid as a child of \"%s\"\n",
+                   cpath, ppath);
 
-       if (atpos)
-               basenamelen = atpos - name;
-       else
-               basenamelen = strlen(name);
-
-       if (strspn(name, PROPCHAR) < basenamelen)
-               return -1;
+       /* root node is a special case */
+       if (!streq(ppath, "/"))
+               plen++;
 
-       if (atpos
-           && ((basenamelen + 1 + strspn(atpos+1, UNITCHAR)) < strlen(name)))
-               return -1;
-
-       return basenamelen;
+       return strdup(cpath + plen);
 }
 
 static struct node *unflatten_tree(struct inbuf *dtbuf,
                                   struct inbuf *strbuf,
-                                  const char *parent_path, int flags)
+                                  const char *parent_flatname, int flags)
 {
        struct node *node;
-       u32 val;
+       char *flatname;
+       uint32_t val;
 
        node = build_node(NULL, NULL);
 
-       if (flags & FTF_FULLPATH) {
-               node->fullpath = flat_read_string(dtbuf);
-               node->name = nodename_from_path(parent_path, node->fullpath);
-
-               if (! node->name)
-                       die("Path \"%s\" is not valid as a child of \"%s\"\n",
-                           node->fullpath, parent_path);
-       } else {
-               node->name = flat_read_string(dtbuf);
-               node->fullpath = join_path(parent_path, node->name);
-       }
+       flatname = flat_read_string(dtbuf);
 
-       node->basenamelen = check_node_name(node->name);
-       if (node->basenamelen < 0) {
-               fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name);
-       }
+       if (flags & FTF_FULLPATH)
+               node->name = nodename_from_path(parent_flatname, flatname);
+       else
+               node->name = flatname;
 
        do {
                struct property *prop;
@@ -795,8 +745,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
                        break;
 
                case FDT_BEGIN_NODE:
-                       child = unflatten_tree(dtbuf,strbuf, node->fullpath,
-                                              flags);
+                       child = unflatten_tree(dtbuf,strbuf, flatname, flags);
                        add_child(node, child);
                        break;
 
@@ -825,10 +774,11 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
 }
 
 
-struct boot_info *dt_from_blob(FILE *f)
+struct boot_info *dt_from_blob(const char *fname)
 {
-       u32 magic, totalsize, version, size_str, size_dt;
-       u32 off_dt, off_str, off_mem_rsvmap;
+       struct dtc_file *dtcf;
+       uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
+       uint32_t off_dt, off_str, off_mem_rsvmap;
        int rc;
        char *blob;
        struct fdt_header *fdt;
@@ -838,54 +788,56 @@ struct boot_info *dt_from_blob(FILE *f)
        int sizeleft;
        struct reserve_info *reservelist;
        struct node *tree;
-       u32 val;
+       uint32_t val;
        int flags = 0;
 
-       rc = fread(&magic, sizeof(magic), 1, f);
-       if (ferror(f))
+       dtcf = dtc_open_file(fname, NULL);
+
+       rc = fread(&magic, sizeof(magic), 1, dtcf->file);
+       if (ferror(dtcf->file))
                die("Error reading DT blob magic number: %s\n",
                    strerror(errno));
        if (rc < 1) {
-               if (feof(f))
+               if (feof(dtcf->file))
                        die("EOF reading DT blob magic number\n");
                else
                        die("Mysterious short read reading magic number\n");
        }
 
-       magic = be32_to_cpu(magic);
+       magic = fdt32_to_cpu(magic);
        if (magic != FDT_MAGIC)
                die("Blob has incorrect magic number\n");
 
-       rc = fread(&totalsize, sizeof(totalsize), 1, f);
-       if (ferror(f))
+       rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file);
+       if (ferror(dtcf->file))
                die("Error reading DT blob size: %s\n", strerror(errno));
        if (rc < 1) {
-               if (feof(f))
+               if (feof(dtcf->file))
                        die("EOF reading DT blob size\n");
                else
                        die("Mysterious short read reading blob size\n");
        }
 
-       totalsize = be32_to_cpu(totalsize);
+       totalsize = fdt32_to_cpu(totalsize);
        if (totalsize < FDT_V1_SIZE)
                die("DT blob size (%d) is too small\n", totalsize);
 
        blob = xmalloc(totalsize);
 
        fdt = (struct fdt_header *)blob;
-       fdt->magic = cpu_to_be32(magic);
-       fdt->totalsize = cpu_to_be32(totalsize);
+       fdt->magic = cpu_to_fdt32(magic);
+       fdt->totalsize = cpu_to_fdt32(totalsize);
 
        sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
        p = blob + sizeof(magic)  + sizeof(totalsize);
 
        while (sizeleft) {
-               if (feof(f))
+               if (feof(dtcf->file))
                        die("EOF before reading %d bytes of DT blob\n",
                            totalsize);
 
-               rc = fread(p, 1, sizeleft, f);
-               if (ferror(f))
+               rc = fread(p, 1, sizeleft, dtcf->file);
+               if (ferror(dtcf->file))
                        die("Error reading DT blob: %s\n",
                            strerror(errno));
 
@@ -893,19 +845,11 @@ struct boot_info *dt_from_blob(FILE *f)
                p += rc;
        }
 
-       off_dt = be32_to_cpu(fdt->off_dt_struct);
-       off_str = be32_to_cpu(fdt->off_dt_strings);
-       off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap);
-       version = be32_to_cpu(fdt->version);
-
-       fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
-       fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
-       fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
-       fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
-       fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap);
-       fprintf(stderr, "\tversion:\t\t0x%x\n", version );
-       fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
-               be32_to_cpu(fdt->last_comp_version));
+       off_dt = fdt32_to_cpu(fdt->off_dt_struct);
+       off_str = fdt32_to_cpu(fdt->off_dt_strings);
+       off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
+       version = fdt32_to_cpu(fdt->version);
+       boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
 
        if (off_mem_rsvmap >= totalsize)
                die("Mem Reserve structure offset exceeds total size\n");
@@ -916,21 +860,17 @@ struct boot_info *dt_from_blob(FILE *f)
        if (off_str > totalsize)
                die("String table offset exceeds total size\n");
 
-       if (version >= 2)
-               fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n",
-                       be32_to_cpu(fdt->boot_cpuid_phys));
-
-       size_str = -1;
        if (version >= 3) {
-               size_str = be32_to_cpu(fdt->size_dt_strings);
-               fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str);
+               uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
                if (off_str+size_str > totalsize)
                        die("String table extends past total size\n");
+               inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
+       } else {
+               inbuf_init(&strbuf, blob + off_str, blob + totalsize);
        }
 
        if (version >= 17) {
-               size_dt = be32_to_cpu(fdt->size_dt_struct);
-               fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt);
+               size_dt = fdt32_to_cpu(fdt->size_dt_struct);
                if (off_dt+size_dt > totalsize)
                        die("Structure block extends past total size\n");
        }
@@ -944,10 +884,6 @@ struct boot_info *dt_from_blob(FILE *f)
        inbuf_init(&memresvbuf,
                   blob + off_mem_rsvmap, blob + totalsize);
        inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
-       if (size_str >= 0)
-               inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
-       else
-               inbuf_init(&strbuf, blob + off_str, blob + totalsize);
 
        reservelist = flat_read_mem_reserve(&memresvbuf);
 
@@ -964,5 +900,7 @@ struct boot_info *dt_from_blob(FILE *f)
 
        free(blob);
 
-       return build_boot_info(reservelist, tree);
+       dtc_close_file(dtcf);
+
+       return build_boot_info(reservelist, tree, boot_cpuid_phys);
 }
index 2a160a46998ee99ad3189a948a5f6894a63e75a6..766b2694d93589fe39ea6313dbae7b1ce5a21daa 100644 (file)
@@ -31,8 +31,8 @@ static struct node *read_fstree(const char *dirname)
        struct node *tree;
 
        d = opendir(dirname);
-       if (! d)
-               die("opendir(): %s\n", strerror(errno));
+       if (!d)
+               die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
 
        tree = build_node(NULL, NULL);
 
@@ -87,8 +87,6 @@ struct boot_info *dt_from_fs(const char *dirname)
        tree = read_fstree(dirname);
        tree = name_node(tree, "", NULL);
 
-       fill_fullpaths(tree, "");
-
-       return build_boot_info(NULL, tree);
+       return build_boot_info(NULL, tree, 0);
 }
 
diff --git a/arch/powerpc/boot/dtc-src/libfdt_env.h b/arch/powerpc/boot/dtc-src/libfdt_env.h
new file mode 100644 (file)
index 0000000..449bf60
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define _B(n)  ((unsigned long long)((uint8_t *)&x)[n])
+static inline uint32_t fdt32_to_cpu(uint32_t x)
+{
+       return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+}
+#define cpu_to_fdt32(x) fdt32_to_cpu(x)
+
+static inline uint64_t fdt64_to_cpu(uint64_t x)
+{
+       return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
+               | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+}
+#define cpu_to_fdt64(x) fdt64_to_cpu(x)
+#undef _B
+
+#endif /* _LIBFDT_ENV_H */
index 6ba0846b4310a5dd97e0ae4729afbe8a4203af4d..0ca3de550b3ff7d1ef6d437849061238275b0d4d 100644 (file)
@@ -115,6 +115,7 @@ void add_child(struct node *parent, struct node *child)
        struct node **p;
 
        child->next_sibling = NULL;
+       child->parent = parent;
 
        p = &parent->children;
        while (*p)
@@ -123,7 +124,8 @@ void add_child(struct node *parent, struct node *child)
        *p = child;
 }
 
-struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label)
+struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
+                                        char *label)
 {
        struct reserve_info *new = xmalloc(sizeof(*new));
 
@@ -165,13 +167,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
 }
 
 struct boot_info *build_boot_info(struct reserve_info *reservelist,
-                                 struct node *tree)
+                                 struct node *tree, uint32_t boot_cpuid_phys)
 {
        struct boot_info *bi;
 
        bi = xmalloc(sizeof(*bi));
        bi->reservelist = reservelist;
        bi->dt = tree;
+       bi->boot_cpuid_phys = boot_cpuid_phys;
 
        return bi;
 }
@@ -202,7 +205,7 @@ struct property *get_property(struct node *node, const char *propname)
 cell_t propval_cell(struct property *prop)
 {
        assert(prop->val.len == sizeof(cell_t));
-       return be32_to_cpu(*((cell_t *)prop->val.val));
+       return fdt32_to_cpu(*((cell_t *)prop->val.val));
 }
 
 struct node *get_subnode(struct node *node, const char *nodename)
index 352b0fe06fde1f6e9b112ffdf01941d8a5398de5..9641b7628b4de60b8d476f5329334b6dc6a10144 100644 (file)
 #include "dtc.h"
 #include "srcpos.h"
 
-
-/*
- * Record the complete unique set of opened file names.
- * Primarily used to cache source position file names.
- */
-#define MAX_N_FILE_NAMES       (100)
-
-const char *file_names[MAX_N_FILE_NAMES];
-static int n_file_names = 0;
-
 /*
  * Like yylineno, this is the current open file pos.
  */
 
-int srcpos_filenum = -1;
-
+struct dtc_file *srcpos_file;
 
-
-FILE *dtc_open_file(const char *fname)
+static int dtc_open_one(struct dtc_file *file,
+                        const char *search,
+                        const char *fname)
 {
-       FILE *f;
+       char *fullname;
 
-       if (lookup_file_name(fname, 1) < 0)
-               die("Too many files opened\n");
+       if (search) {
+               fullname = xmalloc(strlen(search) + strlen(fname) + 2);
 
-       if (streq(fname, "-"))
-               f = stdin;
-       else
-               f = fopen(fname, "r");
+               strcpy(fullname, search);
+               strcat(fullname, "/");
+               strcat(fullname, fname);
+       } else {
+               fullname = strdup(fname);
+       }
 
-       if (! f)
-               die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+       file->file = fopen(fullname, "r");
+       if (!file->file) {
+               free(fullname);
+               return 0;
+       }
 
-       return f;
+       file->name = fullname;
+       return 1;
 }
 
 
+struct dtc_file *dtc_open_file(const char *fname,
+                               const struct search_path *search)
+{
+       static const struct search_path default_search = { NULL, NULL, NULL };
 
-/*
- * Locate and optionally add filename fname in the file_names[] array.
- *
- * If the filename is currently not in the array and the boolean
- * add_it is non-zero, an attempt to add the filename will be made.
- *
- * Returns;
- *    Index [0..MAX_N_FILE_NAMES) where the filename is kept
- *    -1 if the name can not be recorded
- */
+       struct dtc_file *file;
+       const char *slash;
 
-int lookup_file_name(const char *fname, int add_it)
-{
-       int i;
+       file = xmalloc(sizeof(struct dtc_file));
 
-       for (i = 0; i < n_file_names; i++) {
-               if (strcmp(file_names[i], fname) == 0)
-                       return i;
+       slash = strrchr(fname, '/');
+       if (slash) {
+               char *dir = xmalloc(slash - fname + 1);
+
+               memcpy(dir, fname, slash - fname);
+               dir[slash - fname] = 0;
+               file->dir = dir;
+       } else {
+               file->dir = NULL;
        }
 
-       if (add_it) {
-               if (n_file_names < MAX_N_FILE_NAMES) {
-                       file_names[n_file_names] = strdup(fname);
-                       return n_file_names++;
-               }
+       if (streq(fname, "-")) {
+               file->name = "stdin";
+               file->file = stdin;
+               return file;
        }
 
-       return -1;
-}
+       if (fname[0] == '/') {
+               file->file = fopen(fname, "r");
+               if (!file->file)
+                       goto fail;
+
+               file->name = strdup(fname);
+               return file;
+       }
 
+       if (!search)
+               search = &default_search;
 
-const char *srcpos_filename_for_num(int filenum)
-{
-       if (0 <= filenum && filenum < n_file_names) {
-               return file_names[filenum];
+       while (search) {
+               if (dtc_open_one(file, search->dir, fname))
+                       return file;
+
+               if (errno != ENOENT)
+                       goto fail;
+
+               search = search->next;
        }
 
-       return 0;
+fail:
+       die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
 }
 
-
-const char *srcpos_get_filename(void)
+void dtc_close_file(struct dtc_file *file)
 {
-       return srcpos_filename_for_num(srcpos_filenum);
+       if (fclose(file->file))
+               die("Error closing \"%s\": %s\n", file->name, strerror(errno));
+
+       free(file->dir);
+       free(file);
 }
index ce7ab5ba5b4659ab90426f62ed7a2182187ca805..e17c7c04db8ea4c17d4dfc94e7082b6eb9f296cb 100644 (file)
  * array of all opened filenames.
  */
 
+#include <stdio.h>
+
+struct dtc_file {
+       char *dir;
+       const char *name;
+       FILE *file;
+};
+
 #if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
 typedef struct YYLTYPE {
     int first_line;
     int first_column;
     int last_line;
     int last_column;
-    int filenum;
+    struct dtc_file *file;
 } YYLTYPE;
 
 #define YYLTYPE_IS_DECLARED    1
@@ -48,7 +56,7 @@ typedef struct YYLTYPE {
          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-         (Current).filenum      = YYRHSLOC (Rhs, N).filenum;           \
+         (Current).file         = YYRHSLOC (Rhs, N).file;              \
        }                                                               \
       else                                                             \
        {                                                               \
@@ -56,20 +64,22 @@ typedef struct YYLTYPE {
            YYRHSLOC (Rhs, 0).last_line;                                \
          (Current).first_column = (Current).last_column =              \
            YYRHSLOC (Rhs, 0).last_column;                              \
-         (Current).filenum      = YYRHSLOC (Rhs, 0).filenum;           \
+         (Current).file         = YYRHSLOC (Rhs, 0).file;              \
        }                                                               \
     while (YYID (0))
 
 
 
 extern void yyerror(char const *);
+extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
 
-extern int srcpos_filenum;
+extern struct dtc_file *srcpos_file;
 
-extern int push_input_file(const char *filename);
-extern int pop_input_file(void);
+struct search_path {
+       const char *dir; /* NULL for current directory */
+       struct search_path *prev, *next;
+};
 
-extern FILE *dtc_open_file(const char *fname);
-extern int lookup_file_name(const char *fname, int add_it);
-extern const char *srcpos_filename_for_num(int filenum);
-const char *srcpos_get_filename(void);
+extern struct dtc_file *dtc_open_file(const char *fname,
+                                      const struct search_path *search);
+extern void dtc_close_file(struct dtc_file *file);
index a6a7767976364498a99b1a3c6c7d4d8f6071446a..ebeb6eb27907db69cd113ba0de8fa9dfd856d25f 100644 (file)
 
 extern FILE *yyin;
 extern int yyparse(void);
-extern void yyerror(char const *);
 
 struct boot_info *the_boot_info;
+int treesource_error;
 
 struct boot_info *dt_from_source(const char *fname)
 {
        the_boot_info = NULL;
+       treesource_error = 0;
 
-       push_input_file(fname);
+       srcpos_file = dtc_open_file(fname, NULL);
+       yyin = srcpos_file->file;
 
        if (yyparse() != 0)
-               return NULL;
+               die("Unable to parse input tree\n");
 
-       fill_fullpaths(the_boot_info->dt, "");
+       if (treesource_error)
+               die("Syntax error parsing input tree\n");
 
        return the_boot_info;
 }
@@ -144,7 +147,7 @@ static void write_propval_cells(FILE *f, struct data val)
                        m = m->next;
                }
 
-               fprintf(f, "0x%x", be32_to_cpu(*cp++));
+               fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
                if ((void *)cp >= propend)
                        break;
                fprintf(f, " ");
@@ -173,7 +176,7 @@ static void write_propval_bytes(FILE *f, struct data val)
                }
 
                fprintf(f, "%02hhx", *bp++);
-               if ((void *)bp >= propend)
+               if ((const void *)bp >= propend)
                        break;
                fprintf(f, " ");
        }
index 6c343031538ee00658c5f4424a3412afc59a5d21..658ff42429d64eba3e37d34c1f66d760631814bd 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.0.0-gd6f9b62f"
+#define DTC_VERSION "DTC 1.2.0"
diff --git a/arch/powerpc/boot/dts/arches.dts b/arch/powerpc/boot/dts/arches.dts
new file mode 100644 (file)
index 0000000..d9113b1
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Device Tree Source for AMCC Arches (dual 460GT board)
+ *
+ * (C) Copyright 2008 Applied Micro Circuits Corporation
+ * Victor Gallardo <vgallardo@amcc.com>
+ * Adam Graham <agraham@amcc.com>
+ *
+ * Based on the glacier.dts file
+ *   Stefan Roese <sr@denx.de>
+ *   Copyright 2008 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       model = "amcc,arches";
+       compatible = "amcc,arches";
+       dcr-parent = <&{/cpus/cpu@0}>;
+
+       aliases {
+               ethernet0 = &EMAC0;
+               ethernet1 = &EMAC1;
+               ethernet2 = &EMAC2;
+               serial0 = &UART0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       model = "PowerPC,460GT";
+                       reg = <0x00000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+                       timebase-frequency = <0>; /* Filled in by U-Boot */
+                       i-cache-line-size = <32>;
+                       d-cache-line-size = <32>;
+                       i-cache-size = <32768>;
+                       d-cache-size = <32768>;
+                       dcr-controller;
+                       dcr-access-method = "native";
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
+       };
+
+       UIC0: interrupt-controller0 {
+               compatible = "ibm,uic-460gt","ibm,uic";
+               interrupt-controller;
+               cell-index = <0>;
+               dcr-reg = <0x0c0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+       };
+
+       UIC1: interrupt-controller1 {
+               compatible = "ibm,uic-460gt","ibm,uic";
+               interrupt-controller;
+               cell-index = <1>;
+               dcr-reg = <0x0d0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC2: interrupt-controller2 {
+               compatible = "ibm,uic-460gt","ibm,uic";
+               interrupt-controller;
+               cell-index = <2>;
+               dcr-reg = <0x0e0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       UIC3: interrupt-controller3 {
+               compatible = "ibm,uic-460gt","ibm,uic";
+               interrupt-controller;
+               cell-index = <3>;
+               dcr-reg = <0x0f0 0x009>;
+               #address-cells = <0>;
+               #size-cells = <0>;
+               #interrupt-cells = <2>;
+               interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
+               interrupt-parent = <&UIC0>;
+       };
+
+       SDR0: sdr {
+               compatible = "ibm,sdr-460gt";
+               dcr-reg = <0x00e 0x002>;
+       };
+
+       CPR0: cpr {
+               compatible = "ibm,cpr-460gt";
+               dcr-reg = <0x00c 0x002>;
+       };
+
+       plb {
+               compatible = "ibm,plb-460gt", "ibm,plb4";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges;
+               clock-frequency = <0>; /* Filled in by U-Boot */
+
+               SDRAM0: sdram {
+                       compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
+                       dcr-reg = <0x010 0x002>;
+               };
+
+               MAL0: mcmal {
+                       compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
+                       dcr-reg = <0x180 0x062>;
+                       num-tx-chans = <3>;
+                       num-rx-chans = <24>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-parent = <&UIC2>;
+                       interrupts = <  /*TXEOB*/ 0x6 0x4
+                                       /*RXEOB*/ 0x7 0x4
+                                       /*SERR*/  0x3 0x4
+                                       /*TXDE*/  0x4 0x4
+                                       /*RXDE*/  0x5 0x4>;
+                       desc-base-addr-high = <0x8>;
+               };
+
+               POB0: opb {
+                       compatible = "ibm,opb-460gt", "ibm,opb";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+
+                       EBC0: ebc {
+                               compatible = "ibm,ebc-460gt", "ibm,ebc";
+                               dcr-reg = <0x012 0x002>;
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               /* ranges property is supplied by U-Boot */
+                               interrupts = <0x6 0x4>;
+                               interrupt-parent = <&UIC1>;
+                       };
+
+                       UART0: serial@ef600300 {
+                               device_type = "serial";
+                               compatible = "ns16550";
+                               reg = <0xef600300 0x00000008>;
+                               virtual-reg = <0xef600300>;
+                               clock-frequency = <0>; /* Filled in by U-Boot */
+                               current-speed = <0>; /* Filled in by U-Boot */
+                               interrupt-parent = <&UIC1>;
+                               interrupts = <0x1 0x4>;
+                       };
+
+                       IIC0: i2c@ef600700 {
+                               compatible = "ibm,iic-460gt", "ibm,iic";
+                               reg = <0xef600700 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x2 0x4>;
+                       };
+
+                       IIC1: i2c@ef600800 {
+                               compatible = "ibm,iic-460gt", "ibm,iic";
+                               reg = <0xef600800 0x00000014>;
+                               interrupt-parent = <&UIC0>;
+                               interrupts = <0x3 0x4>;
+                       };
+
+                       TAH0: emac-tah@ef601350 {
+                               compatible = "ibm,tah-460gt", "ibm,tah";
+                               reg = <0xef601350 0x00000030>;
+                       };
+
+                       TAH1: emac-tah@ef601450 {
+                               compatible = "ibm,tah-460gt", "ibm,tah";
+                               reg = <0xef601450 0x00000030>;
+                       };
+
+                       EMAC0: ethernet@ef600e00 {
+                               device_type = "network";
+                               compatible = "ibm,emac-460gt", "ibm,emac4sync";
+                               interrupt-parent = <&EMAC0>;
+                               interrupts = <0x0 0x1>;
+                               #interrupt-cells = <1>;
+                               #address-cells = <0>;
+                               #size-cells = <0>;
+                               interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
+                                                /*Wake*/   0x1 &UIC2 0x14 0x4>;
+                               reg = <0xef600e00 0x000000c4>;
+                               local-mac-address = [000000000000]; /* Filled in by U-Boot */
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <0>;
+                               mal-rx-channel = <0>;
+                               cell-index = <0>;
+                               max-frame-size = <9000>;
+                               rx-fifo-size = <4096>;
+                               tx-fifo-size = <2048>;
+                               phy-mode = "sgmii";
+                               phy-map = <0xffffffff>;
+                               gpcs-address = <0x0000000a>;
+                               tah-device = <&TAH0>;
+                               tah-channel = <0>;
+                               has-inverted-stacr-oc;
+                               has-new-stacr-staopc;
+                       };
+
+                       EMAC1: ethernet@ef600f00 {
+                               device_type = "network";
+                               compatible = "ibm,emac-460gt", "ibm,emac4sync";
+                               interrupt-parent = <&EMAC1>;
+                               interrupts = <0x0 0x1>;
+                               #interrupt-cells = <1>;
+                               #address-cells = <0>;
+                               #size-cells = <0>;
+                               interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
+                                                /*Wake*/   0x1 &UIC2 0x15 0x4>;
+                               reg = <0xef600f00 0x000000c4>;
+                               local-mac-address = [000000000000]; /* Filled in by U-Boot */
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <1>;
+                               mal-rx-channel = <8>;
+                               cell-index = <1>;
+                               max-frame-size = <9000>;
+                               rx-fifo-size = <4096>;
+                               tx-fifo-size = <2048>;
+                               phy-mode = "sgmii";
+                               phy-map = <0x00000000>;
+                               gpcs-address = <0x0000000b>;
+                               tah-device = <&TAH1>;
+                               tah-channel = <1>;
+                               has-inverted-stacr-oc;
+                               has-new-stacr-staopc;
+                               mdio-device = <&EMAC0>;
+                       };
+
+                       EMAC2: ethernet@ef601100 {
+                               device_type = "network";
+                               compatible = "ibm,emac-460gt", "ibm,emac4sync";
+                               interrupt-parent = <&EMAC2>;
+                               interrupts = <0x0 0x1>;
+                               #interrupt-cells = <1>;
+                               #address-cells = <0>;
+                               #size-cells = <0>;
+                               interrupt-map = </*Status*/ 0x0 &UIC2 0x12 0x4
+                                                /*Wake*/   0x1 &UIC2 0x16 0x4>;
+                               reg = <0xef601100 0x000000c4>;
+                               local-mac-address = [000000000000]; /* Filled in by U-Boot */
+                               mal-device = <&MAL0>;
+                               mal-tx-channel = <2>;
+                               mal-rx-channel = <16>;
+                               cell-index = <2>;
+                               max-frame-size = <9000>;
+                               rx-fifo-size = <4096>;
+                               tx-fifo-size = <2048>;
+                               phy-mode = "sgmii";
+                               phy-map = <0x00000001>;
+                               gpcs-address = <0x0000000C>;
+                               has-inverted-stacr-oc;
+                               has-new-stacr-staopc;
+                               mdio-device = <&EMAC0>;
+                       };
+               };
+       };
+};
index 8b1bb0e41905c422a30697c7ae04b9e008589ffb..6235fca445de43ec0418cc2beb8c0bf91919bff3 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8347-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8347-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8347-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8347-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
new file mode 100644 (file)
index 0000000..6ed6083
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * GE Fanuc SBC610 Device Tree Source
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_sbc610.dtb gef_sbc610.dts
+ */
+
+/dts-v1/;
+
+/ {
+       model = "GEF_SBC610";
+       compatible = "gef,sbc610";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8641@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;       // 32 bytes
+                       i-cache-line-size = <32>;       // 32 bytes
+                       d-cache-size = <32768>;         // L1, 32K
+                       i-cache-size = <32768>;         // L1, 32K
+                       timebase-frequency = <0>;       // From uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+               };
+               PowerPC,8641@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       d-cache-line-size = <32>;       // 32 bytes
+                       i-cache-line-size = <32>;       // 32 bytes
+                       d-cache-size = <32768>;         // L1, 32K
+                       i-cache-size = <32768>;         // L1, 32K
+                       timebase-frequency = <0>;       // From uboot
+                       bus-frequency = <0>;            // From uboot
+                       clock-frequency = <0>;          // From uboot
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x40000000>; // set by uboot
+       };
+
+       localbus@fef05000 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc8641-localbus", "simple-bus";
+               reg = <0xf8005000 0x1000>;
+               interrupts = <19 2>;
+               interrupt-parent = <&mpic>;
+
+               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+                         1 0 0xe8000000 0x08000000     // Paged Flash 0
+                         2 0 0xe0000000 0x08000000     // Paged Flash 1
+                         3 0 0xfc100000 0x00020000     // NVRAM
+                         4 0 0xfc000000 0x00008000     // FPGA
+                         5 0 0xfc008000 0x00008000     // AFIX FPGA
+                         6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
+                         7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
+
+               fpga@4,0 {
+                       compatible = "gef,fpga-regs";
+                       reg = <0x4 0x0 0x40>;
+               };
+               gef_pic: pic@4,4000 {
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       compatible = "gef,fpga-pic";
+                       reg = <0x4 0x4000 0x20>;
+                       interrupts = <0x8
+                                     0x9>;
+                       interrupt-parent = <&mpic>;
+
+               };
+       };
+
+       soc@fef00000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               #interrupt-cells = <2>;
+               device_type = "soc";
+               compatible = "simple-bus";
+               ranges = <0x0 0xfef00000 0x00100000>;
+               reg = <0xfef00000 0x100000>;    // CCSRBAR 1M
+               bus-frequency = <0>;
+
+               i2c1: i2c@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3000 0x100>;
+                       interrupts = <0x2b 0x2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+
+                       eti@6b {
+                               compatible = "dallas,ds1682";
+                               reg = <0x6b>;
+                       };
+               };
+
+               i2c2: i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3100 0x100>;
+                       interrupts = <0x2b 0x2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
+               dma@21300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+                       reg = <0x21300 0x4>;
+                       ranges = <0x0 0x21100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,mpc8641-dma-channel",
+                                          "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <20 2>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,mpc8641-dma-channel",
+                                          "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <21 2>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,mpc8641-dma-channel",
+                                          "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <22 2>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,mpc8641-dma-channel",
+                                          "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <23 2>;
+                       };
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <0x24520 0x20>;
+
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x9 0x4>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x8 0x4>;
+                               reg = <3>;
+                       };
+               };
+
+               enet0: ethernet@24000 {
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x24000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "gmii";
+               };
+
+               enet1: ethernet@26000 {
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x26000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <0x1f 0x2 0x20 0x2 0x21 0x2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "gmii";
+               };
+
+               serial0: serial@4500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4500 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <0x2a 0x2>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               serial1: serial@4600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4600 0x100>;
+                       clock-frequency = <0>;
+                       interrupts = <0x1c 0x2>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               mpic: pic@40000 {
+                       clock-frequency = <0>;
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+               };
+
+               global-utilities@e0000 {
+                       compatible = "fsl,mpc8641-guts";
+                       reg = <0xe0000 0x1000>;
+                       fsl,has-rstcr;
+               };
+       };
+
+       pci0: pcie@fef08000 {
+               compatible = "fsl,mpc8641-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xfef08000 0x1000>;
+               bus-range = <0x0 0xff>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <0x18 0x2>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+                       0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
+                       0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
+                       0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
+                       0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
+               >;
+
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x40000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00400000>;
+               };
+       };
+};
index 24cf0dba120c89f53933250688783db89cbc627a..f3787a27f6342a2d2a9c17738df5bac9e3a7bd37 100644 (file)
@@ -14,7 +14,7 @@
        #address-cells = <2>;
        #size-cells = <1>;
        model = "amcc,glacier";
-       compatible = "amcc,glacier", "amcc,canyonlands";
+       compatible = "amcc,glacier";
        dcr-parent = <&{/cpus/cpu@0}>;
 
        aliases {
diff --git a/arch/powerpc/boot/dts/mgcoge.dts b/arch/powerpc/boot/dts/mgcoge.dts
new file mode 100644 (file)
index 0000000..633255a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Device Tree for the MGCOGE plattform from keymile
+ *
+ * Copyright 2008 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.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.
+ */
+
+/dts-v1/;
+/ {
+       model = "MGCOGE";
+       compatible = "keymile,mgcoge";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &eth0;
+               serial0 = &smc2;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8247@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <16384>;
+                       i-cache-size = <16384>;
+                       timebase-frequency = <0>; /* Filled in by U-Boot */
+                       clock-frequency = <0>; /* Filled in by U-Boot */
+                       bus-frequency = <0>; /* Filled in by U-Boot */
+               };
+       };
+
+       localbus@f0010100 {
+               compatible = "fsl,mpc8247-localbus",
+                            "fsl,pq2-localbus",
+                            "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               reg = <0xf0010100 0x40>;
+
+               ranges = <0 0 0xfe000000 0x00400000
+                         5 0 0x50000000 0x20000000
+                       >; /* Filled in by U-Boot */
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0x0 0x400000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       bank-width = <1>;
+                       device-width = <1>;
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0 0x40000>;
+                       };
+                       partition@40000 {
+                               label = "env";
+                               reg = <0x40000 0x20000>;
+                       };
+                       partition@60000 {
+                               label = "kernel";
+                               reg = <0x60000 0x220000>;
+                       };
+                       partition@280000 {
+                               label = "dtb";
+                               reg = <0x280000 0x20000>;
+                       };
+               };
+
+               flash@5,0 {
+                       compatible = "cfi-flash";
+                       reg = <5 0x0 0x2000000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       partition@0 {
+                               label = "ramdisk";
+                               reg = <0 0x7a0000>;
+                       };
+                       partition@7a0000 {
+                               label = "user";
+                               reg = <0x7a0000 0x1860000>;
+                       };
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0 0>; /* Filled in by U-Boot */
+       };
+
+       soc@f0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc8247-immr", "fsl,pq2-soc", "simple-bus";
+               ranges = <0x00000000 0xf0000000 0x00053000>;
+
+               // Temporary until code stops depending on it.
+               device_type = "soc";
+
+               cpm@119c0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       #interrupt-cells = <2>;
+                       compatible = "fsl,mpc8247-cpm", "fsl,cpm2",
+                                       "simple-bus";
+                       reg = <0x119c0 0x30>;
+                       ranges;
+
+                       muram {
+                               compatible = "fsl,cpm-muram";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x10000>;
+
+                               data@0 {
+                                       compatible = "fsl,cpm-muram-data";
+                                       reg = <0x80 0x1f80 0x9800 0x800>;
+                               };
+                       };
+
+                       brg@119f0 {
+                               compatible = "fsl,mpc8247-brg",
+                                            "fsl,cpm2-brg",
+                                            "fsl,cpm-brg";
+                               reg = <0x119f0 0x10 0x115f0 0x10>;
+                       };
+
+                       /* Monitor port/SMC2 */
+                       smc2: serial@11a90 {
+                               device_type = "serial";
+                               compatible = "fsl,mpc8247-smc-uart",
+                                            "fsl,cpm2-smc-uart";
+                               reg = <0x11a90 0x20 0x88fc 0x02>;
+                               interrupts = <5 8>;
+                               interrupt-parent = <&PIC>;
+                               fsl,cpm-brg = <2>;
+                               fsl,cpm-command = <0x21200000>;
+                               current-speed = <0>; /* Filled in by U-Boot */
+                       };
+
+                       eth0: ethernet@11a60 {
+                               device_type = "network";
+                               compatible = "fsl,mpc8247-scc-enet",
+                                            "fsl,cpm2-scc-enet";
+                               reg = <0x11a60 0x20 0x8300 0x100 0x11390 1>;
+                               local-mac-address = [ 00 00 00 00 00 00 ]; /* Filled in by U-Boot */
+                               interrupts = <43 8>;
+                               interrupt-parent = <&PIC>;
+                               linux,network-index = <0>;
+                               fsl,cpm-command = <0xce00000>;
+                               fixed-link = <0 0 10 0 0>;
+                       };
+
+               };
+
+               PIC: interrupt-controller@10c00 {
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       reg = <0x10c00 0x80>;
+                       compatible = "fsl,mpc8247-pic", "fsl,pq2-pic";
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mgsuvd.dts b/arch/powerpc/boot/dts/mgsuvd.dts
new file mode 100644 (file)
index 0000000..e4fc53a
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * MGSUVD Device Tree Source
+ *
+ * Copyright 2008 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.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.
+ */
+
+/dts-v1/;
+/ {
+       model = "MGSUVD";
+       compatible = "keymile,mgsuvd";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,852@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <16>;
+                       i-cache-line-size = <16>;
+                       d-cache-size = <8192>;
+                       i-cache-size = <8192>;
+                       timebase-frequency = <0>;       /* Filled in by u-boot */
+                       bus-frequency = <0>;            /* Filled in by u-boot */
+                       clock-frequency = <0>;          /* Filled in by u-boot */
+                       interrupts = <15 2>;            /* decrementer interrupt */
+                       interrupt-parent = <&PIC>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <00000000 0x4000000>;  /* Filled in by u-boot */
+       };
+
+       localbus@fff00100 {
+               compatible = "fsl,mpc852-localbus", "fsl,pq1-localbus", "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               reg = <0xfff00100 0x40>;
+
+               ranges = <0 0 0xf0000000 0x01000000>;  /* Filled in by u-boot */
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x1000000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       bank-width = <1>;
+                       device-width = <1>;
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0 0x80000>;
+                       };
+                       partition@80000 {
+                               label = "env";
+                               reg = <0x80000 0x20000>;
+                       };
+                       partition@a0000 {
+                               label = "kernel";
+                               reg = <0xa0000 0x1e0000>;
+                       };
+                       partition@280000 {
+                               label = "dtb";
+                               reg = <0x280000 0x20000>;
+                       };
+                       partition@2a0000 {
+                               label = "root";
+                               reg = <0x2a0000 0x500000>;
+                       };
+                       partition@7a0000 {
+                               label = "user";
+                               reg = <0x7a0000 0x860000>;
+                       };
+               };
+       };
+
+       soc@fff00000 {
+               compatible = "fsl,mpc852", "fsl,pq1-soc", "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               ranges = <0 0xfff00000 0x00004000>;
+
+               PIC: interrupt-controller@0 {
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       reg = <0 24>;
+                       compatible = "fsl,mpc852-pic", "fsl,pq1-pic";
+               };
+
+               cpm@9c0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,mpc852-cpm", "fsl,cpm1", "simple-bus";
+                       interrupts = <0>;       /* cpm error interrupt */
+                       interrupt-parent = <&CPM_PIC>;
+                       reg = <0x9c0 10>;
+                       ranges;
+
+                       muram@2000 {
+                               compatible = "fsl,cpm-muram";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2000 0x2000>;
+
+                               data@0 {
+                                       compatible = "fsl,cpm-muram-data";
+                                       reg = <0x800 0x1800>;
+                               };
+                       };
+
+                       brg@9f0 {
+                               compatible = "fsl,mpc852-brg",
+                                            "fsl,cpm1-brg",
+                                            "fsl,cpm-brg";
+                               reg = <0x9f0 0x10>;
+                               clock-frequency = <0>; /* Filled in by u-boot */
+                       };
+
+                       CPM_PIC: interrupt-controller@930 {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               interrupts = <5 2 0 2>;
+                               interrupt-parent = <&PIC>;
+                               reg = <0x930 0x20>;
+                               compatible = "fsl,cpm1-pic";
+                       };
+
+                       /* MON-1 */
+                       serial@a80 {
+                               device_type = "serial";
+                               compatible = "fsl,cpm1-smc-uart";
+                               reg = <0xa80 0x10 0x3fc0 0x40>;
+                               interrupts = <4>;
+                               interrupt-parent = <&CPM_PIC>;
+                               fsl,cpm-brg = <1>;
+                               fsl,cpm-command = <0x0090>;
+                               current-speed = <0>; /* Filled in by u-boot */
+                       };
+
+                       ethernet@a40 {
+                               device_type = "network";
+                               compatible  = "fsl,mpc866-scc-enet",
+                                             "fsl,cpm1-scc-enet";
+                               reg = <0xa40 0x18 0x3e00 0x100>;
+                               local-mac-address = [ 00 00 00 00 00 00 ];  /* Filled in by u-boot */
+                               interrupts = <28>;
+                               interrupt-parent = <&CPM_PIC>;
+                               fsl,cpm-command = <0x80>;
+                               fixed-link = <0 0 10 0 0>;
+                       };
+               };
+       };
+};
index 1f9036c317b4ab235e9264705ee38fdd1e2c5d14..c2b8dbfab79e6dc1e4fa5f4b365a06d6f103776f 100644 (file)
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0x80008500 0x100>;
+               reg = <0x80008500 0x100         /* internal registers */
+                      0x80008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc5121-pci";
                device_type = "pci";
        };
index 2a94ae0dc8b875c5c080e69c894838ca21545263..747f27676332f1d1fc243da4f36ad19faa23e328 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8313-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8313-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8313-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8313-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        #interrupt-cells = <1>;
                        #size-cells = <2>;
                        #address-cells = <3>;
-                       reg = <0xe0008500 0x100>;
+                       reg = <0xe0008500 0x100         /* internal registers */
+                              0xe0008300 0x8>;         /* config space access registers */
                        compatible = "fsl,mpc8349-pci";
                        device_type = "pci";
                };
index f704513fb930b5dd6dcf4270e9592ae8368f271c..7449e54c1a908d46e780aa5815c4ef83b71551bb 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8315-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8315-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8315-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8315-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index fbc930410ff6f91f08f9ad16f182906213e2c711..e4cc1768f24165b56446ce5b06a0d4d422f64bbf 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index b157d1885a2884729eeeffe432afb4fe2f9e2d9c..226ff066652ba36e8f5e5c229b643a68c03da49d 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8323-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 700e076ef3f55eb7d47ccde848a1a81ffdaa05c8..5cedf373a1d802e39aba5c21e232b49db2ed71a6 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008600 0x100>;
+               reg = <0xe0008600 0x100         /* internal registers */
+                      0xe0008380 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index cdd3063258ea6a762de3716d49db8a1fe7b748af..81ae1d3e9440ad06be3e14eeb9cb10ce544ae659 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008600 0x100>;
+               reg = <0xe0008600 0x100         /* internal registers */
+                      0xe0008380 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 783241c0024007f1244b7c933159ae454c3b6e94..04bfde3ea605b2ec64cc528c0e64341e89ff8c33 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008600 0x100>;
+               reg = <0xe0008600 0x100         /* internal registers */
+                      0xe0008380 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index a3b76a709951bce3ffee81bc1b2f19204108eee1..66a12d2631fbd4e39b93e3d6c351ed820703d6c9 100644 (file)
                reg = <0x00000000 0x10000000>;
        };
 
-       bcsr@f8000000 {
-               device_type = "board-control";
-               reg = <0xf8000000 0x8000>;
+       localbus@e0005000 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
+                            "simple-bus";
+               reg = <0xe0005000 0xd8>;
+               ranges = <0 0 0xfe000000 0x02000000
+                         1 0 0xf8000000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x2000000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+               };
+
+               bcsr@1,0 {
+                       device_type = "board-control";
+                       reg = <1 0 0x8000>;
+               };
        };
 
        soc8360@e0000000 {
                        dma-channel@0 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 89c9202f8bd784477e1cce9d1e1ed8867842fd38..decadf3d9e989e935faa898c3d56d5d0676531e1 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8360-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        device-width = <1>;
                };
 
+               upm@1,0 {
+                       compatible = "fsl,upm-nand";
+                       reg = <1 0 1>;
+                       fsl,upm-addr-offset = <16>;
+                       fsl,upm-cmd-offset = <8>;
+                       gpios = <&qe_pio_e 18 0>;
+
+                       flash {
+                               compatible = "stm,nand512-a";
+                       };
+               };
+
                display@2,0 {
                        device_type = "display";
                        compatible = "fujitsu,MB86277", "fujitsu,mint";
                #interrupt-cells = <1>;
                device_type = "pci";
                compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci";
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000
                          0x42000000 0 0x80000000 0x80000000 0 0x10000000
                          0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>;
index 432782b6d20ae132ac6644994a9d3cc0dcb2e8f3..0484561bd2c022aab258f40a2ea523144c663339 100644 (file)
                        interrupts = <14 0x8>;
                        interrupt-parent = <&ipic>;
                        dfsrr;
+
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                               interrupts = <19 0x8>;
+                               interrupt-parent = <&ipic>;
+                       };
                };
 
                i2c@3100 {
                        dma-channel@0 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <0x47 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <0x47 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <0x47 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <0x47 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index ed137aa83d5f01d5c4e50442a6d521a1db84c7ce..53191ba67aaa3a1d2493fb8a251b0f437efff167 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index ed32c8ddafe3e0177b6e415fb2556e4c01d99ad2..67a08d2e2ff254fff684ecfc550cd73e680f0318 100644 (file)
                        interrupts = <14 0x8>;
                        interrupt-parent = <&ipic>;
                        dfsrr;
+
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                               interrupts = <19 0x8>;
+                               interrupt-parent = <&ipic>;
+                       };
                };
 
                i2c@3100 {
                        dma-channel@0 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 34a7f2f935e1482d72717d0045fee840a58e69bf..4a09153d160c90967b5b27a0bcfe52cc49561251 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8378-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index f4db9ed4a301e1719aa04df4a5d9d2a4f3ff965c..323370a2b5ff6fa38266e593b66110f8230fc33c 100644 (file)
                        interrupts = <14 0x8>;
                        interrupt-parent = <&ipic>;
                        dfsrr;
+
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                               interrupts = <19 0x8>;
+                               interrupt-parent = <&ipic>;
+                       };
                };
 
                i2c@3100 {
                        dma-channel@0 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index e4d7030d50e558ded5a02f4566d2b5d3cf2a0d08..bbd884ac9dc0e3f84a487f2edb6277416b008cd8 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8379-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 1505d6855eff0eb0e1f5fe7a67c1622b1de6825f..93fdd99901b6e61c9909542ec30338df5b0d8cd8 100644 (file)
@@ -91,6 +91,8 @@
                        rtc@68 {
                                compatible = "dallas,ds3232";
                                reg = <0x68>;
+                               interrupts = <0 0x1>;
+                               interrupt-parent = <&mpic>;
                        };
                };
 
index 584a4f184eb26cddbac0d50c7feb52f406ab7e05..f724d72c7b92db819d2b9229da620938ba6c0104 100644 (file)
                        reg = <0xe4000 0x100>;
                };
 
-               i2s@16000 {
+               ssi@16000 {
                        compatible = "fsl,mpc8610-ssi";
                        cell-index = <0>;
                        reg = <0x16000 0x100>;
                        interrupts = <62 2>;
                        fsl,mode = "i2s-slave";
                        codec-handle = <&cs4270>;
+                       fsl,playback-dma = <&dma00>;
+                       fsl,capture-dma = <&dma01>;
                };
 
                ssi@16100 {
                        reg = <0x21300 0x4>; /* DMA general status register */
                        ranges = <0x0 0x21100 0x200>;
 
-                       dma-channel@0 {
+                       dma00: dma-channel@0 {
                                compatible = "fsl,mpc8610-dma-channel",
-                                       "fsl,eloplus-dma-channel";
+                                       "fsl,ssi-dma-channel";
                                cell-index = <0>;
                                reg = <0x0 0x80>;
                                interrupt-parent = <&mpic>;
                                interrupts = <20 2>;
                        };
-                       dma-channel@1 {
+                       dma01: dma-channel@1 {
                                compatible = "fsl,mpc8610-dma-channel",
-                                       "fsl,eloplus-dma-channel";
+                                       "fsl,ssi-dma-channel";
                                cell-index = <1>;
                                reg = <0x80 0x80>;
                                interrupt-parent = <&mpic>;
index 45f789b56709b410133cb778a4a3c0e736778484..0f941f310e444ae2d209f8195b7f71525cb07ad4 100644 (file)
                        dma-channel@0 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0 0x80>;
+                               cell-index = <0>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@80 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x80 0x80>;
+                               cell-index = <1>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@100 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x100 0x80>;
+                               cell-index = <2>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                        dma-channel@180 {
                                compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
                                reg = <0x180 0x28>;
+                               cell-index = <3>;
                                interrupt-parent = <&ipic>;
                                interrupts = <71 8>;
                        };
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
-               reg = <0xe0008500 0x100>;
+               reg = <0xe0008500 0x100         /* internal registers */
+                      0xe0008300 0x8>;         /* config space access registers */
                compatible = "fsl,mpc8349-pci";
                device_type = "pci";
        };
index 72d15f075d34638a377b27d62355e1e38adf455c..3b295e8df53f10e5e2f6591b57e9871d21631588 100644 (file)
                        };
 
                        IIC0: i2c@ef600700 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                compatible = "ibm,iic-440epx", "ibm,iic";
                                reg = <0xef600700 0x00000014>;
                                interrupt-parent = <&UIC0>;
                                interrupts = <0x2 0x4>;
+
+                               hwmon@48 {
+                                       compatible = "adi,ad7414";
+                                       reg = <0x48>;
+                               };
                        };
 
                        IIC1: i2c@ef600800 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                compatible = "ibm,iic-440epx", "ibm,iic";
                                reg = <0xef600800 0x00000014>;
                                interrupt-parent = <&UIC0>;
index e39422aa0d855e794658c65a79bdab132ecdc3f1..1fa3cb4c4ebb7fd352c3a73c6cdca89623a6df38 100644 (file)
@@ -15,7 +15,7 @@
        #address-cells = <2>;
        #size-cells = <1>;
        model = "amcc,yosemite";
-       compatible = "amcc,yosemite","amcc,bamboo";
+       compatible = "amcc,yosemite";
        dcr-parent = <&{/cpus/cpu@0}>;
 
        aliases {
index 7454aa4cc20c6a76068c4c2a54e0bf910a2becbd..1567a0c0f05c6639a96ce4947dfb9bdf23eda8fc 100644 (file)
@@ -27,7 +27,8 @@ int parse_elf64(void *hdr, struct elf_info *info)
              elf64->e_ident[EI_MAG3]  == ELFMAG3       &&
              elf64->e_ident[EI_CLASS] == ELFCLASS64    &&
              elf64->e_ident[EI_DATA]  == ELFDATA2MSB   &&
-             elf64->e_type            == ET_EXEC       &&
+             (elf64->e_type            == ET_EXEC ||
+              elf64->e_type            == ET_DYN)      &&
              elf64->e_machine         == EM_PPC64))
                return 0;
 
@@ -58,7 +59,8 @@ int parse_elf32(void *hdr, struct elf_info *info)
              elf32->e_ident[EI_MAG3]  == ELFMAG3       &&
              elf32->e_ident[EI_CLASS] == ELFCLASS32    &&
              elf32->e_ident[EI_DATA]  == ELFDATA2MSB   &&
-             elf32->e_type            == ET_EXEC       &&
+             (elf32->e_type            == ET_EXEC ||
+              elf32->e_type            == ET_DYN)      &&
              elf32->e_machine         == EM_PPC))
                return 0;
 
index 82f9c6a8287b8a7793efdd8f58118f45d7020d34..6c42acfa21ec61282dd53f67dbb70c795c5cc649 100644 (file)
@@ -3,12 +3,6 @@
 # This is not a complete Makefile of itself.  Instead, it is designed to
 # be easily embeddable into other systems of Makefiles.
 #
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_EXTRA = libfdt_internal.h
-LIBFDT_LIB = libfdt/libfdt.a
-
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
-
-$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
-
index 586a36136db215fbffb450cfa475403d6755c311..2acaec5923aea4fc5cb3f8360a1e6105f7c99897 100644 (file)
@@ -63,7 +63,7 @@ int fdt_check_header(const void *fdt)
                        return -FDT_ERR_BADVERSION;
                if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
                        return -FDT_ERR_BADVERSION;
-       } else if (fdt_magic(fdt) == SW_MAGIC) {
+       } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
                /* Unfinished sequential-write blob */
                if (fdt_size_dt_struct(fdt) == 0)
                        return -FDT_ERR_BADSTATE;
@@ -76,7 +76,7 @@ int fdt_check_header(const void *fdt)
 
 const void *fdt_offset_ptr(const void *fdt, int offset, int len)
 {
-       const void *p;
+       const char *p;
 
        if (fdt_version(fdt) >= 0x11)
                if (((offset + len) < offset)
@@ -124,11 +124,59 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
        }
 
        if (nextoffset)
-               *nextoffset = ALIGN(offset, FDT_TAGSIZE);
+               *nextoffset = FDT_TAGALIGN(offset);
 
        return tag;
 }
 
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+       if ((offset < 0) || (offset % FDT_TAGSIZE)
+           || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+               return -FDT_ERR_BADOFFSET;
+
+       return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+       int nextoffset = 0;
+       uint32_t tag;
+
+       if (offset >= 0)
+               if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+                       return nextoffset;
+
+       do {
+               offset = nextoffset;
+               tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+               switch (tag) {
+               case FDT_PROP:
+               case FDT_NOP:
+                       break;
+
+               case FDT_BEGIN_NODE:
+                       if (depth)
+                               (*depth)++;
+                       break;
+
+               case FDT_END_NODE:
+                       if (depth)
+                               (*depth)--;
+                       break;
+
+               case FDT_END:
+                       return -FDT_ERR_NOTFOUND;
+
+               default:
+                       return -FDT_ERR_BADSTRUCTURE;
+               }
+       } while (tag != FDT_BEGIN_NODE);
+
+       return offset;
+}
+
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 {
        int len = strlen(s) + 1;
@@ -136,17 +184,14 @@ const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
        const char *p;
 
        for (p = strtab; p <= last; p++)
-               if (memeq(p, s, len))
+               if (memcmp(p, s, len) == 0)
                        return p;
        return NULL;
 }
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-       int err = fdt_check_header(fdt);
-
-       if (err)
-               return err;
+       FDT_CHECK_HEADER(fdt);
 
        if (fdt_totalsize(fdt) > bufsize)
                return -FDT_ERR_NOSPACE;
index 12a37d59f96eba267235cf06962f7ccc7a6c2259..129b532bcc1a8f9752caf666a0b1e45956e926eb 100644 (file)
 
 #include "libfdt_internal.h"
 
-#define CHECK_HEADER(fdt) \
-       { \
-               int err; \
-               if ((err = fdt_check_header(fdt)) != 0) \
-                       return err; \
-       }
-
-static int nodename_eq(const void *fdt, int offset,
-                      const char *s, int len)
+static int _fdt_nodename_eq(const void *fdt, int offset,
+                           const char *s, int len)
 {
-       const char *p = fdt_offset_ptr(fdt, offset, len+1);
+       const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
 
        if (! p)
                /* short match */
@@ -84,12 +77,12 @@ static int nodename_eq(const void *fdt, int offset,
 
 const char *fdt_string(const void *fdt, int stroffset)
 {
-       return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+       return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
 }
 
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
        *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
        *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
        return 0;
@@ -104,50 +97,24 @@ int fdt_num_mem_rsv(const void *fdt)
        return i;
 }
 
-int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
                               const char *name, int namelen)
 {
-       int level = 0;
-       uint32_t tag;
-       int offset, nextoffset;
-
-       CHECK_HEADER(fdt);
-
-       tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               return -FDT_ERR_BADOFFSET;
-
-       do {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-               switch (tag) {
-               case FDT_END:
-                       return -FDT_ERR_TRUNCATED;
-
-               case FDT_BEGIN_NODE:
-                       level++;
-                       if (level != 1)
-                               continue;
-                       if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
-                               /* Found it! */
-                               return offset;
-                       break;
-
-               case FDT_END_NODE:
-                       level--;
-                       break;
+       int depth;
 
-               case FDT_PROP:
-               case FDT_NOP:
-                       break;
+       FDT_CHECK_HEADER(fdt);
 
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
-               }
-       } while (level >= 0);
+       for (depth = 0;
+            offset >= 0;
+            offset = fdt_next_node(fdt, offset, &depth)) {
+               if (depth < 0)
+                       return -FDT_ERR_NOTFOUND;
+               else if ((depth == 1)
+                        && _fdt_nodename_eq(fdt, offset, name, namelen))
+                       return offset;
+       }
 
-       return -FDT_ERR_NOTFOUND;
+       return offset; /* error */
 }
 
 int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -162,7 +129,7 @@ int fdt_path_offset(const void *fdt, const char *path)
        const char *p = path;
        int offset = 0;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        if (*path != '/')
                return -FDT_ERR_BADPATH;
@@ -190,16 +157,12 @@ int fdt_path_offset(const void *fdt, const char *path)
 
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
 {
-       const struct fdt_node_header *nh;
+       const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
        int err;
 
-       if ((err = fdt_check_header(fdt)) != 0)
-               goto fail;
-
-       err = -FDT_ERR_BADOFFSET;
-       nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
-       if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
-               goto fail;
+       if (((err = fdt_check_header(fdt)) != 0)
+           || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+                       goto fail;
 
        if (len)
                *len = strlen(nh->name);
@@ -222,17 +185,11 @@ const struct fdt_property *fdt_get_property(const void *fdt,
        int offset, nextoffset;
        int err;
 
-       if ((err = fdt_check_header(fdt)) != 0)
-               goto fail;
-
-       err = -FDT_ERR_BADOFFSET;
-       if (nodeoffset % FDT_TAGSIZE)
-               goto fail;
-
-       tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               goto fail;
+       if (((err = fdt_check_header(fdt)) != 0)
+           || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+                       goto fail;
 
+       nextoffset = err;
        do {
                offset = nextoffset;
 
@@ -253,7 +210,7 @@ const struct fdt_property *fdt_get_property(const void *fdt,
                        if (! prop)
                                goto fail;
                        namestroff = fdt32_to_cpu(prop->nameoff);
-                       if (streq(fdt_string(fdt, namestroff), name)) {
+                       if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
                                /* Found it! */
                                int len = fdt32_to_cpu(prop->len);
                                prop = fdt_offset_ptr(fdt, offset,
@@ -307,115 +264,91 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 
 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 {
-       uint32_t tag;
-       int p = 0, overflow = 0;
-       int offset, nextoffset, namelen;
+       int pdepth = 0, p = 0;
+       int offset, depth, namelen;
        const char *name;
 
-       CHECK_HEADER(fdt);
-
-       tag = fdt_next_tag(fdt, 0, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               return -FDT_ERR_BADSTRUCTURE;
+       FDT_CHECK_HEADER(fdt);
 
        if (buflen < 2)
                return -FDT_ERR_NOSPACE;
-       buf[0] = '/';
-       p = 1;
 
-       while (nextoffset <= nodeoffset) {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-               switch (tag) {
-               case FDT_END:
-                       return -FDT_ERR_BADOFFSET;
+       for (offset = 0, depth = 0;
+            (offset >= 0) && (offset <= nodeoffset);
+            offset = fdt_next_node(fdt, offset, &depth)) {
+               if (pdepth < depth)
+                       continue; /* overflowed buffer */
 
-               case FDT_BEGIN_NODE:
-                       name = fdt_get_name(fdt, offset, &namelen);
-                       if (!name)
-                               return namelen;
-                       if (overflow || ((p + namelen + 1) > buflen)) {
-                               overflow++;
-                               break;
-                       }
+               while (pdepth > depth) {
+                       do {
+                               p--;
+                       } while (buf[p-1] != '/');
+                       pdepth--;
+               }
+
+               name = fdt_get_name(fdt, offset, &namelen);
+               if (!name)
+                       return namelen;
+               if ((p + namelen + 1) <= buflen) {
                        memcpy(buf + p, name, namelen);
                        p += namelen;
                        buf[p++] = '/';
-                       break;
-
-               case FDT_END_NODE:
-                       if (overflow) {
-                               overflow--;
-                               break;
-                       }
-                       do {
-                               p--;
-                       } while  (buf[p-1] != '/');
-                       break;
+                       pdepth++;
+               }
 
-               case FDT_PROP:
-               case FDT_NOP:
-                       break;
+               if (offset == nodeoffset) {
+                       if (pdepth < (depth + 1))
+                               return -FDT_ERR_NOSPACE;
 
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
+                       if (p > 1) /* special case so that root path is "/", not "" */
+                               p--;
+                       buf[p] = '\0';
+                       return p;
                }
        }
 
-       if (overflow)
-               return -FDT_ERR_NOSPACE;
+       if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+               return -FDT_ERR_BADOFFSET;
+       else if (offset == -FDT_ERR_BADOFFSET)
+               return -FDT_ERR_BADSTRUCTURE;
 
-       if (p > 1) /* special case so that root path is "/", not "" */
-               p--;
-       buf[p] = '\0';
-       return p;
+       return offset; /* error from fdt_next_node() */
 }
 
 int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
                                 int supernodedepth, int *nodedepth)
 {
-       int level = -1;
-       uint32_t tag;
-       int offset, nextoffset = 0;
+       int offset, depth;
        int supernodeoffset = -FDT_ERR_INTERNAL;
 
-       CHECK_HEADER(fdt);
+       FDT_CHECK_HEADER(fdt);
 
        if (supernodedepth < 0)
                return -FDT_ERR_NOTFOUND;
 
-       do {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-               switch (tag) {
-               case FDT_END:
-                       return -FDT_ERR_BADOFFSET;
-
-               case FDT_BEGIN_NODE:
-                       level++;
-                       if (level == supernodedepth)
-                               supernodeoffset = offset;
-                       break;
-
-               case FDT_END_NODE:
-                       level--;
-                       break;
+       for (offset = 0, depth = 0;
+            (offset >= 0) && (offset <= nodeoffset);
+            offset = fdt_next_node(fdt, offset, &depth)) {
+               if (depth == supernodedepth)
+                       supernodeoffset = offset;
 
-               case FDT_PROP:
-               case FDT_NOP:
-                       break;
+               if (offset == nodeoffset) {
+                       if (nodedepth)
+                               *nodedepth = depth;
 
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
+                       if (supernodedepth > depth)
+                               return -FDT_ERR_NOTFOUND;
+                       else
+                               return supernodeoffset;
                }
-       } while (offset < nodeoffset);
+       }
 
-       if (nodedepth)
-               *nodedepth = level;
+       if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+               return -FDT_ERR_BADOFFSET;
+       else if (offset == -FDT_ERR_BADOFFSET)
+               return -FDT_ERR_BADSTRUCTURE;
 
-       if (supernodedepth > level)
-               return -FDT_ERR_NOTFOUND;
-       return supernodeoffset;
+       return offset; /* error from fdt_next_node() */
 }
 
 int fdt_node_depth(const void *fdt, int nodeoffset)
@@ -443,51 +376,27 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
                                  const char *propname,
                                  const void *propval, int proplen)
 {
-       uint32_t tag;
-       int offset, nextoffset;
+       int offset;
        const void *val;
        int len;
 
-       CHECK_HEADER(fdt);
-
-       if (startoffset >= 0) {
-               tag = fdt_next_tag(fdt, startoffset, &nextoffset);
-               if (tag != FDT_BEGIN_NODE)
-                       return -FDT_ERR_BADOFFSET;
-       } else {
-               nextoffset = 0;
-       }
+       FDT_CHECK_HEADER(fdt);
 
        /* FIXME: The algorithm here is pretty horrible: we scan each
         * property of a node in fdt_getprop(), then if that didn't
         * find what we want, we scan over them again making our way
         * to the next node.  Still it's the easiest to implement
         * approach; performance can come later. */
-       do {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-               switch (tag) {
-               case FDT_BEGIN_NODE:
-                       val = fdt_getprop(fdt, offset, propname, &len);
-                       if (val
-                           && (len == proplen)
-                           && (memcmp(val, propval, len) == 0))
-                               return offset;
-                       break;
-
-               case FDT_PROP:
-               case FDT_END:
-               case FDT_END_NODE:
-               case FDT_NOP:
-                       break;
-
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
-               }
-       } while (tag != FDT_END);
+       for (offset = fdt_next_node(fdt, startoffset, NULL);
+            offset >= 0;
+            offset = fdt_next_node(fdt, offset, NULL)) {
+               val = fdt_getprop(fdt, offset, propname, &len);
+               if (val && (len == proplen)
+                   && (memcmp(val, propval, len) == 0))
+                       return offset;
+       }
 
-       return -FDT_ERR_NOTFOUND;
+       return offset; /* error from fdt_next_node() */
 }
 
 int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
@@ -499,10 +408,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
                                             &phandle, sizeof(phandle));
 }
 
-int _stringlist_contains(const void *strlist, int listlen, const char *str)
+int _stringlist_contains(const char *strlist, int listlen, const char *str)
 {
        int len = strlen(str);
-       const void *p;
+       const char *p;
 
        while (listlen >= len) {
                if (memcmp(str, strlist, len+1) == 0)
@@ -534,50 +443,24 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
                                  const char *compatible)
 {
-       uint32_t tag;
-       int offset, nextoffset;
-       int err;
-
-       CHECK_HEADER(fdt);
+       int offset, err;
 
-       if (startoffset >= 0) {
-               tag = fdt_next_tag(fdt, startoffset, &nextoffset);
-               if (tag != FDT_BEGIN_NODE)
-                       return -FDT_ERR_BADOFFSET;
-       } else {
-               nextoffset = 0;
-       }
+       FDT_CHECK_HEADER(fdt);
 
        /* FIXME: The algorithm here is pretty horrible: we scan each
         * property of a node in fdt_node_check_compatible(), then if
         * that didn't find what we want, we scan over them again
         * making our way to the next node.  Still it's the easiest to
         * implement approach; performance can come later. */
-       do {
-               offset = nextoffset;
-               tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-               switch (tag) {
-               case FDT_BEGIN_NODE:
-                       err = fdt_node_check_compatible(fdt, offset,
-                                                       compatible);
-                       if ((err < 0)
-                           && (err != -FDT_ERR_NOTFOUND))
-                               return err;
-                       else if (err == 0)
-                               return offset;
-                       break;
-
-               case FDT_PROP:
-               case FDT_END:
-               case FDT_END_NODE:
-               case FDT_NOP:
-                       break;
-
-               default:
-                       return -FDT_ERR_BADSTRUCTURE;
-               }
-       } while (tag != FDT_END);
+       for (offset = fdt_next_node(fdt, startoffset, NULL);
+            offset >= 0;
+            offset = fdt_next_node(fdt, offset, NULL)) {
+               err = fdt_node_check_compatible(fdt, offset, compatible);
+               if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+                       return err;
+               else if (err == 0)
+                       return offset;
+       }
 
-       return -FDT_ERR_NOTFOUND;
+       return offset; /* error from fdt_next_node() */
 }
index 6673f8ec962ad39510e25a36a56a3fd5cd5650d8..8e7ec4cb7bcdc91abe0e4b77e5f2ffdd0b5d0a00 100644 (file)
 
 #include "libfdt_internal.h"
 
-static int _blocks_misordered(const void *fdt,
+static int _fdt_blocks_misordered(const void *fdt,
                              int mem_rsv_size, int struct_size)
 {
-       return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
+       return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
                || (fdt_off_dt_struct(fdt) <
                    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
                || (fdt_off_dt_strings(fdt) <
@@ -67,16 +67,14 @@ static int _blocks_misordered(const void *fdt,
                    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 }
 
-static int rw_check_header(void *fdt)
+static int _fdt_rw_check_header(void *fdt)
 {
-       int err;
+       FDT_CHECK_HEADER(fdt);
 
-       if ((err = fdt_check_header(fdt)))
-               return err;
        if (fdt_version(fdt) < 17)
                return -FDT_ERR_BADVERSION;
-       if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
-                              fdt_size_dt_struct(fdt)))
+       if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+                                  fdt_size_dt_struct(fdt)))
                return -FDT_ERR_BADLAYOUT;
        if (fdt_version(fdt) > 17)
                fdt_set_version(fdt, 17);
@@ -84,36 +82,37 @@ static int rw_check_header(void *fdt)
        return 0;
 }
 
-#define RW_CHECK_HEADER(fdt) \
+#define FDT_RW_CHECK_HEADER(fdt) \
        { \
                int err; \
-               if ((err = rw_check_header(fdt)) != 0) \
+               if ((err = _fdt_rw_check_header(fdt)) != 0) \
                        return err; \
        }
 
-static inline int _blob_data_size(void *fdt)
+static inline int _fdt_data_size(void *fdt)
 {
        return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 }
 
-static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
 {
-       void *end = fdt + _blob_data_size(fdt);
+       char *p = splicepoint;
+       char *end = (char *)fdt + _fdt_data_size(fdt);
 
        if (((p + oldlen) < p) || ((p + oldlen) > end))
                return -FDT_ERR_BADOFFSET;
-       if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
+       if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
                return -FDT_ERR_NOSPACE;
        memmove(p + newlen, p + oldlen, end - p - oldlen);
        return 0;
 }
 
-static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
-                               int oldn, int newn)
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+                              int oldn, int newn)
 {
        int delta = (newn - oldn) * sizeof(*p);
        int err;
-       err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+       err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
        if (err)
                return err;
        fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
@@ -121,13 +120,13 @@ static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
        return 0;
 }
 
-static int _blob_splice_struct(void *fdt, void *p,
-                              int oldlen, int newlen)
+static int _fdt_splice_struct(void *fdt, void *p,
+                             int oldlen, int newlen)
 {
        int delta = newlen - oldlen;
        int err;
 
-       if ((err = _blob_splice(fdt, p, oldlen, newlen)))
+       if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
                return err;
 
        fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@@ -135,19 +134,20 @@ static int _blob_splice_struct(void *fdt, void *p,
        return 0;
 }
 
-static int _blob_splice_string(void *fdt, int newlen)
+static int _fdt_splice_string(void *fdt, int newlen)
 {
-       void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+       void *p = (char *)fdt
+               + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
        int err;
 
-       if ((err = _blob_splice(fdt, p, 0, newlen)))
+       if ((err = _fdt_splice(fdt, p, 0, newlen)))
                return err;
 
        fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
        return 0;
 }
 
-static int _find_add_string(void *fdt, const char *s)
+static int _fdt_find_add_string(void *fdt, const char *s)
 {
        char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
        const char *p;
@@ -161,7 +161,7 @@ static int _find_add_string(void *fdt, const char *s)
                return (p - strtab);
 
        new = strtab + fdt_size_dt_strings(fdt);
-       err = _blob_splice_string(fdt, len);
+       err = _fdt_splice_string(fdt, len);
        if (err)
                return err;
 
@@ -174,11 +174,10 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
        struct fdt_reserve_entry *re;
        int err;
 
-       if ((err = rw_check_header(fdt)))
-               return err;
+       FDT_RW_CHECK_HEADER(fdt);
 
        re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
-       err = _blob_splice_mem_rsv(fdt, re, 0, 1);
+       err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
        if (err)
                return err;
 
@@ -192,19 +191,19 @@ int fdt_del_mem_rsv(void *fdt, int n)
        struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
        int err;
 
-       if ((err = rw_check_header(fdt)))
-               return err;
+       FDT_RW_CHECK_HEADER(fdt);
+
        if (n >= fdt_num_mem_rsv(fdt))
                return -FDT_ERR_NOTFOUND;
 
-       err = _blob_splice_mem_rsv(fdt, re, 1, 0);
+       err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
        if (err)
                return err;
        return 0;
 }
 
-static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
-                           struct fdt_property **prop)
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+                               int len, struct fdt_property **prop)
 {
        int oldlen;
        int err;
@@ -213,36 +212,33 @@ static int _resize_property(void *fdt, int nodeoffset, const char *name, int len
        if (! (*prop))
                return oldlen;
 
-       if ((err = _blob_splice_struct(fdt, (*prop)->data,
-                                      ALIGN(oldlen, FDT_TAGSIZE),
-                                      ALIGN(len, FDT_TAGSIZE))))
+       if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+                                     FDT_TAGALIGN(len))))
                return err;
 
        (*prop)->len = cpu_to_fdt32(len);
        return 0;
 }
 
-static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
-                        struct fdt_property **prop)
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+                            int len, struct fdt_property **prop)
 {
-       uint32_t tag;
        int proplen;
        int nextoffset;
        int namestroff;
        int err;
 
-       tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
-       if (tag != FDT_BEGIN_NODE)
-               return -FDT_ERR_BADOFFSET;
+       if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+               return nextoffset;
 
-       namestroff = _find_add_string(fdt, name);
+       namestroff = _fdt_find_add_string(fdt, name);
        if (namestroff < 0)
                return namestroff;
 
        *prop = _fdt_offset_ptr_w(fdt, nextoffset);
-       proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
+       proplen = sizeof(**prop) + FDT_TAGALIGN(len);
 
-       err = _blob_splice_struct(fdt, *prop, 0, proplen);
+       err = _fdt_splice_struct(fdt, *prop, 0, proplen);
        if (err)
                return err;
 
@@ -252,18 +248,40 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
        return 0;
 }
 
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+       char *namep;
+       int oldlen, newlen;
+       int err;
+
+       FDT_RW_CHECK_HEADER(fdt);
+
+       namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+       if (!namep)
+               return oldlen;
+
+       newlen = strlen(name);
+
+       err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+                                FDT_TAGALIGN(newlen+1));
+       if (err)
+               return err;
+
+       memcpy(namep, name, newlen+1);
+       return 0;
+}
+
 int fdt_setprop(void *fdt, int nodeoffset, const char *name,
                const void *val, int len)
 {
        struct fdt_property *prop;
        int err;
 
-       if ((err = rw_check_header(fdt)))
-               return err;
+       FDT_RW_CHECK_HEADER(fdt);
 
-       err = _resize_property(fdt, nodeoffset, name, len, &prop);
+       err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
        if (err == -FDT_ERR_NOTFOUND)
-               err = _add_property(fdt, nodeoffset, name, len, &prop);
+               err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
        if (err)
                return err;
 
@@ -276,14 +294,14 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
        struct fdt_property *prop;
        int len, proplen;
 
-       RW_CHECK_HEADER(fdt);
+       FDT_RW_CHECK_HEADER(fdt);
 
        prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
        if (! prop)
                return len;
 
-       proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
-       return _blob_splice_struct(fdt, prop, proplen, 0);
+       proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+       return _fdt_splice_struct(fdt, prop, proplen, 0);
 }
 
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -296,7 +314,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
        uint32_t tag;
        uint32_t *endtag;
 
-       RW_CHECK_HEADER(fdt);
+       FDT_RW_CHECK_HEADER(fdt);
 
        offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
        if (offset >= 0)
@@ -309,19 +327,19 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
        do {
                offset = nextoffset;
                tag = fdt_next_tag(fdt, offset, &nextoffset);
-       } while (tag == FDT_PROP);
+       } while ((tag == FDT_PROP) || (tag == FDT_NOP));
 
        nh = _fdt_offset_ptr_w(fdt, offset);
-       nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
+       nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
 
-       err = _blob_splice_struct(fdt, nh, 0, nodelen);
+       err = _fdt_splice_struct(fdt, nh, 0, nodelen);
        if (err)
                return err;
 
        nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
-       memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
+       memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
        memcpy(nh->name, name, namelen);
-       endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
+       endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
        *endtag = cpu_to_fdt32(FDT_END_NODE);
 
        return offset;
@@ -336,36 +354,36 @@ int fdt_del_node(void *fdt, int nodeoffset)
 {
        int endoffset;
 
-       RW_CHECK_HEADER(fdt);
+       FDT_RW_CHECK_HEADER(fdt);
 
        endoffset = _fdt_node_end_offset(fdt, nodeoffset);
        if (endoffset < 0)
                return endoffset;
 
-       return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
-                                  endoffset - nodeoffset, 0);
+       return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+                                 endoffset - nodeoffset, 0);
 }
 
-static void _packblocks(const void *fdt, void *buf,
-                      int mem_rsv_size, int struct_size)
+static void _fdt_packblocks(const char *old, char *new,
+                           int mem_rsv_size, int struct_size)
 {
        int mem_rsv_off, struct_off, strings_off;
 
-       mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8);
+       mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
        struct_off = mem_rsv_off + mem_rsv_size;
        strings_off = struct_off + struct_size;
 
-       memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size);
-       fdt_set_off_mem_rsvmap(buf, mem_rsv_off);
+       memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+       fdt_set_off_mem_rsvmap(new, mem_rsv_off);
 
-       memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size);
-       fdt_set_off_dt_struct(buf, struct_off);
-       fdt_set_size_dt_struct(buf, struct_size);
+       memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+       fdt_set_off_dt_struct(new, struct_off);
+       fdt_set_size_dt_struct(new, struct_size);
 
-       memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt),
-               fdt_size_dt_strings(fdt));
-       fdt_set_off_dt_strings(buf, strings_off);
-       fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt));
+       memmove(new + strings_off, old + fdt_off_dt_strings(old),
+               fdt_size_dt_strings(old));
+       fdt_set_off_dt_strings(new, strings_off);
+       fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
 }
 
 int fdt_open_into(const void *fdt, void *buf, int bufsize)
@@ -373,11 +391,11 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
        int err;
        int mem_rsv_size, struct_size;
        int newsize;
-       void *tmp;
+       const char *fdtstart = fdt;
+       const char *fdtend = fdtstart + fdt_totalsize(fdt);
+       char *tmp;
 
-       err = fdt_check_header(fdt);
-       if (err)
-               return err;
+       FDT_CHECK_HEADER(fdt);
 
        mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
                * sizeof(struct fdt_reserve_entry);
@@ -390,7 +408,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
                        ;
        }
 
-       if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+       if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
                /* no further work necessary */
                err = fdt_move(fdt, buf, bufsize);
                if (err)
@@ -402,22 +420,23 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
        }
 
        /* Need to reorder */
-       newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+       newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
                + struct_size + fdt_size_dt_strings(fdt);
 
        if (bufsize < newsize)
                return -FDT_ERR_NOSPACE;
 
-       if (((buf + newsize) <= fdt)
-           || (buf >= (fdt + fdt_totalsize(fdt)))) {
-               tmp = buf;
-       } else {
-               tmp = (void *)fdt + fdt_totalsize(fdt);
-               if ((tmp + newsize) > (buf + bufsize))
+       /* First attempt to build converted tree at beginning of buffer */
+       tmp = buf;
+       /* But if that overlaps with the old tree... */
+       if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+               /* Try right after the old tree instead */
+               tmp = (char *)(uintptr_t)fdtend;
+               if ((tmp + newsize) > ((char *)buf + bufsize))
                        return -FDT_ERR_NOSPACE;
        }
 
-       _packblocks(fdt, tmp, mem_rsv_size, struct_size);
+       _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
        memmove(buf, tmp, newsize);
 
        fdt_set_magic(buf, FDT_MAGIC);
@@ -432,16 +451,13 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
 int fdt_pack(void *fdt)
 {
        int mem_rsv_size;
-       int err;
 
-       err = rw_check_header(fdt);
-       if (err)
-               return err;
+       FDT_RW_CHECK_HEADER(fdt);
 
        mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
                * sizeof(struct fdt_reserve_entry);
-       _packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
-       fdt_set_totalsize(fdt, _blob_data_size(fdt));
+       _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+       fdt_set_totalsize(fdt, _fdt_data_size(fdt));
 
        return 0;
 }
index f9d32ef5360ab7acc84f23df066621b18f01f646..e6c3ceee8c58c56beee386e6ed730e32c4ff646b 100644 (file)
 
 #include "libfdt_internal.h"
 
-struct errtabent {
+struct fdt_errtabent {
        const char *str;
 };
 
-#define ERRTABENT(val) \
+#define FDT_ERRTABENT(val) \
        [(val)] = { .str = #val, }
 
-static struct errtabent errtable[] = {
-       ERRTABENT(FDT_ERR_NOTFOUND),
-       ERRTABENT(FDT_ERR_EXISTS),
-       ERRTABENT(FDT_ERR_NOSPACE),
+static struct fdt_errtabent fdt_errtable[] = {
+       FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+       FDT_ERRTABENT(FDT_ERR_EXISTS),
+       FDT_ERRTABENT(FDT_ERR_NOSPACE),
 
-       ERRTABENT(FDT_ERR_BADOFFSET),
-       ERRTABENT(FDT_ERR_BADPATH),
-       ERRTABENT(FDT_ERR_BADSTATE),
+       FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+       FDT_ERRTABENT(FDT_ERR_BADPATH),
+       FDT_ERRTABENT(FDT_ERR_BADSTATE),
 
-       ERRTABENT(FDT_ERR_TRUNCATED),
-       ERRTABENT(FDT_ERR_BADMAGIC),
-       ERRTABENT(FDT_ERR_BADVERSION),
-       ERRTABENT(FDT_ERR_BADSTRUCTURE),
-       ERRTABENT(FDT_ERR_BADLAYOUT),
+       FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+       FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+       FDT_ERRTABENT(FDT_ERR_BADVERSION),
+       FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+       FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
 };
-#define ERRTABSIZE     (sizeof(errtable) / sizeof(errtable[0]))
+#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
 
 const char *fdt_strerror(int errval)
 {
@@ -85,8 +85,8 @@ const char *fdt_strerror(int errval)
                return "<valid offset/length>";
        else if (errval == 0)
                return "<no error>";
-       else if (errval > -ERRTABSIZE) {
-               const char *s = errtable[-errval].str;
+       else if (errval > -FDT_ERRTABSIZE) {
+               const char *s = fdt_errtable[-errval].str;
 
                if (s)
                        return s;
index dda2de34b2e0a968463cf808b669b37e226620df..698329e0ccaf8f94d2e333b277a78ab3dcff9adc 100644 (file)
 
 #include "libfdt_internal.h"
 
-static int check_header_sw(void *fdt)
+static int _fdt_sw_check_header(void *fdt)
 {
-       if (fdt_magic(fdt) != SW_MAGIC)
+       if (fdt_magic(fdt) != FDT_SW_MAGIC)
                return -FDT_ERR_BADMAGIC;
+       /* FIXME: should check more details about the header state */
        return 0;
 }
 
-static void *grab_space(void *fdt, int len)
+#define FDT_SW_CHECK_HEADER(fdt) \
+       { \
+               int err; \
+               if ((err = _fdt_sw_check_header(fdt)) != 0) \
+                       return err; \
+       }
+
+static void *_fdt_grab_space(void *fdt, int len)
 {
        int offset = fdt_size_dt_struct(fdt);
        int spaceleft;
@@ -86,13 +94,13 @@ int fdt_create(void *buf, int bufsize)
 
        memset(buf, 0, bufsize);
 
-       fdt_set_magic(fdt, SW_MAGIC);
+       fdt_set_magic(fdt, FDT_SW_MAGIC);
        fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
        fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
        fdt_set_totalsize(fdt,  bufsize);
 
-       fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
-                                         sizeof(struct fdt_reserve_entry)));
+       fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+                                             sizeof(struct fdt_reserve_entry)));
        fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
        fdt_set_off_dt_strings(fdt, bufsize);
 
@@ -102,11 +110,10 @@ int fdt_create(void *buf, int bufsize)
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
 {
        struct fdt_reserve_entry *re;
-       int err = check_header_sw(fdt);
        int offset;
 
-       if (err)
-               return err;
+       FDT_SW_CHECK_HEADER(fdt);
+
        if (fdt_size_dt_struct(fdt))
                return -FDT_ERR_BADSTATE;
 
@@ -114,7 +121,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
        if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
                return -FDT_ERR_NOSPACE;
 
-       re = (struct fdt_reserve_entry *)(fdt + offset);
+       re = (struct fdt_reserve_entry *)((char *)fdt + offset);
        re->address = cpu_to_fdt64(addr);
        re->size = cpu_to_fdt64(size);
 
@@ -131,13 +138,11 @@ int fdt_finish_reservemap(void *fdt)
 int fdt_begin_node(void *fdt, const char *name)
 {
        struct fdt_node_header *nh;
-       int err = check_header_sw(fdt);
        int namelen = strlen(name) + 1;
 
-       if (err)
-               return err;
+       FDT_SW_CHECK_HEADER(fdt);
 
-       nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
+       nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
        if (! nh)
                return -FDT_ERR_NOSPACE;
 
@@ -149,12 +154,10 @@ int fdt_begin_node(void *fdt, const char *name)
 int fdt_end_node(void *fdt)
 {
        uint32_t *en;
-       int err = check_header_sw(fdt);
 
-       if (err)
-               return err;
+       FDT_SW_CHECK_HEADER(fdt);
 
-       en = grab_space(fdt, FDT_TAGSIZE);
+       en = _fdt_grab_space(fdt, FDT_TAGSIZE);
        if (! en)
                return -FDT_ERR_NOSPACE;
 
@@ -162,7 +165,7 @@ int fdt_end_node(void *fdt)
        return 0;
 }
 
-static int find_add_string(void *fdt, const char *s)
+static int _fdt_find_add_string(void *fdt, const char *s)
 {
        char *strtab = (char *)fdt + fdt_totalsize(fdt);
        const char *p;
@@ -188,17 +191,15 @@ static int find_add_string(void *fdt, const char *s)
 int fdt_property(void *fdt, const char *name, const void *val, int len)
 {
        struct fdt_property *prop;
-       int err = check_header_sw(fdt);
        int nameoff;
 
-       if (err)
-               return err;
+       FDT_SW_CHECK_HEADER(fdt);
 
-       nameoff = find_add_string(fdt, name);
+       nameoff = _fdt_find_add_string(fdt, name);
        if (nameoff == 0)
                return -FDT_ERR_NOSPACE;
 
-       prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
+       prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
        if (! prop)
                return -FDT_ERR_NOSPACE;
 
@@ -211,18 +212,16 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
 
 int fdt_finish(void *fdt)
 {
-       int err = check_header_sw(fdt);
        char *p = (char *)fdt;
        uint32_t *end;
        int oldstroffset, newstroffset;
        uint32_t tag;
        int offset, nextoffset;
 
-       if (err)
-               return err;
+       FDT_SW_CHECK_HEADER(fdt);
 
        /* Add terminator */
-       end = grab_space(fdt, sizeof(*end));
+       end = _fdt_grab_space(fdt, sizeof(*end));
        if (! end)
                return -FDT_ERR_NOSPACE;
        *end = cpu_to_fdt32(FDT_END);
index 88e24b8318f449e4ab7902fc27b4e7345948299d..a4652c6e787ec8ef6823454eaa4c8932343863e2 100644 (file)
@@ -72,11 +72,11 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
        return 0;
 }
 
-static void nop_region(void *start, int len)
+static void _fdt_nop_region(void *start, int len)
 {
        uint32_t *p;
 
-       for (p = start; (void *)p < (start + len); p++)
+       for (p = start; (char *)p < ((char *)start + len); p++)
                *p = cpu_to_fdt32(FDT_NOP);
 }
 
@@ -89,7 +89,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
        if (! prop)
                return len;
 
-       nop_region(prop, len + sizeof(*prop));
+       _fdt_nop_region(prop, len + sizeof(*prop));
 
        return 0;
 }
@@ -139,6 +139,7 @@ int fdt_nop_node(void *fdt, int nodeoffset)
        if (endoffset < 0)
                return endoffset;
 
-       nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
+       _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+                       endoffset - nodeoffset);
        return 0;
 }
index 6b2fb92ea3578b7a4b6fb5c49ee2c1d8f4ecee5a..ce80e4fb41b2b35533a54ac1b0b7fa47a1b53c9b 100644 (file)
 const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
 {
-       return (void *)fdt_offset_ptr(fdt, offset, checklen);
+       return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
 }
 
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
+/**********************************************************************/
+/* Traversal functions                                                */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
@@ -207,7 +213,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
 /**********************************************************************/
 
 /**
- * fdt_string - retreive a string from the strings block of a device tree
+ * fdt_string - retrieve a string from the strings block of a device tree
  * @fdt: pointer to the device tree blob
  * @stroffset: offset of the string within the strings block (native endian)
  *
@@ -221,7 +227,7 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
 const char *fdt_string(const void *fdt, int stroffset);
 
 /**
- * fdt_num_mem_rsv - retreive the number of memory reserve map entries
+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
  *
  * Returns the number of entries in the device tree blob's memory
@@ -234,7 +240,7 @@ const char *fdt_string(const void *fdt, int stroffset);
 int fdt_num_mem_rsv(const void *fdt);
 
 /**
- * fdt_get_mem_rsv - retreive one memory reserve map entry
+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
  * @fdt: pointer to the device tree blob
  * @address, @size: pointers to 64-bit variables
  *
@@ -314,7 +320,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
 int fdt_path_offset(const void *fdt, const char *path);
 
 /**
- * fdt_get_name - retreive the name of a given node
+ * fdt_get_name - retrieve the name of a given node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: structure block offset of the starting node
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
@@ -346,7 +352,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
  * fdt_get_property() retrieves a pointer to the fdt_property
  * structure within the device tree blob corresponding to the property
  * named 'name' of the node at offset nodeoffset.  If lenp is
- * non-NULL, the length of the property value also returned, in the
+ * non-NULL, the length of the property value is also returned, in the
  * integer pointed to by lenp.
  *
  * returns:
@@ -369,8 +375,8 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
                                                      const char *name,
                                                      int *lenp)
 {
-       return (struct fdt_property *)fdt_get_property(fdt, nodeoffset,
-                                                      name, lenp);
+       return (struct fdt_property *)(uintptr_t)
+               fdt_get_property(fdt, nodeoffset, name, lenp);
 }
 
 /**
@@ -383,7 +389,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
  * fdt_getprop() retrieves a pointer to the value of the property
  * named 'name' of the node at offset nodeoffset (this will be a
  * pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value also
+ * If lenp is non-NULL, the length of the property value is also
  * returned, in the integer pointed to by lenp.
  *
  * returns:
@@ -405,11 +411,11 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
 static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
                                  const char *name, int *lenp)
 {
-       return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
+       return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
 }
 
 /**
- * fdt_get_phandle - retreive the phandle of a given node
+ * fdt_get_phandle - retrieve the phandle of a given node
  * @fdt: pointer to the device tree blob
  * @nodeoffset: structure block offset of the node
  *
@@ -417,7 +423,7 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
  * structure block offset nodeoffset.
  *
  * returns:
- *     the phandle of the node at nodeoffset, on succes (!= 0, != -1)
+ *     the phandle of the node at nodeoffset, on success (!= 0, != -1)
  *     0, if the node has no phandle, or another error occurs
  */
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
@@ -516,7 +522,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
  * structure from the start to nodeoffset, *twice*.
  *
  * returns:
- *     stucture block offset of the parent of the node at nodeoffset
+ *     structure block offset of the parent of the node at nodeoffset
  *             (>=0), on success
  *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
  *     -FDT_ERR_BADMAGIC,
@@ -573,7 +579,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
  * @fdt: pointer to the device tree blob
  * @phandle: phandle value
  *
- * fdt_node_offset_by_prop_value() returns the offset of the node
+ * fdt_node_offset_by_phandle() returns the offset of the node
  * which has the given phandle value.  If there is more than one node
  * in the tree with the given phandle (an invalid tree), results are
  * undefined.
@@ -655,8 +661,65 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 /* Write-in-place functions                                           */
 /**********************************************************************/
 
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len.  This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ *     -FDT_ERR_NOTFOUND, node does not have the named property
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
                        const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: cell (32-bit integer) value to replace the property with
+ *
+ * fdt_setprop_inplace_cell() replaces the value of a given property
+ * with the 32-bit integer cell value in val, converting val to
+ * big-endian if necessary.  This function cannot change the size of a
+ * property, and so will only work if the property already exists and
+ * has length 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, if the property's length is not equal to 4
+  *    -FDT_ERR_NOTFOUND, node does not have the named property
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
                                           const char *name, uint32_t val)
 {
@@ -664,7 +727,54 @@ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
        return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOTFOUND, node does not have the named property
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_nop_node(void *fdt, int nodeoffset);
 
 /**********************************************************************/
@@ -693,23 +803,268 @@ int fdt_finish(void *fdt);
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
 int fdt_pack(void *fdt);
 
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new reservation entry
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ *             are less than n+1 reserve map entries)
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_del_mem_rsv(void *fdt, int n);
 
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string.  NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ *             to contain the new name
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_setprop(void *fdt, int nodeoffset, const char *name,
                const void *val, int len);
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_cell() sets the value of the named property in the
+ * given node to the given cell value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
                                   uint32_t val)
 {
        val = cpu_to_fdt32(val);
        return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
 }
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *             contain the new property value
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 #define fdt_setprop_string(fdt, nodeoffset, name, str) \
        fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOTFOUND, node does not have the named property
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node.  This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,
                            const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ *     structure block offset of the created nodeequested subnode (>=0), on success
+ *     -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *     -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ *             the given name
+ *     -FDT_ERR_NOSPACE, if there is insufficient free space in the
+ *             blob to contain the new node
+ *     -FDT_ERR_NOSPACE
+ *     -FDT_ERR_BADLAYOUT
+ *      -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings.
+ */
 int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
 int fdt_del_node(void *fdt, int nodeoffset);
 
 /**********************************************************************/
index 1e60936beb5bbff7d609fc55011430fdadc8bd82..46eb93e4af5c471ecac7bc470065c11f6ae6f9e6 100644 (file)
  */
 #include <fdt.h>
 
-#define ALIGN(x, a)    (((x) + (a) - 1) & ~((a) - 1))
-#define PALIGN(p, a)   ((void *)ALIGN((unsigned long)(p), (a)))
+#define FDT_ALIGN(x, a)                (((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x)                (FDT_ALIGN((x), FDT_TAGSIZE))
 
-#define memeq(p, q, n) (memcmp((p), (q), (n)) == 0)
-#define streq(p, q)    (strcmp((p), (q)) == 0)
+#define FDT_CHECK_HEADER(fdt) \
+       { \
+               int err; \
+               if ((err = fdt_check_header(fdt)) != 0) \
+                       return err; \
+       }
 
 uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
+int _fdt_check_node_offset(const void *fdt, int offset);
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
 int _fdt_node_end_offset(void *fdt, int nodeoffset);
 
 static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
 {
-       return fdt + fdt_off_dt_struct(fdt) + offset;
+       return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
 }
 
 static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
 {
-       return (void *)_fdt_offset_ptr(fdt, offset);
+       return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
 }
 
 static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
 {
        const struct fdt_reserve_entry *rsv_table =
-               fdt + fdt_off_mem_rsvmap(fdt);
+               (const struct fdt_reserve_entry *)
+               ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
 
        return rsv_table + n;
 }
 static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
 {
-       return (void *)_fdt_mem_rsv(fdt, n);
+       return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
 }
 
-#define SW_MAGIC               (~FDT_MAGIC)
+#define FDT_SW_MAGIC           (~FDT_MAGIC)
 
 #endif /* _LIBFDT_INTERNAL_H */
index a4b0fc959ecebc34d96997cb898ae956b1c7272a..c89fdb1b80e161e78888cf6fc61de13035cd263c 100644 (file)
@@ -6,6 +6,7 @@
 
 typedef u32 uint32_t;
 typedef u64 uint64_t;
+typedef unsigned long uintptr_t;
 
 #define fdt16_to_cpu(x)                (x)
 #define cpu_to_fdt16(x)                (x)
index 965c237c122d781063697dff3a9cef20dd2859ca..ee0dc41d7c5659bb063e37b23bf180b2c8ba578b 100755 (executable)
@@ -307,7 +307,9 @@ fi
 # post-processing needed for some platforms
 case "$platform" in
 pseries|chrp)
-    $objbin/addnote "$ofile"
+    ${CROSS}objcopy -O binary -j .fakeelf "$kernel" "$ofile".rpanote
+    $objbin/addnote "$ofile" "$ofile".rpanote
+    rm -r "$ofile".rpanote
     ;;
 coff)
     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig
new file mode 100644 (file)
index 0000000..70f4607
--- /dev/null
@@ -0,0 +1,767 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc5
+# Wed Oct  1 15:54:57 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+CONFIG_44x=y
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_4xx=y
+CONFIG_BOOKE=y
+CONFIG_PTE_64BIT=y
+CONFIG_PHYS_64BIT=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+CONFIG_PPC4xx_PCI_EXPRESS=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_BAMBOO is not set
+# CONFIG_EBONY is not set
+# CONFIG_SAM440EP is not set
+# CONFIG_SEQUOIA is not set
+# CONFIG_TAISHAN is not set
+# CONFIG_KATMAI is not set
+# CONFIG_RAINIER is not set
+# CONFIG_WARP is not set
+CONFIG_ARCHES=y
+# CONFIG_CANYONLANDS is not set
+# CONFIG_GLACIER is not set
+# CONFIG_YOSEMITE is not set
+# CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
+CONFIG_PPC44x_SIMPLE=y
+CONFIG_460EX=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+CONFIG_EXTRA_TARGETS=""
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_4xx_SOC=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP 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_FIB_HASH=y
+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_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBM_NEW_EMAC=y
+CONFIG_IBM_NEW_EMAC_RXB=256
+CONFIG_IBM_NEW_EMAC_TXB=256
+CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_NEW_EMAC_DEBUG is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+CONFIG_IBM_NEW_EMAC_TAH=y
+CONFIG_IBM_NEW_EMAC_EMAC4=y
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+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
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
index 5e6780a088ce591d1690b5594dab9181a71682c2..0b1fa20f745ce6cd988c8fa60b2d6a8a44fb05a8 100644 (file)
@@ -164,11 +164,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index 2028337868b4f28a78b881cc17599087d1dccfce..b7eae2bdf19c1b731a40fda61411d2cde532f048 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index dd80eb0a87a100ee42ff3f1cdbb0b6ce3e1d30b0..b0a27a67d8c7c145d31f765c5e4119dc719ac814 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index bdf50c8a17e6b86ca109ba0fbdd466e24bb4f94f..ad825bcddd1fab5b35d6c0e972301645b8d23acc 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index 4eef8c95480ed6c4da4310cc7ed1fa89e692ccda..38267501f44ddfb9329b1a5b6946f9daf0470d57 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index 8d6513931850d4b888d3d23615ae8dd92da9e315..90aab340e7ff30f679fac524bffe7f6da23e841d 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index a8afa39d6f76cf834cfb1715750e5c2dccf1a775..7458a242d251b37fc9e72e20e35cbce409770ae1 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index 24c320a36670642e359d960dbd82ec3e2d6e06de..1a92798938cf9d458ea6c953d6fa9e621c07d7be 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index e029e9e1462208ad30007a2040b19b5740907557..03d8cede02727b447f3ddd101cfab8da57c49444 100644 (file)
@@ -163,11 +163,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
@@ -383,7 +383,84 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 # CONFIG_PARPORT is not set
index 7d674be702fe75c1280c6dccdf6ffa68e0ac6ab8..cdf84177370a4a1be216db4785461cecbebf2207 100644 (file)
@@ -164,11 +164,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index de472022aa81d4057cecc0ac19aeb3a38d9756f2..97e02d7a5b0960d62d42648d63013e1e6364a659 100644 (file)
@@ -164,11 +164,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index e8d2d691d26c9d7efeb73c26e50f2c5ff1e3511a..5ac33054ce2c81a24dceb892b7f303296682dc06 100644 (file)
@@ -164,11 +164,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
index 9245a67da20029e2cb179ff12f7743bc80fa2ee2..c359cc2a380e2f7cd84ee9a96048b0100c9ebb7c 100644 (file)
@@ -162,11 +162,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
new file mode 100644 (file)
index 0000000..312d7af
--- /dev/null
@@ -0,0 +1,1657 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc5
+# Wed Jun 11 12:06:53 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8641_HPCN is not set
+# CONFIG_SBC8641D is not set
+# CONFIG_MPC8610_HPCD is not set
+CONFIG_GEF_SBC610=y
+CONFIG_MPC8641=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=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_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+# CONFIG_NET_SCH_RR is not set
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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 is not set
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+# 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_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_COW_COMMON 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=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_SATA_SIL=y
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# 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
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# 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_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=y
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM92=y
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_ATM is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+# CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO 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_EXT2_FS_XIP 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+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_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+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_WEAK_PW_HASH is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_DEBUGGER=y
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
new file mode 100644 (file)
index 0000000..c98c6ee
--- /dev/null
@@ -0,0 +1,1497 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc4
+# Thu Aug 21 00:52:10 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_HIBERNATE_32=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_MPC8641_HPCN is not set
+# CONFIG_SBC8641D is not set
+CONFIG_MPC8610_HPCD=y
+CONFIG_MPC8610=y
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_TAU is not set
+CONFIG_FSL_ULI1575=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_ISA is not set
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_FSL_ELBC=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_MAC_FLOPPY 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=y
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+CONFIG_PATA_ALI=y
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+# CONFIG_TULIP is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+CONFIG_ULI526X=y
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_BRIQ_PANEL is not set
+# CONFIG_HVC_RTAS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# Mac SMBus host controller drivers
+#
+# CONFIG_I2C_HYDRA is not set
+CONFIG_I2C_POWERMAC=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# 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_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_FSL_DIU=y
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# 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_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X 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_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER 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_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+# CONFIG_SND_POWERMAC is not set
+# CONFIG_SND_AOA is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MPC8610=y
+CONFIG_SND_SOC_MPC8610_HPCD=y
+CONFIG_SND_SOC_CS4270=y
+CONFIG_SND_SOC_CS4270_VD33_ERRATA=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+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=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=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_TALITOS is not set
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
new file mode 100644 (file)
index 0000000..444ddf9
--- /dev/null
@@ -0,0 +1,1666 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc4
+# Thu Aug 21 00:52:11 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+CONFIG_MPC8641_HPCN=y
+# CONFIG_SBC8641D is not set
+# CONFIG_MPC8610_HPCD is not set
+CONFIG_MPC8641=y
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_TAU is not set
+CONFIG_FSL_ULI1575=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_ISA is not set
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_MAC_FLOPPY 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+CONFIG_PATA_ALI=y
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+CONFIG_VITESSE_PHY=y
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_SFC is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# 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
+# 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
+# CONFIG_HVC_RTAS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# Mac SMBus host controller drivers
+#
+# CONFIG_I2C_HYDRA is not set
+CONFIG_I2C_POWERMAC=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+# CONFIG_TTPCI_EEPROM is not set
+# CONFIG_DVB_BUDGET_CORE is not set
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+# CONFIG_DVB_TTUSB_BUDGET is not set
+# CONFIG_DVB_TTUSB_DEC is not set
+# CONFIG_DVB_CINERGYT2 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported BT878 Adapters
+#
+
+#
+# Supported Pluto2 Adapters
+#
+# CONFIG_DVB_PLUTO2 is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TUA6100 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_SP8870 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_DRX397XD is not set
+# CONFIG_DVB_L64781 is not set
+# CONFIG_DVB_TDA1004X is not set
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_ZL10353 is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+# CONFIG_DVB_DIB7000M is not set
+# CONFIG_DVB_DIB7000P is not set
+# CONFIG_DVB_TDA10048 is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_VES1820 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_STV0297 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_AU8522 is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# 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_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X 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_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+# CONFIG_SND_POWERMAC is not set
+# CONFIG_SND_AOA is not set
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_SIERRA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_TALITOS is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig
new file mode 100644 (file)
index 0000000..d900f8f
--- /dev/null
@@ -0,0 +1,1481 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc4
+# Thu Aug 21 00:52:15 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_LOCKBREAK=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_MPC8641_HPCN is not set
+CONFIG_SBC8641D=y
+# CONFIG_MPC8610_HPCD is not set
+CONFIG_MPC8641=y
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_ISA is not set
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=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_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_SECURITY is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+CONFIG_IP6_NF_MANGLE=m
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_RAW=m
+# CONFIG_IP6_NF_SECURITY is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_OF_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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 is not set
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+# 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_OTP 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_PHYSMAP_OF=y
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_MAC_FLOPPY 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_COW_COMMON 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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
+# CONFIG_MD_RAID456 is not set
+CONFIG_MD_MULTIPATH=y
+CONFIG_MD_FAULTY=y
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=y
+CONFIG_DM_SNAPSHOT=y
+CONFIG_DM_MIRROR=y
+CONFIG_DM_ZERO=y
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+# CONFIG_ATM_LANAI is not set
+# CONFIG_ATM_ENI is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+# CONFIG_ATM_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# 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_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
+# CONFIG_HVC_RTAS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# Mac SMBus host controller drivers
+#
+# CONFIG_I2C_HYDRA is not set
+CONFIG_I2C_POWERMAC=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_AMS is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_ALIM7101_WDT is not set
+# CONFIG_8xxx_WDT is not set
+# CONFIG_WATCHDOG_RTAS is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO 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_EXT2_FS_XIP 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_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+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=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_TALITOS is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
index ef0c6e8005089580dc11ec3d50449ddd45dcf314..cd691f7708108662f1ac8b4b945043789fd2750c 100644 (file)
@@ -150,11 +150,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 CONFIG_PPC_82xx=y
diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig
new file mode 100644 (file)
index 0000000..cc9eaba
--- /dev/null
@@ -0,0 +1,900 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc2
+# Thu May 22 08:18:47 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+CONFIG_PPC_82xx=y
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_MPC8272_ADS is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_EP8248E is not set
+CONFIG_MGCOGE=y
+# CONFIG_PQ2ADS is not set
+CONFIG_8260=y
+CONFIG_8272=y
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPM2=y
+CONFIG_PPC_CPM_NEW_BINDING=y
+# CONFIG_FSL_ULI1575 is not set
+CONFIG_CPM=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_IP_MROUTE is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# 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_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# 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_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_HAS_SCC=y
+# CONFIG_FS_ENET_HAS_FCC is not set
+# CONFIG_FS_ENET_MDIO_FCC is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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=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
+# 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=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_KGDB_CONSOLE is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+CONFIG_BDI_SWITCH=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_PCBC=y
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig
new file mode 100644 (file)
index 0000000..3cd6ce4
--- /dev/null
@@ -0,0 +1,872 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc2
+# Wed May 21 13:30:33 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+CONFIG_PPC_8xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_8xx=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=1
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_MPC512x is not set
+# CONFIG_PPC_MPC5121 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_CPM1=y
+# CONFIG_MPC8XXFADS is not set
+# CONFIG_MPC86XADS is not set
+# CONFIG_MPC885ADS is not set
+# CONFIG_PPC_EP88XC is not set
+# CONFIG_PPC_ADDER875 is not set
+CONFIG_PPC_MGSUVD=y
+
+#
+# MPC8xx CPM Options
+#
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+CONFIG_8xx_CPU6=y
+CONFIG_8xx_CPU15=y
+# CONFIG_NO_UCODE_PATCH is not set
+# CONFIG_USB_SOF_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_UCODE_PATCH is not set
+CONFIG_I2C_SPI_SMC1_UCODE_PATCH=y
+CONFIG_UCODE_PATCH=y
+# CONFIG_PQ2ADS is not set
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_CPM_NEW_BINDING=y
+# CONFIG_FSL_ULI1575 is not set
+CONFIG_CPM=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCI_QSPAN is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xfd000000
+CONFIG_CONSISTENT_SIZE=0x00200000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# 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_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+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_PHYSMAP_OF=y
+# CONFIG_MTD_CFI_FLAGADM is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_HAS_SCC=y
+# CONFIG_FS_ENET_HAS_FEC is not set
+# CONFIG_FS_ENET_MDIO_FEC is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+# CONFIG_SERIAL_CPM_SMC2 is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 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_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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_PPC_CLOCK is not set
+CONFIG_PPC_LIB_RHEAP=y
+# CONFIG_VIRTUALIZATION is not set
index 7c435c84c8751dc91d271e96109686f47a12f99a..ff6f7c475f47ceacbf4b30fdb536dc21866f8985 100644 (file)
@@ -151,11 +151,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 CONFIG_PPC_82xx=y
index 916e3df7cc451496e0403c49f5964dbe6e8c276f..991c9bda12a98cba9c758105584310007bf6780d 100644 (file)
@@ -166,11 +166,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_82xx is not set
diff --git a/arch/powerpc/configs/mpc8610_hpcd_defconfig b/arch/powerpc/configs/mpc8610_hpcd_defconfig
deleted file mode 100644 (file)
index 1a99907..0000000
+++ /dev/null
@@ -1,1497 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Thu Aug 21 00:52:10 2008
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-CONFIG_6xx=y
-# CONFIG_PPC_85xx is not set
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_PPC_STD_MMU=y
-CONFIG_PPC_STD_MMU_32=y
-# CONFIG_PPC_MM_SLICES is not set
-# CONFIG_SMP is not set
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
-CONFIG_MMU=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_TIME_VSYSCALL=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-CONFIG_HIBERNATE_32=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-# CONFIG_ELF_CORE is not set
-CONFIG_PCSPKR_PLATFORM=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_DEFAULT_AS is not set
-CONFIG_DEFAULT_DEADLINE=y
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="deadline"
-CONFIG_CLASSIC_RCU=y
-
-#
-# Platform support
-#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
-# CONFIG_MPC5121_ADS is not set
-# CONFIG_MPC5121_GENERIC is not set
-# CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PPC_82xx is not set
-# CONFIG_PQ2ADS is not set
-# CONFIG_PPC_83xx is not set
-CONFIG_PPC_86xx=y
-# CONFIG_MPC8641_HPCN is not set
-# CONFIG_SBC8641D is not set
-CONFIG_MPC8610_HPCD=y
-CONFIG_MPC8610=y
-# CONFIG_EMBEDDED6xx is not set
-CONFIG_PPC_NATIVE=y
-# CONFIG_UDBG_RTAS_CONSOLE is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
-CONFIG_PPC_RTAS=y
-# CONFIG_RTAS_ERROR_LOGGING is not set
-CONFIG_RTAS_PROC=y
-# CONFIG_MMIO_NVRAM is not set
-CONFIG_PPC_MPC106=y
-# CONFIG_PPC_970_NAP is not set
-# CONFIG_PPC_INDIRECT_IO is not set
-# CONFIG_GENERIC_IOMAP is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-# CONFIG_TAU is not set
-CONFIG_FSL_ULI1575=y
-
-#
-# Kernel options
-#
-CONFIG_HIGHMEM=y
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
-CONFIG_SCHED_HRTICK=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_IOMMU_HELPER is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-# CONFIG_KEXEC is not set
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_FORCE_MAX_ZONEORDER=12
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-# CONFIG_SECCOMP is not set
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIEAER=y
-# CONFIG_PCIEASPM is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
-CONFIG_PCI_DEBUG=y
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-CONFIG_IPV6=y
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_IPV6_ROUTER_PREF is not set
-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
-CONFIG_INET6_XFRM_MODE_BEET=y
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_OF_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_PHYSMAP_OF=y
-# CONFIG_MTD_INTEL_VR_NOR is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-CONFIG_MTD_NAND=y
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_NAND_ECC_SMC is not set
-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
-CONFIG_MTD_NAND_IDS=y
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_CAFE is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
-CONFIG_MTD_NAND_FSL_ELBC=y
-# CONFIG_MTD_ONENAND is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_MAC_FLOPPY 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_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=131072
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-CONFIG_HAVE_IDE=y
-CONFIG_IDE=y
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-CONFIG_SCSI_TGT=y
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-# CONFIG_SCSI_SRP is not set
-# CONFIG_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_SATA_PMP=y
-CONFIG_SATA_AHCI=y
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-CONFIG_PATA_ALI=y
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_SCH is not set
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-# CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-CONFIG_NET_TULIP=y
-# CONFIG_DE2104X is not set
-# CONFIG_TULIP is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-CONFIG_ULI526X=y
-# CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS 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_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_BRIQ_PANEL is not set
-# CONFIG_HVC_RTAS is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# 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_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 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
-
-#
-# Mac SMBus host controller drivers
-#
-# CONFIG_I2C_HYDRA is not set
-CONFIG_I2C_POWERMAC=y
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-
-#
-# Graphics support
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-
-#
-# Frame buffer hardware drivers
-#
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_OF is not set
-# CONFIG_FB_CONTROL is not set
-# 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_VGA16 is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_VT8623 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_CARMINE is not set
-CONFIG_FB_FSL_DIU=y
-# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-# CONFIG_LOGO is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_PCM_OSS_PLUGINS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 is not set
-# 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_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X 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_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER 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_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_PPC=y
-# CONFIG_SND_POWERMAC is not set
-# CONFIG_SND_AOA is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_SOC_MPC8610=y
-CONFIG_SND_SOC_MPC8610_HPCD=y
-CONFIG_SND_SOC_CS4270=y
-CONFIG_SND_SOC_CS4270_VD33_ERRATA=y
-# CONFIG_SOUND_PRIME is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1374 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PPC is not set
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-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=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=y
-# CONFIG_LDM_DEBUG is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-# CONFIG_SYSV68_PARTITION is not set
-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
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC_T10DIF=y
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SHIRQ=y
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-# CONFIG_CRYPTO_MANAGER is not set
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-# CONFIG_CRYPTO_CBC is not set
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-# CONFIG_CRYPTO_DEV_TALITOS is not set
-# CONFIG_PPC_CLOCK is not set
-CONFIG_PPC_LIB_RHEAP=y
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
deleted file mode 100644 (file)
index ea09be3..0000000
+++ /dev/null
@@ -1,1666 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Thu Aug 21 00:52:11 2008
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-CONFIG_6xx=y
-# CONFIG_PPC_85xx is not set
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_PPC_STD_MMU=y
-CONFIG_PPC_STD_MMU_32=y
-# CONFIG_PPC_MM_SLICES is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
-CONFIG_MMU=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_TIME_VSYSCALL=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-CONFIG_GENERIC_TBSYNC=y
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-CONFIG_AUDIT=y
-# CONFIG_AUDITSYSCALL is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-# CONFIG_FAIR_GROUP_SCHED is not set
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_PCSPKR_PLATFORM=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLUB_DEBUG=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# Platform support
-#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
-# CONFIG_MPC5121_ADS is not set
-# CONFIG_MPC5121_GENERIC is not set
-# CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PPC_82xx is not set
-# CONFIG_PQ2ADS is not set
-# CONFIG_PPC_83xx is not set
-CONFIG_PPC_86xx=y
-CONFIG_MPC8641_HPCN=y
-# CONFIG_SBC8641D is not set
-# CONFIG_MPC8610_HPCD is not set
-CONFIG_MPC8641=y
-CONFIG_PPC_NATIVE=y
-# CONFIG_UDBG_RTAS_CONSOLE is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
-CONFIG_PPC_RTAS=y
-# CONFIG_RTAS_ERROR_LOGGING is not set
-CONFIG_RTAS_PROC=y
-# CONFIG_MMIO_NVRAM is not set
-CONFIG_PPC_MPC106=y
-# CONFIG_PPC_970_NAP is not set
-# CONFIG_PPC_INDIRECT_IO is not set
-# CONFIG_GENERIC_IOMAP is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-# CONFIG_TAU is not set
-CONFIG_FSL_ULI1575=y
-
-#
-# Kernel options
-#
-CONFIG_HIGHMEM=y
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
-CONFIG_SCHED_HRTICK=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
-# CONFIG_HOTPLUG_CPU is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-# CONFIG_KEXEC is not set
-# CONFIG_IRQ_ALL_CPUS is not set
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_FORCE_MAX_ZONEORDER=11
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-# CONFIG_PCIEPORTBUS is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-CONFIG_HAS_RAPIDIO=y
-# CONFIG_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
-CONFIG_NET_KEY=m
-# CONFIG_NET_KEY_MIGRATE is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_ASK_IP_FIB_HASH=y
-# CONFIG_IP_FIB_TRIE is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_NET_IPGRE=y
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=y
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-CONFIG_IPV6=y
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_IPV6_ROUTER_PREF is not set
-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
-CONFIG_INET6_XFRM_MODE_BEET=y
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=y
-CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-# CONFIG_MTD is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_MAC_FLOPPY 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_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=y
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=131072
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-CONFIG_SCSI_LOGGING=y
-# CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-# CONFIG_SCSI_SRP is not set
-# CONFIG_SCSI_DH is not set
-CONFIG_ATA=y
-# CONFIG_ATA_NONSTANDARD is not set
-CONFIG_SATA_PMP=y
-CONFIG_SATA_AHCI=y
-# CONFIG_SATA_SIL24 is not set
-# CONFIG_SATA_FSL is not set
-CONFIG_ATA_SFF=y
-# CONFIG_SATA_SVW is not set
-# CONFIG_ATA_PIIX is not set
-# CONFIG_SATA_MV is not set
-# CONFIG_SATA_NV is not set
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SX4 is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
-# CONFIG_SATA_INIC162X is not set
-CONFIG_PATA_ALI=y
-# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
-# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_CMD640_PCI is not set
-# CONFIG_PATA_CMD64X is not set
-# CONFIG_PATA_CS5520 is not set
-# CONFIG_PATA_CS5530 is not set
-# CONFIG_PATA_CYPRESS is not set
-# CONFIG_PATA_EFAR is not set
-# CONFIG_ATA_GENERIC is not set
-# CONFIG_PATA_HPT366 is not set
-# CONFIG_PATA_HPT37X is not set
-# CONFIG_PATA_HPT3X2N is not set
-# CONFIG_PATA_HPT3X3 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_TRIFLEX is not set
-# CONFIG_PATA_MARVELL is not set
-# CONFIG_PATA_MPIIX is not set
-# CONFIG_PATA_OLDPIIX is not set
-# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
-# CONFIG_PATA_NS87410 is not set
-# CONFIG_PATA_NS87415 is not set
-# CONFIG_PATA_OPTI is not set
-# CONFIG_PATA_OPTIDMA is not set
-# CONFIG_PATA_PDC_OLD is not set
-# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RZ1000 is not set
-# CONFIG_PATA_SC1200 is not set
-# CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
-# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_VIA is not set
-# CONFIG_PATA_WINBOND is not set
-# CONFIG_PATA_PLATFORM is not set
-# CONFIG_PATA_SCH is not set
-# CONFIG_MD is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-# CONFIG_ARCNET is not set
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-CONFIG_VITESSE_PHY=y
-# CONFIG_SMSC_PHY is not set
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
-# CONFIG_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_GIANFAR=y
-# CONFIG_MV643XX_ETH is not set
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-CONFIG_NETDEV_10000=y
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_IXGBE is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-# CONFIG_NETXEN_NIC is not set
-# CONFIG_NIU is not set
-# CONFIG_MLX4_CORE is not set
-# CONFIG_TEHUTI is not set
-# CONFIG_BNX2X is not set
-# CONFIG_SFC is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-
-#
-# USB Network Adapters
-#
-# 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
-# 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_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_XILINX_XPS_PS2 is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_BRIQ_PANEL is not set
-# CONFIG_HVC_RTAS is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_NVRAM=y
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_CHARDEV is not set
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# 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_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 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
-
-#
-# Mac SMBus host controller drivers
-#
-# CONFIG_I2C_HYDRA is not set
-CONFIG_I2C_POWERMAC=y
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_CINERGYT2 is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported DVB Frontends
-#
-
-#
-# Customise DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-
-#
-# DVB-S (satellite) frontends
-#
-# CONFIG_DVB_CX24110 is not set
-# CONFIG_DVB_CX24123 is not set
-# CONFIG_DVB_MT312 is not set
-# CONFIG_DVB_S5H1420 is not set
-# CONFIG_DVB_STV0299 is not set
-# CONFIG_DVB_TDA8083 is not set
-# CONFIG_DVB_TDA10086 is not set
-# CONFIG_DVB_VES1X93 is not set
-# CONFIG_DVB_TUNER_ITD1000 is not set
-# CONFIG_DVB_TDA826X is not set
-# CONFIG_DVB_TUA6100 is not set
-
-#
-# DVB-T (terrestrial) frontends
-#
-# CONFIG_DVB_SP8870 is not set
-# CONFIG_DVB_SP887X is not set
-# CONFIG_DVB_CX22700 is not set
-# CONFIG_DVB_CX22702 is not set
-# CONFIG_DVB_DRX397XD is not set
-# CONFIG_DVB_L64781 is not set
-# CONFIG_DVB_TDA1004X is not set
-# CONFIG_DVB_NXT6000 is not set
-# CONFIG_DVB_MT352 is not set
-# CONFIG_DVB_ZL10353 is not set
-# CONFIG_DVB_DIB3000MB is not set
-# CONFIG_DVB_DIB3000MC is not set
-# CONFIG_DVB_DIB7000M is not set
-# CONFIG_DVB_DIB7000P is not set
-# CONFIG_DVB_TDA10048 is not set
-
-#
-# DVB-C (cable) frontends
-#
-# CONFIG_DVB_VES1820 is not set
-# CONFIG_DVB_TDA10021 is not set
-# CONFIG_DVB_TDA10023 is not set
-# CONFIG_DVB_STV0297 is not set
-
-#
-# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
-#
-# CONFIG_DVB_NXT200X is not set
-# CONFIG_DVB_OR51211 is not set
-# CONFIG_DVB_OR51132 is not set
-# CONFIG_DVB_BCM3510 is not set
-# CONFIG_DVB_LGDT330X is not set
-# CONFIG_DVB_S5H1409 is not set
-# CONFIG_DVB_AU8522 is not set
-# CONFIG_DVB_S5H1411 is not set
-
-#
-# Digital terrestrial only tuners/PLL
-#
-# CONFIG_DVB_PLL is not set
-# CONFIG_DVB_TUNER_DIB0070 is not set
-
-#
-# SEC control devices for DVB-S
-#
-# CONFIG_DVB_LNBP21 is not set
-# CONFIG_DVB_ISL6405 is not set
-# CONFIG_DVB_ISL6421 is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
-
-#
-# Graphics support
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_PCM_OSS_PLUGINS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-CONFIG_SND_VMASTER=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-# CONFIG_SND_AC97_POWER_SAVE is not set
-CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALS4000 is not set
-# 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_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5530 is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X 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_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_HIFIER is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-CONFIG_SND_PPC=y
-# CONFIG_SND_POWERMAC is not set
-# CONFIG_SND_AOA is not set
-CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
-# CONFIG_SND_USB_CAIAQ is not set
-# CONFIG_SND_SOC is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_AC97_BUS=y
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_DEVICE_CLASS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=y
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_FSL is not set
-CONFIG_USB_EHCI_HCD_PPC_OF=y
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
-CONFIG_USB_OHCI_HCD_PCI=y
-CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-# CONFIG_USB_R8A66597_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_WDM is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_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_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1374 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-
-#
-# SPI RTC drivers
-#
-
-#
-# Platform RTC drivers
-#
-CONFIG_RTC_DRV_CMOS=y
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_RTC_DRV_PPC is not set
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-CONFIG_NTFS_FS=y
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=y
-CONFIG_VXFS_FS=m
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-# CONFIG_ROMFS_FS is not set
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_UFS_DEBUG is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# 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=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-# CONFIG_SYSV68_PARTITION is not set
-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=m
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-# CONFIG_SLUB_STATS is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_HIGHMEM is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=m
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-# CONFIG_CRYPTO_DEV_TALITOS is not set
-# CONFIG_PPC_CLOCK is not set
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/mpc86xx_defconfig b/arch/powerpc/configs/mpc86xx_defconfig
new file mode 100644 (file)
index 0000000..9d4be82
--- /dev/null
@@ -0,0 +1,1646 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc5
+# Tue Sep 23 23:28:38 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_CLK is not set
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_MPC8xxx_GPIO is not set
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
+CONFIG_MPC8641_HPCN=y
+CONFIG_SBC8641D=y
+CONFIG_MPC8610_HPCD=y
+CONFIG_GEF_SBC610=y
+CONFIG_MPC8641=y
+CONFIG_MPC8610=y
+# CONFIG_IPIC is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+CONFIG_FSL_ULI1575=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_PAGE_OFFSET=0xc0000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+CONFIG_TASK_SIZE=0xc0000000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_FSL is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+CONFIG_PATA_ALI=y
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+CONFIG_VITESSE_PHY=y
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_SFC is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# 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
+# 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 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
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+# CONFIG_TTPCI_EEPROM is not set
+# CONFIG_DVB_BUDGET_CORE is not set
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+# CONFIG_DVB_TTUSB_BUDGET is not set
+# CONFIG_DVB_TTUSB_DEC is not set
+# CONFIG_DVB_CINERGYT2 is not set
+# CONFIG_DVB_SIANO_SMS1XXX is not set
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported BT878 Adapters
+#
+
+#
+# Supported Pluto2 Adapters
+#
+# CONFIG_DVB_PLUTO2 is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TUA6100 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_SP8870 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_DRX397XD is not set
+# CONFIG_DVB_L64781 is not set
+# CONFIG_DVB_TDA1004X is not set
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_ZL10353 is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+# CONFIG_DVB_DIB7000M is not set
+# CONFIG_DVB_DIB7000P is not set
+# CONFIG_DVB_TDA10048 is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_VES1820 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_STV0297 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_AU8522 is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+# CONFIG_DVB_TUNER_DIB0070 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# 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_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X 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_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_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_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_SIERRA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+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=m
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_TALITOS is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
index b390b74766499bf3ad8a7458b71f3444ee960a13..7e17862c38b8f933edbfb1d60b34b84a60714b72 100644 (file)
@@ -152,11 +152,11 @@ CONFIG_CLASSIC_RCU=y
 #
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
 # CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
 CONFIG_PPC_82xx=y
diff --git a/arch/powerpc/configs/sbc8641d_defconfig b/arch/powerpc/configs/sbc8641d_defconfig
deleted file mode 100644 (file)
index f545421..0000000
+++ /dev/null
@@ -1,1481 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Thu Aug 21 00:52:15 2008
-#
-# CONFIG_PPC64 is not set
-
-#
-# Processor support
-#
-CONFIG_6xx=y
-# CONFIG_PPC_85xx is not set
-# CONFIG_PPC_8xx is not set
-# CONFIG_40x is not set
-# CONFIG_44x is not set
-# CONFIG_E200 is not set
-CONFIG_PPC_FPU=y
-CONFIG_ALTIVEC=y
-CONFIG_PPC_STD_MMU=y
-CONFIG_PPC_STD_MMU_32=y
-# CONFIG_PPC_MM_SLICES is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_PPC32=y
-CONFIG_WORD_SIZE=32
-CONFIG_PPC_MERGE=y
-CONFIG_MMU=y
-CONFIG_GENERIC_CMOS_UPDATE=y
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_TIME_VSYSCALL=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
-CONFIG_IRQ_PER_CPU=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_LOCKBREAK=y
-CONFIG_ARCH_HAS_ILOG2_U32=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
-CONFIG_PPC=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_PPC_OF=y
-CONFIG_OF=y
-CONFIG_PPC_UDBG_16550=y
-CONFIG_GENERIC_TBSYNC=y
-CONFIG_AUDIT_ARCH=y
-CONFIG_GENERIC_BUG=y
-CONFIG_DEFAULT_UIMAGE=y
-# CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_RELAY=y
-# CONFIG_NAMESPACES is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_PCSPKR_PLATFORM=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_USE_GENERIC_SMP_HELPERS=y
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# Platform support
-#
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
-CONFIG_PPC_CHRP=y
-# CONFIG_MPC5121_ADS is not set
-# CONFIG_MPC5121_GENERIC is not set
-# CONFIG_PPC_MPC52xx is not set
-CONFIG_PPC_PMAC=y
-# CONFIG_PPC_CELL is not set
-# CONFIG_PPC_CELL_NATIVE is not set
-# CONFIG_PPC_82xx is not set
-# CONFIG_PQ2ADS is not set
-# CONFIG_PPC_83xx is not set
-CONFIG_PPC_86xx=y
-# CONFIG_MPC8641_HPCN is not set
-CONFIG_SBC8641D=y
-# CONFIG_MPC8610_HPCD is not set
-CONFIG_MPC8641=y
-CONFIG_PPC_NATIVE=y
-# CONFIG_UDBG_RTAS_CONSOLE is not set
-# CONFIG_IPIC is not set
-CONFIG_MPIC=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
-CONFIG_PPC_RTAS=y
-# CONFIG_RTAS_ERROR_LOGGING is not set
-CONFIG_RTAS_PROC=y
-# CONFIG_MMIO_NVRAM is not set
-CONFIG_PPC_MPC106=y
-# CONFIG_PPC_970_NAP is not set
-# CONFIG_PPC_INDIRECT_IO is not set
-# CONFIG_GENERIC_IOMAP is not set
-# CONFIG_CPU_FREQ is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-# CONFIG_TAU is not set
-# CONFIG_FSL_ULI1575 is not set
-
-#
-# Kernel options
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_TICK_ONESHOT=y
-# CONFIG_NO_HZ is not set
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
-CONFIG_SCHED_HRTICK=y
-# CONFIG_PREEMPT_NONE is not set
-# CONFIG_PREEMPT_VOLUNTARY is not set
-CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
-# CONFIG_HOTPLUG_CPU is not set
-CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-CONFIG_ARCH_HAS_WALK_MEMORY=y
-CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
-# CONFIG_KEXEC is not set
-CONFIG_IRQ_ALL_CPUS=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_POPULATES_NODE_MAP=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_FORCE_MAX_ZONEORDER=11
-# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_EXTRA_TARGETS=""
-# CONFIG_PM is not set
-CONFIG_SECCOMP=y
-CONFIG_ISA_DMA_API=y
-
-#
-# Bus options
-#
-# CONFIG_ISA is not set
-CONFIG_ZONE_DMA=y
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_INDIRECT_PCI=y
-CONFIG_FSL_SOC=y
-CONFIG_FSL_PCI=y
-CONFIG_PPC_PCI_CHOICE=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_SYSCALL=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIEAER=y
-# CONFIG_PCIEASPM is not set
-CONFIG_ARCH_SUPPORTS_MSI=y
-# CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCCARD is not set
-# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_PAGE_OFFSET=0xc0000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_PHYSICAL_START=0x00000000
-CONFIG_TASK_SIZE=0xc0000000
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
-# CONFIG_XFRM_STATISTICS is not set
-CONFIG_XFRM_IPCOMP=m
-CONFIG_NET_KEY=m
-# CONFIG_NET_KEY_MIGRATE is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_ASK_IP_FIB_HASH=y
-# CONFIG_IP_FIB_TRIE is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_INET_XFRM_TUNNEL=m
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_IPV6_ROUTER_PREF is not set
-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-# CONFIG_IPV6_MIP6 is not set
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_NDISC_NODETYPE=y
-CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETLABEL is not set
-# CONFIG_NETWORK_SECMARK is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
-# CONFIG_NETFILTER_NETLINK_LOG is not set
-# CONFIG_NF_CONNTRACK is not set
-CONFIG_NETFILTER_XTABLES=m
-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
-# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
-# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
-# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
-# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
-# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-# CONFIG_NETFILTER_XT_MATCH_TIME is not set
-# CONFIG_NETFILTER_XT_MATCH_U32 is not set
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-# CONFIG_IP_NF_MATCH_AH is not set
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=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_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_RAW=m
-# CONFIG_IP_NF_SECURITY is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_AH is not set
-# CONFIG_IP6_NF_MATCH_MH is not set
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-# CONFIG_IP6_NF_TARGET_REJECT is not set
-CONFIG_IP6_NF_MANGLE=m
-# CONFIG_IP6_NF_TARGET_HL is not set
-CONFIG_IP6_NF_RAW=m
-# CONFIG_IP6_NF_SECURITY is not set
-
-#
-# Bridge: Netfilter Configuration
-#
-# CONFIG_BRIDGE_NF_EBTABLES is not set
-# CONFIG_IP_DCCP is not set
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-CONFIG_TIPC=m
-# CONFIG_TIPC_ADVANCED is not set
-# CONFIG_TIPC_DEBUG is not set
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_STP=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-# CONFIG_VLAN_8021Q_GVRP is not set
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
-CONFIG_NET_SCHED=y
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-# CONFIG_NET_CLS_BASIC is not set
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_FLOW is not set
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_SCH_FIFO=y
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-CONFIG_FIB_RULES=y
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_OF_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS 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 is not set
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_LE_BYTE_SWAP=y
-# 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_OTP 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_PHYSMAP_OF=y
-# CONFIG_MTD_INTEL_VR_NOR is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
-CONFIG_OF_DEVICE=y
-CONFIG_OF_I2C=y
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_MAC_FLOPPY 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_COW_COMMON 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_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
-# CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_HP_ILO is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
-# CONFIG_SCSI_NETLINK is not set
-# CONFIG_ATA is not set
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID10=y
-# CONFIG_MD_RAID456 is not set
-CONFIG_MD_MULTIPATH=y
-CONFIG_MD_FAULTY=y
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_DEBUG is not set
-CONFIG_DM_CRYPT=y
-CONFIG_DM_SNAPSHOT=y
-CONFIG_DM_MIRROR=y
-CONFIG_DM_ZERO=y
-# CONFIG_DM_MULTIPATH is not set
-# CONFIG_DM_DELAY is not set
-# CONFIG_DM_UEVENT is not set
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# Enable only one of the two stacks, unless you know what you are doing
-#
-# CONFIG_FIREWIRE is not set
-# CONFIG_IEEE1394 is not set
-# CONFIG_I2O is not set
-# CONFIG_MACINTOSH_DRIVERS is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_VETH is not set
-# CONFIG_ARCNET is not set
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
-# CONFIG_SMSC_PHY is not set
-CONFIG_BROADCOM_PHY=y
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_B44 is not set
-CONFIG_NETDEV_1000=y
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
-# CONFIG_IP1000 is not set
-# CONFIG_IGB is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_GIANFAR=y
-# CONFIG_MV643XX_ETH is not set
-# CONFIG_QLA3XXX is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_WAN is not set
-CONFIG_ATM_DRIVERS=y
-# CONFIG_ATM_DUMMY is not set
-# CONFIG_ATM_TCP is not set
-# CONFIG_ATM_LANAI is not set
-# CONFIG_ATM_ENI is not set
-# CONFIG_ATM_FIRESTREAM is not set
-# CONFIG_ATM_ZATM is not set
-# CONFIG_ATM_NICSTAR is not set
-# CONFIG_ATM_IDT77252 is not set
-# CONFIG_ATM_AMBASSADOR is not set
-# CONFIG_ATM_HORIZON is not set
-# CONFIG_ATM_IA is not set
-# CONFIG_ATM_FORE200E is not set
-# CONFIG_ATM_HE is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPP_MPPE is not set
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
-# CONFIG_PPPOL2TP is not set
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLHC=m
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=y
-# CONFIG_NETCONSOLE_DYNAMIC is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-
-#
-# 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_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_PCI is not set
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_UARTLITE is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
-# CONFIG_SERIAL_JSM is not set
-# CONFIG_SERIAL_OF_PLATFORM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_BRIQ_PANEL is not set
-# CONFIG_HVC_RTAS is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=m
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# PC SMBus host controller drivers
-#
-# 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_ISCH is not set
-# CONFIG_I2C_PIIX4 is not set
-# CONFIG_I2C_NFORCE2 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
-
-#
-# Mac SMBus host controller drivers
-#
-# CONFIG_I2C_HYDRA is not set
-CONFIG_I2C_POWERMAC=y
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-CONFIG_I2C_MPC=y
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_SIMTEC is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-
-#
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7473 is not set
-# CONFIG_SENSORS_AMS is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_I5K_AMB is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-# CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=m
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_8xxx_WDT is not set
-# CONFIG_WATCHDOG_RTAS is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-
-#
-# Graphics support
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-
-#
-# Enable Host or Gadget support to see Inventra options
-#
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
-# CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
-# CONFIG_DMADEVICES is not set
-# CONFIG_UIO 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_EXT2_FS_XIP 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_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-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=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-# CONFIG_REISERFS_FS_SECURITY is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-CONFIG_OCFS2_FS=m
-CONFIG_OCFS2_FS_O2CB=m
-CONFIG_OCFS2_FS_STATS=y
-CONFIG_OCFS2_DEBUG_MASKLOG=y
-# CONFIG_OCFS2_DEBUG_FS is not set
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-CONFIG_MINIX_FS=m
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-CONFIG_ROMFS_FS=m
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_WEAK_PW_HASH is not set
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-# CONFIG_CIFS_DEBUG2 is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=m
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-# CONFIG_DLM is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-CONFIG_CRC_CCITT=m
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_HAVE_LMB=y
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_UNUSED_SYMBOLS is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_VIRQ_DEBUG is not set
-# CONFIG_BDI_SWITCH is not set
-# CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-# CONFIG_SECURITY_NETWORK_XFRM is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_NULL=m
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
-# CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_XCBC is not set
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_WP512=m
-
-#
-# Ciphers
-#
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
-# CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-CONFIG_CRYPTO_KHAZAD=m
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-
-#
-# Compression
-#
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_LZO is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-# CONFIG_CRYPTO_DEV_TALITOS is not set
-# CONFIG_PPC_CLOCK is not set
-# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/include/asm/a.out.h b/arch/powerpc/include/asm/a.out.h
deleted file mode 100644 (file)
index 89cead6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_POWERPC_A_OUT_H
-#define _ASM_POWERPC_A_OUT_H
-
-struct exec
-{
-       unsigned long a_info;   /* Use macros N_MAGIC, etc for access */
-       unsigned a_text;        /* length of text, in bytes */
-       unsigned a_data;        /* length of data, in bytes */
-       unsigned a_bss;         /* length of uninitialized data area for file, in bytes */
-       unsigned a_syms;        /* length of symbol table data in file, in bytes */
-       unsigned a_entry;       /* start address */
-       unsigned a_trsize;      /* length of relocation info for text, in bytes */
-       unsigned a_drsize;      /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* _ASM_POWERPC_A_OUT_H */
index ef8a248dfd558697a374868bf35f4b8e8d5950d1..1e94b07a020ed6907be0fd1d35a2ec58b4d5b852 100644 (file)
@@ -62,6 +62,7 @@ enum powerpc_pmc_type {
        PPC_PMC_DEFAULT = 0,
        PPC_PMC_IBM = 1,
        PPC_PMC_PA6T = 2,
+       PPC_PMC_G4 = 3,
 };
 
 struct pt_regs;
@@ -192,6 +193,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_NO_SLBIE_B             LONG_ASM_CONST(0x0008000000000000)
 #define CPU_FTR_VSX                    LONG_ASM_CONST(0x0010000000000000)
 #define CPU_FTR_SAO                    LONG_ASM_CONST(0x0020000000000000)
+#define CPU_FTR_CP_USE_DCBTZ           LONG_ASM_CONST(0x0040000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -387,10 +389,11 @@ extern const char *powerpc_base_platform;
            CPU_FTR_MMCRA | CPU_FTR_CTRL)
 #define CPU_FTRS_POWER4        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_MMCRA)
+           CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ)
 #define CPU_FTRS_PPC970        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
-           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
+           CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \
+           CPU_FTR_CP_USE_DCBTZ)
 #define CPU_FTRS_POWER5        (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -411,7 +414,8 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_CELL  (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
-           CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
+           CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | \
+           CPU_FTR_CELL_TB_BUG | CPU_FTR_CP_USE_DCBTZ)
 #define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
index f15296cf35988c7e78a1d1d0236ae843bde73005..828e3aa1f2fcb007aa8ec4ace12004fffd36b74e 100644 (file)
 #define SDR0_UART3             0x0123
 #define SDR0_CUST0             0x4000
 
+/* SDR for 405EZ */
+#define DCRN_SDR_ICINTSTAT     0x4510
+#define ICINTSTAT_ICRX 0x80000000
+#define ICINTSTAT_ICTX0        0x40000000
+#define ICINTSTAT_ICTX1 0x20000000
+#define ICINTSTAT_ICTX 0x60000000
+
 /* SDRs (460EX/460GT) */
 #define SDR0_ETH_CFG           0x4103
 #define SDR0_ETH_CFG_ECS       0x00000100      /* EMAC int clk source */
index 228ab2a315b9cd1354004bb96a77419574c52af8..dfd504caccc1c711216adc077b351eb5710f32ca 100644 (file)
@@ -16,9 +16,6 @@ struct dev_archdata {
        /* DMA operations on that device */
        struct dma_mapping_ops  *dma_ops;
        void                    *dma_data;
-
-       /* NUMA node if applicable */
-       int                     numa_node;
 };
 
 #endif /* _ASM_POWERPC_DEVICE_H */
index c7ca45f97dd210e9ef611ba8d4877b6f64067021..fddb229bd74f270231c570726d7e15bef0a201f5 100644 (file)
@@ -44,8 +44,6 @@ extern void __dma_sync_page(struct page *page, unsigned long offset,
 
 #endif /* ! CONFIG_NOT_COHERENT_CACHE */
 
-#ifdef CONFIG_PPC64
-
 static inline unsigned long device_to_mask(struct device *dev)
 {
        if (dev->dma_mask && *dev->dma_mask)
@@ -76,8 +74,24 @@ struct dma_mapping_ops {
                                struct dma_attrs *attrs);
        int             (*dma_supported)(struct device *dev, u64 mask);
        int             (*set_dma_mask)(struct device *dev, u64 dma_mask);
+       dma_addr_t      (*map_page)(struct device *dev, struct page *page,
+                               unsigned long offset, size_t size,
+                               enum dma_data_direction direction,
+                               struct dma_attrs *attrs);
+       void            (*unmap_page)(struct device *dev,
+                               dma_addr_t dma_address, size_t size,
+                               enum dma_data_direction direction,
+                               struct dma_attrs *attrs);
 };
 
+/*
+ * Available generic sets of operations
+ */
+#ifdef CONFIG_PPC64
+extern struct dma_mapping_ops dma_iommu_ops;
+#endif
+extern struct dma_mapping_ops dma_direct_ops;
+
 static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
 {
        /* We don't handle the NULL dev case for ISA for now. We could
@@ -85,8 +99,19 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
         * only ISA DMA device we support is the floppy and we have a hack
         * in the floppy driver directly to get a device for us.
         */
-       if (unlikely(dev == NULL || dev->archdata.dma_ops == NULL))
+
+       if (unlikely(dev == NULL) || dev->archdata.dma_ops == NULL) {
+#ifdef CONFIG_PPC64
                return NULL;
+#else
+               /* Use default on 32-bit if dma_ops is not set up */
+               /* TODO: Long term, we should fix drivers so that dev and
+                * archdata dma_ops are set up for all buses.
+                */
+               return &dma_direct_ops;
+#endif
+       }
+
        return dev->archdata.dma_ops;
 }
 
@@ -123,6 +148,12 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
        return 0;
 }
 
+/*
+ * TODO: map_/unmap_single will ideally go away, to be completely
+ * replaced by map/unmap_page.   Until then, we allow dma_ops to have
+ * one or the other, or both by checking to see if the specific
+ * function requested exists; and if not, falling back on the other set.
+ */
 static inline dma_addr_t dma_map_single_attrs(struct device *dev,
                                              void *cpu_addr,
                                              size_t size,
@@ -132,7 +163,14 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       return dma_ops->map_single(dev, cpu_addr, size, direction, attrs);
+
+       if (dma_ops->map_single)
+               return dma_ops->map_single(dev, cpu_addr, size, direction,
+                                          attrs);
+
+       return dma_ops->map_page(dev, virt_to_page(cpu_addr),
+                                (unsigned long)cpu_addr % PAGE_SIZE, size,
+                                direction, attrs);
 }
 
 static inline void dma_unmap_single_attrs(struct device *dev,
@@ -144,7 +182,13 @@ static inline void dma_unmap_single_attrs(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->unmap_single(dev, dma_addr, size, direction, attrs);
+
+       if (dma_ops->unmap_single) {
+               dma_ops->unmap_single(dev, dma_addr, size, direction, attrs);
+               return;
+       }
+
+       dma_ops->unmap_page(dev, dma_addr, size, direction, attrs);
 }
 
 static inline dma_addr_t dma_map_page_attrs(struct device *dev,
@@ -156,8 +200,13 @@ static inline dma_addr_t dma_map_page_attrs(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
+
+       if (dma_ops->map_page)
+               return dma_ops->map_page(dev, page, offset, size, direction,
+                                        attrs);
+
        return dma_ops->map_single(dev, page_address(page) + offset, size,
-                       direction, attrs);
+                                  direction, attrs);
 }
 
 static inline void dma_unmap_page_attrs(struct device *dev,
@@ -169,6 +218,12 @@ static inline void dma_unmap_page_attrs(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
+
+       if (dma_ops->unmap_page) {
+               dma_ops->unmap_page(dev, dma_address, size, direction, attrs);
+               return;
+       }
+
        dma_ops->unmap_single(dev, dma_address, size, direction, attrs);
 }
 
@@ -253,126 +308,6 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
        dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
 }
 
-/*
- * Available generic sets of operations
- */
-extern struct dma_mapping_ops dma_iommu_ops;
-extern struct dma_mapping_ops dma_direct_ops;
-
-#else /* CONFIG_PPC64 */
-
-#define dma_supported(dev, mask)       (1)
-
-static inline int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-       if (!dev->dma_mask || !dma_supported(dev, mask))
-               return -EIO;
-
-       *dev->dma_mask = dma_mask;
-
-       return 0;
-}
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t * dma_handle,
-                                      gfp_t gfp)
-{
-#ifdef CONFIG_NOT_COHERENT_CACHE
-       return __dma_alloc_coherent(size, dma_handle, gfp);
-#else
-       void *ret;
-       /* ignore region specifiers */
-       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-       if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
-               gfp |= GFP_DMA;
-
-       ret = (void *)__get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-
-       return ret;
-#endif
-}
-
-static inline void
-dma_free_coherent(struct device *dev, size_t size, void *vaddr,
-                 dma_addr_t dma_handle)
-{
-#ifdef CONFIG_NOT_COHERENT_CACHE
-       __dma_free_coherent(size, vaddr);
-#else
-       free_pages((unsigned long)vaddr, get_order(size));
-#endif
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       __dma_sync(ptr, size, direction);
-
-       return virt_to_bus(ptr);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-                                   size_t size,
-                                   enum dma_data_direction direction)
-{
-       /* We do nothing. */
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-            unsigned long offset, size_t size,
-            enum dma_data_direction direction)
-{
-       BUG_ON(direction == DMA_NONE);
-
-       __dma_sync_page(page, offset, size, direction);
-
-       return page_to_bus(page) + offset;
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-                                 size_t size,
-                                 enum dma_data_direction direction)
-{
-       /* We do nothing. */
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
-          enum dma_data_direction direction)
-{
-       struct scatterlist *sg;
-       int i;
-
-       BUG_ON(direction == DMA_NONE);
-
-       for_each_sg(sgl, sg, nents, i) {
-               BUG_ON(!sg_page(sg));
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
-               sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
-       }
-
-       return nents;
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-                               int nhwentries,
-                               enum dma_data_direction direction)
-{
-       /* We don't do anything here. */
-}
-
-#endif /* CONFIG_PPC64 */
-
 static inline void dma_sync_single_for_cpu(struct device *dev,
                dma_addr_t dma_handle, size_t size,
                enum dma_data_direction direction)
index 64c6ee22eefd6ba4cb6dd5da54bd801440111c2a..d812929390e45e602b0a2e02506c7e4e4ac1474c 100644 (file)
@@ -232,7 +232,7 @@ typedef elf_vrregset_t elf_fpxregset_t;
 #endif /* __powerpc64__ */
 
 #ifdef __powerpc64__
-# define SET_PERSONALITY(ex, ibcs2)                            \
+# define SET_PERSONALITY(ex)                                   \
 do {                                                           \
        unsigned long new_flags = 0;                            \
        if ((ex).e_ident[EI_CLASS] == ELFCLASS32)               \
@@ -256,7 +256,7 @@ do {                                                                \
 # define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \
                (exec_stk != EXSTACK_DISABLE_X) : 0)
 #else 
-# define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+# define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 #endif /* __powerpc64__ */
 
 extern int dcache_bsize;
index 329148b5acc6478fb37afedb7affb3c89738eb37..d3d4534e3c74888e55e26e43e083a3a138ff8b81 100644 (file)
  * low halfword of the address, but for Kdump we need the whole low
  * word.
  */
-#ifdef CONFIG_CRASH_DUMP
 #define LOAD_HANDLER(reg, label)                                       \
-       oris    reg,reg,(label)@h;      /* virt addr of handler ... */  \
-       ori     reg,reg,(label)@l;      /* .. and the rest */
-#else
-#define LOAD_HANDLER(reg, label)                                       \
-       ori     reg,reg,(label)@l;      /* virt addr of handler ... */
-#endif
+       addi    reg,reg,(label)-_stext; /* virt addr of handler ... */
 
 #define EXCEPTION_PROLOG_1(area)                               \
        mfspr   r13,SPRN_SPRG3;         /* get paca address into r13 */ \
        std     r9,area+EX_R13(r13);                                    \
        mfcr    r9
 
-/*
- * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
- * The firmware calls the registered system_reset_fwnmi and
- * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
- * a 32bit application at the time of the event.
- * This firmware bug is present on POWER4 and JS20.
- */
-#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label)              \
-       EXCEPTION_PROLOG_1(area);                                       \
-       clrrdi  r12,r13,32;             /* get high part of &label */   \
-       mfmsr   r10;                                                    \
-       /* force 64bit mode */                                          \
-       li      r11,5;                  /* MSR_SF_LG|MSR_ISF_LG */      \
-       rldimi  r10,r11,61,0;           /* insert into top 3 bits */    \
-       /* done 64bit mode */                                           \
-       mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
-       LOAD_HANDLER(r12,label)                                         \
-       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
-       mtspr   SPRN_SRR0,r12;                                          \
-       mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
-       mtspr   SPRN_SRR1,r10;                                          \
-       rfid;                                                           \
-       b       .       /* prevent speculative execution */
-
 #define EXCEPTION_PROLOG_PSERIES(area, label)                          \
        EXCEPTION_PROLOG_1(area);                                       \
-       clrrdi  r12,r13,32;             /* get high part of &label */   \
-       mfmsr   r10;                                                    \
+       ld      r12,PACAKBASE(r13);     /* get high part of &label */   \
+       ld      r10,PACAKMSR(r13);      /* get MSR value for kernel */  \
        mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
        LOAD_HANDLER(r12,label)                                         \
-       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
        mtspr   SPRN_SRR0,r12;                                          \
        mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
        mtspr   SPRN_SRR1,r10;                                          \
@@ -210,11 +179,10 @@ label##_pSeries:                                                  \
        std     r10,PACA_EXGEN+EX_R13(r13);                             \
        std     r11,PACA_EXGEN+EX_R11(r13);                             \
        std     r12,PACA_EXGEN+EX_R12(r13);                             \
-       clrrdi  r12,r13,32;             /* get high part of &label */   \
-       mfmsr   r10;                                                    \
+       ld      r12,PACAKBASE(r13);     /* get high part of &label */   \
+       ld      r10,PACAKMSR(r13);      /* get MSR value for kernel */  \
        mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
        LOAD_HANDLER(r12,label##_common)                                \
-       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
        mtspr   SPRN_SRR0,r12;                                          \
        mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
        mtspr   SPRN_SRR1,r10;                                          \
index 303f5484c0507154a8177614eb8b3d6a83a538cd..63a4f779f5312d54281373c29bd319ce74a4f6ca 100644 (file)
@@ -23,9 +23,9 @@
 #ifndef __ASM_FSL_LBC_H
 #define __ASM_FSL_LBC_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 struct fsl_lbc_bank {
        __be32 br;             /**< Base Register  */
@@ -227,9 +227,6 @@ struct fsl_lbc_regs {
        u8 res8[0xF00];
 };
 
-extern struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-extern spinlock_t fsl_lbc_lock;
-
 /*
  * FSL UPM routines
  */
@@ -268,44 +265,7 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
                cpu_relax();
 }
 
-/**
- * fsl_upm_run_pattern - actually run an UPM pattern
- * @upm:       pointer to the fsl_upm structure obtained via fsl_upm_find
- * @io_base:   remapped pointer to where memory access should happen
- * @mar:       MAR register content during pattern execution
- *
- * This function triggers dummy write to the memory specified by the io_base,
- * thus UPM pattern actually executed. Note that mar usage depends on the
- * pre-programmed AMX bits in the UPM RAM.
- */
-static inline int fsl_upm_run_pattern(struct fsl_upm *upm,
-                                     void __iomem *io_base, u32 mar)
-{
-       int ret = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fsl_lbc_lock, flags);
-
-       out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
-
-       switch (upm->width) {
-       case 8:
-               out_8(io_base, 0x0);
-               break;
-       case 16:
-               out_be16(io_base, 0x0);
-               break;
-       case 32:
-               out_be32(io_base, 0x0);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       spin_unlock_irqrestore(&fsl_lbc_lock, flags);
-
-       return ret;
-}
+extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
+                              u32 mar);
 
 #endif /* __ASM_FSL_LBC_H */
index 5d99b6489d569d44e54a3781734e797d72100b5c..91c589520c0aa65256f954c0fce003e37a527b5d 100644 (file)
@@ -84,7 +84,7 @@ static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgpro
 #ifdef CONFIG_DEBUG_HIGHMEM
        BUG_ON(!pte_none(*(kmap_pte-idx)));
 #endif
-       set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+       __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
        flush_tlb_page(NULL, vaddr);
 
        return (void*) vaddr;
index 77c7fa025e658cd736175f16fc4e2144538cdd19..08266d2728b315f78d4b48231d5ac2db7bce2eb4 100644 (file)
@@ -711,7 +711,7 @@ static inline void * phys_to_virt(unsigned long address)
 /*
  * Change "struct page" to physical address.
  */
-#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
+#define page_to_phys(page)     ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
 /* We do NOT want virtual merging, it would put too much pressure on
  * our iommu allocator. Instead, we want drivers to be smart enough
index a372f76836c23145586144933e4f03f4b63bd692..0a5137676e1b89f4f76d2532d820399c2413743c 100644 (file)
@@ -236,15 +236,27 @@ extern unsigned int irq_find_mapping(struct irq_host *host,
 extern unsigned int irq_create_direct_mapping(struct irq_host *host);
 
 /**
- * irq_radix_revmap - Find a linux virq from a hw irq number.
+ * irq_radix_revmap_insert - Insert a hw irq to linux virq number mapping.
+ * @host: host owning this hardware interrupt
+ * @virq: linux irq number
+ * @hwirq: hardware irq number in that host space
+ *
+ * This is for use by irq controllers that use a radix tree reverse
+ * mapping for fast lookup.
+ */
+extern void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq,
+                                   irq_hw_number_t hwirq);
+
+/**
+ * irq_radix_revmap_lookup - Find a linux virq from a hw irq number.
  * @host: host owning this hardware interrupt
  * @hwirq: hardware irq number in that host space
  *
  * This is a fast path, for use by irq controller code that uses radix tree
  * revmaps
  */
-extern unsigned int irq_radix_revmap(struct irq_host *host,
-                                    irq_hw_number_t hwirq);
+extern unsigned int irq_radix_revmap_lookup(struct irq_host *host,
+                                           irq_hw_number_t hwirq);
 
 /**
  * irq_linear_revmap - Find a linux virq from a hw irq number.
index 2655e2a4831ead92bfc16f2b764ac80a2c2dbd31..34b52b7180cd52da00f31532cb956dff68923a86 100644 (file)
@@ -81,11 +81,17 @@ struct kvm_vcpu_arch {
        struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
        /* Pages which are referenced in the shadow TLB. */
        struct page *shadow_pages[PPC44x_TLB_SIZE];
-       /* Copy of the host's TLB. */
-       struct tlbe host_tlb[PPC44x_TLB_SIZE];
+
+       /* Track which TLB entries we've modified in the current exit. */
+       u8 shadow_tlb_mod[PPC44x_TLB_SIZE];
 
        u32 host_stack;
        u32 host_pid;
+       u32 host_dbcr0;
+       u32 host_dbcr1;
+       u32 host_dbcr2;
+       u32 host_iac[4];
+       u32 host_msr;
 
        u64 fpr[32];
        u32 gpr[32];
@@ -123,7 +129,11 @@ struct kvm_vcpu_arch {
        u32 ivor[16];
        u32 ivpr;
        u32 pir;
+
+       u32 shadow_pid;
        u32 pid;
+       u32 swap_pid;
+
        u32 pvr;
        u32 ccr0;
        u32 ccr1;
index a8b068792260a56a5371fcec5845a66a634d0453..8931ba729d2b519ec4d4efb1d0851301d96e1d3a 100644 (file)
@@ -64,6 +64,10 @@ extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
 extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
                                   gva_t eend, u32 asid);
 extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
+extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid);
+
+/* XXX Book E specific */
+extern void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i);
 
 extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
 
@@ -92,4 +96,12 @@ static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
                kvm_vcpu_block(vcpu);
 }
 
+static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
+{
+       if (vcpu->arch.pid != new_pid) {
+               vcpu->arch.pid = new_pid;
+               vcpu->arch.swap_pid = 1;
+       }
+}
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index 893aafd87fde2b20ce7eda9dee61f30b79c9ec91..2740c44ff71766e5e9dad9c01b33e7377d0d4bbd 100644 (file)
@@ -88,8 +88,6 @@ struct machdep_calls {
        unsigned long   (*tce_get)(struct iommu_table *tbl,
                                    long index);
        void            (*tce_flush)(struct iommu_table *tbl);
-       void            (*pci_dma_dev_setup)(struct pci_dev *dev);
-       void            (*pci_dma_bus_setup)(struct pci_bus *bus);
 
        void __iomem *  (*ioremap)(phys_addr_t addr, unsigned long size,
                                   unsigned long flags);
@@ -101,6 +99,9 @@ struct machdep_calls {
 #endif
 #endif /* CONFIG_PPC64 */
 
+       void            (*pci_dma_dev_setup)(struct pci_dev *dev);
+       void            (*pci_dma_bus_setup)(struct pci_bus *bus);
+
        int             (*probe)(void);
        void            (*setup_arch)(void); /* Optional, may be NULL */
        void            (*init_early)(void);
index 9209f755763e100bd93a3b8046098a09c4972de1..e7b99bac9f4875312655e1f3b44799b6734f6a16 100644 (file)
@@ -44,7 +44,7 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot)
 
 static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags)
 {
-       return (vm_flags & VM_SAO) ? __pgprot(_PAGE_SAO) : 0;
+       return (vm_flags & VM_SAO) ? __pgprot(_PAGE_SAO) : __pgprot(0);
 }
 #define arch_vm_get_page_prot(vm_flags) arch_vm_get_page_prot(vm_flags)
 
index c2df53c5ceb9a253c7c4661731b67397b14afac3..5a441742ffba45434038716ae368aa516eccbdfe 100644 (file)
@@ -437,7 +437,7 @@ typedef struct {
        })
 #endif /* 1 */
 
-/* This is only valid for addresses >= KERNELBASE */
+/* This is only valid for addresses >= PAGE_OFFSET */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
        if (ssize == MMU_SEGSIZE_256M)
index fe566a348a86e7e770ab014b11d96b380563183f..34d9ac433ace02fc169be44afc3fdd450bfb615c 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/irq.h>
 #include <linux/sysdev.h>
 #include <asm/dcr.h>
+#include <asm/msi_bitmap.h>
 
 /*
  * Global registers
@@ -301,8 +302,7 @@ struct mpic
 #endif
 
 #ifdef CONFIG_PCI_MSI
-       spinlock_t              bitmap_lock;
-       unsigned long           *hwirq_bitmap;
+       struct msi_bitmap       msi_bitmap;
 #endif
 
 #ifdef CONFIG_MPIC_BROKEN_REGREAD
diff --git a/arch/powerpc/include/asm/msi_bitmap.h b/arch/powerpc/include/asm/msi_bitmap.h
new file mode 100644 (file)
index 0000000..97ac3f4
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _POWERPC_SYSDEV_MSI_BITMAP_H
+#define _POWERPC_SYSDEV_MSI_BITMAP_H
+
+/*
+ * Copyright 2008, Michael Ellerman, 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; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/of.h>
+#include <asm/irq.h>
+
+struct msi_bitmap {
+       struct device_node      *of_node;
+       unsigned long           *bitmap;
+       spinlock_t              lock;
+       unsigned int            irq_count;
+};
+
+int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num);
+void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset,
+                           unsigned int num);
+void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq);
+
+int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp);
+
+int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count,
+                    struct device_node *of_node);
+void msi_bitmap_free(struct msi_bitmap *bmp);
+
+#endif /* _POWERPC_SYSDEV_MSI_BITMAP_H */
index 3c123990ca2e0f3db95b03c939e62a6e6050df30..a64debf177dca8efcbe7534333f81a5b2d3d26d5 100644 (file)
@@ -24,8 +24,5 @@ extern struct of_device *of_device_alloc(struct device_node *np,
 extern int of_device_uevent(struct device *dev,
                            struct kobj_uevent_env *env);
 
-/* This is just here during the transition */
-#include <linux/of_device.h>
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_OF_DEVICE_H */
index 18659ef72139c3599796b5fc718a23fe676bc71d..53b46507ffde02c9baab0c6343cd22ffb76c8092 100644 (file)
@@ -11,9 +11,6 @@
  *
  */
 
-/* This is just here during the transition */
-#include <linux/of_platform.h>
-
 /* Platform drivers register/unregister */
 static inline int of_register_platform_driver(struct of_platform_driver *drv)
 {
index 6493a395508b800678e0df51b4d0d17fb587a2a0..082b3aedf145b4fe3d368f39829cc87911e9b62a 100644 (file)
@@ -62,6 +62,8 @@ struct paca_struct {
        u16 paca_index;                 /* Logical processor number */
 
        u64 kernel_toc;                 /* Kernel TOC address */
+       u64 kernelbase;                 /* Base address of kernel */
+       u64 kernel_msr;                 /* MSR while running in kernel */
        u64 stab_real;                  /* Absolute address of segment table */
        u64 stab_addr;                  /* Virtual address of segment table */
        void *emergency_sp;             /* pointer to emergency stack */
index e088545cb3f5ea67b2065f962f89c34f4798ae1a..64e144505f653e0ae1d4f190690ef458e9aad5e7 100644 (file)
 #define PAGE_OFFSET    ASM_CONST(CONFIG_PAGE_OFFSET)
 #define LOAD_OFFSET    ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))
 
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_FLATMEM)
+#if defined(CONFIG_RELOCATABLE)
 #ifndef __ASSEMBLY__
 extern phys_addr_t memstart_addr;
 extern phys_addr_t kernstart_addr;
 #endif
 #define PHYSICAL_START kernstart_addr
-#define MEMORY_START   memstart_addr
 #else
 #define PHYSICAL_START ASM_CONST(CONFIG_PHYSICAL_START)
+#endif
+
+#ifdef CONFIG_PPC64
+#define MEMORY_START   0UL
+#elif defined(CONFIG_RELOCATABLE)
+#define MEMORY_START   memstart_addr
+#else
 #define MEMORY_START   (PHYSICAL_START + PAGE_OFFSET - KERNELBASE)
 #endif
 
@@ -92,8 +98,8 @@ extern phys_addr_t kernstart_addr;
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define __va(x) ((void *)((unsigned long)(x) - PHYSICAL_START + KERNELBASE))
-#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - MEMORY_START))
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
 
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
index ebfae530a3799b075c201df143394d1694ef74e7..d77072a32cc68b2553b1e329542b1f4925656c57 100644 (file)
 #define ARCH_KMALLOC_MINALIGN  L1_CACHE_BYTES
 #endif
 
+#ifdef CONFIG_PTE_64BIT
+#define PTE_FLAGS_OFFSET       4       /* offset of PTE flags, in bytes */
+#else
+#define PTE_FLAGS_OFFSET       0
+#endif
+
 #ifndef __ASSEMBLY__
 /*
  * The basic type of a PTE - 64 bits for those CPUs with > 32 bit
- * physical addressing.  For now this just the IBM PPC440.
+ * physical addressing.
  */
 #ifdef CONFIG_PTE_64BIT
 typedef unsigned long long pte_basic_t;
index a05a942b1c2573d4dae0ba35e2bbf24d6b3d2f14..0e52c7828ea498d48c34a37155dba0f57b39a349 100644 (file)
@@ -60,6 +60,14 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return channel ? 15 : 14;
 }
 
+#ifdef CONFIG_PCI
+extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
+extern struct dma_mapping_ops *get_pci_dma_ops(void);
+#else  /* CONFIG_PCI */
+#define set_pci_dma_ops(d)
+#define get_pci_dma_ops()      NULL
+#endif
+
 #ifdef CONFIG_PPC64
 
 /*
@@ -70,9 +78,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 #define PCI_DISABLE_MWI
 
 #ifdef CONFIG_PCI
-extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
-extern struct dma_mapping_ops *get_pci_dma_ops(void);
-
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
                                        unsigned long *strategy_parameter)
@@ -89,9 +94,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
        *strat = PCI_DMA_BURST_MULTIPLE;
        *strategy_parameter = cacheline_size;
 }
-#else  /* CONFIG_PCI */
-#define set_pci_dma_ops(d)
-#define get_pci_dma_ops()      NULL
 #endif
 
 #else /* 32-bit */
index 6fe39e327047d16814f345402303efb75e9822b7..6ab7c67cb5ab6355ba453e4832ad55bcdb03ec85 100644 (file)
@@ -261,6 +261,7 @@ extern int icache_44x_need_flush;
 #define _PAGE_HWEXEC   0x00000004              /* H: Execute permission */
 #define _PAGE_ACCESSED 0x00000008              /* S: Page referenced */
 #define _PAGE_DIRTY    0x00000010              /* S: Page dirty */
+#define _PAGE_SPECIAL  0x00000020              /* S: Special page */
 #define _PAGE_USER     0x00000040              /* S: User page */
 #define _PAGE_ENDIAN   0x00000080              /* H: E bit */
 #define _PAGE_GUARDED  0x00000100              /* H: G bit */
@@ -276,6 +277,7 @@ extern int icache_44x_need_flush;
 /* ERPN in a PTE never gets cleared, ignore it */
 #define _PTE_NONE_MASK 0xffffffff00000000ULL
 
+#define __HAVE_ARCH_PTE_SPECIAL
 
 #elif defined(CONFIG_FSL_BOOKE)
 /*
@@ -305,6 +307,7 @@ extern int icache_44x_need_flush;
 #define _PAGE_COHERENT 0x00100 /* H: M bit */
 #define _PAGE_NO_CACHE 0x00200 /* H: I bit */
 #define _PAGE_WRITETHRU        0x00400 /* H: W bit */
+#define _PAGE_SPECIAL  0x00800 /* S: Special page */
 
 #ifdef CONFIG_PTE_64BIT
 /* ERPN in a PTE never gets cleared, ignore it */
@@ -315,6 +318,8 @@ extern int icache_44x_need_flush;
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD       (~PAGE_MASK)
 
+#define __HAVE_ARCH_PTE_SPECIAL
+
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT  0x0001  /* Page is valid */
@@ -362,8 +367,14 @@ extern int icache_44x_need_flush;
 #define _PAGE_ACCESSED 0x100   /* R: page referenced */
 #define _PAGE_EXEC     0x200   /* software: i-cache coherency required */
 #define _PAGE_RW       0x400   /* software: user write access allowed */
+#define _PAGE_SPECIAL  0x800   /* software: Special page */
 
+#ifdef CONFIG_PTE_64BIT
+/* We never clear the high word of the pte */
+#define _PTE_NONE_MASK (0xffffffff00000000ULL | _PAGE_HASHPTE)
+#else
 #define _PTE_NONE_MASK _PAGE_HASHPTE
+#endif
 
 #define _PMD_PRESENT   0
 #define _PMD_PRESENT_MASK (PAGE_MASK)
@@ -372,6 +383,8 @@ extern int icache_44x_need_flush;
 /* Hash table based platforms need atomic updates of the linux PTE */
 #define PTE_ATOMIC_UPDATES     1
 
+#define __HAVE_ARCH_PTE_SPECIAL
+
 #endif
 
 /*
@@ -404,6 +417,9 @@ extern int icache_44x_need_flush;
 #ifndef _PAGE_WRITETHRU
 #define _PAGE_WRITETHRU        0
 #endif
+#ifndef _PAGE_SPECIAL
+#define _PAGE_SPECIAL  0
+#endif
 #ifndef _PMD_PRESENT_MASK
 #define _PMD_PRESENT_MASK      _PMD_PRESENT
 #endif
@@ -415,11 +431,11 @@ extern int icache_44x_need_flush;
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
 
-#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
-                                _PAGE_WRITETHRU | _PAGE_ENDIAN | \
-                                _PAGE_USER | _PAGE_ACCESSED | \
-                                _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
-                                _PAGE_EXEC | _PAGE_HWEXEC)
+#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
+                        _PAGE_WRITETHRU | _PAGE_ENDIAN | \
+                        _PAGE_USER | _PAGE_ACCESSED | \
+                        _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
+                        _PAGE_EXEC | _PAGE_HWEXEC)
 /*
  * Note: the _PAGE_COHERENT bit automatically gets set in the hardware
  * PTE if CONFIG_SMP is defined (hash_page does this); there is no need
@@ -517,7 +533,8 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
 
 #define pte_none(pte)          ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
 #define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(mm,addr,ptep)        do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
+#define pte_clear(mm, addr, ptep) \
+       do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0)
 
 #define pmd_none(pmd)          (!pmd_val(pmd))
 #define        pmd_bad(pmd)            (pmd_val(pmd) & _PMD_BAD)
@@ -533,7 +550,7 @@ static inline int pte_write(pte_t pte)              { return pte_val(pte) & _PAGE_RW; }
 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_file(pte_t pte)          { return pte_val(pte) & _PAGE_FILE; }
-static inline int pte_special(pte_t pte)       { return 0; }
+static inline int pte_special(pte_t pte)       { return pte_val(pte) & _PAGE_SPECIAL; }
 
 static inline void pte_uncache(pte_t pte)       { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)         { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -552,10 +569,10 @@ static inline pte_t pte_mkdirty(pte_t pte) {
 static inline pte_t pte_mkyoung(pte_t pte) {
        pte_val(pte) |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkspecial(pte_t pte) {
-       return pte; }
-static inline unsigned long pte_pgprot(pte_t pte)
+       pte_val(pte) |= _PAGE_SPECIAL; return pte; }
+static inline pgprot_t pte_pgprot(pte_t pte)
 {
-       return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+       return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
 }
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -575,6 +592,10 @@ extern int flush_hash_pages(unsigned context, unsigned long va,
 extern void add_hash_page(unsigned context, unsigned long va,
                          unsigned long pmdval);
 
+/* Flush an entry from the TLB/hash table */
+extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
+                            unsigned long address);
+
 /*
  * Atomic PTE updates.
  *
@@ -612,9 +633,6 @@ static inline unsigned long pte_update(pte_t *p,
        return old;
 }
 #else /* CONFIG_PTE_64BIT */
-/* TODO: Change that to only modify the low word and move set_pte_at()
- * out of line
- */
 static inline unsigned long long pte_update(pte_t *p,
                                            unsigned long clr,
                                            unsigned long set)
@@ -652,14 +670,36 @@ static inline unsigned long long pte_update(pte_t *p,
  * On machines which use an MMU hash table we avoid changing the
  * _PAGE_HASHPTE bit.
  */
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t pte)
 {
-#if _PAGE_HASHPTE != 0
+#if (_PAGE_HASHPTE != 0) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT)
        pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
+#elif defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
+#if _PAGE_HASHPTE != 0
+       if (pte_val(*ptep) & _PAGE_HASHPTE)
+               flush_hash_entry(mm, ptep, addr);
+#endif
+       __asm__ __volatile__("\
+               stw%U0%X0 %2,%0\n\
+               eieio\n\
+               stw%U0%X0 %L2,%1"
+       : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
+       : "r" (pte) : "memory");
 #else
-       *ptep = pte;
+       *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE)
+                     | (pte_val(pte) & ~_PAGE_HASHPTE));
+#endif
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pte)
+{
+#if defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP)
+       WARN_ON(pte_present(*ptep));
 #endif
+       __set_pte_at(mm, addr, ptep, pte);
 }
 
 /*
index 4597c491e9b52ee72c854271a88e0b572823507a..4c0a8c62859d0f6d1560c2b575ecc85cfc219831 100644 (file)
 #define PAGE_AGP       __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE)
 #define HAVE_PAGE_AGP
 
-#define PAGE_PROT_BITS __pgprot(_PAGE_GUARDED | _PAGE_COHERENT | \
-                                _PAGE_NO_CACHE | _PAGE_WRITETHRU | \
-                                _PAGE_4K_PFN | _PAGE_RW | _PAGE_USER | \
-                                _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
+#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | \
+                        _PAGE_NO_CACHE | _PAGE_WRITETHRU |             \
+                        _PAGE_4K_PFN | _PAGE_RW | _PAGE_USER |         \
+                        _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
 /* PTEIDX nibble */
 #define _PTEIDX_SECONDARY      0x8
 #define _PTEIDX_GROUP_IX       0x7
@@ -264,9 +264,9 @@ static inline pte_t pte_mkhuge(pte_t pte) {
        return pte; }
 static inline pte_t pte_mkspecial(pte_t pte) {
        pte_val(pte) |= _PAGE_SPECIAL; return pte; }
-static inline unsigned long pte_pgprot(pte_t pte)
+static inline pgprot_t pte_pgprot(pte_t pte)
 {
-       return __pgprot(pte_val(pte)) & PAGE_PROT_BITS;
+       return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
 }
 
 /* Atomic PTE updates */
index 0966899d974b07050e79003c1d50eb267dbb1b6e..c4a029ccb4d31d5273cc6e43fc381e23ff6f9c08 100644 (file)
@@ -268,7 +268,7 @@ n:
  *   Loads the value of the constant expression 'expr' into register 'rn'
  *   using immediate instructions only.  Use this when it's important not
  *   to reference other data (i.e. on ppc64 when the TOC pointer is not
- *   valid).
+ *   valid) and when 'expr' is a constant or absolute address.
  *
  * LOAD_REG_ADDR(rn, name)
  *   Loads the address of label 'name' into register 'rn'.  Use this when
index be980f4ee4956cd20d00fe107c103d7b2a58d21a..67453766bff1f7b6593fb1c3e75aca686e4c23c6 100644 (file)
 #define SPRN_EVPR      0x3D6   /* Exception Vector Prefix Register */
 #define SPRN_L1CSR0    0x3F2   /* L1 Cache Control and Status Register 0 */
 #define SPRN_L1CSR1    0x3F3   /* L1 Cache Control and Status Register 1 */
+#define SPRN_MMUCSR0   0x3F4   /* MMU Control and Status Register 0 */
 #define SPRN_PIT       0x3DB   /* Programmable Interval Timer */
 #define SPRN_BUCSR     0x3F5   /* Branch Unit Control and Status */
 #define SPRN_L2CSR0    0x3F9   /* L2 Data Cache Control and Status Register 0 */
 #define L2CSR0_L2LOA   0x00000080      /* L2 Cache Lock Overflow Allocate */
 #define L2CSR0_L2LO    0x00000020      /* L2 Cache Lock Overflow */
 
+/* Bit definitions for MMUCSR0 */
+#define MMUCSR0_TLB1FI 0x00000002      /* TLB1 Flash invalidate */
+#define MMUCSR0_TLB0FI 0x00000004      /* TLB0 Flash invalidate */
+#define MMUCSR0_TLB2FI 0x00000040      /* TLB2 Flash invalidate */
+#define MMUCSR0_TLB3FI 0x00000020      /* TLB3 Flash invalidate */
+
 /* Bit definitions for SGR. */
 #define SGR_NORMAL     0               /* Speculative fetching allowed. */
 #define SGR_GUARDED    1               /* Speculative fetching disallowed. */
index 07956f3e78444f5f63390d8d328c000af957061f..6fbce725c710f97453079205e190c02c7365cd0b 100644 (file)
@@ -18,6 +18,12 @@ static inline int in_kernel_text(unsigned long addr)
        return 0;
 }
 
+static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
+{
+       return start < (unsigned long)__init_end &&
+               (unsigned long)_stext < end;
+}
+
 #undef dereference_function_descriptor
 static inline void *dereference_function_descriptor(void *ptr)
 {
diff --git a/arch/powerpc/include/asm/sfp-machine.h b/arch/powerpc/include/asm/sfp-machine.h
new file mode 100644 (file)
index 0000000..ced34f1
--- /dev/null
@@ -0,0 +1,353 @@
+/* Machine-dependent software floating-point definitions.  PPC version.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Actually, this is a PPC (32bit) version, written based on the
+   i386, sparc, and sparc64 versions, by me,
+   Peter Maydell (pmaydell@chiark.greenend.org.uk).
+   Comments are by and large also mine, although they may be inaccurate.
+
+   In picking out asm fragments I've gone with the lowest common
+   denominator, which also happens to be the hardware I have :->
+   That is, a SPARC without hardware multiply and divide.
+ */
+
+/* basic word size definitions */
+#define _FP_W_TYPE_SIZE                32
+#define _FP_W_TYPE             unsigned long
+#define _FP_WS_TYPE            signed long
+#define _FP_I_TYPE             long
+
+#define __ll_B                 ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t)                ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t)       ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* You can optionally code some things like addition in asm. For
+ * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
+ * then you get a fragment of C code [if you change an #ifdef 0
+ * in op-2.h] or a call to add_ssaaaa (see below).
+ * Good places to look for asm fragments to use are gcc and glibc.
+ * gcc's longlong.h is useful.
+ */
+
+/* We need to know how to multiply and divide. If the host word size
+ * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
+ * codes the multiply with whatever gcc does to 'a * b'.
+ * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm
+ * function that can multiply two 1W values and get a 2W result.
+ * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
+ * does bitshifting to avoid overflow.
+ * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
+ * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or
+ * _FP_DIV_HELP_ldiv (see op-1.h).
+ * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
+ * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
+ * to do this.]
+ * In general, 'n' is the number of words required to hold the type,
+ * and 't' is either S, D or Q for single/double/quad.
+ *           -- PMM
+ */
+/* Example: SPARC64:
+ * #define _FP_MUL_MEAT_S(R,X,Y)       _FP_MUL_MEAT_1_imm(S,R,X,Y)
+ * #define _FP_MUL_MEAT_D(R,X,Y)       _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
+ * #define _FP_MUL_MEAT_Q(R,X,Y)       _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y)       _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+ * #define _FP_DIV_MEAT_D(R,X,Y)       _FP_DIV_MEAT_1_udiv(D,R,X,Y)
+ * #define _FP_DIV_MEAT_Q(R,X,Y)       _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
+ *
+ * Example: i386:
+ * #define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
+ * #define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
+ * #define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
+ */
+
+#define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+
+/* These macros define what NaN looks like. They're supposed to expand to
+ * a comma-separated set of 32bit unsigned ints that encode NaN.
+ */
+#define _FP_NANFRAC_S          ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D          ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q          ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+
+/* Exception flags.  We use the bit positions of the appropriate bits
+   in the FPSCR, which also correspond to the FE_* bits.  This makes
+   everything easier ;-).  */
+#define FP_EX_INVALID         (1 << (31 - 2))
+#define FP_EX_INVALID_SNAN     EFLAG_VXSNAN
+#define FP_EX_INVALID_ISI      EFLAG_VXISI
+#define FP_EX_INVALID_IDI      EFLAG_VXIDI
+#define FP_EX_INVALID_ZDZ      EFLAG_VXZDZ
+#define FP_EX_INVALID_IMZ      EFLAG_VXIMZ
+#define FP_EX_OVERFLOW        (1 << (31 - 3))
+#define FP_EX_UNDERFLOW       (1 << (31 - 4))
+#define FP_EX_DIVZERO         (1 << (31 - 5))
+#define FP_EX_INEXACT         (1 << (31 - 6))
+
+/* This macro appears to be called when both X and Y are NaNs, and
+ * has to choose one and copy it to R. i386 goes for the larger of the
+ * two, sparc64 just picks Y. I don't understand this at all so I'll
+ * go with sparc64 because it's shorter :->   -- PMM
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)             \
+  do {                                                 \
+    R##_s = Y##_s;                                     \
+    _FP_FRAC_COPY_##wc(R,Y);                           \
+    R##_c = FP_CLS_NAN;                                        \
+  } while (0)
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#define __FPU_FPSCR    (current->thread.fpscr.val)
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_ENABLED_EXC \
+({                                             \
+       (__FPU_FPSCR >> 3) & 0x1f;      \
+})
+
+#define __FPU_TRAP_P(bits) \
+       ((__FPU_ENABLED_EXC & (bits)) != 0)
+
+#define __FP_PACK_S(val,X)                     \
+({  int __exc = _FP_PACK_CANONICAL(S,1,X);     \
+    if(!__exc || !__FPU_TRAP_P(__exc))         \
+        _FP_PACK_RAW_1_P(S,val,X);             \
+    __exc;                                     \
+})
+
+#define __FP_PACK_D(val,X)                     \
+   do {                                                                        \
+       _FP_PACK_CANONICAL(D, 2, X);                                    \
+       if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS))     \
+               _FP_PACK_RAW_2_P(D, val, X);                            \
+   } while (0)
+
+#define __FP_PACK_DS(val,X)                                                    \
+   do {                                                                                \
+          FP_DECL_S(__X);                                                      \
+          FP_CONV(S, D, 1, 2, __X, X);                                         \
+          _FP_PACK_CANONICAL(S, 1, __X);                                       \
+          if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) {        \
+                  _FP_UNPACK_CANONICAL(S, 1, __X);                             \
+                  FP_CONV(D, S, 2, 1, X, __X);                                 \
+                  _FP_PACK_CANONICAL(D, 2, X);                                 \
+                  if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS))  \
+                  _FP_PACK_RAW_2_P(D, val, X);                                 \
+          }                                                                    \
+   } while (0)
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE                   \
+({                                     \
+       __FPU_FPSCR & 0x3;              \
+})
+
+/* the asm fragments go here: all these are taken from glibc-2.0.5's
+ * stdlib/longlong.h
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/* add_ssaaaa is used in op-2.h and should be equivalent to
+ * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
+ * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ * high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ * respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+ * (i.e. carry out) is not stored anywhere, and is lost.
+ */
+#define add_ssaaaa(sh, sl, ah, al, bh, bl)                             \
+  do {                                                                 \
+    if (__builtin_constant_p (bh) && (bh) == 0)                                \
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"          \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"          \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+    else                                                               \
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"         \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "r" ((USItype)(bh)),                                     \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+  } while (0)
+
+/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
+ * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
+ * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ * LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+ * and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
+ * and is lost.
+ */
+#define sub_ddmmss(sh, sl, ah, al, bh, bl)                             \
+  do {                                                                 \
+    if (__builtin_constant_p (ah) && (ah) == 0)                                \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"      \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0)         \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"      \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (bh) && (bh) == 0)                   \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"                \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"                \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else                                                               \
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"     \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+  } while (0)
+
+/* asm fragments for mul and div */
+
+/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+ * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+ * word product in HIGH_PROD and LOW_PROD.
+ */
+#define umul_ppmm(ph, pl, m0, m1)                                      \
+  do {                                                                 \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("mulhwu %0,%1,%2"                                         \
+            : "=r" ((USItype)(ph))                                     \
+            : "%r" (__m0),                                             \
+               "r" (__m1));                                            \
+    (pl) = __m0 * __m1;                                                        \
+  } while (0)
+
+/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ * denominator) divides a UDWtype, composed by the UWtype integers
+ * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ * in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
+ * than DENOMINATOR for correct operation.  If, in addition, the most
+ * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ * UDIV_NEEDS_NORMALIZATION is defined to 1.
+ */
+#define udiv_qrnnd(q, r, n1, n0, d)                                    \
+  do {                                                                 \
+    UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;                    \
+    __d1 = __ll_highpart (d);                                          \
+    __d0 = __ll_lowpart (d);                                           \
+                                                                       \
+    __r1 = (n1) % __d1;                                                        \
+    __q1 = (n1) / __d1;                                                        \
+    __m = (UWtype) __q1 * __d0;                                                \
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
+    if (__r1 < __m)                                                    \
+      {                                                                        \
+       __q1--, __r1 += (d);                                            \
+       if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */  \
+         if (__r1 < __m)                                               \
+           __q1--, __r1 += (d);                                        \
+      }                                                                        \
+    __r1 -= __m;                                                       \
+                                                                       \
+    __r0 = __r1 % __d1;                                                        \
+    __q0 = __r1 / __d1;                                                        \
+    __m = (UWtype) __q0 * __d0;                                                \
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
+    if (__r0 < __m)                                                    \
+      {                                                                        \
+       __q0--, __r0 += (d);                                            \
+       if (__r0 >= (d))                                                \
+         if (__r0 < __m)                                               \
+           __q0--, __r0 += (d);                                        \
+      }                                                                        \
+    __r0 -= __m;                                                       \
+                                                                       \
+    (q) = (UWtype) __q1 * __ll_B | __q0;                               \
+    (r) = __r0;                                                                \
+  } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1
+
+#define abort()                                                                \
+       return 0
+
+#ifdef __BIG_ENDIAN
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+/* Exception flags. */
+#define EFLAG_INVALID          (1 << (31 - 2))
+#define EFLAG_OVERFLOW         (1 << (31 - 3))
+#define EFLAG_UNDERFLOW                (1 << (31 - 4))
+#define EFLAG_DIVZERO          (1 << (31 - 5))
+#define EFLAG_INEXACT          (1 << (31 - 6))
+
+#define EFLAG_VXSNAN           (1 << (31 - 7))
+#define EFLAG_VXISI            (1 << (31 - 8))
+#define EFLAG_VXIDI            (1 << (31 - 9))
+#define EFLAG_VXZDZ            (1 << (31 - 10))
+#define EFLAG_VXIMZ            (1 << (31 - 11))
+#define EFLAG_VXVC             (1 << (31 - 12))
+#define EFLAG_VXSOFT           (1 << (31 - 21))
+#define EFLAG_VXSQRT           (1 << (31 - 22))
+#define EFLAG_VXCVI            (1 << (31 - 23))
index 4d28e1e4521b8c39992d327a4d0699d8f0df4ba2..1866cec4f9677b5fc995e754cea3ed6936d7ec57 100644 (file)
@@ -56,9 +56,16 @@ extern int smp_hw_index[];
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 #define hard_smp_processor_id()        (smp_hw_index[smp_processor_id()])
-#define get_hard_smp_processor_id(cpu) (smp_hw_index[(cpu)])
-#define set_hard_smp_processor_id(cpu, phys)\
-                                       (smp_hw_index[(cpu)] = (phys))
+
+static inline int get_hard_smp_processor_id(int cpu)
+{
+       return smp_hw_index[cpu];
+}
+
+static inline void set_hard_smp_processor_id(int cpu, int phys)
+{
+       smp_hw_index[cpu] = phys;
+}
 #endif
 
 DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
@@ -86,15 +93,21 @@ extern void __cpu_die(unsigned int cpu);
 
 #else
 /* for UP */
-#define hard_smp_processor_id()                0
+#define hard_smp_processor_id()                get_hard_smp_processor_id(0)
 #define smp_setup_cpu_maps()
 
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC64
-#define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id)
-#define set_hard_smp_processor_id(CPU, VAL) \
-       do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0)
+static inline int get_hard_smp_processor_id(int cpu)
+{
+       return paca[cpu].hw_cpu_id;
+}
+
+static inline void set_hard_smp_processor_id(int cpu, int phys)
+{
+       paca[cpu].hw_cpu_id = phys;
+}
 
 extern void smp_release_cpus(void);
 
@@ -102,10 +115,17 @@ extern void smp_release_cpus(void);
 /* 32-bit */
 #ifndef CONFIG_SMP
 extern int boot_cpuid_phys;
-#define get_hard_smp_processor_id(cpu)         boot_cpuid_phys
-#define set_hard_smp_processor_id(cpu, phys)
-#endif
-#endif
+static inline int get_hard_smp_processor_id(int cpu)
+{
+       return boot_cpuid_phys;
+}
+
+static inline void set_hard_smp_processor_id(int cpu, int phys)
+{
+       boot_cpuid_phys = phys;
+}
+#endif /* !CONFIG_SMP */
+#endif /* !CONFIG_PPC64 */
 
 extern int smt_enabled_at_boot;
 
index 67024026c10d281dcfe5e3ab602305d6f07cf664..5244834583a42c950c09285f589ed80b0141c9a3 100644 (file)
@@ -1,60 +1,6 @@
 #ifndef _ASM_POWERPC_STATFS_H
 #define _ASM_POWERPC_STATFS_H
 
-/* For ppc32 we just use the generic definitions, not so simple on ppc64 */
-
-#ifndef __powerpc64__
 #include <asm-generic/statfs.h>
-#else
-
-#ifndef __KERNEL_STRICT_NAMES
-#include <linux/types.h>
-typedef __kernel_fsid_t        fsid_t;
-#endif
-
-/*
- * We're already 64-bit, so duplicate the definition
- */
-struct statfs {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct statfs64 {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
 
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-};
-#endif /* ! __powerpc64__ */
 #endif
index f6cc7a43b4faadeb17f080794ff7e8d2a06f4a72..803def236654a0e81b4e6ab105e994e63fb164a4 100644 (file)
@@ -32,7 +32,7 @@ COMPAT_SYS_SPU(stime)
 COMPAT_SYS(ptrace)
 SYSCALL_SPU(alarm)
 OLDSYS(fstat)
-COMPAT_SYS(pause)
+SYSCALL(pause)
 COMPAT_SYS(utime)
 SYSCALL(ni_syscall)
 SYSCALL(ni_syscall)
index 361cd5c7a32b428107b6815ae2240fce19de99e1..a2c6bfd85fb7a38ab6d002373c24afbf8648399a 100644 (file)
@@ -29,6 +29,9 @@
 #include <linux/mm.h>
 
 extern void _tlbie(unsigned long address, unsigned int pid);
+extern void _tlbil_all(void);
+extern void _tlbil_pid(unsigned int pid);
+extern void _tlbil_va(unsigned long address, unsigned int pid);
 
 #if defined(CONFIG_40x) || defined(CONFIG_8xx)
 #define _tlbia()       asm volatile ("tlbia; sync" : : : "memory")
@@ -38,31 +41,31 @@ extern void _tlbia(void);
 
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
-       _tlbia();
+       _tlbil_pid(mm->context.id);
 }
 
 static inline void flush_tlb_page(struct vm_area_struct *vma,
                                  unsigned long vmaddr)
 {
-       _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
+       _tlbil_va(vmaddr, vma ? vma->vm_mm->context.id : 0);
 }
 
 static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
                                         unsigned long vmaddr)
 {
-       _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
+       flush_tlb_page(vma, vmaddr);
 }
 
 static inline void flush_tlb_range(struct vm_area_struct *vma,
                                   unsigned long start, unsigned long end)
 {
-       _tlbia();
+       _tlbil_pid(vma->vm_mm->context.id);
 }
 
 static inline void flush_tlb_kernel_range(unsigned long start,
                                          unsigned long end)
 {
-       _tlbia();
+       _tlbil_pid(0);
 }
 
 #elif defined(CONFIG_PPC32)
index d3374bc865ba565c803056ed33cc57d64241d670..c004c13f291e771fa63a6f842094b3faacee7037 100644 (file)
@@ -48,14 +48,7 @@ typedef struct {
 
 typedef __vector128 vector128;
 
-/* Physical address used by some IO functions */
-#if defined(CONFIG_PPC64) || defined(CONFIG_PHYS_64BIT)
-typedef u64 phys_addr_t;
-#else
-typedef u32 phys_addr_t;
-#endif
-
-#ifdef __powerpc64__
+#if defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)
 typedef u64 dma_addr_t;
 #else
 typedef u32 dma_addr_t;
diff --git a/arch/powerpc/kernel/.gitignore b/arch/powerpc/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index 946daea780f1ea6858624368e235142f0448a508..fdb58253fa5b15727580cdc2119eef4512596411 100644 (file)
@@ -28,13 +28,14 @@ endif
 obj-y                          := cputable.o ptrace.o syscalls.o \
                                   irq.o align.o signal_32.o pmc.o vdso.o \
                                   init_task.o process.o systbl.o idle.o \
-                                  signal.o
+                                  signal.o sysfs.o
 obj-y                          += vdso32/
 obj-$(CONFIG_PPC64)            += setup_64.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
                                   paca.o cpu_setup_ppc970.o \
                                   cpu_setup_pa6t.o \
-                                  firmware.o sysfs.o nvram_64.o
+                                  firmware.o nvram_64.o
+obj64-$(CONFIG_RELOCATABLE)    += reloc_64.o
 obj-$(CONFIG_PPC64)            += vdso64/
 obj-$(CONFIG_ALTIVEC)          += vecemu.o vector.o
 obj-$(CONFIG_PPC_970_NAP)      += idle_power4.o
@@ -69,10 +70,10 @@ extra-$(CONFIG_8xx)         := head_8xx.o
 extra-y                                += vmlinux.lds
 
 obj-y                          += time.o prom.o traps.o setup-common.o \
-                                  udbg.o misc.o io.o \
+                                  udbg.o misc.o io.o dma.o \
                                   misc_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC32)            += entry_32.o setup_32.o
-obj-$(CONFIG_PPC64)            += dma_64.o iommu.o
+obj-$(CONFIG_PPC64)            += dma-iommu.o iommu.o
 obj-$(CONFIG_KGDB)             += kgdb.o
 obj-$(CONFIG_PPC_MULTIPLATFORM)        += prom_init.o
 obj-$(CONFIG_MODULES)          += ppc_ksyms.o
index 92768d3006f7c0800c263bd2d121537fba2a4409..75c5dd0138fd327a96d22d0fe46b9bac899cb610 100644 (file)
@@ -122,6 +122,8 @@ int main(void)
        DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
        DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
        DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
+       DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
+       DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
        DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
        DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
        DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
@@ -350,14 +352,15 @@ int main(void)
 #endif
 
        DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
+       DEFINE(PTE_SIZE, sizeof(pte_t));
 
 #ifdef CONFIG_KVM
        DEFINE(TLBE_BYTES, sizeof(struct tlbe));
 
        DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
        DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
-       DEFINE(VCPU_HOST_TLB, offsetof(struct kvm_vcpu, arch.host_tlb));
        DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb));
+       DEFINE(VCPU_SHADOW_MOD, offsetof(struct kvm_vcpu, arch.shadow_tlb_mod));
        DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
        DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
        DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
@@ -369,7 +372,7 @@ int main(void)
        DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5));
        DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6));
        DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7));
-       DEFINE(VCPU_PID, offsetof(struct kvm_vcpu, arch.pid));
+       DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid));
 
        DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
        DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
index d8f0329b13444b73be463ea06c71169a193d180f..26e58630ed7bf3d2f618abae3f6a74d7f4350e4b 100644 (file)
@@ -442,28 +442,26 @@ void btext_drawtext(const char *c, unsigned int len)
 
 void btext_drawhex(unsigned long v)
 {
-       char *hex_table = "0123456789abcdef";
-
        if (!boot_text_mapped)
                return;
 #ifdef CONFIG_PPC64
-       btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]);
+       btext_drawchar(hex_asc_hi(v >> 56));
+       btext_drawchar(hex_asc_lo(v >> 56));
+       btext_drawchar(hex_asc_hi(v >> 48));
+       btext_drawchar(hex_asc_lo(v >> 48));
+       btext_drawchar(hex_asc_hi(v >> 40));
+       btext_drawchar(hex_asc_lo(v >> 40));
+       btext_drawchar(hex_asc_hi(v >> 32));
+       btext_drawchar(hex_asc_lo(v >> 32));
 #endif
-       btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >>  8) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >>  4) & 0x0000000FUL]);
-       btext_drawchar(hex_table[(v >>  0) & 0x0000000FUL]);
+       btext_drawchar(hex_asc_hi(v >> 24));
+       btext_drawchar(hex_asc_lo(v >> 24));
+       btext_drawchar(hex_asc_hi(v >> 16));
+       btext_drawchar(hex_asc_lo(v >> 16));
+       btext_drawchar(hex_asc_hi(v >> 8));
+       btext_drawchar(hex_asc_lo(v >> 8));
+       btext_drawchar(hex_asc_hi(v));
+       btext_drawchar(hex_asc_lo(v));
        btext_drawchar(' ');
 }
 
index bf118c3857520a81eb978b016512607f49c8b611..27f2507279d830571fcecd0aa4e13c8a41d81062 100644 (file)
@@ -110,7 +110,7 @@ load_hids:
        isync
 
        /* Save away cpu state */
-       LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+       LOAD_REG_ADDR(r5,cpu_state_storage)
 
        /* Save HID0,1,4 and 5 */
        mfspr   r3,SPRN_HID0
@@ -134,7 +134,7 @@ _GLOBAL(__restore_cpu_ppc970)
        rldicl. r0,r0,4,63
        beqlr
 
-       LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+       LOAD_REG_ADDR(r5,cpu_state_storage)
        /* Before accessing memory, we make sure rm_ci is clear */
        li      r0,0
        mfspr   r3,SPRN_HID4
index 25c273c761d19855f2d8861720c24f7cb095bb2f..e70d0483fb4e55494c87f4d97d33b120336deed0 100644 (file)
@@ -610,6 +610,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750cx,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -623,6 +624,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750cx,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -636,6 +638,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750cx,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -649,6 +652,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -662,6 +666,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -675,6 +680,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -688,6 +694,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -701,6 +708,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750fx,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -714,6 +722,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750fx,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -727,6 +736,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_IBM,
                .cpu_setup              = __setup_cpu_750,
                .machine_check          = machine_check_generic,
                .platform               = "ppc750",
@@ -741,6 +751,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_7400,
                .machine_check          = machine_check_generic,
                .platform               = "ppc7400",
@@ -755,6 +766,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_7400,
                .machine_check          = machine_check_generic,
                .platform               = "ppc7400",
@@ -769,6 +781,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 4,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_7410,
                .machine_check          = machine_check_generic,
                .platform               = "ppc7400",
@@ -783,6 +796,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -799,6 +813,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -815,6 +830,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -831,6 +847,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -847,6 +864,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -863,6 +881,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -879,6 +898,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -895,6 +915,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -910,6 +931,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -926,6 +948,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
@@ -942,6 +965,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
                .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_G4,
                .cpu_setup              = __setup_cpu_745x,
                .oprofile_cpu_type      = "ppc/7450",
                .oprofile_type          = PPC_OPROFILE_G4,
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
new file mode 100644 (file)
index 0000000..49248f8
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
+ *
+ * Provide default implementations of the DMA mapping callbacks for
+ * busses using the iommu infrastructure
+ */
+
+#include <asm/iommu.h>
+
+/*
+ * Generic iommu implementation
+ */
+
+/* Allocates a contiguous real buffer and creates mappings over it.
+ * Returns the virtual address of the buffer and sets dma_handle
+ * to the dma address (mapping) of the first page.
+ */
+static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
+                                     dma_addr_t *dma_handle, gfp_t flag)
+{
+       return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
+                                   dma_handle, device_to_mask(dev), flag,
+                                   dev_to_node(dev));
+}
+
+static void dma_iommu_free_coherent(struct device *dev, size_t size,
+                                   void *vaddr, dma_addr_t dma_handle)
+{
+       iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
+}
+
+/* Creates TCEs for a user provided buffer.  The user buffer must be
+ * contiguous real kernel storage (not vmalloc).  The address of the buffer
+ * passed here is the kernel (virtual) address of the buffer.  The buffer
+ * need not be page aligned, the dma_addr_t returned will point to the same
+ * byte within the page as vaddr.
+ */
+static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
+                                      size_t size,
+                                      enum dma_data_direction direction,
+                                      struct dma_attrs *attrs)
+{
+       return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
+                               device_to_mask(dev), direction, attrs);
+}
+
+
+static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
+                                  size_t size,
+                                  enum dma_data_direction direction,
+                                  struct dma_attrs *attrs)
+{
+       iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction,
+                          attrs);
+}
+
+
+static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+                           int nelems, enum dma_data_direction direction,
+                           struct dma_attrs *attrs)
+{
+       return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
+                           device_to_mask(dev), direction, attrs);
+}
+
+static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
+               int nelems, enum dma_data_direction direction,
+               struct dma_attrs *attrs)
+{
+       iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction,
+                      attrs);
+}
+
+/* We support DMA to/from any memory page via the iommu */
+static int dma_iommu_dma_supported(struct device *dev, u64 mask)
+{
+       struct iommu_table *tbl = dev->archdata.dma_data;
+
+       if (!tbl || tbl->it_offset > mask) {
+               printk(KERN_INFO
+                      "Warning: IOMMU offset too big for device mask\n");
+               if (tbl)
+                       printk(KERN_INFO
+                              "mask: 0x%08lx, table offset: 0x%08lx\n",
+                               mask, tbl->it_offset);
+               else
+                       printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+                               mask);
+               return 0;
+       } else
+               return 1;
+}
+
+struct dma_mapping_ops dma_iommu_ops = {
+       .alloc_coherent = dma_iommu_alloc_coherent,
+       .free_coherent  = dma_iommu_free_coherent,
+       .map_single     = dma_iommu_map_single,
+       .unmap_single   = dma_iommu_unmap_single,
+       .map_sg         = dma_iommu_map_sg,
+       .unmap_sg       = dma_iommu_unmap_sg,
+       .dma_supported  = dma_iommu_dma_supported,
+};
+EXPORT_SYMBOL(dma_iommu_ops);
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
new file mode 100644 (file)
index 0000000..1562daf
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
+ *
+ * Provide default implementations of the DMA mapping callbacks for
+ * directly mapped busses.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/bug.h>
+#include <asm/abs_addr.h>
+
+/*
+ * Generic direct DMA implementation
+ *
+ * This implementation supports a per-device offset that can be applied if
+ * the address at which memory is visible to devices is not 0. Platform code
+ * can set archdata.dma_data to an unsigned long holding the offset. By
+ * default the offset is PCI_DRAM_OFFSET.
+ */
+
+static unsigned long get_dma_direct_offset(struct device *dev)
+{
+       if (dev)
+               return (unsigned long)dev->archdata.dma_data;
+
+       return PCI_DRAM_OFFSET;
+}
+
+void *dma_direct_alloc_coherent(struct device *dev, size_t size,
+                               dma_addr_t *dma_handle, gfp_t flag)
+{
+       void *ret;
+#ifdef CONFIG_NOT_COHERENT_CACHE
+       ret = __dma_alloc_coherent(size, dma_handle, flag);
+       if (ret == NULL)
+               return NULL;
+       *dma_handle += get_dma_direct_offset(dev);
+       return ret;
+#else
+       struct page *page;
+       int node = dev_to_node(dev);
+
+       /* ignore region specifiers */
+       flag  &= ~(__GFP_HIGHMEM);
+
+       page = alloc_pages_node(node, flag, get_order(size));
+       if (page == NULL)
+               return NULL;
+       ret = page_address(page);
+       memset(ret, 0, size);
+       *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev);
+
+       return ret;
+#endif
+}
+
+void dma_direct_free_coherent(struct device *dev, size_t size,
+                             void *vaddr, dma_addr_t dma_handle)
+{
+#ifdef CONFIG_NOT_COHERENT_CACHE
+       __dma_free_coherent(size, vaddr);
+#else
+       free_pages((unsigned long)vaddr, get_order(size));
+#endif
+}
+
+static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
+                            int nents, enum dma_data_direction direction,
+                            struct dma_attrs *attrs)
+{
+       struct scatterlist *sg;
+       int i;
+
+       for_each_sg(sgl, sg, nents, i) {
+               sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
+               sg->dma_length = sg->length;
+       }
+
+       return nents;
+}
+
+static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
+                               int nents, enum dma_data_direction direction,
+                               struct dma_attrs *attrs)
+{
+}
+
+static int dma_direct_dma_supported(struct device *dev, u64 mask)
+{
+#ifdef CONFIG_PPC64
+       /* Could be improved to check for memory though it better be
+        * done via some global so platforms can set the limit in case
+        * they have limited DMA windows
+        */
+       return mask >= DMA_32BIT_MASK;
+#else
+       return 1;
+#endif
+}
+
+static inline dma_addr_t dma_direct_map_page(struct device *dev,
+                                            struct page *page,
+                                            unsigned long offset,
+                                            size_t size,
+                                            enum dma_data_direction dir,
+                                            struct dma_attrs *attrs)
+{
+       BUG_ON(dir == DMA_NONE);
+       __dma_sync_page(page, offset, size, dir);
+       return page_to_phys(page) + offset + get_dma_direct_offset(dev);
+}
+
+static inline void dma_direct_unmap_page(struct device *dev,
+                                        dma_addr_t dma_address,
+                                        size_t size,
+                                        enum dma_data_direction direction,
+                                        struct dma_attrs *attrs)
+{
+}
+
+struct dma_mapping_ops dma_direct_ops = {
+       .alloc_coherent = dma_direct_alloc_coherent,
+       .free_coherent  = dma_direct_free_coherent,
+       .map_sg         = dma_direct_map_sg,
+       .unmap_sg       = dma_direct_unmap_sg,
+       .dma_supported  = dma_direct_dma_supported,
+       .map_page       = dma_direct_map_page,
+       .unmap_page     = dma_direct_unmap_page,
+};
+EXPORT_SYMBOL(dma_direct_ops);
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
deleted file mode 100644 (file)
index ae5708e..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
- *
- * Provide default implementations of the DMA mapping callbacks for
- * directly mapped busses and busses using the iommu infrastructure
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <asm/bug.h>
-#include <asm/iommu.h>
-#include <asm/abs_addr.h>
-
-/*
- * Generic iommu implementation
- */
-
-/* Allocates a contiguous real buffer and creates mappings over it.
- * Returns the virtual address of the buffer and sets dma_handle
- * to the dma address (mapping) of the first page.
- */
-static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
-                                     dma_addr_t *dma_handle, gfp_t flag)
-{
-       return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
-                                   dma_handle, device_to_mask(dev), flag,
-                                   dev->archdata.numa_node);
-}
-
-static void dma_iommu_free_coherent(struct device *dev, size_t size,
-                                   void *vaddr, dma_addr_t dma_handle)
-{
-       iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
-}
-
-/* Creates TCEs for a user provided buffer.  The user buffer must be
- * contiguous real kernel storage (not vmalloc).  The address of the buffer
- * passed here is the kernel (virtual) address of the buffer.  The buffer
- * need not be page aligned, the dma_addr_t returned will point to the same
- * byte within the page as vaddr.
- */
-static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
-                                      size_t size,
-                                      enum dma_data_direction direction,
-                                      struct dma_attrs *attrs)
-{
-       return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
-                               device_to_mask(dev), direction, attrs);
-}
-
-
-static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
-                                  size_t size,
-                                  enum dma_data_direction direction,
-                                  struct dma_attrs *attrs)
-{
-       iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction,
-                          attrs);
-}
-
-
-static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
-                           int nelems, enum dma_data_direction direction,
-                           struct dma_attrs *attrs)
-{
-       return iommu_map_sg(dev, dev->archdata.dma_data, sglist, nelems,
-                           device_to_mask(dev), direction, attrs);
-}
-
-static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
-               int nelems, enum dma_data_direction direction,
-               struct dma_attrs *attrs)
-{
-       iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction,
-                      attrs);
-}
-
-/* We support DMA to/from any memory page via the iommu */
-static int dma_iommu_dma_supported(struct device *dev, u64 mask)
-{
-       struct iommu_table *tbl = dev->archdata.dma_data;
-
-       if (!tbl || tbl->it_offset > mask) {
-               printk(KERN_INFO
-                      "Warning: IOMMU offset too big for device mask\n");
-               if (tbl)
-                       printk(KERN_INFO
-                              "mask: 0x%08lx, table offset: 0x%08lx\n",
-                               mask, tbl->it_offset);
-               else
-                       printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
-                               mask);
-               return 0;
-       } else
-               return 1;
-}
-
-struct dma_mapping_ops dma_iommu_ops = {
-       .alloc_coherent = dma_iommu_alloc_coherent,
-       .free_coherent  = dma_iommu_free_coherent,
-       .map_single     = dma_iommu_map_single,
-       .unmap_single   = dma_iommu_unmap_single,
-       .map_sg         = dma_iommu_map_sg,
-       .unmap_sg       = dma_iommu_unmap_sg,
-       .dma_supported  = dma_iommu_dma_supported,
-};
-EXPORT_SYMBOL(dma_iommu_ops);
-
-/*
- * Generic direct DMA implementation
- *
- * This implementation supports a per-device offset that can be applied if
- * the address at which memory is visible to devices is not 0. Platform code
- * can set archdata.dma_data to an unsigned long holding the offset. By
- * default the offset is zero.
- */
-
-static unsigned long get_dma_direct_offset(struct device *dev)
-{
-       return (unsigned long)dev->archdata.dma_data;
-}
-
-static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag)
-{
-       struct page *page;
-       void *ret;
-       int node = dev->archdata.numa_node;
-
-       page = alloc_pages_node(node, flag, get_order(size));
-       if (page == NULL)
-               return NULL;
-       ret = page_address(page);
-       memset(ret, 0, size);
-       *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev);
-
-       return ret;
-}
-
-static void dma_direct_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle)
-{
-       free_pages((unsigned long)vaddr, get_order(size));
-}
-
-static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
-                                       size_t size,
-                                       enum dma_data_direction direction,
-                                       struct dma_attrs *attrs)
-{
-       return virt_to_abs(ptr) + get_dma_direct_offset(dev);
-}
-
-static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
-                                   size_t size,
-                                   enum dma_data_direction direction,
-                                   struct dma_attrs *attrs)
-{
-}
-
-static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
-                            int nents, enum dma_data_direction direction,
-                            struct dma_attrs *attrs)
-{
-       struct scatterlist *sg;
-       int i;
-
-       for_each_sg(sgl, sg, nents, i) {
-               sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev);
-               sg->dma_length = sg->length;
-       }
-
-       return nents;
-}
-
-static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
-                               int nents, enum dma_data_direction direction,
-                               struct dma_attrs *attrs)
-{
-}
-
-static int dma_direct_dma_supported(struct device *dev, u64 mask)
-{
-       /* Could be improved to check for memory though it better be
-        * done via some global so platforms can set the limit in case
-        * they have limited DMA windows
-        */
-       return mask >= DMA_32BIT_MASK;
-}
-
-struct dma_mapping_ops dma_direct_ops = {
-       .alloc_coherent = dma_direct_alloc_coherent,
-       .free_coherent  = dma_direct_free_coherent,
-       .map_single     = dma_direct_map_single,
-       .unmap_single   = dma_direct_unmap_single,
-       .map_sg         = dma_direct_map_sg,
-       .unmap_sg       = dma_direct_unmap_sg,
-       .dma_supported  = dma_direct_dma_supported,
-};
-EXPORT_SYMBOL(dma_direct_ops);
index 2d802e97097c55056757fab95a86aa400f352d99..fd8b4bae9b04e2926277f7dc9945358f8eeed7a8 100644 (file)
@@ -512,31 +512,12 @@ _GLOBAL(ret_from_except_lite)
 #endif
 
 restore:
-       ld      r5,SOFTE(r1)
-#ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
-       cmpdi   0,r5,0
-       beq     4f
-       /* Check for pending interrupts (iSeries) */
-       ld      r3,PACALPPACAPTR(r13)
-       ld      r3,LPPACAANYINT(r3)
-       cmpdi   r3,0
-       beq+    4f                      /* skip do_IRQ if no interrupts */
-
-       li      r3,0
-       stb     r3,PACASOFTIRQEN(r13)   /* ensure we are soft-disabled */
-#ifdef CONFIG_TRACE_IRQFLAGS
-       bl      .trace_hardirqs_off
-       mfmsr   r10
-#endif
-       ori     r10,r10,MSR_EE
-       mtmsrd  r10                     /* hard-enable again */
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .do_IRQ
-       b       .ret_from_except_lite           /* loop back and handle more */
-4:
-END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
-#endif
+       ld      r5,SOFTE(r1)
+FW_FTR_SECTION_ELSE
+       b       iseries_check_pending_irqs
+ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
+2:
        TRACE_AND_RESTORE_IRQ(r5);
 
        /* extract EE bit and use it to restore paca->hard_enabled */
@@ -592,6 +573,30 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
        rfid
        b       .       /* prevent speculative execution */
 
+iseries_check_pending_irqs:
+#ifdef CONFIG_PPC_ISERIES
+       ld      r5,SOFTE(r1)
+       cmpdi   0,r5,0
+       beq     2b
+       /* Check for pending interrupts (iSeries) */
+       ld      r3,PACALPPACAPTR(r13)
+       ld      r3,LPPACAANYINT(r3)
+       cmpdi   r3,0
+       beq+    2b                      /* skip do_IRQ if no interrupts */
+
+       li      r3,0
+       stb     r3,PACASOFTIRQEN(r13)   /* ensure we are soft-disabled */
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      .trace_hardirqs_off
+       mfmsr   r10
+#endif
+       ori     r10,r10,MSR_EE
+       mtmsrd  r10                     /* hard-enable again */
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .do_IRQ
+       b       .ret_from_except_lite           /* loop back and handle more */
+#endif
+
 do_work:
 #ifdef CONFIG_PREEMPT
        andi.   r0,r3,MSR_PR    /* Returning to user mode? */
@@ -685,10 +690,6 @@ _GLOBAL(enter_rtas)
        std     r7,_DAR(r1)
        mfdsisr r8
        std     r8,_DSISR(r1)
-       mfsrr0  r9
-       std     r9,_SRR0(r1)
-       mfsrr1  r10
-       std     r10,_SRR1(r1)
 
        /* Temporary workaround to clear CR until RTAS can be modified to
         * ignore all bits.
@@ -749,6 +750,10 @@ _STATIC(rtas_return_loc)
        mfspr   r4,SPRN_SPRG3           /* Get PACA */
        clrldi  r4,r4,2                 /* convert to realmode address */
 
+       bcl     20,31,$+4
+0:     mflr    r3
+       ld      r3,(1f-0b)(r3)          /* get &.rtas_restore_regs */
+
        mfmsr   r6
        li      r0,MSR_RI
        andc    r6,r6,r0
@@ -756,7 +761,6 @@ _STATIC(rtas_return_loc)
        mtmsrd  r6
         
         ld     r1,PACAR1(r4)           /* Restore our SP */
-       LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs)
         ld     r4,PACASAVEDMSR(r4)     /* Restore our MSR */
 
        mtspr   SPRN_SRR0,r3
@@ -764,6 +768,9 @@ _STATIC(rtas_return_loc)
        rfid
        b       .       /* prevent speculative execution */
 
+       .align  3
+1:     .llong  .rtas_restore_regs
+
 _STATIC(rtas_restore_regs)
        /* relocation is on at this point */
        REST_GPR(2, r1)                 /* Restore the TOC */
@@ -783,10 +790,6 @@ _STATIC(rtas_restore_regs)
        mtdar   r7
        ld      r8,_DSISR(r1)
        mtdsisr r8
-       ld      r9,_SRR0(r1)
-       mtsrr0  r9
-       ld      r10,_SRR1(r1)
-       mtsrr1  r10
 
         addi   r1,r1,RTAS_FRAME_SIZE   /* Unstack our frame */
        ld      r0,16(r1)               /* get return address */
index 8bb65751929948fbc35e29fce9fb899058d9b39a..0c326823c6d4caf088663efd2c68804c6696d983 100644 (file)
@@ -110,6 +110,12 @@ __start:
 #ifdef CONFIG_PPC_MULTIPLATFORM
        cmpwi   0,r5,0
        beq     1f
+
+       /* find out where we are now */
+       bcl     20,31,$+4
+0:     mflr    r8                      /* r8 = runtime addr here */
+       addis   r8,r8,(_stext - 0b)@ha
+       addi    r8,r8,(_stext - 0b)@l   /* current runtime base addr */
        bl      prom_init
        trap
 #endif
@@ -369,13 +375,13 @@ i##n:                                                             \
 DataAccess:
        EXCEPTION_PROLOG
        mfspr   r10,SPRN_DSISR
+       stw     r10,_DSISR(r11)
        andis.  r0,r10,0xa470           /* weird error? */
        bne     1f                      /* if not, try to put a PTE */
        mfspr   r4,SPRN_DAR             /* into the hash table */
        rlwinm  r3,r10,32-15,21,21      /* DSISR_STORE -> _PAGE_RW */
        bl      hash_page
-1:     stw     r10,_DSISR(r11)
-       mr      r5,r10
+1:     lwz     r5,_DSISR(r11)          /* get DSISR value */
        mfspr   r4,SPRN_DAR
        EXC_XFER_EE_LITE(0x300, handle_page_fault)
 
index cc8fb474d5204ed3c2cf2c48bd754b1fdf3758c9..84856bee33a54a5bc58d7c99edf67286ddd281e0 100644 (file)
@@ -82,7 +82,11 @@ END_FTR_SECTION(0, 1)
        /* Catch branch to 0 in real mode */
        trap
 
-       /* Secondary processors spin on this value until it goes to 1. */
+       /* Secondary processors spin on this value until it becomes nonzero.
+        * When it does it contains the real address of the descriptor
+        * of the function that the cpu should jump to to continue
+        * initialization.
+        */
        .globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
        .llong  0x0
@@ -109,8 +113,11 @@ __secondary_hold_acknowledge:
  * before the bulk of the kernel has been relocated.  This code
  * is relocated to physical address 0x60 before prom_init is run.
  * All of it must fit below the first exception vector at 0x100.
+ * Use .globl here not _GLOBAL because we want __secondary_hold
+ * to be the actual text address, not a descriptor.
  */
-_GLOBAL(__secondary_hold)
+       .globl  __secondary_hold
+__secondary_hold:
        mfmsr   r24
        ori     r24,r24,MSR_RI
        mtmsrd  r24                     /* RI on */
@@ -121,16 +128,16 @@ _GLOBAL(__secondary_hold)
        /* Tell the master cpu we're here */
        /* Relocation is off & we are located at an address less */
        /* than 0x100, so only need to grab low order offset.    */
-       std     r24,__secondary_hold_acknowledge@l(0)
+       std     r24,__secondary_hold_acknowledge-_stext(0)
        sync
 
        /* All secondary cpus wait here until told to start. */
-100:   ld      r4,__secondary_hold_spinloop@l(0)
-       cmpdi   0,r4,1
-       bne     100b
+100:   ld      r4,__secondary_hold_spinloop-_stext(0)
+       cmpdi   0,r4,0
+       beq     100b
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
-       LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
+       ld      r4,0(r4)                /* deref function descriptor */
        mtctr   r4
        mr      r3,r24
        bctr
@@ -147,6 +154,10 @@ exception_marker:
 /*
  * This is the start of the interrupt handlers for pSeries
  * This code runs with relocation off.
+ * Code from here to __end_interrupts gets copied down to real
+ * address 0x100 when we are running a relocatable kernel.
+ * Therefore any relative branches in this section must only
+ * branch to labels in this section.
  */
        . = 0x100
        .globl __start_interrupts
@@ -200,7 +211,20 @@ data_access_slb_pSeries:
        mfspr   r10,SPRN_SPRG1
        std     r10,PACA_EXSLB+EX_R13(r13)
        mfspr   r12,SPRN_SRR1           /* and SRR1 */
-       b       .slb_miss_realmode      /* Rel. branch works in real mode */
+#ifndef CONFIG_RELOCATABLE
+       b       .slb_miss_realmode
+#else
+       /*
+        * We can't just use a direct branch to .slb_miss_realmode
+        * because the distance from here to there depends on where
+        * the kernel ends up being put.
+        */
+       mfctr   r11
+       ld      r10,PACAKBASE(r13)
+       LOAD_HANDLER(r10, .slb_miss_realmode)
+       mtctr   r10
+       bctr
+#endif
 
        STD_EXCEPTION_PSERIES(0x400, instruction_access)
 
@@ -225,7 +249,15 @@ instruction_access_slb_pSeries:
        mfspr   r10,SPRN_SPRG1
        std     r10,PACA_EXSLB+EX_R13(r13)
        mfspr   r12,SPRN_SRR1           /* and SRR1 */
-       b       .slb_miss_realmode      /* Rel. branch works in real mode */
+#ifndef CONFIG_RELOCATABLE
+       b       .slb_miss_realmode
+#else
+       mfctr   r11
+       ld      r10,PACAKBASE(r13)
+       LOAD_HANDLER(r10, .slb_miss_realmode)
+       mtctr   r10
+       bctr
+#endif
 
        MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
        STD_EXCEPTION_PSERIES(0x600, alignment)
@@ -244,14 +276,12 @@ BEGIN_FTR_SECTION
        beq-    1f
 END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
        mr      r9,r13
-       mfmsr   r10
        mfspr   r13,SPRN_SPRG3
        mfspr   r11,SPRN_SRR0
-       clrrdi  r12,r13,32
-       oris    r12,r12,system_call_common@h
-       ori     r12,r12,system_call_common@l
+       ld      r12,PACAKBASE(r13)
+       ld      r10,PACAKMSR(r13)
+       LOAD_HANDLER(r12, system_call_entry)
        mtspr   SPRN_SRR0,r12
-       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI
        mfspr   r12,SPRN_SRR1
        mtspr   SPRN_SRR1,r10
        rfid
@@ -325,16 +355,32 @@ do_stab_bolted_pSeries:
        mfspr   r12,SPRN_SPRG2
        EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
 
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Vectors for the FWNMI option.  Share common code.
+ */
+       .globl system_reset_fwnmi
+      .align 7
+system_reset_fwnmi:
+       HMT_MEDIUM
+       mtspr   SPRN_SPRG1,r13          /* save r13 */
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+
+       .globl machine_check_fwnmi
+      .align 7
+machine_check_fwnmi:
+       HMT_MEDIUM
+       mtspr   SPRN_SPRG1,r13          /* save r13 */
+       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+#endif /* CONFIG_PPC_PSERIES */
+
+#ifdef __DISABLED__
 /*
- * We have some room here  we use that to put
- * the peries slb miss user trampoline code so it's reasonably
- * away from slb_miss_user_common to avoid problems with rfid
- *
  * This is used for when the SLB miss handler has to go virtual,
  * which doesn't happen for now anymore but will once we re-implement
  * dynamic VSIDs for shared page tables
  */
-#ifdef __DISABLED__
 slb_miss_user_pseries:
        std     r10,PACA_EXGEN+EX_R10(r13)
        std     r11,PACA_EXGEN+EX_R11(r13)
@@ -357,25 +403,17 @@ slb_miss_user_pseries:
        b       .                               /* prevent spec. execution */
 #endif /* __DISABLED__ */
 
-#ifdef CONFIG_PPC_PSERIES
+       .align  7
+       .globl  __end_interrupts
+__end_interrupts:
+
 /*
- * Vectors for the FWNMI option.  Share common code.
+ * Code from here down to __end_handlers is invoked from the
+ * exception prologs above.  Because the prologs assemble the
+ * addresses of these handlers using the LOAD_HANDLER macro,
+ * which uses an addi instruction, these handlers must be in
+ * the first 32k of the kernel image.
  */
-       .globl system_reset_fwnmi
-      .align 7
-system_reset_fwnmi:
-       HMT_MEDIUM
-       mtspr   SPRN_SPRG1,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
-
-       .globl machine_check_fwnmi
-      .align 7
-machine_check_fwnmi:
-       HMT_MEDIUM
-       mtspr   SPRN_SPRG1,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
-
-#endif /* CONFIG_PPC_PSERIES */
 
 /*** Common interrupt handlers ***/
 
@@ -414,6 +452,10 @@ machine_check_common:
        STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
 #endif /* CONFIG_CBE_RAS */
 
+       .align  7
+system_call_entry:
+       b       system_call_common
+
 /*
  * Here we have detected that the kernel stack pointer is bad.
  * R9 contains the saved CR, r13 points to the paca,
@@ -456,65 +498,6 @@ bad_stack:
        bl      .kernel_bad_stack
        b       1b
 
-/*
- * Return from an exception with minimal checks.
- * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
- * If interrupts have been enabled, or anything has been
- * done that might have changed the scheduling status of
- * any task or sent any task a signal, you should use
- * ret_from_except or ret_from_except_lite instead of this.
- */
-fast_exc_return_irq:                   /* restores irq state too */
-       ld      r3,SOFTE(r1)
-       TRACE_AND_RESTORE_IRQ(r3);
-       ld      r12,_MSR(r1)
-       rldicl  r4,r12,49,63            /* get MSR_EE to LSB */
-       stb     r4,PACAHARDIRQEN(r13)   /* restore paca->hard_enabled */
-       b       1f
-
-       .globl  fast_exception_return
-fast_exception_return:
-       ld      r12,_MSR(r1)
-1:     ld      r11,_NIP(r1)
-       andi.   r3,r12,MSR_RI           /* check if RI is set */
-       beq-    unrecov_fer
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-       andi.   r3,r12,MSR_PR
-       beq     2f
-       ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
-#endif
-
-       ld      r3,_CCR(r1)
-       ld      r4,_LINK(r1)
-       ld      r5,_CTR(r1)
-       ld      r6,_XER(r1)
-       mtcr    r3
-       mtlr    r4
-       mtctr   r5
-       mtxer   r6
-       REST_GPR(0, r1)
-       REST_8GPRS(2, r1)
-
-       mfmsr   r10
-       rldicl  r10,r10,48,1            /* clear EE */
-       rldicr  r10,r10,16,61           /* clear RI (LE is 0 already) */
-       mtmsrd  r10,1
-
-       mtspr   SPRN_SRR1,r12
-       mtspr   SPRN_SRR0,r11
-       REST_4GPRS(10, r1)
-       ld      r1,GPR1(r1)
-       rfid
-       b       .       /* prevent speculative execution */
-
-unrecov_fer:
-       bl      .save_nvgprs
-1:     addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .unrecoverable_exception
-       b       1b
-
 /*
  * Here r13 points to the paca, r9 contains the saved CR,
  * SRR0 and SRR1 are saved in r11 and r12,
@@ -616,6 +599,9 @@ unrecov_user_slb:
  */
 _GLOBAL(slb_miss_realmode)
        mflr    r10
+#ifdef CONFIG_RELOCATABLE
+       mtctr   r11
+#endif
 
        stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
        std     r10,PACA_EXSLB+EX_LR(r13)       /* save LR */
@@ -666,11 +652,10 @@ BEGIN_FW_FTR_SECTION
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif /* CONFIG_PPC_ISERIES */
        mfspr   r11,SPRN_SRR0
-       clrrdi  r10,r13,32
+       ld      r10,PACAKBASE(r13)
        LOAD_HANDLER(r10,unrecov_slb)
        mtspr   SPRN_SRR0,r10
-       mfmsr   r10
-       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI
+       ld      r10,PACAKMSR(r13)
        mtspr   SPRN_SRR1,r10
        rfid
        b       .
@@ -766,6 +751,85 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        bl      .altivec_unavailable_exception
        b       .ret_from_except
 
+       .align  7
+       .globl vsx_unavailable_common
+vsx_unavailable_common:
+       EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+       bne     .load_up_vsx
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+       bl      .save_nvgprs
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       ENABLE_INTS
+       bl      .vsx_unavailable_exception
+       b       .ret_from_except
+
+       .align  7
+       .globl  __end_handlers
+__end_handlers:
+
+/*
+ * Return from an exception with minimal checks.
+ * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
+ * If interrupts have been enabled, or anything has been
+ * done that might have changed the scheduling status of
+ * any task or sent any task a signal, you should use
+ * ret_from_except or ret_from_except_lite instead of this.
+ */
+fast_exc_return_irq:                   /* restores irq state too */
+       ld      r3,SOFTE(r1)
+       TRACE_AND_RESTORE_IRQ(r3);
+       ld      r12,_MSR(r1)
+       rldicl  r4,r12,49,63            /* get MSR_EE to LSB */
+       stb     r4,PACAHARDIRQEN(r13)   /* restore paca->hard_enabled */
+       b       1f
+
+       .globl  fast_exception_return
+fast_exception_return:
+       ld      r12,_MSR(r1)
+1:     ld      r11,_NIP(r1)
+       andi.   r3,r12,MSR_RI           /* check if RI is set */
+       beq-    unrecov_fer
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+       andi.   r3,r12,MSR_PR
+       beq     2f
+       ACCOUNT_CPU_USER_EXIT(r3, r4)
+2:
+#endif
+
+       ld      r3,_CCR(r1)
+       ld      r4,_LINK(r1)
+       ld      r5,_CTR(r1)
+       ld      r6,_XER(r1)
+       mtcr    r3
+       mtlr    r4
+       mtctr   r5
+       mtxer   r6
+       REST_GPR(0, r1)
+       REST_8GPRS(2, r1)
+
+       mfmsr   r10
+       rldicl  r10,r10,48,1            /* clear EE */
+       rldicr  r10,r10,16,61           /* clear RI (LE is 0 already) */
+       mtmsrd  r10,1
+
+       mtspr   SPRN_SRR1,r12
+       mtspr   SPRN_SRR0,r11
+       REST_4GPRS(10, r1)
+       ld      r1,GPR1(r1)
+       rfid
+       b       .       /* prevent speculative execution */
+
+unrecov_fer:
+       bl      .save_nvgprs
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .unrecoverable_exception
+       b       1b
+
 #ifdef CONFIG_ALTIVEC
 /*
  * load_up_altivec(unused, unused, tsk)
@@ -840,22 +904,6 @@ _STATIC(load_up_altivec)
        blr
 #endif /* CONFIG_ALTIVEC */
 
-       .align  7
-       .globl vsx_unavailable_common
-vsx_unavailable_common:
-       EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-       bne     .load_up_vsx
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_VSX)
-#endif
-       bl      .save_nvgprs
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       ENABLE_INTS
-       bl      .vsx_unavailable_exception
-       b       .ret_from_except
-
 #ifdef CONFIG_VSX
 /*
  * load_up_vsx(unused, unused, tsk)
@@ -1175,11 +1223,14 @@ _GLOBAL(generic_secondary_smp_init)
        /* turn on 64-bit mode */
        bl      .enable_64b_mode
 
+       /* get the TOC pointer (real address) */
+       bl      .relative_toc
+
        /* Set up a paca value for this processor. Since we have the
         * physical cpu id in r24, we need to search the pacas to find
         * which logical id maps to our physical one.
         */
-       LOAD_REG_IMMEDIATE(r13, paca)   /* Get base vaddr of paca array  */
+       LOAD_REG_ADDR(r13, paca)        /* Get base vaddr of paca array  */
        li      r5,0                    /* logical cpu id                */
 1:     lhz     r6,PACAHWCPUID(r13)     /* Load HW procid from paca      */
        cmpw    r6,r24                  /* Compare to our id             */
@@ -1208,7 +1259,7 @@ _GLOBAL(generic_secondary_smp_init)
        sync                            /* order paca.run and cur_cpu_spec */
 
        /* See if we need to call a cpu state restore handler */
-       LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
+       LOAD_REG_ADDR(r23, cur_cpu_spec)
        ld      r23,0(r23)
        ld      r23,CPU_SPEC_RESTORE(r23)
        cmpdi   0,r23,0
@@ -1224,10 +1275,15 @@ _GLOBAL(generic_secondary_smp_init)
        b       __secondary_start
 #endif
 
+/*
+ * Turn the MMU off.
+ * Assumes we're mapped EA == RA if the MMU is on.
+ */
 _STATIC(__mmu_off)
        mfmsr   r3
        andi.   r0,r3,MSR_IR|MSR_DR
        beqlr
+       mflr    r4
        andc    r3,r3,r0
        mtspr   SPRN_SRR0,r4
        mtspr   SPRN_SRR1,r3
@@ -1248,6 +1304,18 @@ _STATIC(__mmu_off)
  *
  */
 _GLOBAL(__start_initialization_multiplatform)
+       /* Make sure we are running in 64 bits mode */
+       bl      .enable_64b_mode
+
+       /* Get TOC pointer (current runtime address) */
+       bl      .relative_toc
+
+       /* find out where we are now */
+       bcl     20,31,$+4
+0:     mflr    r26                     /* r26 = runtime addr here */
+       addis   r26,r26,(_stext - 0b)@ha
+       addi    r26,r26,(_stext - 0b)@l /* current runtime base addr */
+
        /*
         * Are we booted from a PROM Of-type client-interface ?
         */
@@ -1259,9 +1327,6 @@ _GLOBAL(__start_initialization_multiplatform)
        mr      r31,r3
        mr      r30,r4
 
-       /* Make sure we are running in 64 bits mode */
-       bl      .enable_64b_mode
-
        /* Setup some critical 970 SPRs before switching MMU off */
        mfspr   r0,SPRN_PVR
        srwi    r0,r0,16
@@ -1276,9 +1341,7 @@ _GLOBAL(__start_initialization_multiplatform)
 1:     bl      .__cpu_preinit_ppc970
 2:
 
-       /* Switch off MMU if not already */
-       LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
-       add     r4,r4,r30
+       /* Switch off MMU if not already off */
        bl      .__mmu_off
        b       .__after_prom_start
 
@@ -1293,22 +1356,15 @@ _INIT_STATIC(__boot_from_prom)
        /*
         * Align the stack to 16-byte boundary
         * Depending on the size and layout of the ELF sections in the initial
-        * boot binary, the stack pointer will be unalignet on PowerMac
+        * boot binary, the stack pointer may be unaligned on PowerMac
         */
        rldicr  r1,r1,0,59
 
-       /* Make sure we are running in 64 bits mode */
-       bl      .enable_64b_mode
-
-       /* put a relocation offset into r3 */
-       bl      .reloc_offset
-
-       LOAD_REG_IMMEDIATE(r2,__toc_start)
-       addi    r2,r2,0x4000
-       addi    r2,r2,0x4000
-
-       /* Relocate the TOC from a virt addr to a real addr */
-       add     r2,r2,r3
+#ifdef CONFIG_RELOCATABLE
+       /* Relocate code for where we are now */
+       mr      r3,r26
+       bl      .relocate
+#endif
 
        /* Restore parameters */
        mr      r3,r31
@@ -1318,60 +1374,51 @@ _INIT_STATIC(__boot_from_prom)
        mr      r7,r27
 
        /* Do all of the interaction with OF client interface */
+       mr      r8,r26
        bl      .prom_init
        /* We never return */
        trap
 
 _STATIC(__after_prom_start)
+#ifdef CONFIG_RELOCATABLE
+       /* process relocations for the final address of the kernel */
+       lis     r25,PAGE_OFFSET@highest /* compute virtual base of kernel */
+       sldi    r25,r25,32
+       mr      r3,r25
+       bl      .relocate
+#endif
 
 /*
- * We need to run with __start at physical address PHYSICAL_START.
+ * We need to run with _stext at physical address PHYSICAL_START.
  * This will leave some code in the first 256B of
  * real memory, which are reserved for software use.
- * The remainder of the first page is loaded with the fixed
- * interrupt vectors.  The next two pages are filled with
- * unknown exception placeholders.
  *
  * Note: This process overwrites the OF exception vectors.
- *     r26 == relocation offset
- *     r27 == KERNELBASE
  */
-       bl      .reloc_offset
-       mr      r26,r3
-       LOAD_REG_IMMEDIATE(r27, KERNELBASE)
-
-       LOAD_REG_IMMEDIATE(r3, PHYSICAL_START)  /* target addr */
-
-       // XXX FIXME: Use phys returned by OF (r30)
-       add     r4,r27,r26              /* source addr                   */
-                                       /* current address of _start     */
-                                       /*   i.e. where we are running   */
-                                       /*      the source addr          */
-
-       cmpdi   r4,0                    /* In some cases the loader may  */
-       bne     1f
-       b       .start_here_multiplatform /* have already put us at zero */
-                                       /* so we can skip the copy.      */
-1:     LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
-       sub     r5,r5,r27
-
+       li      r3,0                    /* target addr */
+       mr.     r4,r26                  /* In some cases the loader may  */
+       beq     9f                      /* have already put us at zero */
+       lis     r5,(copy_to_here - _stext)@ha
+       addi    r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
        li      r6,0x100                /* Start offset, the first 0x100 */
                                        /* bytes were copied earlier.    */
 
        bl      .copy_and_flush         /* copy the first n bytes        */
                                        /* this includes the code being  */
                                        /* executed here.                */
-
-       LOAD_REG_IMMEDIATE(r0, 4f)      /* Jump to the copy of this code */
-       mtctr   r0                      /* that we just made/relocated   */
+       addis   r8,r3,(4f - _stext)@ha  /* Jump to the copy of this code */
+       addi    r8,r8,(4f - _stext)@l   /* that we just made */
+       mtctr   r8
        bctr
 
-4:     LOAD_REG_IMMEDIATE(r5,klimit)
-       add     r5,r5,r26
-       ld      r5,0(r5)                /* get the value of klimit */
-       sub     r5,r5,r27
+4:     /* Now copy the rest of the kernel up to _end */
+       addis   r5,r26,(p_end - _stext)@ha
+       ld      r5,(p_end - _stext)@l(r5)       /* get _end */
        bl      .copy_and_flush         /* copy the rest */
-       b       .start_here_multiplatform
+
+9:     b       .start_here_multiplatform
+
+p_end: .llong  _end - _stext
 
 /*
  * Copy routine used to copy the kernel to start at physical address 0
@@ -1436,6 +1483,9 @@ _GLOBAL(pmac_secondary_start)
        /* turn on 64-bit mode */
        bl      .enable_64b_mode
 
+       /* get TOC pointer (real address) */
+       bl      .relative_toc
+
        /* Copy some CPU settings from CPU 0 */
        bl      .__restore_cpu_ppc970
 
@@ -1445,10 +1495,10 @@ _GLOBAL(pmac_secondary_start)
        mtmsrd  r3                      /* RI on */
 
        /* Set up a paca value for this processor. */
-       LOAD_REG_IMMEDIATE(r4, paca)    /* Get base vaddr of paca array */
-       mulli   r13,r24,PACA_SIZE        /* Calculate vaddr of right paca */
+       LOAD_REG_ADDR(r4,paca)          /* Get base vaddr of paca array */
+       mulli   r13,r24,PACA_SIZE       /* Calculate vaddr of right paca */
        add     r13,r13,r4              /* for this processor.          */
-       mtspr   SPRN_SPRG3,r13           /* Save vaddr of paca in SPRG3 */
+       mtspr   SPRN_SPRG3,r13          /* Save vaddr of paca in SPRG3  */
 
        /* Create a temp kernel stack for use before relocation is on.  */
        ld      r1,PACAEMERGSP(r13)
@@ -1476,9 +1526,6 @@ __secondary_start:
        /* Set thread priority to MEDIUM */
        HMT_MEDIUM
 
-       /* Load TOC */
-       ld      r2,PACATOC(r13)
-
        /* Do early setup for that CPU (stab, slb, hash table pointer) */
        bl      .early_setup_secondary
 
@@ -1515,9 +1562,11 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
 /* 
  * Running with relocation on at this point.  All we want to do is
- * zero the stack back-chain pointer before going into C code.
+ * zero the stack back-chain pointer and get the TOC virtual address
+ * before going into C code.
  */
 _GLOBAL(start_secondary_prolog)
+       ld      r2,PACATOC(r13)
        li      r3,0
        std     r3,0(r1)                /* Zero the stack frame pointer */
        bl      .start_secondary
@@ -1529,34 +1578,46 @@ _GLOBAL(start_secondary_prolog)
  */
 _GLOBAL(enable_64b_mode)
        mfmsr   r11                     /* grab the current MSR */
-       li      r12,1
-       rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
-       or      r11,r11,r12
-       li      r12,1
-       rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+       li      r12,(MSR_SF | MSR_ISF)@highest
+       sldi    r12,r12,48
        or      r11,r11,r12
        mtmsrd  r11
        isync
        blr
 
+/*
+ * This puts the TOC pointer into r2, offset by 0x8000 (as expected
+ * by the toolchain).  It computes the correct value for wherever we
+ * are running at the moment, using position-independent code.
+ */
+_GLOBAL(relative_toc)
+       mflr    r0
+       bcl     20,31,$+4
+0:     mflr    r9
+       ld      r2,(p_toc - 0b)(r9)
+       add     r2,r2,r9
+       mtlr    r0
+       blr
+
+p_toc: .llong  __toc_start + 0x8000 - 0b
+
 /*
  * This is where the main kernel code starts.
  */
 _INIT_STATIC(start_here_multiplatform)
-       /* get a new offset, now that the kernel has moved. */
-       bl      .reloc_offset
-       mr      r26,r3
+       /* set up the TOC (real address) */
+       bl      .relative_toc
 
        /* Clear out the BSS. It may have been done in prom_init,
         * already but that's irrelevant since prom_init will soon
         * be detached from the kernel completely. Besides, we need
         * to clear it now for kexec-style entry.
         */
-       LOAD_REG_IMMEDIATE(r11,__bss_stop)
-       LOAD_REG_IMMEDIATE(r8,__bss_start)
+       LOAD_REG_ADDR(r11,__bss_stop)
+       LOAD_REG_ADDR(r8,__bss_start)
        sub     r11,r11,r8              /* bss size                     */
        addi    r11,r11,7               /* round up to an even double word */
-       rldicl. r11,r11,61,3            /* shift right by 3             */
+       srdi.   r11,r11,3               /* shift right by 3             */
        beq     4f
        addi    r8,r8,-8
        li      r0,0
@@ -1569,35 +1630,35 @@ _INIT_STATIC(start_here_multiplatform)
        ori     r6,r6,MSR_RI
        mtmsrd  r6                      /* RI on */
 
-       /* The following gets the stack and TOC set up with the regs */
+#ifdef CONFIG_RELOCATABLE
+       /* Save the physical address we're running at in kernstart_addr */
+       LOAD_REG_ADDR(r4, kernstart_addr)
+       clrldi  r0,r25,2
+       std     r0,0(r4)
+#endif
+
+       /* The following gets the stack set up with the regs */
        /* pointing to the real addr of the kernel stack.  This is   */
        /* all done to support the C function call below which sets  */
        /* up the htab.  This is done because we have relocated the  */
        /* kernel but are still running in real mode. */
 
-       LOAD_REG_IMMEDIATE(r3,init_thread_union)
-       add     r3,r3,r26
+       LOAD_REG_ADDR(r3,init_thread_union)
 
-       /* set up a stack pointer (physical address) */
+       /* set up a stack pointer */
        addi    r1,r3,THREAD_SIZE
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
 
-       /* set up the TOC (physical address) */
-       LOAD_REG_IMMEDIATE(r2,__toc_start)
-       addi    r2,r2,0x4000
-       addi    r2,r2,0x4000
-       add     r2,r2,r26
-
        /* Do very early kernel initializations, including initial hash table,
         * stab and slb setup before we turn on relocation.     */
 
        /* Restore parameters passed from prom_init/kexec */
        mr      r3,r31
-       bl      .early_setup
+       bl      .early_setup            /* also sets r13 and SPRG3 */
 
-       LOAD_REG_IMMEDIATE(r3, .start_here_common)
-       LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
+       LOAD_REG_ADDR(r3, .start_here_common)
+       ld      r4,PACAKMSR(r13)
        mtspr   SPRN_SRR0,r3
        mtspr   SPRN_SRR1,r4
        rfid
@@ -1606,20 +1667,10 @@ _INIT_STATIC(start_here_multiplatform)
        /* This is where all platforms converge execution */
 _INIT_GLOBAL(start_here_common)
        /* relocation is on at this point */
+       std     r1,PACAKSAVE(r13)
 
-       /* The following code sets up the SP and TOC now that we are */
-       /* running with translation enabled. */
-
-       LOAD_REG_IMMEDIATE(r3,init_thread_union)
-
-       /* set up the stack */
-       addi    r1,r3,THREAD_SIZE
-       li      r0,0
-       stdu    r0,-STACK_FRAME_OVERHEAD(r1)
-
-       /* Load the TOC */
+       /* Load the TOC (virtual address) */
        ld      r2,PACATOC(r13)
-       std     r1,PACAKSAVE(r13)
 
        bl      .setup_system
 
index 3cb52fa0eda319a7ff52c496e89802b162a5c56f..590304c24dad37ea5d49f06c6176eb9ae1aab2ac 100644 (file)
@@ -422,7 +422,6 @@ skpinv:     addi    r6,r6,1                         /* Increment */
  *   r12 is pointer to the pte
  */
 #ifdef CONFIG_PTE_64BIT
-#define PTE_FLAGS_OFFSET       4
 #define FIND_PTE       \
        rlwinm  r12, r10, 13, 19, 29;   /* Compute pgdir/pmd offset */  \
        lwzx    r11, r12, r11;          /* Get pgd/pmd entry */         \
@@ -431,7 +430,6 @@ skpinv:     addi    r6,r6,1                         /* Increment */
        rlwimi  r12, r10, 23, 20, 28;   /* Compute pte address */       \
        lwz     r11, 4(r12);            /* Get pte entry */
 #else
-#define PTE_FLAGS_OFFSET       0
 #define FIND_PTE       \
        rlwimi  r11, r10, 12, 20, 29;   /* Create L1 (pgdir/pmd) address */     \
        lwz     r11, 0(r11);            /* Get L1 entry */                      \
@@ -579,13 +577,19 @@ interrupt_base:
 
        FIND_PTE
        andc.   r13,r13,r11             /* Check permission */
-       bne     2f                      /* Bail if permission mismach */
 
 #ifdef CONFIG_PTE_64BIT
-       lwz     r13, 0(r12)
+#ifdef CONFIG_SMP
+       subf    r10,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r10             /* Get upper pte bits */
+#else
+       lwz     r13,0(r12)              /* Get upper pte bits */
+#endif
 #endif
 
-        /* Jump to common tlb load */
+       bne     2f                      /* Bail if permission/valid mismach */
+
+       /* Jump to common tlb load */
        b       finish_tlb_load
 2:
        /* The bailout.  Restore registers to pre-exception conditions
@@ -640,12 +644,18 @@ interrupt_base:
 
        FIND_PTE
        andc.   r13,r13,r11             /* Check permission */
-       bne     2f                      /* Bail if permission mismach */
 
 #ifdef CONFIG_PTE_64BIT
-       lwz     r13, 0(r12)
+#ifdef CONFIG_SMP
+       subf    r10,r11,r12             /* create false data dep */
+       lwzx    r13,r11,r10             /* Get upper pte bits */
+#else
+       lwz     r13,0(r12)              /* Get upper pte bits */
+#endif
 #endif
 
+       bne     2f                      /* Bail if permission mismach */
+
        /* Jump to common TLB load point */
        b       finish_tlb_load
 
@@ -702,7 +712,7 @@ interrupt_base:
 /*
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
- *     r10 - EA of fault
+ *     r10 - available to use
  *     r11 - TLB (info from Linux PTE)
  *     r12 - available to use
  *     r13 - upper bits of PTE (if PTE_64BIT) or available to use
index 550a19399bfaac81bceabfbeb60f4a29e0e0752f..ea1ba89f9c9001ccff8b2d5256d09fe17dafd4c7 100644 (file)
@@ -51,17 +51,6 @@ static int protect4gb = 1;
 
 static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int);
 
-static inline unsigned long iommu_num_pages(unsigned long vaddr,
-                                           unsigned long slen)
-{
-       unsigned long npages;
-
-       npages = IOMMU_PAGE_ALIGN(vaddr + slen) - (vaddr & IOMMU_PAGE_MASK);
-       npages >>= IOMMU_PAGE_SHIFT;
-
-       return npages;
-}
-
 static int __init setup_protect4gb(char *str)
 {
        if (strcmp(str, "on") == 0)
@@ -325,7 +314,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                }
                /* Allocate iommu entries for that segment */
                vaddr = (unsigned long) sg_virt(s);
-               npages = iommu_num_pages(vaddr, slen);
+               npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE);
                align = 0;
                if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
                    (vaddr & ~PAGE_MASK) == 0)
@@ -418,7 +407,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                        unsigned long vaddr, npages;
 
                        vaddr = s->dma_address & IOMMU_PAGE_MASK;
-                       npages = iommu_num_pages(s->dma_address, s->dma_length);
+                       npages = iommu_num_pages(s->dma_address, s->dma_length,
+                                                IOMMU_PAGE_SIZE);
                        __iommu_free(tbl, vaddr, npages);
                        s->dma_address = DMA_ERROR_CODE;
                        s->dma_length = 0;
@@ -452,7 +442,8 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 
                if (sg->dma_length == 0)
                        break;
-               npages = iommu_num_pages(dma_handle, sg->dma_length);
+               npages = iommu_num_pages(dma_handle, sg->dma_length,
+                                        IOMMU_PAGE_SIZE);
                __iommu_free(tbl, dma_handle, npages);
                sg = sg_next(sg);
        }
@@ -584,7 +575,7 @@ dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
        BUG_ON(direction == DMA_NONE);
 
        uaddr = (unsigned long)vaddr;
-       npages = iommu_num_pages(uaddr, size);
+       npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE);
 
        if (tbl) {
                align = 0;
@@ -617,7 +608,7 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
        BUG_ON(direction == DMA_NONE);
 
        if (tbl) {
-               npages = iommu_num_pages(dma_handle, size);
+               npages = iommu_num_pages(dma_handle, size, IOMMU_PAGE_SIZE);
                iommu_free(tbl, dma_handle, npages);
        }
 }
index d972decf0324d4b92e748f4a271e4ad3b4ed4475..ac222d0ab12e86406bcbc6247adb3b8150ed49ee 100644 (file)
@@ -439,8 +439,8 @@ void do_softirq(void)
 
 static LIST_HEAD(irq_hosts);
 static DEFINE_SPINLOCK(irq_big_lock);
-static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
-static unsigned int irq_radix_writer;
+static unsigned int revmap_trees_allocated;
+static DEFINE_MUTEX(revmap_trees_mutex);
 struct irq_map_entry irq_map[NR_IRQS];
 static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_host *irq_default_host;
@@ -583,57 +583,6 @@ void irq_set_virq_count(unsigned int count)
                irq_virq_count = count;
 }
 
-/* radix tree not lockless safe ! we use a brlock-type mecanism
- * for now, until we can use a lockless radix tree
- */
-static void irq_radix_wrlock(unsigned long *flags)
-{
-       unsigned int cpu, ok;
-
-       spin_lock_irqsave(&irq_big_lock, *flags);
-       irq_radix_writer = 1;
-       smp_mb();
-       do {
-               barrier();
-               ok = 1;
-               for_each_possible_cpu(cpu) {
-                       if (per_cpu(irq_radix_reader, cpu)) {
-                               ok = 0;
-                               break;
-                       }
-               }
-               if (!ok)
-                       cpu_relax();
-       } while(!ok);
-}
-
-static void irq_radix_wrunlock(unsigned long flags)
-{
-       smp_wmb();
-       irq_radix_writer = 0;
-       spin_unlock_irqrestore(&irq_big_lock, flags);
-}
-
-static void irq_radix_rdlock(unsigned long *flags)
-{
-       local_irq_save(*flags);
-       __get_cpu_var(irq_radix_reader) = 1;
-       smp_mb();
-       if (likely(irq_radix_writer == 0))
-               return;
-       __get_cpu_var(irq_radix_reader) = 0;
-       smp_wmb();
-       spin_lock(&irq_big_lock);
-       __get_cpu_var(irq_radix_reader) = 1;
-       spin_unlock(&irq_big_lock);
-}
-
-static void irq_radix_rdunlock(unsigned long flags)
-{
-       __get_cpu_var(irq_radix_reader) = 0;
-       local_irq_restore(flags);
-}
-
 static int irq_setup_virq(struct irq_host *host, unsigned int virq,
                            irq_hw_number_t hwirq)
 {
@@ -788,7 +737,6 @@ void irq_dispose_mapping(unsigned int virq)
 {
        struct irq_host *host;
        irq_hw_number_t hwirq;
-       unsigned long flags;
 
        if (virq == NO_IRQ)
                return;
@@ -821,12 +769,16 @@ void irq_dispose_mapping(unsigned int virq)
                        host->revmap_data.linear.revmap[hwirq] = NO_IRQ;
                break;
        case IRQ_HOST_MAP_TREE:
-               /* Check if radix tree allocated yet */
-               if (host->revmap_data.tree.gfp_mask == 0)
+               /*
+                * Check if radix tree allocated yet, if not then nothing to
+                * remove.
+                */
+               smp_rmb();
+               if (revmap_trees_allocated < 1)
                        break;
-               irq_radix_wrlock(&flags);
+               mutex_lock(&revmap_trees_mutex);
                radix_tree_delete(&host->revmap_data.tree, hwirq);
-               irq_radix_wrunlock(flags);
+               mutex_unlock(&revmap_trees_mutex);
                break;
        }
 
@@ -875,43 +827,62 @@ unsigned int irq_find_mapping(struct irq_host *host,
 EXPORT_SYMBOL_GPL(irq_find_mapping);
 
 
-unsigned int irq_radix_revmap(struct irq_host *host,
-                             irq_hw_number_t hwirq)
+unsigned int irq_radix_revmap_lookup(struct irq_host *host,
+                                    irq_hw_number_t hwirq)
 {
-       struct radix_tree_root *tree;
        struct irq_map_entry *ptr;
        unsigned int virq;
-       unsigned long flags;
 
        WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE);
 
-       /* Check if the radix tree exist yet. We test the value of
-        * the gfp_mask for that. Sneaky but saves another int in the
-        * structure. If not, we fallback to slow mode
+       /*
+        * Check if the radix tree exists and has bee initialized.
+        * If not, we fallback to slow mode
         */
-       tree = &host->revmap_data.tree;
-       if (tree->gfp_mask == 0)
+       if (revmap_trees_allocated < 2)
                return irq_find_mapping(host, hwirq);
 
        /* Now try to resolve */
-       irq_radix_rdlock(&flags);
-       ptr = radix_tree_lookup(tree, hwirq);
-       irq_radix_rdunlock(flags);
+       /*
+        * No rcu_read_lock(ing) needed, the ptr returned can't go under us
+        * as it's referencing an entry in the static irq_map table.
+        */
+       ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq);
 
-       /* Found it, return */
-       if (ptr) {
+       /*
+        * If found in radix tree, then fine.
+        * Else fallback to linear lookup - this should not happen in practice
+        * as it means that we failed to insert the node in the radix tree.
+        */
+       if (ptr)
                virq = ptr - irq_map;
-               return virq;
-       }
+       else
+               virq = irq_find_mapping(host, hwirq);
+
+       return virq;
+}
+
+void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq,
+                            irq_hw_number_t hwirq)
+{
+
+       WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE);
+
+       /*
+        * Check if the radix tree exists yet.
+        * If not, then the irq will be inserted into the tree when it gets
+        * initialized.
+        */
+       smp_rmb();
+       if (revmap_trees_allocated < 1)
+               return;
 
-       /* If not there, try to insert it */
-       virq = irq_find_mapping(host, hwirq);
        if (virq != NO_IRQ) {
-               irq_radix_wrlock(&flags);
-               radix_tree_insert(tree, hwirq, &irq_map[virq]);
-               irq_radix_wrunlock(flags);
+               mutex_lock(&revmap_trees_mutex);
+               radix_tree_insert(&host->revmap_data.tree, hwirq,
+                                 &irq_map[virq]);
+               mutex_unlock(&revmap_trees_mutex);
        }
-       return virq;
 }
 
 unsigned int irq_linear_revmap(struct irq_host *host,
@@ -1020,14 +991,44 @@ void irq_early_init(void)
 static int irq_late_init(void)
 {
        struct irq_host *h;
-       unsigned long flags;
+       unsigned int i;
 
-       irq_radix_wrlock(&flags);
+       /*
+        * No mutual exclusion with respect to accessors of the tree is needed
+        * here as the synchronization is done via the state variable
+        * revmap_trees_allocated.
+        */
        list_for_each_entry(h, &irq_hosts, link) {
                if (h->revmap_type == IRQ_HOST_MAP_TREE)
-                       INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
+                       INIT_RADIX_TREE(&h->revmap_data.tree, GFP_KERNEL);
+       }
+
+       /*
+        * Make sure the radix trees inits are visible before setting
+        * the flag
+        */
+       smp_wmb();
+       revmap_trees_allocated = 1;
+
+       /*
+        * Insert the reverse mapping for those interrupts already present
+        * in irq_map[].
+        */
+       mutex_lock(&revmap_trees_mutex);
+       for (i = 0; i < irq_virq_count; i++) {
+               if (irq_map[i].host &&
+                   (irq_map[i].host->revmap_type == IRQ_HOST_MAP_TREE))
+                       radix_tree_insert(&irq_map[i].host->revmap_data.tree,
+                                         irq_map[i].hwirq, &irq_map[i]);
        }
-       irq_radix_wrunlock(flags);
+       mutex_unlock(&revmap_trees_mutex);
+
+       /*
+        * Make sure the radix trees insertions are visible before setting
+        * the flag
+        */
+       smp_wmb();
+       revmap_trees_allocated = 2;
 
        return 0;
 }
index b3eef30b5131a0d1eaf43551ae0d0aa2ccda6d92..d051e8cbcd0373138f4c88cd59538067e73bbec1 100644 (file)
@@ -510,10 +510,10 @@ static ssize_t update_ppp(u64 *entitlement, u8 *weight)
                return -EINVAL;
 
        pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
-                __FUNCTION__, ppp_data.entitlement, ppp_data.weight);
+                __func__, ppp_data.entitlement, ppp_data.weight);
 
        pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
-                __FUNCTION__, new_entitled, new_weight);
+                __func__, new_entitled, new_weight);
 
        retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
        return retval;
@@ -556,10 +556,10 @@ static ssize_t update_mpp(u64 *entitlement, u8 *weight)
                return -EINVAL;
 
        pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
-                __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight);
+                __func__, mpp_data.entitled_mem, mpp_data.mem_weight);
 
        pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
-                __FUNCTION__, new_entitled, new_weight);
+                __func__, new_entitled, new_weight);
 
        rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
        return rc;
index 85cb6f340846248882074a2b08f0e920f6acbb2f..2d29752cbe169ea9398fbd1381cd9eff64ec28c8 100644 (file)
@@ -31,11 +31,14 @@ _GLOBAL(reloc_offset)
        mflr    r0
        bl      1f
 1:     mflr    r3
-       LOAD_REG_IMMEDIATE(r4,1b)
+       PPC_LL  r4,(2f-1b)(r3)
        subf    r3,r4,r3
        mtlr    r0
        blr
 
+       .align  3
+2:     PPC_LONG 1b
+
 /*
  * add_reloc_offset(x) returns x + reloc_offset().
  */
@@ -43,12 +46,15 @@ _GLOBAL(add_reloc_offset)
        mflr    r0
        bl      1f
 1:     mflr    r5
-       LOAD_REG_IMMEDIATE(r4,1b)
+       PPC_LL  r4,(2f-1b)(r5)
        subf    r5,r4,r5
        add     r3,r3,r5
        mtlr    r0
        blr
 
+       .align  3
+2:     PPC_LONG 1b
+
 _GLOBAL(kernel_execve)
        li      r0,__NR_execve
        sc
index 7a6dfbca76821bd5e49cbbb04fcda1d045441907..6a9b4bf0d173e0f0a656c0ef313af7fed325df59 100644 (file)
@@ -274,6 +274,10 @@ _GLOBAL(real_writeb)
 /*
  * Flush MMU TLB
  */
+#ifndef CONFIG_FSL_BOOKE
+_GLOBAL(_tlbil_all)
+_GLOBAL(_tlbil_pid)
+#endif
 _GLOBAL(_tlbia)
 #if defined(CONFIG_40x)
        sync                    /* Flush to memory before changing mapping */
@@ -344,6 +348,9 @@ _GLOBAL(_tlbia)
 /*
  * Flush MMU TLB for a particular address
  */
+#ifndef CONFIG_FSL_BOOKE
+_GLOBAL(_tlbil_va)
+#endif
 _GLOBAL(_tlbie)
 #if defined(CONFIG_40x)
        /* We run the search with interrupts disabled because we have to change
@@ -436,6 +443,53 @@ _GLOBAL(_tlbie)
 #endif /* ! CONFIG_40x */
        blr
 
+#if defined(CONFIG_FSL_BOOKE)
+/*
+ * Flush MMU TLB, but only on the local processor (no broadcast)
+ */
+_GLOBAL(_tlbil_all)
+#define MMUCSR0_TLBFI  (MMUCSR0_TLB0FI | MMUCSR0_TLB1FI | \
+                        MMUCSR0_TLB2FI | MMUCSR0_TLB3FI)
+       li      r3,(MMUCSR0_TLBFI)@l
+       mtspr   SPRN_MMUCSR0, r3
+1:
+       mfspr   r3,SPRN_MMUCSR0
+       andi.   r3,r3,MMUCSR0_TLBFI@l
+       bne     1b
+       blr
+
+/*
+ * Flush MMU TLB for a particular process id, but only on the local processor
+ * (no broadcast)
+ */
+_GLOBAL(_tlbil_pid)
+/* we currently do an invalidate all since we don't have per pid invalidate */
+       li      r3,(MMUCSR0_TLBFI)@l
+       mtspr   SPRN_MMUCSR0, r3
+1:
+       mfspr   r3,SPRN_MMUCSR0
+       andi.   r3,r3,MMUCSR0_TLBFI@l
+       bne     1b
+       blr
+
+/*
+ * Flush MMU TLB for a particular address, but only on the local processor
+ * (no broadcast)
+ */
+_GLOBAL(_tlbil_va)
+       slwi    r4,r4,16
+       mtspr   SPRN_MAS6,r4            /* assume AS=0 for now */
+       tlbsx   0,r3
+       mfspr   r4,SPRN_MAS1            /* check valid */
+       andis.  r3,r4,MAS1_VALID@h
+       beqlr
+       rlwinm  r4,r4,0,1,31
+       mtspr   SPRN_MAS1,r4
+       tlbwe
+       blr
+#endif /* CONFIG_FSL_BOOKE */
+
+
 /*
  * Flush instruction cache.
  * This is a no-op on the 601.
@@ -846,8 +900,10 @@ _GLOBAL(kernel_thread)
        li      r4,0            /* new sp (unused) */
        li      r0,__NR_clone
        sc
-       cmpwi   0,r3,0          /* parent or child? */
-       bne     1f              /* return if parent */
+       bns+    1f              /* did system call indicate error? */
+       neg     r3,r3           /* if so, make return code negative */
+1:     cmpwi   0,r3,0          /* parent or child? */
+       bne     2f              /* return if parent */
        li      r0,0            /* make top-level stack frame */
        stwu    r0,-16(r1)
        mtlr    r30             /* fn addr in lr */
@@ -857,7 +913,7 @@ _GLOBAL(kernel_thread)
        li      r0,__NR_exit    /* exit if function returns */
        li      r3,0
        sc
-1:     lwz     r30,8(r1)
+2:     lwz     r30,8(r1)
        lwz     r31,12(r1)
        addi    r1,r1,16
        blr
index 4dd70cf7bb4eb6e17e8755b4f5fad3b4fb9ae49d..3053fe5c62f2a67694d430187df900495c19531b 100644 (file)
@@ -426,8 +426,10 @@ _GLOBAL(kernel_thread)
        li      r4,0            /* new sp (unused) */
        li      r0,__NR_clone
        sc
-       cmpdi   0,r3,0          /* parent or child? */
-       bne     1f              /* return if parent */
+       bns+    1f              /* did system call indicate error? */
+       neg     r3,r3           /* if so, make return code negative */
+1:     cmpdi   0,r3,0          /* parent or child? */
+       bne     2f              /* return if parent */
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
        ld      r2,8(r29)
@@ -438,7 +440,7 @@ _GLOBAL(kernel_thread)
        li      r0,__NR_exit    /* exit after child exits */
         li     r3,0
        sc
-1:     addi    r1,r1,STACK_FRAME_OVERHEAD      
+2:     addi    r1,r1,STACK_FRAME_OVERHEAD
        ld      r29,-24(r1)
        ld      r30,-16(r1)
        blr
index e9be908f199b6fa46ee4ec2226316db2ad1702c6..93ae5b169f418b59e9fd7dadc1f5b89890a9d6fc 100644 (file)
@@ -78,7 +78,7 @@ struct of_device *of_device_alloc(struct device_node *np,
        dev->dev.parent = parent;
        dev->dev.release = of_release_dev;
        dev->dev.archdata.of_node = np;
-       dev->dev.archdata.numa_node = of_node_to_nid(np);
+       set_dev_node(&dev->dev, of_node_to_nid(np));
 
        if (bus_id)
                strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
index c9bf17eec31b1d14c5fd144b18e372e05e6b5868..48a347133f41607c84a05e4b26647f17e4b6829c 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/lppaca.h>
 #include <asm/paca.h>
+#include <asm/sections.h>
 
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
@@ -79,6 +80,8 @@ void __init initialise_pacas(void)
                new_paca->lock_token = 0x8000;
                new_paca->paca_index = cpu;
                new_paca->kernel_toc = kernel_toc;
+               new_paca->kernelbase = (unsigned long) _stext;
+               new_paca->kernel_msr = MSR_KERNEL;
                new_paca->hw_cpu_id = 0xffff;
                new_paca->slb_shadow_ptr = &slb_shadow[cpu];
                new_paca->__current = &init_task;
index ea0c61e09b7640553cf70c92b184339ff3bfd0bc..01ce8c38bae635334b6b3b9d104f0bb26d5861fe 100644 (file)
@@ -56,6 +56,34 @@ resource_size_t isa_mem_base;
 /* Default PCI flags is 0 */
 unsigned int ppc_pci_flags;
 
+static struct dma_mapping_ops *pci_dma_ops;
+
+void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
+{
+       pci_dma_ops = dma_ops;
+}
+
+struct dma_mapping_ops *get_pci_dma_ops(void)
+{
+       return pci_dma_ops;
+}
+EXPORT_SYMBOL(get_pci_dma_ops);
+
+int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       return dma_set_mask(&dev->dev, mask);
+}
+
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       int rc;
+
+       rc = dma_set_mask(&dev->dev, mask);
+       dev->dev.coherent_dma_mask = dev->dma_mask;
+
+       return rc;
+}
+
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
        struct pci_controller *phb;
@@ -180,6 +208,26 @@ char __devinit *pcibios_setup(char *str)
        return str;
 }
 
+void __devinit pcibios_setup_new_device(struct pci_dev *dev)
+{
+       struct dev_archdata *sd = &dev->dev.archdata;
+
+       sd->of_node = pci_device_to_OF_node(dev);
+
+       DBG("PCI: device %s OF node: %s\n", pci_name(dev),
+           sd->of_node ? sd->of_node->full_name : "<none>");
+
+       sd->dma_ops = pci_dma_ops;
+#ifdef CONFIG_PPC32
+       sd->dma_data = (void *)PCI_DRAM_OFFSET;
+#endif
+       set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
+
+       if (ppc_md.pci_dma_dev_setup)
+               ppc_md.pci_dma_dev_setup(dev);
+}
+EXPORT_SYMBOL(pcibios_setup_new_device);
+
 /*
  * Reads the interrupt pin to determine if interrupt is use by card.
  * If the interrupt is used, then gets the interrupt line from the
@@ -371,7 +419,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
        struct pci_dev *pdev = NULL;
        struct resource *found = NULL;
        unsigned long prot = pgprot_val(protection);
-       unsigned long offset = pfn << PAGE_SHIFT;
+       resource_size_t offset = ((resource_size_t)pfn) << PAGE_SHIFT;
        int i;
 
        if (page_is_ram(pfn))
@@ -422,7 +470,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state, int write_combine)
 {
-       resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT;
+       resource_size_t offset =
+               ((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT;
        struct resource *rp;
        int ret;
 
@@ -731,11 +780,6 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 
        res->start = (res->start + offset) & mask;
        res->end = (res->end + offset) & mask;
-
-       pr_debug("PCI:%s            %016llx-%016llx\n",
-                pci_name(dev),
-                (unsigned long long)res->start,
-                (unsigned long long)res->end);
 }
 
 
@@ -781,6 +825,11 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
                         (unsigned int)res->flags);
 
                fixup_resource(res, dev);
+
+               pr_debug("PCI:%s            %016llx-%016llx\n",
+                        pci_name(dev),
+                        (unsigned long long)res->start,
+                        (unsigned long long)res->end);
        }
 
        /* Call machine specific resource fixup */
@@ -789,58 +838,127 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
 
-static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+/* This function tries to figure out if a bridge resource has been initialized
+ * by the firmware or not. It doesn't have to be absolutely bullet proof, but
+ * things go more smoothly when it gets it right. It should covers cases such
+ * as Apple "closed" bridge resources and bare-metal pSeries unassigned bridges
+ */
+static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
+                                                          struct resource *res)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pci_dev *dev = bus->self;
+       resource_size_t offset;
+       u16 command;
+       int i;
 
-       pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
+       /* We don't do anything if PCI_PROBE_ONLY is set */
+       if (ppc_pci_flags & PPC_PCI_PROBE_ONLY)
+               return 0;
 
-       /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
-        * now differently between 32 and 64 bits.
-        */
-       if (dev != NULL) {
-               struct resource *res;
-               int i;
+       /* Job is a bit different between memory and IO */
+       if (res->flags & IORESOURCE_MEM) {
+               /* If the BAR is non-0 (res != pci_mem_offset) then it's probably been
+                * initialized by somebody
+                */
+               if (res->start != hose->pci_mem_offset)
+                       return 0;
 
-               for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
-                       if ((res = bus->resource[i]) == NULL)
-                               continue;
-                       if (!res->flags)
-                               continue;
-                       if (i >= 3 && bus->self->transparent)
-                               continue;
-                       /* On PowerMac, Apple leaves bridge windows open over
-                        * an inaccessible region of memory space (0...fffff)
-                        * which is somewhat bogus, but that's what they think
-                        * means disabled...
-                        *
-                        * We clear those to force them to be reallocated later
-                        *
-                        * We detect such regions by the fact that the base is
-                        * equal to the pci_mem_offset of the host bridge and
-                        * their size is smaller than 1M.
-                        */
-                       if (res->flags & IORESOURCE_MEM &&
-                           res->start == hose->pci_mem_offset &&
-                           res->end < 0x100000) {
-                               printk(KERN_INFO
-                                      "PCI: Closing bogus Apple Firmware"
-                                      " region %d on bus 0x%02x\n",
-                                      i, bus->number);
-                               res->flags = 0;
-                               continue;
-                       }
+               /* The BAR is 0, let's check if memory decoding is enabled on
+                * the bridge. If not, we consider it unassigned
+                */
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               if ((command & PCI_COMMAND_MEMORY) == 0)
+                       return 1;
 
-                       pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
-                                pci_name(dev), i,
-                                (unsigned long long)res->start,\
-                                (unsigned long long)res->end,
-                                (unsigned int)res->flags);
+               /* Memory decoding is enabled and the BAR is 0. If any of the bridge
+                * resources covers that starting address (0 then it's good enough for
+                * us for memory
+                */
+               for (i = 0; i < 3; i++) {
+                       if ((hose->mem_resources[i].flags & IORESOURCE_MEM) &&
+                           hose->mem_resources[i].start == hose->pci_mem_offset)
+                               return 0;
+               }
 
-                       fixup_resource(res, dev);
+               /* Well, it starts at 0 and we know it will collide so we may as
+                * well consider it as unassigned. That covers the Apple case.
+                */
+               return 1;
+       } else {
+               /* If the BAR is non-0, then we consider it assigned */
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+               if (((res->start - offset) & 0xfffffffful) != 0)
+                       return 0;
+
+               /* Here, we are a bit different than memory as typically IO space
+                * starting at low addresses -is- valid. What we do instead if that
+                * we consider as unassigned anything that doesn't have IO enabled
+                * in the PCI command register, and that's it.
+                */
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               if (command & PCI_COMMAND_IO)
+                       return 0;
+
+               /* It's starting at 0 and IO is disabled in the bridge, consider
+                * it unassigned
+                */
+               return 1;
+       }
+}
+
+/* Fixup resources of a PCI<->PCI bridge */
+static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
+{
+       struct resource *res;
+       int i;
+
+       struct pci_dev *dev = bus->self;
+
+       for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+               if ((res = bus->resource[i]) == NULL)
+                       continue;
+               if (!res->flags)
+                       continue;
+               if (i >= 3 && bus->self->transparent)
+                       continue;
+
+               pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
+                        pci_name(dev), i,
+                        (unsigned long long)res->start,\
+                        (unsigned long long)res->end,
+                        (unsigned int)res->flags);
+
+               /* Perform fixup */
+               fixup_resource(res, dev);
+
+               /* Try to detect uninitialized P2P bridge resources,
+                * and clear them out so they get re-assigned later
+                */
+               if (pcibios_uninitialized_bridge_resource(bus, res)) {
+                       res->flags = 0;
+                       pr_debug("PCI:%s            (unassigned)\n", pci_name(dev));
+               } else {
+
+                       pr_debug("PCI:%s            %016llx-%016llx\n",
+                                pci_name(dev),
+                                (unsigned long long)res->start,
+                                (unsigned long long)res->end);
                }
        }
+}
+
+static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev = bus->self;
+
+       pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
+
+       /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
+        * now differently between 32 and 64 bits.
+        */
+       if (dev != NULL)
+               pcibios_fixup_bridge(bus);
 
        /* Additional setup that is different between 32 and 64 bits for now */
        pcibios_do_bus_setup(bus);
index 88db4ffaf11c772e5f73ccbbca6cd96f07eb2c88..131b1dfa68c6993ff32006ae1cf22a7f0386211f 100644 (file)
@@ -53,12 +53,19 @@ LIST_HEAD(hose_list);
 
 static int pci_bus_count;
 
+/* This will remain NULL for now, until isa-bridge.c is made common
+ * to both 32-bit and 64-bit.
+ */
+struct pci_dev *isa_bridge_pcidev;
+EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
+
 static void
-fixup_hide_host_resource_fsl(struct pci_devdev)
+fixup_hide_host_resource_fsl(struct pci_dev *dev)
 {
        int i, class = dev->class >> 8;
 
-       if ((class == PCI_CLASS_PROCESSOR_POWERPC) &&
+       if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
+            class == PCI_CLASS_BRIDGE_OTHER) &&
                (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
                (dev->bus->parent == NULL)) {
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
@@ -424,6 +431,7 @@ void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
        unsigned long io_offset;
        struct resource *res;
        int i;
+       struct pci_dev *dev;
 
        /* Hookup PHB resources */
        io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
@@ -457,6 +465,12 @@ void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
                        bus->resource[i+1] = res;
                }
        }
+
+       if (ppc_md.pci_dma_bus_setup)
+               ppc_md.pci_dma_bus_setup(bus);
+
+       list_for_each_entry(dev, &bus->devices, bus_list)
+               pcibios_setup_new_device(dev);
 }
 
 /* the next one is stolen from the alpha port... */
index 30eedfc5a566d4411caf634f564d5af0225d0ef5..8247cff1cb3e0dc313861d041bcf7afae3c559e4 100644 (file)
@@ -52,35 +52,6 @@ EXPORT_SYMBOL(pci_io_base);
 
 LIST_HEAD(hose_list);
 
-static struct dma_mapping_ops *pci_dma_ops;
-
-void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
-{
-       pci_dma_ops = dma_ops;
-}
-
-struct dma_mapping_ops *get_pci_dma_ops(void)
-{
-       return pci_dma_ops;
-}
-EXPORT_SYMBOL(get_pci_dma_ops);
-
-
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       int rc;
-
-       rc = dma_set_mask(&dev->dev, mask);
-       dev->dev.coherent_dma_mask = dev->dma_mask;
-
-       return rc;
-}
-
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
        if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -548,26 +519,6 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-void __devinit pcibios_setup_new_device(struct pci_dev *dev)
-{
-       struct dev_archdata *sd = &dev->dev.archdata;
-
-       sd->of_node = pci_device_to_OF_node(dev);
-
-       DBG("PCI: device %s OF node: %s\n", pci_name(dev),
-           sd->of_node ? sd->of_node->full_name : "<none>");
-
-       sd->dma_ops = pci_dma_ops;
-#ifdef CONFIG_NUMA
-       sd->numa_node = pcibus_to_node(dev->bus);
-#else
-       sd->numa_node = -1;
-#endif
-       if (ppc_md.pci_dma_dev_setup)
-               ppc_md.pci_dma_dev_setup(dev);
-}
-EXPORT_SYMBOL(pcibios_setup_new_device);
-
 void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
        struct pci_dev *dev;
index e1ea4fe5cfbde0a6c436978f5864f650b10928d2..8edc2359c4193f564752dfee6643512266efcc25 100644 (file)
@@ -119,6 +119,9 @@ EXPORT_SYMBOL(flush_instruction_cache);
 EXPORT_SYMBOL(flush_tlb_kernel_range);
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(_tlbie);
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE)
+EXPORT_SYMBOL(_tlbil_va);
+#endif
 #endif
 EXPORT_SYMBOL(__flush_icache_range);
 EXPORT_SYMBOL(flush_dcache_range);
index 87d83c56b31ec1671007195ce092523535108bb9..3a2dc7e6586a392292ccf3ccbfacb39151a3f675 100644 (file)
@@ -888,9 +888,10 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
  */
 static int __init early_init_dt_scan_drconf_memory(unsigned long node)
 {
-       cell_t *dm, *ls;
+       cell_t *dm, *ls, *usm;
        unsigned long l, n, flags;
        u64 base, size, lmb_size;
+       unsigned int is_kexec_kdump = 0, rngs;
 
        ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
        if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
@@ -905,6 +906,12 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
        if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
                return 0;
 
+       /* check if this is a kexec/kdump kernel. */
+       usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory",
+                                                &l);
+       if (usm != NULL)
+               is_kexec_kdump = 1;
+
        for (; n != 0; --n) {
                base = dt_mem_next_cell(dt_root_addr_cells, &dm);
                flags = dm[3];
@@ -915,13 +922,34 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
                if ((flags & 0x80) || !(flags & 0x8))
                        continue;
                size = lmb_size;
-               if (iommu_is_off) {
-                       if (base >= 0x80000000ul)
+               rngs = 1;
+               if (is_kexec_kdump) {
+                       /*
+                        * For each lmb in ibm,dynamic-memory, a corresponding
+                        * entry in linux,drconf-usable-memory property contains
+                        * a counter 'p' followed by 'p' (base, size) duple.
+                        * Now read the counter from
+                        * linux,drconf-usable-memory property
+                        */
+                       rngs = dt_mem_next_cell(dt_root_size_cells, &usm);
+                       if (!rngs) /* there are no (base, size) duple */
                                continue;
-                       if ((base + size) > 0x80000000ul)
-                               size = 0x80000000ul - base;
                }
-               lmb_add(base, size);
+               do {
+                       if (is_kexec_kdump) {
+                               base = dt_mem_next_cell(dt_root_addr_cells,
+                                                        &usm);
+                               size = dt_mem_next_cell(dt_root_size_cells,
+                                                        &usm);
+                       }
+                       if (iommu_is_off) {
+                               if (base >= 0x80000000ul)
+                                       continue;
+                               if ((base + size) > 0x80000000ul)
+                                       size = 0x80000000ul - base;
+                       }
+                       lmb_add(base, size);
+               } while (--rngs);
        }
        lmb_dump_all();
        return 0;
@@ -1164,6 +1192,9 @@ void __init early_init_devtree(void *params)
 
        /* Reserve LMB regions used by kernel, initrd, dt, etc... */
        lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
+       /* If relocatable, reserve first 32k for interrupt vectors etc. */
+       if (PHYSICAL_START > MEMORY_START)
+               lmb_reserve(MEMORY_START, 0x8000);
        reserve_kdump_trampoline();
        reserve_crashkernel();
        early_reserve_mem();
index b72849ac7db39af14fe1547571da83066cdc3d77..2fdbc18ae94afe3ef27c0a32debbca2535767b7a 100644 (file)
@@ -732,7 +732,7 @@ static struct fake_elf {
                        u32     ignore_me;
                } rpadesc;
        } rpanote;
-} fake_elf = {
+} fake_elf __section(.fakeelf) = {
        .elfhdr = {
                .e_ident = { 0x7f, 'E', 'L', 'F',
                             ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
@@ -774,13 +774,13 @@ static struct fake_elf {
                .type = 0x12759999,
                .name = "IBM,RPA-Client-Config",
                .rpadesc = {
-                       .lpar_affinity = 0,
-                       .min_rmo_size = 64,     /* in megabytes */
+                       .lpar_affinity = 1,
+                       .min_rmo_size = 128,    /* in megabytes */
                        .min_rmo_percent = 0,
-                       .max_pft_size = 48,     /* 2^48 bytes max PFT size */
+                       .max_pft_size = 46,     /* 2^46 bytes max PFT size */
                        .splpar = 1,
                        .min_load = ~0U,
-                       .new_mem_def = 0
+                       .new_mem_def = 1
                }
        }
 };
@@ -1321,7 +1321,7 @@ static void __init prom_initialize_tce_table(void)
  *
  * -- Cort
  */
-extern void __secondary_hold(void);
+extern char __secondary_hold;
 extern unsigned long __secondary_hold_spinloop;
 extern unsigned long __secondary_hold_acknowledge;
 
@@ -1342,13 +1342,7 @@ static void __init prom_hold_cpus(void)
                = (void *) LOW_ADDR(__secondary_hold_spinloop);
        unsigned long *acknowledge
                = (void *) LOW_ADDR(__secondary_hold_acknowledge);
-#ifdef CONFIG_PPC64
-       /* __secondary_hold is actually a descriptor, not the text address */
-       unsigned long secondary_hold
-               = __pa(*PTRRELOC((unsigned long *)__secondary_hold));
-#else
        unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
-#endif
 
        prom_debug("prom_hold_cpus: start...\n");
        prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
@@ -2315,13 +2309,14 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
 
 unsigned long __init prom_init(unsigned long r3, unsigned long r4,
                               unsigned long pp,
-                              unsigned long r6, unsigned long r7)
+                              unsigned long r6, unsigned long r7,
+                              unsigned long kbase)
 {      
        struct prom_t *_prom;
        unsigned long hdr;
-       unsigned long offset = reloc_offset();
 
 #ifdef CONFIG_PPC32
+       unsigned long offset = reloc_offset();
        reloc_got2(offset);
 #endif
 
@@ -2355,9 +2350,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         */
        RELOC(of_platform) = prom_find_machine_type();
 
+#ifndef CONFIG_RELOCATABLE
        /* Bail if this is a kdump kernel. */
        if (PHYSICAL_START > 0)
                prom_panic("Error: You can't boot a kdump kernel from OF!\n");
+#endif
 
        /*
         * Check for an initrd
@@ -2377,7 +2374,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         * Copy the CPU hold code
         */
        if (RELOC(of_platform) != PLATFORM_POWERMAC)
-               copy_and_flush(0, KERNELBASE + offset, 0x100, 0);
+               copy_and_flush(0, kbase, 0x100, 0);
 
        /*
         * Do early parsing of command line
@@ -2480,7 +2477,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
        reloc_got2(-offset);
 #endif
 
-       __start(hdr, KERNELBASE + offset, 0);
+       __start(hdr, kbase, 0);
 
        return 0;
 }
diff --git a/arch/powerpc/kernel/reloc_64.S b/arch/powerpc/kernel/reloc_64.S
new file mode 100644 (file)
index 0000000..b47a0e1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Code to process dynamic relocations in the kernel.
+ *
+ * Copyright 2008 Paul Mackerras, 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.
+ */
+
+#include <asm/ppc_asm.h>
+
+RELA = 7
+RELACOUNT = 0x6ffffff9
+R_PPC64_RELATIVE = 22
+
+/*
+ * r3 = desired final address of kernel
+ */
+_GLOBAL(relocate)
+       mflr    r0
+       bcl     20,31,$+4
+0:     mflr    r12             /* r12 has runtime addr of label 0 */
+       mtlr    r0
+       ld      r11,(p_dyn - 0b)(r12)
+       add     r11,r11,r12     /* r11 has runtime addr of .dynamic section */
+       ld      r9,(p_rela - 0b)(r12)
+       add     r9,r9,r12       /* r9 has runtime addr of .rela.dyn section */
+       ld      r10,(p_st - 0b)(r12)
+       add     r10,r10,r12     /* r10 has runtime addr of _stext */
+
+       /*
+        * Scan the dynamic section for the RELA and RELACOUNT entries.
+        */
+       li      r7,0
+       li      r8,0
+1:     ld      r6,0(r11)       /* get tag */
+       cmpdi   r6,0
+       beq     4f              /* end of list */
+       cmpdi   r6,RELA
+       bne     2f
+       ld      r7,8(r11)       /* get RELA pointer in r7 */
+       b       3f
+2:     addis   r6,r6,(-RELACOUNT)@ha
+       cmpdi   r6,RELACOUNT@l
+       bne     3f
+       ld      r8,8(r11)       /* get RELACOUNT value in r8 */
+3:     addi    r11,r11,16
+       b       1b
+4:     cmpdi   r7,0            /* check we have both RELA and RELACOUNT */
+       cmpdi   cr1,r8,0
+       beq     6f
+       beq     cr1,6f
+
+       /*
+        * Work out linktime address of _stext and hence the
+        * relocation offset to be applied.
+        * cur_offset [r7] = rela.run [r9] - rela.link [r7]
+        * _stext.link [r10] = _stext.run [r10] - cur_offset [r7]
+        * final_offset [r3] = _stext.final [r3] - _stext.link [r10]
+        */
+       subf    r7,r7,r9        /* cur_offset */
+       subf    r10,r7,r10
+       subf    r3,r10,r3       /* final_offset */
+
+       /*
+        * Run through the list of relocations and process the
+        * R_PPC64_RELATIVE ones.
+        */
+       mtctr   r8
+5:     lwz     r0,12(9)        /* ELF64_R_TYPE(reloc->r_info) */
+       cmpwi   r0,R_PPC64_RELATIVE
+       bne     6f
+       ld      r6,0(r9)        /* reloc->r_offset */
+       ld      r0,16(r9)       /* reloc->r_addend */
+       add     r0,r0,r3
+       stdx    r0,r7,r6
+       addi    r9,r9,24
+       bdnz    5b
+
+6:     blr
+
+p_dyn: .llong  __dynamic_start - 0b
+p_rela:        .llong  __rela_dyn_start - 0b
+p_st:  .llong  _stext - 0b
+
index 9cc5a52711e5b585bf78ee2e3934e94405508707..5ec56ff03e8621584cf026b2fdbb0405dddd84b0 100644 (file)
@@ -254,8 +254,21 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        /* If we are a Freescale core do a simple check so
         * we dont have to keep adding cases in the future */
        if (PVR_VER(pvr) & 0x8000) {
-               maj = PVR_MAJ(pvr);
-               min = PVR_MIN(pvr);
+               switch (PVR_VER(pvr)) {
+               case 0x8000:    /* 7441/7450/7451, Voyager */
+               case 0x8001:    /* 7445/7455, Apollo 6 */
+               case 0x8002:    /* 7447/7457, Apollo 7 */
+               case 0x8003:    /* 7447A, Apollo 7 PM */
+               case 0x8004:    /* 7448, Apollo 8 */
+               case 0x800c:    /* 7410, Nitro */
+                       maj = ((pvr >> 8) & 0xF);
+                       min = PVR_MIN(pvr);
+                       break;
+               default:        /* e500/book-e */
+                       maj = PVR_MAJ(pvr);
+                       min = PVR_MIN(pvr);
+                       break;
+               }
        } else {
                switch (PVR_VER(pvr)) {
                        case 0x0020:    /* 403 family */
index 066e65c59b58230091db2145e1e4115abe541b84..c1a27626a940d1b49c990bbcc3f3f2c5f538b097 100644 (file)
@@ -111,7 +111,7 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(unsigned long dt_ptr, unsigned long phys)
+notrace void __init machine_init(unsigned long dt_ptr)
 {
        /* Enable early debugging if any specified (see udbg.h) */
        udbg_early_init();
@@ -209,23 +209,12 @@ EXPORT_SYMBOL(nvram_sync);
 
 #endif /* CONFIG_NVRAM */
 
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
 int __init ppc_init(void)
 {
-       int cpu;
-
        /* clear the progress line */
        if (ppc_md.progress)
                ppc_md.progress("             ", 0xffff);
 
-       /* register CPU devices */
-       for_each_possible_cpu(cpu) {
-               struct cpu *c = &per_cpu(cpu_devices, cpu);
-               c->hotpluggable = 1;
-               register_cpu(c, cpu);
-       }
-
        /* call platform init */
        if (ppc_md.init != NULL) {
                ppc_md.init();
index 8b25f51f03bf9b8fc78da61015859a4ce9585fd0..843c0af210d0f7f0161b8583c50b71a90604faf0 100644 (file)
@@ -255,9 +255,11 @@ void early_setup_secondary(void)
 #endif /* CONFIG_SMP */
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+extern unsigned long __secondary_hold_spinloop;
+extern void generic_secondary_smp_init(void);
+
 void smp_release_cpus(void)
 {
-       extern unsigned long __secondary_hold_spinloop;
        unsigned long *ptr;
 
        DBG(" -> smp_release_cpus()\n");
@@ -266,12 +268,11 @@ void smp_release_cpus(void)
         * all now so they can start to spin on their individual paca
         * spinloops. For non SMP kernels, the secondary cpus never get out
         * of the common spinloop.
-        * This is useless but harmless on iSeries, secondaries are already
-        * waiting on their paca spinloops. */
+        */
 
        ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
                        - PHYSICAL_START);
-       *ptr = 1;
+       *ptr = __pa(generic_secondary_smp_init);
        mb();
 
        DBG(" <- smp_release_cpus()\n");
index c27b10a1bd79adffe0a2686b9c5baaf34d3eb724..ff9f7010097d1568943329a15d8c04458beddc4c 100644 (file)
@@ -101,8 +101,7 @@ void smp_message_recv(int msg)
                generic_smp_call_function_interrupt();
                break;
        case PPC_MSG_RESCHEDULE:
-               /* XXX Do we have to do this? */
-               set_need_resched();
+               /* we notice need_resched on exit */
                break;
        case PPC_MSG_CALL_FUNC_SINGLE:
                generic_smp_call_function_single_interrupt();
index c906c4bf68357f7fb65dcf19298269a6d03cfafd..23c8c5e7dc4d0be08d0e153fb597ebc3b7535bc2 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 
 #include <asm/pgtable.h>
index e092c3cbdb9b978ac3f7a9123375e07769e0aab5..86ac1d90d02bcb3d80060d7531da58022f685987 100644 (file)
@@ -133,7 +133,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 
        cmpdi   r12,0
        beq-    nothing_to_copy
-       li      r15,512
+       li      r15,PAGE_SIZE>>3
 copyloop:
        ld      r13,pbe_address(r12)
        ld      r14,pbe_orig_address(r12)
index d98634c76060e735290c03f0fabff5d635437e8c..bb1cfcfdbbbbc02e73c4c5292b900e6f7a86c8f8 100644 (file)
@@ -61,42 +61,6 @@ asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
        return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       long err;
-
-       if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
-           !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
-       err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= __put_user(ino, &statbuf->st_ino);
-       err |= __put_user(stat->mode, &statbuf->st_mode);
-       err |= __put_user(stat->nlink, &statbuf->st_nlink);
-       err |= __put_user(stat->uid, &statbuf->st_uid);
-       err |= __put_user(stat->gid, &statbuf->st_gid);
-       err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= __put_user(stat->size, &statbuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &statbuf->st_blksize);
-       err |= __put_user(stat->blocks, &statbuf->st_blocks);
-       err |= __put_user(0, &statbuf->__unused4[0]);
-       err |= __put_user(0, &statbuf->__unused4[1]);
-
-       return err;
-}
-
 /* Note: it is necessary to treat option as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -107,77 +71,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
        return sys_sysfs((int)option, arg1, arg2);
 }
 
-asmlinkage long compat_sys_pause(void)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       
-       return -ERESTARTNOHAND;
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (!access_ok(VERIFY_READ, i, sizeof(*i)))
-               return -EFAULT;
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-       return 0;
-}
-
-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) |
-                __put_user(i->tv_usec, &o->tv_usec)));
-}
-
-
-
-
-/* Translations due to time_t size differences.  Which affects all
-   sorts of things, like timeval and itimerval.  */
-extern struct timezone sys_tz;
-
-asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       
-       return 0;
-}
-
-
-
-asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-       
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 #ifdef CONFIG_SYSVIPC
 long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
               u32 fifth)
index 56d172d16e5654b483e2ddaa087c9c6302e6e42d..86a2ffccef2592066ece036093a4e0b73858f7da 100644 (file)
 #include <asm/firmware.h>
 #include <asm/hvcall.h>
 #include <asm/prom.h>
-#include <asm/paca.h>
-#include <asm/lppaca.h>
 #include <asm/machdep.h>
 #include <asm/smp.h>
 
+#ifdef CONFIG_PPC64
+#include <asm/paca.h>
+#include <asm/lppaca.h>
+#endif
+
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
 static DEFINE_PER_CPU(struct kobject *, cache_toplevel);
 
-/* SMT stuff */
+/*
+ * SMT snooze delay stuff, 64-bit only for now
+ */
+
+#ifdef CONFIG_PPC64
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 /* Time in microseconds we delay before sleeping in the idle loop */
 DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 };
 
@@ -106,7 +112,7 @@ static int __init setup_smt_snooze_delay(char *str)
 }
 __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC64 */
 
 /*
  * Enabling PMCs will slow partition context switch times so we only do
@@ -115,7 +121,7 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
 static DEFINE_PER_CPU(char, pmcs_enabled);
 
-void ppc64_enable_pmcs(void)
+void ppc_enable_pmcs(void)
 {
        /* Only need to enable them once */
        if (__get_cpu_var(pmcs_enabled))
@@ -126,8 +132,9 @@ void ppc64_enable_pmcs(void)
        if (ppc_md.enable_pmcs)
                ppc_md.enable_pmcs();
 }
-EXPORT_SYMBOL(ppc64_enable_pmcs);
+EXPORT_SYMBOL(ppc_enable_pmcs);
 
+#if defined(CONFIG_6xx) || defined(CONFIG_PPC64)
 /* XXX convert to rusty's on_one_cpu */
 static unsigned long run_on_cpu(unsigned long cpu,
                                unsigned long (*func)(unsigned long),
@@ -146,6 +153,7 @@ static unsigned long run_on_cpu(unsigned long cpu,
 
        return ret;
 }
+#endif
 
 #define SYSFS_PMCSETUP(NAME, ADDRESS) \
 static unsigned long read_##NAME(unsigned long junk) \
@@ -154,7 +162,7 @@ static unsigned long read_##NAME(unsigned long junk) \
 } \
 static unsigned long write_##NAME(unsigned long val) \
 { \
-       ppc64_enable_pmcs(); \
+       ppc_enable_pmcs(); \
        mtspr(ADDRESS, val); \
        return 0; \
 } \
@@ -184,28 +192,53 @@ static ssize_t __used \
  * that are implemented on the current processor
  */
 
+#if defined(CONFIG_PPC64)
+#define HAS_PPC_PMC_CLASSIC    1
+#define HAS_PPC_PMC_IBM                1
+#define HAS_PPC_PMC_PA6T       1
+#elif defined(CONFIG_6xx)
+#define HAS_PPC_PMC_CLASSIC    1
+#define HAS_PPC_PMC_IBM                1
+#define HAS_PPC_PMC_G4         1
+#endif
+
+
+#ifdef HAS_PPC_PMC_CLASSIC
 SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0);
 SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1);
-SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
 SYSFS_PMCSETUP(pmc1, SPRN_PMC1);
 SYSFS_PMCSETUP(pmc2, SPRN_PMC2);
 SYSFS_PMCSETUP(pmc3, SPRN_PMC3);
 SYSFS_PMCSETUP(pmc4, SPRN_PMC4);
 SYSFS_PMCSETUP(pmc5, SPRN_PMC5);
 SYSFS_PMCSETUP(pmc6, SPRN_PMC6);
+
+#ifdef HAS_PPC_PMC_G4
+SYSFS_PMCSETUP(mmcr2, SPRN_MMCR2);
+#endif
+
+#ifdef CONFIG_PPC64
 SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
 SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
+
+SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
 SYSFS_PMCSETUP(purr, SPRN_PURR);
 SYSFS_PMCSETUP(spurr, SPRN_SPURR);
 SYSFS_PMCSETUP(dscr, SPRN_DSCR);
 
+static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
+static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
+static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
+static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
+#endif /* CONFIG_PPC64 */
+
+#ifdef HAS_PPC_PMC_PA6T
 SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0);
 SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1);
 SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2);
 SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
 SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
 SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
-
 #ifdef CONFIG_DEBUG_KERNEL
 SYSFS_PMCSETUP(hid0, SPRN_HID0);
 SYSFS_PMCSETUP(hid1, SPRN_HID1);
@@ -236,28 +269,37 @@ SYSFS_PMCSETUP(tsr1, SPRN_PA6T_TSR1);
 SYSFS_PMCSETUP(tsr2, SPRN_PA6T_TSR2);
 SYSFS_PMCSETUP(tsr3, SPRN_PA6T_TSR3);
 #endif /* CONFIG_DEBUG_KERNEL */
+#endif /* HAS_PPC_PMC_PA6T */
 
-static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
-static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
-static SYSDEV_ATTR(dscr, 0600, show_dscr, store_dscr);
-static SYSDEV_ATTR(purr, 0600, show_purr, store_purr);
-
+#ifdef HAS_PPC_PMC_IBM
 static struct sysdev_attribute ibm_common_attrs[] = {
        _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
        _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
 };
+#endif /* HAS_PPC_PMC_G4 */
+
+#ifdef HAS_PPC_PMC_G4
+static struct sysdev_attribute g4_common_attrs[] = {
+       _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
+       _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
+       _SYSDEV_ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2),
+};
+#endif /* HAS_PPC_PMC_G4 */
 
-static struct sysdev_attribute ibm_pmc_attrs[] = {
+static struct sysdev_attribute classic_pmc_attrs[] = {
        _SYSDEV_ATTR(pmc1, 0600, show_pmc1, store_pmc1),
        _SYSDEV_ATTR(pmc2, 0600, show_pmc2, store_pmc2),
        _SYSDEV_ATTR(pmc3, 0600, show_pmc3, store_pmc3),
        _SYSDEV_ATTR(pmc4, 0600, show_pmc4, store_pmc4),
        _SYSDEV_ATTR(pmc5, 0600, show_pmc5, store_pmc5),
        _SYSDEV_ATTR(pmc6, 0600, show_pmc6, store_pmc6),
+#ifdef CONFIG_PPC64
        _SYSDEV_ATTR(pmc7, 0600, show_pmc7, store_pmc7),
        _SYSDEV_ATTR(pmc8, 0600, show_pmc8, store_pmc8),
+#endif
 };
 
+#ifdef HAS_PPC_PMC_PA6T
 static struct sysdev_attribute pa6t_attrs[] = {
        _SYSDEV_ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0),
        _SYSDEV_ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1),
@@ -298,6 +340,8 @@ static struct sysdev_attribute pa6t_attrs[] = {
        _SYSDEV_ATTR(tsr3, 0600, show_tsr3, store_tsr3),
 #endif /* CONFIG_DEBUG_KERNEL */
 };
+#endif /* HAS_PPC_PMC_PA6T */
+#endif /* HAS_PPC_PMC_CLASSIC */
 
 struct cache_desc {
        struct kobject kobj;
@@ -588,23 +632,36 @@ static void __cpuinit register_cpu_online(unsigned int cpu)
        struct sysdev_attribute *attrs, *pmc_attrs;
        int i, nattrs;
 
+#ifdef CONFIG_PPC64
        if (!firmware_has_feature(FW_FEATURE_ISERIES) &&
                        cpu_has_feature(CPU_FTR_SMT))
                sysdev_create_file(s, &attr_smt_snooze_delay);
+#endif
 
        /* PMC stuff */
        switch (cur_cpu_spec->pmc_type) {
+#ifdef HAS_PPC_PMC_IBM
        case PPC_PMC_IBM:
                attrs = ibm_common_attrs;
                nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute);
-               pmc_attrs = ibm_pmc_attrs;
+               pmc_attrs = classic_pmc_attrs;
                break;
+#endif /* HAS_PPC_PMC_IBM */
+#ifdef HAS_PPC_PMC_G4
+       case PPC_PMC_G4:
+               attrs = g4_common_attrs;
+               nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute);
+               pmc_attrs = classic_pmc_attrs;
+               break;
+#endif /* HAS_PPC_PMC_G4 */
+#ifdef HAS_PPC_PMC_PA6T
        case PPC_PMC_PA6T:
                /* PA Semi starts counting at PMC0 */
                attrs = pa6t_attrs;
                nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute);
                pmc_attrs = NULL;
                break;
+#endif /* HAS_PPC_PMC_PA6T */
        default:
                attrs = NULL;
                nattrs = 0;
@@ -618,6 +675,7 @@ static void __cpuinit register_cpu_online(unsigned int cpu)
                for (i = 0; i < cur_cpu_spec->num_pmcs; i++)
                        sysdev_create_file(s, &pmc_attrs[i]);
 
+#ifdef CONFIG_PPC64
        if (cpu_has_feature(CPU_FTR_MMCRA))
                sysdev_create_file(s, &attr_mmcra);
 
@@ -629,6 +687,7 @@ static void __cpuinit register_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                sysdev_create_file(s, &attr_dscr);
+#endif /* CONFIG_PPC64 */
 
        create_cache_info(s);
 }
@@ -641,16 +700,9 @@ static void remove_cache_info(struct sys_device *sysdev)
        int cpu = sysdev->id;
 
        cache_desc = per_cpu(cache_desc, cpu);
-       if (cache_desc != NULL) {
-               sysfs_remove_file(&cache_desc->kobj, &cache_size_attr.attr);
-               sysfs_remove_file(&cache_desc->kobj, &cache_line_size_attr.attr);
-               sysfs_remove_file(&cache_desc->kobj, &cache_type_attr.attr);
-               sysfs_remove_file(&cache_desc->kobj, &cache_level_attr.attr);
-               sysfs_remove_file(&cache_desc->kobj, &cache_nr_sets_attr.attr);
-               sysfs_remove_file(&cache_desc->kobj, &cache_assoc_attr.attr);
-
+       if (cache_desc != NULL)
                kobject_put(&cache_desc->kobj);
-       }
+
        cache_toplevel = per_cpu(cache_toplevel, cpu);
        if (cache_toplevel != NULL)
                kobject_put(cache_toplevel);
@@ -671,17 +723,28 @@ static void unregister_cpu_online(unsigned int cpu)
 
        /* PMC stuff */
        switch (cur_cpu_spec->pmc_type) {
+#ifdef HAS_PPC_PMC_IBM
        case PPC_PMC_IBM:
                attrs = ibm_common_attrs;
                nattrs = sizeof(ibm_common_attrs) / sizeof(struct sysdev_attribute);
-               pmc_attrs = ibm_pmc_attrs;
+               pmc_attrs = classic_pmc_attrs;
+               break;
+#endif /* HAS_PPC_PMC_IBM */
+#ifdef HAS_PPC_PMC_G4
+       case PPC_PMC_G4:
+               attrs = g4_common_attrs;
+               nattrs = sizeof(g4_common_attrs) / sizeof(struct sysdev_attribute);
+               pmc_attrs = classic_pmc_attrs;
                break;
+#endif /* HAS_PPC_PMC_G4 */
+#ifdef HAS_PPC_PMC_PA6T
        case PPC_PMC_PA6T:
                /* PA Semi starts counting at PMC0 */
                attrs = pa6t_attrs;
                nattrs = sizeof(pa6t_attrs) / sizeof(struct sysdev_attribute);
                pmc_attrs = NULL;
                break;
+#endif /* HAS_PPC_PMC_PA6T */
        default:
                attrs = NULL;
                nattrs = 0;
@@ -695,6 +758,7 @@ static void unregister_cpu_online(unsigned int cpu)
                for (i = 0; i < cur_cpu_spec->num_pmcs; i++)
                        sysdev_remove_file(s, &pmc_attrs[i]);
 
+#ifdef CONFIG_PPC64
        if (cpu_has_feature(CPU_FTR_MMCRA))
                sysdev_remove_file(s, &attr_mmcra);
 
@@ -706,6 +770,7 @@ static void unregister_cpu_online(unsigned int cpu)
 
        if (cpu_has_feature(CPU_FTR_DSCR))
                sysdev_remove_file(s, &attr_dscr);
+#endif /* CONFIG_PPC64 */
 
        remove_cache_info(s);
 }
index 81ccb8dd1a54d8f95b0ed84f357d6e64e5395ab1..f5def6cf5cd61b0114458c74a5171fe724683267 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/module.h>
index 2750fbab1975b2e7e4c84d48a67589385aeb9e40..434c92a85c037431512e96f16b4e9ea49265a6c6 100644 (file)
@@ -1232,7 +1232,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
        else
                viodev->dev.archdata.dma_ops = &dma_iommu_ops;
        viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
-       viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
+       set_dev_node(&viodev->dev, of_node_to_nid(of_node));
 
        /* init generic 'struct device' fields: */
        viodev->dev.parent = &vio_bus_device.dev;
index 9f6c1ca1739e08ecc1e56a64ffed6c6a610a3e1a..b39c27ed79196c2d7cd1d4f32843fd3ee5563581 100644 (file)
@@ -187,6 +187,24 @@ SECTIONS
                *(.machine.desc)
                __machine_desc_end = . ;
        }
+       . = ALIGN(8);
+       .dynsym : AT(ADDR(.dynsym) - LOAD_OFFSET) { *(.dynsym) }
+       .dynstr : AT(ADDR(.dynstr) - LOAD_OFFSET) { *(.dynstr) }
+       .dynamic : AT(ADDR(.dynamic) - LOAD_OFFSET)
+       {
+               __dynamic_start = .;
+               *(.dynamic)
+       }
+       .hash : AT(ADDR(.hash) - LOAD_OFFSET) { *(.hash) }
+       .interp : AT(ADDR(.interp) - LOAD_OFFSET) { *(.interp) }
+       .rela.dyn : AT(ADDR(.rela.dyn) - LOAD_OFFSET)
+       {
+               __rela_dyn_start = .;
+               *(.rela*)
+       }
+
+       /* Fake ELF header containing RPA note; for addnote */
+       .fakeelf : AT(ADDR(.fakeelf) - LOAD_OFFSET) { *(.fakeelf) }
 
        /* freed after init ends here */
        . = ALIGN(PAGE_SIZE);
index 5a5602da50910d441f806c6b0a111fcd3e19aab3..2e227a412bc240f2bc889b0c7c1fe2e17a7bdd8c 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/highmem.h>
 #include <asm/mmu-44x.h>
@@ -109,7 +110,6 @@ static int kvmppc_44x_tlbe_is_writable(struct tlbe *tlbe)
        return tlbe->word2 & (PPC44x_TLB_SW|PPC44x_TLB_UW);
 }
 
-/* Must be called with mmap_sem locked for writing. */
 static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
                                       unsigned int index)
 {
@@ -124,6 +124,11 @@ static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
        }
 }
 
+void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i)
+{
+    vcpu->arch.shadow_tlb_mod[i] = 1;
+}
+
 /* Caller must ensure that the specified guest TLB entry is safe to insert into
  * the shadow TLB. */
 void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
@@ -142,19 +147,16 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
        stlbe = &vcpu->arch.shadow_tlb[victim];
 
        /* Get reference to new page. */
-       down_read(&current->mm->mmap_sem);
        new_page = gfn_to_page(vcpu->kvm, gfn);
        if (is_error_page(new_page)) {
                printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", gfn);
                kvm_release_page_clean(new_page);
-               up_read(&current->mm->mmap_sem);
                return;
        }
        hpaddr = page_to_phys(new_page);
 
        /* Drop reference to old page. */
        kvmppc_44x_shadow_release(vcpu, victim);
-       up_read(&current->mm->mmap_sem);
 
        vcpu->arch.shadow_pages[victim] = new_page;
 
@@ -164,27 +166,30 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
 
        /* XXX what about AS? */
 
-       stlbe->tid = asid & 0xff;
+       stlbe->tid = !(asid & 0xff);
 
        /* Force TS=1 for all guest mappings. */
        /* For now we hardcode 4KB mappings, but it will be important to
         * use host large pages in the future. */
        stlbe->word0 = (gvaddr & PAGE_MASK) | PPC44x_TLB_VALID | PPC44x_TLB_TS
                       | PPC44x_TLB_4K;
-
        stlbe->word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
        stlbe->word2 = kvmppc_44x_tlb_shadow_attrib(flags,
                                                    vcpu->arch.msr & MSR_PR);
+       kvmppc_tlbe_set_modified(vcpu, victim);
+
+       KVMTRACE_5D(STLB_WRITE, vcpu, victim,
+                       stlbe->tid, stlbe->word0, stlbe->word1, stlbe->word2,
+                       handler);
 }
 
 void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
                            gva_t eend, u32 asid)
 {
-       unsigned int pid = asid & 0xff;
+       unsigned int pid = !(asid & 0xff);
        int i;
 
        /* XXX Replace loop with fancy data structures. */
-       down_write(&current->mm->mmap_sem);
        for (i = 0; i <= tlb_44x_hwater; i++) {
                struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
                unsigned int tid;
@@ -204,21 +209,35 @@ void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
 
                kvmppc_44x_shadow_release(vcpu, i);
                stlbe->word0 = 0;
+               kvmppc_tlbe_set_modified(vcpu, i);
+               KVMTRACE_5D(STLB_INVAL, vcpu, i,
+                               stlbe->tid, stlbe->word0, stlbe->word1,
+                               stlbe->word2, handler);
        }
-       up_write(&current->mm->mmap_sem);
 }
 
-/* Invalidate all mappings, so that when they fault back in they will get the
- * proper permission bits. */
+/* Invalidate all mappings on the privilege switch after PID has been changed.
+ * The guest always runs with PID=1, so we must clear the entire TLB when
+ * switching address spaces. */
 void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
 {
        int i;
 
-       /* XXX Replace loop with fancy data structures. */
-       down_write(&current->mm->mmap_sem);
-       for (i = 0; i <= tlb_44x_hwater; i++) {
-               kvmppc_44x_shadow_release(vcpu, i);
-               vcpu->arch.shadow_tlb[i].word0 = 0;
+       if (vcpu->arch.swap_pid) {
+               /* XXX Replace loop with fancy data structures. */
+               for (i = 0; i <= tlb_44x_hwater; i++) {
+                       struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
+
+                       /* Future optimization: clear only userspace mappings. */
+                       kvmppc_44x_shadow_release(vcpu, i);
+                       stlbe->word0 = 0;
+                       kvmppc_tlbe_set_modified(vcpu, i);
+                       KVMTRACE_5D(STLB_INVAL, vcpu, i,
+                                   stlbe->tid, stlbe->word0, stlbe->word1,
+                                   stlbe->word2, handler);
+               }
+               vcpu->arch.swap_pid = 0;
        }
-       up_write(&current->mm->mmap_sem);
+
+       vcpu->arch.shadow_pid = !usermode;
 }
index 6b076010213ba28248a9c81813ca0920bef43e08..53aaa66b25e5ada55b425004e7a004295747857b 100644 (file)
@@ -37,6 +37,17 @@ config KVM_BOOKE_HOST
          Provides host support for KVM on Book E PowerPC processors. Currently
          this works on 440 processors only.
 
+config KVM_TRACE
+       bool "KVM trace support"
+       depends on KVM && MARKERS && SYSFS
+       select RELAY
+       select DEBUG_FS
+       default n
+       ---help---
+         This option allows reading a trace of kvm-related events through
+         relayfs.  Note the ABI is not considered stable and will be
+         modified in future updates.
+
 source drivers/virtio/Kconfig
 
 endif # VIRTUALIZATION
index 04e3449e1f427f0ee644443a6a66c233afef58fc..2a5d4397ac4b06f7545a5fc764b9da98b0ba580a 100644 (file)
@@ -4,9 +4,11 @@
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
 
-common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
 
-kvm-objs := $(common-objs) powerpc.o emulate.o booke_guest.o
+common-objs-$(CONFIG_KVM_TRACE)  += $(addprefix ../../../virt/kvm/, kvm_trace.o)
+
+kvm-objs := $(common-objs-y) powerpc.o emulate.o booke_guest.o
 obj-$(CONFIG_KVM) += kvm.o
 
 AFLAGS_booke_interrupts.o := -I$(obj)
index 9c8ad850c6e32ebcc78b697c8e8246e69d91dffa..7b2591e26bae3dc93dc7f002e833fd98de8288bb 100644 (file)
@@ -410,6 +410,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                break;
        }
 
+       case BOOKE_INTERRUPT_DEBUG: {
+               u32 dbsr;
+
+               vcpu->arch.pc = mfspr(SPRN_CSRR0);
+
+               /* clear IAC events in DBSR register */
+               dbsr = mfspr(SPRN_DBSR);
+               dbsr &= DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4;
+               mtspr(SPRN_DBSR, dbsr);
+
+               run->exit_reason = KVM_EXIT_DEBUG;
+               r = RESUME_HOST;
+               break;
+       }
+
        default:
                printk(KERN_EMERG "exit_nr %d\n", exit_nr);
                BUG();
@@ -471,6 +486,8 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.msr = 0;
        vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */
 
+       vcpu->arch.shadow_pid = 1;
+
        /* Eye-catching number so we know if the guest takes an interrupt
         * before it's programmed its own IVPR. */
        vcpu->arch.ivpr = 0x55550000;
index 3b653b5309b8ecc2dad5b5137163a9465408ca22..95e165baf85faee89b7dfa30e628b75778358618 100644 (file)
@@ -42,7 +42,8 @@
 #define HOST_STACK_LR   (HOST_STACK_SIZE + 4) /* In caller stack frame. */
 
 #define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \
-                        (1<<BOOKE_INTERRUPT_DTLB_MISS))
+                        (1<<BOOKE_INTERRUPT_DTLB_MISS) | \
+                        (1<<BOOKE_INTERRUPT_DEBUG))
 
 #define NEED_DEAR_MASK ((1<<BOOKE_INTERRUPT_DATA_STORAGE) | \
                         (1<<BOOKE_INTERRUPT_DTLB_MISS))
@@ -331,51 +332,57 @@ lightweight_exit:
 
        mfspr   r3, SPRN_PID
        stw     r3, VCPU_HOST_PID(r4)
-       lwz     r3, VCPU_PID(r4)
+       lwz     r3, VCPU_SHADOW_PID(r4)
        mtspr   SPRN_PID, r3
 
-       /* Prevent all TLB updates. */
+       /* Prevent all asynchronous TLB updates. */
        mfmsr   r5
        lis     r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@h
        ori     r6, r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
        andc    r6, r5, r6
        mtmsr   r6
 
-       /* Save the host's non-pinned TLB mappings, and load the guest mappings
-        * over them. Leave the host's "pinned" kernel mappings in place. */
-       /* XXX optimization: use generation count to avoid swapping unmodified
-        * entries. */
+       /* Load the guest mappings, leaving the host's "pinned" kernel mappings
+        * in place. */
        mfspr   r10, SPRN_MMUCR                 /* Save host MMUCR. */
-       lis     r8, tlb_44x_hwater@ha
-       lwz     r8, tlb_44x_hwater@l(r8)
-       addi    r3, r4, VCPU_HOST_TLB - 4
-       addi    r9, r4, VCPU_SHADOW_TLB - 4
-       li      r6, 0
+       li      r5, PPC44x_TLB_SIZE
+       lis     r5, tlb_44x_hwater@ha
+       lwz     r5, tlb_44x_hwater@l(r5)
+       mtctr   r5
+       addi    r9, r4, VCPU_SHADOW_TLB
+       addi    r5, r4, VCPU_SHADOW_MOD
+       li      r3, 0
 1:
-       /* Save host entry. */
-       tlbre   r7, r6, PPC44x_TLB_PAGEID
-       mfspr   r5, SPRN_MMUCR
-       stwu    r5, 4(r3)
-       stwu    r7, 4(r3)
-       tlbre   r7, r6, PPC44x_TLB_XLAT
-       stwu    r7, 4(r3)
-       tlbre   r7, r6, PPC44x_TLB_ATTRIB
-       stwu    r7, 4(r3)
+       lbzx    r7, r3, r5
+       cmpwi   r7, 0
+       beq     3f
+
        /* Load guest entry. */
-       lwzu    r7, 4(r9)
+       mulli   r11, r3, TLBE_BYTES
+       add     r11, r11, r9
+       lwz     r7, 0(r11)
        mtspr   SPRN_MMUCR, r7
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_PAGEID
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_XLAT
-       lwzu    r7, 4(r9)
-       tlbwe   r7, r6, PPC44x_TLB_ATTRIB
-       /* Increment index. */
-       addi    r6, r6, 1
-       cmpw    r6, r8
-       blt     1b
+       lwz     r7, 4(r11)
+       tlbwe   r7, r3, PPC44x_TLB_PAGEID
+       lwz     r7, 8(r11)
+       tlbwe   r7, r3, PPC44x_TLB_XLAT
+       lwz     r7, 12(r11)
+       tlbwe   r7, r3, PPC44x_TLB_ATTRIB
+3:
+       addi    r3, r3, 1                       /* Increment index. */
+       bdnz    1b
+
        mtspr   SPRN_MMUCR, r10                 /* Restore host MMUCR. */
 
+       /* Clear bitmap of modified TLB entries */
+       li      r5, PPC44x_TLB_SIZE>>2
+       mtctr   r5
+       addi    r5, r4, VCPU_SHADOW_MOD - 4
+       li      r6, 0
+1:
+       stwu    r6, 4(r5)
+       bdnz    1b
+
        iccci   0, 0 /* XXX hack */
 
        /* Load some guest volatiles. */
@@ -431,6 +438,14 @@ lightweight_exit:
        oris    r3, r3, KVMPPC_MSR_MASK@h
        ori     r3, r3, KVMPPC_MSR_MASK@l
        mtsrr1  r3
+
+       /* Clear any debug events which occurred since we disabled MSR[DE].
+        * XXX This gives us a 3-instruction window in which a breakpoint
+        * intended for guest context could fire in the host instead. */
+       lis     r3, 0xffff
+       ori     r3, r3, 0xffff
+       mtspr   SPRN_DBSR, r3
+
        lwz     r3, VCPU_GPR(r3)(r4)
        lwz     r4, VCPU_GPR(r4)(r4)
        rfi
index 8c605d0a5488fdce0268cbbdf3055d9404028f7b..0fce4fbdc20d2015f44ce3c2c8bfcef291bc82b9 100644 (file)
@@ -170,6 +170,10 @@ static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
                kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags);
        }
 
+       KVMTRACE_5D(GTLB_WRITE, vcpu, index,
+                       tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2,
+                       handler);
+
        return EMULATE_DONE;
 }
 
@@ -504,7 +508,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        case SPRN_MMUCR:
                                vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
                        case SPRN_PID:
-                               vcpu->arch.pid = vcpu->arch.gpr[rs]; break;
+                               kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
                        case SPRN_CCR0:
                                vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
                        case SPRN_CCR1:
@@ -765,6 +769,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
                break;
        }
 
+       KVMTRACE_3D(PPC_INSTR, vcpu, inst, vcpu->arch.pc, emulated, entryexit);
+
        if (advance)
                vcpu->arch.pc += 4; /* Advance past emulated instruction. */
 
index 53826a5f6c06d406bb7a95ebb8017f0b4d1a1185..90a6fc422b238ccbd38becc6d36546c0a7ca0cd0 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/cputable.h>
 #include <asm/uaccess.h>
 #include <asm/kvm_ppc.h>
+#include <asm/tlbflush.h>
 
 
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
@@ -239,18 +240,114 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
 }
 
+/* Note: clearing MSR[DE] just means that the debug interrupt will not be
+ * delivered *immediately*. Instead, it simply sets the appropriate DBSR bits.
+ * If those DBSR bits are still set when MSR[DE] is re-enabled, the interrupt
+ * will be delivered as an "imprecise debug event" (which is indicated by
+ * DBSR[IDE].
+ */
+static void kvmppc_disable_debug_interrupts(void)
+{
+       mtmsr(mfmsr() & ~MSR_DE);
+}
+
+static void kvmppc_restore_host_debug_state(struct kvm_vcpu *vcpu)
+{
+       kvmppc_disable_debug_interrupts();
+
+       mtspr(SPRN_IAC1, vcpu->arch.host_iac[0]);
+       mtspr(SPRN_IAC2, vcpu->arch.host_iac[1]);
+       mtspr(SPRN_IAC3, vcpu->arch.host_iac[2]);
+       mtspr(SPRN_IAC4, vcpu->arch.host_iac[3]);
+       mtspr(SPRN_DBCR1, vcpu->arch.host_dbcr1);
+       mtspr(SPRN_DBCR2, vcpu->arch.host_dbcr2);
+       mtspr(SPRN_DBCR0, vcpu->arch.host_dbcr0);
+       mtmsr(vcpu->arch.host_msr);
+}
+
+static void kvmppc_load_guest_debug_registers(struct kvm_vcpu *vcpu)
+{
+       struct kvm_guest_debug *dbg = &vcpu->guest_debug;
+       u32 dbcr0 = 0;
+
+       vcpu->arch.host_msr = mfmsr();
+       kvmppc_disable_debug_interrupts();
+
+       /* Save host debug register state. */
+       vcpu->arch.host_iac[0] = mfspr(SPRN_IAC1);
+       vcpu->arch.host_iac[1] = mfspr(SPRN_IAC2);
+       vcpu->arch.host_iac[2] = mfspr(SPRN_IAC3);
+       vcpu->arch.host_iac[3] = mfspr(SPRN_IAC4);
+       vcpu->arch.host_dbcr0 = mfspr(SPRN_DBCR0);
+       vcpu->arch.host_dbcr1 = mfspr(SPRN_DBCR1);
+       vcpu->arch.host_dbcr2 = mfspr(SPRN_DBCR2);
+
+       /* set registers up for guest */
+
+       if (dbg->bp[0]) {
+               mtspr(SPRN_IAC1, dbg->bp[0]);
+               dbcr0 |= DBCR0_IAC1 | DBCR0_IDM;
+       }
+       if (dbg->bp[1]) {
+               mtspr(SPRN_IAC2, dbg->bp[1]);
+               dbcr0 |= DBCR0_IAC2 | DBCR0_IDM;
+       }
+       if (dbg->bp[2]) {
+               mtspr(SPRN_IAC3, dbg->bp[2]);
+               dbcr0 |= DBCR0_IAC3 | DBCR0_IDM;
+       }
+       if (dbg->bp[3]) {
+               mtspr(SPRN_IAC4, dbg->bp[3]);
+               dbcr0 |= DBCR0_IAC4 | DBCR0_IDM;
+       }
+
+       mtspr(SPRN_DBCR0, dbcr0);
+       mtspr(SPRN_DBCR1, 0);
+       mtspr(SPRN_DBCR2, 0);
+}
+
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+       int i;
+
+       if (vcpu->guest_debug.enabled)
+               kvmppc_load_guest_debug_registers(vcpu);
+
+       /* Mark every guest entry in the shadow TLB entry modified, so that they
+        * will all be reloaded on the next vcpu run (instead of being
+        * demand-faulted). */
+       for (i = 0; i <= tlb_44x_hwater; i++)
+               kvmppc_tlbe_set_modified(vcpu, i);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+       if (vcpu->guest_debug.enabled)
+               kvmppc_restore_host_debug_state(vcpu);
+
+       /* Don't leave guest TLB entries resident when being de-scheduled. */
+       /* XXX It would be nice to differentiate between heavyweight exit and
+        * sched_out here, since we could avoid the TLB flush for heavyweight
+        * exits. */
+       _tlbia();
 }
 
 int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
                                     struct kvm_debug_guest *dbg)
 {
-       return -ENOTSUPP;
+       int i;
+
+       vcpu->guest_debug.enabled = dbg->enabled;
+       if (vcpu->guest_debug.enabled) {
+               for (i=0; i < ARRAY_SIZE(vcpu->guest_debug.bp); i++) {
+                       if (dbg->breakpoints[i].enabled)
+                               vcpu->guest_debug.bp[i] = dbg->breakpoints[i].address;
+                       else
+                               vcpu->guest_debug.bp[i] = 0;
+               }
+       }
+
+       return 0;
 }
 
 static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
index f9837f44ac0bac2c2ba8d6c81b5f9eeb735b431b..75f3267fdc300977f26ac6cc6e2a0db41add6525 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ * Copyright (C) 2008 Mark Nelson, IBM Corp.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  */
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+        .section        ".toc","aw"
+PPC64_CACHES:
+        .tc             ppc64_caches[TC],ppc64_caches
+        .section        ".text"
+
 
 _GLOBAL(copy_4K_page)
-       std     r31,-8(1)
-       std     r30,-16(1)
-       std     r29,-24(1)
-       std     r28,-32(1)
-       std     r27,-40(1)
-       std     r26,-48(1)
-       std     r25,-56(1)
-       std     r24,-64(1)
-       std     r23,-72(1)
-       std     r22,-80(1)
-       std     r21,-88(1)
-       std     r20,-96(1)
-       li      r5,4096/32 - 1
+       li      r5,4096         /* 4K page size */
+BEGIN_FTR_SECTION
+       ld      r10,PPC64_CACHES@toc(r2)
+       lwz     r11,DCACHEL1LOGLINESIZE(r10)    /* log2 of cache line size */
+       lwz     r12,DCACHEL1LINESIZE(r10)       /* get cache line size */
+       li      r9,0
+       srd     r8,r5,r11
+
+       mtctr   r8
+setup:
+       dcbt    r9,r4
+       dcbz    r9,r3
+       add     r9,r9,r12
+       bdnz    setup
+END_FTR_SECTION_IFSET(CPU_FTR_CP_USE_DCBTZ)
        addi    r3,r3,-8
-       li      r12,5
-0:     addi    r5,r5,-24
-       mtctr   r12
-       ld      r22,640(4)
-       ld      r21,512(4)
-       ld      r20,384(4)
-       ld      r11,256(4)
-       ld      r9,128(4)
-       ld      r7,0(4)
-       ld      r25,648(4)
-       ld      r24,520(4)
-       ld      r23,392(4)
-       ld      r10,264(4)
-       ld      r8,136(4)
-       ldu     r6,8(4)
-       cmpwi   r5,24
-1:     std     r22,648(3)
-       std     r21,520(3)
-       std     r20,392(3)
-       std     r11,264(3)
-       std     r9,136(3)
-       std     r7,8(3)
-       ld      r28,648(4)
-       ld      r27,520(4)
-       ld      r26,392(4)
-       ld      r31,264(4)
-       ld      r30,136(4)
-       ld      r29,8(4)
-       std     r25,656(3)
-       std     r24,528(3)
-       std     r23,400(3)
-       std     r10,272(3)
-       std     r8,144(3)
-       std     r6,16(3)
-       ld      r22,656(4)
-       ld      r21,528(4)
-       ld      r20,400(4)
-       ld      r11,272(4)
-       ld      r9,144(4)
-       ld      r7,16(4)
-       std     r28,664(3)
-       std     r27,536(3)
-       std     r26,408(3)
-       std     r31,280(3)
-       std     r30,152(3)
-       stdu    r29,24(3)
-       ld      r25,664(4)
-       ld      r24,536(4)
-       ld      r23,408(4)
-       ld      r10,280(4)
-       ld      r8,152(4)
-       ldu     r6,24(4)
+       srdi    r8,r5,7         /* page is copied in 128 byte strides */
+       addi    r8,r8,-1        /* one stride copied outside loop */
+
+       mtctr   r8
+
+       ld      r5,0(r4)
+       ld      r6,8(r4)
+       ld      r7,16(r4)
+       ldu     r8,24(r4)
+1:     std     r5,8(r3)
+       ld      r9,8(r4)
+       std     r6,16(r3)
+       ld      r10,16(r4)
+       std     r7,24(r3)
+       ld      r11,24(r4)
+       std     r8,32(r3)
+       ld      r12,32(r4)
+       std     r9,40(r3)
+       ld      r5,40(r4)
+       std     r10,48(r3)
+       ld      r6,48(r4)
+       std     r11,56(r3)
+       ld      r7,56(r4)
+       std     r12,64(r3)
+       ld      r8,64(r4)
+       std     r5,72(r3)
+       ld      r9,72(r4)
+       std     r6,80(r3)
+       ld      r10,80(r4)
+       std     r7,88(r3)
+       ld      r11,88(r4)
+       std     r8,96(r3)
+       ld      r12,96(r4)
+       std     r9,104(r3)
+       ld      r5,104(r4)
+       std     r10,112(r3)
+       ld      r6,112(r4)
+       std     r11,120(r3)
+       ld      r7,120(r4)
+       stdu    r12,128(r3)
+       ldu     r8,128(r4)
        bdnz    1b
-       std     r22,648(3)
-       std     r21,520(3)
-       std     r20,392(3)
-       std     r11,264(3)
-       std     r9,136(3)
-       std     r7,8(3)
-       addi    r4,r4,640
-       addi    r3,r3,648
-       bge     0b
-       mtctr   r5
-       ld      r7,0(4)
-       ld      r8,8(4)
-       ldu     r9,16(4)
-3:     ld      r10,8(4)
-       std     r7,8(3)
-       ld      r7,16(4)
-       std     r8,16(3)
-       ld      r8,24(4)
-       std     r9,24(3)
-       ldu     r9,32(4)
-       stdu    r10,32(3)
-       bdnz    3b
-4:     ld      r10,8(4)
-       std     r7,8(3)
-       std     r8,16(3)
-       std     r9,24(3)
-       std     r10,32(3)
-9:     ld      r20,-96(1)
-       ld      r21,-88(1)
-       ld      r22,-80(1)
-       ld      r23,-72(1)
-       ld      r24,-64(1)
-       ld      r25,-56(1)
-       ld      r26,-48(1)
-       ld      r27,-40(1)
-       ld      r28,-32(1)
-       ld      r29,-24(1)
-       ld      r30,-16(1)
-       ld      r31,-8(1)
+
+       std     r5,8(r3)
+       ld      r9,8(r4)
+       std     r6,16(r3)
+       ld      r10,16(r4)
+       std     r7,24(r3)
+       ld      r11,24(r4)
+       std     r8,32(r3)
+       ld      r12,32(r4)
+       std     r9,40(r3)
+       ld      r5,40(r4)
+       std     r10,48(r3)
+       ld      r6,48(r4)
+       std     r11,56(r3)
+       ld      r7,56(r4)
+       std     r12,64(r3)
+       ld      r8,64(r4)
+       std     r5,72(r3)
+       ld      r9,72(r4)
+       std     r6,80(r3)
+       ld      r10,80(r4)
+       std     r7,88(r3)
+       ld      r11,88(r4)
+       std     r8,96(r3)
+       ld      r12,96(r4)
+       std     r9,104(r3)
+       std     r10,112(r3)
+       std     r11,120(r3)
+       std     r12,128(r3)
        blr
index 5d83907f6591dbf9cf68b32dbceaa99ddaf3563e..31734c0969cd28014b226f300f0b1932186ea4e1 100644 (file)
@@ -203,7 +203,7 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
                /*
                 * Set the "dma handle"
                 */
-               *handle = page_to_bus(page);
+               *handle = page_to_phys(page);
 
                do {
                        BUG_ON(!pte_none(*pte));
index 29bc9126241b1d9893acf6d51024a6f6797efa19..03aa98dd9f0a5c0b1a6f564bd9a658d2260620cc 100644 (file)
@@ -4,13 +4,14 @@ obj-y                         := math.o fmr.o lfd.o stfd.o
 obj-$(CONFIG_MATH_EMULATION)   += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
                                        fctiw.o fctiwz.o fdiv.o fdivs.o \
                                        fmadd.o fmadds.o fmsub.o fmsubs.o \
-                                       fmul.o fmuls.o fnabs.o fneg.o types.o \
+                                       fmul.o fmuls.o fnabs.o fneg.o \
                                        fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \
                                        fres.o frsp.o frsqrte.o fsel.o lfs.o \
                                        fsqrt.o fsqrts.o fsub.o fsubs.o \
                                        mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
-                                       mtfsf.o mtfsfi.o stfiwx.o stfs.o \
-                                       udivmodti4.o
+                                       mtfsf.o mtfsfi.o stfiwx.o stfs.o
 
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
+
+EXTRA_CFLAGS = -I. -Iinclude/math-emu -w
diff --git a/arch/powerpc/math-emu/double.h b/arch/powerpc/math-emu/double.h
deleted file mode 100644 (file)
index ffba8b6..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Definitions for IEEE Double Precision
- */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid.  Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_D                (2 * _FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_D                _FP_W_TYPE_SIZE
-#endif
-
-#define _FP_FRACBITS_D         53
-#define _FP_FRACXBITS_D                (_FP_FRACTBITS_D - _FP_FRACBITS_D)
-#define _FP_WFRACBITS_D                (_FP_WORKBITS + _FP_FRACBITS_D)
-#define _FP_WFRACXBITS_D       (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
-#define _FP_EXPBITS_D          11
-#define _FP_EXPBIAS_D          1023
-#define _FP_EXPMAX_D           2047
-
-#define _FP_QNANBIT_D          \
-       ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE))
-#define _FP_IMPLBIT_D          \
-       ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE))
-#define _FP_OVERFLOW_D         \
-       ((_FP_W_TYPE)1 << (_FP_WFRACBITS_D % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_D
-{
-  double flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign  : 1;
-    unsigned exp   : _FP_EXPBITS_D;
-    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
-    unsigned frac0 : _FP_W_TYPE_SIZE;
-#else
-    unsigned frac0 : _FP_W_TYPE_SIZE;
-    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
-    unsigned exp   : _FP_EXPBITS_D;
-    unsigned sign  : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X)           _FP_DECL(2,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
-#define FP_PACK_RAW_D(val,X)   _FP_PACK_RAW_2(D,val,X)
-
-#define FP_UNPACK_D(X,val)             \
-  do {                                 \
-    _FP_UNPACK_RAW_2(D,X,val);         \
-    _FP_UNPACK_CANONICAL(D,2,X);       \
-  } while (0)
-
-#define FP_PACK_D(val,X)               \
-  do {                                 \
-    _FP_PACK_CANONICAL(D,2,X);         \
-    _FP_PACK_RAW_2(D,val,X);           \
-  } while (0)
-
-#define FP_NEG_D(R,X)          _FP_NEG(D,2,R,X)
-#define FP_ADD_D(R,X,Y)                _FP_ADD(D,2,R,X,Y)
-#define FP_SUB_D(R,X,Y)                _FP_SUB(D,2,R,X,Y)
-#define FP_MUL_D(R,X,Y)                _FP_MUL(D,2,R,X,Y)
-#define FP_DIV_D(R,X,Y)                _FP_DIV(D,2,R,X,Y)
-#define FP_SQRT_D(R,X)         _FP_SQRT(D,2,R,X)
-
-#define FP_CMP_D(r,X,Y,un)     _FP_CMP(D,2,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y)     _FP_CMP_EQ(D,2,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,2,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,2,X,r,rs,rt)
-
-#else
-
-union _FP_UNION_D
-{
-  double flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign : 1;
-    unsigned exp  : _FP_EXPBITS_D;
-    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-#else
-    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-    unsigned exp  : _FP_EXPBITS_D;
-    unsigned sign : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X)           _FP_DECL(1,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
-#define FP_PACK_RAW_D(val,X)   _FP_PACK_RAW_1(D,val,X)
-
-#define FP_UNPACK_D(X,val)             \
-  do {                                 \
-    _FP_UNPACK_RAW_1(D,X,val);         \
-    _FP_UNPACK_CANONICAL(D,1,X);       \
-  } while (0)
-
-#define FP_PACK_D(val,X)               \
-  do {                                 \
-    _FP_PACK_CANONICAL(D,1,X);         \
-    _FP_PACK_RAW_1(D,val,X);           \
-  } while (0)
-
-#define FP_NEG_D(R,X)          _FP_NEG(D,1,R,X)
-#define FP_ADD_D(R,X,Y)                _FP_ADD(D,1,R,X,Y)
-#define FP_SUB_D(R,X,Y)                _FP_SUB(D,1,R,X,Y)
-#define FP_MUL_D(R,X,Y)                _FP_MUL(D,1,R,X,Y)
-#define FP_DIV_D(R,X,Y)                _FP_DIV(D,1,R,X,Y)
-#define FP_SQRT_D(R,X)         _FP_SQRT(D,1,R,X)
-
-/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
-   the target machine.  */
-
-#define FP_CMP_D(r,X,Y,un)     _FP_CMP(D,1,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y)     _FP_CMP_EQ(D,1,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,1,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,1,X,r,rs,rt)
-
-#endif /* W_TYPE_SIZE < 64 */
index 7befbbf2c3323c5803bbaa6d5da5ac3d3ad6f433..04d3b4aa32cedb9ab75801aaa6b21a5019118a98 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fadd(void *frD, void *frA, void *frB)
@@ -11,28 +12,28 @@ fadd(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
        printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
 #endif
 
-       if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
-
        FP_ADD_D(R, A, B);
 
 #ifdef DEBUG
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 2b346b38b4805298d12c74edb7e63d77d9ecb68c..5930f40a868743dfb0683350bc2f2e789aa6d9ea 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fadds(void *frD, void *frA, void *frB)
@@ -12,28 +13,27 @@ fadds(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
-       int ret = 0;
+       FP_DECL_EX;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
        printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
 #endif
 
-       if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
-
        FP_ADD_D(R, A, B);
 
 #ifdef DEBUG
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 36d689044c63ad4e0a42a5084241017dfbfd50c9..b5dc4498cd71023dfdc237f79415b1043901f36b 100644 (file)
@@ -2,14 +2,16 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
 {
        FP_DECL_D(A);
        FP_DECL_D(B);
+       FP_DECL_EX;
        int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
        long cmp;
        int ret = 0;
@@ -18,8 +20,8 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
        printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
index 53d93894f2a692d00ebaac71d4014bb8e0fc4356..d4fb1babc6ada6abdaa069934f9f9f48ff73f136 100644 (file)
@@ -2,14 +2,16 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
 {
        FP_DECL_D(A);
        FP_DECL_D(B);
+       FP_DECL_EX;
        int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
        long cmp;
 
@@ -17,8 +19,8 @@ fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
        printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
index fcd7a95e021dcb5b9711115c57830ceeefaeefef..f694440ddc003a276ef5630f4ad3d5b259a18cc4 100644 (file)
@@ -2,16 +2,18 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fctiw(u32 *frD, void *frB)
 {
        FP_DECL_D(B);
+       FP_DECL_EX;
        unsigned int r;
 
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(B, frB);
        FP_TO_INT_D(r, B, 32, 1);
        frD[1] = r;
 
index 1514d59e146ea77bf103d37539da4c435bd4fcb8..71e782fd4fe35b13a2d1e1b77d6f8b7f32855738 100644 (file)
@@ -2,13 +2,15 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fctiwz(u32 *frD, void *frB)
 {
        FP_DECL_D(B);
+       FP_DECL_EX;
        u32 fpscr;
        unsigned int r;
 
@@ -16,7 +18,7 @@ fctiwz(u32 *frD, void *frB)
        __FPU_FPSCR &= ~(3);
        __FPU_FPSCR |= FP_RND_ZERO;
 
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(B, frB);
        FP_TO_INT_D(r, B, 32, 1);
        frD[1] = r;
 
index 18a20fe396b09f4d660ccb61ae2d6869fac15eeb..2db15097d98e9ba65ad049023561bdf397d26054 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fdiv(void *frD, void *frA, void *frB)
@@ -11,14 +12,15 @@ fdiv(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -49,5 +51,7 @@ fdiv(void *frD, void *frA, void *frB)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 24feed689c3581665796b6577eae5d9f988324a0..797f6a9a20b53f405687828c556ca526235ef201 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fdivs(void *frD, void *frA, void *frB)
@@ -12,14 +13,15 @@ fdivs(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -51,5 +53,7 @@ fdivs(void *frD, void *frA, void *frB)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index dedb465fdc68b5baa1fdc772286a37745fa2cc15..925313aa6f82b38b73307d0bfea6936d3021917e 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fmadd(void *frD, void *frA, void *frB, void *frC)
@@ -13,15 +14,16 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -44,5 +46,7 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 6bbb56d5502cb53c073fc3dea8e0f6ee0148bd1c..aea80ef79399d3630d5574a534a49e64d978810a 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fmadds(void *frD, void *frA, void *frB, void *frC)
@@ -14,15 +15,16 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -45,5 +47,7 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index f311e2c7e67e50fcc6a54f13a3534b68bf2f9ff9..a644d525fca66442f0c2322b52fe0d9c6d1d4f5c 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fmsub(void *frD, void *frA, void *frB, void *frC)
@@ -13,15 +14,16 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -47,5 +49,7 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 81a716d3ee2e6859c1ed7435dc8ca23cfed9368e..2fdeeb9bb569690b5c5e67adca34f2f3d51f68da 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fmsubs(void *frD, void *frA, void *frB, void *frC)
@@ -14,15 +15,16 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -48,5 +50,7 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 2f3d32784a04ac69e7fc5e8a13a97f0a163bbede..391fd17d3440fd85c1637480857ffc386c219e6c 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fmul(void *frD, void *frA, void *frB)
@@ -11,14 +12,15 @@ fmul(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
@@ -38,5 +40,7 @@ fmul(void *frD, void *frA, void *frB)
               R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 962b5883f784b0bb460f0f5448d4edcf737c42c9..2d3ec5f7da20f4c20a255e4eca8b804f2a47a913 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fmuls(void *frD, void *frA, void *frB)
@@ -12,14 +13,15 @@ fmuls(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
@@ -39,5 +41,7 @@ fmuls(void *frD, void *frA, void *frB)
               R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 8cf7827c4fb5949b142e9e7a5ab086bc7dd8cf01..2497b86494e5425ac64fe8355b91a0c2827afb4a 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fnmadd(void *frD, void *frA, void *frB, void *frC)
@@ -13,15 +14,16 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -47,5 +49,7 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index f1c4f0f0d807cf10db3e826b827a026d64a5b6a5..ee9d71e0b376f7578a9ebd25c0b8ef12746d4e72 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fnmadds(void *frD, void *frA, void *frB, void *frC)
@@ -14,15 +15,16 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -48,5 +50,7 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 98944e6e260181ca8c52ceaba4ebcb2df7ce2eff..3885a77acc9324919f89ee5aef1d6c842d4c1b17 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fnmsub(void *frD, void *frA, void *frB, void *frC)
@@ -13,15 +14,16 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -50,5 +52,7 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index b20f4eb63fb96ae7bd5fe156e4f41cd4fbe5a881..f835dfeb0fd1f3b8e8cdafec9d8cf581f6025b4b 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fnmsubs(void *frD, void *frA, void *frB, void *frC)
@@ -14,15 +15,16 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(B);
        FP_DECL_D(C);
        FP_DECL_D(T);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
-       __FP_UNPACK_D(C, frC);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
+       FP_UNPACK_DP(C, frC);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -51,5 +53,7 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 724ccbc0468e03332218be05b3f67093626e1cfb..ddcc14664b1a23a7116b95d9883cb92b4b7604ae 100644 (file)
@@ -2,24 +2,28 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 frsp(void *frD, void *frB)
 {
        FP_DECL_D(B);
+       FP_DECL_EX;
 
 #ifdef DEBUG
        printk("%s: D %p, B %p\n", __func__, frD, frB);
 #endif
 
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
 #endif
 
-       return __FP_PACK_DS(frD, B);
+       __FP_PACK_DS(frD, B);
+
+       return FP_CUR_EXCEPTIONS;
 }
index ecb5f28eb1f3f0f2701e8eac842202d216889362..1b0c144980320a87d5982d052419301ba15a2777 100644 (file)
@@ -2,19 +2,21 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fsel(u32 *frD, void *frA, u32 *frB, u32 *frC)
 {
        FP_DECL_D(A);
+       FP_DECL_EX;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
 #endif
 
-       __FP_UNPACK_D(A, frA);
+       FP_UNPACK_DP(A, frA);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
index 38ec2b752e9d1d65e7f7af874ee2c984e9d7caa7..3e90072693a0befdd1661000bfe629f1074ae9d0 100644 (file)
@@ -2,21 +2,23 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fsqrt(void *frD, void *frB)
 {
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frB);
 #endif
 
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
@@ -33,5 +35,7 @@ fsqrt(void *frD, void *frB)
        printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 335263e06ee54d56cbe2cd7d296e9a9695cff846..2843be986e2e97aa1a09f2ad8e5e7eb46cdd9852 100644 (file)
@@ -2,22 +2,24 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fsqrts(void *frD, void *frB)
 {
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frB);
 #endif
 
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
@@ -34,5 +36,7 @@ fsqrts(void *frD, void *frB)
        printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 208d20fc52a51bb6656203e70b8e8ef38313c8e9..78b09446a0e14f61e5288aba797df5ca87c523de 100644 (file)
@@ -2,8 +2,9 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
 
 int
 fsub(void *frD, void *frA, void *frB)
@@ -11,14 +12,15 @@ fsub(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -37,5 +39,7 @@ fsub(void *frD, void *frA, void *frB)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_D(frD, R));
+       __FP_PACK_D(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 0e61b808c44b88df221e6ca16fb49d6e5c3827e6..d3bf90863cf29ba0abec9285c0c386785b4b20c6 100644 (file)
@@ -2,9 +2,10 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 fsubs(void *frD, void *frA, void *frB)
@@ -12,14 +13,15 @@ fsubs(void *frD, void *frA, void *frB)
        FP_DECL_D(A);
        FP_DECL_D(B);
        FP_DECL_D(R);
+       FP_DECL_EX;
        int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
 #endif
 
-       __FP_UNPACK_D(A, frA);
-       __FP_UNPACK_D(B, frB);
+       FP_UNPACK_DP(A, frA);
+       FP_UNPACK_DP(B, frB);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -38,5 +40,7 @@ fsubs(void *frD, void *frA, void *frB)
        printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return (ret | __FP_PACK_DS(frD, R));
+       __FP_PACK_DS(frD, R);
+
+       return FP_CUR_EXCEPTIONS;
 }
index 6ec90b57c61a5c3a11d1e4d5735852138860dcd6..79ac76d596c31f30279bb678a600be120308d750 100644 (file)
@@ -2,8 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "sfp-machine.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/double.h>
 
 int
 lfd(void *frD, void *ea)
index 6f18ebe3a7ff510ec6aa7a8edd72fbc474e179ab..434ed27be8dbaee074943bc80b6141c773d2ecf6 100644 (file)
@@ -2,15 +2,17 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 lfs(void *frD, void *ea)
 {
        FP_DECL_D(R);
        FP_DECL_S(A);
+       FP_DECL_EX;
        float f;
 
 #ifdef DEBUG
@@ -20,7 +22,7 @@ lfs(void *frD, void *ea)
        if (copy_from_user(&f, ea, sizeof(float)))
                return -EFAULT;
 
-       __FP_UNPACK_S(A, &f);
+       FP_UNPACK_S(A, f);
 
 #ifdef DEBUG
        printk("A: %ld %lu %ld (%ld) [%08lx]\n", A_s, A_f, A_e, A_c,
@@ -33,5 +35,12 @@ lfs(void *frD, void *ea)
        printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
 #endif
 
-       return __FP_PACK_D(frD, R);
+       if (R_c == FP_CLS_NAN) {
+               R_e = _FP_EXPMAX_D;
+               _FP_PACK_RAW_2_P(D, frD, R);
+       } else {
+               __FP_PACK_D(frD, R);
+       }
+
+       return 0;
 }
index 29e545e0272e62abd85ec7cf3d4933b882ce6da8..164d55935bd82ce7903d0e6717ad2cc029d422bf 100644 (file)
@@ -8,8 +8,8 @@
 #include <asm/uaccess.h>
 #include <asm/reg.h>
 
-#include "sfp-machine.h"
-#include "double.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/double.h>
 
 #define FLOATFUNC(x)   extern int x(void *, void *, void *, void *)
 
@@ -168,6 +168,8 @@ record_exception(struct pt_regs *regs, int eflag)
                        fpscr |= FPSCR_ZX;
                if (eflag & EFLAG_INEXACT)
                        fpscr |= FPSCR_XX;
+               if (eflag & EFLAG_INVALID)
+                       fpscr |= FPSCR_VX;
                if (eflag & EFLAG_VXSNAN)
                        fpscr |= FPSCR_VXSNAN;
                if (eflag & EFLAG_VXISI)
@@ -188,7 +190,7 @@ record_exception(struct pt_regs *regs, int eflag)
                        fpscr |= FPSCR_VXCVI;
        }
 
-       fpscr &= ~(FPSCR_VX);
+//     fpscr &= ~(FPSCR_VX);
        if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
                     FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
                     FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
index 41ba247faf897e1d35dad1728c144b89f7e18573..e948d5708e2b722041c712810964bb95fa0f197e 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mcrfs(u32 *ccr, u32 crfD, u32 crfS)
index b0e2106e6eb6d71e10a8bf678b8f97e72248b274..5526cf96ede5e0e33b462f09f44b8c8177c636c9 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mffs(u32 *frD)
index d3062350ea215535cf60d999ff181e95197be6ed..bc985585bca8afd65c6b964184a30e74b4376ede 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mtfsb0(int crbD)
index 2e948704b56ea0259aa00ba8b6619d97f923c545..fe6ed5ac85b331cf75e14c695996a6733ff03a14 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mtfsb1(int crbD)
index 48014d8e3af1efa9e7c701c59140ec75f658180f..dbce92e4f046d9295c057f4fb3408f52b17990cc 100644 (file)
@@ -2,12 +2,14 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mtfsf(unsigned int FM, u32 *frB)
 {
        u32 mask;
+       u32 fpscr;
 
        if (FM == 0)
                return 0;
@@ -37,6 +39,22 @@ mtfsf(unsigned int FM, u32 *frB)
        __FPU_FPSCR &= ~(mask);
        __FPU_FPSCR |= (frB[1] & mask);
 
+       __FPU_FPSCR &= ~(FPSCR_VX);
+       if (__FPU_FPSCR & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
+                    FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
+                    FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
+               __FPU_FPSCR |= FPSCR_VX;
+
+       fpscr = __FPU_FPSCR;
+       fpscr &= ~(FPSCR_FEX);
+       if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) ||
+           ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) ||
+           ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) ||
+           ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) ||
+           ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE)))
+               fpscr |= FPSCR_FEX;
+       __FPU_FPSCR = fpscr;
+
 #ifdef DEBUG
        printk("%s: %02x %p: %08lx\n", __func__, FM, frB, __FPU_FPSCR);
 #endif
index 031e200935493c49be352a410127a57476853faf..fd2acc26813b7f1a240f80427075bc43a52b0c53 100644 (file)
@@ -2,7 +2,8 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
 
 int
 mtfsfi(unsigned int crfD, unsigned int IMM)
diff --git a/arch/powerpc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h
deleted file mode 100644 (file)
index c92fa95..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Basic one-word fraction declaration and manipulation.
- */
-
-#define _FP_FRAC_DECL_1(X)     _FP_W_TYPE X##_f
-#define _FP_FRAC_COPY_1(D,S)   (D##_f = S##_f)
-#define _FP_FRAC_SET_1(X,I)    (X##_f = I)
-#define _FP_FRAC_HIGH_1(X)     (X##_f)
-#define _FP_FRAC_LOW_1(X)      (X##_f)
-#define _FP_FRAC_WORD_1(X,w)   (X##_f)
-
-#define _FP_FRAC_ADDI_1(X,I)   (X##_f += I)
-#define _FP_FRAC_SLL_1(X,N)                    \
-  do {                                         \
-    if (__builtin_constant_p(N) && (N) == 1)   \
-      X##_f += X##_f;                          \
-    else                                       \
-      X##_f <<= (N);                           \
-  } while (0)
-#define _FP_FRAC_SRL_1(X,N)    (X##_f >>= N)
-
-/* Right shift with sticky-lsb.  */
-#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
-
-#define __FP_FRAC_SRS_1(X,N,sz)                                                \
-   (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1               \
-                    ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
-
-#define _FP_FRAC_ADD_1(R,X,Y)  (R##_f = X##_f + Y##_f)
-#define _FP_FRAC_SUB_1(R,X,Y)  (R##_f = X##_f - Y##_f)
-#define _FP_FRAC_CLZ_1(z, X)   __FP_CLZ(z, X##_f)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_1(X)     ((_FP_WS_TYPE)X##_f < 0)
-#define _FP_FRAC_ZEROP_1(X)    (X##_f == 0)
-#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_1(X, Y)    (X##_f == Y##_f)
-#define _FP_FRAC_GE_1(X, Y)    (X##_f >= Y##_f)
-#define _FP_FRAC_GT_1(X, Y)    (X##_f > Y##_f)
-
-#define _FP_ZEROFRAC_1         0
-#define _FP_MINFRAC_1          1
-
-/*
- * Unpack the raw bits of a native fp value.  Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_1(fs, X, val)                           \
-  do {                                                         \
-    union _FP_UNION_##fs _flo; _flo.flt = (val);               \
-                                                               \
-    X##_f = _flo.bits.frac;                                    \
-    X##_e = _flo.bits.exp;                                     \
-    X##_s = _flo.bits.sign;                                    \
-  } while (0)
-
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_1(fs, val, X)                             \
-  do {                                                         \
-    union _FP_UNION_##fs _flo;                                 \
-                                                               \
-    _flo.bits.frac = X##_f;                                    \
-    _flo.bits.exp  = X##_e;                                    \
-    _flo.bits.sign = X##_s;                                    \
-                                                               \
-    (val) = _flo.flt;                                          \
-  } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
-   multiplication immediately.  */
-
-#define _FP_MUL_MEAT_1_imm(fs, R, X, Y)                                        \
-  do {                                                                 \
-    R##_f = X##_f * Y##_f;                                             \
-    /* Normalize since we know where the msb of the multiplicands      \
-       were (bit B), we know that the msb of the of the product is     \
-       at either 2B or 2B-1.  */                                       \
-    _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);     \
-  } while (0)
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
-
-#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit)                         \
-  do {                                                                 \
-    _FP_W_TYPE _Z_f0, _Z_f1;                                           \
-    doit(_Z_f1, _Z_f0, X##_f, Y##_f);                                  \
-    /* Normalize since we know where the msb of the multiplicands      \
-       were (bit B), we know that the msb of the of the product is     \
-       at either 2B or 2B-1.  */                                       \
-    _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);    \
-    R##_f = _Z_f0;                                                     \
-  } while (0)
-
-/* Finally, a simple widening multiply algorithm.  What fun!  */
-
-#define _FP_MUL_MEAT_1_hard(fs, R, X, Y)                               \
-  do {                                                                 \
-    _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;         \
-                                                                       \
-    /* split the words in half */                                      \
-    _xh = X##_f >> (_FP_W_TYPE_SIZE/2);                                        \
-    _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);                \
-    _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);                                        \
-    _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);                \
-                                                                       \
-    /* multiply the pieces */                                          \
-    _z_f0 = _xl * _yl;                                                 \
-    _a_f0 = _xh * _yl;                                                 \
-    _a_f1 = _xl * _yh;                                                 \
-    _z_f1 = _xh * _yh;                                                 \
-                                                                       \
-    /* reassemble into two full words */                               \
-    if ((_a_f0 += _a_f1) < _a_f1)                                      \
-      _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);                   \
-    _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);                              \
-    _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);                              \
-    _FP_FRAC_ADD_2(_z, _z, _a);                                                \
-                                                                       \
-    /* normalize */                                                    \
-    _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs);  \
-    R##_f = _z_f0;                                                     \
-  } while (0)
-
-
-/*
- * Division algorithms:
- */
-
-/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
-   division immediately.  Give this macro either _FP_DIV_HELP_imm for
-   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
-   choose will depend on what the compiler does with divrem4.  */
-
-#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)          \
-  do {                                                 \
-    _FP_W_TYPE _q, _r;                                 \
-    X##_f <<= (X##_f < Y##_f                           \
-              ? R##_e--, _FP_WFRACBITS_##fs            \
-              : _FP_WFRACBITS_##fs - 1);               \
-    doit(_q, _r, X##_f, Y##_f);                                \
-    R##_f = _q | (_r != 0);                            \
-  } while (0)
-
-/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
-   that may be useful in this situation.  This first is for a primitive
-   that requires normalization, the second for one that does not.  Look
-   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
-
-#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)                          \
-  do {                                                                 \
-    _FP_W_TYPE _nh, _nl, _q, _r;                                       \
-                                                                       \
-    /* Normalize Y -- i.e. make the most significant bit set.  */      \
-    Y##_f <<= _FP_WFRACXBITS_##fs - 1;                                 \
-                                                                       \
-    /* Shift X op correspondingly high, that is, up one full word.  */ \
-    if (X##_f <= Y##_f)                                                        \
-      {                                                                        \
-       _nl = 0;                                                        \
-       _nh = X##_f;                                                    \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       R##_e++;                                                        \
-       _nl = X##_f << (_FP_W_TYPE_SIZE-1);                             \
-       _nh = X##_f >> 1;                                               \
-      }                                                                        \
-                                                                       \
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);                               \
-    R##_f = _q | (_r != 0);                                            \
-  } while (0)
-
-#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)               \
-  do {                                                 \
-    _FP_W_TYPE _nh, _nl, _q, _r;                       \
-    if (X##_f < Y##_f)                                 \
-      {                                                        \
-       R##_e--;                                        \
-       _nl = X##_f << _FP_WFRACBITS_##fs;              \
-       _nh = X##_f >> _FP_WFRACXBITS_##fs;             \
-      }                                                        \
-    else                                               \
-      {                                                        \
-       _nl = X##_f << (_FP_WFRACBITS_##fs - 1);        \
-       _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);       \
-      }                                                        \
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);               \
-    R##_f = _q | (_r != 0);                            \
-  } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
-
-#define _FP_SQRT_MEAT_1(R, S, T, X, q)                 \
-  do {                                                 \
-    while (q)                                          \
-      {                                                        \
-        T##_f = S##_f + q;                             \
-        if (T##_f <= X##_f)                            \
-          {                                            \
-            S##_f = T##_f + q;                         \
-            X##_f -= T##_f;                            \
-            R##_f += q;                                        \
-          }                                            \
-        _FP_FRAC_SLL_1(X, 1);                          \
-        q >>= 1;                                       \
-      }                                                        \
-  } while (0)
-
-/*
- * Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)       (r = X##_f)
-#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)    (X##_f = r)
-
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S)                              \
-  do {                                                                 \
-    D##_f = S##_f;                                                     \
-    if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)                     \
-      _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),     \
-                    _FP_WFRACBITS_##sfs);                              \
-    else                                                               \
-      D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;             \
-  } while (0)
diff --git a/arch/powerpc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h
deleted file mode 100644 (file)
index 7d6f17c..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Basic two-word fraction declaration and manipulation.
- */
-
-#define _FP_FRAC_DECL_2(X)     _FP_W_TYPE X##_f0, X##_f1
-#define _FP_FRAC_COPY_2(D,S)   (D##_f0 = S##_f0, D##_f1 = S##_f1)
-#define _FP_FRAC_SET_2(X,I)    __FP_FRAC_SET_2(X, I)
-#define _FP_FRAC_HIGH_2(X)     (X##_f1)
-#define _FP_FRAC_LOW_2(X)      (X##_f0)
-#define _FP_FRAC_WORD_2(X,w)   (X##_f##w)
-
-#define _FP_FRAC_SLL_2(X,N)                                            \
-  do {                                                                 \
-    if ((N) < _FP_W_TYPE_SIZE)                                         \
-      {                                                                        \
-        if (__builtin_constant_p(N) && (N) == 1)                       \
-          {                                                            \
-            X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);  \
-            X##_f0 += X##_f0;                                          \
-          }                                                            \
-        else                                                           \
-          {                                                            \
-           X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
-           X##_f0 <<= (N);                                             \
-         }                                                             \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE);                     \
-       X##_f0 = 0;                                                     \
-      }                                                                        \
-  } while (0)
-
-#define _FP_FRAC_SRL_2(X,N)                                            \
-  do {                                                                 \
-    if ((N) < _FP_W_TYPE_SIZE)                                         \
-      {                                                                        \
-       X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N));     \
-       X##_f1 >>= (N);                                                 \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE);                     \
-       X##_f1 = 0;                                                     \
-      }                                                                        \
-  } while (0)
-
-/* Right shift with sticky-lsb.  */
-#define _FP_FRAC_SRS_2(X,N,sz)                                         \
-  do {                                                                 \
-    if ((N) < _FP_W_TYPE_SIZE)                                         \
-      {                                                                        \
-       X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) |   \
-                 (__builtin_constant_p(N) && (N) == 1                  \
-                  ? X##_f0 & 1                                         \
-                  : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0));        \
-       X##_f1 >>= (N);                                                 \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |                   \
-                 (((X##_f1 << (2 * _FP_W_TYPE_SIZE - (N))) |           \
-                  X##_f0) != 0));                                      \
-       X##_f1 = 0;                                                     \
-      }                                                                        \
-  } while (0)
-
-#define _FP_FRAC_ADDI_2(X,I) \
-  __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
-
-#define _FP_FRAC_ADD_2(R,X,Y) \
-  __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_SUB_2(R,X,Y) \
-  __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_CLZ_2(R,X)    \
-  do {                         \
-    if (X##_f1)                        \
-      __FP_CLZ(R,X##_f1);      \
-    else                       \
-    {                          \
-      __FP_CLZ(R,X##_f0);      \
-      R += _FP_W_TYPE_SIZE;    \
-    }                          \
-  } while(0)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_2(X)     ((_FP_WS_TYPE)X##_f1 < 0)
-#define _FP_FRAC_ZEROP_2(X)    ((X##_f1 | X##_f0) == 0)
-#define _FP_FRAC_OVERP_2(fs,X) (X##_f1 & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_2(X, Y)    (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
-#define _FP_FRAC_GT_2(X, Y)    \
-  ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
-#define _FP_FRAC_GE_2(X, Y)    \
-  ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
-
-#define _FP_ZEROFRAC_2         0, 0
-#define _FP_MINFRAC_2          0, 1
-
-/*
- * Internals
- */
-
-#define __FP_FRAC_SET_2(X,I1,I0)       (X##_f0 = I0, X##_f1 = I1)
-
-#define __FP_CLZ_2(R, xh, xl)  \
-  do {                         \
-    if (xh)                    \
-      __FP_CLZ(R,xl);          \
-    else                       \
-    {                          \
-      __FP_CLZ(R,xl);          \
-      R += _FP_W_TYPE_SIZE;    \
-    }                          \
-  } while(0)
-
-#if 0
-
-#ifndef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) \
-  (xh += ((xl += i) < i))
-#endif
-#ifndef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
-  (rh = xh + yh + ((rl = xl + yl) < xl))
-#endif
-#ifndef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
-  (rh = xh - yh - ((rl = xl - yl) > xl))
-#endif
-
-#else
-
-#undef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i)    add_ssaaaa(xh, xl, xh, xl, 0, i)
-#undef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2                        add_ssaaaa
-#undef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2                        sub_ddmmss
-
-#endif
-
-/*
- * Unpack the raw bits of a native fp value.  Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_2(fs, X, val)                   \
-  do {                                                 \
-    union _FP_UNION_##fs _flo; _flo.flt = (val);       \
-                                                       \
-    X##_f0 = _flo.bits.frac0;                          \
-    X##_f1 = _flo.bits.frac1;                          \
-    X##_e  = _flo.bits.exp;                            \
-    X##_s  = _flo.bits.sign;                           \
-  } while (0)
-
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_2(fs, val, X)                     \
-  do {                                                 \
-    union _FP_UNION_##fs _flo;                         \
-                                                       \
-    _flo.bits.frac0 = X##_f0;                          \
-    _flo.bits.frac1 = X##_f1;                          \
-    _flo.bits.exp   = X##_e;                           \
-    _flo.bits.sign  = X##_s;                           \
-                                                       \
-    (val) = _flo.flt;                                  \
-  } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
-
-#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit)                         \
-  do {                                                                 \
-    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);     \
-                                                                       \
-    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
-    doit(_b_f1, _b_f0, X##_f0, Y##_f1);                                        \
-    doit(_c_f1, _c_f0, X##_f1, Y##_f0);                                        \
-    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
-                                                                       \
-    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),       \
-                   _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),        \
-                   0, _b_f1, _b_f0, 0,                                 \
-                   _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),        \
-                   _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));       \
-    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),       \
-                   _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),        \
-                   0, _c_f1, _c_f0, 0,                                 \
-                   _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),        \
-                   _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));       \
-                                                                       \
-    /* Normalize since we know where the msb of the multiplicands      \
-       were (bit B), we know that the msb of the of the product is     \
-       at either 2B or 2B-1.  */                                       \
-    _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);    \
-    R##_f0 = _FP_FRAC_WORD_4(_z,0);                                    \
-    R##_f1 = _FP_FRAC_WORD_4(_z,1);                                    \
-  } while (0)
-
-/* This next macro appears to be totally broken. Fortunately nowhere
- * seems to use it :-> The problem is that we define _z[4] but
- * then use it in _FP_FRAC_SRS_4, which will attempt to access
- * _z_f[n] which will cause an error. The fix probably involves
- * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998
- */
-#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y)                                        \
-  do {                                                                 \
-    _FP_W_TYPE _x[2], _y[2], _z[4];                                    \
-    _x[0] = X##_f0; _x[1] = X##_f1;                                    \
-    _y[0] = Y##_f0; _y[1] = Y##_f1;                                    \
-                                                                       \
-    mpn_mul_n(_z, _x, _y, 2);                                          \
-                                                                       \
-    /* Normalize since we know where the msb of the multiplicands      \
-       were (bit B), we know that the msb of the of the product is     \
-       at either 2B or 2B-1.  */                                       \
-    _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs);    \
-    R##_f0 = _z[0];                                                    \
-    R##_f1 = _z[1];                                                    \
-  } while (0)
-
-
-/*
- * Division algorithms:
- * This seems to be giving me difficulties -- PMM
- * Look, NetBSD seems to be able to comment algorithms. Can't you?
- * I've thrown printks at the problem.
- * This now appears to work, but I still don't really know why.
- * Also, I don't think the result is properly normalised...
- */
-
-#define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y)                            \
-  do {                                                                 \
-    extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],       \
-                              _FP_W_TYPE n1, _FP_W_TYPE n0,            \
-                              _FP_W_TYPE d1, _FP_W_TYPE d0);           \
-    _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0;               \
-    _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0;                             \
-    _FP_W_TYPE _rmem[2], _qmem[2];                                     \
-    /* I think this check is to ensure that the result is normalised.   \
-     * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in         \
-     * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y.      \
-     * In this case we tweak things. (this is based on comments in      \
-     * the NetBSD FPU emulation code. )                                 \
-     * We know X,Y are normalised because we ensure this as part of     \
-     * the unpacking process. -- PMM                                    \
-     */                                                                        \
-    if (_FP_FRAC_GT_2(X, Y))                                           \
-      {                                                                        \
-/*     R##_e++; */                                                     \
-       _n_f3 = X##_f1 >> 1;                                            \
-       _n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;          \
-       _n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1);                        \
-       _n_f0 = 0;                                                      \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       R##_e--;                                                        \
-       _n_f3 = X##_f1;                                                 \
-       _n_f2 = X##_f0;                                                 \
-       _n_f1 = _n_f0 = 0;                                              \
-      }                                                                        \
-                                                                       \
-    /* Normalize, i.e. make the most significant bit of the            \
-       denominator set.  CHANGED: - 1 to nothing -- PMM */             \
-    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */);                   \
-                                                                       \
-    /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4    \
-       primitive snagged from libgcc2.c.  */                           \
-                                                                       \
-    _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1);             \
-    _q_f1 = _qmem[0];                                                  \
-    umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0);                            \
-    _r_f1 = _rmem[0];                                                  \
-    _r_f0 = _n_f1;                                                     \
-    if (_FP_FRAC_GT_2(_m, _r))                                         \
-      {                                                                        \
-       _q_f1--;                                                        \
-       _FP_FRAC_ADD_2(_r, _r, Y);                                      \
-       if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))              \
-         {                                                             \
-           _q_f1--;                                                    \
-           _FP_FRAC_ADD_2(_r, _r, Y);                                  \
-         }                                                             \
-      }                                                                        \
-    _FP_FRAC_SUB_2(_r, _r, _m);                                                \
-                                                                       \
-    _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1);             \
-    _q_f0 = _qmem[0];                                                  \
-    umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0);                            \
-    _r_f1 = _rmem[0];                                                  \
-    _r_f0 = _n_f0;                                                     \
-    if (_FP_FRAC_GT_2(_m, _r))                                         \
-      {                                                                        \
-       _q_f0--;                                                        \
-       _FP_FRAC_ADD_2(_r, _r, Y);                                      \
-       if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))              \
-         {                                                             \
-           _q_f0--;                                                    \
-           _FP_FRAC_ADD_2(_r, _r, Y);                                  \
-         }                                                             \
-      }                                                                        \
-    _FP_FRAC_SUB_2(_r, _r, _m);                                                \
-                                                                       \
-    R##_f1 = _q_f1;                                                    \
-    R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0);                           \
-    /* adjust so answer is normalized again. I'm not sure what the     \
-     * final sz param should be. In practice it's never used since      \
-     * N is 1 which is always going to be < _FP_W_TYPE_SIZE...         \
-     */                                                                        \
-    /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs); */                      \
-  } while (0)
-
-
-#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y)                                        \
-  do {                                                                 \
-    _FP_W_TYPE _x[4], _y[2], _z[4];                                    \
-    _y[0] = Y##_f0; _y[1] = Y##_f1;                                    \
-    _x[0] = _x[3] = 0;                                                 \
-    if (_FP_FRAC_GT_2(X, Y))                                           \
-      {                                                                        \
-       R##_e++;                                                        \
-       _x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) |        \
-                X##_f1 >> (_FP_W_TYPE_SIZE -                           \
-                           (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE)));      \
-       _x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE);          \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       _x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) |          \
-                X##_f1 >> (_FP_W_TYPE_SIZE -                           \
-                           (_FP_WFRACBITS - _FP_W_TYPE_SIZE)));        \
-       _x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE);            \
-      }                                                                        \
-                                                                       \
-    (void) mpn_divrem (_z, 0, _x, 4, _y, 2);                           \
-    R##_f1 = _z[1];                                                    \
-    R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0);                           \
-  } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
-
-#define _FP_SQRT_MEAT_2(R, S, T, X, q)                 \
-  do {                                                 \
-    while (q)                                          \
-      {                                                        \
-        T##_f1 = S##_f1 + q;                           \
-        if (T##_f1 <= X##_f1)                          \
-          {                                            \
-            S##_f1 = T##_f1 + q;                       \
-            X##_f1 -= T##_f1;                          \
-            R##_f1 += q;                               \
-          }                                            \
-        _FP_FRAC_SLL_2(X, 1);                          \
-        q >>= 1;                                       \
-      }                                                        \
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);                \
-    while (q)                                          \
-      {                                                        \
-        T##_f0 = S##_f0 + q;                           \
-        T##_f1 = S##_f1;                               \
-        if (T##_f1 < X##_f1 ||                                 \
-            (T##_f1 == X##_f1 && T##_f0 < X##_f0))     \
-          {                                            \
-            S##_f0 = T##_f0 + q;                       \
-            if (((_FP_WS_TYPE)T##_f0) < 0 &&           \
-                ((_FP_WS_TYPE)S##_f0) >= 0)            \
-              S##_f1++;                                        \
-            _FP_FRAC_SUB_2(X, X, T);                   \
-            R##_f0 += q;                               \
-          }                                            \
-        _FP_FRAC_SLL_2(X, 1);                          \
-        q >>= 1;                                       \
-      }                                                        \
-  } while (0)
-
-
-/*
- * Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_2(r, X, rsize)       \
-  do {                                         \
-    if (rsize <= _FP_W_TYPE_SIZE)              \
-      r = X##_f0;                              \
-    else                                       \
-      {                                                \
-       r = X##_f1;                             \
-       r <<= _FP_W_TYPE_SIZE;                  \
-       r += X##_f0;                            \
-      }                                                \
-  } while (0)
-
-#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)                            \
-  do {                                                                 \
-    X##_f0 = r;                                                                \
-    X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);    \
-  } while (0)
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S)                              \
-  do {                                                                 \
-    _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
-                  _FP_WFRACBITS_##sfs);                                \
-    D##_f = S##_f0;                                                    \
-  } while (0)
-
-#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S)                              \
-  do {                                                                 \
-    D##_f0 = S##_f;                                                    \
-    D##_f1 = 0;                                                                \
-    _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
-  } while (0)
-
diff --git a/arch/powerpc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h
deleted file mode 100644 (file)
index c9ae626..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Basic four-word fraction declaration and manipulation.
- *
- * When adding quadword support for 32 bit machines, we need
- * to be a little careful as double multiply uses some of these
- * macros: (in op-2.h)
- * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4,
- * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4
- * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use
- * _FP_FRAC_DECL_4: it appears to be broken and is not used
- * anywhere anyway. )
- *
- * I've now fixed all the macros that were here from the sparc64 code.
- * [*none* of the shift macros were correct!] -- PMM 02/1998
- *
- * The only quadword stuff that remains to be coded is:
- * 1) the conversion to/from ints, which requires
- * that we check (in op-common.h) that the following do the right thing
- * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt)
- * 2) multiply, divide and sqrt, which require:
- * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q),
- * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to
- * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h.
- * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for
- * these; they are used nowhere else. ]
- */
-
-#define _FP_FRAC_DECL_4(X)     _FP_W_TYPE X##_f[4]
-#define _FP_FRAC_COPY_4(D,S)                   \
-  (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],   \
-   D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
-/* The _FP_FRAC_SET_n(X,I) macro is intended for use with another
- * macro such as _FP_ZEROFRAC_n which returns n comma separated values.
- * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3)
- * which just assigns the In values to the array X##_f[].
- * This is why the number of parameters doesn't appear to match
- * at first glance...      -- PMM
- */
-#define _FP_FRAC_SET_4(X,I)    __FP_FRAC_SET_4(X, I)
-#define _FP_FRAC_HIGH_4(X)     (X##_f[3])
-#define _FP_FRAC_LOW_4(X)      (X##_f[0])
-#define _FP_FRAC_WORD_4(X,w)   (X##_f[w])
-
-#define _FP_FRAC_SLL_4(X,N)                                            \
-  do {                                                                 \
-    _FP_I_TYPE _up, _down, _skip, _i;                                  \
-    _skip = (N) / _FP_W_TYPE_SIZE;                                     \
-    _up = (N) % _FP_W_TYPE_SIZE;                                       \
-    _down = _FP_W_TYPE_SIZE - _up;                                     \
-    for (_i = 3; _i > _skip; --_i)                                     \
-      X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down; \
-/* bugfixed: was X##_f[_i] <<= _up;  -- PMM 02/1998 */                  \
-    X##_f[_i] = X##_f[0] << _up;                                       \
-    for (--_i; _i >= 0; --_i)                                          \
-      X##_f[_i] = 0;                                                   \
-  } while (0)
-
-/* This one was broken too */
-#define _FP_FRAC_SRL_4(X,N)                                            \
-  do {                                                                 \
-    _FP_I_TYPE _up, _down, _skip, _i;                                  \
-    _skip = (N) / _FP_W_TYPE_SIZE;                                     \
-    _down = (N) % _FP_W_TYPE_SIZE;                                     \
-    _up = _FP_W_TYPE_SIZE - _down;                                     \
-    for (_i = 0; _i < 3-_skip; ++_i)                                   \
-      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \
-    X##_f[_i] = X##_f[3] >> _down;                                     \
-    for (++_i; _i < 4; ++_i)                                           \
-      X##_f[_i] = 0;                                                   \
-  } while (0)
-
-
-/* Right shift with sticky-lsb.
- * What this actually means is that we do a standard right-shift,
- * but that if any of the bits that fall off the right hand side
- * were one then we always set the LSbit.
- */
-#define _FP_FRAC_SRS_4(X,N,size)                                       \
-  do {                                                                 \
-    _FP_I_TYPE _up, _down, _skip, _i;                                  \
-    _FP_W_TYPE _s;                                                     \
-    _skip = (N) / _FP_W_TYPE_SIZE;                                     \
-    _down = (N) % _FP_W_TYPE_SIZE;                                     \
-    _up = _FP_W_TYPE_SIZE - _down;                                     \
-    for (_s = _i = 0; _i < _skip; ++_i)                                        \
-      _s |= X##_f[_i];                                                 \
-    _s |= X##_f[_i] << _up;                                            \
-/* s is now != 0 if we want to set the LSbit */                         \
-    for (_i = 0; _i < 3-_skip; ++_i)                                   \
-      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \
-    X##_f[_i] = X##_f[3] >> _down;                                     \
-    for (++_i; _i < 4; ++_i)                                           \
-      X##_f[_i] = 0;                                                   \
-    /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
-    X##_f[0] |= (_s != 0);                                              \
-  } while (0)
-
-#define _FP_FRAC_ADD_4(R,X,Y)                                          \
-  __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],              \
-                 X##_f[3], X##_f[2], X##_f[1], X##_f[0],               \
-                 Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_SUB_4(R,X,Y)                                           \
-  __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],              \
-                 X##_f[3], X##_f[2], X##_f[1], X##_f[0],               \
-                 Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_ADDI_4(X,I)                                            \
-  __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
-
-#define _FP_ZEROFRAC_4  0,0,0,0
-#define _FP_MINFRAC_4   0,0,0,1
-
-#define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
-#define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
-#define _FP_FRAC_OVERP_4(fs,X)  (X##_f[0] & _FP_OVERFLOW_##fs)
-
-#define _FP_FRAC_EQ_4(X,Y)                              \
- (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]          \
-  && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
-
-#define _FP_FRAC_GT_4(X,Y)                              \
- (X##_f[3] > Y##_f[3] ||                                \
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
-    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])       \
-   ))                                                   \
-  ))                                                    \
- )
-
-#define _FP_FRAC_GE_4(X,Y)                              \
- (X##_f[3] > Y##_f[3] ||                                \
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
-    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])      \
-   ))                                                   \
-  ))                                                    \
- )
-
-
-#define _FP_FRAC_CLZ_4(R,X)             \
-  do {                                  \
-    if (X##_f[3])                       \
-    {                                   \
-        __FP_CLZ(R,X##_f[3]);           \
-    }                                   \
-    else if (X##_f[2])                  \
-    {                                   \
-        __FP_CLZ(R,X##_f[2]);           \
-        R += _FP_W_TYPE_SIZE;           \
-    }                                   \
-    else if (X##_f[1])                  \
-    {                                   \
-        __FP_CLZ(R,X##_f[2]);           \
-        R += _FP_W_TYPE_SIZE*2;         \
-    }                                   \
-    else                                \
-    {                                   \
-        __FP_CLZ(R,X##_f[0]);           \
-        R += _FP_W_TYPE_SIZE*3;         \
-    }                                   \
-  } while(0)
-
-
-#define _FP_UNPACK_RAW_4(fs, X, val)                            \
-  do {                                                          \
-    union _FP_UNION_##fs _flo; _flo.flt = (val);               \
-    X##_f[0] = _flo.bits.frac0;                                 \
-    X##_f[1] = _flo.bits.frac1;                                 \
-    X##_f[2] = _flo.bits.frac2;                                 \
-    X##_f[3] = _flo.bits.frac3;                                 \
-    X##_e  = _flo.bits.exp;                                     \
-    X##_s  = _flo.bits.sign;                                    \
-  } while (0)
-
-#define _FP_PACK_RAW_4(fs, val, X)                              \
-  do {                                                          \
-    union _FP_UNION_##fs _flo;                                 \
-    _flo.bits.frac0 = X##_f[0];                                 \
-    _flo.bits.frac1 = X##_f[1];                                 \
-    _flo.bits.frac2 = X##_f[2];                                 \
-    _flo.bits.frac3 = X##_f[3];                                 \
-    _flo.bits.exp   = X##_e;                                    \
-    _flo.bits.sign  = X##_s;                                    \
-    (val) = _flo.flt;                                          \
-  } while (0)
-
-
-/*
- * Internals
- */
-
-#define __FP_FRAC_SET_4(X,I3,I2,I1,I0)                                 \
-  (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
-
-#ifndef __FP_FRAC_ADD_4
-#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)   \
-  do {                                                         \
-    int _c1, _c2, _c3;                                         \
-    r0 = x0 + y0;                                              \
-    _c1 = r0 < x0;                                             \
-    r1 = x1 + y1;                                              \
-    _c2 = r1 < x1;                                             \
-    r1 += _c1;                                                 \
-    _c2 |= r1 < _c1;                                           \
-    r2 = x2 + y2;                                              \
-    _c3 = r2 < x2;                                             \
-    r2 += _c2;                                                 \
-    _c3 |= r2 < _c2;                                           \
-    r3 = x3 + y3 + _c3;                                                \
-  } while (0)
-#endif
-
-#ifndef __FP_FRAC_SUB_4
-#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)   \
-  do {                                                         \
-    int _c1, _c2, _c3;                                         \
-    r0 = x0 - y0;                                              \
-    _c1 = r0 > x0;                                             \
-    r1 = x1 - y1;                                              \
-    _c2 = r1 > x1;                                             \
-    r1 -= _c1;                                                 \
-    _c2 |= r1 > _c1;                                           \
-    r2 = x2 - y2;                                              \
-    _c3 = r2 > x2;                                             \
-    r2 -= _c2;                                                 \
-    _c3 |= r2 > _c2;                                           \
-    r3 = x3 - y3 - _c3;                                                \
-  } while (0)
-#endif
-
-#ifndef __FP_FRAC_ADDI_4
-/* I always wanted to be a lisp programmer :-> */
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)                                 \
-  (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2)))
-#endif
-
-/* Convert FP values between word sizes. This appears to be more
- * complicated than I'd have expected it to be, so these might be
- * wrong... These macros are in any case somewhat bogus because they
- * use information about what various FRAC_n variables look like
- * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
- * the ones in op-2.h and op-1.h.
- */
-#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
-                        _FP_WFRACBITS_##sfs);                           \
-     D##_f = S##_f[0];                                                   \
-  } while (0)
-
-#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
-                        _FP_WFRACBITS_##sfs);                           \
-     D##_f0 = S##_f[0];                                                  \
-     D##_f1 = S##_f[1];                                                  \
-  } while (0)
-
-/* Assembly/disassembly for converting to/from integral types.
- * No shifting or overflow handled here.
- */
-/* Put the FP value X into r, which is an integer of size rsize. */
-#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)                                \
-  do {                                                                  \
-    if (rsize <= _FP_W_TYPE_SIZE)                                       \
-      r = X##_f[0];                                                     \
-    else if (rsize <= 2*_FP_W_TYPE_SIZE)                                \
-    {                                                                   \
-      r = X##_f[1];                                                     \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[0];                                                    \
-    }                                                                   \
-    else                                                                \
-    {                                                                   \
-      /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
-      /* and int == 4words as a single case.                         */ \
-      r = X##_f[3];                                                     \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[2];                                                    \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[1];                                                    \
-      r <<= _FP_W_TYPE_SIZE;                                            \
-      r += X##_f[0];                                                    \
-    }                                                                   \
-  } while (0)
-
-/* "No disassemble Number Five!" */
-/* move an integer of size rsize into X's fractional part. We rely on
- * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
- * having to mask the values we store into it.
- */
-#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)                             \
-  do {                                                                  \
-    X##_f[0] = r;                                                       \
-    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);   \
-    X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
-    X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
-  } while (0)
-
-#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     D##_f[0] = S##_f;                                                  \
-     D##_f[1] = D##_f[2] = D##_f[3] = 0;                                \
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
-   } while (0)
-
-#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)                               \
-   do {                                                                 \
-     D##_f[0] = S##_f0;                                                 \
-     D##_f[1] = S##_f1;                                                 \
-     D##_f[2] = D##_f[3] = 0;                                           \
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
-   } while (0)
-
-/* FIXME! This has to be written */
-#define _FP_SQRT_MEAT_4(R, S, T, X, q)
diff --git a/arch/powerpc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h
deleted file mode 100644 (file)
index afb82b6..0000000
+++ /dev/null
@@ -1,688 +0,0 @@
-#define _FP_DECL(wc, X)                        \
-  _FP_I_TYPE X##_c, X##_s, X##_e;      \
-  _FP_FRAC_DECL_##wc(X)
-
-/*
- * Finish truely unpacking a native fp value by classifying the kind
- * of fp value and normalizing both the exponent and the fraction.
- */
-
-#define _FP_UNPACK_CANONICAL(fs, wc, X)                                        \
-do {                                                                   \
-  switch (X##_e)                                                       \
-  {                                                                    \
-  default:                                                             \
-    _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs;                         \
-    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);                                        \
-    X##_e -= _FP_EXPBIAS_##fs;                                         \
-    X##_c = FP_CLS_NORMAL;                                             \
-    break;                                                             \
-                                                                       \
-  case 0:                                                              \
-    if (_FP_FRAC_ZEROP_##wc(X))                                                \
-      X##_c = FP_CLS_ZERO;                                             \
-    else                                                               \
-      {                                                                        \
-       /* a denormalized number */                                     \
-       _FP_I_TYPE _shift;                                              \
-       _FP_FRAC_CLZ_##wc(_shift, X);                                   \
-       _shift -= _FP_FRACXBITS_##fs;                                   \
-       _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));                    \
-       X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;                         \
-       X##_c = FP_CLS_NORMAL;                                          \
-      }                                                                        \
-    break;                                                             \
-                                                                       \
-  case _FP_EXPMAX_##fs:                                                        \
-    if (_FP_FRAC_ZEROP_##wc(X))                                                \
-      X##_c = FP_CLS_INF;                                              \
-    else                                                               \
-      /* we don't differentiate between signaling and quiet nans */    \
-      X##_c = FP_CLS_NAN;                                              \
-    break;                                                             \
-  }                                                                    \
-} while (0)
-
-
-/*
- * Before packing the bits back into the native fp result, take care
- * of such mundane things as rounding and overflow.  Also, for some
- * kinds of fp values, the original parts may not have been fully
- * extracted -- but that is ok, we can regenerate them now.
- */
-
-#define _FP_PACK_CANONICAL(fs, wc, X)                          \
-({int __ret = 0;                                               \
-  switch (X##_c)                                               \
-  {                                                            \
-  case FP_CLS_NORMAL:                                          \
-    X##_e += _FP_EXPBIAS_##fs;                                 \
-    if (X##_e > 0)                                             \
-      {                                                                \
-       __ret |= _FP_ROUND(wc, X);                              \
-       if (_FP_FRAC_OVERP_##wc(fs, X))                         \
-         {                                                     \
-           _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1));             \
-           X##_e++;                                            \
-         }                                                     \
-       else                                                    \
-         _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                   \
-       if (X##_e >= _FP_EXPMAX_##fs)                           \
-         {                                                     \
-           /* overflow to infinity */                          \
-           X##_e = _FP_EXPMAX_##fs;                            \
-           _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
-            __ret |= EFLAG_OVERFLOW;                           \
-         }                                                     \
-      }                                                                \
-    else                                                       \
-      {                                                                \
-       /* we've got a denormalized number */                   \
-       X##_e = -X##_e + 1;                                     \
-       if (X##_e <= _FP_WFRACBITS_##fs)                        \
-         {                                                     \
-           _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
-           _FP_FRAC_SLL_##wc(X, 1);                            \
-           if (_FP_FRAC_OVERP_##wc(fs, X))                     \
-             {                                                 \
-               X##_e = 1;                                      \
-               _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
-             }                                                 \
-           else                                                \
-             {                                                 \
-               X##_e = 0;                                      \
-               _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1);           \
-                __ret |= EFLAG_UNDERFLOW;                      \
-             }                                                 \
-         }                                                     \
-       else                                                    \
-         {                                                     \
-           /* underflow to zero */                             \
-           X##_e = 0;                                          \
-           _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);            \
-            __ret |= EFLAG_UNDERFLOW;                          \
-         }                                                     \
-      }                                                                \
-    break;                                                     \
-                                                               \
-  case FP_CLS_ZERO:                                            \
-    X##_e = 0;                                                 \
-    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                   \
-    break;                                                     \
-                                                               \
-  case FP_CLS_INF:                                             \
-    X##_e = _FP_EXPMAX_##fs;                                   \
-    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                   \
-    break;                                                     \
-                                                               \
-  case FP_CLS_NAN:                                             \
-    X##_e = _FP_EXPMAX_##fs;                                   \
-    if (!_FP_KEEPNANFRACP)                                     \
-      {                                                                \
-       _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);                 \
-       X##_s = 0;                                              \
-      }                                                                \
-    else                                                       \
-      _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs;               \
-    break;                                                     \
-  }                                                            \
-  __ret;                                                       \
-})
-
-
-/*
- * Main addition routine.  The input values should be cooked.
- */
-
-#define _FP_ADD(fs, wc, R, X, Y)                                            \
-do {                                                                        \
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))                                    \
-  {                                                                         \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):                        \
-    {                                                                       \
-      /* shift the smaller number so that its exponent matches the larger */ \
-      _FP_I_TYPE diff = X##_e - Y##_e;                                      \
-                                                                            \
-      if (diff < 0)                                                         \
-       {                                                                    \
-         diff = -diff;                                                      \
-         if (diff <= _FP_WFRACBITS_##fs)                                    \
-           _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);                  \
-         else if (!_FP_FRAC_ZEROP_##wc(X))                                  \
-           _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                          \
-         else                                                               \
-           _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                         \
-         R##_e = Y##_e;                                                     \
-       }                                                                    \
-      else                                                                  \
-       {                                                                    \
-         if (diff > 0)                                                      \
-           {                                                                \
-             if (diff <= _FP_WFRACBITS_##fs)                                \
-               _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);              \
-             else if (!_FP_FRAC_ZEROP_##wc(Y))                              \
-               _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                      \
-             else                                                           \
-               _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc);                     \
-           }                                                                \
-         R##_e = X##_e;                                                     \
-       }                                                                    \
-                                                                            \
-      R##_c = FP_CLS_NORMAL;                                                \
-                                                                            \
-      if (X##_s == Y##_s)                                                   \
-       {                                                                    \
-         R##_s = X##_s;                                                     \
-         _FP_FRAC_ADD_##wc(R, X, Y);                                        \
-         if (_FP_FRAC_OVERP_##wc(fs, R))                                    \
-           {                                                                \
-             _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
-             R##_e++;                                                       \
-           }                                                                \
-       }                                                                    \
-      else                                                                  \
-       {                                                                    \
-         R##_s = X##_s;                                                     \
-         _FP_FRAC_SUB_##wc(R, X, Y);                                        \
-         if (_FP_FRAC_ZEROP_##wc(R))                                        \
-           {                                                                \
-             /* return an exact zero */                                     \
-             if (FP_ROUNDMODE == FP_RND_MINF)                               \
-               R##_s |= Y##_s;                                              \
-             else                                                           \
-               R##_s &= Y##_s;                                              \
-             R##_c = FP_CLS_ZERO;                                           \
-           }                                                                \
-         else                                                               \
-           {                                                                \
-             if (_FP_FRAC_NEGP_##wc(R))                                     \
-               {                                                            \
-                 _FP_FRAC_SUB_##wc(R, Y, X);                                \
-                 R##_s = Y##_s;                                             \
-               }                                                            \
-                                                                            \
-             /* renormalize after subtraction */                            \
-             _FP_FRAC_CLZ_##wc(diff, R);                                    \
-             diff -= _FP_WFRACXBITS_##fs;                                   \
-             if (diff)                                                      \
-               {                                                            \
-                 R##_e -= diff;                                             \
-                 _FP_FRAC_SLL_##wc(R, diff);                                \
-               }                                                            \
-           }                                                                \
-       }                                                                    \
-      break;                                                                \
-    }                                                                       \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):                              \
-    _FP_CHOOSENAN(fs, wc, R, X, Y);                                         \
-    break;                                                                  \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):                          \
-    R##_e = X##_e;                                                          \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):                           \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):                              \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                                     \
-    _FP_FRAC_COPY_##wc(R, X);                                               \
-    R##_s = X##_s;                                                          \
-    R##_c = X##_c;                                                          \
-    break;                                                                  \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):                          \
-    R##_e = Y##_e;                                                          \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):                           \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):                              \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                                     \
-    _FP_FRAC_COPY_##wc(R, Y);                                               \
-    R##_s = Y##_s;                                                          \
-    R##_c = Y##_c;                                                          \
-    break;                                                                  \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):                              \
-    if (X##_s != Y##_s)                                                             \
-      {                                                                             \
-       /* +INF + -INF => NAN */                                             \
-       _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                              \
-       R##_s = X##_s ^ Y##_s;                                               \
-       R##_c = FP_CLS_NAN;                                                  \
-       break;                                                               \
-      }                                                                             \
-    /* FALLTHRU */                                                          \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):                           \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                                     \
-    R##_s = X##_s;                                                          \
-    R##_c = FP_CLS_INF;                                                             \
-    break;                                                                  \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):                           \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                                     \
-    R##_s = Y##_s;                                                          \
-    R##_c = FP_CLS_INF;                                                             \
-    break;                                                                  \
-                                                                            \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):                            \
-    /* make sure the sign is correct */                                             \
-    if (FP_ROUNDMODE == FP_RND_MINF)                                        \
-      R##_s = X##_s | Y##_s;                                                \
-    else                                                                    \
-      R##_s = X##_s & Y##_s;                                                \
-    R##_c = FP_CLS_ZERO;                                                    \
-    break;                                                                  \
-                                                                            \
-  default:                                                                  \
-    abort();                                                                \
-  }                                                                         \
-} while (0)
-
-
-/*
- * Main negation routine.  FIXME -- when we care about setting exception
- * bits reliably, this will not do.  We should examine all of the fp classes.
- */
-
-#define _FP_NEG(fs, wc, R, X)          \
-  do {                                 \
-    _FP_FRAC_COPY_##wc(R, X);          \
-    R##_c = X##_c;                     \
-    R##_e = X##_e;                     \
-    R##_s = 1 ^ X##_s;                 \
-  } while (0)
-
-
-/*
- * Main multiplication routine.  The input values should be cooked.
- */
-
-#define _FP_MUL(fs, wc, R, X, Y)                       \
-do {                                                   \
-  R##_s = X##_s ^ Y##_s;                               \
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))               \
-  {                                                    \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):   \
-    R##_c = FP_CLS_NORMAL;                             \
-    R##_e = X##_e + Y##_e + 1;                         \
-                                                       \
-    _FP_MUL_MEAT_##fs(R,X,Y);                          \
-                                                       \
-    if (_FP_FRAC_OVERP_##wc(fs, R))                    \
-      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);     \
-    else                                               \
-      R##_e--;                                         \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):         \
-    _FP_CHOOSENAN(fs, wc, R, X, Y);                    \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):      \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):         \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                \
-    R##_s = X##_s;                                     \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):         \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):      \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):     \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):       \
-    _FP_FRAC_COPY_##wc(R, X);                          \
-    R##_c = X##_c;                                     \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):      \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):         \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                \
-    R##_s = Y##_s;                                     \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):      \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):     \
-    _FP_FRAC_COPY_##wc(R, Y);                          \
-    R##_c = Y##_c;                                     \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                \
-    R##_c = FP_CLS_NAN;                                        \
-    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
-    break;                                             \
-                                                       \
-  default:                                             \
-    abort();                                           \
-  }                                                    \
-} while (0)
-
-
-/*
- * Main division routine.  The input values should be cooked.
- */
-
-#define _FP_DIV(fs, wc, R, X, Y)                       \
-do {                                                   \
-  R##_s = X##_s ^ Y##_s;                               \
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))               \
-  {                                                    \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):   \
-    R##_c = FP_CLS_NORMAL;                             \
-    R##_e = X##_e - Y##_e;                             \
-                                                       \
-    _FP_DIV_MEAT_##fs(R,X,Y);                          \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):         \
-    _FP_CHOOSENAN(fs, wc, R, X, Y);                    \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):      \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):         \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):                \
-    R##_s = X##_s;                                     \
-    _FP_FRAC_COPY_##wc(R, X);                          \
-    R##_c = X##_c;                                     \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):      \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):         \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):                \
-    R##_s = Y##_s;                                     \
-    _FP_FRAC_COPY_##wc(R, Y);                          \
-    R##_c = Y##_c;                                     \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):      \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):                \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):     \
-    R##_c = FP_CLS_ZERO;                               \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):     \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):                \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):      \
-    R##_c = FP_CLS_INF;                                        \
-    break;                                             \
-                                                       \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):         \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):       \
-    R##_c = FP_CLS_NAN;                                        \
-    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
-    break;                                             \
-                                                       \
-  default:                                             \
-    abort();                                           \
-  }                                                    \
-} while (0)
-
-
-/*
- * Main differential comparison routine.  The inputs should be raw not
- * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
- */
-
-#define _FP_CMP(fs, wc, ret, X, Y, un)                                 \
-  do {                                                                 \
-    /* NANs are unordered */                                           \
-    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))          \
-       || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))       \
-      {                                                                        \
-       ret = un;                                                       \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-        int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;     \
-        int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;     \
-                                                                       \
-       if (__x_zero && __y_zero)                                       \
-         ret = 0;                                                      \
-       else if (__x_zero)                                              \
-         ret = Y##_s ? 1 : -1;                                         \
-       else if (__y_zero)                                              \
-         ret = X##_s ? -1 : 1;                                         \
-       else if (X##_s != Y##_s)                                        \
-         ret = X##_s ? -1 : 1;                                         \
-       else if (X##_e > Y##_e)                                         \
-         ret = X##_s ? -1 : 1;                                         \
-       else if (X##_e < Y##_e)                                         \
-         ret = X##_s ? 1 : -1;                                         \
-       else if (_FP_FRAC_GT_##wc(X, Y))                                \
-         ret = X##_s ? -1 : 1;                                         \
-       else if (_FP_FRAC_GT_##wc(Y, X))                                \
-         ret = X##_s ? 1 : -1;                                         \
-       else                                                            \
-         ret = 0;                                                      \
-      }                                                                        \
-  } while (0)
-
-
-/* Simplification for strict equality.  */
-
-#define _FP_CMP_EQ(fs, wc, ret, X, Y)                                    \
-  do {                                                                   \
-    /* NANs are unordered */                                             \
-    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))            \
-       || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))         \
-      {                                                                          \
-       ret = 1;                                                          \
-      }                                                                          \
-    else                                                                 \
-      {                                                                          \
-       ret = !(X##_e == Y##_e                                            \
-               && _FP_FRAC_EQ_##wc(X, Y)                                 \
-               && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
-      }                                                                          \
-  } while (0)
-
-/*
- * Main square root routine.  The input value should be cooked.
- */
-
-#define _FP_SQRT(fs, wc, R, X)                                         \
-do {                                                                   \
-    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);                      \
-    _FP_W_TYPE q;                                                      \
-    switch (X##_c)                                                     \
-    {                                                                  \
-    case FP_CLS_NAN:                                                   \
-       R##_s = 0;                                                      \
-       R##_c = FP_CLS_NAN;                                             \
-       _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                        \
-       break;                                                          \
-    case FP_CLS_INF:                                                   \
-       if (X##_s)                                                      \
-         {                                                             \
-           R##_s = 0;                                                  \
-           R##_c = FP_CLS_NAN; /* sNAN */                              \
-         }                                                             \
-       else                                                            \
-         {                                                             \
-           R##_s = 0;                                                  \
-           R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */                 \
-         }                                                             \
-       break;                                                          \
-    case FP_CLS_ZERO:                                                  \
-       R##_s = X##_s;                                                  \
-       R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */                      \
-       break;                                                          \
-    case FP_CLS_NORMAL:                                                        \
-       R##_s = 0;                                                      \
-        if (X##_s)                                                     \
-          {                                                            \
-           R##_c = FP_CLS_NAN; /* sNAN */                              \
-           break;                                                      \
-          }                                                            \
-       R##_c = FP_CLS_NORMAL;                                          \
-        if (X##_e & 1)                                                 \
-          _FP_FRAC_SLL_##wc(X, 1);                                     \
-        R##_e = X##_e >> 1;                                            \
-        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);                       \
-        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);                       \
-        q = _FP_OVERFLOW_##fs;                                         \
-        _FP_FRAC_SLL_##wc(X, 1);                                       \
-        _FP_SQRT_MEAT_##wc(R, S, T, X, q);                             \
-        _FP_FRAC_SRL_##wc(R, 1);                                       \
-    }                                                                  \
-  } while (0)
-
-/*
- * Convert from FP to integer
- */
-
-/* "When a NaN, infinity, large positive argument >= 2147483648.0, or
- * large negative argument <= -2147483649.0 is converted to an integer,
- * the invalid_current bit...should be set and fp_exception_IEEE_754 should
- * be raised. If the floating point invalid trap is disabled, no trap occurs
- * and a numerical result is generated: if the sign bit of the operand
- * is 0, the result is 2147483647; if the sign bit of the operand is 1,
- * the result is -2147483648."
- * Similarly for conversion to extended ints, except that the boundaries
- * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and
- * -2^63 for s=1.
- * -- SPARC Architecture Manual V9, Appendix B, which specifies how
- * SPARCs resolve implementation dependencies in the IEEE-754 spec.
- * I don't believe that the code below follows this. I'm not even sure
- * it's right!
- * It doesn't cope with needing to convert to an n bit integer when there
- * is no n bit integer type. Fortunately gcc provides long long so this
- * isn't a problem for sparc32.
- * I have, however, fixed its NaN handling to conform as above.
- *         -- PMM 02/1998
- * NB: rsigned is not 'is r declared signed?' but 'should the value stored
- * in r be signed or unsigned?'. r is always(?) declared unsigned.
- * Comments below are mine, BTW -- PMM
- */
-#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                       \
-  do {                                                                 \
-    switch (X##_c)                                                     \
-      {                                                                        \
-      case FP_CLS_NORMAL:                                              \
-       if (X##_e < 0)                                                  \
-         {                                                             \
-         /* case FP_CLS_NAN: see above! */                             \
-         case FP_CLS_ZERO:                                             \
-           r = 0;                                                      \
-         }                                                             \
-       else if (X##_e >= rsize - (rsigned != 0))                       \
-         {     /* overflow */                                          \
-         case FP_CLS_NAN:                                              \
-          case FP_CLS_INF:                                             \
-           if (rsigned)                                                \
-             {                                                         \
-               r = 1;                                                  \
-               r <<= rsize - 1;                                        \
-               r -= 1 - X##_s;                                         \
-             }                                                         \
-           else                                                        \
-             {                                                         \
-               r = 0;                                                  \
-               if (!X##_s)                                             \
-                 r = ~r;                                               \
-             }                                                         \
-         }                                                             \
-       else                                                            \
-         {                                                             \
-           if (_FP_W_TYPE_SIZE*wc < rsize)                             \
-             {                                                         \
-               _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                    \
-               r <<= X##_e - _FP_WFRACBITS_##fs;                       \
-             }                                                         \
-           else                                                        \
-             {                                                         \
-               if (X##_e >= _FP_WFRACBITS_##fs)                        \
-                 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\
-               else                                                    \
-                 _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\
-               _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                    \
-             }                                                         \
-           if (rsigned && X##_s)                                       \
-             r = -r;                                                   \
-         }                                                             \
-       break;                                                          \
-      }                                                                        \
-  } while (0)
-
-#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                       \
-  do {                                                                 \
-    if (r)                                                             \
-      {                                                                        \
-       X##_c = FP_CLS_NORMAL;                                          \
-                                                                       \
-       if ((X##_s = (r < 0)))                                          \
-         r = -r;                                                       \
-       /* Note that `r' is now considered unsigned, so we don't have   \
-          to worry about the single signed overflow case.  */          \
-                                                                       \
-       if (rsize <= _FP_W_TYPE_SIZE)                                   \
-         __FP_CLZ(X##_e, r);                                           \
-       else                                                            \
-         __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE),         \
-                    (_FP_W_TYPE)r);                                    \
-       if (rsize < _FP_W_TYPE_SIZE)                                    \
-               X##_e -= (_FP_W_TYPE_SIZE - rsize);                     \
-       X##_e = rsize - X##_e - 1;                                      \
-                                                                       \
-       if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)    \
-         __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize);      \
-       r &= ~((_FP_W_TYPE)1 << X##_e);                                 \
-       _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize);       \
-       _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));         \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       X##_c = FP_CLS_ZERO, X##_s = 0;                                 \
-      }                                                                        \
-  } while (0)
-
-
-#define FP_CONV(dfs,sfs,dwc,swc,D,S)                   \
-  do {                                                 \
-    _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);       \
-    D##_e = S##_e;                                     \
-    D##_c = S##_c;                                     \
-    D##_s = S##_s;                                     \
-  } while (0)
-
-/*
- * Helper primitives.
- */
-
-/* Count leading zeros in a word.  */
-
-#ifndef __FP_CLZ
-#if _FP_W_TYPE_SIZE < 64
-/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
-#define __FP_CLZ(r, x)                         \
-  do {                                         \
-    _FP_W_TYPE _t = (x);                       \
-    r = _FP_W_TYPE_SIZE - 1;                   \
-    if (_t > 0xffff) r -= 16;                  \
-    if (_t > 0xffff) _t >>= 16;                        \
-    if (_t > 0xff) r -= 8;                     \
-    if (_t > 0xff) _t >>= 8;                   \
-    if (_t & 0xf0) r -= 4;                     \
-    if (_t & 0xf0) _t >>= 4;                   \
-    if (_t & 0xc) r -= 2;                      \
-    if (_t & 0xc) _t >>= 2;                    \
-    if (_t & 0x2) r -= 1;                      \
-  } while (0)
-#else /* not _FP_W_TYPE_SIZE < 64 */
-#define __FP_CLZ(r, x)                         \
-  do {                                         \
-    _FP_W_TYPE _t = (x);                       \
-    r = _FP_W_TYPE_SIZE - 1;                   \
-    if (_t > 0xffffffff) r -= 32;              \
-    if (_t > 0xffffffff) _t >>= 32;            \
-    if (_t > 0xffff) r -= 16;                  \
-    if (_t > 0xffff) _t >>= 16;                        \
-    if (_t > 0xff) r -= 8;                     \
-    if (_t > 0xff) _t >>= 8;                   \
-    if (_t & 0xf0) r -= 4;                     \
-    if (_t & 0xf0) _t >>= 4;                   \
-    if (_t & 0xc) r -= 2;                      \
-    if (_t & 0xc) _t >>= 2;                    \
-    if (_t & 0x2) r -= 1;                      \
-  } while (0)
-#endif /* not _FP_W_TYPE_SIZE < 64 */
-#endif /* ndef __FP_CLZ */
-
-#define _FP_DIV_HELP_imm(q, r, n, d)           \
-  do {                                         \
-    q = n / d, r = n % d;                      \
-  } while (0)
-
diff --git a/arch/powerpc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h
deleted file mode 100644 (file)
index 4b17d83..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Machine-dependent software floating-point definitions.  PPC version.
-   Copyright (C) 1997 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-   Actually, this is a PPC (32bit) version, written based on the
-   i386, sparc, and sparc64 versions, by me,
-   Peter Maydell (pmaydell@chiark.greenend.org.uk).
-   Comments are by and large also mine, although they may be inaccurate.
-
-   In picking out asm fragments I've gone with the lowest common
-   denominator, which also happens to be the hardware I have :->
-   That is, a SPARC without hardware multiply and divide.
- */
-
-/* basic word size definitions */
-#define _FP_W_TYPE_SIZE                32
-#define _FP_W_TYPE             unsigned long
-#define _FP_WS_TYPE            signed long
-#define _FP_I_TYPE             long
-
-#define __ll_B                 ((UWtype) 1 << (W_TYPE_SIZE / 2))
-#define __ll_lowpart(t)                ((UWtype) (t) & (__ll_B - 1))
-#define __ll_highpart(t)       ((UWtype) (t) >> (W_TYPE_SIZE / 2))
-
-/* You can optionally code some things like addition in asm. For
- * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
- * then you get a fragment of C code [if you change an #ifdef 0
- * in op-2.h] or a call to add_ssaaaa (see below).
- * Good places to look for asm fragments to use are gcc and glibc.
- * gcc's longlong.h is useful.
- */
-
-/* We need to know how to multiply and divide. If the host word size
- * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
- * codes the multiply with whatever gcc does to 'a * b'.
- * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm
- * function that can multiply two 1W values and get a 2W result.
- * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
- * does bitshifting to avoid overflow.
- * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
- * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or
- * _FP_DIV_HELP_ldiv (see op-1.h).
- * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
- * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
- * to do this.]
- * In general, 'n' is the number of words required to hold the type,
- * and 't' is either S, D or Q for single/double/quad.
- *           -- PMM
- */
-/* Example: SPARC64:
- * #define _FP_MUL_MEAT_S(R,X,Y)       _FP_MUL_MEAT_1_imm(S,R,X,Y)
- * #define _FP_MUL_MEAT_D(R,X,Y)       _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
- * #define _FP_MUL_MEAT_Q(R,X,Y)       _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
- *
- * #define _FP_DIV_MEAT_S(R,X,Y)       _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
- * #define _FP_DIV_MEAT_D(R,X,Y)       _FP_DIV_MEAT_1_udiv(D,R,X,Y)
- * #define _FP_DIV_MEAT_Q(R,X,Y)       _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
- *
- * Example: i386:
- * #define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
- * #define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
- *
- * #define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
- * #define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
- */
-
-#define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
-
-#define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y)
-#define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
-
-/* These macros define what NaN looks like. They're supposed to expand to
- * a comma-separated set of 32bit unsigned ints that encode NaN.
- */
-#define _FP_NANFRAC_S          _FP_QNANBIT_S
-#define _FP_NANFRAC_D          _FP_QNANBIT_D, 0
-#define _FP_NANFRAC_Q           _FP_QNANBIT_Q, 0, 0, 0
-
-#define _FP_KEEPNANFRACP 1
-
-/* This macro appears to be called when both X and Y are NaNs, and
- * has to choose one and copy it to R. i386 goes for the larger of the
- * two, sparc64 just picks Y. I don't understand this at all so I'll
- * go with sparc64 because it's shorter :->   -- PMM
- */
-#define _FP_CHOOSENAN(fs, wc, R, X, Y)                 \
-  do {                                                 \
-    R##_s = Y##_s;                                     \
-    _FP_FRAC_COPY_##wc(R,Y);                           \
-    R##_c = FP_CLS_NAN;                                        \
-  } while (0)
-
-
-extern void fp_unpack_d(long *, unsigned long *, unsigned long *,
-                       long *, long *, void *);
-extern int  fp_pack_d(void *, long, unsigned long, unsigned long, long, long);
-extern int  fp_pack_ds(void *, long, unsigned long, unsigned long, long, long);
-
-#define __FP_UNPACK_RAW_1(fs, X, val)                  \
-  do {                                                 \
-    union _FP_UNION_##fs *_flo =                       \
-       (union _FP_UNION_##fs *)val;                    \
-                                                       \
-    X##_f = _flo->bits.frac;                           \
-    X##_e = _flo->bits.exp;                            \
-    X##_s = _flo->bits.sign;                           \
-  } while (0)
-
-#define __FP_UNPACK_RAW_2(fs, X, val)                  \
-  do {                                                 \
-    union _FP_UNION_##fs *_flo =                       \
-       (union _FP_UNION_##fs *)val;                    \
-                                                       \
-    X##_f0 = _flo->bits.frac0;                         \
-    X##_f1 = _flo->bits.frac1;                         \
-    X##_e  = _flo->bits.exp;                           \
-    X##_s  = _flo->bits.sign;                          \
-  } while (0)
-
-#define __FP_UNPACK_S(X,val)           \
-  do {                                 \
-    __FP_UNPACK_RAW_1(S,X,val);                \
-    _FP_UNPACK_CANONICAL(S,1,X);       \
-  } while (0)
-
-#define __FP_UNPACK_D(X,val)           \
-       fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val)
-
-#define __FP_PACK_RAW_1(fs, val, X)                    \
-  do {                                                 \
-    union _FP_UNION_##fs *_flo =                       \
-       (union _FP_UNION_##fs *)val;                    \
-                                                       \
-    _flo->bits.frac = X##_f;                           \
-    _flo->bits.exp  = X##_e;                           \
-    _flo->bits.sign = X##_s;                           \
-  } while (0)
-
-#define __FP_PACK_RAW_2(fs, val, X)                    \
-  do {                                                 \
-    union _FP_UNION_##fs *_flo =                       \
-       (union _FP_UNION_##fs *)val;                    \
-                                                       \
-    _flo->bits.frac0 = X##_f0;                         \
-    _flo->bits.frac1 = X##_f1;                         \
-    _flo->bits.exp   = X##_e;                          \
-    _flo->bits.sign  = X##_s;                          \
-  } while (0)
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#define __FPU_FPSCR    (current->thread.fpscr.val)
-
-/* We only actually write to the destination register
- * if exceptions signalled (if any) will not trap.
- */
-#define __FPU_ENABLED_EXC \
-({                                             \
-       (__FPU_FPSCR >> 3) & 0x1f;      \
-})
-
-#define __FPU_TRAP_P(bits) \
-       ((__FPU_ENABLED_EXC & (bits)) != 0)
-
-#define __FP_PACK_S(val,X)                     \
-({  int __exc = _FP_PACK_CANONICAL(S,1,X);     \
-    if(!__exc || !__FPU_TRAP_P(__exc))         \
-        __FP_PACK_RAW_1(S,val,X);              \
-    __exc;                                     \
-})
-
-#define __FP_PACK_D(val,X)                     \
-       fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
-
-#define __FP_PACK_DS(val,X)                    \
-       fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
-
-/* Obtain the current rounding mode. */
-#define FP_ROUNDMODE                   \
-({                                     \
-       __FPU_FPSCR & 0x3;              \
-})
-
-/* the asm fragments go here: all these are taken from glibc-2.0.5's
- * stdlib/longlong.h
- */
-
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-/* add_ssaaaa is used in op-2.h and should be equivalent to
- * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
- * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
- * high_addend_2, low_addend_2) adds two UWtype integers, composed by
- * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
- * respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
- * (i.e. carry out) is not stored anywhere, and is lost.
- */
-#define add_ssaaaa(sh, sl, ah, al, bh, bl)                             \
-  do {                                                                 \
-    if (__builtin_constant_p (bh) && (bh) == 0)                                \
-      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"          \
-            : "=r" ((USItype)(sh)),                                    \
-              "=&r" ((USItype)(sl))                                    \
-            : "%r" ((USItype)(ah)),                                    \
-              "%r" ((USItype)(al)),                                    \
-              "rI" ((USItype)(bl)));                                   \
-    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
-      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"          \
-            : "=r" ((USItype)(sh)),                                    \
-              "=&r" ((USItype)(sl))                                    \
-            : "%r" ((USItype)(ah)),                                    \
-              "%r" ((USItype)(al)),                                    \
-              "rI" ((USItype)(bl)));                                   \
-    else                                                               \
-      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"         \
-            : "=r" ((USItype)(sh)),                                    \
-              "=&r" ((USItype)(sl))                                    \
-            : "%r" ((USItype)(ah)),                                    \
-              "r" ((USItype)(bh)),                                     \
-              "%r" ((USItype)(al)),                                    \
-              "rI" ((USItype)(bl)));                                   \
-  } while (0)
-
-/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
- * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
- * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
- * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
- * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
- * LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
- * and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
- * and is lost.
- */
-#define sub_ddmmss(sh, sl, ah, al, bh, bl)                             \
-  do {                                                                 \
-    if (__builtin_constant_p (ah) && (ah) == 0)                                \
-      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"      \
-              : "=r" ((USItype)(sh)),                                  \
-                "=&r" ((USItype)(sl))                                  \
-              : "r" ((USItype)(bh)),                                   \
-                "rI" ((USItype)(al)),                                  \
-                "r" ((USItype)(bl)));                                  \
-    else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0)         \
-      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"      \
-              : "=r" ((USItype)(sh)),                                  \
-                "=&r" ((USItype)(sl))                                  \
-              : "r" ((USItype)(bh)),                                   \
-                "rI" ((USItype)(al)),                                  \
-                "r" ((USItype)(bl)));                                  \
-    else if (__builtin_constant_p (bh) && (bh) == 0)                   \
-      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"                \
-              : "=r" ((USItype)(sh)),                                  \
-                "=&r" ((USItype)(sl))                                  \
-              : "r" ((USItype)(ah)),                                   \
-                "rI" ((USItype)(al)),                                  \
-                "r" ((USItype)(bl)));                                  \
-    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
-      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"                \
-              : "=r" ((USItype)(sh)),                                  \
-                "=&r" ((USItype)(sl))                                  \
-              : "r" ((USItype)(ah)),                                   \
-                "rI" ((USItype)(al)),                                  \
-                "r" ((USItype)(bl)));                                  \
-    else                                                               \
-      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"     \
-              : "=r" ((USItype)(sh)),                                  \
-                "=&r" ((USItype)(sl))                                  \
-              : "r" ((USItype)(ah)),                                   \
-                "r" ((USItype)(bh)),                                   \
-                "rI" ((USItype)(al)),                                  \
-                "r" ((USItype)(bl)));                                  \
-  } while (0)
-
-/* asm fragments for mul and div */
-
-/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
- * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
- * word product in HIGH_PROD and LOW_PROD.
- */
-#define umul_ppmm(ph, pl, m0, m1)                                      \
-  do {                                                                 \
-    USItype __m0 = (m0), __m1 = (m1);                                  \
-    __asm__ ("mulhwu %0,%1,%2"                                         \
-            : "=r" ((USItype)(ph))                                     \
-            : "%r" (__m0),                                             \
-               "r" (__m1));                                            \
-    (pl) = __m0 * __m1;                                                        \
-  } while (0)
-
-/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
- * denominator) divides a UDWtype, composed by the UWtype integers
- * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
- * in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
- * than DENOMINATOR for correct operation.  If, in addition, the most
- * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
- * UDIV_NEEDS_NORMALIZATION is defined to 1.
- */
-#define udiv_qrnnd(q, r, n1, n0, d)                                    \
-  do {                                                                 \
-    UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;                    \
-    __d1 = __ll_highpart (d);                                          \
-    __d0 = __ll_lowpart (d);                                           \
-                                                                       \
-    __r1 = (n1) % __d1;                                                        \
-    __q1 = (n1) / __d1;                                                        \
-    __m = (UWtype) __q1 * __d0;                                                \
-    __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
-    if (__r1 < __m)                                                    \
-      {                                                                        \
-       __q1--, __r1 += (d);                                            \
-       if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */  \
-         if (__r1 < __m)                                               \
-           __q1--, __r1 += (d);                                        \
-      }                                                                        \
-    __r1 -= __m;                                                       \
-                                                                       \
-    __r0 = __r1 % __d1;                                                        \
-    __q0 = __r1 / __d1;                                                        \
-    __m = (UWtype) __q0 * __d0;                                                \
-    __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
-    if (__r0 < __m)                                                    \
-      {                                                                        \
-       __q0--, __r0 += (d);                                            \
-       if (__r0 >= (d))                                                \
-         if (__r0 < __m)                                               \
-           __q0--, __r0 += (d);                                        \
-      }                                                                        \
-    __r0 -= __m;                                                       \
-                                                                       \
-    (q) = (UWtype) __q1 * __ll_B | __q0;                               \
-    (r) = __r0;                                                                \
-  } while (0)
-
-#define UDIV_NEEDS_NORMALIZATION 1
-
-#define abort()                                                                \
-       return 0
-
-#ifdef __BIG_ENDIAN
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
-
-/* Exception flags. */
-#define EFLAG_INVALID          (1 << (31 - 2))
-#define EFLAG_OVERFLOW         (1 << (31 - 3))
-#define EFLAG_UNDERFLOW                (1 << (31 - 4))
-#define EFLAG_DIVZERO          (1 << (31 - 5))
-#define EFLAG_INEXACT          (1 << (31 - 6))
-
-#define EFLAG_VXSNAN           (1 << (31 - 7))
-#define EFLAG_VXISI            (1 << (31 - 8))
-#define EFLAG_VXIDI            (1 << (31 - 9))
-#define EFLAG_VXZDZ            (1 << (31 - 10))
-#define EFLAG_VXIMZ            (1 << (31 - 11))
-#define EFLAG_VXVC             (1 << (31 - 12))
-#define EFLAG_VXSOFT           (1 << (31 - 21))
-#define EFLAG_VXSQRT           (1 << (31 - 22))
-#define EFLAG_VXCVI            (1 << (31 - 23))
diff --git a/arch/powerpc/math-emu/single.h b/arch/powerpc/math-emu/single.h
deleted file mode 100644 (file)
index f19d994..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Definitions for IEEE Single Precision
- */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid.  Go buy yourself a real computer."
-#endif
-
-#define _FP_FRACBITS_S         24
-#define _FP_FRACXBITS_S                (_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
-#define _FP_WFRACBITS_S                (_FP_WORKBITS + _FP_FRACBITS_S)
-#define _FP_WFRACXBITS_S       (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
-#define _FP_EXPBITS_S          8
-#define _FP_EXPBIAS_S          127
-#define _FP_EXPMAX_S           255
-#define _FP_QNANBIT_S          ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
-#define _FP_IMPLBIT_S          ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
-#define _FP_OVERFLOW_S         ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
-
-/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
-   chosen by the target machine.  */
-
-union _FP_UNION_S
-{
-  float flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign : 1;
-    unsigned exp  : _FP_EXPBITS_S;
-    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
-#else
-    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
-    unsigned exp  : _FP_EXPBITS_S;
-    unsigned sign : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_S(X)           _FP_DECL(1,X)
-#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
-#define FP_PACK_RAW_S(val,X)   _FP_PACK_RAW_1(S,val,X)
-
-#define FP_UNPACK_S(X,val)             \
-  do {                                 \
-    _FP_UNPACK_RAW_1(S,X,val);         \
-    _FP_UNPACK_CANONICAL(S,1,X);       \
-  } while (0)
-
-#define FP_PACK_S(val,X)               \
-  do {                                 \
-    _FP_PACK_CANONICAL(S,1,X);         \
-    _FP_PACK_RAW_1(S,val,X);           \
-  } while (0)
-
-#define FP_NEG_S(R,X)          _FP_NEG(S,1,R,X)
-#define FP_ADD_S(R,X,Y)                _FP_ADD(S,1,R,X,Y)
-#define FP_SUB_S(R,X,Y)                _FP_SUB(S,1,R,X,Y)
-#define FP_MUL_S(R,X,Y)                _FP_MUL(S,1,R,X,Y)
-#define FP_DIV_S(R,X,Y)                _FP_DIV(S,1,R,X,Y)
-#define FP_SQRT_S(R,X)         _FP_SQRT(S,1,R,X)
-
-#define FP_CMP_S(r,X,Y,un)     _FP_CMP(S,1,r,X,Y,un)
-#define FP_CMP_EQ_S(r,X,Y)     _FP_CMP_EQ(S,1,r,X,Y)
-
-#define FP_TO_INT_S(r,X,rsz,rsg)  _FP_TO_INT(S,1,r,X,rsz,rsg)
-#define FP_FROM_INT_S(X,r,rs,rt)  _FP_FROM_INT(S,1,X,r,rs,rt)
diff --git a/arch/powerpc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h
deleted file mode 100644 (file)
index cca3959..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef SOFT_FP_H
-#define SOFT_FP_H
-
-#include "sfp-machine.h"
-
-#define _FP_WORKBITS           3
-#define _FP_WORK_LSB           ((_FP_W_TYPE)1 << 3)
-#define _FP_WORK_ROUND         ((_FP_W_TYPE)1 << 2)
-#define _FP_WORK_GUARD         ((_FP_W_TYPE)1 << 1)
-#define _FP_WORK_STICKY                ((_FP_W_TYPE)1 << 0)
-
-#ifndef FP_RND_NEAREST
-# define FP_RND_NEAREST                0
-# define FP_RND_ZERO           1
-# define FP_RND_PINF           2
-# define FP_RND_MINF           3
-#ifndef FP_ROUNDMODE
-# define FP_ROUNDMODE          FP_RND_NEAREST
-#endif
-#endif
-
-#define _FP_ROUND_NEAREST(wc, X)                       \
-({  int __ret = 0;                                     \
-    int __frac = _FP_FRAC_LOW_##wc(X) & 15;            \
-    if (__frac & 7) {                                  \
-      __ret = EFLAG_INEXACT;                           \
-      if ((__frac & 7) != _FP_WORK_ROUND)              \
-        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);         \
-      else if (__frac & _FP_WORK_LSB)                  \
-        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);         \
-    }                                                  \
-    __ret;                                             \
-})
-
-#define _FP_ROUND_ZERO(wc, X)                          \
-({  int __ret = 0;                                     \
-    if (_FP_FRAC_LOW_##wc(X) & 7)                      \
-      __ret = EFLAG_INEXACT;                           \
-    __ret;                                             \
-})
-
-#define _FP_ROUND_PINF(wc, X)                          \
-({  int __ret = EFLAG_INEXACT;                         \
-    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))          \
-      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);             \
-    else __ret = 0;                                    \
-    __ret;                                             \
-})
-
-#define _FP_ROUND_MINF(wc, X)                          \
-({  int __ret = EFLAG_INEXACT;                         \
-    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))           \
-      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);             \
-    else __ret = 0;                                    \
-    __ret;                                             \
-})
-
-#define _FP_ROUND(wc, X)                       \
-({     int __ret = 0;                          \
-       switch (FP_ROUNDMODE)                   \
-       {                                       \
-         case FP_RND_NEAREST:                  \
-           __ret |= _FP_ROUND_NEAREST(wc,X);   \
-           break;                              \
-         case FP_RND_ZERO:                     \
-           __ret |= _FP_ROUND_ZERO(wc,X);      \
-           break;                              \
-         case FP_RND_PINF:                     \
-           __ret |= _FP_ROUND_PINF(wc,X);      \
-           break;                              \
-         case FP_RND_MINF:                     \
-           __ret |= _FP_ROUND_MINF(wc,X);      \
-           break;                              \
-       };                                      \
-       __ret;                                  \
-})
-
-#define FP_CLS_NORMAL          0
-#define FP_CLS_ZERO            1
-#define FP_CLS_INF             2
-#define FP_CLS_NAN             3
-
-#define _FP_CLS_COMBINE(x,y)   (((x) << 2) | (y))
-
-#include "op-1.h"
-#include "op-2.h"
-#include "op-4.h"
-#include "op-common.h"
-
-/* Sigh.  Silly things longlong.h needs.  */
-#define UWtype         _FP_W_TYPE
-#define W_TYPE_SIZE    _FP_W_TYPE_SIZE
-
-typedef int SItype __attribute__((mode(SI)));
-typedef int DItype __attribute__((mode(DI)));
-typedef unsigned int USItype __attribute__((mode(SI)));
-typedef unsigned int UDItype __attribute__((mode(DI)));
-#if _FP_W_TYPE_SIZE == 32
-typedef unsigned int UHWtype __attribute__((mode(HI)));
-#elif _FP_W_TYPE_SIZE == 64
-typedef USItype UHWtype;
-#endif
-
-#endif
index 8689aa48ef6952b8d45d9e3218d8bd97f7f8f71d..6122147356d1b2fa008922ae86e0fb157ce557f7 100644 (file)
@@ -2,23 +2,24 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
+#include <asm/sfp-machine.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/double.h>
+#include <math-emu/single.h>
 
 int
 stfs(void *frS, void *ea)
 {
        FP_DECL_D(A);
        FP_DECL_S(R);
+       FP_DECL_EX;
        float f;
-       int err;
 
 #ifdef DEBUG
        printk("%s: S %p, ea %p\n", __func__, frS, ea);
 #endif
 
-       __FP_UNPACK_D(A, frS);
+       FP_UNPACK_DP(A, frS);
 
 #ifdef DEBUG
        printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
@@ -30,12 +31,12 @@ stfs(void *frS, void *ea)
        printk("R: %ld %lu %ld (%ld)\n", R_s, R_f, R_e, R_c);
 #endif
 
-       err = _FP_PACK_CANONICAL(S, 1, R);
-       if (!err || !__FPU_TRAP_P(err)) {
-               __FP_PACK_RAW_1(S, &f, R);
+       _FP_PACK_CANONICAL(S, 1, R);
+       if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) {
+               _FP_PACK_RAW_1_P(S, &f, R);
                if (copy_to_user(ea, &f, sizeof(float)))
                        return -EFAULT;
        }
 
-       return err;
+       return FP_CUR_EXCEPTIONS;
 }
diff --git a/arch/powerpc/math-emu/types.c b/arch/powerpc/math-emu/types.c
deleted file mode 100644 (file)
index e1ed15d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-void
-fp_unpack_d(long *_s, unsigned long *_f1, unsigned long *_f0,
-           long *_e, long *_c, void *val)
-{
-       FP_DECL_D(X);
-
-       __FP_UNPACK_RAW_2(D, X, val);
-
-       _FP_UNPACK_CANONICAL(D, 2, X);
-
-       *_s = X_s;
-       *_f1 = X_f1;
-       *_f0 = X_f0;
-       *_e = X_e;
-       *_c = X_c;
-}
-
-int
-fp_pack_d(void *val, long X_s, unsigned long X_f1,
-         unsigned long X_f0, long X_e, long X_c)
-{
-       int exc;
-
-       exc = _FP_PACK_CANONICAL(D, 2, X);
-       if (!exc || !__FPU_TRAP_P(exc))
-               __FP_PACK_RAW_2(D, val, X);
-       return exc;
-}
-
-int
-fp_pack_ds(void *val, long X_s, unsigned long X_f1,
-          unsigned long X_f0, long X_e, long X_c)
-{
-       FP_DECL_S(__X);
-       int exc;
-
-       FP_CONV(S, D, 1, 2, __X, X);
-       exc = _FP_PACK_CANONICAL(S, 1, __X);
-       if (!exc || !__FPU_TRAP_P(exc)) {
-               _FP_UNPACK_CANONICAL(S, 1, __X);
-               FP_CONV(D, S, 2, 1, X, __X);
-               exc |= _FP_PACK_CANONICAL(D, 2, X);
-               if (!exc || !__FPU_TRAP_P(exc))
-                       __FP_PACK_RAW_2(D, val, X);
-       }
-       return exc;
-}
index 7e112dc1e2f2f81bb958dcb6cf60dafbec4ca275..6172044ab00339768dc41c69613ffbccb829ae40 100644 (file)
@@ -1,6 +1,6 @@
 /* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny.  */
 
-#include "soft-fp.h"
+#include <math-emu/soft-fp.h>
 
 #undef count_leading_zeros
 #define count_leading_zeros  __FP_CLZ
index ce10e2b1b902e5ddba7abcd9f48489ef1f2f862e..23cee39534fddf8ab832658e6a3f0cb658cabec8 100644 (file)
@@ -202,7 +202,7 @@ adjust_total_lowmem(void)
                cam_max_size = max_lowmem_size;
 
        /* adjust lowmem size to max_lowmem_size */
-       ram = min(max_lowmem_size, (phys_addr_t)total_lowmem);
+       ram = min(max_lowmem_size, total_lowmem);
 
        /* Calculate CAM values */
        __cam0 = 1UL << 2 * (__ilog2(ram) / 2);
@@ -225,7 +225,8 @@ adjust_total_lowmem(void)
        printk(KERN_INFO "Memory CAM mapping: CAM0=%ldMb, CAM1=%ldMb,"
                        " CAM2=%ldMb residual: %ldMb\n",
                        __cam0 >> 20, __cam1 >> 20, __cam2 >> 20,
-                       (total_lowmem - __cam0 - __cam1 - __cam2) >> 20);
+                       (long int)((total_lowmem - __cam0 - __cam1 - __cam2)
+                                  >> 20));
        __max_low_memory = __cam0 + __cam1 + __cam2;
        __initial_memory_limit_addr = memstart_addr + __max_low_memory;
 }
index 9fdf4d6335e43b0388088ca2e00fe43ca8d0aff3..28a114db3ba0d9a405fbd743b3b6b86359201795 100644 (file)
@@ -41,7 +41,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                page = pte_page(pte);
                if (!page_cache_get_speculative(page))
                        return 0;
-               if (unlikely(pte != *ptep)) {
+               if (unlikely(pte_val(pte) != pte_val(*ptep))) {
                        put_page(page);
                        return 0;
                }
@@ -92,7 +92,7 @@ static noinline int gup_huge_pte(pte_t *ptep, struct hstate *hstate,
                *nr -= refs;
                return 0;
        }
-       if (unlikely(pte != *ptep)) {
+       if (unlikely(pte_val(pte) != pte_val(*ptep))) {
                /* Could be optimized better */
                while (*nr) {
                        put_page(page);
@@ -237,7 +237,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                        pgd_t pgd = *pgdp;
 
                        VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift);
-                       pr_debug("  %016lx: normal pgd %p\n", addr, (void *)pgd);
+                       pr_debug("  %016lx: normal pgd %p\n", addr,
+                                (void *)pgd_val(pgd));
                        next = pgd_addr_end(addr, end);
                        if (pgd_none(pgd))
                                goto slow;
index b9ba7d9308017814c97bb1b3ef920d31a63e8494..7bffb70b9fe25cd71750428578ba961561412ee6 100644 (file)
@@ -75,7 +75,7 @@ _GLOBAL(hash_page_sync)
  * Returns to the caller if the access is illegal or there is no
  * mapping for the address.  Otherwise it places an appropriate PTE
  * in the hash table and returns from the exception.
- * Uses r0, r3 - r8, ctr, lr.
+ * Uses r0, r3 - r8, r10, ctr, lr.
  */
        .text
 _GLOBAL(hash_page)
@@ -106,9 +106,15 @@ _GLOBAL(hash_page)
        addi    r5,r5,swapper_pg_dir@l  /* kernel page table */
        rlwimi  r3,r9,32-12,29,29       /* MSR_PR -> _PAGE_USER */
 112:   add     r5,r5,r7                /* convert to phys addr */
+#ifndef CONFIG_PTE_64BIT
        rlwimi  r5,r4,12,20,29          /* insert top 10 bits of address */
        lwz     r8,0(r5)                /* get pmd entry */
        rlwinm. r8,r8,0,0,19            /* extract address of pte page */
+#else
+       rlwinm  r8,r4,13,19,29          /* Compute pgdir/pmd offset */
+       lwzx    r8,r8,r5                /* Get L1 entry */
+       rlwinm. r8,r8,0,0,20            /* extract pt base address */
+#endif
 #ifdef CONFIG_SMP
        beq-    hash_page_out           /* return if no mapping */
 #else
@@ -118,7 +124,11 @@ _GLOBAL(hash_page)
           to the address following the rfi. */
        beqlr-
 #endif
+#ifndef CONFIG_PTE_64BIT
        rlwimi  r8,r4,22,20,29          /* insert next 10 bits of address */
+#else
+       rlwimi  r8,r4,23,20,28          /* compute pte address */
+#endif
        rlwinm  r0,r3,32-3,24,24        /* _PAGE_RW access -> _PAGE_DIRTY */
        ori     r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
 
@@ -127,9 +137,15 @@ _GLOBAL(hash_page)
         * because almost always, there won't be a permission violation
         * and there won't already be an HPTE, and thus we will have
         * to update the PTE to set _PAGE_HASHPTE.  -- paulus.
+        *
+        * If PTE_64BIT is set, the low word is the flags word; use that
+        * word for locking since it contains all the interesting bits.
         */
+#if (PTE_FLAGS_OFFSET != 0)
+       addi    r8,r8,PTE_FLAGS_OFFSET
+#endif
 retry:
-       lwarx   r6,0,r8                 /* get linux-style pte */
+       lwarx   r6,0,r8                 /* get linux-style pte, flag word */
        andc.   r5,r3,r6                /* check access & ~permission */
 #ifdef CONFIG_SMP
        bne-    hash_page_out           /* return if access not permitted */
@@ -137,6 +153,15 @@ retry:
        bnelr-
 #endif
        or      r5,r0,r6                /* set accessed/dirty bits */
+#ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_SMP
+       subf    r10,r6,r8               /* create false data dependency */
+       subi    r10,r10,PTE_FLAGS_OFFSET
+       lwzx    r10,r6,r10              /* Get upper PTE word */
+#else
+       lwz     r10,-PTE_FLAGS_OFFSET(r8)
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_PTE_64BIT */
        stwcx.  r5,0,r8                 /* attempt to update PTE */
        bne-    retry                   /* retry if someone got there first */
 
@@ -203,9 +228,9 @@ _GLOBAL(add_hash_page)
         * we can't take a hash table miss (assuming the code is
         * covered by a BAT).  -- paulus
         */
-       mfmsr   r10
+       mfmsr   r9
        SYNC
-       rlwinm  r0,r10,0,17,15          /* clear bit 16 (MSR_EE) */
+       rlwinm  r0,r9,0,17,15           /* clear bit 16 (MSR_EE) */
        rlwinm  r0,r0,0,28,26           /* clear MSR_DR */
        mtmsr   r0
        SYNC_601
@@ -214,14 +239,14 @@ _GLOBAL(add_hash_page)
        tophys(r7,0)
 
 #ifdef CONFIG_SMP
-       addis   r9,r7,mmu_hash_lock@ha
-       addi    r9,r9,mmu_hash_lock@l
-10:    lwarx   r0,0,r9                 /* take the mmu_hash_lock */
+       addis   r6,r7,mmu_hash_lock@ha
+       addi    r6,r6,mmu_hash_lock@l
+10:    lwarx   r0,0,r6                 /* take the mmu_hash_lock */
        cmpi    0,r0,0
        bne-    11f
-       stwcx.  r8,0,r9
+       stwcx.  r8,0,r6
        beq+    12f
-11:    lwz     r0,0(r9)
+11:    lwz     r0,0(r6)
        cmpi    0,r0,0
        beq     10b
        b       11b
@@ -234,10 +259,24 @@ _GLOBAL(add_hash_page)
         * HPTE, so we just unlock and return.
         */
        mr      r8,r5
+#ifndef CONFIG_PTE_64BIT
        rlwimi  r8,r4,22,20,29
+#else
+       rlwimi  r8,r4,23,20,28
+       addi    r8,r8,PTE_FLAGS_OFFSET
+#endif
 1:     lwarx   r6,0,r8
        andi.   r0,r6,_PAGE_HASHPTE
        bne     9f                      /* if HASHPTE already set, done */
+#ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_SMP
+       subf    r10,r6,r8               /* create false data dependency */
+       subi    r10,r10,PTE_FLAGS_OFFSET
+       lwzx    r10,r6,r10              /* Get upper PTE word */
+#else
+       lwz     r10,-PTE_FLAGS_OFFSET(r8)
+#endif /* CONFIG_SMP */
+#endif /* CONFIG_PTE_64BIT */
        ori     r5,r6,_PAGE_HASHPTE
        stwcx.  r5,0,r8
        bne-    1b
@@ -246,13 +285,15 @@ _GLOBAL(add_hash_page)
 
 9:
 #ifdef CONFIG_SMP
+       addis   r6,r7,mmu_hash_lock@ha
+       addi    r6,r6,mmu_hash_lock@l
        eieio
        li      r0,0
-       stw     r0,0(r9)                /* clear mmu_hash_lock */
+       stw     r0,0(r6)                /* clear mmu_hash_lock */
 #endif
 
        /* reenable interrupts and DR */
-       mtmsr   r10
+       mtmsr   r9
        SYNC_601
        isync
 
@@ -267,7 +308,8 @@ _GLOBAL(add_hash_page)
  * r5 contains the linux PTE, r6 contains the old value of the
  * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
  * offset to be added to addresses (0 if the MMU is on,
- * -KERNELBASE if it is off).
+ * -KERNELBASE if it is off).  r10 contains the upper half of
+ * the PTE if CONFIG_PTE_64BIT.
  * On SMP, the caller should have the mmu_hash_lock held.
  * We assume that the caller has (or will) set the _PAGE_HASHPTE
  * bit in the linux PTE in memory.  The value passed in r6 should
@@ -285,7 +327,7 @@ Hash_bits = 12                              /* e.g. 256kB hash table */
 Hash_msk = (((1 << Hash_bits) - 1) * 64)
 
 /* defines for the PTE format for 32-bit PPCs */
-#define PTE_SIZE       8
+#define HPTE_SIZE      8
 #define PTEG_SIZE      64
 #define LG_PTEG_SIZE   6
 #define LDPTEu         lwzu
@@ -313,6 +355,11 @@ _GLOBAL(create_hpte)
 BEGIN_FTR_SECTION
        ori     r8,r8,_PAGE_COHERENT    /* set M (coherence required) */
 END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
+#ifdef CONFIG_PTE_64BIT
+       /* Put the XPN bits into the PTE */
+       rlwimi  r8,r10,8,20,22
+       rlwimi  r8,r10,2,29,29
+#endif
 
        /* Construct the high word of the PPC-style PTE (r5) */
        rlwinm  r5,r3,7,1,24            /* put VSID in 0x7fffff80 bits */
@@ -342,8 +389,8 @@ _GLOBAL(hash_page_patch_A)
 
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        mtctr   r0
-       addi    r4,r3,-PTE_SIZE
-1:     LDPTEu  r6,PTE_SIZE(r4)         /* get next PTE */
+       addi    r4,r3,-HPTE_SIZE
+1:     LDPTEu  r6,HPTE_SIZE(r4)        /* get next PTE */
        CMPPTE  0,r6,r5
        bdnzf   2,1b                    /* loop while ctr != 0 && !cr0.eq */
        beq+    found_slot
@@ -353,9 +400,9 @@ _GLOBAL(hash_page_patch_A)
 _GLOBAL(hash_page_patch_B)
        xoris   r4,r3,Hash_msk>>16      /* compute secondary hash */
        xori    r4,r4,(-PTEG_SIZE & 0xffff)
-       addi    r4,r4,-PTE_SIZE
+       addi    r4,r4,-HPTE_SIZE
        mtctr   r0
-2:     LDPTEu  r6,PTE_SIZE(r4)
+2:     LDPTEu  r6,HPTE_SIZE(r4)
        CMPPTE  0,r6,r5
        bdnzf   2,2b
        beq+    found_slot
@@ -363,8 +410,8 @@ _GLOBAL(hash_page_patch_B)
 
        /* Search the primary PTEG for an empty slot */
 10:    mtctr   r0
-       addi    r4,r3,-PTE_SIZE         /* search primary PTEG */
-1:     LDPTEu  r6,PTE_SIZE(r4)         /* get next PTE */
+       addi    r4,r3,-HPTE_SIZE        /* search primary PTEG */
+1:     LDPTEu  r6,HPTE_SIZE(r4)        /* get next PTE */
        TST_V(r6)                       /* test valid bit */
        bdnzf   2,1b                    /* loop while ctr != 0 && !cr0.eq */
        beq+    found_empty
@@ -380,9 +427,9 @@ _GLOBAL(hash_page_patch_B)
 _GLOBAL(hash_page_patch_C)
        xoris   r4,r3,Hash_msk>>16      /* compute secondary hash */
        xori    r4,r4,(-PTEG_SIZE & 0xffff)
-       addi    r4,r4,-PTE_SIZE
+       addi    r4,r4,-HPTE_SIZE
        mtctr   r0
-2:     LDPTEu  r6,PTE_SIZE(r4)
+2:     LDPTEu  r6,HPTE_SIZE(r4)
        TST_V(r6)
        bdnzf   2,2b
        beq+    found_empty
@@ -409,11 +456,11 @@ _GLOBAL(hash_page_patch_C)
 
 1:     addis   r4,r7,next_slot@ha              /* get next evict slot */
        lwz     r6,next_slot@l(r4)
-       addi    r6,r6,PTE_SIZE                  /* search for candidate */
-       andi.   r6,r6,7*PTE_SIZE
+       addi    r6,r6,HPTE_SIZE                 /* search for candidate */
+       andi.   r6,r6,7*HPTE_SIZE
        stw     r6,next_slot@l(r4)
        add     r4,r3,r6
-       LDPTE   r0,PTE_SIZE/2(r4)               /* get PTE second word */
+       LDPTE   r0,HPTE_SIZE/2(r4)              /* get PTE second word */
        clrrwi  r0,r0,12
        lis     r6,etext@h
        ori     r6,r6,etext@l                   /* get etext */
@@ -426,7 +473,7 @@ _GLOBAL(hash_page_patch_C)
 found_empty:
        STPTE   r5,0(r4)
 found_slot:
-       STPTE   r8,PTE_SIZE/2(r4)
+       STPTE   r8,HPTE_SIZE/2(r4)
 
 #else /* CONFIG_SMP */
 /*
@@ -452,7 +499,7 @@ found_slot:
        STPTE   r5,0(r4)
        sync
        TLBSYNC
-       STPTE   r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
+       STPTE   r8,HPTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
        sync
        SET_V(r5)
        STPTE   r5,0(r4)        /* finally set V bit in PTE */
@@ -499,14 +546,18 @@ _GLOBAL(flush_hash_pages)
        isync
 
        /* First find a PTE in the range that has _PAGE_HASHPTE set */
+#ifndef CONFIG_PTE_64BIT
        rlwimi  r5,r4,22,20,29
-1:     lwz     r0,0(r5)
+#else
+       rlwimi  r5,r4,23,20,28
+#endif
+1:     lwz     r0,PTE_FLAGS_OFFSET(r5)
        cmpwi   cr1,r6,1
        andi.   r0,r0,_PAGE_HASHPTE
        bne     2f
        ble     cr1,19f
        addi    r4,r4,0x1000
-       addi    r5,r5,4
+       addi    r5,r5,PTE_SIZE
        addi    r6,r6,-1
        b       1b
 
@@ -545,7 +596,10 @@ _GLOBAL(flush_hash_pages)
         * already clear, we're done (for this pte).  If not,
         * clear it (atomically) and proceed.  -- paulus.
         */
-33:    lwarx   r8,0,r5                 /* fetch the pte */
+#if (PTE_FLAGS_OFFSET != 0)
+       addi    r5,r5,PTE_FLAGS_OFFSET
+#endif
+33:    lwarx   r8,0,r5                 /* fetch the pte flags word */
        andi.   r0,r8,_PAGE_HASHPTE
        beq     8f                      /* done if HASHPTE is already clear */
        rlwinm  r8,r8,0,31,29           /* clear HASHPTE bit */
@@ -562,8 +616,8 @@ _GLOBAL(flush_hash_patch_A)
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        li      r0,8                    /* PTEs/group */
        mtctr   r0
-       addi    r12,r8,-PTE_SIZE
-1:     LDPTEu  r0,PTE_SIZE(r12)        /* get next PTE */
+       addi    r12,r8,-HPTE_SIZE
+1:     LDPTEu  r0,HPTE_SIZE(r12)       /* get next PTE */
        CMPPTE  0,r0,r11
        bdnzf   2,1b                    /* loop while ctr != 0 && !cr0.eq */
        beq+    3f
@@ -574,9 +628,9 @@ _GLOBAL(flush_hash_patch_A)
 _GLOBAL(flush_hash_patch_B)
        xoris   r12,r8,Hash_msk>>16     /* compute secondary hash */
        xori    r12,r12,(-PTEG_SIZE & 0xffff)
-       addi    r12,r12,-PTE_SIZE
+       addi    r12,r12,-HPTE_SIZE
        mtctr   r0
-2:     LDPTEu  r0,PTE_SIZE(r12)
+2:     LDPTEu  r0,HPTE_SIZE(r12)
        CMPPTE  0,r0,r11
        bdnzf   2,2b
        xori    r11,r11,PTE_H           /* clear H again */
@@ -590,7 +644,7 @@ _GLOBAL(flush_hash_patch_B)
 
 8:     ble     cr1,9f                  /* if all ptes checked */
 81:    addi    r6,r6,-1
-       addi    r5,r5,4                 /* advance to next pte */
+       addi    r5,r5,PTE_SIZE
        addi    r4,r4,0x1000
        lwz     r0,0(r5)                /* check next pte */
        cmpwi   cr1,r6,1
index 8920eea3452844dfb906fc3f9d6b67a01d37561f..5c64af1747525d7b7b5fd0adbae202845564f9e1 100644 (file)
@@ -194,7 +194,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                unsigned long tprot = prot;
 
                /* Make kernel text executable */
-               if (in_kernel_text(vaddr))
+               if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
 
                hash = hpt_hash(va, shift, ssize);
@@ -348,6 +348,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
        return 0;
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
 /* Scan for 16G memory blocks that have been set aside for huge pages
  * and reserve those blocks for 16G huge pages.
  */
@@ -385,6 +386,7 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
        add_gpage(phys_addr, block_size, expected_pages);
        return 0;
 }
+#endif /* CONFIG_HUGETLB_PAGE */
 
 static void __init htab_init_page_sizes(void)
 {
@@ -539,7 +541,7 @@ static unsigned long __init htab_get_table_size(void)
 void create_section_mapping(unsigned long start, unsigned long end)
 {
        BUG_ON(htab_bolt_mapping(start, end, __pa(start),
-                                PAGE_KERNEL, mmu_linear_psize,
+                                pgprot_val(PAGE_KERNEL), mmu_linear_psize,
                                 mmu_kernel_ssize));
 }
 
@@ -647,7 +649,7 @@ void __init htab_initialize(void)
                mtspr(SPRN_SDR1, _SDR1);
        }
 
-       prot = PAGE_KERNEL;
+       prot = pgprot_val(PAGE_KERNEL);
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
        linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT;
index f1c2d55b4377c1a09af0e860316e80d56f6557e2..a117024ab8cdb68af98c8bfc13f822695dc4c2bf 100644 (file)
@@ -128,29 +128,37 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        return 0;
 }
 
-/* Base page size affects how we walk hugetlb page tables */
-#ifdef CONFIG_PPC_64K_PAGES
-#define hpmd_offset(pud, addr, h)      pmd_offset(pud, addr)
-#define hpmd_alloc(mm, pud, addr, h)   pmd_alloc(mm, pud, addr)
-#else
-static inline
-pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate)
+
+static pud_t *hpud_offset(pgd_t *pgd, unsigned long addr, struct hstate *hstate)
+{
+       if (huge_page_shift(hstate) < PUD_SHIFT)
+               return pud_offset(pgd, addr);
+       else
+               return (pud_t *) pgd;
+}
+static pud_t *hpud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
+                        struct hstate *hstate)
 {
-       if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
+       if (huge_page_shift(hstate) < PUD_SHIFT)
+               return pud_alloc(mm, pgd, addr);
+       else
+               return (pud_t *) pgd;
+}
+static pmd_t *hpmd_offset(pud_t *pud, unsigned long addr, struct hstate *hstate)
+{
+       if (huge_page_shift(hstate) < PMD_SHIFT)
                return pmd_offset(pud, addr);
        else
                return (pmd_t *) pud;
 }
-static inline
-pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
-                 struct hstate *hstate)
+static pmd_t *hpmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
+                        struct hstate *hstate)
 {
-       if (huge_page_shift(hstate) == PAGE_SHIFT_64K)
+       if (huge_page_shift(hstate) < PMD_SHIFT)
                return pmd_alloc(mm, pud, addr);
        else
                return (pmd_t *) pud;
 }
-#endif
 
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy or bootmem allocator is setup.
@@ -204,7 +212,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 
        pg = pgd_offset(mm, addr);
        if (!pgd_none(*pg)) {
-               pu = pud_offset(pg, addr);
+               pu = hpud_offset(pg, addr, hstate);
                if (!pud_none(*pu)) {
                        pm = hpmd_offset(pu, addr, hstate);
                        if (!pmd_none(*pm))
@@ -233,7 +241,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
        addr &= hstate->mask;
 
        pg = pgd_offset(mm, addr);
-       pu = pud_alloc(mm, pg, addr);
+       pu = hpud_alloc(mm, pg, addr, hstate);
 
        if (pu) {
                pm = hpmd_alloc(mm, pu, addr, hstate);
@@ -316,13 +324,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
        pud = pud_offset(pgd, addr);
        do {
                next = pud_addr_end(addr, end);
-#ifdef CONFIG_PPC_64K_PAGES
-               if (pud_none_or_clear_bad(pud))
-                       continue;
-               hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling,
-                                      psize);
-#else
-               if (shift == PAGE_SHIFT_64K) {
+               if (shift < PMD_SHIFT) {
                        if (pud_none_or_clear_bad(pud))
                                continue;
                        hugetlb_free_pmd_range(tlb, pud, addr, next, floor,
@@ -332,7 +334,6 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
                                continue;
                        free_hugepte_range(tlb, (hugepd_t *)pud, psize);
                }
-#endif
        } while (pud++, addr = next, addr != end);
 
        start &= PGDIR_MASK;
@@ -422,9 +423,15 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                psize = get_slice_psize(tlb->mm, addr);
                BUG_ON(!mmu_huge_psizes[psize]);
                next = pgd_addr_end(addr, end);
-               if (pgd_none_or_clear_bad(pgd))
-                       continue;
-               hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
+               if (mmu_psize_to_shift(psize) < PUD_SHIFT) {
+                       if (pgd_none_or_clear_bad(pgd))
+                               continue;
+                       hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
+               } else {
+                       if (pgd_none(*pgd))
+                               continue;
+                       free_hugepte_range(tlb, (hugepd_t *)pgd, psize);
+               }
        } while (pgd++, addr = next, addr != end);
 }
 
index 036fe2f10c7780c59545f72ac3f718b59fecd7cc..3e6a6543f53a9fa193d49081d1d6fcb3b8353776 100644 (file)
@@ -228,8 +228,8 @@ int __meminit vmemmap_populate(struct page *start_page,
                        start, p, __pa(p));
 
                mapped = htab_bolt_mapping(start, start + page_size, __pa(p),
-                                          PAGE_KERNEL, mmu_vmemmap_psize,
-                                          mmu_kernel_ssize);
+                                          pgprot_val(PAGE_KERNEL),
+                                          mmu_vmemmap_psize, mmu_kernel_ssize);
                BUG_ON(mapped < 0);
        }
 
index 1c93c255873b5a4fb9640dd2de7d58332dfabded..98d7bf99533aff312712d747beed29141294608d 100644 (file)
@@ -75,11 +75,10 @@ static inline pte_t *virt_to_kpte(unsigned long vaddr)
 
 int page_is_ram(unsigned long pfn)
 {
-       unsigned long paddr = (pfn << PAGE_SHIFT);
-
 #ifndef CONFIG_PPC64   /* XXX for now */
-       return paddr < __pa(high_memory);
+       return pfn < max_pfn;
 #else
+       unsigned long paddr = (pfn << PAGE_SHIFT);
        int i;
        for (i=0; i < lmb.memory.cnt; i++) {
                unsigned long base;
index d9a1813513322889af782dd71625f46db3bab1c4..6cf5c71c431fddc43d33ba920753023d847a991e 100644 (file)
@@ -89,6 +89,46 @@ static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
        return 0;
 }
 
+/*
+ * get_active_region_work_fn - A helper function for get_node_active_region
+ *     Returns datax set to the start_pfn and end_pfn if they contain
+ *     the initial value of datax->start_pfn between them
+ * @start_pfn: start page(inclusive) of region to check
+ * @end_pfn: end page(exclusive) of region to check
+ * @datax: comes in with ->start_pfn set to value to search for and
+ *     goes out with active range if it contains it
+ * Returns 1 if search value is in range else 0
+ */
+static int __init get_active_region_work_fn(unsigned long start_pfn,
+                                       unsigned long end_pfn, void *datax)
+{
+       struct node_active_region *data;
+       data = (struct node_active_region *)datax;
+
+       if (start_pfn <= data->start_pfn && end_pfn > data->start_pfn) {
+               data->start_pfn = start_pfn;
+               data->end_pfn = end_pfn;
+               return 1;
+       }
+       return 0;
+
+}
+
+/*
+ * get_node_active_region - Return active region containing start_pfn
+ * @start_pfn: The page to return the region for.
+ * @node_ar: Returned set to the active region containing start_pfn
+ */
+static void __init get_node_active_region(unsigned long start_pfn,
+                      struct node_active_region *node_ar)
+{
+       int nid = early_pfn_to_nid(start_pfn);
+
+       node_ar->nid = nid;
+       node_ar->start_pfn = start_pfn;
+       work_with_active_regions(nid, get_active_region_work_fn, node_ar);
+}
+
 static void __cpuinit map_cpu_to_node(int cpu, int node)
 {
        numa_cpu_lookup_table[cpu] = node;
@@ -150,6 +190,21 @@ static const int *of_get_associativity(struct device_node *dev)
        return of_get_property(dev, "ibm,associativity", NULL);
 }
 
+/*
+ * Returns the property linux,drconf-usable-memory if
+ * it exists (the property exists only in kexec/kdump kernels,
+ * added by kexec-tools)
+ */
+static const u32 *of_get_usable_memory(struct device_node *memory)
+{
+       const u32 *prop;
+       u32 len;
+       prop = of_get_property(memory, "linux,drconf-usable-memory", &len);
+       if (!prop || len < sizeof(unsigned int))
+               return 0;
+       return prop;
+}
+
 /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
  * info is found.
  */
@@ -486,15 +541,30 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start,
        return lmb_end_of_DRAM() - start;
 }
 
+/*
+ * Reads the counter for a given entry in
+ * linux,drconf-usable-memory property
+ */
+static inline int __init read_usm_ranges(const u32 **usm)
+{
+       /*
+        * For each lmb in ibm,dynamic-memory a corresponding
+        * entry in linux,drconf-usable-memory property contains
+        * a counter followed by that many (base, size) duple.
+        * read the counter from linux,drconf-usable-memory
+        */
+       return read_n_cells(n_mem_size_cells, usm);
+}
+
 /*
  * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
  * node.  This assumes n_mem_{addr,size}_cells have been set.
  */
 static void __init parse_drconf_memory(struct device_node *memory)
 {
-       const u32 *dm;
-       unsigned int n, rc;
-       unsigned long lmb_size, size;
+       const u32 *dm, *usm;
+       unsigned int n, rc, ranges, is_kexec_kdump = 0;
+       unsigned long lmb_size, base, size, sz;
        int nid;
        struct assoc_arrays aa;
 
@@ -510,6 +580,11 @@ static void __init parse_drconf_memory(struct device_node *memory)
        if (rc)
                return;
 
+       /* check if this is a kexec/kdump kernel */
+       usm = of_get_usable_memory(memory);
+       if (usm != NULL)
+               is_kexec_kdump = 1;
+
        for (; n != 0; --n) {
                struct of_drconf_cell drmem;
 
@@ -521,21 +596,31 @@ static void __init parse_drconf_memory(struct device_node *memory)
                    || !(drmem.flags & DRCONF_MEM_ASSIGNED))
                        continue;
 
-               nid = of_drconf_to_nid_single(&drmem, &aa);
+               base = drmem.base_addr;
+               size = lmb_size;
+               ranges = 1;
 
-               fake_numa_create_new_node(
-                               ((drmem.base_addr + lmb_size) >> PAGE_SHIFT),
+               if (is_kexec_kdump) {
+                       ranges = read_usm_ranges(&usm);
+                       if (!ranges) /* there are no (base, size) duple */
+                               continue;
+               }
+               do {
+                       if (is_kexec_kdump) {
+                               base = read_n_cells(n_mem_addr_cells, &usm);
+                               size = read_n_cells(n_mem_size_cells, &usm);
+                       }
+                       nid = of_drconf_to_nid_single(&drmem, &aa);
+                       fake_numa_create_new_node(
+                               ((base + size) >> PAGE_SHIFT),
                                           &nid);
-
-               node_set_online(nid);
-
-               size = numa_enforce_memory_limit(drmem.base_addr, lmb_size);
-               if (!size)
-                       continue;
-
-               add_active_range(nid, drmem.base_addr >> PAGE_SHIFT,
-                                (drmem.base_addr >> PAGE_SHIFT)
-                                + (size >> PAGE_SHIFT));
+                       node_set_online(nid);
+                       sz = numa_enforce_memory_limit(base, size);
+                       if (sz)
+                               add_active_range(nid, base >> PAGE_SHIFT,
+                                                (base >> PAGE_SHIFT)
+                                                + (sz >> PAGE_SHIFT));
+               } while (--ranges);
        }
 }
 
@@ -837,38 +922,50 @@ void __init do_init_bootmem(void)
                                  start_pfn, end_pfn);
 
                free_bootmem_with_active_regions(nid, end_pfn);
+       }
 
-               /* Mark reserved regions on this node */
-               for (i = 0; i < lmb.reserved.cnt; i++) {
-                       unsigned long physbase = lmb.reserved.region[i].base;
-                       unsigned long size = lmb.reserved.region[i].size;
-                       unsigned long start_paddr = start_pfn << PAGE_SHIFT;
-                       unsigned long end_paddr = end_pfn << PAGE_SHIFT;
-
-                       if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid &&
-                           early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid)
-                               continue;
-
-                       if (physbase < end_paddr &&
-                           (physbase+size) > start_paddr) {
-                               /* overlaps */
-                               if (physbase < start_paddr) {
-                                       size -= start_paddr - physbase;
-                                       physbase = start_paddr;
-                               }
-
-                               if (size > end_paddr - physbase)
-                                       size = end_paddr - physbase;
-
-                               dbg("reserve_bootmem %lx %lx\n", physbase,
-                                   size);
-                               reserve_bootmem_node(NODE_DATA(nid), physbase,
-                                                    size, BOOTMEM_DEFAULT);
-                       }
+       /* Mark reserved regions */
+       for (i = 0; i < lmb.reserved.cnt; i++) {
+               unsigned long physbase = lmb.reserved.region[i].base;
+               unsigned long size = lmb.reserved.region[i].size;
+               unsigned long start_pfn = physbase >> PAGE_SHIFT;
+               unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
+               struct node_active_region node_ar;
+
+               get_node_active_region(start_pfn, &node_ar);
+               while (start_pfn < end_pfn) {
+                       /*
+                        * if reserved region extends past active region
+                        * then trim size to active region
+                        */
+                       if (end_pfn > node_ar.end_pfn)
+                               size = (node_ar.end_pfn << PAGE_SHIFT)
+                                       - (start_pfn << PAGE_SHIFT);
+                       dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, size,
+                               node_ar.nid);
+                       reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase,
+                                               size, BOOTMEM_DEFAULT);
+                       /*
+                        * if reserved region is contained in the active region
+                        * then done.
+                        */
+                       if (end_pfn <= node_ar.end_pfn)
+                               break;
+
+                       /*
+                        * reserved region extends past the active region
+                        *   get next active region that contains this
+                        *   reserved region
+                        */
+                       start_pfn = node_ar.end_pfn;
+                       physbase = start_pfn << PAGE_SHIFT;
+                       get_node_active_region(start_pfn, &node_ar);
                }
 
-               sparse_memory_present_with_active_regions(nid);
        }
+
+       for_each_online_node(nid)
+               sparse_memory_present_with_active_regions(nid);
 }
 
 void __init paging_init(void)
index 2001abdb1912bec23dfa6635010359edddf4423b..c31d6d26f0b57c50b5b38bdc042f7221a93adf82 100644 (file)
@@ -73,7 +73,7 @@ extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
 #endif /* HAVE_TLBCAM */
 
 #ifdef CONFIG_PTE_64BIT
-/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
+/* Some processors use an 8kB pgdir because they have 8-byte Linux PTEs. */
 #define PGDIR_ORDER    1
 #else
 #define PGDIR_ORDER    0
@@ -288,7 +288,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
 }
 
 /*
- * Map in all of physical memory starting at KERNELBASE.
+ * Map in a big chunk of physical memory starting at KERNELBASE.
  */
 void __init mapin_ram(void)
 {
index eb4b512d65fabc4a2b6b291d04d8dacac08e9813..f9a47fee39278174872a30a7844ff2b01c99d4c1 100644 (file)
@@ -45,6 +45,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
                flush_hash_pages(mm->context.id, addr, ptephys, 1);
        }
 }
+EXPORT_SYMBOL(flush_hash_entry);
 
 /*
  * Called by ptep_set_access_flags, must flush on CPUs for which the
index fff66662d021ed152c1e17601cb319bd3f4c6ec8..258fa4411e9e48dde2c9bfdffce352c49e3d9a21 100644 (file)
@@ -229,7 +229,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
         */
        overlay_tbl_offset = vma_map_lookup(map, ovly_table_sym,
                                            aSpu, &grd_val);
-       if (overlay_tbl_offset 0) {
+       if (overlay_tbl_offset > 0x10000000) {
                printk(KERN_ERR "SPU_PROF: "
                       "%s, line %d: Error finding SPU overlay table\n",
                       __func__, __LINE__);
index 446a8bbb847b0f2dcd679ac74eaece531cee4476..3e3d91f536e0be0daa3a1b7e031023de475ea5a3 100644 (file)
@@ -64,7 +64,7 @@ static int power4_reg_setup(struct op_counter_config *ctr,
        return 0;
 }
 
-extern void ppc64_enable_pmcs(void);
+extern void ppc_enable_pmcs(void);
 
 /*
  * Older CPUs require the MMCRA sample bit to be always set, but newer 
@@ -91,7 +91,7 @@ static int power4_cpu_setup(struct op_counter_config *ctr)
        unsigned int mmcr0 = mmcr0_val;
        unsigned long mmcra = mmcra_val;
 
-       ppc64_enable_pmcs();
+       ppc_enable_pmcs();
 
        /* set the freeze bit */
        mmcr0 |= MMCR0_FC;
index 249ba01c667416cfb62f8743f2701f087732b088..79c1154f88d42464796c3dd0d5ce8194a8c7862c 100644 (file)
@@ -2,6 +2,7 @@ config BAMBOO
        bool "Bamboo"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440EP
        select PCI
        help
@@ -30,6 +31,7 @@ config SEQUOIA
        bool "Sequoia"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440EPX
        help
          This option enables support for the AMCC PPC440EPX evaluation board.
@@ -38,6 +40,7 @@ config TAISHAN
        bool "Taishan"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440GX
        select PCI
        help
@@ -48,6 +51,7 @@ config KATMAI
        bool "Katmai"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440SPe
        select PCI
        select PPC4xx_PCI_EXPRESS
@@ -58,6 +62,7 @@ config RAINIER
        bool "Rainier"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440GRX
        select PCI
        help
@@ -76,20 +81,48 @@ config WARP
          See http://www.pikatechnologies.com/ and follow the "PIKA for Computer
          Telephony Developers" link for more information.
 
+config ARCHES
+       bool "Arches"
+       depends on 44x
+       default n
+       select PPC44x_SIMPLE
+       select 460EX # Odd since it uses 460GT but the effects are the same
+       select PCI
+       select PPC4xx_PCI_EXPRESS
+       help
+         This option enables support for the AMCC Dual PPC460GT evaluation board.
+
 config CANYONLANDS
        bool "Canyonlands"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 460EX
        select PCI
        select PPC4xx_PCI_EXPRESS
+       select IBM_NEW_EMAC_RGMII
+       select IBM_NEW_EMAC_ZMII
        help
          This option enables support for the AMCC PPC460EX evaluation board.
 
+config GLACIER
+       bool "Glacier"
+       depends on 44x
+       default n
+       select PPC44x_SIMPLE
+       select 460EX # Odd since it uses 460GT but the effects are the same
+       select PCI
+       select PPC4xx_PCI_EXPRESS
+       select IBM_NEW_EMAC_RGMII
+       select IBM_NEW_EMAC_ZMII
+       help
+         This option enables support for the AMCC PPC460GT evaluation board.
+
 config YOSEMITE
        bool "Yosemite"
        depends on 44x
        default n
+       select PPC44x_SIMPLE
        select 440EP
        select PCI
        help
@@ -127,6 +160,13 @@ config XILINX_VIRTEX440_GENERIC_BOARD
          Most Virtex 5 designs should use this unless it needs to do some
          special configuration at board probe time.
 
+config PPC44x_SIMPLE
+       bool "Simple PowerPC 44x board support"
+       depends on 44x
+       default n
+       help
+         This option enables the simple PowerPC 44x platform support.
+
 # 44x specific CPU modules, selected based on the board above.
 config 440EP
        bool
@@ -170,8 +210,6 @@ config 460EX
        bool
        select PPC_FPU
        select IBM_NEW_EMAC_EMAC4
-       select IBM_NEW_EMAC_RGMII
-       select IBM_NEW_EMAC_ZMII
        select IBM_NEW_EMAC_TAH
 
 # 44x errata/workaround config symbols, selected by the CPU models above
index 8d0b1a192d626826a60dd9c6128b0423b472c60b..698133180aee5da1a35fb8eb4df181edac4b0833 100644 (file)
@@ -1,13 +1,7 @@
 obj-$(CONFIG_44x)      := misc_44x.o idle.o
+obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o
 obj-$(CONFIG_EBONY)    += ebony.o
-obj-$(CONFIG_TAISHAN)  += taishan.o
-obj-$(CONFIG_BAMBOO)   += bamboo.o
-obj-$(CONFIG_YOSEMITE) += bamboo.o
 obj-$(CONFIG_SAM440EP)         += sam440ep.o
-obj-$(CONFIG_SEQUOIA)  += sequoia.o
-obj-$(CONFIG_KATMAI)   += katmai.o
-obj-$(CONFIG_RAINIER)  += rainier.o
 obj-$(CONFIG_WARP)     += warp.o
 obj-$(CONFIG_WARP)     += warp-nand.o
-obj-$(CONFIG_CANYONLANDS) += canyonlands.o
 obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
deleted file mode 100644 (file)
index cef169e..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Bamboo board specific routines
- *
- * Wade Farnsworth <wfarnsworth@mvista.com>
- * Copyright 2004 MontaVista Software Inc.
- *
- * Rewritten and ported to the merged powerpc tree:
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id bamboo_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init bamboo_device_probe(void)
-{
-       of_platform_bus_probe(NULL, bamboo_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(bamboo, bamboo_device_probe);
-
-static int __init bamboo_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,bamboo"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(bamboo) {
-       .name                   = "Bamboo",
-       .probe                  = bamboo_probe,
-       .progress               = udbg_progress,
-       .init_IRQ               = uic_init_tree,
-       .get_irq                = uic_get_irq,
-       .restart                = ppc4xx_reset_system,
-       .calibrate_decr         = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
deleted file mode 100644 (file)
index 3949289..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Canyonlands board specific routines
- *
- * Copyright 2008 DENX Software Engineering, Stefan Roese <sr@denx.de>
- *
- * Based on the Katmai code by
- * Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * Copyright 2007 IBM Corp.
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id canyonlands_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init canyonlands_device_probe(void)
-{
-       of_platform_bus_probe(NULL, canyonlands_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(canyonlands, canyonlands_device_probe);
-
-static int __init canyonlands_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,canyonlands"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(canyonlands) {
-       .name                           = "Canyonlands",
-       .probe                          = canyonlands_probe,
-       .progress                       = udbg_progress,
-       .init_IRQ                       = uic_init_tree,
-       .get_irq                        = uic_get_irq,
-       .restart                        = ppc4xx_reset_system,
-       .calibrate_decr                 = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/katmai.c b/arch/powerpc/platforms/44x/katmai.c
deleted file mode 100644 (file)
index 44f4b3a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Katmai board specific routines
- *
- * Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * Copyright 2007 IBM Corp.
- *
- * Based on the Bamboo code by
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id katmai_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init katmai_device_probe(void)
-{
-       of_platform_bus_probe(NULL, katmai_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(katmai, katmai_device_probe);
-
-static int __init katmai_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,katmai"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(katmai) {
-       .name                           = "Katmai",
-       .probe                          = katmai_probe,
-       .progress                       = udbg_progress,
-       .init_IRQ                       = uic_init_tree,
-       .get_irq                        = uic_get_irq,
-       .restart                        = ppc4xx_reset_system,
-       .calibrate_decr                 = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
new file mode 100644 (file)
index 0000000..2967126
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Generic PowerPC 44x platform support
+ *
+ * Copyright 2008 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; version 2 of the License.
+ *
+ * This implements simple platform support for PowerPC 44x chips.  This is
+ * mostly used for eval boards or other simple and "generic" 44x boards.  If
+ * your board has custom functions or hardware, then you will likely want to
+ * implement your own board.c file to accommodate it.
+ */
+
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc4xx.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+#include <asm/uic.h>
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+
+static __initdata struct of_device_id ppc44x_of_bus[] = {
+       { .compatible = "ibm,plb4", },
+       { .compatible = "ibm,opb", },
+       { .compatible = "ibm,ebc", },
+       { .compatible = "simple-bus", },
+       {},
+};
+
+static int __init ppc44x_device_probe(void)
+{
+       of_platform_bus_probe(NULL, ppc44x_of_bus, NULL);
+
+       return 0;
+}
+machine_device_initcall(ppc44x_simple, ppc44x_device_probe);
+
+/* This is the list of boards that can be supported by this simple
+ * platform code.  This does _not_ mean the boards are compatible,
+ * as they most certainly are not from a device tree perspective.
+ * However, their differences are handled by the device tree and the
+ * drivers and therefore they don't need custom board support files.
+ *
+ * Again, if your board needs to do things differently then create a
+ * board.c file for it rather than adding it to this list.
+ */
+static char *board[] __initdata = {
+       "amcc,arches",
+       "amcc,bamboo",
+       "amcc,canyonlands",
+       "amcc,glacier",
+       "ibm,ebony",
+       "amcc,katmai",
+       "amcc,rainier",
+       "amcc,sequoia",
+       "amcc,taishan",
+       "amcc,yosemite"
+};
+
+static int __init ppc44x_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+       int i = 0;
+
+       for (i = 0; i < ARRAY_SIZE(board); i++) {
+               if (of_flat_dt_is_compatible(root, board[i])) {
+                       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+define_machine(ppc44x_simple) {
+       .name = "PowerPC 44x Platform",
+       .probe = ppc44x_probe,
+       .progress = udbg_progress,
+       .init_IRQ = uic_init_tree,
+       .get_irq = uic_get_irq,
+       .restart = ppc4xx_reset_system,
+       .calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/44x/rainier.c b/arch/powerpc/platforms/44x/rainier.c
deleted file mode 100644 (file)
index 4f1ff84..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Rainier board specific routines
- *
- * Valentine Barshak <vbarshak@ru.mvista.com>
- * Copyright 2007 MontaVista Software Inc.
- *
- * Based on the Bamboo code by
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id rainier_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init rainier_device_probe(void)
-{
-       of_platform_bus_probe(NULL, rainier_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(rainier, rainier_device_probe);
-
-static int __init rainier_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,rainier"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(rainier) {
-       .name                           = "Rainier",
-       .probe                          = rainier_probe,
-       .progress                       = udbg_progress,
-       .init_IRQ                       = uic_init_tree,
-       .get_irq                        = uic_get_irq,
-       .restart                        = ppc4xx_reset_system,
-       .calibrate_decr                 = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
deleted file mode 100644 (file)
index 49eb73d..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Sequoia board specific routines
- *
- * Valentine Barshak <vbarshak@ru.mvista.com>
- * Copyright 2007 MontaVista Software Inc.
- *
- * Based on the Bamboo code by
- * Josh Boyer <jwboyer@linux.vnet.ibm.com>
- * Copyright 2007 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.
- */
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id sequoia_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init sequoia_device_probe(void)
-{
-       of_platform_bus_probe(NULL, sequoia_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(sequoia, sequoia_device_probe);
-
-static int __init sequoia_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,sequoia"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(sequoia) {
-       .name                           = "Sequoia",
-       .probe                          = sequoia_probe,
-       .progress                       = udbg_progress,
-       .init_IRQ                       = uic_init_tree,
-       .get_irq                        = uic_get_irq,
-       .restart                        = ppc4xx_reset_system,
-       .calibrate_decr                 = generic_calibrate_decr,
-};
diff --git a/arch/powerpc/platforms/44x/taishan.c b/arch/powerpc/platforms/44x/taishan.c
deleted file mode 100644 (file)
index 49c78b2..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Taishan board specific routines based off ebony.c code
- * original copyrights below
- *
- * Matt Porter <mporter@kernel.crashing.org>
- * Copyright 2002-2005 MontaVista Software Inc.
- *
- * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003-2005 Zultys Technologies
- *
- * Rewritten and ported to the merged powerpc tree:
- * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
- *
- * Modified from ebony.c for taishan:
- * Copyright 2007 Hugh Blemings <hugh@au.ibm.com>, 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.
- */
-
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/time.h>
-#include <asm/uic.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc4xx.h>
-
-static __initdata struct of_device_id taishan_of_bus[] = {
-       { .compatible = "ibm,plb4", },
-       { .compatible = "ibm,opb", },
-       { .compatible = "ibm,ebc", },
-       {},
-};
-
-static int __init taishan_device_probe(void)
-{
-       of_platform_bus_probe(NULL, taishan_of_bus, NULL);
-
-       return 0;
-}
-machine_device_initcall(taishan, taishan_device_probe);
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init taishan_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "amcc,taishan"))
-               return 0;
-
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
-
-       return 1;
-}
-
-define_machine(taishan) {
-       .name                   = "Taishan",
-       .probe                  = taishan_probe,
-       .progress               = udbg_progress,
-       .init_IRQ               = uic_init_tree,
-       .get_irq                = uic_get_irq,
-       .restart                = ppc4xx_reset_system,
-       .calibrate_decr         = generic_calibrate_decr,
-};
index c62f893ede190f984c6d235304b196651fb3b3c6..326852c78b8fa79caf1349f0e1776b955285a26c 100644 (file)
@@ -3,6 +3,8 @@ config PPC_MPC512x
        select FSL_SOC
        select IPIC
        select PPC_CLOCK
+       select PPC_PCI_CHOICE
+       select FSL_PCI if PCI
 
 config PPC_MPC5121
        bool
index 5ebf6939a6975ba593b1d4b1372a5ebd19c68a11..441abc488851c9f95bf6b674b7198041bf2cd79f 100644 (file)
 #include <asm/prom.h>
 #include <asm/time.h>
 
+#include <sysdev/fsl_pci.h>
+
 #include "mpc512x.h"
 #include "mpc5121_ads.h"
 
 static void __init mpc5121_ads_setup_arch(void)
 {
+#ifdef CONFIG_PCI
+       struct device_node *np;
+#endif
        printk(KERN_INFO "MPC5121 ADS board from Freescale Semiconductor\n");
        /*
         * cpld regs are needed early
         */
        mpc5121_ads_cpld_map();
+
+#ifdef CONFIG_PCI
+       for_each_compatible_node(np, "pci", "fsl,mpc5121-pci")
+               mpc83xx_add_bridge(np);
+#endif
 }
 
 static void __init mpc5121_ads_init_IRQ(void)
index 4d5fd1dbd4007a5235b5b170367e451cc4f40b67..044b4e6e874383a77e31fe5e80d8737a465865c5 100644 (file)
@@ -90,7 +90,7 @@ mpc5200_setup_xlb_arbiter(void)
        of_node_put(np);
        if (!xlb) {
                printk(KERN_ERR __FILE__ ": "
-                       "Error mapping XLB in mpc52xx_setup_cpu().  "
+                       "Error mapping XLB in mpc52xx_setup_cpu(). "
                        "Expect some abnormal behavior\n");
                return;
        }
@@ -216,7 +216,8 @@ mpc52xx_restart(char *cmd)
                out_be32(&mpc52xx_wdt->count, 0x000000ff);
                out_be32(&mpc52xx_wdt->mode, 0x00009004);
        } else
-               printk("mpc52xx_restart: Can't access wdt. "
+               printk(KERN_ERR __FILE__ ": "
+                       "mpc52xx_restart: Can't access wdt. "
                        "Restart impossible, system halted.\n");
 
        while (1);
index 5a382bb15f6266a8c8835c9e8eef4d2951dc84ae..b49a1852766131655a57effc2514439225ba6b9c 100644 (file)
@@ -265,8 +265,11 @@ mpc52xx_pci_setup(struct pci_controller *hose,
        /* Memory windows */
        res = &hose->mem_resources[0];
        if (res->flags) {
-               pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
-                        res->start, res->end, res->flags);
+               pr_debug("mem_resource[0] = "
+                        "{.start=%llx, .end=%llx, .flags=%llx}\n",
+                        (unsigned long long)res->start,
+                        (unsigned long long)res->end,
+                        (unsigned long long)res->flags);
                out_be32(&pci_regs->iw0btar,
                         MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
                                  res->end - res->start + 1));
@@ -297,9 +300,11 @@ mpc52xx_pci_setup(struct pci_controller *hose,
                printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
                return;
        }
-       pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+       pr_debug(".io_resource={.start=%llx,.end=%llx,.flags=%llx} "
                 ".io_base_phys=0x%p\n",
-                res->start, res->end, res->flags, (void*)hose->io_base_phys);
+                (unsigned long long)res->start,
+                (unsigned long long)res->end,
+                (unsigned long long)res->flags, (void*)hose->io_base_phys);
        out_be32(&pci_regs->iw2btar,
                 MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
                                                res->start,
index 75eb1ede54978a26af11f5fc791febbb459aa647..30f008b2f92e825f64cd518defc8bab99a9bb892 100644 (file)
@@ -38,6 +38,14 @@ config EP8248E
          This board is also resold by Freescale as the QUICCStart
          MPC8248 Evaluation System and/or the CWH-PPC-8248N-VE.
 
+config MGCOGE
+       bool "Keymile MGCOGE"
+       select 8272
+       select 8260
+       select FSL_SOC
+       help
+         This enables support for the Keymile MGCOGE board.
+
 endif
 
 config PQ2ADS
index 6cd5cd59bf2a4abaa2d4901b176fe7c5994a86a4..d982793f4dbd111b0535436ee39deb06c1cb40ca 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_CPM2) += pq2.o
 obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
 obj-$(CONFIG_PQ2FADS) += pq2fads.o
 obj-$(CONFIG_EP8248E) += ep8248e.o
+obj-$(CONFIG_MGCOGE) += mgcoge.o
diff --git a/arch/powerpc/platforms/82xx/mgcoge.c b/arch/powerpc/platforms/82xx/mgcoge.c
new file mode 100644 (file)
index 0000000..c2af169
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Keymile mgcoge support
+ * Copyright 2008 DENX Software Engineering GmbH
+ * Author: Heiko Schocher <hs@denx.de>
+ *
+ * based on code from:
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/cpm2.h>
+#include <asm/udbg.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/mpc8260.h>
+#include <asm/prom.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/cpm2_pic.h>
+
+#include "pq2.h"
+
+static void __init mgcoge_pic_init(void)
+{
+       struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
+       if (!np) {
+               printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
+               return;
+       }
+
+       cpm2_pic_init(np);
+       of_node_put(np);
+}
+
+struct cpm_pin {
+       int port, pin, flags;
+};
+
+static __initdata struct cpm_pin mgcoge_pins[] = {
+
+       /* SMC2 */
+       {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {1, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+       /* SCC4 */
+       {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {3, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {3,  9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {3,  8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {4, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+       {4, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+};
+
+static void __init init_ioports(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mgcoge_pins); i++) {
+               const struct cpm_pin *pin = &mgcoge_pins[i];
+               cpm2_set_pin(pin->port - 1, pin->pin, pin->flags);
+       }
+
+       cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+       cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
+       cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
+}
+
+static void __init mgcoge_setup_arch(void)
+{
+       if (ppc_md.progress)
+               ppc_md.progress("mgcoge_setup_arch()", 0);
+
+       cpm2_reset();
+
+       /* When this is set, snooping CPM DMA from RAM causes
+        * machine checks.  See erratum SIU18.
+        */
+       clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
+
+       init_ioports();
+
+       if (ppc_md.progress)
+               ppc_md.progress("mgcoge_setup_arch(), finish", 0);
+}
+
+static  __initdata struct of_device_id of_bus_ids[] = {
+       { .compatible = "simple-bus", },
+       {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+       of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+       return 0;
+}
+machine_device_initcall(mgcoge, declare_of_platform_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mgcoge_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+       return of_flat_dt_is_compatible(root, "keymile,mgcoge");
+}
+
+define_machine(mgcoge)
+{
+       .name = "Keymile MGCOGE",
+       .probe = mgcoge_probe,
+       .setup_arch = mgcoge_setup_arch,
+       .init_IRQ = mgcoge_pic_init,
+       .get_irq = cpm2_get_irq,
+       .calibrate_decr = generic_calibrate_decr,
+       .restart = pq2_restart,
+       .progress = udbg_progress,
+};
index 6159c5d4e5f1335d2fd3e7f44dbe887885dab183..83c664afc897c76023d65e7e4b231e9fa26c0310 100644 (file)
@@ -19,7 +19,6 @@ config MPC831x_RDB
 config MPC832x_MDS
        bool "Freescale MPC832x MDS"
        select DEFAULT_UIMAGE
-       select QUICC_ENGINE
        select PPC_MPC832x
        help
          This option enables support for the MPC832x MDS evaluation board.
@@ -27,7 +26,6 @@ config MPC832x_MDS
 config MPC832x_RDB
        bool "Freescale MPC832x RDB"
        select DEFAULT_UIMAGE
-       select QUICC_ENGINE
        select PPC_MPC832x
        help
          This option enables support for the MPC8323 RDB board.
@@ -57,15 +55,12 @@ config MPC834x_ITX
 config MPC836x_MDS
        bool "Freescale MPC836x MDS"
        select DEFAULT_UIMAGE
-       select QUICC_ENGINE
        help
          This option enables support for the MPC836x MDS Processor Board.
 
 config MPC836x_RDK
        bool "Freescale/Logic MPC836x RDK"
        select DEFAULT_UIMAGE
-       select QUICC_ENGINE
-       select QE_GPIO
        select FSL_GTM
        select FSL_LBC
        help
index be62de23beadc1748a3d391c51578ddb74c0a4fc..8bb13c807142c9155940da690e26cdc6b8de48cc 100644 (file)
@@ -85,8 +85,14 @@ static void __init mpc837x_mds_setup_arch(void)
                ppc_md.progress("mpc837x_mds_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+       for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") {
+               if (!of_device_is_available(np)) {
+                       pr_warning("%s: disabled by the firmware.\n",
+                                  np->full_name);
+                       continue;
+               }
                mpc83xx_add_bridge(np);
+       }
 #endif
        mpc837xmds_usb_cfg();
 }
index 291675b0097a902d620b9f203857d925ce919127..b79dc710ed346483d8201a68984fe06cfecb6dbe 100644 (file)
@@ -33,7 +33,6 @@ config MPC85xx_CDS
 config MPC85xx_MDS
        bool "Freescale MPC85xx MDS"
        select DEFAULT_UIMAGE
-       select QUICC_ENGINE
        select PHYLIB
        help
          This option enables support for the MPC85xx MDS board
index d17807a6b89a141b555a7d31781093239249ec26..0293e3d3580f4bd950835cd18ce0f08455a58644 100644 (file)
@@ -213,7 +213,6 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
        svid = mfspr(SPRN_SVR);
 
        seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
-       seq_printf(m, "Machine\t\t: mpc85xx\n");
        seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 
index 6509ade71668e658729ddb6266217c6ccd8538fe..0c9a856f66b6f7e2c4c918574e958e804d37292d 100644 (file)
@@ -156,7 +156,7 @@ static void __init init_ioports(void)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) {
-               struct cpm_pin *pin = &sbc8560_pins[i];
+               const struct cpm_pin *pin = &sbc8560_pins[i];
                cpm2_set_pin(pin->port, pin->pin, pin->flags);
        }
 
@@ -200,7 +200,6 @@ static void sbc8560_show_cpuinfo(struct seq_file *m)
        svid = mfspr(SPRN_SVR);
 
        seq_printf(m, "Vendor\t\t: Wind River\n");
-       seq_printf(m, "Machine\t\t: SBC8560\n");
        seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 
index 9355a52694314573d9960ccb292ef42d22b7e704..77dd797a2580e73f90dce98b08a20d1ed5313b75 100644 (file)
@@ -31,6 +31,13 @@ config MPC8610_HPCD
        help
          This option enables support for the MPC8610 HPCD board.
 
+config GEF_SBC610
+       bool "GE Fanuc SBC610"
+       select DEFAULT_UIMAGE
+       select HAS_RAPIDIO
+       help
+         This option enables support for GE Fanuc's SBC610.
+
 endif
 
 config MPC8641
@@ -39,7 +46,7 @@ config MPC8641
        select FSL_PCI if PCI
        select PPC_UDBG_16550
        select MPIC
-       default y if MPC8641_HPCN || SBC8641D
+       default y if MPC8641_HPCN || SBC8641D || GEF_SBC610
 
 config MPC8610
        bool
index 8fee37dec79517ffb344f20398e34361df748e34..4a56ff619afdee7fc649c4e17203d73104f6d521 100644 (file)
@@ -7,3 +7,4 @@ obj-$(CONFIG_SMP)               += mpc86xx_smp.o
 obj-$(CONFIG_MPC8641_HPCN)     += mpc86xx_hpcn.o
 obj-$(CONFIG_SBC8641D)         += sbc8641d.o
 obj-$(CONFIG_MPC8610_HPCD)     += mpc8610_hpcd.o
+obj-$(CONFIG_GEF_SBC610)       += gef_sbc610.o gef_pic.o
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
new file mode 100644 (file)
index 0000000..50d0a2b
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Interrupt handling for GE Fanuc's FPGA based PIC
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, 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/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/irq.h>
+
+#include "gef_pic.h"
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0)
+#else
+#define DBG(fmt...) do { } while (0)
+#endif
+
+#define GEF_PIC_NUM_IRQS       32
+
+/* Interrupt Controller Interface Registers */
+#define GEF_PIC_INTR_STATUS    0x0000
+
+#define GEF_PIC_INTR_MASK(cpu) (0x0010 + (0x4 * cpu))
+#define GEF_PIC_CPU0_INTR_MASK GEF_PIC_INTR_MASK(0)
+#define GEF_PIC_CPU1_INTR_MASK GEF_PIC_INTR_MASK(1)
+
+#define GEF_PIC_MCP_MASK(cpu)  (0x0018 + (0x4 * cpu))
+#define GEF_PIC_CPU0_MCP_MASK  GEF_PIC_MCP_MASK(0)
+#define GEF_PIC_CPU1_MCP_MASK  GEF_PIC_MCP_MASK(1)
+
+#define gef_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
+
+
+static DEFINE_SPINLOCK(gef_pic_lock);
+
+static void __iomem *gef_pic_irq_reg_base;
+static struct irq_host *gef_pic_irq_host;
+static int gef_pic_cascade_irq;
+
+/*
+ * Interrupt Controller Handling
+ *
+ * The interrupt controller handles interrupts for most on board interrupts,
+ * apart from PCI interrupts. For example on SBC610:
+ *
+ * 17:31 RO Reserved
+ * 16    RO PCI Express Doorbell 3 Status
+ * 15    RO PCI Express Doorbell 2 Status
+ * 14    RO PCI Express Doorbell 1 Status
+ * 13    RO PCI Express Doorbell 0 Status
+ * 12    RO Real Time Clock Interrupt Status
+ * 11    RO Temperature Interrupt Status
+ * 10    RO Temperature Critical Interrupt Status
+ * 9     RO Ethernet PHY1 Interrupt Status
+ * 8     RO Ethernet PHY3 Interrupt Status
+ * 7     RO PEX8548 Interrupt Status
+ * 6     RO Reserved
+ * 5     RO Watchdog 0 Interrupt Status
+ * 4     RO Watchdog 1 Interrupt Status
+ * 3     RO AXIS Message FIFO A Interrupt Status
+ * 2     RO AXIS Message FIFO B Interrupt Status
+ * 1     RO AXIS Message FIFO C Interrupt Status
+ * 0     RO AXIS Message FIFO D Interrupt Status
+ *
+ * Interrupts can be forwarded to one of two output lines. Nothing
+ * clever is done, so if the masks are incorrectly set, a single input
+ * interrupt could generate interrupts on both output lines!
+ *
+ * The dual lines are there to allow the chained interrupts to be easily
+ * passed into two different cores. We currently do not use this functionality
+ * in this driver.
+ *
+ * Controller can also be configured to generate Machine checks (MCP), again on
+ * two lines, to be attached to two different cores. It is suggested that these
+ * should be masked out.
+ */
+
+void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
+{
+       unsigned int cascade_irq;
+
+       /*
+        * See if we actually have an interrupt, call generic handling code if
+        * we do.
+        */
+       cascade_irq = gef_pic_get_irq();
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       desc->chip->eoi(irq);
+
+}
+
+static void gef_pic_mask(unsigned int virq)
+{
+       unsigned long flags;
+       unsigned int hwirq;
+       u32 mask;
+
+       hwirq = gef_irq_to_hw(virq);
+
+       spin_lock_irqsave(&gef_pic_lock, flags);
+       mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+       mask &= ~(1 << hwirq);
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
+       spin_unlock_irqrestore(&gef_pic_lock, flags);
+}
+
+static void gef_pic_mask_ack(unsigned int virq)
+{
+       /* Don't think we actually have to do anything to ack an interrupt,
+        * we just need to clear down the devices interrupt and it will go away
+        */
+       gef_pic_mask(virq);
+}
+
+static void gef_pic_unmask(unsigned int virq)
+{
+       unsigned long flags;
+       unsigned int hwirq;
+       u32 mask;
+
+       hwirq = gef_irq_to_hw(virq);
+
+       spin_lock_irqsave(&gef_pic_lock, flags);
+       mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+       mask |= (1 << hwirq);
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
+       spin_unlock_irqrestore(&gef_pic_lock, flags);
+}
+
+static struct irq_chip gef_pic_chip = {
+       .typename       = "gefp",
+       .mask           = gef_pic_mask,
+       .mask_ack       = gef_pic_mask_ack,
+       .unmask         = gef_pic_unmask,
+};
+
+
+/* When an interrupt is being configured, this call allows some flexibilty
+ * in deciding which irq_chip structure is used
+ */
+static int gef_pic_host_map(struct irq_host *h, unsigned int virq,
+                         irq_hw_number_t hwirq)
+{
+       /* All interrupts are LEVEL sensitive */
+       get_irq_desc(virq)->status |= IRQ_LEVEL;
+       set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
+
+       return 0;
+}
+
+static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+                           u32 *intspec, unsigned int intsize,
+                           irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+
+       *out_hwirq = intspec[0];
+       if (intsize > 1)
+               *out_flags = intspec[1];
+       else
+               *out_flags = IRQ_TYPE_LEVEL_HIGH;
+
+       return 0;
+}
+
+static struct irq_host_ops gef_pic_host_ops = {
+       .map    = gef_pic_host_map,
+       .xlate  = gef_pic_host_xlate,
+};
+
+
+/*
+ * Initialisation of PIC, this should be called in BSP
+ */
+void __init gef_pic_init(struct device_node *np)
+{
+       unsigned long flags;
+
+       /* Map the devices registers into memory */
+       gef_pic_irq_reg_base = of_iomap(np, 0);
+
+       spin_lock_irqsave(&gef_pic_lock, flags);
+
+       /* Initialise everything as masked. */
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0);
+
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
+       out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
+
+       spin_unlock_irqrestore(&gef_pic_lock, flags);
+
+       /* Map controller */
+       gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
+       if (gef_pic_cascade_irq == NO_IRQ) {
+               printk(KERN_ERR "SBC610: failed to map cascade interrupt");
+               return;
+       }
+
+       /* Setup an irq_host structure */
+       gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+                                         GEF_PIC_NUM_IRQS,
+                                         &gef_pic_host_ops, NO_IRQ);
+       if (gef_pic_irq_host == NULL)
+               return;
+
+       /* Chain with parent controller */
+       set_irq_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
+}
+
+/*
+ * This is called when we receive an interrupt with apparently comes from this
+ * chip - check, returning the highest interrupt generated or return NO_IRQ
+ */
+unsigned int gef_pic_get_irq(void)
+{
+       u32 cause, mask, active;
+       unsigned int virq = NO_IRQ;
+       int hwirq;
+
+       cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS);
+
+       mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
+
+       active = cause & mask;
+
+       if (active) {
+               for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) {
+                       if (active & (0x1 << hwirq))
+                               break;
+               }
+               virq = irq_linear_revmap(gef_pic_irq_host,
+                       (irq_hw_number_t)hwirq);
+       }
+
+       return virq;
+}
+
diff --git a/arch/powerpc/platforms/86xx/gef_pic.h b/arch/powerpc/platforms/86xx/gef_pic.h
new file mode 100644 (file)
index 0000000..6149916
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __GEF_PIC_H__
+#define __GEF_PIC_H__
+
+#include <linux/init.h>
+
+void gef_pic_cascade(unsigned int, struct irq_desc *);
+unsigned int gef_pic_get_irq(void);
+void gef_pic_init(struct device_node *);
+
+#endif /* __GEF_PIC_H__ */
+
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
new file mode 100644 (file)
index 0000000..821c45f
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * GE Fanuc SBC610 board support
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+#include "gef_pic.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "SBC610: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *sbc610_regs;
+
+static void __init gef_sbc610_init_irq(void)
+{
+       struct device_node *cascade_node = NULL;
+
+       mpc86xx_init_irq();
+
+       /*
+        * There is a simple interrupt handler in the main FPGA, this needs
+        * to be cascaded into the MPIC
+        */
+       cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
+       if (!cascade_node) {
+               printk(KERN_WARNING "SBC610: No FPGA PIC\n");
+               return;
+       }
+
+       gef_pic_init(cascade_node);
+       of_node_put(cascade_node);
+}
+
+static void __init gef_sbc610_setup_arch(void)
+{
+       struct device_node *regs;
+#ifdef CONFIG_PCI
+       struct device_node *np;
+
+       for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
+               fsl_add_bridge(np, 1);
+       }
+#endif
+
+       printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC610 6U VPX SBC\n");
+
+#ifdef CONFIG_SMP
+       mpc86xx_smp_init();
+#endif
+
+       /* Remap basic board registers */
+       regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
+       if (regs) {
+               sbc610_regs = of_iomap(regs, 0);
+               if (sbc610_regs == NULL)
+                       printk(KERN_WARNING "Unable to map board registers\n");
+               of_node_put(regs);
+       }
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc610_get_pcb_rev(void)
+{
+       unsigned int reg;
+
+       reg = ioread32(sbc610_regs);
+       return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_sbc610_get_board_rev(void)
+{
+       unsigned int reg;
+
+       reg = ioread32(sbc610_regs);
+       return (reg >> 16) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_sbc610_get_fpga_rev(void)
+{
+       unsigned int reg;
+
+       reg = ioread32(sbc610_regs);
+       return (reg >> 24) & 0xf;
+}
+
+static void gef_sbc610_show_cpuinfo(struct seq_file *m)
+{
+       uint memsize = total_memory;
+       uint svid = mfspr(SPRN_SVR);
+
+       seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+
+       seq_printf(m, "Revision\t: %u%c\n", gef_sbc610_get_pcb_rev(),
+               ('A' + gef_sbc610_get_board_rev() - 1));
+       seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc610_get_fpga_rev());
+
+       seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+       seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev)
+{
+       unsigned int val;
+
+       printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+       /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
+       pci_read_config_dword(pdev, 0xe0, &val);
+       pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x5);
+
+       /* System clock is 48-MHz Oscillator and EHCI Enabled. */
+       pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+       gef_sbc610_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_sbc610_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (of_flat_dt_is_compatible(root, "gef,sbc610"))
+               return 1;
+
+       return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+       unsigned int temp;
+
+       /* Set the time base to zero */
+       mtspr(SPRN_TBWL, 0);
+       mtspr(SPRN_TBWU, 0);
+
+       temp = mfspr(SPRN_HID0);
+       temp |= HID0_TBEN;
+       mtspr(SPRN_HID0, temp);
+       asm volatile("isync");
+
+       return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+       { .compatible = "simple-bus", },
+       {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+       printk(KERN_DEBUG "Probe platform devices\n");
+       of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+       return 0;
+}
+machine_device_initcall(gef_sbc610, declare_of_platform_devices);
+
+define_machine(gef_sbc610) {
+       .name                   = "GE Fanuc SBC610",
+       .probe                  = gef_sbc610_probe,
+       .setup_arch             = gef_sbc610_setup_arch,
+       .init_IRQ               = gef_sbc610_init_irq,
+       .show_cpuinfo           = gef_sbc610_show_cpuinfo,
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .time_init              = mpc86xx_time_init,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+};
index 5eedb710896e7568b8fc29cb1c78b1f7f5def81b..e8d54ac5292c3ec972497fc1ee1b4178915e0345 100644 (file)
@@ -238,7 +238,6 @@ static void __init mpc86xx_hpcd_setup_arch(void)
         }
 #endif
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-       preallocate_diu_videomemory();
        diu_ops.get_pixel_format        = mpc8610hpcd_get_pixel_format;
        diu_ops.set_gamma_table         = mpc8610hpcd_set_gamma_table;
        diu_ops.set_monitor_port        = mpc8610hpcd_set_monitor_port;
index f712d9c0991be7ef9c6c0cc3cdccec2e98e1094e..2672829a71dc400397d3adefc84cb5dcbc15ffd5 100644 (file)
@@ -101,19 +101,11 @@ mpc86xx_hpcn_setup_arch(void)
 static void
 mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
 {
-       struct device_node *root;
        uint memsize = total_memory;
-       const char *model = "";
        uint svid = mfspr(SPRN_SVR);
 
        seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
 
-       root = of_find_node_by_path("/");
-       if (root)
-               model = of_get_property(root, "model", NULL);
-       seq_printf(m, "Machine\t\t: %s\n", model);
-       of_node_put(root);
-
        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
        seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 }
index 00e6fad3b3ca99f155350617d8838f33abe1069a..da677a74e2d110068ca8608cc064645be0625e88 100644 (file)
@@ -63,19 +63,11 @@ sbc8641_setup_arch(void)
 static void
 sbc8641_show_cpuinfo(struct seq_file *m)
 {
-       struct device_node *root;
        uint memsize = total_memory;
-       const char *model = "";
        uint svid = mfspr(SPRN_SVR);
 
        seq_printf(m, "Vendor\t\t: Wind River Systems\n");
 
-       root = of_find_node_by_path("/");
-       if (root)
-               model = of_get_property(root, "model", NULL);
-       seq_printf(m, "Machine\t\t: %s\n", model);
-       of_node_put(root);
-
        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
        seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 }
index 71d7562e190be1120090b04d1ac547173812af73..48a920a98e7bff033c07070f3d68f1ec8ccafcc7 100644 (file)
@@ -49,6 +49,12 @@ config PPC_ADDER875
          This enables support for the Analogue & Micro Adder 875
          board.
 
+config PPC_MGSUVD
+       bool "MGSUVD"
+       select CPM1
+       help
+         This enables support for the Keymile MGSUVD board.
+
 endchoice
 
 menu "Freescale Ethernet driver platform-specific options"
index 7b71d9c8fb457e1e59444553572f61c83d50164d..bdbfd74960188ae6c39b2fd0c057a3b061154f4a 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_MPC885ADS)   += mpc885ads_setup.o
 obj-$(CONFIG_MPC86XADS)   += mpc86xads_setup.o
 obj-$(CONFIG_PPC_EP88XC)  += ep88xc.o
 obj-$(CONFIG_PPC_ADDER875) += adder875.o
+obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o
diff --git a/arch/powerpc/platforms/8xx/mgsuvd.c b/arch/powerpc/platforms/8xx/mgsuvd.c
new file mode 100644 (file)
index 0000000..ca3cb07
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *
+ * Platform setup for the Keymile mgsuvd board
+ *
+ * Heiko Schocher <hs@denx.de>
+ *
+ * Copyright 2008 DENX Software Engineering GmbH
+ *
+ * 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/ioport.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/processor.h>
+#include <asm/cpm1.h>
+#include <asm/prom.h>
+#include <asm/fs_pd.h>
+
+#include "mpc8xx.h"
+
+struct cpm_pin {
+       int port, pin, flags;
+};
+
+static __initdata struct cpm_pin mgsuvd_pins[] = {
+       /* SMC1 */
+       {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
+       {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
+
+       /* SCC3 */
+       {CPM_PORTA, 10, CPM_PIN_INPUT},
+       {CPM_PORTA, 11, CPM_PIN_INPUT},
+       {CPM_PORTA, 3, CPM_PIN_INPUT},
+       {CPM_PORTA, 2, CPM_PIN_INPUT},
+       {CPM_PORTC, 13, CPM_PIN_INPUT},
+};
+
+static void __init init_ioports(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mgsuvd_pins); i++) {
+               struct cpm_pin *pin = &mgsuvd_pins[i];
+               cpm1_set_pin(pin->port, pin->pin, pin->flags);
+       }
+
+       setbits16(&mpc8xx_immr->im_ioport.iop_pcso, 0x300);
+       cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RX);
+       cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_TX);
+       cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
+}
+
+static void __init mgsuvd_setup_arch(void)
+{
+       cpm_reset();
+       init_ioports();
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+       { .compatible = "simple-bus" },
+       {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+       of_platform_bus_probe(NULL, of_bus_ids, NULL);
+       return 0;
+}
+machine_device_initcall(mgsuvd, declare_of_platform_devices);
+
+static int __init mgsuvd_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+       return of_flat_dt_is_compatible(root, "keymile,mgsuvd");
+}
+
+define_machine(mgsuvd) {
+       .name           = "MGSUVD",
+       .probe          = mgsuvd_probe,
+       .setup_arch     = mgsuvd_setup_arch,
+       .init_IRQ       = mpc8xx_pics_init,
+       .get_irq        = mpc8xx_get_irq,
+       .restart        = mpc8xx_restart,
+       .calibrate_decr = mpc8xx_calibrate_decr,
+       .set_rtc_time   = mpc8xx_set_rtc_time,
+       .get_rtc_time   = mpc8xx_get_rtc_time,
+};
index 4c900efa164e43fcd4331bddc81b925e35ad77c8..47e956c871fe8cfc3aea613e5a1552771eccb9b4 100644 (file)
@@ -239,7 +239,8 @@ config TAU_AVERAGE
          If in doubt, say N here.
 
 config QUICC_ENGINE
-       bool
+       bool "Freescale QUICC Engine (QE) Support"
+       depends on FSL_SOC
        select PPC_LIB_RHEAP
        select CRC32
        help
@@ -248,6 +249,15 @@ config QUICC_ENGINE
          Selecting this option means that you wish to build a kernel
          for a machine with a QE coprocessor.
 
+config QE_GPIO
+       bool "QE GPIO support"
+       depends on QUICC_ENGINE
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Say Y here if you're going to use hardware that connects to the
+         QE GPIOs.
+
 config CPM2
        bool "Enable support for the CPM2 (Communications Processor Module)"
        depends on MPC85xx || 8260
@@ -293,4 +303,13 @@ config OF_RTC
 
 source "arch/powerpc/sysdev/bestcomm/Kconfig"
 
+config MPC8xxx_GPIO
+       bool "MPC8xxx GPIO support"
+       depends on PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || PPC_85xx || PPC_86xx
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Say Y here if you're going to use hardware that connects to the
+         MPC831x/834x/837x/8572/8610 GPIOs.
+
 endmenu
index 7f6512733862b02138f4e0370a994a223a1e9a07..548efa55c8fe590b4b10674488a709563e51108f 100644 (file)
@@ -50,6 +50,7 @@ config 44x
        select PPC_UDBG_16550
        select 4xx_SOC
        select PPC_PCI_CHOICE
+       select PHYS_64BIT
 
 config E200
        bool "Freescale e200"
@@ -128,18 +129,19 @@ config FSL_EMB_PERFMON
 
 config PTE_64BIT
        bool
-       depends on 44x || E500
-       default y if 44x
-       default y if E500 && PHYS_64BIT
+       depends on 44x || E500 || PPC_86xx
+       default y if PHYS_64BIT
 
 config PHYS_64BIT
-       bool 'Large physical address support' if E500
-       depends on 44x || E500
-       select RESOURCES_64BIT
-       default y if 44x
+       bool 'Large physical address support' if E500 || PPC_86xx
+       depends on (44x || E500 || PPC_86xx) && !PPC_83xx && !PPC_82xx
        ---help---
          This option enables kernel support for larger than 32-bit physical
-         addresses.  This features is not be available on all e500 cores.
+         addresses.  This feature may not be available on all cores.
+
+         If you have more than 3.5GB of RAM or so, you also need to enable
+         SWIOTLB under Kernel Options for this to work.  The actual number
+         is platform-dependent.
 
          If in doubt, say N here.
 
index e06420af5fe9116cd007645594ee6cd0a962a6ea..ef92e71462151efc9e97c26c0c7442ad7a8c4caf 100644 (file)
@@ -556,11 +556,11 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
         * node's iommu. We -might- do something smarter later though it may
         * never be necessary
         */
-       iommu = cell_iommu_for_node(archdata->numa_node);
+       iommu = cell_iommu_for_node(dev_to_node(dev));
        if (iommu == NULL || list_empty(&iommu->windows)) {
                printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
                       archdata->of_node ? archdata->of_node->full_name : "?",
-                      archdata->numa_node);
+                      dev_to_node(dev));
                return NULL;
        }
        window = list_entry(iommu->windows.next, struct iommu_window, list);
@@ -577,7 +577,7 @@ static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
                return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
                                            size, dma_handle,
                                            device_to_mask(dev), flag,
-                                           dev->archdata.numa_node);
+                                           dev_to_node(dev));
        else
                return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
                                                     flag);
index 690ca7b0dcf68e5f96562efef97b092b4a5433c6..cb85d237e492b7156745acc396f308fd99068a34 100644 (file)
@@ -298,8 +298,8 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
 
        d_instantiate(dentry, inode);
        dget(dentry);
-       dir->i_nlink++;
-       dentry->d_inode->i_nlink++;
+       inc_nlink(dir);
+       inc_nlink(dentry->d_inode);
        goto out;
 
 out_free_ctx:
@@ -496,6 +496,8 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
        ret = spufs_context_open(dget(dentry), mntget(mnt));
        if (ret < 0) {
                WARN_ON(spufs_rmdir(inode, dentry));
+               if (affinity)
+                       mutex_unlock(&gang->aff_mutex);
                mutex_unlock(&inode->i_mutex);
                spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
                goto out;
@@ -538,8 +540,8 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
        inode->i_fop = &simple_dir_operations;
 
        d_instantiate(dentry, inode);
-       dir->i_nlink++;
-       dentry->d_inode->i_nlink++;
+       inc_nlink(dir);
+       inc_nlink(dentry->d_inode);
        return ret;
 
 out_iput:
@@ -659,7 +661,7 @@ enum {
        Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err,
 };
 
-static match_table_t spufs_tokens = {
+static const match_table_t spufs_tokens = {
        { Opt_uid,   "uid=%d" },
        { Opt_gid,   "gid=%d" },
        { Opt_mode,  "mode=%o" },
@@ -755,6 +757,7 @@ spufs_create_root(struct super_block *sb, void *data)
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        SPUFS_I(inode)->i_ctx = NULL;
+       inc_nlink(inode);
 
        ret = -EINVAL;
        if (!spufs_parse_options(sb, data, inode))
index 768c262b936891eeaebb361a1c2612e8ef429588..d3cde6b9d2df68046eaa41512676ed50fea78c66 100644 (file)
@@ -260,13 +260,13 @@ chrp_find_bridges(void)
                                dev->full_name);
                        continue;
                }
-               hose->first_busno = bus_range[0];
+               hose->first_busno = hose->self_busno = bus_range[0];
                hose->last_busno = bus_range[1];
 
                model = of_get_property(dev, "model", NULL);
                if (model == NULL)
                        model = "<none>";
-               if (of_device_is_compatible(dev, "IBM,python")) {
+               if (strncmp(model, "IBM, Python", 11) == 0) {
                        setup_python(hose, dev);
                } else if (is_mot
                           || strncmp(model, "Motorola, Grackle", 17) == 0) {
index 1ba7ce5aafaed24ef6cae57e36dcd21d454c1d94..272d79a8d2896ade7f8f36e22f2b6279077f6793 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/ptrace.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>
index 96d1e4b3c493f8628049891f8f54d1813e8cadaa..054dfe5b8e77f39c27d88c70ebcd4295d642bcd0 100644 (file)
@@ -94,12 +94,12 @@ int chrp_set_rtc_time(struct rtc_time *tmarg)
        chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(tm.tm_sec);
-               BIN_TO_BCD(tm.tm_min);
-               BIN_TO_BCD(tm.tm_hour);
-               BIN_TO_BCD(tm.tm_mon);
-               BIN_TO_BCD(tm.tm_mday);
-               BIN_TO_BCD(tm.tm_year);
+               tm.tm_sec = bin2bcd(tm.tm_sec);
+               tm.tm_min = bin2bcd(tm.tm_min);
+               tm.tm_hour = bin2bcd(tm.tm_hour);
+               tm.tm_mon = bin2bcd(tm.tm_mon);
+               tm.tm_mday = bin2bcd(tm.tm_mday);
+               tm.tm_year = bin2bcd(tm.tm_year);
        }
        chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
        chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
@@ -136,12 +136,12 @@ void chrp_get_rtc_time(struct rtc_time *tm)
        } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
 
        if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
        }
        if (year < 70)
                year += 100;
index 84e2d78b9a627020848a9b1c8264b8a06d0c4b47..7a2ba39d7811a101b1fa14439e087a67b85e2e29 100644 (file)
@@ -164,7 +164,6 @@ static void __init mpc7448_hpc2_init_IRQ(void)
 void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
 {
        seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
-       seq_printf(m, "machine\t\t: MPC7448hpc2\n");
 }
 
 void mpc7448_hpc2_restart(char *cmd)
index 8ff330d026ca686c462b30e8085ae7d7fd701340..2f581521eb9ba9b2e93707eee069cd18a9e322e1 100644 (file)
 
        .globl system_reset_iSeries
 system_reset_iSeries:
+       bl      .relative_toc
        mfspr   r13,SPRN_SPRG3          /* Get alpaca address */
-       LOAD_REG_IMMEDIATE(r23, alpaca)
+       LOAD_REG_ADDR(r23, alpaca)
        li      r0,ALPACA_SIZE
        sub     r23,r13,r23
        divdu   r23,r23,r0              /* r23 has cpu number */
-       LOAD_REG_IMMEDIATE(r13, paca)
+       LOAD_REG_ADDR(r13, paca)
        mulli   r0,r23,PACA_SIZE
        add     r13,r13,r0
        mtspr   SPRN_SPRG3,r13          /* Save it away for the future */
@@ -60,14 +61,14 @@ system_reset_iSeries:
        mtspr   SPRN_CTRLT,r4
 
 /* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
-/* In the UP case we'll yeild() later, and we will not access the paca anyway */
+/* In the UP case we'll yield() later, and we will not access the paca anyway */
 #ifdef CONFIG_SMP
 1:
        HMT_LOW
-       LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
+       LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
        ld      r23,0(r23)
        sync
-       LOAD_REG_IMMEDIATE(r3,current_set)
+       LOAD_REG_ADDR(r3,current_set)
        sldi    r28,r24,3               /* get current_set[cpu#] */
        ldx     r3,r3,r28
        addi    r1,r3,THREAD_SIZE
@@ -90,7 +91,7 @@ system_reset_iSeries:
        lbz     r23,PACAPROCSTART(r13)  /* Test if this processor
                                         * should start */
        sync
-       LOAD_REG_IMMEDIATE(r3,current_set)
+       LOAD_REG_ADDR(r3,current_set)
        sldi    r28,r24,3               /* get current_set[cpu#] */
        ldx     r3,r3,r28
        addi    r1,r3,THREAD_SIZE
@@ -255,8 +256,8 @@ hardware_interrupt_iSeries_masked:
 
 _INIT_STATIC(__start_initialization_iSeries)
        /* Clear out the BSS */
-       LOAD_REG_IMMEDIATE(r11,__bss_stop)
-       LOAD_REG_IMMEDIATE(r8,__bss_start)
+       LOAD_REG_ADDR(r11,__bss_stop)
+       LOAD_REG_ADDR(r8,__bss_start)
        sub     r11,r11,r8              /* bss size                     */
        addi    r11,r11,7               /* round up to an even double word */
        rldicl. r11,r11,61,3            /* shift right by 3             */
@@ -267,15 +268,11 @@ _INIT_STATIC(__start_initialization_iSeries)
 3:     stdu    r0,8(r8)
        bdnz    3b
 4:
-       LOAD_REG_IMMEDIATE(r1,init_thread_union)
+       LOAD_REG_ADDR(r1,init_thread_union)
        addi    r1,r1,THREAD_SIZE
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
 
-       LOAD_REG_IMMEDIATE(r2,__toc_start)
-       addi    r2,r2,0x4000
-       addi    r2,r2,0x4000
-
        bl      .iSeries_early_setup
        bl      .early_setup
 
index 731d7b157749e29547c0a615e66b35e0329ea72d..3689c2413d24d758faf9bd9bda5c41400d1b6b71 100644 (file)
@@ -722,13 +722,13 @@ static int mf_set_rtc(struct rtc_time *tm)
        day = tm->tm_mday;
        mon = tm->tm_mon + 1;
 
-       BIN_TO_BCD(sec);
-       BIN_TO_BCD(min);
-       BIN_TO_BCD(hour);
-       BIN_TO_BCD(mon);
-       BIN_TO_BCD(day);
-       BIN_TO_BCD(y1);
-       BIN_TO_BCD(y2);
+       sec = bin2bcd(sec);
+       min = bin2bcd(min);
+       hour = bin2bcd(hour);
+       mon = bin2bcd(mon);
+       day = bin2bcd(day);
+       y1 = bin2bcd(y1);
+       y2 = bin2bcd(y2);
 
        memset(ce_time, 0, sizeof(ce_time));
        ce_time[3] = 0x41;
@@ -777,12 +777,12 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
                u8 day = ce_msg[10];
                u8 mon = ce_msg[11];
 
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
 
                if (year <= 69)
                        year += 100;
index 364714757cf1a633093a30ef935ca4f4ae5fd762..d4c61c3c9669fabaf76f7f48670f30a7427a7abd 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/string.h>
 #include <linux/delay.h>
index 53bca132fb484d413aa27020a8596f58a9409cf6..eac569dee27cc0d576069ddbd933520121ff681d 100644 (file)
@@ -68,12 +68,12 @@ void maple_get_rtc_time(struct rtc_time *tm)
 
        if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
            || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(tm->tm_sec);
-               BCD_TO_BIN(tm->tm_min);
-               BCD_TO_BIN(tm->tm_hour);
-               BCD_TO_BIN(tm->tm_mday);
-               BCD_TO_BIN(tm->tm_mon);
-               BCD_TO_BIN(tm->tm_year);
+               tm->tm_sec = bcd2bin(tm->tm_sec);
+               tm->tm_min = bcd2bin(tm->tm_min);
+               tm->tm_hour = bcd2bin(tm->tm_hour);
+               tm->tm_mday = bcd2bin(tm->tm_mday);
+               tm->tm_mon = bcd2bin(tm->tm_mon);
+               tm->tm_year = bcd2bin(tm->tm_year);
          }
        if ((tm->tm_year + 1900) < 1970)
                tm->tm_year += 100;
@@ -104,12 +104,12 @@ int maple_set_rtc_time(struct rtc_time *tm)
        year = tm->tm_year;
 
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(sec);
-               BIN_TO_BCD(min);
-               BIN_TO_BCD(hour);
-               BIN_TO_BCD(mon);
-               BIN_TO_BCD(mday);
-               BIN_TO_BCD(year);
+               sec = bin2bcd(sec);
+               min = bin2bcd(min);
+               hour = bin2bcd(hour);
+               mon = bin2bcd(mon);
+               mday = bin2bcd(mday);
+               year = bin2bcd(year);
        }
        maple_clock_write(sec, RTC_SECONDS);
        maple_clock_write(min, RTC_MINUTES);
index 5169ecc37123c07edd3a3344d37434031923eea9..e6c0040ee79752c9721d5b69fbb29dd057de42ef 100644 (file)
@@ -2677,7 +2677,7 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
        macio_chips[i].of_node  = node;
        macio_chips[i].type     = type;
        macio_chips[i].base     = base;
-       macio_chips[i].flags    = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+       macio_chips[i].flags    = MACIO_FLAG_SCCA_ON | MACIO_FLAG_SCCB_ON;
        macio_chips[i].name     = macio_names[type];
        revp = of_get_property(node, "revision-id", NULL);
        if (revp)
index 88ccf3a08a9c387ef13ac373d3f08e2368460350..82c14d203d8bcc92dfc7e4ba46a96ea16177cb8e 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/string.h>
 #include <linux/delay.h>
index 4ae3d00e0bdd9bc98dde1368cd2abc226e6cf1d9..40f72c2a4699f101dbe90f17abbb2e0d31ab54fd 100644 (file)
@@ -787,7 +787,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
 {
        unsigned int save_vector;
        unsigned long target, flags;
-       unsigned int *vector = (unsigned int *)(KERNELBASE+0x100);
+       unsigned int *vector = (unsigned int *)(PAGE_OFFSET+0x100);
 
        if (nr < 0 || nr > 3)
                return;
@@ -801,7 +801,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
        save_vector = *vector;
 
        /* Setup fake reset vector that does
-        *   b __secondary_start_pmac_0 + nr*8 - KERNELBASE
+        *   b __secondary_start_pmac_0 + nr*8
         */
        target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
        patch_branch(vector, target, BRANCH_SET_LINK);
index bbbefd64ab5991f3c30c5e7d34a074a3e224d326..59eb840d8ce20782c7cf5809dc46356e2651244c 100644 (file)
@@ -93,11 +93,14 @@ static void to_rtc_time(unsigned long now, struct rtc_time *tm)
 }
 #endif
 
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) || \
+    defined(CONFIG_PMAC_SMU)
 static unsigned long from_rtc_time(struct rtc_time *tm)
 {
        return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
                      tm->tm_hour, tm->tm_min, tm->tm_sec);
 }
+#endif
 
 #ifdef CONFIG_ADB_CUDA
 static unsigned long cuda_get_time(void)
index 280ee88cb0b001c21449c18694d498a9c58e6de0..a789bf58ca8b83bb60b98de3d2641cab5b52705c 100644 (file)
@@ -762,7 +762,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
        };
 
        dev->core.archdata.of_node = NULL;
-       dev->core.archdata.numa_node = 0;
+       set_dev_node(&dev->core, 0);
 
        pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
 
index 38fe32a7cc7007b2c3a24a5ed688db7c1a9d7dd2..5cd4d276162085f43177ac56d7effb162dcdb090 100644 (file)
@@ -121,7 +121,7 @@ static long cmm_alloc_pages(long nr)
                        npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN |
                                                                       __GFP_NORETRY | __GFP_NOMEMALLOC);
                        if (!npa) {
-                               pr_info("%s: Can not allocate new page list\n", __FUNCTION__);
+                               pr_info("%s: Can not allocate new page list\n", __func__);
                                free_page(addr);
                                break;
                        }
@@ -138,7 +138,7 @@ static long cmm_alloc_pages(long nr)
                }
 
                if ((rc = plpar_page_set_loaned(__pa(addr)))) {
-                       pr_err("%s: Can not set page to loaned. rc=%ld\n", __FUNCTION__, rc);
+                       pr_err("%s: Can not set page to loaned. rc=%ld\n", __func__, rc);
                        spin_unlock(&cmm_lock);
                        free_page(addr);
                        break;
index 8c1ca477c52cb9164f93ecb03ac698926fccfe98..0ad56ff7b4a04cdd2c024fd4414a39d0f6ac5196 100644 (file)
@@ -41,7 +41,7 @@ static inline const char * pcid_name (struct pci_dev *pdev)
        return "";
 }
 
-#ifdef DEBUG
+#if 0
 static void print_device_node_tree(struct pci_dn *pdn, int dent)
 {
        int i;
index a1a368dd2d992adb57f4b99942ffdb1e6e55a87b..140d02a5232af273b617a464fa08052438266262 100644 (file)
@@ -21,7 +21,7 @@ static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size)
        struct zone *zone;
        int ret;
 
-       start_pfn = base >> PFN_SECTION_SHIFT;
+       start_pfn = base >> PAGE_SHIFT;
        zone = page_zone(pfn_to_page(start_pfn));
 
        /*
index 7637bd38c7957d77d50d01c5f70a8597f3a4ddad..c591a25b0b0d816d7e3f3c206c205ece673ea871 100644 (file)
@@ -466,11 +466,11 @@ static int do_update_property(char *buf, size_t bufsize)
                else
                        action = PSERIES_DRCONF_MEM_REMOVE;
 
-               blocking_notifier_call_chain(&pSeries_reconfig_chain,
-                                            action, value);
+               rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+                                                 action, value);
        }
 
-       return 0;
+       return rc;
 }
 
 /**
index c9ffd8c225f1a7b1b2e852bf86899bd8d785e3b4..f4e55be2eea948548837177f432e893175960391 100644 (file)
@@ -295,19 +295,29 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
        if (!tmp)
                return -ENOMEM;
 
-
        spin_lock_irqsave(&rtasd_log_lock, s);
        /* if it's 0, then we know we got the last one (the one in NVRAM) */
-       if (rtas_log_size == 0 && logging_enabled)
-               nvram_clear_error_log();
-       spin_unlock_irqrestore(&rtasd_log_lock, s);
+       while (rtas_log_size == 0) {
+               if (file->f_flags & O_NONBLOCK) {
+                       spin_unlock_irqrestore(&rtasd_log_lock, s);
+                       error = -EAGAIN;
+                       goto out;
+               }
 
+               if (!logging_enabled) {
+                       spin_unlock_irqrestore(&rtasd_log_lock, s);
+                       error = -ENODATA;
+                       goto out;
+               }
+               nvram_clear_error_log();
 
-       error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
-       if (error)
-               goto out;
+               spin_unlock_irqrestore(&rtasd_log_lock, s);
+               error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
+               if (error)
+                       goto out;
+               spin_lock_irqsave(&rtasd_log_lock, s);
+       }
 
-       spin_lock_irqsave(&rtasd_log_lock, s);
        offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK);
        memcpy(tmp, &rtas_log_buf[offset], count);
 
index 7b01d67b4e48ca40dd4d053ae02a59edc702b326..ec341707e41b2fc7891173afc60298f8017107b4 100644 (file)
@@ -25,7 +25,6 @@
 #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>
index 9d8f8c84ab8900e0d661118addbc551bb2c3714d..e00f96baa38160f3b9e5773e88d5d04ab2da7df7 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/paca.h>
 #include <asm/time.h>
 #include <asm/machdep.h>
-#include "xics.h"
 #include <asm/cputable.h>
 #include <asm/firmware.h>
 #include <asm/system.h>
@@ -49,6 +48,7 @@
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
+#include "xics.h"
 
 
 /*
@@ -105,36 +105,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 }
 
 #ifdef CONFIG_XICS
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-       set_bit(msg, &xics_ipi_message[cpu].value);
-       mb();
-       xics_cause_IPI(cpu);
-}
-
-static void smp_xics_message_pass(int target, int msg)
-{
-       unsigned int i;
-
-       if (target < NR_CPUS) {
-               smp_xics_do_message(target, msg);
-       } else {
-               for_each_online_cpu(i) {
-                       if (target == MSG_ALL_BUT_SELF
-                           && i == smp_processor_id())
-                               continue;
-                       smp_xics_do_message(i, msg);
-               }
-       }
-}
-
-static int __init smp_xics_probe(void)
-{
-       xics_request_IPIs();
-
-       return cpus_weight(cpu_possible_map);
-}
-
 static void __devinit smp_xics_setup_cpu(int cpu)
 {
        if (cpu != boot_cpuid)
index 0fc830f576f5532870157af81cdaf4c65625b67d..e1904774a70fecd21673f6e899d89251905f91d3 100644 (file)
@@ -9,32 +9,30 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-
 #include <linux/types.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/signal.h>
 #include <linux/init.h>
-#include <linux/gfp.h>
 #include <linux/radix-tree.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
 
 #include <asm/firmware.h>
-#include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/smp.h>
 #include <asm/rtas.h>
 #include <asm/hvcall.h>
 #include <asm/machdep.h>
-#include <asm/i8259.h>
 
 #include "xics.h"
 #include "plpar_wrappers.h"
 
+static struct irq_host *xics_host;
+
 #define XICS_IPI               2
 #define XICS_IRQ_SPURIOUS      0
 
  */
 #define IPI_PRIORITY           4
 
+static unsigned int default_server = 0xFF;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
+
+/* RTAS service tokens */
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
+
+
+/* Direct hardware low level accessors */
+
+/* The part of the interrupt presentation layer that we care about */
 struct xics_ipl {
        union {
                u32 word;
@@ -65,27 +77,6 @@ struct xics_ipl {
 
 static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 
-static unsigned int default_server = 0xFF;
-static unsigned int default_distrib_server = 0;
-static unsigned int interrupt_server_size = 8;
-
-static struct irq_host *xics_host;
-
-/*
- * XICS only has a single IPI, so encode the messages per CPU
- */
-struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
-
-/* RTAS service tokens */
-static int ibm_get_xive;
-static int ibm_set_xive;
-static int ibm_int_on;
-static int ibm_int_off;
-
-
-/* Direct HW low level accessors */
-
-
 static inline unsigned int direct_xirr_info_get(void)
 {
        int cpu = smp_processor_id();
@@ -93,7 +84,7 @@ static inline unsigned int direct_xirr_info_get(void)
        return in_be32(&xics_per_cpu[cpu]->xirr.word);
 }
 
-static inline void direct_xirr_info_set(int value)
+static inline void direct_xirr_info_set(unsigned int value)
 {
        int cpu = smp_processor_id();
 
@@ -115,7 +106,6 @@ static inline void direct_qirr_info(int n_cpu, u8 value)
 
 /* LPAR low level accessors */
 
-
 static inline unsigned int lpar_xirr_info_get(void)
 {
        unsigned long lpar_rc;
@@ -127,15 +117,14 @@ static inline unsigned int lpar_xirr_info_get(void)
        return (unsigned int)return_value;
 }
 
-static inline void lpar_xirr_info_set(int value)
+static inline void lpar_xirr_info_set(unsigned int value)
 {
        unsigned long lpar_rc;
-       unsigned long val64 = value & 0xffffffff;
 
-       lpar_rc = plpar_eoi(val64);
+       lpar_rc = plpar_eoi(value);
        if (lpar_rc != H_SUCCESS)
-               panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
-                     val64);
+               panic("bad return code EOI - rc = %ld, value=%x\n", lpar_rc,
+                     value);
 }
 
 static inline void lpar_cppr_info(u8 value)
@@ -157,48 +146,7 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
 }
 
 
-/* High level handlers and init code */
-
-static void xics_update_irq_servers(void)
-{
-       int i, j;
-       struct device_node *np;
-       u32 ilen;
-       const u32 *ireg, *isize;
-       u32 hcpuid;
-
-       /* Find the server numbers for the boot cpu. */
-       np = of_get_cpu_node(boot_cpuid, NULL);
-       BUG_ON(!np);
-
-       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
-       if (!ireg) {
-               of_node_put(np);
-               return;
-       }
-
-       i = ilen / sizeof(int);
-       hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
-       /* Global interrupt distribution server is specified in the last
-        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
-        * entry fom this property for current boot cpu id and use it as
-        * default distribution server
-        */
-       for (j = 0; j < i; j += 2) {
-               if (ireg[j] == hcpuid) {
-                       default_server = hcpuid;
-                       default_distrib_server = ireg[j+1];
-
-                       isize = of_get_property(np,
-                                       "ibm,interrupt-server#-size", NULL);
-                       if (isize)
-                               interrupt_server_size = *isize;
-               }
-       }
-
-       of_node_put(np);
-}
+/* Interface to generic irq subsystem */
 
 #ifdef CONFIG_SMP
 static int get_irq_server(unsigned int virq, unsigned int strict_check)
@@ -208,9 +156,6 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
        cpumask_t cpumask = irq_desc[virq].affinity;
        cpumask_t tmp = CPU_MASK_NONE;
 
-       if (! cpu_isset(default_server, cpu_online_map))
-               xics_update_irq_servers();
-
        if (!distribute_irqs)
                return default_server;
 
@@ -238,7 +183,6 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
 }
 #endif
 
-
 static void xics_unmask_irq(unsigned int virq)
 {
        unsigned int irq;
@@ -257,21 +201,28 @@ static void xics_unmask_irq(unsigned int virq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
                                DEFAULT_PRIORITY);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
-                      "returned %d\n", irq, call_status);
-               printk("set_xive %x, server %x\n", ibm_set_xive, server);
+               printk(KERN_ERR
+                       "%s: ibm_set_xive irq %u server %x returned %d\n",
+                       __func__, irq, server, call_status);
                return;
        }
 
        /* Now unmask the interrupt (often a no-op) */
        call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
-                      "returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 }
 
+static unsigned int xics_startup(unsigned int virq)
+{
+       /* unmask it */
+       xics_unmask_irq(virq);
+       return 0;
+}
+
 static void xics_mask_real_irq(unsigned int irq)
 {
        int call_status;
@@ -281,8 +232,8 @@ static void xics_mask_real_irq(unsigned int irq)
 
        call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
-                      "ibm_int_off returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 
@@ -290,8 +241,8 @@ static void xics_mask_real_irq(unsigned int irq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
                                default_server, 0xff);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
-                      " returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 }
@@ -308,132 +259,77 @@ static void xics_mask_irq(unsigned int virq)
        xics_mask_real_irq(irq);
 }
 
-static unsigned int xics_startup(unsigned int virq)
-{
-       unsigned int irq;
-
-       /* force a reverse mapping of the interrupt so it gets in the cache */
-       irq = (unsigned int)irq_map[virq].hwirq;
-       irq_radix_revmap(xics_host, irq);
-
-       /* unmask it */
-       xics_unmask_irq(virq);
-       return 0;
-}
-
-static void xics_eoi_direct(unsigned int virq)
+static void xics_mask_unknown_vec(unsigned int vec)
 {
-       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-       iosync();
-       direct_xirr_info_set((0xff << 24) | irq);
+       printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
+       xics_mask_real_irq(vec);
 }
 
-
-static void xics_eoi_lpar(unsigned int virq)
+static inline unsigned int xics_xirr_vector(unsigned int xirr)
 {
-       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-       iosync();
-       lpar_xirr_info_set((0xff << 24) | irq);
+       /*
+        * The top byte is the old cppr, to be restored on EOI.
+        * The remaining 24 bits are the vector.
+        */
+       return xirr & 0x00ffffff;
 }
 
-static inline unsigned int xics_remap_irq(unsigned int vec)
+static unsigned int xics_get_irq_direct(void)
 {
+       unsigned int xirr = direct_xirr_info_get();
+       unsigned int vec = xics_xirr_vector(xirr);
        unsigned int irq;
 
-       vec &= 0x00ffffff;
-
        if (vec == XICS_IRQ_SPURIOUS)
                return NO_IRQ;
-       irq = irq_radix_revmap(xics_host, vec);
+
+       irq = irq_radix_revmap_lookup(xics_host, vec);
        if (likely(irq != NO_IRQ))
                return irq;
 
-       printk(KERN_ERR "Interrupt %u (real) is invalid,"
-              " disabling it.\n", vec);
-       xics_mask_real_irq(vec);
-       return NO_IRQ;
-}
+       /* We don't have a linux mapping, so have rtas mask it. */
+       xics_mask_unknown_vec(vec);
 
-static unsigned int xics_get_irq_direct(void)
-{
-       return xics_remap_irq(direct_xirr_info_get());
+       /* We might learn about it later, so EOI it */
+       direct_xirr_info_set(xirr);
+       return NO_IRQ;
 }
 
 static unsigned int xics_get_irq_lpar(void)
 {
-       return xics_remap_irq(lpar_xirr_info_get());
-}
-
-#ifdef CONFIG_SMP
-
-static irqreturn_t xics_ipi_dispatch(int cpu)
-{
-       WARN_ON(cpu_is_offline(cpu));
+       unsigned int xirr = lpar_xirr_info_get();
+       unsigned int vec = xics_xirr_vector(xirr);
+       unsigned int irq;
 
-       while (xics_ipi_message[cpu].value) {
-               if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_CALL_FUNCTION);
-               }
-               if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_RESCHEDULE);
-               }
-               if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
-               }
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-               if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
-               }
-#endif
-       }
-       return IRQ_HANDLED;
-}
+       if (vec == XICS_IRQ_SPURIOUS)
+               return NO_IRQ;
 
-static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
-{
-       int cpu = smp_processor_id();
+       irq = irq_radix_revmap_lookup(xics_host, vec);
+       if (likely(irq != NO_IRQ))
+               return irq;
 
-       direct_qirr_info(cpu, 0xff);
+       /* We don't have a linux mapping, so have RTAS mask it. */
+       xics_mask_unknown_vec(vec);
 
-       return xics_ipi_dispatch(cpu);
+       /* We might learn about it later, so EOI it */
+       lpar_xirr_info_set(xirr);
+       return NO_IRQ;
 }
 
-static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+static void xics_eoi_direct(unsigned int virq)
 {
-       int cpu = smp_processor_id();
-
-       lpar_qirr_info(cpu, 0xff);
+       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-       return xics_ipi_dispatch(cpu);
+       iosync();
+       direct_xirr_info_set((0xff << 24) | irq);
 }
 
-void xics_cause_IPI(int cpu)
+static void xics_eoi_lpar(unsigned int virq)
 {
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               lpar_qirr_info(cpu, IPI_PRIORITY);
-       else
-               direct_qirr_info(cpu, IPI_PRIORITY);
-}
-
-#endif /* CONFIG_SMP */
+       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-static void xics_set_cpu_priority(unsigned char cppr)
-{
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               lpar_cppr_info(cppr);
-       else
-               direct_cppr_info(cppr);
        iosync();
+       lpar_xirr_info_set((0xff << 24) | irq);
 }
 
 static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
@@ -450,8 +346,8 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
-                      "returns %d\n", irq, status);
+               printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+                       __func__, irq, status);
                return;
        }
 
@@ -463,8 +359,9 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        if (irq_server == -1) {
                char cpulist[128];
                cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
-               printk(KERN_WARNING "xics_set_affinity: No online cpus in "
-                               "the mask %s for irq %d\n", cpulist, virq);
+               printk(KERN_WARNING
+                       "%s: No online cpus in the mask %s for irq %d\n",
+                       __func__, cpulist, virq);
                return;
        }
 
@@ -472,28 +369,12 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
                                irq, irq_server, xics_status[1]);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
-                      "returns %d\n", irq, status);
+               printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
+                       __func__, irq, status);
                return;
        }
 }
 
-void xics_setup_cpu(void)
-{
-       xics_set_cpu_priority(0xff);
-
-       /*
-        * Put the calling processor into the GIQ.  This is really only
-        * necessary from a secondary thread as the OF start-cpu interface
-        * performs this function for us on primary threads.
-        *
-        * XXX: undo of teardown on kexec needs this too, as may hotplug
-        */
-       rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
-}
-
-
 static struct irq_chip xics_pic_direct = {
        .typename = " XICS     ",
        .startup = xics_startup,
@@ -503,7 +384,6 @@ static struct irq_chip xics_pic_direct = {
        .set_affinity = xics_set_affinity
 };
 
-
 static struct irq_chip xics_pic_lpar = {
        .typename = " XICS     ",
        .startup = xics_startup,
@@ -513,6 +393,9 @@ static struct irq_chip xics_pic_lpar = {
        .set_affinity = xics_set_affinity
 };
 
+
+/* Interface to arch irq controller subsystem layer */
+
 /* Points to the irq_chip we're actually using */
 static struct irq_chip *xics_irq_chip;
 
@@ -530,6 +413,9 @@ static int xics_host_map(struct irq_host *h, unsigned int virq,
 {
        pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
 
+       /* Insert the interrupt mapping into the radix tree for fast lookup */
+       irq_radix_revmap_insert(xics_host, virq, hw);
+
        get_irq_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
        return 0;
@@ -569,10 +455,169 @@ static void __init xics_init_host(void)
        irq_set_default_host(xics_host);
 }
 
+
+/* Inter-processor interrupt support */
+
+#ifdef CONFIG_SMP
+/*
+ * XICS only has a single IPI, so encode the messages per CPU
+ */
+struct xics_ipi_struct {
+        unsigned long value;
+       } ____cacheline_aligned;
+
+static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+       set_bit(msg, &xics_ipi_message[cpu].value);
+       mb();
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_qirr_info(cpu, IPI_PRIORITY);
+       else
+               direct_qirr_info(cpu, IPI_PRIORITY);
+}
+
+void smp_xics_message_pass(int target, int msg)
+{
+       unsigned int i;
+
+       if (target < NR_CPUS) {
+               smp_xics_do_message(target, msg);
+       } else {
+               for_each_online_cpu(i) {
+                       if (target == MSG_ALL_BUT_SELF
+                           && i == smp_processor_id())
+                               continue;
+                       smp_xics_do_message(i, msg);
+               }
+       }
+}
+
+static irqreturn_t xics_ipi_dispatch(int cpu)
+{
+       WARN_ON(cpu_is_offline(cpu));
+
+       mb();   /* order mmio clearing qirr */
+       while (xics_ipi_message[cpu].value) {
+               if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_CALL_FUNCTION);
+               }
+               if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_RESCHEDULE);
+               }
+               if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
+               }
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+               if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+               }
+#endif
+       }
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
+{
+       int cpu = smp_processor_id();
+
+       direct_qirr_info(cpu, 0xff);
+
+       return xics_ipi_dispatch(cpu);
+}
+
+static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+{
+       int cpu = smp_processor_id();
+
+       lpar_qirr_info(cpu, 0xff);
+
+       return xics_ipi_dispatch(cpu);
+}
+
+static void xics_request_ipi(void)
+{
+       unsigned int ipi;
+       int rc;
+
+       ipi = irq_create_mapping(xics_host, XICS_IPI);
+       BUG_ON(ipi == NO_IRQ);
+
+       /*
+        * IPIs are marked IRQF_DISABLED as they must run with irqs
+        * disabled
+        */
+       set_irq_handler(ipi, handle_percpu_irq);
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               rc = request_irq(ipi, xics_ipi_action_lpar,
+                               IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+       else
+               rc = request_irq(ipi, xics_ipi_action_direct,
+                               IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+       BUG_ON(rc);
+}
+
+int __init smp_xics_probe(void)
+{
+       xics_request_ipi();
+
+       return cpus_weight(cpu_possible_map);
+}
+
+#endif /* CONFIG_SMP */
+
+
+/* Initialization */
+
+static void xics_update_irq_servers(void)
+{
+       int i, j;
+       struct device_node *np;
+       u32 ilen;
+       const u32 *ireg, *isize;
+       u32 hcpuid;
+
+       /* Find the server numbers for the boot cpu. */
+       np = of_get_cpu_node(boot_cpuid, NULL);
+       BUG_ON(!np);
+
+       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+       if (!ireg) {
+               of_node_put(np);
+               return;
+       }
+
+       i = ilen / sizeof(int);
+       hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+       /* Global interrupt distribution server is specified in the last
+        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+        * entry fom this property for current boot cpu id and use it as
+        * default distribution server
+        */
+       for (j = 0; j < i; j += 2) {
+               if (ireg[j] == hcpuid) {
+                       default_server = hcpuid;
+                       default_distrib_server = ireg[j+1];
+               }
+       }
+
+       /* get the bit size of server numbers */
+       isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
+       if (isize)
+               interrupt_server_size = *isize;
+
+       of_node_put(np);
+}
+
 static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
                                     unsigned long size)
 {
-#ifdef CONFIG_SMP
        int i;
 
        /* This may look gross but it's good enough for now, we don't quite
@@ -586,11 +631,6 @@ static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
                        return;
                }
        }
-#else
-       if (hw_id != 0)
-               return;
-       xics_per_cpu[0] = ioremap(addr, size);
-#endif /* CONFIG_SMP */
 }
 
 static void __init xics_init_one_node(struct device_node *np,
@@ -652,15 +692,17 @@ void __init xics_init_IRQ(void)
 
        for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
                found = 1;
-               if (firmware_has_feature(FW_FEATURE_LPAR))
+               if (firmware_has_feature(FW_FEATURE_LPAR)) {
+                       of_node_put(np);
                        break;
+                       }
                xics_init_one_node(np, &indx);
        }
        if (found == 0)
                return;
 
-       xics_init_host();
        xics_update_irq_servers();
+       xics_init_host();
 
        if (firmware_has_feature(FW_FEATURE_LPAR))
                ppc_md.get_irq = xics_get_irq_lpar;
@@ -672,30 +714,31 @@ void __init xics_init_IRQ(void)
        ppc64_boot_msg(0x21, "XICS Done");
 }
 
+/* Cpu startup, shutdown, and hotplug */
 
-#ifdef CONFIG_SMP
-void xics_request_IPIs(void)
+static void xics_set_cpu_priority(unsigned char cppr)
 {
-       unsigned int ipi;
-       int rc;
-
-       ipi = irq_create_mapping(xics_host, XICS_IPI);
-       BUG_ON(ipi == NO_IRQ);
-
-       /*
-        * IPIs are marked IRQF_DISABLED as they must run with irqs
-        * disabled
-        */
-       set_irq_handler(ipi, handle_percpu_irq);
        if (firmware_has_feature(FW_FEATURE_LPAR))
-               rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
-                               "IPI", NULL);
+               lpar_cppr_info(cppr);
        else
-               rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
-                               "IPI", NULL);
-       BUG_ON(rc);
+               direct_cppr_info(cppr);
+       iosync();
+}
+
+/* Have the calling processor join or leave the specified global queue */
+static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
+{
+       int status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
+               (1UL << interrupt_server_size) - 1 - gserver, join);
+       WARN_ON(status < 0);
+}
+
+void xics_setup_cpu(void)
+{
+       xics_set_cpu_priority(0xff);
+
+       xics_set_cpu_giq(default_distrib_server, 1);
 }
-#endif /* CONFIG_SMP */
 
 void xics_teardown_cpu(void)
 {
@@ -703,9 +746,7 @@ void xics_teardown_cpu(void)
 
        xics_set_cpu_priority(0);
 
-       /*
-        * Clear IPI
-        */
+       /* Clear any pending IPI request */
        if (firmware_has_feature(FW_FEATURE_LPAR))
                lpar_qirr_info(cpu, 0xff);
        else
@@ -714,34 +755,28 @@ void xics_teardown_cpu(void)
 
 void xics_kexec_teardown_cpu(int secondary)
 {
-       unsigned int ipi;
-       struct irq_desc *desc;
-
        xics_teardown_cpu();
 
        /*
-        * we need to EOI the IPI
+        * we take the ipi irq but and never return so we
+        * need to EOI the IPI, but want to leave our priority 0
         *
-        * probably need to check all the other interrupts too
+        * should we check all the other interrupts too?
         * should we be flagging idle loop instead?
         * or creating some task to be scheduled?
         */
 
-       ipi = irq_find_mapping(xics_host, XICS_IPI);
-       if (ipi == XICS_IRQ_SPURIOUS)
-               return;
-       desc = get_irq_desc(ipi);
-       if (desc->chip && desc->chip->eoi)
-               desc->chip->eoi(ipi);
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_xirr_info_set((0x00 << 24) | XICS_IPI);
+       else
+               direct_xirr_info_set((0x00 << 24) | XICS_IPI);
 
        /*
         * Some machines need to have at least one cpu in the GIQ,
         * so leave the master cpu in the group.
         */
        if (secondary)
-               rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-                                  (1UL << interrupt_server_size) - 1 -
-                                  default_distrib_server, 0);
+               xics_set_cpu_giq(default_distrib_server, 0);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -749,17 +784,18 @@ void xics_kexec_teardown_cpu(int secondary)
 /* Interrupts are disabled. */
 void xics_migrate_irqs_away(void)
 {
-       int status;
        int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
        unsigned int irq, virq;
 
+       /* If we used to be the default server, move to the new "boot_cpuid" */
+       if (hw_cpu == default_server)
+               xics_update_irq_servers();
+
        /* Reject any interrupt that was queued to us... */
        xics_set_cpu_priority(0);
 
-       /* remove ourselves from the global interrupt queue */
-       status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
-       WARN_ON(status < 0);
+       /* Remove ourselves from the global interrupt queue */
+       xics_set_cpu_giq(default_distrib_server, 0);
 
        /* Allow IPIs again... */
        xics_set_cpu_priority(DEFAULT_PRIORITY);
@@ -767,6 +803,7 @@ void xics_migrate_irqs_away(void)
        for_each_irq(virq) {
                struct irq_desc *desc;
                int xics_status[2];
+               int status;
                unsigned long flags;
 
                /* We cant set affinity on ISA interrupts */
@@ -790,9 +827,8 @@ void xics_migrate_irqs_away(void)
 
                status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
                if (status) {
-                       printk(KERN_ERR "migrate_irqs_away: irq=%u "
-                                       "ibm,get-xive returns %d\n",
-                                       virq, status);
+                       printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+                                       __func__, irq, status);
                        goto unlock;
                }
 
index 1c5321ae8f2f06a507a7ecbdccfd076077c00144..d1d5a83039aeb7928bf9b8849e33e2be6bc605ee 100644 (file)
 #ifndef _POWERPC_KERNEL_XICS_H
 #define _POWERPC_KERNEL_XICS_H
 
-#include <linux/cache.h>
-
 extern void xics_init_IRQ(void);
 extern void xics_setup_cpu(void);
 extern void xics_teardown_cpu(void);
 extern void xics_kexec_teardown_cpu(int secondary);
-extern void xics_cause_IPI(int cpu);
-extern  void xics_request_IPIs(void);
 extern void xics_migrate_irqs_away(void);
-
-struct xics_ipi_struct {
-       volatile unsigned long value;
-} ____cacheline_aligned;
-
-extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+extern int smp_xics_probe(void);
+extern void smp_xics_message_pass(int target, int msg);
 
 #endif /* _POWERPC_KERNEL_XICS_H */
index 72fb35b9ebcadfbe50a72cabf66cad08305b6bc1..396582835cb51bf46dc7ac8623ea29b723a5251b 100644 (file)
@@ -6,3 +6,9 @@ config PPC4xx_PCI_EXPRESS
        bool
        depends on PCI && 4xx
        default n
+
+config PPC_MSI_BITMAP
+       bool
+       depends on PCI_MSI
+       default y if MPIC
+       default y if FSL_PCI
index a90054b56d5c5a8cba8589885566b1eb88c1545b..a44709a94f9734e0b51981a06a32f1550c19194f 100644 (file)
@@ -5,6 +5,7 @@ endif
 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
 fsl-msi-obj-$(CONFIG_PCI_MSI)  += fsl_msi.o
+obj-$(CONFIG_PPC_MSI_BITMAP)   += msi_bitmap.o
 
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
 obj-$(CONFIG_PPC_DCR_NATIVE)   += dcr-low.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_FSL_SOC)         += fsl_soc.o
 obj-$(CONFIG_FSL_PCI)          += fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
+obj-$(CONFIG_MPC8xxx_GPIO)     += mpc8xxx_gpio.o
 obj-$(CONFIG_RAPIDIO)          += fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)    += tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)     += qe_lib/
@@ -36,15 +38,12 @@ ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_4xx)              += ppc4xx_pci.o
 endif
 
-# Temporary hack until we have migrated to asm-powerpc
-ifeq ($(ARCH),powerpc)
 obj-$(CONFIG_CPM)              += cpm_common.o
 obj-$(CONFIG_CPM2)             += cpm2.o cpm2_pic.o
 obj-$(CONFIG_QUICC_ENGINE)     += cpm_common.o
 obj-$(CONFIG_PPC_DCR)          += dcr.o
 obj-$(CONFIG_8xx)              += mpc8xx_pic.o cpm1.o
 obj-$(CONFIG_UCODE_PATCH)      += micropatch.o
-endif
 
 ifeq ($(CONFIG_SUSPEND),y)
 obj-$(CONFIG_6xx)              += 6xx-suspend.o
index 4a04823e8423b9f8a24098a2fec81acf917598a9..490473ce81030475fbfa6075a2c76612dcd48b0e 100644 (file)
@@ -546,15 +546,11 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio)
        return !!(in_be16(&iop->dat) & pin_mask);
 }
 
-static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
+static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask,
+       int value)
 {
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
        struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
        struct cpm_ioport16 __iomem *iop = mm_gc->regs;
-       unsigned long flags;
-       u16 pin_mask = 1 << (15 - gpio);
-
-       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        if (value)
                cpm1_gc->cpdata |= pin_mask;
@@ -562,6 +558,18 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
                cpm1_gc->cpdata &= ~pin_mask;
 
        out_be16(&iop->dat, cpm1_gc->cpdata);
+}
+
+static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
+{
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+       unsigned long flags;
+       u16 pin_mask = 1 << (15 - gpio);
+
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
+
+       __cpm1_gpio16_set(mm_gc, pin_mask, value);
 
        spin_unlock_irqrestore(&cpm1_gc->lock, flags);
 }
@@ -569,14 +577,17 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
 static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
        struct cpm_ioport16 __iomem *iop = mm_gc->regs;
-       u16 pin_mask;
+       unsigned long flags;
+       u16 pin_mask = 1 << (15 - gpio);
 
-       pin_mask = 1 << (15 - gpio);
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        setbits16(&iop->dir, pin_mask);
+       __cpm1_gpio16_set(mm_gc, pin_mask, val);
 
-       cpm1_gpio16_set(gc, gpio, val);
+       spin_unlock_irqrestore(&cpm1_gc->lock, flags);
 
        return 0;
 }
@@ -584,13 +595,17 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
        struct cpm_ioport16 __iomem *iop = mm_gc->regs;
-       u16 pin_mask;
+       unsigned long flags;
+       u16 pin_mask = 1 << (15 - gpio);
 
-       pin_mask = 1 << (15 - gpio);
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        clrbits16(&iop->dir, pin_mask);
 
+       spin_unlock_irqrestore(&cpm1_gc->lock, flags);
+
        return 0;
 }
 
@@ -655,15 +670,11 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
        return !!(in_be32(&iop->dat) & pin_mask);
 }
 
-static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
+static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask,
+       int value)
 {
-       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
        struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
        struct cpm_ioport32b __iomem *iop = mm_gc->regs;
-       unsigned long flags;
-       u32 pin_mask = 1 << (31 - gpio);
-
-       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        if (value)
                cpm1_gc->cpdata |= pin_mask;
@@ -671,6 +682,18 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
                cpm1_gc->cpdata &= ~pin_mask;
 
        out_be32(&iop->dat, cpm1_gc->cpdata);
+}
+
+static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
+{
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+       unsigned long flags;
+       u32 pin_mask = 1 << (31 - gpio);
+
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
+
+       __cpm1_gpio32_set(mm_gc, pin_mask, value);
 
        spin_unlock_irqrestore(&cpm1_gc->lock, flags);
 }
@@ -678,14 +701,17 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
 static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
        struct cpm_ioport32b __iomem *iop = mm_gc->regs;
-       u32 pin_mask;
+       unsigned long flags;
+       u32 pin_mask = 1 << (31 - gpio);
 
-       pin_mask = 1 << (31 - gpio);
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        setbits32(&iop->dir, pin_mask);
+       __cpm1_gpio32_set(mm_gc, pin_mask, val);
 
-       cpm1_gpio32_set(gc, gpio, val);
+       spin_unlock_irqrestore(&cpm1_gc->lock, flags);
 
        return 0;
 }
@@ -693,13 +719,17 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
        struct cpm_ioport32b __iomem *iop = mm_gc->regs;
-       u32 pin_mask;
+       unsigned long flags;
+       u32 pin_mask = 1 << (31 - gpio);
 
-       pin_mask = 1 << (31 - gpio);
+       spin_lock_irqsave(&cpm1_gc->lock, flags);
 
        clrbits32(&iop->dir, pin_mask);
 
+       spin_unlock_irqrestore(&cpm1_gc->lock, flags);
+
        return 0;
 }
 
index 422c8faef5938d38f0f57da4e8018bf11e3b975b..0494ee55920f7c55f6aac6c2447a0cd7c2ad76c0 100644 (file)
  * (at your option) any later version.
  */
 
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/io.h>
 #include <linux/of.h>
+#include <asm/prom.h>
 #include <asm/fsl_lbc.h>
 
-spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-
-struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-EXPORT_SYMBOL(fsl_lbc_regs);
+static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
 
 static char __initdata *compat_lbc[] = {
        "fsl,pq2-localbus",
@@ -127,3 +132,43 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
        return 0;
 }
 EXPORT_SYMBOL(fsl_upm_find);
+
+/**
+ * fsl_upm_run_pattern - actually run an UPM pattern
+ * @upm:       pointer to the fsl_upm structure obtained via fsl_upm_find
+ * @io_base:   remapped pointer to where memory access should happen
+ * @mar:       MAR register content during pattern execution
+ *
+ * This function triggers dummy write to the memory specified by the io_base,
+ * thus UPM pattern actually executed. Note that mar usage depends on the
+ * pre-programmed AMX bits in the UPM RAM.
+ */
+int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&fsl_lbc_lock, flags);
+
+       out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width));
+
+       switch (upm->width) {
+       case 8:
+               out_8(io_base, 0x0);
+               break;
+       case 16:
+               out_be16(io_base, 0x0);
+               break;
+       case 32:
+               out_be32(io_base, 0x0);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       spin_unlock_irqrestore(&fsl_lbc_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(fsl_upm_run_pattern);
index 2c5187cc8a24e31e45aaf2a107677fbd9ce81d3f..f25ce818d40a16061e40209309c78c6fce4ad9c0 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include <linux/irq.h>
 #include <linux/bootmem.h>
-#include <linux/bitmap.h>
 #include <linux/msi.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
@@ -67,95 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = {
        .map = fsl_msi_host_map,
 };
 
-static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num)
-{
-       unsigned long flags;
-       int order = get_count_order(num);
-       int offset;
-
-       spin_lock_irqsave(&msi->bitmap_lock, flags);
-
-       offset = bitmap_find_free_region(msi->fsl_msi_bitmap,
-                                       NR_MSI_IRQS, order);
-
-       spin_unlock_irqrestore(&msi->bitmap_lock, flags);
-
-       pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n",
-               __func__, num, order, offset);
-
-       return offset;
-}
-
-static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num)
-{
-       unsigned long flags;
-       int order = get_count_order(num);
-
-       pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n",
-               __func__, num, order, offset);
-
-       spin_lock_irqsave(&msi->bitmap_lock, flags);
-       bitmap_release_region(msi->fsl_msi_bitmap, offset, order);
-       spin_unlock_irqrestore(&msi->bitmap_lock, flags);
-}
-
-static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi)
-{
-       int i;
-       int len;
-       const u32 *p;
-
-       bitmap_allocate_region(msi->fsl_msi_bitmap, 0,
-                      get_count_order(NR_MSI_IRQS));
-
-       p = of_get_property(msi->of_node, "msi-available-ranges", &len);
-
-       if (!p) {
-               /* No msi-available-ranges property,
-                * All the 256 MSI interrupts can be used
-                */
-               fsl_msi_free_hwirqs(msi, 0, 0x100);
-               return 0;
-       }
-
-       if ((len % (2 * sizeof(u32))) != 0) {
-               printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges "
-                      "property on %s\n", msi->of_node->full_name);
-               return -EINVAL;
-       }
-
-       /* Format is: (<u32 start> <u32 count>)+ */
-       len /= 2 * sizeof(u32);
-       for (i = 0; i < len; i++, p += 2)
-               fsl_msi_free_hwirqs(msi, *p, *(p + 1));
-
-       return 0;
-}
-
 static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
 {
        int rc;
-       int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32);
 
-       msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL);
+       rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
+                             msi_data->irqhost->of_node);
+       if (rc)
+               return rc;
 
-       if (msi_data->fsl_msi_bitmap == NULL) {
-               pr_debug("%s: ENOMEM allocating allocator bitmap!\n",
-                               __func__);
-               return -ENOMEM;
+       rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
+       if (rc < 0) {
+               msi_bitmap_free(&msi_data->bitmap);
+               return rc;
        }
 
-       rc = fsl_msi_free_dt_hwirqs(msi_data);
-       if (rc)
-               goto out_free;
-
        return 0;
-out_free:
-       kfree(msi_data->fsl_msi_bitmap);
-
-       msi_data->fsl_msi_bitmap = NULL;
-       return rc;
-
 }
 
 static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
@@ -175,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
                set_irq_msi(entry->irq, NULL);
-               fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1);
+               msi_bitmap_free_hwirqs(&msi_data->bitmap,
+                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
        }
 
@@ -197,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
 
 static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
-       irq_hw_number_t hwirq;
-       int rc;
+       int rc, hwirq;
        unsigned int virq;
        struct msi_desc *entry;
        struct msi_msg msg;
        struct fsl_msi *msi_data = fsl_msi;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
-               hwirq = fsl_msi_alloc_hwirqs(msi_data, 1);
+               hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
                if (hwirq < 0) {
                        rc = hwirq;
                        pr_debug("%s: fail allocating msi interrupt\n",
@@ -216,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                virq = irq_create_mapping(msi_data->irqhost, hwirq);
 
                if (virq == NO_IRQ) {
-                       pr_debug("%s: fail mapping hwirq 0x%lx\n",
+                       pr_debug("%s: fail mapping hwirq 0x%x\n",
                                        __func__, hwirq);
-                       fsl_msi_free_hwirqs(msi_data, hwirq, 1);
+                       msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
                        rc = -ENOSPC;
                        goto out_free;
                }
@@ -317,14 +243,11 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
                goto error_out;
        }
 
-       msi->of_node = of_node_get(dev->node);
+       msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR,
+                                     NR_MSI_IRQS, &fsl_msi_host_ops, 0);
 
-       msi->irqhost = irq_alloc_host(of_node_get(dev->node),
-                               IRQ_HOST_MAP_LINEAR,
-                               NR_MSI_IRQS, &fsl_msi_host_ops, 0);
        if (msi->irqhost == NULL) {
                dev_err(&dev->dev, "No memory for MSI irqhost\n");
-               of_node_put(dev->node);
                err = -ENOMEM;
                goto error_out;
        }
index a653468521fa36b1050e32ba5032b4ed686fee6f..331c7e7025b786bf7d3ed071038ceb6330f971fc 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _POWERPC_SYSDEV_FSL_MSI_H
 #define _POWERPC_SYSDEV_FSL_MSI_H
 
+#include <asm/msi_bitmap.h>
+
 #define NR_MSI_REG             8
 #define IRQS_PER_MSI_REG       32
 #define NR_MSI_IRQS    (NR_MSI_REG * IRQS_PER_MSI_REG)
@@ -22,9 +24,6 @@
 #define FSL_PIC_IP_IPIC        0x00000002
 
 struct fsl_msi {
-       /* Device node of the MSI interrupt*/
-       struct device_node *of_node;
-
        struct irq_host *irqhost;
 
        unsigned long cascade_irq;
@@ -34,8 +33,7 @@ struct fsl_msi {
        void __iomem *msi_regs;
        u32 feature;
 
-       unsigned long *fsl_msi_bitmap;
-       spinlock_t bitmap_lock;
+       struct msi_bitmap bitmap;
 };
 
 #endif /* _POWERPC_SYSDEV_FSL_MSI_H */
index 61e6d77efa4fcec7d17fe31d6b5763786ba58319..5b264eb4b1f7f6af12115640ed8c17d139cb9e3b 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * MPC85xx/86xx PCI/PCIE support routing.
+ * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007 Freescale Semiconductor, Inc
+ * Copyright 2007,2008 Freescale Semiconductor, Inc
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
  * Recode: ZHANG WEI <wei.zhang@freescale.com>
@@ -251,20 +251,47 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
 #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
 
-#if defined(CONFIG_PPC_83xx)
+#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
 int __init mpc83xx_add_bridge(struct device_node *dev)
 {
        int len;
        struct pci_controller *hose;
-       struct resource rsrc;
+       struct resource rsrc_reg;
+       struct resource rsrc_cfg;
        const int *bus_range;
-       int primary = 1, has_address = 0;
-       phys_addr_t immr = get_immrbase();
+       int primary;
 
        pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
        /* Fetch host bridge registers address */
-       has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+       if (of_address_to_resource(dev, 0, &rsrc_reg)) {
+               printk(KERN_WARNING "Can't get pci register base!\n");
+               return -ENOMEM;
+       }
+
+       memset(&rsrc_cfg, 0, sizeof(rsrc_cfg));
+
+       if (of_address_to_resource(dev, 1, &rsrc_cfg)) {
+               printk(KERN_WARNING
+                       "No pci config register base in dev tree, "
+                       "using default\n");
+               /*
+                * MPC83xx supports up to two host controllers
+                *      one at 0x8500 has config space registers at 0x8300
+                *      one at 0x8600 has config space registers at 0x8380
+                */
+               if ((rsrc_reg.start & 0xfffff) == 0x8500)
+                       rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300;
+               else if ((rsrc_reg.start & 0xfffff) == 0x8600)
+                       rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380;
+       }
+       /*
+        * Controller at offset 0x8500 is primary
+        */
+       if ((rsrc_reg.start & 0xfffff) == 0x8500)
+               primary = 1;
+       else
+               primary = 0;
 
        /* Get bus range if any */
        bus_range = of_get_property(dev, "bus-range", &len);
@@ -281,22 +308,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
        hose->first_busno = bus_range ? bus_range[0] : 0;
        hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
-       /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
-        * the other at 0x8600, we consider the 0x8500 the primary controller
-        */
-       /* PCI 1 */
-       if ((rsrc.start & 0xfffff) == 0x8500) {
-               setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
-       }
-       /* PCI 2 */
-       if ((rsrc.start & 0xfffff) == 0x8600) {
-               setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
-               primary = 0;
-       }
+       setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0);
 
-       printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
+       printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
               "Firmware bus number: %d->%d\n",
-              (unsigned long long)rsrc.start, hose->first_busno,
+              (unsigned long long)rsrc_reg.start, hose->first_busno,
               hose->last_busno);
 
        pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
index 214388e11807a039d05a9d6baf4fcf1a25b2f18a..01b884b25696847d6c58817169156c49e49c11e0 100644 (file)
@@ -412,53 +412,6 @@ err:
 
 arch_initcall(gfar_of_init);
 
-
-#ifdef CONFIG_PPC_83xx
-static int __init mpc83xx_wdt_init(void)
-{
-       struct resource r;
-       struct device_node *np;
-       struct platform_device *dev;
-       u32 freq = fsl_get_sys_freq();
-       int ret;
-
-       np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
-
-       if (!np) {
-               ret = -ENODEV;
-               goto nodev;
-       }
-
-       memset(&r, 0, sizeof(r));
-
-       ret = of_address_to_resource(np, 0, &r);
-       if (ret)
-               goto err;
-
-       dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
-       if (IS_ERR(dev)) {
-               ret = PTR_ERR(dev);
-               goto err;
-       }
-
-       ret = platform_device_add_data(dev, &freq, sizeof(freq));
-       if (ret)
-               goto unreg;
-
-       of_node_put(np);
-       return 0;
-
-unreg:
-       platform_device_unregister(dev);
-err:
-       of_node_put(np);
-nodev:
-       return ret;
-}
-
-arch_initcall(mpc83xx_wdt_init);
-#endif
-
 static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
 {
        if (!phy_type)
@@ -767,42 +720,6 @@ void fsl_rstcr_restart(char *cmd)
 #endif
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-struct platform_diu_data_ops diu_ops = {
-       .diu_size = 1280 * 1024 * 4,    /* default one 1280x1024 buffer */
-};
+struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
-
-int __init preallocate_diu_videomemory(void)
-{
-       pr_debug("diu_size=%lu\n", diu_ops.diu_size);
-
-       diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0);
-       if (!diu_ops.diu_mem) {
-               printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n",
-                       diu_ops.diu_size);
-               return -ENOMEM;
-       }
-
-       pr_debug("diu_mem=%p\n", diu_ops.diu_mem);
-
-       rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block),
-               diu_ops.diu_rh_block);
-       return rh_attach_region(&diu_ops.diu_rh_info,
-                               (unsigned long) diu_ops.diu_mem,
-                               diu_ops.diu_size);
-}
-
-static int __init early_parse_diufb(char *p)
-{
-       if (!p)
-               return 1;
-
-       diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8);
-
-       pr_debug("diu_size=%lu\n", diu_ops.diu_size);
-
-       return 0;
-}
-early_param("diufb", early_parse_diufb);
-
 #endif
index 0242998873526c32ada0e52e3b3f45283f407395..60f7f227327ce04dbb0fc81c82e424bfbfcdb2a8 100644 (file)
@@ -20,14 +20,7 @@ extern int fsl_spi_init(struct spi_board_info *board_infos,
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-#include <linux/bootmem.h>
-#include <asm/rheap.h>
 struct platform_diu_data_ops {
-       rh_block_t diu_rh_block[16];
-       rh_info_t diu_rh_info;
-       unsigned long diu_size;
-       void *diu_mem;
-
        unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
                int monitor_port);
        void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
@@ -38,7 +31,6 @@ struct platform_diu_data_ops {
 };
 
 extern struct platform_diu_data_ops diu_ops;
-int __init preallocate_diu_videomemory(void);
 #endif
 
 #endif
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
new file mode 100644 (file)
index 0000000..103eace
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * GPIOs on MPC8349/8572/8610 and compatible
+ *
+ * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+
+#define MPC8XXX_GPIO_PINS      32
+
+#define GPIO_DIR               0x00
+#define GPIO_ODR               0x04
+#define GPIO_DAT               0x08
+#define GPIO_IER               0x0c
+#define GPIO_IMR               0x10
+#define GPIO_ICR               0x14
+
+struct mpc8xxx_gpio_chip {
+       struct of_mm_gpio_chip mm_gc;
+       spinlock_t lock;
+
+       /*
+        * shadowed data register to be able to clear/set output pins in
+        * open drain mode safely
+        */
+       u32 data;
+};
+
+static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
+{
+       return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio);
+}
+
+static inline struct mpc8xxx_gpio_chip *
+to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm)
+{
+       return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc);
+}
+
+static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm)
+{
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+
+       mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT);
+}
+
+static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+
+       return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio);
+}
+
+static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+       if (val)
+               mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
+       else
+               mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio);
+
+       out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
+
+       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+}
+
+static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       unsigned long flags;
+
+       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+       clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+       return 0;
+}
+
+static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       unsigned long flags;
+
+       mpc8xxx_gpio_set(gc, gpio, val);
+
+       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+
+       setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
+
+       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+
+       return 0;
+}
+
+static void __init mpc8xxx_add_controller(struct device_node *np)
+{
+       struct mpc8xxx_gpio_chip *mpc8xxx_gc;
+       struct of_mm_gpio_chip *mm_gc;
+       struct of_gpio_chip *of_gc;
+       struct gpio_chip *gc;
+       int ret;
+
+       mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
+       if (!mpc8xxx_gc) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       spin_lock_init(&mpc8xxx_gc->lock);
+
+       mm_gc = &mpc8xxx_gc->mm_gc;
+       of_gc = &mm_gc->of_gc;
+       gc = &of_gc->gc;
+
+       mm_gc->save_regs = mpc8xxx_gpio_save_regs;
+       of_gc->gpio_cells = 2;
+       gc->ngpio = MPC8XXX_GPIO_PINS;
+       gc->direction_input = mpc8xxx_gpio_dir_in;
+       gc->direction_output = mpc8xxx_gpio_dir_out;
+       gc->get = mpc8xxx_gpio_get;
+       gc->set = mpc8xxx_gpio_set;
+
+       ret = of_mm_gpiochip_add(np, mm_gc);
+       if (ret)
+               goto err;
+
+       return;
+
+err:
+       pr_err("%s: registration failed with status %d\n",
+              np->full_name, ret);
+       kfree(mpc8xxx_gc);
+
+       return;
+}
+
+static int __init mpc8xxx_add_gpiochips(void)
+{
+       struct device_node *np;
+
+       for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio")
+               mpc8xxx_add_controller(np);
+
+       for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio")
+               mpc8xxx_add_controller(np);
+
+       for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio")
+               mpc8xxx_add_controller(np);
+
+       return 0;
+}
+arch_initcall(mpc8xxx_add_gpiochips);
index fbf8a266941c27ba6ff54867c8c2fab3a56d5690..6209c62a426d1177cb574a1bf92f0dc6f7ed7b43 100644 (file)
@@ -14,8 +14,6 @@
 #ifdef CONFIG_PCI_MSI
 extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
 extern int mpic_msi_init_allocator(struct mpic *mpic);
-extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
-extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
 extern int mpic_u3msi_init(struct mpic *mpic);
 extern int mpic_pasemi_msi_init(struct mpic *mpic);
 #else
index de3e5e8bc3241e297ed321b240fb95edaa4350e2..1d44eee80fa1275c5527967a4edf3a57f5f53f7f 100644 (file)
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
+#include <asm/msi_bitmap.h>
 
 #include <sysdev/mpic.h>
 
-static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
-{
-       pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
-       bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
-}
-
 void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
 {
-       unsigned long flags;
-
        /* The mpic calls this even when there is no allocator setup */
-       if (!mpic->hwirq_bitmap)
+       if (!mpic->msi_bitmap.bitmap)
                return;
 
-       spin_lock_irqsave(&mpic->bitmap_lock, flags);
-       __mpic_msi_reserve_hwirq(mpic, hwirq);
-       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
-}
-
-irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
-{
-       unsigned long flags;
-       int offset, order = get_count_order(num);
-
-       spin_lock_irqsave(&mpic->bitmap_lock, flags);
-       /*
-        * This is fast, but stricter than we need. We might want to add
-        * a fallback routine which does a linear search with no alignment.
-        */
-       offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
-                                        order);
-       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
-
-       pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
-                num, order, offset);
-
-       return offset;
-}
-
-void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
-{
-       unsigned long flags;
-       int order = get_count_order(num);
-
-       pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
-                num, order, offset);
-
-       spin_lock_irqsave(&mpic->bitmap_lock, flags);
-       bitmap_release_region(mpic->hwirq_bitmap, offset, order);
-       spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+       msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
 }
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
@@ -83,13 +41,13 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
 
        /* Reserve source numbers we know are reserved in the HW */
        for (i = 0;   i < 8;   i++)
-               __mpic_msi_reserve_hwirq(mpic, i);
+               msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
        for (i = 42;  i < 46;  i++)
-               __mpic_msi_reserve_hwirq(mpic, i);
+               msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
        for (i = 100; i < 105; i++)
-               __mpic_msi_reserve_hwirq(mpic, i);
+               msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
        np = NULL;
        while ((np = of_find_all_nodes(np))) {
@@ -99,7 +57,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
                while (of_irq_map_one(np, index++, &oirq) == 0) {
                        ops->xlate(mpic->irqhost, NULL, oirq.specifier,
                                                oirq.size, &hwirq, &flags);
-                       __mpic_msi_reserve_hwirq(mpic, hwirq);
+                       msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
                }
        }
 
@@ -112,70 +70,25 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
 }
 #endif
 
-static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
-{
-       int i, len;
-       const u32 *p;
-
-       p = of_get_property(mpic->irqhost->of_node,
-                           "msi-available-ranges", &len);
-       if (!p) {
-               pr_debug("mpic: no msi-available-ranges property found on %s\n",
-                         mpic->irqhost->of_node->full_name);
-               return -ENODEV;
-       }
-
-       if (len % 8 != 0) {
-               printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
-                      "property on %s\n", mpic->irqhost->of_node->full_name);
-               return -EINVAL;
-       }
-
-       bitmap_allocate_region(mpic->hwirq_bitmap, 0,
-                              get_count_order(mpic->irq_count));
-
-       /* Format is: (<u32 start> <u32 count>)+ */
-       len /= sizeof(u32);
-       for (i = 0; i < len / 2; i++, p += 2)
-               mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
-
-       return 0;
-}
-
 int mpic_msi_init_allocator(struct mpic *mpic)
 {
-       int rc, size;
-
-       BUG_ON(mpic->hwirq_bitmap);
-       spin_lock_init(&mpic->bitmap_lock);
+       int rc;
 
-       size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
-       pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
+       rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count,
+                             mpic->irqhost->of_node);
+       if (rc)
+               return rc;
 
-       mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
-
-       if (!mpic->hwirq_bitmap) {
-               pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
-               return -ENOMEM;
-       }
-
-       memset(mpic->hwirq_bitmap, 0, size);
-
-       rc = mpic_msi_reserve_dt_hwirqs(mpic);
-       if (rc) {
+       rc = msi_bitmap_reserve_dt_hwirqs(&mpic->msi_bitmap);
+       if (rc > 0) {
                if (mpic->flags & MPIC_U3_HT_IRQS)
                        rc = mpic_msi_reserve_u3_hwirqs(mpic);
 
-               if (rc)
-                       goto out_free;
+               if (rc) {
+                       msi_bitmap_free(&mpic->msi_bitmap);
+                       return rc;
+               }
        }
 
        return 0;
-
- out_free:
-       if (mem_init_done)
-               kfree(mpic->hwirq_bitmap);
-
-       mpic->hwirq_bitmap = NULL;
-       return rc;
 }
index 68aff6076675a433fe1144c20eff86e85e4c37c1..656cb772b6910458392cc2cc0c5001fced632189 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
+#include <asm/msi_bitmap.h>
 
 #include "mpic.h"
 
@@ -81,8 +82,8 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
                        continue;
 
                set_irq_msi(entry->irq, NULL);
-               mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq),
-                                    ALLOC_CHUNK);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
+                                      virq_to_hw(entry->irq), ALLOC_CHUNK);
                irq_dispose_mapping(entry->irq);
        }
 
@@ -91,11 +92,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
 
 static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
-       irq_hw_number_t hwirq;
        unsigned int virq;
        struct msi_desc *entry;
        struct msi_msg msg;
-       int ret;
+       int hwirq;
 
        pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",
                 pdev, nvec, type);
@@ -109,17 +109,19 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                 * few MSIs for someone, but restrictions will apply to how the
                 * sources can be changed independently.
                 */
-               ret = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK);
-               hwirq = ret;
-               if (ret < 0) {
+               hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap,
+                                               ALLOC_CHUNK);
+               if (hwirq < 0) {
                        pr_debug("pasemi_msi: failed allocating hwirq\n");
                        return hwirq;
                }
 
                virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
                if (virq == NO_IRQ) {
-                       pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq);
-                       mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK);
+                       pr_debug("pasemi_msi: failed mapping hwirq 0x%x\n",
+                                 hwirq);
+                       msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq,
+                                              ALLOC_CHUNK);
                        return -ENOSPC;
                }
 
@@ -133,8 +135,8 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                set_irq_chip(virq, &mpic_pasemi_msi_chip);
                set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
-               pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%x\n",
-                         virq, hwirq, msg.address_lo);
+               pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \
+                        "addr 0x%x\n", virq, hwirq, msg.address_lo);
 
                /* Likewise, the device writes [0...511] into the target
                 * register to generate MSI [512...1023]
index 6e2f8686fdfc0471946b8344f75ed70c042150e3..0a8f5a9e87c94d48b040735d156d1e6ff298ee62 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
+#include <asm/msi_bitmap.h>
 
 #include "mpic.h"
 
@@ -101,7 +102,8 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
                        continue;
 
                set_irq_msi(entry->irq, NULL);
-               mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
+                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
        }
 
@@ -110,29 +112,27 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
 
 static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
-       irq_hw_number_t hwirq;
        unsigned int virq;
        struct msi_desc *entry;
        struct msi_msg msg;
        u64 addr;
-       int ret;
+       int hwirq;
 
        addr = find_ht_magic_addr(pdev);
        msg.address_lo = addr & 0xFFFFFFFF;
        msg.address_hi = addr >> 32;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
-               ret = mpic_msi_alloc_hwirqs(msi_mpic, 1);
-               if (ret < 0) {
+               hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
+               if (hwirq < 0) {
                        pr_debug("u3msi: failed allocating hwirq\n");
-                       return ret;
+                       return hwirq;
                }
-               hwirq = ret;
 
                virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
                if (virq == NO_IRQ) {
-                       pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq);
-                       mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
+                       pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
+                       msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
                        return -ENOSPC;
                }
 
@@ -140,8 +140,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                set_irq_chip(virq, &mpic_u3msi_chip);
                set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
-               pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n",
-                         virq, hwirq, addr);
+               pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
+                         virq, hwirq, (unsigned long)addr);
 
                msg.data = hwirq;
                write_msi_msg(virq, &msg);
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
new file mode 100644 (file)
index 0000000..f84217b
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2006-2008, Michael Ellerman, 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; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitmap.h>
+#include <asm/msi_bitmap.h>
+
+int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num)
+{
+       unsigned long flags;
+       int offset, order = get_count_order(num);
+
+       spin_lock_irqsave(&bmp->lock, flags);
+       /*
+        * This is fast, but stricter than we need. We might want to add
+        * a fallback routine which does a linear search with no alignment.
+        */
+       offset = bitmap_find_free_region(bmp->bitmap, bmp->irq_count, order);
+       spin_unlock_irqrestore(&bmp->lock, flags);
+
+       pr_debug("msi_bitmap: allocated 0x%x (2^%d) at offset 0x%x\n",
+                num, order, offset);
+
+       return offset;
+}
+
+void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset,
+                           unsigned int num)
+{
+       unsigned long flags;
+       int order = get_count_order(num);
+
+       pr_debug("msi_bitmap: freeing 0x%x (2^%d) at offset 0x%x\n",
+                num, order, offset);
+
+       spin_lock_irqsave(&bmp->lock, flags);
+       bitmap_release_region(bmp->bitmap, offset, order);
+       spin_unlock_irqrestore(&bmp->lock, flags);
+}
+
+void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq)
+{
+       unsigned long flags;
+
+       pr_debug("msi_bitmap: reserving hwirq 0x%x\n", hwirq);
+
+       spin_lock_irqsave(&bmp->lock, flags);
+       bitmap_allocate_region(bmp->bitmap, hwirq, 0);
+       spin_unlock_irqrestore(&bmp->lock, flags);
+}
+
+/**
+ * msi_bitmap_reserve_dt_hwirqs - Reserve irqs specified in the device tree.
+ * @bmp: pointer to the MSI bitmap.
+ *
+ * Looks in the device tree to see if there is a property specifying which
+ * irqs can be used for MSI. If found those irqs reserved in the device tree
+ * are reserved in the bitmap.
+ *
+ * Returns 0 for success, < 0 if there was an error, and > 0 if no property
+ * was found in the device tree.
+ **/
+int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp)
+{
+       int i, j, len;
+       const u32 *p;
+
+       if (!bmp->of_node)
+               return 1;
+
+       p = of_get_property(bmp->of_node, "msi-available-ranges", &len);
+       if (!p) {
+               pr_debug("msi_bitmap: no msi-available-ranges property " \
+                        "found on %s\n", bmp->of_node->full_name);
+               return 1;
+       }
+
+       if (len % (2 * sizeof(u32)) != 0) {
+               printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges"
+                      " property on %s\n", bmp->of_node->full_name);
+               return -EINVAL;
+       }
+
+       bitmap_allocate_region(bmp->bitmap, 0, get_count_order(bmp->irq_count));
+
+       spin_lock(&bmp->lock);
+
+       /* Format is: (<u32 start> <u32 count>)+ */
+       len /= 2 * sizeof(u32);
+       for (i = 0; i < len; i++, p += 2) {
+               for (j = 0; j < *(p + 1); j++)
+                       bitmap_release_region(bmp->bitmap, *p + j, 0);
+       }
+
+       spin_unlock(&bmp->lock);
+
+       return 0;
+}
+
+int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count,
+                    struct device_node *of_node)
+{
+       int size;
+
+       if (!irq_count)
+               return -EINVAL;
+
+       size = BITS_TO_LONGS(irq_count) * sizeof(long);
+       pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size);
+
+       bmp->bitmap = zalloc_maybe_bootmem(size, GFP_KERNEL);
+       if (!bmp->bitmap) {
+               pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n");
+               return -ENOMEM;
+       }
+
+       /* We zalloc'ed the bitmap, so all irqs are free by default */
+       spin_lock_init(&bmp->lock);
+       bmp->of_node = of_node_get(of_node);
+       bmp->irq_count = irq_count;
+
+       return 0;
+}
+
+void msi_bitmap_free(struct msi_bitmap *bmp)
+{
+       /* we can't free the bitmap we don't know if it's bootmem etc. */
+       of_node_put(bmp->of_node);
+       bmp->bitmap = NULL;
+}
+
+#ifdef CONFIG_MSI_BITMAP_SELFTEST
+
+#define check(x)       \
+       if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
+
+void test_basics(void)
+{
+       struct msi_bitmap bmp;
+       int i, size = 512;
+
+       /* Can't allocate a bitmap of 0 irqs */
+       check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
+
+       /* of_node may be NULL */
+       check(0 == msi_bitmap_alloc(&bmp, size, NULL));
+
+       /* Should all be free by default */
+       check(0 == bitmap_find_free_region(bmp.bitmap, size,
+                                          get_count_order(size)));
+       bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
+
+       /* With no node, there's no msi-available-ranges, so expect > 0 */
+       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+
+       /* Should all still be free */
+       check(0 == bitmap_find_free_region(bmp.bitmap, size,
+                                          get_count_order(size)));
+       bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
+
+       /* Check we can fill it up and then no more */
+       for (i = 0; i < size; i++)
+               check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
+
+       check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
+
+       /* Should all be allocated */
+       check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0);
+
+       /* And if we free one we can then allocate another */
+       msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
+       check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
+
+       msi_bitmap_free(&bmp);
+
+       /* Clients may check bitmap == NULL for "not-allocated" */
+       check(bmp.bitmap == NULL);
+
+       kfree(bmp.bitmap);
+}
+
+void test_of_node(void)
+{
+       u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 };
+       const char *expected_str = "0-9,20-24,28-39,41-99,220-255";
+       char *prop_name = "msi-available-ranges";
+       char *node_name = "/fakenode";
+       struct device_node of_node;
+       struct property prop;
+       struct msi_bitmap bmp;
+       int size = 256;
+       DECLARE_BITMAP(expected, size);
+
+       /* There should really be a struct device_node allocator */
+       memset(&of_node, 0, sizeof(of_node));
+       kref_init(&of_node.kref);
+       of_node.full_name = node_name;
+
+       check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
+
+       /* No msi-available-ranges, so expect > 0 */
+       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+
+       /* Should all still be free */
+       check(0 == bitmap_find_free_region(bmp.bitmap, size,
+                                          get_count_order(size)));
+       bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
+
+       /* Now create a fake msi-available-ranges property */
+
+       /* There should really .. oh whatever */
+       memset(&prop, 0, sizeof(prop));
+       prop.name = prop_name;
+       prop.value = &prop_data;
+       prop.length = sizeof(prop_data);
+
+       of_node.properties = &prop;
+
+       /* msi-available-ranges, so expect == 0 */
+       check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
+
+       /* Check we got the expected result */
+       check(0 == bitmap_parselist(expected_str, expected, size));
+       check(bitmap_equal(expected, bmp.bitmap, size));
+
+       msi_bitmap_free(&bmp);
+       kfree(bmp.bitmap);
+}
+
+int msi_bitmap_selftest(void)
+{
+       printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n");
+
+       test_basics();
+       test_of_node();
+
+       return 0;
+}
+late_initcall(msi_bitmap_selftest);
+#endif /* CONFIG_MSI_BITMAP_SELFTEST */
index fb368dfde5d472403a67c33ec88d8cde55beec6f..d3e4d61030b59039759ad4d4d2eaa9318e32abe0 100644 (file)
 #include <asm/machdep.h>
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
+#include <mm/mmu_decl.h>
 
 #include "ppc4xx_pci.h"
 
 static int dma_offset_set;
 
-/* Move that to a useable header */
-extern unsigned long total_memory;
-
 #define U64_TO_U32_LOW(val)    ((u32)((val) & 0x00000000ffffffffULL))
 #define U64_TO_U32_HIGH(val)   ((u32)((val) >> 32))
 
-#ifdef CONFIG_RESOURCES_64BIT
-#define RES_TO_U32_LOW(val)    U64_TO_U32_LOW(val)
-#define RES_TO_U32_HIGH(val)   U64_TO_U32_HIGH(val)
-#else
-#define RES_TO_U32_LOW(val)    (val)
-#define RES_TO_U32_HIGH(val)   (0)
-#endif
+#define RES_TO_U32_LOW(val)    \
+       ((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_LOW(val) : (val))
+#define RES_TO_U32_HIGH(val)   \
+       ((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_HIGH(val) : (0))
 
 static inline int ppc440spe_revA(void)
 {
@@ -105,7 +100,8 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
 
        /* Default */
        res->start = 0;
-       res->end = size = 0x80000000;
+       size = 0x80000000;
+       res->end = size - 1;
        res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
 
        /* Get dma-ranges property */
@@ -145,12 +141,11 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
 
                /* Use that */
                res->start = pci_addr;
-#ifndef CONFIG_RESOURCES_64BIT
                /* Beware of 32 bits resources */
-               if ((pci_addr + size) > 0x100000000ull)
+               if (sizeof(resource_size_t) == sizeof(u32) &&
+                   (pci_addr + size) > 0x100000000ull)
                        res->end = 0xffffffff;
                else
-#endif
                        res->end = res->start + size - 1;
                break;
        }
@@ -167,13 +162,13 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
         */
        if (size < total_memory) {
                printk(KERN_ERR "%s: dma-ranges too small "
-                      "(size=%llx total_memory=%lx)\n",
-                      hose->dn->full_name, size, total_memory);
+                      "(size=%llx total_memory=%llx)\n",
+                      hose->dn->full_name, size, (u64)total_memory);
                return -ENXIO;
        }
 
        /* Check we are a power of 2 size and that base is a multiple of size*/
-       if (!is_power_of_2(size) ||
+       if ((size & (size - 1)) != 0  ||
            (res->start & (size - 1)) != 0) {
                printk(KERN_ERR "%s: dma-ranges unaligned\n",
                       hose->dn->full_name);
@@ -277,9 +272,16 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
        const int *bus_range;
        int primary = 0;
 
+       /* Check if device is enabled */
+       if (!of_device_is_available(np)) {
+               printk(KERN_INFO "%s: Port disabled via device-tree\n",
+                      np->full_name);
+               return;
+       }
+
        /* Fetch config space registers address */
        if (of_address_to_resource(np, 0, &rsrc_cfg)) {
-               printk(KERN_ERR "%s:Can't get PCI config register base !",
+               printk(KERN_ERR "%s: Can't get PCI config register base !",
                       np->full_name);
                return;
        }
@@ -810,7 +812,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
        switch (port->index) {
        case 0:
                mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
-               mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136);
+               mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130);
                mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
 
                mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000);
@@ -821,10 +823,10 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
                mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);
                mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);
                mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230);
-               mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136);
-               mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136);
-               mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136);
-               mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136);
+               mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000130);
+               mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000130);
+               mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000130);
+               mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000130);
                mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);
                mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);
                mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006);
index 1ce546462be5af559539fb00314c8fc89d0c03b1..76ffbc48d4b949f410e611b15d6550a647bdb30b 100644 (file)
@@ -24,12 +24,3 @@ config QE_USB
        bool
        help
          QE USB Host Controller support
-
-config QE_GPIO
-       bool "QE GPIO support"
-       depends on QUICC_ENGINE
-       select GENERIC_GPIO
-       select ARCH_REQUIRE_GPIOLIB
-       help
-         Say Y here if you're going to use hardware that connects to the
-         QE GPIOs.
index 4c03049e7db9195586fe00b07a22c067dcc3f30a..bc581d8a7cd9c35995e6bb75ae1f17d101840de1 100644 (file)
@@ -565,13 +565,16 @@ config ZFCPDUMP
          Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
 
 config S390_GUEST
-bool "s390 guest support (EXPERIMENTAL)"
+bool "s390 guest support for KVM (EXPERIMENTAL)"
        depends on 64BIT && EXPERIMENTAL
        select VIRTIO
        select VIRTIO_RING
        select VIRTIO_CONSOLE
        help
-         Select this option if you want to run the kernel under s390 linux
+         Select this option if you want to run the kernel as a guest under
+         the KVM hypervisor. This will add detection for KVM as well  as a
+         virtio transport. If KVM is detected, the virtio console will be
+         the default console.
 endmenu
 
 source "net/Kconfig"
index 7383781f3e6a60ba3c632b1f0d3b26c7800c6ecf..36313801cd5cf29e49d5c2c4d9c4e7a9cd12c104 100644 (file)
@@ -219,7 +219,7 @@ static int hypfs_release(struct inode *inode, struct file *filp)
 
 enum { opt_uid, opt_gid, opt_err };
 
-static match_table_t hypfs_tokens = {
+static const match_table_t hypfs_tokens = {
        {opt_uid, "uid=%u"},
        {opt_gid, "gid=%u"},
        {opt_err, NULL}
index 3cad56923815156107862b27e69bb4b2648b5ad8..261785ab5b2248f41e274fb8ec93d03e0f4d2f76 100644 (file)
@@ -166,13 +166,11 @@ extern char elf_platform[];
 #define ELF_PLATFORM (elf_platform)
 
 #ifndef __s390x__
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 #else /* __s390x__ */
-#define SET_PERSONALITY(ex, ibcs2)                     \
+#define SET_PERSONALITY(ex)                            \
 do {                                                   \
-       if (ibcs2)                                      \
-               set_personality(PER_SVR4);              \
-       else if (current->personality != PER_LINUX32)   \
+       if (current->personality != PER_LINUX32)        \
                set_personality(PER_LINUX);             \
        if ((ex).e_ident[EI_CLASS] == ELFCLASS32)       \
                set_thread_flag(TIF_31BIT);             \
index 099a45579190e4764343dfebe85cc05f178293f9..06cc70307eceb96e152e4565b366e3feac3e7353 100644 (file)
 #ifndef __s390x__
 #include <asm-generic/statfs.h>
 #else
+/*
+ * We can't use <asm-generic/statfs.h> because in 64-bit mode
+ * we mix ints of different sizes in our struct statfs.
+ */
 
 #ifndef __KERNEL_STRICT_NAMES
-
 #include <linux/types.h>
-
 typedef __kernel_fsid_t        fsid_t;
-
 #endif
 
-/*
- * This is ugly -- we're already 64-bit clean, so just duplicate the 
- * definitions.
- */
 struct statfs {
        int  f_type;
        int  f_bsize;
index 98e246dc02338bef90d6cd9f27d39069b4cac414..4646382af34f1260a547274d69c4341852fb55fb 100644 (file)
@@ -279,22 +279,6 @@ asmlinkage long sys32_getegid16(void)
        return high2lowgid(current->egid);
 }
 
-/* 32-bit timeval and related flotsam.  */
-
-static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
-       return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
-               (__get_user(o->tv_sec, &i->tv_sec) ||
-                __get_user(o->tv_usec, &i->tv_usec)));
-}
-
-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) ||
-                __put_user(i->tv_usec, &o->tv_usec)));
-}
-
 /*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
  *
@@ -362,41 +346,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
                return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(stat->ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
-       err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-/* fixme
-       err |= put_user(0, &statbuf->__unused4[0]);
-       err |= put_user(0, &statbuf->__unused4[1]);
-*/
-       return err;
-}
-
 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
                                struct compat_timespec __user *interval)
 {
@@ -557,57 +506,6 @@ sys32_delete_module(const char __user *name_user, unsigned int flags)
 
 #endif  /* CONFIG_MODULES */
 
-/* Translations due to time_t size differences.  Which affects all
-   sorts of things, like timeval and itimerval.  */
-
-extern struct timezone sys_tz;
-
-asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (!access_ok(VERIFY_READ, i, sizeof(*i)))
-               return -EFAULT;
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-       return 0;
-}
-
-asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
                                size_t count, u32 poshi, u32 poslo)
 {
index 05f8516366ab0df450c12a53723a53fe94ef841e..836a28842900eee9b6c6e1f038a9a6d124e55707 100644 (file)
@@ -202,10 +202,6 @@ long sys32_execve(void);
 long sys32_init_module(void __user *umod, unsigned long len,
                       const char __user *uargs);
 long sys32_delete_module(const char __user *name_user, unsigned int flags);
-long sys32_gettimeofday(struct compat_timeval __user *tv,
-                       struct timezone __user *tz);
-long sys32_settimeofday(struct compat_timeval __user *tv,
-                       struct timezone __user *tz);
 long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count,
                   u32 poshi, u32 poslo);
 long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
index ee51ca9e23b56e1ba0380323f4cac8193d63c627..fc2c97197a53ffbe9df9917e7087de4ecb1a57d9 100644 (file)
@@ -332,17 +332,17 @@ compat_sys_getrusage_wrapper:
        llgtr   %r3,%r3                 # struct rusage_emu31 *
        jg      compat_sys_getrusage    # branch to system call
 
-       .globl  sys32_gettimeofday_wrapper
-sys32_gettimeofday_wrapper:
+       .globl  compat_sys_gettimeofday_wrapper
+compat_sys_gettimeofday_wrapper:
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
-       jg      sys32_gettimeofday      # branch to system call
+       jg      compat_sys_gettimeofday # branch to system call
 
-       .globl  sys32_settimeofday_wrapper
-sys32_settimeofday_wrapper:
+       .globl  compat_sys_settimeofday_wrapper
+compat_sys_settimeofday_wrapper:
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
-       jg      sys32_settimeofday      # branch to system call
+       jg      compat_sys_settimeofday # branch to system call
 
        .globl  sys32_getgroups16_wrapper
 sys32_getgroups16_wrapper:
index 3ae303914b4201f63dc83c09ca74744e2e3ec283..2d61787949d5b9ee99b7512373668131ad7da7b4 100644 (file)
@@ -86,8 +86,8 @@ SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
 SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper)      /* 75 */
 SYSCALL(sys_old_getrlimit,sys_getrlimit,compat_sys_old_getrlimit_wrapper)
 SYSCALL(sys_getrusage,sys_getrusage,compat_sys_getrusage_wrapper)
-SYSCALL(sys_gettimeofday,sys_gettimeofday,sys32_gettimeofday_wrapper)
-SYSCALL(sys_settimeofday,sys_settimeofday,sys32_settimeofday_wrapper)
+SYSCALL(sys_gettimeofday,sys_gettimeofday,compat_sys_gettimeofday_wrapper)
+SYSCALL(sys_settimeofday,sys_settimeofday,compat_sys_settimeofday_wrapper)
 SYSCALL(sys_getgroups16,sys_ni_syscall,sys32_getgroups16_wrapper)      /* 80 old getgroups16 syscall */
 SYSCALL(sys_setgroups16,sys_ni_syscall,sys32_setgroups16_wrapper)      /* old setgroups16 syscall */
 NI_SYSCALL                                                     /* old select syscall */
index d1faf5c544057f718c3737faf2340dfbaf3914c1..cce40ff2913bbf851059c8ea0f8d604d4eb94304 100644 (file)
@@ -157,8 +157,8 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
        int rc;
 
        vcpu->stat.instruction_stfl++;
-       facility_list &= ~(1UL<<24); /* no stfle */
-       facility_list &= ~(1UL<<23); /* no large pages */
+       /* only pass the facility bits, which we can handle */
+       facility_list &= 0xfe00fff3;
 
        rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
                           &facility_list, sizeof(facility_list));
index f01449a8d378c498197150df82abf6ab8b439b09..ee02db110f0da3b78aa0c5a4c66ba13c28c362a3 100644 (file)
@@ -189,7 +189,7 @@ do {                                                                        \
 } while (0)
 #endif
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
 struct task_struct;
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
index 2ba7183bc1f05572fba2636ce160a5c43400963e..2d2769d766ec7cacc827737bdbea9d73e139cfce 100644 (file)
@@ -15,8 +15,6 @@ header-y += signal_32.h
 header-y += signal_64.h
 header-y += stat_32.h
 header-y += stat_64.h
-header-y += statfs_32.h
-header-y += statfs_64.h
 header-y += unistd_32.h
 header-y += unistd_64.h
 
index b7ab605478270779478103013c5fca34ea55f3f4..381a1b5256d6c9f23e0cb683b90ba8307265a409 100644 (file)
@@ -137,6 +137,6 @@ typedef struct {
 
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif /* !(__ASMSPARC_ELF_H) */
index 0818a1308f4e7a252b213d07a0025f5e70c72dca..425c2f9be6d5abe1e5e9aa53a157440807817838 100644 (file)
@@ -195,7 +195,7 @@ static inline unsigned int sparc64_elf_hwcap(void)
 
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2)                     \
+#define SET_PERSONALITY(ex)                            \
 do {   unsigned long new_flags = current_thread_info()->flags; \
        new_flags &= _TIF_32BIT;                        \
        if ((ex).e_ident[EI_CLASS] == ELFCLASS32)       \
@@ -208,9 +208,7 @@ do {        unsigned long new_flags = current_thread_info()->flags; \
        else                                            \
                clear_thread_flag(TIF_ABI_PENDING);     \
        /* flush_thread will update pgd cache */        \
-       if (ibcs2)                                      \
-               set_personality(PER_SVR4);              \
-       else if (current->personality != PER_LINUX32)   \
+       if (current->personality != PER_LINUX32)        \
                set_personality(PER_LINUX);             \
 } while (0)
 
diff --git a/arch/sparc/include/asm/serial.h b/arch/sparc/include/asm/serial.h
new file mode 100644 (file)
index 0000000..f90d61c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SPARC_SERIAL_H
+#define __SPARC_SERIAL_H
+
+#define BASE_BAUD ( 1843200 / 16 )
+
+#endif /* __SPARC_SERIAL_H */
index 5e937a73743dd85d7b830db6be254be72ed01105..55e607ad461d1ddfded240eb124030a8d4810c98 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef ___ASM_SPARC_STATFS_H
 #define ___ASM_SPARC_STATFS_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/statfs_64.h>
-#else
-#include <asm/statfs_32.h>
-#endif
+
+#include <asm-generic/statfs.h>
+
 #endif
diff --git a/arch/sparc/include/asm/statfs_32.h b/arch/sparc/include/asm/statfs_32.h
deleted file mode 100644 (file)
index 304520f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _SPARC_STATFS_H
-#define _SPARC_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif
diff --git a/arch/sparc/include/asm/statfs_64.h b/arch/sparc/include/asm/statfs_64.h
deleted file mode 100644 (file)
index 79b3c89..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _SPARC64_STATFS_H
-#define _SPARC64_STATFS_H
-
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t        fsid_t;
-
-#endif
-
-struct statfs {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct statfs64 {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-};
-
-#endif
index ce3d45db94e9f777d3520e52c2052c33cfc93017..7a6a5e7959282e736fb5b01baa591d9d52b478d4 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
+#include <linux/cpu.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
index 0c564ba9e70938727e8460ae2a78806e268893bd..5fc386d08c4713ae0dd968cc02df4f044f0a77b2 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
+#include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
index 967b04886822273f73f00cf550007cb0c51da68b..3b9f4d6e14a9d3119a939e7b5edfc3aec30c554b 100644 (file)
@@ -831,7 +831,7 @@ static int __init us3mc_init(void)
        if (!us3mc_platform())
                return -ENODEV;
 
-       __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+       __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
        if ((ver >> 32UL) == __JALAPENO_ID ||
            (ver >> 32UL) == __SERRANO_ID) {
                mc_type = MC_TYPE_JBUS;
index 2a37a6ca2a16d46e5dd5ea5680230b56e11bedb3..1cc1995531e22d3f7e5066fadd2fc66df16e3a63 100644 (file)
@@ -575,7 +575,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
                }
                /* Allocate iommu entries for that segment */
                paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
-               npages = iommu_num_pages(paddr, slen);
+               npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
                entry = iommu_range_alloc(dev, iommu, npages, &handle);
 
                /* Handle failure */
@@ -647,7 +647,8 @@ iommu_map_failed:
                        iopte_t *base;
 
                        vaddr = s->dma_address & IO_PAGE_MASK;
-                       npages = iommu_num_pages(s->dma_address, s->dma_length);
+                       npages = iommu_num_pages(s->dma_address, s->dma_length,
+                                                IO_PAGE_SIZE);
                        iommu_range_free(iommu, vaddr, npages);
 
                        entry = (vaddr - iommu->page_table_map_base)
@@ -715,7 +716,7 @@ static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
 
                if (!len)
                        break;
-               npages = iommu_num_pages(dma_handle, len);
+               npages = iommu_num_pages(dma_handle, len, IO_PAGE_SIZE);
                iommu_range_free(iommu, dma_handle, npages);
 
                entry = ((dma_handle - iommu->page_table_map_base)
index 53b19c8231a931ee1ab2f1a863e62053026ac748..591f5879039ce316a2a9d5187af3367f46e86ecb 100644 (file)
 
 #define SG_ENT_PHYS_ADDRESS(SG)        (__pa(sg_virt((SG))))
 
-static inline unsigned long iommu_num_pages(unsigned long vaddr,
-                                           unsigned long slen)
-{
-       unsigned long npages;
-
-       npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK);
-       npages >>= IO_PAGE_SHIFT;
-
-       return npages;
-}
-
 static inline int is_span_boundary(unsigned long entry,
                                   unsigned long shift,
                                   unsigned long boundary_size,
@@ -53,7 +42,8 @@ static inline int is_span_boundary(unsigned long entry,
                                   struct scatterlist *sg)
 {
        unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
-       int nr = iommu_num_pages(paddr, outs->dma_length + sg->length);
+       int nr = iommu_num_pages(paddr, outs->dma_length + sg->length,
+                                IO_PAGE_SIZE);
 
        return iommu_is_span_boundary(entry, nr, shift, boundary_size);
 }
index e86c73ec167b3ff66d887204f41630d71e7f2d08..34a1fded39415cbbc863f39babe56bacd39d489a 100644 (file)
@@ -384,7 +384,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
                }
                /* Allocate iommu entries for that segment */
                paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
-               npages = iommu_num_pages(paddr, slen);
+               npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
                entry = iommu_range_alloc(dev, iommu, npages, &handle);
 
                /* Handle failure */
@@ -461,7 +461,8 @@ iommu_map_failed:
                        unsigned long vaddr, npages;
 
                        vaddr = s->dma_address & IO_PAGE_MASK;
-                       npages = iommu_num_pages(s->dma_address, s->dma_length);
+                       npages = iommu_num_pages(s->dma_address, s->dma_length,
+                                                IO_PAGE_SIZE);
                        iommu_range_free(iommu, vaddr, npages);
                        /* XXX demap? XXX */
                        s->dma_address = DMA_ERROR_CODE;
@@ -500,7 +501,7 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 
                if (!len)
                        break;
-               npages = iommu_num_pages(dma_handle, len);
+               npages = iommu_num_pages(dma_handle, len, IO_PAGE_SIZE);
                iommu_range_free(iommu, dma_handle, npages);
 
                entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
index 2be166c544ca42a27222325cc61001b5190e368c..e5627118e6131b527468b4107f3d9f40a63387ea 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/jiffies.h>
 #include <linux/profile.h>
 #include <linux/lmb.h>
+#include <linux/cpu.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -115,6 +116,9 @@ void __cpuinit smp_callin(void)
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
 
+       /* inform the notifiers about the new cpu */
+       notify_cpu_starting(cpuid);
+
        while (!cpu_isset(cpuid, smp_commenced_mask))
                rmb();
 
index 3320c9d0075f79eac52690def1371024d1b3f9bb..e800503879e4b6dc410eecd74ee2d2138d742083 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/compat_signal.h>
 
-/* 32-bit timeval and related flotsam.  */
-
-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-               (__put_user(i->tv_sec, &o->tv_sec) |
-                __put_user(i->tv_usec, &o->tv_usec)));
-}
-
 #ifdef CONFIG_SYSVIPC                                                        
 asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
 {
@@ -148,41 +139,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
                return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(stat->ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
-       err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-       err |= put_user(0, &statbuf->__unused4[0]);
-       err |= put_user(0, &statbuf->__unused4[1]);
-
-       return err;
-}
-
 static int cp_compat_stat64(struct kstat *stat,
                            struct compat_stat64 __user *statbuf)
 {
@@ -522,59 +478,6 @@ asmlinkage long sys32_delete_module(const char __user *name_user)
 
 #endif  /* CONFIG_MODULES */
 
-/* Translations due to time_t size differences.  Which affects all
-   sorts of things, like timeval and itimerval.  */
-
-extern struct timezone sys_tz;
-
-asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
-                                  struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
-{
-       long usec;
-
-       if (!access_ok(VERIFY_READ, i, sizeof(*i)))
-               return -EFAULT;
-       if (__get_user(o->tv_sec, &i->tv_sec))
-               return -EFAULT;
-       if (__get_user(usec, &i->tv_usec))
-               return -EFAULT;
-       o->tv_nsec = usec * 1000;
-       return 0;
-}
-
-asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
-                                  struct timezone __user *tz)
-{
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_ts32(&kts, tv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
                                        char __user *ubuf,
                                        compat_size_t count,
index 5daee4b04dd5a655c313c07ee1dabf4ea34871fe..b2fa4c1636387f2e40bf52a09c8d80bae7dce36c 100644 (file)
@@ -41,8 +41,8 @@ sys_call_table32:
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
        .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/        .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
-       .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
-/*120*/        .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys_fchown16, sys_fchmod
+       .word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
+/*120*/        .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
        .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
 /*130*/        .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
        .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
index 47e3acafb5be4c0f0786bbe12fd2b353334f4d92..365b6464e2ce20037e27af6023aa330ba6380612 100644 (file)
@@ -183,7 +183,6 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
        table[3].index = 0;
        table[3].frequency = CPUFREQ_TABLE_END;
 
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
        policy->cpuinfo.transition_latency = 0;
        policy->cur = clock_tick;
 
index e09edfa560da5c1ec5eb0d40f247d13a5eee29c7..1f57c113df6dab5d6816b829d994958c1ad657e4 100644 (file)
@@ -9,8 +9,9 @@ config UML_X86
        default y
 
 config X86_32
-       bool
-       default y
+       bool
+       default y
+       select HAVE_AOUT
 
 config RWSEM_XCHGADD_ALGORITHM
        def_bool y
@@ -42,6 +43,3 @@ config ARCH_REUSE_HOST_VSYSCALL_AREA
 config GENERIC_HWEIGHT
        bool
        default y
-
-config ARCH_SUPPORTS_AOUT
-       def_bool y
index 5696e7b374b31904b7559d045b7235b4e25bcf3e..40b3407cfe169c9b5d68aef83f06b75a382f85c0 100644 (file)
@@ -37,6 +37,3 @@ config SMP_BROKEN
 config GENERIC_HWEIGHT
        bool
        default y
-
-config ARCH_SUPPORTS_AOUT
-       def_bool y
index d741f35d7b3a3654e20e2ccf780fc54e8c76f1be..14a102e877d66e51a1e28a4f5a64ce23b509050a 100644 (file)
@@ -275,6 +275,8 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
        case TIOCGLTC:
        case TIOCSLTC:
 #endif
+       /* Note: these are out of date as we now have TCGETS2 etc but this
+          whole lot should probably go away */
        case TCGETS:
        case TCSETSF:
        case TCSETSW:
index f5d7f4569ba726f51fc92ef1b3b7e0ccdcb4e230..598711c62c82cbb59ce79193eaa67e70d45b48e3 100644 (file)
@@ -42,23 +42,11 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
        PT_REGS_SP(regs) = esp;
 }
 
-#ifdef CONFIG_TTY_LOG
-extern void log_exec(char **argv, void *tty);
-#endif
-
 static long execve1(char *file, char __user * __user *argv,
                    char __user *__user *env)
 {
        long error;
-#ifdef CONFIG_TTY_LOG
-       struct tty_struct *tty;
 
-       mutex_lock(&tty_mutex);
-       tty = get_current_tty();
-       if (tty)
-               log_exec(argv, tty);
-       mutex_unlock(&tty_mutex);
-#endif
        error = do_execve(file, argv, env, &current->thread.regs);
        if (error == 0) {
                task_lock(current);
index 8a48d6a30064139fa28bcfc53a0897b046988a3b..d66f0388f091f17e0b7d06257853bc9b2e3b1859 100644 (file)
@@ -7,9 +7,6 @@ obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
        registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
        umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
 
-obj-$(CONFIG_TTY_LOG) += tty_log.o
-user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
        main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
        tty.o tls.o uaccess.o umid.o util.o
diff --git a/arch/um/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
deleted file mode 100644 (file)
index cc648e6..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
- * geoffrey hing <ghing@net.ohio-state.edu>
- * Licensed under the GPL
- */
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include "init.h"
-#include "user.h"
-#include "os.h"
-
-#define TTY_LOG_DIR "./"
-
-/* Set early in boot and then unchanged */
-static char *tty_log_dir = TTY_LOG_DIR;
-static int tty_log_fd = -1;
-
-#define TTY_LOG_OPEN 1
-#define TTY_LOG_CLOSE 2
-#define TTY_LOG_WRITE 3
-#define TTY_LOG_EXEC 4
-
-#define TTY_READ 1
-#define TTY_WRITE 2
-
-struct tty_log_buf {
-       int what;
-       unsigned long tty;
-       int len;
-       int direction;
-       unsigned long sec;
-       unsigned long usec;
-};
-
-int open_tty_log(void *tty, void *current_tty)
-{
-       struct timeval tv;
-       struct tty_log_buf data;
-       char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
-       int fd;
-
-       gettimeofday(&tv, NULL);
-       if(tty_log_fd != -1){
-               data = ((struct tty_log_buf) { .what    = TTY_LOG_OPEN,
-                                              .tty  = (unsigned long) tty,
-                                              .len  = sizeof(current_tty),
-                                              .direction = 0,
-                                              .sec = tv.tv_sec,
-                                              .usec = tv.tv_usec } );
-               write(tty_log_fd, &data, sizeof(data));
-               write(tty_log_fd, &current_tty, data.len);
-               return tty_log_fd;
-       }
-
-       sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
-               (unsigned int) tv.tv_usec);
-
-       fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
-                         0644);
-       if(fd < 0){
-               printk("open_tty_log : couldn't open '%s', errno = %d\n",
-                      buf, -fd);
-       }
-       return fd;
-}
-
-void close_tty_log(int fd, void *tty)
-{
-       struct tty_log_buf data;
-       struct timeval tv;
-
-       if(tty_log_fd != -1){
-               gettimeofday(&tv, NULL);
-               data = ((struct tty_log_buf) { .what    = TTY_LOG_CLOSE,
-                                              .tty  = (unsigned long) tty,
-                                              .len  = 0,
-                                              .direction = 0,
-                                              .sec = tv.tv_sec,
-                                              .usec = tv.tv_usec } );
-               write(tty_log_fd, &data, sizeof(data));
-               return;
-       }
-       os_close_file(fd);
-}
-
-static int log_chunk(int fd, const char *buf, int len)
-{
-       int total = 0, try, missed, n;
-       char chunk[64];
-
-       while(len > 0){
-               try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
-               missed = copy_from_user_proc(chunk, (char *) buf, try);
-               try -= missed;
-               n = write(fd, chunk, try);
-               if(n != try) {
-                       if(n < 0)
-                               return -errno;
-                       return -EIO;
-               }
-               if(missed != 0)
-                       return -EFAULT;
-
-               len -= try;
-               total += try;
-               buf += try;
-       }
-
-       return total;
-}
-
-int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
-{
-       struct timeval tv;
-       struct tty_log_buf data;
-       int direction;
-
-       if(fd == tty_log_fd){
-               gettimeofday(&tv, NULL);
-               direction = is_read ? TTY_READ : TTY_WRITE;
-               data = ((struct tty_log_buf) { .what    = TTY_LOG_WRITE,
-                                              .tty  = (unsigned long) tty,
-                                              .len  = len,
-                                              .direction = direction,
-                                              .sec = tv.tv_sec,
-                                              .usec = tv.tv_usec } );
-               write(tty_log_fd, &data, sizeof(data));
-       }
-
-       return log_chunk(fd, buf, len);
-}
-
-void log_exec(char **argv, void *tty)
-{
-       struct timeval tv;
-       struct tty_log_buf data;
-       char **ptr,*arg;
-       int len;
-
-       if(tty_log_fd == -1) return;
-
-       gettimeofday(&tv, NULL);
-
-       len = 0;
-       for(ptr = argv; ; ptr++){
-               if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-                       return;
-               if(arg == NULL) break;
-               len += strlen_user_proc(arg);
-       }
-
-       data = ((struct tty_log_buf) { .what    = TTY_LOG_EXEC,
-                                      .tty  = (unsigned long) tty,
-                                      .len  = len,
-                                      .direction = 0,
-                                      .sec = tv.tv_sec,
-                                      .usec = tv.tv_usec } );
-       write(tty_log_fd, &data, sizeof(data));
-
-       for(ptr = argv; ; ptr++){
-               if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
-                       return;
-               if(arg == NULL) break;
-               log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
-       }
-}
-
-extern void register_tty_logger(int (*opener)(void *, void *),
-                               int (*writer)(int, const char *, int,
-                                             void *, int),
-                               void (*closer)(int, void *));
-
-static int register_logger(void)
-{
-       register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
-       return 0;
-}
-
-__uml_initcall(register_logger);
-
-static int __init set_tty_log_dir(char *name, int *add)
-{
-       tty_log_dir = name;
-       return 0;
-}
-
-__uml_setup("tty_log_dir=", set_tty_log_dir,
-"tty_log_dir=<directory>\n"
-"    This is used to specify the directory where the logs of all pty\n"
-"    data from this UML machine will be written.\n\n"
-);
-
-static int __init set_tty_log_fd(char *name, int *add)
-{
-       char *end;
-
-       tty_log_fd = strtoul(name, &end, 0);
-       if((*end != '\0') || (end == name)){
-               printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
-               tty_log_fd = -1;
-       }
-
-       *add = 0;
-       return 0;
-}
-
-__uml_setup("tty_log_fd=", set_tty_log_fd,
-"tty_log_fd=<fd>\n"
-"    This is used to specify a preconfigured file descriptor to which all\n"
-"    tty data will be written.  Preconfigure the descriptor with something\n"
-"    like '10>tty_log tty_log_fd=10'.\n\n"
-);
index fc8351f374fd466b8f9b287a6f5d4a2ec3b0fd32..bd3c2c53873ecb4cd0b944e31996b746884d6cf0 100644 (file)
@@ -18,6 +18,7 @@ config X86_64
 ### Arch settings
 config X86
        def_bool y
+       select HAVE_AOUT if X86_32
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
        select HAVE_OPROFILE
@@ -38,10 +39,6 @@ config ARCH_DEFCONFIG
        default "arch/x86/configs/i386_defconfig" if X86_32
        default "arch/x86/configs/x86_64_defconfig" if X86_64
 
-
-config GENERIC_LOCKBREAK
-       def_bool n
-
 config GENERIC_TIME
        def_bool y
 
@@ -94,7 +91,7 @@ config GENERIC_HWEIGHT
        def_bool y
 
 config GENERIC_GPIO
-       def_bool n
+       bool
 
 config ARCH_MAY_HAVE_PC_FDC
        def_bool y
@@ -105,12 +102,6 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        def_bool X86_XADD
 
-config ARCH_HAS_ILOG2_U32
-       def_bool n
-
-config ARCH_HAS_ILOG2_U64
-       def_bool n
-
 config ARCH_HAS_CPU_IDLE_WAIT
        def_bool y
 
@@ -152,9 +143,6 @@ config AUDIT_ARCH
        bool
        default X86_64
 
-config ARCH_SUPPORTS_AOUT
-       def_bool y
-
 config ARCH_SUPPORTS_OPTIMIZED_INLINING
        def_bool y
 
@@ -760,9 +748,8 @@ config I8K
          Say N otherwise.
 
 config X86_REBOOTFIXUPS
-       def_bool n
-       prompt "Enable X86 board specific fixups for reboot"
-       depends on X86_32 && X86
+       bool "Enable X86 board specific fixups for reboot"
+       depends on X86_32
        ---help---
          This enables chipset and/or board specific fixups to be done
          in order to get reboot to work correctly. This is only needed on
@@ -946,16 +933,17 @@ config HIGHMEM
        depends on X86_32 && (HIGHMEM64G || HIGHMEM4G)
 
 config X86_PAE
-       def_bool n
-       prompt "PAE (Physical Address Extension) Support"
+       bool "PAE (Physical Address Extension) Support"
        depends on X86_32 && !HIGHMEM4G
-       select RESOURCES_64BIT
        help
          PAE is required for NX support, and furthermore enables
          larger swapspace support for non-overcommit purposes. It
          has the cost of more pagetable lookup overhead, and also
          consumes more pagetable space per process.
 
+config ARCH_PHYS_ADDR_T_64BIT
+       def_bool X86_64 || X86_PAE
+
 # Common NUMA Features
 config NUMA
        bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)"
@@ -1240,8 +1228,7 @@ config X86_PAT
          If unsure, say Y.
 
 config EFI
-       def_bool n
-       prompt "EFI runtime service support"
+       bool "EFI runtime service support"
        depends on ACPI
        ---help---
        This enables the kernel to use EFI runtime services that are
@@ -1885,7 +1872,7 @@ config IA32_EMULATION
 
 config IA32_AOUT
        tristate "IA32 a.out support"
-       depends on IA32_EMULATION && ARCH_SUPPORTS_AOUT
+       depends on IA32_EMULATION
        help
          Support old a.out binaries in the 32bit emulation.
 
index c5f1013605203de94c93af52d105512ace47c1c6..0b7c4a3f0651e8e03e7f0c8ea3083bab77775812 100644 (file)
@@ -38,8 +38,7 @@ config M386
          - "Crusoe" for the Transmeta Crusoe series.
          - "Efficeon" for the Transmeta Efficeon series.
          - "Winchip-C6" for original IDT Winchip.
-         - "Winchip-2" for IDT Winchip 2.
-         - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+         - "Winchip-2" for IDT Winchips with 3dNow! capabilities.
          - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
          - "Geode GX/LX" For AMD Geode GX and LX processors.
          - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
@@ -194,19 +193,11 @@ config MWINCHIPC6
          treat this chip as a 586TSC with some extended instructions
          and alignment requirements.
 
-config MWINCHIP2
-       bool "Winchip-2"
-       depends on X86_32
-       help
-         Select this for an IDT Winchip-2.  Linux and GCC
-         treat this chip as a 586TSC with some extended instructions
-         and alignment requirements.
-
 config MWINCHIP3D
-       bool "Winchip-2A/Winchip-3"
+       bool "Winchip-2/Winchip-2A/Winchip-3"
        depends on X86_32
        help
-         Select this for an IDT Winchip-2A or 3.  Linux and GCC
+         Select this for an IDT Winchip-2, 2A or 3.  Linux and GCC
          treat this chip as a 586TSC with some extended instructions
          and alignment requirements.  Also enable out of order memory
          stores for this CPU, which can increase performance of some
@@ -318,7 +309,7 @@ config X86_L1_CACHE_SHIFT
        int
        default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC
        default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
-       default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
+       default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
        default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
 
 config X86_XADD
@@ -360,7 +351,7 @@ config X86_POPAD_OK
 
 config X86_ALIGNMENT_16
        def_bool y
-       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+       depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
 
 config X86_INTEL_USERCOPY
        def_bool y
@@ -368,7 +359,7 @@ config X86_INTEL_USERCOPY
 
 config X86_USE_PPRO_CHECKSUM
        def_bool y
-       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
+       depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
 
 config X86_USE_3DNOW
        def_bool y
@@ -376,7 +367,7 @@ config X86_USE_3DNOW
 
 config X86_OOSTORE
        def_bool y
-       depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+       depends on (MWINCHIP3D || MWINCHIPC6) && MTRR
 
 #
 # P6_NOPs are a relatively minor optimization that require a family >=
@@ -396,7 +387,7 @@ config X86_P6_NOP
 
 config X86_TSC
        def_bool y
-       depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
+       depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
 
 config X86_CMPXCHG64
        def_bool y
@@ -406,7 +397,7 @@ config X86_CMPXCHG64
 # generates cmov.
 config X86_CMOV
        def_bool y
-       depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || X86_64)
+       depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64)
 
 config X86_MINIMUM_CPU_FAMILY
        int
@@ -417,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY
 
 config X86_DEBUGCTLMSR
        def_bool y
-       depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
+       depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
 
 menuconfig PROCESSOR_SELECT
        bool "Supported processor vendors" if EMBEDDED
index b72b4f7531138cbc4c5042ac90942e752a74b8a4..80177ec052f0378d63caef550e7ea8d805ada907 100644 (file)
@@ -28,7 +28,6 @@ cflags-$(CONFIG_MK8)          += $(call cc-option,-march=k8,-march=athlon)
 cflags-$(CONFIG_MCRUSOE)       += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MEFFICEON)     += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MWINCHIPC6)    += $(call cc-option,-march=winchip-c6,-march=i586)
-cflags-$(CONFIG_MWINCHIP2)     += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MWINCHIP3D)    += $(call cc-option,-march=winchip2,-march=i586)
 cflags-$(CONFIG_MCYRIXIII)     += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
 cflags-$(CONFIG_MVIAC3_2)      += $(call cc-option,-march=c3-2,-march=i686)
index 1e6fe0214c85a34788f8ddb55f3d9b3f559b0f41..99b3079dc6ab1fb25c4f083639b13547fa663354 100644 (file)
@@ -88,14 +88,11 @@ static int vesa_probe(void)
                           (vminfo.memory_layout == 4 ||
                            vminfo.memory_layout == 6) &&
                           vminfo.memory_planes == 1) {
-#ifdef CONFIG_FB
+#ifdef CONFIG_FB_BOOT_VESA_SUPPORT
                        /* Graphics mode, color, linear frame buffer
                           supported.  Only register the mode if
                           if framebuffer is configured, however,
-                          otherwise the user will be left without a screen.
-                          We don't require CONFIG_FB_VESA, however, since
-                          some of the other framebuffer drivers can use
-                          this mode-setting, too. */
+                          otherwise the user will be left without a screen. */
                        mi = GET_HEAP(struct mode_info, 1);
                        mi->mode = mode + VIDEO_FIRST_VESA;
                        mi->depth = vminfo.bpp;
@@ -133,10 +130,12 @@ static int vesa_set_mode(struct mode_info *mode)
        if ((vminfo.mode_attr & 0x15) == 0x05) {
                /* It's a supported text mode */
                is_graphic = 0;
+#ifdef CONFIG_FB_BOOT_VESA_SUPPORT
        } else if ((vminfo.mode_attr & 0x99) == 0x99) {
                /* It's a graphics mode with linear frame buffer */
                is_graphic = 1;
                vesa_mode |= 0x4000; /* Request linear frame buffer */
+#endif
        } else {
                return -1;      /* Invalid mode */
        }
index ca226ca31288254bd40eb45ba55047c04b01bb09..52d0359719d7dda3c15ec870be577e653d829896 100644 (file)
@@ -213,7 +213,6 @@ CONFIG_M686=y
 # CONFIG_MCRUSOE is not set
 # CONFIG_MEFFICEON is not set
 # CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
 # CONFIG_MGEODEGX1 is not set
 # CONFIG_MGEODE_LX is not set
index 2c4b1c771e28dd3758388a8a634414577db9fd91..f0a03d7a7d63f2f2c32f7daea043a0935021bba3 100644 (file)
@@ -210,7 +210,6 @@ CONFIG_X86_PC=y
 # CONFIG_MCRUSOE is not set
 # CONFIG_MEFFICEON is not set
 # CONFIG_MWINCHIPC6 is not set
-# CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
 # CONFIG_MGEODEGX1 is not set
 # CONFIG_MGEODE_LX is not set
index ffc1bb4fed7d1ade2ed385597fd05464fea55528..256b00b61892b2e3049ef8ff65a672df701efc77 100644 (file)
        .endm 
 
        /* clobbers %eax */     
-       .macro  CLEAR_RREGS
+       .macro  CLEAR_RREGS _r9=rax
        xorl    %eax,%eax
        movq    %rax,R11(%rsp)
        movq    %rax,R10(%rsp)
-       movq    %rax,R9(%rsp)
+       movq    %\_r9,R9(%rsp)
        movq    %rax,R8(%rsp)
        .endm
 
         * We don't reload %eax because syscall_trace_enter() returned
         * the value it wants us to use in the table lookup.
         */
-       .macro LOAD_ARGS32 offset
-       movl \offset(%rsp),%r11d
-       movl \offset+8(%rsp),%r10d
+       .macro LOAD_ARGS32 offset, _r9=0
+       .if \_r9
        movl \offset+16(%rsp),%r9d
-       movl \offset+24(%rsp),%r8d
+       .endif
        movl \offset+40(%rsp),%ecx
        movl \offset+48(%rsp),%edx
        movl \offset+56(%rsp),%esi
@@ -145,7 +144,7 @@ ENTRY(ia32_sysenter_target)
        SAVE_ARGS 0,0,1
        /* no need to do an access_ok check here because rbp has been
           32bit zero extended */ 
-1:     movl    (%rbp),%r9d
+1:     movl    (%rbp),%ebp
        .section __ex_table,"a"
        .quad 1b,ia32_badarg
        .previous       
@@ -157,7 +156,7 @@ ENTRY(ia32_sysenter_target)
        cmpl    $(IA32_NR_syscalls-1),%eax
        ja      ia32_badsys
 sysenter_do_call:
-       IA32_ARG_FIXUP 1
+       IA32_ARG_FIXUP
 sysenter_dispatch:
        call    *ia32_sys_call_table(,%rax,8)
        movq    %rax,RAX-ARGOFFSET(%rsp)
@@ -234,20 +233,17 @@ sysexit_audit:
 #endif
 
 sysenter_tracesys:
-       xchgl   %r9d,%ebp
 #ifdef CONFIG_AUDITSYSCALL
        testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
        jz      sysenter_auditsys
 #endif
        SAVE_REST
        CLEAR_RREGS
-       movq    %r9,R9(%rsp)
        movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
        LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
-       xchgl   %ebp,%r9d
        cmpl    $(IA32_NR_syscalls-1),%eax
        ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
        jmp     sysenter_do_call
@@ -314,9 +310,9 @@ ENTRY(ia32_cstar_target)
        testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
        CFI_REMEMBER_STATE
        jnz   cstar_tracesys
-cstar_do_call: 
        cmpl $IA32_NR_syscalls-1,%eax
        ja  ia32_badsys
+cstar_do_call:
        IA32_ARG_FIXUP 1
 cstar_dispatch:
        call *ia32_sys_call_table(,%rax,8)
@@ -357,15 +353,13 @@ cstar_tracesys:
 #endif
        xchgl %r9d,%ebp
        SAVE_REST
-       CLEAR_RREGS
-       movq %r9,R9(%rsp)
+       CLEAR_RREGS r9
        movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
-       LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+       LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
        RESTORE_REST
        xchgl %ebp,%r9d
-       movl RSP-ARGOFFSET(%rsp), %r8d
        cmpl $(IA32_NR_syscalls-1),%eax
        ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
        jmp cstar_do_call
@@ -577,8 +571,8 @@ ia32_sys_call_table:
        .quad compat_sys_setrlimit      /* 75 */
        .quad compat_sys_old_getrlimit  /* old_getrlimit */
        .quad compat_sys_getrusage
-       .quad sys32_gettimeofday
-       .quad sys32_settimeofday
+       .quad compat_sys_gettimeofday
+       .quad compat_sys_settimeofday
        .quad sys_getgroups16   /* 80 */
        .quad sys_setgroups16
        .quad sys32_old_select
index beda4232ce695cc2f42aea28dea84dad02a38235..2e09dcd3c0a6034d46e3345efa40736e49941d13 100644 (file)
 
 #define AA(__x)                ((unsigned long)(__x))
 
-int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf)
-{
-       compat_ino_t ino;
-
-       typeof(ubuf->st_uid) uid = 0;
-       typeof(ubuf->st_gid) gid = 0;
-       SET_UID(uid, kbuf->uid);
-       SET_GID(gid, kbuf->gid);
-       if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev))
-               return -EOVERFLOW;
-       if (kbuf->size >= 0x7fffffff)
-               return -EOVERFLOW;
-       ino = kbuf->ino;
-       if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino)
-               return -EOVERFLOW;
-       if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
-           __put_user(old_encode_dev(kbuf->dev), &ubuf->st_dev) ||
-           __put_user(ino, &ubuf->st_ino) ||
-           __put_user(kbuf->mode, &ubuf->st_mode) ||
-           __put_user(kbuf->nlink, &ubuf->st_nlink) ||
-           __put_user(uid, &ubuf->st_uid) ||
-           __put_user(gid, &ubuf->st_gid) ||
-           __put_user(old_encode_dev(kbuf->rdev), &ubuf->st_rdev) ||
-           __put_user(kbuf->size, &ubuf->st_size) ||
-           __put_user(kbuf->atime.tv_sec, &ubuf->st_atime) ||
-           __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) ||
-           __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime) ||
-           __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
-           __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime) ||
-           __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
-           __put_user(kbuf->blksize, &ubuf->st_blksize) ||
-           __put_user(kbuf->blocks, &ubuf->st_blocks))
-               return -EFAULT;
-       return 0;
-}
 
 asmlinkage long sys32_truncate64(char __user *filename,
                                 unsigned long offset_low,
@@ -402,75 +367,11 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
        return 0;
 }
 
-static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
-       int err = -EFAULT;
-
-       if (access_ok(VERIFY_READ, i, sizeof(*i))) {
-               err = __get_user(o->tv_sec, &i->tv_sec);
-               err |= __get_user(o->tv_usec, &i->tv_usec);
-       }
-       return err;
-}
-
-static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
-{
-       int err = -EFAULT;
-
-       if (access_ok(VERIFY_WRITE, o, sizeof(*o))) {
-               err = __put_user(i->tv_sec, &o->tv_sec);
-               err |= __put_user(i->tv_usec, &o->tv_usec);
-       }
-       return err;
-}
-
 asmlinkage long sys32_alarm(unsigned int seconds)
 {
        return alarm_setitimer(seconds);
 }
 
-/*
- * Translations due to time_t size differences. Which affects all
- * sorts of things, like timeval and itimerval.
- */
-asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
-                                  struct timezone __user *tz)
-{
-       if (tv) {
-               struct timeval ktv;
-
-               do_gettimeofday(&ktv);
-               if (put_tv32(tv, &ktv))
-                       return -EFAULT;
-       }
-       if (tz) {
-               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-                       return -EFAULT;
-       }
-       return 0;
-}
-
-asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
-                                  struct timezone __user *tz)
-{
-       struct timeval ktv;
-       struct timespec kts;
-       struct timezone ktz;
-
-       if (tv) {
-               if (get_tv32(&ktv, tv))
-                       return -EFAULT;
-               kts.tv_sec = ktv.tv_sec;
-               kts.tv_nsec = ktv.tv_usec * NSEC_PER_USEC;
-       }
-       if (tz) {
-               if (copy_from_user(&ktz, tz, sizeof(ktz)))
-                       return -EFAULT;
-       }
-
-       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
-}
-
 struct sel_arg_struct {
        unsigned int n;
        unsigned int inp;
index 5098585f87ce8fdc29fd82fde6e53711238f11cd..0d41f0343dc0753e5be4c97fd8b36460bc0ab2a5 100644 (file)
@@ -23,7 +23,7 @@ CFLAGS_hpet.o         := $(nostackp)
 CFLAGS_tsc.o           := $(nostackp)
 
 obj-y                  := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
-obj-y                  += traps_$(BITS).o irq_$(BITS).o
+obj-y                  += traps.o irq_$(BITS).o dumpstack_$(BITS).o
 obj-y                  += time_$(BITS).o ioport.o ldt.o
 obj-y                  += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o
 obj-$(CONFIG_X86_VISWS)        += visws_quirks.o
index fb04e49776ba308b2cd8f86315bcb7692122ce80..a84ac7b570e6bb4582788da74a4c570e28fd65e9 100644 (file)
@@ -444,7 +444,7 @@ void __init alternative_instructions(void)
                                            _text, _etext);
 
                /* Only switch to UP mode if we don't immediately boot others */
-               if (num_possible_cpus() == 1 || setup_max_cpus <= 1)
+               if (num_present_cpus() == 1 || setup_max_cpus <= 1)
                        alternatives_smp_switch(0);
        }
 #endif
index 34e4d112b1ef1bf54720a17f71756f8dd1394dfa..a8fd9ebdc8e25232e66b4d28a10edc0a70b8b151 100644 (file)
@@ -295,7 +295,7 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
                u64 address, size_t size)
 {
        int s = 0;
-       unsigned pages = iommu_num_pages(address, size);
+       unsigned pages = iommu_num_pages(address, size, PAGE_SIZE);
 
        address &= PAGE_MASK;
 
@@ -680,7 +680,8 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
            iommu->exclusion_start < dma_dom->aperture_size) {
                unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
                int pages = iommu_num_pages(iommu->exclusion_start,
-                                           iommu->exclusion_length);
+                                           iommu->exclusion_length,
+                                           PAGE_SIZE);
                dma_ops_reserve_addresses(dma_dom, startpage, pages);
        }
 
@@ -935,7 +936,7 @@ static dma_addr_t __map_single(struct device *dev,
        unsigned long align_mask = 0;
        int i;
 
-       pages = iommu_num_pages(paddr, size);
+       pages = iommu_num_pages(paddr, size, PAGE_SIZE);
        paddr &= PAGE_MASK;
 
        if (align)
@@ -980,7 +981,7 @@ static void __unmap_single(struct amd_iommu *iommu,
        if ((dma_addr == 0) || (dma_addr + size > dma_dom->aperture_size))
                return;
 
-       pages = iommu_num_pages(dma_addr, size);
+       pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
        dma_addr &= PAGE_MASK;
        start = dma_addr;
 
index a91c57cb666a3c752295875ac4ff14298502f5b7..21c831d96af3d8f8ef63e6403f56fd0e71f5730c 100644 (file)
@@ -295,6 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
  *
  * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
  * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ *
+ * If mask=1, the LVT entry does not generate interrupts while mask=0
+ * enables the vector. See also the BKDGs.
  */
 
 #define APIC_EILVT_LVTOFF_MCE 0
@@ -319,6 +322,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
        setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
        return APIC_EILVT_LVTOFF_IBS;
 }
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
 
 /*
  * Program the next event, relative to now
index 53898b65a6ae1a7bac6a9145caf1113c39274d84..94ddb69ae15e55f39d195267f73bfbdfa346377d 100644 (file)
@@ -307,6 +307,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
  *
  * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and
  * MCE interrupts are supported. Thus MCE offset must be set to 0.
+ *
+ * If mask=1, the LVT entry does not generate interrupts while mask=0
+ * enables the vector. See also the BKDGs.
  */
 
 #define APIC_EILVT_LVTOFF_MCE 0
@@ -331,6 +334,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask)
        setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask);
        return APIC_EILVT_LVTOFF_IBS;
 }
+EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs);
 
 /*
  * Program the next event, relative to now
index fb789dd9e691cafffb4d25fc0e26b5c35b4c0869..25581dcb280ea8d3a9c8840cd70fcc726e10b76f 100644 (file)
@@ -124,18 +124,25 @@ static inline int flag_is_changeable_p(u32 flag)
 {
        u32 f1, f2;
 
-       asm("pushfl\n\t"
-           "pushfl\n\t"
-           "popl %0\n\t"
-           "movl %0,%1\n\t"
-           "xorl %2,%0\n\t"
-           "pushl %0\n\t"
-           "popfl\n\t"
-           "pushfl\n\t"
-           "popl %0\n\t"
-           "popfl\n\t"
-           : "=&r" (f1), "=&r" (f2)
-           : "ir" (flag));
+       /*
+        * Cyrix and IDT cpus allow disabling of CPUID
+        * so the code below may return different results
+        * when it is executed before and after enabling
+        * the CPUID. Add "volatile" to not allow gcc to
+        * optimize the subsequent calls to this function.
+        */
+       asm volatile ("pushfl\n\t"
+                     "pushfl\n\t"
+                     "popl %0\n\t"
+                     "movl %0,%1\n\t"
+                     "xorl %2,%0\n\t"
+                     "pushl %0\n\t"
+                     "popfl\n\t"
+                     "pushfl\n\t"
+                     "popl %0\n\t"
+                     "popfl\n\t"
+                     : "=&r" (f1), "=&r" (f2)
+                     : "ir" (flag));
 
        return ((f1^f2) & flag) != 0;
 }
@@ -719,12 +726,24 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 #endif
 }
 
+#ifdef CONFIG_X86_64
+static void vgetcpu_set_mode(void)
+{
+       if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
+               vgetcpu_mode = VGETCPU_RDTSCP;
+       else
+               vgetcpu_mode = VGETCPU_LSL;
+}
+#endif
+
 void __init identify_boot_cpu(void)
 {
        identify_cpu(&boot_cpu_data);
 #ifdef CONFIG_X86_32
        sysenter_setup();
        enable_sep_cpu();
+#else
+       vgetcpu_set_mode();
 #endif
 }
 
@@ -797,7 +816,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
        else if (c->cpuid_level >= 0)
                vendor = c->x86_vendor_id;
 
-       if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
+       if (vendor && !strstr(c->x86_model_id, vendor))
                printk(KERN_CONT "%s ", vendor);
 
        if (c->x86_model_id[0])
index 6a44d646599156cc5910cce8f503832688c973a5..72cefd1e649ba4be254b5ec497f442160dab1752 100644 (file)
@@ -147,8 +147,8 @@ static __cpuinit int cpuid_device_create(int cpu)
 {
        struct device *dev;
 
-       dev = device_create_drvdata(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
-                                   NULL, "cpu%d", cpu);
+       dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL,
+                           "cpu%d", cpu);
        return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
index 395acb12b0d1bfe1a5e1764d00ef4271b00a7e2f..b4f14c6c09d9b12971c1673ebac761515e91a4be 100644 (file)
@@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = {
                .ds             = __USER_DS,
                .fs             = __KERNEL_PERCPU,
 
-               .__cr3          = __phys_addr_const((unsigned long)swapper_pg_dir)
+               .__cr3          = __pa_nodebug(swapper_pg_dir),
        }
 };
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
new file mode 100644 (file)
index 0000000..1a78180
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ */
+#include <linux/kallsyms.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/utsname.h>
+#include <linux/hardirq.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/kexec.h>
+#include <linux/bug.h>
+#include <linux/nmi.h>
+#include <linux/sysfs.h>
+
+#include <asm/stacktrace.h>
+
+#define STACKSLOTS_PER_LINE 8
+#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
+
+int panic_on_unrecovered_nmi;
+int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
+static unsigned int code_bytes = 64;
+static int die_counter;
+
+void printk_address(unsigned long address, int reliable)
+{
+       printk(" [<%p>] %s%pS\n", (void *) address,
+                       reliable ? "" : "? ", (void *) address);
+}
+
+static inline int valid_stack_ptr(struct thread_info *tinfo,
+                       void *p, unsigned int size, void *end)
+{
+       void *t = tinfo;
+       if (end) {
+               if (p < end && p >= (end-THREAD_SIZE))
+                       return 1;
+               else
+                       return 0;
+       }
+       return p > t && p < t + THREAD_SIZE - size;
+}
+
+/* The form of the top of the frame on the stack */
+struct stack_frame {
+       struct stack_frame *next_frame;
+       unsigned long return_address;
+};
+
+static inline unsigned long
+print_context_stack(struct thread_info *tinfo,
+               unsigned long *stack, unsigned long bp,
+               const struct stacktrace_ops *ops, void *data,
+               unsigned long *end)
+{
+       struct stack_frame *frame = (struct stack_frame *)bp;
+
+       while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
+               unsigned long addr;
+
+               addr = *stack;
+               if (__kernel_text_address(addr)) {
+                       if ((unsigned long) stack == bp + sizeof(long)) {
+                               ops->address(data, addr, 1);
+                               frame = frame->next_frame;
+                               bp = (unsigned long) frame;
+                       } else {
+                               ops->address(data, addr, bp == 0);
+                       }
+               }
+               stack++;
+       }
+       return bp;
+}
+
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp,
+               const struct stacktrace_ops *ops, void *data)
+{
+       if (!task)
+               task = current;
+
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+               if (task && task != current)
+                       stack = (unsigned long *)task->thread.sp;
+       }
+
+#ifdef CONFIG_FRAME_POINTER
+       if (!bp) {
+               if (task == current) {
+                       /* Grab bp right from our regs */
+                       get_bp(bp);
+               } else {
+                       /* bp is the last reg pushed by switch_to */
+                       bp = *(unsigned long *) task->thread.sp;
+               }
+       }
+#endif
+
+       for (;;) {
+               struct thread_info *context;
+
+               context = (struct thread_info *)
+                       ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+               bp = print_context_stack(context, stack, bp, ops, data, NULL);
+
+               stack = (unsigned long *)context->previous_esp;
+               if (!stack)
+                       break;
+               if (ops->stack(data, "IRQ") < 0)
+                       break;
+               touch_nmi_watchdog();
+       }
+}
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+       printk(data);
+       print_symbol(msg, symbol);
+       printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+       printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+       printk("%s <%s> ", (char *)data, name);
+       return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+       touch_nmi_watchdog();
+       printk(data);
+       printk_address(addr, reliable);
+}
+
+static const struct stacktrace_ops print_trace_ops = {
+       .warning = print_trace_warning,
+       .warning_symbol = print_trace_warning_symbol,
+       .stack = print_trace_stack,
+       .address = print_trace_address,
+};
+
+static void
+show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp, char *log_lvl)
+{
+       printk("%sCall Trace:\n", log_lvl);
+       dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+}
+
+void show_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp)
+{
+       show_trace_log_lvl(task, regs, stack, bp, "");
+}
+
+static void
+show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *sp, unsigned long bp, char *log_lvl)
+{
+       unsigned long *stack;
+       int i;
+
+       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 % STACKSLOTS_PER_LINE) == 0))
+                       printk("\n%s", log_lvl);
+               printk(" %08lx", *stack++);
+               touch_nmi_watchdog();
+       }
+       printk("\n");
+       show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       show_stack_log_lvl(task, NULL, sp, 0, "");
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+       unsigned long bp = 0;
+       unsigned long stack;
+
+#ifdef CONFIG_FRAME_POINTER
+       if (!bp)
+               get_bp(bp);
+#endif
+
+       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+               current->pid, current->comm, print_tainted(),
+               init_utsname()->release,
+               (int)strcspn(init_utsname()->version, " "),
+               init_utsname()->version);
+       show_trace(NULL, NULL, &stack, bp);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void show_registers(struct pt_regs *regs)
+{
+       int i;
+
+       print_modules();
+       __show_regs(regs, 0);
+
+       printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n",
+               TASK_COMM_LEN, current->comm, task_pid_nr(current),
+               current_thread_info(), current, task_thread_info(current));
+       /*
+        * When in-kernel, we also print out the stack and code at the
+        * time of the fault..
+        */
+       if (!user_mode_vm(regs)) {
+               unsigned int code_prologue = code_bytes * 43 / 64;
+               unsigned int code_len = code_bytes;
+               unsigned char c;
+               u8 *ip;
+
+               printk(KERN_EMERG "Stack:\n");
+               show_stack_log_lvl(NULL, regs, &regs->sp,
+                               0, KERN_EMERG);
+
+               printk(KERN_EMERG "Code: ");
+
+               ip = (u8 *)regs->ip - code_prologue;
+               if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+                       /* try starting at IP */
+                       ip = (u8 *)regs->ip;
+                       code_len = code_len - code_prologue + 1;
+               }
+               for (i = 0; i < code_len; i++, ip++) {
+                       if (ip < (u8 *)PAGE_OFFSET ||
+                                       probe_kernel_address(ip, c)) {
+                               printk(" Bad EIP value.");
+                               break;
+                       }
+                       if (ip == (u8 *)regs->ip)
+                               printk("<%02x> ", c);
+                       else
+                               printk("%02x ", c);
+               }
+       }
+       printk("\n");
+}
+
+int is_valid_bugaddr(unsigned long ip)
+{
+       unsigned short ud2;
+
+       if (ip < PAGE_OFFSET)
+               return 0;
+       if (probe_kernel_address((unsigned short *)ip, ud2))
+               return 0;
+
+       return ud2 == 0x0b0f;
+}
+
+static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static int die_owner = -1;
+static unsigned int die_nest_count;
+
+unsigned __kprobes long oops_begin(void)
+{
+       unsigned long flags;
+
+       oops_enter();
+
+       if (die_owner != raw_smp_processor_id()) {
+               console_verbose();
+               raw_local_irq_save(flags);
+               __raw_spin_lock(&die_lock);
+               die_owner = smp_processor_id();
+               die_nest_count = 0;
+               bust_spinlocks(1);
+       } else {
+               raw_local_irq_save(flags);
+       }
+       die_nest_count++;
+       return flags;
+}
+
+void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+{
+       bust_spinlocks(0);
+       die_owner = -1;
+       add_taint(TAINT_DIE);
+       __raw_spin_unlock(&die_lock);
+       raw_local_irq_restore(flags);
+
+       if (!regs)
+               return;
+
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+       if (panic_on_oops)
+               panic("Fatal exception");
+       oops_exit();
+       do_exit(signr);
+}
+
+int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+{
+       unsigned short ss;
+       unsigned long sp;
+
+       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+       printk("PREEMPT ");
+#endif
+#ifdef CONFIG_SMP
+       printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       printk("DEBUG_PAGEALLOC");
+#endif
+       printk("\n");
+       sysfs_printk_last_file();
+       if (notify_die(DIE_OOPS, str, regs, err,
+                       current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+               return 1;
+
+       show_registers(regs);
+       /* Executive summary in case the oops scrolled away */
+       sp = (unsigned long) (&regs->sp);
+       savesegment(ss, ss);
+       if (user_mode(regs)) {
+               sp = regs->sp;
+               ss = regs->ss & 0xffff;
+       }
+       printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+       print_symbol("%s", regs->ip);
+       printk(" SS:ESP %04x:%08lx\n", ss, sp);
+       return 0;
+}
+
+/*
+ * This is gone through when something in the kernel has done something bad
+ * and is about to be terminated:
+ */
+void die(const char *str, struct pt_regs *regs, long err)
+{
+       unsigned long flags = oops_begin();
+
+       if (die_nest_count < 3) {
+               report_bug(regs->ip, regs);
+
+               if (__die(str, regs, err))
+                       regs = NULL;
+       } else {
+               printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
+       }
+
+       oops_end(flags, regs, SIGSEGV);
+}
+
+static DEFINE_SPINLOCK(nmi_print_lock);
+
+void notrace __kprobes
+die_nmi(char *str, struct pt_regs *regs, int do_panic)
+{
+       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+               return;
+
+       spin_lock(&nmi_print_lock);
+       /*
+       * We are in trouble anyway, lets at least try
+       * to get a message out:
+       */
+       bust_spinlocks(1);
+       printk(KERN_EMERG "%s", str);
+       printk(" on CPU%d, ip %08lx, registers:\n",
+               smp_processor_id(), regs->ip);
+       show_registers(regs);
+       if (do_panic)
+               panic("Non maskable interrupt");
+       console_silent();
+       spin_unlock(&nmi_print_lock);
+       bust_spinlocks(0);
+
+       /*
+        * If we are in kernel we are probably nested up pretty bad
+        * and might aswell get out now while we still can:
+        */
+       if (!user_mode_vm(regs)) {
+               current->thread.trap_no = 2;
+               crash_kexec(regs);
+       }
+
+       do_exit(SIGSEGV);
+}
+
+static int __init oops_setup(char *s)
+{
+       if (!s)
+               return -EINVAL;
+       if (!strcmp(s, "panic"))
+               panic_on_oops = 1;
+       return 0;
+}
+early_param("oops", oops_setup);
+
+static int __init kstack_setup(char *s)
+{
+       if (!s)
+               return -EINVAL;
+       kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+       return 0;
+}
+early_param("kstack", kstack_setup);
+
+static int __init code_bytes_setup(char *s)
+{
+       code_bytes = simple_strtoul(s, NULL, 0);
+       if (code_bytes > 8192)
+               code_bytes = 8192;
+
+       return 1;
+}
+__setup("code_bytes=", code_bytes_setup);
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
new file mode 100644 (file)
index 0000000..96a5db7
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ */
+#include <linux/kallsyms.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/utsname.h>
+#include <linux/hardirq.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/kexec.h>
+#include <linux/bug.h>
+#include <linux/nmi.h>
+#include <linux/sysfs.h>
+
+#include <asm/stacktrace.h>
+
+#define STACKSLOTS_PER_LINE 4
+#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
+
+int panic_on_unrecovered_nmi;
+int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
+static unsigned int code_bytes = 64;
+static int die_counter;
+
+void printk_address(unsigned long address, int reliable)
+{
+       printk(" [<%p>] %s%pS\n", (void *) address,
+                       reliable ? "" : "? ", (void *) address);
+}
+
+static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+                                       unsigned *usedp, char **idp)
+{
+       static char ids[][8] = {
+               [DEBUG_STACK - 1] = "#DB",
+               [NMI_STACK - 1] = "NMI",
+               [DOUBLEFAULT_STACK - 1] = "#DF",
+               [STACKFAULT_STACK - 1] = "#SS",
+               [MCE_STACK - 1] = "#MC",
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+               [N_EXCEPTION_STACKS ...
+                       N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
+#endif
+       };
+       unsigned k;
+
+       /*
+        * Iterate over all exception stacks, and figure out whether
+        * 'stack' is in one of them:
+        */
+       for (k = 0; k < N_EXCEPTION_STACKS; k++) {
+               unsigned long end = per_cpu(orig_ist, cpu).ist[k];
+               /*
+                * Is 'stack' above this exception frame's end?
+                * If yes then skip to the next frame.
+                */
+               if (stack >= end)
+                       continue;
+               /*
+                * Is 'stack' above this exception frame's start address?
+                * If yes then we found the right frame.
+                */
+               if (stack >= end - EXCEPTION_STKSZ) {
+                       /*
+                        * Make sure we only iterate through an exception
+                        * stack once. If it comes up for the second time
+                        * then there's something wrong going on - just
+                        * break out and return NULL:
+                        */
+                       if (*usedp & (1U << k))
+                               break;
+                       *usedp |= 1U << k;
+                       *idp = ids[k];
+                       return (unsigned long *)end;
+               }
+               /*
+                * If this is a debug stack, and if it has a larger size than
+                * the usual exception stacks, then 'stack' might still
+                * be within the lower portion of the debug stack:
+                */
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+               if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
+                       unsigned j = N_EXCEPTION_STACKS - 1;
+
+                       /*
+                        * Black magic. A large debug stack is composed of
+                        * multiple exception stack entries, which we
+                        * iterate through now. Dont look:
+                        */
+                       do {
+                               ++j;
+                               end -= EXCEPTION_STKSZ;
+                               ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
+                       } while (stack < end - EXCEPTION_STKSZ);
+                       if (*usedp & (1U << j))
+                               break;
+                       *usedp |= 1U << j;
+                       *idp = ids[j];
+                       return (unsigned long *)end;
+               }
+#endif
+       }
+       return NULL;
+}
+
+/*
+ * x86-64 can have up to three kernel stacks:
+ * process stack
+ * interrupt stack
+ * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+ */
+
+static inline int valid_stack_ptr(struct thread_info *tinfo,
+                       void *p, unsigned int size, void *end)
+{
+       void *t = tinfo;
+       if (end) {
+               if (p < end && p >= (end-THREAD_SIZE))
+                       return 1;
+               else
+                       return 0;
+       }
+       return p > t && p < t + THREAD_SIZE - size;
+}
+
+/* The form of the top of the frame on the stack */
+struct stack_frame {
+       struct stack_frame *next_frame;
+       unsigned long return_address;
+};
+
+static inline unsigned long
+print_context_stack(struct thread_info *tinfo,
+               unsigned long *stack, unsigned long bp,
+               const struct stacktrace_ops *ops, void *data,
+               unsigned long *end)
+{
+       struct stack_frame *frame = (struct stack_frame *)bp;
+
+       while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
+               unsigned long addr;
+
+               addr = *stack;
+               if (__kernel_text_address(addr)) {
+                       if ((unsigned long) stack == bp + sizeof(long)) {
+                               ops->address(data, addr, 1);
+                               frame = frame->next_frame;
+                               bp = (unsigned long) frame;
+                       } else {
+                               ops->address(data, addr, bp == 0);
+                       }
+               }
+               stack++;
+       }
+       return bp;
+}
+
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp,
+               const struct stacktrace_ops *ops, void *data)
+{
+       const unsigned cpu = get_cpu();
+       unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
+       unsigned used = 0;
+       struct thread_info *tinfo;
+
+       if (!task)
+               task = current;
+
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+               if (task && task != current)
+                       stack = (unsigned long *)task->thread.sp;
+       }
+
+#ifdef CONFIG_FRAME_POINTER
+       if (!bp) {
+               if (task == current) {
+                       /* Grab bp right from our regs */
+                       get_bp(bp);
+               } else {
+                       /* bp is the last reg pushed by switch_to */
+                       bp = *(unsigned long *) task->thread.sp;
+               }
+       }
+#endif
+
+       /*
+        * Print function call entries in all stacks, starting at the
+        * current stack address. If the stacks consist of nested
+        * exceptions
+        */
+       tinfo = task_thread_info(task);
+       for (;;) {
+               char *id;
+               unsigned long *estack_end;
+               estack_end = in_exception_stack(cpu, (unsigned long)stack,
+                                               &used, &id);
+
+               if (estack_end) {
+                       if (ops->stack(data, id) < 0)
+                               break;
+
+                       bp = print_context_stack(tinfo, stack, bp, ops,
+                                                       data, estack_end);
+                       ops->stack(data, "<EOE>");
+                       /*
+                        * We link to the next stack via the
+                        * second-to-last pointer (index -2 to end) in the
+                        * exception stack:
+                        */
+                       stack = (unsigned long *) estack_end[-2];
+                       continue;
+               }
+               if (irqstack_end) {
+                       unsigned long *irqstack;
+                       irqstack = irqstack_end -
+                               (IRQSTACKSIZE - 64) / sizeof(*irqstack);
+
+                       if (stack >= irqstack && stack < irqstack_end) {
+                               if (ops->stack(data, "IRQ") < 0)
+                                       break;
+                               bp = print_context_stack(tinfo, stack, bp,
+                                               ops, data, irqstack_end);
+                               /*
+                                * We link to the next stack (which would be
+                                * the process stack normally) the last
+                                * pointer (index -1 to end) in the IRQ stack:
+                                */
+                               stack = (unsigned long *) (irqstack_end[-1]);
+                               irqstack_end = NULL;
+                               ops->stack(data, "EOI");
+                               continue;
+                       }
+               }
+               break;
+       }
+
+       /*
+        * This handles the process stack:
+        */
+       bp = print_context_stack(tinfo, stack, bp, ops, data, NULL);
+       put_cpu();
+}
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+       printk(data);
+       print_symbol(msg, symbol);
+       printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+       printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+       printk("%s <%s> ", (char *)data, name);
+       return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+       touch_nmi_watchdog();
+       printk(data);
+       printk_address(addr, reliable);
+}
+
+static const struct stacktrace_ops print_trace_ops = {
+       .warning = print_trace_warning,
+       .warning_symbol = print_trace_warning_symbol,
+       .stack = print_trace_stack,
+       .address = print_trace_address,
+};
+
+static void
+show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp, char *log_lvl)
+{
+       printk("%sCall Trace:\n", log_lvl);
+       dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+}
+
+void show_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack, unsigned long bp)
+{
+       show_trace_log_lvl(task, regs, stack, bp, "");
+}
+
+static void
+show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *sp, unsigned long bp, char *log_lvl)
+{
+       unsigned long *stack;
+       int i;
+       const int cpu = smp_processor_id();
+       unsigned long *irqstack_end =
+               (unsigned long *) (cpu_pda(cpu)->irqstackptr);
+       unsigned long *irqstack =
+               (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
+
+       /*
+        * debugging aid: "show_stack(NULL, 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 (stack >= irqstack && stack <= irqstack_end) {
+                       if (stack == irqstack_end) {
+                               stack = (unsigned long *) (irqstack_end[-1]);
+                               printk(" <EOI> ");
+                       }
+               } else {
+               if (((long) stack & (THREAD_SIZE-1)) == 0)
+                       break;
+               }
+               if (i && ((i % STACKSLOTS_PER_LINE) == 0))
+                       printk("\n%s", log_lvl);
+               printk(" %016lx", *stack++);
+               touch_nmi_watchdog();
+       }
+       printk("\n");
+       show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       show_stack_log_lvl(task, NULL, sp, 0, "");
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+       unsigned long bp = 0;
+       unsigned long stack;
+
+#ifdef CONFIG_FRAME_POINTER
+       if (!bp)
+               get_bp(bp);
+#endif
+
+       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+               current->pid, current->comm, print_tainted(),
+               init_utsname()->release,
+               (int)strcspn(init_utsname()->version, " "),
+               init_utsname()->version);
+       show_trace(NULL, NULL, &stack, bp);
+}
+EXPORT_SYMBOL(dump_stack);
+
+void show_registers(struct pt_regs *regs)
+{
+       int i;
+       unsigned long sp;
+       const int cpu = smp_processor_id();
+       struct task_struct *cur = cpu_pda(cpu)->pcurrent;
+
+       sp = regs->sp;
+       printk("CPU %d ", cpu);
+       __show_regs(regs, 1);
+       printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
+               cur->comm, cur->pid, task_thread_info(cur), cur);
+
+       /*
+        * When in-kernel, we also print out the stack and code at the
+        * time of the fault..
+        */
+       if (!user_mode(regs)) {
+               unsigned int code_prologue = code_bytes * 43 / 64;
+               unsigned int code_len = code_bytes;
+               unsigned char c;
+               u8 *ip;
+
+               printk(KERN_EMERG "Stack:\n");
+               show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
+                               regs->bp, KERN_EMERG);
+
+               printk(KERN_EMERG "Code: ");
+
+               ip = (u8 *)regs->ip - code_prologue;
+               if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+                       /* try starting at IP */
+                       ip = (u8 *)regs->ip;
+                       code_len = code_len - code_prologue + 1;
+               }
+               for (i = 0; i < code_len; i++, ip++) {
+                       if (ip < (u8 *)PAGE_OFFSET ||
+                                       probe_kernel_address(ip, c)) {
+                               printk(" Bad RIP value.");
+                               break;
+                       }
+                       if (ip == (u8 *)regs->ip)
+                               printk("<%02x> ", c);
+                       else
+                               printk("%02x ", c);
+               }
+       }
+       printk("\n");
+}
+
+int is_valid_bugaddr(unsigned long ip)
+{
+       unsigned short ud2;
+
+       if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
+               return 0;
+
+       return ud2 == 0x0b0f;
+}
+
+static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static int die_owner = -1;
+static unsigned int die_nest_count;
+
+unsigned __kprobes long oops_begin(void)
+{
+       int cpu;
+       unsigned long flags;
+
+       oops_enter();
+
+       /* racy, but better than risking deadlock. */
+       raw_local_irq_save(flags);
+       cpu = smp_processor_id();
+       if (!__raw_spin_trylock(&die_lock)) {
+               if (cpu == die_owner)
+                       /* nested oops. should stop eventually */;
+               else
+                       __raw_spin_lock(&die_lock);
+       }
+       die_nest_count++;
+       die_owner = cpu;
+       console_verbose();
+       bust_spinlocks(1);
+       return flags;
+}
+
+void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+{
+       die_owner = -1;
+       bust_spinlocks(0);
+       die_nest_count--;
+       if (!die_nest_count)
+               /* Nest count reaches zero, release the lock. */
+               __raw_spin_unlock(&die_lock);
+       raw_local_irq_restore(flags);
+       if (!regs) {
+               oops_exit();
+               return;
+       }
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+       if (panic_on_oops)
+               panic("Fatal exception");
+       oops_exit();
+       do_exit(signr);
+}
+
+int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+{
+       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+       printk("PREEMPT ");
+#endif
+#ifdef CONFIG_SMP
+       printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       printk("DEBUG_PAGEALLOC");
+#endif
+       printk("\n");
+       sysfs_printk_last_file();
+       if (notify_die(DIE_OOPS, str, regs, err,
+                       current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+               return 1;
+
+       show_registers(regs);
+       add_taint(TAINT_DIE);
+       /* Executive summary in case the oops scrolled away */
+       printk(KERN_ALERT "RIP ");
+       printk_address(regs->ip, 1);
+       printk(" RSP <%016lx>\n", regs->sp);
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
+       return 0;
+}
+
+void die(const char *str, struct pt_regs *regs, long err)
+{
+       unsigned long flags = oops_begin();
+
+       if (!user_mode(regs))
+               report_bug(regs->ip, regs);
+
+       if (__die(str, regs, err))
+               regs = NULL;
+       oops_end(flags, regs, SIGSEGV);
+}
+
+notrace __kprobes void
+die_nmi(char *str, struct pt_regs *regs, int do_panic)
+{
+       unsigned long flags;
+
+       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+               return;
+
+       flags = oops_begin();
+       /*
+        * We are in trouble anyway, lets at least try
+        * to get a message out.
+        */
+       printk(KERN_EMERG "%s", str);
+       printk(" on CPU%d, ip %08lx, registers:\n",
+               smp_processor_id(), regs->ip);
+       show_registers(regs);
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
+       if (do_panic || panic_on_oops)
+               panic("Non maskable interrupt");
+       oops_end(flags, NULL, SIGBUS);
+       nmi_exit();
+       local_irq_enable();
+       do_exit(SIGBUS);
+}
+
+static int __init oops_setup(char *s)
+{
+       if (!s)
+               return -EINVAL;
+       if (!strcmp(s, "panic"))
+               panic_on_oops = 1;
+       return 0;
+}
+early_param("oops", oops_setup);
+
+static int __init kstack_setup(char *s)
+{
+       if (!s)
+               return -EINVAL;
+       kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+       return 0;
+}
+early_param("kstack", kstack_setup);
+
+static int __init code_bytes_setup(char *s)
+{
+       code_bytes = simple_strtoul(s, NULL, 0);
+       if (code_bytes > 8192)
+               code_bytes = 8192;
+
+       return 1;
+}
+__setup("code_bytes=", code_bytes_setup);
index 78e642feac30423f57369166cb76724efe474b7c..ce97bf3bed12d71ee6d1fce3ca5bb67b4ac53156 100644 (file)
@@ -1282,12 +1282,10 @@ void __init e820_reserve_resources(void)
        e820_res = res;
        for (i = 0; i < e820.nr_map; i++) {
                end = e820.map[i].addr + e820.map[i].size - 1;
-#ifndef CONFIG_RESOURCES_64BIT
-               if (end > 0x100000000ULL) {
+               if (end != (resource_size_t)end) {
                        res++;
                        continue;
                }
-#endif
                res->name = e820_type_to_string(e820.map[i].type);
                res->start = e820.map[i].addr;
                res->end = end;
index 109792bc7cfa178e50e07e81ae33dc9e6700a597..b21fbfaffe391a974d10d7417a9f00c99ab05228 100644 (file)
@@ -730,6 +730,7 @@ error_code:
        movl $(__USER_DS), %ecx
        movl %ecx, %ds
        movl %ecx, %es
+       TRACE_IRQS_OFF
        movl %esp,%eax                  # pt_regs pointer
        call *%edi
        jmp ret_from_exception
@@ -760,20 +761,9 @@ ENTRY(device_not_available)
        RING0_INT_FRAME
        pushl $-1                       # mark this as an int
        CFI_ADJUST_CFA_OFFSET 4
-       SAVE_ALL
-       GET_CR0_INTO_EAX
-       testl $0x4, %eax                # EM (math emulation bit)
-       jne device_not_available_emulate
-       preempt_stop(CLBR_ANY)
-       call math_state_restore
-       jmp ret_from_exception
-device_not_available_emulate:
-       pushl $0                        # temporary storage for ORIG_EIP
+       pushl $do_device_not_available
        CFI_ADJUST_CFA_OFFSET 4
-       call math_emulate
-       addl $4, %esp
-       CFI_ADJUST_CFA_OFFSET -4
-       jmp ret_from_exception
+       jmp error_code
        CFI_ENDPROC
 END(device_not_available)
 
@@ -814,6 +804,7 @@ debug_stack_correct:
        pushl $-1                       # mark this as an int
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
+       TRACE_IRQS_OFF
        xorl %edx,%edx                  # error code 0
        movl %esp,%eax                  # pt_regs pointer
        call do_debug
@@ -858,6 +849,7 @@ nmi_stack_correct:
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
+       TRACE_IRQS_OFF
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_nmi
@@ -898,6 +890,7 @@ nmi_espfix_stack:
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
+       TRACE_IRQS_OFF
        FIXUP_ESPFIX_STACK              # %eax == %esp
        xorl %edx,%edx                  # zero error code
        call do_nmi
@@ -928,6 +921,7 @@ KPROBE_ENTRY(int3)
        pushl $-1                       # mark this as an int
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
+       TRACE_IRQS_OFF
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_int3
@@ -1030,7 +1024,7 @@ ENTRY(machine_check)
        RING0_INT_FRAME
        pushl $0
        CFI_ADJUST_CFA_OFFSET 4
-       pushl machine_check_vector
+       pushl $do_machine_check
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
index cf3a0b2d00599adb2a79fefa991c0d8223059fba..1db6ce4314e19325a740e15fc1ec60db3de8cf38 100644 (file)
@@ -667,6 +667,13 @@ END(stub_rt_sigreturn)
        SAVE_ARGS
        leaq -ARGOFFSET(%rsp),%rdi      # arg1 for handler
        pushq %rbp
+       /*
+        * Save rbp twice: One is for marking the stack frame, as usual, and the
+        * other, to fill pt_regs properly. This is because bx comes right
+        * before the last saved register in that structure, and not bp. If the
+        * base pointer were in the place bx is today, this would not be needed.
+        */
+       movq %rbp, -8(%rsp)
        CFI_ADJUST_CFA_OFFSET   8
        CFI_REL_OFFSET          rbp, 0
        movq %rsp,%rbp
@@ -932,6 +939,9 @@ END(spurious_interrupt)
        .if \ist
        movq    %gs:pda_data_offset, %rbp
        .endif
+       .if \irqtrace
+       TRACE_IRQS_OFF
+       .endif
        movq %rsp,%rdi
        movq ORIG_RAX(%rsp),%rsi
        movq $-1,ORIG_RAX(%rsp)
@@ -1058,7 +1068,8 @@ KPROBE_ENTRY(error_entry)
        je  error_kernelspace
 error_swapgs:  
        SWAPGS
-error_sti:     
+error_sti:
+       TRACE_IRQS_OFF
        movq %rdi,RDI(%rsp)     
        CFI_REL_OFFSET  rdi,RDI
        movq %rsp,%rdi
@@ -1232,7 +1243,7 @@ ENTRY(simd_coprocessor_error)
 END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
-       zeroentry math_state_restore
+       zeroentry do_device_not_available
 END(device_not_available)
 
        /* runs on exception stack */
index 849e5cd485b8a2184296745751a0ed527b1f831e..f454c78fcef6c7172db2fc0088548974f2f083e1 100644 (file)
@@ -109,6 +109,7 @@ struct oem_table {
 };
 
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr);
 #endif
 
 struct mip_reg {
@@ -243,21 +244,38 @@ parse_unisys_oem (char *oemptr)
 }
 
 #ifdef CONFIG_ACPI
-int __init
-find_unisys_acpi_oem_table(unsigned long *oem_addr)
+static unsigned long oem_addrX;
+static unsigned long oem_size;
+int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
 {
        struct acpi_table_header *header = NULL;
        int i = 0;
-       while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) {
+       acpi_size tbl_size;
+
+       while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) {
                if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
                        struct oem_table *t = (struct oem_table *)header;
-                       *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr,
-                                                                   t->OEMTableSize);
+
+                       oem_addrX = t->OEMTableAddr;
+                       oem_size = t->OEMTableSize;
+                       early_acpi_os_unmap_memory(header, tbl_size);
+
+                       *oem_addr = (unsigned long)__acpi_map_table(oem_addrX,
+                                                                   oem_size);
                        return 0;
                }
+               early_acpi_os_unmap_memory(header, tbl_size);
        }
        return -1;
 }
+
+void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
+{
+       if (!oem_addr)
+               return;
+
+       __acpi_unmap_table((char *)oem_addr, oem_size);
+}
 #endif
 
 static void
index ae2ffc8a400ccc131aa8d584a2a9a420f8c40463..33581d94a90e5bebea90a9a26d413524947c7340 100644 (file)
@@ -114,7 +114,7 @@ static void uv_send_IPI_one(int cpu, int vector)
        unsigned long val, apicid, lapicid;
        int pnode;
 
-       apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */
+       apicid = per_cpu(x86_cpu_to_apicid, cpu);
        lapicid = apicid & 0x3f;                /* ZZZ macro needed */
        pnode = uv_apicid_to_pnode(apicid);
        val =
@@ -202,12 +202,10 @@ static unsigned int phys_pkg_id(int index_msb)
        return uv_read_apic_id() >> index_msb;
 }
 
-#ifdef ZZZ             /* Needs x2apic patch */
 static void uv_send_IPI_self(int vector)
 {
        apic_write(APIC_SELF_IPI, vector);
 }
-#endif
 
 struct genapic apic_x2apic_uv_x = {
        .name = "UV large system",
@@ -215,15 +213,15 @@ struct genapic apic_x2apic_uv_x = {
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
        .target_cpus = uv_target_cpus,
-       .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */
+       .vector_allocation_domain = uv_vector_allocation_domain,
        .apic_id_registered = uv_apic_id_registered,
        .init_apic_ldr = uv_init_apic_ldr,
        .send_IPI_all = uv_send_IPI_all,
        .send_IPI_allbutself = uv_send_IPI_allbutself,
        .send_IPI_mask = uv_send_IPI_mask,
-       /* ZZZ.send_IPI_self = uv_send_IPI_self, */
+       .send_IPI_self = uv_send_IPI_self,
        .cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
-       .phys_pkg_id = phys_pkg_id,     /* Fixme ZZZ */
+       .phys_pkg_id = phys_pkg_id,
        .get_apic_id = get_apic_id,
        .set_apic_id = set_apic_id,
        .apic_id_mask = (0xFFFFFFFFu),
@@ -286,12 +284,13 @@ static __init void map_low_mmrs(void)
 
 enum map_type {map_wb, map_uc};
 
-static __init void map_high(char *id, unsigned long base, int shift, enum map_type map_type)
+static __init void map_high(char *id, unsigned long base, int shift,
+                           int max_pnode, enum map_type map_type)
 {
        unsigned long bytes, paddr;
 
        paddr = base << shift;
-       bytes = (1UL << shift);
+       bytes = (1UL << shift) * (max_pnode + 1);
        printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr,
                                                paddr + bytes);
        if (map_type == map_uc)
@@ -307,7 +306,7 @@ static __init void map_gru_high(int max_pnode)
 
        gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
        if (gru.s.enable)
-               map_high("GRU", gru.s.base, shift, map_wb);
+               map_high("GRU", gru.s.base, shift, max_pnode, map_wb);
 }
 
 static __init void map_config_high(int max_pnode)
@@ -317,7 +316,7 @@ static __init void map_config_high(int max_pnode)
 
        cfg.v = uv_read_local_mmr(UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR);
        if (cfg.s.enable)
-               map_high("CONFIG", cfg.s.base, shift, map_uc);
+               map_high("CONFIG", cfg.s.base, shift, max_pnode, map_uc);
 }
 
 static __init void map_mmr_high(int max_pnode)
@@ -327,7 +326,7 @@ static __init void map_mmr_high(int max_pnode)
 
        mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR);
        if (mmr.s.enable)
-               map_high("MMR", mmr.s.base, shift, map_uc);
+               map_high("MMR", mmr.s.base, shift, max_pnode, map_uc);
 }
 
 static __init void map_mmioh_high(int max_pnode)
@@ -337,7 +336,7 @@ static __init void map_mmioh_high(int max_pnode)
 
        mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
        if (mmioh.s.enable)
-               map_high("MMIOH", mmioh.s.base, shift, map_uc);
+               map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc);
 }
 
 static __init void uv_rtc_init(void)
index 3e66bd364a9db3cf8f3fb624f96eeb7075364d78..1dcb0f13897e9b6d4773111e1bc8300713efe0e8 100644 (file)
@@ -35,6 +35,7 @@ void __init reserve_ebda_region(void)
 
        /* start of EBDA area */
        ebda_addr = get_bios_ebda();
+       printk(KERN_INFO "BIOS EBDA/lowmem at: %08x/%08x\n", ebda_addr, lowmem);
 
        /* Fixup: bios puts an EBDA in the top 64K segment */
        /* of conventional memory, but does not adjust lowmem. */
index 73deaffadd036a578984bb8ad6e0455f1044558a..acf62fc233da6c0ee8196d18c53a9a55d31bd10f 100644 (file)
@@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id)
        hd.hd_phys_address = hpet_address;
        hd.hd_address = hpet;
        hd.hd_nirqs = nrtimers;
-       hd.hd_flags = HPET_DATA_PLATFORM;
        hpet_reserve_timer(&hd, 0);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
        hpet_reserve_timer(&hd, 1);
 #endif
 
+       /*
+        * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254
+        * is wrong for i8259!) not the output IRQ.  Many BIOS writers
+        * don't bother configuring *any* comparator interrupts.
+        */
        hd.hd_irq[0] = HPET_LEGACY_8254;
        hd.hd_irq[1] = HPET_LEGACY_RTC;
 
index 1f26fd9ec4f4ea101c69ee030ac4142f4458d5ae..5b5be9d43c2a865fdcbe1ac0f689e750f5e6f5de 100644 (file)
@@ -135,7 +135,7 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
        [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
 };
 
-static void __init init_ISA_irqs (void)
+void __init init_ISA_irqs(void)
 {
        int i;
 
@@ -164,22 +164,8 @@ static void __init init_ISA_irqs (void)
 
 void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
 
-void __init native_init_IRQ(void)
+static void __init smp_intr_init(void)
 {
-       int i;
-
-       init_ISA_irqs();
-       /*
-        * Cover the whole vector space, no vector can escape
-        * us. (some of these will be overridden and become
-        * 'special' SMP interrupts)
-        */
-       for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
-               int vector = FIRST_EXTERNAL_VECTOR + i;
-               if (vector != IA32_SYSCALL_VECTOR)
-                       set_intr_gate(vector, interrupt[i]);
-       }
-
 #ifdef CONFIG_SMP
        /*
         * The reschedule interrupt is a CPU-to-CPU reschedule-helper
@@ -207,6 +193,12 @@ void __init native_init_IRQ(void)
        /* Low priority IPI to cleanup after moving an irq */
        set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
 #endif
+}
+
+static void __init apic_intr_init(void)
+{
+       smp_intr_init();
+
        alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
        alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 
@@ -216,6 +208,25 @@ void __init native_init_IRQ(void)
        /* IPI vectors for APIC spurious and error interrupts */
        alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
        alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+}
+
+void __init native_init_IRQ(void)
+{
+       int i;
+
+       init_ISA_irqs();
+       /*
+        * Cover the whole vector space, no vector can escape
+        * us. (some of these will be overridden and become
+        * 'special' SMP interrupts)
+        */
+       for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
+               int vector = FIRST_EXTERNAL_VECTOR + i;
+               if (vector != IA32_SYSCALL_VECTOR)
+                       set_intr_gate(vector, interrupt[i]);
+       }
+
+       apic_intr_init();
 
        if (!acpi_ioapic)
                setup_irq(2, &irq2);
index d02def06ca91540dd174f219eee8fe6eee6f095c..774ac4991568db3928b6741371735aa1f8b8d7ee 100644 (file)
@@ -78,6 +78,34 @@ static cycle_t kvm_clock_read(void)
        return ret;
 }
 
+/*
+ * If we don't do that, there is the possibility that the guest
+ * will calibrate under heavy load - thus, getting a lower lpj -
+ * and execute the delays themselves without load. This is wrong,
+ * because no delay loop can finish beforehand.
+ * Any heuristics is subject to fail, because ultimately, a large
+ * poll of guests can be running and trouble each other. So we preset
+ * lpj here
+ */
+static unsigned long kvm_get_tsc_khz(void)
+{
+       return preset_lpj;
+}
+
+static void kvm_get_preset_lpj(void)
+{
+       struct pvclock_vcpu_time_info *src;
+       unsigned long khz;
+       u64 lpj;
+
+       src = &per_cpu(hv_clock, 0);
+       khz = pvclock_tsc_khz(src);
+
+       lpj = ((u64)khz * 1000);
+       do_div(lpj, HZ);
+       preset_lpj = lpj;
+}
+
 static struct clocksource kvm_clock = {
        .name = "kvm-clock",
        .read = kvm_clock_read,
@@ -153,6 +181,7 @@ void __init kvmclock_init(void)
                pv_time_ops.get_wallclock = kvm_get_wallclock;
                pv_time_ops.set_wallclock = kvm_set_wallclock;
                pv_time_ops.sched_clock = kvm_clock_read;
+               pv_time_ops.get_tsc_khz = kvm_get_tsc_khz;
 #ifdef CONFIG_X86_LOCAL_APIC
                pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock;
 #endif
@@ -163,6 +192,7 @@ void __init kvmclock_init(void)
 #ifdef CONFIG_KEXEC
                machine_ops.crash_shutdown  = kvm_crash_shutdown;
 #endif
+               kvm_get_preset_lpj();
                clocksource_register(&kvm_clock);
        }
 }
index 2e2af5d1819160c6047b82a06b6f141e5a23f39c..82a7c7ed6d456401ef1776a53030a4db7890443e 100644 (file)
@@ -163,8 +163,8 @@ static int __cpuinit msr_device_create(int cpu)
 {
        struct device *dev;
 
-       dev = device_create_drvdata(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
-                                   NULL, "msr%d", cpu);
+       dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu), NULL,
+                           "msr%d", cpu);
        return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
index 080d1d27f37a0b4e042c6623af4cbf0c9ff5e8e7..e1e731d78f3821bb6f27950eca4033e52a77c606 100644 (file)
@@ -217,16 +217,6 @@ static inline unsigned long verify_bit_range(unsigned long* bitmap,
 
 #endif /* CONFIG_IOMMU_DEBUG */
 
-static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
-{
-       unsigned int npages;
-
-       npages = PAGE_ALIGN(dma + dmalen) - (dma & PAGE_MASK);
-       npages >>= PAGE_SHIFT;
-
-       return npages;
-}
-
 static inline int translation_enabled(struct iommu_table *tbl)
 {
        /* only PHBs with translation enabled have an IOMMU table */
@@ -408,7 +398,7 @@ static void calgary_unmap_sg(struct device *dev,
                if (dmalen == 0)
                        break;
 
-               npages = num_dma_pages(dma, dmalen);
+               npages = iommu_num_pages(dma, dmalen, PAGE_SIZE);
                iommu_free(tbl, dma, npages);
        }
 }
@@ -427,7 +417,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
                BUG_ON(!sg_page(s));
 
                vaddr = (unsigned long) sg_virt(s);
-               npages = num_dma_pages(vaddr, s->length);
+               npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);
 
                entry = iommu_range_alloc(dev, tbl, npages);
                if (entry == bad_dma_address) {
@@ -464,7 +454,7 @@ static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
        struct iommu_table *tbl = find_iommu_table(dev);
 
        uaddr = (unsigned long)vaddr;
-       npages = num_dma_pages(uaddr, size);
+       npages = iommu_num_pages(uaddr, size, PAGE_SIZE);
 
        return iommu_alloc(dev, tbl, vaddr, npages, direction);
 }
@@ -475,7 +465,7 @@ static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
        struct iommu_table *tbl = find_iommu_table(dev);
        unsigned int npages;
 
-       npages = num_dma_pages(dma_handle, size);
+       npages = iommu_num_pages(dma_handle, size, PAGE_SIZE);
        iommu_free(tbl, dma_handle, npages);
 }
 
index 0a3824e837b4c1b38d3fdc6b778e4d6ba076f4bc..192624820217f9eeeb64ee39ada5ad57a76a0df5 100644 (file)
@@ -125,13 +125,13 @@ void __init pci_iommu_alloc(void)
        pci_swiotlb_init();
 }
 
-unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
+unsigned long iommu_nr_pages(unsigned long addr, unsigned long len)
 {
        unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
 
        return size >> PAGE_SHIFT;
 }
-EXPORT_SYMBOL(iommu_num_pages);
+EXPORT_SYMBOL(iommu_nr_pages);
 #endif
 
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
index 145f1c83369f17a7e5696a7e241d1d28573606dc..e3f75bbcedea9287d8941897004e25159b3e9796 100644 (file)
@@ -231,7 +231,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
                                size_t size, int dir, unsigned long align_mask)
 {
-       unsigned long npages = iommu_num_pages(phys_mem, size);
+       unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
        unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
        int i;
 
@@ -285,7 +285,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
                return;
 
        iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
-       npages = iommu_num_pages(dma_addr, size);
+       npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
        for (i = 0; i < npages; i++) {
                iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
                CLEAR_LEAK(iommu_page + i);
@@ -368,7 +368,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start,
                }
 
                addr = phys_addr;
-               pages = iommu_num_pages(s->offset, s->length);
+               pages = iommu_num_pages(s->offset, s->length, PAGE_SIZE);
                while (pages--) {
                        iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr);
                        SET_LEAK(iommu_page);
@@ -451,7 +451,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 
                seg_size += s->length;
                need = nextneed;
-               pages += iommu_num_pages(s->offset, s->length);
+               pages += iommu_num_pages(s->offset, s->length, PAGE_SIZE);
                ps = s;
        }
        if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
index 922c14058f975d92cbb51d764d8a84256ad9f3fb..0a1302fe6d45307ffa880ed9e355050a194518af 100644 (file)
@@ -123,7 +123,7 @@ void cpu_idle(void)
        }
 }
 
-void __show_registers(struct pt_regs *regs, int all)
+void __show_regs(struct pt_regs *regs, int all)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
        unsigned long d0, d1, d2, d3, d6, d7;
@@ -189,7 +189,7 @@ void __show_registers(struct pt_regs *regs, int all)
 
 void show_regs(struct pt_regs *regs)
 {
-       __show_registers(regs, 1);
+       __show_regs(regs, 1);
        show_trace(NULL, regs, &regs->sp, regs->bp);
 }
 
index ca80394ef5b80ebff3fb5fad35aec9d683a8b32c..cd8c0ed02b7e2c017905a403f10fc3cd25413f4a 100644 (file)
@@ -136,7 +136,7 @@ void cpu_idle(void)
 }
 
 /* Prints also some state that isn't saved in the pt_regs */
-void __show_regs(struct pt_regs *regs)
+void __show_regs(struct pt_regs *regs, int all)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
        unsigned long d0, d1, d2, d3, d6, d7;
@@ -175,6 +175,9 @@ void __show_regs(struct pt_regs *regs)
        rdmsrl(MSR_GS_BASE, gs);
        rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
 
+       if (!all)
+               return;
+
        cr0 = read_cr0();
        cr2 = read_cr2();
        cr3 = read_cr3();
@@ -200,7 +203,7 @@ void __show_regs(struct pt_regs *regs)
 void show_regs(struct pt_regs *regs)
 {
        printk(KERN_INFO "CPU %d:", smp_processor_id());
-       __show_regs(regs);
+       __show_regs(regs, 1);
        show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
 }
 
index 05fbe9a0325a513c81fed8359a3bc259bce54edc..4f9c55f3a7c0f7e2590a5e248428bd19aa0d5c37 100644 (file)
@@ -97,6 +97,18 @@ static unsigned pvclock_get_time_values(struct pvclock_shadow_time *dst,
        return dst->version;
 }
 
+unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src)
+{
+       u64 pv_tsc_khz = 1000000ULL << 32;
+
+       do_div(pv_tsc_khz, src->tsc_to_system_mul);
+       if (src->tsc_shift < 0)
+               pv_tsc_khz <<= -src->tsc_shift;
+       else
+               pv_tsc_khz >>= src->tsc_shift;
+       return pv_tsc_khz;
+}
+
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
        struct pvclock_shadow_time shadow;
index d13858818100e6f35cb328bab4394dc00885d712..f6a11b9b1f9887f8979e67c982c5c5a39b3e1915 100644 (file)
@@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void)
        printk(KERN_DEBUG "Force enabled HPET at resume\n");
 }
 
+static u32 ati_ixp4x0_rev(struct pci_dev *dev)
+{
+       u32 d;
+       u8  b;
+
+       pci_read_config_byte(dev, 0xac, &b);
+       b &= ~(1<<5);
+       pci_write_config_byte(dev, 0xac, b);
+       pci_read_config_dword(dev, 0x70, &d);
+       d |= 1<<8;
+       pci_write_config_dword(dev, 0x70, d);
+       pci_read_config_dword(dev, 0x8, &d);
+       d &= 0xff;
+       dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d);
+       return d;
+}
+
 static void ati_force_enable_hpet(struct pci_dev *dev)
 {
-       u32 uninitialized_var(val);
+       u32 d, val;
+       u8  b;
 
        if (hpet_address || force_hpet_address)
                return;
@@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev)
                return;
        }
 
+       d = ati_ixp4x0_rev(dev);
+       if (d  < 0x82)
+               return;
+
+       /* base address */
        pci_write_config_dword(dev, 0x14, 0xfed00000);
        pci_read_config_dword(dev, 0x14, &val);
+
+       /* enable interrupt */
+       outb(0x72, 0xcd6); b = inb(0xcd7);
+       b |= 0x1;
+       outb(0x72, 0xcd6); outb(b, 0xcd7);
+       outb(0x72, 0xcd6); b = inb(0xcd7);
+       if (!(b & 0x1))
+               return;
+       pci_read_config_dword(dev, 0x64, &d);
+       d |= (1<<10);
+       pci_write_config_dword(dev, 0x64, d);
+       pci_read_config_dword(dev, 0x64, &d);
+       if (!(d & (1<<10)))
+               return;
+
        force_hpet_address = val;
        force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
        dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
                   force_hpet_address);
        cached_dev = dev;
-       return;
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
                         ati_force_enable_hpet);
index 05191bbc68b8bef23926a60b28b461ca559e5502..0a23b5795b25a87c38b117e4bfc168dfc565c2d5 100644 (file)
@@ -223,11 +223,25 @@ static struct platform_device rtc_device = {
 static __init int add_rtc_cmos(void)
 {
 #ifdef CONFIG_PNP
-       if (!pnp_platform_devices)
-               platform_device_register(&rtc_device);
-#else
+       static const char *ids[] __initconst =
+           { "PNP0b00", "PNP0b01", "PNP0b02", };
+       struct pnp_dev *dev;
+       struct pnp_id *id;
+       int i;
+
+       pnp_for_each_dev(dev) {
+               for (id = dev->id; id; id = id->next) {
+                       for (i = 0; i < ARRAY_SIZE(ids); i++) {
+                               if (compare_pnp_id(id, ids[i]) != 0)
+                                       return 0;
+                       }
+               }
+       }
+#endif
+
        platform_device_register(&rtc_device);
-#endif /* CONFIG_PNP */
+       dev_info(&rtc_device.dev,
+                "registered platform RTC device (no PNP device found)\n");
        return 0;
 }
 device_initcall(add_rtc_cmos);
index 21b8e0a59780105c673813c9500207758b1def7a..2255782e8d4b94664ff8c3c053af26aa114d0e6c 100644 (file)
@@ -302,7 +302,7 @@ static void __init relocate_initrd(void)
                if (clen > MAX_MAP_CHUNK-slop)
                        clen = MAX_MAP_CHUNK-slop;
                mapaddr = ramdisk_image & PAGE_MASK;
-               p = early_ioremap(mapaddr, clen+slop);
+               p = early_memremap(mapaddr, clen+slop);
                memcpy(q, p+slop, clen);
                early_iounmap(p, clen+slop);
                q += clen;
@@ -379,7 +379,7 @@ static void __init parse_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, PAGE_SIZE);
+               data = early_memremap(pa_data, PAGE_SIZE);
                switch (data->type) {
                case SETUP_E820_EXT:
                        parse_e820_ext(data, pa_data);
@@ -402,7 +402,7 @@ static void __init e820_reserve_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, sizeof(*data));
+               data = early_memremap(pa_data, sizeof(*data));
                e820_update_range(pa_data, sizeof(*data)+data->len,
                         E820_RAM, E820_RESERVED_KERN);
                found = 1;
@@ -428,7 +428,7 @@ static void __init reserve_early_setup_data(void)
                return;
        pa_data = boot_params.hdr.setup_data;
        while (pa_data) {
-               data = early_ioremap(pa_data, sizeof(*data));
+               data = early_memremap(pa_data, sizeof(*data));
                sprintf(buf, "setup data %x", data->type);
                reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
                pa_data = data->next;
@@ -998,6 +998,8 @@ void __init setup_arch(char **cmdline_p)
         */
        acpi_boot_table_init();
 
+       early_acpi_boot_init();
+
 #ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
index 76b6f50978f7f7219125ffb05b55fa1fd4f273a0..7ed9e070a6e930d97e2d55c8750a50f57a9baef1 100644 (file)
@@ -282,6 +282,8 @@ static void __cpuinit smp_callin(void)
        cpu_set(cpuid, cpu_callin_map);
 }
 
+static int __cpuinitdata unsafe_smp;
+
 /*
  * Activate a secondary processor.
  */
@@ -334,14 +336,17 @@ static void __cpuinit start_secondary(void *unused)
         * does not change while we are assigning vectors to cpus.  Holding
         * this lock ensures we don't half assign or remove an irq from a cpu.
         */
-       ipi_call_lock_irq();
+       ipi_call_lock();
        lock_vector_lock();
        __setup_vector_irq(smp_processor_id());
        cpu_set(smp_processor_id(), cpu_online_map);
        unlock_vector_lock();
-       ipi_call_unlock_irq();
+       ipi_call_unlock();
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 
+       /* enable local interrupts */
+       local_irq_enable();
+
        setup_secondary_clock();
 
        wmb();
@@ -394,7 +399,7 @@ static void __cpuinit smp_apply_quirks(struct cpuinfo_x86 *c)
                                goto valid_k7;
 
                /* If we get here, not a certified SMP capable AMD system. */
-               add_taint(TAINT_UNSAFE_SMP);
+               unsafe_smp = 1;
        }
 
 valid_k7:
@@ -411,12 +416,10 @@ static void __cpuinit smp_checks(void)
         * Don't taint if we are running SMP kernel on a single non-MP
         * approved Athlon
         */
-       if (tainted & TAINT_UNSAFE_SMP) {
-               if (num_online_cpus())
-                       printk(KERN_INFO "WARNING: This combination of AMD"
-                               "processors is not suitable for SMP.\n");
-               else
-                       tainted &= ~TAINT_UNSAFE_SMP;
+       if (unsafe_smp && num_online_cpus() > 1) {
+               printk(KERN_INFO "WARNING: This combination of AMD"
+                       "processors is not suitable for SMP.\n");
+               add_taint(TAINT_UNSAFE_SMP);
        }
 }
 
@@ -596,10 +599,12 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
         * Give the other CPU some time to accept the IPI.
         */
        udelay(200);
-       maxlvt = lapic_get_maxlvt();
-       if (maxlvt > 3)                 /* Due to the Pentium erratum 3AP.  */
-               apic_write(APIC_ESR, 0);
-       accept_status = (apic_read(APIC_ESR) & 0xEF);
+       if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+               maxlvt = lapic_get_maxlvt();
+               if (maxlvt > 3)                 /* Due to the Pentium erratum 3AP.  */
+                       apic_write(APIC_ESR, 0);
+               accept_status = (apic_read(APIC_ESR) & 0xEF);
+       }
        pr_debug("NMI sent.\n");
 
        if (send_status)
@@ -1256,39 +1261,6 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
        check_nmi_watchdog();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
-static void remove_siblinginfo(int cpu)
-{
-       int sibling;
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
-
-       for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) {
-               cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
-               /*/
-                * last thread sibling in this cpu core going down
-                */
-               if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
-                       cpu_data(sibling).booted_cores--;
-       }
-
-       for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu))
-               cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
-       cpus_clear(per_cpu(cpu_sibling_map, cpu));
-       cpus_clear(per_cpu(cpu_core_map, cpu));
-       c->phys_proc_id = 0;
-       c->cpu_core_id = 0;
-       cpu_clear(cpu, cpu_sibling_setup_map);
-}
-
-static int additional_cpus __initdata = -1;
-
-static __init int setup_additional_cpus(char *s)
-{
-       return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
-}
-early_param("additional_cpus", setup_additional_cpus);
-
 /*
  * cpu_possible_map should be static, it cannot change as cpu's
  * are onlined, or offlined. The reason is per-cpu data-structures
@@ -1308,21 +1280,13 @@ early_param("additional_cpus", setup_additional_cpus);
  */
 __init void prefill_possible_map(void)
 {
-       int i;
-       int possible;
+       int i, possible;
 
        /* no processor from mptable or madt */
        if (!num_processors)
                num_processors = 1;
 
-       if (additional_cpus == -1) {
-               if (disabled_cpus > 0)
-                       additional_cpus = disabled_cpus;
-               else
-                       additional_cpus = 0;
-       }
-
-       possible = num_processors + additional_cpus;
+       possible = num_processors + disabled_cpus;
        if (possible > NR_CPUS)
                possible = NR_CPUS;
 
@@ -1335,6 +1299,31 @@ __init void prefill_possible_map(void)
        nr_cpu_ids = possible;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void remove_siblinginfo(int cpu)
+{
+       int sibling;
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+       for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) {
+               cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+               /*/
+                * last thread sibling in this cpu core going down
+                */
+               if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+                       cpu_data(sibling).booted_cores--;
+       }
+
+       for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu))
+               cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
+       cpus_clear(per_cpu(cpu_sibling_map, cpu));
+       cpus_clear(per_cpu(cpu_core_map, cpu));
+       c->phys_proc_id = 0;
+       c->cpu_core_id = 0;
+       cpu_clear(cpu, cpu_sibling_setup_map);
+}
+
 static void __ref remove_cpu_from_maps(int cpu)
 {
        cpu_clear(cpu, cpu_online_map);
index bbecf8b6bf96392de71968bdfd5da4b8aae006ad..77b400f06ea2335fa770fb3273ce5cd7e5820c18 100644 (file)
@@ -47,10 +47,9 @@ unsigned long profile_pc(struct pt_regs *regs)
        unsigned long pc = instruction_pointer(regs);
 
 #ifdef CONFIG_SMP
-       if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->cs) &&
-           in_lock_functions(pc)) {
+       if (!user_mode_vm(regs) && in_lock_functions(pc)) {
 #ifdef CONFIG_FRAME_POINTER
-               return *(unsigned long *)(regs->bp + 4);
+               return *(unsigned long *)(regs->bp + sizeof(long));
 #else
                unsigned long *sp = (unsigned long *)&regs->sp;
 
@@ -95,6 +94,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
 
        do_timer_interrupt_hook();
 
+#ifdef CONFIG_MCA
        if (MCA_bus) {
                /* The PS/2 uses level-triggered interrupts.  You can't
                turn them off, nor would you want to (any attempt to
@@ -108,6 +108,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
                u8 irq_v = inb_p( 0x61 );       /* read the current state */
                outb_p( irq_v|0x80, 0x61 );     /* reset the IRQ */
        }
+#endif
 
        return IRQ_HANDLED;
 }
index e3d49c553af22aec7c773006b7018325dccb6ec0..cb19d650c21643599aa1423a57b64a85ee26afe8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/time.h>
+#include <linux/mca.h>
 
 #include <asm/i8253.h>
 #include <asm/hpet.h>
@@ -33,23 +34,34 @@ unsigned long profile_pc(struct pt_regs *regs)
        /* Assume the lock function has either no stack frame or a copy
           of flags from PUSHF
           Eflags always has bits 22 and up cleared unlike kernel addresses. */
-       if (!user_mode(regs) && in_lock_functions(pc)) {
+       if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
+               return *(unsigned long *)(regs->bp + sizeof(long));
+#else
                unsigned long *sp = (unsigned long *)regs->sp;
                if (sp[0] >> 22)
                        return sp[0];
                if (sp[1] >> 22)
                        return sp[1];
+#endif
        }
        return pc;
 }
 EXPORT_SYMBOL(profile_pc);
 
-static irqreturn_t timer_event_interrupt(int irq, void *dev_id)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
        add_pda(irq0_irqs, 1);
 
        global_clock_event->event_handler(global_clock_event);
 
+#ifdef CONFIG_MCA
+       if (MCA_bus) {
+               u8 irq_v = inb_p(0x61);       /* read the current state */
+               outb_p(irq_v|0x80, 0x61);     /* reset the IRQ */
+       }
+#endif
+
        return IRQ_HANDLED;
 }
 
@@ -100,7 +112,7 @@ unsigned long __init calibrate_cpu(void)
 }
 
 static struct irqaction irq0 = {
-       .handler        = timer_event_interrupt,
+       .handler        = timer_interrupt,
        .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
        .mask           = CPU_MASK_NONE,
        .name           = "timer"
@@ -111,16 +123,13 @@ void __init hpet_time_init(void)
        if (!hpet_enable())
                setup_pit_timer();
 
+       irq0.mask = cpumask_of_cpu(0);
        setup_irq(0, &irq0);
 }
 
 void __init time_init(void)
 {
        tsc_init();
-       if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
-               vgetcpu_mode = VGETCPU_RDTSCP;
-       else
-               vgetcpu_mode = VGETCPU_LSL;
 
        late_time_init = choose_time_init();
 }
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
new file mode 100644 (file)
index 0000000..e062974
--- /dev/null
@@ -0,0 +1,1034 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *
+ *  Pentium III FXSR, SSE support
+ *     Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * Handle hardware traps and faults.
+ */
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/utsname.h>
+#include <linux/kdebug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/unwind.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kexec.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/nmi.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_EISA
+#include <linux/ioport.h>
+#include <linux/eisa.h>
+#endif
+
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
+
+#if defined(CONFIG_EDAC)
+#include <linux/edac.h>
+#endif
+
+#include <asm/stacktrace.h>
+#include <asm/processor.h>
+#include <asm/debugreg.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/unwind.h>
+#include <asm/traps.h>
+#include <asm/desc.h>
+#include <asm/i387.h>
+
+#include <mach_traps.h>
+
+#ifdef CONFIG_X86_64
+#include <asm/pgalloc.h>
+#include <asm/proto.h>
+#include <asm/pda.h>
+#else
+#include <asm/processor-flags.h>
+#include <asm/arch_hooks.h>
+#include <asm/nmi.h>
+#include <asm/smp.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+
+#include "cpu/mcheck/mce.h"
+
+DECLARE_BITMAP(used_vectors, NR_VECTORS);
+EXPORT_SYMBOL_GPL(used_vectors);
+
+asmlinkage int system_call(void);
+
+/* Do we ignore FPU interrupts ? */
+char ignore_fpu_irq;
+
+/*
+ * The IDT has to be page-aligned to simplify the Pentium
+ * F0 0F bug workaround.. We have a special link segment
+ * for this.
+ */
+gate_desc idt_table[256]
+       __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
+#endif
+
+static int ignore_nmis;
+
+static inline void conditional_sti(struct pt_regs *regs)
+{
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_enable();
+}
+
+static inline void preempt_conditional_sti(struct pt_regs *regs)
+{
+       inc_preempt_count();
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_enable();
+}
+
+static inline void preempt_conditional_cli(struct pt_regs *regs)
+{
+       if (regs->flags & X86_EFLAGS_IF)
+               local_irq_disable();
+       dec_preempt_count();
+}
+
+#ifdef CONFIG_X86_32
+static inline void
+die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+       if (!user_mode_vm(regs))
+               die(str, regs, err);
+}
+
+/*
+ * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+ * invalid offset set (the LAZY one) and the faulting thread has
+ * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS,
+ * we set the offset field correctly and return 1.
+ */
+static int lazy_iobitmap_copy(void)
+{
+       struct thread_struct *thread;
+       struct tss_struct *tss;
+       int cpu;
+
+       cpu = get_cpu();
+       tss = &per_cpu(init_tss, cpu);
+       thread = &current->thread;
+
+       if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+           thread->io_bitmap_ptr) {
+               memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
+                      thread->io_bitmap_max);
+               /*
+                * If the previously set map was extending to higher ports
+                * than the current one, pad extra space with 0xff (no access).
+                */
+               if (thread->io_bitmap_max < tss->io_bitmap_max) {
+                       memset((char *) tss->io_bitmap +
+                               thread->io_bitmap_max, 0xff,
+                               tss->io_bitmap_max - thread->io_bitmap_max);
+               }
+               tss->io_bitmap_max = thread->io_bitmap_max;
+               tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
+               tss->io_bitmap_owner = thread;
+               put_cpu();
+
+               return 1;
+       }
+       put_cpu();
+
+       return 0;
+}
+#endif
+
+static void __kprobes
+do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
+       long error_code, siginfo_t *info)
+{
+       struct task_struct *tsk = current;
+
+#ifdef CONFIG_X86_32
+       if (regs->flags & X86_VM_MASK) {
+               /*
+                * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
+                * On nmi (interrupt 2), do_trap should not be called.
+                */
+               if (trapnr < 6)
+                       goto vm86_trap;
+               goto trap_signal;
+       }
+#endif
+
+       if (!user_mode(regs))
+               goto kernel_trap;
+
+#ifdef CONFIG_X86_32
+trap_signal:
+#endif
+       /*
+        * We want error_code and trap_no set for userspace faults and
+        * kernelspace faults which result in die(), but not
+        * kernelspace faults which are fixed up.  die() gives the
+        * process no chance to handle the signal and notice the
+        * kernel fault information, so that won't result in polluting
+        * the information about previously queued, but not yet
+        * delivered, faults.  See also do_general_protection below.
+        */
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = trapnr;
+
+#ifdef CONFIG_X86_64
+       if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+           printk_ratelimit()) {
+               printk(KERN_INFO
+                      "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+                      tsk->comm, tsk->pid, str,
+                      regs->ip, regs->sp, error_code);
+               print_vma_addr(" in ", regs->ip);
+               printk("\n");
+       }
+#endif
+
+       if (info)
+               force_sig_info(signr, info, tsk);
+       else
+               force_sig(signr, tsk);
+       return;
+
+kernel_trap:
+       if (!fixup_exception(regs)) {
+               tsk->thread.error_code = error_code;
+               tsk->thread.trap_no = trapnr;
+               die(str, regs, error_code);
+       }
+       return;
+
+#ifdef CONFIG_X86_32
+vm86_trap:
+       if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
+                                               error_code, trapnr))
+               goto trap_signal;
+       return;
+#endif
+}
+
+#define DO_ERROR(trapnr, signr, str, name)                             \
+dotraplinkage void do_##name(struct pt_regs *regs, long error_code)    \
+{                                                                      \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
+                                                       == NOTIFY_STOP) \
+               return;                                                 \
+       conditional_sti(regs);                                          \
+       do_trap(trapnr, signr, str, regs, error_code, NULL);            \
+}
+
+#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)                \
+dotraplinkage 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;                           \
+       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
+                                                       == NOTIFY_STOP) \
+               return;                                                 \
+       conditional_sti(regs);                                          \
+       do_trap(trapnr, signr, str, regs, error_code, &info);           \
+}
+
+DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+DO_ERROR(4, SIGSEGV, "overflow", overflow)
+DO_ERROR(5, SIGSEGV, "bounds", bounds)
+DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
+DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+#ifdef CONFIG_X86_32
+DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+#endif
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+
+#ifdef CONFIG_X86_64
+/* Runs on IST stack */
+dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+{
+       if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
+                       12, SIGBUS) == NOTIFY_STOP)
+               return;
+       preempt_conditional_sti(regs);
+       do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+       preempt_conditional_cli(regs);
+}
+
+dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
+{
+       static const char str[] = "double fault";
+       struct task_struct *tsk = current;
+
+       /* Return not checked because double check cannot be ignored */
+       notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
+
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 8;
+
+       /* This is always a kernel trap and never fixable (and thus must
+          never return). */
+       for (;;)
+               die(str, regs, error_code);
+}
+#endif
+
+dotraplinkage void __kprobes
+do_general_protection(struct pt_regs *regs, long error_code)
+{
+       struct task_struct *tsk;
+
+       conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+       if (lazy_iobitmap_copy()) {
+               /* restart the faulting instruction */
+               return;
+       }
+
+       if (regs->flags & X86_VM_MASK)
+               goto gp_in_vm86;
+#endif
+
+       tsk = current;
+       if (!user_mode(regs))
+               goto gp_in_kernel;
+
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 13;
+
+       if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+                       printk_ratelimit()) {
+               printk(KERN_INFO
+                       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+                       tsk->comm, task_pid_nr(tsk),
+                       regs->ip, regs->sp, error_code);
+               print_vma_addr(" in ", regs->ip);
+               printk("\n");
+       }
+
+       force_sig(SIGSEGV, tsk);
+       return;
+
+#ifdef CONFIG_X86_32
+gp_in_vm86:
+       local_irq_enable();
+       handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+       return;
+#endif
+
+gp_in_kernel:
+       if (fixup_exception(regs))
+               return;
+
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 13;
+       if (notify_die(DIE_GPF, "general protection fault", regs,
+                               error_code, 13, SIGSEGV) == NOTIFY_STOP)
+               return;
+       die("general protection fault", regs, error_code);
+}
+
+static notrace __kprobes void
+mem_parity_error(unsigned char reason, struct pt_regs *regs)
+{
+       printk(KERN_EMERG
+               "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+                       reason, smp_processor_id());
+
+       printk(KERN_EMERG
+               "You have some hardware problem, likely on the PCI bus.\n");
+
+#if defined(CONFIG_EDAC)
+       if (edac_handler_set()) {
+               edac_atomic_assert_error();
+               return;
+       }
+#endif
+
+       if (panic_on_unrecovered_nmi)
+               panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+
+       /* Clear and disable the memory parity error line. */
+       reason = (reason & 0xf) | 4;
+       outb(reason, 0x61);
+}
+
+static notrace __kprobes void
+io_check_error(unsigned char reason, struct pt_regs *regs)
+{
+       unsigned long i;
+
+       printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+       show_registers(regs);
+
+       /* Re-enable the IOCK line, wait for a few seconds */
+       reason = (reason & 0xf) | 8;
+       outb(reason, 0x61);
+
+       i = 2000;
+       while (--i)
+               udelay(1000);
+
+       reason &= ~8;
+       outb(reason, 0x61);
+}
+
+static notrace __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+{
+       if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
+                       NOTIFY_STOP)
+               return;
+#ifdef CONFIG_MCA
+       /*
+        * Might actually be able to figure out what the guilty party
+        * is:
+        */
+       if (MCA_bus) {
+               mca_handle_nmi();
+               return;
+       }
+#endif
+       printk(KERN_EMERG
+               "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+                       reason, smp_processor_id());
+
+       printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+       if (panic_on_unrecovered_nmi)
+               panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+}
+
+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+{
+       unsigned char reason = 0;
+       int cpu;
+
+       cpu = smp_processor_id();
+
+       /* Only the BSP gets external NMIs from the system. */
+       if (!cpu)
+               reason = get_nmi_reason();
+
+       if (!(reason & 0xc0)) {
+               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+                                                               == NOTIFY_STOP)
+                       return;
+#ifdef CONFIG_X86_LOCAL_APIC
+               /*
+                * Ok, so this is none of the documented NMI sources,
+                * so it must be the NMI watchdog.
+                */
+               if (nmi_watchdog_tick(regs, reason))
+                       return;
+               if (!do_nmi_callback(regs, cpu))
+                       unknown_nmi_error(reason, regs);
+#else
+               unknown_nmi_error(reason, regs);
+#endif
+
+               return;
+       }
+       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+               return;
+
+       /* AK: following checks seem to be broken on modern chipsets. FIXME */
+       if (reason & 0x80)
+               mem_parity_error(reason, regs);
+       if (reason & 0x40)
+               io_check_error(reason, regs);
+#ifdef CONFIG_X86_32
+       /*
+        * Reassert NMI in case it became active meanwhile
+        * as it's edge-triggered:
+        */
+       reassert_nmi();
+#endif
+}
+
+dotraplinkage notrace __kprobes void
+do_nmi(struct pt_regs *regs, long error_code)
+{
+       nmi_enter();
+
+#ifdef CONFIG_X86_32
+       { int cpu; cpu = smp_processor_id(); ++nmi_count(cpu); }
+#else
+       add_pda(__nmi_count, 1);
+#endif
+
+       if (!ignore_nmis)
+               default_do_nmi(regs);
+
+       nmi_exit();
+}
+
+void stop_nmi(void)
+{
+       acpi_nmi_disable();
+       ignore_nmis++;
+}
+
+void restart_nmi(void)
+{
+       ignore_nmis--;
+       acpi_nmi_enable();
+}
+
+/* May run on IST stack. */
+dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
+{
+#ifdef CONFIG_KPROBES
+       if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+                       == NOTIFY_STOP)
+               return;
+#else
+       if (notify_die(DIE_TRAP, "int3", regs, error_code, 3, SIGTRAP)
+                       == NOTIFY_STOP)
+               return;
+#endif
+
+       preempt_conditional_sti(regs);
+       do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+       preempt_conditional_cli(regs);
+}
+
+#ifdef CONFIG_X86_64
+/* Help handler running on IST stack to switch back to user stack
+   for scheduling or signal handling. The actual stack switch is done in
+   entry.S */
+asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
+{
+       struct pt_regs *regs = eregs;
+       /* Did already sync */
+       if (eregs == (struct pt_regs *)eregs->sp)
+               ;
+       /* Exception from user space */
+       else if (user_mode(eregs))
+               regs = task_pt_regs(current);
+       /* Exception from kernel and interrupts are enabled. Move to
+          kernel process stack. */
+       else if (eregs->flags & X86_EFLAGS_IF)
+               regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
+       if (eregs != regs)
+               *regs = *eregs;
+       return regs;
+}
+#endif
+
+/*
+ * Our handling of the processor debug registers is non-trivial.
+ * We do not clear them on entry and exit from the kernel. Therefore
+ * it is possible to get a watchpoint trap here from inside the kernel.
+ * However, the code in ./ptrace.c has ensured that the user can
+ * only set watchpoints on userspace addresses. Therefore the in-kernel
+ * watchpoint trap can only occur in code which is reading/writing
+ * from user space. Such code must not hold kernel locks (since it
+ * can equally take a page fault), therefore it is safe to call
+ * force_sig_info even though that claims and releases locks.
+ *
+ * Code in ./signal.c ensures that the debug control register
+ * is restored before we deliver any signal, and therefore that
+ * user code runs with the correct debug control register even though
+ * we clear it here.
+ *
+ * Being careful here means that we don't have to be as careful in a
+ * lot of more complicated places (task switching can be a bit lazy
+ * about restoring all the debug state, and ptrace doesn't have to
+ * find every occurrence of the TF bit that could be saved away even
+ * by user code)
+ *
+ * May run on IST stack.
+ */
+dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
+{
+       struct task_struct *tsk = current;
+       unsigned long condition;
+       int si_code;
+
+       get_debugreg(condition, 6);
+
+       /*
+        * The processor cleared BTF, so don't mark that we need it set.
+        */
+       clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
+       tsk->thread.debugctlmsr = 0;
+
+       if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+                                               SIGTRAP) == NOTIFY_STOP)
+               return;
+
+       /* It's safe to allow irq's after DR6 has been saved */
+       preempt_conditional_sti(regs);
+
+       /* Mask out spurious debug traps due to lazy DR7 setting */
+       if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+               if (!tsk->thread.debugreg7)
+                       goto clear_dr7;
+       }
+
+#ifdef CONFIG_X86_32
+       if (regs->flags & X86_VM_MASK)
+               goto debug_vm86;
+#endif
+
+       /* Save debug status register where ptrace can see it */
+       tsk->thread.debugreg6 = condition;
+
+       /*
+        * Single-stepping through TF: make sure we ignore any events in
+        * kernel space (but re-enable TF when returning to user mode).
+        */
+       if (condition & DR_STEP) {
+               if (!user_mode(regs))
+                       goto clear_TF_reenable;
+       }
+
+       si_code = get_si_code(condition);
+       /* Ok, finally something we can handle */
+       send_sigtrap(tsk, regs, error_code, si_code);
+
+       /*
+        * Disable additional traps. They'll be re-enabled when
+        * the signal is delivered.
+        */
+clear_dr7:
+       set_debugreg(0, 7);
+       preempt_conditional_cli(regs);
+       return;
+
+#ifdef CONFIG_X86_32
+debug_vm86:
+       handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+       preempt_conditional_cli(regs);
+       return;
+#endif
+
+clear_TF_reenable:
+       set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+       regs->flags &= ~X86_EFLAGS_TF;
+       preempt_conditional_cli(regs);
+       return;
+}
+
+#ifdef CONFIG_X86_64
+static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
+{
+       if (fixup_exception(regs))
+               return 1;
+
+       notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
+       /* Illegal floating point operation in the kernel */
+       current->thread.trap_no = trapnr;
+       die(str, regs, 0);
+       return 0;
+}
+#endif
+
+/*
+ * Note that we play around with the 'TS' bit in an attempt to get
+ * the correct behaviour even in the presence of the asynchronous
+ * IRQ13 behaviour
+ */
+void math_error(void __user *ip)
+{
+       struct task_struct *task;
+       siginfo_t info;
+       unsigned short cwd, swd;
+
+       /*
+        * Save the info for the exception handler and clear the error.
+        */
+       task = current;
+       save_init_fpu(task);
+       task->thread.trap_no = 16;
+       task->thread.error_code = 0;
+       info.si_signo = SIGFPE;
+       info.si_errno = 0;
+       info.si_code = __SI_FAULT;
+       info.si_addr = ip;
+       /*
+        * (~cwd & swd) will mask out exceptions that are not set to unmasked
+        * status.  0x3f is the exception bits in these regs, 0x200 is the
+        * C1 reg you need in case of a stack fault, 0x040 is the stack
+        * fault bit.  We should only be taking one exception at a time,
+        * so if this combination doesn't produce any single exception,
+        * then we have a bad program that isn't synchronizing its FPU usage
+        * and it will suffer the consequences since we won't be able to
+        * fully reproduce the context of the exception
+        */
+       cwd = get_fpu_cwd(task);
+       swd = get_fpu_swd(task);
+       switch (swd & ~cwd & 0x3f) {
+       case 0x000: /* No unmasked exception */
+#ifdef CONFIG_X86_32
+               return;
+#endif
+       default: /* Multiple exceptions */
+               break;
+       case 0x001: /* Invalid Op */
+               /*
+                * swd & 0x240 == 0x040: Stack Underflow
+                * swd & 0x240 == 0x240: Stack Overflow
+                * User must clear the SF bit (0x40) if set
+                */
+               info.si_code = FPE_FLTINV;
+               break;
+       case 0x002: /* Denormalize */
+       case 0x010: /* Underflow */
+               info.si_code = FPE_FLTUND;
+               break;
+       case 0x004: /* Zero Divide */
+               info.si_code = FPE_FLTDIV;
+               break;
+       case 0x008: /* Overflow */
+               info.si_code = FPE_FLTOVF;
+               break;
+       case 0x020: /* Precision */
+               info.si_code = FPE_FLTRES;
+               break;
+       }
+       force_sig_info(SIGFPE, &info, task);
+}
+
+dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
+{
+       conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+       ignore_fpu_irq = 1;
+#else
+       if (!user_mode(regs) &&
+           kernel_math_error(regs, "kernel x87 math error", 16))
+               return;
+#endif
+
+       math_error((void __user *)regs->ip);
+}
+
+static void simd_math_error(void __user *ip)
+{
+       struct task_struct *task;
+       siginfo_t info;
+       unsigned short mxcsr;
+
+       /*
+        * Save the info for the exception handler and clear the error.
+        */
+       task = current;
+       save_init_fpu(task);
+       task->thread.trap_no = 19;
+       task->thread.error_code = 0;
+       info.si_signo = SIGFPE;
+       info.si_errno = 0;
+       info.si_code = __SI_FAULT;
+       info.si_addr = ip;
+       /*
+        * The SIMD FPU exceptions are handled a little differently, as there
+        * is only a single status/control register.  Thus, to determine which
+        * unmasked exception was caught we must mask the exception mask bits
+        * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+        */
+       mxcsr = get_fpu_mxcsr(task);
+       switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+       case 0x000:
+       default:
+               break;
+       case 0x001: /* Invalid Op */
+               info.si_code = FPE_FLTINV;
+               break;
+       case 0x002: /* Denormalize */
+       case 0x010: /* Underflow */
+               info.si_code = FPE_FLTUND;
+               break;
+       case 0x004: /* Zero Divide */
+               info.si_code = FPE_FLTDIV;
+               break;
+       case 0x008: /* Overflow */
+               info.si_code = FPE_FLTOVF;
+               break;
+       case 0x020: /* Precision */
+               info.si_code = FPE_FLTRES;
+               break;
+       }
+       force_sig_info(SIGFPE, &info, task);
+}
+
+dotraplinkage void
+do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+{
+       conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+       if (cpu_has_xmm) {
+               /* Handle SIMD FPU exceptions on PIII+ processors. */
+               ignore_fpu_irq = 1;
+               simd_math_error((void __user *)regs->ip);
+               return;
+       }
+       /*
+        * Handle strange cache flush from user space exception
+        * in all other cases.  This is undocumented behaviour.
+        */
+       if (regs->flags & X86_VM_MASK) {
+               handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
+               return;
+       }
+       current->thread.trap_no = 19;
+       current->thread.error_code = error_code;
+       die_if_kernel("cache flush denied", regs, error_code);
+       force_sig(SIGSEGV, current);
+#else
+       if (!user_mode(regs) &&
+                       kernel_math_error(regs, "kernel simd math error", 19))
+               return;
+       simd_math_error((void __user *)regs->ip);
+#endif
+}
+
+dotraplinkage void
+do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+{
+       conditional_sti(regs);
+#if 0
+       /* No need to warn about this any longer. */
+       printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+#endif
+}
+
+#ifdef CONFIG_X86_32
+unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+{
+       struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
+       unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+       unsigned long new_kesp = kesp - base;
+       unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+       __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
+
+       /* Set up base for espfix segment */
+       desc &= 0x00f0ff0000000000ULL;
+       desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+               ((((__u64)base) << 32) & 0xff00000000000000ULL) |
+               ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+               (lim_pages & 0xffff);
+       *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
+
+       return new_kesp;
+}
+#else
+asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+{
+}
+
+asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+{
+}
+#endif
+
+/*
+ * 'math_state_restore()' saves the current math information in the
+ * old math state array, and gets the new ones from the current task
+ *
+ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+ * Don't touch unless you *really* know how it works.
+ *
+ * Must be called with kernel preemption disabled (in this case,
+ * local interrupts are disabled at the call-site in entry.S).
+ */
+asmlinkage void math_state_restore(void)
+{
+       struct thread_info *thread = current_thread_info();
+       struct task_struct *tsk = thread->task;
+
+       if (!tsk_used_math(tsk)) {
+               local_irq_enable();
+               /*
+                * does a slab alloc which can sleep
+                */
+               if (init_fpu(tsk)) {
+                       /*
+                        * ran out of memory!
+                        */
+                       do_group_exit(SIGKILL);
+                       return;
+               }
+               local_irq_disable();
+       }
+
+       clts();                         /* Allow maths ops (or we recurse) */
+#ifdef CONFIG_X86_32
+       restore_fpu(tsk);
+#else
+       /*
+        * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+        */
+       if (unlikely(restore_fpu_checking(tsk))) {
+               stts();
+               force_sig(SIGSEGV, tsk);
+               return;
+       }
+#endif
+       thread->status |= TS_USEDFPU;   /* So we fnsave on switch_to() */
+       tsk->fpu_counter++;
+}
+EXPORT_SYMBOL_GPL(math_state_restore);
+
+#ifndef CONFIG_MATH_EMULATION
+asmlinkage void math_emulate(long arg)
+{
+       printk(KERN_EMERG
+               "math-emulation not enabled and no coprocessor found.\n");
+       printk(KERN_EMERG "killing %s.\n", current->comm);
+       force_sig(SIGFPE, current);
+       schedule();
+}
+#endif /* CONFIG_MATH_EMULATION */
+
+dotraplinkage void __kprobes
+do_device_not_available(struct pt_regs *regs, long error)
+{
+#ifdef CONFIG_X86_32
+       if (read_cr0() & X86_CR0_EM) {
+               conditional_sti(regs);
+               math_emulate(0);
+       } else {
+               math_state_restore(); /* interrupts still off */
+               conditional_sti(regs);
+       }
+#else
+       math_state_restore();
+#endif
+}
+
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_MCE
+dotraplinkage void __kprobes do_machine_check(struct pt_regs *regs, long error)
+{
+       conditional_sti(regs);
+       machine_check_vector(regs, error);
+}
+#endif
+
+dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
+{
+       siginfo_t info;
+       local_irq_enable();
+
+       info.si_signo = SIGILL;
+       info.si_errno = 0;
+       info.si_code = ILL_BADSTK;
+       info.si_addr = 0;
+       if (notify_die(DIE_TRAP, "iret exception",
+                       regs, error_code, 32, SIGILL) == NOTIFY_STOP)
+               return;
+       do_trap(32, SIGILL, "iret exception", regs, error_code, &info);
+}
+#endif
+
+void __init trap_init(void)
+{
+#ifdef CONFIG_X86_32
+       int i;
+#endif
+
+#ifdef CONFIG_EISA
+       void __iomem *p = early_ioremap(0x0FFFD9, 4);
+
+       if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
+               EISA_bus = 1;
+       early_iounmap(p, 4);
+#endif
+
+       set_intr_gate(0, &divide_error);
+       set_intr_gate_ist(1, &debug, DEBUG_STACK);
+       set_intr_gate_ist(2, &nmi, NMI_STACK);
+       /* int3 can be called from all */
+       set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
+       /* int4 can be called from all */
+       set_system_intr_gate(4, &overflow);
+       set_intr_gate(5, &bounds);
+       set_intr_gate(6, &invalid_op);
+       set_intr_gate(7, &device_not_available);
+#ifdef CONFIG_X86_32
+       set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS);
+#else
+       set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK);
+#endif
+       set_intr_gate(9, &coprocessor_segment_overrun);
+       set_intr_gate(10, &invalid_TSS);
+       set_intr_gate(11, &segment_not_present);
+       set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
+       set_intr_gate(13, &general_protection);
+       set_intr_gate(14, &page_fault);
+       set_intr_gate(15, &spurious_interrupt_bug);
+       set_intr_gate(16, &coprocessor_error);
+       set_intr_gate(17, &alignment_check);
+#ifdef CONFIG_X86_MCE
+       set_intr_gate_ist(18, &machine_check, MCE_STACK);
+#endif
+       set_intr_gate(19, &simd_coprocessor_error);
+
+#ifdef CONFIG_IA32_EMULATION
+       set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
+#endif
+
+#ifdef CONFIG_X86_32
+       if (cpu_has_fxsr) {
+               printk(KERN_INFO "Enabling fast FPU save and restore... ");
+               set_in_cr4(X86_CR4_OSFXSR);
+               printk("done.\n");
+       }
+       if (cpu_has_xmm) {
+               printk(KERN_INFO
+                       "Enabling unmasked SIMD FPU exception support... ");
+               set_in_cr4(X86_CR4_OSXMMEXCPT);
+               printk("done.\n");
+       }
+
+       set_system_trap_gate(SYSCALL_VECTOR, &system_call);
+
+       /* Reserve all the builtin and the syscall vector: */
+       for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
+               set_bit(i, used_vectors);
+
+       set_bit(SYSCALL_VECTOR, used_vectors);
+#endif
+       /*
+        * Should be a barrier for any external CPU state:
+        */
+       cpu_init();
+
+#ifdef CONFIG_X86_32
+       trap_init_hook();
+#endif
+}
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
deleted file mode 100644 (file)
index 0429c5d..0000000
+++ /dev/null
@@ -1,1257 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
- *
- *  Pentium III FXSR, SSE support
- *     Gareth Hughes <gareth@valinux.com>, May 2000
- */
-
-/*
- * 'Traps.c' handles hardware traps and faults after we have saved some
- * state in 'asm.s'.
- */
-#include <linux/interrupt.h>
-#include <linux/kallsyms.h>
-#include <linux/spinlock.h>
-#include <linux/highmem.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/utsname.h>
-#include <linux/kdebug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/unwind.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/kexec.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bug.h>
-#include <linux/nmi.h>
-#include <linux/mm.h>
-
-#ifdef CONFIG_EISA
-#include <linux/ioport.h>
-#include <linux/eisa.h>
-#endif
-
-#ifdef CONFIG_MCA
-#include <linux/mca.h>
-#endif
-
-#if defined(CONFIG_EDAC)
-#include <linux/edac.h>
-#endif
-
-#include <asm/arch_hooks.h>
-#include <asm/stacktrace.h>
-#include <asm/processor.h>
-#include <asm/debugreg.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/unwind.h>
-#include <asm/desc.h>
-#include <asm/i387.h>
-#include <asm/nmi.h>
-#include <asm/smp.h>
-#include <asm/io.h>
-#include <asm/traps.h>
-
-#include "mach_traps.h"
-
-DECLARE_BITMAP(used_vectors, NR_VECTORS);
-EXPORT_SYMBOL_GPL(used_vectors);
-
-asmlinkage int system_call(void);
-
-/* Do we ignore FPU interrupts ? */
-char ignore_fpu_irq;
-
-/*
- * The IDT has to be page-aligned to simplify the Pentium
- * F0 0F bug workaround.. We have a special link segment
- * for this.
- */
-gate_desc idt_table[256]
-       __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
-
-int panic_on_unrecovered_nmi;
-int kstack_depth_to_print = 24;
-static unsigned int code_bytes = 64;
-static int ignore_nmis;
-static int die_counter;
-
-void printk_address(unsigned long address, int reliable)
-{
-#ifdef CONFIG_KALLSYMS
-       unsigned long offset = 0;
-       unsigned long symsize;
-       const char *symname;
-       char *modname;
-       char *delim = ":";
-       char namebuf[KSYM_NAME_LEN];
-       char reliab[4] = "";
-
-       symname = kallsyms_lookup(address, &symsize, &offset,
-                                       &modname, namebuf);
-       if (!symname) {
-               printk(" [<%08lx>]\n", address);
-               return;
-       }
-       if (!reliable)
-               strcpy(reliab, "? ");
-
-       if (!modname)
-               modname = delim = "";
-       printk(" [<%08lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
-               address, reliab, delim, modname, delim, symname, offset, symsize);
-#else
-       printk(" [<%08lx>]\n", address);
-#endif
-}
-
-static inline int valid_stack_ptr(struct thread_info *tinfo,
-                       void *p, unsigned int size)
-{
-       void *t = tinfo;
-       return  p > t && p <= t + THREAD_SIZE - size;
-}
-
-/* The form of the top of the frame on the stack */
-struct stack_frame {
-       struct stack_frame *next_frame;
-       unsigned long return_address;
-};
-
-static inline unsigned long
-print_context_stack(struct thread_info *tinfo,
-               unsigned long *stack, unsigned long bp,
-               const struct stacktrace_ops *ops, void *data)
-{
-       struct stack_frame *frame = (struct stack_frame *)bp;
-
-       while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) {
-               unsigned long addr;
-
-               addr = *stack;
-               if (__kernel_text_address(addr)) {
-                       if ((unsigned long) stack == bp + 4) {
-                               ops->address(data, addr, 1);
-                               frame = frame->next_frame;
-                               bp = (unsigned long) frame;
-                       } else {
-                               ops->address(data, addr, bp == 0);
-                       }
-               }
-               stack++;
-       }
-       return bp;
-}
-
-void dump_trace(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp,
-               const struct stacktrace_ops *ops, void *data)
-{
-       if (!task)
-               task = current;
-
-       if (!stack) {
-               unsigned long dummy;
-               stack = &dummy;
-               if (task != current)
-                       stack = (unsigned long *)task->thread.sp;
-       }
-
-#ifdef CONFIG_FRAME_POINTER
-       if (!bp) {
-               if (task == current) {
-                       /* Grab bp right from our regs */
-                       asm("movl %%ebp, %0" : "=r" (bp) :);
-               } else {
-                       /* bp is the last reg pushed by switch_to */
-                       bp = *(unsigned long *) task->thread.sp;
-               }
-       }
-#endif
-
-       for (;;) {
-               struct thread_info *context;
-
-               context = (struct thread_info *)
-                       ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-               bp = print_context_stack(context, stack, bp, ops, data);
-               /*
-                * Should be after the line below, but somewhere
-                * in early boot context comes out corrupted and we
-                * can't reference it:
-                */
-               if (ops->stack(data, "IRQ") < 0)
-                       break;
-               stack = (unsigned long *)context->previous_esp;
-               if (!stack)
-                       break;
-               touch_nmi_watchdog();
-       }
-}
-EXPORT_SYMBOL(dump_trace);
-
-static void
-print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
-{
-       printk(data);
-       print_symbol(msg, symbol);
-       printk("\n");
-}
-
-static void print_trace_warning(void *data, char *msg)
-{
-       printk("%s%s\n", (char *)data, msg);
-}
-
-static int print_trace_stack(void *data, char *name)
-{
-       return 0;
-}
-
-/*
- * Print one address/symbol entries per line.
- */
-static void print_trace_address(void *data, unsigned long addr, int reliable)
-{
-       printk("%s [<%08lx>] ", (char *)data, addr);
-       if (!reliable)
-               printk("? ");
-       print_symbol("%s\n", addr);
-       touch_nmi_watchdog();
-}
-
-static const struct stacktrace_ops print_trace_ops = {
-       .warning = print_trace_warning,
-       .warning_symbol = print_trace_warning_symbol,
-       .stack = print_trace_stack,
-       .address = print_trace_address,
-};
-
-static void
-show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp, char *log_lvl)
-{
-       dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
-       printk("%s =======================\n", log_lvl);
-}
-
-void show_trace(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp)
-{
-       show_trace_log_lvl(task, regs, stack, bp, "");
-}
-
-static void
-show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-                  unsigned long *sp, unsigned long bp, char *log_lvl)
-{
-       unsigned long *stack;
-       int i;
-
-       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 % 8) == 0))
-                       printk("\n%s       ", log_lvl);
-               printk("%08lx ", *stack++);
-       }
-       printk("\n%sCall Trace:\n", log_lvl);
-
-       show_trace_log_lvl(task, regs, sp, bp, log_lvl);
-}
-
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
-       printk("       ");
-       show_stack_log_lvl(task, NULL, sp, 0, "");
-}
-
-/*
- * The architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
-       unsigned long bp = 0;
-       unsigned long stack;
-
-#ifdef CONFIG_FRAME_POINTER
-       if (!bp)
-               asm("movl %%ebp, %0" : "=r" (bp):);
-#endif
-
-       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
-               current->pid, current->comm, print_tainted(),
-               init_utsname()->release,
-               (int)strcspn(init_utsname()->version, " "),
-               init_utsname()->version);
-
-       show_trace(current, NULL, &stack, bp);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
-void show_registers(struct pt_regs *regs)
-{
-       int i;
-
-       print_modules();
-       __show_registers(regs, 0);
-
-       printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
-               TASK_COMM_LEN, current->comm, task_pid_nr(current),
-               current_thread_info(), current, task_thread_info(current));
-       /*
-        * When in-kernel, we also print out the stack and code at the
-        * time of the fault..
-        */
-       if (!user_mode_vm(regs)) {
-               unsigned int code_prologue = code_bytes * 43 / 64;
-               unsigned int code_len = code_bytes;
-               unsigned char c;
-               u8 *ip;
-
-               printk("\n" KERN_EMERG "Stack: ");
-               show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
-
-               printk(KERN_EMERG "Code: ");
-
-               ip = (u8 *)regs->ip - code_prologue;
-               if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
-                       /* try starting at EIP */
-                       ip = (u8 *)regs->ip;
-                       code_len = code_len - code_prologue + 1;
-               }
-               for (i = 0; i < code_len; i++, ip++) {
-                       if (ip < (u8 *)PAGE_OFFSET ||
-                                       probe_kernel_address(ip, c)) {
-                               printk(" Bad EIP value.");
-                               break;
-                       }
-                       if (ip == (u8 *)regs->ip)
-                               printk("<%02x> ", c);
-                       else
-                               printk("%02x ", c);
-               }
-       }
-       printk("\n");
-}
-
-int is_valid_bugaddr(unsigned long ip)
-{
-       unsigned short ud2;
-
-       if (ip < PAGE_OFFSET)
-               return 0;
-       if (probe_kernel_address((unsigned short *)ip, ud2))
-               return 0;
-
-       return ud2 == 0x0b0f;
-}
-
-static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
-static int die_owner = -1;
-static unsigned int die_nest_count;
-
-unsigned __kprobes long oops_begin(void)
-{
-       unsigned long flags;
-
-       oops_enter();
-
-       if (die_owner != raw_smp_processor_id()) {
-               console_verbose();
-               raw_local_irq_save(flags);
-               __raw_spin_lock(&die_lock);
-               die_owner = smp_processor_id();
-               die_nest_count = 0;
-               bust_spinlocks(1);
-       } else {
-               raw_local_irq_save(flags);
-       }
-       die_nest_count++;
-       return flags;
-}
-
-void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
-{
-       bust_spinlocks(0);
-       die_owner = -1;
-       add_taint(TAINT_DIE);
-       __raw_spin_unlock(&die_lock);
-       raw_local_irq_restore(flags);
-
-       if (!regs)
-               return;
-
-       if (kexec_should_crash(current))
-               crash_kexec(regs);
-
-       if (in_interrupt())
-               panic("Fatal exception in interrupt");
-
-       if (panic_on_oops)
-               panic("Fatal exception");
-
-       oops_exit();
-       do_exit(signr);
-}
-
-int __kprobes __die(const char *str, struct pt_regs *regs, long err)
-{
-       unsigned short ss;
-       unsigned long sp;
-
-       printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
-       printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
-       printk("SMP ");
-#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk("DEBUG_PAGEALLOC");
-#endif
-       printk("\n");
-       if (notify_die(DIE_OOPS, str, regs, err,
-                       current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
-               return 1;
-
-       show_registers(regs);
-       /* Executive summary in case the oops scrolled away */
-       sp = (unsigned long) (&regs->sp);
-       savesegment(ss, ss);
-       if (user_mode(regs)) {
-               sp = regs->sp;
-               ss = regs->ss & 0xffff;
-       }
-       printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
-       print_symbol("%s", regs->ip);
-       printk(" SS:ESP %04x:%08lx\n", ss, sp);
-       return 0;
-}
-
-/*
- * This is gone through when something in the kernel has done something bad
- * and is about to be terminated:
- */
-void die(const char *str, struct pt_regs *regs, long err)
-{
-       unsigned long flags = oops_begin();
-
-       if (die_nest_count < 3) {
-               report_bug(regs->ip, regs);
-
-               if (__die(str, regs, err))
-                       regs = NULL;
-       } else {
-               printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
-       }
-
-       oops_end(flags, regs, SIGSEGV);
-}
-
-static inline void
-die_if_kernel(const char *str, struct pt_regs *regs, long err)
-{
-       if (!user_mode_vm(regs))
-               die(str, regs, err);
-}
-
-static void __kprobes
-do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
-       long error_code, siginfo_t *info)
-{
-       struct task_struct *tsk = current;
-
-       if (regs->flags & X86_VM_MASK) {
-               if (vm86)
-                       goto vm86_trap;
-               goto trap_signal;
-       }
-
-       if (!user_mode(regs))
-               goto kernel_trap;
-
-trap_signal:
-       /*
-        * We want error_code and trap_no set for userspace faults and
-        * kernelspace faults which result in die(), but not
-        * kernelspace faults which are fixed up.  die() gives the
-        * process no chance to handle the signal and notice the
-        * kernel fault information, so that won't result in polluting
-        * the information about previously queued, but not yet
-        * delivered, faults.  See also do_general_protection below.
-        */
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
-
-       if (info)
-               force_sig_info(signr, info, tsk);
-       else
-               force_sig(signr, tsk);
-       return;
-
-kernel_trap:
-       if (!fixup_exception(regs)) {
-               tsk->thread.error_code = error_code;
-               tsk->thread.trap_no = trapnr;
-               die(str, regs, error_code);
-       }
-       return;
-
-vm86_trap:
-       if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
-                                               error_code, trapnr))
-               goto trap_signal;
-       return;
-}
-
-#define DO_ERROR(trapnr, signr, str, name)                             \
-void do_##name(struct pt_regs *regs, long error_code)                  \
-{                                                                      \
-       trace_hardirqs_fixup();                                         \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       do_trap(trapnr, signr, str, 0, regs, error_code, NULL);         \
-}
-
-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq)   \
-void do_##name(struct pt_regs *regs, long error_code)                  \
-{                                                                      \
-       siginfo_t info;                                                 \
-       if (irq)                                                        \
-               local_irq_enable();                                     \
-       info.si_signo = signr;                                          \
-       info.si_errno = 0;                                              \
-       info.si_code = sicode;                                          \
-       info.si_addr = (void __user *)siaddr;                           \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       do_trap(trapnr, signr, str, 0, regs, error_code, &info);        \
-}
-
-#define DO_VM86_ERROR(trapnr, signr, str, name)                                \
-void do_##name(struct pt_regs *regs, long error_code)                  \
-{                                                                      \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       do_trap(trapnr, signr, str, 1, regs, error_code, NULL);         \
-}
-
-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)   \
-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;                           \
-       trace_hardirqs_fixup();                                         \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       do_trap(trapnr, signr, str, 1, regs, error_code, &info);        \
-}
-
-DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
-#ifndef CONFIG_KPROBES
-DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
-#endif
-DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
-DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
-DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
-DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
-DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
-DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
-
-void __kprobes
-do_general_protection(struct pt_regs *regs, long error_code)
-{
-       struct task_struct *tsk;
-       struct thread_struct *thread;
-       struct tss_struct *tss;
-       int cpu;
-
-       cpu = get_cpu();
-       tss = &per_cpu(init_tss, cpu);
-       thread = &current->thread;
-
-       /*
-        * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
-        * invalid offset set (the LAZY one) and the faulting thread has
-        * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS
-        * and we set the offset field correctly. Then we let the CPU to
-        * restart the faulting instruction.
-        */
-       if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
-           thread->io_bitmap_ptr) {
-               memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
-                      thread->io_bitmap_max);
-               /*
-                * If the previously set map was extending to higher ports
-                * than the current one, pad extra space with 0xff (no access).
-                */
-               if (thread->io_bitmap_max < tss->io_bitmap_max) {
-                       memset((char *) tss->io_bitmap +
-                               thread->io_bitmap_max, 0xff,
-                               tss->io_bitmap_max - thread->io_bitmap_max);
-               }
-               tss->io_bitmap_max = thread->io_bitmap_max;
-               tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
-               tss->io_bitmap_owner = thread;
-               put_cpu();
-
-               return;
-       }
-       put_cpu();
-
-       if (regs->flags & X86_VM_MASK)
-               goto gp_in_vm86;
-
-       tsk = current;
-       if (!user_mode(regs))
-               goto gp_in_kernel;
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-
-       if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-                       printk_ratelimit()) {
-               printk(KERN_INFO
-                       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
-                       tsk->comm, task_pid_nr(tsk),
-                       regs->ip, regs->sp, error_code);
-               print_vma_addr(" in ", regs->ip);
-               printk("\n");
-       }
-
-       force_sig(SIGSEGV, tsk);
-       return;
-
-gp_in_vm86:
-       local_irq_enable();
-       handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
-       return;
-
-gp_in_kernel:
-       if (fixup_exception(regs))
-               return;
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-       if (notify_die(DIE_GPF, "general protection fault", regs,
-                               error_code, 13, SIGSEGV) == NOTIFY_STOP)
-               return;
-       die("general protection fault", regs, error_code);
-}
-
-static notrace __kprobes void
-mem_parity_error(unsigned char reason, struct pt_regs *regs)
-{
-       printk(KERN_EMERG
-               "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-                       reason, smp_processor_id());
-
-       printk(KERN_EMERG
-               "You have some hardware problem, likely on the PCI bus.\n");
-
-#if defined(CONFIG_EDAC)
-       if (edac_handler_set()) {
-               edac_atomic_assert_error();
-               return;
-       }
-#endif
-
-       if (panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
-
-       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
-
-       /* Clear and disable the memory parity error line. */
-       clear_mem_error(reason);
-}
-
-static notrace __kprobes void
-io_check_error(unsigned char reason, struct pt_regs *regs)
-{
-       unsigned long i;
-
-       printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
-       show_registers(regs);
-
-       /* Re-enable the IOCK line, wait for a few seconds */
-       reason = (reason & 0xf) | 8;
-       outb(reason, 0x61);
-
-       i = 2000;
-       while (--i)
-               udelay(1000);
-
-       reason &= ~8;
-       outb(reason, 0x61);
-}
-
-static notrace __kprobes void
-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
-{
-       if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
-               return;
-#ifdef CONFIG_MCA
-       /*
-        * Might actually be able to figure out what the guilty party
-        * is:
-        */
-       if (MCA_bus) {
-               mca_handle_nmi();
-               return;
-       }
-#endif
-       printk(KERN_EMERG
-               "Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-                       reason, smp_processor_id());
-
-       printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
-       if (panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
-
-       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
-}
-
-static DEFINE_SPINLOCK(nmi_print_lock);
-
-void notrace __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
-{
-       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
-               return;
-
-       spin_lock(&nmi_print_lock);
-       /*
-       * We are in trouble anyway, lets at least try
-       * to get a message out:
-       */
-       bust_spinlocks(1);
-       printk(KERN_EMERG "%s", str);
-       printk(" on CPU%d, ip %08lx, registers:\n",
-               smp_processor_id(), regs->ip);
-       show_registers(regs);
-       if (do_panic)
-               panic("Non maskable interrupt");
-       console_silent();
-       spin_unlock(&nmi_print_lock);
-       bust_spinlocks(0);
-
-       /*
-        * If we are in kernel we are probably nested up pretty bad
-        * and might aswell get out now while we still can:
-        */
-       if (!user_mode_vm(regs)) {
-               current->thread.trap_no = 2;
-               crash_kexec(regs);
-       }
-
-       do_exit(SIGSEGV);
-}
-
-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
-{
-       unsigned char reason = 0;
-       int cpu;
-
-       cpu = smp_processor_id();
-
-       /* Only the BSP gets external NMIs from the system. */
-       if (!cpu)
-               reason = get_nmi_reason();
-
-       if (!(reason & 0xc0)) {
-               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
-                                                               == NOTIFY_STOP)
-                       return;
-#ifdef CONFIG_X86_LOCAL_APIC
-               /*
-                * Ok, so this is none of the documented NMI sources,
-                * so it must be the NMI watchdog.
-                */
-               if (nmi_watchdog_tick(regs, reason))
-                       return;
-               if (!do_nmi_callback(regs, cpu))
-                       unknown_nmi_error(reason, regs);
-#else
-               unknown_nmi_error(reason, regs);
-#endif
-
-               return;
-       }
-       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
-               return;
-
-       /* AK: following checks seem to be broken on modern chipsets. FIXME */
-       if (reason & 0x80)
-               mem_parity_error(reason, regs);
-       if (reason & 0x40)
-               io_check_error(reason, regs);
-       /*
-        * Reassert NMI in case it became active meanwhile
-        * as it's edge-triggered:
-        */
-       reassert_nmi();
-}
-
-notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
-{
-       int cpu;
-
-       nmi_enter();
-
-       cpu = smp_processor_id();
-
-       ++nmi_count(cpu);
-
-       if (!ignore_nmis)
-               default_do_nmi(regs);
-
-       nmi_exit();
-}
-
-void stop_nmi(void)
-{
-       acpi_nmi_disable();
-       ignore_nmis++;
-}
-
-void restart_nmi(void)
-{
-       ignore_nmis--;
-       acpi_nmi_enable();
-}
-
-#ifdef CONFIG_KPROBES
-void __kprobes do_int3(struct pt_regs *regs, long error_code)
-{
-       trace_hardirqs_fixup();
-
-       if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-                       == NOTIFY_STOP)
-               return;
-       /*
-        * This is an interrupt gate, because kprobes wants interrupts
-        * disabled. Normal trap handlers don't.
-        */
-       restore_interrupts(regs);
-
-       do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
-}
-#endif
-
-/*
- * Our handling of the processor debug registers is non-trivial.
- * We do not clear them on entry and exit from the kernel. Therefore
- * it is possible to get a watchpoint trap here from inside the kernel.
- * However, the code in ./ptrace.c has ensured that the user can
- * only set watchpoints on userspace addresses. Therefore the in-kernel
- * watchpoint trap can only occur in code which is reading/writing
- * from user space. Such code must not hold kernel locks (since it
- * can equally take a page fault), therefore it is safe to call
- * force_sig_info even though that claims and releases locks.
- *
- * Code in ./signal.c ensures that the debug control register
- * is restored before we deliver any signal, and therefore that
- * user code runs with the correct debug control register even though
- * we clear it here.
- *
- * Being careful here means that we don't have to be as careful in a
- * lot of more complicated places (task switching can be a bit lazy
- * about restoring all the debug state, and ptrace doesn't have to
- * find every occurrence of the TF bit that could be saved away even
- * by user code)
- */
-void __kprobes do_debug(struct pt_regs *regs, long error_code)
-{
-       struct task_struct *tsk = current;
-       unsigned int condition;
-       int si_code;
-
-       trace_hardirqs_fixup();
-
-       get_debugreg(condition, 6);
-
-       /*
-        * The processor cleared BTF, so don't mark that we need it set.
-        */
-       clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
-       tsk->thread.debugctlmsr = 0;
-
-       if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
-                                               SIGTRAP) == NOTIFY_STOP)
-               return;
-       /* It's safe to allow irq's after DR6 has been saved */
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_enable();
-
-       /* Mask out spurious debug traps due to lazy DR7 setting */
-       if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
-               if (!tsk->thread.debugreg7)
-                       goto clear_dr7;
-       }
-
-       if (regs->flags & X86_VM_MASK)
-               goto debug_vm86;
-
-       /* Save debug status register where ptrace can see it */
-       tsk->thread.debugreg6 = condition;
-
-       /*
-        * Single-stepping through TF: make sure we ignore any events in
-        * kernel space (but re-enable TF when returning to user mode).
-        */
-       if (condition & DR_STEP) {
-               /*
-                * We already checked v86 mode above, so we can
-                * check for kernel mode by just checking the CPL
-                * of CS.
-                */
-               if (!user_mode(regs))
-                       goto clear_TF_reenable;
-       }
-
-       si_code = get_si_code((unsigned long)condition);
-       /* Ok, finally something we can handle */
-       send_sigtrap(tsk, regs, error_code, si_code);
-
-       /*
-        * Disable additional traps. They'll be re-enabled when
-        * the signal is delivered.
-        */
-clear_dr7:
-       set_debugreg(0, 7);
-       return;
-
-debug_vm86:
-       handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
-       return;
-
-clear_TF_reenable:
-       set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
-       regs->flags &= ~X86_EFLAGS_TF;
-       return;
-}
-
-/*
- * Note that we play around with the 'TS' bit in an attempt to get
- * the correct behaviour even in the presence of the asynchronous
- * IRQ13 behaviour
- */
-void math_error(void __user *ip)
-{
-       struct task_struct *task;
-       siginfo_t info;
-       unsigned short cwd, swd;
-
-       /*
-        * Save the info for the exception handler and clear the error.
-        */
-       task = current;
-       save_init_fpu(task);
-       task->thread.trap_no = 16;
-       task->thread.error_code = 0;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_code = __SI_FAULT;
-       info.si_addr = ip;
-       /*
-        * (~cwd & swd) will mask out exceptions that are not set to unmasked
-        * status.  0x3f is the exception bits in these regs, 0x200 is the
-        * C1 reg you need in case of a stack fault, 0x040 is the stack
-        * fault bit.  We should only be taking one exception at a time,
-        * so if this combination doesn't produce any single exception,
-        * then we have a bad program that isn't synchronizing its FPU usage
-        * and it will suffer the consequences since we won't be able to
-        * fully reproduce the context of the exception
-        */
-       cwd = get_fpu_cwd(task);
-       swd = get_fpu_swd(task);
-       switch (swd & ~cwd & 0x3f) {
-       case 0x000: /* No unmasked exception */
-               return;
-       default: /* Multiple exceptions */
-               break;
-       case 0x001: /* Invalid Op */
-               /*
-                * swd & 0x240 == 0x040: Stack Underflow
-                * swd & 0x240 == 0x240: Stack Overflow
-                * User must clear the SF bit (0x40) if set
-                */
-               info.si_code = FPE_FLTINV;
-               break;
-       case 0x002: /* Denormalize */
-       case 0x010: /* Underflow */
-               info.si_code = FPE_FLTUND;
-               break;
-       case 0x004: /* Zero Divide */
-               info.si_code = FPE_FLTDIV;
-               break;
-       case 0x008: /* Overflow */
-               info.si_code = FPE_FLTOVF;
-               break;
-       case 0x020: /* Precision */
-               info.si_code = FPE_FLTRES;
-               break;
-       }
-       force_sig_info(SIGFPE, &info, task);
-}
-
-void do_coprocessor_error(struct pt_regs *regs, long error_code)
-{
-       ignore_fpu_irq = 1;
-       math_error((void __user *)regs->ip);
-}
-
-static void simd_math_error(void __user *ip)
-{
-       struct task_struct *task;
-       siginfo_t info;
-       unsigned short mxcsr;
-
-       /*
-        * Save the info for the exception handler and clear the error.
-        */
-       task = current;
-       save_init_fpu(task);
-       task->thread.trap_no = 19;
-       task->thread.error_code = 0;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_code = __SI_FAULT;
-       info.si_addr = ip;
-       /*
-        * The SIMD FPU exceptions are handled a little differently, as there
-        * is only a single status/control register.  Thus, to determine which
-        * unmasked exception was caught we must mask the exception mask bits
-        * at 0x1f80, and then use these to mask the exception bits at 0x3f.
-        */
-       mxcsr = get_fpu_mxcsr(task);
-       switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
-       case 0x000:
-       default:
-               break;
-       case 0x001: /* Invalid Op */
-               info.si_code = FPE_FLTINV;
-               break;
-       case 0x002: /* Denormalize */
-       case 0x010: /* Underflow */
-               info.si_code = FPE_FLTUND;
-               break;
-       case 0x004: /* Zero Divide */
-               info.si_code = FPE_FLTDIV;
-               break;
-       case 0x008: /* Overflow */
-               info.si_code = FPE_FLTOVF;
-               break;
-       case 0x020: /* Precision */
-               info.si_code = FPE_FLTRES;
-               break;
-       }
-       force_sig_info(SIGFPE, &info, task);
-}
-
-void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
-{
-       if (cpu_has_xmm) {
-               /* Handle SIMD FPU exceptions on PIII+ processors. */
-               ignore_fpu_irq = 1;
-               simd_math_error((void __user *)regs->ip);
-               return;
-       }
-       /*
-        * Handle strange cache flush from user space exception
-        * in all other cases.  This is undocumented behaviour.
-        */
-       if (regs->flags & X86_VM_MASK) {
-               handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
-               return;
-       }
-       current->thread.trap_no = 19;
-       current->thread.error_code = error_code;
-       die_if_kernel("cache flush denied", regs, error_code);
-       force_sig(SIGSEGV, current);
-}
-
-void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
-{
-#if 0
-       /* No need to warn about this any longer. */
-       printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
-#endif
-}
-
-unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
-{
-       struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
-       unsigned long base = (kesp - uesp) & -THREAD_SIZE;
-       unsigned long new_kesp = kesp - base;
-       unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
-       __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
-
-       /* Set up base for espfix segment */
-       desc &= 0x00f0ff0000000000ULL;
-       desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
-               ((((__u64)base) << 32) & 0xff00000000000000ULL) |
-               ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
-               (lim_pages & 0xffff);
-       *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
-
-       return new_kesp;
-}
-
-/*
- * 'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task
- *
- * Careful.. There are problems with IBM-designed IRQ13 behaviour.
- * Don't touch unless you *really* know how it works.
- *
- * Must be called with kernel preemption disabled (in this case,
- * local interrupts are disabled at the call-site in entry.S).
- */
-asmlinkage void math_state_restore(void)
-{
-       struct thread_info *thread = current_thread_info();
-       struct task_struct *tsk = thread->task;
-
-       if (!tsk_used_math(tsk)) {
-               local_irq_enable();
-               /*
-                * does a slab alloc which can sleep
-                */
-               if (init_fpu(tsk)) {
-                       /*
-                        * ran out of memory!
-                        */
-                       do_group_exit(SIGKILL);
-                       return;
-               }
-               local_irq_disable();
-       }
-
-       clts();                         /* Allow maths ops (or we recurse) */
-       restore_fpu(tsk);
-       thread->status |= TS_USEDFPU;   /* So we fnsave on switch_to() */
-       tsk->fpu_counter++;
-}
-EXPORT_SYMBOL_GPL(math_state_restore);
-
-#ifndef CONFIG_MATH_EMULATION
-
-asmlinkage void math_emulate(long arg)
-{
-       printk(KERN_EMERG
-               "math-emulation not enabled and no coprocessor found.\n");
-       printk(KERN_EMERG "killing %s.\n", current->comm);
-       force_sig(SIGFPE, current);
-       schedule();
-}
-
-#endif /* CONFIG_MATH_EMULATION */
-
-void __init trap_init(void)
-{
-       int i;
-
-#ifdef CONFIG_EISA
-       void __iomem *p = early_ioremap(0x0FFFD9, 4);
-
-       if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
-               EISA_bus = 1;
-       early_iounmap(p, 4);
-#endif
-
-       set_trap_gate(0, &divide_error);
-       set_intr_gate(1, &debug);
-       set_intr_gate(2, &nmi);
-       set_system_intr_gate(3, &int3); /* int3 can be called from all */
-       set_system_gate(4, &overflow); /* int4 can be called from all */
-       set_trap_gate(5, &bounds);
-       set_trap_gate(6, &invalid_op);
-       set_trap_gate(7, &device_not_available);
-       set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS);
-       set_trap_gate(9, &coprocessor_segment_overrun);
-       set_trap_gate(10, &invalid_TSS);
-       set_trap_gate(11, &segment_not_present);
-       set_trap_gate(12, &stack_segment);
-       set_trap_gate(13, &general_protection);
-       set_intr_gate(14, &page_fault);
-       set_trap_gate(15, &spurious_interrupt_bug);
-       set_trap_gate(16, &coprocessor_error);
-       set_trap_gate(17, &alignment_check);
-#ifdef CONFIG_X86_MCE
-       set_trap_gate(18, &machine_check);
-#endif
-       set_trap_gate(19, &simd_coprocessor_error);
-
-       if (cpu_has_fxsr) {
-               printk(KERN_INFO "Enabling fast FPU save and restore... ");
-               set_in_cr4(X86_CR4_OSFXSR);
-               printk("done.\n");
-       }
-       if (cpu_has_xmm) {
-               printk(KERN_INFO
-                       "Enabling unmasked SIMD FPU exception support... ");
-               set_in_cr4(X86_CR4_OSXMMEXCPT);
-               printk("done.\n");
-       }
-
-       set_system_gate(SYSCALL_VECTOR, &system_call);
-
-       /* Reserve all the builtin and the syscall vector: */
-       for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
-               set_bit(i, used_vectors);
-
-       set_bit(SYSCALL_VECTOR, used_vectors);
-
-       /*
-        * Should be a barrier for any external CPU state:
-        */
-       cpu_init();
-
-       trap_init_hook();
-}
-
-static int __init kstack_setup(char *s)
-{
-       kstack_depth_to_print = simple_strtoul(s, NULL, 0);
-
-       return 1;
-}
-__setup("kstack=", kstack_setup);
-
-static int __init code_bytes_setup(char *s)
-{
-       code_bytes = simple_strtoul(s, NULL, 0);
-       if (code_bytes > 8192)
-               code_bytes = 8192;
-
-       return 1;
-}
-__setup("code_bytes=", code_bytes_setup);
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
deleted file mode 100644 (file)
index 9c0ac0c..0000000
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
- *
- *  Pentium III FXSR, SSE support
- *     Gareth Hughes <gareth@valinux.com>, May 2000
- */
-
-/*
- * 'Traps.c' handles hardware traps and faults after we have saved some
- * state in 'entry.S'.
- */
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/kallsyms.h>
-#include <linux/spinlock.h>
-#include <linux/kprobes.h>
-#include <linux/uaccess.h>
-#include <linux/utsname.h>
-#include <linux/kdebug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/unwind.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/kexec.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/bug.h>
-#include <linux/nmi.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#if defined(CONFIG_EDAC)
-#include <linux/edac.h>
-#endif
-
-#include <asm/stacktrace.h>
-#include <asm/processor.h>
-#include <asm/debugreg.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-#include <asm/unwind.h>
-#include <asm/desc.h>
-#include <asm/i387.h>
-#include <asm/pgalloc.h>
-#include <asm/proto.h>
-#include <asm/pda.h>
-#include <asm/traps.h>
-
-#include <mach_traps.h>
-
-int panic_on_unrecovered_nmi;
-int kstack_depth_to_print = 12;
-static unsigned int code_bytes = 64;
-static int ignore_nmis;
-static int die_counter;
-
-static inline void conditional_sti(struct pt_regs *regs)
-{
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_enable();
-}
-
-static inline void preempt_conditional_sti(struct pt_regs *regs)
-{
-       inc_preempt_count();
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_enable();
-}
-
-static inline void preempt_conditional_cli(struct pt_regs *regs)
-{
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_disable();
-       /* Make sure to not schedule here because we could be running
-          on an exception stack. */
-       dec_preempt_count();
-}
-
-void printk_address(unsigned long address, int reliable)
-{
-       printk(" [<%016lx>] %s%pS\n",
-                       address, reliable ?     "" : "? ", (void *) address);
-}
-
-static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
-                                       unsigned *usedp, char **idp)
-{
-       static char ids[][8] = {
-               [DEBUG_STACK - 1] = "#DB",
-               [NMI_STACK - 1] = "NMI",
-               [DOUBLEFAULT_STACK - 1] = "#DF",
-               [STACKFAULT_STACK - 1] = "#SS",
-               [MCE_STACK - 1] = "#MC",
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-               [N_EXCEPTION_STACKS ...
-                       N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
-#endif
-       };
-       unsigned k;
-
-       /*
-        * Iterate over all exception stacks, and figure out whether
-        * 'stack' is in one of them:
-        */
-       for (k = 0; k < N_EXCEPTION_STACKS; k++) {
-               unsigned long end = per_cpu(orig_ist, cpu).ist[k];
-               /*
-                * Is 'stack' above this exception frame's end?
-                * If yes then skip to the next frame.
-                */
-               if (stack >= end)
-                       continue;
-               /*
-                * Is 'stack' above this exception frame's start address?
-                * If yes then we found the right frame.
-                */
-               if (stack >= end - EXCEPTION_STKSZ) {
-                       /*
-                        * Make sure we only iterate through an exception
-                        * stack once. If it comes up for the second time
-                        * then there's something wrong going on - just
-                        * break out and return NULL:
-                        */
-                       if (*usedp & (1U << k))
-                               break;
-                       *usedp |= 1U << k;
-                       *idp = ids[k];
-                       return (unsigned long *)end;
-               }
-               /*
-                * If this is a debug stack, and if it has a larger size than
-                * the usual exception stacks, then 'stack' might still
-                * be within the lower portion of the debug stack:
-                */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-               if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
-                       unsigned j = N_EXCEPTION_STACKS - 1;
-
-                       /*
-                        * Black magic. A large debug stack is composed of
-                        * multiple exception stack entries, which we
-                        * iterate through now. Dont look:
-                        */
-                       do {
-                               ++j;
-                               end -= EXCEPTION_STKSZ;
-                               ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
-                       } while (stack < end - EXCEPTION_STKSZ);
-                       if (*usedp & (1U << j))
-                               break;
-                       *usedp |= 1U << j;
-                       *idp = ids[j];
-                       return (unsigned long *)end;
-               }
-#endif
-       }
-       return NULL;
-}
-
-/*
- * x86-64 can have up to three kernel stacks:
- * process stack
- * interrupt stack
- * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
- */
-
-static inline int valid_stack_ptr(struct thread_info *tinfo,
-                       void *p, unsigned int size, void *end)
-{
-       void *t = tinfo;
-       if (end) {
-               if (p < end && p >= (end-THREAD_SIZE))
-                       return 1;
-               else
-                       return 0;
-       }
-       return p > t && p < t + THREAD_SIZE - size;
-}
-
-/* The form of the top of the frame on the stack */
-struct stack_frame {
-       struct stack_frame *next_frame;
-       unsigned long return_address;
-};
-
-static inline unsigned long
-print_context_stack(struct thread_info *tinfo,
-               unsigned long *stack, unsigned long bp,
-               const struct stacktrace_ops *ops, void *data,
-               unsigned long *end)
-{
-       struct stack_frame *frame = (struct stack_frame *)bp;
-
-       while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
-               unsigned long addr;
-
-               addr = *stack;
-               if (__kernel_text_address(addr)) {
-                       if ((unsigned long) stack == bp + 8) {
-                               ops->address(data, addr, 1);
-                               frame = frame->next_frame;
-                               bp = (unsigned long) frame;
-                       } else {
-                               ops->address(data, addr, bp == 0);
-                       }
-               }
-               stack++;
-       }
-       return bp;
-}
-
-void dump_trace(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp,
-               const struct stacktrace_ops *ops, void *data)
-{
-       const unsigned cpu = get_cpu();
-       unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
-       unsigned used = 0;
-       struct thread_info *tinfo;
-
-       if (!task)
-               task = current;
-
-       if (!stack) {
-               unsigned long dummy;
-               stack = &dummy;
-               if (task && task != current)
-                       stack = (unsigned long *)task->thread.sp;
-       }
-
-#ifdef CONFIG_FRAME_POINTER
-       if (!bp) {
-               if (task == current) {
-                       /* Grab bp right from our regs */
-                       asm("movq %%rbp, %0" : "=r" (bp) : );
-               } else {
-                       /* bp is the last reg pushed by switch_to */
-                       bp = *(unsigned long *) task->thread.sp;
-               }
-       }
-#endif
-
-       /*
-        * Print function call entries in all stacks, starting at the
-        * current stack address. If the stacks consist of nested
-        * exceptions
-        */
-       tinfo = task_thread_info(task);
-       for (;;) {
-               char *id;
-               unsigned long *estack_end;
-               estack_end = in_exception_stack(cpu, (unsigned long)stack,
-                                               &used, &id);
-
-               if (estack_end) {
-                       if (ops->stack(data, id) < 0)
-                               break;
-
-                       bp = print_context_stack(tinfo, stack, bp, ops,
-                                                       data, estack_end);
-                       ops->stack(data, "<EOE>");
-                       /*
-                        * We link to the next stack via the
-                        * second-to-last pointer (index -2 to end) in the
-                        * exception stack:
-                        */
-                       stack = (unsigned long *) estack_end[-2];
-                       continue;
-               }
-               if (irqstack_end) {
-                       unsigned long *irqstack;
-                       irqstack = irqstack_end -
-                               (IRQSTACKSIZE - 64) / sizeof(*irqstack);
-
-                       if (stack >= irqstack && stack < irqstack_end) {
-                               if (ops->stack(data, "IRQ") < 0)
-                                       break;
-                               bp = print_context_stack(tinfo, stack, bp,
-                                               ops, data, irqstack_end);
-                               /*
-                                * We link to the next stack (which would be
-                                * the process stack normally) the last
-                                * pointer (index -1 to end) in the IRQ stack:
-                                */
-                               stack = (unsigned long *) (irqstack_end[-1]);
-                               irqstack_end = NULL;
-                               ops->stack(data, "EOI");
-                               continue;
-                       }
-               }
-               break;
-       }
-
-       /*
-        * This handles the process stack:
-        */
-       bp = print_context_stack(tinfo, stack, bp, ops, data, NULL);
-       put_cpu();
-}
-EXPORT_SYMBOL(dump_trace);
-
-static void
-print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
-{
-       print_symbol(msg, symbol);
-       printk("\n");
-}
-
-static void print_trace_warning(void *data, char *msg)
-{
-       printk("%s\n", msg);
-}
-
-static int print_trace_stack(void *data, char *name)
-{
-       printk(" <%s> ", name);
-       return 0;
-}
-
-static void print_trace_address(void *data, unsigned long addr, int reliable)
-{
-       touch_nmi_watchdog();
-       printk_address(addr, reliable);
-}
-
-static const struct stacktrace_ops print_trace_ops = {
-       .warning = print_trace_warning,
-       .warning_symbol = print_trace_warning_symbol,
-       .stack = print_trace_stack,
-       .address = print_trace_address,
-};
-
-static void
-show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp, char *log_lvl)
-{
-       printk("Call Trace:\n");
-       dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
-}
-
-void show_trace(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *stack, unsigned long bp)
-{
-       show_trace_log_lvl(task, regs, stack, bp, "");
-}
-
-static void
-show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-               unsigned long *sp, unsigned long bp, char *log_lvl)
-{
-       unsigned long *stack;
-       int i;
-       const int cpu = smp_processor_id();
-       unsigned long *irqstack_end =
-               (unsigned long *) (cpu_pda(cpu)->irqstackptr);
-       unsigned long *irqstack =
-               (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
-
-       /*
-        * debugging aid: "show_stack(NULL, 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 (stack >= irqstack && stack <= irqstack_end) {
-                       if (stack == irqstack_end) {
-                               stack = (unsigned long *) (irqstack_end[-1]);
-                               printk(" <EOI> ");
-                       }
-               } else {
-               if (((long) stack & (THREAD_SIZE-1)) == 0)
-                       break;
-               }
-               if (i && ((i % 4) == 0))
-                       printk("\n");
-               printk(" %016lx", *stack++);
-               touch_nmi_watchdog();
-       }
-       printk("\n");
-       show_trace_log_lvl(task, regs, sp, bp, log_lvl);
-}
-
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
-       show_stack_log_lvl(task, NULL, sp, 0, "");
-}
-
-/*
- * The architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
-       unsigned long bp = 0;
-       unsigned long stack;
-
-#ifdef CONFIG_FRAME_POINTER
-       if (!bp)
-               asm("movq %%rbp, %0" : "=r" (bp) : );
-#endif
-
-       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
-               current->pid, current->comm, print_tainted(),
-               init_utsname()->release,
-               (int)strcspn(init_utsname()->version, " "),
-               init_utsname()->version);
-       show_trace(NULL, NULL, &stack, bp);
-}
-EXPORT_SYMBOL(dump_stack);
-
-void show_registers(struct pt_regs *regs)
-{
-       int i;
-       unsigned long sp;
-       const int cpu = smp_processor_id();
-       struct task_struct *cur = cpu_pda(cpu)->pcurrent;
-
-       sp = regs->sp;
-       printk("CPU %d ", cpu);
-       __show_regs(regs);
-       printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
-               cur->comm, cur->pid, task_thread_info(cur), cur);
-
-       /*
-        * When in-kernel, we also print out the stack and code at the
-        * time of the fault..
-        */
-       if (!user_mode(regs)) {
-               unsigned int code_prologue = code_bytes * 43 / 64;
-               unsigned int code_len = code_bytes;
-               unsigned char c;
-               u8 *ip;
-
-               printk("Stack: ");
-               show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-                               regs->bp, "");
-
-               printk(KERN_EMERG "Code: ");
-
-               ip = (u8 *)regs->ip - code_prologue;
-               if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
-                       /* try starting at RIP */
-                       ip = (u8 *)regs->ip;
-                       code_len = code_len - code_prologue + 1;
-               }
-               for (i = 0; i < code_len; i++, ip++) {
-                       if (ip < (u8 *)PAGE_OFFSET ||
-                                       probe_kernel_address(ip, c)) {
-                               printk(" Bad RIP value.");
-                               break;
-                       }
-                       if (ip == (u8 *)regs->ip)
-                               printk("<%02x> ", c);
-                       else
-                               printk("%02x ", c);
-               }
-       }
-       printk("\n");
-}
-
-int is_valid_bugaddr(unsigned long ip)
-{
-       unsigned short ud2;
-
-       if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
-               return 0;
-
-       return ud2 == 0x0b0f;
-}
-
-static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
-static int die_owner = -1;
-static unsigned int die_nest_count;
-
-unsigned __kprobes long oops_begin(void)
-{
-       int cpu;
-       unsigned long flags;
-
-       oops_enter();
-
-       /* racy, but better than risking deadlock. */
-       raw_local_irq_save(flags);
-       cpu = smp_processor_id();
-       if (!__raw_spin_trylock(&die_lock)) {
-               if (cpu == die_owner)
-                       /* nested oops. should stop eventually */;
-               else
-                       __raw_spin_lock(&die_lock);
-       }
-       die_nest_count++;
-       die_owner = cpu;
-       console_verbose();
-       bust_spinlocks(1);
-       return flags;
-}
-
-void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
-{
-       die_owner = -1;
-       bust_spinlocks(0);
-       die_nest_count--;
-       if (!die_nest_count)
-               /* Nest count reaches zero, release the lock. */
-               __raw_spin_unlock(&die_lock);
-       raw_local_irq_restore(flags);
-       if (!regs) {
-               oops_exit();
-               return;
-       }
-       if (panic_on_oops)
-               panic("Fatal exception");
-       oops_exit();
-       do_exit(signr);
-}
-
-int __kprobes __die(const char *str, struct pt_regs *regs, long err)
-{
-       printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
-       printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
-       printk("SMP ");
-#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk("DEBUG_PAGEALLOC");
-#endif
-       printk("\n");
-       if (notify_die(DIE_OOPS, str, regs, err,
-                       current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
-               return 1;
-
-       show_registers(regs);
-       add_taint(TAINT_DIE);
-       /* Executive summary in case the oops scrolled away */
-       printk(KERN_ALERT "RIP ");
-       printk_address(regs->ip, 1);
-       printk(" RSP <%016lx>\n", regs->sp);
-       if (kexec_should_crash(current))
-               crash_kexec(regs);
-       return 0;
-}
-
-void die(const char *str, struct pt_regs *regs, long err)
-{
-       unsigned long flags = oops_begin();
-
-       if (!user_mode(regs))
-               report_bug(regs->ip, regs);
-
-       if (__die(str, regs, err))
-               regs = NULL;
-       oops_end(flags, regs, SIGSEGV);
-}
-
-notrace __kprobes void
-die_nmi(char *str, struct pt_regs *regs, int do_panic)
-{
-       unsigned long flags;
-
-       if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
-               return;
-
-       flags = oops_begin();
-       /*
-        * We are in trouble anyway, lets at least try
-        * to get a message out.
-        */
-       printk(KERN_EMERG "%s", str);
-       printk(" on CPU%d, ip %08lx, registers:\n",
-               smp_processor_id(), regs->ip);
-       show_registers(regs);
-       if (kexec_should_crash(current))
-               crash_kexec(regs);
-       if (do_panic || panic_on_oops)
-               panic("Non maskable interrupt");
-       oops_end(flags, NULL, SIGBUS);
-       nmi_exit();
-       local_irq_enable();
-       do_exit(SIGBUS);
-}
-
-static void __kprobes
-do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
-       long error_code, siginfo_t *info)
-{
-       struct task_struct *tsk = current;
-
-       if (!user_mode(regs))
-               goto kernel_trap;
-
-       /*
-        * We want error_code and trap_no set for userspace faults and
-        * kernelspace faults which result in die(), but not
-        * kernelspace faults which are fixed up.  die() gives the
-        * process no chance to handle the signal and notice the
-        * kernel fault information, so that won't result in polluting
-        * the information about previously queued, but not yet
-        * delivered, faults.  See also do_general_protection below.
-        */
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = trapnr;
-
-       if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
-           printk_ratelimit()) {
-               printk(KERN_INFO
-                      "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
-                      tsk->comm, tsk->pid, str,
-                      regs->ip, regs->sp, error_code);
-               print_vma_addr(" in ", regs->ip);
-               printk("\n");
-       }
-
-       if (info)
-               force_sig_info(signr, info, tsk);
-       else
-               force_sig(signr, tsk);
-       return;
-
-kernel_trap:
-       if (!fixup_exception(regs)) {
-               tsk->thread.error_code = error_code;
-               tsk->thread.trap_no = trapnr;
-               die(str, regs, error_code);
-       }
-       return;
-}
-
-#define DO_ERROR(trapnr, signr, str, name) \
-asmlinkage void do_##name(struct pt_regs *regs, long error_code)       \
-{                                                                      \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       conditional_sti(regs);                                          \
-       do_trap(trapnr, signr, str, 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;                           \
-       trace_hardirqs_fixup();                                         \
-       if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)  \
-                                                       == NOTIFY_STOP) \
-               return;                                                 \
-       conditional_sti(regs);                                          \
-       do_trap(trapnr, signr, str, regs, error_code, &info);           \
-}
-
-DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
-DO_ERROR(4, SIGSEGV, "overflow", overflow)
-DO_ERROR(5, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
-DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
-DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
-
-/* Runs on IST stack */
-asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
-{
-       if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
-                       12, SIGBUS) == NOTIFY_STOP)
-               return;
-       preempt_conditional_sti(regs);
-       do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
-       preempt_conditional_cli(regs);
-}
-
-asmlinkage void do_double_fault(struct pt_regs *regs, long error_code)
-{
-       static const char str[] = "double fault";
-       struct task_struct *tsk = current;
-
-       /* Return not checked because double check cannot be ignored */
-       notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 8;
-
-       /* This is always a kernel trap and never fixable (and thus must
-          never return). */
-       for (;;)
-               die(str, regs, error_code);
-}
-
-asmlinkage void __kprobes
-do_general_protection(struct pt_regs *regs, long error_code)
-{
-       struct task_struct *tsk;
-
-       conditional_sti(regs);
-
-       tsk = current;
-       if (!user_mode(regs))
-               goto gp_in_kernel;
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-
-       if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
-                       printk_ratelimit()) {
-               printk(KERN_INFO
-                       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
-                       tsk->comm, tsk->pid,
-                       regs->ip, regs->sp, error_code);
-               print_vma_addr(" in ", regs->ip);
-               printk("\n");
-       }
-
-       force_sig(SIGSEGV, tsk);
-       return;
-
-gp_in_kernel:
-       if (fixup_exception(regs))
-               return;
-
-       tsk->thread.error_code = error_code;
-       tsk->thread.trap_no = 13;
-       if (notify_die(DIE_GPF, "general protection fault", regs,
-                               error_code, 13, SIGSEGV) == NOTIFY_STOP)
-               return;
-       die("general protection fault", regs, error_code);
-}
-
-static notrace __kprobes void
-mem_parity_error(unsigned char reason, struct pt_regs *regs)
-{
-       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
-               reason);
-       printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
-
-#if defined(CONFIG_EDAC)
-       if (edac_handler_set()) {
-               edac_atomic_assert_error();
-               return;
-       }
-#endif
-
-       if (panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
-
-       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
-
-       /* Clear and disable the memory parity error line. */
-       reason = (reason & 0xf) | 4;
-       outb(reason, 0x61);
-}
-
-static notrace __kprobes void
-io_check_error(unsigned char reason, struct pt_regs *regs)
-{
-       printk("NMI: IOCK error (debug interrupt?)\n");
-       show_registers(regs);
-
-       /* Re-enable the IOCK line, wait for a few seconds */
-       reason = (reason & 0xf) | 8;
-       outb(reason, 0x61);
-       mdelay(2000);
-       reason &= ~8;
-       outb(reason, 0x61);
-}
-
-static notrace __kprobes void
-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
-{
-       if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
-                       NOTIFY_STOP)
-               return;
-       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
-               reason);
-       printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
-
-       if (panic_on_unrecovered_nmi)
-               panic("NMI: Not continuing");
-
-       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
-}
-
-/* Runs on IST stack. This code must keep interrupts off all the time.
-   Nested NMIs are prevented by the CPU. */
-asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs)
-{
-       unsigned char reason = 0;
-       int cpu;
-
-       cpu = smp_processor_id();
-
-       /* Only the BSP gets external NMIs from the system. */
-       if (!cpu)
-               reason = get_nmi_reason();
-
-       if (!(reason & 0xc0)) {
-               if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
-                                                               == NOTIFY_STOP)
-                       return;
-               /*
-                * Ok, so this is none of the documented NMI sources,
-                * so it must be the NMI watchdog.
-                */
-               if (nmi_watchdog_tick(regs, reason))
-                       return;
-               if (!do_nmi_callback(regs, cpu))
-                       unknown_nmi_error(reason, regs);
-
-               return;
-       }
-       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
-               return;
-
-       /* AK: following checks seem to be broken on modern chipsets. FIXME */
-       if (reason & 0x80)
-               mem_parity_error(reason, regs);
-       if (reason & 0x40)
-               io_check_error(reason, regs);
-}
-
-asmlinkage notrace __kprobes void
-do_nmi(struct pt_regs *regs, long error_code)
-{
-       nmi_enter();
-
-       add_pda(__nmi_count, 1);
-
-       if (!ignore_nmis)
-               default_do_nmi(regs);
-
-       nmi_exit();
-}
-
-void stop_nmi(void)
-{
-       acpi_nmi_disable();
-       ignore_nmis++;
-}
-
-void restart_nmi(void)
-{
-       ignore_nmis--;
-       acpi_nmi_enable();
-}
-
-/* runs on IST stack. */
-asmlinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
-{
-       trace_hardirqs_fixup();
-
-       if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-                       == NOTIFY_STOP)
-               return;
-
-       preempt_conditional_sti(regs);
-       do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
-       preempt_conditional_cli(regs);
-}
-
-/* Help handler running on IST stack to switch back to user stack
-   for scheduling or signal handling. The actual stack switch is done in
-   entry.S */
-asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
-{
-       struct pt_regs *regs = eregs;
-       /* Did already sync */
-       if (eregs == (struct pt_regs *)eregs->sp)
-               ;
-       /* Exception from user space */
-       else if (user_mode(eregs))
-               regs = task_pt_regs(current);
-       /* Exception from kernel and interrupts are enabled. Move to
-          kernel process stack. */
-       else if (eregs->flags & X86_EFLAGS_IF)
-               regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
-       if (eregs != regs)
-               *regs = *eregs;
-       return regs;
-}
-
-/* runs on IST stack. */
-asmlinkage void __kprobes do_debug(struct pt_regs *regs,
-                                  unsigned long error_code)
-{
-       struct task_struct *tsk = current;
-       unsigned long condition;
-       siginfo_t info;
-
-       trace_hardirqs_fixup();
-
-       get_debugreg(condition, 6);
-
-       /*
-        * The processor cleared BTF, so don't mark that we need it set.
-        */
-       clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
-       tsk->thread.debugctlmsr = 0;
-
-       if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
-                                               SIGTRAP) == NOTIFY_STOP)
-               return;
-
-       preempt_conditional_sti(regs);
-
-       /* Mask out spurious debug traps due to lazy DR7 setting */
-       if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
-               if (!tsk->thread.debugreg7)
-                       goto clear_dr7;
-       }
-
-       tsk->thread.debugreg6 = condition;
-
-       /*
-        * Single-stepping through TF: make sure we ignore any events in
-        * kernel space (but re-enable TF when returning to user mode).
-        */
-       if (condition & DR_STEP) {
-               if (!user_mode(regs))
-                       goto clear_TF_reenable;
-       }
-
-       /* Ok, finally something we can handle */
-       tsk->thread.trap_no = 1;
-       tsk->thread.error_code = error_code;
-       info.si_signo = SIGTRAP;
-       info.si_errno = 0;
-       info.si_code = get_si_code(condition);
-       info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
-       force_sig_info(SIGTRAP, &info, tsk);
-
-clear_dr7:
-       set_debugreg(0, 7);
-       preempt_conditional_cli(regs);
-       return;
-
-clear_TF_reenable:
-       set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
-       regs->flags &= ~X86_EFLAGS_TF;
-       preempt_conditional_cli(regs);
-       return;
-}
-
-static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
-{
-       if (fixup_exception(regs))
-               return 1;
-
-       notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
-       /* Illegal floating point operation in the kernel */
-       current->thread.trap_no = trapnr;
-       die(str, regs, 0);
-       return 0;
-}
-
-/*
- * Note that we play around with the 'TS' bit in an attempt to get
- * the correct behaviour even in the presence of the asynchronous
- * IRQ13 behaviour
- */
-asmlinkage void do_coprocessor_error(struct pt_regs *regs)
-{
-       void __user *ip = (void __user *)(regs->ip);
-       struct task_struct *task;
-       siginfo_t info;
-       unsigned short cwd, swd;
-
-       conditional_sti(regs);
-       if (!user_mode(regs) &&
-           kernel_math_error(regs, "kernel x87 math error", 16))
-               return;
-
-       /*
-        * Save the info for the exception handler and clear the error.
-        */
-       task = current;
-       save_init_fpu(task);
-       task->thread.trap_no = 16;
-       task->thread.error_code = 0;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_code = __SI_FAULT;
-       info.si_addr = ip;
-       /*
-        * (~cwd & swd) will mask out exceptions that are not set to unmasked
-        * status.  0x3f is the exception bits in these regs, 0x200 is the
-        * C1 reg you need in case of a stack fault, 0x040 is the stack
-        * fault bit.  We should only be taking one exception at a time,
-        * so if this combination doesn't produce any single exception,
-        * then we have a bad program that isn't synchronizing its FPU usage
-        * and it will suffer the consequences since we won't be able to
-        * fully reproduce the context of the exception
-        */
-       cwd = get_fpu_cwd(task);
-       swd = get_fpu_swd(task);
-       switch (swd & ~cwd & 0x3f) {
-       case 0x000: /* No unmasked exception */
-       default: /* Multiple exceptions */
-               break;
-       case 0x001: /* Invalid Op */
-               /*
-                * swd & 0x240 == 0x040: Stack Underflow
-                * swd & 0x240 == 0x240: Stack Overflow
-                * User must clear the SF bit (0x40) if set
-                */
-               info.si_code = FPE_FLTINV;
-               break;
-       case 0x002: /* Denormalize */
-       case 0x010: /* Underflow */
-               info.si_code = FPE_FLTUND;
-               break;
-       case 0x004: /* Zero Divide */
-               info.si_code = FPE_FLTDIV;
-               break;
-       case 0x008: /* Overflow */
-               info.si_code = FPE_FLTOVF;
-               break;
-       case 0x020: /* Precision */
-               info.si_code = FPE_FLTRES;
-               break;
-       }
-       force_sig_info(SIGFPE, &info, task);
-}
-
-asmlinkage void bad_intr(void)
-{
-       printk("bad interrupt");
-}
-
-asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
-{
-       void __user *ip = (void __user *)(regs->ip);
-       struct task_struct *task;
-       siginfo_t info;
-       unsigned short mxcsr;
-
-       conditional_sti(regs);
-       if (!user_mode(regs) &&
-                       kernel_math_error(regs, "kernel simd math error", 19))
-               return;
-
-       /*
-        * Save the info for the exception handler and clear the error.
-        */
-       task = current;
-       save_init_fpu(task);
-       task->thread.trap_no = 19;
-       task->thread.error_code = 0;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_code = __SI_FAULT;
-       info.si_addr = ip;
-       /*
-        * The SIMD FPU exceptions are handled a little differently, as there
-        * is only a single status/control register.  Thus, to determine which
-        * unmasked exception was caught we must mask the exception mask bits
-        * at 0x1f80, and then use these to mask the exception bits at 0x3f.
-        */
-       mxcsr = get_fpu_mxcsr(task);
-       switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
-       case 0x000:
-       default:
-               break;
-       case 0x001: /* Invalid Op */
-               info.si_code = FPE_FLTINV;
-               break;
-       case 0x002: /* Denormalize */
-       case 0x010: /* Underflow */
-               info.si_code = FPE_FLTUND;
-               break;
-       case 0x004: /* Zero Divide */
-               info.si_code = FPE_FLTDIV;
-               break;
-       case 0x008: /* Overflow */
-               info.si_code = FPE_FLTOVF;
-               break;
-       case 0x020: /* Precision */
-               info.si_code = FPE_FLTRES;
-               break;
-       }
-       force_sig_info(SIGFPE, &info, task);
-}
-
-asmlinkage void do_spurious_interrupt_bug(struct pt_regs *regs)
-{
-}
-
-asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
-{
-}
-
-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
-{
-}
-
-/*
- * 'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task
- *
- * Careful.. There are problems with IBM-designed IRQ13 behaviour.
- * Don't touch unless you *really* know how it works.
- */
-asmlinkage void math_state_restore(void)
-{
-       struct task_struct *me = current;
-
-       if (!used_math()) {
-               local_irq_enable();
-               /*
-                * does a slab alloc which can sleep
-                */
-               if (init_fpu(me)) {
-                       /*
-                        * ran out of memory!
-                        */
-                       do_group_exit(SIGKILL);
-                       return;
-               }
-               local_irq_disable();
-       }
-
-       clts();                         /* Allow maths ops (or we recurse) */
-       /*
-        * Paranoid restore. send a SIGSEGV if we fail to restore the state.
-        */
-       if (unlikely(restore_fpu_checking(me))) {
-               stts();
-               force_sig(SIGSEGV, me);
-               return;
-       }
-       task_thread_info(me)->status |= TS_USEDFPU;
-       me->fpu_counter++;
-}
-EXPORT_SYMBOL_GPL(math_state_restore);
-
-void __init trap_init(void)
-{
-       set_intr_gate(0, &divide_error);
-       set_intr_gate_ist(1, &debug, DEBUG_STACK);
-       set_intr_gate_ist(2, &nmi, NMI_STACK);
-       /* int3 can be called from all */
-       set_system_gate_ist(3, &int3, DEBUG_STACK);
-       /* int4 can be called from all */
-       set_system_gate(4, &overflow);
-       set_intr_gate(5, &bounds);
-       set_intr_gate(6, &invalid_op);
-       set_intr_gate(7, &device_not_available);
-       set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK);
-       set_intr_gate(9, &coprocessor_segment_overrun);
-       set_intr_gate(10, &invalid_TSS);
-       set_intr_gate(11, &segment_not_present);
-       set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
-       set_intr_gate(13, &general_protection);
-       set_intr_gate(14, &page_fault);
-       set_intr_gate(15, &spurious_interrupt_bug);
-       set_intr_gate(16, &coprocessor_error);
-       set_intr_gate(17, &alignment_check);
-#ifdef CONFIG_X86_MCE
-       set_intr_gate_ist(18, &machine_check, MCE_STACK);
-#endif
-       set_intr_gate(19, &simd_coprocessor_error);
-
-#ifdef CONFIG_IA32_EMULATION
-       set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
-#endif
-       /*
-        * Should be a barrier for any external CPU state:
-        */
-       cpu_init();
-}
-
-static int __init oops_setup(char *s)
-{
-       if (!s)
-               return -EINVAL;
-       if (!strcmp(s, "panic"))
-               panic_on_oops = 1;
-       return 0;
-}
-early_param("oops", oops_setup);
-
-static int __init kstack_setup(char *s)
-{
-       if (!s)
-               return -EINVAL;
-       kstack_depth_to_print = simple_strtoul(s, NULL, 0);
-       return 0;
-}
-early_param("kstack", kstack_setup);
-
-static int __init code_bytes_setup(char *s)
-{
-       code_bytes = simple_strtoul(s, NULL, 0);
-       if (code_bytes > 8192)
-               code_bytes = 8192;
-
-       return 1;
-}
-__setup("code_bytes=", code_bytes_setup);
index d0e940bb6f401839681f79fee8367b1a27678b1a..c02343594b4de95bb79ce31bf78de03fb48ed636 100644 (file)
@@ -3,10 +3,13 @@
 #
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
-                coalesced_mmio.o)
+                coalesced_mmio.o irq_comm.o)
 ifeq ($(CONFIG_KVM_TRACE),y)
 common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
 endif
+ifeq ($(CONFIG_DMAR),y)
+common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+endif
 
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
 
index c0f7872a9124873ac9c01937bd4400ca2f3fe47b..634132a9a512391d324def8826390a709d257c80 100644 (file)
@@ -200,13 +200,14 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
 
        if (!atomic_inc_and_test(&pt->pending))
                set_bit(KVM_REQ_PENDING_TIMER, &vcpu0->requests);
-       if (vcpu0 && waitqueue_active(&vcpu0->wq)) {
-               vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
+       if (vcpu0 && waitqueue_active(&vcpu0->wq))
                wake_up_interruptible(&vcpu0->wq);
-       }
 
        pt->timer.expires = ktime_add_ns(pt->timer.expires, pt->period);
        pt->scheduled = ktime_to_ns(pt->timer.expires);
+       if (pt->period)
+               ps->channels[0].count_load_time = pt->timer.expires;
 
        return (pt->period == 0 ? 0 : 1);
 }
@@ -215,12 +216,22 @@ int pit_has_pending_timer(struct kvm_vcpu *vcpu)
 {
        struct kvm_pit *pit = vcpu->kvm->arch.vpit;
 
-       if (pit && vcpu->vcpu_id == 0 && pit->pit_state.inject_pending)
+       if (pit && vcpu->vcpu_id == 0 && pit->pit_state.irq_ack)
                return atomic_read(&pit->pit_state.pit_timer.pending);
-
        return 0;
 }
 
+static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
+{
+       struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
+                                                irq_ack_notifier);
+       spin_lock(&ps->inject_lock);
+       if (atomic_dec_return(&ps->pit_timer.pending) < 0)
+               atomic_inc(&ps->pit_timer.pending);
+       ps->irq_ack = 1;
+       spin_unlock(&ps->inject_lock);
+}
+
 static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
 {
        struct kvm_kpit_state *ps;
@@ -255,8 +266,9 @@ static void destroy_pit_timer(struct kvm_kpit_timer *pt)
        hrtimer_cancel(&pt->timer);
 }
 
-static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
+static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period)
 {
+       struct kvm_kpit_timer *pt = &ps->pit_timer;
        s64 interval;
 
        interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
@@ -268,6 +280,7 @@ static void create_pit_timer(struct kvm_kpit_timer *pt, u32 val, int is_period)
        pt->period = (is_period == 0) ? 0 : interval;
        pt->timer.function = pit_timer_fn;
        atomic_set(&pt->pending, 0);
+       ps->irq_ack = 1;
 
        hrtimer_start(&pt->timer, ktime_add_ns(ktime_get(), interval),
                      HRTIMER_MODE_ABS);
@@ -302,11 +315,11 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
        case 1:
         /* FIXME: enhance mode 4 precision */
        case 4:
-               create_pit_timer(&ps->pit_timer, val, 0);
+               create_pit_timer(ps, val, 0);
                break;
        case 2:
        case 3:
-               create_pit_timer(&ps->pit_timer, val, 1);
+               create_pit_timer(ps, val, 1);
                break;
        default:
                destroy_pit_timer(&ps->pit_timer);
@@ -520,7 +533,7 @@ void kvm_pit_reset(struct kvm_pit *pit)
        mutex_unlock(&pit->pit_state.lock);
 
        atomic_set(&pit->pit_state.pit_timer.pending, 0);
-       pit->pit_state.inject_pending = 1;
+       pit->pit_state.irq_ack = 1;
 }
 
 struct kvm_pit *kvm_create_pit(struct kvm *kvm)
@@ -534,6 +547,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
 
        mutex_init(&pit->pit_state.lock);
        mutex_lock(&pit->pit_state.lock);
+       spin_lock_init(&pit->pit_state.inject_lock);
 
        /* Initialize PIO device */
        pit->dev.read = pit_ioport_read;
@@ -555,6 +569,9 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
        pit_state->pit = pit;
        hrtimer_init(&pit_state->pit_timer.timer,
                     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       pit_state->irq_ack_notifier.gsi = 0;
+       pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
+       kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
        mutex_unlock(&pit->pit_state.lock);
 
        kvm_pit_reset(pit);
@@ -578,10 +595,8 @@ void kvm_free_pit(struct kvm *kvm)
 static void __inject_pit_timer_intr(struct kvm *kvm)
 {
        mutex_lock(&kvm->lock);
-       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 1);
-       kvm_ioapic_set_irq(kvm->arch.vioapic, 0, 0);
-       kvm_pic_set_irq(pic_irqchip(kvm), 0, 1);
-       kvm_pic_set_irq(pic_irqchip(kvm), 0, 0);
+       kvm_set_irq(kvm, 0, 1);
+       kvm_set_irq(kvm, 0, 0);
        mutex_unlock(&kvm->lock);
 }
 
@@ -592,37 +607,19 @@ void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
        struct kvm_kpit_state *ps;
 
        if (vcpu && pit) {
+               int inject = 0;
                ps = &pit->pit_state;
 
-               /* Try to inject pending interrupts when:
-                * 1. Pending exists
-                * 2. Last interrupt was accepted or waited for too long time*/
-               if (atomic_read(&ps->pit_timer.pending) &&
-                   (ps->inject_pending ||
-                   (jiffies - ps->last_injected_time
-                               >= KVM_MAX_PIT_INTR_INTERVAL))) {
-                       ps->inject_pending = 0;
-                       __inject_pit_timer_intr(kvm);
-                       ps->last_injected_time = jiffies;
-               }
-       }
-}
-
-void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
-       struct kvm_arch *arch = &vcpu->kvm->arch;
-       struct kvm_kpit_state *ps;
-
-       if (vcpu && arch->vpit) {
-               ps = &arch->vpit->pit_state;
-               if (atomic_read(&ps->pit_timer.pending) &&
-               (((arch->vpic->pics[0].imr & 1) == 0 &&
-                 arch->vpic->pics[0].irq_base == vec) ||
-                 (arch->vioapic->redirtbl[0].fields.vector == vec &&
-                 arch->vioapic->redirtbl[0].fields.mask != 1))) {
-                       ps->inject_pending = 1;
-                       atomic_dec(&ps->pit_timer.pending);
-                       ps->channels[0].count_load_time = ktime_get();
+               /* Try to inject pending interrupts when
+                * last one has been acked.
+                */
+               spin_lock(&ps->inject_lock);
+               if (atomic_read(&ps->pit_timer.pending) && ps->irq_ack) {
+                       ps->irq_ack = 0;
+                       inject = 1;
                }
+               spin_unlock(&ps->inject_lock);
+               if (inject)
+                       __inject_pit_timer_intr(kvm);
        }
 }
index db25c2a6c8c4a612afedd77a9c93d3378230ab33..e436d4983aa15e349eec174ed1643435060305e2 100644 (file)
@@ -8,7 +8,6 @@ struct kvm_kpit_timer {
        int irq;
        s64 period; /* unit: ns */
        s64 scheduled;
-       ktime_t last_update;
        atomic_t pending;
 };
 
@@ -34,8 +33,9 @@ struct kvm_kpit_state {
        u32    speaker_data_on;
        struct mutex lock;
        struct kvm_pit *pit;
-       bool inject_pending; /* if inject pending interrupts */
-       unsigned long last_injected_time;
+       spinlock_t inject_lock;
+       unsigned long irq_ack;
+       struct kvm_irq_ack_notifier irq_ack_notifier;
 };
 
 struct kvm_pit {
@@ -54,7 +54,6 @@ struct kvm_pit {
 #define KVM_PIT_CHANNEL_MASK       0x3
 
 void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu);
-void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
 void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val);
 struct kvm_pit *kvm_create_pit(struct kvm *kvm);
 void kvm_free_pit(struct kvm *kvm);
index c31164e8aa46c498643b9fa953df3920d598a1d3..17e41e165f1a296cb538f48ec118db1109cf3b92 100644 (file)
 
 #include <linux/kvm_host.h>
 
+static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
+{
+       s->isr &= ~(1 << irq);
+       s->isr_ack |= (1 << irq);
+}
+
+void kvm_pic_clear_isr_ack(struct kvm *kvm)
+{
+       struct kvm_pic *s = pic_irqchip(kvm);
+       s->pics[0].isr_ack = 0xff;
+       s->pics[1].isr_ack = 0xff;
+}
+
 /*
  * set irq level. If an edge is detected, then the IRR is set to 1
  */
@@ -141,11 +154,12 @@ void kvm_pic_set_irq(void *opaque, int irq, int level)
  */
 static inline void pic_intack(struct kvm_kpic_state *s, int irq)
 {
+       s->isr |= 1 << irq;
        if (s->auto_eoi) {
                if (s->rotate_on_auto_eoi)
                        s->priority_add = (irq + 1) & 7;
-       } else
-               s->isr |= (1 << irq);
+               pic_clear_isr(s, irq);
+       }
        /*
         * We don't clear a level sensitive interrupt here
         */
@@ -153,9 +167,10 @@ static inline void pic_intack(struct kvm_kpic_state *s, int irq)
                s->irr &= ~(1 << irq);
 }
 
-int kvm_pic_read_irq(struct kvm_pic *s)
+int kvm_pic_read_irq(struct kvm *kvm)
 {
        int irq, irq2, intno;
+       struct kvm_pic *s = pic_irqchip(kvm);
 
        irq = pic_get_irq(&s->pics[0]);
        if (irq >= 0) {
@@ -181,16 +196,32 @@ int kvm_pic_read_irq(struct kvm_pic *s)
                intno = s->pics[0].irq_base + irq;
        }
        pic_update_irq(s);
+       kvm_notify_acked_irq(kvm, irq);
 
        return intno;
 }
 
 void kvm_pic_reset(struct kvm_kpic_state *s)
 {
+       int irq, irqbase;
+       struct kvm *kvm = s->pics_state->irq_request_opaque;
+       struct kvm_vcpu *vcpu0 = kvm->vcpus[0];
+
+       if (s == &s->pics_state->pics[0])
+               irqbase = 0;
+       else
+               irqbase = 8;
+
+       for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
+               if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
+                       if (s->irr & (1 << irq) || s->isr & (1 << irq))
+                               kvm_notify_acked_irq(kvm, irq+irqbase);
+       }
        s->last_irr = 0;
        s->irr = 0;
        s->imr = 0;
        s->isr = 0;
+       s->isr_ack = 0xff;
        s->priority_add = 0;
        s->irq_base = 0;
        s->read_reg_select = 0;
@@ -243,7 +274,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                priority = get_priority(s, s->isr);
                                if (priority != 8) {
                                        irq = (priority + s->priority_add) & 7;
-                                       s->isr &= ~(1 << irq);
+                                       pic_clear_isr(s, irq);
                                        if (cmd == 5)
                                                s->priority_add = (irq + 1) & 7;
                                        pic_update_irq(s->pics_state);
@@ -251,7 +282,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                break;
                        case 3:
                                irq = val & 7;
-                               s->isr &= ~(1 << irq);
+                               pic_clear_isr(s, irq);
                                pic_update_irq(s->pics_state);
                                break;
                        case 6:
@@ -260,8 +291,8 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                break;
                        case 7:
                                irq = val & 7;
-                               s->isr &= ~(1 << irq);
                                s->priority_add = (irq + 1) & 7;
+                               pic_clear_isr(s, irq);
                                pic_update_irq(s->pics_state);
                                break;
                        default:
@@ -303,7 +334,7 @@ static u32 pic_poll_read(struct kvm_kpic_state *s, u32 addr1)
                        s->pics_state->pics[0].irr &= ~(1 << 2);
                }
                s->irr &= ~(1 << ret);
-               s->isr &= ~(1 << ret);
+               pic_clear_isr(s, ret);
                if (addr1 >> 7 || ret != 2)
                        pic_update_irq(s->pics_state);
        } else {
@@ -422,10 +453,14 @@ static void pic_irq_request(void *opaque, int level)
 {
        struct kvm *kvm = opaque;
        struct kvm_vcpu *vcpu = kvm->vcpus[0];
+       struct kvm_pic *s = pic_irqchip(kvm);
+       int irq = pic_get_irq(&s->pics[0]);
 
-       pic_irqchip(kvm)->output = level;
-       if (vcpu)
+       s->output = level;
+       if (vcpu && level && (s->pics[0].isr_ack & (1 << irq))) {
+               s->pics[0].isr_ack &= ~(1 << irq);
                kvm_vcpu_kick(vcpu);
+       }
 }
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm)
index 76d736b5f66464372a95979c0ada398f6f109a1d..c019b8edcdb76bab269ceb48f8bc96e02fae7817 100644 (file)
@@ -72,7 +72,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
                if (kvm_apic_accept_pic_intr(v)) {
                        s = pic_irqchip(v->kvm);
                        s->output = 0;          /* PIC */
-                       vector = kvm_pic_read_irq(s);
+                       vector = kvm_pic_read_irq(v->kvm);
                }
        }
        return vector;
@@ -90,7 +90,6 @@ EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
 void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
 {
        kvm_apic_timer_intr_post(vcpu, vec);
-       kvm_pit_timer_intr_post(vcpu, vec);
        /* TODO: PIT, RTC etc. */
 }
 EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
index 7ca47cbb48bb3c2239a2ebb13975d43f5f9bac4b..f17c8f5bbf31b8bae7b1d2a0d770bd5a968a7a6a 100644 (file)
@@ -42,6 +42,7 @@ struct kvm_kpic_state {
        u8 irr;         /* interrupt request register */
        u8 imr;         /* interrupt mask register */
        u8 isr;         /* interrupt service register */
+       u8 isr_ack;     /* interrupt ack detection */
        u8 priority_add;        /* highest irq priority */
        u8 irq_base;
        u8 read_reg_select;
@@ -63,12 +64,13 @@ struct kvm_pic {
        void *irq_request_opaque;
        int output;             /* intr from master PIC */
        struct kvm_io_device dev;
+       void (*ack_notifier)(void *opaque, int irq);
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
-void kvm_pic_set_irq(void *opaque, int irq, int level);
-int kvm_pic_read_irq(struct kvm_pic *s);
+int kvm_pic_read_irq(struct kvm *kvm);
 void kvm_pic_update_irq(struct kvm_pic *s);
+void kvm_pic_clear_isr_ack(struct kvm *kvm);
 
 static inline struct kvm_pic *pic_irqchip(struct kvm *kvm)
 {
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h
new file mode 100644 (file)
index 0000000..1ff819d
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef ASM_KVM_CACHE_REGS_H
+#define ASM_KVM_CACHE_REGS_H
+
+static inline unsigned long kvm_register_read(struct kvm_vcpu *vcpu,
+                                             enum kvm_reg reg)
+{
+       if (!test_bit(reg, (unsigned long *)&vcpu->arch.regs_avail))
+               kvm_x86_ops->cache_reg(vcpu, reg);
+
+       return vcpu->arch.regs[reg];
+}
+
+static inline void kvm_register_write(struct kvm_vcpu *vcpu,
+                                     enum kvm_reg reg,
+                                     unsigned long val)
+{
+       vcpu->arch.regs[reg] = val;
+       __set_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
+       __set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
+}
+
+static inline unsigned long kvm_rip_read(struct kvm_vcpu *vcpu)
+{
+       return kvm_register_read(vcpu, VCPU_REGS_RIP);
+}
+
+static inline void kvm_rip_write(struct kvm_vcpu *vcpu, unsigned long val)
+{
+       kvm_register_write(vcpu, VCPU_REGS_RIP, val);
+}
+
+#endif
index 73f43de69f676b9a784de04b4a7b5dbd43ecc3b1..6571926bfd339b498c2ca06835b71d8ead494787 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/current.h>
 #include <asm/apicdef.h>
 #include <asm/atomic.h>
+#include "kvm_cache_regs.h"
 #include "irq.h"
 
 #define PRId64 "d"
@@ -338,13 +339,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                } else
                        apic_clear_vector(vector, apic->regs + APIC_TMR);
 
-               if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
-                       kvm_vcpu_kick(vcpu);
-               else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
-                       vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-                       if (waitqueue_active(&vcpu->wq))
-                               wake_up_interruptible(&vcpu->wq);
-               }
+               kvm_vcpu_kick(vcpu);
 
                result = (orig_irr == 0);
                break;
@@ -370,21 +365,18 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                        vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
                        kvm_vcpu_kick(vcpu);
                } else {
-                       printk(KERN_DEBUG
-                              "Ignoring de-assert INIT to vcpu %d\n",
-                              vcpu->vcpu_id);
+                       apic_debug("Ignoring de-assert INIT to vcpu %d\n",
+                                  vcpu->vcpu_id);
                }
-
                break;
 
        case APIC_DM_STARTUP:
-               printk(KERN_DEBUG "SIPI to vcpu %d vector 0x%02x\n",
-                      vcpu->vcpu_id, vector);
+               apic_debug("SIPI to vcpu %d vector 0x%02x\n",
+                          vcpu->vcpu_id, vector);
                if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
                        vcpu->arch.sipi_vector = vector;
                        vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
-                       if (waitqueue_active(&vcpu->wq))
-                               wake_up_interruptible(&vcpu->wq);
+                       kvm_vcpu_kick(vcpu);
                }
                break;
 
@@ -438,7 +430,7 @@ struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
 static void apic_set_eoi(struct kvm_lapic *apic)
 {
        int vector = apic_find_highest_isr(apic);
-
+       int trigger_mode;
        /*
         * Not every write EOI will has corresponding ISR,
         * one example is when Kernel check timer on setup_IO_APIC
@@ -450,7 +442,10 @@ static void apic_set_eoi(struct kvm_lapic *apic)
        apic_update_ppr(apic);
 
        if (apic_test_and_clear_vector(vector, apic->regs + APIC_TMR))
-               kvm_ioapic_update_eoi(apic->vcpu->kvm, vector);
+               trigger_mode = IOAPIC_LEVEL_TRIG;
+       else
+               trigger_mode = IOAPIC_EDGE_TRIG;
+       kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode);
 }
 
 static void apic_send_ipi(struct kvm_lapic *apic)
@@ -558,8 +553,7 @@ static void __report_tpr_access(struct kvm_lapic *apic, bool write)
        struct kvm_run *run = vcpu->run;
 
        set_bit(KVM_REQ_REPORT_TPR_ACCESS, &vcpu->requests);
-       kvm_x86_ops->cache_regs(vcpu);
-       run->tpr_access.rip = vcpu->arch.rip;
+       run->tpr_access.rip = kvm_rip_read(vcpu);
        run->tpr_access.is_write = write;
 }
 
@@ -683,9 +677,9 @@ static void apic_mmio_write(struct kvm_io_device *this,
         * Refer SDM 8.4.1
         */
        if (len != 4 || alignment) {
-               if (printk_ratelimit())
-                       printk(KERN_ERR "apic write: bad size=%d %lx\n",
-                              len, (long)address);
+               /* Don't shout loud, $infamous_os would cause only noise. */
+               apic_debug("apic write: bad size=%d %lx\n",
+                          len, (long)address);
                return;
        }
 
@@ -947,10 +941,9 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 
        if(!atomic_inc_and_test(&apic->timer.pending))
                set_bit(KVM_REQ_PENDING_TIMER, &apic->vcpu->requests);
-       if (waitqueue_active(q)) {
-               apic->vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+       if (waitqueue_active(q))
                wake_up_interruptible(q);
-       }
+
        if (apic_lvtt_period(apic)) {
                result = 1;
                apic->timer.dev.expires = ktime_add_ns(
index 3da2508eb22a2d9577a0a24847065af3e21acbcc..99c239c5c0ac7becff901a5bbdd399af4ec48293 100644 (file)
@@ -70,6 +70,9 @@ static int dbg = 0;
 module_param(dbg, bool, 0644);
 #endif
 
+static int oos_shadow = 1;
+module_param(oos_shadow, bool, 0644);
+
 #ifndef MMU_DEBUG
 #define ASSERT(x) do { } while (0)
 #else
@@ -135,18 +138,24 @@ module_param(dbg, bool, 0644);
 #define ACC_USER_MASK    PT_USER_MASK
 #define ACC_ALL          (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
 
-struct kvm_pv_mmu_op_buffer {
-       void *ptr;
-       unsigned len;
-       unsigned processed;
-       char buf[512] __aligned(sizeof(long));
-};
+#define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
 
 struct kvm_rmap_desc {
        u64 *shadow_ptes[RMAP_EXT];
        struct kvm_rmap_desc *more;
 };
 
+struct kvm_shadow_walk {
+       int (*entry)(struct kvm_shadow_walk *walk, struct kvm_vcpu *vcpu,
+                    u64 addr, u64 *spte, int level);
+};
+
+struct kvm_unsync_walk {
+       int (*entry) (struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk);
+};
+
+typedef int (*mmu_parent_walk_fn) (struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp);
+
 static struct kmem_cache *pte_chain_cache;
 static struct kmem_cache *rmap_desc_cache;
 static struct kmem_cache *mmu_page_header_cache;
@@ -405,16 +414,19 @@ static int host_largepage_backed(struct kvm *kvm, gfn_t gfn)
 {
        struct vm_area_struct *vma;
        unsigned long addr;
+       int ret = 0;
 
        addr = gfn_to_hva(kvm, gfn);
        if (kvm_is_error_hva(addr))
-               return 0;
+               return ret;
 
+       down_read(&current->mm->mmap_sem);
        vma = find_vma(current->mm, addr);
        if (vma && is_vm_hugetlb_page(vma))
-               return 1;
+               ret = 1;
+       up_read(&current->mm->mmap_sem);
 
-       return 0;
+       return ret;
 }
 
 static int is_largepage_backed(struct kvm_vcpu *vcpu, gfn_t large_gfn)
@@ -649,8 +661,6 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
 
        if (write_protected)
                kvm_flush_remote_tlbs(kvm);
-
-       account_shadowed(kvm, gfn);
 }
 
 static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
@@ -859,6 +869,77 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
        BUG();
 }
 
+
+static void mmu_parent_walk(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+                           mmu_parent_walk_fn fn)
+{
+       struct kvm_pte_chain *pte_chain;
+       struct hlist_node *node;
+       struct kvm_mmu_page *parent_sp;
+       int i;
+
+       if (!sp->multimapped && sp->parent_pte) {
+               parent_sp = page_header(__pa(sp->parent_pte));
+               fn(vcpu, parent_sp);
+               mmu_parent_walk(vcpu, parent_sp, fn);
+               return;
+       }
+       hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
+               for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
+                       if (!pte_chain->parent_ptes[i])
+                               break;
+                       parent_sp = page_header(__pa(pte_chain->parent_ptes[i]));
+                       fn(vcpu, parent_sp);
+                       mmu_parent_walk(vcpu, parent_sp, fn);
+               }
+}
+
+static void kvm_mmu_update_unsync_bitmap(u64 *spte)
+{
+       unsigned int index;
+       struct kvm_mmu_page *sp = page_header(__pa(spte));
+
+       index = spte - sp->spt;
+       __set_bit(index, sp->unsync_child_bitmap);
+       sp->unsync_children = 1;
+}
+
+static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp)
+{
+       struct kvm_pte_chain *pte_chain;
+       struct hlist_node *node;
+       int i;
+
+       if (!sp->parent_pte)
+               return;
+
+       if (!sp->multimapped) {
+               kvm_mmu_update_unsync_bitmap(sp->parent_pte);
+               return;
+       }
+
+       hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
+               for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
+                       if (!pte_chain->parent_ptes[i])
+                               break;
+                       kvm_mmu_update_unsync_bitmap(pte_chain->parent_ptes[i]);
+               }
+}
+
+static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+{
+       sp->unsync_children = 1;
+       kvm_mmu_update_parents_unsync(sp);
+       return 1;
+}
+
+static void kvm_mmu_mark_parents_unsync(struct kvm_vcpu *vcpu,
+                                       struct kvm_mmu_page *sp)
+{
+       mmu_parent_walk(vcpu, sp, unsync_walk_fn);
+       kvm_mmu_update_parents_unsync(sp);
+}
+
 static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
                                    struct kvm_mmu_page *sp)
 {
@@ -868,6 +949,58 @@ static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
                sp->spt[i] = shadow_trap_nonpresent_pte;
 }
 
+static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
+                              struct kvm_mmu_page *sp)
+{
+       return 1;
+}
+
+static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
+{
+}
+
+#define for_each_unsync_children(bitmap, idx)          \
+       for (idx = find_first_bit(bitmap, 512);         \
+            idx < 512;                                 \
+            idx = find_next_bit(bitmap, 512, idx+1))
+
+static int mmu_unsync_walk(struct kvm_mmu_page *sp,
+                          struct kvm_unsync_walk *walker)
+{
+       int i, ret;
+
+       if (!sp->unsync_children)
+               return 0;
+
+       for_each_unsync_children(sp->unsync_child_bitmap, i) {
+               u64 ent = sp->spt[i];
+
+               if (is_shadow_present_pte(ent)) {
+                       struct kvm_mmu_page *child;
+                       child = page_header(ent & PT64_BASE_ADDR_MASK);
+
+                       if (child->unsync_children) {
+                               ret = mmu_unsync_walk(child, walker);
+                               if (ret)
+                                       return ret;
+                               __clear_bit(i, sp->unsync_child_bitmap);
+                       }
+
+                       if (child->unsync) {
+                               ret = walker->entry(child, walker);
+                               __clear_bit(i, sp->unsync_child_bitmap);
+                               if (ret)
+                                       return ret;
+                       }
+               }
+       }
+
+       if (find_first_bit(sp->unsync_child_bitmap, 512) == 512)
+               sp->unsync_children = 0;
+
+       return 0;
+}
+
 static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
 {
        unsigned index;
@@ -888,6 +1021,59 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
        return NULL;
 }
 
+static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+       WARN_ON(!sp->unsync);
+       sp->unsync = 0;
+       --kvm->stat.mmu_unsync;
+}
+
+static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp);
+
+static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+{
+       if (sp->role.glevels != vcpu->arch.mmu.root_level) {
+               kvm_mmu_zap_page(vcpu->kvm, sp);
+               return 1;
+       }
+
+       rmap_write_protect(vcpu->kvm, sp->gfn);
+       if (vcpu->arch.mmu.sync_page(vcpu, sp)) {
+               kvm_mmu_zap_page(vcpu->kvm, sp);
+               return 1;
+       }
+
+       kvm_mmu_flush_tlb(vcpu);
+       kvm_unlink_unsync_page(vcpu->kvm, sp);
+       return 0;
+}
+
+struct sync_walker {
+       struct kvm_vcpu *vcpu;
+       struct kvm_unsync_walk walker;
+};
+
+static int mmu_sync_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
+{
+       struct sync_walker *sync_walk = container_of(walk, struct sync_walker,
+                                                    walker);
+       struct kvm_vcpu *vcpu = sync_walk->vcpu;
+
+       kvm_sync_page(vcpu, sp);
+       return (need_resched() || spin_needbreak(&vcpu->kvm->mmu_lock));
+}
+
+static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+{
+       struct sync_walker walker = {
+               .walker = { .entry = mmu_sync_fn, },
+               .vcpu = vcpu,
+       };
+
+       while (mmu_unsync_walk(sp, &walker.walker))
+               cond_resched_lock(&vcpu->kvm->mmu_lock);
+}
+
 static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                                             gfn_t gfn,
                                             gva_t gaddr,
@@ -901,7 +1087,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        unsigned quadrant;
        struct hlist_head *bucket;
        struct kvm_mmu_page *sp;
-       struct hlist_node *node;
+       struct hlist_node *node, *tmp;
 
        role.word = 0;
        role.glevels = vcpu->arch.mmu.root_level;
@@ -917,9 +1103,20 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                 gfn, role.word);
        index = kvm_page_table_hashfn(gfn);
        bucket = &vcpu->kvm->arch.mmu_page_hash[index];
-       hlist_for_each_entry(sp, node, bucket, hash_link)
-               if (sp->gfn == gfn && sp->role.word == role.word) {
+       hlist_for_each_entry_safe(sp, node, tmp, bucket, hash_link)
+               if (sp->gfn == gfn) {
+                       if (sp->unsync)
+                               if (kvm_sync_page(vcpu, sp))
+                                       continue;
+
+                       if (sp->role.word != role.word)
+                               continue;
+
                        mmu_page_add_parent_pte(vcpu, sp, parent_pte);
+                       if (sp->unsync_children) {
+                               set_bit(KVM_REQ_MMU_SYNC, &vcpu->requests);
+                               kvm_mmu_mark_parents_unsync(vcpu, sp);
+                       }
                        pgprintk("%s: found\n", __func__);
                        return sp;
                }
@@ -931,8 +1128,10 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        sp->gfn = gfn;
        sp->role = role;
        hlist_add_head(&sp->hash_link, bucket);
-       if (!metaphysical)
+       if (!metaphysical) {
                rmap_write_protect(vcpu->kvm, gfn);
+               account_shadowed(vcpu->kvm, gfn);
+       }
        if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)
                vcpu->arch.mmu.prefetch_page(vcpu, sp);
        else
@@ -940,6 +1139,35 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        return sp;
 }
 
+static int walk_shadow(struct kvm_shadow_walk *walker,
+                      struct kvm_vcpu *vcpu, u64 addr)
+{
+       hpa_t shadow_addr;
+       int level;
+       int r;
+       u64 *sptep;
+       unsigned index;
+
+       shadow_addr = vcpu->arch.mmu.root_hpa;
+       level = vcpu->arch.mmu.shadow_root_level;
+       if (level == PT32E_ROOT_LEVEL) {
+               shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3];
+               shadow_addr &= PT64_BASE_ADDR_MASK;
+               --level;
+       }
+
+       while (level >= PT_PAGE_TABLE_LEVEL) {
+               index = SHADOW_PT_INDEX(addr, level);
+               sptep = ((u64 *)__va(shadow_addr)) + index;
+               r = walker->entry(walker, vcpu, addr, sptep, level);
+               if (r)
+                       return r;
+               shadow_addr = *sptep & PT64_BASE_ADDR_MASK;
+               --level;
+       }
+       return 0;
+}
+
 static void kvm_mmu_page_unlink_children(struct kvm *kvm,
                                         struct kvm_mmu_page *sp)
 {
@@ -955,7 +1183,6 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
                                rmap_remove(kvm, &pt[i]);
                        pt[i] = shadow_trap_nonpresent_pte;
                }
-               kvm_flush_remote_tlbs(kvm);
                return;
        }
 
@@ -974,7 +1201,6 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
                }
                pt[i] = shadow_trap_nonpresent_pte;
        }
-       kvm_flush_remote_tlbs(kvm);
 }
 
 static void kvm_mmu_put_page(struct kvm_mmu_page *sp, u64 *parent_pte)
@@ -991,11 +1217,10 @@ static void kvm_mmu_reset_last_pte_updated(struct kvm *kvm)
                        kvm->vcpus[i]->arch.last_pte_updated = NULL;
 }
 
-static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
        u64 *parent_pte;
 
-       ++kvm->stat.mmu_shadow_zapped;
        while (sp->multimapped || sp->parent_pte) {
                if (!sp->multimapped)
                        parent_pte = sp->parent_pte;
@@ -1010,21 +1235,59 @@ static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
                kvm_mmu_put_page(sp, parent_pte);
                set_shadow_pte(parent_pte, shadow_trap_nonpresent_pte);
        }
+}
+
+struct zap_walker {
+       struct kvm_unsync_walk walker;
+       struct kvm *kvm;
+       int zapped;
+};
+
+static int mmu_zap_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
+{
+       struct zap_walker *zap_walk = container_of(walk, struct zap_walker,
+                                                    walker);
+       kvm_mmu_zap_page(zap_walk->kvm, sp);
+       zap_walk->zapped = 1;
+       return 0;
+}
+
+static int mmu_zap_unsync_children(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+       struct zap_walker walker = {
+               .walker = { .entry = mmu_zap_fn, },
+               .kvm = kvm,
+               .zapped = 0,
+       };
+
+       if (sp->role.level == PT_PAGE_TABLE_LEVEL)
+               return 0;
+       mmu_unsync_walk(sp, &walker.walker);
+       return walker.zapped;
+}
+
+static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+       int ret;
+       ++kvm->stat.mmu_shadow_zapped;
+       ret = mmu_zap_unsync_children(kvm, sp);
        kvm_mmu_page_unlink_children(kvm, sp);
+       kvm_mmu_unlink_parents(kvm, sp);
+       kvm_flush_remote_tlbs(kvm);
+       if (!sp->role.invalid && !sp->role.metaphysical)
+               unaccount_shadowed(kvm, sp->gfn);
+       if (sp->unsync)
+               kvm_unlink_unsync_page(kvm, sp);
        if (!sp->root_count) {
-               if (!sp->role.metaphysical && !sp->role.invalid)
-                       unaccount_shadowed(kvm, sp->gfn);
                hlist_del(&sp->hash_link);
                kvm_mmu_free_page(kvm, sp);
        } else {
-               int invalid = sp->role.invalid;
-               list_move(&sp->link, &kvm->arch.active_mmu_pages);
                sp->role.invalid = 1;
+               list_move(&sp->link, &kvm->arch.active_mmu_pages);
                kvm_reload_remote_mmus(kvm);
-               if (!sp->role.metaphysical && !invalid)
-                       unaccount_shadowed(kvm, sp->gfn);
        }
        kvm_mmu_reset_last_pte_updated(kvm);
+       return ret;
 }
 
 /*
@@ -1077,8 +1340,9 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
                if (sp->gfn == gfn && !sp->role.metaphysical) {
                        pgprintk("%s: gfn %lx role %x\n", __func__, gfn,
                                 sp->role.word);
-                       kvm_mmu_zap_page(kvm, sp);
                        r = 1;
+                       if (kvm_mmu_zap_page(kvm, sp))
+                               n = bucket->first;
                }
        return r;
 }
@@ -1101,6 +1365,20 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
        __set_bit(slot, &sp->slot_bitmap);
 }
 
+static void mmu_convert_notrap(struct kvm_mmu_page *sp)
+{
+       int i;
+       u64 *pt = sp->spt;
+
+       if (shadow_trap_nonpresent_pte == shadow_notrap_nonpresent_pte)
+               return;
+
+       for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+               if (pt[i] == shadow_notrap_nonpresent_pte)
+                       set_shadow_pte(&pt[i], shadow_trap_nonpresent_pte);
+       }
+}
+
 struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
 {
        struct page *page;
@@ -1110,51 +1388,60 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
        if (gpa == UNMAPPED_GVA)
                return NULL;
 
-       down_read(&current->mm->mmap_sem);
        page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
-       up_read(&current->mm->mmap_sem);
 
        return page;
 }
 
-static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
-                        unsigned pt_access, unsigned pte_access,
-                        int user_fault, int write_fault, int dirty,
-                        int *ptwrite, int largepage, gfn_t gfn,
-                        pfn_t pfn, bool speculative)
+static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
-       u64 spte;
-       int was_rmapped = 0;
-       int was_writeble = is_writeble_pte(*shadow_pte);
+       unsigned index;
+       struct hlist_head *bucket;
+       struct kvm_mmu_page *s;
+       struct hlist_node *node, *n;
 
-       pgprintk("%s: spte %llx access %x write_fault %d"
-                " user_fault %d gfn %lx\n",
-                __func__, *shadow_pte, pt_access,
-                write_fault, user_fault, gfn);
+       index = kvm_page_table_hashfn(sp->gfn);
+       bucket = &vcpu->kvm->arch.mmu_page_hash[index];
+       /* don't unsync if pagetable is shadowed with multiple roles */
+       hlist_for_each_entry_safe(s, node, n, bucket, hash_link) {
+               if (s->gfn != sp->gfn || s->role.metaphysical)
+                       continue;
+               if (s->role.word != sp->role.word)
+                       return 1;
+       }
+       kvm_mmu_mark_parents_unsync(vcpu, sp);
+       ++vcpu->kvm->stat.mmu_unsync;
+       sp->unsync = 1;
+       mmu_convert_notrap(sp);
+       return 0;
+}
 
-       if (is_rmap_pte(*shadow_pte)) {
-               /*
-                * If we overwrite a PTE page pointer with a 2MB PMD, unlink
-                * the parent of the now unreachable PTE.
-                */
-               if (largepage && !is_large_pte(*shadow_pte)) {
-                       struct kvm_mmu_page *child;
-                       u64 pte = *shadow_pte;
+static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
+                                 bool can_unsync)
+{
+       struct kvm_mmu_page *shadow;
 
-                       child = page_header(pte & PT64_BASE_ADDR_MASK);
-                       mmu_page_remove_parent_pte(child, shadow_pte);
-               } else if (pfn != spte_to_pfn(*shadow_pte)) {
-                       pgprintk("hfn old %lx new %lx\n",
-                                spte_to_pfn(*shadow_pte), pfn);
-                       rmap_remove(vcpu->kvm, shadow_pte);
-               } else {
-                       if (largepage)
-                               was_rmapped = is_large_pte(*shadow_pte);
-                       else
-                               was_rmapped = 1;
-               }
+       shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
+       if (shadow) {
+               if (shadow->role.level != PT_PAGE_TABLE_LEVEL)
+                       return 1;
+               if (shadow->unsync)
+                       return 0;
+               if (can_unsync && oos_shadow)
+                       return kvm_unsync_page(vcpu, shadow);
+               return 1;
        }
+       return 0;
+}
 
+static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+                   unsigned pte_access, int user_fault,
+                   int write_fault, int dirty, int largepage,
+                   gfn_t gfn, pfn_t pfn, bool speculative,
+                   bool can_unsync)
+{
+       u64 spte;
+       int ret = 0;
        /*
         * We don't set the accessed bit, since we sometimes want to see
         * whether the guest actually used the pte (in order to detect
@@ -1162,7 +1449,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
         */
        spte = shadow_base_present_pte | shadow_dirty_mask;
        if (!speculative)
-               pte_access |= PT_ACCESSED_MASK;
+               spte |= shadow_accessed_mask;
        if (!dirty)
                pte_access &= ~ACC_WRITE_MASK;
        if (pte_access & ACC_EXEC_MASK)
@@ -1178,35 +1465,82 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
 
        if ((pte_access & ACC_WRITE_MASK)
            || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
-               struct kvm_mmu_page *shadow;
+
+               if (largepage && has_wrprotected_page(vcpu->kvm, gfn)) {
+                       ret = 1;
+                       spte = shadow_trap_nonpresent_pte;
+                       goto set_pte;
+               }
 
                spte |= PT_WRITABLE_MASK;
 
-               shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
-               if (shadow ||
-                  (largepage && has_wrprotected_page(vcpu->kvm, gfn))) {
+               if (mmu_need_write_protect(vcpu, gfn, can_unsync)) {
                        pgprintk("%s: found shadow page for %lx, marking ro\n",
                                 __func__, gfn);
+                       ret = 1;
                        pte_access &= ~ACC_WRITE_MASK;
-                       if (is_writeble_pte(spte)) {
+                       if (is_writeble_pte(spte))
                                spte &= ~PT_WRITABLE_MASK;
-                               kvm_x86_ops->tlb_flush(vcpu);
-                       }
-                       if (write_fault)
-                               *ptwrite = 1;
                }
        }
 
        if (pte_access & ACC_WRITE_MASK)
                mark_page_dirty(vcpu->kvm, gfn);
 
-       pgprintk("%s: setting spte %llx\n", __func__, spte);
-       pgprintk("instantiating %s PTE (%s) at %ld (%llx) addr %p\n",
-                (spte&PT_PAGE_SIZE_MASK)? "2MB" : "4kB",
-                (spte&PT_WRITABLE_MASK)?"RW":"R", gfn, spte, shadow_pte);
+set_pte:
        set_shadow_pte(shadow_pte, spte);
-       if (!was_rmapped && (spte & PT_PAGE_SIZE_MASK)
-           && (spte & PT_PRESENT_MASK))
+       return ret;
+}
+
+static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+                        unsigned pt_access, unsigned pte_access,
+                        int user_fault, int write_fault, int dirty,
+                        int *ptwrite, int largepage, gfn_t gfn,
+                        pfn_t pfn, bool speculative)
+{
+       int was_rmapped = 0;
+       int was_writeble = is_writeble_pte(*shadow_pte);
+
+       pgprintk("%s: spte %llx access %x write_fault %d"
+                " user_fault %d gfn %lx\n",
+                __func__, *shadow_pte, pt_access,
+                write_fault, user_fault, gfn);
+
+       if (is_rmap_pte(*shadow_pte)) {
+               /*
+                * If we overwrite a PTE page pointer with a 2MB PMD, unlink
+                * the parent of the now unreachable PTE.
+                */
+               if (largepage && !is_large_pte(*shadow_pte)) {
+                       struct kvm_mmu_page *child;
+                       u64 pte = *shadow_pte;
+
+                       child = page_header(pte & PT64_BASE_ADDR_MASK);
+                       mmu_page_remove_parent_pte(child, shadow_pte);
+               } else if (pfn != spte_to_pfn(*shadow_pte)) {
+                       pgprintk("hfn old %lx new %lx\n",
+                                spte_to_pfn(*shadow_pte), pfn);
+                       rmap_remove(vcpu->kvm, shadow_pte);
+               } else {
+                       if (largepage)
+                               was_rmapped = is_large_pte(*shadow_pte);
+                       else
+                               was_rmapped = 1;
+               }
+       }
+       if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault,
+                     dirty, largepage, gfn, pfn, speculative, true)) {
+               if (write_fault)
+                       *ptwrite = 1;
+               kvm_x86_ops->tlb_flush(vcpu);
+       }
+
+       pgprintk("%s: setting spte %llx\n", __func__, *shadow_pte);
+       pgprintk("instantiating %s PTE (%s) at %ld (%llx) addr %p\n",
+                is_large_pte(*shadow_pte)? "2MB" : "4kB",
+                is_present_pte(*shadow_pte)?"RW":"R", gfn,
+                *shadow_pte, shadow_pte);
+       if (!was_rmapped && is_large_pte(*shadow_pte))
                ++vcpu->kvm->stat.lpages;
 
        page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
@@ -1230,54 +1564,67 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
 {
 }
 
-static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
-                          int largepage, gfn_t gfn, pfn_t pfn,
-                          int level)
-{
-       hpa_t table_addr = vcpu->arch.mmu.root_hpa;
-       int pt_write = 0;
-
-       for (; ; level--) {
-               u32 index = PT64_INDEX(v, level);
-               u64 *table;
-
-               ASSERT(VALID_PAGE(table_addr));
-               table = __va(table_addr);
+struct direct_shadow_walk {
+       struct kvm_shadow_walk walker;
+       pfn_t pfn;
+       int write;
+       int largepage;
+       int pt_write;
+};
 
-               if (level == 1) {
-                       mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
-                                    0, write, 1, &pt_write, 0, gfn, pfn, false);
-                       return pt_write;
-               }
+static int direct_map_entry(struct kvm_shadow_walk *_walk,
+                           struct kvm_vcpu *vcpu,
+                           u64 addr, u64 *sptep, int level)
+{
+       struct direct_shadow_walk *walk =
+               container_of(_walk, struct direct_shadow_walk, walker);
+       struct kvm_mmu_page *sp;
+       gfn_t pseudo_gfn;
+       gfn_t gfn = addr >> PAGE_SHIFT;
+
+       if (level == PT_PAGE_TABLE_LEVEL
+           || (walk->largepage && level == PT_DIRECTORY_LEVEL)) {
+               mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL,
+                            0, walk->write, 1, &walk->pt_write,
+                            walk->largepage, gfn, walk->pfn, false);
+               ++vcpu->stat.pf_fixed;
+               return 1;
+       }
 
-               if (largepage && level == 2) {
-                       mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
-                                    0, write, 1, &pt_write, 1, gfn, pfn, false);
-                       return pt_write;
+       if (*sptep == shadow_trap_nonpresent_pte) {
+               pseudo_gfn = (addr & PT64_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT;
+               sp = kvm_mmu_get_page(vcpu, pseudo_gfn, (gva_t)addr, level - 1,
+                                     1, ACC_ALL, sptep);
+               if (!sp) {
+                       pgprintk("nonpaging_map: ENOMEM\n");
+                       kvm_release_pfn_clean(walk->pfn);
+                       return -ENOMEM;
                }
 
-               if (table[index] == shadow_trap_nonpresent_pte) {
-                       struct kvm_mmu_page *new_table;
-                       gfn_t pseudo_gfn;
-
-                       pseudo_gfn = (v & PT64_DIR_BASE_ADDR_MASK)
-                               >> PAGE_SHIFT;
-                       new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
-                                                    v, level - 1,
-                                                    1, ACC_ALL, &table[index]);
-                       if (!new_table) {
-                               pgprintk("nonpaging_map: ENOMEM\n");
-                               kvm_release_pfn_clean(pfn);
-                               return -ENOMEM;
-                       }
-
-                       set_shadow_pte(&table[index],
-                                      __pa(new_table->spt)
-                                      | PT_PRESENT_MASK | PT_WRITABLE_MASK
-                                      | shadow_user_mask | shadow_x_mask);
-               }
-               table_addr = table[index] & PT64_BASE_ADDR_MASK;
+               set_shadow_pte(sptep,
+                              __pa(sp->spt)
+                              | PT_PRESENT_MASK | PT_WRITABLE_MASK
+                              | shadow_user_mask | shadow_x_mask);
        }
+       return 0;
+}
+
+static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
+                       int largepage, gfn_t gfn, pfn_t pfn)
+{
+       int r;
+       struct direct_shadow_walk walker = {
+               .walker = { .entry = direct_map_entry, },
+               .pfn = pfn,
+               .largepage = largepage,
+               .write = write,
+               .pt_write = 0,
+       };
+
+       r = walk_shadow(&walker.walker, vcpu, gfn << PAGE_SHIFT);
+       if (r < 0)
+               return r;
+       return walker.pt_write;
 }
 
 static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
@@ -1287,16 +1634,14 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
        pfn_t pfn;
        unsigned long mmu_seq;
 
-       down_read(&current->mm->mmap_sem);
        if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
                gfn &= ~(KVM_PAGES_PER_HPAGE-1);
                largepage = 1;
        }
 
        mmu_seq = vcpu->kvm->mmu_notifier_seq;
-       /* implicit mb(), we'll read before PT lock is unlocked */
+       smp_rmb();
        pfn = gfn_to_pfn(vcpu->kvm, gfn);
-       up_read(&current->mm->mmap_sem);
 
        /* mmio */
        if (is_error_pfn(pfn)) {
@@ -1308,8 +1653,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
        if (mmu_notifier_retry(vcpu, mmu_seq))
                goto out_unlock;
        kvm_mmu_free_some_pages(vcpu);
-       r = __direct_map(vcpu, v, write, largepage, gfn, pfn,
-                        PT32E_ROOT_LEVEL);
+       r = __direct_map(vcpu, v, write, largepage, gfn, pfn);
        spin_unlock(&vcpu->kvm->mmu_lock);
 
 
@@ -1405,6 +1749,37 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
        vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
 }
 
+static void mmu_sync_roots(struct kvm_vcpu *vcpu)
+{
+       int i;
+       struct kvm_mmu_page *sp;
+
+       if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+               return;
+       if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_LEVEL) {
+               hpa_t root = vcpu->arch.mmu.root_hpa;
+               sp = page_header(root);
+               mmu_sync_children(vcpu, sp);
+               return;
+       }
+       for (i = 0; i < 4; ++i) {
+               hpa_t root = vcpu->arch.mmu.pae_root[i];
+
+               if (root) {
+                       root &= PT64_BASE_ADDR_MASK;
+                       sp = page_header(root);
+                       mmu_sync_children(vcpu, sp);
+               }
+       }
+}
+
+void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
+{
+       spin_lock(&vcpu->kvm->mmu_lock);
+       mmu_sync_roots(vcpu);
+       spin_unlock(&vcpu->kvm->mmu_lock);
+}
+
 static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
        return vaddr;
@@ -1446,15 +1821,13 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
        if (r)
                return r;
 
-       down_read(&current->mm->mmap_sem);
        if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
                gfn &= ~(KVM_PAGES_PER_HPAGE-1);
                largepage = 1;
        }
        mmu_seq = vcpu->kvm->mmu_notifier_seq;
-       /* implicit mb(), we'll read before PT lock is unlocked */
+       smp_rmb();
        pfn = gfn_to_pfn(vcpu->kvm, gfn);
-       up_read(&current->mm->mmap_sem);
        if (is_error_pfn(pfn)) {
                kvm_release_pfn_clean(pfn);
                return 1;
@@ -1464,7 +1837,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
                goto out_unlock;
        kvm_mmu_free_some_pages(vcpu);
        r = __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK,
-                        largepage, gfn, pfn, kvm_x86_ops->get_tdp_level());
+                        largepage, gfn, pfn);
        spin_unlock(&vcpu->kvm->mmu_lock);
 
        return r;
@@ -1489,6 +1862,8 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu)
        context->gva_to_gpa = nonpaging_gva_to_gpa;
        context->free = nonpaging_free;
        context->prefetch_page = nonpaging_prefetch_page;
+       context->sync_page = nonpaging_sync_page;
+       context->invlpg = nonpaging_invlpg;
        context->root_level = 0;
        context->shadow_root_level = PT32E_ROOT_LEVEL;
        context->root_hpa = INVALID_PAGE;
@@ -1536,6 +1911,8 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu, int level)
        context->page_fault = paging64_page_fault;
        context->gva_to_gpa = paging64_gva_to_gpa;
        context->prefetch_page = paging64_prefetch_page;
+       context->sync_page = paging64_sync_page;
+       context->invlpg = paging64_invlpg;
        context->free = paging_free;
        context->root_level = level;
        context->shadow_root_level = level;
@@ -1557,6 +1934,8 @@ static int paging32_init_context(struct kvm_vcpu *vcpu)
        context->gva_to_gpa = paging32_gva_to_gpa;
        context->free = paging_free;
        context->prefetch_page = paging32_prefetch_page;
+       context->sync_page = paging32_sync_page;
+       context->invlpg = paging32_invlpg;
        context->root_level = PT32_ROOT_LEVEL;
        context->shadow_root_level = PT32E_ROOT_LEVEL;
        context->root_hpa = INVALID_PAGE;
@@ -1576,6 +1955,8 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
        context->page_fault = tdp_page_fault;
        context->free = nonpaging_free;
        context->prefetch_page = nonpaging_prefetch_page;
+       context->sync_page = nonpaging_sync_page;
+       context->invlpg = nonpaging_invlpg;
        context->shadow_root_level = kvm_x86_ops->get_tdp_level();
        context->root_hpa = INVALID_PAGE;
 
@@ -1647,6 +2028,7 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)
        spin_lock(&vcpu->kvm->mmu_lock);
        kvm_mmu_free_some_pages(vcpu);
        mmu_alloc_roots(vcpu);
+       mmu_sync_roots(vcpu);
        spin_unlock(&vcpu->kvm->mmu_lock);
        kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa);
        kvm_mmu_flush_tlb(vcpu);
@@ -1767,15 +2149,13 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                return;
        gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
 
-       down_read(&current->mm->mmap_sem);
        if (is_large_pte(gpte) && is_largepage_backed(vcpu, gfn)) {
                gfn &= ~(KVM_PAGES_PER_HPAGE-1);
                vcpu->arch.update_pte.largepage = 1;
        }
        vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq;
-       /* implicit mb(), we'll read before PT lock is unlocked */
+       smp_rmb();
        pfn = gfn_to_pfn(vcpu->kvm, gfn);
-       up_read(&current->mm->mmap_sem);
 
        if (is_error_pfn(pfn)) {
                kvm_release_pfn_clean(pfn);
@@ -1837,7 +2217,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        index = kvm_page_table_hashfn(gfn);
        bucket = &vcpu->kvm->arch.mmu_page_hash[index];
        hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) {
-               if (sp->gfn != gfn || sp->role.metaphysical)
+               if (sp->gfn != gfn || sp->role.metaphysical || sp->role.invalid)
                        continue;
                pte_size = sp->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
                misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
@@ -1855,7 +2235,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                         */
                        pgprintk("misaligned: gpa %llx bytes %d role %x\n",
                                 gpa, bytes, sp->role.word);
-                       kvm_mmu_zap_page(vcpu->kvm, sp);
+                       if (kvm_mmu_zap_page(vcpu->kvm, sp))
+                               n = bucket->first;
                        ++vcpu->kvm->stat.mmu_flooded;
                        continue;
                }
@@ -1969,6 +2350,16 @@ out:
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
 
+void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
+{
+       spin_lock(&vcpu->kvm->mmu_lock);
+       vcpu->arch.mmu.invlpg(vcpu, gva);
+       spin_unlock(&vcpu->kvm->mmu_lock);
+       kvm_mmu_flush_tlb(vcpu);
+       ++vcpu->stat.invlpg;
+}
+EXPORT_SYMBOL_GPL(kvm_mmu_invlpg);
+
 void kvm_enable_tdp(void)
 {
        tdp_enabled = true;
@@ -2055,6 +2446,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
 {
        struct kvm_mmu_page *sp;
 
+       spin_lock(&kvm->mmu_lock);
        list_for_each_entry(sp, &kvm->arch.active_mmu_pages, link) {
                int i;
                u64 *pt;
@@ -2068,6 +2460,8 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
                        if (pt[i] & PT_WRITABLE_MASK)
                                pt[i] &= ~PT_WRITABLE_MASK;
        }
+       kvm_flush_remote_tlbs(kvm);
+       spin_unlock(&kvm->mmu_lock);
 }
 
 void kvm_mmu_zap_all(struct kvm *kvm)
@@ -2076,7 +2470,9 @@ void kvm_mmu_zap_all(struct kvm *kvm)
 
        spin_lock(&kvm->mmu_lock);
        list_for_each_entry_safe(sp, node, &kvm->arch.active_mmu_pages, link)
-               kvm_mmu_zap_page(kvm, sp);
+               if (kvm_mmu_zap_page(kvm, sp))
+                       node = container_of(kvm->arch.active_mmu_pages.next,
+                                           struct kvm_mmu_page, link);
        spin_unlock(&kvm->mmu_lock);
 
        kvm_flush_remote_tlbs(kvm);
@@ -2291,18 +2687,18 @@ int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
                  gpa_t addr, unsigned long *ret)
 {
        int r;
-       struct kvm_pv_mmu_op_buffer buffer;
+       struct kvm_pv_mmu_op_buffer *buffer = &vcpu->arch.mmu_op_buffer;
 
-       buffer.ptr = buffer.buf;
-       buffer.len = min_t(unsigned long, bytes, sizeof buffer.buf);
-       buffer.processed = 0;
+       buffer->ptr = buffer->buf;
+       buffer->len = min_t(unsigned long, bytes, sizeof buffer->buf);
+       buffer->processed = 0;
 
-       r = kvm_read_guest(vcpu->kvm, addr, buffer.buf, buffer.len);
+       r = kvm_read_guest(vcpu->kvm, addr, buffer->buf, buffer->len);
        if (r)
                goto out;
 
-       while (buffer.len) {
-               r = kvm_pv_mmu_op_one(vcpu, &buffer);
+       while (buffer->len) {
+               r = kvm_pv_mmu_op_one(vcpu, buffer);
                if (r < 0)
                        goto out;
                if (r == 0)
@@ -2311,7 +2707,7 @@ int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
 
        r = 1;
 out:
-       *ret = buffer.processed;
+       *ret = buffer->processed;
        return r;
 }
 
index 4a814bff21f27cb9b829df36071ffb40b43818ca..613ec9aa674afe06cd76c99b8ebc06eaa3f91f32 100644 (file)
 #if PTTYPE == 64
        #define pt_element_t u64
        #define guest_walker guest_walker64
+       #define shadow_walker shadow_walker64
        #define FNAME(name) paging##64_##name
        #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK
        #define PT_DIR_BASE_ADDR_MASK PT64_DIR_BASE_ADDR_MASK
        #define PT_INDEX(addr, level) PT64_INDEX(addr, level)
-       #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
        #define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
        #define PT_LEVEL_BITS PT64_LEVEL_BITS
        #ifdef CONFIG_X86_64
 #elif PTTYPE == 32
        #define pt_element_t u32
        #define guest_walker guest_walker32
+       #define shadow_walker shadow_walker32
        #define FNAME(name) paging##32_##name
        #define PT_BASE_ADDR_MASK PT32_BASE_ADDR_MASK
        #define PT_DIR_BASE_ADDR_MASK PT32_DIR_BASE_ADDR_MASK
        #define PT_INDEX(addr, level) PT32_INDEX(addr, level)
-       #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level)
        #define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
        #define PT_LEVEL_BITS PT32_LEVEL_BITS
        #define PT_MAX_FULL_LEVELS 2
@@ -73,6 +73,17 @@ struct guest_walker {
        u32 error_code;
 };
 
+struct shadow_walker {
+       struct kvm_shadow_walk walker;
+       struct guest_walker *guest_walker;
+       int user_fault;
+       int write_fault;
+       int largepage;
+       int *ptwrite;
+       pfn_t pfn;
+       u64 *sptep;
+};
+
 static gfn_t gpte_to_gfn(pt_element_t gpte)
 {
        return (gpte & PT_BASE_ADDR_MASK) >> PAGE_SHIFT;
@@ -91,14 +102,10 @@ static bool FNAME(cmpxchg_gpte)(struct kvm *kvm,
        pt_element_t *table;
        struct page *page;
 
-       down_read(&current->mm->mmap_sem);
        page = gfn_to_page(kvm, table_gfn);
-       up_read(&current->mm->mmap_sem);
 
        table = kmap_atomic(page, KM_USER0);
-
        ret = CMPXCHG(&table[index], orig_pte, new_pte);
-
        kunmap_atomic(table, KM_USER0);
 
        kvm_release_page_dirty(page);
@@ -274,86 +281,89 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
 /*
  * Fetch a shadow pte for a specific level in the paging hierarchy.
  */
-static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
-                        struct guest_walker *walker,
-                        int user_fault, int write_fault, int largepage,
-                        int *ptwrite, pfn_t pfn)
+static int FNAME(shadow_walk_entry)(struct kvm_shadow_walk *_sw,
+                                   struct kvm_vcpu *vcpu, u64 addr,
+                                   u64 *sptep, int level)
 {
-       hpa_t shadow_addr;
-       int level;
-       u64 *shadow_ent;
-       unsigned access = walker->pt_access;
-
-       if (!is_present_pte(walker->ptes[walker->level - 1]))
-               return NULL;
-
-       shadow_addr = vcpu->arch.mmu.root_hpa;
-       level = vcpu->arch.mmu.shadow_root_level;
-       if (level == PT32E_ROOT_LEVEL) {
-               shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3];
-               shadow_addr &= PT64_BASE_ADDR_MASK;
-               --level;
+       struct shadow_walker *sw =
+               container_of(_sw, struct shadow_walker, walker);
+       struct guest_walker *gw = sw->guest_walker;
+       unsigned access = gw->pt_access;
+       struct kvm_mmu_page *shadow_page;
+       u64 spte;
+       int metaphysical;
+       gfn_t table_gfn;
+       int r;
+       pt_element_t curr_pte;
+
+       if (level == PT_PAGE_TABLE_LEVEL
+           || (sw->largepage && level == PT_DIRECTORY_LEVEL)) {
+               mmu_set_spte(vcpu, sptep, access, gw->pte_access & access,
+                            sw->user_fault, sw->write_fault,
+                            gw->ptes[gw->level-1] & PT_DIRTY_MASK,
+                            sw->ptwrite, sw->largepage, gw->gfn, sw->pfn,
+                            false);
+               sw->sptep = sptep;
+               return 1;
        }
 
-       for (; ; level--) {
-               u32 index = SHADOW_PT_INDEX(addr, level);
-               struct kvm_mmu_page *shadow_page;
-               u64 shadow_pte;
-               int metaphysical;
-               gfn_t table_gfn;
-
-               shadow_ent = ((u64 *)__va(shadow_addr)) + index;
-               if (level == PT_PAGE_TABLE_LEVEL)
-                       break;
-
-               if (largepage && level == PT_DIRECTORY_LEVEL)
-                       break;
+       if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
+               return 0;
 
-               if (is_shadow_present_pte(*shadow_ent)
-                   && !is_large_pte(*shadow_ent)) {
-                       shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
-                       continue;
-               }
+       if (is_large_pte(*sptep)) {
+               set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
+               kvm_flush_remote_tlbs(vcpu->kvm);
+               rmap_remove(vcpu->kvm, sptep);
+       }
 
-               if (is_large_pte(*shadow_ent))
-                       rmap_remove(vcpu->kvm, shadow_ent);
-
-               if (level - 1 == PT_PAGE_TABLE_LEVEL
-                   && walker->level == PT_DIRECTORY_LEVEL) {
-                       metaphysical = 1;
-                       if (!is_dirty_pte(walker->ptes[level - 1]))
-                               access &= ~ACC_WRITE_MASK;
-                       table_gfn = gpte_to_gfn(walker->ptes[level - 1]);
-               } else {
-                       metaphysical = 0;
-                       table_gfn = walker->table_gfn[level - 2];
-               }
-               shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
-                                              metaphysical, access,
-                                              shadow_ent);
-               if (!metaphysical) {
-                       int r;
-                       pt_element_t curr_pte;
-                       r = kvm_read_guest_atomic(vcpu->kvm,
-                                                 walker->pte_gpa[level - 2],
-                                                 &curr_pte, sizeof(curr_pte));
-                       if (r || curr_pte != walker->ptes[level - 2]) {
-                               kvm_release_pfn_clean(pfn);
-                               return NULL;
-                       }
+       if (level == PT_DIRECTORY_LEVEL && gw->level == PT_DIRECTORY_LEVEL) {
+               metaphysical = 1;
+               if (!is_dirty_pte(gw->ptes[level - 1]))
+                       access &= ~ACC_WRITE_MASK;
+               table_gfn = gpte_to_gfn(gw->ptes[level - 1]);
+       } else {
+               metaphysical = 0;
+               table_gfn = gw->table_gfn[level - 2];
+       }
+       shadow_page = kvm_mmu_get_page(vcpu, table_gfn, (gva_t)addr, level-1,
+                                      metaphysical, access, sptep);
+       if (!metaphysical) {
+               r = kvm_read_guest_atomic(vcpu->kvm, gw->pte_gpa[level - 2],
+                                         &curr_pte, sizeof(curr_pte));
+               if (r || curr_pte != gw->ptes[level - 2]) {
+                       kvm_release_pfn_clean(sw->pfn);
+                       sw->sptep = NULL;
+                       return 1;
                }
-               shadow_addr = __pa(shadow_page->spt);
-               shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
-                       | PT_WRITABLE_MASK | PT_USER_MASK;
-               set_shadow_pte(shadow_ent, shadow_pte);
        }
 
-       mmu_set_spte(vcpu, shadow_ent, access, walker->pte_access & access,
-                    user_fault, write_fault,
-                    walker->ptes[walker->level-1] & PT_DIRTY_MASK,
-                    ptwrite, largepage, walker->gfn, pfn, false);
+       spte = __pa(shadow_page->spt) | PT_PRESENT_MASK | PT_ACCESSED_MASK
+               | PT_WRITABLE_MASK | PT_USER_MASK;
+       *sptep = spte;
+       return 0;
+}
+
+static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+                        struct guest_walker *guest_walker,
+                        int user_fault, int write_fault, int largepage,
+                        int *ptwrite, pfn_t pfn)
+{
+       struct shadow_walker walker = {
+               .walker = { .entry = FNAME(shadow_walk_entry), },
+               .guest_walker = guest_walker,
+               .user_fault = user_fault,
+               .write_fault = write_fault,
+               .largepage = largepage,
+               .ptwrite = ptwrite,
+               .pfn = pfn,
+       };
+
+       if (!is_present_pte(guest_walker->ptes[guest_walker->level - 1]))
+               return NULL;
+
+       walk_shadow(&walker.walker, vcpu, addr);
 
-       return shadow_ent;
+       return walker.sptep;
 }
 
 /*
@@ -407,7 +417,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
                return 0;
        }
 
-       down_read(&current->mm->mmap_sem);
        if (walker.level == PT_DIRECTORY_LEVEL) {
                gfn_t large_gfn;
                large_gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE-1);
@@ -417,9 +426,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
                }
        }
        mmu_seq = vcpu->kvm->mmu_notifier_seq;
-       /* implicit mb(), we'll read before PT lock is unlocked */
+       smp_rmb();
        pfn = gfn_to_pfn(vcpu->kvm, walker.gfn);
-       up_read(&current->mm->mmap_sem);
 
        /* mmio */
        if (is_error_pfn(pfn)) {
@@ -453,6 +461,31 @@ out_unlock:
        return 0;
 }
 
+static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw,
+                                     struct kvm_vcpu *vcpu, u64 addr,
+                                     u64 *sptep, int level)
+{
+
+       if (level == PT_PAGE_TABLE_LEVEL) {
+               if (is_shadow_present_pte(*sptep))
+                       rmap_remove(vcpu->kvm, sptep);
+               set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
+               return 1;
+       }
+       if (!is_shadow_present_pte(*sptep))
+               return 1;
+       return 0;
+}
+
+static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
+{
+       struct shadow_walker walker = {
+               .walker = { .entry = FNAME(shadow_invlpg_entry), },
+       };
+
+       walk_shadow(&walker.walker, vcpu, gva);
+}
+
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
        struct guest_walker walker;
@@ -499,12 +532,66 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
        }
 }
 
+/*
+ * Using the cached information from sp->gfns is safe because:
+ * - The spte has a reference to the struct page, so the pfn for a given gfn
+ *   can't change unless all sptes pointing to it are nuked first.
+ * - Alias changes zap the entire shadow cache.
+ */
+static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+{
+       int i, offset, nr_present;
+
+       offset = nr_present = 0;
+
+       if (PTTYPE == 32)
+               offset = sp->role.quadrant << PT64_LEVEL_BITS;
+
+       for (i = 0; i < PT64_ENT_PER_PAGE; i++) {
+               unsigned pte_access;
+               pt_element_t gpte;
+               gpa_t pte_gpa;
+               gfn_t gfn = sp->gfns[i];
+
+               if (!is_shadow_present_pte(sp->spt[i]))
+                       continue;
+
+               pte_gpa = gfn_to_gpa(sp->gfn);
+               pte_gpa += (i+offset) * sizeof(pt_element_t);
+
+               if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte,
+                                         sizeof(pt_element_t)))
+                       return -EINVAL;
+
+               if (gpte_to_gfn(gpte) != gfn || !is_present_pte(gpte) ||
+                   !(gpte & PT_ACCESSED_MASK)) {
+                       u64 nonpresent;
+
+                       rmap_remove(vcpu->kvm, &sp->spt[i]);
+                       if (is_present_pte(gpte))
+                               nonpresent = shadow_trap_nonpresent_pte;
+                       else
+                               nonpresent = shadow_notrap_nonpresent_pte;
+                       set_shadow_pte(&sp->spt[i], nonpresent);
+                       continue;
+               }
+
+               nr_present++;
+               pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
+               set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
+                        is_dirty_pte(gpte), 0, gfn,
+                        spte_to_pfn(sp->spt[i]), true, false);
+       }
+
+       return !nr_present;
+}
+
 #undef pt_element_t
 #undef guest_walker
+#undef shadow_walker
 #undef FNAME
 #undef PT_BASE_ADDR_MASK
 #undef PT_INDEX
-#undef SHADOW_PT_INDEX
 #undef PT_LEVEL_MASK
 #undef PT_DIR_BASE_ADDR_MASK
 #undef PT_LEVEL_BITS
index 8233b86c778cfd0a01b2ca96dbe7d27776381037..9c4ce657d96389753ff9650bb06f12bf76e003c8 100644 (file)
@@ -18,6 +18,7 @@
 #include "kvm_svm.h"
 #include "irq.h"
 #include "mmu.h"
+#include "kvm_cache_regs.h"
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -35,10 +36,6 @@ MODULE_LICENSE("GPL");
 #define IOPM_ALLOC_ORDER 2
 #define MSRPM_ALLOC_ORDER 1
 
-#define DB_VECTOR 1
-#define UD_VECTOR 6
-#define GP_VECTOR 13
-
 #define DR7_GD_MASK (1 << 13)
 #define DR6_BD_MASK (1 << 13)
 
@@ -47,7 +44,7 @@ MODULE_LICENSE("GPL");
 
 #define SVM_FEATURE_NPT  (1 << 0)
 #define SVM_FEATURE_LBRV (1 << 1)
-#define SVM_DEATURE_SVML (1 << 2)
+#define SVM_FEATURE_SVML (1 << 2)
 
 #define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
 
@@ -236,13 +233,11 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
                printk(KERN_DEBUG "%s: NOP\n", __func__);
                return;
        }
-       if (svm->next_rip - svm->vmcb->save.rip > MAX_INST_SIZE)
-               printk(KERN_ERR "%s: ip 0x%llx next 0x%llx\n",
-                      __func__,
-                      svm->vmcb->save.rip,
-                      svm->next_rip);
+       if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE)
+               printk(KERN_ERR "%s: ip 0x%lx next 0x%llx\n",
+                      __func__, kvm_rip_read(vcpu), svm->next_rip);
 
-       vcpu->arch.rip = svm->vmcb->save.rip = svm->next_rip;
+       kvm_rip_write(vcpu, svm->next_rip);
        svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
 
        vcpu->arch.interrupt_window_open = 1;
@@ -530,6 +525,7 @@ static void init_vmcb(struct vcpu_svm *svm)
                                (1ULL << INTERCEPT_CPUID) |
                                (1ULL << INTERCEPT_INVD) |
                                (1ULL << INTERCEPT_HLT) |
+                               (1ULL << INTERCEPT_INVLPG) |
                                (1ULL << INTERCEPT_INVLPGA) |
                                (1ULL << INTERCEPT_IOIO_PROT) |
                                (1ULL << INTERCEPT_MSR_PROT) |
@@ -581,6 +577,7 @@ static void init_vmcb(struct vcpu_svm *svm)
        save->dr7 = 0x400;
        save->rflags = 2;
        save->rip = 0x0000fff0;
+       svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip;
 
        /*
         * cr0 val on cpu init should be 0x60000010, we enable cpu
@@ -593,7 +590,8 @@ static void init_vmcb(struct vcpu_svm *svm)
        if (npt_enabled) {
                /* Setup VMCB for Nested Paging */
                control->nested_ctl = 1;
-               control->intercept &= ~(1ULL << INTERCEPT_TASK_SWITCH);
+               control->intercept &= ~((1ULL << INTERCEPT_TASK_SWITCH) |
+                                       (1ULL << INTERCEPT_INVLPG));
                control->intercept_exceptions &= ~(1 << PF_VECTOR);
                control->intercept_cr_read &= ~(INTERCEPT_CR0_MASK|
                                                INTERCEPT_CR3_MASK);
@@ -615,10 +613,12 @@ static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
        init_vmcb(svm);
 
        if (vcpu->vcpu_id != 0) {
-               svm->vmcb->save.rip = 0;
+               kvm_rip_write(vcpu, 0);
                svm->vmcb->save.cs.base = svm->vcpu.arch.sipi_vector << 12;
                svm->vmcb->save.cs.selector = svm->vcpu.arch.sipi_vector << 8;
        }
+       vcpu->arch.regs_avail = ~0;
+       vcpu->arch.regs_dirty = ~0;
 
        return 0;
 }
@@ -721,23 +721,6 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
        rdtscll(vcpu->arch.host_tsc);
 }
 
-static void svm_cache_regs(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-
-       vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
-       vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
-       vcpu->arch.rip = svm->vmcb->save.rip;
-}
-
-static void svm_decache_regs(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-       svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
-       svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
-       svm->vmcb->save.rip = vcpu->arch.rip;
-}
-
 static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 {
        return to_svm(vcpu)->vmcb->save.rflags;
@@ -1040,7 +1023,7 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        if (npt_enabled)
                svm_flush_tlb(&svm->vcpu);
 
-       if (event_injection)
+       if (!npt_enabled && event_injection)
                kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
        return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
 }
@@ -1139,14 +1122,14 @@ static int nop_on_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 
 static int halt_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
-       svm->next_rip = svm->vmcb->save.rip + 1;
+       svm->next_rip = kvm_rip_read(&svm->vcpu) + 1;
        skip_emulated_instruction(&svm->vcpu);
        return kvm_emulate_halt(&svm->vcpu);
 }
 
 static int vmmcall_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
-       svm->next_rip = svm->vmcb->save.rip + 3;
+       svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
        skip_emulated_instruction(&svm->vcpu);
        kvm_emulate_hypercall(&svm->vcpu);
        return 1;
@@ -1178,11 +1161,18 @@ static int task_switch_interception(struct vcpu_svm *svm,
 
 static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
-       svm->next_rip = svm->vmcb->save.rip + 2;
+       svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
        kvm_emulate_cpuid(&svm->vcpu);
        return 1;
 }
 
+static int invlpg_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+       if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0) != EMULATE_DONE)
+               pr_unimpl(&svm->vcpu, "%s: failed\n", __func__);
+       return 1;
+}
+
 static int emulate_on_interception(struct vcpu_svm *svm,
                                   struct kvm_run *kvm_run)
 {
@@ -1273,9 +1263,9 @@ static int rdmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
                KVMTRACE_3D(MSR_READ, &svm->vcpu, ecx, (u32)data,
                            (u32)(data >> 32), handler);
 
-               svm->vmcb->save.rax = data & 0xffffffff;
+               svm->vcpu.arch.regs[VCPU_REGS_RAX] = data & 0xffffffff;
                svm->vcpu.arch.regs[VCPU_REGS_RDX] = data >> 32;
-               svm->next_rip = svm->vmcb->save.rip + 2;
+               svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
                skip_emulated_instruction(&svm->vcpu);
        }
        return 1;
@@ -1359,13 +1349,13 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
 static int wrmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
        u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
-       u64 data = (svm->vmcb->save.rax & -1u)
+       u64 data = (svm->vcpu.arch.regs[VCPU_REGS_RAX] & -1u)
                | ((u64)(svm->vcpu.arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
        KVMTRACE_3D(MSR_WRITE, &svm->vcpu, ecx, (u32)data, (u32)(data >> 32),
                    handler);
 
-       svm->next_rip = svm->vmcb->save.rip + 2;
+       svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
        if (svm_set_msr(&svm->vcpu, ecx, data))
                kvm_inject_gp(&svm->vcpu, 0);
        else
@@ -1436,7 +1426,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
        [SVM_EXIT_CPUID]                        = cpuid_interception,
        [SVM_EXIT_INVD]                         = emulate_on_interception,
        [SVM_EXIT_HLT]                          = halt_interception,
-       [SVM_EXIT_INVLPG]                       = emulate_on_interception,
+       [SVM_EXIT_INVLPG]                       = invlpg_interception,
        [SVM_EXIT_INVLPGA]                      = invalid_op_interception,
        [SVM_EXIT_IOIO]                         = io_interception,
        [SVM_EXIT_MSR]                          = msr_interception,
@@ -1538,6 +1528,7 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
 
        KVMTRACE_1D(INJ_VIRQ, &svm->vcpu, (u32)irq, handler);
 
+       ++svm->vcpu.stat.irq_injections;
        control = &svm->vmcb->control;
        control->int_vector = irq;
        control->int_ctl &= ~V_INTR_PRIO_MASK;
@@ -1716,6 +1707,12 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
        svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
 }
 
+#ifdef CONFIG_X86_64
+#define R "r"
+#else
+#define R "e"
+#endif
+
 static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1723,6 +1720,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        u16 gs_selector;
        u16 ldt_selector;
 
+       svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
+       svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
+       svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
+
        pre_svm_run(svm);
 
        sync_lapic_to_cr8(vcpu);
@@ -1750,19 +1751,14 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        local_irq_enable();
 
        asm volatile (
+               "push %%"R"bp; \n\t"
+               "mov %c[rbx](%[svm]), %%"R"bx \n\t"
+               "mov %c[rcx](%[svm]), %%"R"cx \n\t"
+               "mov %c[rdx](%[svm]), %%"R"dx \n\t"
+               "mov %c[rsi](%[svm]), %%"R"si \n\t"
+               "mov %c[rdi](%[svm]), %%"R"di \n\t"
+               "mov %c[rbp](%[svm]), %%"R"bp \n\t"
 #ifdef CONFIG_X86_64
-               "push %%rbp; \n\t"
-#else
-               "push %%ebp; \n\t"
-#endif
-
-#ifdef CONFIG_X86_64
-               "mov %c[rbx](%[svm]), %%rbx \n\t"
-               "mov %c[rcx](%[svm]), %%rcx \n\t"
-               "mov %c[rdx](%[svm]), %%rdx \n\t"
-               "mov %c[rsi](%[svm]), %%rsi \n\t"
-               "mov %c[rdi](%[svm]), %%rdi \n\t"
-               "mov %c[rbp](%[svm]), %%rbp \n\t"
                "mov %c[r8](%[svm]),  %%r8  \n\t"
                "mov %c[r9](%[svm]),  %%r9  \n\t"
                "mov %c[r10](%[svm]), %%r10 \n\t"
@@ -1771,41 +1767,24 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %c[r13](%[svm]), %%r13 \n\t"
                "mov %c[r14](%[svm]), %%r14 \n\t"
                "mov %c[r15](%[svm]), %%r15 \n\t"
-#else
-               "mov %c[rbx](%[svm]), %%ebx \n\t"
-               "mov %c[rcx](%[svm]), %%ecx \n\t"
-               "mov %c[rdx](%[svm]), %%edx \n\t"
-               "mov %c[rsi](%[svm]), %%esi \n\t"
-               "mov %c[rdi](%[svm]), %%edi \n\t"
-               "mov %c[rbp](%[svm]), %%ebp \n\t"
 #endif
 
-#ifdef CONFIG_X86_64
-               /* Enter guest mode */
-               "push %%rax \n\t"
-               "mov %c[vmcb](%[svm]), %%rax \n\t"
-               __ex(SVM_VMLOAD) "\n\t"
-               __ex(SVM_VMRUN) "\n\t"
-               __ex(SVM_VMSAVE) "\n\t"
-               "pop %%rax \n\t"
-#else
                /* Enter guest mode */
-               "push %%eax \n\t"
-               "mov %c[vmcb](%[svm]), %%eax \n\t"
+               "push %%"R"ax \n\t"
+               "mov %c[vmcb](%[svm]), %%"R"ax \n\t"
                __ex(SVM_VMLOAD) "\n\t"
                __ex(SVM_VMRUN) "\n\t"
                __ex(SVM_VMSAVE) "\n\t"
-               "pop %%eax \n\t"
-#endif
+               "pop %%"R"ax \n\t"
 
                /* Save guest registers, load host registers */
+               "mov %%"R"bx, %c[rbx](%[svm]) \n\t"
+               "mov %%"R"cx, %c[rcx](%[svm]) \n\t"
+               "mov %%"R"dx, %c[rdx](%[svm]) \n\t"
+               "mov %%"R"si, %c[rsi](%[svm]) \n\t"
+               "mov %%"R"di, %c[rdi](%[svm]) \n\t"
+               "mov %%"R"bp, %c[rbp](%[svm]) \n\t"
 #ifdef CONFIG_X86_64
-               "mov %%rbx, %c[rbx](%[svm]) \n\t"
-               "mov %%rcx, %c[rcx](%[svm]) \n\t"
-               "mov %%rdx, %c[rdx](%[svm]) \n\t"
-               "mov %%rsi, %c[rsi](%[svm]) \n\t"
-               "mov %%rdi, %c[rdi](%[svm]) \n\t"
-               "mov %%rbp, %c[rbp](%[svm]) \n\t"
                "mov %%r8,  %c[r8](%[svm]) \n\t"
                "mov %%r9,  %c[r9](%[svm]) \n\t"
                "mov %%r10, %c[r10](%[svm]) \n\t"
@@ -1814,18 +1793,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %%r13, %c[r13](%[svm]) \n\t"
                "mov %%r14, %c[r14](%[svm]) \n\t"
                "mov %%r15, %c[r15](%[svm]) \n\t"
-
-               "pop  %%rbp; \n\t"
-#else
-               "mov %%ebx, %c[rbx](%[svm]) \n\t"
-               "mov %%ecx, %c[rcx](%[svm]) \n\t"
-               "mov %%edx, %c[rdx](%[svm]) \n\t"
-               "mov %%esi, %c[rsi](%[svm]) \n\t"
-               "mov %%edi, %c[rdi](%[svm]) \n\t"
-               "mov %%ebp, %c[rbp](%[svm]) \n\t"
-
-               "pop  %%ebp; \n\t"
 #endif
+               "pop %%"R"bp"
                :
                : [svm]"a"(svm),
                  [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)),
@@ -1846,11 +1815,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                  [r15]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R15]))
 #endif
                : "cc", "memory"
+               , R"bx", R"cx", R"dx", R"si", R"di"
 #ifdef CONFIG_X86_64
-               , "rbx", "rcx", "rdx", "rsi", "rdi"
                , "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15"
-#else
-               , "ebx", "ecx", "edx" , "esi", "edi"
 #endif
                );
 
@@ -1858,6 +1825,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                load_db_regs(svm->host_db_regs);
 
        vcpu->arch.cr2 = svm->vmcb->save.cr2;
+       vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
+       vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
+       vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
        write_dr6(svm->host_dr6);
        write_dr7(svm->host_dr7);
@@ -1879,6 +1849,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        svm->next_rip = 0;
 }
 
+#undef R
+
 static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1977,8 +1949,6 @@ static struct kvm_x86_ops svm_x86_ops = {
        .set_gdt = svm_set_gdt,
        .get_dr = svm_get_dr,
        .set_dr = svm_set_dr,
-       .cache_regs = svm_cache_regs,
-       .decache_regs = svm_decache_regs,
        .get_rflags = svm_get_rflags,
        .set_rflags = svm_set_rflags,
 
index 7041cc52b562eccc98f4a5fd060390709bc915b4..2643b430d83a0cb2f6519dbdaccd8e9a4cd480d7 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/highmem.h>
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
+#include "kvm_cache_regs.h"
+#include "x86.h"
 
 #include <asm/io.h>
 #include <asm/desc.h>
@@ -47,6 +49,9 @@ module_param(flexpriority_enabled, bool, 0);
 static int enable_ept = 1;
 module_param(enable_ept, bool, 0);
 
+static int emulate_invalid_guest_state = 0;
+module_param(emulate_invalid_guest_state, bool, 0);
+
 struct vmcs {
        u32 revision_id;
        u32 abort;
@@ -56,6 +61,7 @@ struct vmcs {
 struct vcpu_vmx {
        struct kvm_vcpu       vcpu;
        struct list_head      local_vcpus_link;
+       unsigned long         host_rsp;
        int                   launched;
        u8                    fail;
        u32                   idt_vectoring_info;
@@ -83,6 +89,7 @@ struct vcpu_vmx {
                } irq;
        } rmode;
        int vpid;
+       bool emulation_required;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -468,7 +475,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        if (!vcpu->fpu_active)
                eb |= 1u << NM_VECTOR;
        if (vcpu->guest_debug.enabled)
-               eb |= 1u << 1;
+               eb |= 1u << DB_VECTOR;
        if (vcpu->arch.rmode.active)
                eb = ~0;
        if (vm_need_ept())
@@ -715,9 +722,9 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        unsigned long rip;
        u32 interruptibility;
 
-       rip = vmcs_readl(GUEST_RIP);
+       rip = kvm_rip_read(vcpu);
        rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
-       vmcs_writel(GUEST_RIP, rip);
+       kvm_rip_write(vcpu, rip);
 
        /*
         * We emulated an instruction, so temporary interrupt blocking
@@ -733,19 +740,35 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
 static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
                                bool has_error_code, u32 error_code)
 {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (has_error_code)
+               vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+
+       if (vcpu->arch.rmode.active) {
+               vmx->rmode.irq.pending = true;
+               vmx->rmode.irq.vector = nr;
+               vmx->rmode.irq.rip = kvm_rip_read(vcpu);
+               if (nr == BP_VECTOR)
+                       vmx->rmode.irq.rip++;
+               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+                            nr | INTR_TYPE_SOFT_INTR
+                            | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
+                            | INTR_INFO_VALID_MASK);
+               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+               kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+               return;
+       }
+
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                     nr | INTR_TYPE_EXCEPTION
                     | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
                     | INTR_INFO_VALID_MASK);
-       if (has_error_code)
-               vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
 }
 
 static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-
-       return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+       return false;
 }
 
 /*
@@ -947,24 +970,19 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
        return ret;
 }
 
-/*
- * Sync the rsp and rip registers into the vcpu structure.  This allows
- * registers to be accessed by indexing vcpu->arch.regs.
- */
-static void vcpu_load_rsp_rip(struct kvm_vcpu *vcpu)
-{
-       vcpu->arch.regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
-       vcpu->arch.rip = vmcs_readl(GUEST_RIP);
-}
-
-/*
- * Syncs rsp and rip back into the vmcs.  Should be called after possible
- * modification.
- */
-static void vcpu_put_rsp_rip(struct kvm_vcpu *vcpu)
+static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
 {
-       vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
-       vmcs_writel(GUEST_RIP, vcpu->arch.rip);
+       __set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
+       switch (reg) {
+       case VCPU_REGS_RSP:
+               vcpu->arch.regs[VCPU_REGS_RSP] = vmcs_readl(GUEST_RSP);
+               break;
+       case VCPU_REGS_RIP:
+               vcpu->arch.regs[VCPU_REGS_RIP] = vmcs_readl(GUEST_RIP);
+               break;
+       default:
+               break;
+       }
 }
 
 static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
@@ -1007,17 +1025,9 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg)
 
 static int vmx_get_irq(struct kvm_vcpu *vcpu)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 idtv_info_field;
-
-       idtv_info_field = vmx->idt_vectoring_info;
-       if (idtv_info_field & INTR_INFO_VALID_MASK) {
-               if (is_external_interrupt(idtv_info_field))
-                       return idtv_info_field & VECTORING_INFO_VECTOR_MASK;
-               else
-                       printk(KERN_DEBUG "pending exception: not handled yet\n");
-       }
-       return -1;
+       if (!vcpu->arch.interrupt.pending)
+               return -1;
+       return vcpu->arch.interrupt.nr;
 }
 
 static __init int cpu_has_kvm_support(void)
@@ -1031,9 +1041,9 @@ static __init int vmx_disabled_by_bios(void)
        u64 msr;
 
        rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
-       return (msr & (MSR_IA32_FEATURE_CONTROL_LOCKED |
-                      MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
-           == MSR_IA32_FEATURE_CONTROL_LOCKED;
+       return (msr & (FEATURE_CONTROL_LOCKED |
+                      FEATURE_CONTROL_VMXON_ENABLED))
+           == FEATURE_CONTROL_LOCKED;
        /* locked but not enabled */
 }
 
@@ -1045,14 +1055,14 @@ static void hardware_enable(void *garbage)
 
        INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
        rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-       if ((old & (MSR_IA32_FEATURE_CONTROL_LOCKED |
-                   MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
-           != (MSR_IA32_FEATURE_CONTROL_LOCKED |
-               MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED))
+       if ((old & (FEATURE_CONTROL_LOCKED |
+                   FEATURE_CONTROL_VMXON_ENABLED))
+           != (FEATURE_CONTROL_LOCKED |
+               FEATURE_CONTROL_VMXON_ENABLED))
                /* enable and lock */
                wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
-                      MSR_IA32_FEATURE_CONTROL_LOCKED |
-                      MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED);
+                      FEATURE_CONTROL_LOCKED |
+                      FEATURE_CONTROL_VMXON_ENABLED);
        write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug safe */
        asm volatile (ASM_VMX_VMXON_RAX
                      : : "a"(&phys_addr), "m"(phys_addr)
@@ -1120,7 +1130,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
              CPU_BASED_CR3_STORE_EXITING |
              CPU_BASED_USE_IO_BITMAPS |
              CPU_BASED_MOV_DR_EXITING |
-             CPU_BASED_USE_TSC_OFFSETING;
+             CPU_BASED_USE_TSC_OFFSETING |
+             CPU_BASED_INVLPG_EXITING;
        opt = CPU_BASED_TPR_SHADOW |
              CPU_BASED_USE_MSR_BITMAPS |
              CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
@@ -1149,9 +1160,11 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                _cpu_based_exec_control &= ~CPU_BASED_TPR_SHADOW;
 #endif
        if (_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_EPT) {
-               /* CR3 accesses don't need to cause VM Exits when EPT enabled */
+               /* CR3 accesses and invlpg don't need to cause VM Exits when EPT
+                  enabled */
                min &= ~(CPU_BASED_CR3_LOAD_EXITING |
-                        CPU_BASED_CR3_STORE_EXITING);
+                        CPU_BASED_CR3_STORE_EXITING |
+                        CPU_BASED_INVLPG_EXITING);
                if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
                                        &_cpu_based_exec_control) < 0)
                        return -EIO;
@@ -1288,7 +1301,9 @@ static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
 static void enter_pmode(struct kvm_vcpu *vcpu)
 {
        unsigned long flags;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       vmx->emulation_required = 1;
        vcpu->arch.rmode.active = 0;
 
        vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base);
@@ -1305,6 +1320,9 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 
        update_exception_bitmap(vcpu);
 
+       if (emulate_invalid_guest_state)
+               return;
+
        fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
        fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
        fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
@@ -1345,7 +1363,9 @@ static void fix_rmode_seg(int seg, struct kvm_save_segment *save)
 static void enter_rmode(struct kvm_vcpu *vcpu)
 {
        unsigned long flags;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       vmx->emulation_required = 1;
        vcpu->arch.rmode.active = 1;
 
        vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
@@ -1367,6 +1387,9 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
        update_exception_bitmap(vcpu);
 
+       if (emulate_invalid_guest_state)
+               goto continue_rmode;
+
        vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
        vmcs_write32(GUEST_SS_LIMIT, 0xffff);
        vmcs_write32(GUEST_SS_AR_BYTES, 0xf3);
@@ -1382,6 +1405,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        fix_rmode_seg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
        fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
 
+continue_rmode:
        kvm_mmu_reset_context(vcpu);
        init_rmode(vcpu->kvm);
 }
@@ -1715,6 +1739,186 @@ static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
        vmcs_writel(GUEST_GDTR_BASE, dt->base);
 }
 
+static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_segment var;
+       u32 ar;
+
+       vmx_get_segment(vcpu, &var, seg);
+       ar = vmx_segment_access_rights(&var);
+
+       if (var.base != (var.selector << 4))
+               return false;
+       if (var.limit != 0xffff)
+               return false;
+       if (ar != 0xf3)
+               return false;
+
+       return true;
+}
+
+static bool code_segment_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment cs;
+       unsigned int cs_rpl;
+
+       vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+       cs_rpl = cs.selector & SELECTOR_RPL_MASK;
+
+       if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK))
+               return false;
+       if (!cs.s)
+               return false;
+       if (!(~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK))) {
+               if (cs.dpl > cs_rpl)
+                       return false;
+       } else if (cs.type & AR_TYPE_CODE_MASK) {
+               if (cs.dpl != cs_rpl)
+                       return false;
+       }
+       if (!cs.present)
+               return false;
+
+       /* TODO: Add Reserved field check, this'll require a new member in the kvm_segment_field structure */
+       return true;
+}
+
+static bool stack_segment_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment ss;
+       unsigned int ss_rpl;
+
+       vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+       ss_rpl = ss.selector & SELECTOR_RPL_MASK;
+
+       if ((ss.type != 3) || (ss.type != 7))
+               return false;
+       if (!ss.s)
+               return false;
+       if (ss.dpl != ss_rpl) /* DPL != RPL */
+               return false;
+       if (!ss.present)
+               return false;
+
+       return true;
+}
+
+static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+       struct kvm_segment var;
+       unsigned int rpl;
+
+       vmx_get_segment(vcpu, &var, seg);
+       rpl = var.selector & SELECTOR_RPL_MASK;
+
+       if (!var.s)
+               return false;
+       if (!var.present)
+               return false;
+       if (~var.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK)) {
+               if (var.dpl < rpl) /* DPL < RPL */
+                       return false;
+       }
+
+       /* TODO: Add other members to kvm_segment_field to allow checking for other access
+        * rights flags
+        */
+       return true;
+}
+
+static bool tr_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment tr;
+
+       vmx_get_segment(vcpu, &tr, VCPU_SREG_TR);
+
+       if (tr.selector & SELECTOR_TI_MASK)     /* TI = 1 */
+               return false;
+       if ((tr.type != 3) || (tr.type != 11)) /* TODO: Check if guest is in IA32e mode */
+               return false;
+       if (!tr.present)
+               return false;
+
+       return true;
+}
+
+static bool ldtr_valid(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment ldtr;
+
+       vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR);
+
+       if (ldtr.selector & SELECTOR_TI_MASK)   /* TI = 1 */
+               return false;
+       if (ldtr.type != 2)
+               return false;
+       if (!ldtr.present)
+               return false;
+
+       return true;
+}
+
+static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
+{
+       struct kvm_segment cs, ss;
+
+       vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+       vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+
+       return ((cs.selector & SELECTOR_RPL_MASK) ==
+                (ss.selector & SELECTOR_RPL_MASK));
+}
+
+/*
+ * Check if guest state is valid. Returns true if valid, false if
+ * not.
+ * We assume that registers are always usable
+ */
+static bool guest_state_valid(struct kvm_vcpu *vcpu)
+{
+       /* real mode guest state checks */
+       if (!(vcpu->arch.cr0 & X86_CR0_PE)) {
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_DS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_ES))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_FS))
+                       return false;
+               if (!rmode_segment_valid(vcpu, VCPU_SREG_GS))
+                       return false;
+       } else {
+       /* protected mode guest state checks */
+               if (!cs_ss_rpl_check(vcpu))
+                       return false;
+               if (!code_segment_valid(vcpu))
+                       return false;
+               if (!stack_segment_valid(vcpu))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_DS))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_ES))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_FS))
+                       return false;
+               if (!data_segment_valid(vcpu, VCPU_SREG_GS))
+                       return false;
+               if (!tr_valid(vcpu))
+                       return false;
+               if (!ldtr_valid(vcpu))
+                       return false;
+       }
+       /* TODO:
+        * - Add checks on RIP
+        * - Add checks on RFLAGS
+        */
+
+       return true;
+}
+
 static int init_rmode_tss(struct kvm *kvm)
 {
        gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
@@ -1726,7 +1930,8 @@ static int init_rmode_tss(struct kvm *kvm)
        if (r < 0)
                goto out;
        data = TSS_BASE_SIZE + TSS_REDIRECTION_SIZE;
-       r = kvm_write_guest_page(kvm, fn++, &data, 0x66, sizeof(u16));
+       r = kvm_write_guest_page(kvm, fn++, &data,
+                       TSS_IOPB_BASE_OFFSET, sizeof(u16));
        if (r < 0)
                goto out;
        r = kvm_clear_guest_page(kvm, fn++, 0, PAGE_SIZE);
@@ -1789,7 +1994,7 @@ static void seg_setup(int seg)
        vmcs_write16(sf->selector, 0);
        vmcs_writel(sf->base, 0);
        vmcs_write32(sf->limit, 0xffff);
-       vmcs_write32(sf->ar_bytes, 0x93);
+       vmcs_write32(sf->ar_bytes, 0xf3);
 }
 
 static int alloc_apic_access_page(struct kvm *kvm)
@@ -1808,9 +2013,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
        if (r)
                goto out;
 
-       down_read(&current->mm->mmap_sem);
        kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
-       up_read(&current->mm->mmap_sem);
 out:
        up_write(&kvm->slots_lock);
        return r;
@@ -1832,10 +2035,8 @@ static int alloc_identity_pagetable(struct kvm *kvm)
        if (r)
                goto out;
 
-       down_read(&current->mm->mmap_sem);
        kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
                        VMX_EPT_IDENTITY_PAGETABLE_ADDR >> PAGE_SHIFT);
-       up_read(&current->mm->mmap_sem);
 out:
        up_write(&kvm->slots_lock);
        return r;
@@ -1917,7 +2118,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        }
        if (!vm_need_ept())
                exec_control |= CPU_BASED_CR3_STORE_EXITING |
-                               CPU_BASED_CR3_LOAD_EXITING;
+                               CPU_BASED_CR3_LOAD_EXITING  |
+                               CPU_BASED_INVLPG_EXITING;
        vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
 
        if (cpu_has_secondary_exec_ctrls()) {
@@ -2019,6 +2221,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
        u64 msr;
        int ret;
 
+       vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
        down_read(&vcpu->kvm->slots_lock);
        if (!init_rmode(vmx->vcpu.kvm)) {
                ret = -ENOMEM;
@@ -2036,6 +2239,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        fx_init(&vmx->vcpu);
 
+       seg_setup(VCPU_SREG_CS);
        /*
         * GUEST_CS_BASE should really be 0xffff0000, but VT vm86 mode
         * insists on having GUEST_CS_BASE == GUEST_CS_SELECTOR << 4.  Sigh.
@@ -2047,8 +2251,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                vmcs_write16(GUEST_CS_SELECTOR, vmx->vcpu.arch.sipi_vector << 8);
                vmcs_writel(GUEST_CS_BASE, vmx->vcpu.arch.sipi_vector << 12);
        }
-       vmcs_write32(GUEST_CS_LIMIT, 0xffff);
-       vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
 
        seg_setup(VCPU_SREG_DS);
        seg_setup(VCPU_SREG_ES);
@@ -2072,10 +2274,10 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        vmcs_writel(GUEST_RFLAGS, 0x02);
        if (vmx->vcpu.vcpu_id == 0)
-               vmcs_writel(GUEST_RIP, 0xfff0);
+               kvm_rip_write(vcpu, 0xfff0);
        else
-               vmcs_writel(GUEST_RIP, 0);
-       vmcs_writel(GUEST_RSP, 0);
+               kvm_rip_write(vcpu, 0);
+       kvm_register_write(vcpu, VCPU_REGS_RSP, 0);
 
        /* todo: dr0 = dr1 = dr2 = dr3 = 0; dr6 = 0xffff0ff0 */
        vmcs_writel(GUEST_DR7, 0x400);
@@ -2125,6 +2327,9 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 
        ret = 0;
 
+       /* HACK: Don't enable emulation on guest boot/reset */
+       vmx->emulation_required = 0;
+
 out:
        up_read(&vcpu->kvm->slots_lock);
        return ret;
@@ -2136,14 +2341,15 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
 
        KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
 
+       ++vcpu->stat.irq_injections;
        if (vcpu->arch.rmode.active) {
                vmx->rmode.irq.pending = true;
                vmx->rmode.irq.vector = irq;
-               vmx->rmode.irq.rip = vmcs_readl(GUEST_RIP);
+               vmx->rmode.irq.rip = kvm_rip_read(vcpu);
                vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                             irq | INTR_TYPE_SOFT_INTR | INTR_INFO_VALID_MASK);
                vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
-               vmcs_writel(GUEST_RIP, vmx->rmode.irq.rip - 1);
+               kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
                return;
        }
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
@@ -2154,7 +2360,6 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 {
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
                        INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-       vcpu->arch.nmi_pending = 0;
 }
 
 static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
@@ -2166,7 +2371,7 @@ static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
        clear_bit(bit_index, &vcpu->arch.irq_pending[word_index]);
        if (!vcpu->arch.irq_pending[word_index])
                clear_bit(word_index, &vcpu->arch.irq_summary);
-       vmx_inject_irq(vcpu, irq);
+       kvm_queue_interrupt(vcpu, irq);
 }
 
 
@@ -2180,13 +2385,12 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
                 (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
 
        if (vcpu->arch.interrupt_window_open &&
-           vcpu->arch.irq_summary &&
-           !(vmcs_read32(VM_ENTRY_INTR_INFO_FIELD) & INTR_INFO_VALID_MASK))
-               /*
-                * If interrupts enabled, and not blocked by sti or mov ss. Good.
-                */
+           vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
                kvm_do_inject_irq(vcpu);
 
+       if (vcpu->arch.interrupt_window_open && vcpu->arch.interrupt.pending)
+               vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+
        cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
        if (!vcpu->arch.interrupt_window_open &&
            (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
@@ -2237,9 +2441,6 @@ static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu)
 static int handle_rmode_exception(struct kvm_vcpu *vcpu,
                                  int vec, u32 err_code)
 {
-       if (!vcpu->arch.rmode.active)
-               return 0;
-
        /*
         * Instruction with address size override prefix opcode 0x67
         * Cause the #SS fault with 0 error code in VM86 mode.
@@ -2247,6 +2448,25 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
        if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
                if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
                        return 1;
+       /*
+        * Forward all other exceptions that are valid in real mode.
+        * FIXME: Breaks guest debugging in real mode, needs to be fixed with
+        *        the required debugging infrastructure rework.
+        */
+       switch (vec) {
+       case DE_VECTOR:
+       case DB_VECTOR:
+       case BP_VECTOR:
+       case OF_VECTOR:
+       case BR_VECTOR:
+       case UD_VECTOR:
+       case DF_VECTOR:
+       case SS_VECTOR:
+       case GP_VECTOR:
+       case MF_VECTOR:
+               kvm_queue_exception(vcpu, vec);
+               return 1;
+       }
        return 0;
 }
 
@@ -2288,7 +2508,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        }
 
        error_code = 0;
-       rip = vmcs_readl(GUEST_RIP);
+       rip = kvm_rip_read(vcpu);
        if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
        if (is_page_fault(intr_info)) {
@@ -2298,7 +2518,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
                KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2,
                            (u32)((u64)cr2 >> 32), handler);
-               if (vect_info & VECTORING_INFO_VALID_MASK)
+               if (vcpu->arch.interrupt.pending || vcpu->arch.exception.pending)
                        kvm_mmu_unprotect_page_virt(vcpu, cr2);
                return kvm_mmu_page_fault(vcpu, cr2, error_code);
        }
@@ -2386,27 +2606,25 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        reg = (exit_qualification >> 8) & 15;
        switch ((exit_qualification >> 4) & 3) {
        case 0: /* mov to cr */
-               KVMTRACE_3D(CR_WRITE, vcpu, (u32)cr, (u32)vcpu->arch.regs[reg],
-                           (u32)((u64)vcpu->arch.regs[reg] >> 32), handler);
+               KVMTRACE_3D(CR_WRITE, vcpu, (u32)cr,
+                           (u32)kvm_register_read(vcpu, reg),
+                           (u32)((u64)kvm_register_read(vcpu, reg) >> 32),
+                           handler);
                switch (cr) {
                case 0:
-                       vcpu_load_rsp_rip(vcpu);
-                       kvm_set_cr0(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr0(vcpu, kvm_register_read(vcpu, reg));
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 3:
-                       vcpu_load_rsp_rip(vcpu);
-                       kvm_set_cr3(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr3(vcpu, kvm_register_read(vcpu, reg));
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 4:
-                       vcpu_load_rsp_rip(vcpu);
-                       kvm_set_cr4(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr4(vcpu, kvm_register_read(vcpu, reg));
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 8:
-                       vcpu_load_rsp_rip(vcpu);
-                       kvm_set_cr8(vcpu, vcpu->arch.regs[reg]);
+                       kvm_set_cr8(vcpu, kvm_register_read(vcpu, reg));
                        skip_emulated_instruction(vcpu);
                        if (irqchip_in_kernel(vcpu->kvm))
                                return 1;
@@ -2415,7 +2633,6 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                };
                break;
        case 2: /* clts */
-               vcpu_load_rsp_rip(vcpu);
                vmx_fpu_deactivate(vcpu);
                vcpu->arch.cr0 &= ~X86_CR0_TS;
                vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
@@ -2426,21 +2643,17 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        case 1: /*mov from cr*/
                switch (cr) {
                case 3:
-                       vcpu_load_rsp_rip(vcpu);
-                       vcpu->arch.regs[reg] = vcpu->arch.cr3;
-                       vcpu_put_rsp_rip(vcpu);
+                       kvm_register_write(vcpu, reg, vcpu->arch.cr3);
                        KVMTRACE_3D(CR_READ, vcpu, (u32)cr,
-                                   (u32)vcpu->arch.regs[reg],
-                                   (u32)((u64)vcpu->arch.regs[reg] >> 32),
+                                   (u32)kvm_register_read(vcpu, reg),
+                                   (u32)((u64)kvm_register_read(vcpu, reg) >> 32),
                                    handler);
                        skip_emulated_instruction(vcpu);
                        return 1;
                case 8:
-                       vcpu_load_rsp_rip(vcpu);
-                       vcpu->arch.regs[reg] = kvm_get_cr8(vcpu);
-                       vcpu_put_rsp_rip(vcpu);
+                       kvm_register_write(vcpu, reg, kvm_get_cr8(vcpu));
                        KVMTRACE_2D(CR_READ, vcpu, (u32)cr,
-                                   (u32)vcpu->arch.regs[reg], handler);
+                                   (u32)kvm_register_read(vcpu, reg), handler);
                        skip_emulated_instruction(vcpu);
                        return 1;
                }
@@ -2472,7 +2685,6 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
        dr = exit_qualification & 7;
        reg = (exit_qualification >> 8) & 15;
-       vcpu_load_rsp_rip(vcpu);
        if (exit_qualification & 16) {
                /* mov from dr */
                switch (dr) {
@@ -2485,12 +2697,11 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                default:
                        val = 0;
                }
-               vcpu->arch.regs[reg] = val;
+               kvm_register_write(vcpu, reg, val);
                KVMTRACE_2D(DR_READ, vcpu, (u32)dr, (u32)val, handler);
        } else {
                /* mov to dr */
        }
-       vcpu_put_rsp_rip(vcpu);
        skip_emulated_instruction(vcpu);
        return 1;
 }
@@ -2583,6 +2794,15 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       u64 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+
+       kvm_mmu_invlpg(vcpu, exit_qualification);
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
 static int handle_wbinvd(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        skip_emulated_instruction(vcpu);
@@ -2695,6 +2915,43 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
+                               struct kvm_run *kvm_run)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       int err;
+
+       preempt_enable();
+       local_irq_enable();
+
+       while (!guest_state_valid(vcpu)) {
+               err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
+
+               switch (err) {
+                       case EMULATE_DONE:
+                               break;
+                       case EMULATE_DO_MMIO:
+                               kvm_report_emulation_failure(vcpu, "mmio");
+                               /* TODO: Handle MMIO */
+                               return;
+                       default:
+                               kvm_report_emulation_failure(vcpu, "emulation failure");
+                               return;
+               }
+
+               if (signal_pending(current))
+                       break;
+               if (need_resched())
+                       schedule();
+       }
+
+       local_irq_disable();
+       preempt_disable();
+
+       /* Guest state should be valid now, no more emulation should be needed */
+       vmx->emulation_required = 0;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -2714,6 +2971,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
        [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
        [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
        [EXIT_REASON_HLT]                     = handle_halt,
+       [EXIT_REASON_INVLPG]                  = handle_invlpg,
        [EXIT_REASON_VMCALL]                  = handle_vmcall,
        [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
        [EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
@@ -2735,8 +2993,8 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 vectoring_info = vmx->idt_vectoring_info;
 
-       KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)vmcs_readl(GUEST_RIP),
-                   (u32)((u64)vmcs_readl(GUEST_RIP) >> 32), entryexit);
+       KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu),
+                   (u32)((u64)kvm_rip_read(vcpu) >> 32), entryexit);
 
        /* Access CR3 don't cause VMExit in paging mode, so we need
         * to sync with guest real CR3. */
@@ -2829,88 +3087,92 @@ static void enable_intr_window(struct kvm_vcpu *vcpu)
                enable_irq_window(vcpu);
 }
 
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
+static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 idtv_info_field, intr_info_field, exit_intr_info_field;
-       int vector;
+       u32 exit_intr_info;
+       u32 idt_vectoring_info;
+       bool unblock_nmi;
+       u8 vector;
+       int type;
+       bool idtv_info_valid;
+       u32 error;
 
-       update_tpr_threshold(vcpu);
-
-       intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
-       exit_intr_info_field = vmcs_read32(VM_EXIT_INTR_INFO);
-       idtv_info_field = vmx->idt_vectoring_info;
-       if (intr_info_field & INTR_INFO_VALID_MASK) {
-               if (idtv_info_field & INTR_INFO_VALID_MASK) {
-                       /* TODO: fault when IDT_Vectoring */
-                       if (printk_ratelimit())
-                               printk(KERN_ERR "Fault when IDT_Vectoring\n");
-               }
-               enable_intr_window(vcpu);
-               return;
+       exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+       if (cpu_has_virtual_nmis()) {
+               unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
+               vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
+               /*
+                * SDM 3: 25.7.1.2
+                * Re-set bit "block by NMI" before VM entry if vmexit caused by
+                * a guest IRET fault.
+                */
+               if (unblock_nmi && vector != DF_VECTOR)
+                       vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+                                     GUEST_INTR_STATE_NMI);
        }
-       if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) {
-               if ((idtv_info_field & VECTORING_INFO_TYPE_MASK)
-                   == INTR_TYPE_EXT_INTR
-                   && vcpu->arch.rmode.active) {
-                       u8 vect = idtv_info_field & VECTORING_INFO_VECTOR_MASK;
-
-                       vmx_inject_irq(vcpu, vect);
-                       enable_intr_window(vcpu);
-                       return;
-               }
-
-               KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler);
 
+       idt_vectoring_info = vmx->idt_vectoring_info;
+       idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
+       vector = idt_vectoring_info & VECTORING_INFO_VECTOR_MASK;
+       type = idt_vectoring_info & VECTORING_INFO_TYPE_MASK;
+       if (vmx->vcpu.arch.nmi_injected) {
                /*
                 * SDM 3: 25.7.1.2
                 * Clear bit "block by NMI" before VM entry if a NMI delivery
                 * faulted.
                 */
-               if ((idtv_info_field & VECTORING_INFO_TYPE_MASK)
-                   == INTR_TYPE_NMI_INTR && cpu_has_virtual_nmis())
-                       vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
-                               vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
-                               ~GUEST_INTR_STATE_NMI);
-
-               vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field
-                               & ~INTR_INFO_RESVD_BITS_MASK);
-               vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
-                               vmcs_read32(VM_EXIT_INSTRUCTION_LEN));
-
-               if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK))
-                       vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
-                               vmcs_read32(IDT_VECTORING_ERROR_CODE));
-               enable_intr_window(vcpu);
-               return;
+               if (idtv_info_valid && type == INTR_TYPE_NMI_INTR)
+                       vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+                                       GUEST_INTR_STATE_NMI);
+               else
+                       vmx->vcpu.arch.nmi_injected = false;
+       }
+       kvm_clear_exception_queue(&vmx->vcpu);
+       if (idtv_info_valid && type == INTR_TYPE_EXCEPTION) {
+               if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
+                       error = vmcs_read32(IDT_VECTORING_ERROR_CODE);
+                       kvm_queue_exception_e(&vmx->vcpu, vector, error);
+               } else
+                       kvm_queue_exception(&vmx->vcpu, vector);
+               vmx->idt_vectoring_info = 0;
        }
+       kvm_clear_interrupt_queue(&vmx->vcpu);
+       if (idtv_info_valid && type == INTR_TYPE_EXT_INTR) {
+               kvm_queue_interrupt(&vmx->vcpu, vector);
+               vmx->idt_vectoring_info = 0;
+       }
+}
+
+static void vmx_intr_assist(struct kvm_vcpu *vcpu)
+{
+       update_tpr_threshold(vcpu);
+
        if (cpu_has_virtual_nmis()) {
-               /*
-                * SDM 3: 25.7.1.2
-                * Re-set bit "block by NMI" before VM entry if vmexit caused by
-                * a guest IRET fault.
-                */
-               if ((exit_intr_info_field & INTR_INFO_UNBLOCK_NMI) &&
-                   (exit_intr_info_field & INTR_INFO_VECTOR_MASK) != 8)
-                       vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
-                               vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) |
-                               GUEST_INTR_STATE_NMI);
-               else if (vcpu->arch.nmi_pending) {
-                       if (vmx_nmi_enabled(vcpu))
-                               vmx_inject_nmi(vcpu);
+               if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
+                       if (vmx_nmi_enabled(vcpu)) {
+                               vcpu->arch.nmi_pending = false;
+                               vcpu->arch.nmi_injected = true;
+                       } else {
+                               enable_intr_window(vcpu);
+                               return;
+                       }
+               }
+               if (vcpu->arch.nmi_injected) {
+                       vmx_inject_nmi(vcpu);
                        enable_intr_window(vcpu);
                        return;
                }
-
        }
-       if (!kvm_cpu_has_interrupt(vcpu))
-               return;
-       if (vmx_irq_enabled(vcpu)) {
-               vector = kvm_cpu_get_interrupt(vcpu);
-               vmx_inject_irq(vcpu, vector);
-               kvm_timer_intr_post(vcpu, vector);
-       } else
-               enable_irq_window(vcpu);
+       if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
+               if (vmx_irq_enabled(vcpu))
+                       kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+               else
+                       enable_irq_window(vcpu);
+       }
+       if (vcpu->arch.interrupt.pending) {
+               vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+               kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
+       }
 }
 
 /*
@@ -2922,9 +3184,9 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
 static void fixup_rmode_irq(struct vcpu_vmx *vmx)
 {
        vmx->rmode.irq.pending = 0;
-       if (vmcs_readl(GUEST_RIP) + 1 != vmx->rmode.irq.rip)
+       if (kvm_rip_read(&vmx->vcpu) + 1 != vmx->rmode.irq.rip)
                return;
-       vmcs_writel(GUEST_RIP, vmx->rmode.irq.rip);
+       kvm_rip_write(&vmx->vcpu, vmx->rmode.irq.rip);
        if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) {
                vmx->idt_vectoring_info &= ~VECTORING_INFO_TYPE_MASK;
                vmx->idt_vectoring_info |= INTR_TYPE_EXT_INTR;
@@ -2936,11 +3198,30 @@ static void fixup_rmode_irq(struct vcpu_vmx *vmx)
                | vmx->rmode.irq.vector;
 }
 
+#ifdef CONFIG_X86_64
+#define R "r"
+#define Q "q"
+#else
+#define R "e"
+#define Q "l"
+#endif
+
 static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 intr_info;
 
+       /* Handle invalid guest state instead of entering VMX */
+       if (vmx->emulation_required && emulate_invalid_guest_state) {
+               handle_invalid_guest_state(vcpu, kvm_run);
+               return;
+       }
+
+       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
+       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+
        /*
         * Loading guest fpu may have cleared host cr0.ts
         */
@@ -2948,26 +3229,25 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        asm(
                /* Store host registers */
-#ifdef CONFIG_X86_64
-               "push %%rdx; push %%rbp;"
-               "push %%rcx \n\t"
-#else
-               "push %%edx; push %%ebp;"
-               "push %%ecx \n\t"
-#endif
+               "push %%"R"dx; push %%"R"bp;"
+               "push %%"R"cx \n\t"
+               "cmp %%"R"sp, %c[host_rsp](%0) \n\t"
+               "je 1f \n\t"
+               "mov %%"R"sp, %c[host_rsp](%0) \n\t"
                __ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"
+               "1: \n\t"
                /* Check if vmlaunch of vmresume is needed */
                "cmpl $0, %c[launched](%0) \n\t"
                /* Load guest registers.  Don't clobber flags. */
+               "mov %c[cr2](%0), %%"R"ax \n\t"
+               "mov %%"R"ax, %%cr2 \n\t"
+               "mov %c[rax](%0), %%"R"ax \n\t"
+               "mov %c[rbx](%0), %%"R"bx \n\t"
+               "mov %c[rdx](%0), %%"R"dx \n\t"
+               "mov %c[rsi](%0), %%"R"si \n\t"
+               "mov %c[rdi](%0), %%"R"di \n\t"
+               "mov %c[rbp](%0), %%"R"bp \n\t"
 #ifdef CONFIG_X86_64
-               "mov %c[cr2](%0), %%rax \n\t"
-               "mov %%rax, %%cr2 \n\t"
-               "mov %c[rax](%0), %%rax \n\t"
-               "mov %c[rbx](%0), %%rbx \n\t"
-               "mov %c[rdx](%0), %%rdx \n\t"
-               "mov %c[rsi](%0), %%rsi \n\t"
-               "mov %c[rdi](%0), %%rdi \n\t"
-               "mov %c[rbp](%0), %%rbp \n\t"
                "mov %c[r8](%0),  %%r8  \n\t"
                "mov %c[r9](%0),  %%r9  \n\t"
                "mov %c[r10](%0), %%r10 \n\t"
@@ -2976,18 +3256,9 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %c[r13](%0), %%r13 \n\t"
                "mov %c[r14](%0), %%r14 \n\t"
                "mov %c[r15](%0), %%r15 \n\t"
-               "mov %c[rcx](%0), %%rcx \n\t" /* kills %0 (rcx) */
-#else
-               "mov %c[cr2](%0), %%eax \n\t"
-               "mov %%eax,   %%cr2 \n\t"
-               "mov %c[rax](%0), %%eax \n\t"
-               "mov %c[rbx](%0), %%ebx \n\t"
-               "mov %c[rdx](%0), %%edx \n\t"
-               "mov %c[rsi](%0), %%esi \n\t"
-               "mov %c[rdi](%0), %%edi \n\t"
-               "mov %c[rbp](%0), %%ebp \n\t"
-               "mov %c[rcx](%0), %%ecx \n\t" /* kills %0 (ecx) */
 #endif
+               "mov %c[rcx](%0), %%"R"cx \n\t" /* kills %0 (ecx) */
+
                /* Enter guest mode */
                "jne .Llaunched \n\t"
                __ex(ASM_VMX_VMLAUNCH) "\n\t"
@@ -2995,15 +3266,15 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
                ".Lkvm_vmx_return: "
                /* Save guest registers, load host registers, keep flags */
+               "xchg %0,     (%%"R"sp) \n\t"
+               "mov %%"R"ax, %c[rax](%0) \n\t"
+               "mov %%"R"bx, %c[rbx](%0) \n\t"
+               "push"Q" (%%"R"sp); pop"Q" %c[rcx](%0) \n\t"
+               "mov %%"R"dx, %c[rdx](%0) \n\t"
+               "mov %%"R"si, %c[rsi](%0) \n\t"
+               "mov %%"R"di, %c[rdi](%0) \n\t"
+               "mov %%"R"bp, %c[rbp](%0) \n\t"
 #ifdef CONFIG_X86_64
-               "xchg %0,     (%%rsp) \n\t"
-               "mov %%rax, %c[rax](%0) \n\t"
-               "mov %%rbx, %c[rbx](%0) \n\t"
-               "pushq (%%rsp); popq %c[rcx](%0) \n\t"
-               "mov %%rdx, %c[rdx](%0) \n\t"
-               "mov %%rsi, %c[rsi](%0) \n\t"
-               "mov %%rdi, %c[rdi](%0) \n\t"
-               "mov %%rbp, %c[rbp](%0) \n\t"
                "mov %%r8,  %c[r8](%0) \n\t"
                "mov %%r9,  %c[r9](%0) \n\t"
                "mov %%r10, %c[r10](%0) \n\t"
@@ -3012,28 +3283,16 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                "mov %%r13, %c[r13](%0) \n\t"
                "mov %%r14, %c[r14](%0) \n\t"
                "mov %%r15, %c[r15](%0) \n\t"
-               "mov %%cr2, %%rax   \n\t"
-               "mov %%rax, %c[cr2](%0) \n\t"
-
-               "pop  %%rbp; pop  %%rbp; pop  %%rdx \n\t"
-#else
-               "xchg %0, (%%esp) \n\t"
-               "mov %%eax, %c[rax](%0) \n\t"
-               "mov %%ebx, %c[rbx](%0) \n\t"
-               "pushl (%%esp); popl %c[rcx](%0) \n\t"
-               "mov %%edx, %c[rdx](%0) \n\t"
-               "mov %%esi, %c[rsi](%0) \n\t"
-               "mov %%edi, %c[rdi](%0) \n\t"
-               "mov %%ebp, %c[rbp](%0) \n\t"
-               "mov %%cr2, %%eax  \n\t"
-               "mov %%eax, %c[cr2](%0) \n\t"
-
-               "pop %%ebp; pop %%ebp; pop %%edx \n\t"
 #endif
+               "mov %%cr2, %%"R"ax   \n\t"
+               "mov %%"R"ax, %c[cr2](%0) \n\t"
+
+               "pop  %%"R"bp; pop  %%"R"bp; pop  %%"R"dx \n\t"
                "setbe %c[fail](%0) \n\t"
              : : "c"(vmx), "d"((unsigned long)HOST_RSP),
                [launched]"i"(offsetof(struct vcpu_vmx, launched)),
                [fail]"i"(offsetof(struct vcpu_vmx, fail)),
+               [host_rsp]"i"(offsetof(struct vcpu_vmx, host_rsp)),
                [rax]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RAX])),
                [rbx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RBX])),
                [rcx]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_RCX])),
@@ -3053,14 +3312,15 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 #endif
                [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
              : "cc", "memory"
+               , R"bx", R"di", R"si"
 #ifdef CONFIG_X86_64
-               , "rbx", "rdi", "rsi"
                , "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-#else
-               , "ebx", "edi", "rsi"
 #endif
              );
 
+       vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
+       vcpu->arch.regs_dirty = 0;
+
        vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
        if (vmx->rmode.irq.pending)
                fixup_rmode_irq(vmx);
@@ -3080,8 +3340,13 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                KVMTRACE_0D(NMI, vcpu, handler);
                asm("int $2");
        }
+
+       vmx_complete_interrupts(vmx);
 }
 
+#undef R
+#undef Q
+
 static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3224,8 +3489,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .set_idt = vmx_set_idt,
        .get_gdt = vmx_get_gdt,
        .set_gdt = vmx_set_gdt,
-       .cache_regs = vcpu_load_rsp_rip,
-       .decache_regs = vcpu_put_rsp_rip,
+       .cache_reg = vmx_cache_reg,
        .get_rflags = vmx_get_rflags,
        .set_rflags = vmx_set_rflags,
 
index 17e25995b65b62986ec2d4bbff7f7e9ce6d162f6..3e010d21fdd71afdf65cdb086fb158632e391abf 100644 (file)
@@ -331,9 +331,6 @@ enum vmcs_field {
 
 #define AR_RESERVD_MASK 0xfffe0f00
 
-#define MSR_IA32_FEATURE_CONTROL_LOCKED         0x1
-#define MSR_IA32_FEATURE_CONTROL_VMXON_ENABLED  0x4
-
 #define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT       9
 #define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT     10
 
index 0d682fc6aeb333c382e6b9324105e2eb941bc545..4f0677d1eae8f495147b2184474f5806c81303bd 100644 (file)
@@ -4,10 +4,14 @@
  * derived from drivers/kvm/kvm_main.c
  *
  * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright (C) 2008 Qumranet, Inc.
+ * Copyright IBM Corporation, 2008
  *
  * Authors:
  *   Avi Kivity   <avi@qumranet.com>
  *   Yaniv Kamay  <yaniv@qumranet.com>
+ *   Amit Shah    <amit.shah@qumranet.com>
+ *   Ben-Ami Yassour <benami@il.ibm.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
 #include "mmu.h"
 #include "i8254.h"
 #include "tss.h"
+#include "kvm_cache_regs.h"
+#include "x86.h"
 
 #include <linux/clocksource.h>
+#include <linux/interrupt.h>
 #include <linux/kvm.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/highmem.h>
+#include <linux/intel-iommu.h>
 
 #include <asm/uaccess.h>
 #include <asm/msr.h>
@@ -61,6 +69,7 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
                                    struct kvm_cpuid_entry2 __user *entries);
 
 struct kvm_x86_ops *kvm_x86_ops;
+EXPORT_SYMBOL_GPL(kvm_x86_ops);
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "pf_fixed", VCPU_STAT(pf_fixed) },
@@ -83,6 +92,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "fpu_reload", VCPU_STAT(fpu_reload) },
        { "insn_emulation", VCPU_STAT(insn_emulation) },
        { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) },
+       { "irq_injections", VCPU_STAT(irq_injections) },
        { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) },
        { "mmu_pte_write", VM_STAT(mmu_pte_write) },
        { "mmu_pte_updated", VM_STAT(mmu_pte_updated) },
@@ -90,12 +100,12 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "mmu_flooded", VM_STAT(mmu_flooded) },
        { "mmu_recycled", VM_STAT(mmu_recycled) },
        { "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
+       { "mmu_unsync", VM_STAT(mmu_unsync) },
        { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
        { "largepages", VM_STAT(lpages) },
        { NULL }
 };
 
-
 unsigned long segment_base(u16 selector)
 {
        struct descriptor_table gdt;
@@ -352,6 +362,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
 void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
        if (cr3 == vcpu->arch.cr3 && !pdptrs_changed(vcpu)) {
+               kvm_mmu_sync_roots(vcpu);
                kvm_mmu_flush_tlb(vcpu);
                return;
        }
@@ -564,7 +575,7 @@ static void kvm_set_time_scale(uint32_t tsc_khz, struct pvclock_vcpu_time_info *
        hv_clock->tsc_to_system_mul = div_frac(nsecs, tps32);
 
        pr_debug("%s: tsc_khz %u, tsc_shift %d, tsc_mul %u\n",
-                __FUNCTION__, tsc_khz, hv_clock->tsc_shift,
+                __func__, tsc_khz, hv_clock->tsc_shift,
                 hv_clock->tsc_to_system_mul);
 }
 
@@ -662,6 +673,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                pr_unimpl(vcpu, "%s: MSR_IA32_MCG_CTL 0x%llx, nop\n",
                        __func__, data);
                break;
+       case MSR_IA32_DEBUGCTLMSR:
+               if (!data) {
+                       /* We support the non-activated case already */
+                       break;
+               } else if (data & ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_BTF)) {
+                       /* Values other than LBR and BTF are vendor-specific,
+                          thus reserved and should throw a #GP */
+                       return 1;
+               }
+               pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
+                       __func__, data);
+               break;
        case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
                break;
@@ -692,10 +715,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                /* ...but clean it before doing the actual write */
                vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
 
-               down_read(&current->mm->mmap_sem);
                vcpu->arch.time_page =
                                gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
-               up_read(&current->mm->mmap_sem);
 
                if (is_error_page(vcpu->arch.time_page)) {
                        kvm_release_page_clean(vcpu->arch.time_page);
@@ -752,8 +773,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_IA32_MC0_MISC+8:
        case MSR_IA32_MC0_MISC+12:
        case MSR_IA32_MC0_MISC+16:
+       case MSR_IA32_MC0_MISC+20:
        case MSR_IA32_UCODE_REV:
        case MSR_IA32_EBL_CR_POWERON:
+       case MSR_IA32_DEBUGCTLMSR:
+       case MSR_IA32_LASTBRANCHFROMIP:
+       case MSR_IA32_LASTBRANCHTOIP:
+       case MSR_IA32_LASTINTFROMIP:
+       case MSR_IA32_LASTINTTOIP:
                data = 0;
                break;
        case MSR_MTRRcap:
@@ -901,6 +928,9 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PV_MMU:
                r = !tdp_enabled;
                break;
+       case KVM_CAP_IOMMU:
+               r = intel_iommu_found();
+               break;
        default:
                r = 0;
                break;
@@ -1303,28 +1333,33 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        struct kvm_vcpu *vcpu = filp->private_data;
        void __user *argp = (void __user *)arg;
        int r;
+       struct kvm_lapic_state *lapic = NULL;
 
        switch (ioctl) {
        case KVM_GET_LAPIC: {
-               struct kvm_lapic_state lapic;
+               lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
 
-               memset(&lapic, 0, sizeof lapic);
-               r = kvm_vcpu_ioctl_get_lapic(vcpu, &lapic);
+               r = -ENOMEM;
+               if (!lapic)
+                       goto out;
+               r = kvm_vcpu_ioctl_get_lapic(vcpu, lapic);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &lapic, sizeof lapic))
+               if (copy_to_user(argp, lapic, sizeof(struct kvm_lapic_state)))
                        goto out;
                r = 0;
                break;
        }
        case KVM_SET_LAPIC: {
-               struct kvm_lapic_state lapic;
-
+               lapic = kmalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
+               r = -ENOMEM;
+               if (!lapic)
+                       goto out;
                r = -EFAULT;
-               if (copy_from_user(&lapic, argp, sizeof lapic))
+               if (copy_from_user(lapic, argp, sizeof(struct kvm_lapic_state)))
                        goto out;
-               r = kvm_vcpu_ioctl_set_lapic(vcpu, &lapic);;
+               r = kvm_vcpu_ioctl_set_lapic(vcpu, lapic);
                if (r)
                        goto out;
                r = 0;
@@ -1422,6 +1457,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = -EINVAL;
        }
 out:
+       if (lapic)
+               kfree(lapic);
        return r;
 }
 
@@ -1630,6 +1667,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
        struct kvm *kvm = filp->private_data;
        void __user *argp = (void __user *)arg;
        int r = -EINVAL;
+       /*
+        * This union makes it completely explicit to gcc-3.x
+        * that these two variables' stack usage should be
+        * combined, not added together.
+        */
+       union {
+               struct kvm_pit_state ps;
+               struct kvm_memory_alias alias;
+       } u;
 
        switch (ioctl) {
        case KVM_SET_TSS_ADDR:
@@ -1661,17 +1707,14 @@ long kvm_arch_vm_ioctl(struct file *filp,
        case KVM_GET_NR_MMU_PAGES:
                r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
                break;
-       case KVM_SET_MEMORY_ALIAS: {
-               struct kvm_memory_alias alias;
-
+       case KVM_SET_MEMORY_ALIAS:
                r = -EFAULT;
-               if (copy_from_user(&alias, argp, sizeof alias))
+               if (copy_from_user(&u.alias, argp, sizeof(struct kvm_memory_alias)))
                        goto out;
-               r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
+               r = kvm_vm_ioctl_set_memory_alias(kvm, &u.alias);
                if (r)
                        goto out;
                break;
-       }
        case KVM_CREATE_IRQCHIP:
                r = -ENOMEM;
                kvm->arch.vpic = kvm_create_pic(kvm);
@@ -1699,13 +1742,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
                        goto out;
                if (irqchip_in_kernel(kvm)) {
                        mutex_lock(&kvm->lock);
-                       if (irq_event.irq < 16)
-                               kvm_pic_set_irq(pic_irqchip(kvm),
-                                       irq_event.irq,
-                                       irq_event.level);
-                       kvm_ioapic_set_irq(kvm->arch.vioapic,
-                                       irq_event.irq,
-                                       irq_event.level);
+                       kvm_set_irq(kvm, irq_event.irq, irq_event.level);
                        mutex_unlock(&kvm->lock);
                        r = 0;
                }
@@ -1713,65 +1750,77 @@ long kvm_arch_vm_ioctl(struct file *filp,
        }
        case KVM_GET_IRQCHIP: {
                /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
-               struct kvm_irqchip chip;
+               struct kvm_irqchip *chip = kmalloc(sizeof(*chip), GFP_KERNEL);
 
-               r = -EFAULT;
-               if (copy_from_user(&chip, argp, sizeof chip))
+               r = -ENOMEM;
+               if (!chip)
                        goto out;
+               r = -EFAULT;
+               if (copy_from_user(chip, argp, sizeof *chip))
+                       goto get_irqchip_out;
                r = -ENXIO;
                if (!irqchip_in_kernel(kvm))
-                       goto out;
-               r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
+                       goto get_irqchip_out;
+               r = kvm_vm_ioctl_get_irqchip(kvm, chip);
                if (r)
-                       goto out;
+                       goto get_irqchip_out;
                r = -EFAULT;
-               if (copy_to_user(argp, &chip, sizeof chip))
-                       goto out;
+               if (copy_to_user(argp, chip, sizeof *chip))
+                       goto get_irqchip_out;
                r = 0;
+       get_irqchip_out:
+               kfree(chip);
+               if (r)
+                       goto out;
                break;
        }
        case KVM_SET_IRQCHIP: {
                /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
-               struct kvm_irqchip chip;
+               struct kvm_irqchip *chip = kmalloc(sizeof(*chip), GFP_KERNEL);
 
-               r = -EFAULT;
-               if (copy_from_user(&chip, argp, sizeof chip))
+               r = -ENOMEM;
+               if (!chip)
                        goto out;
+               r = -EFAULT;
+               if (copy_from_user(chip, argp, sizeof *chip))
+                       goto set_irqchip_out;
                r = -ENXIO;
                if (!irqchip_in_kernel(kvm))
-                       goto out;
-               r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
+                       goto set_irqchip_out;
+               r = kvm_vm_ioctl_set_irqchip(kvm, chip);
                if (r)
-                       goto out;
+                       goto set_irqchip_out;
                r = 0;
+       set_irqchip_out:
+               kfree(chip);
+               if (r)
+                       goto out;
                break;
        }
        case KVM_GET_PIT: {
-               struct kvm_pit_state ps;
                r = -EFAULT;
-               if (copy_from_user(&ps, argp, sizeof ps))
+               if (copy_from_user(&u.ps, argp, sizeof(struct kvm_pit_state)))
                        goto out;
                r = -ENXIO;
                if (!kvm->arch.vpit)
                        goto out;
-               r = kvm_vm_ioctl_get_pit(kvm, &ps);
+               r = kvm_vm_ioctl_get_pit(kvm, &u.ps);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &ps, sizeof ps))
+               if (copy_to_user(argp, &u.ps, sizeof(struct kvm_pit_state)))
                        goto out;
                r = 0;
                break;
        }
        case KVM_SET_PIT: {
-               struct kvm_pit_state ps;
                r = -EFAULT;
-               if (copy_from_user(&ps, argp, sizeof ps))
+               if (copy_from_user(&u.ps, argp, sizeof u.ps))
                        goto out;
                r = -ENXIO;
                if (!kvm->arch.vpit)
                        goto out;
-               r = kvm_vm_ioctl_set_pit(kvm, &ps);
+               r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
                if (r)
                        goto out;
                r = 0;
@@ -2018,9 +2067,7 @@ static int emulator_cmpxchg_emulated(unsigned long addr,
 
                val = *(u64 *)new;
 
-               down_read(&current->mm->mmap_sem);
                page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
-               up_read(&current->mm->mmap_sem);
 
                kaddr = kmap_atomic(page, KM_USER0);
                set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
@@ -2040,6 +2087,7 @@ static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg)
 
 int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address)
 {
+       kvm_mmu_invlpg(vcpu, address);
        return X86EMUL_CONTINUE;
 }
 
@@ -2080,7 +2128,7 @@ int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
 void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
 {
        u8 opcodes[4];
-       unsigned long rip = vcpu->arch.rip;
+       unsigned long rip = kvm_rip_read(vcpu);
        unsigned long rip_linear;
 
        if (!printk_ratelimit())
@@ -2102,6 +2150,14 @@ static struct x86_emulate_ops emulate_ops = {
        .cmpxchg_emulated    = emulator_cmpxchg_emulated,
 };
 
+static void cache_all_regs(struct kvm_vcpu *vcpu)
+{
+       kvm_register_read(vcpu, VCPU_REGS_RAX);
+       kvm_register_read(vcpu, VCPU_REGS_RSP);
+       kvm_register_read(vcpu, VCPU_REGS_RIP);
+       vcpu->arch.regs_dirty = ~0;
+}
+
 int emulate_instruction(struct kvm_vcpu *vcpu,
                        struct kvm_run *run,
                        unsigned long cr2,
@@ -2111,8 +2167,15 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
        int r;
        struct decode_cache *c;
 
+       kvm_clear_exception_queue(vcpu);
        vcpu->arch.mmio_fault_cr2 = cr2;
-       kvm_x86_ops->cache_regs(vcpu);
+       /*
+        * TODO: fix x86_emulate.c to use guest_read/write_register
+        * instead of direct ->regs accesses, can save hundred cycles
+        * on Intel for instructions that don't read/change RSP, for
+        * for example.
+        */
+       cache_all_regs(vcpu);
 
        vcpu->mmio_is_write = 0;
        vcpu->arch.pio.string = 0;
@@ -2172,7 +2235,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
                return EMULATE_DO_MMIO;
        }
 
-       kvm_x86_ops->decache_regs(vcpu);
        kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
 
        if (vcpu->mmio_is_write) {
@@ -2225,20 +2287,19 @@ int complete_pio(struct kvm_vcpu *vcpu)
        struct kvm_pio_request *io = &vcpu->arch.pio;
        long delta;
        int r;
-
-       kvm_x86_ops->cache_regs(vcpu);
+       unsigned long val;
 
        if (!io->string) {
-               if (io->in)
-                       memcpy(&vcpu->arch.regs[VCPU_REGS_RAX], vcpu->arch.pio_data,
-                              io->size);
+               if (io->in) {
+                       val = kvm_register_read(vcpu, VCPU_REGS_RAX);
+                       memcpy(&val, vcpu->arch.pio_data, io->size);
+                       kvm_register_write(vcpu, VCPU_REGS_RAX, val);
+               }
        } else {
                if (io->in) {
                        r = pio_copy_data(vcpu);
-                       if (r) {
-                               kvm_x86_ops->cache_regs(vcpu);
+                       if (r)
                                return r;
-                       }
                }
 
                delta = 1;
@@ -2248,19 +2309,24 @@ int complete_pio(struct kvm_vcpu *vcpu)
                         * The size of the register should really depend on
                         * current address size.
                         */
-                       vcpu->arch.regs[VCPU_REGS_RCX] -= delta;
+                       val = kvm_register_read(vcpu, VCPU_REGS_RCX);
+                       val -= delta;
+                       kvm_register_write(vcpu, VCPU_REGS_RCX, val);
                }
                if (io->down)
                        delta = -delta;
                delta *= io->size;
-               if (io->in)
-                       vcpu->arch.regs[VCPU_REGS_RDI] += delta;
-               else
-                       vcpu->arch.regs[VCPU_REGS_RSI] += delta;
+               if (io->in) {
+                       val = kvm_register_read(vcpu, VCPU_REGS_RDI);
+                       val += delta;
+                       kvm_register_write(vcpu, VCPU_REGS_RDI, val);
+               } else {
+                       val = kvm_register_read(vcpu, VCPU_REGS_RSI);
+                       val += delta;
+                       kvm_register_write(vcpu, VCPU_REGS_RSI, val);
+               }
        }
 
-       kvm_x86_ops->decache_regs(vcpu);
-
        io->count -= io->cur_count;
        io->cur_count = 0;
 
@@ -2313,6 +2379,7 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
                  int size, unsigned port)
 {
        struct kvm_io_device *pio_dev;
+       unsigned long val;
 
        vcpu->run->exit_reason = KVM_EXIT_IO;
        vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
@@ -2333,8 +2400,8 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
                KVMTRACE_2D(IO_WRITE, vcpu, vcpu->run->io.port, (u32)size,
                            handler);
 
-       kvm_x86_ops->cache_regs(vcpu);
-       memcpy(vcpu->arch.pio_data, &vcpu->arch.regs[VCPU_REGS_RAX], 4);
+       val = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       memcpy(vcpu->arch.pio_data, &val, 4);
 
        kvm_x86_ops->skip_emulated_instruction(vcpu);
 
@@ -2492,11 +2559,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
        KVMTRACE_0D(HLT, vcpu, handler);
        if (irqchip_in_kernel(vcpu->kvm)) {
                vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
-               up_read(&vcpu->kvm->slots_lock);
-               kvm_vcpu_block(vcpu);
-               down_read(&vcpu->kvm->slots_lock);
-               if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
-                       return -EINTR;
                return 1;
        } else {
                vcpu->run->exit_reason = KVM_EXIT_HLT;
@@ -2519,13 +2581,11 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        unsigned long nr, a0, a1, a2, a3, ret;
        int r = 1;
 
-       kvm_x86_ops->cache_regs(vcpu);
-
-       nr = vcpu->arch.regs[VCPU_REGS_RAX];
-       a0 = vcpu->arch.regs[VCPU_REGS_RBX];
-       a1 = vcpu->arch.regs[VCPU_REGS_RCX];
-       a2 = vcpu->arch.regs[VCPU_REGS_RDX];
-       a3 = vcpu->arch.regs[VCPU_REGS_RSI];
+       nr = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);
+       a1 = kvm_register_read(vcpu, VCPU_REGS_RCX);
+       a2 = kvm_register_read(vcpu, VCPU_REGS_RDX);
+       a3 = kvm_register_read(vcpu, VCPU_REGS_RSI);
 
        KVMTRACE_1D(VMMCALL, vcpu, (u32)nr, handler);
 
@@ -2548,8 +2608,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
                ret = -KVM_ENOSYS;
                break;
        }
-       vcpu->arch.regs[VCPU_REGS_RAX] = ret;
-       kvm_x86_ops->decache_regs(vcpu);
+       kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
        ++vcpu->stat.hypercalls;
        return r;
 }
@@ -2559,6 +2618,7 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 {
        char instruction[3];
        int ret = 0;
+       unsigned long rip = kvm_rip_read(vcpu);
 
 
        /*
@@ -2568,9 +2628,8 @@ int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
         */
        kvm_mmu_zap_all(vcpu->kvm);
 
-       kvm_x86_ops->cache_regs(vcpu);
        kvm_x86_ops->patch_hypercall(vcpu, instruction);
-       if (emulator_write_emulated(vcpu->arch.rip, instruction, 3, vcpu)
+       if (emulator_write_emulated(rip, instruction, 3, vcpu)
            != X86EMUL_CONTINUE)
                ret = -EFAULT;
 
@@ -2700,13 +2759,12 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
        u32 function, index;
        struct kvm_cpuid_entry2 *e, *best;
 
-       kvm_x86_ops->cache_regs(vcpu);
-       function = vcpu->arch.regs[VCPU_REGS_RAX];
-       index = vcpu->arch.regs[VCPU_REGS_RCX];
-       vcpu->arch.regs[VCPU_REGS_RAX] = 0;
-       vcpu->arch.regs[VCPU_REGS_RBX] = 0;
-       vcpu->arch.regs[VCPU_REGS_RCX] = 0;
-       vcpu->arch.regs[VCPU_REGS_RDX] = 0;
+       function = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       index = kvm_register_read(vcpu, VCPU_REGS_RCX);
+       kvm_register_write(vcpu, VCPU_REGS_RAX, 0);
+       kvm_register_write(vcpu, VCPU_REGS_RBX, 0);
+       kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
+       kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
        best = NULL;
        for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
                e = &vcpu->arch.cpuid_entries[i];
@@ -2724,18 +2782,17 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
                                best = e;
        }
        if (best) {
-               vcpu->arch.regs[VCPU_REGS_RAX] = best->eax;
-               vcpu->arch.regs[VCPU_REGS_RBX] = best->ebx;
-               vcpu->arch.regs[VCPU_REGS_RCX] = best->ecx;
-               vcpu->arch.regs[VCPU_REGS_RDX] = best->edx;
+               kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax);
+               kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx);
+               kvm_register_write(vcpu, VCPU_REGS_RCX, best->ecx);
+               kvm_register_write(vcpu, VCPU_REGS_RDX, best->edx);
        }
-       kvm_x86_ops->decache_regs(vcpu);
        kvm_x86_ops->skip_emulated_instruction(vcpu);
        KVMTRACE_5D(CPUID, vcpu, function,
-                   (u32)vcpu->arch.regs[VCPU_REGS_RAX],
-                   (u32)vcpu->arch.regs[VCPU_REGS_RBX],
-                   (u32)vcpu->arch.regs[VCPU_REGS_RCX],
-                   (u32)vcpu->arch.regs[VCPU_REGS_RDX], handler);
+                   (u32)kvm_register_read(vcpu, VCPU_REGS_RAX),
+                   (u32)kvm_register_read(vcpu, VCPU_REGS_RBX),
+                   (u32)kvm_register_read(vcpu, VCPU_REGS_RCX),
+                   (u32)kvm_register_read(vcpu, VCPU_REGS_RDX), handler);
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
 
@@ -2776,9 +2833,7 @@ static void vapic_enter(struct kvm_vcpu *vcpu)
        if (!apic || !apic->vapic_addr)
                return;
 
-       down_read(&current->mm->mmap_sem);
        page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-       up_read(&current->mm->mmap_sem);
 
        vcpu->arch.apic->vapic_page = page;
 }
@@ -2796,28 +2851,10 @@ static void vapic_exit(struct kvm_vcpu *vcpu)
        up_read(&vcpu->kvm->slots_lock);
 }
 
-static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        int r;
 
-       if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
-               pr_debug("vcpu %d received sipi with vector # %x\n",
-                      vcpu->vcpu_id, vcpu->arch.sipi_vector);
-               kvm_lapic_reset(vcpu);
-               r = kvm_x86_ops->vcpu_reset(vcpu);
-               if (r)
-                       return r;
-               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
-       }
-
-       down_read(&vcpu->kvm->slots_lock);
-       vapic_enter(vcpu);
-
-preempted:
-       if (vcpu->guest_debug.enabled)
-               kvm_x86_ops->guest_debug_pre(vcpu);
-
-again:
        if (vcpu->requests)
                if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
                        kvm_mmu_unload(vcpu);
@@ -2829,6 +2866,8 @@ again:
        if (vcpu->requests) {
                if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests))
                        __kvm_migrate_timers(vcpu);
+               if (test_and_clear_bit(KVM_REQ_MMU_SYNC, &vcpu->requests))
+                       kvm_mmu_sync_roots(vcpu);
                if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
                        kvm_x86_ops->tlb_flush(vcpu);
                if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS,
@@ -2854,21 +2893,15 @@ again:
 
        local_irq_disable();
 
-       if (vcpu->requests || need_resched()) {
+       if (vcpu->requests || need_resched() || signal_pending(current)) {
                local_irq_enable();
                preempt_enable();
                r = 1;
                goto out;
        }
 
-       if (signal_pending(current)) {
-               local_irq_enable();
-               preempt_enable();
-               r = -EINTR;
-               kvm_run->exit_reason = KVM_EXIT_INTR;
-               ++vcpu->stat.signal_exits;
-               goto out;
-       }
+       if (vcpu->guest_debug.enabled)
+               kvm_x86_ops->guest_debug_pre(vcpu);
 
        vcpu->guest_mode = 1;
        /*
@@ -2917,8 +2950,8 @@ again:
         * Profile KVM exit RIPs:
         */
        if (unlikely(prof_on == KVM_PROFILING)) {
-               kvm_x86_ops->cache_regs(vcpu);
-               profile_hit(KVM_PROFILING, (void *)vcpu->arch.rip);
+               unsigned long rip = kvm_rip_read(vcpu);
+               profile_hit(KVM_PROFILING, (void *)rip);
        }
 
        if (vcpu->arch.exception.pending && kvm_x86_ops->exception_injected(vcpu))
@@ -2927,26 +2960,63 @@ again:
        kvm_lapic_sync_from_vapic(vcpu);
 
        r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
+out:
+       return r;
+}
 
-       if (r > 0) {
-               if (dm_request_for_irq_injection(vcpu, kvm_run)) {
-                       r = -EINTR;
-                       kvm_run->exit_reason = KVM_EXIT_INTR;
-                       ++vcpu->stat.request_irq_exits;
-                       goto out;
-               }
-               if (!need_resched())
-                       goto again;
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       int r;
+
+       if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
+               pr_debug("vcpu %d received sipi with vector # %x\n",
+                        vcpu->vcpu_id, vcpu->arch.sipi_vector);
+               kvm_lapic_reset(vcpu);
+               r = kvm_x86_ops->vcpu_reset(vcpu);
+               if (r)
+                       return r;
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
        }
 
-out:
-       up_read(&vcpu->kvm->slots_lock);
-       if (r > 0) {
-               kvm_resched(vcpu);
-               down_read(&vcpu->kvm->slots_lock);
-               goto preempted;
+       down_read(&vcpu->kvm->slots_lock);
+       vapic_enter(vcpu);
+
+       r = 1;
+       while (r > 0) {
+               if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
+                       r = vcpu_enter_guest(vcpu, kvm_run);
+               else {
+                       up_read(&vcpu->kvm->slots_lock);
+                       kvm_vcpu_block(vcpu);
+                       down_read(&vcpu->kvm->slots_lock);
+                       if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
+                               if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
+                                       vcpu->arch.mp_state =
+                                                       KVM_MP_STATE_RUNNABLE;
+                       if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
+                               r = -EINTR;
+               }
+
+               if (r > 0) {
+                       if (dm_request_for_irq_injection(vcpu, kvm_run)) {
+                               r = -EINTR;
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
+                               ++vcpu->stat.request_irq_exits;
+                       }
+                       if (signal_pending(current)) {
+                               r = -EINTR;
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
+                               ++vcpu->stat.signal_exits;
+                       }
+                       if (need_resched()) {
+                               up_read(&vcpu->kvm->slots_lock);
+                               kvm_resched(vcpu);
+                               down_read(&vcpu->kvm->slots_lock);
+                       }
+               }
        }
 
+       up_read(&vcpu->kvm->slots_lock);
        post_kvm_run_save(vcpu, kvm_run);
 
        vapic_exit(vcpu);
@@ -2966,6 +3036,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
                kvm_vcpu_block(vcpu);
+               clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
                r = -EAGAIN;
                goto out;
        }
@@ -2999,11 +3070,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                }
        }
 #endif
-       if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL) {
-               kvm_x86_ops->cache_regs(vcpu);
-               vcpu->arch.regs[VCPU_REGS_RAX] = kvm_run->hypercall.ret;
-               kvm_x86_ops->decache_regs(vcpu);
-       }
+       if (kvm_run->exit_reason == KVM_EXIT_HYPERCALL)
+               kvm_register_write(vcpu, VCPU_REGS_RAX,
+                                    kvm_run->hypercall.ret);
 
        r = __vcpu_run(vcpu, kvm_run);
 
@@ -3019,28 +3088,26 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        vcpu_load(vcpu);
 
-       kvm_x86_ops->cache_regs(vcpu);
-
-       regs->rax = vcpu->arch.regs[VCPU_REGS_RAX];
-       regs->rbx = vcpu->arch.regs[VCPU_REGS_RBX];
-       regs->rcx = vcpu->arch.regs[VCPU_REGS_RCX];
-       regs->rdx = vcpu->arch.regs[VCPU_REGS_RDX];
-       regs->rsi = vcpu->arch.regs[VCPU_REGS_RSI];
-       regs->rdi = vcpu->arch.regs[VCPU_REGS_RDI];
-       regs->rsp = vcpu->arch.regs[VCPU_REGS_RSP];
-       regs->rbp = vcpu->arch.regs[VCPU_REGS_RBP];
+       regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       regs->rbx = kvm_register_read(vcpu, VCPU_REGS_RBX);
+       regs->rcx = kvm_register_read(vcpu, VCPU_REGS_RCX);
+       regs->rdx = kvm_register_read(vcpu, VCPU_REGS_RDX);
+       regs->rsi = kvm_register_read(vcpu, VCPU_REGS_RSI);
+       regs->rdi = kvm_register_read(vcpu, VCPU_REGS_RDI);
+       regs->rsp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+       regs->rbp = kvm_register_read(vcpu, VCPU_REGS_RBP);
 #ifdef CONFIG_X86_64
-       regs->r8 = vcpu->arch.regs[VCPU_REGS_R8];
-       regs->r9 = vcpu->arch.regs[VCPU_REGS_R9];
-       regs->r10 = vcpu->arch.regs[VCPU_REGS_R10];
-       regs->r11 = vcpu->arch.regs[VCPU_REGS_R11];
-       regs->r12 = vcpu->arch.regs[VCPU_REGS_R12];
-       regs->r13 = vcpu->arch.regs[VCPU_REGS_R13];
-       regs->r14 = vcpu->arch.regs[VCPU_REGS_R14];
-       regs->r15 = vcpu->arch.regs[VCPU_REGS_R15];
+       regs->r8 = kvm_register_read(vcpu, VCPU_REGS_R8);
+       regs->r9 = kvm_register_read(vcpu, VCPU_REGS_R9);
+       regs->r10 = kvm_register_read(vcpu, VCPU_REGS_R10);
+       regs->r11 = kvm_register_read(vcpu, VCPU_REGS_R11);
+       regs->r12 = kvm_register_read(vcpu, VCPU_REGS_R12);
+       regs->r13 = kvm_register_read(vcpu, VCPU_REGS_R13);
+       regs->r14 = kvm_register_read(vcpu, VCPU_REGS_R14);
+       regs->r15 = kvm_register_read(vcpu, VCPU_REGS_R15);
 #endif
 
-       regs->rip = vcpu->arch.rip;
+       regs->rip = kvm_rip_read(vcpu);
        regs->rflags = kvm_x86_ops->get_rflags(vcpu);
 
        /*
@@ -3058,29 +3125,29 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
        vcpu_load(vcpu);
 
-       vcpu->arch.regs[VCPU_REGS_RAX] = regs->rax;
-       vcpu->arch.regs[VCPU_REGS_RBX] = regs->rbx;
-       vcpu->arch.regs[VCPU_REGS_RCX] = regs->rcx;
-       vcpu->arch.regs[VCPU_REGS_RDX] = regs->rdx;
-       vcpu->arch.regs[VCPU_REGS_RSI] = regs->rsi;
-       vcpu->arch.regs[VCPU_REGS_RDI] = regs->rdi;
-       vcpu->arch.regs[VCPU_REGS_RSP] = regs->rsp;
-       vcpu->arch.regs[VCPU_REGS_RBP] = regs->rbp;
+       kvm_register_write(vcpu, VCPU_REGS_RAX, regs->rax);
+       kvm_register_write(vcpu, VCPU_REGS_RBX, regs->rbx);
+       kvm_register_write(vcpu, VCPU_REGS_RCX, regs->rcx);
+       kvm_register_write(vcpu, VCPU_REGS_RDX, regs->rdx);
+       kvm_register_write(vcpu, VCPU_REGS_RSI, regs->rsi);
+       kvm_register_write(vcpu, VCPU_REGS_RDI, regs->rdi);
+       kvm_register_write(vcpu, VCPU_REGS_RSP, regs->rsp);
+       kvm_register_write(vcpu, VCPU_REGS_RBP, regs->rbp);
 #ifdef CONFIG_X86_64
-       vcpu->arch.regs[VCPU_REGS_R8] = regs->r8;
-       vcpu->arch.regs[VCPU_REGS_R9] = regs->r9;
-       vcpu->arch.regs[VCPU_REGS_R10] = regs->r10;
-       vcpu->arch.regs[VCPU_REGS_R11] = regs->r11;
-       vcpu->arch.regs[VCPU_REGS_R12] = regs->r12;
-       vcpu->arch.regs[VCPU_REGS_R13] = regs->r13;
-       vcpu->arch.regs[VCPU_REGS_R14] = regs->r14;
-       vcpu->arch.regs[VCPU_REGS_R15] = regs->r15;
+       kvm_register_write(vcpu, VCPU_REGS_R8, regs->r8);
+       kvm_register_write(vcpu, VCPU_REGS_R9, regs->r9);
+       kvm_register_write(vcpu, VCPU_REGS_R10, regs->r10);
+       kvm_register_write(vcpu, VCPU_REGS_R11, regs->r11);
+       kvm_register_write(vcpu, VCPU_REGS_R12, regs->r12);
+       kvm_register_write(vcpu, VCPU_REGS_R13, regs->r13);
+       kvm_register_write(vcpu, VCPU_REGS_R14, regs->r14);
+       kvm_register_write(vcpu, VCPU_REGS_R15, regs->r15);
+
 #endif
 
-       vcpu->arch.rip = regs->rip;
+       kvm_rip_write(vcpu, regs->rip);
        kvm_x86_ops->set_rflags(vcpu, regs->rflags);
 
-       kvm_x86_ops->decache_regs(vcpu);
 
        vcpu->arch.exception.pending = false;
 
@@ -3294,11 +3361,33 @@ static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int kvm_load_realmode_segment(struct kvm_vcpu *vcpu, u16 selector, int seg)
+{
+       struct kvm_segment segvar = {
+               .base = selector << 4,
+               .limit = 0xffff,
+               .selector = selector,
+               .type = 3,
+               .present = 1,
+               .dpl = 3,
+               .db = 0,
+               .s = 1,
+               .l = 0,
+               .g = 0,
+               .avl = 0,
+               .unusable = 0,
+       };
+       kvm_x86_ops->set_segment(vcpu, &segvar, seg);
+       return 0;
+}
+
 int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
                                int type_bits, int seg)
 {
        struct kvm_segment kvm_seg;
 
+       if (!(vcpu->arch.cr0 & X86_CR0_PE))
+               return kvm_load_realmode_segment(vcpu, selector, seg);
        if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
                return 1;
        kvm_seg.type |= type_bits;
@@ -3316,17 +3405,16 @@ static void save_state_to_tss32(struct kvm_vcpu *vcpu,
                                struct tss_segment_32 *tss)
 {
        tss->cr3 = vcpu->arch.cr3;
-       tss->eip = vcpu->arch.rip;
+       tss->eip = kvm_rip_read(vcpu);
        tss->eflags = kvm_x86_ops->get_rflags(vcpu);
-       tss->eax = vcpu->arch.regs[VCPU_REGS_RAX];
-       tss->ecx = vcpu->arch.regs[VCPU_REGS_RCX];
-       tss->edx = vcpu->arch.regs[VCPU_REGS_RDX];
-       tss->ebx = vcpu->arch.regs[VCPU_REGS_RBX];
-       tss->esp = vcpu->arch.regs[VCPU_REGS_RSP];
-       tss->ebp = vcpu->arch.regs[VCPU_REGS_RBP];
-       tss->esi = vcpu->arch.regs[VCPU_REGS_RSI];
-       tss->edi = vcpu->arch.regs[VCPU_REGS_RDI];
-
+       tss->eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       tss->ecx = kvm_register_read(vcpu, VCPU_REGS_RCX);
+       tss->edx = kvm_register_read(vcpu, VCPU_REGS_RDX);
+       tss->ebx = kvm_register_read(vcpu, VCPU_REGS_RBX);
+       tss->esp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+       tss->ebp = kvm_register_read(vcpu, VCPU_REGS_RBP);
+       tss->esi = kvm_register_read(vcpu, VCPU_REGS_RSI);
+       tss->edi = kvm_register_read(vcpu, VCPU_REGS_RDI);
        tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
        tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
        tss->ss = get_segment_selector(vcpu, VCPU_SREG_SS);
@@ -3342,17 +3430,17 @@ static int load_state_from_tss32(struct kvm_vcpu *vcpu,
 {
        kvm_set_cr3(vcpu, tss->cr3);
 
-       vcpu->arch.rip = tss->eip;
+       kvm_rip_write(vcpu, tss->eip);
        kvm_x86_ops->set_rflags(vcpu, tss->eflags | 2);
 
-       vcpu->arch.regs[VCPU_REGS_RAX] = tss->eax;
-       vcpu->arch.regs[VCPU_REGS_RCX] = tss->ecx;
-       vcpu->arch.regs[VCPU_REGS_RDX] = tss->edx;
-       vcpu->arch.regs[VCPU_REGS_RBX] = tss->ebx;
-       vcpu->arch.regs[VCPU_REGS_RSP] = tss->esp;
-       vcpu->arch.regs[VCPU_REGS_RBP] = tss->ebp;
-       vcpu->arch.regs[VCPU_REGS_RSI] = tss->esi;
-       vcpu->arch.regs[VCPU_REGS_RDI] = tss->edi;
+       kvm_register_write(vcpu, VCPU_REGS_RAX, tss->eax);
+       kvm_register_write(vcpu, VCPU_REGS_RCX, tss->ecx);
+       kvm_register_write(vcpu, VCPU_REGS_RDX, tss->edx);
+       kvm_register_write(vcpu, VCPU_REGS_RBX, tss->ebx);
+       kvm_register_write(vcpu, VCPU_REGS_RSP, tss->esp);
+       kvm_register_write(vcpu, VCPU_REGS_RBP, tss->ebp);
+       kvm_register_write(vcpu, VCPU_REGS_RSI, tss->esi);
+       kvm_register_write(vcpu, VCPU_REGS_RDI, tss->edi);
 
        if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
                return 1;
@@ -3380,16 +3468,16 @@ static int load_state_from_tss32(struct kvm_vcpu *vcpu,
 static void save_state_to_tss16(struct kvm_vcpu *vcpu,
                                struct tss_segment_16 *tss)
 {
-       tss->ip = vcpu->arch.rip;
+       tss->ip = kvm_rip_read(vcpu);
        tss->flag = kvm_x86_ops->get_rflags(vcpu);
-       tss->ax = vcpu->arch.regs[VCPU_REGS_RAX];
-       tss->cx = vcpu->arch.regs[VCPU_REGS_RCX];
-       tss->dx = vcpu->arch.regs[VCPU_REGS_RDX];
-       tss->bx = vcpu->arch.regs[VCPU_REGS_RBX];
-       tss->sp = vcpu->arch.regs[VCPU_REGS_RSP];
-       tss->bp = vcpu->arch.regs[VCPU_REGS_RBP];
-       tss->si = vcpu->arch.regs[VCPU_REGS_RSI];
-       tss->di = vcpu->arch.regs[VCPU_REGS_RDI];
+       tss->ax = kvm_register_read(vcpu, VCPU_REGS_RAX);
+       tss->cx = kvm_register_read(vcpu, VCPU_REGS_RCX);
+       tss->dx = kvm_register_read(vcpu, VCPU_REGS_RDX);
+       tss->bx = kvm_register_read(vcpu, VCPU_REGS_RBX);
+       tss->sp = kvm_register_read(vcpu, VCPU_REGS_RSP);
+       tss->bp = kvm_register_read(vcpu, VCPU_REGS_RBP);
+       tss->si = kvm_register_read(vcpu, VCPU_REGS_RSI);
+       tss->di = kvm_register_read(vcpu, VCPU_REGS_RDI);
 
        tss->es = get_segment_selector(vcpu, VCPU_SREG_ES);
        tss->cs = get_segment_selector(vcpu, VCPU_SREG_CS);
@@ -3402,16 +3490,16 @@ static void save_state_to_tss16(struct kvm_vcpu *vcpu,
 static int load_state_from_tss16(struct kvm_vcpu *vcpu,
                                 struct tss_segment_16 *tss)
 {
-       vcpu->arch.rip = tss->ip;
+       kvm_rip_write(vcpu, tss->ip);
        kvm_x86_ops->set_rflags(vcpu, tss->flag | 2);
-       vcpu->arch.regs[VCPU_REGS_RAX] = tss->ax;
-       vcpu->arch.regs[VCPU_REGS_RCX] = tss->cx;
-       vcpu->arch.regs[VCPU_REGS_RDX] = tss->dx;
-       vcpu->arch.regs[VCPU_REGS_RBX] = tss->bx;
-       vcpu->arch.regs[VCPU_REGS_RSP] = tss->sp;
-       vcpu->arch.regs[VCPU_REGS_RBP] = tss->bp;
-       vcpu->arch.regs[VCPU_REGS_RSI] = tss->si;
-       vcpu->arch.regs[VCPU_REGS_RDI] = tss->di;
+       kvm_register_write(vcpu, VCPU_REGS_RAX, tss->ax);
+       kvm_register_write(vcpu, VCPU_REGS_RCX, tss->cx);
+       kvm_register_write(vcpu, VCPU_REGS_RDX, tss->dx);
+       kvm_register_write(vcpu, VCPU_REGS_RBX, tss->bx);
+       kvm_register_write(vcpu, VCPU_REGS_RSP, tss->sp);
+       kvm_register_write(vcpu, VCPU_REGS_RBP, tss->bp);
+       kvm_register_write(vcpu, VCPU_REGS_RSI, tss->si);
+       kvm_register_write(vcpu, VCPU_REGS_RDI, tss->di);
 
        if (kvm_load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
                return 1;
@@ -3534,7 +3622,6 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
        }
 
        kvm_x86_ops->skip_emulated_instruction(vcpu);
-       kvm_x86_ops->cache_regs(vcpu);
 
        if (nseg_desc.type & 8)
                ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base,
@@ -3559,7 +3646,6 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason)
        tr_seg.type = 11;
        kvm_set_segment(vcpu, &tr_seg, VCPU_SREG_TR);
 out:
-       kvm_x86_ops->decache_regs(vcpu);
        return ret;
 }
 EXPORT_SYMBOL_GPL(kvm_task_switch);
@@ -3622,6 +3708,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                        pr_debug("Set back pending irq %d\n",
                                 pending_vec);
                }
+               kvm_pic_clear_isr_ack(vcpu->kvm);
        }
 
        kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
@@ -3634,6 +3721,12 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
        kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
 
+       /* Older userspace won't unhalt the vcpu on reset. */
+       if (vcpu->vcpu_id == 0 && kvm_rip_read(vcpu) == 0xfff0 &&
+           sregs->cs.selector == 0xf000 && sregs->cs.base == 0xffff0000 &&
+           !(vcpu->arch.cr0 & X86_CR0_PE))
+               vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+
        vcpu_put(vcpu);
 
        return 0;
@@ -3918,6 +4011,7 @@ struct  kvm *kvm_arch_create_vm(void)
                return ERR_PTR(-ENOMEM);
 
        INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
+       INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
        return kvm;
 }
@@ -3950,6 +4044,8 @@ static void kvm_free_vcpus(struct kvm *kvm)
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+       kvm_iommu_unmap_guest(kvm);
+       kvm_free_all_assigned_devices(kvm);
        kvm_free_pit(kvm);
        kfree(kvm->arch.vpic);
        kfree(kvm->arch.vioapic);
@@ -3981,7 +4077,7 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
                        userspace_addr = do_mmap(NULL, 0,
                                                 npages * PAGE_SIZE,
                                                 PROT_READ | PROT_WRITE,
-                                                MAP_SHARED | MAP_ANONYMOUS,
+                                                MAP_PRIVATE | MAP_ANONYMOUS,
                                                 0);
                        up_write(&current->mm->mmap_sem);
 
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
new file mode 100644 (file)
index 0000000..6a4be78
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef ARCH_X86_KVM_X86_H
+#define ARCH_X86_KVM_X86_H
+
+#include <linux/kvm_host.h>
+
+static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.exception.pending = false;
+}
+
+static inline void kvm_queue_interrupt(struct kvm_vcpu *vcpu, u8 vector)
+{
+       vcpu->arch.interrupt.pending = true;
+       vcpu->arch.interrupt.nr = vector;
+}
+
+static inline void kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.interrupt.pending = false;
+}
+
+#endif
index f2f90468f8b1c90042cc468f77eee4b5b19412ba..ea051173b0da9e950ca92d6841a42c507e957444 100644 (file)
@@ -26,6 +26,7 @@
 #define DPRINTF(_f, _a ...) printf(_f , ## _a)
 #else
 #include <linux/kvm_host.h>
+#include "kvm_cache_regs.h"
 #define DPRINTF(x...) do {} while (0)
 #endif
 #include <linux/module.h>
 #define ImplicitOps (1<<1)     /* Implicit in opcode. No generic decode. */
 #define DstReg      (2<<1)     /* Register operand. */
 #define DstMem      (3<<1)     /* Memory operand. */
-#define DstMask     (3<<1)
+#define DstAcc      (4<<1)      /* Destination Accumulator */
+#define DstMask     (7<<1)
 /* Source operand type. */
-#define SrcNone     (0<<3)     /* No source operand. */
-#define SrcImplicit (0<<3)     /* Source operand is implicit in the opcode. */
-#define SrcReg      (1<<3)     /* Register operand. */
-#define SrcMem      (2<<3)     /* Memory operand. */
-#define SrcMem16    (3<<3)     /* Memory operand (16-bit). */
-#define SrcMem32    (4<<3)     /* Memory operand (32-bit). */
-#define SrcImm      (5<<3)     /* Immediate operand. */
-#define SrcImmByte  (6<<3)     /* 8-bit sign-extended immediate operand. */
-#define SrcMask     (7<<3)
+#define SrcNone     (0<<4)     /* No source operand. */
+#define SrcImplicit (0<<4)     /* Source operand is implicit in the opcode. */
+#define SrcReg      (1<<4)     /* Register operand. */
+#define SrcMem      (2<<4)     /* Memory operand. */
+#define SrcMem16    (3<<4)     /* Memory operand (16-bit). */
+#define SrcMem32    (4<<4)     /* Memory operand (32-bit). */
+#define SrcImm      (5<<4)     /* Immediate operand. */
+#define SrcImmByte  (6<<4)     /* 8-bit sign-extended immediate operand. */
+#define SrcMask     (7<<4)
 /* Generic ModRM decode. */
-#define ModRM       (1<<6)
+#define ModRM       (1<<7)
 /* Destination is only written; never read. */
-#define Mov         (1<<7)
-#define BitOp       (1<<8)
-#define MemAbs      (1<<9)      /* Memory operand is absolute displacement */
-#define String      (1<<10)     /* String instruction (rep capable) */
-#define Stack       (1<<11)     /* Stack instruction (push/pop) */
+#define Mov         (1<<8)
+#define BitOp       (1<<9)
+#define MemAbs      (1<<10)      /* Memory operand is absolute displacement */
+#define String      (1<<12)     /* String instruction (rep capable) */
+#define Stack       (1<<13)     /* Stack instruction (push/pop) */
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
 #define GroupMask   0xff        /* Group number stored in bits 0:7 */
@@ -94,7 +96,7 @@ static u16 opcode_table[256] = {
        /* 0x20 - 0x27 */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
-       SrcImmByte, SrcImm, 0, 0,
+       DstAcc | SrcImmByte, DstAcc | SrcImm, 0, 0,
        /* 0x28 - 0x2F */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -106,7 +108,8 @@ static u16 opcode_table[256] = {
        /* 0x38 - 0x3F */
        ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
-       0, 0, 0, 0,
+       ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
+       0, 0,
        /* 0x40 - 0x47 */
        DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
        /* 0x48 - 0x4F */
@@ -153,9 +156,16 @@ static u16 opcode_table[256] = {
        0, 0, ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
        ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
        ByteOp | ImplicitOps | String, ImplicitOps | String,
-       /* 0xB0 - 0xBF */
-       0, 0, 0, 0, 0, 0, 0, 0,
-       DstReg | SrcImm | Mov, 0, 0, 0, 0, 0, 0, 0,
+       /* 0xB0 - 0xB7 */
+       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
+       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
+       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
+       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
+       /* 0xB8 - 0xBF */
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
        /* 0xC0 - 0xC7 */
        ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
        0, ImplicitOps | Stack, 0, 0,
@@ -169,17 +179,20 @@ static u16 opcode_table[256] = {
        /* 0xD8 - 0xDF */
        0, 0, 0, 0, 0, 0, 0, 0,
        /* 0xE0 - 0xE7 */
-       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0,
+       SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
+       SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
        /* 0xE8 - 0xEF */
        ImplicitOps | Stack, SrcImm | ImplicitOps,
        ImplicitOps, SrcImmByte | ImplicitOps,
-       0, 0, 0, 0,
+       SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
+       SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
        /* 0xF0 - 0xF7 */
        0, 0, 0, 0,
        ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3,
        /* 0xF8 - 0xFF */
        ImplicitOps, 0, ImplicitOps, ImplicitOps,
-       0, 0, Group | Group4, Group | Group5,
+       ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
 };
 
 static u16 twobyte_table[256] = {
@@ -268,15 +281,16 @@ static u16 group_table[] = {
        ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
        0, 0, 0, 0,
        [Group3*8] =
-       DstMem | SrcImm | ModRM | SrcImm, 0,
-       DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
+       DstMem | SrcImm | ModRM, 0,
+       DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
        0, 0, 0, 0,
        [Group4*8] =
        ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM,
        0, 0, 0, 0, 0, 0,
        [Group5*8] =
-       DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, 0, 0,
-       SrcMem | ModRM, 0, SrcMem | ModRM | Stack, 0,
+       DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM,
+       SrcMem | ModRM | Stack, 0,
+       SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, 0,
        [Group7*8] =
        0, 0, ModRM | SrcMem, ModRM | SrcMem,
        SrcNone | ModRM | DstMem | Mov, 0,
@@ -839,7 +853,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        /* Shadow copy of register state. Committed on successful emulation. */
 
        memset(c, 0, sizeof(struct decode_cache));
-       c->eip = ctxt->vcpu->arch.rip;
+       c->eip = kvm_rip_read(ctxt->vcpu);
        ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
        memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
 
@@ -1048,6 +1062,23 @@ done_prefixes:
                }
                c->dst.type = OP_MEM;
                break;
+       case DstAcc:
+               c->dst.type = OP_REG;
+               c->dst.bytes = c->op_bytes;
+               c->dst.ptr = &c->regs[VCPU_REGS_RAX];
+               switch (c->op_bytes) {
+                       case 1:
+                               c->dst.val = *(u8 *)c->dst.ptr;
+                               break;
+                       case 2:
+                               c->dst.val = *(u16 *)c->dst.ptr;
+                               break;
+                       case 4:
+                               c->dst.val = *(u32 *)c->dst.ptr;
+                               break;
+               }
+               c->dst.orig_val = c->dst.val;
+               break;
        }
 
        if (c->rip_relative)
@@ -1151,6 +1182,14 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
        case 1: /* dec */
                emulate_1op("dec", c->dst, ctxt->eflags);
                break;
+       case 2: /* call near abs */ {
+               long int old_eip;
+               old_eip = c->eip;
+               c->eip = c->src.val;
+               c->src.val = old_eip;
+               emulate_push(ctxt);
+               break;
+       }
        case 4: /* jmp abs */
                c->eip = c->src.val;
                break;
@@ -1251,6 +1290,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        u64 msr_data;
        unsigned long saved_eip = 0;
        struct decode_cache *c = &ctxt->decode;
+       unsigned int port;
+       int io_dir_in;
        int rc = 0;
 
        /* Shadow copy of register state. Committed on successful emulation.
@@ -1267,7 +1308,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        if (c->rep_prefix && (c->d & String)) {
                /* All REP prefixes have the same first termination condition */
                if (c->regs[VCPU_REGS_RCX] == 0) {
-                       ctxt->vcpu->arch.rip = c->eip;
+                       kvm_rip_write(ctxt->vcpu, c->eip);
                        goto done;
                }
                /* The second termination condition only applies for REPE
@@ -1281,17 +1322,17 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
                                (c->b == 0xae) || (c->b == 0xaf)) {
                        if ((c->rep_prefix == REPE_PREFIX) &&
                                ((ctxt->eflags & EFLG_ZF) == 0)) {
-                                       ctxt->vcpu->arch.rip = c->eip;
+                                       kvm_rip_write(ctxt->vcpu, c->eip);
                                        goto done;
                        }
                        if ((c->rep_prefix == REPNE_PREFIX) &&
                                ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
-                               ctxt->vcpu->arch.rip = c->eip;
+                               kvm_rip_write(ctxt->vcpu, c->eip);
                                goto done;
                        }
                }
                c->regs[VCPU_REGS_RCX]--;
-               c->eip = ctxt->vcpu->arch.rip;
+               c->eip = kvm_rip_read(ctxt->vcpu);
        }
 
        if (c->src.type == OP_MEM) {
@@ -1351,27 +1392,10 @@ special_insn:
              sbb:              /* sbb */
                emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
                break;
-       case 0x20 ... 0x23:
+       case 0x20 ... 0x25:
              and:              /* and */
                emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags);
                break;
-       case 0x24:              /* and al imm8 */
-               c->dst.type = OP_REG;
-               c->dst.ptr = &c->regs[VCPU_REGS_RAX];
-               c->dst.val = *(u8 *)c->dst.ptr;
-               c->dst.bytes = 1;
-               c->dst.orig_val = c->dst.val;
-               goto and;
-       case 0x25:              /* and ax imm16, or eax imm32 */
-               c->dst.type = OP_REG;
-               c->dst.bytes = c->op_bytes;
-               c->dst.ptr = &c->regs[VCPU_REGS_RAX];
-               if (c->op_bytes == 2)
-                       c->dst.val = *(u16 *)c->dst.ptr;
-               else
-                       c->dst.val = *(u32 *)c->dst.ptr;
-               c->dst.orig_val = c->dst.val;
-               goto and;
        case 0x28 ... 0x2d:
              sub:              /* sub */
                emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
@@ -1659,7 +1683,7 @@ special_insn:
        case 0xae ... 0xaf:     /* scas */
                DPRINTF("Urk! I don't handle SCAS.\n");
                goto cannot_emulate;
-       case 0xb8: /* mov r, imm */
+       case 0xb0 ... 0xbf: /* mov r, imm */
                goto mov;
        case 0xc0 ... 0xc1:
                emulate_grp2(ctxt);
@@ -1679,6 +1703,16 @@ special_insn:
                c->src.val = c->regs[VCPU_REGS_RCX];
                emulate_grp2(ctxt);
                break;
+       case 0xe4:      /* inb */
+       case 0xe5:      /* in */
+               port = insn_fetch(u8, 1, c->eip);
+               io_dir_in = 1;
+               goto do_io;
+       case 0xe6: /* outb */
+       case 0xe7: /* out */
+               port = insn_fetch(u8, 1, c->eip);
+               io_dir_in = 0;
+               goto do_io;
        case 0xe8: /* call (near) */ {
                long int rel;
                switch (c->op_bytes) {
@@ -1729,6 +1763,22 @@ special_insn:
                jmp_rel(c, c->src.val);
                c->dst.type = OP_NONE; /* Disable writeback. */
                break;
+       case 0xec: /* in al,dx */
+       case 0xed: /* in (e/r)ax,dx */
+               port = c->regs[VCPU_REGS_RDX];
+               io_dir_in = 1;
+               goto do_io;
+       case 0xee: /* out al,dx */
+       case 0xef: /* out (e/r)ax,dx */
+               port = c->regs[VCPU_REGS_RDX];
+               io_dir_in = 0;
+       do_io:  if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in,
+                                  (c->d & ByteOp) ? 1 : c->op_bytes,
+                                  port) != 0) {
+                       c->eip = saved_eip;
+                       goto cannot_emulate;
+               }
+               return 0;
        case 0xf4:              /* hlt */
                ctxt->vcpu->arch.halt_request = 1;
                break;
@@ -1754,6 +1804,14 @@ special_insn:
                ctxt->eflags |= X86_EFLAGS_IF;
                c->dst.type = OP_NONE;  /* Disable writeback. */
                break;
+       case 0xfc: /* cld */
+               ctxt->eflags &= ~EFLG_DF;
+               c->dst.type = OP_NONE;  /* Disable writeback. */
+               break;
+       case 0xfd: /* std */
+               ctxt->eflags |= EFLG_DF;
+               c->dst.type = OP_NONE;  /* Disable writeback. */
+               break;
        case 0xfe ... 0xff:     /* Grp4/Grp5 */
                rc = emulate_grp45(ctxt, ops);
                if (rc != 0)
@@ -1768,7 +1826,7 @@ writeback:
 
        /* Commit shadow register state. */
        memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
-       ctxt->vcpu->arch.rip = c->eip;
+       kvm_rip_write(ctxt->vcpu, c->eip);
 
 done:
        if (rc == X86EMUL_UNHANDLEABLE) {
@@ -1793,7 +1851,7 @@ twobyte_insn:
                                goto done;
 
                        /* Let the processor re-execute the fixed hypercall */
-                       c->eip = ctxt->vcpu->arch.rip;
+                       c->eip = kvm_rip_read(ctxt->vcpu);
                        /* Disable writeback. */
                        c->dst.type = OP_NONE;
                        break;
@@ -1889,7 +1947,7 @@ twobyte_insn:
                rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
                if (rc) {
                        kvm_inject_gp(ctxt->vcpu, 0);
-                       c->eip = ctxt->vcpu->arch.rip;
+                       c->eip = kvm_rip_read(ctxt->vcpu);
                }
                rc = X86EMUL_CONTINUE;
                c->dst.type = OP_NONE;
@@ -1899,7 +1957,7 @@ twobyte_insn:
                rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
                if (rc) {
                        kvm_inject_gp(ctxt->vcpu, 0);
-                       c->eip = ctxt->vcpu->arch.rip;
+                       c->eip = kvm_rip_read(ctxt->vcpu);
                } else {
                        c->regs[VCPU_REGS_RAX] = (u32)msr_data;
                        c->regs[VCPU_REGS_RDX] = msr_data >> 32;
index 520cca0ee04e382227acb882ebd3a0665a5135b8..6513d41ea21eb54d84aa3c7720afaf7671f27d8e 100644 (file)
@@ -47,16 +47,26 @@ static __init int mps_oem_check(struct mp_config_table *mpc, char *oem,
 /* Hook from generic ACPI tables.c */
 static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
-       unsigned long oem_addr;
+       unsigned long oem_addr = 0;
+       int check_dsdt;
+       int ret = 0;
+
+       /* check dsdt at first to avoid clear fix_map for oem_addr */
+       check_dsdt = es7000_check_dsdt();
+
        if (!find_unisys_acpi_oem_table(&oem_addr)) {
-               if (es7000_check_dsdt())
-                       return parse_unisys_oem((char *)oem_addr);
+               if (check_dsdt)
+                       ret = parse_unisys_oem((char *)oem_addr);
                else {
                        setup_unisys();
-                       return 1;
+                       ret = 1;
                }
+               /*
+                * we need to unmap it
+                */
+               unmap_unisys_acpi_oem_table(oem_addr);
        }
-       return 0;
+       return ret;
 }
 #else
 static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
index dfb932dcf136c5055dd555d6e5680e4821bacf59..59f89b434b45fbb80df02bafe3f54122a8738b50 100644 (file)
@@ -13,12 +13,8 @@ obj-$(CONFIG_MMIOTRACE)              += mmiotrace.o
 mmiotrace-y                    := pf_in.o mmio-mod.o
 obj-$(CONFIG_MMIOTRACE_TEST)   += testmmiotrace.o
 
-ifeq ($(CONFIG_X86_32),y)
-obj-$(CONFIG_NUMA)             += discontig_32.o
-else
-obj-$(CONFIG_NUMA)             += numa_64.o
+obj-$(CONFIG_NUMA)             += numa_$(BITS).o
 obj-$(CONFIG_K8_NUMA)          += k8topology_64.o
-endif
 obj-$(CONFIG_ACPI_NUMA)                += srat_$(BITS).o
 
 obj-$(CONFIG_MEMTEST)          += memtest.o
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
deleted file mode 100644 (file)
index 847c164..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Written by: Patricia Gaughen <gone@us.ibm.com>, IBM Corporation
- * August 2002: added remote node KVA remap - Martin J. Bligh 
- *
- * 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.
- */
-
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/mmzone.h>
-#include <linux/highmem.h>
-#include <linux/initrd.h>
-#include <linux/nodemask.h>
-#include <linux/module.h>
-#include <linux/kexec.h>
-#include <linux/pfn.h>
-#include <linux/swap.h>
-#include <linux/acpi.h>
-
-#include <asm/e820.h>
-#include <asm/setup.h>
-#include <asm/mmzone.h>
-#include <asm/bios_ebda.h>
-#include <asm/proto.h>
-
-struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
-EXPORT_SYMBOL(node_data);
-
-/*
- * numa interface - we expect the numa architecture specific code to have
- *                  populated the following initialisation.
- *
- * 1) node_online_map  - the map of all nodes configured (online) in the system
- * 2) node_start_pfn   - the starting page frame number for a node
- * 3) node_end_pfn     - the ending page fram number for a node
- */
-unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
-unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
-
-
-#ifdef CONFIG_DISCONTIGMEM
-/*
- * 4) physnode_map     - the mapping between a pfn and owning node
- * physnode_map keeps track of the physical memory layout of a generic
- * numa node on a 64Mb break (each element of the array will
- * represent 64Mb of memory and will be marked by the node id.  so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- *
- *     physnode_map[0-15] = 0;
- *     physnode_map[16-31] = 1;
- *     physnode_map[32- ] = -1;
- */
-s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(physnode_map);
-
-void memory_present(int nid, unsigned long start, unsigned long end)
-{
-       unsigned long pfn;
-
-       printk(KERN_INFO "Node: %d, start_pfn: %lx, end_pfn: %lx\n",
-                       nid, start, end);
-       printk(KERN_DEBUG "  Setting physnode_map array to node %d for pfns:\n", nid);
-       printk(KERN_DEBUG "  ");
-       for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
-               physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
-               printk(KERN_CONT "%lx ", pfn);
-       }
-       printk(KERN_CONT "\n");
-}
-
-unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
-                                             unsigned long end_pfn)
-{
-       unsigned long nr_pages = end_pfn - start_pfn;
-
-       if (!nr_pages)
-               return 0;
-
-       return (nr_pages + 1) * sizeof(struct page);
-}
-#endif
-
-extern unsigned long find_max_low_pfn(void);
-extern unsigned long highend_pfn, highstart_pfn;
-
-#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
-
-unsigned long node_remap_size[MAX_NUMNODES];
-static void *node_remap_start_vaddr[MAX_NUMNODES];
-void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
-
-static unsigned long kva_start_pfn;
-static unsigned long kva_pages;
-/*
- * FLAT - support for basic PC memory model with discontig enabled, essentially
- *        a single node with all available processors in it with a flat
- *        memory map.
- */
-int __init get_memcfg_numa_flat(void)
-{
-       printk(KERN_DEBUG "NUMA - single node, flat memory mode\n");
-
-       node_start_pfn[0] = 0;
-       node_end_pfn[0] = max_pfn;
-       e820_register_active_regions(0, 0, max_pfn);
-       memory_present(0, 0, max_pfn);
-       node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
-
-        /* Indicate there is one node available. */
-       nodes_clear(node_online_map);
-       node_set_online(0);
-       return 1;
-}
-
-/*
- * Find the highest page frame number we have available for the node
- */
-static void __init propagate_e820_map_node(int nid)
-{
-       if (node_end_pfn[nid] > max_pfn)
-               node_end_pfn[nid] = max_pfn;
-       /*
-        * if a user has given mem=XXXX, then we need to make sure 
-        * that the node _starts_ before that, too, not just ends
-        */
-       if (node_start_pfn[nid] > max_pfn)
-               node_start_pfn[nid] = max_pfn;
-       BUG_ON(node_start_pfn[nid] > node_end_pfn[nid]);
-}
-
-/* 
- * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
- * method.  For node zero take this from the bottom of memory, for
- * subsequent nodes place them at node_remap_start_vaddr which contains
- * node local data in physically node local memory.  See setup_memory()
- * for details.
- */
-static void __init allocate_pgdat(int nid)
-{
-       char buf[16];
-
-       if (node_has_online_mem(nid) && node_remap_start_vaddr[nid])
-               NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
-       else {
-               unsigned long pgdat_phys;
-               pgdat_phys = find_e820_area(min_low_pfn<<PAGE_SHIFT,
-                                max_pfn_mapped<<PAGE_SHIFT,
-                                sizeof(pg_data_t),
-                                PAGE_SIZE);
-               NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
-               memset(buf, 0, sizeof(buf));
-               sprintf(buf, "NODE_DATA %d",  nid);
-               reserve_early(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
-       }
-       printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
-               nid, (unsigned long)NODE_DATA(nid));
-}
-
-/*
- * In the DISCONTIGMEM and SPARSEMEM memory model, a portion of the kernel
- * virtual address space (KVA) is reserved and portions of nodes are mapped
- * using it. This is to allow node-local memory to be allocated for
- * structures that would normally require ZONE_NORMAL. The memory is
- * allocated with alloc_remap() and callers should be prepared to allocate
- * from the bootmem allocator instead.
- */
-static unsigned long node_remap_start_pfn[MAX_NUMNODES];
-static void *node_remap_end_vaddr[MAX_NUMNODES];
-static void *node_remap_alloc_vaddr[MAX_NUMNODES];
-static unsigned long node_remap_offset[MAX_NUMNODES];
-
-void *alloc_remap(int nid, unsigned long size)
-{
-       void *allocation = node_remap_alloc_vaddr[nid];
-
-       size = ALIGN(size, L1_CACHE_BYTES);
-
-       if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
-               return 0;
-
-       node_remap_alloc_vaddr[nid] += size;
-       memset(allocation, 0, size);
-
-       return allocation;
-}
-
-static void __init remap_numa_kva(void)
-{
-       void *vaddr;
-       unsigned long pfn;
-       int node;
-
-       for_each_online_node(node) {
-               printk(KERN_DEBUG "remap_numa_kva: node %d\n", node);
-               for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
-                       vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
-                       printk(KERN_DEBUG "remap_numa_kva: %08lx to pfn %08lx\n",
-                               (unsigned long)vaddr,
-                               node_remap_start_pfn[node] + pfn);
-                       set_pmd_pfn((ulong) vaddr, 
-                               node_remap_start_pfn[node] + pfn, 
-                               PAGE_KERNEL_LARGE);
-               }
-       }
-}
-
-static unsigned long calculate_numa_remap_pages(void)
-{
-       int nid;
-       unsigned long size, reserve_pages = 0;
-
-       for_each_online_node(nid) {
-               u64 node_kva_target;
-               u64 node_kva_final;
-
-               /*
-                * The acpi/srat node info can show hot-add memroy zones
-                * where memory could be added but not currently present.
-                */
-               printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
-                       nid, node_start_pfn[nid], node_end_pfn[nid]);
-               if (node_start_pfn[nid] > max_pfn)
-                       continue;
-               if (!node_end_pfn[nid])
-                       continue;
-               if (node_end_pfn[nid] > max_pfn)
-                       node_end_pfn[nid] = max_pfn;
-
-               /* ensure the remap includes space for the pgdat. */
-               size = node_remap_size[nid] + sizeof(pg_data_t);
-
-               /* convert size to large (pmd size) pages, rounding up */
-               size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
-               /* now the roundup is correct, convert to PAGE_SIZE pages */
-               size = size * PTRS_PER_PTE;
-
-               node_kva_target = round_down(node_end_pfn[nid] - size,
-                                                PTRS_PER_PTE);
-               node_kva_target <<= PAGE_SHIFT;
-               do {
-                       node_kva_final = find_e820_area(node_kva_target,
-                                       ((u64)node_end_pfn[nid])<<PAGE_SHIFT,
-                                               ((u64)size)<<PAGE_SHIFT,
-                                               LARGE_PAGE_BYTES);
-                       node_kva_target -= LARGE_PAGE_BYTES;
-               } while (node_kva_final == -1ULL &&
-                        (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
-
-               if (node_kva_final == -1ULL)
-                       panic("Can not get kva ram\n");
-
-               node_remap_size[nid] = size;
-               node_remap_offset[nid] = reserve_pages;
-               reserve_pages += size;
-               printk(KERN_DEBUG "Reserving %ld pages of KVA for lmem_map of"
-                                 " node %d at %llx\n",
-                               size, nid, node_kva_final>>PAGE_SHIFT);
-
-               /*
-                *  prevent kva address below max_low_pfn want it on system
-                *  with less memory later.
-                *  layout will be: KVA address , KVA RAM
-                *
-                *  we are supposed to only record the one less then max_low_pfn
-                *  but we could have some hole in high memory, and it will only
-                *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
-                *  to use it as free.
-                *  So reserve_early here, hope we don't run out of that array
-                */
-               reserve_early(node_kva_final,
-                             node_kva_final+(((u64)size)<<PAGE_SHIFT),
-                             "KVA RAM");
-
-               node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
-               remove_active_range(nid, node_remap_start_pfn[nid],
-                                        node_remap_start_pfn[nid] + size);
-       }
-       printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
-                       reserve_pages);
-       return reserve_pages;
-}
-
-static void init_remap_allocator(int nid)
-{
-       node_remap_start_vaddr[nid] = pfn_to_kaddr(
-                       kva_start_pfn + node_remap_offset[nid]);
-       node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
-               (node_remap_size[nid] * PAGE_SIZE);
-       node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
-               ALIGN(sizeof(pg_data_t), PAGE_SIZE);
-
-       printk(KERN_DEBUG "node %d will remap to vaddr %08lx - %08lx\n", nid,
-               (ulong) node_remap_start_vaddr[nid],
-               (ulong) node_remap_end_vaddr[nid]);
-}
-
-void __init initmem_init(unsigned long start_pfn,
-                                 unsigned long end_pfn)
-{
-       int nid;
-       long kva_target_pfn;
-
-       /*
-        * When mapping a NUMA machine we allocate the node_mem_map arrays
-        * from node local memory.  They are then mapped directly into KVA
-        * between zone normal and vmalloc space.  Calculate the size of
-        * this space and use it to adjust the boundary between ZONE_NORMAL
-        * and ZONE_HIGHMEM.
-        */
-
-       get_memcfg_numa();
-
-       kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
-
-       kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
-       do {
-               kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
-                                       max_low_pfn<<PAGE_SHIFT,
-                                       kva_pages<<PAGE_SHIFT,
-                                       PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
-               kva_target_pfn -= PTRS_PER_PTE;
-       } while (kva_start_pfn == -1UL && kva_target_pfn > min_low_pfn);
-
-       if (kva_start_pfn == -1UL)
-               panic("Can not get kva space\n");
-
-       printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
-               kva_start_pfn, max_low_pfn);
-       printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
-
-       /* avoid clash with initrd */
-       reserve_early(kva_start_pfn<<PAGE_SHIFT,
-                     (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
-                    "KVA PG");
-#ifdef CONFIG_HIGHMEM
-       highstart_pfn = highend_pfn = max_pfn;
-       if (max_pfn > max_low_pfn)
-               highstart_pfn = max_low_pfn;
-       printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-              pages_to_mb(highend_pfn - highstart_pfn));
-       num_physpages = highend_pfn;
-       high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
-#else
-       num_physpages = max_low_pfn;
-       high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
-#endif
-       printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
-                       pages_to_mb(max_low_pfn));
-       printk(KERN_DEBUG "max_low_pfn = %lx, highstart_pfn = %lx\n",
-                       max_low_pfn, highstart_pfn);
-
-       printk(KERN_DEBUG "Low memory ends at vaddr %08lx\n",
-                       (ulong) pfn_to_kaddr(max_low_pfn));
-       for_each_online_node(nid) {
-               init_remap_allocator(nid);
-
-               allocate_pgdat(nid);
-       }
-       remap_numa_kva();
-
-       printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
-                       (ulong) pfn_to_kaddr(highstart_pfn));
-       for_each_online_node(nid)
-               propagate_e820_map_node(nid);
-
-       for_each_online_node(nid)
-               memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
-
-       NODE_DATA(0)->bdata = &bootmem_node_data[0];
-       setup_bootmem_allocator();
-}
-
-void __init set_highmem_pages_init(void)
-{
-#ifdef CONFIG_HIGHMEM
-       struct zone *zone;
-       int nid;
-
-       for_each_zone(zone) {
-               unsigned long zone_start_pfn, zone_end_pfn;
-
-               if (!is_highmem(zone))
-                       continue;
-
-               zone_start_pfn = zone->zone_start_pfn;
-               zone_end_pfn = zone_start_pfn + zone->spanned_pages;
-
-               nid = zone_to_nid(zone);
-               printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",
-                               zone->name, nid, zone_start_pfn, zone_end_pfn);
-
-               add_highpages_with_active_regions(nid, zone_start_pfn,
-                                zone_end_pfn);
-       }
-       totalram_pages += totalhigh_pages;
-#endif
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static int paddr_to_nid(u64 addr)
-{
-       int nid;
-       unsigned long pfn = PFN_DOWN(addr);
-
-       for_each_node(nid)
-               if (node_start_pfn[nid] <= pfn &&
-                   pfn < node_end_pfn[nid])
-                       return nid;
-
-       return -1;
-}
-
-/*
- * This function is used to ask node id BEFORE memmap and mem_section's
- * initialization (pfn_to_nid() can't be used yet).
- * If _PXM is not defined on ACPI's DSDT, node id must be found by this.
- */
-int memory_add_physaddr_to_nid(u64 addr)
-{
-       int nid = paddr_to_nid(addr);
-       return (nid >= 0) ? nid : 0;
-}
-
-EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
-#endif
-
index a742d753d5b0ae438a65e976354556a8b0c938b1..31e8730fa2463214f36c2f6b3df9d0f75f6be346 100644 (file)
@@ -592,11 +592,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
        unsigned long flags;
 #endif
 
-       /*
-        * We can fault from pretty much anywhere, with unknown IRQ state.
-        */
-       trace_hardirqs_fixup();
-
        tsk = current;
        mm = tsk->mm;
        prefetchw(&mm->mmap_sem);
@@ -645,24 +640,23 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
        }
 
 
-#ifdef CONFIG_X86_32
-       /* It's safe to allow irq's after cr2 has been saved and the vmalloc
-          fault has been handled. */
-       if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
-               local_irq_enable();
-
        /*
-        * If we're in an interrupt, have no user context or are running in an
-        * atomic region then we must not take the fault.
+        * It's safe to allow irq's after cr2 has been saved and the
+        * vmalloc fault has been handled.
+        *
+        * User-mode registers count as a user access even for any
+        * potential system fault or CPU buglet.
         */
-       if (in_atomic() || !mm)
-               goto bad_area_nosemaphore;
-#else /* CONFIG_X86_64 */
-       if (likely(regs->flags & X86_EFLAGS_IF))
+       if (user_mode_vm(regs)) {
+               local_irq_enable();
+               error_code |= PF_USER;
+       } else if (regs->flags & X86_EFLAGS_IF)
                local_irq_enable();
 
+#ifdef CONFIG_X86_64
        if (unlikely(error_code & PF_RSVD))
                pgtable_bad(address, regs, error_code);
+#endif
 
        /*
         * If we're in an interrupt, have no user context or are running in an
@@ -671,15 +665,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
        if (unlikely(in_atomic() || !mm))
                goto bad_area_nosemaphore;
 
-       /*
-        * User-mode registers count as a user access even for any
-        * potential system fault or CPU buglet.
-        */
-       if (user_mode_vm(regs))
-               error_code |= PF_USER;
 again:
-#endif
-       /* When running in the kernel we expect faults to occur only to
+       /*
+        * 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.  Unfortunately, in the case of an
         * erroneous fault occurring in a code path which already holds mmap_sem
@@ -742,9 +730,6 @@ good_area:
                        goto bad_area;
        }
 
-#ifdef CONFIG_X86_32
-survive:
-#endif
        /*
         * If for any reason at all we couldn't handle the fault,
         * make sure we exit gracefully rather than endlessly redo
@@ -879,12 +864,11 @@ out_of_memory:
        up_read(&mm->mmap_sem);
        if (is_global_init(tsk)) {
                yield();
-#ifdef CONFIG_X86_32
-               down_read(&mm->mmap_sem);
-               goto survive;
-#else
+               /*
+                * Re-lookup the vma - in theory the vma tree might
+                * have changed:
+                */
                goto again;
-#endif
        }
 
        printk("VM: killing process %s\n", tsk->comm);
index 007bb06c750477b60c158f667f5d0563c2d77433..4ba373c5b8c8b94eec4902f2ec3f1448b8b1f6af 100644 (file)
@@ -82,7 +82,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                pte_t pte = gup_get_pte(ptep);
                struct page *page;
 
-               if ((pte_val(pte) & (mask | _PAGE_SPECIAL)) != mask) {
+               if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
                        pte_unmap(ptep);
                        return 0;
                }
@@ -116,10 +116,10 @@ static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
        mask = _PAGE_PRESENT|_PAGE_USER;
        if (write)
                mask |= _PAGE_RW;
-       if ((pte_val(pte) & mask) != mask)
+       if ((pte_flags(pte) & mask) != mask)
                return 0;
        /* hugepages are never "special" */
-       VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL);
+       VM_BUG_ON(pte_flags(pte) & _PAGE_SPECIAL);
        VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 
        refs = 0;
@@ -173,10 +173,10 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr,
        mask = _PAGE_PRESENT|_PAGE_USER;
        if (write)
                mask |= _PAGE_RW;
-       if ((pte_val(pte) & mask) != mask)
+       if ((pte_flags(pte) & mask) != mask)
                return 0;
        /* hugepages are never "special" */
-       VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL);
+       VM_BUG_ON(pte_flags(pte) & _PAGE_SPECIAL);
        VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
 
        refs = 0;
index bbe044dbe01403b0bdf67dbf4fe7e46e4e00a07e..8396868e82c5637772f8d9fe81129731f87d2e24 100644 (file)
@@ -558,7 +558,7 @@ void zap_low_mappings(void)
 
 int nx_enabled;
 
-pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
+pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
 #ifdef CONFIG_X86_PAE
index 3e10054c57319c25626bd1f43bf830c11453b255..b8e461d4941208fab60f977471dbe088ce48d23e 100644 (file)
@@ -89,7 +89,7 @@ early_param("gbpages", parse_direct_gbpages_on);
 
 int after_bootmem;
 
-unsigned long __supported_pte_mask __read_mostly = ~0UL;
+pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
 static int do_not_nx __cpuinitdata;
@@ -196,9 +196,6 @@ set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte)
        }
 
        pte = pte_offset_kernel(pmd, vaddr);
-       if (!pte_none(*pte) && pte_val(new_pte) &&
-           pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
-               pte_ERROR(*pte);
        set_pte(pte, new_pte);
 
        /*
@@ -313,7 +310,7 @@ static __ref void *alloc_low_page(unsigned long *phys)
        if (pfn >= table_top)
                panic("alloc_low_page: ran out of memory");
 
-       adr = early_ioremap(pfn * PAGE_SIZE, PAGE_SIZE);
+       adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
        memset(adr, 0, PAGE_SIZE);
        *phys  = pfn * PAGE_SIZE;
        return adr;
@@ -749,7 +746,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
                old_start = mr[i].start;
                memmove(&mr[i], &mr[i+1],
                         (nr_range - 1 - i) * sizeof (struct map_range));
-               mr[i].start = old_start;
+               mr[i--].start = old_start;
                nr_range--;
        }
 
index 8cbeda15cd29727bee40bc4f15de3a8fd3b573b2..ae71e11eb3e5e4ddeceadc9128d3afea564f27e0 100644 (file)
@@ -45,6 +45,27 @@ unsigned long __phys_addr(unsigned long x)
 }
 EXPORT_SYMBOL(__phys_addr);
 
+bool __virt_addr_valid(unsigned long x)
+{
+       if (x >= __START_KERNEL_map) {
+               x -= __START_KERNEL_map;
+               if (x >= KERNEL_IMAGE_SIZE)
+                       return false;
+               x += phys_base;
+       } else {
+               if (x < PAGE_OFFSET)
+                       return false;
+               x -= PAGE_OFFSET;
+               if (system_state == SYSTEM_BOOTING ?
+                               x > MAXMEM : !phys_addr_valid(x)) {
+                       return false;
+               }
+       }
+
+       return pfn_valid(x >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(__virt_addr_valid);
+
 #else
 
 static inline int phys_addr_valid(unsigned long addr)
@@ -56,13 +77,24 @@ static inline int phys_addr_valid(unsigned long addr)
 unsigned long __phys_addr(unsigned long x)
 {
        /* VMALLOC_* aren't constants; not available at the boot time */
-       VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING &&
-                                       is_vmalloc_addr((void *)x)));
+       VIRTUAL_BUG_ON(x < PAGE_OFFSET);
+       VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING &&
+               is_vmalloc_addr((void *) x));
        return x - PAGE_OFFSET;
 }
 EXPORT_SYMBOL(__phys_addr);
 #endif
 
+bool __virt_addr_valid(unsigned long x)
+{
+       if (x < PAGE_OFFSET)
+               return false;
+       if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x))
+               return false;
+       return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(__virt_addr_valid);
+
 #endif
 
 int page_is_ram(unsigned long pagenr)
@@ -187,6 +219,12 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        if (is_ISA_range(phys_addr, last_addr))
                return (__force void __iomem *)phys_to_virt(phys_addr);
 
+       /*
+        * Check if the request spans more than any BAR in the iomem resource
+        * tree.
+        */
+       WARN_ON(iomem_map_sanity_check(phys_addr, size));
+
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
@@ -242,16 +280,16 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        switch (prot_val) {
        case _PAGE_CACHE_UC:
        default:
-               prot = PAGE_KERNEL_NOCACHE;
+               prot = PAGE_KERNEL_IO_NOCACHE;
                break;
        case _PAGE_CACHE_UC_MINUS:
-               prot = PAGE_KERNEL_UC_MINUS;
+               prot = PAGE_KERNEL_IO_UC_MINUS;
                break;
        case _PAGE_CACHE_WC:
-               prot = PAGE_KERNEL_WC;
+               prot = PAGE_KERNEL_IO_WC;
                break;
        case _PAGE_CACHE_WB:
-               prot = PAGE_KERNEL;
+               prot = PAGE_KERNEL_IO;
                break;
        }
 
@@ -568,12 +606,12 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
 }
 
 static inline void __init early_set_fixmap(enum fixed_addresses idx,
-                                       unsigned long phys)
+                                          unsigned long phys, pgprot_t prot)
 {
        if (after_paging_init)
-               set_fixmap(idx, phys);
+               __set_fixmap(idx, phys, prot);
        else
-               __early_set_fixmap(idx, phys, PAGE_KERNEL);
+               __early_set_fixmap(idx, phys, prot);
 }
 
 static inline void __init early_clear_fixmap(enum fixed_addresses idx)
@@ -584,16 +622,22 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx)
                __early_set_fixmap(idx, 0, __pgprot(0));
 }
 
-
-static int __initdata early_ioremap_nested;
-
+static void *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
 static int __init check_early_ioremap_leak(void)
 {
-       if (!early_ioremap_nested)
+       int count = 0;
+       int i;
+
+       for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+               if (prev_map[i])
+                       count++;
+
+       if (!count)
                return 0;
        WARN(1, KERN_WARNING
               "Debug warning: early ioremap leak of %d areas detected.\n",
-               early_ioremap_nested);
+               count);
        printk(KERN_WARNING
                "please boot with early_ioremap_debug and report the dmesg.\n");
 
@@ -601,18 +645,33 @@ static int __init check_early_ioremap_leak(void)
 }
 late_initcall(check_early_ioremap_leak);
 
-void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
+static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
 {
        unsigned long offset, last_addr;
-       unsigned int nrpages, nesting;
+       unsigned int nrpages;
        enum fixed_addresses idx0, idx;
+       int i, slot;
 
        WARN_ON(system_state != SYSTEM_BOOTING);
 
-       nesting = early_ioremap_nested;
+       slot = -1;
+       for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+               if (!prev_map[i]) {
+                       slot = i;
+                       break;
+               }
+       }
+
+       if (slot < 0) {
+               printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n",
+                        phys_addr, size);
+               WARN_ON(1);
+               return NULL;
+       }
+
        if (early_ioremap_debug) {
                printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
-                      phys_addr, size, nesting);
+                      phys_addr, size, slot);
                dump_stack();
        }
 
@@ -623,11 +682,7 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
                return NULL;
        }
 
-       if (nesting >= FIX_BTMAPS_NESTING) {
-               WARN_ON(1);
-               return NULL;
-       }
-       early_ioremap_nested++;
+       prev_size[slot] = size;
        /*
         * Mappings have to be page-aligned
         */
@@ -647,10 +702,10 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
        /*
         * Ok, go for it..
         */
-       idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
+       idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
        idx = idx0;
        while (nrpages > 0) {
-               early_set_fixmap(idx, phys_addr);
+               early_set_fixmap(idx, phys_addr, prot);
                phys_addr += PAGE_SIZE;
                --idx;
                --nrpages;
@@ -658,7 +713,20 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
        if (early_ioremap_debug)
                printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
 
-       return (void *) (offset + fix_to_virt(idx0));
+       prev_map[slot] = (void *) (offset + fix_to_virt(idx0));
+       return prev_map[slot];
+}
+
+/* Remap an IO device */
+void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
+{
+       return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
+}
+
+/* Remap memory */
+void __init *early_memremap(unsigned long phys_addr, unsigned long size)
+{
+       return __early_ioremap(phys_addr, size, PAGE_KERNEL);
 }
 
 void __init early_iounmap(void *addr, unsigned long size)
@@ -667,15 +735,33 @@ void __init early_iounmap(void *addr, unsigned long size)
        unsigned long offset;
        unsigned int nrpages;
        enum fixed_addresses idx;
-       int nesting;
+       int i, slot;
+
+       slot = -1;
+       for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+               if (prev_map[i] == addr) {
+                       slot = i;
+                       break;
+               }
+       }
 
-       nesting = --early_ioremap_nested;
-       if (WARN_ON(nesting < 0))
+       if (slot < 0) {
+               printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n",
+                        addr, size);
+               WARN_ON(1);
+               return;
+       }
+
+       if (prev_size[slot] != size) {
+               printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
+                        addr, size, slot, prev_size[slot]);
+               WARN_ON(1);
                return;
+       }
 
        if (early_ioremap_debug) {
                printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
-                      size, nesting);
+                      size, slot);
                dump_stack();
        }
 
@@ -687,12 +773,13 @@ void __init early_iounmap(void *addr, unsigned long size)
        offset = virt_addr & ~PAGE_MASK;
        nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
 
-       idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
+       idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
        while (nrpages > 0) {
                early_clear_fixmap(idx);
                --idx;
                --nrpages;
        }
+       prev_map[slot] = 0;
 }
 
 void __this_fixmap_does_not_exist(void)
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
new file mode 100644 (file)
index 0000000..847c164
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Written by: Patricia Gaughen <gone@us.ibm.com>, IBM Corporation
+ * August 2002: added remote node KVA remap - Martin J. Bligh 
+ *
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/highmem.h>
+#include <linux/initrd.h>
+#include <linux/nodemask.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/pfn.h>
+#include <linux/swap.h>
+#include <linux/acpi.h>
+
+#include <asm/e820.h>
+#include <asm/setup.h>
+#include <asm/mmzone.h>
+#include <asm/bios_ebda.h>
+#include <asm/proto.h>
+
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_data);
+
+/*
+ * numa interface - we expect the numa architecture specific code to have
+ *                  populated the following initialisation.
+ *
+ * 1) node_online_map  - the map of all nodes configured (online) in the system
+ * 2) node_start_pfn   - the starting page frame number for a node
+ * 3) node_end_pfn     - the ending page fram number for a node
+ */
+unsigned long node_start_pfn[MAX_NUMNODES] __read_mostly;
+unsigned long node_end_pfn[MAX_NUMNODES] __read_mostly;
+
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * 4) physnode_map     - the mapping between a pfn and owning node
+ * physnode_map keeps track of the physical memory layout of a generic
+ * numa node on a 64Mb break (each element of the array will
+ * represent 64Mb of memory and will be marked by the node id.  so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ *
+ *     physnode_map[0-15] = 0;
+ *     physnode_map[16-31] = 1;
+ *     physnode_map[32- ] = -1;
+ */
+s8 physnode_map[MAX_ELEMENTS] __read_mostly = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+EXPORT_SYMBOL(physnode_map);
+
+void memory_present(int nid, unsigned long start, unsigned long end)
+{
+       unsigned long pfn;
+
+       printk(KERN_INFO "Node: %d, start_pfn: %lx, end_pfn: %lx\n",
+                       nid, start, end);
+       printk(KERN_DEBUG "  Setting physnode_map array to node %d for pfns:\n", nid);
+       printk(KERN_DEBUG "  ");
+       for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
+               physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
+               printk(KERN_CONT "%lx ", pfn);
+       }
+       printk(KERN_CONT "\n");
+}
+
+unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
+                                             unsigned long end_pfn)
+{
+       unsigned long nr_pages = end_pfn - start_pfn;
+
+       if (!nr_pages)
+               return 0;
+
+       return (nr_pages + 1) * sizeof(struct page);
+}
+#endif
+
+extern unsigned long find_max_low_pfn(void);
+extern unsigned long highend_pfn, highstart_pfn;
+
+#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE)
+
+unsigned long node_remap_size[MAX_NUMNODES];
+static void *node_remap_start_vaddr[MAX_NUMNODES];
+void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
+
+static unsigned long kva_start_pfn;
+static unsigned long kva_pages;
+/*
+ * FLAT - support for basic PC memory model with discontig enabled, essentially
+ *        a single node with all available processors in it with a flat
+ *        memory map.
+ */
+int __init get_memcfg_numa_flat(void)
+{
+       printk(KERN_DEBUG "NUMA - single node, flat memory mode\n");
+
+       node_start_pfn[0] = 0;
+       node_end_pfn[0] = max_pfn;
+       e820_register_active_regions(0, 0, max_pfn);
+       memory_present(0, 0, max_pfn);
+       node_remap_size[0] = node_memmap_size_bytes(0, 0, max_pfn);
+
+        /* Indicate there is one node available. */
+       nodes_clear(node_online_map);
+       node_set_online(0);
+       return 1;
+}
+
+/*
+ * Find the highest page frame number we have available for the node
+ */
+static void __init propagate_e820_map_node(int nid)
+{
+       if (node_end_pfn[nid] > max_pfn)
+               node_end_pfn[nid] = max_pfn;
+       /*
+        * if a user has given mem=XXXX, then we need to make sure 
+        * that the node _starts_ before that, too, not just ends
+        */
+       if (node_start_pfn[nid] > max_pfn)
+               node_start_pfn[nid] = max_pfn;
+       BUG_ON(node_start_pfn[nid] > node_end_pfn[nid]);
+}
+
+/* 
+ * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
+ * method.  For node zero take this from the bottom of memory, for
+ * subsequent nodes place them at node_remap_start_vaddr which contains
+ * node local data in physically node local memory.  See setup_memory()
+ * for details.
+ */
+static void __init allocate_pgdat(int nid)
+{
+       char buf[16];
+
+       if (node_has_online_mem(nid) && node_remap_start_vaddr[nid])
+               NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
+       else {
+               unsigned long pgdat_phys;
+               pgdat_phys = find_e820_area(min_low_pfn<<PAGE_SHIFT,
+                                max_pfn_mapped<<PAGE_SHIFT,
+                                sizeof(pg_data_t),
+                                PAGE_SIZE);
+               NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(pgdat_phys>>PAGE_SHIFT));
+               memset(buf, 0, sizeof(buf));
+               sprintf(buf, "NODE_DATA %d",  nid);
+               reserve_early(pgdat_phys, pgdat_phys + sizeof(pg_data_t), buf);
+       }
+       printk(KERN_DEBUG "allocate_pgdat: node %d NODE_DATA %08lx\n",
+               nid, (unsigned long)NODE_DATA(nid));
+}
+
+/*
+ * In the DISCONTIGMEM and SPARSEMEM memory model, a portion of the kernel
+ * virtual address space (KVA) is reserved and portions of nodes are mapped
+ * using it. This is to allow node-local memory to be allocated for
+ * structures that would normally require ZONE_NORMAL. The memory is
+ * allocated with alloc_remap() and callers should be prepared to allocate
+ * from the bootmem allocator instead.
+ */
+static unsigned long node_remap_start_pfn[MAX_NUMNODES];
+static void *node_remap_end_vaddr[MAX_NUMNODES];
+static void *node_remap_alloc_vaddr[MAX_NUMNODES];
+static unsigned long node_remap_offset[MAX_NUMNODES];
+
+void *alloc_remap(int nid, unsigned long size)
+{
+       void *allocation = node_remap_alloc_vaddr[nid];
+
+       size = ALIGN(size, L1_CACHE_BYTES);
+
+       if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
+               return 0;
+
+       node_remap_alloc_vaddr[nid] += size;
+       memset(allocation, 0, size);
+
+       return allocation;
+}
+
+static void __init remap_numa_kva(void)
+{
+       void *vaddr;
+       unsigned long pfn;
+       int node;
+
+       for_each_online_node(node) {
+               printk(KERN_DEBUG "remap_numa_kva: node %d\n", node);
+               for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
+                       vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
+                       printk(KERN_DEBUG "remap_numa_kva: %08lx to pfn %08lx\n",
+                               (unsigned long)vaddr,
+                               node_remap_start_pfn[node] + pfn);
+                       set_pmd_pfn((ulong) vaddr, 
+                               node_remap_start_pfn[node] + pfn, 
+                               PAGE_KERNEL_LARGE);
+               }
+       }
+}
+
+static unsigned long calculate_numa_remap_pages(void)
+{
+       int nid;
+       unsigned long size, reserve_pages = 0;
+
+       for_each_online_node(nid) {
+               u64 node_kva_target;
+               u64 node_kva_final;
+
+               /*
+                * The acpi/srat node info can show hot-add memroy zones
+                * where memory could be added but not currently present.
+                */
+               printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n",
+                       nid, node_start_pfn[nid], node_end_pfn[nid]);
+               if (node_start_pfn[nid] > max_pfn)
+                       continue;
+               if (!node_end_pfn[nid])
+                       continue;
+               if (node_end_pfn[nid] > max_pfn)
+                       node_end_pfn[nid] = max_pfn;
+
+               /* ensure the remap includes space for the pgdat. */
+               size = node_remap_size[nid] + sizeof(pg_data_t);
+
+               /* convert size to large (pmd size) pages, rounding up */
+               size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
+               /* now the roundup is correct, convert to PAGE_SIZE pages */
+               size = size * PTRS_PER_PTE;
+
+               node_kva_target = round_down(node_end_pfn[nid] - size,
+                                                PTRS_PER_PTE);
+               node_kva_target <<= PAGE_SHIFT;
+               do {
+                       node_kva_final = find_e820_area(node_kva_target,
+                                       ((u64)node_end_pfn[nid])<<PAGE_SHIFT,
+                                               ((u64)size)<<PAGE_SHIFT,
+                                               LARGE_PAGE_BYTES);
+                       node_kva_target -= LARGE_PAGE_BYTES;
+               } while (node_kva_final == -1ULL &&
+                        (node_kva_target>>PAGE_SHIFT) > (node_start_pfn[nid]));
+
+               if (node_kva_final == -1ULL)
+                       panic("Can not get kva ram\n");
+
+               node_remap_size[nid] = size;
+               node_remap_offset[nid] = reserve_pages;
+               reserve_pages += size;
+               printk(KERN_DEBUG "Reserving %ld pages of KVA for lmem_map of"
+                                 " node %d at %llx\n",
+                               size, nid, node_kva_final>>PAGE_SHIFT);
+
+               /*
+                *  prevent kva address below max_low_pfn want it on system
+                *  with less memory later.
+                *  layout will be: KVA address , KVA RAM
+                *
+                *  we are supposed to only record the one less then max_low_pfn
+                *  but we could have some hole in high memory, and it will only
+                *  check page_is_ram(pfn) && !page_is_reserved_early(pfn) to decide
+                *  to use it as free.
+                *  So reserve_early here, hope we don't run out of that array
+                */
+               reserve_early(node_kva_final,
+                             node_kva_final+(((u64)size)<<PAGE_SHIFT),
+                             "KVA RAM");
+
+               node_remap_start_pfn[nid] = node_kva_final>>PAGE_SHIFT;
+               remove_active_range(nid, node_remap_start_pfn[nid],
+                                        node_remap_start_pfn[nid] + size);
+       }
+       printk(KERN_INFO "Reserving total of %lx pages for numa KVA remap\n",
+                       reserve_pages);
+       return reserve_pages;
+}
+
+static void init_remap_allocator(int nid)
+{
+       node_remap_start_vaddr[nid] = pfn_to_kaddr(
+                       kva_start_pfn + node_remap_offset[nid]);
+       node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
+               (node_remap_size[nid] * PAGE_SIZE);
+       node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
+               ALIGN(sizeof(pg_data_t), PAGE_SIZE);
+
+       printk(KERN_DEBUG "node %d will remap to vaddr %08lx - %08lx\n", nid,
+               (ulong) node_remap_start_vaddr[nid],
+               (ulong) node_remap_end_vaddr[nid]);
+}
+
+void __init initmem_init(unsigned long start_pfn,
+                                 unsigned long end_pfn)
+{
+       int nid;
+       long kva_target_pfn;
+
+       /*
+        * When mapping a NUMA machine we allocate the node_mem_map arrays
+        * from node local memory.  They are then mapped directly into KVA
+        * between zone normal and vmalloc space.  Calculate the size of
+        * this space and use it to adjust the boundary between ZONE_NORMAL
+        * and ZONE_HIGHMEM.
+        */
+
+       get_memcfg_numa();
+
+       kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
+
+       kva_target_pfn = round_down(max_low_pfn - kva_pages, PTRS_PER_PTE);
+       do {
+               kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
+                                       max_low_pfn<<PAGE_SHIFT,
+                                       kva_pages<<PAGE_SHIFT,
+                                       PTRS_PER_PTE<<PAGE_SHIFT) >> PAGE_SHIFT;
+               kva_target_pfn -= PTRS_PER_PTE;
+       } while (kva_start_pfn == -1UL && kva_target_pfn > min_low_pfn);
+
+       if (kva_start_pfn == -1UL)
+               panic("Can not get kva space\n");
+
+       printk(KERN_INFO "kva_start_pfn ~ %lx max_low_pfn ~ %lx\n",
+               kva_start_pfn, max_low_pfn);
+       printk(KERN_INFO "max_pfn = %lx\n", max_pfn);
+
+       /* avoid clash with initrd */
+       reserve_early(kva_start_pfn<<PAGE_SHIFT,
+                     (kva_start_pfn + kva_pages)<<PAGE_SHIFT,
+                    "KVA PG");
+#ifdef CONFIG_HIGHMEM
+       highstart_pfn = highend_pfn = max_pfn;
+       if (max_pfn > max_low_pfn)
+               highstart_pfn = max_low_pfn;
+       printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+              pages_to_mb(highend_pfn - highstart_pfn));
+       num_physpages = highend_pfn;
+       high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+       num_physpages = max_low_pfn;
+       high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+#endif
+       printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+                       pages_to_mb(max_low_pfn));
+       printk(KERN_DEBUG "max_low_pfn = %lx, highstart_pfn = %lx\n",
+                       max_low_pfn, highstart_pfn);
+
+       printk(KERN_DEBUG "Low memory ends at vaddr %08lx\n",
+                       (ulong) pfn_to_kaddr(max_low_pfn));
+       for_each_online_node(nid) {
+               init_remap_allocator(nid);
+
+               allocate_pgdat(nid);
+       }
+       remap_numa_kva();
+
+       printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
+                       (ulong) pfn_to_kaddr(highstart_pfn));
+       for_each_online_node(nid)
+               propagate_e820_map_node(nid);
+
+       for_each_online_node(nid)
+               memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+
+       NODE_DATA(0)->bdata = &bootmem_node_data[0];
+       setup_bootmem_allocator();
+}
+
+void __init set_highmem_pages_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+       struct zone *zone;
+       int nid;
+
+       for_each_zone(zone) {
+               unsigned long zone_start_pfn, zone_end_pfn;
+
+               if (!is_highmem(zone))
+                       continue;
+
+               zone_start_pfn = zone->zone_start_pfn;
+               zone_end_pfn = zone_start_pfn + zone->spanned_pages;
+
+               nid = zone_to_nid(zone);
+               printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",
+                               zone->name, nid, zone_start_pfn, zone_end_pfn);
+
+               add_highpages_with_active_regions(nid, zone_start_pfn,
+                                zone_end_pfn);
+       }
+       totalram_pages += totalhigh_pages;
+#endif
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static int paddr_to_nid(u64 addr)
+{
+       int nid;
+       unsigned long pfn = PFN_DOWN(addr);
+
+       for_each_node(nid)
+               if (node_start_pfn[nid] <= pfn &&
+                   pfn < node_end_pfn[nid])
+                       return nid;
+
+       return -1;
+}
+
+/*
+ * This function is used to ask node id BEFORE memmap and mem_section's
+ * initialization (pfn_to_nid() can't be used yet).
+ * If _PXM is not defined on ACPI's DSDT, node id must be found by this.
+ */
+int memory_add_physaddr_to_nid(u64 addr)
+{
+       int nid = paddr_to_nid(addr);
+       return (nid >= 0) ? nid : 0;
+}
+
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
+
index 1b4763e26ea96f52b6240475e85a04cb3a06dc4b..51c0a2fc14fe05521def4af57c0e2d1d29c8359d 100644 (file)
@@ -138,7 +138,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
                return;
        }
 
-       if (is_uv_system())
+       if (get_uv_system_type() >= UV_X2APIC)
                apic_id = (pa->apic_id << 8) | pa->local_sapic_eid;
        else
                apic_id = pa->apic_id;
index 30f3eb3666675e4b8a90bff8f0edfd43cfe99f6f..446902b2a6b6a2fac5080d062e8d86b1caea8aae 100644 (file)
@@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                timer_int.o )
 
 oprofile-y                             := $(DRIVER_OBJS) init.o backtrace.o
-oprofile-$(CONFIG_X86_LOCAL_APIC)      += nmi_int.o op_model_athlon.o \
+oprofile-$(CONFIG_X86_LOCAL_APIC)      += nmi_int.o op_model_amd.o \
                                           op_model_ppro.o op_model_p4.o
 oprofile-$(CONFIG_X86_IO_APIC)         += nmi_timer_int.o
index 8a5f1614a3d57cde8d7495c1b71f8e8542e99c64..57f6c90880816b113074cf306f678f8781c04d50 100644 (file)
@@ -1,10 +1,11 @@
 /**
  * @file nmi_int.c
  *
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2008 OProfile authors
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ * @author Robert Richter <robert.richter@amd.com>
  */
 
 #include <linux/init.h>
@@ -439,6 +440,7 @@ int __init op_nmi_init(struct oprofile_operations *ops)
        __u8 vendor = boot_cpu_data.x86_vendor;
        __u8 family = boot_cpu_data.x86;
        char *cpu_type;
+       int ret = 0;
 
        if (!cpu_has_apic)
                return -ENODEV;
@@ -451,19 +453,23 @@ int __init op_nmi_init(struct oprofile_operations *ops)
                default:
                        return -ENODEV;
                case 6:
-                       model = &op_athlon_spec;
+                       model = &op_amd_spec;
                        cpu_type = "i386/athlon";
                        break;
                case 0xf:
-                       model = &op_athlon_spec;
+                       model = &op_amd_spec;
                        /* Actually it could be i386/hammer too, but give
                         user space an consistent name. */
                        cpu_type = "x86-64/hammer";
                        break;
                case 0x10:
-                       model = &op_athlon_spec;
+                       model = &op_amd_spec;
                        cpu_type = "x86-64/family10";
                        break;
+               case 0x11:
+                       model = &op_amd_spec;
+                       cpu_type = "x86-64/family11h";
+                       break;
                }
                break;
 
@@ -490,17 +496,24 @@ int __init op_nmi_init(struct oprofile_operations *ops)
                return -ENODEV;
        }
 
-       init_sysfs();
 #ifdef CONFIG_SMP
        register_cpu_notifier(&oprofile_cpu_nb);
 #endif
-       using_nmi = 1;
+       /* default values, can be overwritten by model */
        ops->create_files = nmi_create_files;
        ops->setup = nmi_setup;
        ops->shutdown = nmi_shutdown;
        ops->start = nmi_start;
        ops->stop = nmi_stop;
        ops->cpu_type = cpu_type;
+
+       if (model->init)
+               ret = model->init(ops);
+       if (ret)
+               return ret;
+
+       init_sysfs();
+       using_nmi = 1;
        printk(KERN_INFO "oprofile: using NMI interrupt.\n");
        return 0;
 }
@@ -513,4 +526,6 @@ void op_nmi_exit(void)
                unregister_cpu_notifier(&oprofile_cpu_nb);
 #endif
        }
+       if (model->exit)
+               model->exit();
 }
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
new file mode 100644 (file)
index 0000000..d9faf60
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * @file op_model_amd.c
+ * athlon / K7 / K8 / Family 10h model-specific MSR operations
+ *
+ * @remark Copyright 2002-2008 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon
+ * @author Philippe Elie
+ * @author Graydon Hoare
+ * @author Robert Richter <robert.richter@amd.com>
+ * @author Barry Kasindorf
+*/
+
+#include <linux/oprofile.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include <asm/ptrace.h>
+#include <asm/msr.h>
+#include <asm/nmi.h>
+
+#include "op_x86_model.h"
+#include "op_counter.h"
+
+#define NUM_COUNTERS 4
+#define NUM_CONTROLS 4
+
+#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
+#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
+#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0)
+#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
+
+#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
+#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
+#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
+#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
+#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
+#define CTRL_CLEAR_LO(x) (x &= (1<<21))
+#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
+#define CTRL_SET_ENABLE(val) (val |= 1<<20)
+#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
+#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
+#define CTRL_SET_UM(val, m) (val |= (m << 8))
+#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
+#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
+#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9))
+#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
+
+static unsigned long reset_value[NUM_COUNTERS];
+
+#ifdef CONFIG_OPROFILE_IBS
+
+/* IbsFetchCtl bits/masks */
+#define IBS_FETCH_HIGH_VALID_BIT       (1UL << 17)     /* bit 49 */
+#define IBS_FETCH_HIGH_ENABLE          (1UL << 16)     /* bit 48 */
+#define IBS_FETCH_LOW_MAX_CNT_MASK     0x0000FFFFUL    /* MaxCnt mask */
+
+/*IbsOpCtl bits */
+#define IBS_OP_LOW_VALID_BIT           (1ULL<<18)      /* bit 18 */
+#define IBS_OP_LOW_ENABLE              (1ULL<<17)      /* bit 17 */
+
+/* Codes used in cpu_buffer.c */
+/* This produces duplicate code, need to be fixed */
+#define IBS_FETCH_BEGIN 3
+#define IBS_OP_BEGIN    4
+
+/* The function interface needs to be fixed, something like add
+   data. Should then be added to linux/oprofile.h. */
+extern void oprofile_add_ibs_sample(struct pt_regs *const regs,
+                                   unsigned int * const ibs_sample, u8 code);
+
+struct ibs_fetch_sample {
+       /* MSRC001_1031 IBS Fetch Linear Address Register */
+       unsigned int ibs_fetch_lin_addr_low;
+       unsigned int ibs_fetch_lin_addr_high;
+       /* MSRC001_1030 IBS Fetch Control Register */
+       unsigned int ibs_fetch_ctl_low;
+       unsigned int ibs_fetch_ctl_high;
+       /* MSRC001_1032 IBS Fetch Physical Address Register */
+       unsigned int ibs_fetch_phys_addr_low;
+       unsigned int ibs_fetch_phys_addr_high;
+};
+
+struct ibs_op_sample {
+       /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */
+       unsigned int ibs_op_rip_low;
+       unsigned int ibs_op_rip_high;
+       /* MSRC001_1035 IBS Op Data Register */
+       unsigned int ibs_op_data1_low;
+       unsigned int ibs_op_data1_high;
+       /* MSRC001_1036 IBS Op Data 2 Register */
+       unsigned int ibs_op_data2_low;
+       unsigned int ibs_op_data2_high;
+       /* MSRC001_1037 IBS Op Data 3 Register */
+       unsigned int ibs_op_data3_low;
+       unsigned int ibs_op_data3_high;
+       /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */
+       unsigned int ibs_dc_linear_low;
+       unsigned int ibs_dc_linear_high;
+       /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */
+       unsigned int ibs_dc_phys_low;
+       unsigned int ibs_dc_phys_high;
+};
+
+/*
+ * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+
+*/
+static void clear_ibs_nmi(void);
+
+static int ibs_allowed;        /* AMD Family10h and later */
+
+struct op_ibs_config {
+       unsigned long op_enabled;
+       unsigned long fetch_enabled;
+       unsigned long max_cnt_fetch;
+       unsigned long max_cnt_op;
+       unsigned long rand_en;
+       unsigned long dispatched_ops;
+};
+
+static struct op_ibs_config ibs_config;
+
+#endif
+
+/* functions for op_amd_spec */
+
+static void op_amd_fill_in_addresses(struct op_msrs * const msrs)
+{
+       int i;
+
+       for (i = 0; i < NUM_COUNTERS; i++) {
+               if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+                       msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+               else
+                       msrs->counters[i].addr = 0;
+       }
+
+       for (i = 0; i < NUM_CONTROLS; i++) {
+               if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+                       msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+               else
+                       msrs->controls[i].addr = 0;
+       }
+}
+
+
+static void op_amd_setup_ctrs(struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       int i;
+
+       /* clear all counters */
+       for (i = 0 ; i < NUM_CONTROLS; ++i) {
+               if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
+                       continue;
+               CTRL_READ(low, high, msrs, i);
+               CTRL_CLEAR_LO(low);
+               CTRL_CLEAR_HI(high);
+               CTRL_WRITE(low, high, msrs, i);
+       }
+
+       /* avoid a false detection of ctr overflows in NMI handler */
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               if (unlikely(!CTR_IS_RESERVED(msrs, i)))
+                       continue;
+               CTR_WRITE(1, msrs, i);
+       }
+
+       /* enable active counters */
+       for (i = 0; i < NUM_COUNTERS; ++i) {
+               if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
+                       reset_value[i] = counter_config[i].count;
+
+                       CTR_WRITE(counter_config[i].count, msrs, i);
+
+                       CTRL_READ(low, high, msrs, i);
+                       CTRL_CLEAR_LO(low);
+                       CTRL_CLEAR_HI(high);
+                       CTRL_SET_ENABLE(low);
+                       CTRL_SET_USR(low, counter_config[i].user);
+                       CTRL_SET_KERN(low, counter_config[i].kernel);
+                       CTRL_SET_UM(low, counter_config[i].unit_mask);
+                       CTRL_SET_EVENT_LOW(low, counter_config[i].event);
+                       CTRL_SET_EVENT_HIGH(high, counter_config[i].event);
+                       CTRL_SET_HOST_ONLY(high, 0);
+                       CTRL_SET_GUEST_ONLY(high, 0);
+
+                       CTRL_WRITE(low, high, msrs, i);
+               } else {
+                       reset_value[i] = 0;
+               }
+       }
+}
+
+#ifdef CONFIG_OPROFILE_IBS
+
+static inline int
+op_amd_handle_ibs(struct pt_regs * const regs,
+                 struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       struct ibs_fetch_sample ibs_fetch;
+       struct ibs_op_sample ibs_op;
+
+       if (!ibs_allowed)
+               return 1;
+
+       if (ibs_config.fetch_enabled) {
+               rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
+               if (high & IBS_FETCH_HIGH_VALID_BIT) {
+                       ibs_fetch.ibs_fetch_ctl_high = high;
+                       ibs_fetch.ibs_fetch_ctl_low = low;
+                       rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high);
+                       ibs_fetch.ibs_fetch_lin_addr_high = high;
+                       ibs_fetch.ibs_fetch_lin_addr_low = low;
+                       rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high);
+                       ibs_fetch.ibs_fetch_phys_addr_high = high;
+                       ibs_fetch.ibs_fetch_phys_addr_low = low;
+
+                       oprofile_add_ibs_sample(regs,
+                                               (unsigned int *)&ibs_fetch,
+                                               IBS_FETCH_BEGIN);
+
+                       /*reenable the IRQ */
+                       rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
+                       high &= ~IBS_FETCH_HIGH_VALID_BIT;
+                       high |= IBS_FETCH_HIGH_ENABLE;
+                       low &= IBS_FETCH_LOW_MAX_CNT_MASK;
+                       wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
+               }
+       }
+
+       if (ibs_config.op_enabled) {
+               rdmsr(MSR_AMD64_IBSOPCTL, low, high);
+               if (low & IBS_OP_LOW_VALID_BIT) {
+                       rdmsr(MSR_AMD64_IBSOPRIP, low, high);
+                       ibs_op.ibs_op_rip_low = low;
+                       ibs_op.ibs_op_rip_high = high;
+                       rdmsr(MSR_AMD64_IBSOPDATA, low, high);
+                       ibs_op.ibs_op_data1_low = low;
+                       ibs_op.ibs_op_data1_high = high;
+                       rdmsr(MSR_AMD64_IBSOPDATA2, low, high);
+                       ibs_op.ibs_op_data2_low = low;
+                       ibs_op.ibs_op_data2_high = high;
+                       rdmsr(MSR_AMD64_IBSOPDATA3, low, high);
+                       ibs_op.ibs_op_data3_low = low;
+                       ibs_op.ibs_op_data3_high = high;
+                       rdmsr(MSR_AMD64_IBSDCLINAD, low, high);
+                       ibs_op.ibs_dc_linear_low = low;
+                       ibs_op.ibs_dc_linear_high = high;
+                       rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high);
+                       ibs_op.ibs_dc_phys_low = low;
+                       ibs_op.ibs_dc_phys_high = high;
+
+                       /* reenable the IRQ */
+                       oprofile_add_ibs_sample(regs,
+                                               (unsigned int *)&ibs_op,
+                                               IBS_OP_BEGIN);
+                       rdmsr(MSR_AMD64_IBSOPCTL, low, high);
+                       high = 0;
+                       low &= ~IBS_OP_LOW_VALID_BIT;
+                       low |= IBS_OP_LOW_ENABLE;
+                       wrmsr(MSR_AMD64_IBSOPCTL, low, high);
+               }
+       }
+
+       return 1;
+}
+
+#endif
+
+static int op_amd_check_ctrs(struct pt_regs * const regs,
+                            struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       int i;
+
+       for (i = 0 ; i < NUM_COUNTERS; ++i) {
+               if (!reset_value[i])
+                       continue;
+               CTR_READ(low, high, msrs, i);
+               if (CTR_OVERFLOWED(low)) {
+                       oprofile_add_sample(regs, i);
+                       CTR_WRITE(reset_value[i], msrs, i);
+               }
+       }
+
+#ifdef CONFIG_OPROFILE_IBS
+       op_amd_handle_ibs(regs, msrs);
+#endif
+
+       /* See op_model_ppro.c */
+       return 1;
+}
+
+static void op_amd_start(struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       int i;
+       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (reset_value[i]) {
+                       CTRL_READ(low, high, msrs, i);
+                       CTRL_SET_ACTIVE(low);
+                       CTRL_WRITE(low, high, msrs, i);
+               }
+       }
+
+#ifdef CONFIG_OPROFILE_IBS
+       if (ibs_allowed && ibs_config.fetch_enabled) {
+               low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
+               high = IBS_FETCH_HIGH_ENABLE;
+               wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
+       }
+
+       if (ibs_allowed && ibs_config.op_enabled) {
+               low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE;
+               high = 0;
+               wrmsr(MSR_AMD64_IBSOPCTL, low, high);
+       }
+#endif
+}
+
+
+static void op_amd_stop(struct op_msrs const * const msrs)
+{
+       unsigned int low, high;
+       int i;
+
+       /* Subtle: stop on all counters to avoid race with
+        * setting our pm callback */
+       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (!reset_value[i])
+                       continue;
+               CTRL_READ(low, high, msrs, i);
+               CTRL_SET_INACTIVE(low);
+               CTRL_WRITE(low, high, msrs, i);
+       }
+
+#ifdef CONFIG_OPROFILE_IBS
+       if (ibs_allowed && ibs_config.fetch_enabled) {
+               low = 0;                /* clear max count and enable */
+               high = 0;
+               wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
+       }
+
+       if (ibs_allowed && ibs_config.op_enabled) {
+               low = 0;                /* clear max count and enable */
+               high = 0;
+               wrmsr(MSR_AMD64_IBSOPCTL, low, high);
+       }
+#endif
+}
+
+static void op_amd_shutdown(struct op_msrs const * const msrs)
+{
+       int i;
+
+       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (CTR_IS_RESERVED(msrs, i))
+                       release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+       }
+       for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+               if (CTRL_IS_RESERVED(msrs, i))
+                       release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+}
+
+#ifndef CONFIG_OPROFILE_IBS
+
+/* no IBS support */
+
+static int op_amd_init(struct oprofile_operations *ops)
+{
+       return 0;
+}
+
+static void op_amd_exit(void) {}
+
+#else
+
+static u8 ibs_eilvt_off;
+
+static inline void apic_init_ibs_nmi_per_cpu(void *arg)
+{
+       ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+}
+
+static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
+{
+       setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+}
+
+static int pfm_amd64_setup_eilvt(void)
+{
+#define IBSCTL_LVTOFFSETVAL            (1 << 8)
+#define IBSCTL                         0x1cc
+       struct pci_dev *cpu_cfg;
+       int nodes;
+       u32 value = 0;
+
+       /* per CPU setup */
+       on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1);
+
+       nodes = 0;
+       cpu_cfg = NULL;
+       do {
+               cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
+                                        PCI_DEVICE_ID_AMD_10H_NB_MISC,
+                                        cpu_cfg);
+               if (!cpu_cfg)
+                       break;
+               ++nodes;
+               pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+                                      | IBSCTL_LVTOFFSETVAL);
+               pci_read_config_dword(cpu_cfg, IBSCTL, &value);
+               if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+                       printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
+                               "IBSCTL = 0x%08x", value);
+                       return 1;
+               }
+       } while (1);
+
+       if (!nodes) {
+               printk(KERN_DEBUG "No CPU node configured for IBS");
+               return 1;
+       }
+
+#ifdef CONFIG_NUMA
+       /* Sanity check */
+       /* Works only for 64bit with proper numa implementation. */
+       if (nodes != num_possible_nodes()) {
+               printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, "
+                       "found: %d, expected %d",
+                       nodes, num_possible_nodes());
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+/*
+ * initialize the APIC for the IBS interrupts
+ * if available (AMD Family10h rev B0 and later)
+ */
+static void setup_ibs(void)
+{
+       ibs_allowed = boot_cpu_has(X86_FEATURE_IBS);
+
+       if (!ibs_allowed)
+               return;
+
+       if (pfm_amd64_setup_eilvt()) {
+               ibs_allowed = 0;
+               return;
+       }
+
+       printk(KERN_INFO "oprofile: AMD IBS detected\n");
+}
+
+
+/*
+ * unitialize the APIC for the IBS interrupts if needed on AMD Family10h
+ * rev B0 and later */
+static void clear_ibs_nmi(void)
+{
+       if (ibs_allowed)
+               on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
+}
+
+static int (*create_arch_files)(struct super_block * sb, struct dentry * root);
+
+static int setup_ibs_files(struct super_block * sb, struct dentry * root)
+{
+       char buf[12];
+       struct dentry *dir;
+       int ret = 0;
+
+       /* architecture specific files */
+       if (create_arch_files)
+               ret = create_arch_files(sb, root);
+
+       if (ret)
+               return ret;
+
+       if (!ibs_allowed)
+               return ret;
+
+       /* model specific files */
+
+       /* setup some reasonable defaults */
+       ibs_config.max_cnt_fetch = 250000;
+       ibs_config.fetch_enabled = 0;
+       ibs_config.max_cnt_op = 250000;
+       ibs_config.op_enabled = 0;
+       ibs_config.dispatched_ops = 1;
+       snprintf(buf,  sizeof(buf), "ibs_fetch");
+       dir = oprofilefs_mkdir(sb, root, buf);
+       oprofilefs_create_ulong(sb, dir, "rand_enable",
+                               &ibs_config.rand_en);
+       oprofilefs_create_ulong(sb, dir, "enable",
+               &ibs_config.fetch_enabled);
+       oprofilefs_create_ulong(sb, dir, "max_count",
+               &ibs_config.max_cnt_fetch);
+       snprintf(buf,  sizeof(buf), "ibs_uops");
+       dir = oprofilefs_mkdir(sb, root, buf);
+       oprofilefs_create_ulong(sb, dir, "enable",
+               &ibs_config.op_enabled);
+       oprofilefs_create_ulong(sb, dir, "max_count",
+               &ibs_config.max_cnt_op);
+       oprofilefs_create_ulong(sb, dir, "dispatched_ops",
+               &ibs_config.dispatched_ops);
+
+       return 0;
+}
+
+static int op_amd_init(struct oprofile_operations *ops)
+{
+       setup_ibs();
+       create_arch_files = ops->create_files;
+       ops->create_files = setup_ibs_files;
+       return 0;
+}
+
+static void op_amd_exit(void)
+{
+       clear_ibs_nmi();
+}
+
+#endif
+
+struct op_x86_model_spec const op_amd_spec = {
+       .init = op_amd_init,
+       .exit = op_amd_exit,
+       .num_counters = NUM_COUNTERS,
+       .num_controls = NUM_CONTROLS,
+       .fill_in_addresses = &op_amd_fill_in_addresses,
+       .setup_ctrs = &op_amd_setup_ctrs,
+       .check_ctrs = &op_amd_check_ctrs,
+       .start = &op_amd_start,
+       .stop = &op_amd_stop,
+       .shutdown = &op_amd_shutdown
+};
diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c
deleted file mode 100644 (file)
index 3d53487..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * @file op_model_athlon.h
- * athlon / K7 / K8 / Family 10h model-specific MSR operations
- *
- * @remark Copyright 2002 OProfile authors
- * @remark Read the file COPYING
- *
- * @author John Levon
- * @author Philippe Elie
- * @author Graydon Hoare
- */
-
-#include <linux/oprofile.h>
-#include <asm/ptrace.h>
-#include <asm/msr.h>
-#include <asm/nmi.h>
-
-#include "op_x86_model.h"
-#include "op_counter.h"
-
-#define NUM_COUNTERS 4
-#define NUM_CONTROLS 4
-
-#define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0)
-#define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0)
-#define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0)
-#define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
-
-#define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0)
-#define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
-#define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0)
-#define CTRL_SET_ACTIVE(n) (n |= (1<<22))
-#define CTRL_SET_INACTIVE(n) (n &= ~(1<<22))
-#define CTRL_CLEAR_LO(x) (x &= (1<<21))
-#define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0)
-#define CTRL_SET_ENABLE(val) (val |= 1<<20)
-#define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16))
-#define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17))
-#define CTRL_SET_UM(val, m) (val |= (m << 8))
-#define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff))
-#define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf))
-#define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9))
-#define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8))
-
-static unsigned long reset_value[NUM_COUNTERS];
-
-static void athlon_fill_in_addresses(struct op_msrs * const msrs)
-{
-       int i;
-
-       for (i = 0; i < NUM_COUNTERS; i++) {
-               if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
-                       msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
-               else
-                       msrs->counters[i].addr = 0;
-       }
-
-       for (i = 0; i < NUM_CONTROLS; i++) {
-               if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
-                       msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
-               else
-                       msrs->controls[i].addr = 0;
-       }
-}
-
-
-static void athlon_setup_ctrs(struct op_msrs const * const msrs)
-{
-       unsigned int low, high;
-       int i;
-
-       /* clear all counters */
-       for (i = 0 ; i < NUM_CONTROLS; ++i) {
-               if (unlikely(!CTRL_IS_RESERVED(msrs, i)))
-                       continue;
-               CTRL_READ(low, high, msrs, i);
-               CTRL_CLEAR_LO(low);
-               CTRL_CLEAR_HI(high);
-               CTRL_WRITE(low, high, msrs, i);
-       }
-
-       /* avoid a false detection of ctr overflows in NMI handler */
-       for (i = 0; i < NUM_COUNTERS; ++i) {
-               if (unlikely(!CTR_IS_RESERVED(msrs, i)))
-                       continue;
-               CTR_WRITE(1, msrs, i);
-       }
-
-       /* enable active counters */
-       for (i = 0; i < NUM_COUNTERS; ++i) {
-               if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) {
-                       reset_value[i] = counter_config[i].count;
-
-                       CTR_WRITE(counter_config[i].count, msrs, i);
-
-                       CTRL_READ(low, high, msrs, i);
-                       CTRL_CLEAR_LO(low);
-                       CTRL_CLEAR_HI(high);
-                       CTRL_SET_ENABLE(low);
-                       CTRL_SET_USR(low, counter_config[i].user);
-                       CTRL_SET_KERN(low, counter_config[i].kernel);
-                       CTRL_SET_UM(low, counter_config[i].unit_mask);
-                       CTRL_SET_EVENT_LOW(low, counter_config[i].event);
-                       CTRL_SET_EVENT_HIGH(high, counter_config[i].event);
-                       CTRL_SET_HOST_ONLY(high, 0);
-                       CTRL_SET_GUEST_ONLY(high, 0);
-
-                       CTRL_WRITE(low, high, msrs, i);
-               } else {
-                       reset_value[i] = 0;
-               }
-       }
-}
-
-
-static int athlon_check_ctrs(struct pt_regs * const regs,
-                            struct op_msrs const * const msrs)
-{
-       unsigned int low, high;
-       int i;
-
-       for (i = 0 ; i < NUM_COUNTERS; ++i) {
-               if (!reset_value[i])
-                       continue;
-               CTR_READ(low, high, msrs, i);
-               if (CTR_OVERFLOWED(low)) {
-                       oprofile_add_sample(regs, i);
-                       CTR_WRITE(reset_value[i], msrs, i);
-               }
-       }
-
-       /* See op_model_ppro.c */
-       return 1;
-}
-
-
-static void athlon_start(struct op_msrs const * const msrs)
-{
-       unsigned int low, high;
-       int i;
-       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
-               if (reset_value[i]) {
-                       CTRL_READ(low, high, msrs, i);
-                       CTRL_SET_ACTIVE(low);
-                       CTRL_WRITE(low, high, msrs, i);
-               }
-       }
-}
-
-
-static void athlon_stop(struct op_msrs const * const msrs)
-{
-       unsigned int low, high;
-       int i;
-
-       /* Subtle: stop on all counters to avoid race with
-        * setting our pm callback */
-       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
-               if (!reset_value[i])
-                       continue;
-               CTRL_READ(low, high, msrs, i);
-               CTRL_SET_INACTIVE(low);
-               CTRL_WRITE(low, high, msrs, i);
-       }
-}
-
-static void athlon_shutdown(struct op_msrs const * const msrs)
-{
-       int i;
-
-       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
-               if (CTR_IS_RESERVED(msrs, i))
-                       release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-       }
-       for (i = 0 ; i < NUM_CONTROLS ; ++i) {
-               if (CTRL_IS_RESERVED(msrs, i))
-                       release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
-       }
-}
-
-struct op_x86_model_spec const op_athlon_spec = {
-       .num_counters = NUM_COUNTERS,
-       .num_controls = NUM_CONTROLS,
-       .fill_in_addresses = &athlon_fill_in_addresses,
-       .setup_ctrs = &athlon_setup_ctrs,
-       .check_ctrs = &athlon_check_ctrs,
-       .start = &athlon_start,
-       .stop = &athlon_stop,
-       .shutdown = &athlon_shutdown
-};
index 45b605fa71d06f6064b7fb6f3d34a017106b3cb9..05a0261ba0c38208f4481d467ffc9efc70e57479 100644 (file)
@@ -32,6 +32,8 @@ struct pt_regs;
  * various x86 CPU models' perfctr support.
  */
 struct op_x86_model_spec {
+       int (*init)(struct oprofile_operations *ops);
+       void (*exit)(void);
        unsigned int const num_counters;
        unsigned int const num_controls;
        void (*fill_in_addresses)(struct op_msrs * const msrs);
@@ -46,6 +48,6 @@ struct op_x86_model_spec {
 extern struct op_x86_model_spec const op_ppro_spec;
 extern struct op_x86_model_spec const op_p4_spec;
 extern struct op_x86_model_spec const op_p4_ht2_spec;
-extern struct op_x86_model_spec const op_athlon_spec;
+extern struct op_x86_model_spec const op_amd_spec;
 
 #endif /* OP_X86_MODEL_H */
index 4bdaa590375dd302bac474145f6614924a7a6387..3c27a809393b59051aaa794ad33b2310fd70402c 100644 (file)
@@ -511,3 +511,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size);
+
+/*
+ * SB600: Disable BAR1 on device 14.0 to avoid HPET resources from
+ * confusing the PCI engine:
+ */
+static void sb600_disable_hpet_bar(struct pci_dev *dev)
+{
+       u8 val;
+
+       /*
+        * The SB600 and SB700 both share the same device
+        * ID, but the PM register 0x55 does something different
+        * for the SB700, so make sure we are dealing with the
+        * SB600 before touching the bit:
+        */
+
+       pci_read_config_byte(dev, 0x08, &val);
+
+       if (val < 0x2F) {
+               outb(0x55, 0xCD6);
+               val = inb(0xCD7);
+
+               /* Set bit 7 in PM register 0x55 */
+               outb(0x55, 0xCD6);
+               outb(val | 0x80, 0xCD7);
+       }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar);
index 004ba86326ae022eb1b9d60a926a9adc6f207582..c9f7cda48ed78ecbe1b421c540bbe2b777681400 100644 (file)
@@ -198,17 +198,10 @@ unsigned long long xen_sched_clock(void)
 /* Get the TSC speed from Xen */
 unsigned long xen_tsc_khz(void)
 {
-       u64 xen_khz = 1000000ULL << 32;
-       const struct pvclock_vcpu_time_info *info =
+       struct pvclock_vcpu_time_info *info =
                &HYPERVISOR_shared_info->vcpu_info[0].time;
 
-       do_div(xen_khz, info->tsc_to_system_mul);
-       if (info->tsc_shift < 0)
-               xen_khz <<= -info->tsc_shift;
-       else
-               xen_khz >>= info->tsc_shift;
-
-       return xen_khz;
+       return pvclock_tsc_khz(info);
 }
 
 cycle_t xen_clocksource_read(void)
index a00359e8f7a8f06c14bfbff198e34d4bc5d5d5ea..9606d2bd1dd974a4766fed7748836e6cab5e46b8 100644 (file)
@@ -53,11 +53,6 @@ extern struct fd_ops no_fd_ops;
 struct fd_ops *fd_ops;
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-extern struct ide_ops no_ide_ops;
-struct ide_ops *ide_ops;
-#endif
-
 extern struct rtc_ops no_rtc_ops;
 struct rtc_ops *rtc_ops;
 
index 56cb343c76d8d4c507e80a7a08743b695d863756..034112bfe1f32a3876449533530edc0ed875e677 100644 (file)
@@ -1024,8 +1024,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
        bcd->release = release;
        kref_init(&bcd->ref);
        dev = MKDEV(bsg_major, bcd->minor);
-       class_dev = device_create_drvdata(bsg_class, parent, dev, NULL,
-                                         "%s", devname);
+       class_dev = device_create(bsg_class, parent, dev, NULL, "%s", devname);
        if (IS_ERR(class_dev)) {
                ret = PTR_ERR(class_dev);
                goto put_dev;
index 12cf5d491f0de2d0dc086cfb00935d23757b44ff..da49b006bcc58cb4819787cdb3156c82138180af 100644 (file)
@@ -259,7 +259,7 @@ config ACPI_ASUS
 
 config ACPI_TOSHIBA
        tristate "Toshiba Laptop Extras"
-       depends on X86
+       depends on X86 && INPUT
        select INPUT_POLLDEV
        select NET
        select RFKILL
index 3c578ef78c4830f791039b83e2a44ab80d7538d8..24649ada08dfd353c8a9895df6773156520e66ea 100644 (file)
@@ -260,115 +260,3 @@ static int __init init_acpi_device_notify(void)
 }
 
 arch_initcall(init_acpi_device_notify);
-
-
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
-
-#ifdef CONFIG_PM
-static u32 rtc_handler(void *context)
-{
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-       return ACPI_INTERRUPT_HANDLED;
-}
-
-static inline void rtc_wake_setup(void)
-{
-       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
-       /*
-        * After the RTC handler is installed, the Fixed_RTC event should
-        * be disabled. Only when the RTC alarm is set will it be enabled.
-        */
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-}
-
-static void rtc_wake_on(struct device *dev)
-{
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_enable_event(ACPI_EVENT_RTC, 0);
-}
-
-static void rtc_wake_off(struct device *dev)
-{
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-}
-#else
-#define rtc_wake_setup()       do{}while(0)
-#define rtc_wake_on            NULL
-#define rtc_wake_off           NULL
-#endif
-
-/* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
- * its device node and pass extra config data.  This helps its driver use
- * capabilities that the now-obsolete mc146818 didn't have, and informs it
- * that this board's RTC is wakeup-capable (per ACPI spec).
- */
-#include <linux/mc146818rtc.h>
-
-static struct cmos_rtc_board_info rtc_info;
-
-
-/* PNP devices are registered in a subsys_initcall();
- * ACPI specifies the PNP IDs to use.
- */
-#include <linux/pnp.h>
-
-static int __init pnp_match(struct device *dev, void *data)
-{
-       static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
-       struct pnp_dev *pnp = to_pnp_dev(dev);
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ids); i++) {
-               if (compare_pnp_id(pnp->id, ids[i]) != 0)
-                       return 1;
-       }
-       return 0;
-}
-
-static struct device *__init get_rtc_dev(void)
-{
-       return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
-}
-
-static int __init acpi_rtc_init(void)
-{
-       struct device *dev = get_rtc_dev();
-
-       if (acpi_disabled)
-               return 0;
-
-       if (dev) {
-               rtc_wake_setup();
-               rtc_info.wake_on = rtc_wake_on;
-               rtc_info.wake_off = rtc_wake_off;
-
-               /* workaround bug in some ACPI tables */
-               if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
-                       DBG("bogus FADT month_alarm\n");
-                       acpi_gbl_FADT.month_alarm = 0;
-               }
-
-               rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
-               rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
-               rtc_info.rtc_century = acpi_gbl_FADT.century;
-
-               /* NOTE:  S4_RTC_WAKE is NOT currently useful to Linux */
-               if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
-                       printk(PREFIX "RTC can wake from S4\n");
-
-
-               dev->platform_data = &rtc_info;
-
-               /* RTC always wakes from S1/S2/S3, and often S4/STD */
-               device_init_wakeup(dev, 1);
-
-               put_device(dev);
-       } else
-               DBG("RTC unavailable?\n");
-       return 0;
-}
-module_init(acpi_rtc_init);
-
-#endif
index 408da30594c442564f311deea0dcb62d7f14bc8b..1f18ad9e4fe161a6bfa33b84fff06c5c72626228 100644 (file)
@@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
 
        ret = of_irq_to_resource(dn, 0, &irq_res);
        if (ret == NO_IRQ)
-               irq_res.start = irq_res.end = -1;
+               irq_res.start = irq_res.end = 0;
        else
                irq_res.flags = 0;
 
index 41b4361bbf6ed86788634223ce855734f79ada89..02b596b9cf6a55fd058381a4d7d09ae928c4ceba 100644 (file)
@@ -148,6 +148,64 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+
+struct pcmcia_config_check {
+       unsigned long ctl_base;
+       int skip_vcc;
+       int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+                                  cistpl_cftable_entry_t *cfg,
+                                  cistpl_cftable_entry_t *dflt,
+                                  unsigned int vcc,
+                                  void *priv_data)
+{
+       struct pcmcia_config_check *stk = priv_data;
+
+       /* Check for matching Vcc, unless we're desperate */
+       if (!stk->skip_vcc) {
+               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               pdev->io.BasePort1 = io->win[0].base;
+               pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               if (io->nwin == 2) {
+                       pdev->io.NumPorts1 = 8;
+                       pdev->io.BasePort2 = io->win[1].base;
+                       pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort2;
+               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+                       pdev->io.NumPorts1 = io->win[0].len;
+                       pdev->io.NumPorts2 = 0;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+               } else
+                       return -ENODEV;
+               /* If we've got this far, we're done */
+               return 0;
+       }
+       return -ENODEV;
+}
+
 /**
  *     pcmcia_init_one         -       attach a PCMCIA interface
  *     @pdev: pcmcia device
@@ -161,19 +219,11 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        struct ata_host *host;
        struct ata_port *ap;
        struct ata_pcmcia_info *info;
-       tuple_t tuple;
-       struct {
-               unsigned short buf[128];
-               cisparse_t parse;
-               config_info_t conf;
-               cistpl_cftable_entry_t dflt;
-       } *stk = NULL;
-       cistpl_cftable_entry_t *cfg;
-       int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
+       struct pcmcia_config_check *stk = NULL;
+       int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
        unsigned long io_base, ctl_base;
        void __iomem *io_addr, *ctl_addr;
        int n_ports = 1;
-
        struct ata_port_operations *ops = &pcmcia_port_ops;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -193,96 +243,27 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
        pdev->conf.Attributes = CONF_ENABLE_IRQ;
        pdev->conf.IntType = INT_MEMORY_AND_IO;
 
-       /* Allocate resoure probing structures */
-
-       stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-       if (!stk)
-               goto out1;
-
-       cfg = &stk->parse.cftable_entry;
-
-       /* Tuples we are walking */
-       tuple.TupleData = (cisdata_t *)&stk->buf;
-       tuple.TupleOffset = 0;
-       tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-
        /* See if we have a manufacturer identifier. Use it to set is_kme for
           vendor quirks */
        is_kme = ((pdev->manf_id == MANFID_KME) &&
                  ((pdev->card_id == PRODID_KME_KXLC005_A) ||
                   (pdev->card_id == PRODID_KME_KXLC005_B)));
 
-       /* Not sure if this is right... look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf));
-/*     link->conf.Vcc = stk->conf.Vcc; */
-
-       pass = io_base = ctl_base = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       tuple.Attributes = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
-
-       /* Now munch the resources looking for a suitable set */
-       while (1) {
-               if (pcmcia_get_tuple_data(pdev, &tuple) != 0)
-                       goto next_entry;
-               if (pcmcia_parse_tuple(pdev, &tuple, &stk->parse) != 0)
-                       goto next_entry;
-               /* Check for matching Vcc, unless we're desperate */
-               if (!pass) {
-                       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                               if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                                       goto next_entry;
-                       } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                               if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
-                                       goto next_entry;
-                       }
-               }
+       /* Allocate resoure probing structures */
 
-               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       pdev->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-               if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
-                       pdev->conf.ConfigIndex = cfg->index;
-                       pdev->io.BasePort1 = io->win[0].base;
-                       pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       if (io->nwin == 2) {
-                               pdev->io.NumPorts1 = 8;
-                               pdev->io.BasePort2 = io->win[1].base;
-                               pdev->io.NumPorts2 = (is_kme) ? 2 : 1;
-                               if (pcmcia_request_io(pdev, &pdev->io) != 0)
-                                       goto next_entry;
-                               io_base = pdev->io.BasePort1;
-                               ctl_base = pdev->io.BasePort2;
-                       } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-                               pdev->io.NumPorts1 = io->win[0].len;
-                               pdev->io.NumPorts2 = 0;
-                               if (pcmcia_request_io(pdev, &pdev->io) != 0)
-                                       goto next_entry;
-                               io_base = pdev->io.BasePort1;
-                               ctl_base = pdev->io.BasePort1 + 0x0e;
-                       } else
-                               goto next_entry;
-                       /* If we've got this far, we're done */
-                       break;
-               }
-next_entry:
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-                       memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
-               if (pass) {
-                       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple));
-               } else if (pcmcia_get_next_tuple(pdev, &tuple) != 0) {
-                       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
-                       memset(&stk->dflt, 0, sizeof(stk->dflt));
-                       pass++;
-               }
-       }
+       stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+       if (!stk)
+               goto out1;
+       stk->is_kme = is_kme;
+       stk->skip_vcc = io_base = ctl_base = 0;
 
+       if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
+               stk->skip_vcc = 1;
+               if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+                       goto failed; /* No suitable config found */
+       }
+       io_base = pdev->io.BasePort1;
+       ctl_base = stk->ctl_base;
        CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
        CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
 
@@ -384,6 +365,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
        PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
+       PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
        PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
@@ -404,9 +386,9 @@ static struct pcmcia_device_id pcmcia_devices[] = {
        PCMCIA_DEVICE_PROD_ID12("EXP   ", "CD-ROM", 0x0a5c52fd, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("EXP   ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
        PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
-       PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
        PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
        PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
+       PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
        PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
        PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
        PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
index 6318f6b573608f345129234abf85c2629f6df4a1..d8e8c49c0cbd195ec1b16d39f5b9d01a556f0fea 100644 (file)
@@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL
          such firmware, and do not wish to use an initrd.
 
          This single option controls the inclusion of firmware for
-         every driver which usees request_firmare() and ships its
+         every driver which uses request_firmare() and ships its
          firmware in the kernel source tree, to avoid a proliferation
          of 'Include firmware for xxx device' options.
 
index ef522ae5548092f83ddabcbf36d7a54ad56f7282..5aee1c0169eafed102c699281b5bb4875fefd20c 100644 (file)
@@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data)
 {
        const char *name = data;
 
-       if (strcmp(name, dev->bus_id) == 0)
-               return 1;
-       return 0;
+       return sysfs_streq(name, dev->bus_id);
 }
 
 /**
@@ -982,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
 }
 EXPORT_SYMBOL_GPL(bus_get_device_klist);
 
+/*
+ * Yes, this forcably breaks the klist abstraction temporarily.  It
+ * just wants to sort the klist, not change reference counts and
+ * take/drop locks rapidly in the process.  It does all this while
+ * holding the lock for the list, so objects can't otherwise be
+ * added/removed while we're swizzling.
+ */
+static void device_insertion_sort_klist(struct device *a, struct list_head *list,
+                                       int (*compare)(const struct device *a,
+                                                       const struct device *b))
+{
+       struct list_head *pos;
+       struct klist_node *n;
+       struct device *b;
+
+       list_for_each(pos, list) {
+               n = container_of(pos, struct klist_node, n_node);
+               b = container_of(n, struct device, knode_bus);
+               if (compare(a, b) <= 0) {
+                       list_move_tail(&a->knode_bus.n_node,
+                                      &b->knode_bus.n_node);
+                       return;
+               }
+       }
+       list_move_tail(&a->knode_bus.n_node, list);
+}
+
+void bus_sort_breadthfirst(struct bus_type *bus,
+                          int (*compare)(const struct device *a,
+                                         const struct device *b))
+{
+       LIST_HEAD(sorted_devices);
+       struct list_head *pos, *tmp;
+       struct klist_node *n;
+       struct device *dev;
+       struct klist *device_klist;
+
+       device_klist = bus_get_device_klist(bus);
+
+       spin_lock(&device_klist->k_lock);
+       list_for_each_safe(pos, tmp, &device_klist->k_list) {
+               n = container_of(pos, struct klist_node, n_node);
+               dev = container_of(n, struct device, knode_bus);
+               device_insertion_sort_klist(dev, &sorted_devices, compare);
+       }
+       list_splice(&sorted_devices, &device_klist->k_list);
+       spin_unlock(&device_klist->k_lock);
+}
+EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
+
 int __init buses_init(void)
 {
        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
index b98cb1416a2d7a8a74dd5f64e4d1f1abcc35fbf2..8c2cc2648f5a5c0ec330df4991f75b6be07131ae 100644 (file)
@@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n)
  * device_initialize - init device structure.
  * @dev: device.
  *
- * This prepares the device for use by other layers,
- * including adding it to the device hierarchy.
+ * This prepares the device for use by other layers by initializing
+ * its fields.
  * It is the first half of device_register(), if called by
- * that, though it can also be called separately, so one
- * may use @dev's fields (e.g. the refcount).
+ * that function, though it can also be called separately, so one
+ * may use @dev's fields. In particular, get_device()/put_device()
+ * may be used for reference counting of @dev after calling this
+ * function.
+ *
+ * NOTE: Use put_device() to give up your reference instead of freeing
+ * @dev directly once you have called this function.
  */
 void device_initialize(struct device *dev)
 {
@@ -835,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev)
  * This is part 2 of device_register(), though may be called
  * separately _iff_ device_initialize() has been called separately.
  *
- * This adds it to the kobject hierarchy via kobject_add(), adds it
+ * This adds @dev to the kobject hierarchy via kobject_add(), adds it
  * to the global and sibling lists for the device, then
  * adds it to the other relevant subsystems of the driver model.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up your
+ * reference instead.
  */
 int device_add(struct device *dev)
 {
@@ -965,6 +974,10 @@ done:
  * I.e. you should only call the two helpers separately if
  * have a clearly defined need to use and refcount the device
  * before it is added to the hierarchy.
+ *
+ * NOTE: _Never_ directly free @dev after calling this function, even
+ * if it returned an error! Always use put_device() to give up the
+ * reference initialized in this function instead.
  */
 int device_register(struct device *dev)
 {
@@ -1243,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
        return dev;
 
 error:
-       kfree(dev);
+       put_device(dev);
        return ERR_PTR(retval);
 }
 EXPORT_SYMBOL_GPL(device_create_vargs);
@@ -1314,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
  * device_rename - renames a device
  * @dev: the pointer to the struct device to be renamed
  * @new_name: the new name of the device
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of device_rename
+ * on the same device to ensure that new_name is valid and
+ * won't conflict with other devices.
  */
 int device_rename(struct device *dev, char *new_name)
 {
index 3ac443b2ac08579b978b7f49de2a2b73034a88cf..20febc00a5258e253aeb9a309a9447660df40a38 100644 (file)
@@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data)
         * is an error.
         */
 
+       if (drv->bus->match && !drv->bus->match(dev, drv))
+               return 0;
+
        if (dev->parent)        /* Needed for USB */
                down(&dev->parent->sem);
        down(&dev->sem);
index c9c92b00fd555768730b731695bdbac1deeab1e9..b7e571031ecd144e12b7b8c361a9e6fb6ffd4961 100644 (file)
@@ -164,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev,
                }
                /* fallthrough */
        default:
-               printk(KERN_ERR "%s: unexpected value (%d)\n", __func__,
-                      loading);
+               dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
                /* fallthrough */
        case -1:
                fw_load_abort(fw_priv);
@@ -309,7 +308,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
        *dev_p = NULL;
 
        if (!fw_priv || !f_dev) {
-               printk(KERN_ERR "%s: kmalloc failed\n", __func__);
+               dev_err(device, "%s: kmalloc failed\n", __func__);
                retval = -ENOMEM;
                goto error_kfree;
        }
@@ -329,8 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
        f_dev->uevent_suppress = 1;
        retval = device_register(f_dev);
        if (retval) {
-               printk(KERN_ERR "%s: device_register failed\n",
-                      __func__);
+               dev_err(device, "%s: device_register failed\n", __func__);
                goto error_kfree;
        }
        *dev_p = f_dev;
@@ -363,15 +361,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
        fw_priv->fw = fw;
        retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
        if (retval) {
-               printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
-                      __func__);
+               dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
                goto error_unreg;
        }
 
        retval = device_create_file(f_dev, &dev_attr_loading);
        if (retval) {
-               printk(KERN_ERR "%s: device_create_file failed\n",
-                      __func__);
+               dev_err(device, "%s: device_create_file failed\n", __func__);
                goto error_unreg;
        }
 
@@ -401,8 +397,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
 
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
-               printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
-                      __func__);
+               dev_err(device, "%s: kmalloc(struct firmware) failed\n",
+                       __func__);
                retval = -ENOMEM;
                goto out;
        }
@@ -411,15 +407,15 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
             builtin++) {
                if (strcmp(name, builtin->name))
                        continue;
-               printk(KERN_INFO "firmware: using built-in firmware %s\n",
-                      name);
+               dev_info(device, "firmware: using built-in firmware %s\n",
+                        name);
                firmware->size = builtin->size;
                firmware->data = builtin->data;
                return 0;
        }
 
        if (uevent)
-               printk(KERN_INFO "firmware: requesting %s\n", name);
+               dev_info(device, "firmware: requesting %s\n", name);
 
        retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
        if (retval)
index 3f940393d6c7904cdd68a5db804a3c0365ac696a..dfcbfe504867e9db43ea944c55cda9eae9328556 100644 (file)
@@ -42,10 +42,8 @@ struct resource *platform_get_resource(struct platform_device *dev,
        for (i = 0; i < dev->num_resources; i++) {
                struct resource *r = &dev->resource[i];
 
-               if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
-                                IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
-                       if (num-- == 0)
-                               return r;
+               if (type == resource_type(r) && num-- == 0)
+                       return r;
        }
        return NULL;
 }
@@ -78,10 +76,8 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
        for (i = 0; i < dev->num_resources; i++) {
                struct resource *r = &dev->resource[i];
 
-               if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
-                                IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
-                       if (!strcmp(r->name, name))
-                               return r;
+               if (type == resource_type(r) && !strcmp(r->name, name))
+                       return r;
        }
        return NULL;
 }
@@ -259,9 +255,9 @@ int platform_device_add(struct platform_device *pdev)
 
                p = r->parent;
                if (!p) {
-                       if (r->flags & IORESOURCE_MEM)
+                       if (resource_type(r) == IORESOURCE_MEM)
                                p = &iomem_resource;
-                       else if (r->flags & IORESOURCE_IO)
+                       else if (resource_type(r) == IORESOURCE_IO)
                                p = &ioport_resource;
                }
 
@@ -282,9 +278,14 @@ int platform_device_add(struct platform_device *pdev)
                return ret;
 
  failed:
-       while (--i >= 0)
-               if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
-                       release_resource(&pdev->resource[i]);
+       while (--i >= 0) {
+               struct resource *r = &pdev->resource[i];
+               unsigned long type = resource_type(r);
+
+               if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+                       release_resource(r);
+       }
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(platform_device_add);
@@ -306,7 +307,9 @@ void platform_device_del(struct platform_device *pdev)
 
                for (i = 0; i < pdev->num_resources; i++) {
                        struct resource *r = &pdev->resource[i];
-                       if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
+                       unsigned long type = resource_type(r);
+
+                       if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
                                release_resource(r);
                }
        }
@@ -391,6 +394,53 @@ error:
 }
 EXPORT_SYMBOL_GPL(platform_device_register_simple);
 
+/**
+ * platform_device_register_data
+ * @parent: parent device for the device we're adding
+ * @name: base name of the device we're adding
+ * @id: instance id
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * This function creates a simple platform device that requires minimal
+ * resource and memory management. Canned release function freeing memory
+ * allocated for the device allows drivers using such devices to be
+ * unloaded without waiting for the last reference to the device to be
+ * dropped.
+ */
+struct platform_device *platform_device_register_data(
+               struct device *parent,
+               const char *name, int id,
+               const void *data, size_t size)
+{
+       struct platform_device *pdev;
+       int retval;
+
+       pdev = platform_device_alloc(name, id);
+       if (!pdev) {
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       pdev->dev.parent = parent;
+
+       if (size) {
+               retval = platform_device_add_data(pdev, data, size);
+               if (retval)
+                       goto error;
+       }
+
+       retval = platform_device_add(pdev);
+       if (retval)
+               goto error;
+
+       return pdev;
+
+error:
+       platform_device_put(pdev);
+       return ERR_PTR(retval);
+}
+
 static int platform_drv_probe(struct device *_dev)
 {
        struct platform_driver *drv = to_platform_driver(_dev->driver);
@@ -862,7 +912,7 @@ static int platform_pm_restore_noirq(struct device *dev)
 
 #endif /* !CONFIG_HIBERNATION */
 
-struct pm_ext_ops platform_pm_ops = {
+static struct pm_ext_ops platform_pm_ops = {
        .base = {
                .prepare = platform_pm_prepare,
                .complete = platform_pm_complete,
index 273a944d4040e861afa6a1ea6c601264eec6c4a7..692c20ba51444acaafe4ca2e1c63237afa3e42bf 100644 (file)
@@ -83,7 +83,7 @@ void device_pm_add(struct device *dev)
                 * transition is in progress in order to avoid leaving them
                 * unhandled down the road
                 */
-               WARN_ON(true);
+               dev_WARN(dev, "Parentless device registered during a PM transaction\n");
        }
 
        list_add_tail(&dev->power.entry, &dpm_list);
@@ -778,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend);
 
 void __suspend_report_result(const char *function, void *fn, int ret)
 {
-       if (ret) {
-               printk(KERN_ERR "%s(): ", function);
-               print_fn_descriptor_symbol("%s returns ", fn);
-               printk("%d\n", ret);
-       }
+       if (ret)
+               printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
 }
 EXPORT_SYMBOL_GPL(__suspend_report_result);
index 1f56d2c5b7fc67acb83899494c9376297a030f6c..200efc4d2c1e756cd9a7182709bbfb2328a57140 100644 (file)
@@ -284,9 +284,9 @@ aoechr_init(void)
                return PTR_ERR(aoe_class);
        }
        for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-               device_create_drvdata(aoe_class, NULL,
-                                     MKDEV(AOE_MAJOR, chardevs[i].minor),
-                                     NULL, chardevs[i].name);
+               device_create(aoe_class, NULL,
+                             MKDEV(AOE_MAJOR, chardevs[i].minor), NULL,
+                             chardevs[i].name);
 
        return 0;
 }
index 49f274197b16a7ece82403a4118dc26c2d38b514..432cf40182916366b71fad0b9c4f8e1131b2ef66 100644 (file)
@@ -1882,10 +1882,6 @@ static int __init atari_floppy_init (void)
                /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
                return -ENODEV;
 
-       if (MACH_IS_HADES)
-               /* Hades doesn't have Atari-compatible floppy */
-               return -ENODEV;
-
        if (register_blkdev(FLOPPY_MAJOR,"fd"))
                return -EBUSY;
 
index cf64ddf5d83924a1c6445a207ee7d21825483436..2cea27aba9a06c385d62efc49749753da0ae26ce 100644 (file)
@@ -4172,7 +4172,7 @@ static int __init floppy_init(void)
        int i, unit, drive;
        int err, dr;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
        if (check_legacy_ioport(FDC1))
                return -ENODEV;
 #endif
index d731ca42f8024f48a12214b064ed5ff3d13b8543..9dfa27163001e9d31de36f5196be7db0f2334a2d 100644 (file)
@@ -686,9 +686,8 @@ static int __init pg_init(void)
        for (unit = 0; unit < PG_UNITS; unit++) {
                struct pg *dev = &devices[unit];
                if (dev->present)
-                       device_create_drvdata(pg_class, NULL,
-                                             MKDEV(major, unit), NULL,
-                                             "pg%u", unit);
+                       device_create(pg_class, NULL, MKDEV(major, unit), NULL,
+                                     "pg%u", unit);
        }
        err = 0;
        goto out;
index 673b8b2fd337a1e22b442eba939aa4c90a407b86..5ae229656eaa0114e6d80508d1b3ad4417726fd8 100644 (file)
@@ -979,12 +979,10 @@ static int __init pt_init(void)
 
        for (unit = 0; unit < PT_UNITS; unit++)
                if (pt[unit].present) {
-                       device_create_drvdata(pt_class, NULL,
-                                             MKDEV(major, unit), NULL,
-                                             "pt%d", unit);
-                       device_create_drvdata(pt_class, NULL,
-                                             MKDEV(major, unit + 128), NULL,
-                                             "pt%dn", unit);
+                       device_create(pt_class, NULL, MKDEV(major, unit), NULL,
+                                     "pt%d", unit);
+                       device_create(pt_class, NULL, MKDEV(major, unit + 128),
+                                     NULL, "pt%dn", unit);
                }
        goto out;
 
index 0e077150568bbc78b5f44323019dd8a9bf643f87..195ca7c720f584efd0592e072096547423773357 100644 (file)
@@ -302,9 +302,8 @@ static struct kobj_type kobj_pkt_type_wqueue = {
 static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
 {
        if (class_pktcdvd) {
-               pd->dev = device_create_drvdata(class_pktcdvd, NULL,
-                                               pd->pkt_dev, NULL,
-                                               "%s", pd->name);
+               pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL,
+                                       "%s", pd->name);
                if (IS_ERR(pd->dev))
                        pd->dev = NULL;
        }
index f1c8feb5510b1fd77922972df0ff08542d789f8e..1730d29e6044039d12a2da60ebfdf23ea225d0ef 100644 (file)
@@ -249,7 +249,6 @@ static int send_request(struct request *req)
        struct HvLpEvent *hev;
        struct scatterlist sg[VIOMAXBLOCKDMA];
        int sgindex;
-       int statindex;
        struct viodasd_device *d;
        unsigned long flags;
 
@@ -258,11 +257,9 @@ static int send_request(struct request *req)
        if (rq_data_dir(req) == READ) {
                direction = DMA_FROM_DEVICE;
                viocmd = viomajorsubtype_blockio | vioblockread;
-               statindex = 0;
        } else {
                direction = DMA_TO_DEVICE;
                viocmd = viomajorsubtype_blockio | vioblockwrite;
-               statindex = 1;
        }
 
         d = req->rq_disk->private_data;
index bcf57927b7a8ff7e9e377f03e798c37f650689f2..e6ee21d99d92ce42cd0b8091544363f9f4758cb5 100644 (file)
@@ -901,23 +901,23 @@ static int bluecard_config(struct pcmcia_device *link)
        for (n = 0; n < 0x400; n += 0x40) {
                link->io.BasePort1 = n ^ 0x300;
                i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS)
+               if (i == 0)
                        break;
        }
 
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIO, i);
                goto failed;
        }
 
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
                goto failed;
        }
index 27058477cc8b7722bdc901ec7edb21e1d503be27..2cbe70b66470eb7189a7232fa54e8c79d5db70fe 100644 (file)
@@ -678,101 +678,78 @@ static void bt3c_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int bt3c_check_config(struct pcmcia_device *p_dev,
+                            cistpl_cftable_entry_t *cf,
+                            cistpl_cftable_entry_t *dflt,
+                            unsigned int vcc,
+                            void *priv_data)
 {
-       int i;
-
-       i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != CS_SUCCESS)
-               return i;
-
-       return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
+       unsigned long try = (unsigned long) priv_data;
+
+       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+           (cf->io.win[0].base != 0)) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.IOAddrLines = (try == 0) ? 16 :
+                       cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
 }
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
+                                     cistpl_cftable_entry_t *cf,
+                                     cistpl_cftable_entry_t *dflt,
+                                     unsigned int vcc,
+                                     void *priv_data)
 {
-       if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
+       static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+       int j;
+
+       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+               for (j = 0; j < 5; j++) {
+                       p_dev->io.BasePort1 = base[j];
+                       p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int bt3c_config(struct pcmcia_device *link)
 {
-       static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        bt3c_info_t *info = link->priv;
-       tuple_t tuple;
-       u_short buf[256];
-       cisparse_t parse;
-       cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-       int i, j, try;
-
-       /* First pass: look for a config entry that looks normal. */
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0;
-       tuple.TupleDataMax = 255;
-       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(link, &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.Vpp = 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, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
-                       }
-next_entry:
-                       i = next_tuple(link, &tuple, &parse);
-               }
-       }
+       int i;
+       unsigned long try;
+
+       /* First pass: look for a config entry that looks normal.
+          Two tries: without IO aliases, then with aliases */
+       for (try = 0; try < 2; try++)
+               if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try))
+                       goto found_port;
 
        /* 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. */
-       i = first_tuple(link, &tuple, &parse);
-       while (i != CS_NO_MORE_ITEMS) {
-               if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-                       link->conf.ConfigIndex = cf->index;
-                       for (j = 0; j < 5; j++) {
-                               link->io.BasePort1 = base[j];
-                               link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
-                       }
-               }
-               i = next_tuple(link, &tuple, &parse);
-       }
+       if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
+               goto found_port;
 
-found_port:
-       if (i != CS_SUCCESS) {
-               BT_ERR("No usable port range found");
-               cs_error(link, RequestIO, i);
-               goto failed;
-       }
+       BT_ERR("No usable port range found");
+       cs_error(link, RequestIO, -ENODEV);
+       goto failed;
 
+found_port:
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
                goto failed;
        }
index 68d1d258e6a4f5f4e8064a061d374ef1b632dca3..8e556b7ff9f63b3e1d95f99526304655df2c73ad 100644 (file)
@@ -607,102 +607,78 @@ static void btuart_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cf,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
 {
-       int i;
-
-       i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != CS_SUCCESS)
-               return i;
-
-       return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
+       int *try = priv_data;
+
+       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+           (cf->io.win[0].base != 0)) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.IOAddrLines = (*try == 0) ? 16 :
+                       cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
 }
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
+                                       cistpl_cftable_entry_t *cf,
+                                       cistpl_cftable_entry_t *dflt,
+                                       unsigned int vcc,
+                                       void *priv_data)
 {
-       if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
+       static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+       int j;
+
+       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+               for (j = 0; j < 5; j++) {
+                       p_dev->io.BasePort1 = base[j];
+                       p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int btuart_config(struct pcmcia_device *link)
 {
-       static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        btuart_info_t *info = link->priv;
-       tuple_t tuple;
-       u_short buf[256];
-       cisparse_t parse;
-       cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-       int i, j, try;
-
-       /* First pass: look for a config entry that looks normal. */
-       tuple.TupleData = (cisdata_t *) buf;
-       tuple.TupleOffset = 0;
-       tuple.TupleDataMax = 255;
-       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(link, &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.Vpp = 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, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
-                       }
-next_entry:
-                       i = next_tuple(link, &tuple, &parse);
-               }
-       }
+       int i;
+       int try;
+
+       /* First pass: look for a config entry that looks normal.
+          Two tries: without IO aliases, then with aliases */
+       for (try = 0; try < 2; try++)
+               if (!pcmcia_loop_config(link, btuart_check_config, &try))
+                       goto found_port;
 
        /* 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. */
-       i = first_tuple(link, &tuple, &parse);
-       while (i != CS_NO_MORE_ITEMS) {
-               if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
-                   && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-                       link->conf.ConfigIndex = cf->index;
-                       for (j = 0; j < 5; j++) {
-                               link->io.BasePort1 = base[j];
-                               link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
-                       }
-               }
-               i = next_tuple(link, &tuple, &parse);
-       }
+       if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
+               goto found_port;
 
-found_port:
-       if (i != CS_SUCCESS) {
-               BT_ERR("No usable port range found");
-               cs_error(link, RequestIO, i);
-               goto failed;
-       }
+       BT_ERR("No usable port range found");
+       cs_error(link, RequestIO, -ENODEV);
+       goto failed;
 
+found_port:
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
                goto failed;
        }
index dae45cdf02b2db78db84531bd5b0a41243ad891b..e6e6b037695a2692e178deef1ce9bafd8b7bd227 100644 (file)
@@ -590,75 +590,40 @@ static void dtl1_detach(struct pcmcia_device *link)
        kfree(info);
 }
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+static int dtl1_confcheck(struct pcmcia_device *p_dev,
+                         cistpl_cftable_entry_t *cf,
+                         cistpl_cftable_entry_t *dflt,
+                         unsigned int vcc,
+                         void *priv_data)
 {
-       int i;
-
-       i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != CS_SUCCESS)
-               return i;
-
-       return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       return get_tuple(handle, tuple, parse);
+       if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.NumPorts1 = cf->io.win[0].len;        /*yo */
+               p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
 }
 
 static int dtl1_config(struct pcmcia_device *link)
 {
        dtl1_info_t *info = link->priv;
-       tuple_t tuple;
-       u_short buf[256];
-       cisparse_t parse;
-       cistpl_cftable_entry_t *cf = &parse.cftable_entry;
        int i;
 
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0;
-       tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
        /* Look for a generic full-sized window */
        link->io.NumPorts1 = 8;
-       i = first_tuple(link, &tuple, &parse);
-       while (i != CS_NO_MORE_ITEMS) {
-               if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-                       link->conf.ConfigIndex = cf->index;
-                       link->io.BasePort1 = cf->io.win[0].base;
-                       link->io.NumPorts1 = cf->io.win[0].len; /*yo */
-                       link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-                       i = pcmcia_request_io(link, &link->io);
-                       if (i == CS_SUCCESS)
-                               break;
-               }
-               i = next_tuple(link, &tuple, &parse);
-       }
-
-       if (i != CS_SUCCESS) {
-               cs_error(link, RequestIO, i);
+       if (!pcmcia_loop_config(link, dtl1_confcheck, NULL))
                goto failed;
-       }
 
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
                goto failed;
        }
index 8dfcf77cb71783c892437f5cb20eff417c1ee94e..4426bb552bd90849b8df4e06c1a8e03f2a4af12f 100644 (file)
@@ -484,7 +484,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
                return -EUNATCH;
 
        default:
-               err = n_tty_ioctl(tty, file, cmd, arg);
+               err = n_tty_ioctl_helper(tty, file, cmd, arg);
                break;
        };
 
index caff85149b9d43897730d8fb9319ca1c36b9ca87..122254155ae16019e4b56288b2fcdecf67509c6e 100644 (file)
@@ -350,7 +350,7 @@ config STALDRV
 
 config STALLION
        tristate "Stallion EasyIO or EC8/32 support"
-       depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
+       depends on STALDRV && (ISA || EISA || PCI)
        help
          If you have an EasyIO or EasyConnection 8/32 multiport Stallion
          card, then this is for you; say Y.  Make sure to read
@@ -361,7 +361,7 @@ config STALLION
 
 config ISTALLION
        tristate "Stallion EC8/64, ONboard, Brumby support"
-       depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
+       depends on STALDRV && (ISA || EISA || PCI)
        help
          If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
          serial multiport card, say Y here. Make sure to read
@@ -1043,15 +1043,6 @@ config HPET
          open selects one of the timers supported by the HPET.  The timers are
          non-periodic and/or periodic.
 
-config HPET_RTC_IRQ
-       bool
-       default HPET_EMULATE_RTC
-       depends on RTC && HPET
-       help
-         If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It
-         is assumed the platform called hpet_alloc with the RTC IRQ values for
-         the HPET timers.
-
 config HPET_MMAP
        bool "Allow mmap of HPET"
        default y
index 6850f6da75762169374b44a654679d5681f05a1e..1a4247dccac4dfa4d79c27e69c2e93fbdb41fab7 100644 (file)
@@ -7,7 +7,7 @@
 #
 FONTMAPFILE = cp437.uni
 
-obj-y   += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o 
+obj-y   += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
 
 obj-$(CONFIG_LEGACY_PTYS)      += pty.o
 obj-$(CONFIG_UNIX98_PTYS)      += pty.o
index 603a986e96af6299bd6bc9b2e10bb54edc3aea2c..3f98254b911f01cfaae8711dbfda8cadaf451c77 100644 (file)
@@ -223,12 +223,14 @@ static int amd_irongate_configure(void)
 
        current_size = A_SIZE_LVL2(agp_bridge->current_size);
 
-       /* Get the memory mapped registers */
-       pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
-       temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-       amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
-       if (!amd_irongate_private.registers)
-               return -ENOMEM;
+       if (!amd_irongate_private.registers) {
+               /* Get the memory mapped registers */
+               pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
+               temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+               amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+               if (!amd_irongate_private.registers)
+                       return -ENOMEM;
+       }
 
        /* Write out the address of the gatt table */
        writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE);
@@ -492,6 +494,26 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
        agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
+
+static int agp_amdk7_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int agp_amdk7_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       return amd_irongate_driver.configure();
+}
+
+#endif /* CONFIG_PM */
+
 /* must be the same order as name table above */
 static struct pci_device_id agp_amdk7_pci_table[] = {
        {
@@ -528,6 +550,10 @@ static struct pci_driver agp_amdk7_pci_driver = {
        .id_table       = agp_amdk7_pci_table,
        .probe          = agp_amdk7_probe,
        .remove         = agp_amdk7_remove,
+#ifdef CONFIG_PM
+       .suspend        = agp_amdk7_suspend,
+       .resume         = agp_amdk7_resume,
+#endif
 };
 
 static int __init agp_amdk7_init(void)
index 043e36628d6d7faf03c34e5f7a2f9956f5429694..1108665913e207da892459750377400db809c961 100644 (file)
@@ -54,8 +54,7 @@
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
-                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \
-                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB)
+                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
 
 #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
@@ -63,7 +62,8 @@
 
 #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
-               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB)
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB)
 
 extern int agp_memory_reserved;
 
@@ -214,8 +214,8 @@ static int intel_i810_configure(void)
        if (agp_bridge->driver->needs_scratch_page) {
                for (i = 0; i < current_size->num_entries; i++) {
                        writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
-                       readl(intel_private.registers+I810_PTE_BASE+(i*4));     /* PCI posting. */
                }
+               readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */
        }
        global_cache_flush();
        return 0;
@@ -525,8 +525,10 @@ static void intel_i830_init_gtt_entries(void)
                size += 4;
        } else if (IS_G4X) {
                /* On 4 series hardware, GTT stolen is separate from graphics
-                * stolen, ignore it in stolen gtt entries counting */
-               size = 0;
+                * stolen, ignore it in stolen gtt entries counting.  However,
+                * 4KB of the stolen memory doesn't get mapped to the GTT.
+                */
+               size = 4;
        } else {
                /* On previous hardware, the GTT size was just what was
                 * required to map the aperture.
@@ -773,8 +775,8 @@ static int intel_i830_configure(void)
        if (agp_bridge->driver->needs_scratch_page) {
                for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
                        writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
-                       readl(intel_private.registers+I810_PTE_BASE+(i*4));     /* PCI Posting. */
                }
+               readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
        }
 
        global_cache_flush();
@@ -989,8 +991,8 @@ static int intel_i915_configure(void)
        if (agp_bridge->driver->needs_scratch_page) {
                for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
                        writel(agp_bridge->scratch_page, intel_private.gtt+i);
-                       readl(intel_private.gtt+i);     /* PCI Posting. */
                }
+               readl(intel_private.gtt+i-1);   /* PCI Posting. */
        }
 
        global_cache_flush();
index dc70d3771811a1d820bc020d73929ebfd491ad18..5bbed3d79db95f9d62ec32132817d645a961c7d2 100644 (file)
@@ -201,10 +201,15 @@ extern int agp_memory_reserved;
 static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        int i, j;
+       int mask_type;
 
-       if ((type != 0) || (mem->type != 0))
+       mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+       if (mask_type != 0 || type != mem->type)
                return -EINVAL;
 
+       if (mem->page_count == 0)
+               return 0;
+
        if ((pg_start + mem->page_count) >
                (nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE))
                return -EINVAL;
@@ -220,10 +225,13 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
        }
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
-                       mem->memory[i], mem->type),
+                       mem->memory[i], mask_type),
                        agp_bridge->gatt_table+nvidia_private.pg_offset+j);
-               readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j);       /* PCI Posting. */
        }
+
+       /* PCI Posting. */
+       readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j - 1);
+
        agp_bridge->driver->tlb_flush(mem);
        return 0;
 }
@@ -233,9 +241,15 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type
 {
        int i;
 
-       if ((type != 0) || (mem->type != 0))
+       int mask_type;
+
+       mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+       if (mask_type != 0 || type != mem->type)
                return -EINVAL;
 
+       if (mem->page_count == 0)
+               return 0;
+
        for (i = pg_start; i < (mem->page_count + pg_start); i++)
                writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i);
 
index 6e763e3f5a815565d57e06ab26641c4a6979856d..98821f97583c680b9ddc222d8c15e9909c0feb6b 100644 (file)
@@ -837,9 +837,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
        struct async_struct *info;
        unsigned long flags;
 
-       if (!tty)
-               return 0;
-
        info = tty->driver_data;
 
        if (serial_paranoia_check(info, tty->name, "rs_put_char"))
@@ -892,9 +889,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
        struct async_struct *info;
        unsigned long flags;
 
-       if (!tty)
-               return 0;
-
        info = tty->driver_data;
 
        if (serial_paranoia_check(info, tty->name, "rs_write"))
index 31d08b641f5be84667c5d53e49c862915e65d0c8..05674febb0c6bff218d2c76373402e7fcf0e1f58 100644 (file)
@@ -478,7 +478,7 @@ static int do_ac_read(int IndexCard, char __user *buf,
                struct st_ram_io *st_loc, struct mailbox *mailbox)
 {
        void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
-       unsigned char *to = (unsigned char *)&mailbox;
+       unsigned char *to = (unsigned char *)mailbox;
 #ifdef DEBUG
        int c;
 #endif
@@ -712,8 +712,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        
        IndexCard = adgl->num_card-1;
         
-       if(cmd != 0 && cmd != 6 &&
-          ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
+       if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
                static int warncount = 10;
                if (warncount) {
                        printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
@@ -832,8 +831,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                }
                break;
        default:
-               printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ;
-               ret = -EINVAL;
+               ret = -ENOTTY;
                break;
        }
        Dummy = readb(apbs[IndexCard].RamIO + VERS);
index b650b4e48e5042654c139ea0777befe7bbebab4a..456f54db73e2aa0fa395ede67cad3b2b80a40feb 100644 (file)
@@ -229,9 +229,8 @@ static int bsr_create_devs(struct device_node *bn)
                if (result)
                        goto out_err;
 
-               cur->bsr_device = device_create_drvdata(bsr_class, NULL,
-                                                       cur->bsr_dev,
-                                                       cur, cur->bsr_name);
+               cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
+                                               cur, cur->bsr_name);
                if (!cur->bsr_device) {
                        printk(KERN_ERR "device_create failed for %s\n",
                               cur->bsr_name);
index fe6d774fe2e4cbaf6ae0994cab07fccab158acd9..5e5b1dc1a0a72be733ce32b93966113e6cf224c7 100644 (file)
@@ -4993,12 +4993,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
                        device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
                card_name = "Cyclom-Y";
 
-               addr0 = pci_iomap(pdev, 0, CyPCI_Yctl);
+               addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+                               CyPCI_Yctl);
                if (addr0 == NULL) {
                        dev_err(&pdev->dev, "can't remap ctl region\n");
                        goto err_reg;
                }
-               addr2 = pci_iomap(pdev, 2, CyPCI_Ywin);
+               addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+                               CyPCI_Ywin);
                if (addr2 == NULL) {
                        dev_err(&pdev->dev, "can't remap base region\n");
                        goto err_unmap;
@@ -5013,7 +5015,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
        } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
                struct RUNTIME_9060 __iomem *ctl_addr;
 
-               ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl);
+               ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+                               CyPCI_Zctl);
                if (addr0 == NULL) {
                        dev_err(&pdev->dev, "can't remap ctl region\n");
                        goto err_reg;
@@ -5026,8 +5029,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
 
                mailbox = (u32)readl(&ctl_addr->mail_box_0);
 
-               addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ?
-                               CyPCI_Ze_win : CyPCI_Zwin);
+               addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+                               mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
                if (addr2 == NULL) {
                        dev_err(&pdev->dev, "can't remap base region\n");
                        goto err_unmap;
@@ -5159,9 +5162,9 @@ err_null:
        cy_card[card_no].base_addr = NULL;
        free_irq(irq, &cy_card[card_no]);
 err_unmap:
-       pci_iounmap(pdev, addr0);
+       iounmap(addr0);
        if (addr2)
-               pci_iounmap(pdev, addr2);
+               iounmap(addr2);
 err_reg:
        pci_release_regions(pdev);
 err_dis:
@@ -5186,9 +5189,9 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
                cy_writew(cinfo->ctl_addr + 0x68,
                                readw(cinfo->ctl_addr + 0x68) & ~0x0900);
 
-       pci_iounmap(pdev, cinfo->base_addr);
+       iounmap(cinfo->base_addr);
        if (cinfo->ctl_addr)
-               pci_iounmap(pdev, cinfo->ctl_addr);
+               iounmap(cinfo->ctl_addr);
        if (cinfo->irq
 #ifndef CONFIG_CYZ_INTR
                && !IS_CYC_Z(*cinfo)
index fb584938c9c3b2eb81bb954a8a8af41fa40fbf00..5329d482b582bd06fff9d4acf66b044683de05e5 100644 (file)
@@ -443,7 +443,6 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
 {
        unsigned char save_control;
        unsigned long flags;
-       unsigned long uip_watchdog = jiffies;
 
        /*
         * read RTC once any update in progress is done. The update
@@ -456,8 +455,7 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
         */
 
        if (ds1286_is_updating() != 0)
-               while (time_before(jiffies, uip_watchdog + 2*HZ/100))
-                       barrier();
+               msleep(20);
 
        /*
         * Only the values that we read from the RTC are set. We leave
index ca7c72a486b2f1391d57b07621c19e28cb37d65d..85832ab924e662ffa3f1d4cf588c1b5fb7becab2 100644 (file)
@@ -508,8 +508,8 @@ static int __init dsp56k_init_driver(void)
                err = PTR_ERR(dsp56k_class);
                goto out_chrdev;
        }
-       device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
-                             NULL, "dsp56k");
+       device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
+                     "dsp56k");
 
        printk(banner);
        goto out;
index 456e4ede049f2a0dad2bd0452199461272f1c353..4998b2761e8f6e891b1595a686f1e29f948e9fcc 100644 (file)
@@ -1376,6 +1376,7 @@ static void post_fep_init(unsigned int crd)
                unsigned long flags;
                u16 tseg, rseg;
 
+               tty_port_init(&ch->port);
                ch->brdchan = bc;
                ch->mailbox = gd;
                INIT_WORK(&ch->tqueue, do_softint);
@@ -1510,10 +1511,6 @@ static void post_fep_init(unsigned int crd)
                ch->fepstopca = 0;
 
                ch->close_delay = 50;
-               ch->port.count = 0;
-               ch->port.blocked_open = 0;
-               init_waitqueue_head(&ch->port.open_wait);
-               init_waitqueue_head(&ch->port.close_wait);
 
                spin_unlock_irqrestore(&epca_lock, flags);
        }
index 19d3afb0e50c5854d466bcee013217c0d52c64b3..c6090f84a2e46cf5f7c571bfd511c2c5b609cd57 100644 (file)
@@ -54,8 +54,6 @@ int gs_put_char(struct tty_struct * tty, unsigned char ch)
 
        func_enter (); 
 
-       if (!tty) return 0;
-
        port = tty->driver_data;
 
        if (!port) return 0;
@@ -97,8 +95,6 @@ int gs_write(struct tty_struct * tty,
 
        func_enter ();
 
-       if (!tty) return 0;
-
        port = tty->driver_data;
 
        if (!port) return 0;
@@ -185,7 +181,6 @@ static int gs_real_chars_in_buffer(struct tty_struct *tty)
        struct gs_port *port;
        func_enter ();
 
-       if (!tty) return 0;
        port = tty->driver_data;
 
        if (!port->rd) return 0;
@@ -274,8 +269,6 @@ void gs_flush_buffer(struct tty_struct *tty)
 
        func_enter ();
 
-       if (!tty) return;
-
        port = tty->driver_data;
 
        if (!port) return;
@@ -296,8 +289,6 @@ void gs_flush_chars(struct tty_struct * tty)
 
        func_enter ();
 
-       if (!tty) return;
-
        port = tty->driver_data;
 
        if (!port) return;
@@ -321,8 +312,6 @@ void gs_stop(struct tty_struct * tty)
 
        func_enter ();
 
-       if (!tty) return;
-
        port = tty->driver_data;
 
        if (!port) return;
@@ -341,8 +330,6 @@ void gs_start(struct tty_struct * tty)
 {
        struct gs_port *port;
 
-       if (!tty) return;
-
        port = tty->driver_data;
 
        if (!port) return;
@@ -393,8 +380,6 @@ void gs_hangup(struct tty_struct *tty)
 
        func_enter ();
 
-       if (!tty) return;
-
        port = tty->driver_data;
        tty = port->port.tty;
        if (!tty) 
@@ -426,8 +411,6 @@ int gs_block_til_ready(void *port_, struct file * filp)
 
        tty = port->port.tty;
 
-       if (!tty) return 0;
-
        gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
        /*
         * If the device is in the middle of being closed, then block
@@ -523,8 +506,6 @@ void gs_close(struct tty_struct * tty, struct file * filp)
        
        func_enter ();
 
-       if (!tty) return;
-
        port = (struct gs_port *) tty->driver_data;
 
        if (!port) return;
@@ -621,8 +602,6 @@ void gs_set_termios (struct tty_struct * tty,
 
        func_enter();
 
-       if (!tty) return;
-
        port = tty->driver_data;
 
        if (!port) return;
index b3f5dbc6d8807c7a51cf352118bf5ea08e35d635..f3cfb4c761259d5b8f6d331c24ea1108fde307fc 100644 (file)
 
 #define HPET_RANGE_SIZE                1024    /* from HPET spec */
 
+
+/* WARNING -- don't get confused.  These macros are never used
+ * to write the (single) counter, and rarely to read it.
+ * They're badly named; to fix, someday.
+ */
 #if BITS_PER_LONG == 64
 #define        write_counter(V, MC)    writeq(V, MC)
 #define        read_counter(MC)        readq(MC)
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
         .rating         = 250,
         .read           = read_hpet,
         .mask           = CLOCKSOURCE_MASK(64),
-        .mult           = 0, /*to be caluclated*/
+       .mult           = 0, /* to be calculated */
         .shift          = 10,
         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
 
 /* A lock for concurrent access by app and isr hpet activity. */
 static DEFINE_SPINLOCK(hpet_lock);
-/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
-static DEFINE_SPINLOCK(hpet_task_lock);
 
 #define        HPET_DEV_NAME   (7)
 
@@ -99,7 +102,6 @@ struct hpet_dev {
        unsigned long hd_irqdata;
        wait_queue_head_t hd_waitqueue;
        struct fasync_struct *hd_async_queue;
-       struct hpet_task *hd_task;
        unsigned int hd_flags;
        unsigned int hd_irq;
        unsigned int hd_hdwirq;
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
                writel(isr, &devp->hd_hpet->hpet_isr);
        spin_unlock(&hpet_lock);
 
-       spin_lock(&hpet_task_lock);
-       if (devp->hd_task)
-               devp->hd_task->ht_func(devp->hd_task->ht_data);
-       spin_unlock(&hpet_task_lock);
-
        wake_up_interruptible(&devp->hd_waitqueue);
 
        kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
@@ -185,6 +182,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static void hpet_timer_set_irq(struct hpet_dev *devp)
+{
+       unsigned long v;
+       int irq, gsi;
+       struct hpet_timer __iomem *timer;
+
+       spin_lock_irq(&hpet_lock);
+       if (devp->hd_hdwirq) {
+               spin_unlock_irq(&hpet_lock);
+               return;
+       }
+
+       timer = devp->hd_timer;
+
+       /* we prefer level triggered mode */
+       v = readl(&timer->hpet_config);
+       if (!(v & Tn_INT_TYPE_CNF_MASK)) {
+               v |= Tn_INT_TYPE_CNF_MASK;
+               writel(v, &timer->hpet_config);
+       }
+       spin_unlock_irq(&hpet_lock);
+
+       v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
+                                Tn_INT_ROUTE_CAP_SHIFT;
+
+       /*
+        * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
+        * legacy device. In IO APIC mode, we skip all the legacy IRQS.
+        */
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+               v &= ~0xf3df;
+       else
+               v &= ~0xffff;
+
+       for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
+               irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
+
+               if (irq >= NR_IRQS) {
+                       irq = HPET_MAX_IRQ;
+                       break;
+               }
+
+               gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
+                                       ACPI_ACTIVE_LOW);
+               if (gsi > 0)
+                       break;
+
+               /* FIXME: Setup interrupt source table */
+       }
+
+       if (irq < HPET_MAX_IRQ) {
+               spin_lock_irq(&hpet_lock);
+               v = readl(&timer->hpet_config);
+               v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
+               writel(v, &timer->hpet_config);
+               devp->hd_hdwirq = gsi;
+               spin_unlock_irq(&hpet_lock);
+       }
+       return;
+}
+
 static int hpet_open(struct inode *inode, struct file *file)
 {
        struct hpet_dev *devp;
@@ -199,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
 
        for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
                for (i = 0; i < hpetp->hp_ntimer; i++)
-                       if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
-                           || hpetp->hp_dev[i].hd_task)
+                       if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
                                continue;
                        else {
                                devp = &hpetp->hp_dev[i];
@@ -219,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file)
        spin_unlock_irq(&hpet_lock);
        unlock_kernel();
 
+       hpet_timer_set_irq(devp);
+
        return 0;
 }
 
@@ -441,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
        devp->hd_irq = irq;
        t = devp->hd_ireqfreq;
        v = readq(&timer->hpet_config);
-       g = v | Tn_INT_ENB_CNF_MASK;
+
+       /* 64-bit comparators are not yet supported through the ioctls,
+        * so force this into 32-bit mode if it supports both modes
+        */
+       g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
 
        if (devp->hd_flags & HPET_PERIODIC) {
                write_counter(t, &timer->hpet_compare);
@@ -451,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
                v |= Tn_VAL_SET_CNF_MASK;
                writeq(v, &timer->hpet_config);
                local_irq_save(flags);
+
+               /* NOTE:  what we modify here is a hidden accumulator
+                * register supported by periodic-capable comparators.
+                * We never want to modify the (single) counter; that
+                * would affect all the comparators.
+                */
                m = read_counter(&hpet->hpet_mc);
                write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
        } else {
@@ -604,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
        return 0;
 }
 
-static inline int hpet_tpcheck(struct hpet_task *tp)
-{
-       struct hpet_dev *devp;
-       struct hpets *hpetp;
-
-       devp = tp->ht_opaque;
-
-       if (!devp)
-               return -ENXIO;
-
-       for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-               if (devp >= hpetp->hp_dev
-                   && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
-                   && devp->hd_hpet == hpetp->hp_hpet)
-                       return 0;
-
-       return -ENXIO;
-}
-
-#if 0
-int hpet_unregister(struct hpet_task *tp)
-{
-       struct hpet_dev *devp;
-       struct hpet_timer __iomem *timer;
-       int err;
-
-       if ((err = hpet_tpcheck(tp)))
-               return err;
-
-       spin_lock_irq(&hpet_task_lock);
-       spin_lock(&hpet_lock);
-
-       devp = tp->ht_opaque;
-       if (devp->hd_task != tp) {
-               spin_unlock(&hpet_lock);
-               spin_unlock_irq(&hpet_task_lock);
-               return -ENXIO;
-       }
-
-       timer = devp->hd_timer;
-       writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
-              &timer->hpet_config);
-       devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
-       devp->hd_task = NULL;
-       spin_unlock(&hpet_lock);
-       spin_unlock_irq(&hpet_task_lock);
-
-       return 0;
-}
-#endif  /*  0  */
-
 static ctl_table hpet_table[] = {
        {
         .ctl_name = CTL_UNNUMBERED,
@@ -746,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp)
        static struct hpets *last = NULL;
        unsigned long period;
        unsigned long long temp;
+       u32 remainder;
 
        /*
         * hpet_alloc can be called by platform dependent code.
@@ -809,9 +828,13 @@ int hpet_alloc(struct hpet_data *hdp)
                printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
        printk("\n");
 
-       printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
-              hpetp->hp_which, hpetp->hp_ntimer,
-              cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
+       temp = hpetp->hp_tick_freq;
+       remainder = do_div(temp, 1000000);
+       printk(KERN_INFO
+               "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
+               hpetp->hp_which, hpetp->hp_ntimer,
+               cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
+               (unsigned) temp, remainder);
 
        mcfg = readq(&hpet->hpet_config);
        if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
@@ -874,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                hdp->hd_address = ioremap(addr.minimum, addr.address_length);
 
                if (hpet_is_known(hdp)) {
-                       printk(KERN_DEBUG "%s: 0x%lx is busy\n",
-                               __func__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
                        return AE_ALREADY_EXISTS;
                }
@@ -891,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                                                HPET_RANGE_SIZE);
 
                if (hpet_is_known(hdp)) {
-                       printk(KERN_DEBUG "%s: 0x%lx is busy\n",
-                               __func__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
                        return AE_ALREADY_EXISTS;
                }
index fd64137b1ab915fb9384fa674ad54be65c5f0074..bf70450a49ccbc403c62917c53f0db73f7328f5d 100644 (file)
@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
        spin_lock_irqsave(&hp->lock, flags);
 
        if (--hp->count == 0) {
-               if (hp->ops->notifier_del)
-                       hp->ops->notifier_del(hp, hp->data);
-
                /* We are done with the tty pointer now. */
                hp->tty = NULL;
                spin_unlock_irqrestore(&hp->lock, flags);
 
+               if (hp->ops->notifier_del)
+                       hp->ops->notifier_del(hp, hp->data);
+
                /*
                 * Chain calls chars_in_buffer() and returns immediately if
                 * there is no buffered data otherwise sleeps on a wait queue
@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct *tty)
        hp->n_outbuf = 0;
        hp->tty = NULL;
 
+       spin_unlock_irqrestore(&hp->lock, flags);
+
        if (hp->ops->notifier_del)
                        hp->ops->notifier_del(hp, hp->data);
 
-       spin_unlock_irqrestore(&hp->lock, flags);
-
        while(temp_open_count) {
                --temp_open_count;
                kref_put(&hp->kref, destroy_hvc_struct);
@@ -819,11 +819,11 @@ static int hvc_init(void)
        hvc_driver = drv;
        return 0;
 
-put_tty:
-       put_tty_driver(hvc_driver);
 stop_thread:
        kthread_stop(hvc_task);
        hvc_task = NULL;
+put_tty:
+       put_tty_driver(drv);
 out:
        return err;
 }
index 51738bdd834eccd732eb234b8cddd7cb1c83ed61..d4e7dca06e4fa2c6e7bf0d26781ac5627abb97cc 100644 (file)
@@ -118,18 +118,21 @@ static int __init omap_rng_probe(struct platform_device *pdev)
 
        mem = request_mem_region(res->start, res->end - res->start + 1,
                                 pdev->name);
-       if (mem == NULL)
-               return -EBUSY;
+       if (mem == NULL) {
+               ret = -EBUSY;
+               goto err_region;
+       }
 
        dev_set_drvdata(&pdev->dev, mem);
-       rng_base = (u32 __force __iomem *)io_p2v(res->start);
+       rng_base = ioremap(res->start, res->end - res->start + 1);
+       if (!rng_base) {
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
 
        ret = hwrng_register(&omap_rng_ops);
-       if (ret) {
-               release_resource(mem);
-               rng_base = NULL;
-               return ret;
-       }
+       if (ret)
+               goto err_register;
 
        dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
                omap_rng_read_reg(RNG_REV_REG));
@@ -138,6 +141,18 @@ static int __init omap_rng_probe(struct platform_device *pdev)
        rng_dev = pdev;
 
        return 0;
+
+err_register:
+       iounmap(rng_base);
+       rng_base = NULL;
+err_ioremap:
+       release_resource(mem);
+err_region:
+       if (cpu_is_omap24xx()) {
+               clk_disable(rng_ick);
+               clk_put(rng_ick);
+       }
+       return ret;
 }
 
 static int __exit omap_rng_remove(struct platform_device *pdev)
@@ -148,6 +163,8 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
 
        omap_rng_write_reg(RNG_MASK_REG, 0x0);
 
+       iounmap(rng_base);
+
        if (cpu_is_omap24xx()) {
                clk_disable(rng_ick);
                clk_put(rng_ick);
index 939618f62fe1ba09051c9c16f8056afc975cb76e..bc397d92b499cd6c848d246f8f251aa4aa4670a6 100644 (file)
@@ -4,5 +4,5 @@
 
 obj-$(CONFIG_COMPUTONE)         += ip2.o
 
-ip2-objs                       := ip2base.o ip2main.o
+ip2-objs                       := ip2main.o
 
index 3601017f58cfdd936b490fc69936ab2973a864f5..29db44de399ff37111660a6a506875d89df1b827 100644 (file)
@@ -68,38 +68,6 @@ static DEFINE_RWLOCK(Dl_spinlock);
 // iiInitialize
 //=======================================================
 
-//******************************************************************************
-// Function:   iiEllisInit()
-// Parameters: None
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine performs any required initialization of the iiEllis subsystem.
-//
-//******************************************************************************
-static void
-iiEllisInit(void)
-{
-}
-
-//******************************************************************************
-// Function:   iiEllisCleanup()
-// Parameters: None
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine performs any required cleanup of the iiEllis subsystem.
-//
-//******************************************************************************
-static void
-iiEllisCleanup(void)
-{
-}
-
 //******************************************************************************
 // Function:   iiSetAddress(pB, address, delay)
 // Parameters: pB      - pointer to the board structure
index c88a64e527aa510012e249f1037ae853186b0dbc..fb6df2456018a2238393f40b4cc88b6e78868102 100644 (file)
@@ -511,7 +511,6 @@ typedef void (*delayFunc_t)(unsigned int);
 //
 // Initialization of a board & structure is in four (five!) parts:
 //
-// 0) iiEllisInit()  - Initialize iiEllis subsystem.
 // 1) iiSetAddress() - Define the board address & delay function for a board.
 // 2) iiReset()      - Reset the board   (provided it exists)
 //       -- Note you may do this to several boards --
@@ -523,7 +522,6 @@ typedef void (*delayFunc_t)(unsigned int);
 // loadware.  To change loadware, you must begin again with step 2, resetting
 // the board again (step 1 not needed).
 
-static void iiEllisInit(void);
 static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
 static int iiReset(i2eBordStrPtr);
 static int iiResetDelay(i2eBordStrPtr);
diff --git a/drivers/char/ip2/ip2base.c b/drivers/char/ip2/ip2base.c
deleted file mode 100644 (file)
index 8155e24..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// ip2.c
-// This is a dummy module to make the firmware available when needed
-// and allows it to be unloaded when not. Rumor is the __initdata 
-// macro doesn't always works on all platforms so we use this kludge.
-// If not compiled as a module it just makes fip_firm avaliable then
-//  __initdata should work as advertized
-//
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-
-#ifndef __init
-#define __init
-#endif
-#ifndef __initfunc
-#define __initfunc(a) a
-#endif
-#ifndef __initdata
-#define __initdata
-#endif
-
-#include "ip2types.h"          
-
-int
-ip2_loadmain(int *, int *); // ref into ip2main.c
-
-/* Note: Add compiled in defaults to these arrays, not to the structure
-       in ip2.h any longer.  That structure WILL get overridden
-       by these values, or command line values, or insmod values!!!  =mhw=
-*/
-static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; 
-
-static int poll_only = 0;
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards");
-module_param(poll_only, bool, 0);
-MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
-
-
-static int __init ip2_init(void)
-{
-       if( poll_only ) {
-               /* Hard lock the interrupts to zero */
-               irq[0] = irq[1] = irq[2] = irq[3] = 0;
-       }
-
-       return ip2_loadmain(io, irq);
-}
-module_init(ip2_init);
-
-MODULE_LICENSE("GPL");
-
-#ifndef MODULE
-/******************************************************************************
- *     ip2_setup:
- *             str: kernel command line string
- *
- *     Can't autoprobe the boards so user must specify configuration on
- *     kernel command line.  Sane people build it modular but the others
- *     come here.
- *
- *     Alternating pairs of io,irq for up to 4 boards.
- *             ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
- *
- *             io=0 => No board
- *             io=1 => PCI
- *             io=2 => EISA
- *             else => ISA I/O address
- *
- *             irq=0 or invalid for ISA will revert to polling mode
- *
- *             Any value = -1, do not overwrite compiled in value.
- *
- ******************************************************************************/
-static int __init ip2_setup(char *str)
-{
-       int     ints[10];       /* 4 boards, 2 parameters + 2 */
-       int     i, j;
-
-       str = get_options (str, ARRAY_SIZE(ints), ints);
-
-       for( i = 0, j = 1; i < 4; i++ ) {
-               if( j > ints[0] ) {
-                       break;
-               }
-               if( ints[j] >= 0 ) {
-                       io[i] = ints[j];
-               }
-               j++;
-               if( j > ints[0] ) {
-                       break;
-               }
-               if( ints[j] >= 0 ) {
-                       irq[i] = ints[j];
-               }
-               j++;
-       }
-       return 1;
-}
-__setup("ip2=", ip2_setup);
-#endif /* !MODULE */
index 689f9dcd3b866f1bd6ca9e3a0f707f7b2de9cb39..70e0ebc30bd08d5b9e034b2b22c341475c761252 100644 (file)
@@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
 /*************/
 
 /* String constants to identify ourselves */
-static char *pcName    = "Computone IntelliPort Plus multiport driver";
-static char *pcVersion = "1.2.14";
+static const char pcName[] = "Computone IntelliPort Plus multiport driver";
+static const char pcVersion[] = "1.2.14";
 
 /* String constants for port names */
-static char *pcDriver_name   = "ip2";
-static char *pcIpl              = "ip2ipl";
-
-// cheezy kludge or genius - you decide?
-int ip2_loadmain(int *, int *);
+static const char pcDriver_name[] = "ip2";
+static const char pcIpl[] = "ip2ipl";
 
 /***********************/
 /* Function Prototypes */
@@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = {
        .open           = ip2_ipl_open,
 }; 
 
-static unsigned long irq_counter = 0;
-static unsigned long bh_counter = 0;
+static unsigned long irq_counter;
+static unsigned long bh_counter;
 
 // Use immediate queue to service interrupts
 #define USE_IQI
@@ -252,7 +249,6 @@ static unsigned long bh_counter = 0;
  */
 #define  POLL_TIMEOUT   (jiffies + 1)
 static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-static char  TimerOn;
 
 #ifdef IP2DEBUG_TRACE
 /* Trace (debug) buffer data */
@@ -268,8 +264,8 @@ static int tracewrap;
 /**********/
 
 #if defined(MODULE) && defined(IP2DEBUG_OPEN)
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
-                   tty->name,(pCh->flags),ip2_tty_driver->refcount, \
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+                   tty->name,(pCh->flags), \
                    tty->count,/*GET_USE_COUNT(module)*/0,s)
 #else
 #define DBG_CNT(s)
@@ -287,8 +283,9 @@ static int tracewrap;
 
 MODULE_AUTHOR("Doug McNash");
 MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+MODULE_LICENSE("GPL");
 
-static int poll_only = 0;
+static int poll_only;
 
 static int Eisa_irq;
 static int Eisa_slot;
@@ -297,34 +294,46 @@ static int iindx;
 static char rirqs[IP2_MAX_BOARDS];
 static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
 
+/* Note: Add compiled in defaults to these arrays, not to the structure
+       in ip2.h any longer.  That structure WILL get overridden
+       by these values, or command line values, or insmod values!!!  =mhw=
+*/
+static int io[IP2_MAX_BOARDS];
+static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
+module_param(poll_only, bool, 0);
+MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
+
 /* for sysfs class support */
 static struct class *ip2_class;
 
-// Some functions to keep track of what irq's we have
+/* Some functions to keep track of what irqs we have */
 
-static int
-is_valid_irq(int irq)
+static int __init is_valid_irq(int irq)
 {
        int *i = Valid_Irqs;
        
-       while ((*i != 0) && (*i != irq)) {
+       while (*i != 0 && *i != irq)
                i++;
-       }
-       return (*i);
+
+       return *i;
 }
 
-static void
-mark_requested_irq( char irq )
+static void __init mark_requested_irq(char irq)
 {
        rirqs[iindx++] = irq;
 }
 
-#ifdef MODULE
-static int
-clear_requested_irq( char irq )
+static int __exit clear_requested_irq(char irq)
 {
        int i;
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
                if (rirqs[i] == irq) {
                        rirqs[i] = 0;
                        return 1;
@@ -332,17 +341,15 @@ clear_requested_irq( char irq )
        }
        return 0;
 }
-#endif
 
-static int
-have_requested_irq( char irq )
+static int have_requested_irq(char irq)
 {
-       // array init to zeros so 0 irq will not be requested as a side effect
+       /* array init to zeros so 0 irq will not be requested as a side
+        * effect */
        int i;
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i)
                if (rirqs[i] == irq)
                        return 1;
-       }
        return 0;
 }
 
@@ -361,53 +368,45 @@ have_requested_irq( char irq )
 /* handle subsequent installations of the driver. All memory allocated by the */
 /* driver should be returned since it may be unloaded from memory.            */
 /******************************************************************************/
-#ifdef MODULE
-void __exit
-ip2_cleanup_module(void)
+static void __exit ip2_cleanup_module(void)
 {
        int err;
        int i;
 
-#ifdef IP2DEBUG_INIT
-       printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
-#endif
-       /* Stop poll timer if we had one. */
-       if ( TimerOn ) {
-               del_timer ( &PollTimer );
-               TimerOn = 0;
-       }
+       del_timer_sync(&PollTimer);
 
        /* Reset the boards we have. */
-       for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( i2BoardPtrTable[i] ) {
-                       iiReset( i2BoardPtrTable[i] );
-               }
-       }
+       for (i = 0; i < IP2_MAX_BOARDS; i++)
+               if (i2BoardPtrTable[i])
+                       iiReset(i2BoardPtrTable[i]);
 
        /* The following is done at most once, if any boards were installed. */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( i2BoardPtrTable[i] ) {
-                       iiResetDelay( i2BoardPtrTable[i] );
+       for (i = 0; i < IP2_MAX_BOARDS; i++) {
+               if (i2BoardPtrTable[i]) {
+                       iiResetDelay(i2BoardPtrTable[i]);
                        /* free io addresses and Tibet */
-                       release_region( ip2config.addr[i], 8 );
+                       release_region(ip2config.addr[i], 8);
                        device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
-                       device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+                       device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
+                                               4 * i + 1));
                }
                /* Disable and remove interrupt handler. */
-               if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { 
-                       free_irq ( ip2config.irq[i], (void *)&pcName);
-                       clear_requested_irq( ip2config.irq[i]);
+               if (ip2config.irq[i] > 0 &&
+                               have_requested_irq(ip2config.irq[i])) {
+                       free_irq(ip2config.irq[i], (void *)&pcName);
+                       clear_requested_irq(ip2config.irq[i]);
                }
        }
        class_destroy(ip2_class);
-       if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
-               printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
-       }
+       err = tty_unregister_driver(ip2_tty_driver);
+       if (err)
+               printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
+                               err);
        put_tty_driver(ip2_tty_driver);
        unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
        remove_proc_entry("ip2mem", NULL);
 
-       // free memory
+       /* free memory */
        for (i = 0; i < IP2_MAX_BOARDS; i++) {
                void *pB;
 #ifdef CONFIG_PCI
@@ -417,24 +416,18 @@ ip2_cleanup_module(void)
                        ip2config.pci_dev[i] = NULL;
                }
 #endif
-               if ((pB = i2BoardPtrTable[i]) != 0 ) {
-                       kfree ( pB );
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       kfree(pB);
                        i2BoardPtrTable[i] = NULL;
                }
-               if ((DevTableMem[i]) != NULL ) {
-                       kfree ( DevTableMem[i]  );
+               if (DevTableMem[i] != NULL) {
+                       kfree(DevTableMem[i]);
                        DevTableMem[i] = NULL;
                }
        }
-
-       /* Cleanup the iiEllis subsystem. */
-       iiEllisCleanup();
-#ifdef IP2DEBUG_INIT
-       printk (KERN_DEBUG "IP2 Unloaded\n" );
-#endif
 }
 module_exit(ip2_cleanup_module);
-#endif /* MODULE */
 
 static const struct tty_operations ip2_ops = {
        .open            = ip2_open,
@@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void)
        return fw;
 }
 
-int
-ip2_loadmain(int *iop, int *irqp)
+#ifndef MODULE
+/******************************************************************************
+ *     ip2_setup:
+ *             str: kernel command line string
+ *
+ *     Can't autoprobe the boards so user must specify configuration on
+ *     kernel command line.  Sane people build it modular but the others
+ *     come here.
+ *
+ *     Alternating pairs of io,irq for up to 4 boards.
+ *             ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
+ *
+ *             io=0 => No board
+ *             io=1 => PCI
+ *             io=2 => EISA
+ *             else => ISA I/O address
+ *
+ *             irq=0 or invalid for ISA will revert to polling mode
+ *
+ *             Any value = -1, do not overwrite compiled in value.
+ *
+ ******************************************************************************/
+static int __init ip2_setup(char *str)
+{
+       int j, ints[10];        /* 4 boards, 2 parameters + 2 */
+       unsigned int i;
+
+       str = get_options(str, ARRAY_SIZE(ints), ints);
+
+       for (i = 0, j = 1; i < 4; i++) {
+               if (j > ints[0])
+                       break;
+               if (ints[j] >= 0)
+                       io[i] = ints[j];
+               j++;
+               if (j > ints[0])
+                       break;
+               if (ints[j] >= 0)
+                       irq[i] = ints[j];
+               j++;
+       }
+       return 1;
+}
+__setup("ip2=", ip2_setup);
+#endif /* !MODULE */
+
+static int __init ip2_loadmain(void)
 {
        int i, j, box;
        int err = 0;
-       static int loaded;
        i2eBordStrPtr pB = NULL;
        int rc = -1;
-       static struct pci_dev *pci_dev_i = NULL;
+       struct pci_dev *pdev = NULL;
        const struct firmware *fw = NULL;
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
+       if (poll_only) {
+               /* Hard lock the interrupts to zero */
+               irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
+       }
+
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
 
        /* process command line arguments to modprobe or
                insmod i.e. iop & irqp */
        /* irqp and iop should ALWAYS be specified now...  But we check
                them individually just to be sure, anyways... */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if (iop) {
-                       ip2config.addr[i] = iop[i];
-                       if (irqp) {
-                               if( irqp[i] >= 0 ) {
-                                       ip2config.irq[i] = irqp[i];
-                               } else {
-                                       ip2config.irq[i] = 0;
-                               }
-       // This is a little bit of a hack.  If poll_only=1 on command
-       // line back in ip2.c OR all IRQs on all specified boards are
-       // explicitly set to 0, then drop to poll only mode and override
-       // PCI or EISA interrupts.  This superceeds the old hack of
-       // triggering if all interrupts were zero (like da default).
-       // Still a hack but less prone to random acts of terrorism.
-       //
-       // What we really should do, now that the IRQ default is set
-       // to -1, is to use 0 as a hard coded, do not probe.
-       //
-       //      /\/\|=mhw=|\/\/
-                               poll_only |= irqp[i];
-                       }
-               }
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               ip2config.addr[i] = io[i];
+               if (irq[i] >= 0)
+                       ip2config.irq[i] = irq[i];
+               else
+                       ip2config.irq[i] = 0;
+       /* This is a little bit of a hack.  If poll_only=1 on command
+          line back in ip2.c OR all IRQs on all specified boards are
+          explicitly set to 0, then drop to poll only mode and override
+          PCI or EISA interrupts.  This superceeds the old hack of
+          triggering if all interrupts were zero (like da default).
+          Still a hack but less prone to random acts of terrorism.
+
+          What we really should do, now that the IRQ default is set
+          to -1, is to use 0 as a hard coded, do not probe.
+
+               /\/\|=mhw=|\/\/
+       */
+               poll_only |= irq[i];
        }
        poll_only = !poll_only;
 
        /* Announce our presence */
-       printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
-
-       // ip2 can be unloaded and reloaded for no good reason
-       // we can't let that happen here or bad things happen
-       // second load hoses board but not system - fixme later
-       if (loaded) {
-               printk( KERN_INFO "Still loaded\n" );
-               return 0;
-       }
-       loaded++;
+       printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
 
        ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
        if (!ip2_tty_driver)
                return -ENOMEM;
 
-       /* Initialise the iiEllis subsystem. */
-       iiEllisInit();
-
-       /* Initialize arrays. */
-       memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
-       memset( DevTable, 0, sizeof DevTable );
-
        /* Initialise all the boards we can find (up to the maximum). */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               switch ( ip2config.addr[i] ) { 
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               switch (ip2config.addr[i]) {
                case 0: /* skip this slot even if card is present */
                        break;
                default: /* ISA */
                   /* ISA address must be specified */
-                       if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
-                               printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
-                                                        i, ip2config.addr[i] );
+                       if (ip2config.addr[i] < 0x100 ||
+                                       ip2config.addr[i] > 0x3f8) {
+                               printk(KERN_ERR "IP2: Bad ISA board %d "
+                                               "address %x\n", i,
+                                               ip2config.addr[i]);
                                ip2config.addr[i] = 0;
-                       } else {
-                               ip2config.type[i] = ISA;
-
-                               /* Check for valid irq argument, set for polling if invalid */
-                               if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
-                                       printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
-                                       ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
-                               }
+                               break;
+                       }
+                       ip2config.type[i] = ISA;
+
+                       /* Check for valid irq argument, set for polling if
+                        * invalid */
+                       if (ip2config.irq[i] &&
+                                       !is_valid_irq(ip2config.irq[i])) {
+                               printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
+                                               ip2config.irq[i]);
+                               /* 0 is polling and is valid in that sense */
+                               ip2config.irq[i] = 0;
                        }
                        break;
                case PCI:
 #ifdef CONFIG_PCI
-                       {
-                               int status;
+               {
+                       u32 addr;
+                       int status;
 
-                               pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
-                                                         PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
-                               if (pci_dev_i != NULL) {
-                                       unsigned int addr;
-
-                                       if (pci_enable_device(pci_dev_i)) {
-                                               printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
-                                                       pci_name(pci_dev_i));
-                                               break;
-                                       }
-                                       ip2config.type[i] = PCI;
-                                       ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
-                                       status =
-                                       pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
-                                       if ( addr & 1 ) {
-                                               ip2config.addr[i]=(USHORT)(addr&0xfffe);
-                                       } else {
-                                               printk( KERN_ERR "IP2: PCI I/O address error\n");
-                                       }
+                       pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
+                                       PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
+                       if (pdev == NULL) {
+                               ip2config.addr[i] = 0;
+                               printk(KERN_ERR "IP2: PCI board %d not "
+                                               "found\n", i);
+                               break;
+                       }
 
-//             If the PCI BIOS assigned it, lets try and use it.  If we
-//             can't acquire it or it screws up, deal with it then.
-
-//                                     if (!is_valid_irq(pci_irq)) {
-//                                             printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
-//                                             pci_irq = 0;
-//                                     }
-                                       ip2config.irq[i] = pci_dev_i->irq;
-                               } else {        // ann error
-                                       ip2config.addr[i] = 0;
-                                       printk(KERN_ERR "IP2: PCI board %d not found\n", i);
-                               } 
+                       if (pci_enable_device(pdev)) {
+                               dev_err(&pdev->dev, "can't enable device\n");
+                               break;
                        }
+                       ip2config.type[i] = PCI;
+                       ip2config.pci_dev[i] = pci_dev_get(pdev);
+                       status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
+                                       &addr);
+                       if (addr & 1)
+                               ip2config.addr[i] = (USHORT)(addr & 0xfffe);
+                       else
+                               dev_err(&pdev->dev, "I/O address error\n");
+
+                       ip2config.irq[i] = pdev->irq;
+               }
 #else
-                       printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
-                       printk( KERN_ERR "IP2: configured in this kernel.\n");
-                       printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
+                       printk(KERN_ERR "IP2: PCI card specified but PCI "
+                                       "support not enabled.\n");
+                       printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
+                                       "defined!\n");
 #endif /* CONFIG_PCI */
                        break;
                case EISA:
-                       if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
+                       ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
+                       if (ip2config.addr[i] != 0) {
                                /* Eisa_irq set as side effect, boo */
                                ip2config.type[i] = EISA;
                        } 
@@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp)
                        break;
                }       /* switch */
        }       /* for */
-       if (pci_dev_i)
-               pci_dev_put(pci_dev_i);
+       pci_dev_put(pdev);
 
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( ip2config.addr[i] ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (ip2config.addr[i]) {
                        pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
                        if (pB) {
                                i2BoardPtrTable[i] = pB;
-                               iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
-                               iiReset( pB );
-                       } else {
-                               printk(KERN_ERR "IP2: board memory allocation error\n");
-                       }
+                               iiSetAddress(pB, ip2config.addr[i],
+                                               ii2DelayTimer);
+                               iiReset(pB);
+                       } else
+                               printk(KERN_ERR "IP2: board memory allocation "
+                                               "error\n");
                }
        }
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
-                       iiResetDelay( pB );
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       iiResetDelay(pB);
                        break;
                }
        }
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
                /* We don't want to request the firmware unless we have at
                   least one board */
-               if ( i2BoardPtrTable[i] != NULL ) {
+               if (i2BoardPtrTable[i] != NULL) {
                        if (!fw)
                                fw = ip2_request_firmware();
                        if (!fw)
@@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp)
        if (fw)
                release_firmware(fw);
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
 
        ip2_tty_driver->owner               = THIS_MODULE;
        ip2_tty_driver->name                 = "ttyF";
@@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp)
        ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
        ip2_tty_driver->init_termios         = tty_std_termios;
        ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-       ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+       ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
+               TTY_DRIVER_DYNAMIC_DEV;
        tty_set_operations(ip2_tty_driver, &ip2_ops);
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
 
-       /* Register the tty devices. */
-       if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) {
-               printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
+       err = tty_register_driver(ip2_tty_driver);
+       if (err) {
+               printk(KERN_ERR "IP2: failed to register tty driver\n");
                put_tty_driver(ip2_tty_driver);
-               return -EINVAL;
-       } else
-       /* Register the IPL driver. */
-       if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
-               printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
+               return err; /* leaking resources */
+       }
+
+       err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
+       if (err) {
+               printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
+                               err);
        } else {
                /* create the sysfs class */
                ip2_class = class_create(THIS_MODULE, "ip2");
@@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp)
        /* Register the read_procmem thing */
        if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
                printk(KERN_ERR "IP2: failed to register read_procmem\n");
-       } else {
+               return -EIO; /* leaking resources */
+       }
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
-               /* Register the interrupt handler or poll handler, depending upon the
-                * specified interrupt.
-                */
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
+       /* Register the interrupt handler or poll handler, depending upon the
+        * specified interrupt.
+        */
 
-               for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-                       if ( 0 == ip2config.addr[i] ) {
-                               continue;
-                       }
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (ip2config.addr[i] == 0)
+                       continue;
 
-                       if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-                               device_create_drvdata(ip2_class, NULL,
-                                                     MKDEV(IP2_IPL_MAJOR, 4 * i),
-                                                     NULL, "ipl%d", i);
-                               device_create_drvdata(ip2_class, NULL,
-                                                     MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-                                                     NULL, "stat%d", i);
-
-                           for ( box = 0; box < ABS_MAX_BOXES; ++box )
-                           {
-                               for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
-                               {
-                                   if ( pB->i2eChannelMap[box] & (1 << j) )
-                                   {
-                                       tty_register_device(ip2_tty_driver,
-                                           j + ABS_BIGGEST_BOX *
-                                                   (box+i*ABS_MAX_BOXES), NULL);
-                                   }
-                               }
-                           }
-                       }
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       device_create(ip2_class, NULL,
+                                     MKDEV(IP2_IPL_MAJOR, 4 * i),
+                                     NULL, "ipl%d", i);
+                       device_create(ip2_class, NULL,
+                                     MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+                                     NULL, "stat%d", i);
+
+                       for (box = 0; box < ABS_MAX_BOXES; box++)
+                               for (j = 0; j < ABS_BIGGEST_BOX; j++)
+                                       if (pB->i2eChannelMap[box] & (1 << j))
+                                               tty_register_device(
+                                                       ip2_tty_driver,
+                                                       j + ABS_BIGGEST_BOX *
+                                                       (box+i*ABS_MAX_BOXES),
+                                                       NULL);
+               }
 
-                       if (poll_only) {
-//             Poll only forces driver to only use polling and
-//             to ignore the probed PCI or EISA interrupts.
-                               ip2config.irq[i] = CIR_POLL;
-                       }
-                       if ( ip2config.irq[i] == CIR_POLL ) {
+               if (poll_only) {
+                       /* Poll only forces driver to only use polling and
+                          to ignore the probed PCI or EISA interrupts. */
+                       ip2config.irq[i] = CIR_POLL;
+               }
+               if (ip2config.irq[i] == CIR_POLL) {
 retry:
-                               if (!TimerOn) {
-                                       PollTimer.expires = POLL_TIMEOUT;
-                                       add_timer ( &PollTimer );
-                                       TimerOn = 1;
-                                       printk( KERN_INFO "IP2: polling\n");
-                               }
-                       } else {
-                               if (have_requested_irq(ip2config.irq[i]))
-                                       continue;
-                               rc = request_irq( ip2config.irq[i], ip2_interrupt,
-                                       IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
-                                       pcName, i2BoardPtrTable[i]);
-                               if (rc) {
-                                       printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
-                                       ip2config.irq[i] = CIR_POLL;
-                                       printk( KERN_INFO "IP2: Polling %ld/sec.\n",
-                                                       (POLL_TIMEOUT - jiffies));
-                                       goto retry;
-                               } 
-                               mark_requested_irq(ip2config.irq[i]);
-                               /* Initialise the interrupt handler bottom half (aka slih). */
+                       if (!timer_pending(&PollTimer)) {
+                               mod_timer(&PollTimer, POLL_TIMEOUT);
+                               printk(KERN_INFO "IP2: polling\n");
                        }
-               }
-               for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-                       if ( i2BoardPtrTable[i] ) {
-                               set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
+               } else {
+                       if (have_requested_irq(ip2config.irq[i]))
+                               continue;
+                       rc = request_irq(ip2config.irq[i], ip2_interrupt,
+                               IP2_SA_FLAGS |
+                               (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
+                               pcName, i2BoardPtrTable[i]);
+                       if (rc) {
+                               printk(KERN_ERR "IP2: request_irq failed: "
+                                               "error %d\n", rc);
+                               ip2config.irq[i] = CIR_POLL;
+                               printk(KERN_INFO "IP2: Polling %ld/sec.\n",
+                                               (POLL_TIMEOUT - jiffies));
+                               goto retry;
                        }
+                       mark_requested_irq(ip2config.irq[i]);
+                       /* Initialise the interrupt handler bottom half
+                        * (aka slih). */
                }
        }
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
-       goto out;
+
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (i2BoardPtrTable[i]) {
+                       /* set and enable board interrupt */
+                       set_irq(i, ip2config.irq[i]);
+               }
+       }
+
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
+
+       return 0;
 
 out_chrdev:
        unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-out:
+       /* unregister and put tty here */
        return err;
 }
+module_init(ip2_loadmain);
 
 /******************************************************************************/
 /* Function:   ip2_init_board()                                               */
@@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void)
 {
        int i;
        i2eBordStrPtr  pB;
-       const int irq = 0;
 
-       ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
+       ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
 
        /* Service just the boards on the list using this irq */
        for( i = 0; i < i2nBoards; ++i ) {
@@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void)
 //             Only process those boards which match our IRQ.
 //                     IRQ = 0 for polled boards, we won't poll "IRQ" boards
 
-               if ( pB && (pB->i2eUsingIrq == irq) ) {
+               if (pB && pB->i2eUsingIrq == 0)
                        ip2_irq_work(pB);
-               }
        }
 
        ++irq_counter;
@@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg)
 {
        ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
 
-       TimerOn = 0; // it's the truth but not checked in service
-
        // Just polled boards, IRQ = 0 will hit all non-interrupt boards.
        // It will NOT poll boards handled by hard interrupts.
        // The issue of queued BH interrupts is handled in ip2_interrupt().
        ip2_polled_interrupt();
 
-       PollTimer.expires = POLL_TIMEOUT;
-       add_timer( &PollTimer );
-       TimerOn = 1;
+       mod_timer(&PollTimer, POLL_TIMEOUT);
 
        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
 }
@@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
        case 13:
                switch ( cmd ) {
                case 64:        /* Driver - ip2stat */
-                       rc = put_user(ip2_tty_driver->refcount, pIndex++ );
+                       rc = put_user(-1, pIndex++ );
                        rc = put_user(irq_counter, pIndex++  );
                        rc = put_user(bh_counter, pIndex++  );
                        break;
index 64e1c169e826814c922c6937f738424ba819891b..835a33c8d5f510c7ff0ae3e0360e6ef8ec7f2551 100644 (file)
@@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
        entry->dev = dev;
 
        mutex_lock(&reg_list_mutex);
-       device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
+       device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
        list_add(&entry->link, &reg_list);
        mutex_unlock(&reg_list_mutex);
 }
index 8e8afb6141f99edc8f3a38bbcad1e1b9e802961f..3123bf57ad91365039b9b227dc8fb3182a944c06 100644 (file)
@@ -2695,7 +2695,7 @@ static __devinit void default_find_bmc(void)
        for (i = 0; ; i++) {
                if (!ipmi_defaults[i].port)
                        break;
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
                if (check_legacy_ioport(ipmi_defaults[i].port))
                        continue;
 #endif
index 8f7cc190b62d420116b5c0d30e70899c3332c94d..7d30ee1d3fca9de33cb5e23790fd6df96c791e05 100644 (file)
@@ -421,17 +421,16 @@ static void isicom_tx(unsigned long _data)
        if (retries >= 100)
                goto unlock;
 
+       tty = tty_port_tty_get(&port->port);
+       if (tty == NULL)
+               goto put_unlock;
+
        for (; count > 0; count--, port++) {
                /* port not active or tx disabled to force flow control */
                if (!(port->port.flags & ASYNC_INITIALIZED) ||
                                !(port->status & ISI_TXOK))
                        continue;
 
-               tty = port->port.tty;
-
-               if (tty == NULL)
-                       continue;
-
                txcount = min_t(short, TX_SIZE, port->xmit_cnt);
                if (txcount <= 0 || tty->stopped || tty->hw_stopped)
                        continue;
@@ -489,6 +488,8 @@ static void isicom_tx(unsigned long _data)
                        tty_wakeup(tty);
        }
 
+put_unlock:
+       tty_kref_put(tty);
 unlock:
        spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
        /*      schedule another tx for hopefully in about 10ms */
@@ -547,7 +548,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                return IRQ_HANDLED;
        }
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty == NULL) {
                word_count = byte_count >> 1;
                while (byte_count > 1) {
@@ -588,7 +589,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                        }
 
                        if (port->port.flags & ASYNC_CTS_FLOW) {
-                               if (port->port.tty->hw_stopped) {
+                               if (tty->hw_stopped) {
                                        if (header & ISI_CTS) {
                                                port->port.tty->hw_stopped = 0;
                                                /* start tx ing */
@@ -597,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                                                tty_wakeup(tty);
                                        }
                                } else if (!(header & ISI_CTS)) {
-                                       port->port.tty->hw_stopped = 1;
+                                       tty->hw_stopped = 1;
                                        /* stop tx ing */
                                        port->status &= ~(ISI_TXOK | ISI_CTS);
                                }
@@ -660,24 +661,21 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
        }
        outw(0x0000, base+0x04); /* enable interrupts */
        spin_unlock(&card->card_lock);
+       tty_kref_put(tty);
 
        return IRQ_HANDLED;
 }
 
-static void isicom_config_port(struct isi_port *port)
+static void isicom_config_port(struct tty_struct *tty)
 {
+       struct isi_port *port = tty->driver_data;
        struct isi_board *card = port->card;
-       struct tty_struct *tty;
        unsigned long baud;
        unsigned long base = card->base;
        u16 channel_setup, channel = port->channel,
                shift_count = card->shift_count;
        unsigned char flow_ctrl;
 
-       tty = port->port.tty;
-
-       if (tty == NULL)
-               return;
        /* FIXME: Switch to new tty baud API */
        baud = C_BAUD(tty);
        if (baud & CBAUDEX) {
@@ -690,7 +688,7 @@ static void isicom_config_port(struct isi_port *port)
 
                /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
                if (baud < 1 || baud > 4)
-                       port->port.tty->termios->c_cflag &= ~CBAUDEX;
+                       tty->termios->c_cflag &= ~CBAUDEX;
                else
                        baud += 15;
        }
@@ -797,8 +795,9 @@ static inline void isicom_setup_board(struct isi_board *bp)
        spin_unlock_irqrestore(&bp->card_lock, flags);
 }
 
-static int isicom_setup_port(struct isi_port *port)
+static int isicom_setup_port(struct tty_struct *tty)
 {
+       struct isi_port *port = tty->driver_data;
        struct isi_board *card = port->card;
        unsigned long flags;
 
@@ -808,8 +807,7 @@ static int isicom_setup_port(struct isi_port *port)
                return -ENOMEM;
 
        spin_lock_irqsave(&card->card_lock, flags);
-       if (port->port.tty)
-               clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
+       clear_bit(TTY_IO_ERROR, &tty->flags);
        if (port->port.count == 1)
                card->count++;
 
@@ -823,7 +821,7 @@ static int isicom_setup_port(struct isi_port *port)
                InterruptTheCard(card->base);
        }
 
-       isicom_config_port(port);
+       isicom_config_port(tty);
        port->port.flags |= ASYNC_INITIALIZED;
        spin_unlock_irqrestore(&card->card_lock, flags);
 
@@ -934,8 +932,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
 
        port->port.count++;
        tty->driver_data = port;
-       port->port.tty = tty;
-       error = isicom_setup_port(port);
+       tty_port_tty_set(&port->port, tty);
+       error = isicom_setup_port(tty);
        if (error == 0)
                error = block_til_ready(tty, filp, port);
        return error;
@@ -955,15 +953,17 @@ static void isicom_shutdown_port(struct isi_port *port)
        struct isi_board *card = port->card;
        struct tty_struct *tty;
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
 
-       if (!(port->port.flags & ASYNC_INITIALIZED))
+       if (!(port->port.flags & ASYNC_INITIALIZED)) {
+               tty_kref_put(tty);
                return;
+       }
 
        tty_port_free_xmit_buf(&port->port);
        port->port.flags &= ~ASYNC_INITIALIZED;
        /* 3rd October 2000 : Vinayak P Risbud */
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
 
        /*Fix done by Anil .S on 30-04-2001
        remote login through isi port has dtr toggle problem
@@ -1243,9 +1243,10 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
-static int isicom_set_serial_info(struct isi_port *port,
-       struct serial_struct __user *info)
+static int isicom_set_serial_info(struct tty_struct *tty,
+                                       struct serial_struct __user *info)
 {
+       struct isi_port *port = tty->driver_data;
        struct serial_struct newinfo;
        int reconfig_port;
 
@@ -1276,7 +1277,7 @@ static int isicom_set_serial_info(struct isi_port *port,
        if (reconfig_port) {
                unsigned long flags;
                spin_lock_irqsave(&port->card->card_lock, flags);
-               isicom_config_port(port);
+               isicom_config_port(tty);
                spin_unlock_irqrestore(&port->card->card_lock, flags);
        }
        unlock_kernel();
@@ -1318,7 +1319,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
                return isicom_get_serial_info(port, argp);
 
        case TIOCSSERIAL:
-               return isicom_set_serial_info(port, argp);
+               return isicom_set_serial_info(tty, argp);
 
        default:
                return -ENOIOCTLCMD;
@@ -1341,7 +1342,7 @@ static void isicom_set_termios(struct tty_struct *tty,
                return;
 
        spin_lock_irqsave(&port->card->card_lock, flags);
-       isicom_config_port(port);
+       isicom_config_port(tty);
        spin_unlock_irqrestore(&port->card->card_lock, flags);
 
        if ((old_termios->c_cflag & CRTSCTS) &&
@@ -1419,7 +1420,7 @@ static void isicom_hangup(struct tty_struct *tty)
 
        port->port.count = 0;
        port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
        wake_up_interruptible(&port->port.open_wait);
 }
 
index 843a2afaf2040f2a641af8ea33a4f10b570e5a04..44e5d60f517ebd504c0161d516442c76a42f5e57 100644 (file)
@@ -623,24 +623,25 @@ static int        stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
 static void    stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
 static void    stli_poll(unsigned long arg);
 static int     stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
-static int     stli_initopen(struct stlibrd *brdp, struct stliport *portp);
+static int     stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
 static int     stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
 static int     stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int     stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
-static int     stli_setport(struct stliport *portp);
+static int     stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
+                               struct stliport *portp, struct file *filp);
+static int     stli_setport(struct tty_struct *tty);
 static int     stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
 static void    stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
 static void    __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
 static void    stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
-static void    stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
+static void    stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
 static void    stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
 static long    stli_mktiocm(unsigned long sigvalue);
 static void    stli_read(struct stlibrd *brdp, struct stliport *portp);
 static int     stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
-static int     stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
+static int     stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
 static int     stli_getbrdstats(combrd_t __user *bp);
-static int     stli_getportstats(struct stliport *portp, comstats_t __user *cp);
-static int     stli_portcmdstats(struct stliport *portp);
+static int     stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
+static int     stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
 static int     stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
 static int     stli_getportstruct(struct stliport __user *arg);
 static int     stli_getbrdstruct(struct stlibrd __user *arg);
@@ -731,12 +732,16 @@ static void stli_cleanup_ports(struct stlibrd *brdp)
 {
        struct stliport *portp;
        unsigned int j;
+       struct tty_struct *tty;
 
        for (j = 0; j < STL_MAXPORTS; j++) {
                portp = brdp->ports[j];
                if (portp != NULL) {
-                       if (portp->port.tty != NULL)
-                               tty_hangup(portp->port.tty);
+                       tty = tty_port_tty_get(&portp->port);
+                       if (tty != NULL) {
+                               tty_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                        kfree(portp);
                }
        }
@@ -824,7 +829,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
  *     requires several commands to the board we will need to wait for any
  *     other open that is already initializing the port.
  */
-       portp->port.tty = tty;
+       tty_port_tty_set(&portp->port, tty);
        tty->driver_data = portp;
        portp->port.count++;
 
@@ -835,7 +840,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
 
        if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
                set_bit(ST_INITIALIZING, &portp->state);
-               if ((rc = stli_initopen(brdp, portp)) >= 0) {
+               if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
                        portp->port.flags |= ASYNC_INITIALIZED;
                        clear_bit(TTY_IO_ERROR, &tty->flags);
                }
@@ -864,7 +869,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
  *     then also we might have to wait for carrier.
  */
        if (!(filp->f_flags & O_NONBLOCK)) {
-               if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)
+               if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0)
                        return rc;
        }
        portp->port.flags |= ASYNC_NORMAL_ACTIVE;
@@ -930,7 +935,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
        stli_flushbuffer(tty);
 
        tty->closing = 0;
-       portp->port.tty = NULL;
+       tty_port_tty_set(&portp->port, NULL);
 
        if (portp->openwaitcnt) {
                if (portp->close_delay)
@@ -952,9 +957,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
  *     this still all happens pretty quickly.
  */
 
-static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
+static int stli_initopen(struct tty_struct *tty,
+                               struct stlibrd *brdp, struct stliport *portp)
 {
-       struct tty_struct *tty;
        asynotify_t nt;
        asyport_t aport;
        int rc;
@@ -969,10 +974,7 @@ static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
            sizeof(asynotify_t), 0)) < 0)
                return rc;
 
-       tty = portp->port.tty;
-       if (tty == NULL)
-               return -ENODEV;
-       stli_mkasyport(portp, &aport, tty->termios);
+       stli_mkasyport(tty, portp, &aport, tty->termios);
        if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
            sizeof(asyport_t), 0)) < 0)
                return rc;
@@ -1161,22 +1163,21 @@ static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned l
  *     waiting for the command to complete - so must have user context.
  */
 
-static int stli_setport(struct stliport *portp)
+static int stli_setport(struct tty_struct *tty)
 {
+       struct stliport *portp = tty->driver_data;
        struct stlibrd *brdp;
        asyport_t aport;
 
        if (portp == NULL)
                return -ENODEV;
-       if (portp->port.tty == NULL)
-               return -ENODEV;
        if (portp->brdnr >= stli_nrbrds)
                return -ENODEV;
        brdp = stli_brds[portp->brdnr];
        if (brdp == NULL)
                return -ENODEV;
 
-       stli_mkasyport(portp, &aport, portp->port.tty->termios);
+       stli_mkasyport(tty, portp, &aport, tty->termios);
        return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
 }
 
@@ -1187,7 +1188,8 @@ static int stli_setport(struct stliport *portp)
  *     maybe because if we are clocal then we don't need to wait...
  */
 
-static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
+static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
+                               struct stliport *portp, struct file *filp)
 {
        unsigned long flags;
        int rc, doclocal;
@@ -1195,7 +1197,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct
        rc = 0;
        doclocal = 0;
 
-       if (portp->port.tty->termios->c_cflag & CLOCAL)
+       if (tty->termios->c_cflag & CLOCAL)
                doclocal++;
 
        spin_lock_irqsave(&stli_lock, flags);
@@ -1373,8 +1375,6 @@ static void stli_flushchars(struct tty_struct *tty)
        stli_txcookrealsize = 0;
        stli_txcooktty = NULL;
 
-       if (tty == NULL)
-               return;
        if (cooktty == NULL)
                return;
        if (tty != cooktty)
@@ -1572,10 +1572,11 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s
  *     just quietly ignore any requests to change irq, etc.
  */
 
-static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
+static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
 {
        struct serial_struct sio;
        int rc;
+       struct stliport *portp = tty->driver_data;
 
        if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
                return -EFAULT;
@@ -1594,7 +1595,7 @@ static int stli_setserial(struct stliport *portp, struct serial_struct __user *s
        portp->closing_wait = sio.closing_wait;
        portp->custom_divisor = sio.custom_divisor;
 
-       if ((rc = stli_setport(portp)) < 0)
+       if ((rc = stli_setport(tty)) < 0)
                return rc;
        return 0;
 }
@@ -1685,17 +1686,17 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                rc = stli_getserial(portp, argp);
                break;
        case TIOCSSERIAL:
-               rc = stli_setserial(portp, argp);
+               rc = stli_setserial(tty, argp);
                break;
        case STL_GETPFLAG:
                rc = put_user(portp->pflag, (unsigned __user *)argp);
                break;
        case STL_SETPFLAG:
                if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
-                       stli_setport(portp);
+                       stli_setport(tty);
                break;
        case COM_GETPORTSTATS:
-               rc = stli_getportstats(portp, argp);
+               rc = stli_getportstats(tty, portp, argp);
                break;
        case COM_CLRPORTSTATS:
                rc = stli_clrportstats(portp, argp);
@@ -1729,8 +1730,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
        struct ktermios *tiosp;
        asyport_t aport;
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1742,7 +1741,7 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
 
        tiosp = tty->termios;
 
-       stli_mkasyport(portp, &aport, tiosp);
+       stli_mkasyport(tty, portp, &aport, tiosp);
        stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
        stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
        stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
@@ -1854,7 +1853,7 @@ static void stli_hangup(struct tty_struct *tty)
        clear_bit(ST_TXBUSY, &portp->state);
        clear_bit(ST_RXSTOP, &portp->state);
        set_bit(TTY_IO_ERROR, &tty->flags);
-       portp->port.tty = NULL;
+       tty_port_tty_set(&portp->port, NULL);
        portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
        portp->port.count = 0;
        spin_unlock_irqrestore(&stli_lock, flags);
@@ -1935,8 +1934,6 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
        struct stliport *portp;
        unsigned long tend;
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1998,7 +1995,7 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn
        char *sp, *uart;
        int rc, cnt;
 
-       rc = stli_portcmdstats(portp);
+       rc = stli_portcmdstats(NULL, portp);
 
        uart = "UNKNOWN";
        if (brdp->state & BST_STARTED) {
@@ -2188,7 +2185,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
 
        if (test_bit(ST_RXSTOP, &portp->state))
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -2230,6 +2227,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
                set_bit(ST_RXING, &portp->state);
 
        tty_schedule_flip(tty);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -2362,7 +2360,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
        if (ap->notify) {
                nt = ap->changed;
                ap->notify = 0;
-               tty = portp->port.tty;
+               tty = tty_port_tty_get(&portp->port);
 
                if (nt.signal & SG_DCD) {
                        oldsigs = portp->sigs;
@@ -2399,6 +2397,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
                                tty_schedule_flip(tty);
                        }
                }
+               tty_kref_put(tty);
 
                if (nt.data & DT_RXBUSY) {
                        donerx++;
@@ -2535,14 +2534,15 @@ static void stli_poll(unsigned long arg)
  *     the slave.
  */
 
-static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
+static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
+                               asyport_t *pp, struct ktermios *tiosp)
 {
        memset(pp, 0, sizeof(asyport_t));
 
 /*
  *     Start of by setting the baud, char size, parity and stop bit info.
  */
-       pp->baudout = tty_get_baud_rate(portp->port.tty);
+       pp->baudout = tty_get_baud_rate(tty);
        if ((tiosp->c_cflag & CBAUD) == B38400) {
                if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
                        pp->baudout = 57600;
@@ -2695,7 +2695,7 @@ static int stli_initports(struct stlibrd *brdp)
                        printk("STALLION: failed to allocate port structure\n");
                        continue;
                }
-
+               tty_port_init(&portp->port);
                portp->magic = STLI_PORTMAGIC;
                portp->portnr = i;
                portp->brdnr = brdp->brdnr;
@@ -4220,7 +4220,7 @@ static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
  *     what port to get stats for (used through board control device).
  */
 
-static int stli_portcmdstats(struct stliport *portp)
+static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
 {
        unsigned long   flags;
        struct stlibrd  *brdp;
@@ -4249,15 +4249,15 @@ static int stli_portcmdstats(struct stliport *portp)
        stli_comstats.flags = portp->port.flags;
 
        spin_lock_irqsave(&brd_lock, flags);
-       if (portp->port.tty != NULL) {
-               if (portp->port.tty->driver_data == portp) {
-                       stli_comstats.ttystate = portp->port.tty->flags;
+       if (tty != NULL) {
+               if (portp->port.tty == tty) {
+                       stli_comstats.ttystate = tty->flags;
                        stli_comstats.rxbuffered = -1;
-                       if (portp->port.tty->termios != NULL) {
-                               stli_comstats.cflags = portp->port.tty->termios->c_cflag;
-                               stli_comstats.iflags = portp->port.tty->termios->c_iflag;
-                               stli_comstats.oflags = portp->port.tty->termios->c_oflag;
-                               stli_comstats.lflags = portp->port.tty->termios->c_lflag;
+                       if (tty->termios != NULL) {
+                               stli_comstats.cflags = tty->termios->c_cflag;
+                               stli_comstats.iflags = tty->termios->c_iflag;
+                               stli_comstats.oflags = tty->termios->c_oflag;
+                               stli_comstats.lflags = tty->termios->c_lflag;
                        }
                }
        }
@@ -4294,7 +4294,8 @@ static int stli_portcmdstats(struct stliport *portp)
  *     what port to get stats for (used through board control device).
  */
 
-static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
+static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
+                                                       comstats_t __user *cp)
 {
        struct stlibrd *brdp;
        int rc;
@@ -4312,7 +4313,7 @@ static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
        if (!brdp)
                return -ENODEV;
 
-       if ((rc = stli_portcmdstats(portp)) < 0)
+       if ((rc = stli_portcmdstats(tty, portp)) < 0)
                return rc;
 
        return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
@@ -4427,7 +4428,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
 
        switch (cmd) {
        case COM_GETPORTSTATS:
-               rc = stli_getportstats(NULL, argp);
+               rc = stli_getportstats(NULL, NULL, argp);
                done++;
                break;
        case COM_CLRPORTSTATS:
@@ -4599,9 +4600,8 @@ static int __init istallion_module_init(void)
 
        istallion_class = class_create(THIS_MODULE, "staliomem");
        for (i = 0; i < 4; i++)
-               device_create_drvdata(istallion_class, NULL,
-                                     MKDEV(STL_SIOMEMMAJOR, i),
-                                     NULL, "staliomem%d", i);
+               device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+                             NULL, "staliomem%d", i);
 
        return 0;
 err_deinit:
index 7b3a212c86b1ab21d5e3d783716ded2787f3729d..de26a978fbdd140aec88179b99c14fae555c467c 100644 (file)
@@ -1249,7 +1249,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
                return;
        }
 
-       if (keycode > NR_KEYS)
+       if (keycode >= NR_KEYS)
                if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8)
                        keysym = K(KT_BRL, keycode - KEY_BRL_DOT1 + 1);
                else
index 3f2719b9f77b5fca364477dfa7d096c66be759cb..e444c2dba160870658b8ac45910ba79b85d12419 100644 (file)
@@ -813,8 +813,8 @@ static int lp_register(int nr, struct parport *port)
        if (reset)
                lp_reset(nr);
 
-       device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
-                             "lp%d", nr);
+       device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+                     "lp%d", nr);
 
        printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
               (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
index 672b08e694d05cd041e8a3bbac17264f3ca2fb4e..6431f6921a67acde3c214f784904c4ebd0f62678 100644 (file)
@@ -992,9 +992,9 @@ static int __init chr_dev_init(void)
 
        mem_class = class_create(THIS_MODULE, "mem");
        for (i = 0; i < ARRAY_SIZE(devlist); i++)
-               device_create_drvdata(mem_class, NULL,
-                                     MKDEV(MEM_MAJOR, devlist[i].minor),
-                                     NULL, devlist[i].name);
+               device_create(mem_class, NULL,
+                             MKDEV(MEM_MAJOR, devlist[i].minor), NULL,
+                             devlist[i].name);
 
        return 0;
 }
index 999aa779c08a710601fabc93cacb6f52229c53ba..a5e0db9d7662d4a060ff167260753b193a64ee9f 100644 (file)
@@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc)
                misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
        dev = MKDEV(MISC_MAJOR, misc->minor);
 
-       misc->this_device = device_create_drvdata(misc_class, misc->parent,
-                                                 dev, NULL, "%s", misc->name);
+       misc->this_device = device_create(misc_class, misc->parent, dev, NULL,
+                                         "%s", misc->name);
        if (IS_ERR(misc->this_device)) {
                err = PTR_ERR(misc->this_device);
                goto out;
index d3d7864e0c1ef566b86d9a5cfb72c45d2aaf5836..12d327a2c9ba72cadd471670f6300cca3e9a1ad0 100644 (file)
@@ -205,7 +205,7 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
 static void moxa_poll(unsigned long);
 static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
 static void moxa_setup_empty_event(struct tty_struct *);
-static void moxa_shut_down(struct moxa_port *);
+static void moxa_shut_down(struct tty_struct *);
 /*
  * moxa board interface functions:
  */
@@ -217,7 +217,7 @@ static void MoxaPortLineCtrl(struct moxa_port *, int, int);
 static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
 static int MoxaPortLineStatus(struct moxa_port *);
 static void MoxaPortFlushData(struct moxa_port *, int);
-static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int);
+static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
 static int MoxaPortReadData(struct moxa_port *);
 static int MoxaPortTxQueue(struct moxa_port *);
 static int MoxaPortRxQueue(struct moxa_port *);
@@ -332,6 +332,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
                for (i = 0; i < MAX_BOARDS; i++) {
                        p = moxa_boards[i].ports;
                        for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+                               struct tty_struct *ttyp;
                                memset(&tmp, 0, sizeof(tmp));
                                if (!moxa_boards[i].ready)
                                        goto copy;
@@ -344,10 +345,12 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
                                if (status & 4)
                                        tmp.dcd = 1;
 
-                               if (!p->port.tty || !p->port.tty->termios)
+                               ttyp = tty_port_tty_get(&p->port);
+                               if (!ttyp || !ttyp->termios)
                                        tmp.cflag = p->cflag;
                                else
-                                       tmp.cflag = p->port.tty->termios->c_cflag;
+                                       tmp.cflag = ttyp->termios->c_cflag;
+                               tty_kref_put(tty);
 copy:
                                if (copy_to_user(argm, &tmp, sizeof(tmp))) {
                                        mutex_unlock(&moxa_openlock);
@@ -510,7 +513,7 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
                size_t len)
 {
        void __iomem *baseAddr = brd->basemem;
-       const u16 *uptr = ptr;
+       const __le16 *uptr = ptr;
        size_t wlen, len2, j;
        unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
        unsigned int i, retry;
@@ -880,8 +883,14 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
 
        /* pci hot-un-plug support */
        for (a = 0; a < brd->numPorts; a++)
-               if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
-                       tty_hangup(brd->ports[a].port.tty);
+               if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
+                       struct tty_struct *tty = tty_port_tty_get(
+                                               &brd->ports[a].port);
+                       if (tty) {
+                               tty_hangup(tty);
+                               tty_kref_put(tty);
+                       }
+               }
        while (1) {
                opened = 0;
                for (a = 0; a < brd->numPorts; a++)
@@ -1096,13 +1105,14 @@ static void __exit moxa_exit(void)
 module_init(moxa_init);
 module_exit(moxa_exit);
 
-static void moxa_close_port(struct moxa_port *ch)
+static void moxa_close_port(struct tty_struct *tty)
 {
-       moxa_shut_down(ch);
+       struct moxa_port *ch = tty->driver_data;
+       moxa_shut_down(tty);
        MoxaPortFlushData(ch, 2);
        ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-       ch->port.tty->driver_data = NULL;
-       ch->port.tty = NULL;
+       tty->driver_data = NULL;
+       tty_port_tty_set(&ch->port, NULL);
 }
 
 static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
@@ -1161,7 +1171,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
        ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
        ch->port.count++;
        tty->driver_data = ch;
-       ch->port.tty = tty;
+       tty_port_tty_set(&ch->port, tty);
        if (!(ch->port.flags & ASYNC_INITIALIZED)) {
                ch->statusflags = 0;
                moxa_set_tty_param(tty, tty->termios);
@@ -1179,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
        if (retval) {
                if (ch->port.count) /* 0 means already hung up... */
                        if (--ch->port.count == 0)
-                               moxa_close_port(ch);
+                               moxa_close_port(tty);
        } else
                ch->port.flags |= ASYNC_NORMAL_ACTIVE;
        mutex_unlock(&moxa_openlock);
@@ -1219,7 +1229,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
                tty_wait_until_sent(tty, 30 * HZ);      /* 30 seconds timeout */
        }
 
-       moxa_close_port(ch);
+       moxa_close_port(tty);
 unlock:
        mutex_unlock(&moxa_openlock);
 }
@@ -1234,7 +1244,7 @@ static int moxa_write(struct tty_struct *tty,
                return 0;
 
        spin_lock_bh(&moxa_lock);
-       len = MoxaPortWriteData(ch, buf, count);
+       len = MoxaPortWriteData(tty, buf, count);
        spin_unlock_bh(&moxa_lock);
 
        ch->statusflags |= LOWWAIT;
@@ -1409,7 +1419,7 @@ static void moxa_hangup(struct tty_struct *tty)
                return;
        }
        ch->port.count = 0;
-       moxa_close_port(ch);
+       moxa_close_port(tty);
        mutex_unlock(&moxa_openlock);
 
        wake_up_interruptible(&ch->port.open_wait);
@@ -1417,11 +1427,14 @@ static void moxa_hangup(struct tty_struct *tty)
 
 static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 {
+       struct tty_struct *tty;
        dcd = !!dcd;
 
-       if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) {
-               if (!dcd)
-                       tty_hangup(p->port.tty);
+       if (dcd != p->DCDState) {
+               tty = tty_port_tty_get(&p->port);
+               if (tty && C_CLOCAL(tty) && !dcd)
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
        p->DCDState = dcd;
 }
@@ -1429,7 +1442,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
 static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
                u16 __iomem *ip)
 {
-       struct tty_struct *tty = p->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&p->port);
        void __iomem *ofsAddr;
        unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
        u16 intr;
@@ -1476,6 +1489,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
                tty_insert_flip_char(tty, 0, TTY_BREAK);
                tty_schedule_flip(tty);
        }
+       tty_kref_put(tty);
 
        if (intr & IntrLine)
                moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
@@ -1560,9 +1574,9 @@ static void moxa_setup_empty_event(struct tty_struct *tty)
        spin_unlock_bh(&moxa_lock);
 }
 
-static void moxa_shut_down(struct moxa_port *ch)
+static void moxa_shut_down(struct tty_struct *tty)
 {
-       struct tty_struct *tp = ch->port.tty;
+       struct moxa_port *ch = tty->driver_data;
 
        if (!(ch->port.flags & ASYNC_INITIALIZED))
                return;
@@ -1572,7 +1586,7 @@ static void moxa_shut_down(struct moxa_port *ch)
        /*
         * If we're a modem control device and HUPCL is on, drop RTS & DTR.
         */
-       if (C_HUPCL(tp))
+       if (C_HUPCL(tty))
                MoxaPortLineCtrl(ch, 0, 0);
 
        spin_lock_bh(&moxa_lock);
@@ -1953,9 +1967,10 @@ static int MoxaPortLineStatus(struct moxa_port *port)
        return val;
 }
 
-static int MoxaPortWriteData(struct moxa_port *port,
+static int MoxaPortWriteData(struct tty_struct *tty,
                const unsigned char *buffer, int len)
 {
+       struct moxa_port *port = tty->driver_data;
        void __iomem *baseAddr, *ofsAddr, *ofs;
        unsigned int c, total;
        u16 head, tail, tx_mask, spage, epage;
index b638403e8e9c870af1d37cec1a44d5ffd54ae14f..8beef50f95a0929190e8321c49910f5c4b581ca0 100644 (file)
@@ -610,15 +610,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
        return 0;
 }
 
-static int mxser_set_baud(struct mxser_port *info, long newspd)
+static int mxser_set_baud(struct tty_struct *tty, long newspd)
 {
+       struct mxser_port *info = tty->driver_data;
        int quot = 0, baud;
        unsigned char cval;
 
-       if (!info->port.tty || !info->port.tty->termios)
-               return -1;
-
-       if (!(info->ioaddr))
+       if (!info->ioaddr)
                return -1;
 
        if (newspd > info->max_baud)
@@ -626,13 +624,13 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
 
        if (newspd == 134) {
                quot = 2 * info->baud_base / 269;
-               tty_encode_baud_rate(info->port.tty, 134, 134);
+               tty_encode_baud_rate(tty, 134, 134);
        } else if (newspd) {
                quot = info->baud_base / newspd;
                if (quot == 0)
                        quot = 1;
                baud = info->baud_base/quot;
-               tty_encode_baud_rate(info->port.tty, baud, baud);
+               tty_encode_baud_rate(tty, baud, baud);
        } else {
                quot = 0;
        }
@@ -658,7 +656,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
        outb(cval, info->ioaddr + UART_LCR);    /* reset DLAB */
 
 #ifdef BOTHER
-       if (C_BAUD(info->port.tty) == BOTHER) {
+       if (C_BAUD(tty) == BOTHER) {
                quot = info->baud_base % newspd;
                quot *= 8;
                if (quot % newspd > newspd / 2) {
@@ -679,21 +677,20 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
  * This routine is called to set the UART divisor registers to match
  * the specified baud rate for a serial port.
  */
-static int mxser_change_speed(struct mxser_port *info,
-               struct ktermios *old_termios)
+static int mxser_change_speed(struct tty_struct *tty,
+                                       struct ktermios *old_termios)
 {
+       struct mxser_port *info = tty->driver_data;
        unsigned cflag, cval, fcr;
        int ret = 0;
        unsigned char status;
 
-       if (!info->port.tty || !info->port.tty->termios)
-               return ret;
-       cflag = info->port.tty->termios->c_cflag;
-       if (!(info->ioaddr))
+       cflag = tty->termios->c_cflag;
+       if (!info->ioaddr)
                return ret;
 
-       if (mxser_set_baud_method[info->port.tty->index] == 0)
-               mxser_set_baud(info, tty_get_baud_rate(info->port.tty));
+       if (mxser_set_baud_method[tty->index] == 0)
+               mxser_set_baud(tty, tty_get_baud_rate(tty));
 
        /* byte size and parity */
        switch (cflag & CSIZE) {
@@ -762,9 +759,9 @@ static int mxser_change_speed(struct mxser_port *info,
                        info->MCR |= UART_MCR_AFE;
                } else {
                        status = inb(info->ioaddr + UART_MSR);
-                       if (info->port.tty->hw_stopped) {
+                       if (tty->hw_stopped) {
                                if (status & UART_MSR_CTS) {
-                                       info->port.tty->hw_stopped = 0;
+                                       tty->hw_stopped = 0;
                                        if (info->type != PORT_16550A &&
                                                        !info->board->chip_flag) {
                                                outb(info->IER & ~UART_IER_THRI,
@@ -774,11 +771,11 @@ static int mxser_change_speed(struct mxser_port *info,
                                                outb(info->IER, info->ioaddr +
                                                                UART_IER);
                                        }
-                                       tty_wakeup(info->port.tty);
+                                       tty_wakeup(tty);
                                }
                        } else {
                                if (!(status & UART_MSR_CTS)) {
-                                       info->port.tty->hw_stopped = 1;
+                                       tty->hw_stopped = 1;
                                        if ((info->type != PORT_16550A) &&
                                                        (!info->board->chip_flag)) {
                                                info->IER &= ~UART_IER_THRI;
@@ -804,21 +801,21 @@ static int mxser_change_speed(struct mxser_port *info,
         * Set up parity check flag
         */
        info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (I_INPCK(info->port.tty))
+       if (I_INPCK(tty))
                info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+       if (I_BRKINT(tty) || I_PARMRK(tty))
                info->read_status_mask |= UART_LSR_BI;
 
        info->ignore_status_mask = 0;
 
-       if (I_IGNBRK(info->port.tty)) {
+       if (I_IGNBRK(tty)) {
                info->ignore_status_mask |= UART_LSR_BI;
                info->read_status_mask |= UART_LSR_BI;
                /*
                 * If we're ignore parity and break indicators, ignore
                 * overruns too.  (For real raw support).
                 */
-               if (I_IGNPAR(info->port.tty)) {
+               if (I_IGNPAR(tty)) {
                        info->ignore_status_mask |=
                                                UART_LSR_OE |
                                                UART_LSR_PE |
@@ -830,16 +827,16 @@ static int mxser_change_speed(struct mxser_port *info,
                }
        }
        if (info->board->chip_flag) {
-               mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->port.tty));
-               mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->port.tty));
-               if (I_IXON(info->port.tty)) {
+               mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
+               mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
+               if (I_IXON(tty)) {
                        mxser_enable_must_rx_software_flow_control(
                                        info->ioaddr);
                } else {
                        mxser_disable_must_rx_software_flow_control(
                                        info->ioaddr);
                }
-               if (I_IXOFF(info->port.tty)) {
+               if (I_IXOFF(tty)) {
                        mxser_enable_must_tx_software_flow_control(
                                        info->ioaddr);
                } else {
@@ -855,7 +852,8 @@ static int mxser_change_speed(struct mxser_port *info,
        return ret;
 }
 
-static void mxser_check_modem_status(struct mxser_port *port, int status)
+static void mxser_check_modem_status(struct tty_struct *tty,
+                               struct mxser_port *port, int status)
 {
        /* update input line counters */
        if (status & UART_MSR_TERI)
@@ -874,10 +872,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
                        wake_up_interruptible(&port->port.open_wait);
        }
 
+       tty = tty_port_tty_get(&port->port);
        if (port->port.flags & ASYNC_CTS_FLOW) {
-               if (port->port.tty->hw_stopped) {
+               if (tty->hw_stopped) {
                        if (status & UART_MSR_CTS) {
-                               port->port.tty->hw_stopped = 0;
+                               tty->hw_stopped = 0;
 
                                if ((port->type != PORT_16550A) &&
                                                (!port->board->chip_flag)) {
@@ -887,11 +886,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
                                        outb(port->IER, port->ioaddr +
                                                        UART_IER);
                                }
-                               tty_wakeup(port->port.tty);
+                               tty_wakeup(tty);
                        }
                } else {
                        if (!(status & UART_MSR_CTS)) {
-                               port->port.tty->hw_stopped = 1;
+                               tty->hw_stopped = 1;
                                if (port->type != PORT_16550A &&
                                                !port->board->chip_flag) {
                                        port->IER &= ~UART_IER_THRI;
@@ -903,8 +902,9 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
        }
 }
 
-static int mxser_startup(struct mxser_port *info)
+static int mxser_startup(struct tty_struct *tty)
 {
+       struct mxser_port *info = tty->driver_data;
        unsigned long page;
        unsigned long flags;
 
@@ -921,8 +921,7 @@ static int mxser_startup(struct mxser_port *info)
        }
 
        if (!info->ioaddr || !info->type) {
-               if (info->port.tty)
-                       set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+               set_bit(TTY_IO_ERROR, &tty->flags);
                free_page(page);
                spin_unlock_irqrestore(&info->slock, flags);
                return 0;
@@ -952,8 +951,8 @@ static int mxser_startup(struct mxser_port *info)
        if (inb(info->ioaddr + UART_LSR) == 0xff) {
                spin_unlock_irqrestore(&info->slock, flags);
                if (capable(CAP_SYS_ADMIN)) {
-                       if (info->port.tty)
-                               set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+                       if (tty)
+                               set_bit(TTY_IO_ERROR, &tty->flags);
                        return 0;
                } else
                        return -ENODEV;
@@ -991,14 +990,13 @@ static int mxser_startup(struct mxser_port *info)
        (void) inb(info->ioaddr + UART_IIR);
        (void) inb(info->ioaddr + UART_MSR);
 
-       if (info->port.tty)
-               clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+       clear_bit(TTY_IO_ERROR, &tty->flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 
        /*
         * and set the speed of the serial port
         */
-       mxser_change_speed(info, NULL);
+       mxser_change_speed(tty, NULL);
        info->port.flags |= ASYNC_INITIALIZED;
        spin_unlock_irqrestore(&info->slock, flags);
 
@@ -1009,8 +1007,9 @@ static int mxser_startup(struct mxser_port *info)
  * This routine will shutdown a serial port; interrupts maybe disabled, and
  * DTR is dropped if the hangup on close termio flag is on.
  */
-static void mxser_shutdown(struct mxser_port *info)
+static void mxser_shutdown(struct tty_struct *tty)
 {
+       struct mxser_port *info = tty->driver_data;
        unsigned long flags;
 
        if (!(info->port.flags & ASYNC_INITIALIZED))
@@ -1035,7 +1034,7 @@ static void mxser_shutdown(struct mxser_port *info)
        info->IER = 0;
        outb(0x00, info->ioaddr + UART_IER);
 
-       if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
+       if (tty->termios->c_cflag & HUPCL)
                info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
        outb(info->MCR, info->ioaddr + UART_MCR);
 
@@ -1051,8 +1050,7 @@ static void mxser_shutdown(struct mxser_port *info)
        /* read data port to reset things */
        (void) inb(info->ioaddr + UART_RX);
 
-       if (info->port.tty)
-               set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+       set_bit(TTY_IO_ERROR, &tty->flags);
 
        info->port.flags &= ~ASYNC_INITIALIZED;
 
@@ -1084,14 +1082,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
                return -ENODEV;
 
        tty->driver_data = info;
-       info->port.tty = tty;
+       tty_port_tty_set(&info->port, tty);
        /*
         * Start up serial port
         */
        spin_lock_irqsave(&info->slock, flags);
        info->port.count++;
        spin_unlock_irqrestore(&info->slock, flags);
-       retval = mxser_startup(info);
+       retval = mxser_startup(tty);
        if (retval)
                return retval;
 
@@ -1209,13 +1207,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
                                break;
                }
        }
-       mxser_shutdown(info);
+       mxser_shutdown(tty);
 
        mxser_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
-       info->port.tty = NULL;
+       tty_port_tty_set(&info->port, NULL);
        if (info->port.blocked_open) {
                if (info->port.close_delay)
                        schedule_timeout_interruptible(info->port.close_delay);
@@ -1337,12 +1335,13 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
  * friends of mxser_ioctl()
  * ------------------------------------------------------------
  */
-static int mxser_get_serial_info(struct mxser_port *info,
+static int mxser_get_serial_info(struct tty_struct *tty,
                struct serial_struct __user *retinfo)
 {
+       struct mxser_port *info = tty->driver_data;
        struct serial_struct tmp = {
                .type = info->type,
-               .line = info->port.tty->index,
+               .line = tty->index,
                .port = info->ioaddr,
                .irq = info->board->irq,
                .flags = info->port.flags,
@@ -1357,9 +1356,10 @@ static int mxser_get_serial_info(struct mxser_port *info,
        return 0;
 }
 
-static int mxser_set_serial_info(struct mxser_port *info,
+static int mxser_set_serial_info(struct tty_struct *tty,
                struct serial_struct __user *new_info)
 {
+       struct mxser_port *info = tty->driver_data;
        struct serial_struct new_serial;
        speed_t baud;
        unsigned long sl_flags;
@@ -1393,14 +1393,14 @@ static int mxser_set_serial_info(struct mxser_port *info,
                                (new_serial.flags & ASYNC_FLAGS));
                info->port.close_delay = new_serial.close_delay * HZ / 100;
                info->port.closing_wait = new_serial.closing_wait * HZ / 100;
-               info->port.tty->low_latency =
-                               (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+               tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY)
+                                                               ? 1 : 0;
                if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
                                (new_serial.baud_base != info->baud_base ||
                                new_serial.custom_divisor !=
                                info->custom_divisor)) {
                        baud = new_serial.baud_base / new_serial.custom_divisor;
-                       tty_encode_baud_rate(info->port.tty, baud, baud);
+                       tty_encode_baud_rate(tty, baud, baud);
                }
        }
 
@@ -1411,11 +1411,11 @@ static int mxser_set_serial_info(struct mxser_port *info,
        if (info->port.flags & ASYNC_INITIALIZED) {
                if (flags != (info->port.flags & ASYNC_SPD_MASK)) {
                        spin_lock_irqsave(&info->slock, sl_flags);
-                       mxser_change_speed(info, NULL);
+                       mxser_change_speed(tty, NULL);
                        spin_unlock_irqrestore(&info->slock, sl_flags);
                }
        } else
-               retval = mxser_startup(info);
+               retval = mxser_startup(tty);
 
        return retval;
 }
@@ -1461,7 +1461,7 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
        spin_lock_irqsave(&info->slock, flags);
        status = inb(info->ioaddr + UART_MSR);
        if (status & UART_MSR_ANY_DELTA)
-               mxser_check_modem_status(info, status);
+               mxser_check_modem_status(tty, info, status);
        spin_unlock_irqrestore(&info->slock, flags);
        return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
                    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
@@ -1606,6 +1606,7 @@ static int __init mxser_read_register(int port, unsigned short *regs)
 static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 {
        struct mxser_port *port;
+       struct tty_struct *tty;
        int result, status;
        unsigned int i, j;
        int ret = 0;
@@ -1643,12 +1644,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
                                if (!port->ioaddr)
                                        goto copy;
+                               
+                               tty = tty_port_tty_get(&port->port);
 
-                               if (!port->port.tty || !port->port.tty->termios)
+                               if (!tty || !tty->termios)
                                        ms.cflag = port->normal_termios.c_cflag;
                                else
-                                       ms.cflag = port->port.tty->termios->c_cflag;
-
+                                       ms.cflag = tty->termios->c_cflag;
+                               tty_kref_put(tty);
                                status = inb(port->ioaddr + UART_MSR);
                                if (status & UART_MSR_DCD)
                                        ms.dcd = 1;
@@ -1704,15 +1707,18 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                me->up_txcnt[p] = port->mon_data.up_txcnt;
                                me->modem_status[p] =
                                        port->mon_data.modem_status;
-                               me->baudrate[p] = tty_get_baud_rate(port->port.tty);
+                               tty = tty_port_tty_get(&port->port);
 
-                               if (!port->port.tty || !port->port.tty->termios) {
+                               if (!tty || !tty->termios) {
                                        cflag = port->normal_termios.c_cflag;
                                        iflag = port->normal_termios.c_iflag;
+                                       me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios);
                                } else {
-                                       cflag = port->port.tty->termios->c_cflag;
-                                       iflag = port->port.tty->termios->c_iflag;
+                                       cflag = tty->termios->c_cflag;
+                                       iflag = tty->termios->c_iflag;
+                                       me->baudrate[p] = tty_get_baud_rate(tty);
                                }
+                               tty_kref_put(tty);
 
                                me->databits[p] = cflag & CSIZE;
                                me->stopbits[p] = cflag & CSTOPB;
@@ -1822,12 +1828,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
        switch (cmd) {
        case TIOCGSERIAL:
                lock_kernel();
-               retval = mxser_get_serial_info(info, argp);
+               retval = mxser_get_serial_info(tty, argp);
                unlock_kernel();
                return retval;
        case TIOCSSERIAL:
                lock_kernel();
-               retval = mxser_set_serial_info(info, argp);
+               retval = mxser_set_serial_info(tty, argp);
                unlock_kernel();
                return retval;
        case TIOCSERGETLSR:     /* Get line status register */
@@ -1896,7 +1902,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
 
                lock_kernel();
                status = mxser_get_msr(info->ioaddr, 1, tty->index);
-               mxser_check_modem_status(info, status);
+               mxser_check_modem_status(tty, info, status);
 
                mcr = inb(info->ioaddr + UART_MCR);
                if (mcr & MOXA_MUST_MCR_XON_FLAG)
@@ -1909,7 +1915,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                else
                        info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
 
-               if (info->port.tty->hw_stopped)
+               if (tty->hw_stopped)
                        info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
                else
                        info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
@@ -1958,7 +1964,7 @@ static void mxser_stoprx(struct tty_struct *tty)
                }
        }
 
-       if (info->port.tty->termios->c_cflag & CRTSCTS) {
+       if (tty->termios->c_cflag & CRTSCTS) {
                info->MCR &= ~UART_MCR_RTS;
                outb(info->MCR, info->ioaddr + UART_MCR);
        }
@@ -1995,7 +2001,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
                }
        }
 
-       if (info->port.tty->termios->c_cflag & CRTSCTS) {
+       if (tty->termios->c_cflag & CRTSCTS) {
                info->MCR |= UART_MCR_RTS;
                outb(info->MCR, info->ioaddr + UART_MCR);
        }
@@ -2040,7 +2046,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
        unsigned long flags;
 
        spin_lock_irqsave(&info->slock, flags);
-       mxser_change_speed(info, old_termios);
+       mxser_change_speed(tty, old_termios);
        spin_unlock_irqrestore(&info->slock, flags);
 
        if ((old_termios->c_cflag & CRTSCTS) &&
@@ -2138,10 +2144,10 @@ static void mxser_hangup(struct tty_struct *tty)
        struct mxser_port *info = tty->driver_data;
 
        mxser_flush_buffer(tty);
-       mxser_shutdown(info);
+       mxser_shutdown(tty);
        info->port.count = 0;
        info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-       info->port.tty = NULL;
+       tty_port_tty_set(&info->port, NULL);
        wake_up_interruptible(&info->port.open_wait);
 }
 
@@ -2164,9 +2170,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)
        return 0;
 }
 
-static void mxser_receive_chars(struct mxser_port *port, int *status)
+static void mxser_receive_chars(struct tty_struct *tty,
+                               struct mxser_port *port, int *status)
 {
-       struct tty_struct *tty = port->port.tty;
        unsigned char ch, gdl;
        int ignored = 0;
        int cnt = 0;
@@ -2174,9 +2180,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
        int max = 256;
 
        recv_room = tty->receive_room;
-       if ((recv_room == 0) && (!port->ldisc_stop_rx))
+       if (recv_room == 0 && !port->ldisc_stop_rx)
                mxser_stoprx(tty);
-
        if (port->board->chip_flag != MOXA_OTHER_UART) {
 
                if (*status & UART_LSR_SPECIAL)
@@ -2253,7 +2258,7 @@ intr_old:
        } while (*status & UART_LSR_DR);
 
 end_intr:
-       mxvar_log.rxcnt[port->port.tty->index] += cnt;
+       mxvar_log.rxcnt[tty->index] += cnt;
        port->mon_data.rxcnt += cnt;
        port->mon_data.up_rxcnt += cnt;
 
@@ -2267,14 +2272,14 @@ end_intr:
        spin_lock(&port->slock);
 }
 
-static void mxser_transmit_chars(struct mxser_port *port)
+static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
 {
        int count, cnt;
 
        if (port->x_char) {
                outb(port->x_char, port->ioaddr + UART_TX);
                port->x_char = 0;
-               mxvar_log.txcnt[port->port.tty->index]++;
+               mxvar_log.txcnt[tty->index]++;
                port->mon_data.txcnt++;
                port->mon_data.up_txcnt++;
                port->icount.tx++;
@@ -2284,8 +2289,8 @@ static void mxser_transmit_chars(struct mxser_port *port)
        if (port->port.xmit_buf == NULL)
                return;
 
-       if ((port->xmit_cnt <= 0) || port->port.tty->stopped ||
-                       (port->port.tty->hw_stopped &&
+       if (port->xmit_cnt <= 0 || tty->stopped ||
+                       (tty->hw_stopped &&
                        (port->type != PORT_16550A) &&
                        (!port->board->chip_flag))) {
                port->IER &= ~UART_IER_THRI;
@@ -2302,14 +2307,14 @@ static void mxser_transmit_chars(struct mxser_port *port)
                if (--port->xmit_cnt <= 0)
                        break;
        } while (--count > 0);
-       mxvar_log.txcnt[port->port.tty->index] += (cnt - port->xmit_cnt);
+       mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
 
        port->mon_data.txcnt += (cnt - port->xmit_cnt);
        port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
        port->icount.tx += (cnt - port->xmit_cnt);
 
-       if (port->xmit_cnt < WAKEUP_CHARS)
-               tty_wakeup(port->port.tty);
+       if (port->xmit_cnt < WAKEUP_CHARS && tty)
+               tty_wakeup(tty);
 
        if (port->xmit_cnt <= 0) {
                port->IER &= ~UART_IER_THRI;
@@ -2328,6 +2333,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
        int max, irqbits, bits, msr;
        unsigned int int_cnt, pass_counter = 0;
        int handled = IRQ_NONE;
+       struct tty_struct *tty;
 
        for (i = 0; i < MXSER_BOARDS; i++)
                if (dev_id == &mxser_boards[i]) {
@@ -2360,13 +2366,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
                                if (iir & UART_IIR_NO_INT)
                                        break;
                                iir &= MOXA_MUST_IIR_MASK;
-                               if (!port->port.tty ||
+                               tty = tty_port_tty_get(&port->port);
+                               if (!tty ||
                                                (port->port.flags & ASYNC_CLOSING) ||
                                                !(port->port.flags &
                                                        ASYNC_INITIALIZED)) {
                                        status = inb(port->ioaddr + UART_LSR);
                                        outb(0x27, port->ioaddr + UART_FCR);
                                        inb(port->ioaddr + UART_MSR);
+                                       tty_kref_put(tty);
                                        break;
                                }
 
@@ -2387,27 +2395,28 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
                                            iir == MOXA_MUST_IIR_RDA ||
                                            iir == MOXA_MUST_IIR_RTO ||
                                            iir == MOXA_MUST_IIR_LSR)
-                                               mxser_receive_chars(port,
+                                               mxser_receive_chars(tty, port,
                                                                &status);
 
                                } else {
                                        status &= port->read_status_mask;
                                        if (status & UART_LSR_DR)
-                                               mxser_receive_chars(port,
+                                               mxser_receive_chars(tty, port,
                                                                &status);
                                }
                                msr = inb(port->ioaddr + UART_MSR);
                                if (msr & UART_MSR_ANY_DELTA)
-                                       mxser_check_modem_status(port, msr);
+                                       mxser_check_modem_status(tty, port, msr);
 
                                if (port->board->chip_flag) {
                                        if (iir == 0x02 && (status &
                                                                UART_LSR_THRE))
-                                               mxser_transmit_chars(port);
+                                               mxser_transmit_chars(tty, port);
                                } else {
                                        if (status & UART_LSR_THRE)
-                                               mxser_transmit_chars(port);
+                                               mxser_transmit_chars(tty, port);
                                }
+                               tty_kref_put(tty);
                        } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
                        spin_unlock(&port->slock);
                }
index 69ec6399c714b206ea11de8c30d8ba75fd0a9bd6..bacb3e2872ae49cbc5668e6a402cb50fbf75a30b 100644 (file)
@@ -764,7 +764,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
                break;
 
        default:
-               error = n_tty_ioctl (tty, file, cmd, arg);
+               error = n_tty_ioctl_helper(tty, file, cmd, arg);
                break;
        }
        return error;
index ae377aa473ba6fbe5644ac47866fd9637fc1499b..4a8215a89ad3fe4287b0f5f4560844b0c3cb4b2e 100644 (file)
@@ -372,14 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
 static void put_char(struct r3964_info *pInfo, unsigned char ch)
 {
        struct tty_struct *tty = pInfo->tty;
-
-       if (tty == NULL)
-               return;
-
        /* FIXME: put_char should not be called from an IRQ */
-       if (tty->ops->put_char) {
-               tty->ops->put_char(tty, ch);
-       }
+       tty_put_char(tty, ch);
        pInfo->bcc ^= ch;
 }
 
index 708c2b1dbe51068a5d1b91ba27d38d79d0c39308..efbfe9612658bc5cd32b0e36c77e8651a3363746 100644 (file)
@@ -26,7 +26,7 @@
  *
  * 2002/03/18   Implemented n_tty_wakeup to send SIGIO POLL_OUTs to
  *             waiting writing processes-Sapan Bhatia <sapan@corewars.org>.
- *             Also fixed a bug in BLOCKING mode where write_chan returns
+ *             Also fixed a bug in BLOCKING mode where n_tty_write returns
  *             EAGAIN
  */
 
@@ -99,6 +99,7 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
 
 static void n_tty_set_room(struct tty_struct *tty)
 {
+       /* tty->read_cnt is not read locked ? */
        int     left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
 
        /*
@@ -121,6 +122,16 @@ static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
        }
 }
 
+/**
+ *     put_tty_queue           -       add character to tty
+ *     @c: character
+ *     @tty: tty device
+ *
+ *     Add a character to the tty read_buf queue. This is done under the
+ *     read_lock to serialize character addition and also to protect us
+ *     against parallel reads or flushes
+ */
+
 static void put_tty_queue(unsigned char c, struct tty_struct *tty)
 {
        unsigned long flags;
@@ -137,14 +148,11 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)
  *     check_unthrottle        -       allow new receive data
  *     @tty; tty device
  *
- *     Check whether to call the driver.unthrottle function.
- *     We test the TTY_THROTTLED bit first so that it always
- *     indicates the current state. The decision about whether
- *     it is worth allowing more input has been taken by the caller.
+ *     Check whether to call the driver unthrottle functions
+ *
  *     Can sleep, may be called under the atomic_read_lock mutex but
  *     this is not guaranteed.
  */
-
 static void check_unthrottle(struct tty_struct *tty)
 {
        if (tty->count)
@@ -158,6 +166,8 @@ static void check_unthrottle(struct tty_struct *tty)
  *     Reset the read buffer counters, clear the flags,
  *     and make sure the driver is unthrottled. Called
  *     from n_tty_open() and n_tty_flush_buffer().
+ *
+ *     Locking: tty_read_lock for read fields.
  */
 static void reset_buffer_flags(struct tty_struct *tty)
 {
@@ -181,7 +191,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
  *     at hangup) or when the N_TTY line discipline internally has to
  *     clean the pending queue (for example some signals).
  *
- *     Locking: ctrl_lock
+ *     Locking: ctrl_lock, read_lock.
  */
 
 static void n_tty_flush_buffer(struct tty_struct *tty)
@@ -207,6 +217,8 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
  *
  *     Report the number of characters buffered to be delivered to user
  *     at this instant in time.
+ *
+ *     Locking: read_lock
  */
 
 static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
@@ -346,7 +358,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
  *     the simple cases normally found and helps to generate blocks of
  *     symbols for the console driver and thus improve performance.
  *
- *     Called from write_chan under the tty layer write lock. Relies
+ *     Called from n_tty_write under the tty layer write lock. Relies
  *     on lock_kernel for the tty->column state.
  */
 
@@ -410,6 +422,8 @@ break_out:
  *
  *     Echo user input back onto the screen. This must be called only when
  *     L_ECHO(tty) is true. Called from the driver receive_buf path.
+ *
+ *     Relies on BKL for tty column locking
  */
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
@@ -422,6 +436,12 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
                opost(c, tty);
 }
 
+/**
+ *     finsh_erasing           -       complete erase
+ *     @tty: tty doing the erase
+ *
+ *     Relies on BKL for tty column locking
+ */
 static inline void finish_erasing(struct tty_struct *tty)
 {
        if (tty->erasing) {
@@ -439,6 +459,8 @@ static inline void finish_erasing(struct tty_struct *tty)
  *     Perform erase and necessary output when an erase character is
  *     present in the stream from the driver layer. Handles the complexities
  *     of UTF-8 multibyte symbols.
+ *
+ *     Locking: read_lock for tty buffers, BKL for column/erasing state
  */
 
 static void eraser(unsigned char c, struct tty_struct *tty)
@@ -447,6 +469,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
        int head, seen_alnums, cnt;
        unsigned long flags;
 
+       /* FIXME: locking needed ? */
        if (tty->read_head == tty->canon_head) {
                /* opost('\a', tty); */         /* what do you think? */
                return;
@@ -481,6 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
        }
 
        seen_alnums = 0;
+       /* FIXME: Locking ?? */
        while (tty->read_head != tty->canon_head) {
                head = tty->read_head;
 
@@ -583,6 +607,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
  *     may caus terminal flushing to take place according to the termios
  *     settings and character used. Called from the driver receive_buf
  *     path so serialized.
+ *
+ *     Locking: ctrl_lock, read_lock (both via flush buffer)
  */
 
 static inline void isig(int sig, struct tty_struct *tty, int flush)
@@ -1007,12 +1033,26 @@ int is_ignored(int sig)
  *     and is protected from re-entry by the tty layer. The user is
  *     guaranteed that this function will not be re-entered or in progress
  *     when the ldisc is closed.
+ *
+ *     Locking: Caller holds tty->termios_mutex
  */
 
 static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
-       if (!tty)
-               return;
+       int canon_change = 1;
+       BUG_ON(!tty);
+
+       if (old)
+               canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
+       if (canon_change) {
+               memset(&tty->read_flags, 0, sizeof tty->read_flags);
+               tty->canon_head = tty->read_tail;
+               tty->canon_data = 0;
+               tty->erasing = 0;
+       }
+
+       if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+               wake_up_interruptible(&tty->read_wait);
 
        tty->icanon = (L_ICANON(tty) != 0);
        if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
@@ -1143,7 +1183,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
  *     @b: user data
  *     @nr: size of data
  *
- *     Helper function to speed up read_chan.  It is only called when
+ *     Helper function to speed up n_tty_read.  It is only called when
  *     ICANON is off; it copies characters straight from the tty queue to
  *     user space directly.  It can be profitably called twice; once to
  *     drain the space from the tail pointer to the (physical) end of the
@@ -1210,7 +1250,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
        if (file->f_op->write != redirected_tty_write &&
            current->signal->tty == tty) {
                if (!tty->pgrp)
-                       printk(KERN_ERR "read_chan: no tty->pgrp!\n");
+                       printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
                else if (task_pgrp(current) != tty->pgrp) {
                        if (is_ignored(SIGTTIN) ||
                            is_current_pgrp_orphaned())
@@ -1225,7 +1265,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
 
 
 /**
- *     read_chan               -       read function for tty
+ *     n_tty_read              -       read function for tty
  *     @tty: tty device
  *     @file: file object
  *     @buf: userspace buffer pointer
@@ -1239,7 +1279,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
  *     This code must be sure never to sleep through a hangup.
  */
 
-static ssize_t read_chan(struct tty_struct *tty, struct file *file,
+static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
                         unsigned char __user *buf, size_t nr)
 {
        unsigned char __user *b = buf;
@@ -1254,10 +1294,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
 
 do_it_again:
 
-       if (!tty->read_buf) {
-               printk(KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n");
-               return -EIO;
-       }
+       BUG_ON(!tty->read_buf);
 
        c = job_control(tty, file);
        if (c < 0)
@@ -1444,7 +1481,7 @@ do_it_again:
 }
 
 /**
- *     write_chan              -       write function for tty
+ *     n_tty_write             -       write function for tty
  *     @tty: tty device
  *     @file: file object
  *     @buf: userspace buffer pointer
@@ -1458,7 +1495,7 @@ do_it_again:
  *     This code must be sure never to sleep through a hangup.
  */
 
-static ssize_t write_chan(struct tty_struct *tty, struct file *file,
+static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
                          const unsigned char *buf, size_t nr)
 {
        const unsigned char *b = buf;
@@ -1532,7 +1569,7 @@ break_out:
 }
 
 /**
- *     normal_poll             -       poll method for N_TTY
+ *     n_tty_poll              -       poll method for N_TTY
  *     @tty: terminal device
  *     @file: file accessing it
  *     @wait: poll table
@@ -1545,7 +1582,7 @@ break_out:
  *     Called without the kernel lock held - fine
  */
 
-static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
+static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
                                                        poll_table *wait)
 {
        unsigned int mask = 0;
@@ -1573,6 +1610,44 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
        return mask;
 }
 
+static unsigned long inq_canon(struct tty_struct *tty)
+{
+       int nr, head, tail;
+
+       if (!tty->canon_data)
+               return 0;
+       head = tty->canon_head;
+       tail = tty->read_tail;
+       nr = (head - tail) & (N_TTY_BUF_SIZE-1);
+       /* Skip EOF-chars.. */
+       while (head != tail) {
+               if (test_bit(tail, tty->read_flags) &&
+                   tty->read_buf[tail] == __DISABLED_CHAR)
+                       nr--;
+               tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+       }
+       return nr;
+}
+
+static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       int retval;
+
+       switch (cmd) {
+       case TIOCOUTQ:
+               return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
+       case TIOCINQ:
+               /* FIXME: Locking */
+               retval = tty->read_cnt;
+               if (L_ICANON(tty))
+                       retval = inq_canon(tty);
+               return put_user(retval, (unsigned int __user *) arg);
+       default:
+               return n_tty_ioctl_helper(tty, file, cmd, arg);
+       }
+}
+
 struct tty_ldisc_ops tty_ldisc_N_TTY = {
        .magic           = TTY_LDISC_MAGIC,
        .name            = "n_tty",
@@ -1580,11 +1655,11 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
        .close           = n_tty_close,
        .flush_buffer    = n_tty_flush_buffer,
        .chars_in_buffer = n_tty_chars_in_buffer,
-       .read            = read_chan,
-       .write           = write_chan,
+       .read            = n_tty_read,
+       .write           = n_tty_write,
        .ioctl           = n_tty_ioctl,
        .set_termios     = n_tty_set_termios,
-       .poll            = normal_poll,
+       .poll            = n_tty_poll,
        .receive_buf     = n_tty_receive_buf,
        .write_wakeup    = n_tty_write_wakeup
 };
index 66a0f931c66ca91bf06b56e0b789edb8a0d68204..9a34a1935283370a837bd0c72fa5d05463ff2ae7 100644 (file)
@@ -1599,7 +1599,10 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
        return 0;
 }
 
-/* Called when the userspace process close the tty, /dev/noz*. */
+/* Called when the userspace process close the tty, /dev/noz*. Also
+   called immediately if ntty_open fails in which case tty->driver_data
+   will be NULL an we exit by the first return */
+
 static void ntty_close(struct tty_struct *tty, struct file *file)
 {
        struct nozomi *dc = get_dc_by_tty(tty);
index f070ae7bd91a1d905eab711a6ee8d013ae8f3eeb..dbb912574569ef49375866a5053e429bf6d38831 100644 (file)
@@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
+static int cm4000_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cfg,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
+{
+       if (!cfg->io.nwin)
+               return -ENODEV;
+
+       /* Get the IOaddr */
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       p_dev->io.NumPorts1 = cfg->io.win[0].len;
+       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+       if (!(cfg->io.flags & CISTPL_IO_8BIT))
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+       if (!(cfg->io.flags & CISTPL_IO_16BIT))
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+       p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int cm4000_config(struct pcmcia_device * link, int devno)
 {
        struct cm4000_dev *dev;
-       tuple_t tuple;
-       cisparse_t parse;
-       u_char buf[64];
-       int fail_fn, fail_rc;
-       int rc;
 
        /* read the config-tuples */
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-
-       link->io.BasePort2 = 0;
-       link->io.NumPorts2 = 0;
-       link->io.Attributes2 = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       for (rc = pcmcia_get_first_tuple(link, &tuple);
-            rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
-
-               rc = pcmcia_get_tuple_data(link, &tuple);
-               if (rc != CS_SUCCESS)
-                       continue;
-               rc = pcmcia_parse_tuple(link, &tuple, &parse);
-               if (rc != CS_SUCCESS)
-                       continue;
-
-               link->conf.ConfigIndex = parse.cftable_entry.index;
-
-               if (!parse.cftable_entry.io.nwin)
-                       continue;
-
-               /* Get the IOaddr */
-               link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-               link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-               link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-               if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-               if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-               link->io.IOAddrLines = parse.cftable_entry.io.flags
-                   & CISTPL_IO_LINES_MASK;
-
-               rc = pcmcia_request_io(link, &link->io);
-               if (rc == CS_SUCCESS)
-                       break;  /* we are done */
-       }
-       if (rc != CS_SUCCESS)
+       if (pcmcia_loop_config(link, cm4000_config_check, NULL))
                goto cs_release;
 
        link->conf.IntType = 00000002;
 
-       if ((fail_rc =
-            pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
-               fail_fn = RequestConfiguration;
+       if (pcmcia_request_configuration(link, &link->conf))
                goto cs_release;
-       }
 
        dev = link->priv;
        sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
@@ -1896,7 +1871,7 @@ static int cm4000_probe(struct pcmcia_device *link)
                return ret;
        }
 
-       device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
+       device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
 
        return 0;
 }
index 0b5934bef7a4301049f19c8d82393544742f4a84..4f0723b07974615f5177134b49deb671580e8813 100644 (file)
@@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link)
        return;
 }
 
-static int reader_config(struct pcmcia_device *link, int devno)
+static int cm4040_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cfg,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
 {
-       struct reader_dev *dev;
-       tuple_t tuple;
-       cisparse_t parse;
-       u_char buf[64];
-       int fail_fn, fail_rc;
        int rc;
+       if (!cfg->io.nwin)
+               return -ENODEV;
+
+       /* Get the IOaddr */
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       p_dev->io.NumPorts1 = cfg->io.win[0].len;
+       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+       if (!(cfg->io.flags & CISTPL_IO_8BIT))
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+       if (!(cfg->io.flags & CISTPL_IO_16BIT))
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+       p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+       rc = pcmcia_request_io(p_dev, &p_dev->io);
+       dev_printk(KERN_INFO, &handle_to_dev(p_dev),
+                  "pcmcia_request_io returned 0x%x\n", rc);
+       return rc;
+}
+
 
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
+static int reader_config(struct pcmcia_device *link, int devno)
+{
+       struct reader_dev *dev;
+       int fail_rc;
 
        link->io.BasePort2 = 0;
        link->io.NumPorts2 = 0;
        link->io.Attributes2 = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       for (rc = pcmcia_get_first_tuple(link, &tuple);
-            rc == CS_SUCCESS;
-            rc = pcmcia_get_next_tuple(link, &tuple)) {
-               rc = pcmcia_get_tuple_data(link, &tuple);
-               if (rc != CS_SUCCESS)
-                       continue;
-               rc = pcmcia_parse_tuple(link, &tuple, &parse);
-               if (rc != CS_SUCCESS)
-                       continue;
-
-               link->conf.ConfigIndex = parse.cftable_entry.index;
-
-               if (!parse.cftable_entry.io.nwin)
-                       continue;
-
-               link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-               link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-               link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-               if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-               if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-               link->io.IOAddrLines = parse.cftable_entry.io.flags
-                                               & CISTPL_IO_LINES_MASK;
-               rc = pcmcia_request_io(link, &link->io);
-
-               dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
-               if (rc == CS_SUCCESS)
-                       break;
-               else
-                       dev_printk(KERN_INFO, &handle_to_dev(link),
-                                  "pcmcia_request_io failed 0x%x\n", rc);
-       }
-       if (rc != CS_SUCCESS)
+
+       if (pcmcia_loop_config(link, cm4040_config_check, NULL))
                goto cs_release;
 
        link->conf.IntType = 00000002;
 
-       if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
-                                                               !=CS_SUCCESS) {
-               fail_fn = RequestConfiguration;
+       fail_rc = pcmcia_request_configuration(link, &link->conf);
+       if (fail_rc != 0) {
                dev_printk(KERN_INFO, &handle_to_dev(link),
                           "pcmcia_request_configuration failed 0x%x\n",
                           fail_rc);
@@ -653,8 +637,7 @@ static int reader_probe(struct pcmcia_device *link)
                return ret;
        }
 
-       device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
-                             "cmx%d", i);
+       device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i);
 
        return 0;
 }
index 5eca7a99afe6c3daf1c793f4c0990e5125a72862..5216fce0c62d57ce6d2947750ac7dc22f1b82f0e 100644 (file)
@@ -65,9 +65,9 @@ static void signalled_reboot_work(struct work_struct *work_reboot)
        struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
                        work_reboot);
        struct pcmcia_device *link = ipw->link;
-       int ret = pccard_reset_card(link->socket);
+       int ret = pcmcia_reset_card(link->socket);
 
-       if (ret != CS_SUCCESS)
+       if (ret != 0)
                cs_error(link, ResetCard, ret);
 }
 
@@ -83,7 +83,6 @@ static int config_ipwireless(struct ipw_dev *ipw)
 {
        struct pcmcia_device *link = ipw->link;
        int ret;
-       config_info_t conf;
        tuple_t tuple;
        unsigned short buf[64];
        cisparse_t parse;
@@ -105,7 +104,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
        while (ret == 0) {
                ret = pcmcia_get_tuple_data(link, &tuple);
 
-               if (ret != CS_SUCCESS) {
+               if (ret != 0) {
                        cs_error(link, GetTupleData, ret);
                        goto exit0;
                }
@@ -116,21 +115,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_get_first_tuple(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetFirstTuple, ret);
                goto exit0;
        }
 
        ret = pcmcia_get_tuple_data(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetTupleData, ret);
                goto exit0;
        }
 
-       ret = pcmcia_parse_tuple(link, &tuple, &parse);
+       ret = pcmcia_parse_tuple(&tuple, &parse);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, ParseTuple, ret);
                goto exit0;
        }
@@ -152,21 +151,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_get_first_tuple(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetFirstTuple, ret);
                goto exit0;
        }
 
        ret = pcmcia_get_tuple_data(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetTupleData, ret);
                goto exit0;
        }
 
-       ret = pcmcia_parse_tuple(link, &tuple, &parse);
+       ret = pcmcia_parse_tuple(&tuple, &parse);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetTupleData, ret);
                goto exit0;
        }
@@ -181,7 +180,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_request_io(link, &link->io);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, RequestIO, ret);
                goto exit0;
        }
@@ -195,21 +194,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_get_first_tuple(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetFirstTuple, ret);
                goto exit1;
        }
 
        ret = pcmcia_get_tuple_data(link, &tuple);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, GetTupleData, ret);
                goto exit1;
        }
 
-       ret = pcmcia_parse_tuple(link, &tuple, &parse);
+       ret = pcmcia_parse_tuple(&tuple, &parse);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, ParseTuple, ret);
                goto exit1;
        }
@@ -227,7 +226,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
                ret = pcmcia_request_window(&link, &ipw->request_common_memory,
                                &ipw->handle_common_memory);
 
-               if (ret != CS_SUCCESS) {
+               if (ret != 0) {
                        cs_error(link, RequestWindow, ret);
                        goto exit1;
                }
@@ -239,7 +238,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
                ret = pcmcia_map_mem_page(ipw->handle_common_memory,
                                &memreq_common_memory);
 
-               if (ret != CS_SUCCESS) {
+               if (ret != 0) {
                        cs_error(link, MapMemPage, ret);
                        goto exit1;
                }
@@ -261,7 +260,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
                ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
                                &ipw->handle_attr_memory);
 
-               if (ret != CS_SUCCESS) {
+               if (ret != 0) {
                        cs_error(link, RequestWindow, ret);
                        goto exit2;
                }
@@ -272,7 +271,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
                ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
                                &memreq_attr_memory);
 
-               if (ret != CS_SUCCESS) {
+               if (ret != 0) {
                        cs_error(link, MapMemPage, ret);
                        goto exit2;
                }
@@ -292,20 +291,11 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
        ret = pcmcia_request_irq(link, &link->irq);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, RequestIRQ, ret);
                goto exit3;
        }
 
-       /* Look up current Vcc */
-
-       ret = pcmcia_get_configuration_info(link, &conf);
-
-       if (ret != CS_SUCCESS) {
-               cs_error(link, GetConfigurationInfo, ret);
-               goto exit4;
-       }
-
        printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
                        ipw->is_v2_card ? "V2/V3" : "V1");
        printk(KERN_INFO IPWIRELESS_PCCARD_NAME
@@ -341,7 +331,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
         */
        ret = pcmcia_request_configuration(link, &link->conf);
 
-       if (ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, RequestConfiguration, ret);
                goto exit4;
        }
index 3a23e7694d55f2c61374139117c23dc20c52052b..569f2f7743a78ddc80f4e7714c6456506b8a4995 100644 (file)
@@ -276,6 +276,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)
        struct ipw_tty *tty = linux_tty->driver_data;
        int room;
 
+       /* FIXME: Exactly how is the tty object locked here .. */
        if (!tty)
                return -ENODEV;
 
@@ -397,6 +398,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set,
 static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
 {
        struct ipw_tty *tty = linux_tty->driver_data;
+       /* FIXME: Exactly how is the tty object locked here .. */
 
        if (!tty)
                return -ENODEV;
@@ -412,6 +414,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
             unsigned int set, unsigned int clear)
 {
        struct ipw_tty *tty = linux_tty->driver_data;
+       /* FIXME: Exactly how is the tty object locked here .. */
 
        if (!tty)
                return -ENODEV;
@@ -433,6 +436,8 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
        if (!tty->open_count)
                return -EINVAL;
 
+       /* FIXME: Exactly how is the tty object locked here .. */
+
        switch (cmd) {
        case TIOCGSERIAL:
                return ipwireless_get_serial_info(tty, (void __user *) arg);
@@ -467,13 +472,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
                        }
                        return 0;
 
-               case TCGETS:
-               case TCGETA:
-                       return n_tty_ioctl(linux_tty, file, cmd, arg);
-
-               case TCFLSH:
-                       return n_tty_ioctl(linux_tty, file, cmd, arg);
-
                case FIONREAD:
                        {
                                int val = 0;
@@ -482,10 +480,11 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
                                        return -EFAULT;
                        }
                        return 0;
+               case TCFLSH:
+                       return tty_perform_flush(linux_tty, arg);
                }
        }
-
-       return -ENOIOCTLCMD;
+       return tty_mode_ioctl(linux_tty, file, cmd , arg);
 }
 
 static int add_tty(dev_node_t *nodesp, int j,
@@ -588,6 +587,8 @@ void ipwireless_tty_free(struct ipw_tty *tty)
                                tty_hangup(ttyj->linux_tty);
                                /* Wait till the tty_hangup has completed */
                                flush_scheduled_work();
+                               /* FIXME: Exactly how is the tty object locked here
+                                  against a parallel ioctl etc */
                                mutex_lock(&ttyj->ipw_tty_mutex);
                        }
                        while (ttyj->open_count)
index c240562c218b735b985883528458272733294eff..9a626e50b793ba65ce21d269d64a3536546e970c 100644 (file)
@@ -601,7 +601,7 @@ static int mgslpc_config(struct pcmcia_device *link)
 
     cfg = &(parse.cftable_entry);
     CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-    CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
+    CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
 
     if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
     if (cfg->index == 0)
index bee39fdfba738de8a11429a1d2c57caa7b99cc26..c84c34fb123116d0b43b0ec491aacce84342f5bc 100644 (file)
@@ -760,9 +760,8 @@ static const struct file_operations pp_fops = {
 
 static void pp_attach(struct parport *port)
 {
-       device_create_drvdata(ppdev_class, port->dev,
-                             MKDEV(PP_MAJOR, port->number),
-                             NULL, "parport%d", port->number);
+       device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
+                     NULL, "parport%d", port->number);
 }
 
 static void pp_detach(struct parport *port)
index 76b27932d229df31d3ff24f7d09e83afecdb278a..6d4582712b1fa6ae1a1c40fbb792a3f863681657 100644 (file)
@@ -8,10 +8,12 @@
  *  Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
  *      waiting writers -- Sapan Bhatia <sapan@corewars.org>
  *
- *
+ *  When reading this code see also fs/devpts. In particular note that the
+ *  driver_data field is used by the devpts side as a binding to the devpts
+ *  inode.
  */
 
-#include <linux/module.h>      /* For EXPORT_SYMBOL */
+#include <linux/module.h>
 
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/sysctl.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/devpts_fs.h>
 
+#include <asm/system.h>
+
 /* These are global because they are accessed in tty_io.c */
 #ifdef CONFIG_UNIX98_PTYS
 struct tty_driver *ptm_driver;
 static struct tty_driver *pts_driver;
 #endif
 
-static void pty_close(struct tty_struct * tty, struct file * filp)
+static void pty_close(struct tty_struct *tty, struct file *filp)
 {
-       if (!tty)
-               return;
-       if (tty->driver->subtype == PTY_TYPE_MASTER) {
-               if (tty->count > 1)
-                       printk("master pty_close: count = %d!!\n", tty->count);
-       } else {
+       BUG_ON(!tty);
+       if (tty->driver->subtype == PTY_TYPE_MASTER)
+               WARN_ON(tty->count > 1);
+       else {
                if (tty->count > 2)
                        return;
        }
@@ -59,7 +60,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
                set_bit(TTY_OTHER_CLOSED, &tty->flags);
 #ifdef CONFIG_UNIX98_PTYS
                if (tty->driver == ptm_driver)
-                       devpts_pty_kill(tty->index);
+                       devpts_pty_kill(tty->link);
 #endif
                tty_vhangup(tty->link);
        }
@@ -69,13 +70,13 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
  * The unthrottle routine is called by the line discipline to signal
  * that it can receive more characters.  For PTY's, the TTY_THROTTLED
  * flag is always set, to force the line discipline to always call the
- * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE 
+ * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
  * characters in the queue.  This is necessary since each time this
  * happens, we need to wake up any sleeping processes that could be
  * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
  * for the pty buffer to be drained.
  */
-static void pty_unthrottle(struct tty_struct * tty)
+static void pty_unthrottle(struct tty_struct *tty)
 {
        struct tty_struct *o_tty = tty->link;
 
@@ -87,7 +88,7 @@ static void pty_unthrottle(struct tty_struct * tty)
 }
 
 /*
- * WSH 05/24/97: modified to 
+ * WSH 05/24/97: modified to
  *   (1) use space in tty->flip instead of a shared temp buffer
  *      The flip buffers aren't being used for a pty, so there's lots
  *      of space available.  The buffer is protected by a per-pty
@@ -100,7 +101,8 @@ static void pty_unthrottle(struct tty_struct * tty)
  * not our partners. We can't just take the other one blindly without
  * risking deadlocks.
  */
-static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count)
+static int pty_write(struct tty_struct *tty, const unsigned char *buf,
+                                                               int count)
 {
        struct tty_struct *to = tty->link;
        int     c;
@@ -112,7 +114,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun
        if (c > count)
                c = count;
        to->ldisc.ops->receive_buf(to, buf, NULL, c);
-       
+
        return c;
 }
 
@@ -128,17 +130,17 @@ static int pty_write_room(struct tty_struct *tty)
 
 /*
  *     WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
- *     The chars_in_buffer() value is used by the ldisc select() function 
+ *     The chars_in_buffer() value is used by the ldisc select() function
  *     to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
  *     The pty driver chars_in_buffer() Master/Slave must behave differently:
  *
  *      The Master side needs to allow typed-ahead commands to accumulate
  *      while being canonicalized, so we report "our buffer" as empty until
  *     some threshold is reached, and then report the count. (Any count >
- *     WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock 
- *     the count returned must be 0 if no canonical data is available to be 
+ *     WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock
+ *     the count returned must be 0 if no canonical data is available to be
  *     read. (The N_TTY ldisc.chars_in_buffer now knows this.)
- *  
+ *
  *     The Slave side passes all characters in raw mode to the Master side's
  *     buffer where they can be read immediately, so in this case we can
  *     return the true count in the buffer.
@@ -155,21 +157,22 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
        /* The ldisc must report 0 if no characters available to be read */
        count = to->ldisc.ops->chars_in_buffer(to);
 
-       if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
+       if (tty->driver->subtype == PTY_TYPE_SLAVE)
+               return count;
 
-       /* Master side driver ... if the other side's read buffer is less than 
+       /* Master side driver ... if the other side's read buffer is less than
         * half full, return 0 to allow writers to proceed; otherwise return
-        * the count.  This leaves a comfortable margin to avoid overflow, 
+        * the count.  This leaves a comfortable margin to avoid overflow,
         * and still allows half a buffer's worth of typed-ahead commands.
         */
-       return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
+       return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
 }
 
 /* Set the lock flag on a pty */
-static int pty_set_lock(struct tty_struct *tty, int __user * arg)
+static int pty_set_lock(struct tty_struct *tty, int __user *arg)
 {
        int val;
-       if (get_user(val,arg))
+       if (get_user(val, arg))
                return -EFAULT;
        if (val)
                set_bit(TTY_PTY_LOCK, &tty->flags);
@@ -182,13 +185,13 @@ static void pty_flush_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
        unsigned long flags;
-       
+
        if (!to)
                return;
-       
+
        if (to->ldisc.ops->flush_buffer)
                to->ldisc.ops->flush_buffer(to);
-       
+
        if (to->packet) {
                spin_lock_irqsave(&tty->ctrl_lock, flags);
                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
@@ -197,7 +200,7 @@ static void pty_flush_buffer(struct tty_struct *tty)
        }
 }
 
-static int pty_open(struct tty_struct *tty, struct file * filp)
+static int pty_open(struct tty_struct *tty, struct file *filp)
 {
        int     retval = -ENODEV;
 
@@ -220,13 +223,65 @@ out:
        return retval;
 }
 
-static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+static void pty_set_termios(struct tty_struct *tty,
+                                       struct ktermios *old_termios)
+{
+       tty->termios->c_cflag &= ~(CSIZE | PARENB);
+       tty->termios->c_cflag |= (CS8 | CREAD);
+}
+
+static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
-        tty->termios->c_cflag &= ~(CSIZE | PARENB);
-        tty->termios->c_cflag |= (CS8 | CREAD);
+       struct tty_struct *o_tty;
+       int idx = tty->index;
+       int retval;
+
+       o_tty = alloc_tty_struct();
+       if (!o_tty)
+               return -ENOMEM;
+       if (!try_module_get(driver->other->owner)) {
+               /* This cannot in fact currently happen */
+               free_tty_struct(o_tty);
+               return -ENOMEM;
+       }
+       initialize_tty_struct(o_tty, driver->other, idx);
+
+       /* We always use new tty termios data so we can do this
+          the easy way .. */
+       retval = tty_init_termios(tty);
+       if (retval)
+               goto free_mem_out;
+
+       retval = tty_init_termios(o_tty);
+       if (retval) {
+               tty_free_termios(tty);
+               goto free_mem_out;
+       }
+
+       /*
+        * Everything allocated ... set up the o_tty structure.
+        */
+       driver->other->ttys[idx] = o_tty;
+       tty_driver_kref_get(driver->other);
+       if (driver->subtype == PTY_TYPE_MASTER)
+               o_tty->count++;
+       /* Establish the links in both directions */
+       tty->link   = o_tty;
+       o_tty->link = tty;
+
+       tty_driver_kref_get(driver);
+       tty->count++;
+       driver->ttys[idx] = tty;
+       return 0;
+free_mem_out:
+       module_put(o_tty->driver->owner);
+       free_tty_struct(o_tty);
+       return -ENOMEM;
 }
 
+
 static const struct tty_operations pty_ops = {
+       .install = pty_install,
        .open = pty_open,
        .close = pty_close,
        .write = pty_write,
@@ -329,8 +384,11 @@ static inline void legacy_pty_init(void) { }
  * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
  */
 int pty_limit = NR_UNIX98_PTY_DEFAULT;
-static int pty_limit_min = 0;
+static int pty_limit_min;
 static int pty_limit_max = NR_UNIX98_PTY_MAX;
+static int pty_count;
+
+static struct cdev ptmx_cdev;
 
 static struct ctl_table pty_table[] = {
        {
@@ -348,6 +406,7 @@ static struct ctl_table pty_table[] = {
                .procname       = "nr",
                .maxlen         = sizeof(int),
                .mode           = 0444,
+               .data           = &pty_count,
                .proc_handler   = &proc_dointvec,
        }, {
                .ctl_name       = 0
@@ -388,7 +447,127 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
        return -ENOIOCTLCMD;
 }
 
+/**
+ *     ptm_unix98_lookup       -       find a pty master
+ *     @driver: ptm driver
+ *     @idx: tty index
+ *
+ *     Look up a pty master device. Called under the tty_mutex for now.
+ *     This provides our locking.
+ */
+
+static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
+               struct inode *ptm_inode, int idx)
+{
+       struct tty_struct *tty = devpts_get_tty(ptm_inode, idx);
+       if (tty)
+               tty = tty->link;
+       return tty;
+}
+
+/**
+ *     pts_unix98_lookup       -       find a pty slave
+ *     @driver: pts driver
+ *     @idx: tty index
+ *
+ *     Look up a pty master device. Called under the tty_mutex for now.
+ *     This provides our locking.
+ */
+
+static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
+               struct inode *pts_inode, int idx)
+{
+       struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
+       /* Master must be open before slave */
+       if (!tty)
+               return ERR_PTR(-EIO);
+       return tty;
+}
+
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+       /* We have our own method as we don't use the tty index */
+       kfree(tty->termios);
+}
+
+/* We have no need to install and remove our tty objects as devpts does all
+   the work for us */
+
+static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+       struct tty_struct *o_tty;
+       int idx = tty->index;
+
+       o_tty = alloc_tty_struct();
+       if (!o_tty)
+               return -ENOMEM;
+       if (!try_module_get(driver->other->owner)) {
+               /* This cannot in fact currently happen */
+               free_tty_struct(o_tty);
+               return -ENOMEM;
+       }
+       initialize_tty_struct(o_tty, driver->other, idx);
+
+       tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+       if (tty->termios == NULL)
+               goto free_mem_out;
+       *tty->termios = driver->init_termios;
+       tty->termios_locked = tty->termios + 1;
+
+       o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+       if (o_tty->termios == NULL)
+               goto free_mem_out;
+       *o_tty->termios = driver->other->init_termios;
+       o_tty->termios_locked = o_tty->termios + 1;
+
+       tty_driver_kref_get(driver->other);
+       if (driver->subtype == PTY_TYPE_MASTER)
+               o_tty->count++;
+       /* Establish the links in both directions */
+       tty->link   = o_tty;
+       o_tty->link = tty;
+       /*
+        * All structures have been allocated, so now we install them.
+        * Failures after this point use release_tty to clean up, so
+        * there's no need to null out the local pointers.
+        */
+       tty_driver_kref_get(driver);
+       tty->count++;
+       pty_count++;
+       return 0;
+free_mem_out:
+       kfree(o_tty->termios);
+       module_put(o_tty->driver->owner);
+       free_tty_struct(o_tty);
+       kfree(tty->termios);
+       return -ENOMEM;
+}
+
+static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+       pty_count--;
+}
+
+static const struct tty_operations ptm_unix98_ops = {
+       .lookup = ptm_unix98_lookup,
+       .install = pty_unix98_install,
+       .remove = pty_unix98_remove,
+       .open = pty_open,
+       .close = pty_close,
+       .write = pty_write,
+       .write_room = pty_write_room,
+       .flush_buffer = pty_flush_buffer,
+       .chars_in_buffer = pty_chars_in_buffer,
+       .unthrottle = pty_unthrottle,
+       .set_termios = pty_set_termios,
+       .ioctl = pty_unix98_ioctl,
+       .shutdown = pty_unix98_shutdown
+};
+
 static const struct tty_operations pty_unix98_ops = {
+       .lookup = pts_unix98_lookup,
+       .install = pty_unix98_install,
+       .remove = pty_unix98_remove,
        .open = pty_open,
        .close = pty_close,
        .write = pty_write,
@@ -397,9 +576,73 @@ static const struct tty_operations pty_unix98_ops = {
        .chars_in_buffer = pty_chars_in_buffer,
        .unthrottle = pty_unthrottle,
        .set_termios = pty_set_termios,
-       .ioctl = pty_unix98_ioctl
+       .shutdown = pty_unix98_shutdown
 };
 
+/**
+ *     ptmx_open               -       open a unix 98 pty master
+ *     @inode: inode of device file
+ *     @filp: file pointer to tty
+ *
+ *     Allocate a unix98 pty master device from the ptmx driver.
+ *
+ *     Locking: tty_mutex protects the init_dev work. tty->count should
+ *             protect the rest.
+ *             allocated_ptys_lock handles the list of free pty numbers
+ */
+
+static int __ptmx_open(struct inode *inode, struct file *filp)
+{
+       struct tty_struct *tty;
+       int retval;
+       int index;
+
+       nonseekable_open(inode, filp);
+
+       /* find a device that is not in use. */
+       index = devpts_new_index(inode);
+       if (index < 0)
+               return index;
+
+       mutex_lock(&tty_mutex);
+       tty = tty_init_dev(ptm_driver, index, 1);
+       mutex_unlock(&tty_mutex);
+
+       if (IS_ERR(tty)) {
+               retval = PTR_ERR(tty);
+               goto out;
+       }
+
+       set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+       filp->private_data = tty;
+       file_move(filp, &tty->tty_files);
+
+       retval = devpts_pty_new(inode, tty->link);
+       if (retval)
+               goto out1;
+
+       retval = ptm_driver->ops->open(tty, filp);
+       if (!retval)
+               return 0;
+out1:
+       tty_release_dev(filp);
+       return retval;
+out:
+       devpts_kill_index(inode, index);
+       return retval;
+}
+
+static int ptmx_open(struct inode *inode, struct file *filp)
+{
+       int ret;
+
+       lock_kernel();
+       ret = __ptmx_open(inode, filp);
+       unlock_kernel();
+       return ret;
+}
+
+static struct file_operations ptmx_fops;
 
 static void __init unix98_pty_init(void)
 {
@@ -427,7 +670,7 @@ static void __init unix98_pty_init(void)
        ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
        ptm_driver->other = pts_driver;
-       tty_set_operations(ptm_driver, &pty_unix98_ops);
+       tty_set_operations(ptm_driver, &ptm_unix98_ops);
 
        pts_driver->owner = THIS_MODULE;
        pts_driver->driver_name = "pty_slave";
@@ -443,16 +686,26 @@ static void __init unix98_pty_init(void)
        pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
        pts_driver->other = ptm_driver;
-       tty_set_operations(pts_driver, &pty_ops);
-       
+       tty_set_operations(pts_driver, &pty_unix98_ops);
+
        if (tty_register_driver(ptm_driver))
                panic("Couldn't register Unix98 ptm driver");
        if (tty_register_driver(pts_driver))
                panic("Couldn't register Unix98 pts driver");
 
-       pty_table[1].data = &ptm_driver->refcount;
        register_sysctl_table(pty_root_table);
+
+       /* Now create the /dev/ptmx special device */
+       tty_default_fops(&ptmx_fops);
+       ptmx_fops.open = ptmx_open;
+
+       cdev_init(&ptmx_cdev, &ptmx_fops);
+       if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
+           register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
+               panic("Couldn't register /dev/ptmx driver\n");
+       device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 }
+
 #else
 static inline void unix98_pty_init(void) { }
 #endif
index 6af435b89867a7bb99689871624989dd8de14e61..c8752eaad483eea52b4dbc8c8af87eaf931ad189 100644 (file)
@@ -1205,7 +1205,7 @@ static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
        return proc_dostring(&fake_table, write, filp, buffer, lenp, ppos);
 }
 
-static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
+static int uuid_strategy(ctl_table *table,
                         void __user *oldval, size_t __user *oldlenp,
                         void __user *newval, size_t newlen)
 {
index 47b8cf281d4a79766c0717dec1ea4380d2bf9717..e139372d0e6913f1d09a385a8d60617b3e25e089 100644 (file)
@@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
 static void bind_device(struct raw_config_request *rq)
 {
        device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-       device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
-                             NULL, "raw%d", rq->raw_minor);
+       device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
+                     "raw%d", rq->raw_minor);
 }
 
 /*
@@ -283,8 +283,7 @@ static int __init raw_init(void)
                ret = PTR_ERR(raw_class);
                goto error_region;
        }
-       device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
-                             "rawctl");
+       device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
        return 0;
 
index b47710c178855399395b40b41edbc140981df683..17683de95717e2a2b5eb763fa345ce418fed6181 100644 (file)
@@ -96,7 +96,7 @@ static unsigned long rtc_port;
 static int rtc_irq;
 #endif
 
-#ifdef CONFIG_HPET_RTC_IRQ
+#ifdef CONFIG_HPET_EMULATE_RTC
 #undef RTC_IRQ
 #endif
 
index 3ce60df14c0a623f5aff950148f034938988a5f9..32b74de18f5face7e590ac25fc955aef373c6247 100644 (file)
@@ -444,8 +444,8 @@ scdrv_init(void)
                                continue;
                        }
 
-                       device_create_drvdata(snsc_class, NULL, dev, NULL,
-                                             "%s", devname);
+                       device_create(snsc_class, NULL, dev, NULL,
+                                     "%s", devname);
 
                        ia64_sn_irtr_intr_enable(scd->scd_nasid,
                                                 0 /*ignored */ ,
index 19db1eb87c26fa22eb9e4f17d8b6ec384e6c021b..963b03fb29e5583aa45e83f056c6cf1ff412ba43 100644 (file)
@@ -405,9 +405,9 @@ static unsigned int stl_baudrates[] = {
 
 static int     stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
 static int     stl_brdinit(struct stlbrd *brdp);
-static int     stl_getportstats(struct stlport *portp, comstats_t __user *cp);
+static int     stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
 static int     stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-static int     stl_waitcarrier(struct stlport *portp, struct file *filp);
+static int     stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
 
 /*
  *     CD1400 uart specific handling functions.
@@ -612,8 +612,9 @@ static struct class *stallion_class;
 static void stl_cd_change(struct stlport *portp)
 {
        unsigned int oldsigs = portp->sigs;
+       struct tty_struct *tty = tty_port_tty_get(&portp->port);
 
-       if (!portp->port.tty)
+       if (!tty)
                return;
 
        portp->sigs = stl_getsignals(portp);
@@ -623,7 +624,8 @@ static void stl_cd_change(struct stlport *portp)
 
        if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
                if (portp->port.flags & ASYNC_CHECK_CD)
-                       tty_hangup(portp->port.tty);
+                       tty_hangup(tty);
+       tty_kref_put(tty);
 }
 
 /*
@@ -734,7 +736,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  *     On the first open of the device setup the port hardware, and
  *     initialize the per port data structure.
  */
-       portp->port.tty = tty;
+       tty_port_tty_set(&portp->port, tty);
        tty->driver_data = portp;
        portp->port.count++;
 
@@ -774,7 +776,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  *     then also we might have to wait for carrier.
  */
        if (!(filp->f_flags & O_NONBLOCK))
-               if ((rc = stl_waitcarrier(portp, filp)) != 0)
+               if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
                        return rc;
 
        portp->port.flags |= ASYNC_NORMAL_ACTIVE;
@@ -789,7 +791,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  *     maybe because if we are clocal then we don't need to wait...
  */
 
-static int stl_waitcarrier(struct stlport *portp, struct file *filp)
+static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
+                                                       struct file *filp)
 {
        unsigned long   flags;
        int             rc, doclocal;
@@ -801,7 +804,7 @@ static int stl_waitcarrier(struct stlport *portp, struct file *filp)
 
        spin_lock_irqsave(&stallion_lock, flags);
 
-       if (portp->port.tty->termios->c_cflag & CLOCAL)
+       if (tty->termios->c_cflag & CLOCAL)
                doclocal++;
 
        portp->openwaitcnt++;
@@ -846,8 +849,6 @@ static void stl_flushbuffer(struct tty_struct *tty)
 
        pr_debug("stl_flushbuffer(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -865,8 +866,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
 
        pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -949,7 +948,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
-       portp->port.tty = NULL;
+       tty_port_tty_set(&portp->port, NULL);
 
        if (portp->openwaitcnt) {
                if (portp->close_delay)
@@ -1033,8 +1032,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch)
 
        pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == NULL)
-               return -EINVAL;
        portp = tty->driver_data;
        if (portp == NULL)
                return -EINVAL;
@@ -1070,8 +1067,6 @@ static void stl_flushchars(struct tty_struct *tty)
 
        pr_debug("stl_flushchars(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1090,8 +1085,6 @@ static int stl_writeroom(struct tty_struct *tty)
 
        pr_debug("stl_writeroom(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return 0;
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
@@ -1122,8 +1115,6 @@ static int stl_charsinbuffer(struct tty_struct *tty)
 
        pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return 0;
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
@@ -1183,8 +1174,9 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
  *     just quietly ignore any requests to change irq, etc.
  */
 
-static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
+static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
 {
+       struct stlport *        portp = tty->driver_data;
        struct serial_struct    sio;
 
        pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
@@ -1205,7 +1197,7 @@ static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
        portp->close_delay = sio.close_delay;
        portp->closing_wait = sio.closing_wait;
        portp->custom_divisor = sio.custom_divisor;
-       stl_setport(portp, portp->port.tty->termios);
+       stl_setport(portp, tty->termios);
        return 0;
 }
 
@@ -1215,8 +1207,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct stlport  *portp;
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1232,8 +1222,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
        struct stlport  *portp;
        int rts = -1, dtr = -1;
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1262,8 +1250,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
        pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
                        arg);
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1282,10 +1268,10 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                rc = stl_getserial(portp, argp);
                break;
        case TIOCSSERIAL:
-               rc = stl_setserial(portp, argp);
+               rc = stl_setserial(tty, argp);
                break;
        case COM_GETPORTSTATS:
-               rc = stl_getportstats(portp, argp);
+               rc = stl_getportstats(tty, portp, argp);
                break;
        case COM_CLRPORTSTATS:
                rc = stl_clrportstats(portp, argp);
@@ -1317,8 +1303,6 @@ static void stl_start(struct tty_struct *tty)
 
        pr_debug("stl_start(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1334,8 +1318,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
 
        pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1369,8 +1351,6 @@ static void stl_throttle(struct tty_struct *tty)
 
        pr_debug("stl_throttle(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1389,8 +1369,6 @@ static void stl_unthrottle(struct tty_struct *tty)
 
        pr_debug("stl_unthrottle(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1410,8 +1388,6 @@ static void stl_stop(struct tty_struct *tty)
 
        pr_debug("stl_stop(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1432,8 +1408,6 @@ static void stl_hangup(struct tty_struct *tty)
 
        pr_debug("stl_hangup(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1452,7 +1426,7 @@ static void stl_hangup(struct tty_struct *tty)
                portp->tx.head = NULL;
                portp->tx.tail = NULL;
        }
-       portp->port.tty = NULL;
+       tty_port_tty_set(&portp->port, NULL);
        portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
        portp->port.count = 0;
        wake_up_interruptible(&portp->port.open_wait);
@@ -1466,8 +1440,6 @@ static int stl_breakctl(struct tty_struct *tty, int state)
 
        pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
 
-       if (tty == NULL)
-               return -EINVAL;
        portp = tty->driver_data;
        if (portp == NULL)
                return -EINVAL;
@@ -1484,8 +1456,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
 
        pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1805,7 +1775,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
                                "(size=%Zd)\n", sizeof(struct stlport));
                        break;
                }
-
+               tty_port_init(&portp->port);
                portp->magic = STL_PORTMAGIC;
                portp->portnr = i;
                portp->brdnr = panelp->brdnr;
@@ -1832,6 +1802,7 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
        struct stlpanel *panelp;
        struct stlport *portp;
        unsigned int j, k;
+       struct tty_struct *tty;
 
        for (j = 0; j < STL_MAXPANELS; j++) {
                panelp = brdp->panels[j];
@@ -1841,8 +1812,11 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
                        portp = panelp->ports[k];
                        if (portp == NULL)
                                continue;
-                       if (portp->port.tty != NULL)
-                               stl_hangup(portp->port.tty);
+                       tty = tty_port_tty_get(&portp->port);
+                       if (tty != NULL) {
+                               stl_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                        kfree(portp->tx.buf);
                        kfree(portp);
                }
@@ -2498,7 +2472,7 @@ static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
  *     what port to get stats for (used through board control device).
  */
 
-static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
+static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
 {
        comstats_t      stl_comstats;
        unsigned char   *head, *tail;
@@ -2525,18 +2499,17 @@ static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
        portp->stats.rxbuffered = 0;
 
        spin_lock_irqsave(&stallion_lock, flags);
-       if (portp->port.tty != NULL)
-               if (portp->port.tty->driver_data == portp) {
-                       portp->stats.ttystate = portp->port.tty->flags;
-                       /* No longer available as a statistic */
-                       portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
-                       if (portp->port.tty->termios != NULL) {
-                               portp->stats.cflags = portp->port.tty->termios->c_cflag;
-                               portp->stats.iflags = portp->port.tty->termios->c_iflag;
-                               portp->stats.oflags = portp->port.tty->termios->c_oflag;
-                               portp->stats.lflags = portp->port.tty->termios->c_lflag;
-                       }
+       if (tty != NULL && portp->port.tty == tty) {
+               portp->stats.ttystate = tty->flags;
+               /* No longer available as a statistic */
+               portp->stats.rxbuffered = 1; /*tty->flip.count; */
+               if (tty->termios != NULL) {
+                       portp->stats.cflags = tty->termios->c_cflag;
+                       portp->stats.iflags = tty->termios->c_iflag;
+                       portp->stats.oflags = tty->termios->c_oflag;
+                       portp->stats.lflags = tty->termios->c_lflag;
                }
+       }
        spin_unlock_irqrestore(&stallion_lock, flags);
 
        head = portp->tx.head;
@@ -2640,7 +2613,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
 
        switch (cmd) {
        case COM_GETPORTSTATS:
-               rc = stl_getportstats(NULL, argp);
+               rc = stl_getportstats(NULL, NULL, argp);
                break;
        case COM_CLRPORTSTATS:
                rc = stl_clrportstats(NULL, argp);
@@ -3243,7 +3216,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -3288,6 +3261,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
 
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -3305,7 +3279,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -3325,6 +3299,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
        }
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -3478,6 +3453,7 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
        int             len, stlen;
        char            *head, *tail;
        unsigned char   ioack, srer;
+       struct tty_struct *tty;
 
        pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
 
@@ -3504,8 +3480,11 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
        if ((len == 0) || ((len < STL_TXBUFLOW) &&
            (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
                set_bit(ASYI_TXLOW, &portp->istate);
-               if (portp->port.tty)
-                       tty_wakeup(portp->port.tty);
+               tty = tty_port_tty_get(&portp->port);
+               if (tty) {
+                       tty_wakeup(tty);
+                       tty_kref_put(tty);
+               }
        }
 
        if (len == 0) {
@@ -3569,7 +3548,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
                return;
        }
        portp = panelp->ports[(ioack >> 3)];
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
 
        if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
                outb((RDCR + portp->uartaddr), ioaddr);
@@ -3633,10 +3612,12 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
                }
        } else {
                printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
+               tty_kref_put(tty);
                return;
        }
 
 stl_rxalldone:
+       tty_kref_put(tty);
        outb((EOSRR + portp->uartaddr), ioaddr);
        outb(0, (ioaddr + EREG_DATA));
 }
@@ -4175,7 +4156,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -4226,6 +4207,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
 
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4244,7 +4226,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -4269,6 +4251,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
        }
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4408,6 +4391,7 @@ static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
 
 static void stl_sc26198txisr(struct stlport *portp)
 {
+       struct tty_struct *tty;
        unsigned int    ioaddr;
        unsigned char   mr0;
        int             len, stlen;
@@ -4422,8 +4406,11 @@ static void stl_sc26198txisr(struct stlport *portp)
        if ((len == 0) || ((len < STL_TXBUFLOW) &&
            (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
                set_bit(ASYI_TXLOW, &portp->istate);
-               if (portp->port.tty)
-                       tty_wakeup(portp->port.tty);
+               tty = tty_port_tty_get(&portp->port);
+               if (tty) {
+                       tty_wakeup(tty);
+                       tty_kref_put(tty);
+               }
        }
 
        if (len == 0) {
@@ -4476,7 +4463,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
 
        pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
 
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        ioaddr = portp->ioaddr;
        outb(GIBCR, (ioaddr + XP_ADDR));
        len = inb(ioaddr + XP_DATA) + 1;
@@ -4515,6 +4502,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
                        stl_sc26198txunflow(portp, tty);
                }
        }
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4528,7 +4516,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
        struct tty_struct       *tty;
        unsigned int            ioaddr;
 
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        ioaddr = portp->ioaddr;
 
        if (status & SR_RXPARITY)
@@ -4566,6 +4554,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
                if (status == 0)
                        portp->stats.rxtotal++;
        }
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4754,8 +4743,8 @@ static int __init stallion_module_init(void)
        if (IS_ERR(stallion_class))
                printk("STALLION: failed to create class\n");
        for (i = 0; i < 4; i++)
-               device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-                                     NULL, "staliomem%d", i);
+               device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+                             NULL, "staliomem%d", i);
 
        return 0;
 err_unrtty:
index c385206f9db540caa925d615be1c1d4d566482f4..5b8d7a1aa3e64853c21eb524339123a81bd31f3b 100644 (file)
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,
                del_timer(&board->timer);
                if (pdev) {
 #ifdef CONFIG_PCI
-                       pci_iounmap(pdev, board->base);
+                       pci_iounmap(pdev, board->base2);
                        pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
 #endif
                } else {
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
 
        return 0;
 err_unmap:
-       pci_iounmap(pdev, board->base);
+       pci_iounmap(pdev, board->base2);
 err_reg:
        pci_release_region(pdev, reg);
 err_flag:
index 8fdfe9c871e3af99f5a632d2f893bbd0508455ab..dce4cc0e695338210391a11311507ef1b8d49f76 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/reboot.h>
 #include <linux/sysrq.h>
 #include <linux/kbd_kern.h>
+#include <linux/proc_fs.h>
 #include <linux/quotaops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -326,6 +327,7 @@ static struct sysrq_key_op sysrq_moom_op = {
        .handler        = sysrq_handle_moom,
        .help_msg       = "Full",
        .action_msg     = "Manual OOM execution",
+       .enable_mask    = SYSRQ_ENABLE_SIGNAL,
 };
 
 static void sysrq_handle_kill(int key, struct tty_struct *tty)
@@ -533,3 +535,32 @@ int unregister_sysrq_key(int key, struct sysrq_key_op *op_p)
        return __sysrq_swap_key_ops(key, NULL, op_p);
 }
 EXPORT_SYMBOL(unregister_sysrq_key);
+
+#ifdef CONFIG_PROC_FS
+/*
+ * writing 'C' to /proc/sysrq-trigger is like sysrq-C
+ */
+static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       if (count) {
+               char c;
+
+               if (get_user(c, buf))
+                       return -EFAULT;
+               __handle_sysrq(c, NULL, 0);
+       }
+       return count;
+}
+
+static const struct file_operations proc_sysrq_trigger_operations = {
+       .write          = write_sysrq_trigger,
+};
+
+static int __init sysrq_init(void)
+{
+       proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
+       return 0;
+}
+module_init(sysrq_init);
+#endif
index ae766d868454406a6d32bbfc7422975d6a9ce550..e70d13defde4bcc30724187ff6443f553730eeb7 100644 (file)
@@ -525,19 +525,19 @@ void tpm_get_timeouts(struct tpm_chip *chip)
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
        if (timeout)
-               chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_a = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
        if (timeout)
-               chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_b = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
        if (timeout)
-               chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_c = usecs_to_jiffies(timeout);
        timeout =
            be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
        if (timeout)
-               chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+               chip->vendor.timeout_d = usecs_to_jiffies(timeout);
 
 duration:
        memcpy(data, tpm_cap, sizeof(tpm_cap));
@@ -554,15 +554,22 @@ duration:
                return;
 
        chip->vendor.duration[TPM_SHORT] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_1_IDX))));
+       /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
+        * value wrong and apparently reports msecs rather than usecs. So we
+        * fix up the resulting too-small TPM_SHORT value to make things work.
+        */
+       if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
+               chip->vendor.duration[TPM_SHORT] = HZ;
+
        chip->vendor.duration[TPM_MEDIUM] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_2_IDX))));
        chip->vendor.duration[TPM_LONG] =
-           msecs_to_jiffies(be32_to_cpu
+           usecs_to_jiffies(be32_to_cpu
                             (*((__be32 *) (data +
                                            TPM_GET_CAP_RET_UINT32_3_IDX))));
 }
@@ -954,72 +961,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel);
 
 /*
  * Device file system interface to the TPM
+ *
+ * It's assured that the chip will be opened just once,
+ * by the check of is_open variable, which is protected
+ * by driver_lock.
  */
 int tpm_open(struct inode *inode, struct file *file)
 {
-       int rc = 0, minor = iminor(inode);
+       int minor = iminor(inode);
        struct tpm_chip *chip = NULL, *pos;
 
-       lock_kernel();
-       spin_lock(&driver_lock);
-
-       list_for_each_entry(pos, &tpm_chip_list, list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
                if (pos->vendor.miscdev.minor == minor) {
                        chip = pos;
+                       get_device(chip->dev);
                        break;
                }
        }
+       rcu_read_unlock();
 
-       if (chip == NULL) {
-               rc = -ENODEV;
-               goto err_out;
-       }
+       if (!chip)
+               return -ENODEV;
 
-       if (chip->num_opens) {
+       if (test_and_set_bit(0, &chip->is_open)) {
                dev_dbg(chip->dev, "Another process owns this TPM\n");
-               rc = -EBUSY;
-               goto err_out;
+               put_device(chip->dev);
+               return -EBUSY;
        }
 
-       chip->num_opens++;
-       get_device(chip->dev);
-
-       spin_unlock(&driver_lock);
-
        chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
        if (chip->data_buffer == NULL) {
-               chip->num_opens--;
+               clear_bit(0, &chip->is_open);
                put_device(chip->dev);
-               unlock_kernel();
                return -ENOMEM;
        }
 
        atomic_set(&chip->data_pending, 0);
 
        file->private_data = chip;
-       unlock_kernel();
        return 0;
-
-err_out:
-       spin_unlock(&driver_lock);
-       unlock_kernel();
-       return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_open);
 
+/*
+ * Called on file close
+ */
 int tpm_release(struct inode *inode, struct file *file)
 {
        struct tpm_chip *chip = file->private_data;
 
+       del_singleshot_timer_sync(&chip->user_read_timer);
        flush_scheduled_work();
-       spin_lock(&driver_lock);
        file->private_data = NULL;
-       del_singleshot_timer_sync(&chip->user_read_timer);
        atomic_set(&chip->data_pending, 0);
-       chip->num_opens--;
-       put_device(chip->dev);
        kfree(chip->data_buffer);
-       spin_unlock(&driver_lock);
+       clear_bit(0, &chip->is_open);
+       put_device(chip->dev);
        return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_release);
@@ -1093,13 +1091,11 @@ void tpm_remove_hardware(struct device *dev)
        }
 
        spin_lock(&driver_lock);
-
-       list_del(&chip->list);
-
+       list_del_rcu(&chip->list);
        spin_unlock(&driver_lock);
+       synchronize_rcu();
 
        misc_deregister(&chip->vendor.miscdev);
-
        sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
        tpm_bios_log_teardown(chip->bios_dir);
 
@@ -1144,25 +1140,33 @@ int tpm_pm_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
+/* In case vendor provided release function, call it too.*/
+
+void tpm_dev_vendor_release(struct tpm_chip *chip)
+{
+       if (chip->vendor.release)
+               chip->vendor.release(chip->dev);
+
+       clear_bit(chip->dev_num, dev_mask);
+       kfree(chip->vendor.miscdev.name);
+}
+EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
+
+
 /*
  * Once all references to platform device are down to 0,
  * release all allocated structures.
- * In case vendor provided release function,
- * call it too.
  */
 static void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
-       if (chip->vendor.release)
-               chip->vendor.release(dev);
+       tpm_dev_vendor_release(chip);
 
        chip->release(dev);
-
-       clear_bit(chip->dev_num, dev_mask);
-       kfree(chip->vendor.miscdev.name);
        kfree(chip);
 }
+EXPORT_SYMBOL_GPL(tpm_dev_release);
 
 /*
  * Called from tpm_<specific>.c probe function only for devices 
@@ -1171,8 +1175,8 @@ static void tpm_dev_release(struct device *dev)
  * upon errant exit from this function specific probe function should call
  * pci_disable_device
  */
-struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
-                                      *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev,
+                                       const struct tpm_vendor_specific *entry)
 {
 #define DEVNAME_SIZE 7
 
@@ -1183,11 +1187,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
 
-       if (chip == NULL || devname == NULL) {
-               kfree(chip);
-               kfree(devname);
-               return NULL;
-       }
+       if (chip == NULL || devname == NULL)
+               goto out_free;
 
        mutex_init(&chip->buffer_mutex);
        mutex_init(&chip->tpm_mutex);
@@ -1204,8 +1205,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
 
        if (chip->dev_num >= TPM_NUM_DEVICES) {
                dev_err(dev, "No available tpm device numbers\n");
-               kfree(chip);
-               return NULL;
+               goto out_free;
        } else if (chip->dev_num == 0)
                chip->vendor.miscdev.minor = TPM_MINOR;
        else
@@ -1231,22 +1231,26 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
                return NULL;
        }
 
-       spin_lock(&driver_lock);
-
-       list_add(&chip->list, &tpm_chip_list);
-
-       spin_unlock(&driver_lock);
-
        if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
-               list_del(&chip->list);
                misc_deregister(&chip->vendor.miscdev);
                put_device(chip->dev);
+
                return NULL;
        }
 
        chip->bios_dir = tpm_bios_log_setup(devname);
 
+       /* Make chip available */
+       spin_lock(&driver_lock);
+       list_add_rcu(&chip->list, &tpm_chip_list);
+       spin_unlock(&driver_lock);
+
        return chip;
+
+out_free:
+       kfree(chip);
+       kfree(devname);
+       return NULL;
 }
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
index e885148b4cfbd0b177f77b87e6e629511db16983..8e30df4a4388166343af7bfed2aadefdd4f809bc 100644 (file)
@@ -90,7 +90,7 @@ struct tpm_chip {
        struct device *dev;     /* Device stuff */
 
        int dev_num;            /* /dev/tpm# */
-       int num_opens;          /* only one allowed */
+       unsigned long is_open;  /* only one allowed */
        int time_expired;
 
        /* Data passed to and from the tpm via the read/write calls */
@@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *,
                                 const struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
 extern int tpm_release(struct inode *, struct file *);
+extern void tpm_dev_vendor_release(struct tpm_chip *);
 extern ssize_t tpm_write(struct file *, const char __user *, size_t,
                         loff_t *);
 extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
index ed1879c0dd8d1433a0e239631630ce55a971f8b8..717af7ad1bdf5ca28e784b350386182c086f9321 100644 (file)
@@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
        {"", 0}                 /* Terminator */
 };
 
+static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
+{
+       struct tpm_chip *chip = pnp_get_drvdata(dev);
+
+       tpm_dev_vendor_release(chip);
+
+       kfree(chip);
+}
+
+
 static struct pnp_driver tis_pnp_driver = {
        .name = "tpm_tis",
        .id_table = tpm_pnp_tbl,
        .probe = tpm_tis_pnp_init,
        .suspend = tpm_tis_pnp_suspend,
        .resume = tpm_tis_pnp_resume,
+       .remove = tpm_tis_pnp_remove,
 };
 
 #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
@@ -683,6 +694,7 @@ static void __exit cleanup_tis(void)
        spin_lock(&tis_lock);
        list_for_each_entry_safe(i, j, &tis_chips, list) {
                chip = to_tpm_chip(i);
+               tpm_remove_hardware(chip->dev);
                iowrite32(~TPM_GLOBAL_INT_ENABLE &
                          ioread32(chip->vendor.iobase +
                                   TPM_INT_ENABLE(chip->vendor.
@@ -694,9 +706,9 @@ static void __exit cleanup_tis(void)
                        free_irq(chip->vendor.irq, chip);
                iounmap(i->iobase);
                list_del(&i->list);
-               tpm_remove_hardware(chip->dev);
        }
        spin_unlock(&tis_lock);
+
        if (force) {
                platform_device_unregister(pdev);
                driver_unregister(&tis_drv);
index 3582f43345a8c1d40397d2284dd2bc11d77a9fd4..5787249934c8b01b1603b38677cf5f55ff5a4ed9 100644 (file)
@@ -93,7 +93,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
                get_task_comm(name, tsk);
                audit_log_untrustedstring(ab, name);
                audit_log_format(ab, " data=");
-               audit_log_n_untrustedstring(ab, buf->data, buf->valid);
+               audit_log_n_hex(ab, buf->data, buf->valid);
                audit_log_end(ab);
        }
        buf->valid = 0;
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
new file mode 100644 (file)
index 0000000..810ee25
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Tty buffer allocation management
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+/**
+ *     tty_buffer_free_all             -       free buffers used by a tty
+ *     @tty: tty to free from
+ *
+ *     Remove all the buffers pending on a tty whether queued with data
+ *     or in the free ring. Must be called when the tty is no longer in use
+ *
+ *     Locking: none
+ */
+
+void tty_buffer_free_all(struct tty_struct *tty)
+{
+       struct tty_buffer *thead;
+       while ((thead = tty->buf.head) != NULL) {
+               tty->buf.head = thead->next;
+               kfree(thead);
+       }
+       while ((thead = tty->buf.free) != NULL) {
+               tty->buf.free = thead->next;
+               kfree(thead);
+       }
+       tty->buf.tail = NULL;
+       tty->buf.memory_used = 0;
+}
+
+/**
+ *     tty_buffer_alloc        -       allocate a tty buffer
+ *     @tty: tty device
+ *     @size: desired size (characters)
+ *
+ *     Allocate a new tty buffer to hold the desired number of characters.
+ *     Return NULL if out of memory or the allocation would exceed the
+ *     per device queue
+ *
+ *     Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+{
+       struct tty_buffer *p;
+
+       if (tty->buf.memory_used + size > 65536)
+               return NULL;
+       p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+       if (p == NULL)
+               return NULL;
+       p->used = 0;
+       p->size = size;
+       p->next = NULL;
+       p->commit = 0;
+       p->read = 0;
+       p->char_buf_ptr = (char *)(p->data);
+       p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+       tty->buf.memory_used += size;
+       return p;
+}
+
+/**
+ *     tty_buffer_free         -       free a tty buffer
+ *     @tty: tty owning the buffer
+ *     @b: the buffer to free
+ *
+ *     Free a tty buffer, or add it to the free list according to our
+ *     internal strategy
+ *
+ *     Locking: Caller must hold tty->buf.lock
+ */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+       /* Dumb strategy for now - should keep some stats */
+       tty->buf.memory_used -= b->size;
+       WARN_ON(tty->buf.memory_used < 0);
+
+       if (b->size >= 512)
+               kfree(b);
+       else {
+               b->next = tty->buf.free;
+               tty->buf.free = b;
+       }
+}
+
+/**
+ *     __tty_buffer_flush              -       flush full tty buffers
+ *     @tty: tty to flush
+ *
+ *     flush all the buffers containing receive data. Caller must
+ *     hold the buffer lock and must have ensured no parallel flush to
+ *     ldisc is running.
+ *
+ *     Locking: Caller must hold tty->buf.lock
+ */
+
+static void __tty_buffer_flush(struct tty_struct *tty)
+{
+       struct tty_buffer *thead;
+
+       while ((thead = tty->buf.head) != NULL) {
+               tty->buf.head = thead->next;
+               tty_buffer_free(tty, thead);
+       }
+       tty->buf.tail = NULL;
+}
+
+/**
+ *     tty_buffer_flush                -       flush full tty buffers
+ *     @tty: tty to flush
+ *
+ *     flush all the buffers containing receive data. If the buffer is
+ *     being processed by flush_to_ldisc then we defer the processing
+ *     to that function
+ *
+ *     Locking: none
+ */
+
+void tty_buffer_flush(struct tty_struct *tty)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&tty->buf.lock, flags);
+
+       /* If the data is being pushed to the tty layer then we can't
+          process it here. Instead set a flag and the flush_to_ldisc
+          path will process the flush request before it exits */
+       if (test_bit(TTY_FLUSHING, &tty->flags)) {
+               set_bit(TTY_FLUSHPENDING, &tty->flags);
+               spin_unlock_irqrestore(&tty->buf.lock, flags);
+               wait_event(tty->read_wait,
+                               test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+               return;
+       } else
+               __tty_buffer_flush(tty);
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+}
+
+/**
+ *     tty_buffer_find         -       find a free tty buffer
+ *     @tty: tty owning the buffer
+ *     @size: characters wanted
+ *
+ *     Locate an existing suitable tty buffer or if we are lacking one then
+ *     allocate a new one. We round our buffers off in 256 character chunks
+ *     to get better allocation behaviour.
+ *
+ *     Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+       struct tty_buffer **tbh = &tty->buf.free;
+       while ((*tbh) != NULL) {
+               struct tty_buffer *t = *tbh;
+               if (t->size >= size) {
+                       *tbh = t->next;
+                       t->next = NULL;
+                       t->used = 0;
+                       t->commit = 0;
+                       t->read = 0;
+                       tty->buf.memory_used += t->size;
+                       return t;
+               }
+               tbh = &((*tbh)->next);
+       }
+       /* Round the buffer size out */
+       size = (size + 0xFF) & ~0xFF;
+       return tty_buffer_alloc(tty, size);
+       /* Should possibly check if this fails for the largest buffer we
+          have queued and recycle that ? */
+}
+
+/**
+ *     tty_buffer_request_room         -       grow tty buffer if needed
+ *     @tty: tty structure
+ *     @size: size desired
+ *
+ *     Make at least size bytes of linear space available for the tty
+ *     buffer. If we fail return the size we managed to find.
+ *
+ *     Locking: Takes tty->buf.lock
+ */
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+       struct tty_buffer *b, *n;
+       int left;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tty->buf.lock, flags);
+
+       /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+          remove this conditional if its worth it. This would be invisible
+          to the callers */
+       if ((b = tty->buf.tail) != NULL)
+               left = b->size - b->used;
+       else
+               left = 0;
+
+       if (left < size) {
+               /* This is the slow path - looking for new buffers to use */
+               if ((n = tty_buffer_find(tty, size)) != NULL) {
+                       if (b != NULL) {
+                               b->next = n;
+                               b->commit = b->used;
+                       } else
+                               tty->buf.head = n;
+                       tty->buf.tail = n;
+               } else
+                       size = left;
+       }
+
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+       return size;
+}
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+/**
+ *     tty_insert_flip_string  -       Add characters to the tty buffer
+ *     @tty: tty structure
+ *     @chars: characters
+ *     @size: size
+ *
+ *     Queue a series of bytes to the tty buffering. All the characters
+ *     passed are marked as without error. Returns the number added.
+ *
+ *     Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
+                               size_t size)
+{
+       int copied = 0;
+       do {
+               int space = tty_buffer_request_room(tty, size - copied);
+               struct tty_buffer *tb = tty->buf.tail;
+               /* If there is no space then tb may be NULL */
+               if (unlikely(space == 0))
+                       break;
+               memcpy(tb->char_buf_ptr + tb->used, chars, space);
+               memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+               tb->used += space;
+               copied += space;
+               chars += space;
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
+       return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string);
+
+/**
+ *     tty_insert_flip_string_flags    -       Add characters to the tty buffer
+ *     @tty: tty structure
+ *     @chars: characters
+ *     @flags: flag bytes
+ *     @size: size
+ *
+ *     Queue a series of bytes to the tty buffering. For each character
+ *     the flags array indicates the status of the character. Returns the
+ *     number added.
+ *
+ *     Locking: Called functions may take tty->buf.lock
+ */
+
+int tty_insert_flip_string_flags(struct tty_struct *tty,
+               const unsigned char *chars, const char *flags, size_t size)
+{
+       int copied = 0;
+       do {
+               int space = tty_buffer_request_room(tty, size - copied);
+               struct tty_buffer *tb = tty->buf.tail;
+               /* If there is no space then tb may be NULL */
+               if (unlikely(space == 0))
+                       break;
+               memcpy(tb->char_buf_ptr + tb->used, chars, space);
+               memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+               tb->used += space;
+               copied += space;
+               chars += space;
+               flags += space;
+               /* There is a small chance that we need to split the data over
+                  several buffers. If this is the case we must loop */
+       } while (unlikely(size > copied));
+       return copied;
+}
+EXPORT_SYMBOL(tty_insert_flip_string_flags);
+
+/**
+ *     tty_schedule_flip       -       push characters to ldisc
+ *     @tty: tty to push from
+ *
+ *     Takes any pending buffers and transfers their ownership to the
+ *     ldisc side of the queue. It then schedules those characters for
+ *     processing by the line discipline.
+ *
+ *     Locking: Takes tty->buf.lock
+ */
+
+void tty_schedule_flip(struct tty_struct *tty)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&tty->buf.lock, flags);
+       if (tty->buf.tail != NULL)
+               tty->buf.tail->commit = tty->buf.tail->used;
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+       schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
+
+/**
+ *     tty_prepare_flip_string         -       make room for characters
+ *     @tty: tty
+ *     @chars: return pointer for character write area
+ *     @size: desired size
+ *
+ *     Prepare a block of space in the buffer for data. Returns the length
+ *     available and buffer pointer to the space which is now allocated and
+ *     accounted for as ready for normal characters. This is used for drivers
+ *     that need their own block copy routines into the buffer. There is no
+ *     guarantee the buffer is a DMA target!
+ *
+ *     Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
+                                                               size_t size)
+{
+       int space = tty_buffer_request_room(tty, size);
+       if (likely(space)) {
+               struct tty_buffer *tb = tty->buf.tail;
+               *chars = tb->char_buf_ptr + tb->used;
+               memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+               tb->used += space;
+       }
+       return space;
+}
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/**
+ *     tty_prepare_flip_string_flags   -       make room for characters
+ *     @tty: tty
+ *     @chars: return pointer for character write area
+ *     @flags: return pointer for status flag write area
+ *     @size: desired size
+ *
+ *     Prepare a block of space in the buffer for data. Returns the length
+ *     available and buffer pointer to the space which is now allocated and
+ *     accounted for as ready for characters. This is used for drivers
+ *     that need their own block copy routines into the buffer. There is no
+ *     guarantee the buffer is a DMA target!
+ *
+ *     Locking: May call functions taking tty->buf.lock
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty,
+                       unsigned char **chars, char **flags, size_t size)
+{
+       int space = tty_buffer_request_room(tty, size);
+       if (likely(space)) {
+               struct tty_buffer *tb = tty->buf.tail;
+               *chars = tb->char_buf_ptr + tb->used;
+               *flags = tb->flag_buf_ptr + tb->used;
+               tb->used += space;
+       }
+       return space;
+}
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/**
+ *     flush_to_ldisc
+ *     @work: tty structure passed from work queue.
+ *
+ *     This routine is called out of the software interrupt to flush data
+ *     from the buffer chain to the line discipline.
+ *
+ *     Locking: holds tty->buf.lock to guard buffer list. Drops the lock
+ *     while invoking the line discipline receive_buf method. The
+ *     receive_buf method is single threaded for each tty instance.
+ */
+
+static void flush_to_ldisc(struct work_struct *work)
+{
+       struct tty_struct *tty =
+               container_of(work, struct tty_struct, buf.work.work);
+       unsigned long   flags;
+       struct tty_ldisc *disc;
+       struct tty_buffer *tbuf, *head;
+       char *char_buf;
+       unsigned char *flag_buf;
+
+       disc = tty_ldisc_ref(tty);
+       if (disc == NULL)       /*  !TTY_LDISC */
+               return;
+
+       spin_lock_irqsave(&tty->buf.lock, flags);
+       /* So we know a flush is running */
+       set_bit(TTY_FLUSHING, &tty->flags);
+       head = tty->buf.head;
+       if (head != NULL) {
+               tty->buf.head = NULL;
+               for (;;) {
+                       int count = head->commit - head->read;
+                       if (!count) {
+                               if (head->next == NULL)
+                                       break;
+                               tbuf = head;
+                               head = head->next;
+                               tty_buffer_free(tty, tbuf);
+                               continue;
+                       }
+                       /* Ldisc or user is trying to flush the buffers
+                          we are feeding to the ldisc, stop feeding the
+                          line discipline as we want to empty the queue */
+                       if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+                               break;
+                       if (!tty->receive_room) {
+                               schedule_delayed_work(&tty->buf.work, 1);
+                               break;
+                       }
+                       if (count > tty->receive_room)
+                               count = tty->receive_room;
+                       char_buf = head->char_buf_ptr + head->read;
+                       flag_buf = head->flag_buf_ptr + head->read;
+                       head->read += count;
+                       spin_unlock_irqrestore(&tty->buf.lock, flags);
+                       disc->ops->receive_buf(tty, char_buf,
+                                                       flag_buf, count);
+                       spin_lock_irqsave(&tty->buf.lock, flags);
+               }
+               /* Restore the queue head */
+               tty->buf.head = head;
+       }
+       /* We may have a deferred request to flush the input buffer,
+          if so pull the chain under the lock and empty the queue */
+       if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
+               __tty_buffer_flush(tty);
+               clear_bit(TTY_FLUSHPENDING, &tty->flags);
+               wake_up(&tty->read_wait);
+       }
+       clear_bit(TTY_FLUSHING, &tty->flags);
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+       tty_ldisc_deref(disc);
+}
+
+/**
+ *     tty_flip_buffer_push    -       terminal
+ *     @tty: tty to push
+ *
+ *     Queue a push of the terminal flip buffers to the line discipline. This
+ *     function must not be called from IRQ context if tty->low_latency is set.
+ *
+ *     In the event of the queue being busy for flipping the work will be
+ *     held off and retried later.
+ *
+ *     Locking: tty buffer lock. Driver locks in low latency mode.
+ */
+
+void tty_flip_buffer_push(struct tty_struct *tty)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&tty->buf.lock, flags);
+       if (tty->buf.tail != NULL)
+               tty->buf.tail->commit = tty->buf.tail->used;
+       spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+       if (tty->low_latency)
+               flush_to_ldisc(&tty->buf.work.work);
+       else
+               schedule_delayed_work(&tty->buf.work, 1);
+}
+EXPORT_SYMBOL(tty_flip_buffer_push);
+
+/**
+ *     tty_buffer_init         -       prepare a tty buffer structure
+ *     @tty: tty to initialise
+ *
+ *     Set up the initial state of the buffer management for a tty device.
+ *     Must be called before the other tty buffer functions are used.
+ *
+ *     Locking: none
+ */
+
+void tty_buffer_init(struct tty_struct *tty)
+{
+       spin_lock_init(&tty->buf.lock);
+       tty->buf.head = NULL;
+       tty->buf.tail = NULL;
+       tty->buf.free = NULL;
+       tty->buf.memory_used = 0;
+       INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
+}
+
index e4dce87095410f8f648137ecb992927a6630c483..59f472143f087d9486d62bd9f3842c2a9aee7eb6 100644 (file)
@@ -49,7 +49,7 @@
  * implement CONFIG_VT and generalize console device interface.
  *     -- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97
  *
- * Rewrote init_dev and release_dev to eliminate races.
+ * Rewrote tty_init_dev and tty_release_dev to eliminate races.
  *     -- Bill Hawes <whawes@star.net>, June 97
  *
  * Added devfs support.
@@ -136,13 +136,6 @@ LIST_HEAD(tty_drivers);                    /* linked list of tty drivers */
 DEFINE_MUTEX(tty_mutex);
 EXPORT_SYMBOL(tty_mutex);
 
-#ifdef CONFIG_UNIX98_PTYS
-extern struct tty_driver *ptm_driver;  /* Unix98 pty masters; for /dev/ptmx */
-static int ptmx_open(struct inode *, struct file *);
-#endif
-
-static void initialize_tty_struct(struct tty_struct *tty);
-
 static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
 static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
 ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -171,13 +164,11 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
  *     Locking: none
  */
 
-static struct tty_struct *alloc_tty_struct(void)
+struct tty_struct *alloc_tty_struct(void)
 {
        return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
 }
 
-static void tty_buffer_free_all(struct tty_struct *);
-
 /**
  *     free_tty_struct         -       free a disused tty
  *     @tty: tty struct to free
@@ -187,7 +178,7 @@ static void tty_buffer_free_all(struct tty_struct *);
  *     Locking: none. Must be called after tty is definitely unused
  */
 
-static inline void free_tty_struct(struct tty_struct *tty)
+void free_tty_struct(struct tty_struct *tty)
 {
        kfree(tty->write_buf);
        tty_buffer_free_all(tty);
@@ -263,398 +254,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
        return 0;
 }
 
-/*
- * Tty buffer allocation management
- */
-
-/**
- *     tty_buffer_free_all             -       free buffers used by a tty
- *     @tty: tty to free from
- *
- *     Remove all the buffers pending on a tty whether queued with data
- *     or in the free ring. Must be called when the tty is no longer in use
- *
- *     Locking: none
- */
-
-static void tty_buffer_free_all(struct tty_struct *tty)
-{
-       struct tty_buffer *thead;
-       while ((thead = tty->buf.head) != NULL) {
-               tty->buf.head = thead->next;
-               kfree(thead);
-       }
-       while ((thead = tty->buf.free) != NULL) {
-               tty->buf.free = thead->next;
-               kfree(thead);
-       }
-       tty->buf.tail = NULL;
-       tty->buf.memory_used = 0;
-}
-
-/**
- *     tty_buffer_init         -       prepare a tty buffer structure
- *     @tty: tty to initialise
- *
- *     Set up the initial state of the buffer management for a tty device.
- *     Must be called before the other tty buffer functions are used.
- *
- *     Locking: none
- */
-
-static void tty_buffer_init(struct tty_struct *tty)
-{
-       spin_lock_init(&tty->buf.lock);
-       tty->buf.head = NULL;
-       tty->buf.tail = NULL;
-       tty->buf.free = NULL;
-       tty->buf.memory_used = 0;
-}
-
-/**
- *     tty_buffer_alloc        -       allocate a tty buffer
- *     @tty: tty device
- *     @size: desired size (characters)
- *
- *     Allocate a new tty buffer to hold the desired number of characters.
- *     Return NULL if out of memory or the allocation would exceed the
- *     per device queue
- *
- *     Locking: Caller must hold tty->buf.lock
- */
-
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
-{
-       struct tty_buffer *p;
-
-       if (tty->buf.memory_used + size > 65536)
-               return NULL;
-       p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
-       if (p == NULL)
-               return NULL;
-       p->used = 0;
-       p->size = size;
-       p->next = NULL;
-       p->commit = 0;
-       p->read = 0;
-       p->char_buf_ptr = (char *)(p->data);
-       p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-       tty->buf.memory_used += size;
-       return p;
-}
-
-/**
- *     tty_buffer_free         -       free a tty buffer
- *     @tty: tty owning the buffer
- *     @b: the buffer to free
- *
- *     Free a tty buffer, or add it to the free list according to our
- *     internal strategy
- *
- *     Locking: Caller must hold tty->buf.lock
- */
-
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
-{
-       /* Dumb strategy for now - should keep some stats */
-       tty->buf.memory_used -= b->size;
-       WARN_ON(tty->buf.memory_used < 0);
-
-       if (b->size >= 512)
-               kfree(b);
-       else {
-               b->next = tty->buf.free;
-               tty->buf.free = b;
-       }
-}
-
-/**
- *     __tty_buffer_flush              -       flush full tty buffers
- *     @tty: tty to flush
- *
- *     flush all the buffers containing receive data. Caller must
- *     hold the buffer lock and must have ensured no parallel flush to
- *     ldisc is running.
- *
- *     Locking: Caller must hold tty->buf.lock
- */
-
-static void __tty_buffer_flush(struct tty_struct *tty)
-{
-       struct tty_buffer *thead;
-
-       while ((thead = tty->buf.head) != NULL) {
-               tty->buf.head = thead->next;
-               tty_buffer_free(tty, thead);
-       }
-       tty->buf.tail = NULL;
-}
-
-/**
- *     tty_buffer_flush                -       flush full tty buffers
- *     @tty: tty to flush
- *
- *     flush all the buffers containing receive data. If the buffer is
- *     being processed by flush_to_ldisc then we defer the processing
- *     to that function
- *
- *     Locking: none
- */
-
-static void tty_buffer_flush(struct tty_struct *tty)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
-
-       /* If the data is being pushed to the tty layer then we can't
-          process it here. Instead set a flag and the flush_to_ldisc
-          path will process the flush request before it exits */
-       if (test_bit(TTY_FLUSHING, &tty->flags)) {
-               set_bit(TTY_FLUSHPENDING, &tty->flags);
-               spin_unlock_irqrestore(&tty->buf.lock, flags);
-               wait_event(tty->read_wait,
-                               test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
-               return;
-       } else
-               __tty_buffer_flush(tty);
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-}
-
-/**
- *     tty_buffer_find         -       find a free tty buffer
- *     @tty: tty owning the buffer
- *     @size: characters wanted
- *
- *     Locate an existing suitable tty buffer or if we are lacking one then
- *     allocate a new one. We round our buffers off in 256 character chunks
- *     to get better allocation behaviour.
- *
- *     Locking: Caller must hold tty->buf.lock
- */
-
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
-{
-       struct tty_buffer **tbh = &tty->buf.free;
-       while ((*tbh) != NULL) {
-               struct tty_buffer *t = *tbh;
-               if (t->size >= size) {
-                       *tbh = t->next;
-                       t->next = NULL;
-                       t->used = 0;
-                       t->commit = 0;
-                       t->read = 0;
-                       tty->buf.memory_used += t->size;
-                       return t;
-               }
-               tbh = &((*tbh)->next);
-       }
-       /* Round the buffer size out */
-       size = (size + 0xFF) & ~0xFF;
-       return tty_buffer_alloc(tty, size);
-       /* Should possibly check if this fails for the largest buffer we
-          have queued and recycle that ? */
-}
-
-/**
- *     tty_buffer_request_room         -       grow tty buffer if needed
- *     @tty: tty structure
- *     @size: size desired
- *
- *     Make at least size bytes of linear space available for the tty
- *     buffer. If we fail return the size we managed to find.
- *
- *     Locking: Takes tty->buf.lock
- */
-int tty_buffer_request_room(struct tty_struct *tty, size_t size)
-{
-       struct tty_buffer *b, *n;
-       int left;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tty->buf.lock, flags);
-
-       /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
-          remove this conditional if its worth it. This would be invisible
-          to the callers */
-       if ((b = tty->buf.tail) != NULL)
-               left = b->size - b->used;
-       else
-               left = 0;
-
-       if (left < size) {
-               /* This is the slow path - looking for new buffers to use */
-               if ((n = tty_buffer_find(tty, size)) != NULL) {
-                       if (b != NULL) {
-                               b->next = n;
-                               b->commit = b->used;
-                       } else
-                               tty->buf.head = n;
-                       tty->buf.tail = n;
-               } else
-                       size = left;
-       }
-
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-       return size;
-}
-EXPORT_SYMBOL_GPL(tty_buffer_request_room);
-
-/**
- *     tty_insert_flip_string  -       Add characters to the tty buffer
- *     @tty: tty structure
- *     @chars: characters
- *     @size: size
- *
- *     Queue a series of bytes to the tty buffering. All the characters
- *     passed are marked as without error. Returns the number added.
- *
- *     Locking: Called functions may take tty->buf.lock
- */
-
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
-                               size_t size)
-{
-       int copied = 0;
-       do {
-               int space = tty_buffer_request_room(tty, size - copied);
-               struct tty_buffer *tb = tty->buf.tail;
-               /* If there is no space then tb may be NULL */
-               if (unlikely(space == 0))
-                       break;
-               memcpy(tb->char_buf_ptr + tb->used, chars, space);
-               memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
-               tb->used += space;
-               copied += space;
-               chars += space;
-               /* There is a small chance that we need to split the data over
-                  several buffers. If this is the case we must loop */
-       } while (unlikely(size > copied));
-       return copied;
-}
-EXPORT_SYMBOL(tty_insert_flip_string);
-
-/**
- *     tty_insert_flip_string_flags    -       Add characters to the tty buffer
- *     @tty: tty structure
- *     @chars: characters
- *     @flags: flag bytes
- *     @size: size
- *
- *     Queue a series of bytes to the tty buffering. For each character
- *     the flags array indicates the status of the character. Returns the
- *     number added.
- *
- *     Locking: Called functions may take tty->buf.lock
- */
-
-int tty_insert_flip_string_flags(struct tty_struct *tty,
-               const unsigned char *chars, const char *flags, size_t size)
-{
-       int copied = 0;
-       do {
-               int space = tty_buffer_request_room(tty, size - copied);
-               struct tty_buffer *tb = tty->buf.tail;
-               /* If there is no space then tb may be NULL */
-               if (unlikely(space == 0))
-                       break;
-               memcpy(tb->char_buf_ptr + tb->used, chars, space);
-               memcpy(tb->flag_buf_ptr + tb->used, flags, space);
-               tb->used += space;
-               copied += space;
-               chars += space;
-               flags += space;
-               /* There is a small chance that we need to split the data over
-                  several buffers. If this is the case we must loop */
-       } while (unlikely(size > copied));
-       return copied;
-}
-EXPORT_SYMBOL(tty_insert_flip_string_flags);
-
-/**
- *     tty_schedule_flip       -       push characters to ldisc
- *     @tty: tty to push from
- *
- *     Takes any pending buffers and transfers their ownership to the
- *     ldisc side of the queue. It then schedules those characters for
- *     processing by the line discipline.
- *
- *     Locking: Takes tty->buf.lock
- */
-
-void tty_schedule_flip(struct tty_struct *tty)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       if (tty->buf.tail != NULL)
-               tty->buf.tail->commit = tty->buf.tail->used;
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-       schedule_delayed_work(&tty->buf.work, 1);
-}
-EXPORT_SYMBOL(tty_schedule_flip);
-
-/**
- *     tty_prepare_flip_string         -       make room for characters
- *     @tty: tty
- *     @chars: return pointer for character write area
- *     @size: desired size
- *
- *     Prepare a block of space in the buffer for data. Returns the length
- *     available and buffer pointer to the space which is now allocated and
- *     accounted for as ready for normal characters. This is used for drivers
- *     that need their own block copy routines into the buffer. There is no
- *     guarantee the buffer is a DMA target!
- *
- *     Locking: May call functions taking tty->buf.lock
- */
-
-int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
-                                                               size_t size)
-{
-       int space = tty_buffer_request_room(tty, size);
-       if (likely(space)) {
-               struct tty_buffer *tb = tty->buf.tail;
-               *chars = tb->char_buf_ptr + tb->used;
-               memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
-               tb->used += space;
-       }
-       return space;
-}
-
-EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
-
-/**
- *     tty_prepare_flip_string_flags   -       make room for characters
- *     @tty: tty
- *     @chars: return pointer for character write area
- *     @flags: return pointer for status flag write area
- *     @size: desired size
- *
- *     Prepare a block of space in the buffer for data. Returns the length
- *     available and buffer pointer to the space which is now allocated and
- *     accounted for as ready for characters. This is used for drivers
- *     that need their own block copy routines into the buffer. There is no
- *     guarantee the buffer is a DMA target!
- *
- *     Locking: May call functions taking tty->buf.lock
- */
-
-int tty_prepare_flip_string_flags(struct tty_struct *tty,
-                       unsigned char **chars, char **flags, size_t size)
-{
-       int space = tty_buffer_request_room(tty, size);
-       if (likely(space)) {
-               struct tty_buffer *tb = tty->buf.tail;
-               *chars = tb->char_buf_ptr + tb->used;
-               *flags = tb->flag_buf_ptr + tb->used;
-               tb->used += space;
-       }
-       return space;
-}
-
-EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
-
-
-
 /**
  *     get_tty_driver          -       find device of a tty
  *     @dev_t: device identifier
@@ -675,7 +274,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
                if (device < base || device >= base + p->num)
                        continue;
                *index = device - base;
-               return p;
+               return tty_driver_kref_get(p);
        }
        return NULL;
 }
@@ -719,7 +318,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
 
                if (tty_line >= 0 && tty_line <= p->num && p->ops &&
                    p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
-                       res = p;
+                       res = tty_driver_kref_get(p);
                        *line = tty_line;
                        break;
                }
@@ -819,20 +418,6 @@ static const struct file_operations tty_fops = {
        .fasync         = tty_fasync,
 };
 
-#ifdef CONFIG_UNIX98_PTYS
-static const struct file_operations ptmx_fops = {
-       .llseek         = no_llseek,
-       .read           = tty_read,
-       .write          = tty_write,
-       .poll           = tty_poll,
-       .unlocked_ioctl = tty_ioctl,
-       .compat_ioctl   = tty_compat_ioctl,
-       .open           = ptmx_open,
-       .release        = tty_release,
-       .fasync         = tty_fasync,
-};
-#endif
-
 static const struct file_operations console_fops = {
        .llseek         = no_llseek,
        .read           = tty_read,
@@ -953,6 +538,7 @@ static void do_tty_hangup(struct work_struct *work)
        struct tty_ldisc *ld;
        int    closecount = 0, n;
        unsigned long flags;
+       int refs = 0;
 
        if (!tty)
                return;
@@ -1019,8 +605,12 @@ static void do_tty_hangup(struct work_struct *work)
        if (tty->session) {
                do_each_pid_task(tty->session, PIDTYPE_SID, p) {
                        spin_lock_irq(&p->sighand->siglock);
-                       if (p->signal->tty == tty)
+                       if (p->signal->tty == tty) {
                                p->signal->tty = NULL;
+                               /* We defer the dereferences outside fo
+                                  the tasklist lock */
+                               refs++;
+                       }
                        if (!p->signal->leader) {
                                spin_unlock_irq(&p->sighand->siglock);
                                continue;
@@ -1046,6 +636,10 @@ static void do_tty_hangup(struct work_struct *work)
        tty->ctrl_status = 0;
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 
+       /* Account for the p->signal references we killed */
+       while (refs--)
+               tty_kref_put(tty);
+
        /*
         * If one of the devices matches a console pointer, we
         * cannot just call hangup() because that will cause
@@ -1114,6 +708,23 @@ void tty_vhangup(struct tty_struct *tty)
 
 EXPORT_SYMBOL(tty_vhangup);
 
+/**
+ *     tty_vhangup_self        -       process vhangup for own ctty
+ *
+ *     Perform a vhangup on the current controlling tty
+ */
+
+void tty_vhangup_self(void)
+{
+       struct tty_struct *tty;
+
+       tty = get_current_tty();
+       if (tty) {
+               tty_vhangup(tty);
+               tty_kref_put(tty);
+       }
+}
+
 /**
  *     tty_hung_up_p           -       was tty hung up
  *     @filp: file pointer of tty
@@ -1167,16 +778,14 @@ void disassociate_ctty(int on_exit)
        struct pid *tty_pgrp = NULL;
 
 
-       mutex_lock(&tty_mutex);
        tty = get_current_tty();
        if (tty) {
                tty_pgrp = get_pid(tty->pgrp);
                lock_kernel();
-               mutex_unlock(&tty_mutex);
-               /* XXX: here we race, there is nothing protecting tty */
                if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
                        tty_vhangup(tty);
                unlock_kernel();
+               tty_kref_put(tty);
        } else if (on_exit) {
                struct pid *old_pgrp;
                spin_lock_irq(&current->sighand->siglock);
@@ -1188,7 +797,6 @@ void disassociate_ctty(int on_exit)
                        kill_pgrp(old_pgrp, SIGCONT, on_exit);
                        put_pid(old_pgrp);
                }
-               mutex_unlock(&tty_mutex);
                return;
        }
        if (tty_pgrp) {
@@ -1203,8 +811,6 @@ void disassociate_ctty(int on_exit)
        current->signal->tty_old_pgrp = NULL;
        spin_unlock_irq(&current->sighand->siglock);
 
-       mutex_lock(&tty_mutex);
-       /* It is possible that do_tty_hangup has free'd this tty */
        tty = get_current_tty();
        if (tty) {
                unsigned long flags;
@@ -1214,13 +820,13 @@ void disassociate_ctty(int on_exit)
                tty->session = NULL;
                tty->pgrp = NULL;
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+               tty_kref_put(tty);
        } else {
 #ifdef TTY_DEBUG_HANGUP
                printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
                       " = NULL", tty);
 #endif
        }
-       mutex_unlock(&tty_mutex);
 
        /* Now clear signal->tty under the lock */
        read_lock(&tasklist_lock);
@@ -1420,19 +1026,19 @@ static inline ssize_t do_tty_write(
 
        /* write_buf/write_cnt is protected by the atomic_write_lock mutex */
        if (tty->write_cnt < chunk) {
-               unsigned char *buf;
+               unsigned char *buf_chunk;
 
                if (chunk < 1024)
                        chunk = 1024;
 
-               buf = kmalloc(chunk, GFP_KERNEL);
-               if (!buf) {
+               buf_chunk = kmalloc(chunk, GFP_KERNEL);
+               if (!buf_chunk) {
                        ret = -ENOMEM;
                        goto out;
                }
                kfree(tty->write_buf);
                tty->write_cnt = chunk;
-               tty->write_buf = buf;
+               tty->write_buf = buf_chunk;
        }
 
        /* Do the write .. */
@@ -1466,6 +1072,31 @@ out:
        return ret;
 }
 
+/**
+ * tty_write_message - write a message to a certain tty, not just the console.
+ * @tty: the destination tty_struct
+ * @msg: the message to write
+ *
+ * This is used for messages that need to be redirected to a specific tty.
+ * We don't put it into the syslog queue right now maybe in the future if
+ * really needed.
+ *
+ * We must still hold the BKL and test the CLOSING flag for the moment.
+ */
+
+void tty_write_message(struct tty_struct *tty, char *msg)
+{
+       lock_kernel();
+       if (tty) {
+               mutex_lock(&tty->atomic_write_lock);
+               if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags))
+                       tty->ops->write(tty, msg, strlen(msg));
+               tty_write_unlock(tty);
+       }
+       unlock_kernel();
+       return;
+}
+
 
 /**
  *     tty_write               -       write method for tty device file
@@ -1533,42 +1164,6 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,
        return tty_write(file, buf, count, ppos);
 }
 
-void tty_port_init(struct tty_port *port)
-{
-       memset(port, 0, sizeof(*port));
-       init_waitqueue_head(&port->open_wait);
-       init_waitqueue_head(&port->close_wait);
-       mutex_init(&port->mutex);
-       port->close_delay = (50 * HZ) / 100;
-       port->closing_wait = (3000 * HZ) / 100;
-}
-EXPORT_SYMBOL(tty_port_init);
-
-int tty_port_alloc_xmit_buf(struct tty_port *port)
-{
-       /* We may sleep in get_zeroed_page() */
-       mutex_lock(&port->mutex);
-       if (port->xmit_buf == NULL)
-               port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-       mutex_unlock(&port->mutex);
-       if (port->xmit_buf == NULL)
-               return -ENOMEM;
-       return 0;
-}
-EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
-
-void tty_port_free_xmit_buf(struct tty_port *port)
-{
-       mutex_lock(&port->mutex);
-       if (port->xmit_buf != NULL) {
-               free_page((unsigned long)port->xmit_buf);
-               port->xmit_buf = NULL;
-       }
-       mutex_unlock(&port->mutex);
-}
-EXPORT_SYMBOL(tty_port_free_xmit_buf);
-
-
 static char ptychar[] = "pqrstuvwxyzabcde";
 
 /**
@@ -1592,7 +1187,7 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
 }
 
 /**
- *     pty_line_name   -       generate name for a tty
+ *     tty_line_name   -       generate name for a tty
  *     @driver: the tty driver in use
  *     @index: the minor number
  *     @p: output buffer of at least 7 bytes
@@ -1608,10 +1203,148 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
 }
 
 /**
- *     init_dev                -       initialise a tty device
+ *     tty_driver_lookup_tty() - find an existing tty, if any
+ *     @driver: the driver for the tty
+ *     @idx:    the minor number
+ *
+ *     Return the tty, if found or ERR_PTR() otherwise.
+ *
+ *     Locking: tty_mutex must be held. If tty is found, the mutex must
+ *     be held until the 'fast-open' is also done. Will change once we
+ *     have refcounting in the driver and per driver locking
+ */
+struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
+               struct inode *inode, int idx)
+{
+       struct tty_struct *tty;
+
+       if (driver->ops->lookup)
+               return driver->ops->lookup(driver, inode, idx);
+
+       tty = driver->ttys[idx];
+       return tty;
+}
+
+/**
+ *     tty_init_termios        -  helper for termios setup
+ *     @tty: the tty to set up
+ *
+ *     Initialise the termios structures for this tty. Thus runs under
+ *     the tty_mutex currently so we can be relaxed about ordering.
+ */
+
+int tty_init_termios(struct tty_struct *tty)
+{
+       struct ktermios *tp;
+       int idx = tty->index;
+
+       tp = tty->driver->termios[idx];
+       if (tp == NULL) {
+               tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
+               if (tp == NULL)
+                       return -ENOMEM;
+               memcpy(tp, &tty->driver->init_termios,
+                                               sizeof(struct ktermios));
+               tty->driver->termios[idx] = tp;
+       }
+       tty->termios = tp;
+       tty->termios_locked = tp + 1;
+
+       /* Compatibility until drivers always set this */
+       tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
+       tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
+       return 0;
+}
+
+/**
+ *     tty_driver_install_tty() - install a tty entry in the driver
+ *     @driver: the driver for the tty
+ *     @tty: the tty
+ *
+ *     Install a tty object into the driver tables. The tty->index field
+ *     will be set by the time this is called. This method is responsible
+ *     for ensuring any need additional structures are allocated and
+ *     configured.
+ *
+ *     Locking: tty_mutex for now
+ */
+static int tty_driver_install_tty(struct tty_driver *driver,
+                                               struct tty_struct *tty)
+{
+       int idx = tty->index;
+
+       if (driver->ops->install)
+               return driver->ops->install(driver, tty);
+
+       if (tty_init_termios(tty) == 0) {
+               tty_driver_kref_get(driver);
+               tty->count++;
+               driver->ttys[idx] = tty;
+               return 0;
+       }
+       return -ENOMEM;
+}
+
+/**
+ *     tty_driver_remove_tty() - remove a tty from the driver tables
+ *     @driver: the driver for the tty
+ *     @idx:    the minor number
+ *
+ *     Remvoe a tty object from the driver tables. The tty->index field
+ *     will be set by the time this is called.
+ *
+ *     Locking: tty_mutex for now
+ */
+static void tty_driver_remove_tty(struct tty_driver *driver,
+                                               struct tty_struct *tty)
+{
+       if (driver->ops->remove)
+               driver->ops->remove(driver, tty);
+       else
+               driver->ttys[tty->index] = NULL;
+}
+
+/*
+ *     tty_reopen()    - fast re-open of an open tty
+ *     @tty    - the tty to open
+ *
+ *     Return 0 on success, -errno on error.
+ *
+ *     Locking: tty_mutex must be held from the time the tty was found
+ *              till this open completes.
+ */
+static int tty_reopen(struct tty_struct *tty)
+{
+       struct tty_driver *driver = tty->driver;
+
+       if (test_bit(TTY_CLOSING, &tty->flags))
+               return -EIO;
+
+       if (driver->type == TTY_DRIVER_TYPE_PTY &&
+           driver->subtype == PTY_TYPE_MASTER) {
+               /*
+                * special case for PTY masters: only one open permitted,
+                * and the slave side open count is incremented as well.
+                */
+               if (tty->count)
+                       return -EIO;
+
+               tty->link->count++;
+       }
+       tty->count++;
+       tty->driver = driver; /* N.B. why do this every time?? */
+
+       WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
+
+       return 0;
+}
+
+/**
+ *     tty_init_dev            -       initialise a tty device
  *     @driver: tty driver we are opening a device on
  *     @idx: device index
- *     @tty: returned tty structure
+ *     @ret_tty: returned tty structure
+ *     @first_ok: ok to open a new device (used by ptmx)
  *
  *     Prepare a tty device. This may not be a "new" clean device but
  *     could also be an active device. The pty drivers require special
@@ -1631,37 +1364,16 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
  * relaxed for the (most common) case of reopening a tty.
  */
 
-static int init_dev(struct tty_driver *driver, int idx,
-       struct tty_struct **ret_tty)
+struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
+                                                               int first_ok)
 {
-       struct tty_struct *tty, *o_tty;
-       struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
-       struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
-       int retval = 0;
+       struct tty_struct *tty;
+       int retval;
 
-       /* check whether we're reopening an existing tty */
-       if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
-               tty = devpts_get_tty(idx);
-               /*
-                * If we don't have a tty here on a slave open, it's because
-                * the master already started the close process and there's
-                * no relation between devpts file and tty anymore.
-                */
-               if (!tty && driver->subtype == PTY_TYPE_SLAVE) {
-                       retval = -EIO;
-                       goto end_init;
-               }
-               /*
-                * It's safe from now on because init_dev() is called with
-                * tty_mutex held and release_dev() won't change tty->count
-                * or tty->flags without having to grab tty_mutex
-                */
-               if (tty && driver->subtype == PTY_TYPE_MASTER)
-                       tty = tty->link;
-       } else {
-               tty = driver->ttys[idx];
-       }
-       if (tty) goto fast_track;
+       /* Check if pty master is being opened multiple times */
+       if (driver->subtype == PTY_TYPE_MASTER &&
+               (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok)
+               return ERR_PTR(-EIO);
 
        /*
         * First time open is complex, especially for PTY devices.
@@ -1671,189 +1383,69 @@ static int init_dev(struct tty_driver *driver, int idx,
         * and locked termios may be retained.)
         */
 
-       if (!try_module_get(driver->owner)) {
-               retval = -ENODEV;
-               goto end_init;
-       }
-
-       o_tty = NULL;
-       tp = o_tp = NULL;
-       ltp = o_ltp = NULL;
+       if (!try_module_get(driver->owner))
+               return ERR_PTR(-ENODEV);
 
        tty = alloc_tty_struct();
        if (!tty)
                goto fail_no_mem;
-       initialize_tty_struct(tty);
-       tty->driver = driver;
-       tty->ops = driver->ops;
-       tty->index = idx;
-       tty_line_name(driver, idx, tty->name);
-
-       if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
-               tp_loc = &tty->termios;
-               ltp_loc = &tty->termios_locked;
-       } else {
-               tp_loc = &driver->termios[idx];
-               ltp_loc = &driver->termios_locked[idx];
-       }
-
-       if (!*tp_loc) {
-               tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
-               if (!tp)
-                       goto free_mem_out;
-               *tp = driver->init_termios;
-       }
-
-       if (!*ltp_loc) {
-               ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
-               if (!ltp)
-                       goto free_mem_out;
-       }
-
-       if (driver->type == TTY_DRIVER_TYPE_PTY) {
-               o_tty = alloc_tty_struct();
-               if (!o_tty)
-                       goto free_mem_out;
-               initialize_tty_struct(o_tty);
-               o_tty->driver = driver->other;
-               o_tty->ops = driver->ops;
-               o_tty->index = idx;
-               tty_line_name(driver->other, idx, o_tty->name);
-
-               if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
-                       o_tp_loc = &o_tty->termios;
-                       o_ltp_loc = &o_tty->termios_locked;
-               } else {
-                       o_tp_loc = &driver->other->termios[idx];
-                       o_ltp_loc = &driver->other->termios_locked[idx];
-               }
-
-               if (!*o_tp_loc) {
-                       o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);
-                       if (!o_tp)
-                               goto free_mem_out;
-                       *o_tp = driver->other->init_termios;
-               }
-
-               if (!*o_ltp_loc) {
-                       o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
-                       if (!o_ltp)
-                               goto free_mem_out;
-               }
+       initialize_tty_struct(tty, driver, idx);
 
-               /*
-                * Everything allocated ... set up the o_tty structure.
-                */
-               if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM))
-                       driver->other->ttys[idx] = o_tty;
-               if (!*o_tp_loc)
-                       *o_tp_loc = o_tp;
-               if (!*o_ltp_loc)
-                       *o_ltp_loc = o_ltp;
-               o_tty->termios = *o_tp_loc;
-               o_tty->termios_locked = *o_ltp_loc;
-               driver->other->refcount++;
-               if (driver->subtype == PTY_TYPE_MASTER)
-                       o_tty->count++;
-
-               /* Establish the links in both directions */
-               tty->link   = o_tty;
-               o_tty->link = tty;
+       retval = tty_driver_install_tty(driver, tty);
+       if (retval < 0) {
+               free_tty_struct(tty);
+               module_put(driver->owner);
+               return ERR_PTR(retval);
        }
 
-       /*
-        * All structures have been allocated, so now we install them.
-        * Failures after this point use release_tty to clean up, so
-        * there's no need to null out the local pointers.
-        */
-       if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM))
-               driver->ttys[idx] = tty;
-
-       if (!*tp_loc)
-               *tp_loc = tp;
-       if (!*ltp_loc)
-               *ltp_loc = ltp;
-       tty->termios = *tp_loc;
-       tty->termios_locked = *ltp_loc;
-       /* Compatibility until drivers always set this */
-       tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
-       tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
-       driver->refcount++;
-       tty->count++;
-
        /*
         * Structures all installed ... call the ldisc open routines.
         * If we fail here just call release_tty to clean up.  No need
         * to decrement the use counts, as release_tty doesn't care.
         */
 
-       retval = tty_ldisc_setup(tty, o_tty);
-
+       retval = tty_ldisc_setup(tty, tty->link);
        if (retval)
                goto release_mem_out;
-        goto success;
-
-       /*
-        * This fast open can be used if the tty is already open.
-        * No memory is allocated, and the only failures are from
-        * attempting to open a closing tty or attempting multiple
-        * opens on a pty master.
-        */
-fast_track:
-       if (test_bit(TTY_CLOSING, &tty->flags)) {
-               retval = -EIO;
-               goto end_init;
-       }
-       if (driver->type == TTY_DRIVER_TYPE_PTY &&
-           driver->subtype == PTY_TYPE_MASTER) {
-               /*
-                * special case for PTY masters: only one open permitted,
-                * and the slave side open count is incremented as well.
-                */
-               if (tty->count) {
-                       retval = -EIO;
-                       goto end_init;
-               }
-               tty->link->count++;
-       }
-       tty->count++;
-       tty->driver = driver; /* N.B. why do this every time?? */
-
-       /* FIXME */
-       if (!test_bit(TTY_LDISC, &tty->flags))
-               printk(KERN_ERR "init_dev but no ldisc\n");
-success:
-       *ret_tty = tty;
-
-       /* All paths come through here to release the mutex */
-end_init:
-       return retval;
-
-       /* Release locally allocated memory ... nothing placed in slots */
-free_mem_out:
-       kfree(o_tp);
-       if (o_tty)
-               free_tty_struct(o_tty);
-       kfree(ltp);
-       kfree(tp);
-       free_tty_struct(tty);
+       return tty;
 
 fail_no_mem:
        module_put(driver->owner);
-       retval = -ENOMEM;
-       goto end_init;
+       return ERR_PTR(-ENOMEM);
 
        /* call the tty release_tty routine to clean out this slot */
 release_mem_out:
        if (printk_ratelimit())
-               printk(KERN_INFO "init_dev: ldisc open failed, "
+               printk(KERN_INFO "tty_init_dev: ldisc open failed, "
                                 "clearing slot %d\n", idx);
        release_tty(tty, idx);
-       goto end_init;
+       return ERR_PTR(retval);
+}
+
+void tty_free_termios(struct tty_struct *tty)
+{
+       struct ktermios *tp;
+       int idx = tty->index;
+       /* Kill this flag and push into drivers for locking etc */
+       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
+               /* FIXME: Locking on ->termios array */
+               tp = tty->termios;
+               tty->driver->termios[idx] = NULL;
+               kfree(tp);
+       }
+}
+EXPORT_SYMBOL(tty_free_termios);
+
+void tty_shutdown(struct tty_struct *tty)
+{
+       tty_driver_remove_tty(tty->driver, tty);
+       tty_free_termios(tty);
 }
+EXPORT_SYMBOL(tty_shutdown);
 
 /**
  *     release_one_tty         -       release tty structure memory
+ *     @kref: kref of tty we are obliterating
  *
  *     Releases memory associated with a tty structure, and clears out the
  *     driver table slots. This function is called when a device is no longer
@@ -1863,31 +1455,19 @@ release_mem_out:
  *             tty_mutex - sometimes only
  *             takes the file list lock internally when working on the list
  *     of ttys that the driver keeps.
- *             FIXME: should we require tty_mutex is held here ??
  */
-static void release_one_tty(struct tty_struct *tty, int idx)
+static void release_one_tty(struct kref *kref)
 {
-       int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM;
-       struct ktermios *tp;
-
-       if (!devpts)
-               tty->driver->ttys[idx] = NULL;
-
-       if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-               tp = tty->termios;
-               if (!devpts)
-                       tty->driver->termios[idx] = NULL;
-               kfree(tp);
-
-               tp = tty->termios_locked;
-               if (!devpts)
-                       tty->driver->termios_locked[idx] = NULL;
-               kfree(tp);
-       }
-
+       struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
+       struct tty_driver *driver = tty->driver;
 
+       if (tty->ops->shutdown)
+               tty->ops->shutdown(tty);
+       else
+               tty_shutdown(tty);
        tty->magic = 0;
-       tty->driver->refcount--;
+       tty_driver_kref_put(driver);
+       module_put(driver->owner);
 
        file_list_lock();
        list_del_init(&tty->tty_files);
@@ -1896,6 +1476,21 @@ static void release_one_tty(struct tty_struct *tty, int idx)
        free_tty_struct(tty);
 }
 
+/**
+ *     tty_kref_put            -       release a tty kref
+ *     @tty: tty device
+ *
+ *     Release a reference to a tty device and if need be let the kref
+ *     layer destruct the object for us
+ */
+
+void tty_kref_put(struct tty_struct *tty)
+{
+       if (tty)
+               kref_put(&tty->kref, release_one_tty);
+}
+EXPORT_SYMBOL(tty_kref_put);
+
 /**
  *     release_tty             -       release tty structure memory
  *
@@ -1907,15 +1502,16 @@ static void release_one_tty(struct tty_struct *tty, int idx)
  *             takes the file list lock internally when working on the list
  *     of ttys that the driver keeps.
  *             FIXME: should we require tty_mutex is held here ??
+ *
  */
 static void release_tty(struct tty_struct *tty, int idx)
 {
-       struct tty_driver *driver = tty->driver;
+       /* This should always be true but check for the moment */
+       WARN_ON(tty->index != idx);
 
        if (tty->link)
-               release_one_tty(tty->link, idx);
-       release_one_tty(tty, idx);
-       module_put(driver->owner);
+               tty_kref_put(tty->link);
+       tty_kref_put(tty);
 }
 
 /*
@@ -1926,20 +1522,21 @@ static void release_tty(struct tty_struct *tty, int idx)
  * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  * lead to double frees or releasing memory still in use.
  */
-static void release_dev(struct file *filp)
+void tty_release_dev(struct file *filp)
 {
        struct tty_struct *tty, *o_tty;
        int     pty_master, tty_closing, o_tty_closing, do_sleep;
        int     devpts;
        int     idx;
        char    buf[64];
+       struct  inode *inode;
 
+       inode = filp->f_path.dentry->d_inode;
        tty = (struct tty_struct *)filp->private_data;
-       if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode,
-                                                       "release_dev"))
+       if (tty_paranoia_check(tty, inode, "tty_release_dev"))
                return;
 
-       check_tty_count(tty, "release_dev");
+       check_tty_count(tty, "tty_release_dev");
 
        tty_fasync(-1, filp, 0);
 
@@ -1951,33 +1548,27 @@ static void release_dev(struct file *filp)
 
 #ifdef TTY_PARANOIA_CHECK
        if (idx < 0 || idx >= tty->driver->num) {
-               printk(KERN_DEBUG "release_dev: bad idx when trying to "
+               printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
                                  "free (%s)\n", tty->name);
                return;
        }
-       if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
+       if (!devpts) {
                if (tty != tty->driver->ttys[idx]) {
-                       printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
+                       printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
                               "for (%s)\n", idx, tty->name);
                        return;
                }
                if (tty->termios != tty->driver->termios[idx]) {
-                       printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
+                       printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
                               "for (%s)\n",
                               idx, tty->name);
                        return;
                }
-               if (tty->termios_locked != tty->driver->termios_locked[idx]) {
-                       printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
-                              "termios_locked for (%s)\n",
-                              idx, tty->name);
-                       return;
-               }
        }
 #endif
 
 #ifdef TTY_DEBUG_HANGUP
-       printk(KERN_DEBUG "release_dev of %s (tty count=%d)...",
+       printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...",
               tty_name(tty, buf), tty->count);
 #endif
 
@@ -1985,26 +1576,19 @@ static void release_dev(struct file *filp)
        if (tty->driver->other &&
             !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
                if (o_tty != tty->driver->other->ttys[idx]) {
-                       printk(KERN_DEBUG "release_dev: other->table[%d] "
+                       printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
                                          "not o_tty for (%s)\n",
                               idx, tty->name);
                        return;
                }
                if (o_tty->termios != tty->driver->other->termios[idx]) {
-                       printk(KERN_DEBUG "release_dev: other->termios[%d] "
+                       printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
                                          "not o_termios for (%s)\n",
                               idx, tty->name);
                        return;
                }
-               if (o_tty->termios_locked !=
-                     tty->driver->other->termios_locked[idx]) {
-                       printk(KERN_DEBUG "release_dev: other->termios_locked["
-                                         "%d] not o_termios_locked for (%s)\n",
-                              idx, tty->name);
-                       return;
-               }
                if (o_tty->link != tty) {
-                       printk(KERN_DEBUG "release_dev: bad pty pointers\n");
+                       printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
                        return;
                }
        }
@@ -2062,7 +1646,7 @@ static void release_dev(struct file *filp)
                if (!do_sleep)
                        break;
 
-               printk(KERN_WARNING "release_dev: %s: read/write wait queue "
+               printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
                                    "active!\n", tty_name(tty, buf));
                mutex_unlock(&tty_mutex);
                schedule();
@@ -2075,14 +1659,14 @@ static void release_dev(struct file *filp)
         */
        if (pty_master) {
                if (--o_tty->count < 0) {
-                       printk(KERN_WARNING "release_dev: bad pty slave count "
+                       printk(KERN_WARNING "tty_release_dev: bad pty slave count "
                                            "(%d) for %s\n",
                               o_tty->count, tty_name(o_tty, buf));
                        o_tty->count = 0;
                }
        }
        if (--tty->count < 0) {
-               printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n",
+               printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n",
                       tty->count, tty_name(tty, buf));
                tty->count = 0;
        }
@@ -2145,11 +1729,11 @@ static void release_dev(struct file *filp)
 
        /* Make this pty number available for reallocation */
        if (devpts)
-               devpts_kill_index(idx);
+               devpts_kill_index(inode, idx);
 }
 
 /**
- *     tty_open                -       open a tty device
+ *     __tty_open              -       open a tty device
  *     @inode: inode of device file
  *     @filp: file pointer to tty
  *
@@ -2164,14 +1748,14 @@ static void release_dev(struct file *filp)
  *     The termios state of a pty is reset on first open so that
  *     settings don't persist across reuse.
  *
- *     Locking: tty_mutex protects tty, get_tty_driver and init_dev work.
+ *     Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work.
  *              tty->count should protect the rest.
  *              ->siglock protects ->signal/->sighand
  */
 
 static int __tty_open(struct inode *inode, struct file *filp)
 {
-       struct tty_struct *tty;
+       struct tty_struct *tty = NULL;
        int noctty, retval;
        struct tty_driver *driver;
        int index;
@@ -2193,23 +1777,25 @@ retry_open:
                        mutex_unlock(&tty_mutex);
                        return -ENXIO;
                }
-               driver = tty->driver;
+               driver = tty_driver_kref_get(tty->driver);
                index = tty->index;
                filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
                /* noctty = 1; */
+               /* FIXME: Should we take a driver reference ? */
+               tty_kref_put(tty);
                goto got_driver;
        }
 #ifdef CONFIG_VT
        if (device == MKDEV(TTY_MAJOR, 0)) {
                extern struct tty_driver *console_driver;
-               driver = console_driver;
+               driver = tty_driver_kref_get(console_driver);
                index = fg_console;
                noctty = 1;
                goto got_driver;
        }
 #endif
        if (device == MKDEV(TTYAUX_MAJOR, 1)) {
-               driver = console_device(&index);
+               driver = tty_driver_kref_get(console_device(&index));
                if (driver) {
                        /* Don't let /dev/console block */
                        filp->f_flags |= O_NONBLOCK;
@@ -2226,10 +1812,25 @@ retry_open:
                return -ENODEV;
        }
 got_driver:
-       retval = init_dev(driver, index, &tty);
+       if (!tty) {
+               /* check whether we're reopening an existing tty */
+               tty = tty_driver_lookup_tty(driver, inode, index);
+
+               if (IS_ERR(tty))
+                       return PTR_ERR(tty);
+       }
+
+       if (tty) {
+               retval = tty_reopen(tty);
+               if (retval)
+                       tty = ERR_PTR(retval);
+       } else
+               tty = tty_init_dev(driver, index, 0);
+
        mutex_unlock(&tty_mutex);
-       if (retval)
-               return retval;
+       tty_driver_kref_put(driver);
+       if (IS_ERR(tty))
+               return PTR_ERR(tty);
 
        filp->private_data = tty;
        file_move(filp, &tty->tty_files);
@@ -2257,7 +1858,7 @@ got_driver:
                printk(KERN_DEBUG "error %d in opening %s...", retval,
                       tty->name);
 #endif
-               release_dev(filp);
+               tty_release_dev(filp);
                if (retval != -ERESTARTSYS)
                        return retval;
                if (signal_pending(current))
@@ -2296,69 +1897,6 @@ static int tty_open(struct inode *inode, struct file *filp)
 
 
 
-#ifdef CONFIG_UNIX98_PTYS
-/**
- *     ptmx_open               -       open a unix 98 pty master
- *     @inode: inode of device file
- *     @filp: file pointer to tty
- *
- *     Allocate a unix98 pty master device from the ptmx driver.
- *
- *     Locking: tty_mutex protects theinit_dev work. tty->count should
- *             protect the rest.
- *             allocated_ptys_lock handles the list of free pty numbers
- */
-
-static int __ptmx_open(struct inode *inode, struct file *filp)
-{
-       struct tty_struct *tty;
-       int retval;
-       int index;
-
-       nonseekable_open(inode, filp);
-
-       /* find a device that is not in use. */
-       index = devpts_new_index();
-       if (index < 0)
-               return index;
-
-       mutex_lock(&tty_mutex);
-       retval = init_dev(ptm_driver, index, &tty);
-       mutex_unlock(&tty_mutex);
-
-       if (retval)
-               goto out;
-
-       set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-       filp->private_data = tty;
-       file_move(filp, &tty->tty_files);
-
-       retval = devpts_pty_new(tty->link);
-       if (retval)
-               goto out1;
-
-       check_tty_count(tty, "ptmx_open");
-       retval = ptm_driver->ops->open(tty, filp);
-       if (!retval)
-               return 0;
-out1:
-       release_dev(filp);
-       return retval;
-out:
-       devpts_kill_index(index);
-       return retval;
-}
-
-static int ptmx_open(struct inode *inode, struct file *filp)
-{
-       int ret;
-
-       lock_kernel();
-       ret = __ptmx_open(inode, filp);
-       unlock_kernel();
-       return ret;
-}
-#endif
 
 /**
  *     tty_release             -       vfs callback for close
@@ -2369,13 +1907,13 @@ static int ptmx_open(struct inode *inode, struct file *filp)
  *     this tty. There may however be several such references.
  *
  *     Locking:
- *             Takes bkl. See release_dev
+ *             Takes bkl. See tty_release_dev
  */
 
 static int tty_release(struct inode *inode, struct file *filp)
 {
        lock_kernel();
-       release_dev(filp);
+       tty_release_dev(filp);
        unlock_kernel();
        return 0;
 }
@@ -2524,7 +2062,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
 
        /* For a PTY we need to lock the tty side */
        mutex_lock(&real_tty->termios_mutex);
-       if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
+       if (!memcmp(ws, &real_tty->winsize, sizeof(*ws)))
                goto done;
        /* Get the PID values and reference them so we can
           avoid holding the tty ctrl lock while sending signals */
@@ -2996,7 +2534,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case TIOCSTI:
                return tiocsti(tty, p);
        case TIOCGWINSZ:
-               return tiocgwinsz(tty, p);
+               return tiocgwinsz(real_tty, p);
        case TIOCSWINSZ:
                return tiocswinsz(tty, real_tty, p);
        case TIOCCONS:
@@ -3026,10 +2564,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return put_user(tty->ldisc.ops->num, (int __user *)p);
        case TIOCSETD:
                return tiocsetd(tty, p);
-#ifdef CONFIG_VT
-       case TIOCLINUX:
-               return tioclinux(tty, arg);
-#endif
        /*
         * Break handling
         */
@@ -3219,113 +2753,6 @@ void do_SAK(struct tty_struct *tty)
 
 EXPORT_SYMBOL(do_SAK);
 
-/**
- *     flush_to_ldisc
- *     @work: tty structure passed from work queue.
- *
- *     This routine is called out of the software interrupt to flush data
- *     from the buffer chain to the line discipline.
- *
- *     Locking: holds tty->buf.lock to guard buffer list. Drops the lock
- *     while invoking the line discipline receive_buf method. The
- *     receive_buf method is single threaded for each tty instance.
- */
-
-static void flush_to_ldisc(struct work_struct *work)
-{
-       struct tty_struct *tty =
-               container_of(work, struct tty_struct, buf.work.work);
-       unsigned long   flags;
-       struct tty_ldisc *disc;
-       struct tty_buffer *tbuf, *head;
-       char *char_buf;
-       unsigned char *flag_buf;
-
-       disc = tty_ldisc_ref(tty);
-       if (disc == NULL)       /*  !TTY_LDISC */
-               return;
-
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       /* So we know a flush is running */
-       set_bit(TTY_FLUSHING, &tty->flags);
-       head = tty->buf.head;
-       if (head != NULL) {
-               tty->buf.head = NULL;
-               for (;;) {
-                       int count = head->commit - head->read;
-                       if (!count) {
-                               if (head->next == NULL)
-                                       break;
-                               tbuf = head;
-                               head = head->next;
-                               tty_buffer_free(tty, tbuf);
-                               continue;
-                       }
-                       /* Ldisc or user is trying to flush the buffers
-                          we are feeding to the ldisc, stop feeding the
-                          line discipline as we want to empty the queue */
-                       if (test_bit(TTY_FLUSHPENDING, &tty->flags))
-                               break;
-                       if (!tty->receive_room) {
-                               schedule_delayed_work(&tty->buf.work, 1);
-                               break;
-                       }
-                       if (count > tty->receive_room)
-                               count = tty->receive_room;
-                       char_buf = head->char_buf_ptr + head->read;
-                       flag_buf = head->flag_buf_ptr + head->read;
-                       head->read += count;
-                       spin_unlock_irqrestore(&tty->buf.lock, flags);
-                       disc->ops->receive_buf(tty, char_buf,
-                                                       flag_buf, count);
-                       spin_lock_irqsave(&tty->buf.lock, flags);
-               }
-               /* Restore the queue head */
-               tty->buf.head = head;
-       }
-       /* We may have a deferred request to flush the input buffer,
-          if so pull the chain under the lock and empty the queue */
-       if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
-               __tty_buffer_flush(tty);
-               clear_bit(TTY_FLUSHPENDING, &tty->flags);
-               wake_up(&tty->read_wait);
-       }
-       clear_bit(TTY_FLUSHING, &tty->flags);
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-
-       tty_ldisc_deref(disc);
-}
-
-/**
- *     tty_flip_buffer_push    -       terminal
- *     @tty: tty to push
- *
- *     Queue a push of the terminal flip buffers to the line discipline. This
- *     function must not be called from IRQ context if tty->low_latency is set.
- *
- *     In the event of the queue being busy for flipping the work will be
- *     held off and retried later.
- *
- *     Locking: tty buffer lock. Driver locks in low latency mode.
- */
-
-void tty_flip_buffer_push(struct tty_struct *tty)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&tty->buf.lock, flags);
-       if (tty->buf.tail != NULL)
-               tty->buf.tail->commit = tty->buf.tail->used;
-       spin_unlock_irqrestore(&tty->buf.lock, flags);
-
-       if (tty->low_latency)
-               flush_to_ldisc(&tty->buf.work.work);
-       else
-               schedule_delayed_work(&tty->buf.work, 1);
-}
-
-EXPORT_SYMBOL(tty_flip_buffer_push);
-
-
 /**
  *     initialize_tty_struct
  *     @tty: tty to initialize
@@ -3336,9 +2763,11 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
  *     Locking: none - tty in question must not be exposed at this point
  */
 
-static void initialize_tty_struct(struct tty_struct *tty)
+void initialize_tty_struct(struct tty_struct *tty,
+               struct tty_driver *driver, int idx)
 {
        memset(tty, 0, sizeof(struct tty_struct));
+       kref_init(&tty->kref);
        tty->magic = TTY_MAGIC;
        tty_ldisc_init(tty);
        tty->session = NULL;
@@ -3346,7 +2775,6 @@ static void initialize_tty_struct(struct tty_struct *tty)
        tty->overrun_time = jiffies;
        tty->buf.head = tty->buf.tail = NULL;
        tty_buffer_init(tty);
-       INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
        mutex_init(&tty->termios_mutex);
        init_waitqueue_head(&tty->write_wait);
        init_waitqueue_head(&tty->read_wait);
@@ -3357,6 +2785,11 @@ static void initialize_tty_struct(struct tty_struct *tty)
        spin_lock_init(&tty->ctrl_lock);
        INIT_LIST_HEAD(&tty->tty_files);
        INIT_WORK(&tty->SAK_work, do_SAK_work);
+
+       tty->driver = driver;
+       tty->ops = driver->ops;
+       tty->index = idx;
+       tty_line_name(driver, idx, tty->name);
 }
 
 /**
@@ -3377,10 +2810,9 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch)
                return tty->ops->put_char(tty, ch);
        return tty->ops->write(tty, &ch, 1);
 }
-
 EXPORT_SYMBOL_GPL(tty_put_char);
 
-static struct class *tty_class;
+struct class *tty_class;
 
 /**
  *     tty_register_device - register a tty device
@@ -3418,8 +2850,9 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
        else
                tty_line_name(driver, index, name);
 
-       return device_create_drvdata(tty_class, device, dev, NULL, name);
+       return device_create(tty_class, device, dev, NULL, name);
 }
+EXPORT_SYMBOL(tty_register_device);
 
 /**
  *     tty_unregister_device - unregister a tty device
@@ -3437,8 +2870,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
        device_destroy(tty_class,
                MKDEV(driver->major, driver->minor_start) + index);
 }
-
-EXPORT_SYMBOL(tty_register_device);
 EXPORT_SYMBOL(tty_unregister_device);
 
 struct tty_driver *alloc_tty_driver(int lines)
@@ -3447,27 +2878,65 @@ struct tty_driver *alloc_tty_driver(int lines)
 
        driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
        if (driver) {
+               kref_init(&driver->kref);
                driver->magic = TTY_DRIVER_MAGIC;
                driver->num = lines;
                /* later we'll move allocation of tables here */
        }
        return driver;
 }
+EXPORT_SYMBOL(alloc_tty_driver);
 
-void put_tty_driver(struct tty_driver *driver)
+static void destruct_tty_driver(struct kref *kref)
 {
+       struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
+       int i;
+       struct ktermios *tp;
+       void *p;
+
+       if (driver->flags & TTY_DRIVER_INSTALLED) {
+               /*
+                * Free the termios and termios_locked structures because
+                * we don't want to get memory leaks when modular tty
+                * drivers are removed from the kernel.
+                */
+               for (i = 0; i < driver->num; i++) {
+                       tp = driver->termios[i];
+                       if (tp) {
+                               driver->termios[i] = NULL;
+                               kfree(tp);
+                       }
+                       if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
+                               tty_unregister_device(driver, i);
+               }
+               p = driver->ttys;
+               proc_tty_unregister_driver(driver);
+               driver->ttys = NULL;
+               driver->termios = NULL;
+               kfree(p);
+               cdev_del(&driver->cdev);
+       }
        kfree(driver);
 }
 
+void tty_driver_kref_put(struct tty_driver *driver)
+{
+       kref_put(&driver->kref, destruct_tty_driver);
+}
+EXPORT_SYMBOL(tty_driver_kref_put);
+
 void tty_set_operations(struct tty_driver *driver,
                        const struct tty_operations *op)
 {
        driver->ops = op;
 };
+EXPORT_SYMBOL(tty_set_operations);
 
-EXPORT_SYMBOL(alloc_tty_driver);
+void put_tty_driver(struct tty_driver *d)
+{
+       tty_driver_kref_put(d);
+}
 EXPORT_SYMBOL(put_tty_driver);
-EXPORT_SYMBOL(tty_set_operations);
 
 /*
  * Called by a tty driver to register itself.
@@ -3479,11 +2948,8 @@ int tty_register_driver(struct tty_driver *driver)
        dev_t dev;
        void **p = NULL;
 
-       if (driver->flags & TTY_DRIVER_INSTALLED)
-               return 0;
-
        if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
-               p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
+               p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
                if (!p)
                        return -ENOMEM;
        }
@@ -3507,12 +2973,9 @@ int tty_register_driver(struct tty_driver *driver)
        if (p) {
                driver->ttys = (struct tty_struct **)p;
                driver->termios = (struct ktermios **)(p + driver->num);
-               driver->termios_locked = (struct ktermios **)
-                                                       (p + driver->num * 2);
        } else {
                driver->ttys = NULL;
                driver->termios = NULL;
-               driver->termios_locked = NULL;
        }
 
        cdev_init(&driver->cdev, &tty_fops);
@@ -3521,7 +2984,7 @@ int tty_register_driver(struct tty_driver *driver)
        if (error) {
                unregister_chrdev_region(dev, driver->num);
                driver->ttys = NULL;
-               driver->termios = driver->termios_locked = NULL;
+               driver->termios = NULL;
                kfree(p);
                return error;
        }
@@ -3535,6 +2998,7 @@ int tty_register_driver(struct tty_driver *driver)
                    tty_register_device(driver, i, NULL);
        }
        proc_tty_register_driver(driver);
+       driver->flags |= TTY_DRIVER_INSTALLED;
        return 0;
 }
 
@@ -3545,46 +3009,19 @@ EXPORT_SYMBOL(tty_register_driver);
  */
 int tty_unregister_driver(struct tty_driver *driver)
 {
-       int i;
-       struct ktermios *tp;
-       void *p;
-
+#if 0
+       /* FIXME */
        if (driver->refcount)
                return -EBUSY;
-
+#endif
        unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
                                driver->num);
        mutex_lock(&tty_mutex);
        list_del(&driver->tty_drivers);
        mutex_unlock(&tty_mutex);
-
-       /*
-        * Free the termios and termios_locked structures because
-        * we don't want to get memory leaks when modular tty
-        * drivers are removed from the kernel.
-        */
-       for (i = 0; i < driver->num; i++) {
-               tp = driver->termios[i];
-               if (tp) {
-                       driver->termios[i] = NULL;
-                       kfree(tp);
-               }
-               tp = driver->termios_locked[i];
-               if (tp) {
-                       driver->termios_locked[i] = NULL;
-                       kfree(tp);
-               }
-               if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
-                       tty_unregister_device(driver, i);
-       }
-       p = driver->ttys;
-       proc_tty_unregister_driver(driver);
-       driver->ttys = NULL;
-       driver->termios = driver->termios_locked = NULL;
-       kfree(p);
-       cdev_del(&driver->cdev);
        return 0;
 }
+
 EXPORT_SYMBOL(tty_unregister_driver);
 
 dev_t tty_devnum(struct tty_struct *tty)
@@ -3595,9 +3032,13 @@ EXPORT_SYMBOL(tty_devnum);
 
 void proc_clear_tty(struct task_struct *p)
 {
-       spin_lock_irq(&p->sighand->siglock);
+       unsigned long flags;
+       struct tty_struct *tty;
+       spin_lock_irqsave(&p->sighand->siglock, flags);
+       tty = p->signal->tty;
        p->signal->tty = NULL;
-       spin_unlock_irq(&p->sighand->siglock);
+       spin_unlock_irqrestore(&p->sighand->siglock, flags);
+       tty_kref_put(tty);
 }
 
 /* Called under the sighand lock */
@@ -3613,9 +3054,13 @@ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
                tty->pgrp = get_pid(task_pgrp(tsk));
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                tty->session = get_pid(task_session(tsk));
+               if (tsk->signal->tty) {
+                       printk(KERN_DEBUG "tty not NULL!!\n");
+                       tty_kref_put(tsk->signal->tty);
+               }
        }
        put_pid(tsk->signal->tty_old_pgrp);
-       tsk->signal->tty = tty;
+       tsk->signal->tty = tty_kref_get(tty);
        tsk->signal->tty_old_pgrp = NULL;
 }
 
@@ -3629,18 +3074,20 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 struct tty_struct *get_current_tty(void)
 {
        struct tty_struct *tty;
-       WARN_ON_ONCE(!mutex_is_locked(&tty_mutex));
-       tty = current->signal->tty;
-       /*
-        * session->tty can be changed/cleared from under us, make sure we
-        * issue the load. The obtained pointer, when not NULL, is valid as
-        * long as we hold tty_mutex.
-        */
-       barrier();
+       unsigned long flags;
+
+       spin_lock_irqsave(&current->sighand->siglock, flags);
+       tty = tty_kref_get(current->signal->tty);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
        return tty;
 }
 EXPORT_SYMBOL_GPL(get_current_tty);
 
+void tty_default_fops(struct file_operations *fops)
+{
+       *fops = tty_fops;
+}
+
 /*
  * Initialize the console device. This is called *early*, so
  * we can't necessarily depend on lots of kernel help here.
@@ -3678,12 +3125,6 @@ postcore_initcall(tty_class_init);
 /* 3/2004 jmc: why do these devices exist? */
 
 static struct cdev tty_cdev, console_cdev;
-#ifdef CONFIG_UNIX98_PTYS
-static struct cdev ptmx_cdev;
-#endif
-#ifdef CONFIG_VT
-static struct cdev vc0_cdev;
-#endif
 
 /*
  * Ok, now we can initialize the rest of the tty devices and can count
@@ -3695,32 +3136,18 @@ static int __init tty_init(void)
        if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
                panic("Couldn't register /dev/tty driver\n");
-       device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
+       device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
                              "tty");
 
        cdev_init(&console_cdev, &console_fops);
        if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
                panic("Couldn't register /dev/console driver\n");
-       device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+       device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
                              "console");
 
-#ifdef CONFIG_UNIX98_PTYS
-       cdev_init(&ptmx_cdev, &ptmx_fops);
-       if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
-           register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
-               panic("Couldn't register /dev/ptmx driver\n");
-       device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
-#endif
-
 #ifdef CONFIG_VT
-       cdev_init(&vc0_cdev, &console_fops);
-       if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
-           register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
-               panic("Couldn't register /dev/tty0 driver\n");
-       device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
-
-       vty_init();
+       vty_init(&console_fops);
 #endif
        return 0;
 }
index bf34e45974212fc46df349416646779d2e7d78dd..a408c8e487ec006147078f2f7d22b6bce88925bb 100644 (file)
 #define TERMIOS_OLD    8
 
 
+/**
+ *     tty_chars_in_buffer     -       characters pending
+ *     @tty: terminal
+ *
+ *     Return the number of bytes of data in the device private
+ *     output queue. If no private method is supplied there is assumed
+ *     to be no queue on the device.
+ */
+
 int tty_chars_in_buffer(struct tty_struct *tty)
 {
        if (tty->ops->chars_in_buffer)
@@ -47,26 +56,49 @@ int tty_chars_in_buffer(struct tty_struct *tty)
        else
                return 0;
 }
-
 EXPORT_SYMBOL(tty_chars_in_buffer);
 
+/**
+ *     tty_write_room          -       write queue space
+ *     @tty: terminal
+ *
+ *     Return the number of bytes that can be queued to this device
+ *     at the present time. The result should be treated as a guarantee
+ *     and the driver cannot offer a value it later shrinks by more than
+ *     the number of bytes written. If no method is provided 2K is always
+ *     returned and data may be lost as there will be no flow control.
+ */
 int tty_write_room(struct tty_struct *tty)
 {
        if (tty->ops->write_room)
                return tty->ops->write_room(tty);
        return 2048;
 }
-
 EXPORT_SYMBOL(tty_write_room);
 
+/**
+ *     tty_driver_flush_buffer -       discard internal buffer
+ *     @tty: terminal
+ *
+ *     Discard the internal output buffer for this device. If no method
+ *     is provided then either the buffer cannot be hardware flushed or
+ *     there is no buffer driver side.
+ */
 void tty_driver_flush_buffer(struct tty_struct *tty)
 {
        if (tty->ops->flush_buffer)
                tty->ops->flush_buffer(tty);
 }
-
 EXPORT_SYMBOL(tty_driver_flush_buffer);
 
+/**
+ *     tty_throttle            -       flow control
+ *     @tty: terminal
+ *
+ *     Indicate that a tty should stop transmitting data down the stack.
+ */
+
 void tty_throttle(struct tty_struct *tty)
 {
        /* check TTY_THROTTLED first so it indicates our state */
@@ -76,6 +108,13 @@ void tty_throttle(struct tty_struct *tty)
 }
 EXPORT_SYMBOL(tty_throttle);
 
+/**
+ *     tty_unthrottle          -       flow control
+ *     @tty: terminal
+ *
+ *     Indicate that a tty may continue transmitting data down the stack.
+ */
+
 void tty_unthrottle(struct tty_struct *tty)
 {
        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
@@ -112,6 +151,11 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 }
 EXPORT_SYMBOL(tty_wait_until_sent);
 
+
+/*
+ *             Termios Helper Methods
+ */
+
 static void unset_locked_termios(struct ktermios *termios,
                                 struct ktermios *old,
                                 struct ktermios *locked)
@@ -346,6 +390,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
 }
 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
 
+/**
+ *     tty_encode_baud_rate            -       set baud rate of the tty
+ *     @ibaud: input baud rate
+ *     @obad: output baud rate
+ *
+ *     Update the current termios data for the tty with the new speed
+ *     settings. The caller must hold the termios_mutex for the tty in
+ *     question.
+ */
+
 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
 {
        tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
@@ -430,12 +484,11 @@ EXPORT_SYMBOL(tty_termios_hw_change);
  *     is a bit of layering violation here with n_tty in terms of the
  *     internal knowledge of this function.
  *
- *     Locking: termios_sem
+ *     Locking: termios_mutex
  */
 
 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
 {
-       int canon_change;
        struct ktermios old_termios;
        struct tty_ldisc *ld;
        unsigned long flags;
@@ -451,18 +504,6 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
        old_termios = *tty->termios;
        *tty->termios = *new_termios;
        unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
-       canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
-       if (canon_change) {
-               memset(&tty->read_flags, 0, sizeof tty->read_flags);
-               tty->canon_head = tty->read_tail;
-               tty->canon_data = 0;
-               tty->erasing = 0;
-       }
-
-       /* This bit should be in the ldisc code */
-       if (canon_change && !L_ICANON(tty) && tty->read_cnt)
-               /* Get characters left over from canonical mode. */
-               wake_up_interruptible(&tty->read_wait);
 
        /* See if packet mode change of state. */
        if (tty->link && tty->link->packet) {
@@ -508,7 +549,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
  *     functions before using change_termios to do the actual changes.
  *
  *     Locking:
- *             Called functions take ldisc and termios_sem locks
+ *             Called functions take ldisc and termios_mutex locks
  */
 
 static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
@@ -579,25 +620,51 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio)
        return 0;
 }
 
-static unsigned long inq_canon(struct tty_struct *tty)
+
+#ifdef TCGETX
+
+/**
+ *     set_termiox     -       set termiox fields if possible
+ *     @tty: terminal
+ *     @arg: termiox structure from user
+ *     @opt: option flags for ioctl type
+ *
+ *     Implement the device calling points for the SYS5 termiox ioctl
+ *     interface in Linux
+ */
+
+static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
 {
-       int nr, head, tail;
+       struct termiox tnew;
+       struct tty_ldisc *ld;
 
-       if (!tty->canon_data || !tty->read_buf)
-               return 0;
-       head = tty->canon_head;
-       tail = tty->read_tail;
-       nr = (head - tail) & (N_TTY_BUF_SIZE-1);
-       /* Skip EOF-chars.. */
-       while (head != tail) {
-               if (test_bit(tail, tty->read_flags) &&
-                   tty->read_buf[tail] == __DISABLED_CHAR)
-                       nr--;
-               tail = (tail+1) & (N_TTY_BUF_SIZE-1);
+       if (tty->termiox == NULL)
+               return -EINVAL;
+       if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
+               return -EFAULT;
+
+       ld = tty_ldisc_ref(tty);
+       if (ld != NULL) {
+               if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
+                       ld->ops->flush_buffer(tty);
+               tty_ldisc_deref(ld);
        }
-       return nr;
+       if (opt & TERMIOS_WAIT) {
+               tty_wait_until_sent(tty, 0);
+               if (signal_pending(current))
+                       return -EINTR;
+       }
+
+       mutex_lock(&tty->termios_mutex);
+       if (tty->ops->set_termiox)
+               tty->ops->set_termiox(tty, &tnew);
+       mutex_unlock(&tty->termios_mutex);
+       return 0;
 }
 
+#endif
+
+
 #ifdef TIOCGETP
 /*
  * These are deprecated, but there is limited support..
@@ -671,7 +738,7 @@ static void set_sgflags(struct ktermios *termios, int flags)
  *     Updates a terminal from the legacy BSD style terminal information
  *     structure.
  *
- *     Locking: termios_sem
+ *     Locking: termios_mutex
  */
 
 static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
@@ -849,6 +916,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 {
        struct tty_struct *real_tty;
        void __user *p = (void __user *)arg;
+       int ret = 0;
 
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
            tty->driver->subtype == PTY_TYPE_MASTER)
@@ -884,18 +952,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                return set_termios(real_tty, p, TERMIOS_OLD);
 #ifndef TCGETS2
        case TCGETS:
+               mutex_lock(&real_tty->termios_mutex);
                if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
 #else
        case TCGETS:
+               mutex_lock(&real_tty->termios_mutex);
                if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
        case TCGETS2:
+               mutex_lock(&real_tty->termios_mutex);
                if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
        case TCSETSF2:
                return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
        case TCSETSW2:
@@ -913,34 +987,59 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                return set_termios(real_tty, p, TERMIOS_TERMIO);
 #ifndef TCGETS2
        case TIOCGLCKTRMIOS:
+               mutex_lock(&real_tty->termios_mutex);
                if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
        case TIOCSLCKTRMIOS:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
+               mutex_lock(&real_tty->termios_mutex);
                if (user_termios_to_kernel_termios(real_tty->termios_locked,
                                               (struct termios __user *) arg))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
 #else
        case TIOCGLCKTRMIOS:
+               mutex_lock(&real_tty->termios_mutex);
                if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
        case TIOCSLCKTRMIOS:
                if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
+                       ret = -EPERM;
+               mutex_lock(&real_tty->termios_mutex);
                if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
                                               (struct termios __user *) arg))
-                       return -EFAULT;
-                       return 0;
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
 #endif
+#ifdef TCGETX
+       case TCGETX:
+               if (real_tty->termiox == NULL)
+                       return -EINVAL;
+               mutex_lock(&real_tty->termios_mutex);
+               if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
+                       ret = -EFAULT;
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
+       case TCSETX:
+               return set_termiox(real_tty, p, 0);
+       case TCSETXW:
+               return set_termiox(real_tty, p, TERMIOS_WAIT);
+       case TCSETXF:
+               return set_termiox(real_tty, p, TERMIOS_FLUSH);
+#endif         
        case TIOCGSOFTCAR:
-               /* FIXME: for correctness we may need to take the termios
-                  lock here - review */
-               return put_user(C_CLOCAL(real_tty) ? 1 : 0,
+               mutex_lock(&real_tty->termios_mutex);
+               ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
                                                (int __user *)arg);
+               mutex_unlock(&real_tty->termios_mutex);
+               return ret;
        case TIOCSSOFTCAR:
                if (get_user(arg, (unsigned int __user *) arg))
                        return -EFAULT;
@@ -980,7 +1079,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
 }
 EXPORT_SYMBOL_GPL(tty_perform_flush);
 
-int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        unsigned long flags;
@@ -1018,13 +1117,6 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                return 0;
        case TCFLSH:
                return tty_perform_flush(tty, arg);
-       case TIOCOUTQ:
-               return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
-       case TIOCINQ:
-               retval = tty->read_cnt;
-               if (L_ICANON(tty))
-                       retval = inq_canon(tty);
-               return put_user(retval, (unsigned int __user *) arg);
        case TIOCPKT:
        {
                int pktmode;
@@ -1050,4 +1142,4 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                return tty_mode_ioctl(tty, file, cmd, arg);
        }
 }
-EXPORT_SYMBOL(n_tty_ioctl);
+EXPORT_SYMBOL(n_tty_ioctl_helper);
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
new file mode 100644 (file)
index 0000000..553b0e9
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Tty port functions
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+void tty_port_init(struct tty_port *port)
+{
+       memset(port, 0, sizeof(*port));
+       init_waitqueue_head(&port->open_wait);
+       init_waitqueue_head(&port->close_wait);
+       mutex_init(&port->mutex);
+       spin_lock_init(&port->lock);
+       port->close_delay = (50 * HZ) / 100;
+       port->closing_wait = (3000 * HZ) / 100;
+}
+EXPORT_SYMBOL(tty_port_init);
+
+int tty_port_alloc_xmit_buf(struct tty_port *port)
+{
+       /* We may sleep in get_zeroed_page() */
+       mutex_lock(&port->mutex);
+       if (port->xmit_buf == NULL)
+               port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+       mutex_unlock(&port->mutex);
+       if (port->xmit_buf == NULL)
+               return -ENOMEM;
+       return 0;
+}
+EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
+
+void tty_port_free_xmit_buf(struct tty_port *port)
+{
+       mutex_lock(&port->mutex);
+       if (port->xmit_buf != NULL) {
+               free_page((unsigned long)port->xmit_buf);
+               port->xmit_buf = NULL;
+       }
+       mutex_unlock(&port->mutex);
+}
+EXPORT_SYMBOL(tty_port_free_xmit_buf);
+
+
+/**
+ *     tty_port_tty_get        -       get a tty reference
+ *     @port: tty port
+ *
+ *     Return a refcount protected tty instance or NULL if the port is not
+ *     associated with a tty (eg due to close or hangup)
+ */
+
+struct tty_struct *tty_port_tty_get(struct tty_port *port)
+{
+       unsigned long flags;
+       struct tty_struct *tty;
+
+       spin_lock_irqsave(&port->lock, flags);
+       tty = tty_kref_get(port->tty);
+       spin_unlock_irqrestore(&port->lock, flags);
+       return tty;
+}
+EXPORT_SYMBOL(tty_port_tty_get);
+
+/**
+ *     tty_port_tty_set        -       set the tty of a port
+ *     @port: tty port
+ *     @tty: the tty
+ *
+ *     Associate the port and tty pair. Manages any internal refcounts.
+ *     Pass NULL to deassociate a port
+ */
+
+void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       if (port->tty)
+               tty_kref_put(port->tty);
+       port->tty = tty;
+       spin_unlock_irqrestore(&port->lock, flags);
+}
+EXPORT_SYMBOL(tty_port_tty_set);
index c2ae52dd53d1a6447affa697afaa53c9f9f9f7f7..4f3b3f95fc42b4bb7bcf03a561aa5f69c48a393d 100644 (file)
@@ -481,10 +481,10 @@ static struct class *vc_class;
 
 void vcs_make_sysfs(struct tty_struct *tty)
 {
-       device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
-                             NULL, "vcs%u", tty->index + 1);
-       device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
-                             NULL, "vcsa%u", tty->index + 1);
+       device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL,
+                     "vcs%u", tty->index + 1);
+       device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL,
+                     "vcsa%u", tty->index + 1);
 }
 
 void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@ int __init vcs_init(void)
                panic("unable to get major %d for vcs device", VCS_MAJOR);
        vc_class = class_create(THIS_MODULE, "vc");
 
-       device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
-       device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+       device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+       device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
        return 0;
 }
index 7a70a40ad639855b4f3880386ef7b34f47d71f46..ffc9254f7e029d26c7cd0d0d38f75d7f32570e2c 100644 (file)
@@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        state[i].cur_part = 0;
        for (j = 0; j < MAX_PARTITIONS; ++j)
                state[i].part_stat_rwi[j] = VIOT_IDLE;
-       device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
-                             NULL, "iseries!vt%d", i);
-       device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
-                             NULL, "iseries!nvt%d", i);
+       device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
+                     "iseries!vt%d", i);
+       device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL,
+                     "iseries!nvt%d", i);
        printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
                        "resource %10.10s type %4.4s, model %3.3s\n",
                        i, viotape_unitinfo[i].rsrcname,
index 60359c360912c7d4dddee8e76a6a4ffb2c576e7e..d8f83e26e4a4de09210646ea5733d719c42649b4 100644 (file)
@@ -59,7 +59,7 @@
  * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
  *
  * Removed old-style timers, introduced console_timer, made timer
- * deletion SMP-safe.  17Jun00, Andrew Morton <andrewm@uow.edu.au>
+ * deletion SMP-safe.  17Jun00, Andrew Morton
  *
  * Removed console_lock, enabled interrupts across all console operations
  * 13 March 2001, Andrew Morton
 #include <linux/font.h>
 #include <linux/bitops.h>
 #include <linux/notifier.h>
-
-#include <asm/io.h>
+#include <linux/device.h>
+#include <linux/io.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define MAX_NR_CON_DRIVER 16
 
@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
        d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
        s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
        scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
-       scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char,
+       scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
                    vc->vc_size_row * nr);
 }
 
@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
        s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
        step = vc->vc_cols * nr;
        scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
-       scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step);
+       scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
 }
 
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -434,7 +434,6 @@ static void update_attr(struct vc_data *vc)
                      vc->vc_blink, vc->vc_underline,
                      vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
        vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
-       vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -2136,27 +2135,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
            release_console_sem();
            return 0;
        }
-       release_console_sem();
-
        orig_buf = buf;
        orig_count = count;
 
-       /* At this point 'buf' is guaranteed to be a kernel buffer
-        * and therefore no access to userspace (and therefore sleeping)
-        * will be needed.  The con_buf_mtx serializes all tty based
-        * console rendering and vcs write/read operations.  We hold
-        * the console spinlock during the entire write.
-        */
-
-       acquire_console_sem();
-
-       vc = tty->driver_data;
-       if (vc == NULL) {
-               printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
-               release_console_sem();
-               goto out;
-       }
-
        himask = vc->vc_hi_font_mask;
        charmask = himask ? 0x1ff : 0xff;
 
@@ -2370,8 +2351,6 @@ rescan_last_byte:
        FLUSH
        console_conditional_schedule();
        release_console_sem();
-
-out:
        notify_update(vc);
        return n;
 #undef FLUSH
@@ -2583,8 +2562,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        int lines;
        int ret;
 
-       if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE)
-               return -EINVAL;
        if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (get_user(type, p))
@@ -2778,6 +2755,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
                ret = vc_allocate(currcons);
                if (ret == 0) {
                        struct vc_data *vc = vc_cons[currcons].d;
+
+                       /* Still being freed */
+                       if (vc->vc_tty) {
+                               release_console_sem();
+                               return -ERESTARTSYS;
+                       }
                        tty->driver_data = vc;
                        vc->vc_tty = tty;
 
@@ -2798,34 +2781,20 @@ static int con_open(struct tty_struct *tty, struct file *filp)
        return ret;
 }
 
-/*
- * We take tty_mutex in here to prevent another thread from coming in via init_dev
- * and taking a ref against the tty while we're in the process of forgetting
- * about it and cleaning things up.
- *
- * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
- */
 static void con_close(struct tty_struct *tty, struct file *filp)
 {
-       mutex_lock(&tty_mutex);
-       acquire_console_sem();
-       if (tty && tty->count == 1) {
-               struct vc_data *vc = tty->driver_data;
+       /* Nothing to do - we defer to shutdown */
+}
 
-               if (vc)
-                       vc->vc_tty = NULL;
-               tty->driver_data = NULL;
-               vcs_remove_sysfs(tty);
-               release_console_sem();
-               mutex_unlock(&tty_mutex);
-               /*
-                * tty_mutex is released, but we still hold BKL, so there is
-                * still exclusion against init_dev()
-                */
-               return;
-       }
+static void con_shutdown(struct tty_struct *tty)
+{
+       struct vc_data *vc = tty->driver_data;
+       BUG_ON(vc == NULL);
+       acquire_console_sem();
+       vc->vc_tty = NULL;
+       vcs_remove_sysfs(tty);
        release_console_sem();
-       mutex_unlock(&tty_mutex);
+       tty_shutdown(tty);
 }
 
 static int default_italic_color    = 2; // green (ASCII)
@@ -2950,10 +2919,19 @@ static const struct tty_operations con_ops = {
        .throttle = con_throttle,
        .unthrottle = con_unthrottle,
        .resize = vt_resize,
+       .shutdown = con_shutdown
 };
 
-int __init vty_init(void)
+static struct cdev vc0_cdev;
+
+int __init vty_init(const struct file_operations *console_fops)
 {
+       cdev_init(&vc0_cdev, console_fops);
+       if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
+           register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
+               panic("Couldn't register /dev/tty0 driver\n");
+       device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+
        vcs_init();
 
        console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
@@ -2972,7 +2950,6 @@ int __init vty_init(void)
        tty_set_operations(console_driver, &con_ops);
        if (tty_register_driver(console_driver))
                panic("Couldn't register console driver\n");
-
        kbd_init();
        console_map_init();
 #ifdef CONFIG_PROM_CONSOLE
@@ -3466,7 +3443,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
        if (retval)
                goto err;
 
-       con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
+       con_driver->dev = device_create(vtconsole_class, NULL,
                                                MKDEV(0, con_driver->node),
                                                NULL, "vtcon%i",
                                                con_driver->node);
@@ -3577,7 +3554,7 @@ static int __init vtconsole_class_init(void)
                struct con_driver *con = &registered_con_driver[i];
 
                if (con->con && !con->dev) {
-                       con->dev = device_create_drvdata(vtconsole_class, NULL,
+                       con->dev = device_create(vtconsole_class, NULL,
                                                         MKDEV(0, con->node),
                                                         NULL, "vtcon%i",
                                                         con->node);
index c904e9ad4a71a396d5fa3c06747065b99335d392..8944ce508e2fea56a489501023a7dcdc8a22bb81 100644 (file)
@@ -395,6 +395,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
  
        kbd = kbd_table + console;
        switch (cmd) {
+       case TIOCLINUX:
+               return tioclinux(tty, arg);
        case KIOCSOUND:
                if (!perm)
                        goto eperm;
index 278c9857bcf548c14de1c8b7fed133530c6e82f4..ed132fe55d3d35aad97339593d5a131fc601b8ba 100644 (file)
@@ -657,8 +657,7 @@ static int __devinit hwicap_setup(struct device *dev, int id,
                goto failed3;
        }
 
-       device_create_drvdata(icap_class, dev, devt, NULL,
-                             "%s%d", DRIVER_NAME, id);
+       device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
        return 0;               /* success */
 
  failed3:
index 7af4b403bd2d12a6f3219f8f8d6615f5de69def1..bb538b9690e08186ae6c7d73240901b95b6b9ee3 100644 (file)
@@ -15,9 +15,8 @@ int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
        struct device *cd;
        static int req_count;
 
-       cd = device_create_drvdata(dca_class, dca->cd,
-                                  MKDEV(0, slot + 1), NULL,
-                                  "requester%d", req_count++);
+       cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1), NULL,
+                          "requester%d", req_count++);
        if (IS_ERR(cd))
                return PTR_ERR(cd);
        return 0;
@@ -48,8 +47,7 @@ idr_try_again:
                return err;
        }
 
-       cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
-                                  "dca%d", dca->id);
+       cd = device_create(dca_class, dev, MKDEV(0, 0), NULL, "dca%d", dca->id);
        if (IS_ERR(cd)) {
                spin_lock(&dca_idr_lock);
                idr_remove(&dca_idr, dca->id);
index 4a16b5b61cfbdc702530e735af2bbb7a0eac1d2b..f0d9b415db50741bc18f73614be3e7730623b411 100644 (file)
 #define                        FERR_NF_UNCORRECTABLE   (FERR_NF_M12ERR | \
                                                        FERR_NF_M11ERR | \
                                                        FERR_NF_M10ERR | \
+                                                       FERR_NF_M9ERR | \
                                                        FERR_NF_M8ERR | \
                                                        FERR_NF_M7ERR | \
                                                        FERR_NF_M6ERR | \
@@ -301,6 +302,9 @@ static char *numcol_toString[] = {
 };
 #endif
 
+/* enables the report of miscellaneous messages as CE errors - default off */
+static int misc_messages;
+
 /* Enumeration of supported devices */
 enum i5000_chips {
        I5000P = 0,
@@ -466,7 +470,8 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
                                        struct i5000_error_info *info,
                                        int handle_errors)
 {
-       char msg[EDAC_MC_LABEL_LEN + 1 + 90];
+       char msg[EDAC_MC_LABEL_LEN + 1 + 160];
+       char *specific = NULL;
        u32 allErrors;
        int branch;
        int channel;
@@ -480,11 +485,6 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
        if (!allErrors)
                return;         /* if no error, return now */
 
-       /* ONLY ONE of the possible error bits will be set, as per the docs */
-       i5000_mc_printk(mci, KERN_ERR,
-                       "FATAL ERRORS Found!!! 1st FATAL Err Reg= 0x%x\n",
-                       allErrors);
-
        branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
        channel = branch;
 
@@ -501,28 +501,42 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
                rdwr ? "Write" : "Read", ras, cas);
 
        /* Only 1 bit will be on */
-       if (allErrors & FERR_FAT_M1ERR) {
-               i5000_mc_printk(mci, KERN_ERR,
-                               "Alert on non-redundant retry or fast "
-                               "reset timeout\n");
-
-       } else if (allErrors & FERR_FAT_M2ERR) {
-               i5000_mc_printk(mci, KERN_ERR,
-                               "Northbound CRC error on non-redundant "
-                               "retry\n");
-
-       } else if (allErrors & FERR_FAT_M3ERR) {
-               i5000_mc_printk(mci, KERN_ERR,
-                               ">Tmid Thermal event with intelligent "
-                               "throttling disabled\n");
+       switch (allErrors) {
+       case FERR_FAT_M1ERR:
+               specific = "Alert on non-redundant retry or fast "
+                               "reset timeout";
+               break;
+       case FERR_FAT_M2ERR:
+               specific = "Northbound CRC error on non-redundant "
+                               "retry";
+               break;
+       case FERR_FAT_M3ERR:
+               {
+               static int done;
+
+               /*
+                * This error is generated to inform that the intelligent
+                * throttling is disabled and the temperature passed the
+                * specified middle point. Since this is something the BIOS
+                * should take care of, we'll warn only once to avoid
+                * worthlessly flooding the log.
+                */
+               if (done)
+                       return;
+               done++;
+
+               specific = ">Tmid Thermal event with intelligent "
+                          "throttling disabled";
+               }
+               break;
        }
 
        /* Form out message */
        snprintf(msg, sizeof(msg),
                 "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d "
-                "FATAL Err=0x%x)",
+                "FATAL Err=0x%x (%s))",
                 branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
-                allErrors);
+                allErrors, specific);
 
        /* Call the helper to output message */
        edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
@@ -539,7 +553,8 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
                                        struct i5000_error_info *info,
                                        int handle_errors)
 {
-       char msg[EDAC_MC_LABEL_LEN + 1 + 90];
+       char msg[EDAC_MC_LABEL_LEN + 1 + 170];
+       char *specific = NULL;
        u32 allErrors;
        u32 ue_errors;
        u32 ce_errors;
@@ -557,10 +572,6 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
                return;         /* if no error, return now */
 
        /* ONLY ONE of the possible error bits will be set, as per the docs */
-       i5000_mc_printk(mci, KERN_WARNING,
-                       "NON-FATAL ERRORS Found!!! 1st NON-FATAL Err "
-                       "Reg= 0x%x\n", allErrors);
-
        ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
        if (ue_errors) {
                debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
@@ -579,12 +590,47 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
                        rank, channel, channel + 1, branch >> 1, bank,
                        rdwr ? "Write" : "Read", ras, cas);
 
+               switch (ue_errors) {
+               case FERR_NF_M12ERR:
+                       specific = "Non-Aliased Uncorrectable Patrol Data ECC";
+                       break;
+               case FERR_NF_M11ERR:
+                       specific = "Non-Aliased Uncorrectable Spare-Copy "
+                                       "Data ECC";
+                       break;
+               case FERR_NF_M10ERR:
+                       specific = "Non-Aliased Uncorrectable Mirrored Demand "
+                                       "Data ECC";
+                       break;
+               case FERR_NF_M9ERR:
+                       specific = "Non-Aliased Uncorrectable Non-Mirrored "
+                                       "Demand Data ECC";
+                       break;
+               case FERR_NF_M8ERR:
+                       specific = "Aliased Uncorrectable Patrol Data ECC";
+                       break;
+               case FERR_NF_M7ERR:
+                       specific = "Aliased Uncorrectable Spare-Copy Data ECC";
+                       break;
+               case FERR_NF_M6ERR:
+                       specific = "Aliased Uncorrectable Mirrored Demand "
+                                       "Data ECC";
+                       break;
+               case FERR_NF_M5ERR:
+                       specific = "Aliased Uncorrectable Non-Mirrored Demand "
+                                       "Data ECC";
+                       break;
+               case FERR_NF_M4ERR:
+                       specific = "Uncorrectable Data ECC on Replay";
+                       break;
+               }
+
                /* Form out message */
                snprintf(msg, sizeof(msg),
                         "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
-                        "CAS=%d, UE Err=0x%x)",
+                        "CAS=%d, UE Err=0x%x (%s))",
                         branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
-                        ue_errors);
+                        ue_errors, specific);
 
                /* Call the helper to output message */
                edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
@@ -616,51 +662,74 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
                        rank, channel, branch >> 1, bank,
                        rdwr ? "Write" : "Read", ras, cas);
 
+               switch (ce_errors) {
+               case FERR_NF_M17ERR:
+                       specific = "Correctable Non-Mirrored Demand Data ECC";
+                       break;
+               case FERR_NF_M18ERR:
+                       specific = "Correctable Mirrored Demand Data ECC";
+                       break;
+               case FERR_NF_M19ERR:
+                       specific = "Correctable Spare-Copy Data ECC";
+                       break;
+               case FERR_NF_M20ERR:
+                       specific = "Correctable Patrol Data ECC";
+                       break;
+               }
+
                /* Form out message */
                snprintf(msg, sizeof(msg),
                         "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
-                        "CAS=%d, CE Err=0x%x)", branch >> 1, bank,
-                        rdwr ? "Write" : "Read", ras, cas, ce_errors);
+                        "CAS=%d, CE Err=0x%x (%s))", branch >> 1, bank,
+                        rdwr ? "Write" : "Read", ras, cas, ce_errors,
+                        specific);
 
                /* Call the helper to output message */
                edac_mc_handle_fbd_ce(mci, rank, channel, msg);
        }
 
-       /* See if any of the thermal errors have fired */
-       misc_errors = allErrors & FERR_NF_THERMAL;
-       if (misc_errors) {
-               i5000_printk(KERN_WARNING, "\tTHERMAL Error, bits= 0x%x\n",
-                       misc_errors);
-       }
-
-       /* See if any of the thermal errors have fired */
-       misc_errors = allErrors & FERR_NF_NON_RETRY;
-       if (misc_errors) {
-               i5000_printk(KERN_WARNING, "\tNON-Retry  Errors, bits= 0x%x\n",
-                       misc_errors);
-       }
+       if (!misc_messages)
+               return;
 
-       /* See if any of the thermal errors have fired */
-       misc_errors = allErrors & FERR_NF_NORTH_CRC;
+       misc_errors = allErrors & (FERR_NF_NON_RETRY | FERR_NF_NORTH_CRC |
+                                  FERR_NF_SPD_PROTOCOL | FERR_NF_DIMM_SPARE);
        if (misc_errors) {
-               i5000_printk(KERN_WARNING,
-                       "\tNORTHBOUND CRC  Error, bits= 0x%x\n",
-                       misc_errors);
-       }
+               switch (misc_errors) {
+               case FERR_NF_M13ERR:
+                       specific = "Non-Retry or Redundant Retry FBD Memory "
+                                       "Alert or Redundant Fast Reset Timeout";
+                       break;
+               case FERR_NF_M14ERR:
+                       specific = "Non-Retry or Redundant Retry FBD "
+                                       "Configuration Alert";
+                       break;
+               case FERR_NF_M15ERR:
+                       specific = "Non-Retry or Redundant Retry FBD "
+                                       "Northbound CRC error on read data";
+                       break;
+               case FERR_NF_M21ERR:
+                       specific = "FBD Northbound CRC error on "
+                                       "FBD Sync Status";
+                       break;
+               case FERR_NF_M22ERR:
+                       specific = "SPD protocol error";
+                       break;
+               case FERR_NF_M27ERR:
+                       specific = "DIMM-spare copy started";
+                       break;
+               case FERR_NF_M28ERR:
+                       specific = "DIMM-spare copy completed";
+                       break;
+               }
+               branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
 
-       /* See if any of the thermal errors have fired */
-       misc_errors = allErrors & FERR_NF_SPD_PROTOCOL;
-       if (misc_errors) {
-               i5000_printk(KERN_WARNING,
-                       "\tSPD Protocol  Error, bits= 0x%x\n",
-                       misc_errors);
-       }
+               /* Form out message */
+               snprintf(msg, sizeof(msg),
+                        "(Branch=%d Err=%#x (%s))", branch >> 1,
+                        misc_errors, specific);
 
-       /* See if any of the thermal errors have fired */
-       misc_errors = allErrors & FERR_NF_DIMM_SPARE;
-       if (misc_errors) {
-               i5000_printk(KERN_WARNING, "\tDIMM-Spare  Error, bits= 0x%x\n",
-                       misc_errors);
+               /* Call the helper to output message */
+               edac_mc_handle_fbd_ce(mci, 0, 0, msg);
        }
 }
 
@@ -1497,3 +1566,6 @@ MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
 
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+module_param(misc_messages, int, 0444);
+MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
+
index c5305e3ee4346932b44cc73074cb6718bd3a38ad..577760a82a0f7d5519cd2631ccf1d7fd99f3ec05 100644 (file)
@@ -114,6 +114,12 @@ struct i82443bxgx_edacmc_error_info {
 
 static struct edac_pci_ctl_info *i82443bxgx_pci;
 
+static struct pci_dev *mci_pdev;       /* init dev: in case that AGP code has
+                                        * already registered driver
+                                        */
+
+static int i82443bxgx_registered = 1;
+
 static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci,
                                struct i82443bxgx_edacmc_error_info
                                *info)
@@ -345,10 +351,17 @@ EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1);
 static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
                                                const struct pci_device_id *ent)
 {
+       int rc;
+
        debugf0("MC: " __FILE__ ": %s()\n", __func__);
 
        /* don't need to call pci_device_enable() */
-       return i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
+       rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
+
+       if (mci_pdev == NULL)
+               mci_pdev = pci_dev_get(pdev);
+
+       return rc;
 }
 
 static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
@@ -387,15 +400,61 @@ static struct pci_driver i82443bxgx_edacmc_driver = {
 
 static int __init i82443bxgx_edacmc_init(void)
 {
+       int pci_rc;
        /* Ensure that the OPSTATE is set correctly for POLL or NMI */
        opstate_init();
 
-       return pci_register_driver(&i82443bxgx_edacmc_driver);
+       pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver);
+       if (pci_rc < 0)
+               goto fail0;
+
+       if (mci_pdev == NULL) {
+               const struct pci_device_id *id = &i82443bxgx_pci_tbl[0];
+               int i = 0;
+               i82443bxgx_registered = 0;
+
+               while (mci_pdev == NULL && id->vendor != 0) {
+                       mci_pdev = pci_get_device(id->vendor,
+                                       id->device, NULL);
+                       i++;
+                       id = &i82443bxgx_pci_tbl[i];
+               }
+               if (!mci_pdev) {
+                       debugf0("i82443bxgx pci_get_device fail\n");
+                       pci_rc = -ENODEV;
+                       goto fail1;
+               }
+
+               pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl);
+
+               if (pci_rc < 0) {
+                       debugf0("i82443bxgx init fail\n");
+                       pci_rc = -ENODEV;
+                       goto fail1;
+               }
+       }
+
+       return 0;
+
+fail1:
+       pci_unregister_driver(&i82443bxgx_edacmc_driver);
+
+fail0:
+       if (mci_pdev != NULL)
+               pci_dev_put(mci_pdev);
+
+       return pci_rc;
 }
 
 static void __exit i82443bxgx_edacmc_exit(void)
 {
        pci_unregister_driver(&i82443bxgx_edacmc_driver);
+
+       if (!i82443bxgx_registered)
+               i82443bxgx_edacmc_remove_one(mci_pdev);
+
+       if (mci_pdev)
+               pci_dev_put(mci_pdev);
 }
 
 module_init(i82443bxgx_edacmc_init);
index 2265d9ca1535652018fb9f28f87f3d7ba447231c..0cfcb2d075a0620228092f741970b525702319a7 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/mod_devicetable.h>
 #include <linux/edac.h>
+#include <linux/smp.h>
 
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
@@ -40,7 +41,7 @@ static u32 orig_pci_err_en;
 #endif
 
 static u32 orig_l2_err_disable;
-static u32 orig_hid1;
+static u32 orig_hid1[2];
 
 /************************ MC SYSFS parts ***********************************/
 
@@ -647,6 +648,9 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
        {
         .compatible = "fsl,8568-l2-cache-controller",
         },
+       {
+        .compatible = "fsl,mpc8572-l2-cache-controller",
+        },
        {},
 };
 
@@ -912,7 +916,8 @@ static int __devinit mpc85xx_mc_err_probe(struct of_device *op,
                /* register interrupts */
                pdata->irq = irq_of_parse_and_map(op->node, 0);
                res = devm_request_irq(&op->dev, pdata->irq,
-                                      mpc85xx_mc_isr, IRQF_DISABLED,
+                                      mpc85xx_mc_isr,
+                                       IRQF_DISABLED | IRQF_SHARED,
                                       "[EDAC] MC err", mci);
                if (res < 0) {
                        printk(KERN_ERR "%s: Unable to request irq %d for "
@@ -980,6 +985,9 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
        {
         .compatible = "fsl,8568-memory-controller",
         },
+       {
+        .compatible = "fsl,mpc8572-memory-controller",
+        },
        {},
 };
 
@@ -995,6 +1003,14 @@ static struct of_platform_driver mpc85xx_mc_err_driver = {
                   },
 };
 
+
+static void __init mpc85xx_mc_clear_rfxe(void *data)
+{
+       orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
+       mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000));
+}
+
+
 static int __init mpc85xx_mc_init(void)
 {
        int res = 0;
@@ -1030,19 +1046,22 @@ static int __init mpc85xx_mc_init(void)
         * need to clear HID1[RFXE] to disable machine check int
         * so we can catch it
         */
-       if (edac_op_state == EDAC_OPSTATE_INT) {
-               orig_hid1 = mfspr(SPRN_HID1);
-               mtspr(SPRN_HID1, (orig_hid1 & ~0x20000));
-       }
+       if (edac_op_state == EDAC_OPSTATE_INT)
+               on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
 
        return 0;
 }
 
 module_init(mpc85xx_mc_init);
 
+static void __exit mpc85xx_mc_restore_hid1(void *data)
+{
+       mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
+}
+
 static void __exit mpc85xx_mc_exit(void)
 {
-       mtspr(SPRN_HID1, orig_hid1);
+       on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
 #ifdef CONFIG_PCI
        of_unregister_platform_driver(&mpc85xx_pci_err_driver);
 #endif
index bbd73a406e537106a2eeda4ba4a2ba1a543b030d..418c18f07e9d30af996bd4e01eada238e0318113 100644 (file)
@@ -189,39 +189,16 @@ static const char gap_count_table[] = {
        63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
 };
 
-struct bm_data {
-       struct fw_transaction t;
-       struct {
-               __be32 arg;
-               __be32 data;
-       } lock;
-       u32 old;
-       int rcode;
-       struct completion done;
-};
-
-static void
-complete_bm_lock(struct fw_card *card, int rcode,
-                void *payload, size_t length, void *data)
-{
-       struct bm_data *bmd = data;
-
-       if (rcode == RCODE_COMPLETE)
-               bmd->old = be32_to_cpu(*(__be32 *) payload);
-       bmd->rcode = rcode;
-       complete(&bmd->done);
-}
-
 static void
 fw_card_bm_work(struct work_struct *work)
 {
        struct fw_card *card = container_of(work, struct fw_card, work.work);
        struct fw_device *root_device;
        struct fw_node *root_node, *local_node;
-       struct bm_data bmd;
        unsigned long flags;
-       int root_id, new_root_id, irm_id, gap_count, generation, grace;
+       int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
        bool do_reset = false;
+       __be32 lock_data[2];
 
        spin_lock_irqsave(&card->lock, flags);
        local_node = card->local_node;
@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
                        goto pick_me;
                }
 
-               bmd.lock.arg = cpu_to_be32(0x3f);
-               bmd.lock.data = cpu_to_be32(local_node->node_id);
+               lock_data[0] = cpu_to_be32(0x3f);
+               lock_data[1] = cpu_to_be32(local_node->node_id);
 
                spin_unlock_irqrestore(&card->lock, flags);
 
-               init_completion(&bmd.done);
-               fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
-                               irm_id, generation,
-                               SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
-                               &bmd.lock, sizeof(bmd.lock),
-                               complete_bm_lock, &bmd);
-               wait_for_completion(&bmd.done);
+               rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
+                               irm_id, generation, SCODE_100,
+                               CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
+                               lock_data, sizeof(lock_data));
 
-               if (bmd.rcode == RCODE_GENERATION) {
-                       /*
-                        * Another bus reset happened. Just return,
-                        * the BM work has been rescheduled.
-                        */
+               if (rcode == RCODE_GENERATION)
+                       /* Another bus reset, BM work has been rescheduled. */
                        goto out;
-               }
 
-               if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
+               if (rcode == RCODE_COMPLETE &&
+                   lock_data[0] != cpu_to_be32(0x3f))
                        /* Somebody else is BM, let them do the work. */
                        goto out;
 
                spin_lock_irqsave(&card->lock, flags);
-               if (bmd.rcode != RCODE_COMPLETE) {
+
+               if (rcode != RCODE_COMPLETE) {
                        /*
                         * The lock request failed, maybe the IRM
                         * isn't really IRM capable after all. Let's
index 2e6d5848d2172011f94058b09c8634c56b091dea..ed03234cbea89ea2247b9d4d005d7e5d1baf1221 100644 (file)
@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
 #define GET_PAYLOAD_LENGTH(v)  ((v) & 0xffff)
 #define GET_INTERRUPT(v)       (((v) >> 16) & 0x01)
 #define GET_SKIP(v)            (((v) >> 17) & 0x01)
-#define GET_TAG(v)             (((v) >> 18) & 0x02)
-#define GET_SY(v)              (((v) >> 20) & 0x04)
+#define GET_TAG(v)             (((v) >> 18) & 0x03)
+#define GET_SY(v)              (((v) >> 20) & 0x0f)
 #define GET_HEADER_LENGTH(v)   (((v) >> 24) & 0xff)
 
 static int ioctl_queue_iso(struct client *client, void *buffer)
@@ -913,7 +913,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
                        return -EFAULT;
        }
 
-       return 0;
+       return retval;
 }
 
 static long
index 0855fb5568e806cf92546e466b73a702e9f55de6..3fccdd48410094a1bc99fe22e916d465d3ab191b 100644 (file)
@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = {
        __ATTR_NULL,
 };
 
-struct read_quadlet_callback_data {
-       struct completion done;
-       int rcode;
-       u32 data;
-};
-
-static void
-complete_transaction(struct fw_card *card, int rcode,
-                    void *payload, size_t length, void *data)
-{
-       struct read_quadlet_callback_data *callback_data = data;
-
-       if (rcode == RCODE_COMPLETE)
-               callback_data->data = be32_to_cpu(*(__be32 *)payload);
-       callback_data->rcode = rcode;
-       complete(&callback_data->done);
-}
-
 static int
 read_rom(struct fw_device *device, int generation, int index, u32 *data)
 {
-       struct read_quadlet_callback_data callback_data;
-       struct fw_transaction t;
-       u64 offset;
+       int rcode;
 
        /* device->node_id, accessed below, must not be older than generation */
        smp_rmb();
 
-       init_completion(&callback_data.done);
-
-       offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
-       fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+       rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
                        device->node_id, generation, device->max_speed,
-                       offset, NULL, 4, complete_transaction, &callback_data);
-
-       wait_for_completion(&callback_data.done);
-
-       *data = callback_data.data;
+                       (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
+                       data, 4);
+       be32_to_cpus(data);
 
-       return callback_data.rcode;
+       return rcode;
 }
 
 #define READ_BIB_ROM_SIZE      256
index aaff50ebba1def2892a8945be8b9289d39921c4f..ef0b9b419c27a6cbdd4216916368641f3968df17 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <linux/blkdev.h>
+#include <linux/bug.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
@@ -181,10 +182,16 @@ struct sbp2_target {
 #define SBP2_MAX_LOGIN_ORB_TIMEOUT     40000U  /* Timeout in ms */
 #define SBP2_ORB_TIMEOUT               2000U   /* Timeout in ms */
 #define SBP2_ORB_NULL                  0x80000000
-#define SBP2_MAX_SG_ELEMENT_LENGTH     0xf000
 #define SBP2_RETRY_LIMIT               0xf             /* 15 retries */
 #define SBP2_CYCLE_LIMIT               (0xc8 << 12)    /* 200 125us cycles */
 
+/*
+ * The default maximum s/g segment size of a FireWire controller is
+ * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
+ * be quadlet-aligned, we set the length limit to 0xffff & ~3.
+ */
+#define SBP2_MAX_SEG_SIZE              0xfffc
+
 /* Unit directory keys */
 #define SBP2_CSR_UNIT_CHARACTERISTICS  0x3a
 #define SBP2_CSR_FIRMWARE_REVISION     0x3c
@@ -621,25 +628,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
        return retval;
 }
 
-static void
-complete_agent_reset_write(struct fw_card *card, int rcode,
-                          void *payload, size_t length, void *done)
-{
-       complete(done);
-}
-
 static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
 {
        struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-       DECLARE_COMPLETION_ONSTACK(done);
-       struct fw_transaction t;
-       static u32 z;
+       __be32 d = 0;
 
-       fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
-                       lu->tgt->node_id, lu->generation, device->max_speed,
-                       lu->command_block_agent_address + SBP2_AGENT_RESET,
-                       &z, sizeof(z), complete_agent_reset_write, &done);
-       wait_for_completion(&done);
+       fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+                          lu->tgt->node_id, lu->generation, device->max_speed,
+                          lu->command_block_agent_address + SBP2_AGENT_RESET,
+                          &d, sizeof(d));
 }
 
 static void
@@ -653,7 +650,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
 {
        struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
        struct fw_transaction *t;
-       static u32 z;
+       static __be32 d;
 
        t = kmalloc(sizeof(*t), GFP_ATOMIC);
        if (t == NULL)
@@ -662,7 +659,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
        fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
                        lu->tgt->node_id, lu->generation, device->max_speed,
                        lu->command_block_agent_address + SBP2_AGENT_RESET,
-                       &z, sizeof(z), complete_agent_reset_write_no_wait, t);
+                       &d, sizeof(d), complete_agent_reset_write_no_wait, t);
 }
 
 static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation)
@@ -823,13 +820,6 @@ static void sbp2_target_put(struct sbp2_target *tgt)
        kref_put(&tgt->kref, sbp2_release_target);
 }
 
-static void
-complete_set_busy_timeout(struct fw_card *card, int rcode,
-                         void *payload, size_t length, void *done)
-{
-       complete(done);
-}
-
 /*
  * Write retransmit retry values into the BUSY_TIMEOUT register.
  * - The single-phase retry protocol is supported by all SBP-2 devices, but the
@@ -849,17 +839,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
 static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
 {
        struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
-       DECLARE_COMPLETION_ONSTACK(done);
-       struct fw_transaction t;
-       static __be32 busy_timeout;
-
-       busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
+       __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
 
-       fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST,
-                       lu->tgt->node_id, lu->generation, device->max_speed,
-                       CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout,
-                       sizeof(busy_timeout), complete_set_busy_timeout, &done);
-       wait_for_completion(&done);
+       fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
+                          lu->tgt->node_id, lu->generation, device->max_speed,
+                          CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
+                          &d, sizeof(d));
 }
 
 static void sbp2_reconnect(struct work_struct *work);
@@ -1121,6 +1106,10 @@ static int sbp2_probe(struct device *dev)
        struct Scsi_Host *shost;
        u32 model, firmware_revision;
 
+       if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
+               BUG_ON(dma_set_max_seg_size(device->card->device,
+                                           SBP2_MAX_SEG_SIZE));
+
        shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
        if (shost == NULL)
                return -ENOMEM;
@@ -1369,14 +1358,12 @@ static int
 sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
                     struct sbp2_logical_unit *lu)
 {
-       struct scatterlist *sg;
-       int sg_len, l, i, j, count;
-       dma_addr_t sg_addr;
-
-       sg = scsi_sglist(orb->cmd);
-       count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
-                          orb->cmd->sc_data_direction);
-       if (count == 0)
+       struct scatterlist *sg = scsi_sglist(orb->cmd);
+       int i, n;
+
+       n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
+                      orb->cmd->sc_data_direction);
+       if (n == 0)
                goto fail;
 
        /*
@@ -1386,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
         * as the second generation iPod which doesn't support page
         * tables.
         */
-       if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+       if (n == 1) {
                orb->request.data_descriptor.high =
                        cpu_to_be32(lu->tgt->address_high);
                orb->request.data_descriptor.low  =
@@ -1396,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
                return 0;
        }
 
-       /*
-        * Convert the scatterlist to an sbp2 page table.  If any
-        * scatterlist entries are too big for sbp2, we split them as we
-        * go.  Even if we ask the block I/O layer to not give us sg
-        * elements larger than 65535 bytes, some IOMMUs may merge sg elements
-        * during DMA mapping, and Linux currently doesn't prevent this.
-        */
-       for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
-               sg_len = sg_dma_len(sg);
-               sg_addr = sg_dma_address(sg);
-               while (sg_len) {
-                       /* FIXME: This won't get us out of the pinch. */
-                       if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
-                               fw_error("page table overflow\n");
-                               goto fail_page_table;
-                       }
-                       l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
-                       orb->page_table[j].low = cpu_to_be32(sg_addr);
-                       orb->page_table[j].high = cpu_to_be32(l << 16);
-                       sg_addr += l;
-                       sg_len -= l;
-                       j++;
-               }
+       for_each_sg(sg, sg, n, i) {
+               orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
+               orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
        }
 
        orb->page_table_bus =
@@ -1437,13 +1404,13 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
        orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
        orb->request.data_descriptor.low  = cpu_to_be32(orb->page_table_bus);
        orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
-                                        COMMAND_ORB_DATA_SIZE(j));
+                                        COMMAND_ORB_DATA_SIZE(n));
 
        return 0;
 
  fail_page_table:
-       dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
-                    orb->cmd->sc_data_direction);
+       dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
+                    scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
  fail:
        return -ENOMEM;
 }
@@ -1456,7 +1423,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
        struct sbp2_command_orb *orb;
        unsigned int max_payload;
-       int retval = SCSI_MLQUEUE_HOST_BUSY;
+       int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
 
        /*
         * Bidirectional commands are not yet implemented, and unknown
@@ -1500,6 +1467,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        if (cmd->sc_data_direction == DMA_FROM_DEVICE)
                orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
 
+       generation = device->generation;
+       smp_rmb();    /* sbp2_map_scatterlist looks at tgt->address_high */
+
        if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
                goto out;
 
@@ -1512,7 +1482,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        if (dma_mapping_error(device->card->device, orb->base.request_bus))
                goto out;
 
-       sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation,
+       sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
                      lu->command_block_agent_address + SBP2_ORB_POINTER);
        retval = 0;
  out:
@@ -1564,6 +1534,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
                blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
 
+       blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
+
        return 0;
 }
 
index e5d1a0b64fcf1b714a186d31a8b7aabf90e7aa97..022ac4fabb6740d3fec872142e9d65d1bc001a96 100644 (file)
@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
  */
 void
 fw_send_request(struct fw_card *card, struct fw_transaction *t,
-               int tcode, int node_id, int generation, int speed,
+               int tcode, int destination_id, int generation, int speed,
                unsigned long long offset,
                void *payload, size_t length,
                fw_transaction_callback_t callback, void *callback_data)
@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
        card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
        card->tlabel_mask |= (1 << tlabel);
 
-       t->node_id = node_id;
+       t->node_id = destination_id;
        t->tlabel = tlabel;
        t->callback = callback;
        t->callback_data = callback_data;
 
-       fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
-                       generation, speed, offset, payload, length);
+       fw_fill_request(&t->packet, tcode, t->tlabel,
+                       destination_id, card->node_id, generation,
+                       speed, offset, payload, length);
        t->packet.callback = transmit_complete_callback;
 
        list_add_tail(&t->link, &card->transaction_list);
@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
 }
 EXPORT_SYMBOL(fw_send_request);
 
+struct transaction_callback_data {
+       struct completion done;
+       void *payload;
+       int rcode;
+};
+
+static void transaction_callback(struct fw_card *card, int rcode,
+                                void *payload, size_t length, void *data)
+{
+       struct transaction_callback_data *d = data;
+
+       if (rcode == RCODE_COMPLETE)
+               memcpy(d->payload, payload, length);
+       d->rcode = rcode;
+       complete(&d->done);
+}
+
+/**
+ * fw_run_transaction - send request and sleep until transaction is completed
+ *
+ * Returns the RCODE.
+ */
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+               int generation, int speed, unsigned long long offset,
+               void *data, size_t length)
+{
+       struct transaction_callback_data d;
+       struct fw_transaction t;
+
+       init_completion(&d.done);
+       d.payload = data;
+       fw_send_request(card, &t, tcode, destination_id, generation, speed,
+                       offset, data, length, transaction_callback, &d);
+       wait_for_completion(&d.done);
+
+       return d.rcode;
+}
+EXPORT_SYMBOL(fw_run_transaction);
+
 static DEFINE_MUTEX(phy_config_mutex);
 static DECLARE_COMPLETION(phy_config_done);
 
index 2ae1b0d6cb7bdfaa6929ccc06a00d63501acebcf..027f58ce81ad124a03b630071cd94dc1d4579348 100644 (file)
@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
 
 void
 fw_send_request(struct fw_card *card, struct fw_transaction *t,
-               int tcode, int node_id, int generation, int speed,
-               unsigned long long offset,
-               void *data, size_t length,
+               int tcode, int destination_id, int generation, int speed,
+               unsigned long long offset, void *data, size_t length,
                fw_transaction_callback_t callback, void *callback_data);
 
+int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
+                      int generation, int speed, unsigned long long offset,
+                      void *data, size_t length);
+
 int fw_cancel_transaction(struct fw_card *card,
                          struct fw_transaction *transaction);
 
index 455575be3560d2336c75d2cc8aaf42c64a728f9c..3e526b6d00cbff758be01772aa8663c002e4f5a4 100644 (file)
  */
 static char dmi_empty_string[] = "        ";
 
+/*
+ * Catch too early calls to dmi_check_system():
+ */
+static int dmi_initialized;
+
 static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 {
        const u8 *bp = ((u8 *) dm) + dm->length;
@@ -366,7 +371,7 @@ void __init dmi_scan_machine(void)
 
        if (efi_enabled) {
                if (efi.smbios == EFI_INVALID_TABLE_ADDR)
-                       goto out;
+                       goto error;
 
                /* This is called as a core_initcall() because it isn't
                 * needed during early boot.  This also means we can
@@ -374,13 +379,13 @@ void __init dmi_scan_machine(void)
                 */
                p = dmi_ioremap(efi.smbios, 32);
                if (p == NULL)
-                       goto out;
+                       goto error;
 
                rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
                dmi_iounmap(p, 32);
                if (!rc) {
                        dmi_available = 1;
-                       return;
+                       goto out;
                }
        }
        else {
@@ -391,19 +396,22 @@ void __init dmi_scan_machine(void)
                 */
                p = dmi_ioremap(0xF0000, 0x10000);
                if (p == NULL)
-                       goto out;
+                       goto error;
 
                for (q = p; q < p + 0x10000; q += 16) {
                        rc = dmi_present(q);
                        if (!rc) {
                                dmi_available = 1;
                                dmi_iounmap(p, 0x10000);
-                               return;
+                               goto out;
                        }
                }
                dmi_iounmap(p, 0x10000);
        }
- out:  printk(KERN_INFO "DMI not present or invalid.\n");
+ error:
+       printk(KERN_INFO "DMI not present or invalid.\n");
+ out:
+       dmi_initialized = 1;
 }
 
 /**
@@ -424,6 +432,8 @@ int dmi_check_system(const struct dmi_system_id *list)
        int i, count = 0;
        const struct dmi_system_id *d = list;
 
+       WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+
        while (d->ident) {
                for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
                        int s = d->matches[i].slot;
index b91ef63126ede7decff0bdbbbd475f03a07bd219..deb154aa47c412be66f4ee68281f053cf7a4c241 100644 (file)
@@ -334,9 +334,9 @@ static void ibft_release(struct kobject *kobj)
 /*
  *  Routines for parsing the iBFT data to be human readable.
  */
-ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
-                                 struct ibft_attribute *attr,
-                                 char *buf)
+static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
+                                       struct ibft_attribute *attr,
+                                       char *buf)
 {
        struct ibft_initiator *initiator = entry->initiator;
        void *ibft_loc = entry->header;
@@ -376,9 +376,9 @@ ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
        return str - buf;
 }
 
-ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
-                           struct ibft_attribute *attr,
-                           char *buf)
+static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
+                                 struct ibft_attribute *attr,
+                                 char *buf)
 {
        struct ibft_nic *nic = entry->nic;
        void *ibft_loc = entry->header;
@@ -440,9 +440,9 @@ ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
        return str - buf;
 };
 
-ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
-                              struct ibft_attribute *attr,
-                              char *buf)
+static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
+                                    struct ibft_attribute *attr,
+                                    char *buf)
 {
        struct ibft_tgt *tgt = entry->tgt;
        void *ibft_loc = entry->header;
index 8d2940517c99221c33e3bf200ac53a82214cebee..9112830107a53d4c208b5a8cbf1934026549bac1 100644 (file)
@@ -67,17 +67,28 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
  * when setting direction, and otherwise illegal.  Until board setup code
  * and drivers use explicit requests everywhere (which won't happen when
  * those calls have no teeth) we can't avoid autorequesting.  This nag
- * message should motivate switching to explicit requests...
+ * message should motivate switching to explicit requests... so should
+ * the weaker cleanup after faults, compared to gpio_request().
  */
-static void gpio_ensure_requested(struct gpio_desc *desc)
+static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
 {
        if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
-               pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
+               struct gpio_chip *chip = desc->chip;
+               int gpio = chip->base + offset;
+
+               if (!try_module_get(chip->owner)) {
+                       pr_err("GPIO-%d: module can't be gotten \n", gpio);
+                       clear_bit(FLAG_REQUESTED, &desc->flags);
+                       /* lose */
+                       return -EIO;
+               }
+               pr_warning("GPIO-%d autorequested\n", gpio);
                desc_set_label(desc, "[auto]");
-               if (!try_module_get(desc->chip->owner))
-                       pr_err("GPIO-%d: module can't be gotten \n",
-                                       (int)(desc - gpio_desc));
+               /* caller must chip->request() w/o spinlock */
+               if (chip->request)
+                       return 1;
        }
+       return 0;
 }
 
 /* caller holds gpio_lock *OR* gpio is marked as requested */
@@ -752,6 +763,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
 int gpio_request(unsigned gpio, const char *label)
 {
        struct gpio_desc        *desc;
+       struct gpio_chip        *chip;
        int                     status = -EINVAL;
        unsigned long           flags;
 
@@ -760,14 +772,15 @@ int gpio_request(unsigned gpio, const char *label)
        if (!gpio_is_valid(gpio))
                goto done;
        desc = &gpio_desc[gpio];
-       if (desc->chip == NULL)
+       chip = desc->chip;
+       if (chip == NULL)
                goto done;
 
-       if (!try_module_get(desc->chip->owner))
+       if (!try_module_get(chip->owner))
                goto done;
 
        /* NOTE:  gpio_request() can be called in early boot,
-        * before IRQs are enabled.
+        * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
         */
 
        if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
@@ -775,7 +788,20 @@ int gpio_request(unsigned gpio, const char *label)
                status = 0;
        } else {
                status = -EBUSY;
-               module_put(desc->chip->owner);
+               module_put(chip->owner);
+       }
+
+       if (chip->request) {
+               /* chip->request may sleep */
+               spin_unlock_irqrestore(&gpio_lock, flags);
+               status = chip->request(chip, gpio - chip->base);
+               spin_lock_irqsave(&gpio_lock, flags);
+
+               if (status < 0) {
+                       desc_set_label(desc, NULL);
+                       module_put(chip->owner);
+                       clear_bit(FLAG_REQUESTED, &desc->flags);
+               }
        }
 
 done:
@@ -791,6 +817,9 @@ void gpio_free(unsigned gpio)
 {
        unsigned long           flags;
        struct gpio_desc        *desc;
+       struct gpio_chip        *chip;
+
+       might_sleep();
 
        if (!gpio_is_valid(gpio)) {
                WARN_ON(extra_checks);
@@ -802,9 +831,17 @@ void gpio_free(unsigned gpio)
        spin_lock_irqsave(&gpio_lock, flags);
 
        desc = &gpio_desc[gpio];
-       if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
+       chip = desc->chip;
+       if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
+               if (chip->free) {
+                       spin_unlock_irqrestore(&gpio_lock, flags);
+                       might_sleep_if(extra_checks && chip->can_sleep);
+                       chip->free(chip, gpio - chip->base);
+                       spin_lock_irqsave(&gpio_lock, flags);
+               }
                desc_set_label(desc, NULL);
                module_put(desc->chip->owner);
+               clear_bit(FLAG_REQUESTED, &desc->flags);
        } else
                WARN_ON(extra_checks);
 
@@ -869,7 +906,9 @@ int gpio_direction_input(unsigned gpio)
        gpio -= chip->base;
        if (gpio >= chip->ngpio)
                goto fail;
-       gpio_ensure_requested(desc);
+       status = gpio_ensure_requested(desc, gpio);
+       if (status < 0)
+               goto fail;
 
        /* now we know the gpio is valid and chip won't vanish */
 
@@ -877,9 +916,22 @@ int gpio_direction_input(unsigned gpio)
 
        might_sleep_if(extra_checks && chip->can_sleep);
 
+       if (status) {
+               status = chip->request(chip, gpio);
+               if (status < 0) {
+                       pr_debug("GPIO-%d: chip request fail, %d\n",
+                               chip->base + gpio, status);
+                       /* and it's not available to anyone else ...
+                        * gpio_request() is the fully clean solution.
+                        */
+                       goto lose;
+               }
+       }
+
        status = chip->direction_input(chip, gpio);
        if (status == 0)
                clear_bit(FLAG_IS_OUT, &desc->flags);
+lose:
        return status;
 fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
@@ -907,7 +959,9 @@ int gpio_direction_output(unsigned gpio, int value)
        gpio -= chip->base;
        if (gpio >= chip->ngpio)
                goto fail;
-       gpio_ensure_requested(desc);
+       status = gpio_ensure_requested(desc, gpio);
+       if (status < 0)
+               goto fail;
 
        /* now we know the gpio is valid and chip won't vanish */
 
@@ -915,9 +969,22 @@ int gpio_direction_output(unsigned gpio, int value)
 
        might_sleep_if(extra_checks && chip->can_sleep);
 
+       if (status) {
+               status = chip->request(chip, gpio);
+               if (status < 0) {
+                       pr_debug("GPIO-%d: chip request fail, %d\n",
+                               chip->base + gpio, status);
+                       /* and it's not available to anyone else ...
+                        * gpio_request() is the fully clean solution.
+                        */
+                       goto lose;
+               }
+       }
+
        status = chip->direction_output(chip, gpio, value);
        if (status == 0)
                set_bit(FLAG_IS_OUT, &desc->flags);
+lose:
        return status;
 fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
@@ -1008,6 +1075,24 @@ int __gpio_cansleep(unsigned gpio)
 }
 EXPORT_SYMBOL_GPL(__gpio_cansleep);
 
+/**
+ * __gpio_to_irq() - return the IRQ corresponding to a GPIO
+ * @gpio: gpio whose IRQ will be returned (already requested)
+ * Context: any
+ *
+ * This is used directly or indirectly to implement gpio_to_irq().
+ * It returns the number of the IRQ signaled by this (input) GPIO,
+ * or a negative errno.
+ */
+int __gpio_to_irq(unsigned gpio)
+{
+       struct gpio_chip        *chip;
+
+       chip = gpio_to_chip(gpio);
+       return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
+}
+EXPORT_SYMBOL_GPL(__gpio_to_irq);
+
 
 
 /* There's no value in making it easy to inline GPIO calls that may sleep.
index 39c795ad8312283caf2145139dc6f4d088b51227..8b24d784db93e6bfda3e9b28440c10caab8173fa 100644 (file)
@@ -255,10 +255,6 @@ static int __devinit max7301_probe(struct spi_device *spi)
        ts->chip.dev = &spi->dev;
        ts->chip.owner = THIS_MODULE;
 
-       ret = gpiochip_add(&ts->chip);
-       if (ret)
-               goto exit_destroy;
-
        /*
         * tristate all pins in hardware and cache the
         * register values for later use.
@@ -269,17 +265,19 @@ static int __devinit max7301_probe(struct spi_device *spi)
                max7301_write(spi, 0x08 + i, 0xAA);
                ts->port_config[i] = 0xAA;
                for (j = 0; j < 4; j++) {
-                       int idx = ts->chip.base + (i - 1) * 4 + j;
-                       ret = gpio_direction_input(idx);
+                       int offset = (i - 1) * 4 + j;
+                       ret = max7301_direction_input(&ts->chip, offset);
                        if (ret)
-                               goto exit_remove;
-                       gpio_free(idx);
+                               goto exit_destroy;
                }
        }
+
+       ret = gpiochip_add(&ts->chip);
+       if (ret)
+               goto exit_destroy;
+
        return ret;
 
-exit_remove:
-       gpiochip_remove(&ts->chip);
 exit_destroy:
        dev_set_drvdata(&spi->dev, NULL);
        mutex_destroy(&ts->lock);
@@ -325,13 +323,15 @@ static int __init max7301_init(void)
 {
        return spi_register_driver(&max7301_driver);
 }
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max7301_init);
 
 static void __exit max7301_exit(void)
 {
        spi_unregister_driver(&max7301_driver);
 }
-
-module_init(max7301_init);
 module_exit(max7301_exit);
 
 MODULE_AUTHOR("Juergen Beisert");
index b51c8135ca284c8bfd229b763ccd68e45e1b4ae8..55ae9a41897aafe0db3da8d2fde1e7a7aec174d9 100644 (file)
@@ -372,7 +372,10 @@ static int __init max732x_init(void)
 {
        return i2c_add_driver(&max732x_driver);
 }
-module_init(max732x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(max732x_init);
 
 static void __exit max732x_exit(void)
 {
index 8a1b405fefda040f0001a5799299eefbe55f5768..89c1d222e9d10b89b8acc56dbfff0b1933f1a2c3 100644 (file)
@@ -419,7 +419,10 @@ static int __init mcp23s08_init(void)
 {
        return spi_register_driver(&mcp23s08_driver);
 }
-module_init(mcp23s08_init);
+/* register after spi postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(mcp23s08_init);
 
 static void __exit mcp23s08_exit(void)
 {
index cc8468692ae0967b295e196c5073fb102c4894c7..9ceeb89f1325ea776bf47c1e89fbcb5b81b8eeec 100644 (file)
@@ -289,7 +289,10 @@ static int __init pca953x_init(void)
 {
        return i2c_add_driver(&pca953x_driver);
 }
-module_init(pca953x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pca953x_init);
 
 static void __exit pca953x_exit(void)
 {
index fc9c6ae739ee74f8f77b8836bd5e7894001e5d9d..4bc2070dd4a1010b498d63b96926e0cdbec69111 100644 (file)
@@ -351,7 +351,10 @@ static int __init pcf857x_init(void)
 {
        return i2c_add_driver(&pcf857x_driver);
 }
-module_init(pcf857x_init);
+/* register after i2c postcore initcall and before
+ * subsys initcalls that may rely on these GPIOs
+ */
+subsys_initcall(pcf857x_init);
 
 static void __exit pcf857x_exit(void)
 {
index 88974342933c62f253d7406c33989b152014b8b8..9ac4720e647b2e2b026791d3d96d24ee2ef226a2 100644 (file)
@@ -517,7 +517,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
        RING_LOCALS;
 
        DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
+                 __func__,
                  dev_priv->current_page,
                  dev_priv->sarea_priv->pf_current_page);
 
@@ -642,7 +642,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
 static int i915_flip_bufs(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
index cacf89e65af4d9f96b1785c873b6f76b384775c3..f5999a91614e668aade684ccbb89fcaf5e1eba86 100644 (file)
@@ -67,4 +67,201 @@ config HIDRAW
 
 source "drivers/hid/usbhid/Kconfig"
 
+menu "Special HID drivers"
+       depends on HID
+
+config HID_COMPAT
+       bool "Load all HID drivers on hid core load"
+       default y
+       ---help---
+       Compatible option for older userspace. If you have system without udev
+       support of module loading through aliases and also old
+       module-init-tools which can't handle hid bus, choose Y here. Otherwise
+       say N. If you say N and your userspace is old enough, the only
+       functionality you lose is modules autoloading.
+
+       If unsure, say Y.
+
+config HID_A4TECH
+       tristate "A4 tech" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for A4 tech X5 and WOP-35 / Trust 450L mice.
+
+config HID_APPLE
+       tristate "Apple" if EMBEDDED
+       depends on (USB_HID || BT_HIDP)
+       default y
+       ---help---
+       Support for some Apple devices which less or more break
+       HID specification.
+
+       Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
+       MacBooks, MacBook Pros and Apple Aluminum.
+
+config HID_BELKIN
+       tristate "Belkin" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Belkin Flip KVM and Wireless keyboard.
+
+config HID_BRIGHT
+       tristate "Bright" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Bright ABNT-2 keyboard.
+
+config HID_CHERRY
+       tristate "Cherry" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Cherry Cymotion keyboard.
+
+config HID_CHICONY
+       tristate "Chicony" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Chicony Tactical pad.
+
+config HID_CYPRESS
+       tristate "Cypress" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for cypress mouse and barcode readers.
+
+config HID_DELL
+       tristate "Dell" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for quirky Dell HID hardware that require
+       special LED handling (W7658 and SK8115 models)
+
+config HID_EZKEY
+       tristate "Ezkey" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Ezkey BTC 8193 keyboard.
+
+config HID_GYRATION
+       tristate "Gyration" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Gyration remote control.
+
+config HID_LOGITECH
+       tristate "Logitech" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Logitech devices that are not fully compliant with HID standard.
+
+config LOGITECH_FF
+       bool "Logitech force feedback"
+       depends on HID_LOGITECH
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you have one of these devices:
+         - Logitech WingMan Cordless RumblePad
+         - Logitech WingMan Cordless RumblePad 2
+         - Logitech WingMan Force 3D
+         - Logitech Formula Force EX
+         - Logitech MOMO Force wheel
+
+         and if you want to enable force feedback for them.
+         Note: if you say N here, this device will still be supported, but without
+         force feedback.
+
+config LOGIRUMBLEPAD2_FF
+       bool "Logitech Rumblepad 2 force feedback"
+       depends on HID_LOGITECH
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you want to enable force feedback support for Logitech
+         Rumblepad 2 devices.
+
+config HID_MICROSOFT
+       tristate "Microsoft" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Microsoft devices that are not fully compliant with HID standard.
+
+config HID_MONTEREY
+       tristate "Monterey" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Monterey Genius KB29E.
+
+config HID_PANTHERLORD
+       tristate "Pantherlord devices support" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for PantherLord/GreenAsia based device support.
+
+config PANTHERLORD_FF
+       bool "Pantherlord force feedback support"
+       depends on HID_PANTHERLORD
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you have a PantherLord/GreenAsia based game controller
+         or adapter and want to enable force feedback support for it.
+
+config HID_PETALYNX
+       tristate "Petalynx" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Petalynx Maxter remote control.
+
+config HID_SAMSUNG
+       tristate "Samsung" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Samsung InfraRed remote control.
+
+config HID_SONY
+       tristate "Sony" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Sony PS3 controller.
+
+config HID_SUNPLUS
+       tristate "Sunplus" if EMBEDDED
+       depends on USB_HID
+       default y
+       ---help---
+       Support for Sunplus wireless desktop.
+
+config THRUSTMASTER_FF
+       tristate "ThrustMaster devices support"
+       default m
+       depends on USB_HID
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
+         a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
+
+config ZEROPLUS_FF
+       tristate "Zeroplus based game controller support"
+       default m
+       depends on USB_HID
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you have a Zeroplus based game controller.
+
+endmenu
+
 endif # HID_SUPPORT
index 275dc522c7389489583f7424fb75427d2a04867d..b09e43e7413e2ebc2fce3b7ffe5c6c7f708fff94 100644 (file)
@@ -1,13 +1,46 @@
 #
 # Makefile for the HID driver
 #
-hid-objs                       := hid-core.o hid-input.o hid-input-quirks.o
+hid-objs                       := hid-core.o hid-input.o
 
 obj-$(CONFIG_HID)              += hid.o
 
 hid-$(CONFIG_HID_DEBUG)                += hid-debug.o
 hid-$(CONFIG_HIDRAW)           += hidraw.o
 
+ifdef CONFIG_HID_COMPAT
+obj-m                          += hid-dummy.o
+endif
+
+hid-logitech-objs              := hid-lg.o
+ifdef CONFIG_LOGITECH_FF
+       hid-logitech-objs       += hid-lgff.o
+endif
+ifdef CONFIG_LOGIRUMBLEPAD2_FF
+       hid-logitech-objs       += hid-lg2ff.o
+endif
+
+obj-$(CONFIG_HID_A4TECH)       += hid-a4tech.o
+obj-$(CONFIG_HID_APPLE)                += hid-apple.o
+obj-$(CONFIG_HID_BELKIN)       += hid-belkin.o
+obj-$(CONFIG_HID_BRIGHT)       += hid-bright.o
+obj-$(CONFIG_HID_CHERRY)       += hid-cherry.o
+obj-$(CONFIG_HID_CHICONY)      += hid-chicony.o
+obj-$(CONFIG_HID_CYPRESS)      += hid-cypress.o
+obj-$(CONFIG_HID_DELL)         += hid-dell.o
+obj-$(CONFIG_HID_EZKEY)                += hid-ezkey.o
+obj-$(CONFIG_HID_GYRATION)     += hid-gyration.o
+obj-$(CONFIG_HID_LOGITECH)     += hid-logitech.o
+obj-$(CONFIG_HID_MICROSOFT)    += hid-microsoft.o
+obj-$(CONFIG_HID_MONTEREY)     += hid-monterey.o
+obj-$(CONFIG_HID_PANTHERLORD)  += hid-pl.o
+obj-$(CONFIG_HID_PETALYNX)     += hid-petalynx.o
+obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
+obj-$(CONFIG_HID_SONY)         += hid-sony.o
+obj-$(CONFIG_HID_SUNPLUS)      += hid-sunplus.o
+obj-$(CONFIG_THRUSTMASTER_FF)  += hid-tmff.o
+obj-$(CONFIG_ZEROPLUS_FF)      += hid-zpff.o
+
 obj-$(CONFIG_USB_HID)          += usbhid/
 obj-$(CONFIG_USB_MOUSE)                += usbhid/
 obj-$(CONFIG_USB_KBD)          += usbhid/
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
new file mode 100644 (file)
index 0000000..ebca00e
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  HID driver for some a4tech "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define A4_2WHEEL_MOUSE_HACK_7 0x01
+#define A4_2WHEEL_MOUSE_HACK_B8        0x02
+
+struct a4tech_sc {
+       unsigned long quirks;
+       unsigned int hw_wheel;
+       __s32 delayed_value;
+};
+
+static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+       if (usage->type == EV_REL && usage->code == REL_WHEEL)
+               set_bit(REL_HWHEEL, *bit);
+
+       if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)
+               return -1;
+
+       return 0;
+}
+
+static int a4_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+       struct input_dev *input;
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type)
+               return 0;
+
+       input = field->hidinput->input;
+
+       if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {
+               if (usage->type == EV_REL && usage->code == REL_WHEEL) {
+                       a4->delayed_value = value;
+                       return 1;
+               }
+
+               if (usage->hid == 0x000100b8) {
+                       input_event(input, EV_REL, value ? REL_HWHEEL :
+                                       REL_WHEEL, a4->delayed_value);
+                       return 1;
+               }
+       }
+
+       if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {
+               a4->hw_wheel = !!value;
+               return 1;
+       }
+
+       if (usage->code == REL_WHEEL && a4->hw_wheel) {
+               input_event(input, usage->type, REL_HWHEEL, value);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       struct a4tech_sc *a4;
+       int ret;
+
+       a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
+       if (a4 == NULL) {
+               dev_err(&hdev->dev, "can't alloc device descriptor\n");
+               ret = -ENOMEM;
+               goto err_free;
+       }
+
+       a4->quirks = id->driver_data;
+
+       hid_set_drvdata(hdev, a4);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       kfree(a4);
+       return ret;
+}
+
+static void a4_remove(struct hid_device *hdev)
+{
+       struct a4tech_sc *a4 = hid_get_drvdata(hdev);
+
+       hid_hw_stop(hdev);
+       kfree(a4);
+}
+
+static const struct hid_device_id a4_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),
+               .driver_data = A4_2WHEEL_MOUSE_HACK_7 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
+               .driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, a4_devices);
+
+static struct hid_driver a4_driver = {
+       .name = "a4tech",
+       .id_table = a4_devices,
+       .input_mapped = a4_input_mapped,
+       .event = a4_event,
+       .probe = a4_probe,
+       .remove = a4_remove,
+};
+
+static int a4_init(void)
+{
+       return hid_register_driver(&a4_driver);
+}
+
+static void a4_exit(void)
+{
+       hid_unregister_driver(&a4_driver);
+}
+
+module_init(a4_init);
+module_exit(a4_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(a4tech);
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
new file mode 100644 (file)
index 0000000..fd7f896
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ *  USB HID quirks support for Linux
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define APPLE_RDESC_JIS                0x0001
+#define APPLE_IGNORE_MOUSE     0x0002
+#define APPLE_HAS_FN           0x0004
+#define APPLE_HIDDEV           0x0008
+#define APPLE_ISO_KEYBOARD     0x0010
+#define APPLE_MIGHTYMOUSE      0x0020
+#define APPLE_INVERT_HWHEEL    0x0040
+#define APPLE_IGNORE_HIDINPUT  0x0080
+#define APPLE_NUMLOCK_EMULATION        0x0100
+
+#define APPLE_FLAG_FKEY                0x01
+
+static unsigned int fnmode = 1;
+module_param(fnmode, uint, 0644);
+MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
+               "[1] = fkeyslast, 2 = fkeysfirst)");
+
+struct apple_sc {
+       unsigned long quirks;
+       unsigned int fn_on;
+       DECLARE_BITMAP(pressed_fn, KEY_CNT);
+       DECLARE_BITMAP(pressed_numlock, KEY_CNT);
+};
+
+struct apple_key_translation {
+       u16 from;
+       u16 to;
+       u8 flags;
+};
+
+static struct apple_key_translation apple_fn_keys[] = {
+       { KEY_BACKSPACE, KEY_DELETE },
+       { KEY_F1,       KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+       { KEY_F2,       KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
+       { KEY_F3,       KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
+       { KEY_F4,       KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
+       { KEY_F5,       KEY_KBDILLUMDOWN,   APPLE_FLAG_FKEY },
+       { KEY_F6,       KEY_KBDILLUMUP,     APPLE_FLAG_FKEY },
+       { KEY_F7,       KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
+       { KEY_F8,       KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
+       { KEY_F9,       KEY_NEXTSONG,       APPLE_FLAG_FKEY },
+       { KEY_F10,      KEY_MUTE,           APPLE_FLAG_FKEY },
+       { KEY_F11,      KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
+       { KEY_F12,      KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+       { KEY_UP,       KEY_PAGEUP },
+       { KEY_DOWN,     KEY_PAGEDOWN },
+       { KEY_LEFT,     KEY_HOME },
+       { KEY_RIGHT,    KEY_END },
+       { }
+};
+
+static struct apple_key_translation powerbook_fn_keys[] = {
+       { KEY_BACKSPACE, KEY_DELETE },
+       { KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
+       { KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
+       { KEY_F3,       KEY_MUTE,               APPLE_FLAG_FKEY },
+       { KEY_F4,       KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
+       { KEY_F5,       KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
+       { KEY_F6,       KEY_NUMLOCK,            APPLE_FLAG_FKEY },
+       { KEY_F7,       KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
+       { KEY_F8,       KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
+       { KEY_F9,       KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
+       { KEY_F10,      KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
+       { KEY_UP,       KEY_PAGEUP },
+       { KEY_DOWN,     KEY_PAGEDOWN },
+       { KEY_LEFT,     KEY_HOME },
+       { KEY_RIGHT,    KEY_END },
+       { }
+};
+
+static struct apple_key_translation powerbook_numlock_keys[] = {
+       { KEY_J,        KEY_KP1 },
+       { KEY_K,        KEY_KP2 },
+       { KEY_L,        KEY_KP3 },
+       { KEY_U,        KEY_KP4 },
+       { KEY_I,        KEY_KP5 },
+       { KEY_O,        KEY_KP6 },
+       { KEY_7,        KEY_KP7 },
+       { KEY_8,        KEY_KP8 },
+       { KEY_9,        KEY_KP9 },
+       { KEY_M,        KEY_KP0 },
+       { KEY_DOT,      KEY_KPDOT },
+       { KEY_SLASH,    KEY_KPPLUS },
+       { KEY_SEMICOLON, KEY_KPMINUS },
+       { KEY_P,        KEY_KPASTERISK },
+       { KEY_MINUS,    KEY_KPEQUAL },
+       { KEY_0,        KEY_KPSLASH },
+       { KEY_F6,       KEY_NUMLOCK },
+       { KEY_KPENTER,  KEY_KPENTER },
+       { KEY_BACKSPACE, KEY_BACKSPACE },
+       { }
+};
+
+static struct apple_key_translation apple_iso_keyboard[] = {
+       { KEY_GRAVE,    KEY_102ND },
+       { KEY_102ND,    KEY_GRAVE },
+       { }
+};
+
+static struct apple_key_translation *apple_find_translation(
+               struct apple_key_translation *table, u16 from)
+{
+       struct apple_key_translation *trans;
+
+       /* Look for the translation */
+       for (trans = table; trans->from; trans++)
+               if (trans->from == from)
+                       return trans;
+
+       return NULL;
+}
+
+static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
+               struct hid_usage *usage, __s32 value)
+{
+       struct apple_sc *asc = hid_get_drvdata(hid);
+       struct apple_key_translation *trans;
+
+       if (usage->code == KEY_FN) {
+               asc->fn_on = !!value;
+               input_event(input, usage->type, usage->code, value);
+               return 1;
+       }
+
+       if (fnmode) {
+               int do_translate;
+
+               trans = apple_find_translation((hid->product < 0x220 ||
+                                       hid->product >= 0x300) ?
+                                       powerbook_fn_keys : apple_fn_keys,
+                                       usage->code);
+               if (trans) {
+                       if (test_bit(usage->code, asc->pressed_fn))
+                               do_translate = 1;
+                       else if (trans->flags & APPLE_FLAG_FKEY)
+                               do_translate = (fnmode == 2 && asc->fn_on) ||
+                                       (fnmode == 1 && !asc->fn_on);
+                       else
+                               do_translate = asc->fn_on;
+
+                       if (do_translate) {
+                               if (value)
+                                       set_bit(usage->code, asc->pressed_fn);
+                               else
+                                       clear_bit(usage->code, asc->pressed_fn);
+
+                               input_event(input, usage->type, trans->to,
+                                               value);
+
+                               return 1;
+                       }
+               }
+
+               if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
+                               (test_bit(usage->code, asc->pressed_numlock) ||
+                               test_bit(LED_NUML, input->led))) {
+                       trans = apple_find_translation(powerbook_numlock_keys,
+                                       usage->code);
+
+                       if (trans) {
+                               if (value)
+                                       set_bit(usage->code,
+                                                       asc->pressed_numlock);
+                               else
+                                       clear_bit(usage->code,
+                                                       asc->pressed_numlock);
+
+                               input_event(input, usage->type, trans->to,
+                                               value);
+                       }
+
+                       return 1;
+               }
+       }
+
+       if (asc->quirks & APPLE_ISO_KEYBOARD) {
+               trans = apple_find_translation(apple_iso_keyboard, usage->code);
+               if (trans) {
+                       input_event(input, usage->type, trans->to, value);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int apple_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       struct apple_sc *asc = hid_get_drvdata(hdev);
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type)
+               return 0;
+
+       if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
+                       usage->code == REL_HWHEEL) {
+               input_event(field->hidinput->input, usage->type, usage->code,
+                               -value);
+               return 1;
+       }
+
+       if ((asc->quirks & APPLE_HAS_FN) &&
+                       hidinput_apple_event(hdev, field->hidinput->input,
+                               usage, value))
+               return 1;
+
+
+       return 0;
+}
+
+/*
+ * MacBook JIS keyboard has wrong logical maximum
+ */
+static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       struct apple_sc *asc = hid_get_drvdata(hdev);
+
+       if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 &&
+                       rdesc[53] == 0x65 && rdesc[59] == 0x65) {
+               dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
+                               "descriptor\n");
+               rdesc[53] = rdesc[59] = 0xe7;
+       }
+}
+
+static void apple_setup_input(struct input_dev *input)
+{
+       struct apple_key_translation *trans;
+
+       set_bit(KEY_NUMLOCK, input->keybit);
+
+       /* Enable all needed keys */
+       for (trans = apple_fn_keys; trans->from; trans++)
+               set_bit(trans->to, input->keybit);
+
+       for (trans = powerbook_fn_keys; trans->from; trans++)
+               set_bit(trans->to, input->keybit);
+
+       for (trans = powerbook_numlock_keys; trans->from; trans++)
+               set_bit(trans->to, input->keybit);
+
+       for (trans = apple_iso_keyboard; trans->from; trans++)
+               set_bit(trans->to, input->keybit);
+}
+
+static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if (usage->hid == (HID_UP_CUSTOM | 0x0003)) {
+               /* The fn key on Apple USB keyboards */
+               set_bit(EV_REP, hi->input->evbit);
+               hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+               apple_setup_input(hi->input);
+               return 1;
+       }
+
+       /* we want the hid layer to go through standard path (set and ignore) */
+       return 0;
+}
+
+static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       struct apple_sc *asc = hid_get_drvdata(hdev);
+
+       if (asc->quirks & APPLE_MIGHTYMOUSE) {
+               if (usage->hid == HID_GD_Z)
+                       hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
+               else if (usage->code == BTN_1)
+                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2);
+               else if (usage->code == BTN_2)
+                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1);
+       }
+
+       return 0;
+}
+
+static int apple_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       unsigned long quirks = id->driver_data;
+       struct apple_sc *asc;
+       unsigned int connect_mask = HID_CONNECT_DEFAULT;
+       int ret;
+
+       /* return something else or move to hid layer? device will reside
+          allocated */
+       if (id->bus == BUS_USB && (quirks & APPLE_IGNORE_MOUSE) &&
+                       to_usb_interface(hdev->dev.parent)->cur_altsetting->
+                       desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
+               return -ENODEV;
+
+       asc = kzalloc(sizeof(*asc), GFP_KERNEL);
+       if (asc == NULL) {
+               dev_err(&hdev->dev, "can't alloc apple descriptor\n");
+               return -ENOMEM;
+       }
+
+       asc->quirks = quirks;
+
+       hid_set_drvdata(hdev, asc);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       if (quirks & APPLE_HIDDEV)
+               connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+       if (quirks & APPLE_IGNORE_HIDINPUT)
+               connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+       ret = hid_hw_start(hdev, connect_mask);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       kfree(asc);
+       return ret;
+}
+
+static void apple_remove(struct hid_device *hdev)
+{
+       hid_hw_stop(hdev);
+       kfree(hid_get_drvdata(hdev));
+}
+
+static const struct hid_device_id apple_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
+               .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
+               .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
+               .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS},
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
+               .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
+               .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_IGNORE_MOUSE | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
+               .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+                       APPLE_IGNORE_MOUSE },
+
+       /* Apple wireless Mighty Mouse */
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
+               .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
+
+       { }
+};
+MODULE_DEVICE_TABLE(hid, apple_devices);
+
+static struct hid_driver apple_driver = {
+       .name = "apple",
+       .id_table = apple_devices,
+       .report_fixup = apple_report_fixup,
+       .probe = apple_probe,
+       .remove = apple_remove,
+       .event = apple_event,
+       .input_mapping = apple_input_mapping,
+       .input_mapped = apple_input_mapped,
+};
+
+static int apple_init(void)
+{
+       int ret;
+
+       ret = hid_register_driver(&apple_driver);
+       if (ret)
+               printk(KERN_ERR "can't register apple driver\n");
+
+       return ret;
+}
+
+static void apple_exit(void)
+{
+       hid_unregister_driver(&apple_driver);
+}
+
+module_init(apple_init);
+module_exit(apple_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(apple);
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c
new file mode 100644 (file)
index 0000000..12c8a9b
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  HID driver for some belkin "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define BELKIN_HIDDEV  0x01
+#define BELKIN_WKBD    0x02
+
+#define belkin_map_key_clear(c)        hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int belkin_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER ||
+                       !(quirks & BELKIN_WKBD))
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x03a: belkin_map_key_clear(KEY_SOUND);            break;
+       case 0x03b: belkin_map_key_clear(KEY_CAMERA);           break;
+       case 0x03c: belkin_map_key_clear(KEY_DOCUMENTS);        break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       unsigned long quirks = id->driver_data;
+       int ret;
+
+       hid_set_drvdata(hdev, (void *)quirks);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
+               ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0));
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id belkin_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM),
+               .driver_data = BELKIN_HIDDEV },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD),
+               .driver_data = BELKIN_WKBD },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, belkin_devices);
+
+static struct hid_driver belkin_driver = {
+       .name = "belkin",
+       .id_table = belkin_devices,
+       .input_mapping = belkin_input_mapping,
+       .probe = belkin_probe,
+};
+
+static int belkin_init(void)
+{
+       return hid_register_driver(&belkin_driver);
+}
+
+static void belkin_exit(void)
+{
+       hid_unregister_driver(&belkin_driver);
+}
+
+module_init(belkin_init);
+module_exit(belkin_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(belkin);
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
new file mode 100644 (file)
index 0000000..38517a1
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  HID driver for some bright "special" devices
+ *
+ *  Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Based on hid-dell driver
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       usbhid_set_leds(hdev);
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id bright_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, bright_devices);
+
+static struct hid_driver bright_driver = {
+       .name = "bright",
+       .id_table = bright_devices,
+       .probe = bright_probe,
+};
+
+static int bright_init(void)
+{
+       return hid_register_driver(&bright_driver);
+}
+
+static void bright_exit(void)
+{
+       hid_unregister_driver(&bright_driver);
+}
+
+module_init(bright_init);
+module_exit(bright_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(bright);
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c
new file mode 100644 (file)
index 0000000..b833b97
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  HID driver for some cherry "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+               dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
+                               "descriptor\n");
+               rdesc[11] = rdesc[16] = 0xff;
+               rdesc[12] = rdesc[17] = 0x03;
+       }
+}
+
+#define ch_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x301: ch_map_key_clear(KEY_PROG1);        break;
+       case 0x302: ch_map_key_clear(KEY_PROG2);        break;
+       case 0x303: ch_map_key_clear(KEY_PROG3);        break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static const struct hid_device_id ch_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, ch_devices);
+
+static struct hid_driver ch_driver = {
+       .name = "cherry",
+       .id_table = ch_devices,
+       .report_fixup = ch_report_fixup,
+       .input_mapping = ch_input_mapping,
+};
+
+static int ch_init(void)
+{
+       return hid_register_driver(&ch_driver);
+}
+
+static void ch_exit(void)
+{
+       hid_unregister_driver(&ch_driver);
+}
+
+module_init(ch_init);
+module_exit(ch_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(cherry);
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
new file mode 100644 (file)
index 0000000..a54d409
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  HID driver for some chicony "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ch_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+               return 0;
+
+       set_bit(EV_REP, hi->input->evbit);
+       switch (usage->hid & HID_USAGE) {
+       case 0xff01: ch_map_key_clear(BTN_1);   break;
+       case 0xff02: ch_map_key_clear(BTN_2);   break;
+       case 0xff03: ch_map_key_clear(BTN_3);   break;
+       case 0xff04: ch_map_key_clear(BTN_4);   break;
+       case 0xff05: ch_map_key_clear(BTN_5);   break;
+       case 0xff06: ch_map_key_clear(BTN_6);   break;
+       case 0xff07: ch_map_key_clear(BTN_7);   break;
+       case 0xff08: ch_map_key_clear(BTN_8);   break;
+       case 0xff09: ch_map_key_clear(BTN_9);   break;
+       case 0xff0a: ch_map_key_clear(BTN_A);   break;
+       case 0xff0b: ch_map_key_clear(BTN_B);   break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static const struct hid_device_id ch_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, ch_devices);
+
+static struct hid_driver ch_driver = {
+       .name = "chicony",
+       .id_table = ch_devices,
+       .input_mapping = ch_input_mapping,
+};
+
+static int ch_init(void)
+{
+       return hid_register_driver(&ch_driver);
+}
+
+static void ch_exit(void)
+{
+       hid_unregister_driver(&ch_driver);
+}
+
+module_init(ch_init);
+module_exit(ch_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(chicony);
index 426ac5add585c03df6dbdae3c8b2baca175ef043..721a36d97582010674e5a4c81faf0be457441d18 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/hid-debug.h>
 #include <linux/hidraw.h>
 
+#include "hid-ids.h"
+
 /*
  * Version Information
  */
@@ -268,9 +270,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 static u32 item_udata(struct hid_item *item)
 {
        switch (item->size) {
-               case 1: return item->data.u8;
-               case 2: return item->data.u16;
-               case 4: return item->data.u32;
+       case 1: return item->data.u8;
+       case 2: return item->data.u16;
+       case 4: return item->data.u32;
        }
        return 0;
 }
@@ -278,9 +280,9 @@ static u32 item_udata(struct hid_item *item)
 static s32 item_sdata(struct hid_item *item)
 {
        switch (item->size) {
-               case 1: return item->data.s8;
-               case 2: return item->data.s16;
-               case 4: return item->data.s32;
+       case 1: return item->data.s8;
+       case 2: return item->data.s16;
+       case 4: return item->data.s32;
        }
        return 0;
 }
@@ -292,87 +294,91 @@ static s32 item_sdata(struct hid_item *item)
 static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 {
        switch (item->tag) {
+       case HID_GLOBAL_ITEM_TAG_PUSH:
 
-               case HID_GLOBAL_ITEM_TAG_PUSH:
-
-                       if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-                               dbg_hid("global enviroment stack overflow\n");
-                               return -1;
-                       }
+               if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+                       dbg_hid("global enviroment stack overflow\n");
+                       return -1;
+               }
 
-                       memcpy(parser->global_stack + parser->global_stack_ptr++,
-                               &parser->global, sizeof(struct hid_global));
-                       return 0;
+               memcpy(parser->global_stack + parser->global_stack_ptr++,
+                       &parser->global, sizeof(struct hid_global));
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_POP:
+       case HID_GLOBAL_ITEM_TAG_POP:
 
-                       if (!parser->global_stack_ptr) {
-                               dbg_hid("global enviroment stack underflow\n");
-                               return -1;
-                       }
-
-                       memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
-                               sizeof(struct hid_global));
-                       return 0;
+               if (!parser->global_stack_ptr) {
+                       dbg_hid("global enviroment stack underflow\n");
+                       return -1;
+               }
 
-               case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
-                       parser->global.usage_page = item_udata(item);
-                       return 0;
+               memcpy(&parser->global, parser->global_stack +
+                       --parser->global_stack_ptr, sizeof(struct hid_global));
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
-                       parser->global.logical_minimum = item_sdata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+               parser->global.usage_page = item_udata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
-                       if (parser->global.logical_minimum < 0)
-                               parser->global.logical_maximum = item_sdata(item);
-                       else
-                               parser->global.logical_maximum = item_udata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+               parser->global.logical_minimum = item_sdata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
-                       parser->global.physical_minimum = item_sdata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+               if (parser->global.logical_minimum < 0)
+                       parser->global.logical_maximum = item_sdata(item);
+               else
+                       parser->global.logical_maximum = item_udata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
-                       if (parser->global.physical_minimum < 0)
-                               parser->global.physical_maximum = item_sdata(item);
-                       else
-                               parser->global.physical_maximum = item_udata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+               parser->global.physical_minimum = item_sdata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-                       parser->global.unit_exponent = item_sdata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+               if (parser->global.physical_minimum < 0)
+                       parser->global.physical_maximum = item_sdata(item);
+               else
+                       parser->global.physical_maximum = item_udata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_UNIT:
-                       parser->global.unit = item_udata(item);
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+               parser->global.unit_exponent = item_sdata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
-                       if ((parser->global.report_size = item_udata(item)) > 32) {
-                               dbg_hid("invalid report_size %d\n", parser->global.report_size);
-                               return -1;
-                       }
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_UNIT:
+               parser->global.unit = item_udata(item);
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
-                       if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
-                               dbg_hid("invalid report_count %d\n", parser->global.report_count);
-                               return -1;
-                       }
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+               parser->global.report_size = item_udata(item);
+               if (parser->global.report_size > 32) {
+                       dbg_hid("invalid report_size %d\n",
+                                       parser->global.report_size);
+                       return -1;
+               }
+               return 0;
 
-               case HID_GLOBAL_ITEM_TAG_REPORT_ID:
-                       if ((parser->global.report_id = item_udata(item)) == 0) {
-                               dbg_hid("report_id 0 is invalid\n");
-                               return -1;
-                       }
-                       return 0;
+       case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+               parser->global.report_count = item_udata(item);
+               if (parser->global.report_count > HID_MAX_USAGES) {
+                       dbg_hid("invalid report_count %d\n",
+                                       parser->global.report_count);
+                       return -1;
+               }
+               return 0;
 
-               default:
-                       dbg_hid("unknown global tag 0x%x\n", item->tag);
+       case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+               parser->global.report_id = item_udata(item);
+               if (parser->global.report_id == 0) {
+                       dbg_hid("report_id 0 is invalid\n");
                        return -1;
+               }
+               return 0;
+
+       default:
+               dbg_hid("unknown global tag 0x%x\n", item->tag);
+               return -1;
        }
 }
 
@@ -393,77 +399,76 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
        data = item_udata(item);
 
        switch (item->tag) {
-
-               case HID_LOCAL_ITEM_TAG_DELIMITER:
-
-                       if (data) {
-                               /*
-                                * We treat items before the first delimiter
-                                * as global to all usage sets (branch 0).
-                                * In the moment we process only these global
-                                * items and the first delimiter set.
-                                */
-                               if (parser->local.delimiter_depth != 0) {
-                                       dbg_hid("nested delimiters\n");
-                                       return -1;
-                               }
-                               parser->local.delimiter_depth++;
-                               parser->local.delimiter_branch++;
-                       } else {
-                               if (parser->local.delimiter_depth < 1) {
-                                       dbg_hid("bogus close delimiter\n");
-                                       return -1;
-                               }
-                               parser->local.delimiter_depth--;
+       case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+               if (data) {
+                       /*
+                        * We treat items before the first delimiter
+                        * as global to all usage sets (branch 0).
+                        * In the moment we process only these global
+                        * items and the first delimiter set.
+                        */
+                       if (parser->local.delimiter_depth != 0) {
+                               dbg_hid("nested delimiters\n");
+                               return -1;
                        }
-                       return 1;
-
-               case HID_LOCAL_ITEM_TAG_USAGE:
-
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg_hid("alternative usage ignored\n");
-                               return 0;
+                       parser->local.delimiter_depth++;
+                       parser->local.delimiter_branch++;
+               } else {
+                       if (parser->local.delimiter_depth < 1) {
+                               dbg_hid("bogus close delimiter\n");
+                               return -1;
                        }
+                       parser->local.delimiter_depth--;
+               }
+               return 1;
 
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
+       case HID_LOCAL_ITEM_TAG_USAGE:
 
-                       return hid_add_usage(parser, data);
+               if (parser->local.delimiter_branch > 1) {
+                       dbg_hid("alternative usage ignored\n");
+                       return 0;
+               }
 
-               case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+               if (item->size <= 2)
+                       data = (parser->global.usage_page << 16) + data;
 
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg_hid("alternative usage ignored\n");
-                               return 0;
-                       }
+               return hid_add_usage(parser, data);
 
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
+       case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 
-                       parser->local.usage_minimum = data;
+               if (parser->local.delimiter_branch > 1) {
+                       dbg_hid("alternative usage ignored\n");
                        return 0;
+               }
 
-               case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+               if (item->size <= 2)
+                       data = (parser->global.usage_page << 16) + data;
 
-                       if (parser->local.delimiter_branch > 1) {
-                               dbg_hid("alternative usage ignored\n");
-                               return 0;
-                       }
+               parser->local.usage_minimum = data;
+               return 0;
 
-                       if (item->size <= 2)
-                               data = (parser->global.usage_page << 16) + data;
+       case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 
-                       for (n = parser->local.usage_minimum; n <= data; n++)
-                               if (hid_add_usage(parser, n)) {
-                                       dbg_hid("hid_add_usage failed\n");
-                                       return -1;
-                               }
+               if (parser->local.delimiter_branch > 1) {
+                       dbg_hid("alternative usage ignored\n");
                        return 0;
+               }
 
-               default:
+               if (item->size <= 2)
+                       data = (parser->global.usage_page << 16) + data;
 
-                       dbg_hid("unknown local item tag 0x%x\n", item->tag);
-                       return 0;
+               for (n = parser->local.usage_minimum; n <= data; n++)
+                       if (hid_add_usage(parser, n)) {
+                               dbg_hid("hid_add_usage failed\n");
+                               return -1;
+                       }
+               return 0;
+
+       default:
+
+               dbg_hid("unknown local item tag 0x%x\n", item->tag);
+               return 0;
        }
        return 0;
 }
@@ -480,24 +485,24 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
        data = item_udata(item);
 
        switch (item->tag) {
-               case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
-                       ret = open_collection(parser, data & 0xff);
-                       break;
-               case HID_MAIN_ITEM_TAG_END_COLLECTION:
-                       ret = close_collection(parser);
-                       break;
-               case HID_MAIN_ITEM_TAG_INPUT:
-                       ret = hid_add_field(parser, HID_INPUT_REPORT, data);
-                       break;
-               case HID_MAIN_ITEM_TAG_OUTPUT:
-                       ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
-                       break;
-               case HID_MAIN_ITEM_TAG_FEATURE:
-                       ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
-                       break;
-               default:
-                       dbg_hid("unknown main item tag 0x%x\n", item->tag);
-                       ret = 0;
+       case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+               ret = open_collection(parser, data & 0xff);
+               break;
+       case HID_MAIN_ITEM_TAG_END_COLLECTION:
+               ret = close_collection(parser);
+               break;
+       case HID_MAIN_ITEM_TAG_INPUT:
+               ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+               break;
+       case HID_MAIN_ITEM_TAG_OUTPUT:
+               ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+               break;
+       case HID_MAIN_ITEM_TAG_FEATURE:
+               ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+               break;
+       default:
+               dbg_hid("unknown main item tag 0x%x\n", item->tag);
+               ret = 0;
        }
 
        memset(&parser->local, 0, sizeof(parser->local));       /* Reset the local parser environment */
@@ -534,9 +539,10 @@ static void hid_free_report(struct hid_report *report)
  * Free a device structure, all reports, and all fields.
  */
 
-void hid_free_device(struct hid_device *device)
+static void hid_device_release(struct device *dev)
 {
-       unsigned i,j;
+       struct hid_device *device = container_of(dev, struct hid_device, dev);
+       unsigned i, j;
 
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                struct hid_report_enum *report_enum = device->report_enum + i;
@@ -552,7 +558,6 @@ void hid_free_device(struct hid_device *device)
        kfree(device->collection);
        kfree(device);
 }
-EXPORT_SYMBOL_GPL(hid_free_device);
 
 /*
  * Fetch a report description item from the data stream. We support long
@@ -593,47 +598,52 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
        item->size = b & 3;
 
        switch (item->size) {
+       case 0:
+               return start;
 
-               case 0:
-                       return start;
-
-               case 1:
-                       if ((end - start) < 1)
-                               return NULL;
-                       item->data.u8 = *start++;
-                       return start;
+       case 1:
+               if ((end - start) < 1)
+                       return NULL;
+               item->data.u8 = *start++;
+               return start;
 
-               case 2:
-                       if ((end - start) < 2)
-                               return NULL;
-                       item->data.u16 = get_unaligned_le16(start);
-                       start = (__u8 *)((__le16 *)start + 1);
-                       return start;
+       case 2:
+               if ((end - start) < 2)
+                       return NULL;
+               item->data.u16 = get_unaligned_le16(start);
+               start = (__u8 *)((__le16 *)start + 1);
+               return start;
 
-               case 3:
-                       item->size++;
-                       if ((end - start) < 4)
-                               return NULL;
-                       item->data.u32 = get_unaligned_le32(start);
-                       start = (__u8 *)((__le32 *)start + 1);
-                       return start;
+       case 3:
+               item->size++;
+               if ((end - start) < 4)
+                       return NULL;
+               item->data.u32 = get_unaligned_le32(start);
+               start = (__u8 *)((__le32 *)start + 1);
+               return start;
        }
 
        return NULL;
 }
 
-/*
+/**
+ * hid_parse_report - parse device report
+ *
+ * @device: hid device
+ * @start: report start
+ * @size: report size
+ *
  * Parse a report description into a hid_device structure. Reports are
  * enumerated, fields are attached to these reports.
+ * 0 returned on success, otherwise nonzero error value.
  */
-
-struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+int hid_parse_report(struct hid_device *device, __u8 *start,
+               unsigned size)
 {
-       struct hid_device *device;
        struct hid_parser *parser;
        struct hid_item item;
        __u8 *end;
-       unsigned i;
+       int ret;
        static int (*dispatch_type[])(struct hid_parser *parser,
                                      struct hid_item *item) = {
                hid_parser_main,
@@ -642,76 +652,57 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
                hid_parser_reserved
        };
 
-       if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
-               return NULL;
+       if (device->driver->report_fixup)
+               device->driver->report_fixup(device, start, size);
 
-       if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
-                                  HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
-               kfree(device);
-               return NULL;
-       }
-       device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
-       for (i = 0; i < HID_REPORT_TYPES; i++)
-               INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
-       if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
-               kfree(device->collection);
-               kfree(device);
-               return NULL;
-       }
+       device->rdesc = kmalloc(size, GFP_KERNEL);
+       if (device->rdesc == NULL)
+               return -ENOMEM;
        memcpy(device->rdesc, start, size);
        device->rsize = size;
 
-       if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
-               kfree(device->rdesc);
-               kfree(device->collection);
-               kfree(device);
-               return NULL;
+       parser = vmalloc(sizeof(struct hid_parser));
+       if (!parser) {
+               ret = -ENOMEM;
+               goto err;
        }
+
        memset(parser, 0, sizeof(struct hid_parser));
        parser->device = device;
 
        end = start + size;
+       ret = -EINVAL;
        while ((start = fetch_item(start, end, &item)) != NULL) {
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        dbg_hid("unexpected long global item\n");
-                       hid_free_device(device);
-                       vfree(parser);
-                       return NULL;
+                       goto err;
                }
 
                if (dispatch_type[item.type](parser, &item)) {
                        dbg_hid("item %u %u %u %u parsing failed\n",
                                item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-                       hid_free_device(device);
-                       vfree(parser);
-                       return NULL;
+                       goto err;
                }
 
                if (start == end) {
                        if (parser->collection_stack_ptr) {
                                dbg_hid("unbalanced collection at end of report description\n");
-                               hid_free_device(device);
-                               vfree(parser);
-                               return NULL;
+                               goto err;
                        }
                        if (parser->local.delimiter_depth) {
                                dbg_hid("unbalanced delimiter at end of report description\n");
-                               hid_free_device(device);
-                               vfree(parser);
-                               return NULL;
+                               goto err;
                        }
                        vfree(parser);
-                       return device;
+                       return 0;
                }
        }
 
        dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
-       hid_free_device(device);
+err:
        vfree(parser);
-       return NULL;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(hid_parse_report);
 
@@ -724,9 +715,9 @@ EXPORT_SYMBOL_GPL(hid_parse_report);
 static s32 snto32(__u32 value, unsigned n)
 {
        switch (n) {
-               case 8:  return ((__s8)value);
-               case 16: return ((__s16)value);
-               case 32: return ((__s32)value);
+       case 8:  return ((__s8)value);
+       case 16: return ((__s16)value);
+       case 32: return ((__s32)value);
        }
        return value & (1 << (n - 1)) ? value | (-1 << n) : value;
 }
@@ -815,9 +806,73 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n)
        return -1;
 }
 
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
+/**
+ * hid_match_report - check if driver's raw_event should be called
+ *
+ * @hid: hid device
+ * @report_type: type to match against
+ *
+ * compare hid->driver->report_table->report_type to report->type
+ */
+static int hid_match_report(struct hid_device *hid, struct hid_report *report)
+{
+       const struct hid_report_id *id = hid->driver->report_table;
+
+       if (!id) /* NULL means all */
+               return 1;
+
+       for (; id->report_type != HID_TERMINATOR; id++)
+               if (id->report_type == HID_ANY_ID ||
+                               id->report_type == report->type)
+                       return 1;
+       return 0;
+}
+
+/**
+ * hid_match_usage - check if driver's event should be called
+ *
+ * @hid: hid device
+ * @usage: usage to match against
+ *
+ * compare hid->driver->usage_table->usage_{type,code} to
+ * usage->usage_{type,code}
+ */
+static int hid_match_usage(struct hid_device *hid, struct hid_usage *usage)
 {
+       const struct hid_usage_id *id = hid->driver->usage_table;
+
+       if (!id) /* NULL means all */
+               return 1;
+
+       for (; id->usage_type != HID_ANY_ID - 1; id++)
+               if ((id->usage_hid == HID_ANY_ID ||
+                               id->usage_hid == usage->hid) &&
+                               (id->usage_type == HID_ANY_ID ||
+                               id->usage_type == usage->type) &&
+                               (id->usage_code == HID_ANY_ID ||
+                                id->usage_code == usage->code))
+                       return 1;
+       return 0;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field,
+               struct hid_usage *usage, __s32 value, int interrupt)
+{
+       struct hid_driver *hdrv = hid->driver;
+       int ret;
+
        hid_dump_input(usage, value);
+
+       if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
+               ret = hdrv->event(hid, field, usage, value);
+               if (ret != 0) {
+                       if (ret < 0)
+                               dbg_hid("%s's event failed with %d\n",
+                                               hdrv->name, ret);
+                       return;
+               }
+       }
+
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_hid_event(hid, field, usage, value);
        if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
@@ -946,44 +1001,47 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
 }
 EXPORT_SYMBOL_GPL(hid_set_field);
 
-int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
+               const u8 *data)
 {
-       struct hid_report_enum *report_enum = hid->report_enum + type;
        struct hid_report *report;
-       int n, rsize, i;
+       unsigned int n = 0;     /* Normally report number is 0 */
 
-       if (!hid)
-               return -ENODEV;
+       /* Device uses numbered reports, data[0] is report number */
+       if (report_enum->numbered)
+               n = *data;
 
-       if (!size) {
-               dbg_hid("empty report\n");
-               return -1;
-       }
+       report = report_enum->report_id_hash[n];
+       if (report == NULL)
+               dbg_hid("undefined report_id %u received\n", n);
 
-       dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+       return report;
+}
 
-       n = 0;                          /* Normally report number is 0 */
-       if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
-               n = *data++;
-               size--;
-       }
+void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+               int interrupt)
+{
+       struct hid_report_enum *report_enum = hid->report_enum + type;
+       struct hid_report *report;
+       unsigned int a;
+       int rsize, csize = size;
+       u8 *cdata = data;
 
-       /* dump the report */
-       dbg_hid("report %d (size %u) = ", n, size);
-       for (i = 0; i < size; i++)
-               dbg_hid_line(" %02x", data[i]);
-       dbg_hid_line("\n");
+       report = hid_get_report(report_enum, data);
+       if (!report)
+               return;
 
-       if (!(report = report_enum->report_id_hash[n])) {
-               dbg_hid("undefined report_id %d received\n", n);
-               return -1;
+       if (report_enum->numbered) {
+               cdata++;
+               csize--;
        }
 
        rsize = ((report->size - 1) >> 3) + 1;
 
-       if (size < rsize) {
-               dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
-               memset(data + size, 0, rsize - size);
+       if (csize < rsize) {
+               dbg_hid("report %d is too short, (%d < %d)\n", report->id,
+                               csize, rsize);
+               memset(cdata + csize, 0, rsize - csize);
        }
 
        if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
@@ -996,24 +1054,663 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
                        hidraw_report_event(hid, data, size);
        }
 
-       for (n = 0; n < report->maxfield; n++)
-               hid_input_field(hid, report->field[n], data, interrupt);
+       for (a = 0; a < report->maxfield; a++)
+               hid_input_field(hid, report->field[a], cdata, interrupt);
 
        if (hid->claimed & HID_CLAIMED_INPUT)
                hidinput_report_event(hid, report);
+}
+EXPORT_SYMBOL_GPL(hid_report_raw_event);
+
+/**
+ * hid_input_report - report data from lower layer (usb, bt...)
+ *
+ * @hid: hid device
+ * @type: HID report type (HID_*_REPORT)
+ * @data: report contents
+ * @size: size of data parameter
+ * @interrupt: called from atomic?
+ *
+ * This is data entry for lower layers.
+ */
+int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+{
+       struct hid_report_enum *report_enum = hid->report_enum + type;
+       struct hid_driver *hdrv = hid->driver;
+       struct hid_report *report;
+       unsigned int i;
+       int ret;
+
+       if (!hid || !hid->driver)
+               return -ENODEV;
+
+       if (!size) {
+               dbg_hid("empty report\n");
+               return -1;
+       }
+
+       dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+
+       report = hid_get_report(report_enum, data);
+       if (!report)
+               return -1;
+
+       /* dump the report */
+       dbg_hid("report %d (size %u) = ", report->id, size);
+       for (i = 0; i < size; i++)
+               dbg_hid_line(" %02x", data[i]);
+       dbg_hid_line("\n");
+
+       if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
+               ret = hdrv->raw_event(hid, report, data, size);
+               if (ret != 0)
+                       return ret < 0 ? ret : 0;
+       }
+
+       hid_report_raw_event(hid, type, data, size, interrupt);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
 
+static bool hid_match_one_id(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       return id->bus == hdev->bus &&
+               (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) &&
+               (id->product == HID_ANY_ID || id->product == hdev->product);
+}
+
+static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       for (; id->bus; id++)
+               if (hid_match_one_id(hdev, id))
+                       return id;
+
+       return NULL;
+}
+
+static const struct hid_device_id hid_hiddev_list[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1) },
+       { }
+};
+
+static bool hid_hiddev(struct hid_device *hdev)
+{
+       return !!hid_match_id(hdev, hid_hiddev_list);
+}
+
+int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
+{
+       static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
+               "Joystick", "Gamepad", "Keyboard", "Keypad",
+               "Multi-Axis Controller"
+       };
+       const char *type, *bus;
+       char buf[64];
+       unsigned int i;
+       int len;
+
+       if (hdev->bus != BUS_USB)
+               connect_mask &= ~HID_CONNECT_HIDDEV;
+       if (hid_hiddev(hdev))
+               connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+
+       if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev,
+                               connect_mask & HID_CONNECT_HIDINPUT_FORCE))
+               hdev->claimed |= HID_CLAIMED_INPUT;
+       if ((connect_mask & HID_CONNECT_HIDDEV) && hdev->hiddev_connect &&
+                       !hdev->hiddev_connect(hdev,
+                               connect_mask & HID_CONNECT_HIDDEV_FORCE))
+               hdev->claimed |= HID_CLAIMED_HIDDEV;
+       if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev))
+               hdev->claimed |= HID_CLAIMED_HIDRAW;
+
+       if (!hdev->claimed) {
+               dev_err(&hdev->dev, "claimed by neither input, hiddev nor "
+                               "hidraw\n");
+               return -ENODEV;
+       }
+
+       if ((hdev->claimed & HID_CLAIMED_INPUT) &&
+                       (connect_mask & HID_CONNECT_FF) && hdev->ff_init)
+               hdev->ff_init(hdev);
+
+       len = 0;
+       if (hdev->claimed & HID_CLAIMED_INPUT)
+               len += sprintf(buf + len, "input");
+       if (hdev->claimed & HID_CLAIMED_HIDDEV)
+               len += sprintf(buf + len, "%shiddev%d", len ? "," : "",
+                               hdev->minor);
+       if (hdev->claimed & HID_CLAIMED_HIDRAW)
+               len += sprintf(buf + len, "%shidraw%d", len ? "," : "",
+                               ((struct hidraw *)hdev->hidraw)->minor);
+
+       type = "Device";
+       for (i = 0; i < hdev->maxcollection; i++) {
+               struct hid_collection *col = &hdev->collection[i];
+               if (col->type == HID_COLLECTION_APPLICATION &&
+                  (col->usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+                  (col->usage & 0xffff) < ARRAY_SIZE(types)) {
+                       type = types[col->usage & 0xffff];
+                       break;
+               }
+       }
+
+       switch (hdev->bus) {
+       case BUS_USB:
+               bus = "USB";
+               break;
+       case BUS_BLUETOOTH:
+               bus = "BLUETOOTH";
+               break;
+       default:
+               bus = "<UNKNOWN>";
+       }
+
+       dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
+                       buf, bus, hdev->version >> 8, hdev->version & 0xff,
+                       type, hdev->name, hdev->phys);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hid_connect);
+
+static const struct hid_device_id hid_blacklist[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+       { }
+};
+
+static int hid_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+       if (!hid_match_id(hdev, hdrv->id_table))
+               return 0;
+
+       /* generic wants all non-blacklisted */
+       if (!strncmp(hdrv->name, "generic-", 8))
+               return !hid_match_id(hdev, hid_blacklist);
+
+       return 1;
+}
+
+static int hid_device_probe(struct device *dev)
+{
+       struct hid_driver *hdrv = container_of(dev->driver,
+                       struct hid_driver, driver);
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       const struct hid_device_id *id;
+       int ret = 0;
+
+       if (!hdev->driver) {
+               id = hid_match_id(hdev, hdrv->id_table);
+               if (id == NULL)
+                       return -ENODEV;
+
+               hdev->driver = hdrv;
+               if (hdrv->probe) {
+                       ret = hdrv->probe(hdev, id);
+               } else { /* default probe */
+                       ret = hid_parse(hdev);
+                       if (!ret)
+                               ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+               }
+               if (ret)
+                       hdev->driver = NULL;
+       }
+       return ret;
+}
+
+static int hid_device_remove(struct device *dev)
+{
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+       struct hid_driver *hdrv = hdev->driver;
+
+       if (hdrv) {
+               if (hdrv->remove)
+                       hdrv->remove(hdev);
+               else /* default remove */
+                       hid_hw_stop(hdev);
+               hdev->driver = NULL;
+       }
+
+       return 0;
+}
+
+static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+       if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X",
+                       hdev->bus, hdev->vendor, hdev->product))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "HID_NAME=%s", hdev->name))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "HID_PHYS=%s", hdev->phys))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "HID_UNIQ=%s", hdev->uniq))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "MODALIAS=hid:b%04Xv%08Xp%08X",
+                       hdev->bus, hdev->vendor, hdev->product))
+               return -ENOMEM;
+
+       return 0;
+}
+
+static struct bus_type hid_bus_type = {
+       .name           = "hid",
+       .match          = hid_bus_match,
+       .probe          = hid_device_probe,
+       .remove         = hid_device_remove,
+       .uevent         = hid_uevent,
+};
+
+static const struct hid_device_id hid_ignore_list[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
+       { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0001) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WACOM, HID_ANY_ID) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+       { }
+};
+
+static bool hid_ignore(struct hid_device *hdev)
+{
+       switch (hdev->vendor) {
+       case USB_VENDOR_ID_CODEMERCS:
+               /* ignore all Code Mercenaries IOWarrior devices */
+               if (hdev->product >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&
+                               hdev->product <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
+                       return true;
+               break;
+       case USB_VENDOR_ID_LOGITECH:
+               if (hdev->product >= USB_DEVICE_ID_LOGITECH_HARMONY_FIRST &&
+                               hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST)
+                       return true;
+               break;
+       }
+
+       return !!hid_match_id(hdev, hid_ignore_list);
+}
+
+int hid_add_device(struct hid_device *hdev)
+{
+       static atomic_t id = ATOMIC_INIT(0);
+       int ret;
+
+       if (WARN_ON(hdev->status & HID_STAT_ADDED))
+               return -EBUSY;
+
+       /* we need to kill them here, otherwise they will stay allocated to
+        * wait for coming driver */
+       if (hid_ignore(hdev))
+               return -ENODEV;
+
+       /* XXX hack, any other cleaner solution < 20 bus_id bytes? */
+       sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
+                       hdev->vendor, hdev->product, atomic_inc_return(&id));
+
+       ret = device_add(&hdev->dev);
+       if (!ret)
+               hdev->status |= HID_STAT_ADDED;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(hid_add_device);
+
+/**
+ * hid_allocate_device - allocate new hid device descriptor
+ *
+ * Allocate and initialize hid device, so that hid_destroy_device might be
+ * used to free it.
+ *
+ * New hid_device pointer is returned on success, otherwise ERR_PTR encoded
+ * error value.
+ */
+struct hid_device *hid_allocate_device(void)
+{
+       struct hid_device *hdev;
+       unsigned int i;
+       int ret = -ENOMEM;
+
+       hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
+       if (hdev == NULL)
+               return ERR_PTR(ret);
+
+       device_initialize(&hdev->dev);
+       hdev->dev.release = hid_device_release;
+       hdev->dev.bus = &hid_bus_type;
+
+       hdev->collection = kcalloc(HID_DEFAULT_NUM_COLLECTIONS,
+                       sizeof(struct hid_collection), GFP_KERNEL);
+       if (hdev->collection == NULL)
+               goto err;
+       hdev->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
+       for (i = 0; i < HID_REPORT_TYPES; i++)
+               INIT_LIST_HEAD(&hdev->report_enum[i].report_list);
+
+       return hdev;
+err:
+       put_device(&hdev->dev);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(hid_allocate_device);
+
+static void hid_remove_device(struct hid_device *hdev)
+{
+       if (hdev->status & HID_STAT_ADDED) {
+               device_del(&hdev->dev);
+               hdev->status &= ~HID_STAT_ADDED;
+       }
+}
+
+/**
+ * hid_destroy_device - free previously allocated device
+ *
+ * @hdev: hid device
+ *
+ * If you allocate hid_device through hid_allocate_device, you should ever
+ * free by this function.
+ */
+void hid_destroy_device(struct hid_device *hdev)
+{
+       hid_remove_device(hdev);
+       put_device(&hdev->dev);
+}
+EXPORT_SYMBOL_GPL(hid_destroy_device);
+
+int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
+               const char *mod_name)
+{
+       hdrv->driver.name = hdrv->name;
+       hdrv->driver.bus = &hid_bus_type;
+       hdrv->driver.owner = owner;
+       hdrv->driver.mod_name = mod_name;
+
+       return driver_register(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(__hid_register_driver);
+
+void hid_unregister_driver(struct hid_driver *hdrv)
+{
+       driver_unregister(&hdrv->driver);
+}
+EXPORT_SYMBOL_GPL(hid_unregister_driver);
+
+#ifdef CONFIG_HID_COMPAT
+static void hid_compat_load(struct work_struct *ws)
+{
+       request_module("hid-dummy");
+}
+static DECLARE_WORK(hid_compat_work, hid_compat_load);
+static struct workqueue_struct *hid_compat_wq;
+#endif
+
 static int __init hid_init(void)
 {
-       return hidraw_init();
+       int ret;
+
+       ret = bus_register(&hid_bus_type);
+       if (ret) {
+               printk(KERN_ERR "HID: can't register hid bus\n");
+               goto err;
+       }
+
+       ret = hidraw_init();
+       if (ret)
+               goto err_bus;
+
+#ifdef CONFIG_HID_COMPAT
+       hid_compat_wq = create_workqueue("hid_compat");
+       if (!hid_compat_wq) {
+               hidraw_exit();
+               goto err;
+       }
+       queue_work(hid_compat_wq, &hid_compat_work);
+#endif
+
+       return 0;
+err_bus:
+       bus_unregister(&hid_bus_type);
+err:
+       return ret;
 }
 
 static void __exit hid_exit(void)
 {
+#ifdef CONFIG_HID_COMPAT
+       destroy_workqueue(hid_compat_wq);
+#endif
        hidraw_exit();
+       bus_unregister(&hid_bus_type);
 }
 
 module_init(hid_init);
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
new file mode 100644 (file)
index 0000000..5d69d27
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *  HID driver for some cypress "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define CP_RDESC_SWAPPED_MIN_MAX       0x01
+#define CP_2WHEEL_MOUSE_HACK           0x02
+#define CP_2WHEEL_MOUSE_HACK_ON                0x04
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       unsigned int i;
+
+       if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
+               return;
+
+       for (i = 0; i < rsize - 4; i++)
+               if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
+                       __u8 tmp;
+
+                       rdesc[i] = 0x19;
+                       rdesc[i + 2] = 0x29;
+                       tmp = rdesc[i + 3];
+                       rdesc[i + 3] = rdesc[i + 1];
+                       rdesc[i + 1] = tmp;
+               }
+}
+
+static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if (!(quirks & CP_2WHEEL_MOUSE_HACK))
+               return 0;
+
+       if (usage->type == EV_REL && usage->code == REL_WHEEL)
+               set_bit(REL_HWHEEL, *bit);
+       if (usage->hid == 0x00090005)
+               return -1;
+
+       return 0;
+}
+
+static int cp_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK))
+               return 0;
+
+       if (usage->hid == 0x00090005) {
+               if (value)
+                       quirks |=  CP_2WHEEL_MOUSE_HACK_ON;
+               else
+                       quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
+               hid_set_drvdata(hdev, (void *)quirks);
+               return 1;
+       }
+
+       if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
+               struct input_dev *input = field->hidinput->input;
+
+               input_event(input, usage->type, REL_HWHEEL, value);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       unsigned long quirks = id->driver_data;
+       int ret;
+
+       hid_set_drvdata(hdev, (void *)quirks);
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id cp_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1),
+               .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2),
+               .driver_data = CP_RDESC_SWAPPED_MIN_MAX },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
+               .driver_data = CP_2WHEEL_MOUSE_HACK },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, cp_devices);
+
+static struct hid_driver cp_driver = {
+       .name = "cypress",
+       .id_table = cp_devices,
+       .report_fixup = cp_report_fixup,
+       .input_mapped = cp_input_mapped,
+       .event = cp_event,
+       .probe = cp_probe,
+};
+
+static int cp_init(void)
+{
+       return hid_register_driver(&cp_driver);
+}
+
+static void cp_exit(void)
+{
+       hid_unregister_driver(&cp_driver);
+}
+
+module_init(cp_init);
+module_exit(cp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(cypress);
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
new file mode 100644 (file)
index 0000000..1a0d0df
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  HID driver for some dell "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       usbhid_set_leds(hdev);
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id dell_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, dell_devices);
+
+static struct hid_driver dell_driver = {
+       .name = "dell",
+       .id_table = dell_devices,
+       .probe = dell_probe,
+};
+
+static int dell_init(void)
+{
+       return hid_register_driver(&dell_driver);
+}
+
+static void dell_exit(void)
+{
+       hid_unregister_driver(&dell_driver);
+}
+
+module_init(dell_init);
+module_exit(dell_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(dell);
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
new file mode 100644 (file)
index 0000000..e148f86
--- /dev/null
@@ -0,0 +1,72 @@
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/hid.h>
+
+static int __init hid_dummy_init(void)
+{
+#ifdef CONFIG_HID_A4TECH_MODULE
+       HID_COMPAT_CALL_DRIVER(a4tech);
+#endif
+#ifdef CONFIG_HID_APPLE_MODULE
+       HID_COMPAT_CALL_DRIVER(apple);
+#endif
+#ifdef CONFIG_HID_BELKIN_MODULE
+       HID_COMPAT_CALL_DRIVER(belkin);
+#endif
+#ifdef CONFIG_HID_BRIGHT_MODULE
+       HID_COMPAT_CALL_DRIVER(bright);
+#endif
+#ifdef CONFIG_HID_CHERRY_MODULE
+       HID_COMPAT_CALL_DRIVER(cherry);
+#endif
+#ifdef CONFIG_HID_CHICONY_MODULE
+       HID_COMPAT_CALL_DRIVER(chicony);
+#endif
+#ifdef CONFIG_HID_CYPRESS_MODULE
+       HID_COMPAT_CALL_DRIVER(cypress);
+#endif
+#ifdef CONFIG_HID_DELL_MODULE
+       HID_COMPAT_CALL_DRIVER(dell);
+#endif
+#ifdef CONFIG_HID_EZKEY_MODULE
+       HID_COMPAT_CALL_DRIVER(ezkey);
+#endif
+#ifdef CONFIG_HID_GYRATION_MODULE
+       HID_COMPAT_CALL_DRIVER(gyration);
+#endif
+#ifdef CONFIG_HID_LOGITECH_MODULE
+       HID_COMPAT_CALL_DRIVER(logitech);
+#endif
+#ifdef CONFIG_HID_MICROSOFT_MODULE
+       HID_COMPAT_CALL_DRIVER(microsoft);
+#endif
+#ifdef CONFIG_HID_MONTEREY_MODULE
+       HID_COMPAT_CALL_DRIVER(monterey);
+#endif
+#ifdef CONFIG_HID_PANTHERLORD_MODULE
+       HID_COMPAT_CALL_DRIVER(pantherlord);
+#endif
+#ifdef CONFIG_HID_PETALYNX_MODULE
+       HID_COMPAT_CALL_DRIVER(petalynx);
+#endif
+#ifdef CONFIG_HID_SAMSUNG_MODULE
+       HID_COMPAT_CALL_DRIVER(samsung);
+#endif
+#ifdef CONFIG_HID_SONY_MODULE
+       HID_COMPAT_CALL_DRIVER(sony);
+#endif
+#ifdef CONFIG_HID_SUNPLUS_MODULE
+       HID_COMPAT_CALL_DRIVER(sunplus);
+#endif
+#ifdef CONFIG_THRUSTMASTER_FF_MODULE
+       HID_COMPAT_CALL_DRIVER(thrustmaster);
+#endif
+#ifdef CONFIG_ZEROPLUS_FF_MODULE
+       HID_COMPAT_CALL_DRIVER(zeroplus);
+#endif
+
+       return -EIO;
+}
+module_init(hid_dummy_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c
new file mode 100644 (file)
index 0000000..deb42f9
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  HID driver for some ezkey "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ez_map_rel(c)  hid_map_usage(hi, usage, bit, max, EV_REL, (c))
+#define ez_map_key(c)  hid_map_usage(hi, usage, bit, max, EV_KEY, (c))
+
+static int ez_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x230: ez_map_key(BTN_MOUSE);      break;
+       case 0x231: ez_map_rel(REL_WHEEL);      break;
+       /*
+        * this keyboard has a scrollwheel implemented in
+        * totally broken way. We map this usage temporarily
+        * to HWHEEL and handle it in the event quirk handler
+        */
+       case 0x232: ez_map_rel(REL_HWHEEL);     break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int ez_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type)
+               return 0;
+
+       /* handle the temporary quirky mapping to HWHEEL */
+       if (usage->type == EV_REL && usage->code == REL_HWHEEL) {
+               struct input_dev *input = field->hidinput->input;
+               input_event(input, usage->type, REL_WHEEL, -value);
+               return 1;
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id ez_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, ez_devices);
+
+static struct hid_driver ez_driver = {
+       .name = "ezkey",
+       .id_table = ez_devices,
+       .input_mapping = ez_input_mapping,
+       .event = ez_event,
+};
+
+static int ez_init(void)
+{
+       return hid_register_driver(&ez_driver);
+}
+
+static void ez_exit(void)
+{
+       hid_unregister_driver(&ez_driver);
+}
+
+module_init(ez_init);
+module_exit(ez_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(ezkey);
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
new file mode 100644 (file)
index 0000000..ac5120f
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  HID driver for some gyration "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define gy_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+               return 0;
+
+       set_bit(EV_REP, hi->input->evbit);
+       switch (usage->hid & HID_USAGE) {
+       /* Reported on Gyration MCE Remote */
+       case 0x00d: gy_map_key_clear(KEY_HOME);         break;
+       case 0x024: gy_map_key_clear(KEY_DVD);          break;
+       case 0x025: gy_map_key_clear(KEY_PVR);          break;
+       case 0x046: gy_map_key_clear(KEY_MEDIA);        break;
+       case 0x047: gy_map_key_clear(KEY_MP3);          break;
+       case 0x049: gy_map_key_clear(KEY_CAMERA);       break;
+       case 0x04a: gy_map_key_clear(KEY_VIDEO);        break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int gyration_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       struct input_dev *input = field->hidinput->input;
+
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+                       (usage->hid & 0xff) == 0x82) {
+               input_event(input, usage->type, usage->code, 1);
+               input_sync(input);
+               input_event(input, usage->type, usage->code, 0);
+               input_sync(input);
+               return 1;
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id gyration_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, gyration_devices);
+
+static struct hid_driver gyration_driver = {
+       .name = "gyration",
+       .id_table = gyration_devices,
+       .input_mapping = gyration_input_mapping,
+       .event = gyration_event,
+};
+
+static int gyration_init(void)
+{
+       return hid_register_driver(&gyration_driver);
+}
+
+static void gyration_exit(void)
+{
+       hid_unregister_driver(&gyration_driver);
+}
+
+module_init(gyration_init);
+module_exit(gyration_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(gyration);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
new file mode 100644 (file)
index 0000000..d9a1ba9
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ *  USB HID quirks support for Linux
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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 HID_IDS_H_FILE
+#define HID_IDS_H_FILE
+
+#define USB_VENDOR_ID_A4TECH           0x09da
+#define USB_DEVICE_ID_A4TECH_WCP32PU   0x0006
+#define USB_DEVICE_ID_A4TECH_X5_005D   0x000a
+
+#define USB_VENDOR_ID_AASHIMA          0x06d6
+#define USB_DEVICE_ID_AASHIMA_GAMEPAD  0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
+
+#define USB_VENDOR_ID_ACECAD           0x0460
+#define USB_DEVICE_ID_ACECAD_FLAIR     0x0004
+#define USB_DEVICE_ID_ACECAD_302       0x0008
+
+#define USB_VENDOR_ID_ADS_TECH                 0x06e1
+#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X    0xa155
+
+#define USB_VENDOR_ID_AFATECH          0x15a4
+#define USB_DEVICE_ID_AFATECH_AF9016   0x9016
+
+#define USB_VENDOR_ID_AIPTEK           0x08ca
+#define USB_DEVICE_ID_AIPTEK_01                0x0001
+#define USB_DEVICE_ID_AIPTEK_10                0x0010
+#define USB_DEVICE_ID_AIPTEK_20                0x0020
+#define USB_DEVICE_ID_AIPTEK_21                0x0021
+#define USB_DEVICE_ID_AIPTEK_22                0x0022
+#define USB_DEVICE_ID_AIPTEK_23                0x0023
+#define USB_DEVICE_ID_AIPTEK_24                0x0024
+
+#define USB_VENDOR_ID_AIRCABLE         0x16CA
+#define USB_DEVICE_ID_AIRCABLE1                0x1502
+
+#define USB_VENDOR_ID_ALCOR            0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232   0x9720
+
+#define USB_VENDOR_ID_ALPS             0x0433
+#define USB_DEVICE_ID_IBM_GAMEPAD      0x1101
+
+#define USB_VENDOR_ID_APPLE            0x05ac
+#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE        0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI      0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO       0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI        0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI       0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO        0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS        0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI       0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO        0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS        0x021c
+#define USB_DEVICE_ID_APPLE_ALU_ANSI   0x0220
+#define USB_DEVICE_ID_APPLE_ALU_ISO    0x0221
+#define USB_DEVICE_ID_APPLE_ALU_JIS    0x0222
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI    0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO     0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS     0x0225
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI    0x0229
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO     0x022a
+#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS     0x022b
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI  0x022c
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO   0x022d
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS   0x022e
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI   0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO    0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS    0x0232
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
+#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL      0x8241
+#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
+
+#define USB_VENDOR_ID_ASUS             0x0b05
+#define USB_DEVICE_ID_ASUS_LCM         0x1726
+
+#define USB_VENDOR_ID_ATEN             0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
+#define USB_DEVICE_ID_ATEN_CS124U      0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC   0x2208
+
+#define USB_VENDOR_ID_AVERMEDIA                0x07ca
+#define USB_DEVICE_ID_AVER_FM_MR800    0xb800
+
+#define USB_VENDOR_ID_BELKIN           0x050d
+#define USB_DEVICE_ID_FLIP_KVM         0x3201
+
+#define USB_VENDOR_ID_BRIGHT           0x1241
+#define USB_DEVICE_ID_BRIGHT_ABNT2     0x1503
+
+#define USB_VENDOR_ID_BERKSHIRE                0x0c98
+#define USB_DEVICE_ID_BERKSHIRE_PCWD   0x1140
+
+#define USB_VENDOR_ID_CHERRY           0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
+
+#define USB_VENDOR_ID_CHIC             0x05fe
+#define USB_DEVICE_ID_CHIC_GAMEPAD     0x0014
+
+#define USB_VENDOR_ID_CHICONY          0x04f2
+#define USB_DEVICE_ID_CHICONY_TACTICAL_PAD     0x0418
+
+#define USB_VENDOR_ID_CIDC             0x1677
+
+#define USB_VENDOR_ID_CMEDIA           0x0d8c
+#define USB_DEVICE_ID_CM109            0x000e
+
+#define USB_VENDOR_ID_CODEMERCS                0x07c0
+#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST      0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW_LAST       0x15ff
+
+#define USB_VENDOR_ID_CYGNAL           0x10c4
+#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
+
+#define USB_VENDOR_ID_CYPRESS          0x04b4
+#define USB_DEVICE_ID_CYPRESS_MOUSE    0x0001
+#define USB_DEVICE_ID_CYPRESS_HIDCOM   0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE       0x7417
+#define USB_DEVICE_ID_CYPRESS_BARCODE_1        0xde61
+#define USB_DEVICE_ID_CYPRESS_BARCODE_2        0xde64
+
+#define USB_VENDOR_ID_DELL             0x413c
+#define USB_DEVICE_ID_DELL_W7658       0x2005
+#define USB_DEVICE_ID_DELL_SK8115      0x2105
+
+#define USB_VENDOR_ID_DELORME          0x1163
+#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20  0x0200
+
+#define USB_VENDOR_ID_DMI              0x0c0b
+#define USB_DEVICE_ID_DMI_ENC          0x5fab
+
+#define USB_VENDOR_ID_ELO              0x04E7
+#define USB_DEVICE_ID_ELO_TS2700       0x0020
+
+#define USB_VENDOR_ID_ESSENTIAL_REALITY        0x0d7f
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+
+#define USB_VENDOR_ID_EZKEY            0x0518
+#define USB_DEVICE_ID_BTC_8193         0x0002
+
+#define USB_VENDOR_ID_GAMERON          0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+
+#define USB_VENDOR_ID_GENERAL_TOUCH    0x0dfc
+
+#define USB_VENDOR_ID_GLAB             0x06c2
+#define USB_DEVICE_ID_4_PHIDGETSERVO_30        0x0038
+#define USB_DEVICE_ID_1_PHIDGETSERVO_30        0x0039
+#define USB_DEVICE_ID_0_0_4_IF_KIT     0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT   0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT     0x0051
+#define USB_DEVICE_ID_0_8_8_IF_KIT     0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL     0x0058
+
+#define USB_VENDOR_ID_GOTOP            0x08f2
+#define USB_DEVICE_ID_SUPER_Q2         0x007f
+#define USB_DEVICE_ID_GOGOPEN          0x00ce
+#define USB_DEVICE_ID_PENPOWER         0x00f4
+
+#define USB_VENDOR_ID_GREENASIA                0x0e8f
+
+#define USB_VENDOR_ID_GRETAGMACBETH    0x0971
+#define USB_DEVICE_ID_GRETAGMACBETH_HUEY       0x2005
+
+#define USB_VENDOR_ID_GRIFFIN          0x077d
+#define USB_DEVICE_ID_POWERMATE                0x0410
+#define USB_DEVICE_ID_SOUNDKNOB                0x04AA
+
+#define USB_VENDOR_ID_GTCO             0x078c
+#define USB_DEVICE_ID_GTCO_90          0x0090
+#define USB_DEVICE_ID_GTCO_100         0x0100
+#define USB_DEVICE_ID_GTCO_101         0x0101
+#define USB_DEVICE_ID_GTCO_103         0x0103
+#define USB_DEVICE_ID_GTCO_104         0x0104
+#define USB_DEVICE_ID_GTCO_105         0x0105
+#define USB_DEVICE_ID_GTCO_106         0x0106
+#define USB_DEVICE_ID_GTCO_107         0x0107
+#define USB_DEVICE_ID_GTCO_108         0x0108
+#define USB_DEVICE_ID_GTCO_200         0x0200
+#define USB_DEVICE_ID_GTCO_201         0x0201
+#define USB_DEVICE_ID_GTCO_202         0x0202
+#define USB_DEVICE_ID_GTCO_203         0x0203
+#define USB_DEVICE_ID_GTCO_204         0x0204
+#define USB_DEVICE_ID_GTCO_205         0x0205
+#define USB_DEVICE_ID_GTCO_206         0x0206
+#define USB_DEVICE_ID_GTCO_207         0x0207
+#define USB_DEVICE_ID_GTCO_300         0x0300
+#define USB_DEVICE_ID_GTCO_301         0x0301
+#define USB_DEVICE_ID_GTCO_302         0x0302
+#define USB_DEVICE_ID_GTCO_303         0x0303
+#define USB_DEVICE_ID_GTCO_304         0x0304
+#define USB_DEVICE_ID_GTCO_305         0x0305
+#define USB_DEVICE_ID_GTCO_306         0x0306
+#define USB_DEVICE_ID_GTCO_307         0x0307
+#define USB_DEVICE_ID_GTCO_308         0x0308
+#define USB_DEVICE_ID_GTCO_309         0x0309
+#define USB_DEVICE_ID_GTCO_400         0x0400
+#define USB_DEVICE_ID_GTCO_401         0x0401
+#define USB_DEVICE_ID_GTCO_402         0x0402
+#define USB_DEVICE_ID_GTCO_403         0x0403
+#define USB_DEVICE_ID_GTCO_404         0x0404
+#define USB_DEVICE_ID_GTCO_405         0x0405
+#define USB_DEVICE_ID_GTCO_500         0x0500
+#define USB_DEVICE_ID_GTCO_501         0x0501
+#define USB_DEVICE_ID_GTCO_502         0x0502
+#define USB_DEVICE_ID_GTCO_503         0x0503
+#define USB_DEVICE_ID_GTCO_504         0x0504
+#define USB_DEVICE_ID_GTCO_1000                0x1000
+#define USB_DEVICE_ID_GTCO_1001                0x1001
+#define USB_DEVICE_ID_GTCO_1002                0x1002
+#define USB_DEVICE_ID_GTCO_1003                0x1003
+#define USB_DEVICE_ID_GTCO_1004                0x1004
+#define USB_DEVICE_ID_GTCO_1005                0x1005
+#define USB_DEVICE_ID_GTCO_1006                0x1006
+#define USB_DEVICE_ID_GTCO_1007                0x1007
+
+#define USB_VENDOR_ID_GYRATION         0x0c16
+#define USB_DEVICE_ID_GYRATION_REMOTE  0x0002
+
+#define USB_VENDOR_ID_HAPP             0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING     0x0010
+#define USB_DEVICE_ID_UGCI_FLYING      0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
+
+#define USB_VENDOR_ID_IMATION          0x0718
+#define USB_DEVICE_ID_DISC_STAKKA      0xd000
+
+#define USB_VENDOR_ID_KBGEAR           0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
+
+#define USB_VENDOR_ID_LABTEC           0x1020
+#define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
+
+#define USB_VENDOR_ID_LD               0x0f11
+#define USB_DEVICE_ID_LD_CASSY         0x1000
+#define USB_DEVICE_ID_LD_POCKETCASSY   0x1010
+#define USB_DEVICE_ID_LD_MOBILECASSY   0x1020
+#define USB_DEVICE_ID_LD_JWM           0x1080
+#define USB_DEVICE_ID_LD_DMMP          0x1081
+#define USB_DEVICE_ID_LD_UMIP          0x1090
+#define USB_DEVICE_ID_LD_XRAY1         0x1100
+#define USB_DEVICE_ID_LD_XRAY2         0x1101
+#define USB_DEVICE_ID_LD_VIDEOCOM      0x1200
+#define USB_DEVICE_ID_LD_COM3LAB       0x2000
+#define USB_DEVICE_ID_LD_TELEPORT      0x2010
+#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
+#define USB_DEVICE_ID_LD_POWERCONTROL  0x2030
+#define USB_DEVICE_ID_LD_MACHINETEST   0x2040
+
+#define USB_VENDOR_ID_LOGITECH         0x046d
+#define USB_DEVICE_ID_LOGITECH_LX3     0xc044
+#define USB_DEVICE_ID_LOGITECH_V150    0xc047
+#define USB_DEVICE_ID_LOGITECH_RECEIVER        0xc101
+#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST  0xc110
+#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD       0xc211
+#define USB_DEVICE_ID_LOGITECH_EXTREME_3D      0xc215
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2      0xc218
+#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2    0xc219
+#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D     0xc283
+#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO     0xc286
+#define USB_DEVICE_ID_LOGITECH_WHEEL   0xc294
+#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL      0xc295
+#define USB_DEVICE_ID_LOGITECH_ELITE_KBD       0xc30a
+#define USB_DEVICE_ID_LOGITECH_KBD     0xc311
+#define USB_DEVICE_ID_S510_RECEIVER    0xc50c
+#define USB_DEVICE_ID_S510_RECEIVER_2  0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500  0xc512
+#define USB_DEVICE_ID_MX3000_RECEIVER  0xc513
+#define USB_DEVICE_ID_DINOVO_DESKTOP   0xc704
+#define USB_DEVICE_ID_DINOVO_EDGE      0xc714
+#define USB_DEVICE_ID_DINOVO_MINI      0xc71f
+#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2     0xca03
+
+#define USB_VENDOR_ID_MCC              0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
+
+#define USB_VENDOR_ID_MGE              0x0463
+#define USB_DEVICE_ID_MGE_UPS          0xffff
+#define USB_DEVICE_ID_MGE_UPS1         0x0001
+
+#define USB_VENDOR_ID_MICROCHIP                0x04d8
+#define USB_DEVICE_ID_PICKIT1          0x0032
+#define USB_DEVICE_ID_PICKIT2          0x0033
+
+#define USB_VENDOR_ID_MICROSOFT                0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV    0x003b
+#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
+#define USB_DEVICE_ID_MS_NE4K          0x00db
+#define USB_DEVICE_ID_MS_LK6K          0x00f9
+#define USB_DEVICE_ID_MS_PRESENTER_8K_BT       0x0701
+#define USB_DEVICE_ID_MS_PRESENTER_8K_USB      0x0713
+
+
+#define USB_VENDOR_ID_MONTEREY         0x0566
+#define USB_DEVICE_ID_GENIUS_KB29E     0x3004
+
+#define USB_VENDOR_ID_NCR              0x0404
+#define USB_DEVICE_ID_NCR_FIRST                0x0300
+#define USB_DEVICE_ID_NCR_LAST         0x03ff
+
+#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
+#define USB_DEVICE_ID_N_S_HARMONY       0xc359
+
+#define USB_VENDOR_ID_NATSU             0x08b7
+#define USB_DEVICE_ID_NATSU_GAMEPAD     0x0001
+
+#define USB_VENDOR_ID_NEC              0x073e
+#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
+
+#define USB_VENDOR_ID_ONTRAK           0x0a07
+#define USB_DEVICE_ID_ONTRAK_ADU100    0x0064
+
+#define USB_VENDOR_ID_PANJIT           0x134c
+
+#define USB_VENDOR_ID_PANTHERLORD      0x0810
+#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK    0x0001
+
+#define USB_VENDOR_ID_PETALYNX         0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE   0x0037
+
+#define USB_VENDOR_ID_PLAYDOTCOM       0x0b43
+#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII     0x0003
+
+#define USB_VENDOR_ID_SAITEK           0x06a3
+#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
+
+#define USB_VENDOR_ID_SAMSUNG          0x0419
+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE        0x0001
+
+#define USB_VENDOR_ID_SONY                     0x054c
+#define USB_DEVICE_ID_SONY_PS3_CONTROLLER      0x0268
+
+#define USB_VENDOR_ID_SOUNDGRAPH       0x15c2
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD      0x0038
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2     0x0036
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3     0x0034
+
+#define USB_VENDOR_ID_SUN              0x0430
+#define USB_DEVICE_ID_RARITAN_KVM_DONGLE       0xcdab
+
+#define USB_VENDOR_ID_SUNPLUS          0x04fc
+#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
+
+#define USB_VENDOR_ID_TENX             0x1130
+#define USB_DEVICE_ID_TENX_IBUDDY1     0x0001
+#define USB_DEVICE_ID_TENX_IBUDDY2     0x0002
+
+#define USB_VENDOR_ID_THRUSTMASTER     0x044f
+
+#define USB_VENDOR_ID_TOPMAX           0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
+
+#define USB_VENDOR_ID_TURBOX           0x062a
+#define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
+
+#define USB_VENDOR_ID_VERNIER          0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP     0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS  0x0004
+#define USB_DEVICE_ID_VERNIER_LCSPEC   0x0006
+
+#define USB_VENDOR_ID_WACOM            0x056a
+
+#define USB_VENDOR_ID_WISEGROUP                0x0925
+#define USB_DEVICE_ID_1_PHIDGETSERVO_20        0x8101
+#define USB_DEVICE_ID_4_PHIDGETSERVO_20        0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT     0x8201
+#define USB_DEVICE_ID_QUAD_USB_JOYPAD  0x8800
+#define USB_DEVICE_ID_DUAL_USB_JOYPAD  0x8866
+
+#define USB_VENDOR_ID_WISEGROUP_LTD    0x6666
+#define USB_VENDOR_ID_WISEGROUP_LTD2   0x6677
+#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
+
+#define USB_VENDOR_ID_YEALINK          0x6993
+#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
+
+#define USB_VENDOR_ID_ZEROPLUS         0x0c12
+
+#define USB_VENDOR_ID_KYE              0x0458
+#define USB_DEVICE_ID_KYE_GPEN_560     0x5003
+
+#endif
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
deleted file mode 100644 (file)
index 16feea0..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- *  HID-input usage mapping quirks
- *
- *  This is used to handle HID-input mappings for devices violating
- *  HUT 1.12 specification.
- *
- * Copyright (c) 2007-2008 Jiri Kosina
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License
- */
-
-#include <linux/input.h>
-#include <linux/hid.h>
-
-#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
-#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
-#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
-#define map_led(c)      do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
-
-#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, *bit); } while (0)
-#define map_key_clear(c)        do { map_key(c); clear_bit(c, *bit); } while (0)
-
-static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x03a: map_key_clear(KEY_SOUND);           break;
-               case 0x03b: map_key_clear(KEY_CAMERA);          break;
-               case 0x03c: map_key_clear(KEY_DOCUMENTS);       break;
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x301: map_key_clear(KEY_PROG1);           break;
-               case 0x302: map_key_clear(KEY_PROG2);           break;
-               case 0x303: map_key_clear(KEY_PROG3);           break;
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
-               return 0;
-
-       set_bit(EV_REP, input->evbit);
-       switch(usage->hid & HID_USAGE) {
-               /* Reported on Logitech Ultra X Media Remote */
-               case 0x004: map_key_clear(KEY_AGAIN);           break;
-               case 0x00d: map_key_clear(KEY_HOME);            break;
-               case 0x024: map_key_clear(KEY_SHUFFLE);         break;
-               case 0x025: map_key_clear(KEY_TV);              break;
-               case 0x026: map_key_clear(KEY_MENU);            break;
-               case 0x031: map_key_clear(KEY_AUDIO);           break;
-               case 0x032: map_key_clear(KEY_TEXT);            break;
-               case 0x033: map_key_clear(KEY_LAST);            break;
-               case 0x047: map_key_clear(KEY_MP3);             break;
-               case 0x048: map_key_clear(KEY_DVD);             break;
-               case 0x049: map_key_clear(KEY_MEDIA);           break;
-               case 0x04a: map_key_clear(KEY_VIDEO);           break;
-               case 0x04b: map_key_clear(KEY_ANGLE);           break;
-               case 0x04c: map_key_clear(KEY_LANGUAGE);        break;
-               case 0x04d: map_key_clear(KEY_SUBTITLE);        break;
-               case 0x051: map_key_clear(KEY_RED);             break;
-               case 0x052: map_key_clear(KEY_CLOSE);           break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
-               return 0;
-
-       set_bit(EV_REP, input->evbit);
-       switch(usage->hid & HID_USAGE) {
-               /* Reported on Gyration MCE Remote */
-               case 0x00d: map_key_clear(KEY_HOME);            break;
-               case 0x024: map_key_clear(KEY_DVD);             break;
-               case 0x025: map_key_clear(KEY_PVR);             break;
-               case 0x046: map_key_clear(KEY_MEDIA);           break;
-               case 0x047: map_key_clear(KEY_MP3);             break;
-               case 0x049: map_key_clear(KEY_CAMERA);          break;
-               case 0x04a: map_key_clear(KEY_VIDEO);           break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-               return 0;
-
-       set_bit(EV_REP, input->evbit);
-       switch (usage->hid & HID_USAGE) {
-               case 0xff01: map_key_clear(BTN_1);              break;
-               case 0xff02: map_key_clear(BTN_2);              break;
-               case 0xff03: map_key_clear(BTN_3);              break;
-               case 0xff04: map_key_clear(BTN_4);              break;
-               case 0xff05: map_key_clear(BTN_5);              break;
-               case 0xff06: map_key_clear(BTN_6);              break;
-               case 0xff07: map_key_clear(BTN_7);              break;
-               case 0xff08: map_key_clear(BTN_8);              break;
-               case 0xff09: map_key_clear(BTN_9);              break;
-               case 0xff0a: map_key_clear(BTN_A);              break;
-               case 0xff0b: map_key_clear(BTN_B);              break;
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-               return 0;
-
-       switch(usage->hid & HID_USAGE) {
-               case 0xfd06: map_key_clear(KEY_CHAT);           break;
-               case 0xfd07: map_key_clear(KEY_PHONE);          break;
-               case 0xff05:
-                       set_bit(EV_REP, input->evbit);
-                       map_key_clear(KEY_F13);
-                       set_bit(KEY_F14, input->keybit);
-                       set_bit(KEY_F15, input->keybit);
-                       set_bit(KEY_F16, input->keybit);
-                       set_bit(KEY_F17, input->keybit);
-                       set_bit(KEY_F18, input->keybit);
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-               return 0;
-
-       set_bit(EV_REP, input->evbit);
-       switch(usage->hid & HID_USAGE) {
-               case 0xfd08: map_key_clear(KEY_FORWARD);        break;
-               case 0xfd09: map_key_clear(KEY_BACK);           break;
-               case 0xfd0b: map_key_clear(KEY_PLAYPAUSE);      break;
-               case 0xfd0e: map_key_clear(KEY_CLOSE);          break;
-               case 0xfd0f: map_key_clear(KEY_PLAY);           break;
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
-                       ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
-               return 0;
-
-       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR)
-               switch(usage->hid & HID_USAGE) {
-                       case 0x05a: map_key_clear(KEY_TEXT);            break;
-                       case 0x05b: map_key_clear(KEY_RED);             break;
-                       case 0x05c: map_key_clear(KEY_GREEN);           break;
-                       case 0x05d: map_key_clear(KEY_YELLOW);          break;
-                       case 0x05e: map_key_clear(KEY_BLUE);            break;
-                       default:
-                               return 0;
-               }
-
-       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
-               switch(usage->hid & HID_USAGE) {
-                       case 0x0f6: map_key_clear(KEY_NEXT);            break;
-                       case 0x0fa: map_key_clear(KEY_BACK);            break;
-                       default:
-                               return 0;
-               }
-       return 1;
-}
-
-static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x1001: map_key_clear(KEY_MESSENGER);      break;
-               case 0x1003: map_key_clear(KEY_SOUND);          break;
-               case 0x1004: map_key_clear(KEY_VIDEO);          break;
-               case 0x1005: map_key_clear(KEY_AUDIO);          break;
-               case 0x100a: map_key_clear(KEY_DOCUMENTS);      break;
-               case 0x1011: map_key_clear(KEY_PREVIOUSSONG);   break;
-               case 0x1012: map_key_clear(KEY_NEXTSONG);       break;
-               case 0x1013: map_key_clear(KEY_CAMERA);         break;
-               case 0x1014: map_key_clear(KEY_MESSENGER);      break;
-               case 0x1015: map_key_clear(KEY_RECORD);         break;
-               case 0x1016: map_key_clear(KEY_PLAYER);         break;
-               case 0x1017: map_key_clear(KEY_EJECTCD);        break;
-               case 0x1018: map_key_clear(KEY_MEDIA);          break;
-               case 0x1019: map_key_clear(KEY_PROG1);          break;
-               case 0x101a: map_key_clear(KEY_PROG2);          break;
-               case 0x101b: map_key_clear(KEY_PROG3);          break;
-               case 0x101f: map_key_clear(KEY_ZOOMIN);         break;
-               case 0x1020: map_key_clear(KEY_ZOOMOUT);        break;
-               case 0x1021: map_key_clear(KEY_ZOOMRESET);      break;
-               case 0x1023: map_key_clear(KEY_CLOSE);          break;
-               case 0x1027: map_key_clear(KEY_MENU);           break;
-               /* this one is marked as 'Rotate' */
-               case 0x1028: map_key_clear(KEY_ANGLE);          break;
-               case 0x1029: map_key_clear(KEY_SHUFFLE);        break;
-               case 0x102a: map_key_clear(KEY_BACK);           break;
-               case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   break;
-               case 0x1041: map_key_clear(KEY_BATTERY);        break;
-               case 0x1042: map_key_clear(KEY_WORDPROCESSOR);  break;
-               case 0x1043: map_key_clear(KEY_SPREADSHEET);    break;
-               case 0x1044: map_key_clear(KEY_PRESENTATION);   break;
-               case 0x1045: map_key_clear(KEY_UNDO);           break;
-               case 0x1046: map_key_clear(KEY_REDO);           break;
-               case 0x1047: map_key_clear(KEY_PRINT);          break;
-               case 0x1048: map_key_clear(KEY_SAVE);           break;
-               case 0x1049: map_key_clear(KEY_PROG1);          break;
-               case 0x104a: map_key_clear(KEY_PROG2);          break;
-               case 0x104b: map_key_clear(KEY_PROG3);          break;
-               case 0x104c: map_key_clear(KEY_PROG4);          break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x156: map_key_clear(KEY_WORDPROCESSOR);   break;
-               case 0x157: map_key_clear(KEY_SPREADSHEET);     break;
-               case 0x158: map_key_clear(KEY_PRESENTATION);    break;
-               case 0x15c: map_key_clear(KEY_STOP);            break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x230: map_key(BTN_MOUSE);                 break;
-               case 0x231: map_rel(REL_WHEEL);                 break;
-               /* 
-                * this keyboard has a scrollwheel implemented in
-                * totally broken way. We map this usage temporarily
-                * to HWHEEL and handle it in the event quirk handler
-                */
-               case 0x232: map_rel(REL_HWHEEL);                break;
-
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-static int quirk_sunplus_wdesktop(struct hid_usage *usage, struct input_dev *input,
-                             unsigned long **bit, int *max)
-{
-       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-               return 0;
-
-       switch (usage->hid & HID_USAGE) {
-               case 0x2003: map_key_clear(KEY_ZOOMIN);         break;
-               case 0x2103: map_key_clear(KEY_ZOOMOUT);        break;
-               default:
-                       return 0;
-       }
-       return 1;
-}
-
-#define VENDOR_ID_BELKIN                       0x1020
-#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD     0x0006
-
-#define VENDOR_ID_CHERRY                       0x046a
-#define DEVICE_ID_CHERRY_CYMOTION              0x0023
-
-#define VENDOR_ID_CHICONY                      0x04f2
-#define DEVICE_ID_CHICONY_TACTICAL_PAD         0x0418
-
-#define VENDOR_ID_EZKEY                                0x0518
-#define DEVICE_ID_BTC_8193                     0x0002
-
-#define VENDOR_ID_GYRATION                     0x0c16
-#define DEVICE_ID_GYRATION_REMOTE              0x0002
-
-#define VENDOR_ID_LOGITECH                     0x046d
-#define DEVICE_ID_LOGITECH_RECEIVER            0xc101
-#define DEVICE_ID_S510_RECEIVER                        0xc50c
-#define DEVICE_ID_S510_RECEIVER_2              0xc517
-#define DEVICE_ID_MX3000_RECEIVER              0xc513
-
-#define VENDOR_ID_MICROSOFT                    0x045e
-#define DEVICE_ID_MS4K                         0x00db
-#define DEVICE_ID_MS6K                         0x00f9
-#define DEVICE_IS_MS_PRESENTER_8K_BT           0x0701
-#define DEVICE_ID_MS_PRESENTER_8K_USB          0x0713
-
-#define VENDOR_ID_MONTEREY                     0x0566
-#define DEVICE_ID_GENIUS_KB29E                 0x3004
-
-#define VENDOR_ID_PETALYNX                     0x18b1
-#define DEVICE_ID_PETALYNX_MAXTER_REMOTE       0x0037
-
-#define VENDOR_ID_SUNPLUS                      0x04fc
-#define DEVICE_ID_SUNPLUS_WDESKTOP             0x05d8
-
-static const struct hid_input_blacklist {
-       __u16 idVendor;
-       __u16 idProduct;
-       int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
-} hid_input_blacklist[] = {
-       { VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
-
-       { VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion },
-
-       { VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad },
-
-       { VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
-
-       { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },
-
-       { VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
-       { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
-       { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
-       { VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },
-
-       { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
-       { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
-       { VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
-       { VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k },
-
-       { VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
-
-       { VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
-
-       { VENDOR_ID_SUNPLUS, DEVICE_ID_SUNPLUS_WDESKTOP, quirk_sunplus_wdesktop },
-
-       { 0, 0, NULL }
-};
-
-int hidinput_mapping_quirks(struct hid_usage *usage, 
-                                  struct input_dev *input, 
-                                  unsigned long **bit, int *max)
-{
-       struct hid_device *device = input_get_drvdata(input);
-       int i = 0;
-       
-       while (hid_input_blacklist[i].quirk) {
-               if (hid_input_blacklist[i].idVendor == device->vendor &&
-                               hid_input_blacklist[i].idProduct == device->product)
-                       return hid_input_blacklist[i].quirk(usage, input, bit, max);
-               i++;
-       }
-       return 0;
-}
-
-int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
-       struct input_dev *input;
-
-       input = field->hidinput->input;
-
-       if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
-               || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
-               if (value) hid->quirks |=  HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
-               else       hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
-               return 1;
-       }
-
-       if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
-                       (usage->type == EV_REL) &&
-                       (usage->code == REL_WHEEL)) {
-               hid->delayed_value = value;
-               return 1;
-       }
-
-       if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
-                       (usage->hid == 0x000100b8)) {
-               input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
-               return 1;
-       }
-
-       if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
-               input_event(input, usage->type, usage->code, -value);
-               return 1;
-       }
-
-       if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
-               input_event(input, usage->type, REL_HWHEEL, value);
-               return 1;
-       }
-
-       if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
-               return 1;
-
-       /* Handling MS keyboards special buttons */
-       if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && 
-                       usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
-               int key = 0;
-               static int last_key = 0;
-               switch (value) {
-                       case 0x01: key = KEY_F14; break;
-                       case 0x02: key = KEY_F15; break;
-                       case 0x04: key = KEY_F16; break;
-                       case 0x08: key = KEY_F17; break;
-                       case 0x10: key = KEY_F18; break;
-                       default: break;
-               }
-               if (key) {
-                       input_event(input, usage->type, key, 1);
-                       last_key = key;
-               } else {
-                       input_event(input, usage->type, last_key, 0);
-               }
-       }
-
-       /* handle the temporary quirky mapping to HWHEEL */
-       if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
-                       usage->type == EV_REL && usage->code == REL_HWHEEL) {
-               input_event(input, usage->type, REL_WHEEL, -value);
-               return 1;
-       }
-
-       /* Gyration MCE remote "Sleep" key */
-       if (hid->vendor == VENDOR_ID_GYRATION &&
-           hid->product == DEVICE_ID_GYRATION_REMOTE &&
-           (usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
-           (usage->hid & 0xff) == 0x82) {
-               input_event(input, usage->type, usage->code, 1);
-               input_sync(input);
-               input_event(input, usage->type, usage->code, 0);
-               input_sync(input);
-               return 1;
-       }
-       return 0;
-}
-
-
index 1b2e8dc3398d7bf972243507d695f14e2093aaa0..7f183b7147e119b9ac1ea0e98d8c81bce662aaf3 100644 (file)
 #include <linux/hid.h>
 #include <linux/hid-debug.h>
 
-static int hid_apple_fnmode = 1;
-module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
-               "Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
 #define unk    KEY_UNKNOWN
 
 static const unsigned char hid_keyboard[256] = {
@@ -58,227 +53,20 @@ static const unsigned char hid_keyboard[256] = {
        150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
 
-/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
-#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
-static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
-         0,216,  0,213,175,156,  0,  0,  0,  0,
-       144,  0,  0,  0,  0,  0,  0,  0,  0,212,
-       174,167,152,161,112,  0,  0,  0,154,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,183,184,185,186,187,
-       188,189,190,191,192,193,194,  0,  0,  0
-};
-
 static const struct {
        __s32 x;
        __s32 y;
 }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
 
-#define map_abs(c)     do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
-#define map_rel(c)     do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
-#define map_key(c)     do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
-#define map_led(c)     do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
-
-#define map_abs_clear(c)       do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_key_clear(c)       do { map_key(c); clear_bit(c, bit); } while (0)
-
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-
-struct hidinput_key_translation {
-       u16 from;
-       u16 to;
-       u8 flags;
-};
-
-#define APPLE_FLAG_FKEY 0x01
-
-static struct hidinput_key_translation apple_fn_keys[] = {
-       { KEY_BACKSPACE, KEY_DELETE },
-       { KEY_F1,       KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
-       { KEY_F2,       KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
-       { KEY_F3,       KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
-       { KEY_F4,       KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
-       { KEY_F5,       KEY_KBDILLUMDOWN,   APPLE_FLAG_FKEY },
-       { KEY_F6,       KEY_KBDILLUMUP,     APPLE_FLAG_FKEY },
-       { KEY_F7,       KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
-       { KEY_F8,       KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
-       { KEY_F9,       KEY_NEXTSONG,       APPLE_FLAG_FKEY },
-       { KEY_F10,      KEY_MUTE,           APPLE_FLAG_FKEY },
-       { KEY_F11,      KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
-       { KEY_F12,      KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
-       { KEY_UP,       KEY_PAGEUP },
-       { KEY_DOWN,     KEY_PAGEDOWN },
-       { KEY_LEFT,     KEY_HOME },
-       { KEY_RIGHT,    KEY_END },
-       { }
-};
-
-static struct hidinput_key_translation powerbook_fn_keys[] = {
-       { KEY_BACKSPACE, KEY_DELETE },
-       { KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
-       { KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
-       { KEY_F3,       KEY_MUTE,               APPLE_FLAG_FKEY },
-       { KEY_F4,       KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
-       { KEY_F5,       KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
-       { KEY_F6,       KEY_NUMLOCK,            APPLE_FLAG_FKEY },
-       { KEY_F7,       KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
-       { KEY_F8,       KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
-       { KEY_F9,       KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
-       { KEY_F10,      KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
-       { KEY_UP,       KEY_PAGEUP },
-       { KEY_DOWN,     KEY_PAGEDOWN },
-       { KEY_LEFT,     KEY_HOME },
-       { KEY_RIGHT,    KEY_END },
-       { }
-};
-
-static struct hidinput_key_translation powerbook_numlock_keys[] = {
-       { KEY_J,        KEY_KP1 },
-       { KEY_K,        KEY_KP2 },
-       { KEY_L,        KEY_KP3 },
-       { KEY_U,        KEY_KP4 },
-       { KEY_I,        KEY_KP5 },
-       { KEY_O,        KEY_KP6 },
-       { KEY_7,        KEY_KP7 },
-       { KEY_8,        KEY_KP8 },
-       { KEY_9,        KEY_KP9 },
-       { KEY_M,        KEY_KP0 },
-       { KEY_DOT,      KEY_KPDOT },
-       { KEY_SLASH,    KEY_KPPLUS },
-       { KEY_SEMICOLON, KEY_KPMINUS },
-       { KEY_P,        KEY_KPASTERISK },
-       { KEY_MINUS,    KEY_KPEQUAL },
-       { KEY_0,        KEY_KPSLASH },
-       { KEY_F6,       KEY_NUMLOCK },
-       { KEY_KPENTER,  KEY_KPENTER },
-       { KEY_BACKSPACE, KEY_BACKSPACE },
-       { }
-};
-
-static struct hidinput_key_translation apple_iso_keyboard[] = {
-       { KEY_GRAVE,    KEY_102ND },
-       { KEY_102ND,    KEY_GRAVE },
-       { }
-};
+#define map_abs(c)     hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))
+#define map_rel(c)     hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c))
+#define map_key(c)     hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c))
+#define map_led(c)     hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c))
 
-static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
-{
-       struct hidinput_key_translation *trans;
-
-       /* Look for the translation */
-       for (trans = table; trans->from; trans++)
-               if (trans->from == from)
-                       return trans;
-
-       return NULL;
-}
-
-int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
-               struct hid_usage *usage, __s32 value)
-{
-       struct hidinput_key_translation *trans;
-
-       if (usage->code == KEY_FN) {
-               if (value) hid->quirks |=  HID_QUIRK_APPLE_FN_ON;
-               else       hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
-
-               input_event(input, usage->type, usage->code, value);
-
-               return 1;
-       }
-
-       if (hid_apple_fnmode) {
-               int do_translate;
-
-               trans = find_translation((hid->product < 0x220 ||
-                                         hid->product >= 0x300) ?
-                                        powerbook_fn_keys : apple_fn_keys,
-                                        usage->code);
-               if (trans) {
-                       if (test_bit(usage->code, hid->apple_pressed_fn))
-                               do_translate = 1;
-                       else if (trans->flags & APPLE_FLAG_FKEY)
-                               do_translate =
-                                       (hid_apple_fnmode == 2 &&  (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
-                                       (hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
-                       else
-                               do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
-
-                       if (do_translate) {
-                               if (value)
-                                       set_bit(usage->code, hid->apple_pressed_fn);
-                               else
-                                       clear_bit(usage->code, hid->apple_pressed_fn);
-
-                               input_event(input, usage->type, trans->to, value);
-
-                               return 1;
-                       }
-               }
-
-               if (hid->quirks & HID_QUIRK_APPLE_NUMLOCK_EMULATION && (
-                               test_bit(usage->code, hid->pb_pressed_numlock) ||
-                               test_bit(LED_NUML, input->led))) {
-                       trans = find_translation(powerbook_numlock_keys, usage->code);
-
-                       if (trans) {
-                               if (value)
-                                       set_bit(usage->code, hid->pb_pressed_numlock);
-                               else
-                                       clear_bit(usage->code, hid->pb_pressed_numlock);
-
-                               input_event(input, usage->type, trans->to, value);
-                       }
-
-                       return 1;
-               }
-       }
-
-       if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
-               trans = find_translation(apple_iso_keyboard, usage->code);
-               if (trans) {
-                       input_event(input, usage->type, trans->to, value);
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-static void hidinput_apple_setup(struct input_dev *input)
-{
-       struct hidinput_key_translation *trans;
-
-       set_bit(KEY_NUMLOCK, input->keybit);
-
-       /* Enable all needed keys */
-       for (trans = apple_fn_keys; trans->from; trans++)
-               set_bit(trans->to, input->keybit);
-
-       for (trans = powerbook_fn_keys; trans->from; trans++)
-               set_bit(trans->to, input->keybit);
-
-       for (trans = powerbook_numlock_keys; trans->from; trans++)
-               set_bit(trans->to, input->keybit);
-
-       for (trans = apple_iso_keyboard; trans->from; trans++)
-               set_bit(trans->to, input->keybit);
-
-}
-#else
-inline int hidinput_apple_event(struct hid_device *hid,
-                                      struct input_dev *input,
-                                      struct hid_usage *usage, __s32 value)
-{
-       return 0;
-}
-
-static inline void hidinput_apple_setup(struct input_dev *input)
-{
-}
-#endif
+#define map_abs_clear(c)       hid_map_usage_clear(hidinput, usage, &bit, \
+               &max, EV_ABS, (c))
+#define map_key_clear(c)       hid_map_usage_clear(hidinput, usage, &bit, \
+               &max, EV_KEY, (c))
 
 static inline int match_scancode(int code, int scancode)
 {
@@ -366,7 +154,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 {
        struct input_dev *input = hidinput->input;
        struct hid_device *device = input_get_drvdata(input);
-       int max = 0, code, ret;
+       int max = 0, code;
        unsigned long *bit = NULL;
 
        field->hidinput = hidinput;
@@ -385,406 +173,345 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                goto ignore;
        }
 
-       /* handle input mappings for quirky devices */
-       ret = hidinput_mapping_quirks(usage, input, &bit, &max);
-       if (ret)
-               goto mapped;
+       if (device->driver->input_mapping) {
+               int ret = device->driver->input_mapping(device, hidinput, field,
+                               usage, &bit, &max);
+               if (ret > 0)
+                       goto mapped;
+               if (ret < 0)
+                       goto ignore;
+       }
 
        switch (usage->hid & HID_USAGE_PAGE) {
+       case HID_UP_UNDEFINED:
+               goto ignore;
 
-               case HID_UP_UNDEFINED:
-                       goto ignore;
-
-               case HID_UP_KEYBOARD:
+       case HID_UP_KEYBOARD:
+               set_bit(EV_REP, input->evbit);
 
-                       set_bit(EV_REP, input->evbit);
+               if ((usage->hid & HID_USAGE) < 256) {
+                       if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
+                       map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
+               } else
+                       map_key(KEY_UNKNOWN);
 
-                       if ((usage->hid & HID_USAGE) < 256) {
-                               if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
-                               map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
-                       } else
-                               map_key(KEY_UNKNOWN);
+               break;
 
-                       break;
+       case HID_UP_BUTTON:
+               code = ((usage->hid - 1) & 0xf);
 
-               case HID_UP_BUTTON:
-
-                       code = ((usage->hid - 1) & 0xf);
-
-                       switch (field->application) {
-                               case HID_GD_MOUSE:
-                               case HID_GD_POINTER:  code += 0x110; break;
-                               case HID_GD_JOYSTICK: code += 0x120; break;
-                               case HID_GD_GAMEPAD:  code += 0x130; break;
-                               default:
-                                       switch (field->physical) {
-                                               case HID_GD_MOUSE:
-                                               case HID_GD_POINTER:  code += 0x110; break;
-                                               case HID_GD_JOYSTICK: code += 0x120; break;
-                                               case HID_GD_GAMEPAD:  code += 0x130; break;
-                                               default:              code += 0x100;
-                                       }
-                       }
-
-                       /* Special handling for Logitech Cordless Desktop */
-                       if (field->application != HID_GD_MOUSE) {
-                               if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
-                                       int hid = usage->hid & HID_USAGE;
-                                       if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
-                                               code = logitech_expanded_keymap[hid];
-                               }
-                       } else {
-                               if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
-                                       int hid = usage->hid & HID_USAGE;
-                                       if (hid == 7 || hid == 8)
-                                               goto ignore;
-                               }
+               switch (field->application) {
+               case HID_GD_MOUSE:
+               case HID_GD_POINTER:  code += 0x110; break;
+               case HID_GD_JOYSTICK: code += 0x120; break;
+               case HID_GD_GAMEPAD:  code += 0x130; break;
+               default:
+                       switch (field->physical) {
+                       case HID_GD_MOUSE:
+                       case HID_GD_POINTER:  code += 0x110; break;
+                       case HID_GD_JOYSTICK: code += 0x120; break;
+                       case HID_GD_GAMEPAD:  code += 0x130; break;
+                       default:              code += 0x100;
                        }
+               }
 
-                       map_key(code);
-                       break;
-
-
-               case HID_UP_SIMULATION:
-
-                       switch (usage->hid & 0xffff) {
-                               case 0xba: map_abs(ABS_RUDDER);   break;
-                               case 0xbb: map_abs(ABS_THROTTLE); break;
-                               case 0xc4: map_abs(ABS_GAS);      break;
-                               case 0xc5: map_abs(ABS_BRAKE);    break;
-                               case 0xc8: map_abs(ABS_WHEEL);    break;
-                               default:   goto ignore;
+               map_key(code);
+               break;
+
+       case HID_UP_SIMULATION:
+               switch (usage->hid & 0xffff) {
+               case 0xba: map_abs(ABS_RUDDER);   break;
+               case 0xbb: map_abs(ABS_THROTTLE); break;
+               case 0xc4: map_abs(ABS_GAS);      break;
+               case 0xc5: map_abs(ABS_BRAKE);    break;
+               case 0xc8: map_abs(ABS_WHEEL);    break;
+               default:   goto ignore;
+               }
+               break;
+
+       case HID_UP_GENDESK:
+               if ((usage->hid & 0xf0) == 0x80) {      /* SystemControl */
+                       switch (usage->hid & 0xf) {
+                       case 0x1: map_key_clear(KEY_POWER);  break;
+                       case 0x2: map_key_clear(KEY_SLEEP);  break;
+                       case 0x3: map_key_clear(KEY_WAKEUP); break;
+                       default: goto unknown;
                        }
                        break;
+               }
 
-               case HID_UP_GENDESK:
-
-                       if ((usage->hid & 0xf0) == 0x80) {      /* SystemControl */
-                               switch (usage->hid & 0xf) {
-                                       case 0x1: map_key_clear(KEY_POWER);  break;
-                                       case 0x2: map_key_clear(KEY_SLEEP);  break;
-                                       case 0x3: map_key_clear(KEY_WAKEUP); break;
-                                       default: goto unknown;
-                               }
-                               break;
-                       }
-
-                       if ((usage->hid & 0xf0) == 0x90) {      /* D-pad */
-                               switch (usage->hid) {
-                                       case HID_GD_UP:    usage->hat_dir = 1; break;
-                                       case HID_GD_DOWN:  usage->hat_dir = 5; break;
-                                       case HID_GD_RIGHT: usage->hat_dir = 3; break;
-                                       case HID_GD_LEFT:  usage->hat_dir = 7; break;
-                                       default: goto unknown;
-                               }
-                               if (field->dpad) {
-                                       map_abs(field->dpad);
-                                       goto ignore;
-                               }
-                               map_abs(ABS_HAT0X);
-                               break;
-                       }
-
+               if ((usage->hid & 0xf0) == 0x90) {      /* D-pad */
                        switch (usage->hid) {
-
-                               /* These usage IDs map directly to the usage codes. */
-                               case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
-                               case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
-                               case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
-                                       if (field->flags & HID_MAIN_ITEM_RELATIVE)
-                                               map_rel(usage->hid & 0xf);
-                                       else
-                                               map_abs(usage->hid & 0xf);
-                                       break;
-
-                               case HID_GD_HATSWITCH:
-                                       usage->hat_min = field->logical_minimum;
-                                       usage->hat_max = field->logical_maximum;
-                                       map_abs(ABS_HAT0X);
-                                       break;
-
-                               case HID_GD_START:      map_key_clear(BTN_START);       break;
-                               case HID_GD_SELECT:     map_key_clear(BTN_SELECT);      break;
-
-                               default: goto unknown;
+                       case HID_GD_UP:    usage->hat_dir = 1; break;
+                       case HID_GD_DOWN:  usage->hat_dir = 5; break;
+                       case HID_GD_RIGHT: usage->hat_dir = 3; break;
+                       case HID_GD_LEFT:  usage->hat_dir = 7; break;
+                       default: goto unknown;
                        }
-
-                       break;
-
-               case HID_UP_LED:
-
-                       switch (usage->hid & 0xffff) {                        /* HID-Value:                   */
-                               case 0x01:  map_led (LED_NUML);     break;    /*   "Num Lock"                 */
-                               case 0x02:  map_led (LED_CAPSL);    break;    /*   "Caps Lock"                */
-                               case 0x03:  map_led (LED_SCROLLL);  break;    /*   "Scroll Lock"              */
-                               case 0x04:  map_led (LED_COMPOSE);  break;    /*   "Compose"                  */
-                               case 0x05:  map_led (LED_KANA);     break;    /*   "Kana"                     */
-                               case 0x27:  map_led (LED_SLEEP);    break;    /*   "Stand-By"                 */
-                               case 0x4c:  map_led (LED_SUSPEND);  break;    /*   "System Suspend"           */
-                               case 0x09:  map_led (LED_MUTE);     break;    /*   "Mute"                     */
-                               case 0x4b:  map_led (LED_MISC);     break;    /*   "Generic Indicator"        */
-                               case 0x19:  map_led (LED_MAIL);     break;    /*   "Message Waiting"          */
-                               case 0x4d:  map_led (LED_CHARGING); break;    /*   "External Power Connected" */
-
-                               default: goto ignore;
+                       if (field->dpad) {
+                               map_abs(field->dpad);
+                               goto ignore;
                        }
+                       map_abs(ABS_HAT0X);
                        break;
+               }
 
-               case HID_UP_DIGITIZER:
-
-                       switch (usage->hid & 0xff) {
-
-                               case 0x30: /* TipPressure */
-                                       if (!test_bit(BTN_TOUCH, input->keybit)) {
-                                               device->quirks |= HID_QUIRK_NOTOUCH;
-                                               set_bit(EV_KEY, input->evbit);
-                                               set_bit(BTN_TOUCH, input->keybit);
-                                       }
-
-                                       map_abs_clear(ABS_PRESSURE);
-                                       break;
-
-                               case 0x32: /* InRange */
-                                       switch (field->physical & 0xff) {
-                                               case 0x21: map_key(BTN_TOOL_MOUSE); break;
-                                               case 0x22: map_key(BTN_TOOL_FINGER); break;
-                                               default: map_key(BTN_TOOL_PEN); break;
-                                       }
-                                       break;
+               switch (usage->hid) {
+               /* These usage IDs map directly to the usage codes. */
+               case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
+               case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
+               case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
+                       if (field->flags & HID_MAIN_ITEM_RELATIVE)
+                               map_rel(usage->hid & 0xf);
+                       else
+                               map_abs(usage->hid & 0xf);
+                       break;
 
-                               case 0x3c: /* Invert */
-                                       map_key_clear(BTN_TOOL_RUBBER);
-                                       break;
+               case HID_GD_HATSWITCH:
+                       usage->hat_min = field->logical_minimum;
+                       usage->hat_max = field->logical_maximum;
+                       map_abs(ABS_HAT0X);
+                       break;
 
-                               case 0x33: /* Touch */
-                               case 0x42: /* TipSwitch */
-                               case 0x43: /* TipSwitch2 */
-                                       device->quirks &= ~HID_QUIRK_NOTOUCH;
-                                       map_key_clear(BTN_TOUCH);
-                                       break;
+               case HID_GD_START:      map_key_clear(BTN_START);       break;
+               case HID_GD_SELECT:     map_key_clear(BTN_SELECT);      break;
 
-                               case 0x44: /* BarrelSwitch */
-                                       map_key_clear(BTN_STYLUS);
-                                       break;
+               default: goto unknown;
+               }
 
-                               default:  goto unknown;
+               break;
+
+       case HID_UP_LED:
+               switch (usage->hid & 0xffff) {                /* HID-Value:                   */
+               case 0x01:  map_led (LED_NUML);     break;    /*   "Num Lock"                 */
+               case 0x02:  map_led (LED_CAPSL);    break;    /*   "Caps Lock"                */
+               case 0x03:  map_led (LED_SCROLLL);  break;    /*   "Scroll Lock"              */
+               case 0x04:  map_led (LED_COMPOSE);  break;    /*   "Compose"                  */
+               case 0x05:  map_led (LED_KANA);     break;    /*   "Kana"                     */
+               case 0x27:  map_led (LED_SLEEP);    break;    /*   "Stand-By"                 */
+               case 0x4c:  map_led (LED_SUSPEND);  break;    /*   "System Suspend"           */
+               case 0x09:  map_led (LED_MUTE);     break;    /*   "Mute"                     */
+               case 0x4b:  map_led (LED_MISC);     break;    /*   "Generic Indicator"        */
+               case 0x19:  map_led (LED_MAIL);     break;    /*   "Message Waiting"          */
+               case 0x4d:  map_led (LED_CHARGING); break;    /*   "External Power Connected" */
+
+               default: goto ignore;
+               }
+               break;
+
+       case HID_UP_DIGITIZER:
+               switch (usage->hid & 0xff) {
+               case 0x30: /* TipPressure */
+                       if (!test_bit(BTN_TOUCH, input->keybit)) {
+                               device->quirks |= HID_QUIRK_NOTOUCH;
+                               set_bit(EV_KEY, input->evbit);
+                               set_bit(BTN_TOUCH, input->keybit);
                        }
+                       map_abs_clear(ABS_PRESSURE);
                        break;
 
-               case HID_UP_CONSUMER:   /* USB HUT v1.1, pages 56-62 */
-
-                       switch (usage->hid & HID_USAGE) {
-                               case 0x000: goto ignore;
-                               case 0x034: map_key_clear(KEY_SLEEP);           break;
-                               case 0x036: map_key_clear(BTN_MISC);            break;
-
-                               case 0x040: map_key_clear(KEY_MENU);            break;
-                               case 0x045: map_key_clear(KEY_RADIO);           break;
-
-                               case 0x083: map_key_clear(KEY_LAST);            break;
-                               case 0x088: map_key_clear(KEY_PC);              break;
-                               case 0x089: map_key_clear(KEY_TV);              break;
-                               case 0x08a: map_key_clear(KEY_WWW);             break;
-                               case 0x08b: map_key_clear(KEY_DVD);             break;
-                               case 0x08c: map_key_clear(KEY_PHONE);           break;
-                               case 0x08d: map_key_clear(KEY_PROGRAM);         break;
-                               case 0x08e: map_key_clear(KEY_VIDEOPHONE);      break;
-                               case 0x08f: map_key_clear(KEY_GAMES);           break;
-                               case 0x090: map_key_clear(KEY_MEMO);            break;
-                               case 0x091: map_key_clear(KEY_CD);              break;
-                               case 0x092: map_key_clear(KEY_VCR);             break;
-                               case 0x093: map_key_clear(KEY_TUNER);           break;
-                               case 0x094: map_key_clear(KEY_EXIT);            break;
-                               case 0x095: map_key_clear(KEY_HELP);            break;
-                               case 0x096: map_key_clear(KEY_TAPE);            break;
-                               case 0x097: map_key_clear(KEY_TV2);             break;
-                               case 0x098: map_key_clear(KEY_SAT);             break;
-                               case 0x09a: map_key_clear(KEY_PVR);             break;
-
-                               case 0x09c: map_key_clear(KEY_CHANNELUP);       break;
-                               case 0x09d: map_key_clear(KEY_CHANNELDOWN);     break;
-                               case 0x0a0: map_key_clear(KEY_VCR2);            break;
-
-                               case 0x0b0: map_key_clear(KEY_PLAY);            break;
-                               case 0x0b1: map_key_clear(KEY_PAUSE);           break;
-                               case 0x0b2: map_key_clear(KEY_RECORD);          break;
-                               case 0x0b3: map_key_clear(KEY_FASTFORWARD);     break;
-                               case 0x0b4: map_key_clear(KEY_REWIND);          break;
-                               case 0x0b5: map_key_clear(KEY_NEXTSONG);        break;
-                               case 0x0b6: map_key_clear(KEY_PREVIOUSSONG);    break;
-                               case 0x0b7: map_key_clear(KEY_STOPCD);          break;
-                               case 0x0b8: map_key_clear(KEY_EJECTCD);         break;
-                               case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT);    break;
-
-                               case 0x0cd: map_key_clear(KEY_PLAYPAUSE);       break;
-                               case 0x0e0: map_abs_clear(ABS_VOLUME);          break;
-                               case 0x0e2: map_key_clear(KEY_MUTE);            break;
-                               case 0x0e5: map_key_clear(KEY_BASSBOOST);       break;
-                               case 0x0e9: map_key_clear(KEY_VOLUMEUP);        break;
-                               case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);      break;
-
-                               case 0x182: map_key_clear(KEY_BOOKMARKS);       break;
-                               case 0x183: map_key_clear(KEY_CONFIG);          break;
-                               case 0x184: map_key_clear(KEY_WORDPROCESSOR);   break;
-                               case 0x185: map_key_clear(KEY_EDITOR);          break;
-                               case 0x186: map_key_clear(KEY_SPREADSHEET);     break;
-                               case 0x187: map_key_clear(KEY_GRAPHICSEDITOR);  break;
-                               case 0x188: map_key_clear(KEY_PRESENTATION);    break;
-                               case 0x189: map_key_clear(KEY_DATABASE);        break;
-                               case 0x18a: map_key_clear(KEY_MAIL);            break;
-                               case 0x18b: map_key_clear(KEY_NEWS);            break;
-                               case 0x18c: map_key_clear(KEY_VOICEMAIL);       break;
-                               case 0x18d: map_key_clear(KEY_ADDRESSBOOK);     break;
-                               case 0x18e: map_key_clear(KEY_CALENDAR);        break;
-                               case 0x191: map_key_clear(KEY_FINANCE);         break;
-                               case 0x192: map_key_clear(KEY_CALC);            break;
-                               case 0x194: map_key_clear(KEY_FILE);            break;
-                               case 0x196: map_key_clear(KEY_WWW);             break;
-                               case 0x19c: map_key_clear(KEY_LOGOFF);          break;
-                               case 0x19e: map_key_clear(KEY_COFFEE);          break;
-                               case 0x1a6: map_key_clear(KEY_HELP);            break;
-                               case 0x1a7: map_key_clear(KEY_DOCUMENTS);       break;
-                               case 0x1ab: map_key_clear(KEY_SPELLCHECK);      break;
-                               case 0x1b6: map_key_clear(KEY_MEDIA);           break;
-                               case 0x1b7: map_key_clear(KEY_SOUND);           break;
-                               case 0x1bc: map_key_clear(KEY_MESSENGER);       break;
-                               case 0x1bd: map_key_clear(KEY_INFO);            break;
-                               case 0x201: map_key_clear(KEY_NEW);             break;
-                               case 0x202: map_key_clear(KEY_OPEN);            break;
-                               case 0x203: map_key_clear(KEY_CLOSE);           break;
-                               case 0x204: map_key_clear(KEY_EXIT);            break;
-                               case 0x207: map_key_clear(KEY_SAVE);            break;
-                               case 0x208: map_key_clear(KEY_PRINT);           break;
-                               case 0x209: map_key_clear(KEY_PROPS);           break;
-                               case 0x21a: map_key_clear(KEY_UNDO);            break;
-                               case 0x21b: map_key_clear(KEY_COPY);            break;
-                               case 0x21c: map_key_clear(KEY_CUT);             break;
-                               case 0x21d: map_key_clear(KEY_PASTE);           break;
-                               case 0x21f: map_key_clear(KEY_FIND);            break;
-                               case 0x221: map_key_clear(KEY_SEARCH);          break;
-                               case 0x222: map_key_clear(KEY_GOTO);            break;
-                               case 0x223: map_key_clear(KEY_HOMEPAGE);        break;
-                               case 0x224: map_key_clear(KEY_BACK);            break;
-                               case 0x225: map_key_clear(KEY_FORWARD);         break;
-                               case 0x226: map_key_clear(KEY_STOP);            break;
-                               case 0x227: map_key_clear(KEY_REFRESH);         break;
-                               case 0x22a: map_key_clear(KEY_BOOKMARKS);       break;
-                               case 0x22d: map_key_clear(KEY_ZOOMIN);          break;
-                               case 0x22e: map_key_clear(KEY_ZOOMOUT);         break;
-                               case 0x22f: map_key_clear(KEY_ZOOMRESET);       break;
-                               case 0x233: map_key_clear(KEY_SCROLLUP);        break;
-                               case 0x234: map_key_clear(KEY_SCROLLDOWN);      break;
-                               case 0x238: map_rel(REL_HWHEEL);                break;
-                               case 0x25f: map_key_clear(KEY_CANCEL);          break;
-                               case 0x279: map_key_clear(KEY_REDO);            break;
-
-                               case 0x289: map_key_clear(KEY_REPLY);           break;
-                               case 0x28b: map_key_clear(KEY_FORWARDMAIL);     break;
-                               case 0x28c: map_key_clear(KEY_SEND);            break;
-
-                               default:    goto ignore;
+               case 0x32: /* InRange */
+                       switch (field->physical & 0xff) {
+                       case 0x21: map_key(BTN_TOOL_MOUSE); break;
+                       case 0x22: map_key(BTN_TOOL_FINGER); break;
+                       default: map_key(BTN_TOOL_PEN); break;
                        }
                        break;
 
-               case HID_UP_HPVENDOR:   /* Reported on a Dutch layout HP5308 */
-
-                       set_bit(EV_REP, input->evbit);
-                       switch (usage->hid & HID_USAGE) {
-                               case 0x021: map_key_clear(KEY_PRINT);           break;
-                               case 0x070: map_key_clear(KEY_HP);              break;
-                               case 0x071: map_key_clear(KEY_CAMERA);          break;
-                               case 0x072: map_key_clear(KEY_SOUND);           break;
-                               case 0x073: map_key_clear(KEY_QUESTION);        break;
-                               case 0x080: map_key_clear(KEY_EMAIL);           break;
-                               case 0x081: map_key_clear(KEY_CHAT);            break;
-                               case 0x082: map_key_clear(KEY_SEARCH);          break;
-                               case 0x083: map_key_clear(KEY_CONNECT);         break;
-                               case 0x084: map_key_clear(KEY_FINANCE);         break;
-                               case 0x085: map_key_clear(KEY_SPORT);           break;
-                               case 0x086: map_key_clear(KEY_SHOP);            break;
-                               default:    goto ignore;
-                       }
+               case 0x3c: /* Invert */
+                       map_key_clear(BTN_TOOL_RUBBER);
                        break;
 
-               case HID_UP_MSVENDOR:
-
-                       goto ignore;
-
-               case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
-
-                       set_bit(EV_REP, input->evbit);
-                       switch(usage->hid & HID_USAGE) {
-                               case 0x003:
-                                       /* The fn key on Apple USB keyboards */
-                                       map_key_clear(KEY_FN);
-                                       hidinput_apple_setup(input);
-                                       break;
+               case 0x33: /* Touch */
+               case 0x42: /* TipSwitch */
+               case 0x43: /* TipSwitch2 */
+                       device->quirks &= ~HID_QUIRK_NOTOUCH;
+                       map_key_clear(BTN_TOUCH);
+                       break;
 
-                               default:    goto ignore;
-                       }
+               case 0x44: /* BarrelSwitch */
+                       map_key_clear(BTN_STYLUS);
                        break;
 
-               case HID_UP_LOGIVENDOR:
+               default:  goto unknown;
+               }
+               break;
+
+       case HID_UP_CONSUMER:   /* USB HUT v1.1, pages 56-62 */
+               switch (usage->hid & HID_USAGE) {
+               case 0x000: goto ignore;
+               case 0x034: map_key_clear(KEY_SLEEP);           break;
+               case 0x036: map_key_clear(BTN_MISC);            break;
+
+               case 0x040: map_key_clear(KEY_MENU);            break;
+               case 0x045: map_key_clear(KEY_RADIO);           break;
+
+               case 0x083: map_key_clear(KEY_LAST);            break;
+               case 0x088: map_key_clear(KEY_PC);              break;
+               case 0x089: map_key_clear(KEY_TV);              break;
+               case 0x08a: map_key_clear(KEY_WWW);             break;
+               case 0x08b: map_key_clear(KEY_DVD);             break;
+               case 0x08c: map_key_clear(KEY_PHONE);           break;
+               case 0x08d: map_key_clear(KEY_PROGRAM);         break;
+               case 0x08e: map_key_clear(KEY_VIDEOPHONE);      break;
+               case 0x08f: map_key_clear(KEY_GAMES);           break;
+               case 0x090: map_key_clear(KEY_MEMO);            break;
+               case 0x091: map_key_clear(KEY_CD);              break;
+               case 0x092: map_key_clear(KEY_VCR);             break;
+               case 0x093: map_key_clear(KEY_TUNER);           break;
+               case 0x094: map_key_clear(KEY_EXIT);            break;
+               case 0x095: map_key_clear(KEY_HELP);            break;
+               case 0x096: map_key_clear(KEY_TAPE);            break;
+               case 0x097: map_key_clear(KEY_TV2);             break;
+               case 0x098: map_key_clear(KEY_SAT);             break;
+               case 0x09a: map_key_clear(KEY_PVR);             break;
+
+               case 0x09c: map_key_clear(KEY_CHANNELUP);       break;
+               case 0x09d: map_key_clear(KEY_CHANNELDOWN);     break;
+               case 0x0a0: map_key_clear(KEY_VCR2);            break;
+
+               case 0x0b0: map_key_clear(KEY_PLAY);            break;
+               case 0x0b1: map_key_clear(KEY_PAUSE);           break;
+               case 0x0b2: map_key_clear(KEY_RECORD);          break;
+               case 0x0b3: map_key_clear(KEY_FASTFORWARD);     break;
+               case 0x0b4: map_key_clear(KEY_REWIND);          break;
+               case 0x0b5: map_key_clear(KEY_NEXTSONG);        break;
+               case 0x0b6: map_key_clear(KEY_PREVIOUSSONG);    break;
+               case 0x0b7: map_key_clear(KEY_STOPCD);          break;
+               case 0x0b8: map_key_clear(KEY_EJECTCD);         break;
+               case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT);    break;
+
+               case 0x0cd: map_key_clear(KEY_PLAYPAUSE);       break;
+               case 0x0e0: map_abs_clear(ABS_VOLUME);          break;
+               case 0x0e2: map_key_clear(KEY_MUTE);            break;
+               case 0x0e5: map_key_clear(KEY_BASSBOOST);       break;
+               case 0x0e9: map_key_clear(KEY_VOLUMEUP);        break;
+               case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);      break;
+
+               case 0x182: map_key_clear(KEY_BOOKMARKS);       break;
+               case 0x183: map_key_clear(KEY_CONFIG);          break;
+               case 0x184: map_key_clear(KEY_WORDPROCESSOR);   break;
+               case 0x185: map_key_clear(KEY_EDITOR);          break;
+               case 0x186: map_key_clear(KEY_SPREADSHEET);     break;
+               case 0x187: map_key_clear(KEY_GRAPHICSEDITOR);  break;
+               case 0x188: map_key_clear(KEY_PRESENTATION);    break;
+               case 0x189: map_key_clear(KEY_DATABASE);        break;
+               case 0x18a: map_key_clear(KEY_MAIL);            break;
+               case 0x18b: map_key_clear(KEY_NEWS);            break;
+               case 0x18c: map_key_clear(KEY_VOICEMAIL);       break;
+               case 0x18d: map_key_clear(KEY_ADDRESSBOOK);     break;
+               case 0x18e: map_key_clear(KEY_CALENDAR);        break;
+               case 0x191: map_key_clear(KEY_FINANCE);         break;
+               case 0x192: map_key_clear(KEY_CALC);            break;
+               case 0x194: map_key_clear(KEY_FILE);            break;
+               case 0x196: map_key_clear(KEY_WWW);             break;
+               case 0x19c: map_key_clear(KEY_LOGOFF);          break;
+               case 0x19e: map_key_clear(KEY_COFFEE);          break;
+               case 0x1a6: map_key_clear(KEY_HELP);            break;
+               case 0x1a7: map_key_clear(KEY_DOCUMENTS);       break;
+               case 0x1ab: map_key_clear(KEY_SPELLCHECK);      break;
+               case 0x1b6: map_key_clear(KEY_MEDIA);           break;
+               case 0x1b7: map_key_clear(KEY_SOUND);           break;
+               case 0x1bc: map_key_clear(KEY_MESSENGER);       break;
+               case 0x1bd: map_key_clear(KEY_INFO);            break;
+               case 0x201: map_key_clear(KEY_NEW);             break;
+               case 0x202: map_key_clear(KEY_OPEN);            break;
+               case 0x203: map_key_clear(KEY_CLOSE);           break;
+               case 0x204: map_key_clear(KEY_EXIT);            break;
+               case 0x207: map_key_clear(KEY_SAVE);            break;
+               case 0x208: map_key_clear(KEY_PRINT);           break;
+               case 0x209: map_key_clear(KEY_PROPS);           break;
+               case 0x21a: map_key_clear(KEY_UNDO);            break;
+               case 0x21b: map_key_clear(KEY_COPY);            break;
+               case 0x21c: map_key_clear(KEY_CUT);             break;
+               case 0x21d: map_key_clear(KEY_PASTE);           break;
+               case 0x21f: map_key_clear(KEY_FIND);            break;
+               case 0x221: map_key_clear(KEY_SEARCH);          break;
+               case 0x222: map_key_clear(KEY_GOTO);            break;
+               case 0x223: map_key_clear(KEY_HOMEPAGE);        break;
+               case 0x224: map_key_clear(KEY_BACK);            break;
+               case 0x225: map_key_clear(KEY_FORWARD);         break;
+               case 0x226: map_key_clear(KEY_STOP);            break;
+               case 0x227: map_key_clear(KEY_REFRESH);         break;
+               case 0x22a: map_key_clear(KEY_BOOKMARKS);       break;
+               case 0x22d: map_key_clear(KEY_ZOOMIN);          break;
+               case 0x22e: map_key_clear(KEY_ZOOMOUT);         break;
+               case 0x22f: map_key_clear(KEY_ZOOMRESET);       break;
+               case 0x233: map_key_clear(KEY_SCROLLUP);        break;
+               case 0x234: map_key_clear(KEY_SCROLLDOWN);      break;
+               case 0x238: map_rel(REL_HWHEEL);                break;
+               case 0x25f: map_key_clear(KEY_CANCEL);          break;
+               case 0x279: map_key_clear(KEY_REDO);            break;
+
+               case 0x289: map_key_clear(KEY_REPLY);           break;
+               case 0x28b: map_key_clear(KEY_FORWARDMAIL);     break;
+               case 0x28c: map_key_clear(KEY_SEND);            break;
+
+               default:    goto ignore;
+               }
+               break;
+
+       case HID_UP_HPVENDOR:   /* Reported on a Dutch layout HP5308 */
+               set_bit(EV_REP, input->evbit);
+               switch (usage->hid & HID_USAGE) {
+               case 0x021: map_key_clear(KEY_PRINT);           break;
+               case 0x070: map_key_clear(KEY_HP);              break;
+               case 0x071: map_key_clear(KEY_CAMERA);          break;
+               case 0x072: map_key_clear(KEY_SOUND);           break;
+               case 0x073: map_key_clear(KEY_QUESTION);        break;
+               case 0x080: map_key_clear(KEY_EMAIL);           break;
+               case 0x081: map_key_clear(KEY_CHAT);            break;
+               case 0x082: map_key_clear(KEY_SEARCH);          break;
+               case 0x083: map_key_clear(KEY_CONNECT);         break;
+               case 0x084: map_key_clear(KEY_FINANCE);         break;
+               case 0x085: map_key_clear(KEY_SPORT);           break;
+               case 0x086: map_key_clear(KEY_SHOP);            break;
+               default:    goto ignore;
+               }
+               break;
 
-                       goto ignore;
-               
-               case HID_UP_PID:
+       case HID_UP_MSVENDOR:
+               goto ignore;
 
-                       switch(usage->hid & HID_USAGE) {
-                               case 0xa4: map_key_clear(BTN_DEAD);     break;
-                               default: goto ignore;
-                       }
-                       break;
+       case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
+               set_bit(EV_REP, input->evbit);
+               goto ignore;
 
-               default:
-               unknown:
-                       if (field->report_size == 1) {
-                               if (field->report->type == HID_OUTPUT_REPORT) {
-                                       map_led(LED_MISC);
-                                       break;
-                               }
-                               map_key(BTN_MISC);
-                               break;
-                       }
-                       if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-                               map_rel(REL_MISC);
+       case HID_UP_LOGIVENDOR:
+               goto ignore;
+       
+       case HID_UP_PID:
+               switch (usage->hid & HID_USAGE) {
+               case 0xa4: map_key_clear(BTN_DEAD);     break;
+               default: goto ignore;
+               }
+               break;
+
+       default:
+       unknown:
+               if (field->report_size == 1) {
+                       if (field->report->type == HID_OUTPUT_REPORT) {
+                               map_led(LED_MISC);
                                break;
                        }
-                       map_abs(ABS_MISC);
+                       map_key(BTN_MISC);
+                       break;
+               }
+               if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+                       map_rel(REL_MISC);
                        break;
+               }
+               map_abs(ABS_MISC);
+               break;
        }
 
 mapped:
-       if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
-               if (usage->hid == HID_GD_Z)
-                       map_rel(REL_HWHEEL);
-               else if (usage->code == BTN_1)
-                       map_key(BTN_2);
-               else if (usage->code == BTN_2)
-                       map_key(BTN_1);
-       }
-
-       if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
-                       HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
-                       (usage->code == REL_WHEEL))
-               set_bit(REL_HWHEEL, bit);
-
-       if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
-               || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
+       if (device->driver->input_mapped && device->driver->input_mapped(device,
+                               hidinput, field, usage, &bit, &max) < 0)
                goto ignore;
 
-       if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) &&
-               usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE))
-               field->flags &= ~HID_MAIN_ITEM_RELATIVE;
-
        set_bit(usage->type, input->evbit);
 
-       if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
-                       (usage->type == EV_KEY ||
-                        usage->type == EV_REL ||
-                        usage->type == EV_ABS))
-               clear_bit(usage->code, bit);
-
        while (usage->code <= max && test_and_set_bit(usage->code, bit))
                usage->code = find_next_zero_bit(bit, max + 1, usage->code);
 
@@ -858,10 +585,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
        if (!usage->type)
                return;
 
-       /* handle input events for quirky devices */
-       if (hidinput_event_quirks(hid, field, usage, value))
-               return;
-
        if (usage->hat_min < usage->hat_max || usage->hat_dir) {
                int hat_dir = usage->hat_dir;
                if (!hat_dir)
@@ -961,14 +684,14 @@ static int hidinput_open(struct input_dev *dev)
 {
        struct hid_device *hid = input_get_drvdata(dev);
 
-       return hid->hid_open(hid);
+       return hid->ll_driver->open(hid);
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
        struct hid_device *hid = input_get_drvdata(dev);
 
-       hid->hid_close(hid);
+       hid->ll_driver->close(hid);
 }
 
 /*
@@ -977,7 +700,7 @@ static void hidinput_close(struct input_dev *dev)
  * Read all reports and initialize the absolute field values.
  */
 
-int hidinput_connect(struct hid_device *hid)
+int hidinput_connect(struct hid_device *hid, unsigned int force)
 {
        struct hid_report *report;
        struct hid_input *hidinput = NULL;
@@ -985,19 +708,20 @@ int hidinput_connect(struct hid_device *hid)
        int i, j, k;
        int max_report_type = HID_OUTPUT_REPORT;
 
-       if (hid->quirks & HID_QUIRK_IGNORE_HIDINPUT)
-               return -1;
-
        INIT_LIST_HEAD(&hid->inputs);
 
-       for (i = 0; i < hid->maxcollection; i++)
-               if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
-                   hid->collection[i].type == HID_COLLECTION_PHYSICAL)
-                       if (IS_INPUT_APPLICATION(hid->collection[i].usage))
-                               break;
+       if (!force) {
+               for (i = 0; i < hid->maxcollection; i++) {
+                       struct hid_collection *col = &hid->collection[i];
+                       if (col->type == HID_COLLECTION_APPLICATION ||
+                                       col->type == HID_COLLECTION_PHYSICAL)
+                               if (IS_INPUT_APPLICATION(col->usage))
+                                       break;
+               }
 
-       if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
-               return -1;
+               if (i == hid->maxcollection)
+                       return -1;
+       }
 
        if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
                max_report_type = HID_INPUT_REPORT;
@@ -1019,7 +743,8 @@ int hidinput_connect(struct hid_device *hid)
                                }
 
                                input_set_drvdata(input_dev, hid);
-                               input_dev->event = hid->hidinput_input_event;
+                               input_dev->event =
+                                       hid->ll_driver->hidinput_input_event;
                                input_dev->open = hidinput_open;
                                input_dev->close = hidinput_close;
                                input_dev->setkeycode = hidinput_setkeycode;
@@ -1032,7 +757,7 @@ int hidinput_connect(struct hid_device *hid)
                                input_dev->id.vendor  = hid->vendor;
                                input_dev->id.product = hid->product;
                                input_dev->id.version = hid->version;
-                               input_dev->dev.parent = hid->dev;
+                               input_dev->dev.parent = hid->dev.parent;
                                hidinput->input = input_dev;
                                list_add_tail(&hidinput->list, &hid->inputs);
                        }
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
new file mode 100644 (file)
index 0000000..406d8c8
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ *  HID driver for some logitech "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+#include "hid-lg.h"
+
+#define LG_RDESC               0x001
+#define LG_BAD_RELATIVE_KEYS   0x002
+#define LG_DUPLICATE_USAGES    0x004
+#define LG_RESET_LEDS          0x008
+#define LG_EXPANDED_KEYMAP     0x010
+#define LG_IGNORE_DOUBLED_WHEEL        0x020
+#define LG_WIRELESS            0x040
+#define LG_INVERT_HWHEEL       0x080
+#define LG_NOGET               0x100
+#define LG_FF                  0x200
+#define LG_FF2                 0x400
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 &&
+                       rdesc[84] == 0x8c && rdesc[85] == 0x02) {
+               dev_info(&hdev->dev, "fixing up Logitech keyboard report "
+                               "descriptor\n");
+               rdesc[84] = rdesc[89] = 0x4d;
+               rdesc[85] = rdesc[90] = 0x10;
+       }
+}
+
+#define lg_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+               EV_KEY, (c))
+
+static int lg_ultrax_remote_mapping(struct hid_input *hi,
+               struct hid_usage *usage, unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+               return 0;
+
+       set_bit(EV_REP, hi->input->evbit);
+       switch (usage->hid & HID_USAGE) {
+       /* Reported on Logitech Ultra X Media Remote */
+       case 0x004: lg_map_key_clear(KEY_AGAIN);        break;
+       case 0x00d: lg_map_key_clear(KEY_HOME);         break;
+       case 0x024: lg_map_key_clear(KEY_SHUFFLE);      break;
+       case 0x025: lg_map_key_clear(KEY_TV);           break;
+       case 0x026: lg_map_key_clear(KEY_MENU);         break;
+       case 0x031: lg_map_key_clear(KEY_AUDIO);        break;
+       case 0x032: lg_map_key_clear(KEY_TEXT);         break;
+       case 0x033: lg_map_key_clear(KEY_LAST);         break;
+       case 0x047: lg_map_key_clear(KEY_MP3);          break;
+       case 0x048: lg_map_key_clear(KEY_DVD);          break;
+       case 0x049: lg_map_key_clear(KEY_MEDIA);        break;
+       case 0x04a: lg_map_key_clear(KEY_VIDEO);        break;
+       case 0x04b: lg_map_key_clear(KEY_ANGLE);        break;
+       case 0x04c: lg_map_key_clear(KEY_LANGUAGE);     break;
+       case 0x04d: lg_map_key_clear(KEY_SUBTITLE);     break;
+       case 0x051: lg_map_key_clear(KEY_RED);          break;
+       case 0x052: lg_map_key_clear(KEY_CLOSE);        break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x1001: lg_map_key_clear(KEY_MESSENGER);           break;
+       case 0x1003: lg_map_key_clear(KEY_SOUND);               break;
+       case 0x1004: lg_map_key_clear(KEY_VIDEO);               break;
+       case 0x1005: lg_map_key_clear(KEY_AUDIO);               break;
+       case 0x100a: lg_map_key_clear(KEY_DOCUMENTS);           break;
+       case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG);        break;
+       case 0x1012: lg_map_key_clear(KEY_NEXTSONG);            break;
+       case 0x1013: lg_map_key_clear(KEY_CAMERA);              break;
+       case 0x1014: lg_map_key_clear(KEY_MESSENGER);           break;
+       case 0x1015: lg_map_key_clear(KEY_RECORD);              break;
+       case 0x1016: lg_map_key_clear(KEY_PLAYER);              break;
+       case 0x1017: lg_map_key_clear(KEY_EJECTCD);             break;
+       case 0x1018: lg_map_key_clear(KEY_MEDIA);               break;
+       case 0x1019: lg_map_key_clear(KEY_PROG1);               break;
+       case 0x101a: lg_map_key_clear(KEY_PROG2);               break;
+       case 0x101b: lg_map_key_clear(KEY_PROG3);               break;
+       case 0x101f: lg_map_key_clear(KEY_ZOOMIN);              break;
+       case 0x1020: lg_map_key_clear(KEY_ZOOMOUT);             break;
+       case 0x1021: lg_map_key_clear(KEY_ZOOMRESET);           break;
+       case 0x1023: lg_map_key_clear(KEY_CLOSE);               break;
+       case 0x1027: lg_map_key_clear(KEY_MENU);                break;
+       /* this one is marked as 'Rotate' */
+       case 0x1028: lg_map_key_clear(KEY_ANGLE);               break;
+       case 0x1029: lg_map_key_clear(KEY_SHUFFLE);             break;
+       case 0x102a: lg_map_key_clear(KEY_BACK);                break;
+       case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS);        break;
+       case 0x1041: lg_map_key_clear(KEY_BATTERY);             break;
+       case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR);       break;
+       case 0x1043: lg_map_key_clear(KEY_SPREADSHEET);         break;
+       case 0x1044: lg_map_key_clear(KEY_PRESENTATION);        break;
+       case 0x1045: lg_map_key_clear(KEY_UNDO);                break;
+       case 0x1046: lg_map_key_clear(KEY_REDO);                break;
+       case 0x1047: lg_map_key_clear(KEY_PRINT);               break;
+       case 0x1048: lg_map_key_clear(KEY_SAVE);                break;
+       case 0x1049: lg_map_key_clear(KEY_PROG1);               break;
+       case 0x104a: lg_map_key_clear(KEY_PROG2);               break;
+       case 0x104b: lg_map_key_clear(KEY_PROG3);               break;
+       case 0x104c: lg_map_key_clear(KEY_PROG4);               break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       /* extended mapping for certain Logitech hardware (Logitech cordless
+          desktop LX500) */
+       static const u8 e_keymap[] = {
+                 0,216,  0,213,175,156,  0,  0,  0,  0,
+               144,  0,  0,  0,  0,  0,  0,  0,  0,212,
+               174,167,152,161,112,  0,  0,  0,154,  0,
+                 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                 0,  0,  0,  0,  0,183,184,185,186,187,
+               188,189,190,191,192,193,194,  0,  0,  0
+       };
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+       unsigned int hid = usage->hid;
+
+       if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
+                       lg_ultrax_remote_mapping(hi, usage, bit, max))
+               return 1;
+
+       if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
+               return 1;
+
+       if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
+               return 0;
+
+       hid &= HID_USAGE;
+
+       /* Special handling for Logitech Cordless Desktop */
+       if (field->application == HID_GD_MOUSE) {
+               if ((quirks & LG_IGNORE_DOUBLED_WHEEL) &&
+                               (hid == 7 || hid == 8))
+                       return -1;
+       } else {
+               if ((quirks & LG_EXPANDED_KEYMAP) &&
+                               hid < ARRAY_SIZE(e_keymap) &&
+                               e_keymap[hid] != 0) {
+                       hid_map_usage(hi, usage, bit, max, EV_KEY,
+                                       e_keymap[hid]);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
+                       (field->flags & HID_MAIN_ITEM_RELATIVE))
+               field->flags &= ~HID_MAIN_ITEM_RELATIVE;
+
+       if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
+                        usage->type == EV_REL || usage->type == EV_ABS))
+               clear_bit(usage->code, *bit);
+
+       return 0;
+}
+
+static int lg_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
+               input_event(field->hidinput->input, usage->type, usage->code,
+                               -value);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       unsigned long quirks = id->driver_data;
+       unsigned int connect_mask = HID_CONNECT_DEFAULT;
+       int ret;
+
+       hid_set_drvdata(hdev, (void *)quirks);
+
+       if (quirks & LG_NOGET)
+               hdev->quirks |= HID_QUIRK_NOGET;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       if (quirks & (LG_FF | LG_FF2))
+               connect_mask &= ~HID_CONNECT_FF;
+
+       ret = hid_hw_start(hdev, connect_mask);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       if (quirks & LG_RESET_LEDS)
+               usbhid_set_leds(hdev);
+
+       if (quirks & LG_FF)
+               lgff_init(hdev);
+       if (quirks & LG_FF2)
+               lg2ff_init(hdev);
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id lg_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
+               .driver_data = LG_RDESC | LG_WIRELESS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER),
+               .driver_data = LG_RDESC | LG_WIRELESS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2),
+               .driver_data = LG_RDESC | LG_WIRELESS },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER),
+               .driver_data = LG_BAD_RELATIVE_KEYS },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP),
+               .driver_data = LG_DUPLICATE_USAGES },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE),
+               .driver_data = LG_DUPLICATE_USAGES },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
+               .driver_data = LG_DUPLICATE_USAGES },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
+               .driver_data = LG_RESET_LEDS },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
+               .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
+               .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3),
+               .driver_data = LG_INVERT_HWHEEL },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150),
+               .driver_data = LG_INVERT_HWHEEL },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
+               .driver_data = LG_NOGET },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
+               .driver_data = LG_NOGET | LG_FF },
+
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
+               .driver_data = LG_FF },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
+               .driver_data = LG_FF2 },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, lg_devices);
+
+static struct hid_driver lg_driver = {
+       .name = "logitech",
+       .id_table = lg_devices,
+       .report_fixup = lg_report_fixup,
+       .input_mapping = lg_input_mapping,
+       .input_mapped = lg_input_mapped,
+       .event = lg_event,
+       .probe = lg_probe,
+};
+
+static int lg_init(void)
+{
+       return hid_register_driver(&lg_driver);
+}
+
+static void lg_exit(void)
+{
+       hid_unregister_driver(&lg_driver);
+}
+
+module_init(lg_init);
+module_exit(lg_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(logitech);
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
new file mode 100644 (file)
index 0000000..27ae750
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __HID_LG_H
+#define __HID_LG_H
+
+#include <linux/autoconf.h>
+
+#ifdef CONFIG_LOGITECH_FF
+int lgff_init(struct hid_device *hdev);
+#else
+static inline int lgff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#ifdef CONFIG_LOGIRUMBLEPAD2_FF
+int lg2ff_init(struct hid_device *hdev);
+#else
+static inline int lg2ff_init(struct hid_device *hdev) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
new file mode 100644 (file)
index 0000000..4e6dc6e
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Force feedback support for Logitech Rumblepad 2
+ *
+ *  Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
+
+struct lg2ff_device {
+       struct hid_report *report;
+};
+
+static int play_effect(struct input_dev *dev, void *data,
+                        struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct lg2ff_device *lg2ff = data;
+       int weak, strong;
+
+       strong = effect->u.rumble.strong_magnitude;
+       weak = effect->u.rumble.weak_magnitude;
+
+       if (weak || strong) {
+               weak = weak * 0xff / 0xffff;
+               strong = strong * 0xff / 0xffff;
+
+               lg2ff->report->field[0]->value[0] = 0x51;
+               lg2ff->report->field[0]->value[2] = weak;
+               lg2ff->report->field[0]->value[4] = strong;
+       } else {
+               lg2ff->report->field[0]->value[0] = 0xf3;
+               lg2ff->report->field[0]->value[2] = 0x00;
+               lg2ff->report->field[0]->value[4] = 0x00;
+       }
+
+       usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
+       return 0;
+}
+
+int lg2ff_init(struct hid_device *hid)
+{
+       struct lg2ff_device *lg2ff;
+       struct hid_report *report;
+       struct hid_input *hidinput = list_entry(hid->inputs.next,
+                                               struct hid_input, list);
+       struct list_head *report_list =
+                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct input_dev *dev = hidinput->input;
+       int error;
+
+       if (list_empty(report_list)) {
+               dev_err(&hid->dev, "no output report found\n");
+               return -ENODEV;
+       }
+
+       report = list_entry(report_list->next, struct hid_report, list);
+
+       if (report->maxfield < 1) {
+               dev_err(&hid->dev, "output report is empty\n");
+               return -ENODEV;
+       }
+       if (report->field[0]->report_count < 7) {
+               dev_err(&hid->dev, "not enough values in the field\n");
+               return -ENODEV;
+       }
+
+       lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
+       if (!lg2ff)
+               return -ENOMEM;
+
+       set_bit(FF_RUMBLE, dev->ffbit);
+
+       error = input_ff_create_memless(dev, lg2ff, play_effect);
+       if (error) {
+               kfree(lg2ff);
+               return error;
+       }
+
+       lg2ff->report = report;
+       report->field[0]->value[0] = 0xf3;
+       report->field[0]->value[1] = 0x00;
+       report->field[0]->value[2] = 0x00;
+       report->field[0]->value[3] = 0x00;
+       report->field[0]->value[4] = 0x00;
+       report->field[0]->value[5] = 0x00;
+       report->field[0]->value[6] = 0x00;
+
+       usbhid_submit_report(hid, report, USB_DIR_OUT);
+
+       dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by "
+              "Anssi Hannula <anssi.hannula@gmail.com>\n");
+
+       return 0;
+}
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
new file mode 100644 (file)
index 0000000..51aff08
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Force feedback support for hid-compliant for some of the devices from
+ * Logitech, namely:
+ * - WingMan Cordless RumblePad
+ * - WingMan Force 3D
+ *
+ *  Copyright (c) 2002-2004 Johann Deneux
+ *  Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to <johann.deneux@it.uu.se>
+ */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "usbhid/usbhid.h"
+#include "hid-lg.h"
+
+struct dev_type {
+       u16 idVendor;
+       u16 idProduct;
+       const signed short *ff;
+};
+
+static const signed short ff_rumble[] = {
+       FF_RUMBLE,
+       -1
+};
+
+static const signed short ff_joystick[] = {
+       FF_CONSTANT,
+       -1
+};
+
+static const signed short ff_wheel[] = {
+       FF_CONSTANT,
+       FF_AUTOCENTER,
+       -1
+};
+
+static const struct dev_type devices[] = {
+       { 0x046d, 0xc211, ff_rumble },
+       { 0x046d, 0xc219, ff_rumble },
+       { 0x046d, 0xc283, ff_joystick },
+       { 0x046d, 0xc286, ff_joystick },
+       { 0x046d, 0xc294, ff_joystick },
+       { 0x046d, 0xc295, ff_joystick },
+       { 0x046d, 0xca03, ff_wheel },
+};
+
+static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+       int x, y;
+       unsigned int left, right;
+
+#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
+
+       switch (effect->type) {
+       case FF_CONSTANT:
+               x = effect->u.ramp.start_level + 0x7f;  /* 0x7f is center */
+               y = effect->u.ramp.end_level + 0x7f;
+               CLAMP(x);
+               CLAMP(y);
+               report->field[0]->value[0] = 0x51;
+               report->field[0]->value[1] = 0x08;
+               report->field[0]->value[2] = x;
+               report->field[0]->value[3] = y;
+               dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               break;
+
+       case FF_RUMBLE:
+               right = effect->u.rumble.strong_magnitude;
+               left = effect->u.rumble.weak_magnitude;
+               right = right * 0xff / 0xffff;
+               left = left * 0xff / 0xffff;
+               CLAMP(left);
+               CLAMP(right);
+               report->field[0]->value[0] = 0x42;
+               report->field[0]->value[1] = 0x00;
+               report->field[0]->value[2] = left;
+               report->field[0]->value[3] = right;
+               dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               break;
+       }
+       return 0;
+}
+
+static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+       __s32 *value = report->field[0]->value;
+       magnitude = (magnitude >> 12) & 0xf;
+       *value++ = 0xfe;
+       *value++ = 0x0d;
+       *value++ = magnitude;   /* clockwise strength */
+       *value++ = magnitude;   /* counter-clockwise strength */
+       *value++ = 0x80;
+       *value++ = 0x00;
+       *value = 0x00;
+       usbhid_submit_report(hid, report, USB_DIR_OUT);
+}
+
+int lgff_init(struct hid_device* hid)
+{
+       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct input_dev *dev = hidinput->input;
+       struct hid_report *report;
+       struct hid_field *field;
+       const signed short *ff_bits = ff_joystick;
+       int error;
+       int i;
+
+       /* Find the report to use */
+       if (list_empty(report_list)) {
+               err_hid("No output report found");
+               return -1;
+       }
+
+       /* Check that the report looks ok */
+       report = list_entry(report_list->next, struct hid_report, list);
+       if (!report) {
+               err_hid("NULL output report");
+               return -1;
+       }
+
+       field = report->field[0];
+       if (!field) {
+               err_hid("NULL field");
+               return -1;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(devices); i++) {
+               if (dev->id.vendor == devices[i].idVendor &&
+                   dev->id.product == devices[i].idProduct) {
+                       ff_bits = devices[i].ff;
+                       break;
+               }
+       }
+
+       for (i = 0; ff_bits[i] >= 0; i++)
+               set_bit(ff_bits[i], dev->ffbit);
+
+       error = input_ff_create_memless(dev, NULL, hid_lgff_play);
+       if (error)
+               return error;
+
+       if ( test_bit(FF_AUTOCENTER, dev->ffbit) )
+               dev->ff->set_autocenter = hid_lgff_set_autocenter;
+
+       printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
+
+       return 0;
+}
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
new file mode 100644 (file)
index 0000000..d718b16
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ *  HID driver for some microsoft "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define MS_HIDINPUT    0x01
+#define MS_ERGONOMY    0x02
+#define MS_PRESENTER   0x04
+#define MS_RDESC       0x08
+#define MS_NOGET       0x10
+
+/*
+ * Microsoft Wireless Desktop Receiver (Model 1028) has several
+ * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+ */
+static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((quirks & MS_RDESC) && rsize == 571 && rdesc[284] == 0x19 &&
+                       rdesc[286] == 0x2a && rdesc[304] == 0x19 &&
+                       rdesc[306] == 0x29 && rdesc[352] == 0x1a &&
+                       rdesc[355] == 0x2a && rdesc[557] == 0x19 &&
+                       rdesc[559] == 0x29) {
+               dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
+                               "Model 1028 report descriptor\n");
+               rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
+               rdesc[352] = 0x36;
+               rdesc[286] = rdesc[355] = 0x46;
+               rdesc[306] = rdesc[559] = 0x45;
+       }
+}
+
+#define ms_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       struct input_dev *input = hi->input;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0xfd06: ms_map_key_clear(KEY_CHAT);        break;
+       case 0xfd07: ms_map_key_clear(KEY_PHONE);       break;
+       case 0xff05:
+               set_bit(EV_REP, input->evbit);
+               ms_map_key_clear(KEY_F13);
+               set_bit(KEY_F14, input->keybit);
+               set_bit(KEY_F15, input->keybit);
+               set_bit(KEY_F16, input->keybit);
+               set_bit(KEY_F17, input->keybit);
+               set_bit(KEY_F18, input->keybit);
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       set_bit(EV_REP, hi->input->evbit);
+       switch (usage->hid & HID_USAGE) {
+       case 0xfd08: ms_map_key_clear(KEY_FORWARD);     break;
+       case 0xfd09: ms_map_key_clear(KEY_BACK);        break;
+       case 0xfd0b: ms_map_key_clear(KEY_PLAYPAUSE);   break;
+       case 0xfd0e: ms_map_key_clear(KEY_CLOSE);       break;
+       case 0xfd0f: ms_map_key_clear(KEY_PLAY);        break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
+               return 0;
+
+       if (quirks & MS_ERGONOMY) {
+               int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
+               if (ret)
+                       return ret;
+       }
+
+       if ((quirks & MS_PRESENTER) &&
+                       ms_presenter_8k_quirk(hi, usage, bit, max))
+               return 1;
+
+       return 0;
+}
+
+static int ms_event(struct hid_device *hdev, struct hid_field *field,
+               struct hid_usage *usage, __s32 value)
+{
+       unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+       if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
+                       !usage->type)
+               return 0;
+
+       /* Handling MS keyboards special buttons */
+       if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
+               struct input_dev *input = field->hidinput->input;
+               static unsigned int last_key = 0;
+               unsigned int key = 0;
+               switch (value) {
+               case 0x01: key = KEY_F14; break;
+               case 0x02: key = KEY_F15; break;
+               case 0x04: key = KEY_F16; break;
+               case 0x08: key = KEY_F17; break;
+               case 0x10: key = KEY_F18; break;
+               }
+               if (key) {
+                       input_event(input, usage->type, key, 1);
+                       last_key = key;
+               } else
+                       input_event(input, usage->type, last_key, 0);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       unsigned long quirks = id->driver_data;
+       int ret;
+
+       hid_set_drvdata(hdev, (void *)quirks);
+
+       if (quirks & MS_NOGET)
+               hdev->quirks |= HID_QUIRK_NOGET;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
+                               HID_CONNECT_HIDINPUT_FORCE : 0));
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id ms_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
+               .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
+               .driver_data = MS_ERGONOMY },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K),
+               .driver_data = MS_ERGONOMY | MS_RDESC },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
+               .driver_data = MS_PRESENTER },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
+               .driver_data = MS_NOGET },
+
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
+               .driver_data = MS_PRESENTER },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, ms_devices);
+
+static struct hid_driver ms_driver = {
+       .name = "microsoft",
+       .id_table = ms_devices,
+       .report_fixup = ms_report_fixup,
+       .input_mapping = ms_input_mapping,
+       .event = ms_event,
+       .probe = ms_probe,
+};
+
+static int ms_init(void)
+{
+       return hid_register_driver(&ms_driver);
+}
+
+static void ms_exit(void)
+{
+       hid_unregister_driver(&ms_driver);
+}
+
+module_init(ms_init);
+module_exit(ms_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(microsoft);
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c
new file mode 100644 (file)
index 0000000..f3a85a0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  HID driver for some monterey "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
+               dev_info(&hdev->dev, "fixing up button/consumer in HID report "
+                               "descriptor\n");
+               rdesc[30] = 0x0c;
+       }
+}
+
+#define mr_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int mr_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x156: mr_map_key_clear(KEY_WORDPROCESSOR);        break;
+       case 0x157: mr_map_key_clear(KEY_SPREADSHEET);          break;
+       case 0x158: mr_map_key_clear(KEY_PRESENTATION);         break;
+       case 0x15c: mr_map_key_clear(KEY_STOP);                 break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static const struct hid_device_id mr_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, mr_devices);
+
+static struct hid_driver mr_driver = {
+       .name = "monterey",
+       .id_table = mr_devices,
+       .report_fixup = mr_report_fixup,
+       .input_mapping = mr_input_mapping,
+};
+
+static int mr_init(void)
+{
+       return hid_register_driver(&mr_driver);
+}
+
+static void mr_exit(void)
+{
+       hid_unregister_driver(&mr_driver);
+}
+
+module_init(mr_init);
+module_exit(mr_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(monterey);
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c
new file mode 100644 (file)
index 0000000..10945fe
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  HID driver for some petalynx "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
+                       rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
+                       rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
+               dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
+                               "descriptor\n");
+               rdesc[60] = 0xfa;
+               rdesc[40] = 0xfa;
+       }
+}
+
+#define pl_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+                                       EV_KEY, (c))
+static int pl_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR) {
+               switch (usage->hid & HID_USAGE) {
+               case 0x05a: pl_map_key_clear(KEY_TEXT);         break;
+               case 0x05b: pl_map_key_clear(KEY_RED);          break;
+               case 0x05c: pl_map_key_clear(KEY_GREEN);        break;
+               case 0x05d: pl_map_key_clear(KEY_YELLOW);       break;
+               case 0x05e: pl_map_key_clear(KEY_BLUE);         break;
+               default:
+                       return 0;
+               }
+               return 1;
+       }
+
+       if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
+               switch (usage->hid & HID_USAGE) {
+               case 0x0f6: pl_map_key_clear(KEY_NEXT);         break;
+               case 0x0fa: pl_map_key_clear(KEY_BACK);         break;
+               default:
+                       return 0;
+               }
+               return 1;
+       }
+
+       return 0;
+}
+
+static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       hdev->quirks |= HID_QUIRK_NOGET;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id pl_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, pl_devices);
+
+static struct hid_driver pl_driver = {
+       .name = "petalynx",
+       .id_table = pl_devices,
+       .report_fixup = pl_report_fixup,
+       .input_mapping = pl_input_mapping,
+       .probe = pl_probe,
+};
+
+static int pl_init(void)
+{
+       return hid_register_driver(&pl_driver);
+}
+
+static void pl_exit(void)
+{
+       hid_unregister_driver(&pl_driver);
+}
+
+module_init(pl_init);
+module_exit(pl_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(petalynx);
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
new file mode 100644 (file)
index 0000000..acd8155
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  Force feedback support for PantherLord/GreenAsia based devices
+ *
+ *  The devices are distributed under various names and the same USB device ID
+ *  can be used in both adapters and actual game controllers.
+ *
+ *  0810:0001 "Twin USB Joystick"
+ *   - tested with PantherLord USB/PS2 2in1 Adapter
+ *   - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT)
+ *
+ *  0e8f:0003 "GreenAsia Inc.    USB Joystick     "
+ *   - tested with K??ng Gaming gamepad
+ *
+ *  Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/* #define DEBUG */
+
+#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_PANTHERLORD_FF
+#include "usbhid/usbhid.h"
+
+struct plff_device {
+       struct hid_report *report;
+};
+
+static int hid_plff_play(struct input_dev *dev, void *data,
+                        struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct plff_device *plff = data;
+       int left, right;
+
+       left = effect->u.rumble.strong_magnitude;
+       right = effect->u.rumble.weak_magnitude;
+       debug("called with 0x%04x 0x%04x", left, right);
+
+       left = left * 0x7f / 0xffff;
+       right = right * 0x7f / 0xffff;
+
+       plff->report->field[0]->value[2] = left;
+       plff->report->field[0]->value[3] = right;
+       debug("running with 0x%02x 0x%02x", left, right);
+       usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+
+       return 0;
+}
+
+static int plff_init(struct hid_device *hid)
+{
+       struct plff_device *plff;
+       struct hid_report *report;
+       struct hid_input *hidinput;
+       struct list_head *report_list =
+                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct list_head *report_ptr = report_list;
+       struct input_dev *dev;
+       int error;
+
+       /* The device contains one output report per physical device, all
+          containing 1 field, which contains 4 ff00.0002 usages and 4 16bit
+          absolute values.
+
+          The input reports also contain a field which contains
+          8 ff00.0001 usages and 8 boolean values. Their meaning is
+          currently unknown. */
+
+       if (list_empty(report_list)) {
+               dev_err(&hid->dev, "no output reports found\n");
+               return -ENODEV;
+       }
+
+       list_for_each_entry(hidinput, &hid->inputs, list) {
+
+               report_ptr = report_ptr->next;
+
+               if (report_ptr == report_list) {
+                       dev_err(&hid->dev, "required output report is "
+                                       "missing\n");
+                       return -ENODEV;
+               }
+
+               report = list_entry(report_ptr, struct hid_report, list);
+               if (report->maxfield < 1) {
+                       dev_err(&hid->dev, "no fields in the report\n");
+                       return -ENODEV;
+               }
+
+               if (report->field[0]->report_count < 4) {
+                       dev_err(&hid->dev, "not enough values in the field\n");
+                       return -ENODEV;
+               }
+
+               plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
+               if (!plff)
+                       return -ENOMEM;
+
+               dev = hidinput->input;
+
+               set_bit(FF_RUMBLE, dev->ffbit);
+
+               error = input_ff_create_memless(dev, plff, hid_plff_play);
+               if (error) {
+                       kfree(plff);
+                       return error;
+               }
+
+               plff->report = report;
+               plff->report->field[0]->value[0] = 0x00;
+               plff->report->field[0]->value[1] = 0x00;
+               plff->report->field[0]->value[2] = 0x00;
+               plff->report->field[0]->value[3] = 0x00;
+               usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+       }
+
+       dev_info(&hid->dev, "Force feedback for PantherLord/GreenAsia "
+              "devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
+
+       return 0;
+}
+#else
+static inline int plff_init(struct hid_device *hid)
+{
+       return 0;
+}
+#endif
+
+static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       if (id->driver_data)
+               hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err;
+       }
+
+       plff_init(hdev);
+
+       return 0;
+err:
+       return ret;
+}
+
+static const struct hid_device_id pl_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR),
+               .driver_data = 1 }, /* Twin USB Joystick */
+       { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */
+       { }
+};
+MODULE_DEVICE_TABLE(hid, pl_devices);
+
+static struct hid_driver pl_driver = {
+       .name = "pantherlord",
+       .id_table = pl_devices,
+       .probe = pl_probe,
+};
+
+static int pl_init(void)
+{
+       return hid_register_driver(&pl_driver);
+}
+
+static void pl_exit(void)
+{
+       hid_unregister_driver(&pl_driver);
+}
+
+module_init(pl_init);
+module_exit(pl_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(pantherlord);
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c
new file mode 100644 (file)
index 0000000..15f3c04
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  HID driver for some samsung "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/*
+ * Samsung IrDA remote controller (reports as Cypress USB Mouse).
+ *
+ * Vendor specific report #4 has a size of 48 bit,
+ * and therefore is not accepted when inspecting the descriptors.
+ * As a workaround we reinterpret the report as:
+ *   Variable type, count 6, size 8 bit, log. maximum 255
+ * The burden to reconstruct the data is moved into user space.
+ */
+static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       if (rsize >= 182 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
+                       rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
+                       rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
+                       rdesc[182] == 0x40) {
+               dev_info(&hdev->dev, "fixing up Samsung IrDA report "
+                               "descriptor\n");
+               rdesc[176] = 0xff;
+               rdesc[178] = 0x08;
+               rdesc[180] = 0x06;
+               rdesc[182] = 0x42;
+       }
+}
+
+static int samsung_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, (HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT) |
+                       HID_CONNECT_HIDDEV_FORCE);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       return 0;
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id samsung_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, samsung_devices);
+
+static struct hid_driver samsung_driver = {
+       .name = "samsung",
+       .id_table = samsung_devices,
+       .report_fixup = samsung_report_fixup,
+       .probe = samsung_probe,
+};
+
+static int samsung_init(void)
+{
+       return hid_register_driver(&samsung_driver);
+}
+
+static void samsung_exit(void)
+{
+       hid_unregister_driver(&samsung_driver);
+}
+
+module_init(samsung_init);
+module_exit(samsung_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(samsung);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
new file mode 100644 (file)
index 0000000..3af8095
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  HID driver for some sony "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+/*
+ * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
+ * to "operational".  Without this, the ps3 controller will not report any
+ * events.
+ */
+static int sony_set_operational(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct usb_device *dev = interface_to_usbdev(intf);
+       __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+       int ret;
+       char *buf = kmalloc(18, GFP_KERNEL);
+
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                                HID_REQ_GET_REPORT,
+                                USB_DIR_IN | USB_TYPE_CLASS |
+                                USB_RECIP_INTERFACE,
+                                (3 << 8) | 0xf2, ifnum, buf, 17,
+                                USB_CTRL_GET_TIMEOUT);
+       if (ret < 0)
+               dev_err(&hdev->dev, "can't set operational mode\n");
+
+       kfree(buf);
+
+       return ret;
+}
+
+static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err_free;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
+                       HID_CONNECT_HIDDEV_FORCE);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err_free;
+       }
+
+       ret = sony_set_operational(hdev);
+       if (ret)
+               goto err_stop;
+
+       return 0;
+err_stop:
+       hid_hw_stop(hdev);
+err_free:
+       return ret;
+}
+
+static const struct hid_device_id sony_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, sony_devices);
+
+static struct hid_driver sony_driver = {
+       .name = "sony",
+       .id_table = sony_devices,
+       .probe = sony_probe,
+};
+
+static int sony_init(void)
+{
+       return hid_register_driver(&sony_driver);
+}
+
+static void sony_exit(void)
+{
+       hid_unregister_driver(&sony_driver);
+}
+
+module_init(sony_init);
+module_exit(sony_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(sony);
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c
new file mode 100644 (file)
index 0000000..5ba68f7
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  HID driver for some sunplus "special" devices
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *  Copyright (c) 2007 Paul Walmsley
+ *  Copyright (c) 2008 Jiri Slaby
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+               unsigned int rsize)
+{
+       if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 &&
+                       rdesc[106] == 0x03) {
+               dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop "
+                               "report descriptor\n");
+               rdesc[105] = rdesc[110] = 0x03;
+               rdesc[106] = rdesc[111] = 0x21;
+       }
+}
+
+#define sp_map_key_clear(c)    hid_map_usage_clear(hi, usage, bit, max, \
+               EV_KEY, (c))
+static int sp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case 0x2003: sp_map_key_clear(KEY_ZOOMIN);              break;
+       case 0x2103: sp_map_key_clear(KEY_ZOOMOUT);     break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static const struct hid_device_id sp_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, sp_devices);
+
+static struct hid_driver sp_driver = {
+       .name = "sunplus",
+       .id_table = sp_devices,
+       .report_fixup = sp_report_fixup,
+       .input_mapping = sp_input_mapping,
+};
+
+static int sp_init(void)
+{
+       return hid_register_driver(&sp_driver);
+}
+
+static void sp_exit(void)
+{
+       hid_unregister_driver(&sp_driver);
+}
+
+module_init(sp_init);
+module_exit(sp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(sunplus);
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
new file mode 100644 (file)
index 0000000..1b7cba0
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Force feedback support for various HID compliant devices by ThrustMaster:
+ *    ThrustMaster FireStorm Dual Power 2
+ * and possibly others whose device ids haven't been added.
+ *
+ *  Modified to support ThrustMaster devices by Zinx Verituse
+ *  on 2003-01-25 from the Logitech force feedback driver,
+ *  which is by Johann Deneux.
+ *
+ *  Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org>
+ *  Copyright (c) 2002 Johann Deneux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/hid.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#include "usbhid/usbhid.h"
+
+/* Usages for thrustmaster devices I know about */
+#define THRUSTMASTER_USAGE_FF  (HID_UP_GENDESK | 0xbb)
+
+static const signed short ff_rumble[] = {
+       FF_RUMBLE,
+       -1
+};
+
+static const signed short ff_joystick[] = {
+       FF_CONSTANT,
+       -1
+};
+
+struct tmff_device {
+       struct hid_report *report;
+       struct hid_field *ff_field;
+};
+
+/* Changes values from 0 to 0xffff into values from minimum to maximum */
+static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
+{
+       int ret;
+
+       ret = (in * (maximum - minimum) / 0xffff) + minimum;
+       if (ret < minimum)
+               return minimum;
+       if (ret > maximum)
+               return maximum;
+       return ret;
+}
+
+/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
+static inline int tmff_scale_s8(int in, int minimum, int maximum)
+{
+       int ret;
+
+       ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
+       if (ret < minimum)
+               return minimum;
+       if (ret > maximum)
+               return maximum;
+       return ret;
+}
+
+static int tmff_play(struct input_dev *dev, void *data,
+               struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct tmff_device *tmff = data;
+       struct hid_field *ff_field = tmff->ff_field;
+       int x, y;
+       int left, right;        /* Rumbling */
+
+       switch (effect->type) {
+       case FF_CONSTANT:
+               x = tmff_scale_s8(effect->u.ramp.start_level,
+                                       ff_field->logical_minimum,
+                                       ff_field->logical_maximum);
+               y = tmff_scale_s8(effect->u.ramp.end_level,
+                                       ff_field->logical_minimum,
+                                       ff_field->logical_maximum);
+
+               dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
+               ff_field->value[0] = x;
+               ff_field->value[1] = y;
+               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+               break;
+
+       case FF_RUMBLE:
+               left = tmff_scale_u16(effect->u.rumble.weak_magnitude,
+                                       ff_field->logical_minimum,
+                                       ff_field->logical_maximum);
+               right = tmff_scale_u16(effect->u.rumble.strong_magnitude,
+                                       ff_field->logical_minimum,
+                                       ff_field->logical_maximum);
+
+               dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
+               ff_field->value[0] = left;
+               ff_field->value[1] = right;
+               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+               break;
+       }
+       return 0;
+}
+
+static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
+{
+       struct tmff_device *tmff;
+       struct hid_report *report;
+       struct list_head *report_list;
+       struct hid_input *hidinput = list_entry(hid->inputs.next,
+                                                       struct hid_input, list);
+       struct input_dev *input_dev = hidinput->input;
+       int error;
+       int i;
+
+       tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
+       if (!tmff)
+               return -ENOMEM;
+
+       /* Find the report to use */
+       report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       list_for_each_entry(report, report_list, list) {
+               int fieldnum;
+
+               for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
+                       struct hid_field *field = report->field[fieldnum];
+
+                       if (field->maxusage <= 0)
+                               continue;
+
+                       switch (field->usage[0].hid) {
+                       case THRUSTMASTER_USAGE_FF:
+                               if (field->report_count < 2) {
+                                       dev_warn(&hid->dev, "ignoring FF field "
+                                               "with report_count < 2\n");
+                                       continue;
+                               }
+
+                               if (field->logical_maximum ==
+                                               field->logical_minimum) {
+                                       dev_warn(&hid->dev, "ignoring FF field "
+                                                       "with logical_maximum "
+                                                       "== logical_minimum\n");
+                                       continue;
+                               }
+
+                               if (tmff->report && tmff->report != report) {
+                                       dev_warn(&hid->dev, "ignoring FF field "
+                                                       "in other report\n");
+                                       continue;
+                               }
+
+                               if (tmff->ff_field && tmff->ff_field != field) {
+                                       dev_warn(&hid->dev, "ignoring "
+                                                       "duplicate FF field\n");
+                                       continue;
+                               }
+
+                               tmff->report = report;
+                               tmff->ff_field = field;
+
+                               for (i = 0; ff_bits[i] >= 0; i++)
+                                       set_bit(ff_bits[i], input_dev->ffbit);
+
+                               break;
+
+                       default:
+                               dev_warn(&hid->dev, "ignoring unknown output "
+                                               "usage %08x\n",
+                                               field->usage[0].hid);
+                               continue;
+                       }
+               }
+       }
+
+       if (!tmff->report) {
+               dev_err(&hid->dev, "can't find FF field in output reports\n");
+               error = -ENODEV;
+               goto fail;
+       }
+
+       error = input_ff_create_memless(input_dev, tmff, tmff_play);
+       if (error)
+               goto fail;
+
+       dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx "
+                       "Verituse <zinx@epicsol.org>");
+       return 0;
+
+fail:
+       kfree(tmff);
+       return error;
+}
+
+static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err;
+       }
+
+       tmff_init(hdev, (void *)id->driver_data);
+
+       return 0;
+err:
+       return ret;
+}
+
+static const struct hid_device_id tm_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300),
+               .driver_data = (unsigned long)ff_rumble },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),
+               .driver_data = (unsigned long)ff_rumble },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651),   /* FGT Rumble Force Wheel */
+               .driver_data = (unsigned long)ff_rumble },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654),   /* FGT Force Feedback Wheel */
+               .driver_data = (unsigned long)ff_joystick },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, tm_devices);
+
+static struct hid_driver tm_driver = {
+       .name = "thrustmaster",
+       .id_table = tm_devices,
+       .probe = tm_probe,
+};
+
+static int tm_init(void)
+{
+       return hid_register_driver(&tm_driver);
+}
+
+static void tm_exit(void)
+{
+       hid_unregister_driver(&tm_driver);
+}
+
+module_init(tm_init);
+module_exit(tm_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(thrustmaster);
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
new file mode 100644 (file)
index 0000000..ea82f37
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  Force feedback support for Zeroplus based devices
+ *
+ *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#include "usbhid/usbhid.h"
+
+struct zpff_device {
+       struct hid_report *report;
+};
+
+static int zpff_play(struct input_dev *dev, void *data,
+                        struct ff_effect *effect)
+{
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct zpff_device *zpff = data;
+       int left, right;
+
+       /*
+        * The following is specified the other way around in the Zeroplus
+        * datasheet but the order below is correct for the XFX Executioner;
+        * however it is possible that the XFX Executioner is an exception
+        */
+
+       left = effect->u.rumble.strong_magnitude;
+       right = effect->u.rumble.weak_magnitude;
+       dbg_hid("called with 0x%04x 0x%04x\n", left, right);
+
+       left = left * 0x7f / 0xffff;
+       right = right * 0x7f / 0xffff;
+
+       zpff->report->field[2]->value[0] = left;
+       zpff->report->field[3]->value[0] = right;
+       dbg_hid("running with 0x%02x 0x%02x\n", left, right);
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+
+       return 0;
+}
+
+static int zpff_init(struct hid_device *hid)
+{
+       struct zpff_device *zpff;
+       struct hid_report *report;
+       struct hid_input *hidinput = list_entry(hid->inputs.next,
+                                               struct hid_input, list);
+       struct list_head *report_list =
+                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct input_dev *dev = hidinput->input;
+       int error;
+
+       if (list_empty(report_list)) {
+               dev_err(&hid->dev, "no output report found\n");
+               return -ENODEV;
+       }
+
+       report = list_entry(report_list->next, struct hid_report, list);
+
+       if (report->maxfield < 4) {
+               dev_err(&hid->dev, "not enough fields in report\n");
+               return -ENODEV;
+       }
+
+       zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
+       if (!zpff)
+               return -ENOMEM;
+
+       set_bit(FF_RUMBLE, dev->ffbit);
+
+       error = input_ff_create_memless(dev, zpff, zpff_play);
+       if (error) {
+               kfree(zpff);
+               return error;
+       }
+
+       zpff->report = report;
+       zpff->report->field[0]->value[0] = 0x00;
+       zpff->report->field[1]->value[0] = 0x02;
+       zpff->report->field[2]->value[0] = 0x00;
+       zpff->report->field[3]->value[0] = 0x00;
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+
+       dev_info(&hid->dev, "force feedback for Zeroplus based devices by "
+              "Anssi Hannula <anssi.hannula@gmail.com>\n");
+
+       return 0;
+}
+
+static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       int ret;
+
+       ret = hid_parse(hdev);
+       if (ret) {
+               dev_err(&hdev->dev, "parse failed\n");
+               goto err;
+       }
+
+       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+       if (ret) {
+               dev_err(&hdev->dev, "hw start failed\n");
+               goto err;
+       }
+
+       zpff_init(hdev);
+
+       return 0;
+err:
+       return ret;
+}
+
+static const struct hid_device_id zp_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, zp_devices);
+
+static struct hid_driver zp_driver = {
+       .name = "zeroplus",
+       .id_table = zp_devices,
+       .probe = zp_probe,
+};
+
+static int zp_init(void)
+{
+       return hid_register_driver(&zp_driver);
+}
+
+static void zp_exit(void)
+{
+       hid_unregister_driver(&zp_driver);
+}
+
+module_init(zp_init);
+module_exit(zp_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(zeroplus);
index c40f0403edafe1390d5fecb66604e095c8f70057..af3edb98df435f2c3fa22fde81350d4f15dcd286 100644 (file)
@@ -113,7 +113,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
        if (!dev->hid_output_raw_report)
                return -ENODEV;
 
-       if (count > HID_MIN_BUFFER_SIZE) {
+       if (count > HID_MAX_BUFFER_SIZE) {
                printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
                                task_pid_nr(current));
                return -EINVAL;
@@ -181,7 +181,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
 
        dev = hidraw_table[minor];
        if (!dev->open++)
-               dev->hid->hid_open(dev->hid);
+               dev->hid->ll_driver->open(dev->hid);
 
 out_unlock:
        spin_unlock(&minors_lock);
@@ -207,7 +207,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
        dev = hidraw_table[minor];
        if (!dev->open--) {
                if (list->hidraw->exist)
-                       dev->hid->hid_close(dev->hid);
+                       dev->hid->ll_driver->close(dev->hid);
                else
                        kfree(list->hidraw);
        }
@@ -326,9 +326,8 @@ int hidraw_connect(struct hid_device *hid)
                goto out;
        }
 
-       dev->dev = device_create_drvdata(hidraw_class, NULL,
-                                        MKDEV(hidraw_major, minor), NULL,
-                                        "%s%d", "hidraw", minor);
+       dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+                                NULL, "%s%d", "hidraw", minor);
 
        if (IS_ERR(dev->dev)) {
                spin_lock(&minors_lock);
@@ -367,7 +366,7 @@ void hidraw_disconnect(struct hid_device *hid)
        device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
 
        if (hidraw->open) {
-               hid->hid_close(hid);
+               hid->ll_driver->close(hid);
                wake_up_interruptible(&hidraw->wait);
        } else {
                kfree(hidraw);
index 18f09104765c71406020bc2031c76ef901fcaa2c..5d9aa95fc3ef1570c22cb8b0927461dbfba68465 100644 (file)
@@ -24,88 +24,13 @@ config USB_HID
 comment "Input core support is needed for USB HID input layer or HIDBP support"
        depends on USB_HID && INPUT=n
 
-config USB_HIDINPUT_POWERBOOK
-       bool "Enable support for Apple laptop/aluminum USB special keys"
-       default n
-       depends on USB_HID
-       help
-         Say Y here if you want support for the special keys (Fn, Numlock) on
-         Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
-         keyboards.
-
-         If unsure, say N.
-
-config HID_FF
-       bool "Force feedback support (EXPERIMENTAL)"
-       depends on USB_HID && EXPERIMENTAL
-       help
-         Say Y here is you want force feedback support for a few HID devices.
-         See below for a list of supported devices.
-
-         See <file:Documentation/input/ff.txt> for a description of the force
-         feedback API.
-
-         If unsure, say N.
-
 config HID_PID
        bool "PID device support"
-       depends on HID_FF
        help
          Say Y here if you have a PID-compliant device and wish to enable force
          feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such
          devices.
 
-config LOGITECH_FF
-       bool "Logitech devices support"
-       depends on HID_FF
-       select INPUT_FF_MEMLESS if USB_HID
-       help
-         Say Y here if you have one of these devices:
-         - Logitech WingMan Cordless RumblePad
-         - Logitech WingMan Cordless RumblePad 2
-         - Logitech WingMan Force 3D
-         - Logitech Formula Force EX
-         - Logitech MOMO Force wheel
-
-         and if you want to enable force feedback for them.
-         Note: if you say N here, this device will still be supported, but without
-         force feedback.
-
-config LOGIRUMBLEPAD2_FF
-       bool "Logitech Rumblepad 2 support"
-       depends on HID_FF
-       select INPUT_FF_MEMLESS if USB_HID
-       help
-         Say Y here if you want to enable force feedback support for Logitech
-         Rumblepad 2 devices.
-
-config PANTHERLORD_FF
-       bool "PantherLord/GreenAsia based device support"
-       depends on HID_FF
-       select INPUT_FF_MEMLESS if USB_HID
-       help
-         Say Y here if you have a PantherLord/GreenAsia based game controller
-         or adapter and want to enable force feedback support for it.
-
-config THRUSTMASTER_FF
-       bool "ThrustMaster devices support"
-       depends on HID_FF
-       select INPUT_FF_MEMLESS if USB_HID
-       help
-         Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
-         a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel,
-         and want to enable force feedback support for it.
-         Note: if you say N here, this device will still be supported, but without
-         force feedback.
-
-config ZEROPLUS_FF
-       bool "Zeroplus based game controller support"
-       depends on HID_FF
-       select INPUT_FF_MEMLESS if USB_HID
-       help
-         Say Y here if you have a Zeroplus based game controller and want to
-         enable force feedback for it.
-
 config USB_HIDDEV
        bool "/dev/hiddev raw HID device support"
        depends on USB_HID
index 00a7b70901925276e63237b023580c94ec21cec8..1329ecb37a1c7b8b4e0c24f4f3ce341b4e188061 100644 (file)
@@ -13,24 +13,6 @@ endif
 ifeq ($(CONFIG_HID_PID),y)
        usbhid-objs     += hid-pidff.o
 endif
-ifeq ($(CONFIG_LOGITECH_FF),y)
-       usbhid-objs     += hid-lgff.o
-endif
-ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
-       usbhid-objs     += hid-lg2ff.o
-endif
-ifeq ($(CONFIG_PANTHERLORD_FF),y)
-       usbhid-objs     += hid-plff.o
-endif
-ifeq ($(CONFIG_THRUSTMASTER_FF),y)
-       usbhid-objs     += hid-tmff.o
-endif
-ifeq ($(CONFIG_ZEROPLUS_FF),y)
-       usbhid-objs     += hid-zpff.o
-endif
-ifeq ($(CONFIG_HID_FF),y)
-       usbhid-objs     += hid-ff.o
-endif
 
 obj-$(CONFIG_USB_HID)          += usbhid.o
 obj-$(CONFIG_USB_KBD)          += usbkbd.o
index 27fe4d8912cb9a6a1e1b847b0899103199fdbbe9..1d3b8a394d468d28d8364941cf21a2b178532b59 100644 (file)
@@ -44,8 +44,6 @@
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
-                               "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
 /*
  * Module parameters.
  */
@@ -61,12 +59,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
                " quirks=vendorID:productID:quirks"
                " where vendorID, productID, and quirks are all in"
                " 0x-prefixed hex");
-static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
-module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
-MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
-               " rdesc_quirks=vendorID:productID:rdesc_quirks"
-               " where vendorID, productID, and rdesc_quirks are all in"
-               " 0x-prefixed hex");
 /*
  * Input submission and I/O error handler.
  */
@@ -197,31 +189,32 @@ static void hid_irq_in(struct urb *urb)
        int                     status;
 
        switch (urb->status) {
-               case 0:                 /* success */
-                       usbhid->retry_delay = 0;
-                       hid_input_report(urb->context, HID_INPUT_REPORT,
-                                        urb->transfer_buffer,
-                                        urb->actual_length, 1);
-                       break;
-               case -EPIPE:            /* stall */
-                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-                       set_bit(HID_CLEAR_HALT, &usbhid->iofl);
-                       schedule_work(&usbhid->reset_work);
-                       return;
-               case -ECONNRESET:       /* unlink */
-               case -ENOENT:
-               case -ESHUTDOWN:        /* unplug */
-                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-                       return;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
-               case -ETIME:            /* protocol error or unplug */
-               case -ETIMEDOUT:        /* Should never happen, but... */
-                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-                       hid_io_error(hid);
-                       return;
-               default:                /* error */
-                       warn("input irq status %d received", urb->status);
+       case 0:                 /* success */
+               usbhid->retry_delay = 0;
+               hid_input_report(urb->context, HID_INPUT_REPORT,
+                                urb->transfer_buffer,
+                                urb->actual_length, 1);
+               break;
+       case -EPIPE:            /* stall */
+               clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+               set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+               schedule_work(&usbhid->reset_work);
+               return;
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+       case -ESHUTDOWN:        /* unplug */
+               clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+               return;
+       case -EILSEQ:           /* protocol error or unplug */
+       case -EPROTO:           /* protocol error or unplug */
+       case -ETIME:            /* protocol error or unplug */
+       case -ETIMEDOUT:        /* Should never happen, but... */
+               clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+               hid_io_error(hid);
+               return;
+       default:                /* error */
+               dev_warn(&urb->dev->dev, "input irq status %d  "
+                               "received\n", urb->status);
        }
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -240,13 +233,16 @@ static void hid_irq_in(struct urb *urb)
 static int hid_submit_out(struct hid_device *hid)
 {
        struct hid_report *report;
+       char *raw_report;
        struct usbhid_device *usbhid = hid->driver_data;
 
-       report = usbhid->out[usbhid->outtail];
+       report = usbhid->out[usbhid->outtail].report;
+       raw_report = usbhid->out[usbhid->outtail].raw_report;
 
-       hid_output_report(report, usbhid->outbuf);
        usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
        usbhid->urbout->dev = hid_to_usb_dev(hid);
+       memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length);
+       kfree(raw_report);
 
        dbg_hid("submitting out urb\n");
 
@@ -262,17 +258,20 @@ static int hid_submit_ctrl(struct hid_device *hid)
 {
        struct hid_report *report;
        unsigned char dir;
+       char *raw_report;
        int len;
        struct usbhid_device *usbhid = hid->driver_data;
 
        report = usbhid->ctrl[usbhid->ctrltail].report;
+       raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
        dir = usbhid->ctrl[usbhid->ctrltail].dir;
 
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
        if (dir == USB_DIR_OUT) {
-               hid_output_report(report, usbhid->ctrlbuf);
                usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
                usbhid->urbctrl->transfer_buffer_length = len;
+               memcpy(usbhid->ctrlbuf, raw_report, len);
+               kfree(raw_report);
        } else {
                int maxpacket, padlen;
 
@@ -319,17 +318,18 @@ static void hid_irq_out(struct urb *urb)
        int unplug = 0;
 
        switch (urb->status) {
-               case 0:                 /* success */
-                       break;
-               case -ESHUTDOWN:        /* unplug */
-                       unplug = 1;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
-               case -ECONNRESET:       /* unlink */
-               case -ENOENT:
-                       break;
-               default:                /* error */
-                       warn("output irq status %d received", urb->status);
+       case 0:                 /* success */
+               break;
+       case -ESHUTDOWN:        /* unplug */
+               unplug = 1;
+       case -EILSEQ:           /* protocol error or unplug */
+       case -EPROTO:           /* protocol error or unplug */
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+               break;
+       default:                /* error */
+               dev_warn(&urb->dev->dev, "output irq status %d "
+                               "received\n", urb->status);
        }
 
        spin_lock_irqsave(&usbhid->outlock, flags);
@@ -367,21 +367,23 @@ static void hid_ctrl(struct urb *urb)
        spin_lock_irqsave(&usbhid->ctrllock, flags);
 
        switch (urb->status) {
-               case 0:                 /* success */
-                       if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
-                               hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
-                                               urb->transfer_buffer, urb->actual_length, 0);
-                       break;
-               case -ESHUTDOWN:        /* unplug */
-                       unplug = 1;
-               case -EILSEQ:           /* protocol error or unplug */
-               case -EPROTO:           /* protocol error or unplug */
-               case -ECONNRESET:       /* unlink */
-               case -ENOENT:
-               case -EPIPE:            /* report not available */
-                       break;
-               default:                /* error */
-                       warn("ctrl urb status %d received", urb->status);
+       case 0:                 /* success */
+               if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+                       hid_input_report(urb->context,
+                               usbhid->ctrl[usbhid->ctrltail].report->type,
+                               urb->transfer_buffer, urb->actual_length, 0);
+               break;
+       case -ESHUTDOWN:        /* unplug */
+               unplug = 1;
+       case -EILSEQ:           /* protocol error or unplug */
+       case -EPROTO:           /* protocol error or unplug */
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+       case -EPIPE:            /* report not available */
+               break;
+       default:                /* error */
+               dev_warn(&urb->dev->dev, "ctrl urb status %d "
+                               "received\n", urb->status);
        }
 
        if (unplug)
@@ -408,6 +410,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
        int head;
        unsigned long flags;
        struct usbhid_device *usbhid = hid->driver_data;
+       int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 
        if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
                return;
@@ -418,11 +421,18 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
 
                if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
                        spin_unlock_irqrestore(&usbhid->outlock, flags);
-                       warn("output queue full");
+                       dev_warn(&hid->dev, "output queue full\n");
                        return;
                }
 
-               usbhid->out[usbhid->outhead] = report;
+               usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
+               if (!usbhid->out[usbhid->outhead].raw_report) {
+                       spin_unlock_irqrestore(&usbhid->outlock, flags);
+                       warn("output queueing failed");
+                       return;
+               }
+               hid_output_report(report, usbhid->out[usbhid->outhead].raw_report);
+               usbhid->out[usbhid->outhead].report = report;
                usbhid->outhead = head;
 
                if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
@@ -437,10 +447,19 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
 
        if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
                spin_unlock_irqrestore(&usbhid->ctrllock, flags);
-               warn("control queue full");
+               dev_warn(&hid->dev, "control queue full\n");
                return;
        }
 
+       if (dir == USB_DIR_OUT) {
+               usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
+               if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
+                       spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+                       warn("control queueing failed");
+                       return;
+               }
+               hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report);
+       }
        usbhid->ctrl[usbhid->ctrlhead].report = report;
        usbhid->ctrl[usbhid->ctrlhead].dir = dir;
        usbhid->ctrlhead = head;
@@ -451,6 +470,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
 
        spin_unlock_irqrestore(&usbhid->ctrllock, flags);
 }
+EXPORT_SYMBOL_GPL(usbhid_submit_report);
 
 static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -465,7 +485,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
                return -1;
 
        if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
-               warn("event field not found");
+               dev_warn(&dev->dev, "event field not found\n");
                return -1;
        }
 
@@ -568,7 +588,7 @@ void usbhid_init_reports(struct hid_device *hid)
        }
 
        if (err)
-               warn("timeout initializing reports");
+               dev_warn(&hid->dev, "timeout initializing reports\n");
 }
 
 /*
@@ -598,7 +618,7 @@ static int hid_find_field_early(struct hid_device *hid, unsigned int page,
        return -1;
 }
 
-static void usbhid_set_leds(struct hid_device *hid)
+void usbhid_set_leds(struct hid_device *hid)
 {
        struct hid_field *field;
        int offset;
@@ -608,6 +628,7 @@ static void usbhid_set_leds(struct hid_device *hid)
                usbhid_submit_report(hid, field->report, USB_DIR_OUT);
        }
 }
+EXPORT_SYMBOL_GPL(usbhid_set_leds);
 
 /*
  * Traverse the supplied list of reports and find the longest
@@ -675,43 +696,16 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
        usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
 }
 
-/*
- * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
- * to "operational".  Without this, the ps3 controller will not report any
- * events.
- */
-static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
-{
-       int result;
-       char *buf = kmalloc(18, GFP_KERNEL);
-
-       if (!buf)
-               return;
-
-       result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                                HID_REQ_GET_REPORT,
-                                USB_DIR_IN | USB_TYPE_CLASS |
-                                USB_RECIP_INTERFACE,
-                                (3 << 8) | 0xf2, ifnum, buf, 17,
-                                USB_CTRL_GET_TIMEOUT);
-
-       if (result < 0)
-               err_hid("%s failed: %d\n", __func__, result);
-
-       kfree(buf);
-}
-
-static struct hid_device *usb_hid_configure(struct usb_interface *intf)
+static int usbhid_parse(struct hid_device *hid)
 {
+       struct usb_interface *intf = to_usb_interface(hid->dev.parent);
        struct usb_host_interface *interface = intf->cur_altsetting;
        struct usb_device *dev = interface_to_usbdev (intf);
        struct hid_descriptor *hdesc;
-       struct hid_device *hid;
        u32 quirks = 0;
-       unsigned int insize = 0, rsize = 0;
+       unsigned int rsize = 0;
        char *rdesc;
-       int n, len;
-       struct usbhid_device *usbhid;
+       int ret, n;
 
        quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
                        le16_to_cpu(dev->descriptor.idProduct));
@@ -724,63 +718,75 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                                quirks |= HID_QUIRK_NOGET;
        }
 
-       if (quirks & HID_QUIRK_IGNORE)
-               return NULL;
-
-       if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
-               (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
-                       return NULL;
-
-
        if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
            (!interface->desc.bNumEndpoints ||
             usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
                dbg_hid("class descriptor not present\n");
-               return NULL;
+               return -ENODEV;
        }
 
+       hid->version = le16_to_cpu(hdesc->bcdHID);
+       hid->country = hdesc->bCountryCode;
+
        for (n = 0; n < hdesc->bNumDescriptors; n++)
                if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
                        rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
        if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
                dbg_hid("weird size of report descriptor (%u)\n", rsize);
-               return NULL;
+               return -EINVAL;
        }
 
        if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
                dbg_hid("couldn't allocate rdesc memory\n");
-               return NULL;
+               return -ENOMEM;
        }
 
        hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
 
-       if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
+       ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber,
+                       HID_DT_REPORT, rdesc, rsize);
+       if (ret < 0) {
                dbg_hid("reading report descriptor failed\n");
                kfree(rdesc);
-               return NULL;
+               goto err;
        }
 
-       usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
-                       le16_to_cpu(dev->descriptor.idProduct), rdesc,
-                       rsize, rdesc_quirks_param);
-
        dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
        for (n = 0; n < rsize; n++)
                dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
        dbg_hid_line("\n");
 
-       if (!(hid = hid_parse_report(rdesc, n))) {
+       ret = hid_parse_report(hid, rdesc, rsize);
+       kfree(rdesc);
+       if (ret) {
                dbg_hid("parsing report descriptor failed\n");
-               kfree(rdesc);
-               return NULL;
+               goto err;
        }
 
-       kfree(rdesc);
        hid->quirks = quirks;
 
-       if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
-               goto fail_no_usbhid;
+       return 0;
+err:
+       return ret;
+}
+
+static int usbhid_start(struct hid_device *hid)
+{
+       struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+       struct usb_host_interface *interface = intf->cur_altsetting;
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usbhid_device *usbhid;
+       unsigned int n, insize = 0;
+       int ret;
+
+       WARN_ON(hid->driver_data);
+
+       usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL);
+       if (usbhid == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        hid->driver_data = usbhid;
        usbhid->hid = hid;
@@ -799,28 +805,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                insize = HID_MAX_BUFFER_SIZE;
 
        if (hid_alloc_buffers(dev, hid)) {
-               hid_free_buffers(dev, hid);
+               ret = -ENOMEM;
                goto fail;
        }
 
-       hid->name[0] = 0;
-
-       if (dev->manufacturer)
-               strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
-
-       if (dev->product) {
-               if (dev->manufacturer)
-                       strlcat(hid->name, " ", sizeof(hid->name));
-               strlcat(hid->name, dev->product, sizeof(hid->name));
-       }
-
-       if (!strlen(hid->name))
-               snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
-                        le16_to_cpu(dev->descriptor.idVendor),
-                        le16_to_cpu(dev->descriptor.idProduct));
-
        for (n = 0; n < interface->desc.bNumEndpoints; n++) {
-
                struct usb_endpoint_descriptor *endpoint;
                int pipe;
                int interval;
@@ -832,7 +821,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                interval = endpoint->bInterval;
 
                /* Some vendors give fullspeed interval on highspeed devides */
-               if (quirks & HID_QUIRK_FULLSPEED_INTERVAL  &&
+               if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
                    dev->speed == USB_SPEED_HIGH) {
                        interval = fls(endpoint->bInterval*8);
                        printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
@@ -843,6 +832,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
                        interval = hid_mousepoll_interval;
 
+               ret = -ENOMEM;
                if (usb_endpoint_dir_in(endpoint)) {
                        if (usbhid->urbin)
                                continue;
@@ -868,6 +858,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
        if (!usbhid->urbin) {
                err_hid("couldn't find an input interrupt endpoint");
+               ret = -ENODEV;
                goto fail;
        }
 
@@ -879,44 +870,25 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        spin_lock_init(&usbhid->outlock);
        spin_lock_init(&usbhid->ctrllock);
 
-       hid->version = le16_to_cpu(hdesc->bcdHID);
-       hid->country = hdesc->bCountryCode;
-       hid->dev = &intf->dev;
        usbhid->intf = intf;
        usbhid->ifnum = interface->desc.bInterfaceNumber;
 
-       hid->bus = BUS_USB;
-       hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
-       hid->product = le16_to_cpu(dev->descriptor.idProduct);
-
-       usb_make_path(dev, hid->phys, sizeof(hid->phys));
-       strlcat(hid->phys, "/input", sizeof(hid->phys));
-       len = strlen(hid->phys);
-       if (len < sizeof(hid->phys) - 1)
-               snprintf(hid->phys + len, sizeof(hid->phys) - len,
-                        "%d", intf->altsetting[0].desc.bInterfaceNumber);
-
-       if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
-               hid->uniq[0] = 0;
-
        usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-       if (!usbhid->urbctrl)
+       if (!usbhid->urbctrl) {
+               ret = -ENOMEM;
                goto fail;
+       }
 
        usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
                             usbhid->ctrlbuf, 1, hid_ctrl, hid);
        usbhid->urbctrl->setup_dma = usbhid->cr_dma;
        usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
        usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
-       hid->hidinput_input_event = usb_hidinput_input_event;
-       hid->hid_open = usbhid_open;
-       hid->hid_close = usbhid_close;
-#ifdef CONFIG_USB_HIDDEV
-       hid->hiddev_hid_event = hiddev_hid_event;
-       hid->hiddev_report_event = hiddev_report_event;
-#endif
-       hid->hid_output_raw_report = usbhid_output_raw_report;
-       return hid;
+
+       usbhid_init_reports(hid);
+       hid_dump_device(hid);
+
+       return 0;
 
 fail:
        usb_free_urb(usbhid->urbin);
@@ -924,24 +896,18 @@ fail:
        usb_free_urb(usbhid->urbctrl);
        hid_free_buffers(dev, hid);
        kfree(usbhid);
-fail_no_usbhid:
-       hid_free_device(hid);
-
-       return NULL;
+err:
+       return ret;
 }
 
-static void hid_disconnect(struct usb_interface *intf)
+static void usbhid_stop(struct hid_device *hid)
 {
-       struct hid_device *hid = usb_get_intfdata (intf);
-       struct usbhid_device *usbhid;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       if (!hid)
+       if (WARN_ON(!usbhid))
                return;
 
-       usbhid = hid->driver_data;
-
        spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
-       usb_set_intfdata(intf, NULL);
        set_bit(HID_DISCONNECTED, &usbhid->iofl);
        spin_unlock_irq(&usbhid->inlock);
        usb_kill_urb(usbhid->urbin);
@@ -958,86 +924,100 @@ static void hid_disconnect(struct usb_interface *intf)
        if (hid->claimed & HID_CLAIMED_HIDRAW)
                hidraw_disconnect(hid);
 
+       hid->claimed = 0;
+
        usb_free_urb(usbhid->urbin);
        usb_free_urb(usbhid->urbctrl);
        usb_free_urb(usbhid->urbout);
 
        hid_free_buffers(hid_to_usb_dev(hid), hid);
        kfree(usbhid);
-       hid_free_device(hid);
+       hid->driver_data = NULL;
 }
 
+static struct hid_ll_driver usb_hid_driver = {
+       .parse = usbhid_parse,
+       .start = usbhid_start,
+       .stop = usbhid_stop,
+       .open = usbhid_open,
+       .close = usbhid_close,
+       .hidinput_input_event = usb_hidinput_input_event,
+};
+
 static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
+       struct usb_device *dev = interface_to_usbdev(intf);
        struct hid_device *hid;
-       char path[64];
-       int i;
-       char *c;
+       size_t len;
+       int ret;
 
        dbg_hid("HID probe called for ifnum %d\n",
                        intf->altsetting->desc.bInterfaceNumber);
 
-       if (!(hid = usb_hid_configure(intf)))
-               return -ENODEV;
-
-       usbhid_init_reports(hid);
-       hid_dump_device(hid);
-       if (hid->quirks & HID_QUIRK_RESET_LEDS)
-               usbhid_set_leds(hid);
-
-       if (!hidinput_connect(hid))
-               hid->claimed |= HID_CLAIMED_INPUT;
-       if (!hiddev_connect(hid))
-               hid->claimed |= HID_CLAIMED_HIDDEV;
-       if (!hidraw_connect(hid))
-               hid->claimed |= HID_CLAIMED_HIDRAW;
+       hid = hid_allocate_device();
+       if (IS_ERR(hid))
+               return PTR_ERR(hid);
 
        usb_set_intfdata(intf, hid);
+       hid->ll_driver = &usb_hid_driver;
+       hid->hid_output_raw_report = usbhid_output_raw_report;
+       hid->ff_init = hid_pidff_init;
+#ifdef CONFIG_USB_HIDDEV
+       hid->hiddev_connect = hiddev_connect;
+       hid->hiddev_hid_event = hiddev_hid_event;
+       hid->hiddev_report_event = hiddev_report_event;
+#endif
+       hid->dev.parent = &intf->dev;
+       hid->bus = BUS_USB;
+       hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
+       hid->product = le16_to_cpu(dev->descriptor.idProduct);
+       hid->name[0] = 0;
 
-       if (!hid->claimed) {
-               printk ("HID device claimed by neither input, hiddev nor hidraw\n");
-               hid_disconnect(intf);
-               return -ENODEV;
+       if (dev->manufacturer)
+               strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+
+       if (dev->product) {
+               if (dev->manufacturer)
+                       strlcat(hid->name, " ", sizeof(hid->name));
+               strlcat(hid->name, dev->product, sizeof(hid->name));
        }
 
-       if ((hid->claimed & HID_CLAIMED_INPUT))
-               hid_ff_init(hid);
+       if (!strlen(hid->name))
+               snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
+                        le16_to_cpu(dev->descriptor.idVendor),
+                        le16_to_cpu(dev->descriptor.idProduct));
 
-       if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
-               hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
-                       intf->cur_altsetting->desc.bInterfaceNumber);
+       usb_make_path(dev, hid->phys, sizeof(hid->phys));
+       strlcat(hid->phys, "/input", sizeof(hid->phys));
+       len = strlen(hid->phys);
+       if (len < sizeof(hid->phys) - 1)
+               snprintf(hid->phys + len, sizeof(hid->phys) - len,
+                        "%d", intf->altsetting[0].desc.bInterfaceNumber);
 
-       printk(KERN_INFO);
+       if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
+               hid->uniq[0] = 0;
 
-       if (hid->claimed & HID_CLAIMED_INPUT)
-               printk("input");
-       if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) ||
-                               hid->claimed & HID_CLAIMED_HIDRAW))
-               printk(",");
-       if (hid->claimed & HID_CLAIMED_HIDDEV)
-               printk("hiddev%d", hid->minor);
-       if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) &&
-                       (hid->claimed & HID_CLAIMED_HIDRAW))
-               printk(",");
-       if (hid->claimed & HID_CLAIMED_HIDRAW)
-               printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor);
-
-       c = "Device";
-       for (i = 0; i < hid->maxcollection; i++) {
-               if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
-                   (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
-                   (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) {
-                       c = hid_types[hid->collection[i].usage & 0xffff];
-                       break;
-               }
+       ret = hid_add_device(hid);
+       if (ret) {
+               if (ret != -ENODEV)
+                       dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+               goto err;
        }
 
-       usb_make_path(interface_to_usbdev(intf), path, 63);
+       return 0;
+err:
+       hid_destroy_device(hid);
+       return ret;
+}
 
-       printk(": USB HID v%x.%02x %s [%s] on %s\n",
-               hid->version >> 8, hid->version & 0xff, c, hid->name, path);
+static void hid_disconnect(struct usb_interface *intf)
+{
+       struct hid_device *hid = usb_get_intfdata(intf);
 
-       return 0;
+       if (WARN_ON(!hid))
+               return;
+
+       hid_destroy_device(hid);
 }
 
 static int hid_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1107,9 +1087,22 @@ static struct usb_driver hid_driver = {
        .supports_autosuspend = 1,
 };
 
+static const struct hid_device_id hid_usb_table[] = {
+       { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
+       { }
+};
+
+static struct hid_driver hid_usb_driver = {
+       .name = "generic-usb",
+       .id_table = hid_usb_table,
+};
+
 static int __init hid_init(void)
 {
        int retval;
+       retval = hid_register_driver(&hid_usb_driver);
+       if (retval)
+               goto hid_register_fail;
        retval = usbhid_quirks_init(quirks_param);
        if (retval)
                goto usbhid_quirks_init_fail;
@@ -1119,7 +1112,8 @@ static int __init hid_init(void)
        retval = usb_register(&hid_driver);
        if (retval)
                goto usb_register_fail;
-       info(DRIVER_VERSION ":" DRIVER_DESC);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+                       DRIVER_DESC "\n");
 
        return 0;
 usb_register_fail:
@@ -1127,6 +1121,8 @@ usb_register_fail:
 hiddev_init_fail:
        usbhid_quirks_exit();
 usbhid_quirks_init_fail:
+       hid_unregister_driver(&hid_usb_driver);
+hid_register_fail:
        return retval;
 }
 
@@ -1135,6 +1131,7 @@ static void __exit hid_exit(void)
        usb_deregister(&hid_driver);
        hiddev_exit();
        usbhid_quirks_exit();
+       hid_unregister_driver(&hid_usb_driver);
 }
 
 module_init(hid_init);
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c
deleted file mode 100644 (file)
index 1d0dac5..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Force feedback support for hid devices.
- *  Not all hid devices use the same protocol. For example, some use PID,
- *  other use their own proprietary procotol.
- *
- *  Copyright (c) 2002-2004 Johann Deneux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <johann.deneux@it.uu.se>
- */
-
-#include <linux/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/*
- * This table contains pointers to initializers. To add support for new
- * devices, you need to add the USB vendor and product ids here.
- */
-struct hid_ff_initializer {
-       u16 idVendor;
-       u16 idProduct;
-       int (*init)(struct hid_device*);
-};
-
-/*
- * We try pidff when no other driver is found because PID is the
- * standards compliant way of implementing force feedback in HID.
- * pidff_init() will quickly abort if the device doesn't appear to
- * be a PID device
- */
-static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_FF
-       { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
-       { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
-       { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
-       { 0x46d, 0xc286, hid_lgff_init }, /* Logitech Force 3D Pro Joystick */
-       { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
-       { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
-       { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
-#endif
-#ifdef CONFIG_LOGIRUMBLEPAD2_FF
-       { 0x46d, 0xc218, hid_lg2ff_init }, /* Logitech Rumblepad 2 */
-#endif
-#ifdef CONFIG_PANTHERLORD_FF
-       { 0x810, 0x0001, hid_plff_init }, /* "Twin USB Joystick" */
-       { 0xe8f, 0x0003, hid_plff_init }, /* "GreenAsia Inc.    USB Joystick     " */
-#endif
-#ifdef CONFIG_THRUSTMASTER_FF
-       { 0x44f, 0xb300, hid_tmff_init },
-       { 0x44f, 0xb304, hid_tmff_init },
-       { 0x44f, 0xb651, hid_tmff_init }, /* FGT Rumble Force Wheel */
-       { 0x44f, 0xb654, hid_tmff_init }, /* FGT Force Feedback Wheel */
-#endif
-#ifdef CONFIG_ZEROPLUS_FF
-       { 0xc12, 0x0005, hid_zpff_init },
-       { 0xc12, 0x0030, hid_zpff_init },
-#endif
-       { 0,     0,      hid_pidff_init}  /* Matches anything */
-};
-
-int hid_ff_init(struct hid_device* hid)
-{
-       struct hid_ff_initializer *init;
-       int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
-       int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
-
-       for (init = inits; init->idVendor; init++)
-               if (init->idVendor == vendor && init->idProduct == product)
-                       break;
-
-       return init->init(hid);
-}
-EXPORT_SYMBOL_GPL(hid_ff_init);
-
diff --git a/drivers/hid/usbhid/hid-lg2ff.c b/drivers/hid/usbhid/hid-lg2ff.c
deleted file mode 100644 (file)
index d469bd0..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *  Force feedback support for Logitech Rumblepad 2
- *
- *  Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct lg2ff_device {
-       struct hid_report *report;
-};
-
-static int play_effect(struct input_dev *dev, void *data,
-                        struct ff_effect *effect)
-{
-       struct hid_device *hid = input_get_drvdata(dev);
-       struct lg2ff_device *lg2ff = data;
-       int weak, strong;
-
-       strong = effect->u.rumble.strong_magnitude;
-       weak = effect->u.rumble.weak_magnitude;
-
-       if (weak || strong) {
-               weak = weak * 0xff / 0xffff;
-               strong = strong * 0xff / 0xffff;
-
-               lg2ff->report->field[0]->value[0] = 0x51;
-               lg2ff->report->field[0]->value[2] = weak;
-               lg2ff->report->field[0]->value[4] = strong;
-       } else {
-               lg2ff->report->field[0]->value[0] = 0xf3;
-               lg2ff->report->field[0]->value[2] = 0x00;
-               lg2ff->report->field[0]->value[4] = 0x00;
-       }
-
-       usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
-       return 0;
-}
-
-int hid_lg2ff_init(struct hid_device *hid)
-{
-       struct lg2ff_device *lg2ff;
-       struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct list_head *report_list =
-                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
-       int error;
-
-       if (list_empty(report_list)) {
-               printk(KERN_ERR "hid-lg2ff: no output report found\n");
-               return -ENODEV;
-       }
-
-       report = list_entry(report_list->next, struct hid_report, list);
-
-       if (report->maxfield < 1) {
-               printk(KERN_ERR "hid-lg2ff: output report is empty\n");
-               return -ENODEV;
-       }
-       if (report->field[0]->report_count < 7) {
-               printk(KERN_ERR "hid-lg2ff: not enough values in the field\n");
-               return -ENODEV;
-       }
-
-       lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
-       if (!lg2ff)
-               return -ENOMEM;
-
-       set_bit(FF_RUMBLE, dev->ffbit);
-
-       error = input_ff_create_memless(dev, lg2ff, play_effect);
-       if (error) {
-               kfree(lg2ff);
-               return error;
-       }
-
-       lg2ff->report = report;
-       report->field[0]->value[0] = 0xf3;
-       report->field[0]->value[1] = 0x00;
-       report->field[0]->value[2] = 0x00;
-       report->field[0]->value[3] = 0x00;
-       report->field[0]->value[4] = 0x00;
-       report->field[0]->value[5] = 0x00;
-       report->field[0]->value[6] = 0x00;
-
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
-
-       printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by "
-              "Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-       return 0;
-}
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
deleted file mode 100644 (file)
index 4b7ab6a..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Force feedback support for hid-compliant for some of the devices from
- * Logitech, namely:
- * - WingMan Cordless RumblePad
- * - WingMan Force 3D
- *
- *  Copyright (c) 2002-2004 Johann Deneux
- *  Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <johann.deneux@it.uu.se>
- */
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct dev_type {
-       u16 idVendor;
-       u16 idProduct;
-       const signed short *ff;
-};
-
-static const signed short ff_rumble[] = {
-       FF_RUMBLE,
-       -1
-};
-
-static const signed short ff_joystick[] = {
-       FF_CONSTANT,
-       -1
-};
-
-static const struct dev_type devices[] = {
-       { 0x046d, 0xc211, ff_rumble },
-       { 0x046d, 0xc219, ff_rumble },
-       { 0x046d, 0xc283, ff_joystick },
-       { 0x046d, 0xc286, ff_joystick },
-       { 0x046d, 0xc294, ff_joystick },
-       { 0x046d, 0xc295, ff_joystick },
-       { 0x046d, 0xca03, ff_joystick },
-};
-
-static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
-{
-       struct hid_device *hid = input_get_drvdata(dev);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-       int x, y;
-       unsigned int left, right;
-
-#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
-
-       switch (effect->type) {
-       case FF_CONSTANT:
-               x = effect->u.ramp.start_level + 0x7f;  /* 0x7f is center */
-               y = effect->u.ramp.end_level + 0x7f;
-               CLAMP(x);
-               CLAMP(y);
-               report->field[0]->value[0] = 0x51;
-               report->field[0]->value[1] = 0x08;
-               report->field[0]->value[2] = x;
-               report->field[0]->value[3] = y;
-               dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
-               break;
-
-       case FF_RUMBLE:
-               right = effect->u.rumble.strong_magnitude;
-               left = effect->u.rumble.weak_magnitude;
-               right = right * 0xff / 0xffff;
-               left = left * 0xff / 0xffff;
-               CLAMP(left);
-               CLAMP(right);
-               report->field[0]->value[0] = 0x42;
-               report->field[0]->value[1] = 0x00;
-               report->field[0]->value[2] = left;
-               report->field[0]->value[3] = right;
-               dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
-               break;
-       }
-       return 0;
-}
-
-int hid_lgff_init(struct hid_device* hid)
-{
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
-       struct hid_report *report;
-       struct hid_field *field;
-       const signed short *ff_bits = ff_joystick;
-       int error;
-       int i;
-
-       /* Find the report to use */
-       if (list_empty(report_list)) {
-               err_hid("No output report found");
-               return -1;
-       }
-
-       /* Check that the report looks ok */
-       report = list_entry(report_list->next, struct hid_report, list);
-       if (!report) {
-               err_hid("NULL output report");
-               return -1;
-       }
-
-       field = report->field[0];
-       if (!field) {
-               err_hid("NULL field");
-               return -1;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(devices); i++) {
-               if (dev->id.vendor == devices[i].idVendor &&
-                   dev->id.product == devices[i].idProduct) {
-                       ff_bits = devices[i].ff;
-                       break;
-               }
-       }
-
-       for (i = 0; ff_bits[i] >= 0; i++)
-               set_bit(ff_bits[i], dev->ffbit);
-
-       error = input_ff_create_memless(dev, NULL, hid_lgff_play);
-       if (error)
-               return error;
-
-       printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
-
-       return 0;
-}
index 011326178c0670c5b5e680a47d741661101a45aa..484e3eec2f88be2b740536fdae06cdc2e60dbc65 100644 (file)
@@ -397,7 +397,6 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
                          effect->u.condition[i].left_saturation);
                pidff_set(&pidff->set_condition[PID_DEAD_BAND],
                          effect->u.condition[i].deadband);
-               usbhid_wait_io(pidff->hid);
                usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
                                  USB_DIR_OUT);
        }
@@ -512,7 +511,6 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
                pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
        }
 
-       usbhid_wait_io(pidff->hid);
        usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
                          USB_DIR_OUT);
 }
@@ -548,6 +546,9 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
        int pid_id = pidff->pid_id[effect_id];
 
        debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]);
+       /* Wait for the queue to clear. We do not want a full fifo to
+          prevent the effect removal. */
+       usbhid_wait_io(pidff->hid);
        pidff_playback_pid(pidff, pid_id, 0);
        pidff_erase_pid(pidff, pid_id);
 
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c
deleted file mode 100644 (file)
index 9eb83cf..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- *  Force feedback support for PantherLord/GreenAsia based devices
- *
- *  The devices are distributed under various names and the same USB device ID
- *  can be used in both adapters and actual game controllers.
- *
- *  0810:0001 "Twin USB Joystick"
- *   - tested with PantherLord USB/PS2 2in1 Adapter
- *   - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT)
- *
- *  0e8f:0003 "GreenAsia Inc.    USB Joystick     "
- *   - tested with Köng Gaming gamepad
- *
- *  Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct plff_device {
-       struct hid_report *report;
-};
-
-static int hid_plff_play(struct input_dev *dev, void *data,
-                        struct ff_effect *effect)
-{
-       struct hid_device *hid = input_get_drvdata(dev);
-       struct plff_device *plff = data;
-       int left, right;
-
-       left = effect->u.rumble.strong_magnitude;
-       right = effect->u.rumble.weak_magnitude;
-       debug("called with 0x%04x 0x%04x", left, right);
-
-       left = left * 0x7f / 0xffff;
-       right = right * 0x7f / 0xffff;
-
-       plff->report->field[0]->value[2] = left;
-       plff->report->field[0]->value[3] = right;
-       debug("running with 0x%02x 0x%02x", left, right);
-       usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
-
-       return 0;
-}
-
-int hid_plff_init(struct hid_device *hid)
-{
-       struct plff_device *plff;
-       struct hid_report *report;
-       struct hid_input *hidinput;
-       struct list_head *report_list =
-                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct list_head *report_ptr = report_list;
-       struct input_dev *dev;
-       int error;
-
-       /* The device contains one output report per physical device, all
-          containing 1 field, which contains 4 ff00.0002 usages and 4 16bit
-          absolute values.
-
-          The input reports also contain a field which contains
-          8 ff00.0001 usages and 8 boolean values. Their meaning is
-          currently unknown. */
-
-       if (list_empty(report_list)) {
-               printk(KERN_ERR "hid-plff: no output reports found\n");
-               return -ENODEV;
-       }
-
-       list_for_each_entry(hidinput, &hid->inputs, list) {
-
-               report_ptr = report_ptr->next;
-
-               if (report_ptr == report_list) {
-                       printk(KERN_ERR "hid-plff: required output report is missing\n");
-                       return -ENODEV;
-               }
-
-               report = list_entry(report_ptr, struct hid_report, list);
-               if (report->maxfield < 1) {
-                       printk(KERN_ERR "hid-plff: no fields in the report\n");
-                       return -ENODEV;
-               }
-
-               if (report->field[0]->report_count < 4) {
-                       printk(KERN_ERR "hid-plff: not enough values in the field\n");
-                       return -ENODEV;
-               }
-
-               plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
-               if (!plff)
-                       return -ENOMEM;
-
-               dev = hidinput->input;
-
-               set_bit(FF_RUMBLE, dev->ffbit);
-
-               error = input_ff_create_memless(dev, plff, hid_plff_play);
-               if (error) {
-                       kfree(plff);
-                       return error;
-               }
-
-               plff->report = report;
-               plff->report->field[0]->value[0] = 0x00;
-               plff->report->field[0]->value[1] = 0x00;
-               plff->report->field[0]->value[2] = 0x00;
-               plff->report->field[0]->value[3] = 0x00;
-               usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
-       }
-
-       printk(KERN_INFO "hid-plff: Force feedback for PantherLord/GreenAsia "
-              "devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-       return 0;
-}
index b15f882496394cbf7af43d7b07707e6b4750c54e..47ebe045f9b5a1548010a5d19694e4c91dbee9cc 100644 (file)
 
 #include <linux/hid.h>
 
-#define USB_VENDOR_ID_A4TECH           0x09da
-#define USB_DEVICE_ID_A4TECH_WCP32PU   0x0006
-#define USB_DEVICE_ID_A4TECH_X5_005D   0x000a
-
-#define USB_VENDOR_ID_AASHIMA          0x06d6
-#define USB_DEVICE_ID_AASHIMA_GAMEPAD  0x0025
-#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
-
-#define USB_VENDOR_ID_ACECAD           0x0460
-#define USB_DEVICE_ID_ACECAD_FLAIR     0x0004
-#define USB_DEVICE_ID_ACECAD_302       0x0008
-
-#define USB_VENDOR_ID_ADS_TECH                 0x06e1
-#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X    0xa155
-
-#define USB_VENDOR_ID_AFATECH          0x15a4
-#define USB_DEVICE_ID_AFATECH_AF9016   0x9016
-
-#define USB_VENDOR_ID_AIPTEK           0x08ca
-#define USB_DEVICE_ID_AIPTEK_01                0x0001
-#define USB_DEVICE_ID_AIPTEK_10                0x0010
-#define USB_DEVICE_ID_AIPTEK_20                0x0020
-#define USB_DEVICE_ID_AIPTEK_21                0x0021
-#define USB_DEVICE_ID_AIPTEK_22                0x0022
-#define USB_DEVICE_ID_AIPTEK_23                0x0023
-#define USB_DEVICE_ID_AIPTEK_24                0x0024
-
-#define USB_VENDOR_ID_AIRCABLE         0x16CA
-#define USB_DEVICE_ID_AIRCABLE1                0x1502
-
-#define USB_VENDOR_ID_ALCOR            0x058f
-#define USB_DEVICE_ID_ALCOR_USBRS232   0x9720
-
-#define USB_VENDOR_ID_ALPS             0x0433
-#define USB_DEVICE_ID_IBM_GAMEPAD      0x1101
-
-#define USB_VENDOR_ID_APPLE            0x05ac
-#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE        0x0304
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI      0x020e
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO       0x020f
-#define USB_DEVICE_ID_APPLE_GEYSER_ANSI        0x0214
-#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
-#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
-#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI       0x0217
-#define USB_DEVICE_ID_APPLE_GEYSER3_ISO        0x0218
-#define USB_DEVICE_ID_APPLE_GEYSER3_JIS        0x0219
-#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI       0x021a
-#define USB_DEVICE_ID_APPLE_GEYSER4_ISO        0x021b
-#define USB_DEVICE_ID_APPLE_GEYSER4_JIS        0x021c
-#define USB_DEVICE_ID_APPLE_ALU_ANSI   0x0220
-#define USB_DEVICE_ID_APPLE_ALU_ISO    0x0221
-#define USB_DEVICE_ID_APPLE_ALU_JIS    0x0222
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI    0x0223
-#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO     0x0224
-#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS     0x0225
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI    0x0229
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO     0x022a
-#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS     0x022b
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI  0x022c
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO   0x022d
-#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS   0x022e
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI   0x0230
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO    0x0231
-#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS    0x0232
-#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
-#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
-#define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
-
-#define USB_VENDOR_ID_ASUS             0x0b05
-#define USB_DEVICE_ID_ASUS_LCM         0x1726
-
-#define USB_VENDOR_ID_ATEN             0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
-#define USB_DEVICE_ID_ATEN_CS124U      0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC   0x2208
-
-#define USB_VENDOR_ID_BELKIN           0x050d
-#define USB_DEVICE_ID_FLIP_KVM         0x3201
-
-#define USB_VENDOR_ID_BERKSHIRE                0x0c98
-#define USB_DEVICE_ID_BERKSHIRE_PCWD   0x1140
-
-#define USB_VENDOR_ID_CHERRY           0x046a
-#define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
-
-#define USB_VENDOR_ID_CHIC             0x05fe
-#define USB_DEVICE_ID_CHIC_GAMEPAD     0x0014
-
-#define USB_VENDOR_ID_CIDC             0x1677
-
-#define USB_VENDOR_ID_CMEDIA           0x0d8c
-#define USB_DEVICE_ID_CM109            0x000e
-
-#define USB_VENDOR_ID_CODEMERCS                0x07c0
-#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST      0x1500
-#define USB_DEVICE_ID_CODEMERCS_IOW_LAST       0x15ff
-
-#define USB_VENDOR_ID_CYGNAL           0x10c4
-#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X      0x818a
-
-#define USB_VENDOR_ID_CYPRESS          0x04b4
-#define USB_DEVICE_ID_CYPRESS_MOUSE    0x0001
-#define USB_DEVICE_ID_CYPRESS_HIDCOM   0x5500
-#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE       0x7417
-#define USB_DEVICE_ID_CYPRESS_BARCODE_1        0xde61
-#define USB_DEVICE_ID_CYPRESS_BARCODE_2        0xde64
-
-#define USB_VENDOR_ID_DELL             0x413c
-#define USB_DEVICE_ID_DELL_W7658       0x2005
-
-#define USB_VENDOR_ID_DELORME          0x1163
-#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
-#define USB_DEVICE_ID_DELORME_EM_LT20  0x0200
-
-#define USB_VENDOR_ID_DMI              0x0c0b
-#define USB_DEVICE_ID_DMI_ENC          0x5fab
-
-#define USB_VENDOR_ID_ELO              0x04E7
-#define USB_DEVICE_ID_ELO_TS2700       0x0020
-
-#define USB_VENDOR_ID_ESSENTIAL_REALITY        0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
-
-#define USB_VENDOR_ID_EZKEY            0x0518
-#define USB_DEVICE_ID_BTC_8193         0x0002
-
-#define USB_VENDOR_ID_GAMERON          0x0810
-#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
-
-#define USB_VENDOR_ID_GENERAL_TOUCH    0x0dfc
-
-#define USB_VENDOR_ID_GLAB             0x06c2
-#define USB_DEVICE_ID_4_PHIDGETSERVO_30        0x0038
-#define USB_DEVICE_ID_1_PHIDGETSERVO_30        0x0039
-#define USB_DEVICE_ID_0_0_4_IF_KIT     0x0040
-#define USB_DEVICE_ID_0_16_16_IF_KIT   0x0044
-#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
-#define USB_DEVICE_ID_0_8_7_IF_KIT     0x0051
-#define USB_DEVICE_ID_0_8_8_IF_KIT     0x0053
-#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL     0x0058
-
-#define USB_VENDOR_ID_GOTOP            0x08f2
-#define USB_DEVICE_ID_SUPER_Q2         0x007f
-#define USB_DEVICE_ID_GOGOPEN          0x00ce
-#define USB_DEVICE_ID_PENPOWER         0x00f4
-
-#define USB_VENDOR_ID_GRETAGMACBETH    0x0971
-#define USB_DEVICE_ID_GRETAGMACBETH_HUEY       0x2005
-
-#define USB_VENDOR_ID_GRIFFIN          0x077d
-#define USB_DEVICE_ID_POWERMATE                0x0410
-#define USB_DEVICE_ID_SOUNDKNOB                0x04AA
-
-#define USB_VENDOR_ID_GTCO             0x078c
-#define USB_DEVICE_ID_GTCO_90          0x0090
-#define USB_DEVICE_ID_GTCO_100         0x0100
-#define USB_DEVICE_ID_GTCO_101         0x0101
-#define USB_DEVICE_ID_GTCO_103         0x0103
-#define USB_DEVICE_ID_GTCO_104         0x0104
-#define USB_DEVICE_ID_GTCO_105         0x0105
-#define USB_DEVICE_ID_GTCO_106         0x0106
-#define USB_DEVICE_ID_GTCO_107         0x0107
-#define USB_DEVICE_ID_GTCO_108         0x0108
-#define USB_DEVICE_ID_GTCO_200         0x0200
-#define USB_DEVICE_ID_GTCO_201         0x0201
-#define USB_DEVICE_ID_GTCO_202         0x0202
-#define USB_DEVICE_ID_GTCO_203         0x0203
-#define USB_DEVICE_ID_GTCO_204         0x0204
-#define USB_DEVICE_ID_GTCO_205         0x0205
-#define USB_DEVICE_ID_GTCO_206         0x0206
-#define USB_DEVICE_ID_GTCO_207         0x0207
-#define USB_DEVICE_ID_GTCO_300         0x0300
-#define USB_DEVICE_ID_GTCO_301         0x0301
-#define USB_DEVICE_ID_GTCO_302         0x0302
-#define USB_DEVICE_ID_GTCO_303         0x0303
-#define USB_DEVICE_ID_GTCO_304         0x0304
-#define USB_DEVICE_ID_GTCO_305         0x0305
-#define USB_DEVICE_ID_GTCO_306         0x0306
-#define USB_DEVICE_ID_GTCO_307         0x0307
-#define USB_DEVICE_ID_GTCO_308         0x0308
-#define USB_DEVICE_ID_GTCO_309         0x0309
-#define USB_DEVICE_ID_GTCO_400         0x0400
-#define USB_DEVICE_ID_GTCO_401         0x0401
-#define USB_DEVICE_ID_GTCO_402         0x0402
-#define USB_DEVICE_ID_GTCO_403         0x0403
-#define USB_DEVICE_ID_GTCO_404         0x0404
-#define USB_DEVICE_ID_GTCO_405         0x0405
-#define USB_DEVICE_ID_GTCO_500         0x0500
-#define USB_DEVICE_ID_GTCO_501         0x0501
-#define USB_DEVICE_ID_GTCO_502         0x0502
-#define USB_DEVICE_ID_GTCO_503         0x0503
-#define USB_DEVICE_ID_GTCO_504         0x0504
-#define USB_DEVICE_ID_GTCO_1000                0x1000
-#define USB_DEVICE_ID_GTCO_1001                0x1001
-#define USB_DEVICE_ID_GTCO_1002                0x1002
-#define USB_DEVICE_ID_GTCO_1003                0x1003
-#define USB_DEVICE_ID_GTCO_1004                0x1004
-#define USB_DEVICE_ID_GTCO_1005                0x1005
-#define USB_DEVICE_ID_GTCO_1006                0x1006
-#define USB_DEVICE_ID_GTCO_1007                0x1007
-#define USB_VENDOR_ID_HAPP             0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING     0x0010
-#define USB_DEVICE_ID_UGCI_FLYING      0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
-
-#define USB_VENDOR_ID_IMATION          0x0718
-#define USB_DEVICE_ID_DISC_STAKKA      0xd000
-
-#define USB_VENDOR_ID_KBGEAR           0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
-
-#define USB_VENDOR_ID_LD               0x0f11
-#define USB_DEVICE_ID_LD_CASSY         0x1000
-#define USB_DEVICE_ID_LD_POCKETCASSY   0x1010
-#define USB_DEVICE_ID_LD_MOBILECASSY   0x1020
-#define USB_DEVICE_ID_LD_JWM           0x1080
-#define USB_DEVICE_ID_LD_DMMP          0x1081
-#define USB_DEVICE_ID_LD_UMIP          0x1090
-#define USB_DEVICE_ID_LD_XRAY1         0x1100
-#define USB_DEVICE_ID_LD_XRAY2         0x1101
-#define USB_DEVICE_ID_LD_VIDEOCOM      0x1200
-#define USB_DEVICE_ID_LD_COM3LAB       0x2000
-#define USB_DEVICE_ID_LD_TELEPORT      0x2010
-#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
-#define USB_DEVICE_ID_LD_POWERCONTROL  0x2030
-#define USB_DEVICE_ID_LD_MACHINETEST   0x2040
-
-#define USB_VENDOR_ID_LOGITECH         0x046d
-#define USB_DEVICE_ID_LOGITECH_LX3     0xc044
-#define USB_DEVICE_ID_LOGITECH_V150    0xc047
-#define USB_DEVICE_ID_LOGITECH_RECEIVER        0xc101
-#define USB_DEVICE_ID_LOGITECH_HARMONY  0xc110
-#define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
-#define USB_DEVICE_ID_LOGITECH_HARMONY_3 0xc112
-#define USB_DEVICE_ID_LOGITECH_HARMONY_4 0xc113
-#define USB_DEVICE_ID_LOGITECH_HARMONY_5 0xc114
-#define USB_DEVICE_ID_LOGITECH_HARMONY_6 0xc115
-#define USB_DEVICE_ID_LOGITECH_HARMONY_7 0xc116
-#define USB_DEVICE_ID_LOGITECH_HARMONY_8 0xc117
-#define USB_DEVICE_ID_LOGITECH_HARMONY_9 0xc118
-#define USB_DEVICE_ID_LOGITECH_HARMONY_10 0xc119
-#define USB_DEVICE_ID_LOGITECH_HARMONY_11 0xc11a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_12 0xc11b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_13 0xc11c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_14 0xc11d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_15 0xc11e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_16 0xc11f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_17 0xc120
-#define USB_DEVICE_ID_LOGITECH_HARMONY_18 0xc121
-#define USB_DEVICE_ID_LOGITECH_HARMONY_19 0xc122
-#define USB_DEVICE_ID_LOGITECH_HARMONY_20 0xc123
-#define USB_DEVICE_ID_LOGITECH_HARMONY_21 0xc124
-#define USB_DEVICE_ID_LOGITECH_HARMONY_22 0xc125
-#define USB_DEVICE_ID_LOGITECH_HARMONY_23 0xc126
-#define USB_DEVICE_ID_LOGITECH_HARMONY_24 0xc127
-#define USB_DEVICE_ID_LOGITECH_HARMONY_25 0xc128
-#define USB_DEVICE_ID_LOGITECH_HARMONY_26 0xc129
-#define USB_DEVICE_ID_LOGITECH_HARMONY_27 0xc12a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_28 0xc12b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_29 0xc12c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_30 0xc12d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_31 0xc12e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_32 0xc12f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_33 0xc130
-#define USB_DEVICE_ID_LOGITECH_HARMONY_34 0xc131
-#define USB_DEVICE_ID_LOGITECH_HARMONY_35 0xc132
-#define USB_DEVICE_ID_LOGITECH_HARMONY_36 0xc133
-#define USB_DEVICE_ID_LOGITECH_HARMONY_37 0xc134
-#define USB_DEVICE_ID_LOGITECH_HARMONY_38 0xc135
-#define USB_DEVICE_ID_LOGITECH_HARMONY_39 0xc136
-#define USB_DEVICE_ID_LOGITECH_HARMONY_40 0xc137
-#define USB_DEVICE_ID_LOGITECH_HARMONY_41 0xc138
-#define USB_DEVICE_ID_LOGITECH_HARMONY_42 0xc139
-#define USB_DEVICE_ID_LOGITECH_HARMONY_43 0xc13a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_44 0xc13b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_45 0xc13c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_46 0xc13d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_47 0xc13e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_48 0xc13f
-#define USB_DEVICE_ID_LOGITECH_HARMONY_49 0xc140
-#define USB_DEVICE_ID_LOGITECH_HARMONY_50 0xc141
-#define USB_DEVICE_ID_LOGITECH_HARMONY_51 0xc142
-#define USB_DEVICE_ID_LOGITECH_HARMONY_52 0xc143
-#define USB_DEVICE_ID_LOGITECH_HARMONY_53 0xc144
-#define USB_DEVICE_ID_LOGITECH_HARMONY_54 0xc145
-#define USB_DEVICE_ID_LOGITECH_HARMONY_55 0xc146
-#define USB_DEVICE_ID_LOGITECH_HARMONY_56 0xc147
-#define USB_DEVICE_ID_LOGITECH_HARMONY_57 0xc148
-#define USB_DEVICE_ID_LOGITECH_HARMONY_58 0xc149
-#define USB_DEVICE_ID_LOGITECH_HARMONY_59 0xc14a
-#define USB_DEVICE_ID_LOGITECH_HARMONY_60 0xc14b
-#define USB_DEVICE_ID_LOGITECH_HARMONY_61 0xc14c
-#define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
-#define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
-#define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
-#define USB_DEVICE_ID_LOGITECH_EXTREME_3D      0xc215
-#define USB_DEVICE_ID_LOGITECH_WHEEL   0xc294
-#define USB_DEVICE_ID_LOGITECH_ELITE_KBD       0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD     0xc311
-#define USB_DEVICE_ID_S510_RECEIVER    0xc50c
-#define USB_DEVICE_ID_S510_RECEIVER_2  0xc517
-#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500  0xc512
-#define USB_DEVICE_ID_MX3000_RECEIVER  0xc513
-#define USB_DEVICE_ID_DINOVO_DESKTOP   0xc704
-#define USB_DEVICE_ID_DINOVO_EDGE      0xc714
-#define USB_DEVICE_ID_DINOVO_MINI      0xc71f
-
-#define USB_VENDOR_ID_MCC              0x09db
-#define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
-#define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
-
-#define USB_VENDOR_ID_MGE              0x0463
-#define USB_DEVICE_ID_MGE_UPS          0xffff
-#define USB_DEVICE_ID_MGE_UPS1         0x0001
-
-#define USB_VENDOR_ID_MICROCHIP                0x04d8
-#define USB_DEVICE_ID_PICKIT1          0x0032
-#define USB_DEVICE_ID_PICKIT2          0x0033
-
-#define USB_VENDOR_ID_MICROSOFT                0x045e
-#define USB_DEVICE_ID_SIDEWINDER_GV    0x003b
-#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
-#define USB_DEVICE_ID_DESKTOP_RECV_1028 0x00f9
-#define USB_DEVICE_ID_MS_NE4K          0x00db
-#define USB_DEVICE_ID_MS_LK6K          0x00f9
-
-#define USB_VENDOR_ID_MONTEREY         0x0566
-#define USB_DEVICE_ID_GENIUS_KB29E     0x3004
-
-#define USB_VENDOR_ID_NCR              0x0404
-#define USB_DEVICE_ID_NCR_FIRST                0x0300
-#define USB_DEVICE_ID_NCR_LAST         0x03ff
-
-#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
-#define USB_DEVICE_ID_N_S_HARMONY       0xc359
-
-#define USB_VENDOR_ID_NATSU             0x08b7
-#define USB_DEVICE_ID_NATSU_GAMEPAD     0x0001
-
-#define USB_VENDOR_ID_NEC              0x073e
-#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
-
-#define USB_VENDOR_ID_ONTRAK           0x0a07
-#define USB_DEVICE_ID_ONTRAK_ADU100    0x0064
-
-#define USB_VENDOR_ID_PANJIT           0x134c
-
-#define USB_VENDOR_ID_PANTHERLORD      0x0810
-#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK    0x0001
-
-#define USB_VENDOR_ID_PETALYNX         0x18b1
-#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE   0x0037
-
-#define USB_VENDOR_ID_PLAYDOTCOM       0x0b43
-#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII     0x0003
-
-#define USB_VENDOR_ID_SAITEK           0x06a3
-#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
-
-#define USB_VENDOR_ID_SAMSUNG          0x0419
-#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE        0x0001
-
-#define USB_VENDOR_ID_SONY                     0x054c
-#define USB_DEVICE_ID_SONY_PS3_CONTROLLER      0x0268
-
-#define USB_VENDOR_ID_SOUNDGRAPH       0x15c2
-#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD      0x0038
-
-#define USB_VENDOR_ID_SUN              0x0430
-#define USB_DEVICE_ID_RARITAN_KVM_DONGLE       0xcdab
-
-#define USB_VENDOR_ID_SUNPLUS          0x04fc
-#define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8
-
-#define USB_VENDOR_ID_TOPMAX           0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
-
-#define USB_VENDOR_ID_TURBOX           0x062a
-#define USB_DEVICE_ID_TURBOX_KEYBOARD  0x0201
-
-#define USB_VENDOR_ID_VERNIER          0x08f7
-#define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
-#define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
-#define USB_DEVICE_ID_VERNIER_SKIP     0x0003
-#define USB_DEVICE_ID_VERNIER_CYCLOPS  0x0004
-#define USB_DEVICE_ID_VERNIER_LCSPEC   0x0006
-
-#define USB_VENDOR_ID_WACOM            0x056a
-
-#define USB_VENDOR_ID_WISEGROUP                0x0925
-#define USB_DEVICE_ID_1_PHIDGETSERVO_20        0x8101
-#define USB_DEVICE_ID_4_PHIDGETSERVO_20        0x8104
-#define USB_DEVICE_ID_8_8_4_IF_KIT     0x8201
-#define USB_DEVICE_ID_QUAD_USB_JOYPAD  0x8800
-#define USB_DEVICE_ID_DUAL_USB_JOYPAD  0x8866
-
-#define USB_VENDOR_ID_WISEGROUP_LTD    0x6677
-#define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802
-
-#define USB_VENDOR_ID_YEALINK          0x6993
-#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
-
-#define USB_VENDOR_ID_KYE              0x0458
-#define USB_DEVICE_ID_KYE_GPEN_560     0x5003
+#include "../hid-ids.h"
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -433,18 +28,10 @@ static const struct hid_blacklist {
        __u16 idProduct;
        __u32 quirks;
 } hid_blacklist[] = {
-
-       { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
-       { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
-
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
-
        { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
-       { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -453,169 +40,11 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
-
        { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL },
 
-       { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
-       { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
-
-       { USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
-
-       { USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
-       { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GENERAL_TOUCH, 0x0001, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GENERAL_TOUCH, 0x0002, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GENERAL_TOUCH, 0x0003, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GENERAL_TOUCH, 0x0004, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
-
-       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
-
-       { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2, HID_QUIRK_IGNORE },
-
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL },
-
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
-
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
-
        { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
        { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
 
-       { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
-
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
@@ -623,144 +52,13 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
        { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN  | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-
-       { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_4, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_5, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_6, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_7, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_8, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_9, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_10, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_11, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_12, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_13, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_14, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_15, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_16, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_17, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_18, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_19, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_20, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_21, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_22, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_23, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_24, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_25, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_26, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_27, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_28, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_29, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_31, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_32, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_33, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_34, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_35, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_36, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_37, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_38, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_39, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_40, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_41, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_42, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_43, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_44, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_45, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_46, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_47, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_48, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_49, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_50, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_51, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_52, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_53, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_54, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_55, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_56, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_57, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_58, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_59, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_60, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_61, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_62, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
-
-       { 0, 0 }
-};
-
-/* Quirks for devices which require report descriptor fixup go here */
-static const struct hid_rdesc_blacklist {
-       __u16 idVendor;
-       __u16 idProduct;
-       __u32 quirks;
-} hid_rdesc_blacklist[] = {
-
-       { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
-
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
-       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
-       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 },
-
-       { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
-
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
-
-       { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
-
-       { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
-
-       { USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP, HID_QUIRK_RDESC_SUNPLUS_WDESKTOP },
-
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
-       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+       { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 
        { 0, 0 }
 };
@@ -974,16 +272,6 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
        u32 quirks = 0;
        const struct hid_blacklist *bl_entry = NULL;
 
-       /* Ignore all Wacom devices */
-       if (idVendor == USB_VENDOR_ID_WACOM)
-               return HID_QUIRK_IGNORE;
-
-       /* ignore all Code Mercenaries IOWarrior devices */
-       if (idVendor == USB_VENDOR_ID_CODEMERCS)
-               if (idProduct >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&
-                               idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
-                       return HID_QUIRK_IGNORE;
-
        /* NCR devices must not be queried for reports */
        if (idVendor == USB_VENDOR_ID_NCR &&
                        idProduct >= USB_DEVICE_ID_NCR_FIRST &&
@@ -1002,221 +290,3 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
 }
 
 EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
-
-/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
-       if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
-               printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
-               rdesc[11] = rdesc[16] = 0xff;
-               rdesc[12] = rdesc[17] = 0x03;
-       }
-}
-
-
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
-       if (rsize >= 90 && rdesc[83] == 0x26
-                       && rdesc[84] == 0x8c
-                       && rdesc[85] == 0x02) {
-               printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
-               rdesc[84] = rdesc[89] = 0x4d;
-               rdesc[85] = rdesc[90] = 0x10;
-       }
-}
-
-static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize)
-{
-       if (rsize >= 107 && rdesc[104] == 0x26
-                        && rdesc[105] == 0x80
-                        && rdesc[106] == 0x03) {
-               printk(KERN_INFO "Fixing up Sunplus Wireless Desktop report descriptor\n");
-               rdesc[105] = rdesc[110] = 0x03;
-               rdesc[106] = rdesc[111] = 0x21;
-       }
-}
-
-/*
- * Samsung IrDA remote controller (reports as Cypress USB Mouse).
- *
- * Vendor specific report #4 has a size of 48 bit,
- * and therefore is not accepted when inspecting the descriptors.
- * As a workaround we reinterpret the report as:
- *   Variable type, count 6, size 8 bit, log. maximum 255
- * The burden to reconstruct the data is moved into user space.
- */
-static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc,
-                                                 int rsize)
-{
-       if (rsize >= 182 && rdesc[175] == 0x25
-                        && rdesc[176] == 0x40
-                        && rdesc[177] == 0x75
-                        && rdesc[178] == 0x30
-                        && rdesc[179] == 0x95
-                        && rdesc[180] == 0x01
-                        && rdesc[182] == 0x40) {
-               printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n");
-               rdesc[176] = 0xff;
-               rdesc[178] = 0x08;
-               rdesc[180] = 0x06;
-               rdesc[182] = 0x42;
-       }
-}
-
-/* Petalynx Maxter Remote has maximum for consumer page set too low */
-static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
-{
-       if (rsize >= 60 && rdesc[39] == 0x2a
-                       && rdesc[40] == 0xf5
-                       && rdesc[41] == 0x00
-                       && rdesc[59] == 0x26
-                       && rdesc[60] == 0xf9
-                       && rdesc[61] == 0x00) {
-               printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
-               rdesc[60] = 0xfa;
-               rdesc[40] = 0xfa;
-       }
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
-       short fixed = 0;
-       int i;
-
-       for (i = 0; i < rsize - 4; i++) {
-               if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
-                       unsigned char tmp;
-
-                       rdesc[i] = 0x19; rdesc[i+2] = 0x29;
-                       tmp = rdesc[i+3];
-                       rdesc[i+3] = rdesc[i+1];
-                       rdesc[i+1] = tmp;
-               }
-       }
-
-       if (fixed)
-               printk(KERN_INFO "Fixing up Cypress report descriptor\n");
-}
-
-/*
- * MacBook JIS keyboard has wrong logical maximum
- */
-static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
-{
-       if (rsize >= 60 && rdesc[53] == 0x65
-                       && rdesc[59] == 0x65) {
-               printk(KERN_INFO "Fixing up MacBook JIS keyboard report descriptor\n");
-               rdesc[53] = rdesc[59] = 0xe7;
-       }
-}
-
-static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
-{
-       if (rsize >= 30 && rdesc[29] == 0x05
-                       && rdesc[30] == 0x09) {
-               printk(KERN_INFO "Fixing up button/consumer in HID report descriptor\n");
-               rdesc[30] = 0x0c;
-       }
-}
-
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has several
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
-static void usbhid_fixup_microsoft_descriptor(unsigned char *rdesc, int rsize)
-{
-       if (rsize == 571 && rdesc[284] == 0x19
-                        && rdesc[286] == 0x2a
-                        && rdesc[304] == 0x19
-                        && rdesc[306] == 0x29
-                        && rdesc[352] == 0x1a
-                        && rdesc[355] == 0x2a
-                        && rdesc[557] == 0x19
-                        && rdesc[559] == 0x29) {
-               printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
-               rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
-               rdesc[352] = 0x36;
-               rdesc[286] = rdesc[355] = 0x46;
-               rdesc[306] = rdesc[559] = 0x45;
-       }
-}
-
-static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
-{
-       if ((quirks & HID_QUIRK_RDESC_CYMOTION))
-               usbhid_fixup_cymotion_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_LOGITECH)
-               usbhid_fixup_logitech_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
-               usbhid_fixup_cypress_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_PETALYNX)
-               usbhid_fixup_petalynx_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
-               usbhid_fixup_macbook_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
-               usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
-               usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_MICROSOFT_RECV_1028)
-               usbhid_fixup_microsoft_descriptor(rdesc, rsize);
-
-       if (quirks & HID_QUIRK_RDESC_SUNPLUS_WDESKTOP)
-               usbhid_fixup_sunplus_wdesktop(rdesc, rsize);
-}
-
-/**
- * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
- *
- * Description:
- *     Walks the hid_rdesc_blacklist[] array and checks whether the device
- *     is known to have broken report descriptor that needs to be fixed up
- *     prior to entering the HID parser
- *
- * Returns: nothing
- */
-void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
-                                   char *rdesc, unsigned rsize, char **quirks_param)
-{
-       int n, m;
-       u16 paramVendor, paramProduct;
-       u32 quirks;
-
-       /* static rdesc quirk entries */
-       for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
-               if (hid_rdesc_blacklist[n].idVendor == idVendor &&
-                               hid_rdesc_blacklist[n].idProduct == idProduct)
-                       __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
-                                       rdesc, rsize);
-
-       /* runtime rdesc quirk entries handling */
-       for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
-               m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
-                               &paramVendor, &paramProduct, &quirks);
-
-               if (m != 3)
-                       printk(KERN_WARNING
-                               "Could not parse HID quirk module param %s\n",
-                               quirks_param[n]);
-               else if (paramVendor == idVendor && paramProduct == idProduct)
-                       __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
-       }
-}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
deleted file mode 100644 (file)
index 144578b..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Force feedback support for various HID compliant devices by ThrustMaster:
- *    ThrustMaster FireStorm Dual Power 2
- * and possibly others whose device ids haven't been added.
- *
- *  Modified to support ThrustMaster devices by Zinx Verituse
- *  on 2003-01-25 from the Logitech force feedback driver,
- *  which is by Johann Deneux.
- *
- *  Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org>
- *  Copyright (c) 2002 Johann Deneux
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/* Usages for thrustmaster devices I know about */
-#define THRUSTMASTER_USAGE_FF  (HID_UP_GENDESK | 0xbb)
-
-struct dev_type {
-       u16 idVendor;
-       u16 idProduct;
-       const signed short *ff;
-};
-
-static const signed short ff_rumble[] = {
-       FF_RUMBLE,
-       -1
-};
-
-static const signed short ff_joystick[] = {
-       FF_CONSTANT,
-       -1
-};
-
-static const struct dev_type devices[] = {
-       { 0x44f, 0xb300, ff_rumble },
-       { 0x44f, 0xb304, ff_rumble },
-       { 0x44f, 0xb651, ff_rumble },   /* FGT Rumble Force Wheel */
-       { 0x44f, 0xb654, ff_joystick }, /* FGT Force Feedback Wheel */
-};
-
-struct tmff_device {
-       struct hid_report *report;
-       struct hid_field *ff_field;
-};
-
-/* Changes values from 0 to 0xffff into values from minimum to maximum */
-static inline int hid_tmff_scale_u16(unsigned int in,
-                               int minimum, int maximum)
-{
-       int ret;
-
-       ret = (in * (maximum - minimum) / 0xffff) + minimum;
-       if (ret < minimum)
-               return minimum;
-       if (ret > maximum)
-               return maximum;
-       return ret;
-}
-
-/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
-static inline int hid_tmff_scale_s8(int in,
-                                   int minimum, int maximum)
-{
-       int ret;
-
-       ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
-       if (ret < minimum)
-               return minimum;
-       if (ret > maximum)
-               return maximum;
-       return ret;
-}
-
-static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
-{
-       struct hid_device *hid = input_get_drvdata(dev);
-       struct tmff_device *tmff = data;
-       struct hid_field *ff_field = tmff->ff_field;
-       int x, y;
-       int left, right;        /* Rumbling */
-
-       switch (effect->type) {
-       case FF_CONSTANT:
-               x = hid_tmff_scale_s8(effect->u.ramp.start_level,
-                                       ff_field->logical_minimum,
-                                       ff_field->logical_maximum);
-               y = hid_tmff_scale_s8(effect->u.ramp.end_level,
-                                       ff_field->logical_minimum,
-                                       ff_field->logical_maximum);
-
-               dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
-               ff_field->value[0] = x;
-               ff_field->value[1] = y;
-               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
-               break;
-
-       case FF_RUMBLE:
-               left = hid_tmff_scale_u16(effect->u.rumble.weak_magnitude,
-                                       ff_field->logical_minimum,
-                                       ff_field->logical_maximum);
-               right = hid_tmff_scale_u16(effect->u.rumble.strong_magnitude,
-                                       ff_field->logical_minimum,
-                                       ff_field->logical_maximum);
-
-               dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
-               ff_field->value[0] = left;
-               ff_field->value[1] = right;
-               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
-               break;
-       }
-       return 0;
-}
-
-int hid_tmff_init(struct hid_device *hid)
-{
-       struct tmff_device *tmff;
-       struct hid_report *report;
-       struct list_head *report_list;
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
-       const signed short *ff_bits = ff_joystick;
-       int error;
-       int i;
-
-       tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
-       if (!tmff)
-               return -ENOMEM;
-
-       /* Find the report to use */
-       report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       list_for_each_entry(report, report_list, list) {
-               int fieldnum;
-
-               for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
-                       struct hid_field *field = report->field[fieldnum];
-
-                       if (field->maxusage <= 0)
-                               continue;
-
-                       switch (field->usage[0].hid) {
-                       case THRUSTMASTER_USAGE_FF:
-                               if (field->report_count < 2) {
-                                       warn("ignoring FF field with report_count < 2");
-                                       continue;
-                               }
-
-                               if (field->logical_maximum == field->logical_minimum) {
-                                       warn("ignoring FF field with logical_maximum == logical_minimum");
-                                       continue;
-                               }
-
-                               if (tmff->report && tmff->report != report) {
-                                       warn("ignoring FF field in other report");
-                                       continue;
-                               }
-
-                               if (tmff->ff_field && tmff->ff_field != field) {
-                                       warn("ignoring duplicate FF field");
-                                       continue;
-                               }
-
-                               tmff->report = report;
-                               tmff->ff_field = field;
-
-                               for (i = 0; i < ARRAY_SIZE(devices); i++) {
-                                       if (input_dev->id.vendor == devices[i].idVendor &&
-                                           input_dev->id.product == devices[i].idProduct) {
-                                               ff_bits = devices[i].ff;
-                                               break;
-                                       }
-                               }
-
-                               for (i = 0; ff_bits[i] >= 0; i++)
-                                       set_bit(ff_bits[i], input_dev->ffbit);
-
-                               break;
-
-                       default:
-                               warn("ignoring unknown output usage %08x", field->usage[0].hid);
-                               continue;
-                       }
-               }
-       }
-
-       if (!tmff->report) {
-               err("cant find FF field in output reports\n");
-               error = -ENODEV;
-               goto fail;
-       }
-
-       error = input_ff_create_memless(input_dev, tmff, hid_tmff_play);
-       if (error)
-               goto fail;
-
-       info("Force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>");
-       return 0;
-
- fail:
-       kfree(tmff);
-       return error;
-}
-
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
deleted file mode 100644 (file)
index 5a68827..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  Force feedback support for Zeroplus based devices
- *
- *  Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-#include "usbhid.h"
-
-struct zpff_device {
-       struct hid_report *report;
-};
-
-static int hid_zpff_play(struct input_dev *dev, void *data,
-                        struct ff_effect *effect)
-{
-       struct hid_device *hid = input_get_drvdata(dev);
-       struct zpff_device *zpff = data;
-       int left, right;
-
-       /*
-        * The following is specified the other way around in the Zeroplus
-        * datasheet but the order below is correct for the XFX Executioner;
-        * however it is possible that the XFX Executioner is an exception
-        */
-
-       left = effect->u.rumble.strong_magnitude;
-       right = effect->u.rumble.weak_magnitude;
-       dbg_hid("called with 0x%04x 0x%04x\n", left, right);
-
-       left = left * 0x7f / 0xffff;
-       right = right * 0x7f / 0xffff;
-
-       zpff->report->field[2]->value[0] = left;
-       zpff->report->field[3]->value[0] = right;
-       dbg_hid("running with 0x%02x 0x%02x\n", left, right);
-       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
-
-       return 0;
-}
-
-int hid_zpff_init(struct hid_device *hid)
-{
-       struct zpff_device *zpff;
-       struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct list_head *report_list =
-                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
-       int error;
-
-       if (list_empty(report_list)) {
-               printk(KERN_ERR "hid-zpff: no output report found\n");
-               return -ENODEV;
-       }
-
-       report = list_entry(report_list->next, struct hid_report, list);
-
-       if (report->maxfield < 4) {
-               printk(KERN_ERR "hid-zpff: not enough fields in report\n");
-               return -ENODEV;
-       }
-
-       zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
-       if (!zpff)
-               return -ENOMEM;
-
-       set_bit(FF_RUMBLE, dev->ffbit);
-
-       error = input_ff_create_memless(dev, zpff, hid_zpff_play);
-       if (error) {
-               kfree(zpff);
-               return error;
-       }
-
-       zpff->report = report;
-       zpff->report->field[0]->value[0] = 0x00;
-       zpff->report->field[1]->value[0] = 0x02;
-       zpff->report->field[2]->value[0] = 0x00;
-       zpff->report->field[3]->value[0] = 0x00;
-       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
-
-       printk(KERN_INFO "Force feedback for Zeroplus based devices by "
-              "Anssi Hannula <anssi.hannula@gmail.com>\n");
-
-       return 0;
-}
index 842e9edb888ed889c27c19fd2ca705c3da38010f..babd65dd46ad4eefa066c4e842288144f2941ab8 100644 (file)
@@ -790,21 +790,23 @@ static struct usb_class_driver hiddev_class = {
 /*
  * This is where hid.c calls us to connect a hid device to the hiddev driver
  */
-int hiddev_connect(struct hid_device *hid)
+int hiddev_connect(struct hid_device *hid, unsigned int force)
 {
        struct hiddev *hiddev;
        struct usbhid_device *usbhid = hid->driver_data;
-       int i;
        int retval;
 
-       for (i = 0; i < hid->maxcollection; i++)
-               if (hid->collection[i].type ==
-                   HID_COLLECTION_APPLICATION &&
-                   !IS_INPUT_APPLICATION(hid->collection[i].usage))
-                       break;
+       if (!force) {
+               unsigned int i;
+               for (i = 0; i < hid->maxcollection; i++)
+                       if (hid->collection[i].type ==
+                           HID_COLLECTION_APPLICATION &&
+                           !IS_INPUT_APPLICATION(hid->collection[i].usage))
+                               break;
 
-       if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
-               return -1;
+               if (i == hid->maxcollection)
+                       return -1;
+       }
 
        if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
                return -1;
index 62d2d7c925bd3d494c6dd4be8a3f6b66c4aa556c..abedb13c623e419b12b8c3cc02cef4a8a977f520 100644 (file)
@@ -67,7 +67,7 @@ struct usbhid_device {
        spinlock_t ctrllock;                                            /* Control fifo spinlock */
 
        struct urb *urbout;                                             /* Output URB */
-       struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
+       struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE];              /* Output pipe fifo */
        unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
        char *outbuf;                                                   /* Output buffer */
        dma_addr_t outbuf_dma;                                          /* Output buffer dma */
@@ -82,7 +82,7 @@ struct usbhid_device {
 };
 
 #define        hid_to_usb_dev(hid_dev) \
-       container_of(hid_dev->dev->parent, struct usb_device, dev)
+       container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
 
 #endif
 
index 0caaafe018438db68b33acc4ac0d695c717d4058..b342926dd7fcbc91d697e4c058a5c0889a265d4b 100644 (file)
@@ -105,14 +105,16 @@ static void usb_kbd_irq(struct urb *urb)
                        if (usb_kbd_keycode[kbd->old[i]])
                                input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
                        else
-                               info("Unknown key (scancode %#x) released.", kbd->old[i]);
+                               dev_info(&urb->dev->dev,
+                                               "Unknown key (scancode %#x) released.\n", kbd->old[i]);
                }
 
                if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
                        if (usb_kbd_keycode[kbd->new[i]])
                                input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
                        else
-                               info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
+                               dev_info(&urb->dev->dev,
+                                               "Unknown key (scancode %#x) released.\n", kbd->new[i]);
                }
        }
 
@@ -159,7 +161,8 @@ static void usb_kbd_led(struct urb *urb)
        struct usb_kbd *kbd = urb->context;
 
        if (urb->status)
-               warn("led urb status %d received", urb->status);
+               dev_warn(&urb->dev->dev, "led urb status %d received\n",
+                        urb->status);
 
        if (*(kbd->leds) == kbd->newleds)
                return;
@@ -352,7 +355,8 @@ static int __init usb_kbd_init(void)
 {
        int result = usb_register(&usb_kbd_driver);
        if (result == 0)
-               info(DRIVER_VERSION ":" DRIVER_DESC);
+               printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+                               DRIVER_DESC "\n");
        return result;
 }
 
index 35689ef172cc5240fdb4a7882ccaf13fbe3913df..72ab4b2680963ca9721a47d6d5dcd86f5dcc4246 100644 (file)
 #include <linux/usb/input.h>
 #include <linux/hid.h>
 
+/* for apple IDs */
+#ifdef CONFIG_USB_HID_MODULE
+#include "../hid-ids.h"
+#endif
+
 /*
  * Version Information
  */
@@ -240,7 +245,8 @@ static int __init usb_mouse_init(void)
 {
        int retval = usb_register(&usb_mouse_driver);
        if (retval == 0)
-               info(DRIVER_VERSION ":" DRIVER_DESC);
+               printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+                               DRIVER_DESC "\n");
        return retval;
 }
 
index a6221e5dd984292613634a6ddf28c775615e6465..221ef6915a5f74ec06a6ab4e7969f17ae3e90d4b 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
 
 enum ams_irq {
        AMS_IRQ_FREEFALL = 0x01,
index cdb8311e4ef730c503d814de22442917595e9c82..27a5d397f9a127f40b4d9eedbac8f3a205444414 100644 (file)
@@ -175,11 +175,11 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
  * Data structures and manipulation thereof
  * --------------------------------------------------------------------- */
 
-/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
-   the driver field to differentiate between I2C and ISA chips. */
 struct dme1737_data {
-       struct i2c_client client;
+       struct i2c_client *client;      /* for I2C devices only */
        struct device *hwmon_dev;
+       const char *name;
+       unsigned int addr;              /* for ISA devices only */
 
        struct mutex update_lock;
        int valid;                      /* !=0 if following fields are valid */
@@ -512,11 +512,12 @@ static inline int PWM_OFF_TO_REG(int val, int ix, int reg)
  * before calling dme1737_read or dme1737_write.
  * --------------------------------------------------------------------- */
 
-static u8 dme1737_read(struct i2c_client *client, u8 reg)
+static u8 dme1737_read(const struct dme1737_data *data, u8 reg)
 {
+       struct i2c_client *client = data->client;
        s32 val;
 
-       if (client->driver) { /* I2C device */
+       if (client) { /* I2C device */
                val = i2c_smbus_read_byte_data(client, reg);
 
                if (val < 0) {
@@ -525,18 +526,19 @@ static u8 dme1737_read(struct i2c_client *client, u8 reg)
                                 "maintainer.\n", reg);
                }
        } else { /* ISA device */
-               outb(reg, client->addr);
-               val = inb(client->addr + 1);
+               outb(reg, data->addr);
+               val = inb(data->addr + 1);
        }
 
        return val;
 }
 
-static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
+static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val)
 {
+       struct i2c_client *client = data->client;
        s32 res = 0;
 
-       if (client->driver) { /* I2C device */
+       if (client) { /* I2C device */
                res = i2c_smbus_write_byte_data(client, reg, val);
 
                if (res < 0) {
@@ -545,8 +547,8 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
                                 "maintainer.\n", reg);
                }
        } else { /* ISA device */
-               outb(reg, client->addr);
-               outb(val, client->addr + 1);
+               outb(reg, data->addr);
+               outb(val, data->addr + 1);
        }
 
        return res;
@@ -555,7 +557,6 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val)
 static struct dme1737_data *dme1737_update_device(struct device *dev)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        int ix;
        u8 lsb[5];
 
@@ -563,7 +564,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 
        /* Enable a Vbat monitoring cycle every 10 mins */
        if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) {
-               dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client,
+               dme1737_write(data, DME1737_REG_CONFIG, dme1737_read(data,
                                                DME1737_REG_CONFIG) | 0x10);
                data->last_vbat = jiffies;
        }
@@ -571,7 +572,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
        /* Sample register contents every 1 sec */
        if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
                if (data->type != sch5027) {
-                       data->vid = dme1737_read(client, DME1737_REG_VID) &
+                       data->vid = dme1737_read(data, DME1737_REG_VID) &
                                0x3f;
                }
 
@@ -580,11 +581,11 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
                        /* Voltage inputs are stored as 16 bit values even
                         * though they have only 12 bits resolution. This is
                         * to make it consistent with the temp inputs. */
-                       data->in[ix] = dme1737_read(client,
+                       data->in[ix] = dme1737_read(data,
                                        DME1737_REG_IN(ix)) << 8;
-                       data->in_min[ix] = dme1737_read(client,
+                       data->in_min[ix] = dme1737_read(data,
                                        DME1737_REG_IN_MIN(ix));
-                       data->in_max[ix] = dme1737_read(client,
+                       data->in_max[ix] = dme1737_read(data,
                                        DME1737_REG_IN_MAX(ix));
                }
 
@@ -595,14 +596,14 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
                         * to take advantage of implicit conversions between
                         * register values (2's complement) and temp values
                         * (signed decimal). */
-                       data->temp[ix] = dme1737_read(client,
+                       data->temp[ix] = dme1737_read(data,
                                        DME1737_REG_TEMP(ix)) << 8;
-                       data->temp_min[ix] = dme1737_read(client,
+                       data->temp_min[ix] = dme1737_read(data,
                                        DME1737_REG_TEMP_MIN(ix));
-                       data->temp_max[ix] = dme1737_read(client,
+                       data->temp_max[ix] = dme1737_read(data,
                                        DME1737_REG_TEMP_MAX(ix));
                        if (data->type != sch5027) {
-                               data->temp_offset[ix] = dme1737_read(client,
+                               data->temp_offset[ix] = dme1737_read(data,
                                                DME1737_REG_TEMP_OFFSET(ix));
                        }
                }
@@ -612,7 +613,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
                 * which the registers are read (MSB first, then LSB) is
                 * important! */
                for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
-                       lsb[ix] = dme1737_read(client,
+                       lsb[ix] = dme1737_read(data,
                                        DME1737_REG_IN_TEMP_LSB(ix));
                }
                for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
@@ -631,19 +632,19 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
                        if (!(data->has_fan & (1 << ix))) {
                                continue;
                        }
-                       data->fan[ix] = dme1737_read(client,
+                       data->fan[ix] = dme1737_read(data,
                                        DME1737_REG_FAN(ix));
-                       data->fan[ix] |= dme1737_read(client,
+                       data->fan[ix] |= dme1737_read(data,
                                        DME1737_REG_FAN(ix) + 1) << 8;
-                       data->fan_min[ix] = dme1737_read(client,
+                       data->fan_min[ix] = dme1737_read(data,
                                        DME1737_REG_FAN_MIN(ix));
-                       data->fan_min[ix] |= dme1737_read(client,
+                       data->fan_min[ix] |= dme1737_read(data,
                                        DME1737_REG_FAN_MIN(ix) + 1) << 8;
-                       data->fan_opt[ix] = dme1737_read(client,
+                       data->fan_opt[ix] = dme1737_read(data,
                                        DME1737_REG_FAN_OPT(ix));
                        /* fan_max exists only for fan[5-6] */
                        if (ix > 3) {
-                               data->fan_max[ix - 4] = dme1737_read(client,
+                               data->fan_max[ix - 4] = dme1737_read(data,
                                        DME1737_REG_FAN_MAX(ix));
                        }
                }
@@ -655,63 +656,63 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
                        if (!(data->has_pwm & (1 << ix))) {
                                continue;
                        }
-                       data->pwm[ix] = dme1737_read(client,
+                       data->pwm[ix] = dme1737_read(data,
                                        DME1737_REG_PWM(ix));
-                       data->pwm_freq[ix] = dme1737_read(client,
+                       data->pwm_freq[ix] = dme1737_read(data,
                                        DME1737_REG_PWM_FREQ(ix));
                        /* pwm_config and pwm_min exist only for pwm[1-3] */
                        if (ix < 3) {
-                               data->pwm_config[ix] = dme1737_read(client,
+                               data->pwm_config[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_CONFIG(ix));
-                               data->pwm_min[ix] = dme1737_read(client,
+                               data->pwm_min[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_MIN(ix));
                        }
                }
                for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) {
-                       data->pwm_rr[ix] = dme1737_read(client,
+                       data->pwm_rr[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_RR(ix));
                }
 
                /* Thermal zone registers */
                for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {
-                       data->zone_low[ix] = dme1737_read(client,
+                       data->zone_low[ix] = dme1737_read(data,
                                        DME1737_REG_ZONE_LOW(ix));
-                       data->zone_abs[ix] = dme1737_read(client,
+                       data->zone_abs[ix] = dme1737_read(data,
                                        DME1737_REG_ZONE_ABS(ix));
                }
                if (data->type != sch5027) {
                        for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {
-                               data->zone_hyst[ix] = dme1737_read(client,
+                               data->zone_hyst[ix] = dme1737_read(data,
                                                DME1737_REG_ZONE_HYST(ix));
                        }
                }
 
                /* Alarm registers */
-               data->alarms = dme1737_read(client,
+               data->alarms = dme1737_read(data,
                                                DME1737_REG_ALARM1);
                /* Bit 7 tells us if the other alarm registers are non-zero and
                 * therefore also need to be read */
                if (data->alarms & 0x80) {
-                       data->alarms |= dme1737_read(client,
+                       data->alarms |= dme1737_read(data,
                                                DME1737_REG_ALARM2) << 8;
-                       data->alarms |= dme1737_read(client,
+                       data->alarms |= dme1737_read(data,
                                                DME1737_REG_ALARM3) << 16;
                }
 
                /* The ISA chips require explicit clearing of alarm bits.
                 * Don't worry, an alarm will come back if the condition
                 * that causes it still exists */
-               if (!client->driver) {
+               if (!data->client) {
                        if (data->alarms & 0xff0000) {
-                               dme1737_write(client, DME1737_REG_ALARM3,
+                               dme1737_write(data, DME1737_REG_ALARM3,
                                              0xff);
                        }
                        if (data->alarms & 0xff00) {
-                               dme1737_write(client, DME1737_REG_ALARM2,
+                               dme1737_write(data, DME1737_REG_ALARM2,
                                              0xff);
                        }
                        if (data->alarms & 0xff) {
-                               dme1737_write(client, DME1737_REG_ALARM1,
+                               dme1737_write(data, DME1737_REG_ALARM1,
                                              0xff);
                        }
                }
@@ -770,7 +771,6 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
                      const char *buf, size_t count)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        struct sensor_device_attribute_2
                *sensor_attr_2 = to_sensor_dev_attr_2(attr);
        int ix = sensor_attr_2->index;
@@ -781,12 +781,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
        switch (fn) {
        case SYS_IN_MIN:
                data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]);
-               dme1737_write(client, DME1737_REG_IN_MIN(ix),
+               dme1737_write(data, DME1737_REG_IN_MIN(ix),
                              data->in_min[ix]);
                break;
        case SYS_IN_MAX:
                data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]);
-               dme1737_write(client, DME1737_REG_IN_MAX(ix),
+               dme1737_write(data, DME1737_REG_IN_MAX(ix),
                              data->in_max[ix]);
                break;
        default:
@@ -850,7 +850,6 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        struct sensor_device_attribute_2
                *sensor_attr_2 = to_sensor_dev_attr_2(attr);
        int ix = sensor_attr_2->index;
@@ -861,17 +860,17 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
        switch (fn) {
        case SYS_TEMP_MIN:
                data->temp_min[ix] = TEMP_TO_REG(val);
-               dme1737_write(client, DME1737_REG_TEMP_MIN(ix),
+               dme1737_write(data, DME1737_REG_TEMP_MIN(ix),
                              data->temp_min[ix]);
                break;
        case SYS_TEMP_MAX:
                data->temp_max[ix] = TEMP_TO_REG(val);
-               dme1737_write(client, DME1737_REG_TEMP_MAX(ix),
+               dme1737_write(data, DME1737_REG_TEMP_MAX(ix),
                              data->temp_max[ix]);
                break;
        case SYS_TEMP_OFFSET:
                data->temp_offset[ix] = TEMP_TO_REG(val);
-               dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix),
+               dme1737_write(data, DME1737_REG_TEMP_OFFSET(ix),
                              data->temp_offset[ix]);
                break;
        default:
@@ -939,7 +938,6 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
                        const char *buf, size_t count)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        struct sensor_device_attribute_2
                *sensor_attr_2 = to_sensor_dev_attr_2(attr);
        int ix = sensor_attr_2->index;
@@ -950,37 +948,37 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
        switch (fn) {
        case SYS_ZONE_AUTO_POINT1_TEMP_HYST:
                /* Refresh the cache */
-               data->zone_low[ix] = dme1737_read(client,
+               data->zone_low[ix] = dme1737_read(data,
                                                  DME1737_REG_ZONE_LOW(ix));
                /* Modify the temp hyst value */
                data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG(
                                        TEMP_FROM_REG(data->zone_low[ix], 8) -
-                                       val, ix, dme1737_read(client,
+                                       val, ix, dme1737_read(data,
                                        DME1737_REG_ZONE_HYST(ix == 2)));
-               dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2),
+               dme1737_write(data, DME1737_REG_ZONE_HYST(ix == 2),
                              data->zone_hyst[ix == 2]);
                break;
        case SYS_ZONE_AUTO_POINT1_TEMP:
                data->zone_low[ix] = TEMP_TO_REG(val);
-               dme1737_write(client, DME1737_REG_ZONE_LOW(ix),
+               dme1737_write(data, DME1737_REG_ZONE_LOW(ix),
                              data->zone_low[ix]);
                break;
        case SYS_ZONE_AUTO_POINT2_TEMP:
                /* Refresh the cache */
-               data->zone_low[ix] = dme1737_read(client,
+               data->zone_low[ix] = dme1737_read(data,
                                                  DME1737_REG_ZONE_LOW(ix));
                /* Modify the temp range value (which is stored in the upper
                 * nibble of the pwm_freq register) */
                data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val -
                                        TEMP_FROM_REG(data->zone_low[ix], 8),
-                                       dme1737_read(client,
+                                       dme1737_read(data,
                                        DME1737_REG_PWM_FREQ(ix)));
-               dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+               dme1737_write(data, DME1737_REG_PWM_FREQ(ix),
                              data->pwm_freq[ix]);
                break;
        case SYS_ZONE_AUTO_POINT3_TEMP:
                data->zone_abs[ix] = TEMP_TO_REG(val);
-               dme1737_write(client, DME1737_REG_ZONE_ABS(ix),
+               dme1737_write(data, DME1737_REG_ZONE_ABS(ix),
                              data->zone_abs[ix]);
                break;
        default:
@@ -1046,7 +1044,6 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
                       const char *buf, size_t count)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        struct sensor_device_attribute_2
                *sensor_attr_2 = to_sensor_dev_attr_2(attr);
        int ix = sensor_attr_2->index;
@@ -1060,21 +1057,21 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
                        data->fan_min[ix] = FAN_TO_REG(val, 0);
                } else {
                        /* Refresh the cache */
-                       data->fan_opt[ix] = dme1737_read(client,
+                       data->fan_opt[ix] = dme1737_read(data,
                                                DME1737_REG_FAN_OPT(ix));
                        /* Modify the fan min value */
                        data->fan_min[ix] = FAN_TO_REG(val,
                                        FAN_TPC_FROM_REG(data->fan_opt[ix]));
                }
-               dme1737_write(client, DME1737_REG_FAN_MIN(ix),
+               dme1737_write(data, DME1737_REG_FAN_MIN(ix),
                              data->fan_min[ix] & 0xff);
-               dme1737_write(client, DME1737_REG_FAN_MIN(ix) + 1,
+               dme1737_write(data, DME1737_REG_FAN_MIN(ix) + 1,
                              data->fan_min[ix] >> 8);
                break;
        case SYS_FAN_MAX:
                /* Only valid for fan[5-6] */
                data->fan_max[ix - 4] = FAN_MAX_TO_REG(val);
-               dme1737_write(client, DME1737_REG_FAN_MAX(ix),
+               dme1737_write(data, DME1737_REG_FAN_MAX(ix),
                              data->fan_max[ix - 4]);
                break;
        case SYS_FAN_TYPE:
@@ -1086,9 +1083,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
                                 val);
                        goto exit;
                }
-               data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(client,
+               data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(data,
                                        DME1737_REG_FAN_OPT(ix)));
-               dme1737_write(client, DME1737_REG_FAN_OPT(ix),
+               dme1737_write(data, DME1737_REG_FAN_OPT(ix),
                              data->fan_opt[ix]);
                break;
        default:
@@ -1185,7 +1182,6 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                       const char *buf, size_t count)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
        struct sensor_device_attribute_2
                *sensor_attr_2 = to_sensor_dev_attr_2(attr);
        int ix = sensor_attr_2->index;
@@ -1196,12 +1192,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
        switch (fn) {
        case SYS_PWM:
                data->pwm[ix] = SENSORS_LIMIT(val, 0, 255);
-               dme1737_write(client, DME1737_REG_PWM(ix), data->pwm[ix]);
+               dme1737_write(data, DME1737_REG_PWM(ix), data->pwm[ix]);
                break;
        case SYS_PWM_FREQ:
-               data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(client,
+               data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(data,
                                                DME1737_REG_PWM_FREQ(ix)));
-               dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+               dme1737_write(data, DME1737_REG_PWM_FREQ(ix),
                              data->pwm_freq[ix]);
                break;
        case SYS_PWM_ENABLE:
@@ -1214,7 +1210,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        goto exit;
                }
                /* Refresh the cache */
-               data->pwm_config[ix] = dme1737_read(client,
+               data->pwm_config[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_CONFIG(ix));
                if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) {
                        /* Bail out if no change */
@@ -1226,14 +1222,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        data->pwm_acz[ix] = PWM_ACZ_FROM_REG(
                                                        data->pwm_config[ix]);
                        /* Save the current ramp rate state and disable it */
-                       data->pwm_rr[ix > 0] = dme1737_read(client,
+                       data->pwm_rr[ix > 0] = dme1737_read(data,
                                                DME1737_REG_PWM_RR(ix > 0));
                        data->pwm_rr_en &= ~(1 << ix);
                        if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) {
                                data->pwm_rr_en |= (1 << ix);
                                data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix,
                                                        data->pwm_rr[ix > 0]);
-                               dme1737_write(client,
+                               dme1737_write(data,
                                              DME1737_REG_PWM_RR(ix > 0),
                                              data->pwm_rr[ix > 0]);
                        }
@@ -1247,14 +1243,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        /* Turn fan fully on */
                        data->pwm_config[ix] = PWM_EN_TO_REG(0,
                                                        data->pwm_config[ix]);
-                       dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+                       dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
                                      data->pwm_config[ix]);
                        break;
                case 1:
                        /* Turn on manual mode */
                        data->pwm_config[ix] = PWM_EN_TO_REG(1,
                                                        data->pwm_config[ix]);
-                       dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+                       dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
                                      data->pwm_config[ix]);
                        /* Change permissions of pwm[ix] to read-writeable */
                        dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix],
@@ -1269,14 +1265,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        data->pwm_config[ix] = PWM_ACZ_TO_REG(
                                                        data->pwm_acz[ix],
                                                        data->pwm_config[ix]);
-                       dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+                       dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
                                      data->pwm_config[ix]);
                        /* Enable PWM ramp rate if previously enabled */
                        if (data->pwm_rr_en & (1 << ix)) {
                                data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix,
-                                               dme1737_read(client,
+                                               dme1737_read(data,
                                                DME1737_REG_PWM_RR(ix > 0)));
-                               dme1737_write(client,
+                               dme1737_write(data,
                                              DME1737_REG_PWM_RR(ix > 0),
                                              data->pwm_rr[ix > 0]);
                        }
@@ -1286,9 +1282,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
        case SYS_PWM_RAMP_RATE:
                /* Only valid for pwm[1-3] */
                /* Refresh the cache */
-               data->pwm_config[ix] = dme1737_read(client,
+               data->pwm_config[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_CONFIG(ix));
-               data->pwm_rr[ix > 0] = dme1737_read(client,
+               data->pwm_rr[ix > 0] = dme1737_read(data,
                                                DME1737_REG_PWM_RR(ix > 0));
                /* Set the ramp rate value */
                if (val > 0) {
@@ -1301,7 +1297,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix,
                                                        data->pwm_rr[ix > 0]);
                }
-               dme1737_write(client, DME1737_REG_PWM_RR(ix > 0),
+               dme1737_write(data, DME1737_REG_PWM_RR(ix > 0),
                              data->pwm_rr[ix > 0]);
                break;
        case SYS_PWM_AUTO_CHANNELS_ZONE:
@@ -1315,14 +1311,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                        goto exit;
                }
                /* Refresh the cache */
-               data->pwm_config[ix] = dme1737_read(client,
+               data->pwm_config[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_CONFIG(ix));
                if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
                        /* PWM is already in auto mode so update the temp
                         * channel assignment */
                        data->pwm_config[ix] = PWM_ACZ_TO_REG(val,
                                                data->pwm_config[ix]);
-                       dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+                       dme1737_write(data, DME1737_REG_PWM_CONFIG(ix),
                                      data->pwm_config[ix]);
                } else {
                        /* PWM is not in auto mode so we save the temp
@@ -1333,7 +1329,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
        case SYS_PWM_AUTO_PWM_MIN:
                /* Only valid for pwm[1-3] */
                /* Refresh the cache */
-               data->pwm_min[ix] = dme1737_read(client,
+               data->pwm_min[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_MIN(ix));
                /* There are only 2 values supported for the auto_pwm_min
                 * value: 0 or auto_point1_pwm. So if the temperature drops
@@ -1341,20 +1337,20 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                 * off or runs at auto_point1_pwm duty-cycle. */
                if (val > ((data->pwm_min[ix] + 1) / 2)) {
                        data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix,
-                                               dme1737_read(client,
+                                               dme1737_read(data,
                                                DME1737_REG_PWM_RR(0)));
                } else {
                        data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix,
-                                               dme1737_read(client,
+                                               dme1737_read(data,
                                                DME1737_REG_PWM_RR(0)));
                }
-               dme1737_write(client, DME1737_REG_PWM_RR(0),
+               dme1737_write(data, DME1737_REG_PWM_RR(0),
                              data->pwm_rr[0]);
                break;
        case SYS_PWM_AUTO_POINT1_PWM:
                /* Only valid for pwm[1-3] */
                data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255);
-               dme1737_write(client, DME1737_REG_PWM_MIN(ix),
+               dme1737_write(data, DME1737_REG_PWM_MIN(ix),
                              data->pwm_min[ix]);
                break;
        default:
@@ -1402,7 +1398,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr,
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
 
-       return sprintf(buf, "%s\n", data->client.name);
+       return sprintf(buf, "%s\n", data->name);
 }
 
 /* ---------------------------------------------------------------------
@@ -1908,7 +1904,7 @@ static void dme1737_remove_files(struct device *dev)
 
        sysfs_remove_group(&dev->kobj, &dme1737_group);
 
-       if (!data->client.driver) {
+       if (!data->client) {
                sysfs_remove_file(&dev->kobj, &dev_attr_name.attr);
        }
 }
@@ -1919,7 +1915,7 @@ static int dme1737_create_files(struct device *dev)
        int err, ix;
 
        /* Create a name attribute for ISA devices */
-       if (!data->client.driver &&
+       if (!data->client &&
            (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) {
                goto exit;
        }
@@ -2013,14 +2009,14 @@ exit:
 static int dme1737_init_device(struct device *dev)
 {
        struct dme1737_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = &data->client;
+       struct i2c_client *client = data->client;
        int ix;
        u8 reg;
 
        /* Point to the right nominal voltages array */
        data->in_nominal = IN_NOMINAL(data->type);
 
-       data->config = dme1737_read(client, DME1737_REG_CONFIG);
+       data->config = dme1737_read(data, DME1737_REG_CONFIG);
        /* Inform if part is not monitoring/started */
        if (!(data->config & 0x01)) {
                if (!force_start) {
@@ -2032,7 +2028,7 @@ static int dme1737_init_device(struct device *dev)
 
                /* Force monitoring */
                data->config |= 0x01;
-               dme1737_write(client, DME1737_REG_CONFIG, data->config);
+               dme1737_write(data, DME1737_REG_CONFIG, data->config);
        }
        /* Inform if part is not ready */
        if (!(data->config & 0x04)) {
@@ -2041,8 +2037,8 @@ static int dme1737_init_device(struct device *dev)
        }
 
        /* Determine which optional fan and pwm features are enabled/present */
-       if (client->driver) {   /* I2C chip */
-               data->config2 = dme1737_read(client, DME1737_REG_CONFIG2);
+       if (client) {   /* I2C chip */
+               data->config2 = dme1737_read(data, DME1737_REG_CONFIG2);
                /* Check if optional fan3 input is enabled */
                if (data->config2 & 0x04) {
                        data->has_fan |= (1 << 2);
@@ -2051,7 +2047,7 @@ static int dme1737_init_device(struct device *dev)
                /* Fan4 and pwm3 are only available if the client's I2C address
                 * is the default 0x2e. Otherwise the I/Os associated with
                 * these functions are used for addr enable/select. */
-               if (data->client.addr == 0x2e) {
+               if (client->addr == 0x2e) {
                        data->has_fan |= (1 << 3);
                        data->has_pwm |= (1 << 2);
                }
@@ -2086,16 +2082,16 @@ static int dme1737_init_device(struct device *dev)
                 (data->has_fan & (1 << 4)) ? "yes" : "no",
                 (data->has_fan & (1 << 5)) ? "yes" : "no");
 
-       reg = dme1737_read(client, DME1737_REG_TACH_PWM);
+       reg = dme1737_read(data, DME1737_REG_TACH_PWM);
        /* Inform if fan-to-pwm mapping differs from the default */
-       if (client->driver && reg != 0xa4) {   /* I2C chip */
+       if (client && reg != 0xa4) {   /* I2C chip */
                dev_warn(dev, "Non-standard fan to pwm mapping: "
                         "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "
                         "fan4->pwm%d. Please report to the driver "
                         "maintainer.\n",
                         (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
                         ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);
-       } else if (!client->driver && reg != 0x24) {   /* ISA chip */
+       } else if (!client && reg != 0x24) {   /* ISA chip */
                dev_warn(dev, "Non-standard fan to pwm mapping: "
                         "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. "
                         "Please report to the driver maintainer.\n",
@@ -2108,7 +2104,7 @@ static int dme1737_init_device(struct device *dev)
         * disabled). */
        if (!(data->config & 0x02)) {
                for (ix = 0; ix < 3; ix++) {
-                       data->pwm_config[ix] = dme1737_read(client,
+                       data->pwm_config[ix] = dme1737_read(data,
                                                DME1737_REG_PWM_CONFIG(ix));
                        if ((data->has_pwm & (1 << ix)) &&
                            (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
@@ -2116,8 +2112,8 @@ static int dme1737_init_device(struct device *dev)
                                         "manual mode.\n", ix + 1);
                                data->pwm_config[ix] = PWM_EN_TO_REG(1,
                                                        data->pwm_config[ix]);
-                               dme1737_write(client, DME1737_REG_PWM(ix), 0);
-                               dme1737_write(client,
+                               dme1737_write(data, DME1737_REG_PWM(ix), 0);
+                               dme1737_write(data,
                                              DME1737_REG_PWM_CONFIG(ix),
                                              data->pwm_config[ix]);
                        }
@@ -2191,37 +2187,24 @@ exit:
        return err;
 }
 
-static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
-                             int kind)
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int dme1737_i2c_detect(struct i2c_client *client, int kind,
+                             struct i2c_board_info *info)
 {
+       struct i2c_adapter *adapter = client->adapter;
+       struct device *dev = &adapter->dev;
        u8 company, verstep = 0;
-       struct i2c_client *client;
-       struct dme1737_data *data;
-       struct device *dev;
-       int err = 0;
        const char *name;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-               goto exit;
-       }
-
-       if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) {
-               err = -ENOMEM;
-               goto exit;
+               return -ENODEV;
        }
 
-       client = &data->client;
-       i2c_set_clientdata(client, data);
-       client->addr = address;
-       client->adapter = adapter;
-       client->driver = &dme1737_i2c_driver;
-       dev = &client->dev;
-
        /* A negative kind means that the driver was loaded with no force
         * parameter (default), so we must identify the chip. */
        if (kind < 0) {
-               company = dme1737_read(client, DME1737_REG_COMPANY);
-               verstep = dme1737_read(client, DME1737_REG_VERSTEP);
+               company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
+               verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
 
                if (company == DME1737_COMPANY_SMSC &&
                    (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
@@ -2230,8 +2213,7 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
                           verstep == SCH5027_VERSTEP) {
                        kind = sch5027;
                } else {
-                       err = -ENODEV;
-                       goto exit_kfree;
+                       return -ENODEV;
                }
        }
 
@@ -2241,32 +2223,44 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
                kind = dme1737;
                name = "dme1737";
        }
-       data->type = kind;
-
-       /* Fill in the remaining client fields and put it into the global
-        * list */
-       strlcpy(client->name, name, I2C_NAME_SIZE);
-       mutex_init(&data->update_lock);
-
-       /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(client))) {
-               goto exit_kfree;
-       }
 
        dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n",
                 kind == sch5027 ? "SCH5027" : "DME1737", client->addr,
                 verstep);
+       strlcpy(info->type, name, I2C_NAME_SIZE);
+
+       return 0;
+}
+
+static int dme1737_i2c_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
+{
+       struct dme1737_data *data;
+       struct device *dev = &client->dev;
+       int err;
+
+       data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL);
+       if (!data) {
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       i2c_set_clientdata(client, data);
+       data->type = id->driver_data;
+       data->client = client;
+       data->name = client->name;
+       mutex_init(&data->update_lock);
 
        /* Initialize the DME1737 chip */
        if ((err = dme1737_init_device(dev))) {
                dev_err(dev, "Failed to initialize device.\n");
-               goto exit_detach;
+               goto exit_kfree;
        }
 
        /* Create sysfs files */
        if ((err = dme1737_create_files(dev))) {
                dev_err(dev, "Failed to create sysfs files.\n");
-               goto exit_detach;
+               goto exit_kfree;
        }
 
        /* Register device */
@@ -2281,45 +2275,40 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,
 
 exit_remove:
        dme1737_remove_files(dev);
-exit_detach:
-       i2c_detach_client(client);
 exit_kfree:
        kfree(data);
 exit:
        return err;
 }
 
-static int dme1737_i2c_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON)) {
-               return 0;
-       }
-
-       return i2c_probe(adapter, &addr_data, dme1737_i2c_detect);
-}
-
-static int dme1737_i2c_detach_client(struct i2c_client *client)
+static int dme1737_i2c_remove(struct i2c_client *client)
 {
        struct dme1737_data *data = i2c_get_clientdata(client);
-       int err;
 
        hwmon_device_unregister(data->hwmon_dev);
        dme1737_remove_files(&client->dev);
 
-       if ((err = i2c_detach_client(client))) {
-               return err;
-       }
-
        kfree(data);
        return 0;
 }
 
+static const struct i2c_device_id dme1737_id[] = {
+       { "dme1737", dme1737 },
+       { "sch5027", sch5027 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, dme1737_id);
+
 static struct i2c_driver dme1737_i2c_driver = {
+       .class = I2C_CLASS_HWMON,
        .driver = {
                .name = "dme1737",
        },
-       .attach_adapter = dme1737_i2c_attach_adapter,
-       .detach_client = dme1737_i2c_detach_client,
+       .probe = dme1737_i2c_probe,
+       .remove = dme1737_i2c_remove,
+       .id_table = dme1737_id,
+       .detect = dme1737_i2c_detect,
+       .address_data = &addr_data,
 };
 
 /* ---------------------------------------------------------------------
@@ -2403,7 +2392,6 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 {
        u8 company, device;
        struct resource *res;
-       struct i2c_client *client;
        struct dme1737_data *data;
        struct device *dev = &pdev->dev;
        int err;
@@ -2422,15 +2410,13 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
                goto exit_release_region;
        }
 
-       client = &data->client;
-       i2c_set_clientdata(client, data);
-       client->addr = res->start;
+       data->addr = res->start;
        platform_set_drvdata(pdev, data);
 
        /* Skip chip detection if module is loaded with force_id parameter */
        if (!force_id) {
-               company = dme1737_read(client, DME1737_REG_COMPANY);
-               device = dme1737_read(client, DME1737_REG_DEVICE);
+               company = dme1737_read(data, DME1737_REG_COMPANY);
+               device = dme1737_read(data, DME1737_REG_DEVICE);
 
                if (!((company == DME1737_COMPANY_SMSC) &&
                      (device == SCH311X_DEVICE))) {
@@ -2441,10 +2427,10 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
        data->type = sch311x;
 
        /* Fill in the remaining client fields and initialize the mutex */
-       strlcpy(client->name, "sch311x", I2C_NAME_SIZE);
+       data->name = "sch311x";
        mutex_init(&data->update_lock);
 
-       dev_info(dev, "Found a SCH311x chip at 0x%04x\n", client->addr);
+       dev_info(dev, "Found a SCH311x chip at 0x%04x\n", data->addr);
 
        /* Initialize the chip */
        if ((err = dme1737_init_device(dev))) {
@@ -2485,7 +2471,7 @@ static int __devexit dme1737_isa_remove(struct platform_device *pdev)
 
        hwmon_device_unregister(data->hwmon_dev);
        dme1737_remove_files(&pdev->dev);
-       release_region(data->client.addr, DME1737_EXTENT);
+       release_region(data->addr, DME1737_EXTENT);
        platform_set_drvdata(pdev, NULL);
        kfree(data);
 
index 7321a88a51128adef8ba40016e03f0648b7e4a97..076a59cdabe9f7a205cedd3883d40416e2e9b9c7 100644 (file)
@@ -55,8 +55,8 @@ again:
                return ERR_PTR(err);
 
        id = id & MAX_ID_MASK;
-       hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
-                                     HWMON_ID_FORMAT, id);
+       hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
+                             HWMON_ID_FORMAT, id);
 
        if (IS_ERR(hwdev)) {
                spin_lock(&idr_lock);
index 6ee997b2817c450b3ac2fae2bf32e5ad035ff5d3..acadbc51fc0f35f6f1b9f261fc909cfffcef5c3a 100644 (file)
@@ -55,7 +55,7 @@ config I2C_AMD756
 
 config I2C_AMD756_S4882
        tristate "SMBus multiplexing on the Tyan S4882"
-       depends on I2C_AMD756 && EXPERIMENTAL
+       depends on I2C_AMD756 && X86 && EXPERIMENTAL
        help
          Enabling this option will add specific SMBus support for the Tyan
          S4882 motherboard.  On this 4-CPU board, the SMBus is multiplexed
@@ -148,7 +148,7 @@ config I2C_NFORCE2
 
 config I2C_NFORCE2_S4985
        tristate "SMBus multiplexing on the Tyan S4985"
-       depends on I2C_NFORCE2 && EXPERIMENTAL
+       depends on I2C_NFORCE2 && X86 && EXPERIMENTAL
        help
          Enabling this option will add specific SMBus support for the Tyan
          S4985 motherboard.  On this 4-CPU board, the SMBus is multiplexed
@@ -209,7 +209,7 @@ config I2C_VIA
          will be called i2c-via.
 
 config I2C_VIAPRO
-       tristate "VIA VT82C596/82C686/82xx and CX700"
+       tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820"
        depends on PCI
        help
          If you say yes to this option, support will be included for the VIA
@@ -223,6 +223,8 @@ config I2C_VIAPRO
            VT8237R/A/S
            VT8251
            CX700
+           VX800
+           VX820
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-viapro.
@@ -330,6 +332,18 @@ config I2C_GPIO
          This is a very simple bitbanging I2C driver utilizing the
          arch-neutral GPIO API to control the SCL and SDA lines.
 
+config I2C_HIGHLANDER
+       tristate "Highlander FPGA SMBus interface"
+       depends on SH_HIGHLANDER
+       help
+         If you say yes to this option, support will be included for
+         the SMBus interface located in the FPGA on various Highlander
+         boards, particularly the R0P7780LC0011RL and R0P7785LC0011RL
+         FPGAs. This is wholly unrelated to the SoC I2C.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-highlander.
+
 config I2C_IBM_IIC
        tristate "IBM PPC 4xx on-chip I2C interface"
        depends on 4xx
index 97dbfa2107fee2fe7b7170219c9aebf552b8381b..0c2c4b26cdf1ff4d5bac686a40a4a306bf0e730f 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI)        += i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)          += i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
 obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
+obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)      += i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
 obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
new file mode 100644 (file)
index 0000000..f4d22ae
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Renesas Solutions Highlander FPGA I2C/SMBus support.
+ *
+ * Supported devices: R0P7780LC0011RL, R0P7785LC0011RL
+ *
+ * Copyright (C) 2008  Paul Mundt
+ * Copyright (C) 2008  Renesas Solutions Corp.
+ * Copyright (C) 2008  Atom Create Engineering Co., Ltd.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License version 2. See the file "COPYING" in the main directory
+ * of this archive for more details.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define SMCR           0x00
+#define SMCR_START     (1 << 0)
+#define SMCR_IRIC      (1 << 1)
+#define SMCR_BBSY      (1 << 2)
+#define SMCR_ACKE      (1 << 3)
+#define SMCR_RST       (1 << 4)
+#define SMCR_IEIC      (1 << 6)
+
+#define SMSMADR                0x02
+
+#define SMMR           0x04
+#define SMMR_MODE0     (1 << 0)
+#define SMMR_MODE1     (1 << 1)
+#define SMMR_CAP       (1 << 3)
+#define SMMR_TMMD      (1 << 4)
+#define SMMR_SP                (1 << 7)
+
+#define SMSADR         0x06
+#define SMTRDR         0x46
+
+struct highlander_i2c_dev {
+       struct device           *dev;
+       void __iomem            *base;
+       struct i2c_adapter      adapter;
+       struct completion       cmd_complete;
+       unsigned long           last_read_time;
+       int                     irq;
+       u8                      *buf;
+       size_t                  buf_len;
+};
+
+static int iic_force_poll, iic_force_normal;
+static int iic_timeout = 1000, iic_read_delay;
+
+static inline void highlander_i2c_irq_enable(struct highlander_i2c_dev *dev)
+{
+       iowrite16(ioread16(dev->base + SMCR) | SMCR_IEIC, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_irq_disable(struct highlander_i2c_dev *dev)
+{
+       iowrite16(ioread16(dev->base + SMCR) & ~SMCR_IEIC, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_start(struct highlander_i2c_dev *dev)
+{
+       iowrite16(ioread16(dev->base + SMCR) | SMCR_START, dev->base + SMCR);
+}
+
+static inline void highlander_i2c_done(struct highlander_i2c_dev *dev)
+{
+       iowrite16(ioread16(dev->base + SMCR) | SMCR_IRIC, dev->base + SMCR);
+}
+
+static void highlander_i2c_setup(struct highlander_i2c_dev *dev)
+{
+       u16 smmr;
+
+       smmr = ioread16(dev->base + SMMR);
+       smmr |= SMMR_TMMD;
+
+       if (iic_force_normal)
+               smmr &= ~SMMR_SP;
+       else
+               smmr |= SMMR_SP;
+
+       iowrite16(smmr, dev->base + SMMR);
+}
+
+static void smbus_write_data(u8 *src, u16 *dst, int len)
+{
+       for (; len > 1; len -= 2) {
+               *dst++ = be16_to_cpup((u16 *)src);
+               src += 2;
+       }
+
+       if (len)
+               *dst = *src << 8;
+}
+
+static void smbus_read_data(u16 *src, u8 *dst, int len)
+{
+       for (; len > 1; len -= 2) {
+               *(u16 *)dst = cpu_to_be16p(src++);
+               dst += 2;
+       }
+
+       if (len)
+               *dst = *src >> 8;
+}
+
+static void highlander_i2c_command(struct highlander_i2c_dev *dev,
+                                  u8 command, int len)
+{
+       unsigned int i;
+       u16 cmd = (command << 8) | command;
+
+       for (i = 0; i < len; i += 2) {
+               if (len - i == 1)
+                       cmd = command << 8;
+               iowrite16(cmd, dev->base + SMSADR + i);
+               dev_dbg(dev->dev, "command data[%x] 0x%04x\n", i/2, cmd);
+       }
+}
+
+static int highlander_i2c_wait_for_bbsy(struct highlander_i2c_dev *dev)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(iic_timeout);
+       while (ioread16(dev->base + SMCR) & SMCR_BBSY) {
+               if (time_after(jiffies, timeout)) {
+                       dev_warn(dev->dev, "timeout waiting for bus ready\n");
+                       return -ETIMEDOUT;
+               }
+
+               msleep(1);
+       }
+
+       return 0;
+}
+
+static int highlander_i2c_reset(struct highlander_i2c_dev *dev)
+{
+       iowrite16(ioread16(dev->base + SMCR) | SMCR_RST, dev->base + SMCR);
+       return highlander_i2c_wait_for_bbsy(dev);
+}
+
+static int highlander_i2c_wait_for_ack(struct highlander_i2c_dev *dev)
+{
+       u16 tmp = ioread16(dev->base + SMCR);
+
+       if ((tmp & (SMCR_IRIC | SMCR_ACKE)) == SMCR_ACKE) {
+               dev_warn(dev->dev, "ack abnormality\n");
+               return highlander_i2c_reset(dev);
+       }
+
+       return 0;
+}
+
+static irqreturn_t highlander_i2c_irq(int irq, void *dev_id)
+{
+       struct highlander_i2c_dev *dev = dev_id;
+
+       highlander_i2c_done(dev);
+       complete(&dev->cmd_complete);
+
+       return IRQ_HANDLED;
+}
+
+static void highlander_i2c_poll(struct highlander_i2c_dev *dev)
+{
+       unsigned long timeout;
+       u16 smcr;
+
+       timeout = jiffies + msecs_to_jiffies(iic_timeout);
+       for (;;) {
+               smcr = ioread16(dev->base + SMCR);
+
+               /*
+                * Don't bother checking ACKE here, this and the reset
+                * are handled in highlander_i2c_wait_xfer_done() when
+                * waiting for the ACK.
+                */
+
+               if (smcr & SMCR_IRIC)
+                       return;
+               if (time_after(jiffies, timeout))
+                       break;
+
+               cpu_relax();
+               cond_resched();
+       }
+
+       dev_err(dev->dev, "polling timed out\n");
+}
+
+static inline int highlander_i2c_wait_xfer_done(struct highlander_i2c_dev *dev)
+{
+       if (dev->irq)
+               wait_for_completion_timeout(&dev->cmd_complete,
+                                         msecs_to_jiffies(iic_timeout));
+       else
+               /* busy looping, the IRQ of champions */
+               highlander_i2c_poll(dev);
+
+       return highlander_i2c_wait_for_ack(dev);
+}
+
+static int highlander_i2c_read(struct highlander_i2c_dev *dev)
+{
+       int i, cnt;
+       u16 data[16];
+
+       if (highlander_i2c_wait_for_bbsy(dev))
+               return -EAGAIN;
+
+       highlander_i2c_start(dev);
+
+       if (highlander_i2c_wait_xfer_done(dev)) {
+               dev_err(dev->dev, "Arbitration loss\n");
+               return -EAGAIN;
+       }
+
+       /*
+        * The R0P7780LC0011RL FPGA needs a significant delay between
+        * data read cycles, otherwise the transciever gets confused and
+        * garbage is returned when the read is subsequently aborted.
+        *
+        * It is not sufficient to wait for BBSY.
+        *
+        * While this generally only applies to the older SH7780-based
+        * Highlanders, the same issue can be observed on SH7785 ones,
+        * albeit less frequently. SH7780-based Highlanders may need
+        * this to be as high as 1000 ms.
+        */
+       if (iic_read_delay && time_before(jiffies, dev->last_read_time +
+                                msecs_to_jiffies(iic_read_delay)))
+               msleep(jiffies_to_msecs((dev->last_read_time +
+                               msecs_to_jiffies(iic_read_delay)) - jiffies));
+
+       cnt = (dev->buf_len + 1) >> 1;
+       for (i = 0; i < cnt; i++) {
+               data[i] = ioread16(dev->base + SMTRDR + (i * sizeof(u16)));
+               dev_dbg(dev->dev, "read data[%x] 0x%04x\n", i, data[i]);
+       }
+
+       smbus_read_data(data, dev->buf, dev->buf_len);
+
+       dev->last_read_time = jiffies;
+
+       return 0;
+}
+
+static int highlander_i2c_write(struct highlander_i2c_dev *dev)
+{
+       int i, cnt;
+       u16 data[16];
+
+       smbus_write_data(dev->buf, data, dev->buf_len);
+
+       cnt = (dev->buf_len + 1) >> 1;
+       for (i = 0; i < cnt; i++) {
+               iowrite16(data[i], dev->base + SMTRDR + (i * sizeof(u16)));
+               dev_dbg(dev->dev, "write data[%x] 0x%04x\n", i, data[i]);
+       }
+
+       if (highlander_i2c_wait_for_bbsy(dev))
+               return -EAGAIN;
+
+       highlander_i2c_start(dev);
+
+       return highlander_i2c_wait_xfer_done(dev);
+}
+
+static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+                                 unsigned short flags, char read_write,
+                                 u8 command, int size,
+                                 union i2c_smbus_data *data)
+{
+       struct highlander_i2c_dev *dev = i2c_get_adapdata(adap);
+       int read = read_write & I2C_SMBUS_READ;
+       u16 tmp;
+
+       init_completion(&dev->cmd_complete);
+
+       dev_dbg(dev->dev, "addr %04x, command %02x, read_write %d, size %d\n",
+               addr, command, read_write, size);
+
+       /*
+        * Set up the buffer and transfer size
+        */
+       switch (size) {
+       case I2C_SMBUS_BYTE_DATA:
+               dev->buf = &data->byte;
+               dev->buf_len = 1;
+               break;
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               dev->buf = &data->block[1];
+               dev->buf_len = data->block[0];
+               break;
+       default:
+               dev_err(dev->dev, "unsupported command %d\n", size);
+               return -EINVAL;
+       }
+
+       /*
+        * Encode the mode setting
+        */
+       tmp = ioread16(dev->base + SMMR);
+       tmp &= ~(SMMR_MODE0 | SMMR_MODE1);
+
+       switch (dev->buf_len) {
+       case 1:
+               /* default */
+               break;
+       case 8:
+               tmp |= SMMR_MODE0;
+               break;
+       case 16:
+               tmp |= SMMR_MODE1;
+               break;
+       case 32:
+               tmp |= (SMMR_MODE0 | SMMR_MODE1);
+               break;
+       default:
+               dev_err(dev->dev, "unsupported xfer size %d\n", dev->buf_len);
+               return -EINVAL;
+       }
+
+       iowrite16(tmp, dev->base + SMMR);
+
+       /* Ensure we're in a sane state */
+       highlander_i2c_done(dev);
+
+       /* Set slave address */
+       iowrite16((addr << 1) | read, dev->base + SMSMADR);
+
+       highlander_i2c_command(dev, command, dev->buf_len);
+
+       if (read)
+               return highlander_i2c_read(dev);
+       else
+               return highlander_i2c_write(dev);
+}
+
+static u32 highlander_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm highlander_i2c_algo = {
+       .smbus_xfer     = highlander_i2c_smbus_xfer,
+       .functionality  = highlander_i2c_func,
+};
+
+static int __devinit highlander_i2c_probe(struct platform_device *pdev)
+{
+       struct highlander_i2c_dev *dev;
+       struct i2c_adapter *adap;
+       struct resource *res;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "no mem resource\n");
+               return -ENODEV;
+       }
+
+       dev = kzalloc(sizeof(struct highlander_i2c_dev), GFP_KERNEL);
+       if (unlikely(!dev))
+               return -ENOMEM;
+
+       dev->base = ioremap_nocache(res->start, res->end - res->start + 1);
+       if (unlikely(!dev->base)) {
+               ret = -ENXIO;
+               goto err;
+       }
+
+       dev->dev = &pdev->dev;
+       platform_set_drvdata(pdev, dev);
+
+       dev->irq = platform_get_irq(pdev, 0);
+       if (iic_force_poll)
+               dev->irq = 0;
+
+       if (dev->irq) {
+               ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED,
+                                 pdev->name, dev);
+               if (unlikely(ret))
+                       goto err_unmap;
+
+               highlander_i2c_irq_enable(dev);
+       } else {
+               dev_notice(&pdev->dev, "no IRQ, using polling mode\n");
+               highlander_i2c_irq_disable(dev);
+       }
+
+       dev->last_read_time = jiffies;  /* initial read jiffies */
+
+       highlander_i2c_setup(dev);
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+       strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name));
+       adap->algo = &highlander_i2c_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->nr = pdev->id;
+
+       /*
+        * Reset the adapter
+        */
+       ret = highlander_i2c_reset(dev);
+       if (unlikely(ret)) {
+               dev_err(&pdev->dev, "controller didn't come up\n");
+               goto err_free_irq;
+       }
+
+       ret = i2c_add_numbered_adapter(adap);
+       if (unlikely(ret)) {
+               dev_err(&pdev->dev, "failure adding adapter\n");
+               goto err_free_irq;
+       }
+
+       return 0;
+
+err_free_irq:
+       if (dev->irq)
+               free_irq(dev->irq, dev);
+err_unmap:
+       iounmap(dev->base);
+err:
+       kfree(dev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return ret;
+}
+
+static int __devexit highlander_i2c_remove(struct platform_device *pdev)
+{
+       struct highlander_i2c_dev *dev = platform_get_drvdata(pdev);
+
+       i2c_del_adapter(&dev->adapter);
+
+       if (dev->irq)
+               free_irq(dev->irq, dev);
+
+       iounmap(dev->base);
+       kfree(dev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver highlander_i2c_driver = {
+       .driver         = {
+               .name   = "i2c-highlander",
+               .owner  = THIS_MODULE,
+       },
+
+       .probe          = highlander_i2c_probe,
+       .remove         = __devexit_p(highlander_i2c_remove),
+};
+
+static int __init highlander_i2c_init(void)
+{
+       return platform_driver_register(&highlander_i2c_driver);
+}
+
+static void __exit highlander_i2c_exit(void)
+{
+       platform_driver_unregister(&highlander_i2c_driver);
+}
+
+module_init(highlander_i2c_init);
+module_exit(highlander_i2c_exit);
+
+MODULE_AUTHOR("Paul Mundt");
+MODULE_DESCRIPTION("Renesas Highlander FPGA I2C/SMBus adapter");
+MODULE_LICENSE("GPL v2");
+
+module_param(iic_force_poll, bool, 0);
+module_param(iic_force_normal, bool, 0);
+module_param(iic_timeout, int, 0);
+module_param(iic_read_delay, int, 0);
+
+MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
+MODULE_PARM_DESC(iic_force_normal,
+                "Force normal mode (100 kHz), default is fast mode (400 kHz)");
+MODULE_PARM_DESC(iic_timeout, "Set timeout value in msecs (default 1000 ms)");
+MODULE_PARM_DESC(iic_read_delay,
+                "Delay between data read cycles (default 0 ms)");
index 27443f073bc97f668dec983ac287e598a763f2d6..a9a45fcc85447575669593d70d9aaf6aaf5a3375 100644 (file)
@@ -312,7 +312,6 @@ static struct i2c_adapter mpc_ops = {
        .name = "MPC adapter",
        .id = I2C_HW_MPC107,
        .algo = &mpc_algo,
-       .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .timeout = 1,
 };
 
index e7eb7bf9ddecc762e088d17f155c5b38818c6a57..608038d64f81e7b6f0856fcad9b2faeae6fa830e 100644 (file)
@@ -589,11 +589,16 @@ omap_i2c_probe(struct platform_device *pdev)
 
        dev->dev = &pdev->dev;
        dev->irq = irq->start;
-       dev->base = (void __iomem *) IO_ADDRESS(mem->start);
+       dev->base = ioremap(mem->start, mem->end - mem->start + 1);
+       if (!dev->base) {
+               r = -ENOMEM;
+               goto err_free_mem;
+       }
+
        platform_set_drvdata(pdev, dev);
 
        if ((r = omap_i2c_get_clocks(dev)) != 0)
-               goto err_free_mem;
+               goto err_iounmap;
 
        omap_i2c_unidle(dev);
 
@@ -640,6 +645,8 @@ err_unuse_clocks:
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
        omap_i2c_idle(dev);
        omap_i2c_put_clocks(dev);
+err_iounmap:
+       iounmap(dev->base);
 err_free_mem:
        platform_set_drvdata(pdev, NULL);
        kfree(dev);
@@ -661,6 +668,7 @@ omap_i2c_remove(struct platform_device *pdev)
        i2c_del_adapter(&dev->adapter);
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
        omap_i2c_put_clocks(dev);
+       iounmap(dev->base);
        kfree(dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, (mem->end - mem->start) + 1);
index c6faf9bdad18d1ddda022243a4de7cc29d83f185..b2b8380f66029f23f238cef943c8006a35aa95dc 100644 (file)
@@ -123,11 +123,6 @@ static struct i2c_adapter parport_adapter = {
 static int __devinit i2c_parport_probe(struct platform_device *pdev)
 {
        int err;
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
-               return -EBUSY;
 
        /* Reset hardware to a sane state (SCL and SDA high) */
        parport_setsda(NULL, 1);
@@ -138,29 +133,19 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev)
 
        parport_adapter.dev.parent = &pdev->dev;
        err = i2c_bit_add_bus(&parport_adapter);
-       if (err) {
+       if (err)
                dev_err(&pdev->dev, "Unable to register with I2C\n");
-               goto exit_region;
-       }
-       return 0;
-
-exit_region:
-       release_region(res->start, res->end - res->start + 1);
        return err;
 }
 
 static int __devexit i2c_parport_remove(struct platform_device *pdev)
 {
-       struct resource *res;
-
        i2c_del_adapter(&parport_adapter);
 
        /* Un-init if needed (power off...) */
        if (adapter_parm[type].init.val)
                line_set(0, &adapter_parm[type].init);
 
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       release_region(res->start, res->end - res->start + 1);
        return 0;
 }
 
@@ -175,12 +160,6 @@ static struct platform_driver i2c_parport_driver = {
 
 static int __init i2c_parport_device_add(u16 address)
 {
-       struct resource res = {
-               .start  = address,
-               .end    = address + 2,
-               .name   = DRVNAME,
-               .flags  = IORESOURCE_IO,
-       };
        int err;
 
        pdev = platform_device_alloc(DRVNAME, -1);
@@ -190,13 +169,6 @@ static int __init i2c_parport_device_add(u16 address)
                goto exit;
        }
 
-       err = platform_device_add_resources(pdev, &res, 1);
-       if (err) {
-               printk(KERN_ERR DRVNAME ": Device resource addition failed "
-                      "(%d)\n", err);
-               goto exit_device_put;
-       }
-
        err = platform_device_add(pdev);
        if (err) {
                printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
@@ -231,13 +203,16 @@ static int __init i2c_parport_init(void)
                base = DEFAULT_BASE;
        }
 
+       if (!request_region(base, 3, DRVNAME))
+               return -EBUSY;
+
         if (!adapter_parm[type].getscl.val)
                parport_algo_data.getscl = NULL;
 
        /* Sets global pdev as a side effect */
        err = i2c_parport_device_add(base);
        if (err)
-               goto exit;
+               goto exit_release;
 
        err = platform_driver_register(&i2c_parport_driver);
        if (err)
@@ -247,7 +222,8 @@ static int __init i2c_parport_init(void)
 
 exit_device:
        platform_device_unregister(pdev);
-exit:
+exit_release:
+       release_region(base, 3);
        return err;
 }
 
@@ -255,6 +231,7 @@ static void __exit i2c_parport_exit(void)
 {
        platform_driver_unregister(&i2c_parport_driver);
        platform_device_unregister(pdev);
+       release_region(base, 3);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
index a119784bae1069bee133d2b5f5f76ba1dd805f63..9eb76268ec782e81da477a2a25f6c849c18fc501 100644 (file)
@@ -36,8 +36,8 @@
 #define DRIVER "i2c-pca-isa"
 #define IO_SIZE 4
 
-static unsigned long base   = 0x330;
-static int irq           = 10;
+static unsigned long base;
+static int irq = -1;
 
 /* Data sheet recommends 59kHz for 100kHz operation due to variation
  * in the actual clock rate */
@@ -107,13 +107,26 @@ static struct i2c_adapter pca_isa_ops = {
        .timeout        = 100,
 };
 
+static int __devinit pca_isa_match(struct device *dev, unsigned int id)
+{
+       int match = base != 0;
+
+       if (match) {
+               if (irq <= -1)
+                       dev_warn(dev, "Using polling mode (specify irq)\n");
+       } else
+               dev_err(dev, "Please specify I/O base\n");
+
+       return match;
+}
+
 static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
 {
        init_waitqueue_head(&pca_wait);
 
        dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
 
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
        if (check_legacy_ioport(base)) {
                dev_err(dev, "I/O address %#08lx is not available\n", base);
                goto out;
@@ -153,7 +166,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pca_isa_ops);
 
-       if (irq > 0) {
+       if (irq > -1) {
                disable_irq(irq);
                free_irq(irq, &pca_isa_ops);
        }
@@ -163,6 +176,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
 }
 
 static struct isa_driver pca_isa_driver = {
+       .match          = pca_isa_match,
        .probe          = pca_isa_probe,
        .remove         = __devexit_p(pca_isa_remove),
        .driver = {
index 862eb352a2d92b9708cdad16adfec687fdc4dece..73dc52e114eb00009d2b87e43250ce03d233ac17 100644 (file)
@@ -36,6 +36,7 @@
    VT8237S            0x3372             yes
    VT8251             0x3287             yes
    CX700              0x8324             yes
+   VX800/VX820        0x8353             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -82,6 +83,7 @@ static unsigned short SMBHSTCFG = 0xD2;
 #define VT596_BYTE             0x04
 #define VT596_BYTE_DATA                0x08
 #define VT596_WORD_DATA                0x0C
+#define VT596_PROC_CALL                0x10
 #define VT596_BLOCK_DATA       0x14
 #define VT596_I2C_BLOCK_DATA   0x34
 
@@ -232,6 +234,12 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
                }
                size = VT596_WORD_DATA;
                break;
+       case I2C_SMBUS_PROC_CALL:
+               outb_p(command, SMBHSTCMD);
+               outb_p(data->word & 0xff, SMBHSTDAT0);
+               outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+               size = VT596_PROC_CALL;
+               break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
                if (!(vt596_features & FEATURE_I2CBLOCK))
                        goto exit_unsupported;
@@ -262,6 +270,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
        if (status)
                return status;
 
+       if (size == VT596_PROC_CALL)
+               read_write = I2C_SMBUS_READ;
+
        if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
                return 0;
 
@@ -271,6 +282,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
                data->byte = inb_p(SMBHSTDAT0);
                break;
        case VT596_WORD_DATA:
+       case VT596_PROC_CALL:
                data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
                break;
        case VT596_I2C_BLOCK_DATA:
@@ -295,7 +307,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
 {
        u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
-           I2C_FUNC_SMBUS_BLOCK_DATA;
+           I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
 
        if (vt596_features & FEATURE_I2CBLOCK)
                func |= I2C_FUNC_SMBUS_I2C_BLOCK;
@@ -396,6 +408,7 @@ found:
 
        switch (pdev->device) {
        case PCI_DEVICE_ID_VIA_CX700:
+       case PCI_DEVICE_ID_VIA_VX800:
        case PCI_DEVICE_ID_VIA_8251:
        case PCI_DEVICE_ID_VIA_8237:
        case PCI_DEVICE_ID_VIA_8237A:
@@ -459,6 +472,8 @@ static struct pci_device_id vt596_ids[] = {
          .driver_data = SMBBA3 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
          .driver_data = SMBBA3 },
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800),
+         .driver_data = SMBBA3 },
        { 0, }
 };
 
index a95cb9465d656949bed4429279a75c35fb547b23..17356827b93d6ad571f08ca75d58bc6b9dec5426 100644 (file)
@@ -172,4 +172,15 @@ config MENELAUS
          and other features that are often used in portable devices like
          cell phones and PDAs.
 
+config MCU_MPC8349EMITX
+       tristate "MPC8349E-mITX MCU driver"
+       depends on I2C && PPC_83xx
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Say Y here to enable soft power-off functionality on the Freescale
+         boards with the MPC8349E-mITX-compatible MCU chips. This driver will
+         also register MCU GPIOs with the generic GPIO API, so you'll able
+         to use MCU pins as GPIOs.
+
 endmenu
index 39e3e69ed1256bf93de0be16b9687bd15eb8e4a9..ca520fa143d696dd849e80792213ce796e0266a4 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP)    += isp1301_omap.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_MENELAUS)         += menelaus.o
 obj-$(CONFIG_SENSORS_TSL2550)  += tsl2550.o
+obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
index 4655b794ebe3c7d06ad911cf898c25a5061b03d0..28902ebd553905aedd2507d32870d97ea7023ade 100644 (file)
@@ -49,10 +49,9 @@ MODULE_LICENSE("GPL");
 
 struct isp1301 {
        struct otg_transceiver  otg;
-       struct i2c_client       client;
+       struct i2c_client       *client;
        void                    (*i2c_release)(struct device *dev);
 
-       int                     irq;
        int                     irq_type;
 
        u32                     last_otg_ctrl;
@@ -138,14 +137,6 @@ static inline void notresponding(struct isp1301 *isp)
 
 /*-------------------------------------------------------------------------*/
 
-/* only two addresses possible */
-#define        ISP_BASE                0x2c
-static unsigned short normal_i2c[] = {
-       ISP_BASE, ISP_BASE + 1,
-       I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static struct i2c_driver isp1301_driver;
 
 /* smbus apis are used for portability */
@@ -153,25 +144,25 @@ static struct i2c_driver isp1301_driver;
 static inline u8
 isp1301_get_u8(struct isp1301 *isp, u8 reg)
 {
-       return i2c_smbus_read_byte_data(&isp->client, reg + 0);
+       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);
+       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);
+       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);
+       return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -349,10 +340,10 @@ 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);
+               (void) get_device(&isp->client->dev);
                status = schedule_work(&isp->work);
                if (!status && !isp->working)
-                       dev_vdbg(&isp->client.dev,
+                       dev_vdbg(&isp->client->dev,
                                "work item %d may be lost\n", work);
        }
 }
@@ -1135,7 +1126,7 @@ isp1301_work(struct work_struct *work)
                /* 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);
+                       put_device(&isp->client->dev);
                }
 #endif
                /* transfer state from isp1301 to otg engine */
@@ -1143,7 +1134,7 @@ isp1301_work(struct work_struct *work)
                        u8              stat = isp1301_clear_latch(isp);
 
                        isp_update_otg(isp, stat);
-                       put_device(&isp->client.dev);
+                       put_device(&isp->client->dev);
                }
 
                if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) {
@@ -1178,7 +1169,7 @@ isp1301_work(struct work_struct *work)
                        }
                        host_resume(isp);
                        // mdelay(10);
-                       put_device(&isp->client.dev);
+                       put_device(&isp->client->dev);
                }
 
                if (test_and_clear_bit(WORK_TIMER, &isp->todo)) {
@@ -1187,15 +1178,15 @@ isp1301_work(struct work_struct *work)
                        if (!stop)
                                mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
 #endif
-                       put_device(&isp->client.dev);
+                       put_device(&isp->client->dev);
                }
 
                if (isp->todo)
-                       dev_vdbg(&isp->client.dev,
+                       dev_vdbg(&isp->client->dev,
                                "work done, todo = 0x%lx\n",
                                isp->todo);
                if (stop) {
-                       dev_dbg(&isp->client.dev, "stop\n");
+                       dev_dbg(&isp->client->dev, "stop\n");
                        break;
                }
        } while (isp->todo);
@@ -1219,7 +1210,7 @@ static void isp1301_release(struct device *dev)
 {
        struct isp1301  *isp;
 
-       isp = container_of(dev, struct isp1301, client.dev);
+       isp = dev_get_drvdata(dev);
 
        /* ugly -- i2c hijacks our memory hook to wait_for_completion() */
        if (isp->i2c_release)
@@ -1229,15 +1220,15 @@ static void isp1301_release(struct device *dev)
 
 static struct isp1301 *the_transceiver;
 
-static int isp1301_detach_client(struct i2c_client *i2c)
+static int __exit isp1301_remove(struct i2c_client *i2c)
 {
        struct isp1301  *isp;
 
-       isp = container_of(i2c, struct isp1301, client);
+       isp = i2c_get_clientdata(i2c);
 
        isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
        isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);
-       free_irq(isp->irq, isp);
+       free_irq(i2c->irq, isp);
 #ifdef CONFIG_USB_OTG
        otg_unbind(isp);
 #endif
@@ -1252,7 +1243,7 @@ static int isp1301_detach_client(struct i2c_client *i2c)
        put_device(&i2c->dev);
        the_transceiver = 0;
 
-       return i2c_detach_client(i2c);
+       return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1285,7 +1276,7 @@ static int isp1301_otg_enable(struct isp1301 *isp)
        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");
+       dev_info(&isp->client->dev, "ready for dual-role USB ...\n");
 
        return 0;
 }
@@ -1310,7 +1301,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
 
 #ifdef CONFIG_USB_OTG
        isp->otg.host = host;
-       dev_dbg(&isp->client.dev, "registered host\n");
+       dev_dbg(&isp->client->dev, "registered host\n");
        host_suspend(isp);
        if (isp->otg.gadget)
                return isp1301_otg_enable(isp);
@@ -1325,7 +1316,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
        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");
+       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,
@@ -1343,7 +1334,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
        return 0;
 
 #else
-       dev_dbg(&isp->client.dev, "host sessions not allowed\n");
+       dev_dbg(&isp->client->dev, "host sessions not allowed\n");
        return -EINVAL;
 #endif
 
@@ -1370,7 +1361,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
 
 #ifdef CONFIG_USB_OTG
        isp->otg.gadget = gadget;
-       dev_dbg(&isp->client.dev, "registered gadget\n");
+       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);
@@ -1395,7 +1386,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
                INTR_SESS_VLD);
        isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
                INTR_VBUS_VLD);
-       dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
+       dev_info(&isp->client->dev, "B-Peripheral sessions ok\n");
        dump_regs(isp, __func__);
 
        /* If this has a Mini-AB connector, this mode is highly
@@ -1408,7 +1399,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
        return 0;
 
 #else
-       dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
+       dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n");
        return -EINVAL;
 #endif
 }
@@ -1508,12 +1499,10 @@ isp1301_start_hnp(struct otg_transceiver *dev)
 
 /*-------------------------------------------------------------------------*/
 
-/* no error returns, they'd just make bus scanning stop */
-static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
+static int __init isp1301_probe(struct i2c_client *i2c)
 {
        int                     status;
        struct isp1301          *isp;
-       struct i2c_client       *i2c;
 
        if (the_transceiver)
                return 0;
@@ -1527,37 +1516,19 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
        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.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;
-               }
-       }
+       i2c_set_clientdata(i2c, isp);
+       isp->client = i2c;
 
-       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;
+       /* verify the chip (shouldn't be necesary) */
+       status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
+       if (status != I2C_VENDOR_ID_PHILIPS) {
+               dev_dbg(&i2c->dev, "not philips id: %d\n", status);
+               goto fail;
+       }
+       status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
+       if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
+               dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
+               goto fail;
        }
        isp->i2c_release = i2c->dev.release;
        i2c->dev.release = isp1301_release;
@@ -1586,7 +1557,7 @@ fail1:
        status = otg_bind(isp);
        if (status < 0) {
                dev_dbg(&i2c->dev, "can't bind OTG\n");
-               goto fail2;
+               goto fail;
        }
 #endif
 
@@ -1599,26 +1570,21 @@ fail1:
 
                /* IRQ wired at M14 */
                omap_cfg_reg(M14_1510_GPIO2);
-               isp->irq = OMAP_GPIO_IRQ(2);
                if (gpio_request(2, "isp1301") == 0)
                        gpio_direction_input(2);
                isp->irq_type = IRQF_TRIGGER_FALLING;
        }
 
        isp->irq_type |= IRQF_SAMPLE_RANDOM;
-       status = request_irq(isp->irq, isp1301_irq,
+       status = request_irq(i2c->irq, isp1301_irq,
                        isp->irq_type, 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;
+                               i2c->irq, status);
+               goto fail;
        }
 
-       isp->otg.dev = &isp->client.dev;
+       isp->otg.dev = &i2c->dev;
        isp->otg.label = DRIVER_NAME;
 
        isp->otg.set_host = isp1301_set_host,
@@ -1649,22 +1615,25 @@ fail2:
                        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);
+fail:
+       kfree(isp);
+       return -ENODEV;
 }
 
+static const struct i2c_device_id isp1301_id[] = {
+       { "isp1301_omap", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, isp1301_id);
+
 static struct i2c_driver isp1301_driver = {
        .driver = {
                .name   = "isp1301_omap",
        },
-       .attach_adapter = isp1301_scan_bus,
-       .detach_client  = isp1301_detach_client,
+       .probe          = isp1301_probe,
+       .remove         = __exit_p(isp1301_remove),
+       .id_table       = isp1301_id,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c
new file mode 100644 (file)
index 0000000..82a9bcb
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
+ *
+ * Copyright (c) 2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+/*
+ * I don't have specifications for the MCU firmware, I found this register
+ * and bits positions by the trial&error method.
+ */
+#define MCU_REG_CTRL   0x20
+#define MCU_CTRL_POFF  0x40
+
+#define MCU_NUM_GPIO   2
+
+struct mcu {
+       struct mutex lock;
+       struct device_node *np;
+       struct i2c_client *client;
+       struct of_gpio_chip of_gc;
+       u8 reg_ctrl;
+};
+
+static struct mcu *glob_mcu;
+
+static void mcu_power_off(void)
+{
+       struct mcu *mcu = glob_mcu;
+
+       pr_info("Sending power-off request to the MCU...\n");
+       mutex_lock(&mcu->lock);
+       i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+                                 mcu->reg_ctrl | MCU_CTRL_POFF);
+       mutex_unlock(&mcu->lock);
+}
+
+static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
+       struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
+       u8 bit = 1 << (4 + gpio);
+
+       mutex_lock(&mcu->lock);
+       if (val)
+               mcu->reg_ctrl &= ~bit;
+       else
+               mcu->reg_ctrl |= bit;
+
+       i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
+       mutex_unlock(&mcu->lock);
+}
+
+static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       mcu_gpio_set(gc, gpio, val);
+       return 0;
+}
+
+static int mcu_gpiochip_add(struct mcu *mcu)
+{
+       struct device_node *np;
+       struct of_gpio_chip *of_gc = &mcu->of_gc;
+       struct gpio_chip *gc = &of_gc->gc;
+       int ret;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
+       if (!np)
+               return -ENODEV;
+
+       gc->owner = THIS_MODULE;
+       gc->label = np->full_name;
+       gc->can_sleep = 1;
+       gc->ngpio = MCU_NUM_GPIO;
+       gc->base = -1;
+       gc->set = mcu_gpio_set;
+       gc->direction_output = mcu_gpio_dir_out;
+       of_gc->gpio_cells = 2;
+       of_gc->xlate = of_gpio_simple_xlate;
+
+       np->data = of_gc;
+       mcu->np = np;
+
+       /*
+        * We don't want to lose the node, its ->data and ->full_name...
+        * So, if succeeded, we don't put the node here.
+        */
+       ret = gpiochip_add(gc);
+       if (ret)
+               of_node_put(np);
+       return ret;
+}
+
+static int mcu_gpiochip_remove(struct mcu *mcu)
+{
+       int ret;
+
+       ret = gpiochip_remove(&mcu->of_gc.gc);
+       if (ret)
+               return ret;
+       of_node_put(mcu->np);
+
+       return 0;
+}
+
+static int __devinit mcu_probe(struct i2c_client *client,
+                              const struct i2c_device_id *id)
+{
+       struct mcu *mcu;
+       int ret;
+
+       mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
+       if (!mcu)
+               return -ENOMEM;
+
+       mutex_init(&mcu->lock);
+       mcu->client = client;
+       i2c_set_clientdata(client, mcu);
+
+       ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+       if (ret < 0)
+               goto err;
+       mcu->reg_ctrl = ret;
+
+       ret = mcu_gpiochip_add(mcu);
+       if (ret)
+               goto err;
+
+       /* XXX: this is potentially racy, but there is no lock for ppc_md */
+       if (!ppc_md.power_off) {
+               glob_mcu = mcu;
+               ppc_md.power_off = mcu_power_off;
+               dev_info(&client->dev, "will provide power-off service\n");
+       }
+
+       return 0;
+err:
+       kfree(mcu);
+       return ret;
+}
+
+static int __devexit mcu_remove(struct i2c_client *client)
+{
+       struct mcu *mcu = i2c_get_clientdata(client);
+       int ret;
+
+       if (glob_mcu == mcu) {
+               ppc_md.power_off = NULL;
+               glob_mcu = NULL;
+       }
+
+       ret = mcu_gpiochip_remove(mcu);
+       if (ret)
+               return ret;
+       i2c_set_clientdata(client, NULL);
+       kfree(mcu);
+       return 0;
+}
+
+static const struct i2c_device_id mcu_ids[] = {
+       { "mcu-mpc8349emitx", },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, mcu_ids);
+
+static struct i2c_driver mcu_driver = {
+       .driver = {
+               .name = "mcu-mpc8349emitx",
+               .owner = THIS_MODULE,
+       },
+       .probe = mcu_probe,
+       .remove = __devexit_p(mcu_remove),
+       .id_table = mcu_ids,
+};
+
+static int __init mcu_init(void)
+{
+       return i2c_add_driver(&mcu_driver);
+}
+module_init(mcu_init);
+
+static void __exit mcu_exit(void)
+{
+       i2c_del_driver(&mcu_driver);
+}
+module_exit(mcu_exit);
+
+MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
+                  "MPC8349E-mITX-compatible MCU");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
index cf02e8fceb42a7a1ef4ee91c42d0fb8cfdd14ecb..acf8b9d5f575fec8cfe3d2578ab909c0956ce178 100644 (file)
@@ -456,14 +456,17 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
 
 /* offsets 0..3 == GPIO1..GPIO4
  * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes)
+ * offset 6 == vibrator motor driver
  */
 static void
 tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        if (offset < 4)
                tps65010_set_gpio_out_value(offset + 1, value);
-       else
+       else if (offset < 6)
                tps65010_set_led(offset - 3, value ? ON : OFF);
+       else
+               tps65010_set_vib(value);
 }
 
 static int
@@ -477,8 +480,10 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value)
                if (!(tps->outmask & (1 << offset)))
                        return -EINVAL;
                tps65010_set_gpio_out_value(offset + 1, value);
-       } else
+       } else if (offset < 6)
                tps65010_set_led(offset - 3, value ? ON : OFF);
+       else
+               tps65010_set_vib(value);
 
        return 0;
 }
@@ -646,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client,
                tps->chip.get = tps65010_gpio_get;
 
                tps->chip.base = board->base;
-               tps->chip.ngpio = 6;
+               tps->chip.ngpio = 7;
                tps->chip.can_sleep = 1;
 
                status = gpiochip_add(&tps->chip);
@@ -675,6 +680,7 @@ static const struct i2c_device_id tps65010_id[] = {
        { "tps65011", TPS65011 },
        { "tps65012", TPS65012 },
        { "tps65013", TPS65013 },
+       { "tps65014", TPS65011 },       /* tps65011 charging at 6.5V max */
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tps65010_id);
index b346a687ab593a89834270e64b91f2b8b1c4c66f..42e852d79ffaa5b001dda2c44219cad064a537e7 100644 (file)
@@ -437,6 +437,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 {
        int res = 0, dummy;
 
+       /* Can't register until after driver model init */
+       if (unlikely(WARN_ON(!i2c_bus_type.p)))
+               return -EAGAIN;
+
        mutex_init(&adap->bus_lock);
        mutex_init(&adap->clist_lock);
        INIT_LIST_HEAD(&adap->clients);
@@ -696,6 +700,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
        int res;
 
+       /* Can't register until after driver model init */
+       if (unlikely(WARN_ON(!i2c_bus_type.p)))
+               return -EAGAIN;
+
        /* new style driver methods can't mix with legacy ones */
        if (is_newstyle_driver(driver)) {
                if (driver->attach_adapter || driver->detach_adapter
@@ -978,7 +986,10 @@ static void __exit i2c_exit(void)
        bus_unregister(&i2c_bus_type);
 }
 
-subsys_initcall(i2c_init);
+/* We must initialize early, because some subsystems register i2c drivers
+ * in subsys_initcall() code, but are linked (and initialized) before i2c.
+ */
+postcore_initcall(i2c_init);
 module_exit(i2c_exit);
 
 /* ----------------------------------------------------
@@ -1676,6 +1687,28 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 }
 EXPORT_SYMBOL(i2c_smbus_write_word_data);
 
+/**
+ * i2c_smbus_process_call - SMBus "process call" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: 16-bit "word" being written
+ *
+ * This executes the SMBus "process call" protocol, returning negative errno
+ * else a 16-bit unsigned "word" received from the device.
+ */
+s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
+{
+       union i2c_smbus_data data;
+       int status;
+       data.word = value;
+
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_PROC_CALL, &data);
+       return (status < 0) ? status : data.word;
+}
+EXPORT_SYMBOL(i2c_smbus_process_call);
+
 /**
  * i2c_smbus_read_block_data - SMBus "block read" protocol
  * @client: Handle to slave device
index 307d976c9b69b977c389e62abfbe43682b1d3e24..c171988a9f517d7009319674265c47a10859a8c3 100644 (file)
@@ -521,9 +521,9 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
                return PTR_ERR(i2c_dev);
 
        /* register this i2c device with the driver core */
-       i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
-                                            MKDEV(I2C_MAJOR, adap->nr),
-                                            NULL, "i2c-%d", adap->nr);
+       i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
+                                    MKDEV(I2C_MAJOR, adap->nr), NULL,
+                                    "i2c-%d", adap->nr);
        if (IS_ERR(i2c_dev->dev)) {
                res = PTR_ERR(i2c_dev->dev);
                goto error;
index b50b5dac95b0f75a49d9da5aeae42e1db2d87a2c..74a369a6116fc7fbeb7bea0c68c629ec4cfb1102 100644 (file)
@@ -4,7 +4,7 @@
 
 # Select HAVE_IDE if IDE is supported
 config HAVE_IDE
-       def_bool n
+       bool
 
 menuconfig IDE
        tristate "ATA/ATAPI/MFM/RLL support"
@@ -54,38 +54,6 @@ menuconfig IDE
 
 if IDE
 
-config BLK_DEV_IDE
-       tristate "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
-       ---help---
-         If you say Y here, you will use the full-featured IDE driver to
-         control up to ten ATA/IDE interfaces, each being able to serve a
-         "master" and a "slave" device, for a total of up to twenty ATA/IDE
-         disk/cdrom/tape/floppy drives.
-
-         Useful information about large (>540 MB) IDE disks, multiple
-         interfaces, what to do if ATA/IDE devices are not automatically
-         detected, sound card ATA/IDE ports, module support, and other
-         topics, is contained in <file:Documentation/ide/ide.txt>. For detailed
-         information about hard drives, consult the Disk-HOWTO and the
-         Multi-Disk-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To fine-tune ATA/IDE drive/interface parameters for improved
-         performance, look for the hdparm package at
-         <ftp://ibiblio.org/pub/Linux/system/hardware/>.
-
-         To compile this driver as a module, choose M here and read
-         <file:Documentation/ide/ide.txt>. The module will be called ide-mod.
-         Do not compile this driver as a module if your root file system (the
-         one containing the directory /) is located on an IDE device.
-
-         If you have one or more IDE drives, say Y or M here. If your system
-         has no IDE drives, or if memory requirements are really tight, you
-         could say N here, and select the "Old hard disk driver" below
-         instead to save about 13 KB of memory in the kernel.
-
-if BLK_DEV_IDE
-
 comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
 
 config IDE_TIMINGS
@@ -348,7 +316,7 @@ config BLK_DEV_IDEPCI
 
 config IDEPCI_PCIBUS_ORDER
        bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
-       depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
+       depends on IDE=y && BLK_DEV_IDEPCI
        default y
        help
          Probe IDE PCI devices in the order in which they appear on the
@@ -729,7 +697,7 @@ endif
 
 config BLK_DEV_IDE_PMAC
        tristate "PowerMac on-board IDE support"
-       depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
+       depends on PPC_PMAC && IDE=y
        select IDE_TIMINGS
        help
          This driver provides support for the on-board IDE controller on
@@ -963,6 +931,4 @@ config BLK_DEV_IDEDMA
        def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \
                 BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 
-endif
-
 endif # IDE
index 308b8a12f314b758ac28d3e8c44d67d8ec671d85..ceaf779054eac07246702bf789b0ffbc6a97b7b3 100644 (file)
@@ -5,24 +5,25 @@
 EXTRA_CFLAGS                           += -Idrivers/ide
 
 ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
-             ide-taskfile.o ide-pio-blacklist.o
+             ide-taskfile.o ide-park.o ide-pio-blacklist.o
 
 # core IDE code
 ide-core-$(CONFIG_IDE_TIMINGS)         += ide-timings.o
 ide-core-$(CONFIG_IDE_ATAPI)           += ide-atapi.o
 ide-core-$(CONFIG_BLK_DEV_IDEPCI)      += setup-pci.o
 ide-core-$(CONFIG_BLK_DEV_IDEDMA)      += ide-dma.o
+ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF)  += ide-dma-sff.o
 ide-core-$(CONFIG_IDE_PROC_FS)         += ide-proc.o
 ide-core-$(CONFIG_BLK_DEV_IDEACPI)     += ide-acpi.o
 
-obj-$(CONFIG_BLK_DEV_IDE)              += ide-core.o
+obj-$(CONFIG_IDE)                      += ide-core.o
 
 ifeq ($(CONFIG_IDE_ARM), y)
        ide-arm-core-y += arm/ide_arm.o
        obj-y += ide-arm-core.o
 endif
 
-obj-$(CONFIG_BLK_DEV_IDE)              += legacy/ pci/
+obj-$(CONFIG_IDE)                      += legacy/ pci/
 
 obj-$(CONFIG_IDEPCI_PCIBUS_ORDER)      += ide-scan-pci.o
 
@@ -31,15 +32,21 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
        obj-y += cmd640-core.o
 endif
 
-obj-$(CONFIG_BLK_DEV_IDE)              += ppc/
+obj-$(CONFIG_IDE)                      += ppc/
 obj-$(CONFIG_IDE_H8300)                        += h8300/
 obj-$(CONFIG_IDE_GENERIC)              += ide-generic.o
 obj-$(CONFIG_BLK_DEV_IDEPNP)           += ide-pnp.o
 
+ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o
 ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
 ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o
 
-obj-$(CONFIG_BLK_DEV_IDEDISK)          += ide-disk.o
+ifeq ($(CONFIG_IDE_PROC_FS), y)
+       ide-disk_mod-y += ide-disk_proc.o
+       ide-floppy_mod-y += ide-floppy_proc.o
+endif
+
+obj-$(CONFIG_BLK_DEV_IDEDISK)          += ide-disk_mod.o
 obj-$(CONFIG_BLK_DEV_IDECD)            += ide-cd_mod.o
 obj-$(CONFIG_BLK_DEV_IDEFLOPPY)                += ide-floppy_mod.o
 obj-$(CONFIG_BLK_DEV_IDETAPE)          += ide-tape.o
@@ -54,4 +61,4 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
        obj-y += ide-platform-core.o
 endif
 
-obj-$(CONFIG_BLK_DEV_IDE)              += arm/ mips/
+obj-$(CONFIG_IDE)                      += arm/ mips/
index 70f5b164828b0888681cca503c06298f5d59eda5..76bdc9a27f6f7ae91bbdd0ad4635fb169229a27c 100644 (file)
@@ -372,25 +372,6 @@ static int icside_dma_test_irq(ide_drive_t *drive)
                        ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 }
 
-static void icside_dma_timeout(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
-       if (icside_dma_test_irq(drive))
-               return;
-
-       ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
-
-       icside_dma_end(drive);
-}
-
-static void icside_dma_lost_irq(ide_drive_t *drive)
-{
-       printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
 static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
        hwif->dmatable_cpu      = NULL;
@@ -406,8 +387,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = {
        .dma_start              = icside_dma_start,
        .dma_end                = icside_dma_end,
        .dma_test_irq           = icside_dma_test_irq,
-       .dma_timeout            = icside_dma_timeout,
-       .dma_lost_irq           = icside_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
 };
 #else
 #define icside_v6_dma_ops NULL
index bde7a585f1987e3488e318982754143399a3709e..e2cdd2e9cdecc70d388be220b3128d19efaf9de2 100644 (file)
@@ -80,7 +80,7 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
                outb(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               outb((tf->device & HIHI) | drive->select.all,
+               outb((tf->device & HIHI) | drive->select,
                     io_ports->device_addr);
 }
 
index 2427c380b3dcd88e44be8c2c3e66581532c7fd00..244a8a052ce85ff3b7bdbe6a28ab5a234b847359 100644 (file)
@@ -290,7 +290,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
        DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
                 hwif->name, dev->bus_id, port, hwif->channel);
 
-       if (!drive->present) {
+       if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
                DEBPRINT("%s drive %d:%d not present\n",
                         hwif->name, hwif->channel, port);
                goto out;
@@ -420,8 +420,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
 
        DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
 
-       if (!drive->present)
+       if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                goto out;
+
        if (!gtf_count)         /* shouldn't be here */
                goto out;
 
@@ -660,7 +661,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
                if (!drive->acpidata->obj_handle)
                        drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
 
-               if (drive->acpidata->obj_handle && drive->present) {
+               if (drive->acpidata->obj_handle &&
+                   (drive->dev_flags & IDE_DFLAG_PRESENT)) {
                        acpi_bus_set_power(drive->acpidata->obj_handle,
                                on? ACPI_STATE_D0: ACPI_STATE_D3);
                }
@@ -720,7 +722,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
 
                memset(drive->acpidata, 0, sizeof(*drive->acpidata));
 
-               if (!drive->present)
+               if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                        continue;
 
                err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
@@ -745,7 +747,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
        for (i = 0; i < MAX_DRIVES; i++) {
                drive = &hwif->drives[i];
 
-               if (drive->present)
+               if (drive->dev_flags & IDE_DFLAG_PRESENT)
                        /* Execute ACPI startup code */
                        ide_acpi_exec_tfs(drive);
        }
index 608c5bade92939476d15a1c1f053584fde419e95..2e305714c209e8d9573a2aee1f490ece032b2580 100644 (file)
@@ -124,8 +124,8 @@ EXPORT_SYMBOL_GPL(ide_init_pc);
  * the current request, so that it will be processed immediately, on the next
  * pass through the driver.
  */
-void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
-                      struct ide_atapi_pc *pc, struct request *rq)
+static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
+                             struct ide_atapi_pc *pc, struct request *rq)
 {
        blk_rq_init(NULL, rq);
        rq->cmd_type = REQ_TYPE_SPECIAL;
@@ -137,7 +137,6 @@ void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
                rq->cmd[13] = REQ_IDETAPE_PC1;
        ide_do_drive_cmd(drive, rq);
 }
-EXPORT_SYMBOL_GPL(ide_queue_pc_head);
 
 /*
  * Add a special packet command request to the tail of the request queue,
@@ -203,25 +202,80 @@ int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
 }
 EXPORT_SYMBOL_GPL(ide_set_media_lock);
 
-/* TODO: unify the code thus making some arguments go away */
-ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
-       ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
-       void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
-       void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
-       int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
+void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
+       ide_init_pc(pc);
+       pc->c[0] = REQUEST_SENSE;
+       if (drive->media == ide_floppy) {
+               pc->c[4] = 255;
+               pc->req_xfer = 18;
+       } else {
+               pc->c[4] = 20;
+               pc->req_xfer = 20;
+       }
+}
+EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
+
+/*
+ * Called when an error was detected during the last packet command.
+ * We queue a request sense packet command in the head of the request list.
+ */
+void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+{
+       struct request *rq = &drive->request_sense_rq;
+       struct ide_atapi_pc *pc = &drive->request_sense_pc;
+
+       (void)ide_read_error(drive);
+       ide_create_request_sense_cmd(drive, pc);
+       if (drive->media == ide_tape)
+               set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
+       ide_queue_pc_head(drive, disk, pc, rq);
+}
+EXPORT_SYMBOL_GPL(ide_retry_pc);
+
+int ide_scsi_expiry(ide_drive_t *drive)
+{
+       struct ide_atapi_pc *pc = drive->pc;
+
+       debug_log("%s called for %lu at %lu\n", __func__,
+                 pc->scsi_cmd->serial_number, jiffies);
+
+       pc->flags |= PC_FLAG_TIMEDOUT;
+
+       return 0; /* we do not want the IDE subsystem to retry */
+}
+EXPORT_SYMBOL_GPL(ide_scsi_expiry);
+
+/*
+ * This is the usual interrupt handler which will be called during a packet
+ * command.  We will transfer some of the data (as requested by the drive)
+ * and will re-point interrupt handler to us.
+ */
+static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
+{
+       struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = hwif->hwgroup->rq;
        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        xfer_func_t *xferfunc;
-       unsigned int temp;
+       ide_expiry_t *expiry;
+       unsigned int timeout, temp;
        u16 bcount;
-       u8 stat, ireason, scsi = drive->scsi;
+       u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
 
        debug_log("Enter %s - interrupt handler\n", __func__);
 
+       if (scsi) {
+               timeout = ide_scsi_get_timeout(pc);
+               expiry = ide_scsi_expiry;
+       } else {
+               timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+                                                      : WAIT_TAPE_CMD;
+               expiry = NULL;
+       }
+
        if (pc->flags & PC_FLAG_TIMEDOUT) {
-               drive->pc_callback(drive);
+               drive->pc_callback(drive, 0);
                return ide_stopped;
        }
 
@@ -238,8 +292,8 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
                        pc->flags |= PC_FLAG_DMA_ERROR;
                } else {
                        pc->xferred = pc->req_xfer;
-                       if (update_buffers)
-                               update_buffers(drive, pc);
+                       if (drive->pc_update_buffers)
+                               drive->pc_update_buffers(drive, pc);
                }
                debug_log("%s: DMA finished\n", drive->name);
        }
@@ -276,21 +330,19 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
                        debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
 
                        /* Retry operation */
-                       retry_pc(drive);
+                       ide_retry_pc(drive, rq->rq_disk);
 
                        /* queued, but not started */
                        return ide_stopped;
                }
 cmd_finished:
                pc->error = 0;
-               if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
-                   (stat & ATA_DSC) == 0) {
-                       dsc_handle(drive);
-                       return ide_stopped;
-               }
+
+               if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
+                       dsc = 1;
 
                /* Command finished - Call the callback function */
-               drive->pc_callback(drive);
+               drive->pc_callback(drive, dsc);
 
                return ide_stopped;
        }
@@ -336,7 +388,8 @@ cmd_finished:
                                        temp = 0;
                                if (temp) {
                                        if (pc->sg)
-                                               io_buffers(drive, pc, temp, 0);
+                                               drive->pc_io_buffers(drive, pc,
+                                                                    temp, 0);
                                        else
                                                tp_ops->input_data(drive, NULL,
                                                        pc->cur_pos, temp);
@@ -348,9 +401,7 @@ cmd_finished:
                                pc->xferred += temp;
                                pc->cur_pos += temp;
                                ide_pad_transfer(drive, 0, bcount - temp);
-                               ide_set_handler(drive, handler, timeout,
-                                               expiry);
-                               return ide_started;
+                               goto next_irq;
                        }
                        debug_log("The device wants to send us more data than "
                                  "expected - allowing transfer\n");
@@ -362,7 +413,7 @@ cmd_finished:
        if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
            (drive->media == ide_tape && !scsi && pc->bh) ||
            (scsi && pc->sg)) {
-               int done = io_buffers(drive, pc, bcount,
+               int done = drive->pc_io_buffers(drive, pc, bcount,
                                  !!(pc->flags & PC_FLAG_WRITING));
 
                /* FIXME: don't do partial completions */
@@ -377,12 +428,11 @@ cmd_finished:
 
        debug_log("[cmd %x] transferred %d bytes on that intr.\n",
                  rq->cmd[0], bcount);
-
+next_irq:
        /* And set the interrupt handler again */
-       ide_set_handler(drive, handler, timeout, expiry);
+       ide_set_handler(drive, ide_pc_intr, timeout, expiry);
        return ide_started;
 }
-EXPORT_SYMBOL_GPL(ide_pc_intr);
 
 static u8 ide_read_ireason(ide_drive_t *drive)
 {
@@ -418,12 +468,22 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
        return ireason;
 }
 
-ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
-                               ide_handler_t *handler, unsigned int timeout,
-                               ide_expiry_t *expiry)
+static int ide_delayed_transfer_pc(ide_drive_t *drive)
 {
+       /* Send the actual packet */
+       drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
+
+       /* Timeout for the packet command */
+       return WAIT_FLOPPY_CMD;
+}
+
+static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
+{
+       struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = hwif->hwgroup->rq;
+       ide_expiry_t *expiry;
+       unsigned int timeout;
        ide_startstop_t startstop;
        u8 ireason;
 
@@ -434,7 +494,8 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
        }
 
        ireason = ide_read_ireason(drive);
-       if (drive->media == ide_tape && !drive->scsi)
+       if (drive->media == ide_tape &&
+           (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
                ireason = ide_wait_ireason(drive, ireason);
 
        if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
@@ -443,8 +504,27 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
                return ide_do_reset(drive);
        }
 
+       /*
+        * If necessary schedule the packet transfer to occur 'timeout'
+        * miliseconds later in ide_delayed_transfer_pc() after the device
+        * says it's ready for a packet.
+        */
+       if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+               timeout = drive->pc_delay;
+               expiry = &ide_delayed_transfer_pc;
+       } else {
+               if (drive->dev_flags & IDE_DFLAG_SCSI) {
+                       timeout = ide_scsi_get_timeout(pc);
+                       expiry = ide_scsi_expiry;
+               } else {
+                       timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+                                                              : WAIT_TAPE_CMD;
+                       expiry = NULL;
+               }
+       }
+
        /* Set the interrupt routine */
-       ide_set_handler(drive, handler, timeout, expiry);
+       ide_set_handler(drive, ide_pc_intr, timeout, expiry);
 
        /* Begin DMA, if necessary */
        if (pc->flags & PC_FLAG_DMA_OK) {
@@ -458,22 +538,22 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
 
        return ide_started;
 }
-EXPORT_SYMBOL_GPL(ide_transfer_pc);
 
-ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
-                            ide_handler_t *handler, unsigned int timeout,
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
                             ide_expiry_t *expiry)
 {
+       struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
+       u32 tf_flags;
        u16 bcount;
-       u8 dma = 0;
+       u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
 
        /* We haven't transferred any data yet */
        pc->xferred = 0;
        pc->cur_pos = pc->buf;
 
        /* Request to transfer the entire buffer at once */
-       if (drive->media == ide_tape && !drive->scsi)
+       if (drive->media == ide_tape && scsi == 0)
                bcount = pc->req_xfer;
        else
                bcount = min(pc->req_xfer, 63 * 1024);
@@ -483,28 +563,35 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
                ide_dma_off(drive);
        }
 
-       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
-               if (drive->scsi)
+       if ((pc->flags & PC_FLAG_DMA_OK) &&
+           (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
+               if (scsi)
                        hwif->sg_mapped = 1;
-               dma = !hwif->dma_ops->dma_setup(drive);
-               if (drive->scsi)
+               drive->dma = !hwif->dma_ops->dma_setup(drive);
+               if (scsi)
                        hwif->sg_mapped = 0;
        }
 
-       if (!dma)
+       if (!drive->dma)
                pc->flags &= ~PC_FLAG_DMA_OK;
 
-       ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE,
-                          bcount, dma);
+       if (scsi)
+               tf_flags = 0;
+       else if (drive->media == ide_cdrom || drive->media == ide_optical)
+               tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+       else
+               tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+       ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
 
        /* Issue the packet command */
        if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
-               ide_execute_command(drive, ATA_CMD_PACKET, handler,
+               ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
                                    timeout, NULL);
                return ide_started;
        } else {
                ide_execute_pkt_cmd(drive);
-               return (*handler)(drive);
+               return ide_transfer_pc(drive);
        }
 }
 EXPORT_SYMBOL_GPL(ide_issue_pc);
index 465a92ca01794bd7c2bb2b7630a70c84d04b3776..3308b1cd3a335de2cf4da4867ec7ca2597649f5a 100644 (file)
@@ -23,6 +23,9 @@
  *     Documentation/ide/ChangeLog.ide-cd.1994-2004
  */
 
+#define DRV_NAME "ide-cd"
+#define PFX DRV_NAME ": "
+
 #define IDECD_VERSION "5.00"
 
 #include <linux/module.h>
 
 #include "ide-cd.h"
 
-static DEFINE_MUTEX(idecd_ref_mutex);
+#define IDECD_DEBUG_LOG                1
 
-#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+#if IDECD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
 
-#define ide_cd_g(disk) \
-       container_of((disk)->private_data, struct cdrom_info, driver)
+static DEFINE_MUTEX(idecd_ref_mutex);
 
 static void ide_cd_release(struct kref *);
 
@@ -64,7 +70,7 @@ static struct cdrom_info *ide_cd_get(struct gendisk *disk)
        struct cdrom_info *cd = NULL;
 
        mutex_lock(&idecd_ref_mutex);
-       cd = ide_cd_g(disk);
+       cd = ide_drv_g(disk, cdrom_info);
        if (cd) {
                if (ide_device_get(cd->drive))
                        cd = NULL;
@@ -102,6 +108,9 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
 {
        int log = 0;
 
+       ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
+                     sense->sense_key);
+
        if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
                return 0;
 
@@ -150,6 +159,14 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
        unsigned long bio_sectors;
        struct cdrom_info *info = drive->driver_data;
 
+       ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
+                       "sense_key: 0x%x\n", __func__, sense->error_code,
+                       sense->sense_key);
+
+       if (failed_command)
+               ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
+                               __func__, failed_command->cmd[0]);
+
        if (!cdrom_log_sense(drive, failed_command, sense))
                return;
 
@@ -200,6 +217,8 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        struct cdrom_info *info         = drive->driver_data;
        struct request *rq              = &info->request_sense_request;
 
+       ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);
+
        if (sense == NULL)
                sense = &info->sense_data;
 
@@ -219,6 +238,10 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
        /* NOTE! Save the failed command in "rq->buffer" */
        rq->buffer = (void *) failed_command;
 
+       if (failed_command)
+               ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
+                             failed_command->cmd[0]);
+
        ide_do_drive_cmd(drive, rq);
 }
 
@@ -227,6 +250,10 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
        struct request *rq = HWGROUP(drive)->rq;
        int nsectors = rq->hard_cur_sectors;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
+                     "nsectors: %d\n", __func__, rq->cmd[0], uptodate,
+                     nsectors);
+
        if (blk_sense_request(rq) && uptodate) {
                /*
                 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
@@ -269,6 +296,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
        if (!nsectors)
                nsectors = 1;
 
+       ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
+                     __func__, uptodate, nsectors);
+
        ide_end_request(drive, uptodate, nsectors);
 }
 
@@ -304,11 +334,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
        sense_key = err >> 4;
 
        if (rq == NULL) {
-               printk(KERN_ERR "%s: missing rq in %s\n",
+               printk(KERN_ERR PFX "%s: missing rq in %s\n",
                                drive->name, __func__);
                return 1;
        }
 
+       ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
+                     "rq->cmd_type: 0x%x, err: 0x%x\n", __func__, stat,
+                     good_stat, rq->cmd_type, err);
+
        if (blk_sense_request(rq)) {
                /*
                 * We got an error trying to get sense info from the drive
@@ -374,7 +408,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                                cdrom_saw_media_change(drive);
 
                                /* fail the request */
-                               printk(KERN_ERR "%s: tray open\n", drive->name);
+                               printk(KERN_ERR PFX "%s: tray open\n",
+                                               drive->name);
                                do_end_request = 1;
                        } else {
                                struct cdrom_info *info = drive->driver_data;
@@ -460,7 +495,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                if (stat & ATA_ERR)
                        cdrom_queue_request_sense(drive, NULL, NULL);
        } else {
-               blk_dump_rq_flags(rq, "ide-cd: bad rq");
+               blk_dump_rq_flags(rq, PFX "bad rq");
                cdrom_end_request(drive, 0);
        }
 
@@ -488,6 +523,9 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
        struct request *rq = HWGROUP(drive)->rq;
        unsigned long wait = 0;
 
+       ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
+                     rq->cmd[0]);
+
        /*
         * Some commands are *slow* and normally take a long time to complete.
         * Usually we can use the ATAPI "disconnect" to bypass this, but not all
@@ -504,7 +542,7 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
                break;
        default:
                if (!(rq->cmd_flags & REQ_QUIET))
-                       printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n",
+                       printk(KERN_INFO PFX "cmd 0x%x timed out\n",
                                         rq->cmd[0]);
                wait = 0;
                break;
@@ -524,20 +562,21 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
                                                  int xferlen,
                                                  ide_handler_t *handler)
 {
-       struct cdrom_info *info = drive->driver_data;
        ide_hwif_t *hwif = drive->hwif;
 
+       ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
+
        /* FIXME: for Virtual DMA we must check harder */
-       if (info->dma)
-               info->dma = !hwif->dma_ops->dma_setup(drive);
+       if (drive->dma)
+               drive->dma = !hwif->dma_ops->dma_setup(drive);
 
        /* set up the controller registers */
        ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
-                          xferlen, info->dma);
+                          xferlen, drive->dma);
 
        if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
                /* waiting for CDB interrupt, not DMA yet. */
-               if (info->dma)
+               if (drive->dma)
                        drive->waiting_for_dma = 0;
 
                /* packet command */
@@ -564,9 +603,10 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
 {
        ide_hwif_t *hwif = drive->hwif;
        int cmd_len;
-       struct cdrom_info *info = drive->driver_data;
        ide_startstop_t startstop;
 
+       ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
+
        if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
                /*
                 * Here we should have been called after receiving an interrupt
@@ -578,7 +618,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
                        return ide_stopped;
 
                /* ok, next interrupt will be DMA interrupt */
-               if (info->dma)
+               if (drive->dma)
                        drive->waiting_for_dma = 1;
        } else {
                /* otherwise, we must wait for DRQ to get set */
@@ -599,7 +639,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
        hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
 
        /* start the DMA if need be */
-       if (info->dma)
+       if (drive->dma)
                hwif->dma_ops->dma_start(drive);
 
        return ide_started;
@@ -615,6 +655,9 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
 {
        ide_hwif_t *hwif = drive->hwif;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
+                     __func__, ireason, rw);
+
        /*
         * ireason == 0: the drive wants to receive data from us
         * ireason == 2: the drive is expecting to transfer data to us
@@ -624,7 +667,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
        else if (ireason == (rw << 1)) {
 
                /* whoops... */
-               printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+               printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
                                drive->name, __func__);
 
                ide_pad_transfer(drive, rw, len);
@@ -637,7 +680,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
                return 0;
        } else {
                /* drive wants a command packet, or invalid ireason... */
-               printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+               printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
                                drive->name, __func__, ireason);
        }
 
@@ -654,17 +697,19 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
  */
 static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
 {
+       ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);
+
        if ((len % SECTOR_SIZE) == 0)
                return 0;
 
-       printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
-                       drive->name, __func__, len);
+       printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
+                       __func__, len);
 
        if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
-               printk(KERN_ERR "  This drive is not supported by "
-                               "this version of the driver\n");
+               printk(KERN_ERR PFX "This drive is not supported by this "
+                               "version of the driver\n");
        else {
-               printk(KERN_ERR "  Trying to limit transfer sizes\n");
+               printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
                drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
        }
 
@@ -676,6 +721,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
 static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
                                                 struct request *rq)
 {
+       ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
+                     rq->cmd_flags);
+
        if (rq_data_dir(rq) == READ) {
                unsigned short sectors_per_frame =
                        queue_hardsect_size(drive->queue) >> SECTOR_BITS;
@@ -695,7 +743,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
                        /* sanity check... */
                        if (rq->current_nr_sectors !=
                            bio_cur_sectors(rq->bio)) {
-                               printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
+                               printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
                                                drive->name, __func__,
                                                rq->current_nr_sectors);
                                cdrom_end_request(drive, 0);
@@ -704,11 +752,7 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
                        rq->current_nr_sectors += nskip;
                }
        }
-#if 0
-       else
-               /* the immediate bit */
-               rq->cmd[1] = 1 << 3;
-#endif
+
        /* set up the command */
        rq->timeout = ATAPI_WAIT_PC;
 
@@ -739,6 +783,8 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
        int stat;
        static int retry = 10;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        if (cdrom_decode_status(drive, 0, &stat))
                return ide_stopped;
 
@@ -746,7 +792,7 @@ static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
 
        if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
                if (--retry == 0)
-                       drive->dsc_overlap = 0;
+                       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        }
        return ide_stopped;
 }
@@ -755,6 +801,8 @@ static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
 {
        sector_t frame = rq->sector;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
 
        memset(rq->cmd, 0, BLK_MAX_CDB);
@@ -775,8 +823,11 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
  * Fix up a possibly partially-processed request so that we can start it over
  * entirely, or even put it back on the request queue.
  */
-static void restore_request(struct request *rq)
+static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
 {
+
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        if (rq->buffer != bio_data(rq->bio)) {
                sector_t n =
                        (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
@@ -795,8 +846,11 @@ static void restore_request(struct request *rq)
 /*
  * All other packet commands.
  */
-static void ide_cd_request_sense_fixup(struct request *rq)
+static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
 {
+
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        /*
         * Some of the trailing request sense fields are optional,
         * and some drives don't send them.  Sigh.
@@ -822,6 +876,10 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
        if (!sense)
                sense = &local_sense;
 
+       ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
+                     "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
+                     timeout, cmd_flags);
+
        /* start of retry loop */
        do {
                struct request *rq;
@@ -895,7 +953,6 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       struct cdrom_info *info = drive->driver_data;
        struct request *rq = HWGROUP(drive)->rq;
        xfer_func_t *xferfunc;
        ide_expiry_t *expiry = NULL;
@@ -905,13 +962,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        u16 len;
        u8 ireason;
 
+       ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
+                     __func__, rq->cmd[0], write);
+
        /* check for errors */
-       dma = info->dma;
+       dma = drive->dma;
        if (dma) {
-               info->dma = 0;
+               drive->dma = 0;
                dma_error = hwif->dma_ops->dma_end(drive);
                if (dma_error) {
-                       printk(KERN_ERR "%s: DMA %s error\n", drive->name,
+                       printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
                                        write ? "write" : "read");
                        ide_dma_off(drive);
                }
@@ -937,6 +997,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        if (thislen > len)
                thislen = len;
 
+       ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
+                     __func__, stat, thislen);
+
        /* If DRQ is clear, the command has completed. */
        if ((stat & ATA_DRQ) == 0) {
                if (blk_fs_request(rq)) {
@@ -946,7 +1009,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                         */
                        uptodate = 1;
                        if (rq->current_nr_sectors > 0) {
-                               printk(KERN_ERR "%s: %s: data underrun "
+                               printk(KERN_ERR PFX "%s: %s: data underrun "
                                                "(%d blocks)\n",
                                                drive->name, __func__,
                                                rq->current_nr_sectors);
@@ -957,7 +1020,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        cdrom_end_request(drive, uptodate);
                        return ide_stopped;
                } else if (!blk_pc_request(rq)) {
-                       ide_cd_request_sense_fixup(rq);
+                       ide_cd_request_sense_fixup(drive, rq);
                        /* complain if we still have data left to transfer */
                        uptodate = rq->data_len ? 0 : 1;
                }
@@ -1000,6 +1063,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                xferfunc = hwif->tp_ops->input_data;
        }
 
+       ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
+                     "ireason: 0x%x\n", __func__, rq->cmd_type, ireason);
+
        /* transfer data */
        while (thislen > 0) {
                u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
@@ -1024,7 +1090,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                                 */
                                ide_pad_transfer(drive, 0, thislen);
                        else {
-                               printk(KERN_ERR "%s: confused, missing data\n",
+                               printk(KERN_ERR PFX "%s: confused, missing data\n",
                                                drive->name);
                                blk_dump_rq_flags(rq, rq_data_dir(rq)
                                                  ? "cdrom_newpc_intr, write"
@@ -1111,6 +1177,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
        unsigned short sectors_per_frame =
                queue_hardsect_size(drive->queue) >> SECTOR_BITS;
 
+       ide_debug_log(IDE_DBG_RQ, "Call %s, write: 0x%x, secs_per_frame: %u\n",
+                     __func__, write, sectors_per_frame);
+
        if (write) {
                /* disk has become write protected */
                if (get_disk_ro(cd->disk)) {
@@ -1122,7 +1191,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                 * We may be retrying this request after an error.  Fix up any
                 * weirdness which might be present in the request packet.
                 */
-               restore_request(rq);
+               ide_cd_restore_request(drive, rq);
        }
 
        /* use DMA, if possible / writes *must* be hardware frame aligned */
@@ -1132,9 +1201,9 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                        cdrom_end_request(drive, 0);
                        return ide_stopped;
                }
-               cd->dma = 0;
+               drive->dma = 0;
        } else
-               cd->dma = drive->using_dma;
+               drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
        if (write)
                cd->devinfo.media_written = 1;
@@ -1151,14 +1220,16 @@ static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
 
 static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
 {
-       struct cdrom_info *info = drive->driver_data;
+
+       ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd_type: 0x%x\n", __func__,
+                     rq->cmd_type);
 
        if (blk_pc_request(rq))
                rq->cmd_flags |= REQ_QUIET;
        else
                rq->cmd_flags &= ~REQ_FAILED;
 
-       info->dma = 0;
+       drive->dma = 0;
 
        /* sg request */
        if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
@@ -1171,7 +1242,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
                else
                        buf = rq->data;
 
-               info->dma = drive->using_dma;
+               drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
                /*
                 * check if dma is safe
@@ -1182,7 +1253,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
                alignment = queue_dma_alignment(q) | q->dma_pad_mask;
                if ((unsigned long)buf & alignment || rq->data_len & alignment
                    || object_is_on_stack(buf))
-                       info->dma = 0;
+                       drive->dma = 0;
        }
 }
 
@@ -1196,6 +1267,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
        ide_handler_t *fn;
        int xferlen;
 
+       ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd_type: 0x%x, block: %llu\n",
+                     __func__, rq->cmd_type, (unsigned long long)block);
+
        if (blk_fs_request(rq)) {
                if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
                        ide_hwif_t *hwif = drive->hwif;
@@ -1208,7 +1282,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                                                        IDECD_SEEK_TIMER);
                                        return ide_stopped;
                                }
-                               printk(KERN_ERR "%s: DSC timeout\n",
+                               printk(KERN_ERR PFX "%s: DSC timeout\n",
                                                drive->name);
                        }
                        drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
@@ -1216,11 +1290,11 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                if (rq_data_dir(rq) == READ &&
                    IDE_LARGE_SEEK(info->last_block, block,
                            IDECD_SEEK_THRESHOLD) &&
-                   drive->dsc_overlap) {
+                   (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
                        xferlen = 0;
                        fn = cdrom_start_seek_continuation;
 
-                       info->dma = 0;
+                       drive->dma = 0;
                        info->start_seek = jiffies;
 
                        ide_cd_prepare_seek_request(drive, rq);
@@ -1249,7 +1323,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                cdrom_end_request(drive, 1);
                return ide_stopped;
        } else {
-               blk_dump_rq_flags(rq, "ide-cd bad flags");
+               blk_dump_rq_flags(rq, DRV_NAME " bad flags");
                cdrom_end_request(drive, 0);
                return ide_stopped;
        }
@@ -1279,6 +1353,8 @@ int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
        struct cdrom_device_info *cdi = &info->devinfo;
        unsigned char cmd[BLK_MAX_CDB];
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        memset(cmd, 0, BLK_MAX_CDB);
        cmd[0] = GPCMD_TEST_UNIT_READY;
 
@@ -1305,6 +1381,8 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
        unsigned len = sizeof(capbuf);
        u32 blocklen;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        memset(cmd, 0, BLK_MAX_CDB);
        cmd[0] = GPCMD_READ_CDVD_CAPACITY;
 
@@ -1324,10 +1402,10 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
        case 4096:
                break;
        default:
-               printk(KERN_ERR "%s: weird block size %u\n",
-                       drive->name, blocklen);
-               printk(KERN_ERR "%s: default to 2kb block size\n",
-                       drive->name);
+               printk(KERN_ERR PFX "%s: weird block size %u\n",
+                               drive->name, blocklen);
+               printk(KERN_ERR PFX "%s: default to 2kb block size\n",
+                               drive->name);
                blocklen = 2048;
                break;
        }
@@ -1343,6 +1421,8 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
 {
        unsigned char cmd[BLK_MAX_CDB];
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        memset(cmd, 0, BLK_MAX_CDB);
 
        cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
@@ -1371,11 +1451,13 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
        long last_written;
        unsigned long sectors_per_frame = SECTORS_PER_FRAME;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        if (toc == NULL) {
                /* try to allocate space */
                toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
                if (toc == NULL) {
-                       printk(KERN_ERR "%s: No cdrom TOC buffer!\n",
+                       printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
                                        drive->name);
                        return -ENOMEM;
                }
@@ -1531,6 +1613,8 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
        struct packet_command cgc;
        int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
                size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
 
@@ -1549,6 +1633,8 @@ void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
        struct cdrom_info *cd = drive->driver_data;
        u16 curspeed, maxspeed;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
                curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
                maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
@@ -1589,6 +1675,8 @@ static int ide_cdrom_register(ide_drive_t *drive, int nslots)
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *devinfo = &info->devinfo;
 
+       ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);
+
        devinfo->ops = &ide_cdrom_dops;
        devinfo->speed = info->current_speed;
        devinfo->capacity = nslots;
@@ -1610,13 +1698,17 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
        mechtype_t mechtype;
        int nslots = 1;
 
+       ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
+                     "drive->atapi_flags: 0x%lx\n", __func__, drive->media,
+                     drive->atapi_flags);
+
        cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
                     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
                     CDC_MO_DRIVE | CDC_RAM);
 
        if (drive->media == ide_optical) {
                cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
-               printk(KERN_ERR "%s: ATAPI magneto-optical drive\n",
+               printk(KERN_ERR PFX "%s: ATAPI magneto-optical drive\n",
                                drive->name);
                return nslots;
        }
@@ -1674,7 +1766,7 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 
        ide_cdrom_update_speed(drive, buf);
 
-       printk(KERN_INFO "%s: ATAPI", drive->name);
+       printk(KERN_INFO PFX "%s: ATAPI", drive->name);
 
        /* don't print speed if the drive reported 0 */
        if (cd->max_speed)
@@ -1697,7 +1789,8 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
        else
                printk(KERN_CONT " drive");
 
-       printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
+       printk(KERN_CONT ", %dkB Cache\n",
+                        be16_to_cpup((__be16 *)&buf[8 + 12]));
 
        return nslots;
 }
@@ -1809,7 +1902,7 @@ static ide_proc_entry_t idecd_proc[] = {
        { NULL, 0, NULL, NULL }
 };
 
-ide_devset_rw_field(dsc_overlap, dsc_overlap);
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
 
 static const struct ide_proc_devset idecd_settings[] = {
        IDE_PROC_DEVSET(dsc_overlap, 0, 1),
@@ -1884,6 +1977,8 @@ static int ide_cdrom_setup(ide_drive_t *drive)
        char *fw_rev = (char *)&id[ATA_ID_FW_REV];
        int nslots;
 
+       ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);
+
        blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
        blk_queue_dma_alignment(drive->queue, 31);
        blk_queue_update_dma_pad(drive->queue, 15);
@@ -1891,14 +1986,9 @@ static int ide_cdrom_setup(ide_drive_t *drive)
        if (!drive->queue->unplug_delay)
                drive->queue->unplug_delay = 1;
 
-       drive->special.all      = 0;
-
        drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
                       ide_cd_flags(id);
 
-       if ((id[ATA_ID_CONFIG] & 0x0060) == 0x20)
-               drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
-
        if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
            fw_rev[4] == '1' && fw_rev[6] <= '2')
                drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
@@ -1915,10 +2005,13 @@ static int ide_cdrom_setup(ide_drive_t *drive)
        /* set correct block size */
        blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
 
-       drive->dsc_overlap = (drive->next != drive);
+       if (drive->next != drive)
+               drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
 
        if (ide_cdrom_register(drive, nslots)) {
-               printk(KERN_ERR "%s: %s failed to register device with the"
+               printk(KERN_ERR PFX "%s: %s failed to register device with the"
                                " cdrom driver.\n", drive->name, __func__);
                cd->devinfo.handle = NULL;
                return 1;
@@ -1932,6 +2025,8 @@ static void ide_cd_remove(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        ide_proc_unregister_driver(drive, info->driver);
 
        del_gendisk(info->disk);
@@ -1941,15 +2036,17 @@ static void ide_cd_remove(ide_drive_t *drive)
 
 static void ide_cd_release(struct kref *kref)
 {
-       struct cdrom_info *info = to_ide_cd(kref);
+       struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
        struct cdrom_device_info *devinfo = &info->devinfo;
        ide_drive_t *drive = info->drive;
        struct gendisk *g = info->disk;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        kfree(info->toc);
        if (devinfo->handle == drive)
                unregister_cdrom(devinfo);
-       drive->dsc_overlap = 0;
+       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        drive->driver_data = NULL;
        blk_queue_prep_rq(drive->queue, NULL);
        g->private_data = NULL;
@@ -1968,7 +2065,6 @@ static ide_driver_t ide_cdrom_driver = {
        .probe                  = ide_cd_probe,
        .remove                 = ide_cd_remove,
        .version                = IDECD_VERSION,
-       .media                  = ide_cdrom,
        .do_request             = ide_cd_do_request,
        .end_request            = ide_end_request,
        .error                  = __ide_error,
@@ -1999,7 +2095,7 @@ static int idecd_open(struct inode *inode, struct file *file)
 static int idecd_release(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct cdrom_info *info = ide_cd_g(disk);
+       struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
 
        cdrom_release(&info->devinfo, file);
 
@@ -2051,7 +2147,7 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        struct block_device *bdev = inode->i_bdev;
-       struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
+       struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
        int err;
 
        switch (cmd) {
@@ -2072,13 +2168,13 @@ static int idecd_ioctl(struct inode *inode, struct file *file,
 
 static int idecd_media_changed(struct gendisk *disk)
 {
-       struct cdrom_info *info = ide_cd_g(disk);
+       struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
        return cdrom_media_changed(&info->devinfo);
 }
 
 static int idecd_revalidate_disk(struct gendisk *disk)
 {
-       struct cdrom_info *info = ide_cd_g(disk);
+       struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
        struct request_sense sense;
 
        ide_cd_read_toc(info->drive, &sense);
@@ -2097,8 +2193,11 @@ static struct block_device_operations idecd_ops = {
 
 /* module options */
 static char *ignore;
-
 module_param(ignore, charp, 0400);
+
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
+
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
 
 static int ide_cd_probe(ide_drive_t *drive)
@@ -2107,6 +2206,10 @@ static int ide_cd_probe(ide_drive_t *drive)
        struct gendisk *g;
        struct request_sense sense;
 
+       ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
+                     "drive->media: 0x%x\n", __func__, drive->driver_req,
+                     drive->media);
+
        if (!strstr("ide-cdrom", drive->driver_req))
                goto failed;
 
@@ -2116,14 +2219,17 @@ static int ide_cd_probe(ide_drive_t *drive)
        /* skip drives that we were told to ignore */
        if (ignore != NULL) {
                if (strstr(ignore, drive->name)) {
-                       printk(KERN_INFO "ide-cd: ignoring drive %s\n",
+                       printk(KERN_INFO PFX "ignoring drive %s\n",
                                         drive->name);
                        goto failed;
                }
        }
+
+       drive->debug_mask = debug_mask;
+
        info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
        if (info == NULL) {
-               printk(KERN_ERR "%s: Can't allocate a cdrom structure\n",
+               printk(KERN_ERR PFX "%s: Can't allocate a cdrom structure\n",
                                drive->name);
                goto failed;
        }
@@ -2171,6 +2277,7 @@ static void __exit ide_cdrom_exit(void)
 
 static int __init ide_cdrom_init(void)
 {
+       printk(KERN_INFO DRV_NAME " driver " IDECD_VERSION "\n");
        return driver_register(&ide_cdrom_driver.gen_driver);
 }
 
index 61a4599b77dbf3c37528799118c181960a5f5786..5882b9a9ea8b7becc8108872e996ab9f852af95d 100644 (file)
@@ -88,7 +88,6 @@ struct cdrom_info {
        struct request_sense sense_data;
 
        struct request request_sense_request;
-       int dma;
        unsigned long last_block;
        unsigned long start_seek;
 
index 01846f244b40156b3822bcb504f05f7c18b12bd5..3853bde8eedc3c291b8b676529563afccdcc2f0d 100644 (file)
 #define IDE_DISK_MINORS                0
 #endif
 
-struct ide_disk_obj {
-       ide_drive_t     *drive;
-       ide_driver_t    *driver;
-       struct gendisk  *disk;
-       struct kref     kref;
-       unsigned int    openers;        /* protected by BKL for now */
-};
+#include "ide-disk.h"
 
 static DEFINE_MUTEX(idedisk_ref_mutex);
 
 #define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
 
-#define ide_disk_g(disk) \
-       container_of((disk)->private_data, struct ide_disk_obj, driver)
-
 static void ide_disk_release(struct kref *);
 
 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
@@ -140,9 +131,9 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
                                        sector_t block)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       unsigned int dma        = drive->using_dma;
        u16 nsectors            = (u16)rq->nr_sectors;
-       u8 lba48                = (drive->addressing == 1) ? 1 : 0;
+       u8 lba48                = !!(drive->dev_flags & IDE_DFLAG_LBA48);
+       u8 dma                  = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
        ide_task_t              task;
        struct ide_taskfile     *tf = &task.tf;
        ide_startstop_t         rc;
@@ -162,7 +153,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
        memset(&task, 0, sizeof(task));
        task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 
-       if (drive->select.b.lba) {
+       if (drive->dev_flags & IDE_DFLAG_LBA) {
                if (lba48) {
                        pr_debug("%s: LBA=0x%012llx\n", drive->name,
                                        (unsigned long long)block);
@@ -187,6 +178,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
                        tf->lbah   = block >>= 8;
                        tf->device = (block >> 8) & 0xf;
                }
+
+               tf->device |= ATA_LBA;
        } else {
                unsigned int sect, head, cyl, track;
 
@@ -237,7 +230,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 {
        ide_hwif_t *hwif = HWIF(drive);
 
-       BUG_ON(drive->blocked);
+       BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
 
        if (!blk_fs_request(rq)) {
                blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
@@ -384,139 +377,39 @@ static void idedisk_check_hpa(ide_drive_t *drive)
 static void init_idedisk_capacity(ide_drive_t *drive)
 {
        u16 *id = drive->id;
-       /*
-        * If this drive supports the Host Protected Area feature set,
-        * then we may need to change our opinion about the drive's capacity.
-        */
-       int hpa = ata_id_hpa_enabled(id);
+       int lba;
 
        if (ata_id_lba48_enabled(id)) {
                /* drive speaks 48-bit LBA */
-               drive->select.b.lba = 1;
+               lba = 1;
                drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
-               if (hpa)
-                       idedisk_check_hpa(drive);
        } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
                /* drive speaks 28-bit LBA */
-               drive->select.b.lba = 1;
+               lba = 1;
                drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
-               if (hpa)
-                       idedisk_check_hpa(drive);
        } else {
                /* drive speaks boring old 28-bit CHS */
+               lba = 0;
                drive->capacity64 = drive->cyl * drive->head * drive->sect;
        }
-}
 
-static sector_t idedisk_capacity(ide_drive_t *drive)
-{
-       return drive->capacity64;
-}
+       if (lba) {
+               drive->dev_flags |= IDE_DFLAG_LBA;
 
-#ifdef CONFIG_IDE_PROC_FS
-static int smart_enable(ide_drive_t *drive)
-{
-       ide_task_t args;
-       struct ide_taskfile *tf = &args.tf;
-
-       memset(&args, 0, sizeof(ide_task_t));
-       tf->feature = ATA_SMART_ENABLE;
-       tf->lbam    = ATA_SMART_LBAM_PASS;
-       tf->lbah    = ATA_SMART_LBAH_PASS;
-       tf->command = ATA_CMD_SMART;
-       args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-       return ide_no_data_taskfile(drive, &args);
-}
-
-static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
-{
-       ide_task_t args;
-       struct ide_taskfile *tf = &args.tf;
-
-       memset(&args, 0, sizeof(ide_task_t));
-       tf->feature = sub_cmd;
-       tf->nsect   = 0x01;
-       tf->lbam    = ATA_SMART_LBAM_PASS;
-       tf->lbah    = ATA_SMART_LBAH_PASS;
-       tf->command = ATA_CMD_SMART;
-       args.tf_flags   = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-       args.data_phase = TASKFILE_IN;
-       (void) smart_enable(drive);
-       return ide_raw_taskfile(drive, &args, buf, 1);
-}
-
-static int proc_idedisk_read_cache
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t     *drive = (ide_drive_t *) data;
-       char            *out = page;
-       int             len;
-
-       if (drive->id_read)
-               len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
-       else
-               len = sprintf(out, "(none)\n");
-
-       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_read_capacity
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       ide_drive_t*drive = (ide_drive_t *)data;
-       int len;
-
-       len = sprintf(page, "%llu\n", (long long)idedisk_capacity(drive));
-
-       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static int proc_idedisk_read_smart(char *page, char **start, off_t off,
-                                  int count, int *eof, void *data, u8 sub_cmd)
-{
-       ide_drive_t     *drive = (ide_drive_t *)data;
-       int             len = 0, i = 0;
-
-       if (get_smart_data(drive, page, sub_cmd) == 0) {
-               unsigned short *val = (unsigned short *) page;
-               char *out = (char *)val + SECTOR_SIZE;
-
-               page = out;
-               do {
-                       out += sprintf(out, "%04x%c", le16_to_cpu(*val),
-                                      (++i & 7) ? ' ' : '\n');
-                       val += 1;
-               } while (i < SECTOR_SIZE / 2);
-               len = out - page;
+               /*
+               * If this device supports the Host Protected Area feature set,
+               * then we may need to change our opinion about its capacity.
+               */
+               if (ata_id_hpa_enabled(id))
+                       idedisk_check_hpa(drive);
        }
-
-       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
 }
 
-static int proc_idedisk_read_sv
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
+sector_t ide_disk_capacity(ide_drive_t *drive)
 {
-       return proc_idedisk_read_smart(page, start, off, count, eof, data,
-                                      ATA_SMART_READ_VALUES);
-}
-
-static int proc_idedisk_read_st
-       (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-       return proc_idedisk_read_smart(page, start, off, count, eof, data,
-                                      ATA_SMART_READ_THRESHOLDS);
+       return drive->capacity64;
 }
 
-static ide_proc_entry_t idedisk_proc[] = {
-       { "cache",        S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL },
-       { "capacity",     S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
-       { "geometry",     S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL },
-       { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL },
-       { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL },
-       { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
 static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 {
        ide_drive_t *drive = q->queuedata;
@@ -568,25 +461,43 @@ static int set_multcount(ide_drive_t *drive, int arg)
        return (drive->mult_count == arg) ? 0 : -EIO;
 }
 
-ide_devset_get(nowerr, nowerr);
+ide_devset_get_flag(nowerr, IDE_DFLAG_NOWERR);
 
 static int set_nowerr(ide_drive_t *drive, int arg)
 {
        if (arg < 0 || arg > 1)
                return -EINVAL;
 
-       drive->nowerr = arg;
+       if (arg)
+               drive->dev_flags |= IDE_DFLAG_NOWERR;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_NOWERR;
+
        drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+
        return 0;
 }
 
+static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
+{
+       ide_task_t task;
+
+       memset(&task, 0, sizeof(task));
+       task.tf.feature = feature;
+       task.tf.nsect   = nsect;
+       task.tf.command = ATA_CMD_SET_FEATURES;
+       task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+       return ide_no_data_taskfile(drive, &task);
+}
+
 static void update_ordered(ide_drive_t *drive)
 {
        u16 *id = drive->id;
        unsigned ordered = QUEUE_ORDERED_NONE;
        prepare_flush_fn *prep_fn = NULL;
 
-       if (drive->wcache) {
+       if (drive->dev_flags & IDE_DFLAG_WCACHE) {
                unsigned long long capacity;
                int barrier;
                /*
@@ -597,9 +508,11 @@ static void update_ordered(ide_drive_t *drive)
                 * time we have trimmed the drive capacity if LBA48 is
                 * not available so we don't need to recheck that.
                 */
-               capacity = idedisk_capacity(drive);
-               barrier = ata_id_flush_enabled(id) && !drive->noflush &&
-                       (drive->addressing == 0 || capacity <= (1ULL << 28) ||
+               capacity = ide_disk_capacity(drive);
+               barrier = ata_id_flush_enabled(id) &&
+                       (drive->dev_flags & IDE_DFLAG_NOFLUSH) == 0 &&
+                       ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 ||
+                        capacity <= (1ULL << 28) ||
                         ata_id_flush_ext_enabled(id));
 
                printk(KERN_INFO "%s: cache flushes %ssupported\n",
@@ -615,25 +528,24 @@ static void update_ordered(ide_drive_t *drive)
        blk_queue_ordered(drive->queue, ordered, prep_fn);
 }
 
-ide_devset_get(wcache, wcache);
+ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
 
 static int set_wcache(ide_drive_t *drive, int arg)
 {
-       ide_task_t args;
        int err = 1;
 
        if (arg < 0 || arg > 1)
                return -EINVAL;
 
        if (ata_id_flush_enabled(drive->id)) {
-               memset(&args, 0, sizeof(ide_task_t));
-               args.tf.feature = arg ?
-                       SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
-               args.tf.command = ATA_CMD_SET_FEATURES;
-               args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-               err = ide_no_data_taskfile(drive, &args);
-               if (err == 0)
-                       drive->wcache = arg;
+               err = ide_do_setfeature(drive,
+                       arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
+               if (err == 0) {
+                       if (arg)
+                               drive->dev_flags |= IDE_DFLAG_WCACHE;
+                       else
+                               drive->dev_flags &= ~IDE_DFLAG_WCACHE;
+               }
        }
 
        update_ordered(drive);
@@ -658,22 +570,18 @@ ide_devset_get(acoustic, acoustic);
 
 static int set_acoustic(ide_drive_t *drive, int arg)
 {
-       ide_task_t args;
-
        if (arg < 0 || arg > 254)
                return -EINVAL;
 
-       memset(&args, 0, sizeof(ide_task_t));
-       args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
-       args.tf.nsect   = arg;
-       args.tf.command = ATA_CMD_SET_FEATURES;
-       args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-       ide_no_data_taskfile(drive, &args);
+       ide_do_setfeature(drive,
+               arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
+
        drive->acoustic = arg;
+
        return 0;
 }
 
-ide_devset_get(addressing, addressing);
+ide_devset_get_flag(addressing, IDE_DFLAG_LBA48);
 
 /*
  * drive->addressing:
@@ -686,49 +594,27 @@ static int set_addressing(ide_drive_t *drive, int arg)
        if (arg < 0 || arg > 2)
                return -EINVAL;
 
-       drive->addressing =  0;
-
-       if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
-               return 0;
-
-       if (ata_id_lba48_enabled(drive->id) == 0)
+       if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+           ata_id_lba48_enabled(drive->id) == 0))
                return -EIO;
 
-       drive->addressing = arg;
+       if (arg == 2)
+               arg = 0;
+
+       if (arg)
+               drive->dev_flags |= IDE_DFLAG_LBA48;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_LBA48;
 
        return 0;
 }
 
-ide_devset_rw(acoustic, acoustic);
-ide_devset_rw(address, addressing);
-ide_devset_rw(multcount, multcount);
-ide_devset_rw(wcache, wcache);
-
-ide_devset_rw_sync(nowerr, nowerr);
+ide_ext_devset_rw(acoustic, acoustic);
+ide_ext_devset_rw(address, addressing);
+ide_ext_devset_rw(multcount, multcount);
+ide_ext_devset_rw(wcache, wcache);
 
-#ifdef CONFIG_IDE_PROC_FS
-ide_devset_rw_field(bios_cyl, bios_cyl);
-ide_devset_rw_field(bios_head, bios_head);
-ide_devset_rw_field(bios_sect, bios_sect);
-ide_devset_rw_field(failures, failures);
-ide_devset_rw_field(lun, lun);
-ide_devset_rw_field(max_failures, max_failures);
-
-static const struct ide_proc_devset idedisk_settings[] = {
-       IDE_PROC_DEVSET(acoustic,       0,   254),
-       IDE_PROC_DEVSET(address,        0,     2),
-       IDE_PROC_DEVSET(bios_cyl,       0, 65535),
-       IDE_PROC_DEVSET(bios_head,      0,   255),
-       IDE_PROC_DEVSET(bios_sect,      0,    63),
-       IDE_PROC_DEVSET(failures,       0, 65535),
-       IDE_PROC_DEVSET(lun,            0,     7),
-       IDE_PROC_DEVSET(max_failures,   0, 65535),
-       IDE_PROC_DEVSET(multcount,      0,    16),
-       IDE_PROC_DEVSET(nowerr,         0,     1),
-       IDE_PROC_DEVSET(wcache,         0,     1),
-       { 0 },
-};
-#endif
+ide_ext_devset_rw_sync(nowerr, nowerr);
 
 static void idedisk_setup(ide_drive_t *drive)
 {
@@ -740,20 +626,20 @@ static void idedisk_setup(ide_drive_t *drive)
 
        ide_proc_register_driver(drive, idkp->driver);
 
-       if (drive->id_read == 0)
+       if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0)
                return;
 
-       if (drive->removable) {
+       if (drive->dev_flags & IDE_DFLAG_REMOVABLE) {
                /*
                 * Removable disks (eg. SYQUEST); ignore 'WD' drives
                 */
                if (m[0] != 'W' || m[1] != 'D')
-                       drive->doorlocking = 1;
+                       drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
        }
 
        (void)set_addressing(drive, 1);
 
-       if (drive->addressing == 1) {
+       if (drive->dev_flags & IDE_DFLAG_LBA48) {
                int max_s = 2048;
 
                if (max_s > hwif->rqsize)
@@ -769,7 +655,8 @@ static void idedisk_setup(ide_drive_t *drive)
        init_idedisk_capacity(drive);
 
        /* limit drive capacity to 137GB if LBA48 cannot be used */
-       if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
+       if ((drive->dev_flags & IDE_DFLAG_LBA48) == 0 &&
+           drive->capacity64 > 1ULL << 28) {
                printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
                       "%llu sectors (%llu MB)\n",
                       drive->name, (unsigned long long)drive->capacity64,
@@ -777,22 +664,23 @@ static void idedisk_setup(ide_drive_t *drive)
                drive->capacity64 = 1ULL << 28;
        }
 
-       if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && drive->addressing) {
+       if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
+           (drive->dev_flags & IDE_DFLAG_LBA48)) {
                if (drive->capacity64 > 1ULL << 28) {
                        printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode"
                                         " will be used for accessing sectors "
                                         "> %u\n", drive->name, 1 << 28);
                } else
-                       drive->addressing = 0;
+                       drive->dev_flags &= ~IDE_DFLAG_LBA48;
        }
 
        /*
         * if possible, give fdisk access to more of the drive,
         * by correcting bios_cyls:
         */
-       capacity = idedisk_capacity(drive);
+       capacity = ide_disk_capacity(drive);
 
-       if (!drive->forced_geom) {
+       if ((drive->dev_flags & IDE_DFLAG_FORCED_GEOM) == 0) {
                if (ata_id_lba48_enabled(drive->id)) {
                        /* compatibility */
                        drive->bios_sect = 63;
@@ -827,14 +715,15 @@ static void idedisk_setup(ide_drive_t *drive)
 
        /* write cache enabled? */
        if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
-               drive->wcache = 1;
+               drive->dev_flags |= IDE_DFLAG_WCACHE;
 
        set_wcache(drive, 1);
 }
 
 static void ide_cacheflush_p(ide_drive_t *drive)
 {
-       if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0)
+       if (ata_id_flush_enabled(drive->id) == 0 ||
+           (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
                return;
 
        if (do_idedisk_flushcache(drive))
@@ -918,13 +807,12 @@ static ide_driver_t idedisk_driver = {
        .resume                 = ide_disk_resume,
        .shutdown               = ide_device_shutdown,
        .version                = IDEDISK_VERSION,
-       .media                  = ide_disk,
        .do_request             = ide_do_rw_disk,
        .end_request            = ide_end_request,
        .error                  = __ide_error,
 #ifdef CONFIG_IDE_PROC_FS
-       .proc                   = idedisk_proc,
-       .settings               = idedisk_settings,
+       .proc                   = ide_disk_proc,
+       .settings               = ide_disk_settings,
 #endif
 };
 
@@ -953,15 +841,16 @@ static int idedisk_open(struct inode *inode, struct file *filp)
 
        idkp->openers++;
 
-       if (drive->removable && idkp->openers == 1) {
+       if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
                check_disk_change(inode->i_bdev);
                /*
                 * Ignore the return code from door_lock,
                 * since the open() has already succeeded,
                 * and the door_lock is irrelevant at this point.
                 */
-               if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
-                       drive->doorlocking = 0;
+               if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+                   idedisk_set_doorlock(drive, 1))
+                       drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
        }
        return 0;
 }
@@ -975,9 +864,10 @@ static int idedisk_release(struct inode *inode, struct file *filp)
        if (idkp->openers == 1)
                ide_cacheflush_p(drive);
 
-       if (drive->removable && idkp->openers == 1) {
-               if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
-                       drive->doorlocking = 0;
+       if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
+               if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) &&
+                   idedisk_set_doorlock(drive, 0))
+                       drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
        }
 
        idkp->openers--;
@@ -998,48 +888,25 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
 }
 
-static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
-{ HDIO_GET_ADDRESS,    HDIO_SET_ADDRESS,   &ide_devset_address   },
-{ HDIO_GET_MULTCOUNT,  HDIO_SET_MULTCOUNT, &ide_devset_multcount },
-{ HDIO_GET_NOWERR,     HDIO_SET_NOWERR,    &ide_devset_nowerr    },
-{ HDIO_GET_WCACHE,     HDIO_SET_WCACHE,    &ide_devset_wcache    },
-{ HDIO_GET_ACOUSTIC,   HDIO_SET_ACOUSTIC,  &ide_devset_acoustic  },
-{ 0 }
-};
-
-static int idedisk_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
-{
-       struct block_device *bdev = inode->i_bdev;
-       struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
-       ide_drive_t *drive = idkp->drive;
-       int err;
-
-       err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
-       if (err != -EOPNOTSUPP)
-               return err;
-
-       return generic_ide_ioctl(drive, file, bdev, cmd, arg);
-}
-
 static int idedisk_media_changed(struct gendisk *disk)
 {
        struct ide_disk_obj *idkp = ide_disk_g(disk);
        ide_drive_t *drive = idkp->drive;
 
        /* do not scan partitions twice if this is a removable device */
-       if (drive->attach) {
-               drive->attach = 0;
+       if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+               drive->dev_flags &= ~IDE_DFLAG_ATTACH;
                return 0;
        }
+
        /* if removable, always assume it was changed */
-       return drive->removable;
+       return !!(drive->dev_flags & IDE_DFLAG_REMOVABLE);
 }
 
 static int idedisk_revalidate_disk(struct gendisk *disk)
 {
        struct ide_disk_obj *idkp = ide_disk_g(disk);
-       set_capacity(disk, idedisk_capacity(idkp->drive));
+       set_capacity(disk, ide_disk_capacity(idkp->drive));
        return 0;
 }
 
@@ -1047,7 +914,7 @@ static struct block_device_operations idedisk_ops = {
        .owner                  = THIS_MODULE,
        .open                   = idedisk_open,
        .release                = idedisk_release,
-       .ioctl                  = idedisk_ioctl,
+       .ioctl                  = ide_disk_ioctl,
        .getgeo                 = idedisk_getgeo,
        .media_changed          = idedisk_media_changed,
        .revalidate_disk        = idedisk_revalidate_disk
@@ -1088,19 +955,20 @@ static int ide_disk_probe(ide_drive_t *drive)
        drive->driver_data = idkp;
 
        idedisk_setup(drive);
-       if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
+       if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 &&
+           (drive->head == 0 || drive->head > 16)) {
                printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
                        drive->name, drive->head);
-               drive->attach = 0;
+               drive->dev_flags &= ~IDE_DFLAG_ATTACH;
        } else
-               drive->attach = 1;
+               drive->dev_flags |= IDE_DFLAG_ATTACH;
 
        g->minors = IDE_DISK_MINORS;
        g->driverfs_dev = &drive->gendev;
        g->flags |= GENHD_FL_EXT_DEVT;
-       if (drive->removable)
-               g->flags |= GENHD_FL_REMOVABLE;
-       set_capacity(g, idedisk_capacity(drive));
+       if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+               g->flags = GENHD_FL_REMOVABLE;
+       set_capacity(g, ide_disk_capacity(drive));
        g->fops = &idedisk_ops;
        add_disk(g);
        return 0;
@@ -1122,6 +990,7 @@ static int __init idedisk_init(void)
 }
 
 MODULE_ALIAS("ide:*m-disk*");
+MODULE_ALIAS("ide-disk");
 module_init(idedisk_init);
 module_exit(idedisk_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.h b/drivers/ide/ide-disk.h
new file mode 100644 (file)
index 0000000..a82fa43
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __IDE_DISK_H
+#define __IDE_DISK_H
+
+struct ide_disk_obj {
+       ide_drive_t     *drive;
+       ide_driver_t    *driver;
+       struct gendisk  *disk;
+       struct kref     kref;
+       unsigned int    openers;        /* protected by BKL for now */
+};
+
+#define ide_disk_g(disk) \
+       container_of((disk)->private_data, struct ide_disk_obj, driver)
+
+/* ide-disk.c */
+sector_t ide_disk_capacity(ide_drive_t *);
+ide_decl_devset(address);
+ide_decl_devset(multcount);
+ide_decl_devset(nowerr);
+ide_decl_devset(wcache);
+ide_decl_devset(acoustic);
+
+/* ide-disk_ioctl.c */
+int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-disk_proc.c */
+extern ide_proc_entry_t ide_disk_proc[];
+extern const struct ide_proc_devset ide_disk_settings[];
+#endif
+
+#endif /* __IDE_DISK_H */
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
new file mode 100644 (file)
index 0000000..a6cf1a0
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
+{ HDIO_GET_ADDRESS,    HDIO_SET_ADDRESS,   &ide_devset_address   },
+{ HDIO_GET_MULTCOUNT,  HDIO_SET_MULTCOUNT, &ide_devset_multcount },
+{ HDIO_GET_NOWERR,     HDIO_SET_NOWERR,    &ide_devset_nowerr    },
+{ HDIO_GET_WCACHE,     HDIO_SET_WCACHE,    &ide_devset_wcache    },
+{ HDIO_GET_ACOUSTIC,   HDIO_SET_ACOUSTIC,  &ide_devset_acoustic  },
+{ 0 }
+};
+
+int ide_disk_ioctl(struct inode *inode, struct file *file,
+                  unsigned int cmd, unsigned long arg)
+{
+       struct block_device *bdev = inode->i_bdev;
+       struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+       ide_drive_t *drive = idkp->drive;
+       int err;
+
+       err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
+       if (err != -EOPNOTSUPP)
+               return err;
+
+       return generic_ide_ioctl(drive, file, bdev, cmd, arg);
+}
diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c
new file mode 100644 (file)
index 0000000..4724976
--- /dev/null
@@ -0,0 +1,129 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+#include "ide-disk.h"
+
+static int smart_enable(ide_drive_t *drive)
+{
+       ide_task_t args;
+       struct ide_taskfile *tf = &args.tf;
+
+       memset(&args, 0, sizeof(ide_task_t));
+       tf->feature = ATA_SMART_ENABLE;
+       tf->lbam    = ATA_SMART_LBAM_PASS;
+       tf->lbah    = ATA_SMART_LBAH_PASS;
+       tf->command = ATA_CMD_SMART;
+       args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+       return ide_no_data_taskfile(drive, &args);
+}
+
+static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
+{
+       ide_task_t args;
+       struct ide_taskfile *tf = &args.tf;
+
+       memset(&args, 0, sizeof(ide_task_t));
+       tf->feature = sub_cmd;
+       tf->nsect   = 0x01;
+       tf->lbam    = ATA_SMART_LBAM_PASS;
+       tf->lbah    = ATA_SMART_LBAH_PASS;
+       tf->command = ATA_CMD_SMART;
+       args.tf_flags   = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+       args.data_phase = TASKFILE_IN;
+       (void) smart_enable(drive);
+       return ide_raw_taskfile(drive, &args, buf, 1);
+}
+
+static int proc_idedisk_read_cache
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       ide_drive_t     *drive = (ide_drive_t *) data;
+       char            *out = page;
+       int             len;
+
+       if (drive->dev_flags & IDE_DFLAG_ID_READ)
+               len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
+       else
+               len = sprintf(out, "(none)\n");
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_capacity
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       ide_drive_t*drive = (ide_drive_t *)data;
+       int len;
+
+       len = sprintf(page, "%llu\n", (long long)ide_disk_capacity(drive));
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_smart(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data, u8 sub_cmd)
+{
+       ide_drive_t     *drive = (ide_drive_t *)data;
+       int             len = 0, i = 0;
+
+       if (get_smart_data(drive, page, sub_cmd) == 0) {
+               unsigned short *val = (unsigned short *) page;
+               char *out = (char *)val + SECTOR_SIZE;
+
+               page = out;
+               do {
+                       out += sprintf(out, "%04x%c", le16_to_cpu(*val),
+                                      (++i & 7) ? ' ' : '\n');
+                       val += 1;
+               } while (i < SECTOR_SIZE / 2);
+               len = out - page;
+       }
+
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+static int proc_idedisk_read_sv
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      ATA_SMART_READ_VALUES);
+}
+
+static int proc_idedisk_read_st
+       (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+       return proc_idedisk_read_smart(page, start, off, count, eof, data,
+                                      ATA_SMART_READ_THRESHOLDS);
+}
+
+ide_proc_entry_t ide_disk_proc[] = {
+       { "cache",        S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL },
+       { "capacity",     S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
+       { "geometry",     S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL },
+       { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL },
+       { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL },
+       { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(failures, failures);
+ide_devset_rw_field(lun, lun);
+ide_devset_rw_field(max_failures, max_failures);
+
+const struct ide_proc_devset ide_disk_settings[] = {
+       IDE_PROC_DEVSET(acoustic,       0,   254),
+       IDE_PROC_DEVSET(address,        0,     2),
+       IDE_PROC_DEVSET(bios_cyl,       0, 65535),
+       IDE_PROC_DEVSET(bios_head,      0,   255),
+       IDE_PROC_DEVSET(bios_sect,      0,    63),
+       IDE_PROC_DEVSET(failures,       0, 65535),
+       IDE_PROC_DEVSET(lun,            0,     7),
+       IDE_PROC_DEVSET(max_failures,   0, 65535),
+       IDE_PROC_DEVSET(multcount,      0,    16),
+       IDE_PROC_DEVSET(nowerr,         0,     1),
+       IDE_PROC_DEVSET(wcache,         0,     1),
+       { 0 },
+};
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
new file mode 100644 (file)
index 0000000..0903782
--- /dev/null
@@ -0,0 +1,356 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+/**
+ *     config_drive_for_dma    -       attempt to activate IDE DMA
+ *     @drive: the drive to place in DMA mode
+ *
+ *     If the drive supports at least mode 2 DMA or UDMA of any kind
+ *     then attempt to place it into DMA mode. Drives that are known to
+ *     support DMA but predate the DMA properties or that are known
+ *     to have DMA handling bugs are also set up appropriately based
+ *     on the good/bad drive lists.
+ */
+
+int config_drive_for_dma(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u16 *id = drive->id;
+
+       if (drive->media != ide_disk) {
+               if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
+                       return 0;
+       }
+
+       /*
+        * Enable DMA on any drive that has
+        * UltraDMA (mode 0/1/2/3/4/5/6) enabled
+        */
+       if ((id[ATA_ID_FIELD_VALID] & 4) &&
+           ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
+               return 1;
+
+       /*
+        * Enable DMA on any drive that has mode2 DMA
+        * (multi or single) enabled
+        */
+       if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
+               if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
+                   (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
+                       return 1;
+
+       /* Consult the list of known "good" drives */
+       if (ide_dma_good_drive(drive))
+               return 1;
+
+       return 0;
+}
+
+/**
+ *     ide_dma_host_set        -       Enable/disable DMA on a host
+ *     @drive: drive to control
+ *
+ *     Enable/disable DMA on an IDE controller following generic
+ *     bus-mastering IDE controller behaviour.
+ */
+
+void ide_dma_host_set(ide_drive_t *drive, int on)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 unit = drive->dn & 1;
+       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+       if (on)
+               dma_stat |= (1 << (5 + unit));
+       else
+               dma_stat &= ~(1 << (5 + unit));
+
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writeb(dma_stat,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+       else
+               outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_dma_host_set);
+
+/**
+ *     ide_build_dmatable      -       build IDE DMA table
+ *
+ *     ide_build_dmatable() prepares a dma request. We map the command
+ *     to get the pci bus addresses of the buffers and then build up
+ *     the PRD table that the IDE layer wants to be fed.
+ *
+ *     Most chipsets correctly interpret a length of 0x0000 as 64KB,
+ *     but at least one (e.g. CS5530) misinterprets it as zero (!).
+ *     So we break the 64KB entry into two 32KB entries instead.
+ *
+ *     Returns the number of built PRD entries if all went okay,
+ *     returns 0 otherwise.
+ *
+ *     May also be invoked from trm290.c
+ */
+
+int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       __le32 *table = (__le32 *)hwif->dmatable_cpu;
+       unsigned int is_trm290  = (hwif->chipset == ide_trm290) ? 1 : 0;
+       unsigned int count = 0;
+       int i;
+       struct scatterlist *sg;
+
+       hwif->sg_nents = ide_build_sglist(drive, rq);
+       if (hwif->sg_nents == 0)
+               return 0;
+
+       for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) {
+               u32 cur_addr, cur_len, xcount, bcount;
+
+               cur_addr = sg_dma_address(sg);
+               cur_len = sg_dma_len(sg);
+
+               /*
+                * Fill in the dma table, without crossing any 64kB boundaries.
+                * Most hardware requires 16-bit alignment of all blocks,
+                * but the trm290 requires 32-bit alignment.
+                */
+
+               while (cur_len) {
+                       if (count++ >= PRD_ENTRIES)
+                               goto use_pio_instead;
+
+                       bcount = 0x10000 - (cur_addr & 0xffff);
+                       if (bcount > cur_len)
+                               bcount = cur_len;
+                       *table++ = cpu_to_le32(cur_addr);
+                       xcount = bcount & 0xffff;
+                       if (is_trm290)
+                               xcount = ((xcount >> 2) - 1) << 16;
+                       if (xcount == 0x0000) {
+                               if (count++ >= PRD_ENTRIES)
+                                       goto use_pio_instead;
+                               *table++ = cpu_to_le32(0x8000);
+                               *table++ = cpu_to_le32(cur_addr + 0x8000);
+                               xcount = 0x8000;
+                       }
+                       *table++ = cpu_to_le32(xcount);
+                       cur_addr += bcount;
+                       cur_len -= bcount;
+               }
+       }
+
+       if (count) {
+               if (!is_trm290)
+                       *--table |= cpu_to_le32(0x80000000);
+               return count;
+       }
+
+use_pio_instead:
+       printk(KERN_ERR "%s: %s\n", drive->name,
+               count ? "DMA table too small" : "empty DMA table?");
+
+       ide_destroy_dmatable(drive);
+
+       return 0; /* revert to PIO for this request */
+}
+EXPORT_SYMBOL_GPL(ide_build_dmatable);
+
+/**
+ *     ide_dma_setup   -       begin a DMA phase
+ *     @drive: target device
+ *
+ *     Build an IDE DMA PRD (IDE speak for scatter gather table)
+ *     and then set up the DMA transfer registers for a device
+ *     that follows generic IDE PCI DMA behaviour. Controllers can
+ *     override this function if they need to
+ *
+ *     Returns 0 on success. If a PIO fallback is required then 1
+ *     is returned.
+ */
+
+int ide_dma_setup(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq = hwif->hwgroup->rq;
+       unsigned int reading;
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+       u8 dma_stat;
+
+       if (rq_data_dir(rq))
+               reading = 0;
+       else
+               reading = 1 << 3;
+
+       /* fall back to pio! */
+       if (!ide_build_dmatable(drive, rq)) {
+               ide_map_sg(drive, rq);
+               return 1;
+       }
+
+       /* PRD table */
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writel(hwif->dmatable_dma,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
+       else
+               outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
+
+       /* specify r/w */
+       if (mmio)
+               writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+       else
+               outb(reading, hwif->dma_base + ATA_DMA_CMD);
+
+       /* read DMA status for INTR & ERROR flags */
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+       /* clear INTR & ERROR flags */
+       if (mmio)
+               writeb(dma_stat | 6,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+       else
+               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+       drive->waiting_for_dma = 1;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_setup);
+
+/**
+ *     dma_timer_expiry        -       handle a DMA timeout
+ *     @drive: Drive that timed out
+ *
+ *     An IDE DMA transfer timed out. In the event of an error we ask
+ *     the driver to resolve the problem, if a DMA transfer is still
+ *     in progress we continue to wait (arguably we need to add a
+ *     secondary 'I don't care what the drive thinks' timeout here)
+ *     Finally if we have an interrupt we let it complete the I/O.
+ *     But only one time - we clear expiry and if it's still not
+ *     completed after WAIT_CMD, we error and retry in PIO.
+ *     This can occur if an interrupt is lost or due to hang or bugs.
+ */
+
+static int dma_timer_expiry(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+       printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
+               drive->name, __func__, dma_stat);
+
+       if ((dma_stat & 0x18) == 0x18)  /* BUSY Stupid Early Timer !! */
+               return WAIT_CMD;
+
+       hwif->hwgroup->expiry = NULL;   /* one free ride for now */
+
+       /* 1 dmaing, 2 error, 4 intr */
+       if (dma_stat & 2)       /* ERROR */
+               return -1;
+
+       if (dma_stat & 1)       /* DMAing */
+               return WAIT_CMD;
+
+       if (dma_stat & 4)       /* Got an Interrupt */
+               return WAIT_CMD;
+
+       return 0;       /* Status is unknown -- reset the bus */
+}
+
+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+{
+       /* issue cmd to drive */
+       ide_execute_command(drive, command, &ide_dma_intr, 2 * WAIT_CMD,
+                           dma_timer_expiry);
+}
+EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
+
+void ide_dma_start(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 dma_cmd;
+
+       /* Note that this is done *after* the cmd has
+        * been issued to the drive, as per the BM-IDE spec.
+        * The Promise Ultra33 doesn't work correctly when
+        * we do this part before issuing the drive cmd.
+        */
+       if (hwif->host_flags & IDE_HFLAG_MMIO) {
+               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+               /* start DMA */
+               writeb(dma_cmd | 1,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+       } else {
+               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+               outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+       }
+
+       wmb();
+}
+EXPORT_SYMBOL_GPL(ide_dma_start);
+
+/* returns 1 on error, 0 otherwise */
+int ide_dma_end(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+       u8 dma_stat = 0, dma_cmd = 0;
+
+       drive->waiting_for_dma = 0;
+
+       if (mmio) {
+               /* get DMA command mode */
+               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+               /* stop DMA */
+               writeb(dma_cmd & ~1,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+       } else {
+               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+               outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+       }
+
+       /* get DMA status */
+       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+       if (mmio)
+               /* clear the INTR & ERROR bits */
+               writeb(dma_stat | 6,
+                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+       else
+               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
+       /* purge DMA mappings */
+       ide_destroy_dmatable(drive);
+       /* verify good DMA status */
+       wmb();
+       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_end);
+
+/* returns 1 if dma irq issued, 0 otherwise */
+int ide_dma_test_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+       /* return 1 if INTR asserted */
+       if ((dma_stat & 4) == 4)
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ide_dma_test_irq);
+
+const struct ide_dma_ops sff_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = ide_dma_end,
+       .dma_test_irq           = ide_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+};
+EXPORT_SYMBOL_GPL(sff_dma_ops);
index ef2f1504c0d5b238a122d1bb309011a555d2cc70..fffd11717b2d169e3557c501db7c51780db5a4b1 100644 (file)
  * for supplying a Promise UDMA board & WD UDMA drive for this work!
  */
 
-#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/ide.h>
-#include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/io.h>
-#include <asm/irq.h>
-
-static const struct drive_list_entry drive_whitelist [] = {
-
+static const struct drive_list_entry drive_whitelist[] = {
        { "Micropolis 2112A"    ,       NULL            },
        { "CONNER CTMA 4000"    ,       NULL            },
        { "CONNER CTT8000-A"    ,       NULL            },
@@ -53,8 +42,7 @@ static const struct drive_list_entry drive_whitelist [] = {
        { NULL                  ,       NULL            }
 };
 
-static const struct drive_list_entry drive_blacklist [] = {
-
+static const struct drive_list_entry drive_blacklist[] = {
        { "WDC AC11000H"        ,       NULL            },
        { "WDC AC22100H"        ,       NULL            },
        { "WDC AC32500H"        ,       NULL            },
@@ -94,11 +82,11 @@ static const struct drive_list_entry drive_blacklist [] = {
  *     ide_dma_intr    -       IDE DMA interrupt handler
  *     @drive: the drive the interrupt is for
  *
- *     Handle an interrupt completing a read/write DMA transfer on an 
+ *     Handle an interrupt completing a read/write DMA transfer on an
  *     IDE device
  */
-ide_startstop_t ide_dma_intr (ide_drive_t *drive)
+
+ide_startstop_t ide_dma_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        u8 stat = 0, dma_stat = 0;
@@ -108,20 +96,19 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 
        if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
                if (!dma_stat) {
-                       struct request *rq = HWGROUP(drive)->rq;
+                       struct request *rq = hwif->hwgroup->rq;
 
                        task_end_request(drive, rq, stat);
                        return ide_stopped;
                }
-               printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
-                      drive->name, dma_stat);
+               printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n",
+                       drive->name, __func__, dma_stat);
        }
        return ide_error(drive, "dma_intr", stat);
 }
-
 EXPORT_SYMBOL_GPL(ide_dma_intr);
 
-static int ide_dma_good_drive(ide_drive_t *drive)
+int ide_dma_good_drive(ide_drive_t *drive)
 {
        return ide_in_drive_list(drive->id, drive_whitelist);
 }
@@ -139,7 +126,7 @@ static int ide_dma_good_drive(ide_drive_t *drive)
 
 int ide_build_sglist(ide_drive_t *drive, struct request *rq)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
        struct scatterlist *sg = hwif->sg_table;
 
        ide_map_sg(drive, rq);
@@ -152,106 +139,8 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
        return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
                          hwif->sg_dma_direction);
 }
-
 EXPORT_SYMBOL_GPL(ide_build_sglist);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     ide_build_dmatable      -       build IDE DMA table
- *
- *     ide_build_dmatable() prepares a dma request. We map the command
- *     to get the pci bus addresses of the buffers and then build up
- *     the PRD table that the IDE layer wants to be fed. The code
- *     knows about the 64K wrap bug in the CS5530.
- *
- *     Returns the number of built PRD entries if all went okay,
- *     returns 0 otherwise.
- *
- *     May also be invoked from trm290.c
- */
-int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       __le32 *table = (__le32 *)hwif->dmatable_cpu;
-       unsigned int is_trm290  = (hwif->chipset == ide_trm290) ? 1 : 0;
-       unsigned int count = 0;
-       int i;
-       struct scatterlist *sg;
-
-       hwif->sg_nents = i = ide_build_sglist(drive, rq);
-
-       if (!i)
-               return 0;
-
-       sg = hwif->sg_table;
-       while (i) {
-               u32 cur_addr;
-               u32 cur_len;
-
-               cur_addr = sg_dma_address(sg);
-               cur_len = sg_dma_len(sg);
-
-               /*
-                * Fill in the dma table, without crossing any 64kB boundaries.
-                * Most hardware requires 16-bit alignment of all blocks,
-                * but the trm290 requires 32-bit alignment.
-                */
-
-               while (cur_len) {
-                       if (count++ >= PRD_ENTRIES) {
-                               printk(KERN_ERR "%s: DMA table too small\n", drive->name);
-                               goto use_pio_instead;
-                       } else {
-                               u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
-                               if (bcount > cur_len)
-                                       bcount = cur_len;
-                               *table++ = cpu_to_le32(cur_addr);
-                               xcount = bcount & 0xffff;
-                               if (is_trm290)
-                                       xcount = ((xcount >> 2) - 1) << 16;
-                               else if (xcount == 0x0000) {
-       /* 
-        * Most chipsets correctly interpret a length of 0x0000 as 64KB,
-        * but at least one (e.g. CS5530) misinterprets it as zero (!).
-        * So here we break the 64KB entry into two 32KB entries instead.
-        */
-                                       if (count++ >= PRD_ENTRIES) {
-                                               printk(KERN_ERR "%s: DMA table too small\n", drive->name);
-                                               goto use_pio_instead;
-                                       }
-                                       *table++ = cpu_to_le32(0x8000);
-                                       *table++ = cpu_to_le32(cur_addr + 0x8000);
-                                       xcount = 0x8000;
-                               }
-                               *table++ = cpu_to_le32(xcount);
-                               cur_addr += bcount;
-                               cur_len -= bcount;
-                       }
-               }
-
-               sg = sg_next(sg);
-               i--;
-       }
-
-       if (count) {
-               if (!is_trm290)
-                       *--table |= cpu_to_le32(0x80000000);
-               return count;
-       }
-
-       printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
-
-use_pio_instead:
-       ide_destroy_dmatable(drive);
-
-       return 0; /* revert to PIO for this request */
-}
-
-EXPORT_SYMBOL_GPL(ide_build_dmatable);
-#endif
-
 /**
  *     ide_destroy_dmatable    -       clean up DMA mapping
  *     @drive: The drive to unmap
@@ -262,147 +151,30 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
  *     an oops as only one mapping can be live for each target at a given
  *     time.
  */
-void ide_destroy_dmatable (ide_drive_t *drive)
+
+void ide_destroy_dmatable(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
 
        dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
                     hwif->sg_dma_direction);
 }
-
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     config_drive_for_dma    -       attempt to activate IDE DMA
- *     @drive: the drive to place in DMA mode
- *
- *     If the drive supports at least mode 2 DMA or UDMA of any kind
- *     then attempt to place it into DMA mode. Drives that are known to
- *     support DMA but predate the DMA properties or that are known
- *     to have DMA handling bugs are also set up appropriately based
- *     on the good/bad drive lists.
- */
-static int config_drive_for_dma (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u16 *id = drive->id;
-
-       if (drive->media != ide_disk) {
-               if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
-                       return 0;
-       }
-
-       /*
-        * Enable DMA on any drive that has
-        * UltraDMA (mode 0/1/2/3/4/5/6) enabled
-        */
-       if ((id[ATA_ID_FIELD_VALID] & 4) &&
-           ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
-               return 1;
-
-       /*
-        * Enable DMA on any drive that has mode2 DMA
-        * (multi or single) enabled
-        */
-       if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */
-               if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
-                   (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
-                       return 1;
-
-       /* Consult the list of known "good" drives */
-       if (ide_dma_good_drive(drive))
-               return 1;
-
-       return 0;
-}
-
-/**
- *     dma_timer_expiry        -       handle a DMA timeout
- *     @drive: Drive that timed out
- *
- *     An IDE DMA transfer timed out. In the event of an error we ask
- *     the driver to resolve the problem, if a DMA transfer is still
- *     in progress we continue to wait (arguably we need to add a 
- *     secondary 'I don't care what the drive thinks' timeout here)
- *     Finally if we have an interrupt we let it complete the I/O.
- *     But only one time - we clear expiry and if it's still not
- *     completed after WAIT_CMD, we error and retry in PIO.
- *     This can occur if an interrupt is lost or due to hang or bugs.
- */
-static int dma_timer_expiry (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
-               drive->name, dma_stat);
-
-       if ((dma_stat & 0x18) == 0x18)  /* BUSY Stupid Early Timer !! */
-               return WAIT_CMD;
-
-       HWGROUP(drive)->expiry = NULL;  /* one free ride for now */
-
-       /* 1 dmaing, 2 error, 4 intr */
-       if (dma_stat & 2)       /* ERROR */
-               return -1;
-
-       if (dma_stat & 1)       /* DMAing */
-               return WAIT_CMD;
-
-       if (dma_stat & 4)       /* Got an Interrupt */
-               return WAIT_CMD;
-
-       return 0;       /* Status is unknown -- reset the bus */
-}
-
-/**
- *     ide_dma_host_set        -       Enable/disable DMA on a host
- *     @drive: drive to control
- *
- *     Enable/disable DMA on an IDE controller following generic
- *     bus-mastering IDE controller behaviour.
- */
-
-void ide_dma_host_set(ide_drive_t *drive, int on)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 unit                 = (drive->select.b.unit & 0x01);
-       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       if (on)
-               dma_stat |= (1 << (5 + unit));
-       else
-               dma_stat &= ~(1 << (5 + unit));
-
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               writeb(dma_stat,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_host_set);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF  */
-
 /**
  *     ide_dma_off_quietly     -       Generic DMA kill
  *     @drive: drive to control
  *
- *     Turn off the current DMA on this IDE controller. 
+ *     Turn off the current DMA on this IDE controller.
  */
 
 void ide_dma_off_quietly(ide_drive_t *drive)
 {
-       drive->using_dma = 0;
+       drive->dev_flags &= ~IDE_DFLAG_USING_DMA;
        ide_toggle_bounce(drive, 0);
 
        drive->hwif->dma_ops->dma_host_set(drive, 0);
 }
-
 EXPORT_SYMBOL(ide_dma_off_quietly);
 
 /**
@@ -418,7 +190,6 @@ void ide_dma_off(ide_drive_t *drive)
        printk(KERN_INFO "%s: DMA disabled\n", drive->name);
        ide_dma_off_quietly(drive);
 }
-
 EXPORT_SYMBOL(ide_dma_off);
 
 /**
@@ -430,167 +201,13 @@ EXPORT_SYMBOL(ide_dma_off);
 
 void ide_dma_on(ide_drive_t *drive)
 {
-       drive->using_dma = 1;
+       drive->dev_flags |= IDE_DFLAG_USING_DMA;
        ide_toggle_bounce(drive, 1);
 
        drive->hwif->dma_ops->dma_host_set(drive, 1);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-/**
- *     ide_dma_setup   -       begin a DMA phase
- *     @drive: target device
- *
- *     Build an IDE DMA PRD (IDE speak for scatter gather table)
- *     and then set up the DMA transfer registers for a device
- *     that follows generic IDE PCI DMA behaviour. Controllers can
- *     override this function if they need to
- *
- *     Returns 0 on success. If a PIO fallback is required then 1
- *     is returned. 
- */
-
-int ide_dma_setup(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       struct request *rq = HWGROUP(drive)->rq;
-       unsigned int reading;
-       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 dma_stat;
-
-       if (rq_data_dir(rq))
-               reading = 0;
-       else
-               reading = 1 << 3;
-
-       /* fall back to pio! */
-       if (!ide_build_dmatable(drive, rq)) {
-               ide_map_sg(drive, rq);
-               return 1;
-       }
-
-       /* PRD table */
-       if (hwif->host_flags & IDE_HFLAG_MMIO)
-               writel(hwif->dmatable_dma,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
-       else
-               outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
-
-       /* specify r/w */
-       if (mmio)
-               writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       else
-               outb(reading, hwif->dma_base + ATA_DMA_CMD);
-
-       /* read DMA status for INTR & ERROR flags */
-       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       /* clear INTR & ERROR flags */
-       if (mmio)
-               writeb(dma_stat | 6,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
-       drive->waiting_for_dma = 1;
-       return 0;
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_setup);
-
-void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
-{
-       /* issue cmd to drive */
-       ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry);
-}
-EXPORT_SYMBOL_GPL(ide_dma_exec_cmd);
-
-void ide_dma_start(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 dma_cmd;
-
-       /* Note that this is done *after* the cmd has
-        * been issued to the drive, as per the BM-IDE spec.
-        * The Promise Ultra33 doesn't work correctly when
-        * we do this part before issuing the drive cmd.
-        */
-       if (hwif->host_flags & IDE_HFLAG_MMIO) {
-               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-               /* start DMA */
-               writeb(dma_cmd | 1,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       } else {
-               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-               outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
-       }
-
-       hwif->dma = 1;
-       wmb();
-}
-
-EXPORT_SYMBOL_GPL(ide_dma_start);
-
-/* returns 1 on error, 0 otherwise */
-int __ide_dma_end (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 dma_stat = 0, dma_cmd = 0;
-
-       drive->waiting_for_dma = 0;
-
-       if (mmio) {
-               /* get DMA command mode */
-               dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-               /* stop DMA */
-               writeb(dma_cmd & ~1,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
-       } else {
-               dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
-               outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
-       }
-
-       /* get DMA status */
-       dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       if (mmio)
-               /* clear the INTR & ERROR bits */
-               writeb(dma_stat | 6,
-                      (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
-       else
-               outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       hwif->dma = 0;
-       wmb();
-       return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-
-EXPORT_SYMBOL(__ide_dma_end);
-
-/* returns 1 if dma irq issued, 0 otherwise */
-int ide_dma_test_irq(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 dma_stat             = hwif->tp_ops->read_sff_dma_status(hwif);
-
-       /* return 1 if INTR asserted */
-       if ((dma_stat & 4) == 4)
-               return 1;
-       if (!drive->waiting_for_dma)
-               printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                       drive->name, __func__);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ide_dma_test_irq);
-#else
-static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
-
-int __ide_dma_bad_drive (ide_drive_t *drive)
+int __ide_dma_bad_drive(ide_drive_t *drive)
 {
        u16 *id = drive->id;
 
@@ -602,7 +219,6 @@ int __ide_dma_bad_drive (ide_drive_t *drive)
        }
        return 0;
 }
-
 EXPORT_SYMBOL(__ide_dma_bad_drive);
 
 static const u8 xfer_mode_bases[] = {
@@ -618,7 +234,7 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode)
        const struct ide_port_ops *port_ops = hwif->port_ops;
        unsigned int mask = 0;
 
-       switch(base) {
+       switch (base) {
        case XFER_UDMA_0:
                if ((id[ATA_ID_FIELD_VALID] & 4) == 0)
                        break;
@@ -719,7 +335,6 @@ u8 ide_find_dma_mode(ide_drive_t *drive, u8 req_mode)
 
        return mode;
 }
-
 EXPORT_SYMBOL_GPL(ide_find_dma_mode);
 
 static int ide_tune_dma(ide_drive_t *drive)
@@ -727,7 +342,8 @@ static int ide_tune_dma(ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        u8 speed;
 
-       if (drive->nodma || ata_id_has_dma(drive->id) == 0)
+       if (ata_id_has_dma(drive->id) == 0 ||
+           (drive->dev_flags & IDE_DFLAG_NODMA))
                return 0;
 
        /* consult the list of known "bad" drives */
@@ -827,66 +443,59 @@ void ide_check_dma_crc(ide_drive_t *drive)
                ide_dma_on(drive);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_SFF
-void ide_dma_lost_irq (ide_drive_t *drive)
+void ide_dma_lost_irq(ide_drive_t *drive)
 {
-       printk("%s: DMA interrupt recovery\n", drive->name);
+       printk(KERN_ERR "%s: DMA interrupt recovery\n", drive->name);
 }
+EXPORT_SYMBOL_GPL(ide_dma_lost_irq);
 
-EXPORT_SYMBOL(ide_dma_lost_irq);
-
-void ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t *hwif = drive->hwif;
 
        printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
 
        if (hwif->dma_ops->dma_test_irq(drive))
                return;
 
+       ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
+
        hwif->dma_ops->dma_end(drive);
 }
-
-EXPORT_SYMBOL(ide_dma_timeout);
+EXPORT_SYMBOL_GPL(ide_dma_timeout);
 
 void ide_release_dma_engine(ide_hwif_t *hwif)
 {
        if (hwif->dmatable_cpu) {
-               struct pci_dev *pdev = to_pci_dev(hwif->dev);
+               int prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
 
-               pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
-                                   hwif->dmatable_cpu, hwif->dmatable_dma);
+               dma_free_coherent(hwif->dev, prd_size,
+                                 hwif->dmatable_cpu, hwif->dmatable_dma);
                hwif->dmatable_cpu = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(ide_release_dma_engine);
 
 int ide_allocate_dma_engine(ide_hwif_t *hwif)
 {
-       struct pci_dev *pdev = to_pci_dev(hwif->dev);
+       int prd_size;
 
-       hwif->dmatable_cpu = pci_alloc_consistent(pdev,
-                                                 PRD_ENTRIES * PRD_BYTES,
-                                                 &hwif->dmatable_dma);
+       if (hwif->prd_max_nents == 0)
+               hwif->prd_max_nents = PRD_ENTRIES;
+       if (hwif->prd_ent_size == 0)
+               hwif->prd_ent_size = PRD_BYTES;
 
-       if (hwif->dmatable_cpu)
-               return 0;
+       prd_size = hwif->prd_max_nents * hwif->prd_ent_size;
 
-       printk(KERN_ERR "%s: -- Error, unable to allocate DMA table.\n",
+       hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev, prd_size,
+                                               &hwif->dmatable_dma,
+                                               GFP_ATOMIC);
+       if (hwif->dmatable_cpu == NULL) {
+               printk(KERN_ERR "%s: unable to allocate PRD table\n",
                        hwif->name);
+               return -ENOMEM;
+       }
 
-       return 1;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
-
-const struct ide_dma_ops sff_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = ide_dma_start,
-       .dma_end                = __ide_dma_end,
-       .dma_test_irq           = ide_dma_test_irq,
-       .dma_timeout            = ide_dma_timeout,
-       .dma_lost_irq           = ide_dma_lost_irq,
-};
-EXPORT_SYMBOL_GPL(sff_dma_ops);
-#endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
index d36f155470a49dfcafef2ee19dbb9a3835475c9b..cf0aa25470ee87368291dbf8614d2b67020315e9 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #define DRV_NAME "ide-floppy"
+#define PFX DRV_NAME ": "
 
 #define IDEFLOPPY_VERSION "1.00"
 
 
 #include "ide-floppy.h"
 
-/* define to see debug info */
-#define IDEFLOPPY_DEBUG_LOG            0
+/* module parameters */
+static unsigned long debug_mask;
+module_param(debug_mask, ulong, 0644);
 
-/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
-#define IDEFLOPPY_DEBUG(fmt, args...)
+/* define to see debug info */
+#define IDEFLOPPY_DEBUG_LOG    0
 
 #if IDEFLOPPY_DEBUG_LOG
-#define debug_log(fmt, args...) \
-       printk(KERN_INFO "ide-floppy: " fmt, ## args)
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
 #else
-#define debug_log(fmt, args...) do {} while (0)
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
 #endif
 
 /*
 #define CAPACITY_CURRENT       0x02
 #define CAPACITY_NO_CARTRIDGE  0x03
 
-#define IDEFLOPPY_TICKS_DELAY  HZ/20   /* default delay for ZIP 100 (50ms) */
+/*
+ * The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
+ * was apparently being deasserted before the unit was ready to receive data.
+ */
+#define IDEFLOPPY_PC_DELAY     (HZ/20) /* default delay for ZIP 100 (50ms) */
 
 /* Error code returned in rq->errors to the higher part of the driver. */
 #define        IDEFLOPPY_ERROR_GENERAL         101
 
 static DEFINE_MUTEX(idefloppy_ref_mutex);
 
-#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
-
-#define ide_floppy_g(disk) \
-       container_of((disk)->private_data, struct ide_floppy_obj, driver)
-
 static void idefloppy_cleanup_obj(struct kref *);
 
 static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
@@ -92,7 +92,7 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
        struct ide_floppy_obj *floppy = NULL;
 
        mutex_lock(&idefloppy_ref_mutex);
-       floppy = ide_floppy_g(disk);
+       floppy = ide_drv_g(disk, ide_floppy_obj);
        if (floppy) {
                if (ide_device_get(floppy->drive))
                        floppy = NULL;
@@ -123,13 +123,21 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
        struct request *rq = HWGROUP(drive)->rq;
        int error;
 
-       debug_log("Reached %s\n", __func__);
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 
        switch (uptodate) {
-       case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
-       case 1: error = 0; break;
-       default: error = uptodate;
+       case 0:
+               error = IDEFLOPPY_ERROR_GENERAL;
+               break;
+
+       case 1:
+               error = 0;
+               break;
+
+       default:
+               error = uptodate;
        }
+
        if (error)
                floppy->failed_pc = NULL;
        /* Why does this happen? */
@@ -156,13 +164,13 @@ static void idefloppy_update_buffers(ide_drive_t *drive,
                idefloppy_end_request(drive, 1, 0);
 }
 
-static void ide_floppy_callback(ide_drive_t *drive)
+static void ide_floppy_callback(ide_drive_t *drive, int dsc)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
-       struct ide_atapi_pc *pc = floppy->pc;
+       struct ide_atapi_pc *pc = drive->pc;
        int uptodate = pc->error ? 0 : 1;
 
-       debug_log("Reached %s\n", __func__);
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 
        if (floppy->failed_pc == pc)
                floppy->failed_pc = NULL;
@@ -171,7 +179,7 @@ static void ide_floppy_callback(ide_drive_t *drive)
            (pc->rq && blk_pc_request(pc->rq)))
                uptodate = 1; /* FIXME */
        else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
-               u8 *buf = floppy->pc->buf;
+               u8 *buf = pc->buf;
 
                if (!pc->error) {
                        floppy->sense_key = buf[2] & 0x0F;
@@ -181,99 +189,20 @@ static void ide_floppy_callback(ide_drive_t *drive)
                                (u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
 
                        if (floppy->failed_pc)
-                               debug_log("pc = %x, ", floppy->failed_pc->c[0]);
+                               ide_debug_log(IDE_DBG_PC, "pc = %x, ",
+                                             floppy->failed_pc->c[0]);
 
-                       debug_log("sense key = %x, asc = %x, ascq = %x\n",
-                                 floppy->sense_key, floppy->asc, floppy->ascq);
+                       ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
+                                     "ascq = %x\n", floppy->sense_key,
+                                     floppy->asc, floppy->ascq);
                } else
-                       printk(KERN_ERR "Error in REQUEST SENSE itself - "
-                                       "Aborting request!\n");
+                       printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
+                              "Aborting request!\n");
        }
 
        idefloppy_end_request(drive, uptodate, 0);
 }
 
-void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
-       ide_init_pc(pc);
-       pc->c[0] = GPCMD_REQUEST_SENSE;
-       pc->c[4] = 255;
-       pc->req_xfer = 18;
-}
-
-/*
- * Called when an error was detected during the last packet command. We queue a
- * request sense packet command in the head of the request list.
- */
-static void idefloppy_retry_pc(ide_drive_t *drive)
-{
-       struct ide_floppy_obj *floppy = drive->driver_data;
-       struct request *rq = &floppy->request_sense_rq;
-       struct ide_atapi_pc *pc = &floppy->request_sense_pc;
-
-       (void)ide_read_error(drive);
-       ide_floppy_create_request_sense_cmd(pc);
-       ide_queue_pc_head(drive, floppy->disk, pc, rq);
-}
-
-/* The usual interrupt handler called during a packet command. */
-static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-
-       return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr,
-                          WAIT_FLOPPY_CMD, NULL, idefloppy_update_buffers,
-                          idefloppy_retry_pc, NULL, ide_io_buffers);
-}
-
-/*
- * What we have here is a classic case of a top half / bottom half interrupt
- * service routine. In interrupt mode, the device sends an interrupt to signal
- * that it is ready to receive a packet. However, we need to delay about 2-3
- * ticks before issuing the packet or we gets in trouble.
- */
-static int idefloppy_transfer_pc(ide_drive_t *drive)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-
-       /* Send the actual packet */
-       drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
-
-       /* Timeout for the packet command */
-       return WAIT_FLOPPY_CMD;
-}
-
-/*
- * Called as an interrupt (or directly). When the device says it's ready for a
- * packet, we schedule the packet transfer to occur about 2-3 ticks later in
- * transfer_pc.
- */
-static ide_startstop_t idefloppy_start_pc_transfer(ide_drive_t *drive)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-       struct ide_atapi_pc *pc = floppy->pc;
-       ide_expiry_t *expiry;
-       unsigned int timeout;
-
-       /*
-        * The following delay solves a problem with ATAPI Zip 100 drives
-        * where the Busy flag was apparently being deasserted before the
-        * unit was ready to receive data. This was happening on a
-        * 1200 MHz Athlon system. 10/26/01 25msec is too short,
-        * 40 and 50msec work well. idefloppy_pc_intr will not be actually
-        * used until after the packet is moved in about 50 msec.
-        */
-       if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
-               timeout = floppy->ticks;
-               expiry = &idefloppy_transfer_pc;
-       } else {
-               timeout = WAIT_FLOPPY_CMD;
-               expiry = NULL;
-       }
-
-       return ide_transfer_pc(drive, pc, idefloppy_pc_intr, timeout, expiry);
-}
-
 static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
                                    struct ide_atapi_pc *pc)
 {
@@ -283,7 +212,7 @@ static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
            floppy->ascq      == 0x00)
                return;
 
-       printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
+       printk(KERN_ERR PFX "%s: I/O error, pc = %2x, key = %2x, "
                        "asc = %2x, ascq = %2x\n",
                        floppy->drive->name, pc->c[0], floppy->sense_key,
                        floppy->asc, floppy->ascq);
@@ -298,8 +227,9 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
        if (floppy->failed_pc == NULL &&
            pc->c[0] != GPCMD_REQUEST_SENSE)
                floppy->failed_pc = pc;
+
        /* Set the current packet command */
-       floppy->pc = pc;
+       drive->pc = pc;
 
        if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
                if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
@@ -308,16 +238,15 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
                pc->error = IDEFLOPPY_ERROR_GENERAL;
 
                floppy->failed_pc = NULL;
-               drive->pc_callback(drive);
+               drive->pc_callback(drive, 0);
                return ide_stopped;
        }
 
-       debug_log("Retry number - %d\n", pc->retries);
+       ide_debug_log(IDE_DBG_FUNC, "%s: Retry #%d\n", __func__, pc->retries);
 
        pc->retries++;
 
-       return ide_issue_pc(drive, pc, idefloppy_start_pc_transfer,
-                           WAIT_FLOPPY_CMD, NULL);
+       return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
 }
 
 void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
@@ -347,23 +276,23 @@ void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
                length += 32;
                break;
        default:
-               printk(KERN_ERR "ide-floppy: unsupported page code "
-                               "in create_mode_sense_cmd\n");
+               printk(KERN_ERR PFX "unsupported page code in %s\n", __func__);
        }
        put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
        pc->req_xfer = length;
 }
 
-static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
+static void idefloppy_create_rw_cmd(ide_drive_t *drive,
                                    struct ide_atapi_pc *pc, struct request *rq,
                                    unsigned long sector)
 {
+       idefloppy_floppy_t *floppy = drive->driver_data;
        int block = sector / floppy->bs_factor;
        int blocks = rq->nr_sectors / floppy->bs_factor;
        int cmd = rq_data_dir(rq);
 
-       debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
-               block, blocks);
+       ide_debug_log(IDE_DBG_FUNC, "%s: block: %d, blocks: %d\n", __func__,
+                     block, blocks);
 
        ide_init_pc(pc);
        pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
@@ -408,41 +337,42 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
        struct ide_atapi_pc *pc;
        unsigned long block = (unsigned long)block_s;
 
-       debug_log("%s: dev: %s, cmd: 0x%x, cmd_type: %x, errors: %d\n",
-                 __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
-                 rq->cmd[0], rq->cmd_type, rq->errors);
+       ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
+                     "errors: %d\n",
+                     __func__, rq->rq_disk ? rq->rq_disk->disk_name : "?",
+                     rq->cmd[0], rq->cmd_type, rq->errors);
 
-       debug_log("%s: sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",
-                 __func__, (long)rq->sector, rq->nr_sectors,
-                 rq->current_nr_sectors);
+       ide_debug_log(IDE_DBG_FUNC, "%s: sector: %ld, nr_sectors: %ld, "
+                     "current_nr_sectors: %d\n",
+                     __func__, (long)rq->sector, rq->nr_sectors,
+                     rq->current_nr_sectors);
 
        if (rq->errors >= ERROR_MAX) {
                if (floppy->failed_pc)
                        ide_floppy_report_error(floppy, floppy->failed_pc);
                else
-                       printk(KERN_ERR "ide-floppy: %s: I/O error\n",
-                               drive->name);
+                       printk(KERN_ERR PFX "%s: I/O error\n", drive->name);
+
                idefloppy_end_request(drive, 0, 0);
                return ide_stopped;
        }
        if (blk_fs_request(rq)) {
                if (((long)rq->sector % floppy->bs_factor) ||
                    (rq->nr_sectors % floppy->bs_factor)) {
-                       printk(KERN_ERR "%s: unsupported r/w request size\n",
-                                       drive->name);
+                       printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
+                               drive->name);
                        idefloppy_end_request(drive, 0, 0);
                        return ide_stopped;
                }
                pc = &floppy->queued_pc;
-               idefloppy_create_rw_cmd(floppy, pc, rq, block);
+               idefloppy_create_rw_cmd(drive, pc, rq, block);
        } else if (blk_special_request(rq)) {
                pc = (struct ide_atapi_pc *) rq->buffer;
        } else if (blk_pc_request(rq)) {
                pc = &floppy->queued_pc;
                idefloppy_blockpc_cmd(floppy, pc, rq);
        } else {
-               blk_dump_rq_flags(rq,
-                       "ide-floppy: unsupported command in queue");
+               blk_dump_rq_flags(rq, PFX "unsupported command in queue");
                idefloppy_end_request(drive, 0, 0);
                return ide_stopped;
        }
@@ -475,8 +405,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
        ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
 
        if (ide_queue_pc_tail(drive, disk, &pc)) {
-               printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
-                               " parameters\n");
+               printk(KERN_ERR PFX "Can't get flexible disk page params\n");
                return 1;
        }
 
@@ -499,7 +428,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
        capacity = cyls * heads * sectors * sector_size;
 
        if (memcmp(page, &floppy->flexible_disk_page, 32))
-               printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
+               printk(KERN_INFO PFX "%s: %dkB, %d/%d/%d CHS, %d kBps, "
                                "%d sector size, %d rpm\n",
                                drive->name, capacity / 1024, cyls, heads,
                                sectors, transfer_rate / 8, sector_size, rpm);
@@ -511,7 +440,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
        lba_capacity = floppy->blocks * floppy->block_size;
 
        if (capacity < lba_capacity) {
-               printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
+               printk(KERN_NOTICE PFX "%s: The disk reports a capacity of %d "
                        "bytes, but the drive only handles %d\n",
                        drive->name, lba_capacity, capacity);
                floppy->blocks = floppy->block_size ?
@@ -541,7 +470,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
 
        ide_floppy_create_read_capacity_cmd(&pc);
        if (ide_queue_pc_tail(drive, disk, &pc)) {
-               printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+               printk(KERN_ERR PFX "Can't get floppy parameters\n");
                return 1;
        }
        header_len = pc.buf[3];
@@ -554,8 +483,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
                blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
                length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
 
-               debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
-                               i, blocks * length / 1024, blocks, length);
+               ide_debug_log(IDE_DBG_PROBE, "Descriptor %d: %dkB, %d blocks, "
+                             "%d sector size\n",
+                             i, blocks * length / 1024, blocks, length);
 
                if (i)
                        continue;
@@ -575,23 +505,24 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
                case CAPACITY_CURRENT:
                        /* Normal Zip/LS-120 disks */
                        if (memcmp(cap_desc, &floppy->cap_desc, 8))
-                               printk(KERN_INFO "%s: %dkB, %d blocks, %d "
-                                       "sector size\n", drive->name,
-                                       blocks * length / 1024, blocks, length);
+                               printk(KERN_INFO PFX "%s: %dkB, %d blocks, %d "
+                                      "sector size\n",
+                                      drive->name, blocks * length / 1024,
+                                      blocks, length);
                        memcpy(&floppy->cap_desc, cap_desc, 8);
 
                        if (!length || length % 512) {
-                               printk(KERN_NOTICE "%s: %d bytes block size "
-                                       "not supported\n", drive->name, length);
+                               printk(KERN_NOTICE PFX "%s: %d bytes block size"
+                                      not supported\n", drive->name, length);
                        } else {
                                floppy->blocks = blocks;
                                floppy->block_size = length;
                                floppy->bs_factor = length / 512;
                                if (floppy->bs_factor != 1)
-                                       printk(KERN_NOTICE "%s: warning: non "
-                                               "512 bytes block size not "
-                                               "fully supported\n",
-                                               drive->name);
+                                       printk(KERN_NOTICE PFX "%s: Warning: "
+                                              "non 512 bytes block size not "
+                                              "fully supported\n",
+                                              drive->name);
                                rc = 0;
                        }
                        break;
@@ -600,15 +531,16 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
                         * This is a KERN_ERR so it appears on screen
                         * for the user to see
                         */
-                       printk(KERN_ERR "%s: No disk in drive\n", drive->name);
+                       printk(KERN_ERR PFX "%s: No disk in drive\n",
+                              drive->name);
                        break;
                case CAPACITY_INVALID:
-                       printk(KERN_ERR "%s: Invalid capacity for disk "
+                       printk(KERN_ERR PFX "%s: Invalid capacity for disk "
                                "in drive\n", drive->name);
                        break;
                }
-               debug_log("Descriptor 0 Code: %d\n",
-                         pc.buf[desc_start + 4] & 0x03);
+               ide_debug_log(IDE_DBG_PROBE, "Descriptor 0 Code: %d\n",
+                             pc.buf[desc_start + 4] & 0x03);
        }
 
        /* Clik! disk does not support get_flexible_disk_page */
@@ -620,7 +552,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
        return rc;
 }
 
-static sector_t idefloppy_capacity(ide_drive_t *drive)
+sector_t ide_floppy_capacity(ide_drive_t *drive)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
        unsigned long capacity = floppy->blocks * floppy->bs_factor;
@@ -628,46 +560,14 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
        return capacity;
 }
 
-#ifdef CONFIG_IDE_PROC_FS
-ide_devset_rw_field(bios_cyl, bios_cyl);
-ide_devset_rw_field(bios_head, bios_head);
-ide_devset_rw_field(bios_sect, bios_sect);
-
-static int get_ticks(ide_drive_t *drive)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-       return floppy->ticks;
-}
-
-static int set_ticks(ide_drive_t *drive, int arg)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-       floppy->ticks = arg;
-       return 0;
-}
-
-IDE_DEVSET(ticks, DS_SYNC, get_ticks, set_ticks);
-
-static const struct ide_proc_devset idefloppy_settings[] = {
-       IDE_PROC_DEVSET(bios_cyl,  0, 1023),
-       IDE_PROC_DEVSET(bios_head, 0,  255),
-       IDE_PROC_DEVSET(bios_sect, 0,   63),
-       IDE_PROC_DEVSET(ticks,     0,  255),
-       { 0 },
-};
-#endif
-
 static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
 {
        u16 *id = drive->id;
-       u8 gcw[2];
-
-       *((u16 *)&gcw) = id[ATA_ID_CONFIG];
 
-       drive->pc_callback = ide_floppy_callback;
+       drive->pc_callback       = ide_floppy_callback;
+       drive->pc_update_buffers = idefloppy_update_buffers;
+       drive->pc_io_buffers     = ide_io_buffers;
 
-       if (((gcw[0] & 0x60) >> 5) == 1)
-               drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
        /*
         * We used to check revisions here. At this point however I'm giving up.
         * Just assume they are all broken, its easier.
@@ -680,7 +580,7 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
        if (!strncmp((char *)&id[ATA_ID_PROD], "IOMEGA ZIP 100 ATAPI", 20)) {
                drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
                /* This value will be visible in the /proc/ide/hdx/settings */
-               floppy->ticks = IDEFLOPPY_TICKS_DELAY;
+               drive->pc_delay = IDEFLOPPY_PC_DELAY;
                blk_queue_max_sectors(drive->queue, 64);
        }
 
@@ -714,7 +614,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
 
 static void idefloppy_cleanup_obj(struct kref *kref)
 {
-       struct ide_floppy_obj *floppy = to_ide_floppy(kref);
+       struct ide_floppy_obj *floppy = to_ide_drv(kref, ide_floppy_obj);
        ide_drive_t *drive = floppy->drive;
        struct gendisk *g = floppy->disk;
 
@@ -724,24 +624,6 @@ static void idefloppy_cleanup_obj(struct kref *kref)
        kfree(floppy);
 }
 
-#ifdef CONFIG_IDE_PROC_FS
-static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
-               int count, int *eof, void *data)
-{
-       ide_drive_t*drive = (ide_drive_t *)data;
-       int len;
-
-       len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive));
-       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-
-static ide_proc_entry_t idefloppy_proc[] = {
-       { "capacity",   S_IFREG|S_IRUGO, proc_idefloppy_read_capacity,  NULL },
-       { "geometry",   S_IFREG|S_IRUGO, proc_ide_read_geometry,        NULL },
-       { NULL, 0, NULL, NULL }
-};
-#endif /* CONFIG_IDE_PROC_FS */
-
 static int ide_floppy_probe(ide_drive_t *);
 
 static ide_driver_t idefloppy_driver = {
@@ -753,13 +635,12 @@ static ide_driver_t idefloppy_driver = {
        .probe                  = ide_floppy_probe,
        .remove                 = ide_floppy_remove,
        .version                = IDEFLOPPY_VERSION,
-       .media                  = ide_floppy,
        .do_request             = idefloppy_do_request,
        .end_request            = idefloppy_end_request,
        .error                  = __ide_error,
 #ifdef CONFIG_IDE_PROC_FS
-       .proc                   = idefloppy_proc,
-       .settings               = idefloppy_settings,
+       .proc                   = ide_floppy_proc,
+       .settings               = ide_floppy_settings,
 #endif
 };
 
@@ -770,14 +651,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
        ide_drive_t *drive;
        int ret = 0;
 
-       debug_log("Reached %s\n", __func__);
-
        floppy = ide_floppy_get(disk);
        if (!floppy)
                return -ENXIO;
 
        drive = floppy->drive;
 
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
+
        floppy->openers++;
 
        if (floppy->openers == 1) {
@@ -822,10 +703,10 @@ out_put_floppy:
 static int idefloppy_release(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+       struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
        ide_drive_t *drive = floppy->drive;
 
-       debug_log("Reached %s\n", __func__);
+       ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 
        if (floppy->openers == 1) {
                ide_set_media_lock(drive, disk, 0);
@@ -841,7 +722,8 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
 
 static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+       struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
+                                                    ide_floppy_obj);
        ide_drive_t *drive = floppy->drive;
 
        geo->heads = drive->bios_head;
@@ -850,64 +732,15 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
 }
 
-static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
-                              unsigned long arg, unsigned int cmd)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
-       struct gendisk *disk = floppy->disk;
-       int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
-
-       if (floppy->openers > 1)
-               return -EBUSY;
-
-       ide_set_media_lock(drive, disk, prevent);
-
-       if (cmd == CDROMEJECT)
-               ide_do_start_stop(drive, disk, 2);
-
-       return 0;
-}
-
-static int idefloppy_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
-{
-       struct block_device *bdev = inode->i_bdev;
-       struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
-       ide_drive_t *drive = floppy->drive;
-       struct ide_atapi_pc pc;
-       void __user *argp = (void __user *)arg;
-       int err;
-
-       if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
-               return ide_floppy_lockdoor(drive, &pc, arg, cmd);
-
-       err = ide_floppy_format_ioctl(drive, file, cmd, argp);
-       if (err != -ENOTTY)
-               return err;
-
-       /*
-        * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
-        * and CDROM_SEND_PACKET (legacy) ioctls
-        */
-       if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
-               err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
-                                       bdev->bd_disk, cmd, argp);
-
-       if (err == -ENOTTY)
-               err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
-       return err;
-}
-
 static int idefloppy_media_changed(struct gendisk *disk)
 {
-       struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+       struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
        ide_drive_t *drive = floppy->drive;
        int ret;
 
        /* do not scan partitions twice if this is a removable device */
-       if (drive->attach) {
-               drive->attach = 0;
+       if (drive->dev_flags & IDE_DFLAG_ATTACH) {
+               drive->dev_flags &= ~IDE_DFLAG_ATTACH;
                return 0;
        }
        ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
@@ -917,8 +750,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
 
 static int idefloppy_revalidate_disk(struct gendisk *disk)
 {
-       struct ide_floppy_obj *floppy = ide_floppy_g(disk);
-       set_capacity(disk, idefloppy_capacity(floppy->drive));
+       struct ide_floppy_obj *floppy = ide_drv_g(disk, ide_floppy_obj);
+       set_capacity(disk, ide_floppy_capacity(floppy->drive));
        return 0;
 }
 
@@ -926,7 +759,7 @@ static struct block_device_operations idefloppy_ops = {
        .owner                  = THIS_MODULE,
        .open                   = idefloppy_open,
        .release                = idefloppy_release,
-       .ioctl                  = idefloppy_ioctl,
+       .ioctl                  = ide_floppy_ioctl,
        .getgeo                 = idefloppy_getgeo,
        .media_changed          = idefloppy_media_changed,
        .revalidate_disk        = idefloppy_revalidate_disk
@@ -944,14 +777,14 @@ static int ide_floppy_probe(ide_drive_t *drive)
                goto failed;
 
        if (!ide_check_atapi_device(drive, DRV_NAME)) {
-               printk(KERN_ERR "ide-floppy: %s: not supported by this version"
-                               " of ide-floppy\n", drive->name);
+               printk(KERN_ERR PFX "%s: not supported by this version of "
+                      DRV_NAME "\n", drive->name);
                goto failed;
        }
        floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
        if (!floppy) {
-               printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
-                               " structure\n", drive->name);
+               printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
+                      drive->name);
                goto failed;
        }
 
@@ -971,13 +804,16 @@ static int ide_floppy_probe(ide_drive_t *drive)
 
        drive->driver_data = floppy;
 
+       drive->debug_mask = debug_mask;
+
        idefloppy_setup(drive, floppy);
+       drive->dev_flags |= IDE_DFLAG_ATTACH;
 
        g->minors = 1 << PARTN_BITS;
        g->driverfs_dev = &drive->gendev;
-       g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
+       if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
+               g->flags = GENHD_FL_REMOVABLE;
        g->fops = &idefloppy_ops;
-       drive->attach = 1;
        add_disk(g);
        return 0;
 
@@ -994,7 +830,7 @@ static void __exit idefloppy_exit(void)
 
 static int __init idefloppy_init(void)
 {
-       printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
+       printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
        return driver_register(&idefloppy_driver.gen_driver);
 }
 
index ecadc2bc322dc9904acb4507281db91d1138e9a7..17cf865e583d28edd7890b3e874bcd0cdec561ce 100644 (file)
@@ -13,20 +13,14 @@ typedef struct ide_floppy_obj {
        struct kref     kref;
        unsigned int    openers;        /* protected by BKL for now */
 
-       /* Current packet command */
-       struct ide_atapi_pc *pc;
        /* Last failed packet command */
        struct ide_atapi_pc *failed_pc;
        /* used for blk_{fs,pc}_request() requests */
        struct ide_atapi_pc queued_pc;
 
-       struct ide_atapi_pc request_sense_pc;
-       struct request request_sense_rq;
-
        /* Last error information */
        u8 sense_key, asc, ascq;
-       /* delay this long before sending packet command */
-       u8 ticks;
+
        int progress_indication;
 
        /* Device information */
@@ -54,10 +48,15 @@ typedef struct ide_floppy_obj {
 /* ide-floppy.c */
 void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
 void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
-void ide_floppy_create_request_sense_cmd(struct ide_atapi_pc *);
+sector_t ide_floppy_capacity(ide_drive_t *);
 
 /* ide-floppy_ioctl.c */
-int ide_floppy_format_ioctl(ide_drive_t *, struct file *, unsigned int,
-                           void __user *);
+int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
+
+#ifdef CONFIG_IDE_PROC_FS
+/* ide-floppy_proc.c */
+extern ide_proc_entry_t ide_floppy_proc[];
+extern const struct ide_proc_devset ide_floppy_settings[];
+#endif
 
 #endif /*__IDE_FLOPPY_H */
index 5ffc4512d14bbeb02cd6d853603e4564d27df9b5..a3a7a0809e2bdf5edba01c3c93c0f2b6cd467d8a 100644 (file)
@@ -195,7 +195,7 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
        int progress_indication = 0x10000;
 
        if (drive->atapi_flags & IDE_AFLAG_SRFP) {
-               ide_floppy_create_request_sense_cmd(&pc);
+               ide_create_request_sense_cmd(drive, &pc);
                if (ide_queue_pc_tail(drive, floppy->disk, &pc))
                        return -EIO;
 
@@ -223,8 +223,26 @@ static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
        return 0;
 }
 
-int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
-                           unsigned int cmd, void __user *argp)
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+                              unsigned long arg, unsigned int cmd)
+{
+       idefloppy_floppy_t *floppy = drive->driver_data;
+       struct gendisk *disk = floppy->disk;
+       int prevent = (arg && cmd != CDROMEJECT) ? 1 : 0;
+
+       if (floppy->openers > 1)
+               return -EBUSY;
+
+       ide_set_media_lock(drive, disk, prevent);
+
+       if (cmd == CDROMEJECT)
+               ide_do_start_stop(drive, disk, 2);
+
+       return 0;
+}
+
+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
+                                  unsigned int cmd, void __user *argp)
 {
        switch (cmd) {
        case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
@@ -241,3 +259,35 @@ int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
                return -ENOTTY;
        }
 }
+
+int ide_floppy_ioctl(struct inode *inode, struct file *file,
+                   unsigned int cmd, unsigned long arg)
+{
+       struct block_device *bdev = inode->i_bdev;
+       struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
+                                                    ide_floppy_obj);
+       ide_drive_t *drive = floppy->drive;
+       struct ide_atapi_pc pc;
+       void __user *argp = (void __user *)arg;
+       int err;
+
+       if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
+               return ide_floppy_lockdoor(drive, &pc, arg, cmd);
+
+       err = ide_floppy_format_ioctl(drive, file, cmd, argp);
+       if (err != -ENOTTY)
+               return err;
+
+       /*
+        * skip SCSI_IOCTL_SEND_COMMAND (deprecated)
+        * and CDROM_SEND_PACKET (legacy) ioctls
+        */
+       if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
+               err = scsi_cmd_ioctl(file, bdev->bd_disk->queue,
+                                       bdev->bd_disk, cmd, argp);
+
+       if (err == -ENOTTY)
+               err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+
+       return err;
+}
diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c
new file mode 100644 (file)
index 0000000..76f0c6c
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+#include "ide-floppy.h"
+
+static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
+               int count, int *eof, void *data)
+{
+       ide_drive_t*drive = (ide_drive_t *)data;
+       int len;
+
+       len = sprintf(page, "%llu\n", (long long)ide_floppy_capacity(drive));
+       PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+
+ide_proc_entry_t ide_floppy_proc[] = {
+       { "capacity",   S_IFREG|S_IRUGO, proc_idefloppy_read_capacity,  NULL },
+       { "geometry",   S_IFREG|S_IRUGO, proc_ide_read_geometry,        NULL },
+       { NULL, 0, NULL, NULL }
+};
+
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(ticks, pc_delay);
+
+const struct ide_proc_devset ide_floppy_settings[] = {
+       IDE_PROC_DEVSET(bios_cyl,  0, 1023),
+       IDE_PROC_DEVSET(bios_head, 0,  255),
+       IDE_PROC_DEVSET(bios_sect, 0,   63),
+       IDE_PROC_DEVSET(ticks,     0,  255),
+       { 0 },
+};
index 0a3cb0c33ae579533ad33eb46c7d9cbfe3c74276..81a5282ce1eb06e74a93168e33cd94e9d5f1ac52 100644 (file)
@@ -137,15 +137,10 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary)
 
 static int __init ide_generic_init(void)
 {
-       hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
-       struct ide_host *host;
+       hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
        unsigned long io_addr;
-       int i, rc, primary = 0, secondary = 0;
+       int i, rc = 0, primary = 0, secondary = 0;
 
-#ifdef CONFIG_MIPS
-       if (!ide_probe_legacy())
-               return -ENODEV;
-#endif
        ide_generic_check_pci_legacy_iobases(&primary, &secondary);
 
        if (!probe_mask) {
@@ -161,13 +156,9 @@ static int __init ide_generic_init(void)
                printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports "
                        "upon user request\n");
 
-       memset(hws, 0, sizeof(hw_regs_t *) * MAX_HWIFS);
-
        for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) {
                io_addr = legacy_bases[i];
 
-               hws[i] = NULL;
-
                if ((probe_mask & (1 << i)) && io_addr) {
                        if (!request_region(io_addr, 8, DRV_NAME)) {
                                printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX "
@@ -184,45 +175,27 @@ static int __init ide_generic_init(void)
                                continue;
                        }
 
-                       memset(&hw[i], 0, sizeof(hw[i]));
-                       ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
+                       memset(&hw, 0, sizeof(hw));
+                       ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
 #ifdef CONFIG_IA64
-                       hw[i].irq = isa_irq_to_vector(legacy_irqs[i]);
+                       hw.irq = isa_irq_to_vector(legacy_irqs[i]);
 #else
-                       hw[i].irq = legacy_irqs[i];
+                       hw.irq = legacy_irqs[i];
 #endif
-                       hw[i].chipset = ide_generic;
+                       hw.chipset = ide_generic;
 
-                       hws[i] = &hw[i];
+                       rc = ide_host_add(NULL, hws, NULL);
+                       if (rc) {
+                               release_region(io_addr + 0x206, 1);
+                               release_region(io_addr, 8);
+                       }
                }
        }
 
-       host = ide_host_alloc_all(NULL, hws);
-       if (host == NULL) {
-               rc = -ENOMEM;
-               goto err;
-       }
-
-       rc = ide_host_register(host, NULL, hws);
-       if (rc)
-               goto err_free;
-
        if (ide_generic_sysfs_init())
                printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
                                         "class\n");
 
-       return 0;
-err_free:
-       ide_host_free(host);
-err:
-       for (i = 0; i < MAX_HWIFS; i++) {
-               if (hws[i] == NULL)
-                       continue;
-
-               io_addr = hws[i]->io_ports.data_addr;
-               release_region(io_addr + 0x206, 1);
-               release_region(io_addr, 8);
-       }
        return rc;
 }
 
index 1c51949833be5ed17e71bde14a0fa8b55b0e47ee..77c6eaeacefafaf987f0d7500eb82f394e189284 100644 (file)
@@ -78,8 +78,9 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
         * decide whether to reenable DMA -- 3 is a random magic for now,
         * if we DMA timeout more than 3 times, just stay in PIO
         */
-       if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
-               drive->state = 0;
+       if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
+           drive->retry_pio <= 3) {
+               drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
                ide_dma_on(drive);
        }
 
@@ -131,21 +132,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
 }
 EXPORT_SYMBOL(ide_end_request);
 
-/*
- * Power Management state machine. This one is rather trivial for now,
- * we should probably add more, like switching back to PIO on suspend
- * to help some BIOSes, re-do the door locking on resume, etc...
- */
-
-enum {
-       ide_pm_flush_cache      = ide_pm_state_start_suspend,
-       idedisk_pm_standby,
-
-       idedisk_pm_restore_pio  = ide_pm_state_start_resume,
-       idedisk_pm_idle,
-       ide_pm_restore_dma,
-};
-
 static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
 {
        struct request_pm_state *pm = rq->data;
@@ -154,20 +140,20 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s
                return;
 
        switch (pm->pm_step) {
-       case ide_pm_flush_cache:        /* Suspend step 1 (flush cache) complete */
+       case IDE_PM_FLUSH_CACHE:        /* Suspend step 1 (flush cache) */
                if (pm->pm_state == PM_EVENT_FREEZE)
-                       pm->pm_step = ide_pm_state_completed;
+                       pm->pm_step = IDE_PM_COMPLETED;
                else
-                       pm->pm_step = idedisk_pm_standby;
+                       pm->pm_step = IDE_PM_STANDBY;
                break;
-       case idedisk_pm_standby:        /* Suspend step 2 (standby) complete */
-               pm->pm_step = ide_pm_state_completed;
+       case IDE_PM_STANDBY:            /* Suspend step 2 (standby) */
+               pm->pm_step = IDE_PM_COMPLETED;
                break;
-       case idedisk_pm_restore_pio:    /* Resume step 1 complete */
-               pm->pm_step = idedisk_pm_idle;
+       case IDE_PM_RESTORE_PIO:        /* Resume step 1 (restore PIO) */
+               pm->pm_step = IDE_PM_IDLE;
                break;
-       case idedisk_pm_idle:           /* Resume step 2 (idle) complete */
-               pm->pm_step = ide_pm_restore_dma;
+       case IDE_PM_IDLE:               /* Resume step 2 (idle)*/
+               pm->pm_step = IDE_PM_RESTORE_DMA;
                break;
        }
 }
@@ -180,11 +166,12 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
        memset(args, 0, sizeof(*args));
 
        switch (pm->pm_step) {
-       case ide_pm_flush_cache:        /* Suspend step 1 (flush cache) */
+       case IDE_PM_FLUSH_CACHE:        /* Suspend step 1 (flush cache) */
                if (drive->media != ide_disk)
                        break;
                /* Not supported? Switch to next step now. */
-               if (!drive->wcache || ata_id_flush_enabled(drive->id) == 0) {
+               if (ata_id_flush_enabled(drive->id) == 0 ||
+                   (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
                        ide_complete_power_step(drive, rq, 0, 0);
                        return ide_stopped;
                }
@@ -193,27 +180,23 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                else
                        args->tf.command = ATA_CMD_FLUSH;
                goto out_do_tf;
-
-       case idedisk_pm_standby:        /* Suspend step 2 (standby) */
+       case IDE_PM_STANDBY:            /* Suspend step 2 (standby) */
                args->tf.command = ATA_CMD_STANDBYNOW1;
                goto out_do_tf;
-
-       case idedisk_pm_restore_pio:    /* Resume step 1 (restore PIO) */
+       case IDE_PM_RESTORE_PIO:        /* Resume step 1 (restore PIO) */
                ide_set_max_pio(drive);
                /*
-                * skip idedisk_pm_idle for ATAPI devices
+                * skip IDE_PM_IDLE for ATAPI devices
                 */
                if (drive->media != ide_disk)
-                       pm->pm_step = ide_pm_restore_dma;
+                       pm->pm_step = IDE_PM_RESTORE_DMA;
                else
                        ide_complete_power_step(drive, rq, 0, 0);
                return ide_stopped;
-
-       case idedisk_pm_idle:           /* Resume step 2 (idle) */
+       case IDE_PM_IDLE:               /* Resume step 2 (idle) */
                args->tf.command = ATA_CMD_IDLEIMMEDIATE;
                goto out_do_tf;
-
-       case ide_pm_restore_dma:        /* Resume step 3 (restore DMA) */
+       case IDE_PM_RESTORE_DMA:        /* Resume step 3 (restore DMA) */
                /*
                 * Right now, all we do is call ide_set_dma(drive),
                 * we could be smarter and check for current xfer_speed
@@ -222,12 +205,13 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
                if (drive->hwif->dma_ops == NULL)
                        break;
                /*
-                * TODO: respect ->using_dma setting
+                * TODO: respect IDE_DFLAG_USING_DMA
                 */
                ide_set_dma(drive);
                break;
        }
-       pm->pm_step = ide_pm_state_completed;
+
+       pm->pm_step = IDE_PM_COMPLETED;
        return ide_stopped;
 
 out_do_tf:
@@ -287,7 +271,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
        if (blk_pm_suspend_request(rq)) {
                blk_stop_queue(drive->queue);
        } else {
-               drive->blocked = 0;
+               drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
                blk_start_queue(drive->queue);
        }
        HWGROUP(drive)->rq = NULL;
@@ -343,7 +327,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
                        drive->name, rq->pm->pm_step, stat, err);
 #endif
                ide_complete_power_step(drive, rq, stat, err);
-               if (pm->pm_step == ide_pm_state_completed)
+               if (pm->pm_step == IDE_PM_COMPLETED)
                        ide_complete_pm_request(drive, rq);
                return;
        }
@@ -374,13 +358,14 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
+       if ((stat & ATA_BUSY) ||
+           ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
                /* other bits are useless when BUSY */
                rq->errors |= ERROR_RESET;
        } else if (stat & ATA_ERR) {
                /* err has different meaning on cdrom and tape */
                if (err == ATA_ABORTED) {
-                       if (drive->select.b.lba &&
+                       if ((drive->dev_flags & IDE_DFLAG_LBA) &&
                            /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
                            hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
                                return ide_stopped;
@@ -428,7 +413,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       if ((stat & ATA_BUSY) || ((stat & ATA_DF) && !drive->nowerr)) {
+       if ((stat & ATA_BUSY) ||
+           ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
                /* other bits are useless when BUSY */
                rq->errors |= ERROR_RESET;
        } else {
@@ -509,7 +495,7 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
        tf->lbal    = drive->sect;
        tf->lbam    = drive->cyl;
        tf->lbah    = drive->cyl >> 8;
-       tf->device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
+       tf->device  = (drive->head - 1) | drive->select;
        tf->command = ATA_CMD_INIT_DEV_PARAMS;
 }
 
@@ -557,30 +543,6 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
        return ide_started;
 }
 
-/*
- * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
- */
-static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
-{
-       switch (req_pio) {
-       case 202:
-       case 201:
-       case 200:
-       case 102:
-       case 101:
-       case 100:
-               return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
-       case 9:
-       case 8:
-               return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
-       case 7:
-       case 6:
-               return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
-       default:
-               return 0;
-       }
-}
-
 /**
  *     do_special              -       issue some special commands
  *     @drive: drive the command is for
@@ -598,45 +560,12 @@ static ide_startstop_t do_special (ide_drive_t *drive)
 #ifdef DEBUG
        printk("%s: do_special: 0x%02x\n", drive->name, s->all);
 #endif
-       if (s->b.set_tune) {
-               ide_hwif_t *hwif = drive->hwif;
-               const struct ide_port_ops *port_ops = hwif->port_ops;
-               u8 req_pio = drive->tune_req;
-
-               s->b.set_tune = 0;
-
-               if (set_pio_mode_abuse(drive->hwif, req_pio)) {
-                       /*
-                        * take ide_lock for drive->[no_]unmask/[no_]io_32bit
-                        */
-                       if (req_pio == 8 || req_pio == 9) {
-                               unsigned long flags;
-
-                               spin_lock_irqsave(&ide_lock, flags);
-                               port_ops->set_pio_mode(drive, req_pio);
-                               spin_unlock_irqrestore(&ide_lock, flags);
-                       } else
-                               port_ops->set_pio_mode(drive, req_pio);
-               } else {
-                       int keep_dma = drive->using_dma;
-
-                       ide_set_pio(drive, req_pio);
-
-                       if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
-                               if (keep_dma)
-                                       ide_dma_on(drive);
-                       }
-               }
-
-               return ide_stopped;
-       } else {
-               if (drive->media == ide_disk)
-                       return ide_disk_special(drive);
+       if (drive->media == ide_disk)
+               return ide_disk_special(drive);
 
-               s->all = 0;
-               drive->mult_req = 0;
-               return ide_stopped;
-       }
+       s->all = 0;
+       drive->mult_req = 0;
+       return ide_stopped;
 }
 
 void ide_map_sg(ide_drive_t *drive, struct request *rq)
@@ -726,10 +655,7 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
        if (!(setting->flags & DS_SYNC))
                return setting->set(drive, arg);
 
-       rq = blk_get_request(q, READ, GFP_KERNEL);
-       if (!rq)
-               return -ENOMEM;
-
+       rq = blk_get_request(q, READ, __GFP_WAIT);
        rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->cmd_len = 5;
        rq->cmd[0] = REQ_DEVSET_EXEC;
@@ -746,7 +672,32 @@ EXPORT_SYMBOL_GPL(ide_devset_execute);
 
 static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
 {
-       switch (rq->cmd[0]) {
+       u8 cmd = rq->cmd[0];
+
+       if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
+               ide_task_t task;
+               struct ide_taskfile *tf = &task.tf;
+
+               memset(&task, 0, sizeof(task));
+               if (cmd == REQ_PARK_HEADS) {
+                       drive->sleep = *(unsigned long *)rq->special;
+                       drive->dev_flags |= IDE_DFLAG_SLEEPING;
+                       tf->command = ATA_CMD_IDLEIMMEDIATE;
+                       tf->feature = 0x44;
+                       tf->lbal = 0x4c;
+                       tf->lbam = 0x4e;
+                       tf->lbah = 0x55;
+                       task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+               } else          /* cmd == REQ_UNPARK_HEADS */
+                       tf->command = ATA_CMD_CHK_POWER;
+
+               task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+               task.rq = rq;
+               drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
+               return do_rw_taskfile(drive, &task);
+       }
+
+       switch (cmd) {
        case REQ_DEVSET_EXEC:
        {
                int err, (*setfunc)(ide_drive_t *, int) = rq->special;
@@ -773,11 +724,11 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
        struct request_pm_state *pm = rq->data;
 
        if (blk_pm_suspend_request(rq) &&
-           pm->pm_step == ide_pm_state_start_suspend)
+           pm->pm_step == IDE_PM_START_SUSPEND)
                /* Mark drive blocked when starting the suspend sequence. */
-               drive->blocked = 1;
+               drive->dev_flags |= IDE_DFLAG_BLOCKED;
        else if (blk_pm_resume_request(rq) &&
-                pm->pm_step == ide_pm_state_start_resume) {
+                pm->pm_step == IDE_PM_START_RESUME) {
                /* 
                 * The first thing we do on wakeup is to wait for BSY bit to
                 * go away (with a looong timeout) as a drive on this hwif may
@@ -857,7 +808,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 #endif
                        startstop = ide_start_power_step(drive, rq);
                        if (startstop == ide_stopped &&
-                           pm->pm_step == ide_pm_state_completed)
+                           pm->pm_step == IDE_PM_COMPLETED)
                                ide_complete_pm_request(drive, rq);
                        return startstop;
                } else if (!rq->rq_disk && blk_special_request(rq))
@@ -895,7 +846,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
        if (timeout > WAIT_WORSTCASE)
                timeout = WAIT_WORSTCASE;
        drive->sleep = timeout + jiffies;
-       drive->sleeping = 1;
+       drive->dev_flags |= IDE_DFLAG_SLEEPING;
 }
 
 EXPORT_SYMBOL(ide_stall_queue);
@@ -935,18 +886,23 @@ repeat:
        }
 
        do {
-               if ((!drive->sleeping || time_after_eq(jiffies, drive->sleep))
-                   && !elv_queue_empty(drive->queue)) {
-                       if (!best
-                        || (drive->sleeping && (!best->sleeping || time_before(drive->sleep, best->sleep)))
-                        || (!best->sleeping && time_before(WAKEUP(drive), WAKEUP(best))))
-                       {
+               u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
+               u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
+
+               if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
+                   !elv_queue_empty(drive->queue)) {
+                       if (best == NULL ||
+                           (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
+                           (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
                                if (!blk_queue_plugged(drive->queue))
                                        best = drive;
                        }
                }
        } while ((drive = drive->next) != hwgroup->drive);
-       if (best && best->nice1 && !best->sleeping && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+
+       if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
+           (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
+           best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
                long t = (signed long)(WAKEUP(best) - jiffies);
                if (t >= WAIT_MIN_SLEEP) {
                /*
@@ -955,7 +911,7 @@ repeat:
                 */
                        drive = best->next;
                        do {
-                               if (!drive->sleeping
+                               if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
                                 && time_before(jiffies - best->service_time, WAKEUP(drive))
                                 && time_before(WAKEUP(drive), jiffies + t))
                                {
@@ -1026,7 +982,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                        hwgroup->rq = NULL;
                        drive = hwgroup->drive;
                        do {
-                               if (drive->sleeping && (!sleeping || time_before(drive->sleep, sleep))) {
+                               if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
+                                   (sleeping == 0 ||
+                                    time_before(drive->sleep, sleep))) {
                                        sleeping = 1;
                                        sleep = drive->sleep;
                                }
@@ -1075,7 +1033,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                }
                hwgroup->hwif = hwif;
                hwgroup->drive = drive;
-               drive->sleeping = 0;
+               drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
                drive->service_start = jiffies;
 
                if (blk_queue_plugged(drive->queue)) {
@@ -1109,7 +1067,9 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
                 * We count how many times we loop here to make sure we service
                 * all drives in the hwgroup without looping for ever
                 */
-               if (drive->blocked && !blk_pm_request(rq) && !(rq->cmd_flags & REQ_PREEMPT)) {
+               if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
+                   blk_pm_request(rq) == 0 &&
+                   (rq->cmd_flags & REQ_PREEMPT) == 0) {
                        drive = drive->next ? drive->next : hwgroup->drive;
                        if (loops++ < 4 && !blk_queue_plugged(drive->queue))
                                goto again;
@@ -1182,8 +1142,8 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
         * a timeout -- we'll reenable after we finish this next request
         * (or rather the first chunk of it) in pio.
         */
+       drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
        drive->retry_pio++;
-       drive->state = DMA_PIO_RETRY;
        ide_dma_off_quietly(drive);
 
        /*
@@ -1480,23 +1440,16 @@ irqreturn_t ide_intr (int irq, void *dev_id)
        del_timer(&hwgroup->timer);
        spin_unlock(&ide_lock);
 
-       /* Some controllers might set DMA INTR no matter DMA or PIO;
-        * bmdma status might need to be cleared even for
-        * PIO interrupts to prevent spurious/lost irq.
-        */
-       if (hwif->ide_dma_clear_irq && !(drive->waiting_for_dma))
-               /* ide_dma_end() needs bmdma status for error checking.
-                * So, skip clearing bmdma status here and leave it
-                * to ide_dma_end() if this is dma interrupt.
-                */
-               hwif->ide_dma_clear_irq(drive);
+       if (hwif->port_ops && hwif->port_ops->clear_irq)
+               hwif->port_ops->clear_irq(drive);
 
-       if (drive->unmask)
+       if (drive->dev_flags & IDE_DFLAG_UNMASK)
                local_irq_enable_in_hardirq();
+
        /* service this interrupt, may set handler for next interrupt */
        startstop = handler(drive);
-       spin_lock_irq(&ide_lock);
 
+       spin_lock_irq(&ide_lock);
        /*
         * Note that handler() may have set things up for another
         * interrupt to occur soon, but it cannot happen until
index cf01564901af245d976f0edcb6dd9d6c7ba75f97..a90945f4979287ca8d260d65c4fab2e144a846af 100644 (file)
@@ -62,7 +62,7 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
        int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
        int rc = 0;
 
-       if (drive->id_read == 0) {
+       if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
                rc = -ENOMSG;
                goto out;
        }
@@ -86,8 +86,10 @@ out:
 
 static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
 {
-       return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) |
-                       (drive->nice1 << IDE_NICE_1), (long __user *)arg);
+       return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
+                        << IDE_NICE_DSC_OVERLAP) |
+                       (!!(drive->dev_flags & IDE_DFLAG_NICE1)
+                        << IDE_NICE_1), (long __user *)arg);
 }
 
 static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
@@ -97,11 +99,18 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
 
        if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
            (drive->media == ide_disk || drive->media == ide_floppy ||
-            drive->scsi))
+            (drive->dev_flags & IDE_DFLAG_SCSI)))
                return -EPERM;
 
-       drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
-       drive->nice1 = (arg >> IDE_NICE_1) & 1;
+       if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
+               drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
+       if ((arg >> IDE_NICE_1) & 1)
+               drive->dev_flags |= IDE_DFLAG_NICE1;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_NICE1;
 
        return 0;
 }
index 0a2fd3b37ac4b84ecbccc1fdb41efe9da708c268..b762deb2dacb34f408ff55d0104581593f117e5d 100644 (file)
@@ -181,7 +181,7 @@ void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
                tf_outb(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               tf_outb((tf->device & HIHI) | drive->select.all,
+               tf_outb((tf->device & HIHI) | drive->select,
                         io_ports->device_addr);
 }
 EXPORT_SYMBOL_GPL(ide_tf_load);
@@ -647,7 +647,7 @@ u8 eighty_ninty_three (ide_drive_t *drive)
                return 1;
 
 no_80w:
-       if (drive->udma33_warned == 1)
+       if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
                return 0;
 
        printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
@@ -655,7 +655,7 @@ no_80w:
                            drive->name,
                            hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
 
-       drive->udma33_warned = 1;
+       drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
 
        return 0;
 }
@@ -711,7 +711,7 @@ int ide_driveid_update(ide_drive_t *drive)
 
        kfree(id);
 
-       if (drive->using_dma && ide_id_dma_bug(drive))
+       if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
                ide_dma_off(drive);
 
        return 1;
@@ -790,7 +790,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 
  skip:
 #ifdef CONFIG_BLK_DEV_IDEDMA
-       if (speed >= XFER_SW_DMA_0 && drive->using_dma)
+       if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
                hwif->dma_ops->dma_host_set(drive, 1);
        else if (hwif->dma_ops) /* check if host supports DMA */
                ide_dma_off_quietly(drive);
@@ -940,6 +940,25 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
        return ide_stopped;
 }
 
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+       static const char *err_master_vals[] =
+               { NULL, "passed", "formatter device error",
+                 "sector buffer error", "ECC circuitry error",
+                 "controlling MPU error" };
+
+       u8 err_master = err & 0x7f;
+
+       printk(KERN_ERR "%s: reset: master: ", hwif->name);
+       if (err_master && err_master < 6)
+               printk(KERN_CONT "%s", err_master_vals[err_master]);
+       else
+               printk(KERN_CONT "error (0x%02x?)", err);
+       if (err & 0x80)
+               printk(KERN_CONT "; slave: failed");
+       printk(KERN_CONT "\n");
+}
+
 /*
  * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
  * during an ide reset operation. If the drives have not yet responded,
@@ -975,31 +994,14 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
                drive->failures++;
                err = -EIO;
        } else  {
-               printk("%s: reset: ", hwif->name);
                tmp = ide_read_error(drive);
 
                if (tmp == 1) {
-                       printk("success\n");
+                       printk(KERN_INFO "%s: reset: success\n", hwif->name);
                        drive->failures = 0;
                } else {
+                       ide_reset_report_error(hwif, tmp);
                        drive->failures++;
-                       printk("master: ");
-                       switch (tmp & 0x7f) {
-                               case 1: printk("passed");
-                                       break;
-                               case 2: printk("formatter device error");
-                                       break;
-                               case 3: printk("sector buffer error");
-                                       break;
-                               case 4: printk("ECC circuitry error");
-                                       break;
-                               case 5: printk("controlling MPU error");
-                                       break;
-                               default:printk("error (0x%02x?)", tmp);
-                       }
-                       if (tmp & 0x80)
-                               printk("; slave: failed");
-                       printk("\n");
                        err = -EIO;
                }
        }
@@ -1016,9 +1018,14 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
        drive->special.all = 0;
        drive->special.b.set_geometry = legacy;
        drive->special.b.recalibrate  = legacy;
+
        drive->mult_count = 0;
-       if (!drive->keep_settings && !drive->using_dma)
+       drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+       if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+           (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
                drive->mult_req = 0;
+
        if (drive->mult_req != drive->mult_count)
                drive->special.b.set_multmode = 1;
 }
@@ -1030,18 +1037,18 @@ static void pre_reset(ide_drive_t *drive)
        if (drive->media == ide_disk)
                ide_disk_pre_reset(drive);
        else
-               drive->post_reset = 1;
+               drive->dev_flags |= IDE_DFLAG_POST_RESET;
 
-       if (drive->using_dma) {
+       if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
                if (drive->crc_count)
                        ide_check_dma_crc(drive);
                else
                        ide_dma_off(drive);
        }
 
-       if (!drive->keep_settings) {
-               if (!drive->using_dma) {
-                       drive->unmask = 0;
+       if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+               if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+                       drive->dev_flags &= ~IDE_DFLAG_UNMASK;
                        drive->io_32bit = 0;
                }
                return;
@@ -1073,12 +1080,13 @@ static void pre_reset(ide_drive_t *drive)
 static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
 {
        unsigned int unit;
-       unsigned long flags;
+       unsigned long flags, timeout;
        ide_hwif_t *hwif;
        ide_hwgroup_t *hwgroup;
        struct ide_io_ports *io_ports;
        const struct ide_tp_ops *tp_ops;
        const struct ide_port_ops *port_ops;
+       DEFINE_WAIT(wait);
 
        spin_lock_irqsave(&ide_lock, flags);
        hwif = HWIF(drive);
@@ -1105,6 +1113,31 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
                return ide_started;
        }
 
+       /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+       do {
+               unsigned long now;
+
+               prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+               timeout = jiffies;
+               for (unit = 0; unit < MAX_DRIVES; unit++) {
+                       ide_drive_t *tdrive = &hwif->drives[unit];
+
+                       if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
+                           tdrive->dev_flags & IDE_DFLAG_PARKED &&
+                           time_after(tdrive->sleep, timeout))
+                               timeout = tdrive->sleep;
+               }
+
+               now = jiffies;
+               if (time_before_eq(timeout, now))
+                       break;
+
+               spin_unlock_irqrestore(&ide_lock, flags);
+               timeout = schedule_timeout_uninterruptible(timeout - now);
+               spin_lock_irqsave(&ide_lock, flags);
+       } while (timeout);
+       finish_wait(&ide_park_wq, &wait);
+
        /*
         * First, reset any device state data we were maintaining
         * for any of the drives on this interface.
index ed426dd0fdd8a6747a744a64607c030ef0b6ed1e..9fc4cfb2a272bd6b89a112e72158eb6e1d656b9e 100644 (file)
@@ -317,7 +317,7 @@ static void ide_dump_sector(ide_drive_t *drive)
 {
        ide_task_t task;
        struct ide_taskfile *tf = &task.tf;
-       int lba48 = (drive->addressing == 1) ? 1 : 0;
+       u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
 
        memset(&task, 0, sizeof(task));
        if (lba48)
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
new file mode 100644 (file)
index 0000000..03b00e5
--- /dev/null
@@ -0,0 +1,121 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/jiffies.h>
+#include <linux/blkdev.h>
+
+DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
+
+static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
+{
+       struct request_queue *q = drive->queue;
+       struct request *rq;
+       int rc;
+
+       timeout += jiffies;
+       spin_lock_irq(&ide_lock);
+       if (drive->dev_flags & IDE_DFLAG_PARKED) {
+               ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+               int reset_timer;
+
+               reset_timer = time_before(timeout, drive->sleep);
+               drive->sleep = timeout;
+               wake_up_all(&ide_park_wq);
+               if (reset_timer && hwgroup->sleeping &&
+                   del_timer(&hwgroup->timer)) {
+                       hwgroup->sleeping = 0;
+                       hwgroup->busy = 0;
+                       blk_start_queueing(q);
+               }
+               spin_unlock_irq(&ide_lock);
+               return;
+       }
+       spin_unlock_irq(&ide_lock);
+
+       rq = blk_get_request(q, READ, __GFP_WAIT);
+       rq->cmd[0] = REQ_PARK_HEADS;
+       rq->cmd_len = 1;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->special = &timeout;
+       rc = blk_execute_rq(q, NULL, rq, 1);
+       blk_put_request(rq);
+       if (rc)
+               goto out;
+
+       /*
+        * Make sure that *some* command is sent to the drive after the
+        * timeout has expired, so power management will be reenabled.
+        */
+       rq = blk_get_request(q, READ, GFP_NOWAIT);
+       if (unlikely(!rq))
+               goto out;
+
+       rq->cmd[0] = REQ_UNPARK_HEADS;
+       rq->cmd_len = 1;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+
+out:
+       return;
+}
+
+ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
+                     char *buf)
+{
+       ide_drive_t *drive = to_ide_device(dev);
+       unsigned long now;
+       unsigned int msecs;
+
+       if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+               return -EOPNOTSUPP;
+
+       spin_lock_irq(&ide_lock);
+       now = jiffies;
+       if (drive->dev_flags & IDE_DFLAG_PARKED &&
+           time_after(drive->sleep, now))
+               msecs = jiffies_to_msecs(drive->sleep - now);
+       else
+               msecs = 0;
+       spin_unlock_irq(&ide_lock);
+
+       return snprintf(buf, 20, "%u\n", msecs);
+}
+
+ssize_t ide_park_store(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t len)
+{
+#define MAX_PARK_TIMEOUT 30000
+       ide_drive_t *drive = to_ide_device(dev);
+       long int input;
+       int rc;
+
+       rc = strict_strtol(buf, 10, &input);
+       if (rc || input < -2)
+               return -EINVAL;
+       if (input > MAX_PARK_TIMEOUT) {
+               input = MAX_PARK_TIMEOUT;
+               rc = -EOVERFLOW;
+       }
+
+       mutex_lock(&ide_setting_mtx);
+       if (input >= 0) {
+               if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
+                       rc = -EOPNOTSUPP;
+               else if (input || drive->dev_flags & IDE_DFLAG_PARKED)
+                       issue_park_cmd(drive, msecs_to_jiffies(input));
+       } else {
+               if (drive->media == ide_disk)
+                       switch (input) {
+                       case -1:
+                               drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD;
+                               break;
+                       case -2:
+                               drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+                               break;
+                       }
+               else
+                       rc = -EOPNOTSUPP;
+       }
+       mutex_unlock(&ide_setting_mtx);
+
+       return rc ? rc : len;
+}
index 06575a12b63518d01f2de299be39fb97f814afbe..19f8c7770a25d7449486b3df07b56cf536ee5b76 100644 (file)
@@ -121,7 +121,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
        /* read 512 bytes of id info */
        hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
 
-       drive->id_read = 1;
+       drive->dev_flags |= IDE_DFLAG_ID_READ;
+
        local_irq_enable();
 #ifdef DEBUG
        printk(KERN_INFO "%s: dumping identify data\n", drive->name);
@@ -153,8 +154,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
 
        printk(KERN_INFO "%s: %s, ", drive->name, m);
 
-       drive->present = 1;
-       drive->dead = 0;
+       drive->dev_flags |= IDE_DFLAG_PRESENT;
+       drive->dev_flags &= ~IDE_DFLAG_DEAD;
 
        /*
         * Check for an ATAPI device
@@ -172,14 +173,14 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
                                                printk(KERN_CONT "cdrom or floppy?, assuming ");
                                        if (drive->media != ide_cdrom) {
                                                printk(KERN_CONT "FLOPPY");
-                                               drive->removable = 1;
+                                               drive->dev_flags |= IDE_DFLAG_REMOVABLE;
                                                break;
                                        }
                                }
                                /* Early cdrom models used zero */
                                type = ide_cdrom;
                        case ide_cdrom:
-                               drive->removable = 1;
+                               drive->dev_flags |= IDE_DFLAG_REMOVABLE;
 #ifdef CONFIG_PPC
                                /* kludge for Apple PowerBook internal zip */
                                if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
@@ -195,7 +196,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
                                break;
                        case ide_optical:
                                printk(KERN_CONT "OPTICAL");
-                               drive->removable = 1;
+                               drive->dev_flags |= IDE_DFLAG_REMOVABLE;
                                break;
                        default:
                                printk(KERN_CONT "UNKNOWN (type %d)", type);
@@ -205,6 +206,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
                drive->media = type;
                /* an ATAPI device ignores DRDY */
                drive->ready_stat = 0;
+               if (ata_id_cdb_intr(id))
+                       drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+               /* we don't do head unloading on ATAPI devices */
+               drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
                return;
        }
 
@@ -216,17 +221,20 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
 
        /* CF devices are *not* removable in Linux definition of the term */
        if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
-               drive->removable = 1;
+               drive->dev_flags |= IDE_DFLAG_REMOVABLE;
 
        drive->media = ide_disk;
 
+       if (!ata_id_has_unload(drive->id))
+               drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+
        printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
 
        return;
 
 err_misc:
        kfree(id);
-       drive->present = 0;
+       drive->dev_flags &= ~IDE_DFLAG_PRESENT;
        return;
 }
 
@@ -426,16 +434,15 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
        ide_hwif_t *hwif = HWIF(drive);
        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
        int rc;
-       u8 stat;
+       u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
+
+       /* avoid waiting for inappropriate probes */
+       if (present && drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
+               return 4;
 
-       if (drive->present) {
-               /* avoid waiting for inappropriate probes */
-               if (drive->media != ide_disk && cmd == ATA_CMD_ID_ATA)
-                       return 4;
-       }
 #ifdef DEBUG
        printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n",
-               drive->name, drive->present, drive->media,
+               drive->name, present, drive->media,
                (cmd == ATA_CMD_ID_ATA) ? "ATA" : "ATAPI");
 #endif
 
@@ -446,8 +453,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
        SELECT_DRIVE(drive);
        msleep(50);
 
-       if (ide_read_device(drive) != drive->select.all && !drive->present) {
-               if (drive->select.b.unit != 0) {
+       if (ide_read_device(drive) != drive->select && present == 0) {
+               if (drive->dn & 1) {
                        /* exit with drive0 selected */
                        SELECT_DRIVE(&hwif->drives[0]);
                        /* allow ATA_BUSY to assert & clear */
@@ -460,7 +467,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
        stat = tp_ops->read_status(hwif);
 
        if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
-           drive->present || cmd == ATA_CMD_ID_ATAPI) {
+           present || cmd == ATA_CMD_ID_ATAPI) {
                /* send cmd and wait */
                if ((rc = try_to_identify(drive, cmd))) {
                        /* failed: try again */
@@ -493,7 +500,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
                /* not present or maybe ATAPI */
                rc = 3;
        }
-       if (drive->select.b.unit != 0) {
+       if (drive->dn & 1) {
                /* exit with drive0 selected */
                SELECT_DRIVE(&hwif->drives[0]);
                msleep(50);
@@ -542,8 +549,8 @@ static void enable_nest (ide_drive_t *drive)
  *     and presents things to the user as needed.
  *
  *     Returns:        0  no device was found
- *                     1  device was found (note: drive->present might
- *                        still be 0)
+ *                     1  device was found
+ *                        (note: IDE_DFLAG_PRESENT might still be not set)
  */
  
 static inline u8 probe_for_drive (ide_drive_t *drive)
@@ -559,10 +566,10 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
         *      Also note that 0 everywhere means "can't do X"
         */
  
+       drive->dev_flags &= ~IDE_DFLAG_ID_READ;
+
        drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
-       drive->id_read = 0;
-       if(drive->id == NULL)
-       {
+       if (drive->id == NULL) {
                printk(KERN_ERR "ide: out of memory for id data.\n");
                return 0;
        }
@@ -571,14 +578,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
        strcpy(m, "UNKNOWN");
 
        /* skip probing? */
-       if (!drive->noprobe) {
+       if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
 retry:
                /* if !(success||timed-out) */
                if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
                        /* look for ATAPI device */
                        (void)do_probe(drive, ATA_CMD_ID_ATAPI);
 
-               if (!drive->present)
+               if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                        /* drive not found */
                        return 0;
 
@@ -588,7 +595,7 @@ retry:
                }
 
                /* identification failed? */
-               if (!drive->id_read) {
+               if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
                        if (drive->media == ide_disk) {
                                printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
                                        drive->name, drive->cyl,
@@ -598,15 +605,17 @@ retry:
                        } else {
                                /* nuke it */
                                printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
-                               drive->present = 0;
+                               drive->dev_flags &= ~IDE_DFLAG_PRESENT;
                        }
                }
                /* drive was found */
        }
-       if(!drive->present)
+
+       if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                return 0;
+
        /* The drive wasn't being helpful. Add generic info only */
-       if (drive->id_read == 0) {
+       if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
                generic_id(drive);
                return 1;
        }
@@ -616,7 +625,7 @@ retry:
                ide_disk_init_mult_count(drive);
        }
 
-       return drive->present;
+       return !!(drive->dev_flags & IDE_DFLAG_PRESENT);
 }
 
 static void hwif_release_dev(struct device *dev)
@@ -648,8 +657,8 @@ static int ide_register_port(ide_hwif_t *hwif)
                goto out;
        }
 
-       hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
-                                             MKDEV(0, 0), hwif, hwif->name);
+       hwif->portdev = device_create(ide_port_class, &hwif->gendev,
+                                     MKDEV(0, 0), hwif, hwif->name);
        if (IS_ERR(hwif->portdev)) {
                ret = PTR_ERR(hwif->portdev);
                device_unregister(&hwif->gendev);
@@ -707,7 +716,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
                ide_drive_t *drive = &hwif->drives[unit];
 
                /* Ignore disks that we will not probe for later. */
-               if (!drive->noprobe || drive->present) {
+               if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 ||
+                   (drive->dev_flags & IDE_DFLAG_PRESENT)) {
                        SELECT_DRIVE(drive);
                        hwif->tp_ops->set_irq(hwif, 1);
                        mdelay(2);
@@ -739,7 +749,7 @@ void ide_undecoded_slave(ide_drive_t *dev1)
 {
        ide_drive_t *dev0 = &dev1->hwif->drives[0];
 
-       if ((dev1->dn & 1) == 0 || dev0->present == 0)
+       if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0)
                return;
 
        /* If the models don't match they are not the same product */
@@ -759,7 +769,7 @@ void ide_undecoded_slave(ide_drive_t *dev1)
        /* Appears to be an IDE flash adapter with decode bugs */
        printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
 
-       dev1->present = 0;
+       dev1->dev_flags &= ~IDE_DFLAG_PRESENT;
 }
 
 EXPORT_SYMBOL_GPL(ide_undecoded_slave);
@@ -772,7 +782,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
 
        BUG_ON(hwif->present);
 
-       if (hwif->drives[0].noprobe && hwif->drives[1].noprobe)
+       if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) &&
+           (hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE))
                return -EACCES;
 
        /*
@@ -794,9 +805,9 @@ static int ide_probe_port(ide_hwif_t *hwif)
         */
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
-               drive->dn = (hwif->channel ? 2 : 0) + unit;
+
                (void) probe_for_drive(drive);
-               if (drive->present)
+               if (drive->dev_flags & IDE_DFLAG_PRESENT)
                        rc = 0;
        }
 
@@ -820,17 +831,19 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
        for (unit = 0; unit < MAX_DRIVES; unit++) {
                ide_drive_t *drive = &hwif->drives[unit];
 
-               if (drive->present && port_ops && port_ops->quirkproc)
-                       port_ops->quirkproc(drive);
+               if (drive->dev_flags & IDE_DFLAG_PRESENT) {
+                       if (port_ops && port_ops->quirkproc)
+                               port_ops->quirkproc(drive);
+               }
        }
 
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
 
-               if (drive->present) {
+               if (drive->dev_flags & IDE_DFLAG_PRESENT) {
                        ide_set_max_pio(drive);
 
-                       drive->nice1 = 1;
+                       drive->dev_flags |= IDE_DFLAG_NICE1;
 
                        if (hwif->dma_ops)
                                ide_set_dma(drive);
@@ -840,14 +853,14 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
 
-               if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
-                       drive->no_io_32bit = 1;
+               if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) ||
+                   drive->id[ATA_ID_DWORD_IO])
+                       drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
                else
-                       drive->no_io_32bit = drive->id[ATA_ID_DWORD_IO] ? 1 : 0;
+                       drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
        }
 }
 
-#if MAX_HWIFS > 1
 /*
  * save_match() is used to simplify logic in init_irq() below.
  *
@@ -872,7 +885,6 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
        if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
                *match = new;
 }
-#endif /* MAX_HWIFS > 1 */
 
 /*
  * init request queue
@@ -951,26 +963,33 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
  * - allocate the block device queue
  * - link drive into the hwgroup
  */
-static void ide_port_setup_devices(ide_hwif_t *hwif)
+static int ide_port_setup_devices(ide_hwif_t *hwif)
 {
-       int i;
+       int i, j = 0;
 
        mutex_lock(&ide_cfg_mtx);
        for (i = 0; i < MAX_DRIVES; i++) {
                ide_drive_t *drive = &hwif->drives[i];
 
-               if (!drive->present)
+               if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                        continue;
 
                if (ide_init_queue(drive)) {
                        printk(KERN_ERR "ide: failed to init %s\n",
                                        drive->name);
+                       kfree(drive->id);
+                       drive->id = NULL;
+                       drive->dev_flags &= ~IDE_DFLAG_PRESENT;
                        continue;
                }
 
+               j++;
+
                ide_add_drive_to_hwgroup(drive);
        }
        mutex_unlock(&ide_cfg_mtx);
+
+       return j;
 }
 
 static ide_hwif_t *ide_ports[MAX_HWIFS];
@@ -1029,7 +1048,7 @@ static int init_irq (ide_hwif_t *hwif)
 
        mutex_lock(&ide_cfg_mtx);
        hwif->hwgroup = NULL;
-#if MAX_HWIFS > 1
+
        /*
         * Group up with any other hwifs that share our irq(s).
         */
@@ -1054,7 +1073,7 @@ static int init_irq (ide_hwif_t *hwif)
                        }
                }
        }
-#endif /* MAX_HWIFS > 1 */
+
        /*
         * If we are still without a hwgroup, then form a new one
         */
@@ -1153,12 +1172,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
        ide_hwif_t *hwif = data;
        int unit = *part >> PARTN_BITS;
        ide_drive_t *drive = &hwif->drives[unit];
-       if (!drive->present)
+
+       if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                return NULL;
 
        if (drive->media == ide_disk)
                request_module("ide-disk");
-       if (drive->scsi)
+       if (drive->dev_flags & IDE_DFLAG_SCSI)
                request_module("ide-scsi");
        if (drive->media == ide_cdrom || drive->media == ide_optical)
                request_module("ide-cd");
@@ -1205,7 +1225,7 @@ EXPORT_SYMBOL_GPL(ide_unregister_region);
 void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       unsigned int unit = (drive->select.all >> 4) & 1;
+       unsigned int unit = drive->dn & 1;
 
        disk->major = hwif->major;
        disk->first_minor = unit << PARTN_BITS;
@@ -1248,7 +1268,7 @@ static void drive_release_dev (struct device *dev)
        ide_remove_drive_from_hwgroup(drive);
        kfree(drive->id);
        drive->id = NULL;
-       drive->present = 0;
+       drive->dev_flags &= ~IDE_DFLAG_PRESENT;
        /* Messed up locking ... */
        spin_unlock_irq(&ide_lock);
        blk_cleanup_queue(drive->queue);
@@ -1327,7 +1347,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
                struct device *dev = &drive->gendev;
                int ret;
 
-               if (!drive->present)
+               if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                        continue;
 
                snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
@@ -1351,12 +1371,14 @@ static void ide_port_init_devices(ide_hwif_t *hwif)
        for (i = 0; i < MAX_DRIVES; i++) {
                ide_drive_t *drive = &hwif->drives[i];
 
+               drive->dn = i + hwif->channel * 2;
+
                if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
                        drive->io_32bit = 1;
                if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
-                       drive->unmask = 1;
+                       drive->dev_flags |= IDE_DFLAG_UNMASK;
                if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
-                       drive->no_unmask = 1;
+                       drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
 
                if (port_ops && port_ops->init_dev)
                        port_ops->init_dev(drive);
@@ -1513,19 +1535,14 @@ static int ide_find_port_slot(const struct ide_port_info *d)
         * ports 0x1f0/0x170 (the ide0/ide1 defaults).
         */
        mutex_lock(&ide_cfg_mtx);
-       if (MAX_HWIFS == 1) {
-               if (ide_indexes == 0 && i == 0)
-                       idx = 1;
+       if (bootable) {
+               if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+                       idx = ffz(ide_indexes | i);
        } else {
-               if (bootable) {
-                       if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
-                               idx = ffz(ide_indexes | i);
-               } else {
-                       if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
-                               idx = ffz(ide_indexes | 3);
-                       else if ((ide_indexes & 3) != 3)
-                               idx = ffz(ide_indexes);
-               }
+               if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+                       idx = ffz(ide_indexes | 3);
+               else if ((ide_indexes & 3) != 3)
+                       idx = ffz(ide_indexes);
        }
        if (idx >= 0)
                ide_indexes |= (1 << idx);
@@ -1541,8 +1558,7 @@ static void ide_free_port_slot(int idx)
        mutex_unlock(&ide_cfg_mtx);
 }
 
-struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
-                                   hw_regs_t **hws)
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
 {
        struct ide_host *host;
        int i;
@@ -1551,7 +1567,7 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
        if (host == NULL)
                return NULL;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                ide_hwif_t *hwif;
                int idx;
 
@@ -1593,18 +1609,6 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
 
        return host;
 }
-EXPORT_SYMBOL_GPL(ide_host_alloc_all);
-
-struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
-{
-       hw_regs_t *hws_all[MAX_HWIFS];
-       int i;
-
-       for (i = 0; i < MAX_HWIFS; i++)
-               hws_all[i] = (i < 4) ? hws[i] : NULL;
-
-       return ide_host_alloc_all(d, hws_all);
-}
 EXPORT_SYMBOL_GPL(ide_host_alloc);
 
 int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
@@ -1613,7 +1617,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
        ide_hwif_t *hwif, *mate = NULL;
        int i, j = 0;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL) {
@@ -1626,22 +1630,22 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
 
                if (d == NULL) {
                        mate = NULL;
-                       continue;
-               }
+               } else {
+                       if ((i & 1) && mate) {
+                               hwif->mate = mate;
+                               mate->mate = hwif;
+                       }
 
-               if ((i & 1) && mate) {
-                       hwif->mate = mate;
-                       mate->mate = hwif;
-               }
+                       mate = (i & 1) ? NULL : hwif;
 
-               mate = (i & 1) ? NULL : hwif;
+                       ide_init_port(hwif, i & 1, d);
+                       ide_port_cable_detect(hwif);
+               }
 
-               ide_init_port(hwif, i & 1, d);
-               ide_port_cable_detect(hwif);
                ide_port_init_devices(hwif);
        }
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL)
@@ -1658,7 +1662,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        ide_port_tune_devices(hwif);
        }
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL)
@@ -1671,10 +1675,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        continue;
                }
 
-               j++;
-
                if (hwif->present)
-                       ide_port_setup_devices(hwif);
+                       if (ide_port_setup_devices(hwif) == 0) {
+                               hwif->present = 0;
+                               continue;
+                       }
+
+               j++;
 
                ide_acpi_init(hwif);
 
@@ -1682,7 +1689,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        ide_acpi_port_init_devices(hwif);
        }
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL)
@@ -1695,7 +1702,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        hwif_register_devices(hwif);
        }
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL)
@@ -1740,7 +1747,7 @@ void ide_host_free(struct ide_host *host)
        ide_hwif_t *hwif;
        int i;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                hwif = host->ports[i];
 
                if (hwif == NULL)
@@ -1758,7 +1765,7 @@ void ide_host_remove(struct ide_host *host)
 {
        int i;
 
-       for (i = 0; i < MAX_HWIFS; i++) {
+       for (i = 0; i < MAX_HOST_PORTS; i++) {
                if (host->ports[i])
                        ide_unregister(host->ports[i]);
        }
index e7030a491463e126755784f9993db43083543aae..b26926487cc03f907e8e1798cdf6f0323027391e 100644 (file)
@@ -227,7 +227,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
 
 ide_devset_rw(current_speed, xfer_rate);
 ide_devset_rw_field(init_speed, init_speed);
-ide_devset_rw_field(nice1, nice1);
+ide_devset_rw_flag(nice1, IDE_DFLAG_NICE1);
 ide_devset_rw_field(number, dn);
 
 static const struct ide_proc_devset ide_generic_settings[] = {
@@ -622,9 +622,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
        for (d = 0; d < MAX_DRIVES; d++) {
                ide_drive_t *drive = &hwif->drives[d];
 
-               if (!drive->present)
-                       continue;
-               if (drive->proc)
+               if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
                        continue;
 
                drive->proc = proc_mkdir(drive->name, parent);
index f8c84df4a0bcf5e743cc2b341973488786602f29..d879c7797cde3a6ab961088f65ac17ca441f4120 100644 (file)
@@ -172,23 +172,16 @@ typedef struct ide_tape_obj {
        struct kref     kref;
 
        /*
-        *      pc points to the current processed packet command.
-        *
         *      failed_pc points to the last failed packet command, or contains
         *      NULL if we do not need to retry any packet command. This is
         *      required since an additional packet command is needed before the
         *      retry, to get detailed information on what went wrong.
         */
-       /* Current packet command */
-       struct ide_atapi_pc *pc;
        /* Last failed packet command */
        struct ide_atapi_pc *failed_pc;
        /* used by REQ_IDETAPE_{READ,WRITE} requests */
        struct ide_atapi_pc queued_pc;
 
-       struct ide_atapi_pc request_sense_pc;
-       struct request request_sense_rq;
-
        /*
         * DSC polling variables.
         *
@@ -274,11 +267,6 @@ static DEFINE_MUTEX(idetape_ref_mutex);
 
 static struct class *idetape_sysfs_class;
 
-#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
-
-#define ide_tape_g(disk) \
-       container_of((disk)->private_data, struct ide_tape_obj, driver)
-
 static void ide_tape_release(struct kref *);
 
 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
@@ -286,7 +274,7 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
        struct ide_tape_obj *tape = NULL;
 
        mutex_lock(&idetape_ref_mutex);
-       tape = ide_tape_g(disk);
+       tape = ide_drv_g(disk, ide_tape_obj);
        if (tape) {
                if (ide_device_get(tape->drive))
                        tape = NULL;
@@ -313,8 +301,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
  */
 static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
 
-#define ide_tape_f(file) ((file)->private_data)
-
 static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
 {
        struct ide_tape_obj *tape = NULL;
@@ -522,14 +508,19 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
        return 0;
 }
 
-static void ide_tape_callback(ide_drive_t *drive)
+static void ide_tape_handle_dsc(ide_drive_t *);
+
+static void ide_tape_callback(ide_drive_t *drive, int dsc)
 {
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
+       struct ide_atapi_pc *pc = drive->pc;
        int uptodate = pc->error ? 0 : 1;
 
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
+       if (dsc)
+               ide_tape_handle_dsc(drive);
+
        if (tape->failed_pc == pc)
                tape->failed_pc = NULL;
 
@@ -558,7 +549,7 @@ static void ide_tape_callback(ide_drive_t *drive)
                if (pc->error)
                        uptodate = pc->error;
        } else if (pc->c[0] == READ_POSITION && uptodate) {
-               u8 *readpos = tape->pc->buf;
+               u8 *readpos = pc->buf;
 
                debug_log(DBG_SENSE, "BOP - %s\n",
                                (readpos[0] & 0x80) ? "Yes" : "No");
@@ -583,31 +574,6 @@ static void ide_tape_callback(ide_drive_t *drive)
        idetape_end_request(drive, uptodate, 0);
 }
 
-static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
-{
-       ide_init_pc(pc);
-       pc->c[0] = REQUEST_SENSE;
-       pc->c[4] = 20;
-       pc->req_xfer = 20;
-}
-
-/*
- *     idetape_retry_pc is called when an error was detected during the
- *     last packet command. We queue a request sense packet command in
- *     the head of the request list.
- */
-static void idetape_retry_pc(ide_drive_t *drive)
-{
-       struct ide_tape_obj *tape = drive->driver_data;
-       struct request *rq = &tape->request_sense_rq;
-       struct ide_atapi_pc *pc = &tape->request_sense_pc;
-
-       (void)ide_read_error(drive);
-       idetape_create_request_sense_cmd(pc);
-       set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-       ide_queue_pc_head(drive, tape->disk, pc, rq);
-}
-
 /*
  * Postpone the current request so that ide.c will be able to service requests
  * from another device on the same hwgroup while we are polling for DSC.
@@ -645,35 +611,19 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
        return bcount;
 }
 
-/*
- * This is the usual interrupt handler which will be called during a packet
- * command. We will transfer some of the data (as requested by the drive) and
- * will re-point interrupt handler to us. When data transfer is finished, we
- * will act according to the algorithm described before
- * idetape_issue_pc.
- */
-static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       return ide_pc_intr(drive, tape->pc, idetape_pc_intr, WAIT_TAPE_CMD,
-                          NULL, idetape_update_buffers, idetape_retry_pc,
-                          ide_tape_handle_dsc, ide_tape_io_buffers);
-}
-
 /*
  * Packet Command Interface
  *
- * The current Packet Command is available in tape->pc, and will not change
+ * The current Packet Command is available in drive->pc, and will not change
  * until we finish handling it. Each packet command is associated with a
  * callback function that will be called when the command is finished.
  *
  * The handling will be done in three stages:
  *
  * 1. idetape_issue_pc will send the packet command to the drive, and will set
- * the interrupt handler to idetape_pc_intr.
+ * the interrupt handler to ide_pc_intr.
  *
- * 2. On each interrupt, idetape_pc_intr will be called. This step will be
+ * 2. On each interrupt, ide_pc_intr will be called. This step will be
  * repeated until the device signals us that no more interrupts will be issued.
  *
  * 3. ATAPI Tape media access commands have immediate status with a delayed
@@ -697,20 +647,13 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
  * again, the callback function will be called and then we will handle the next
  * request.
  */
-static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
-                              WAIT_TAPE_CMD, NULL);
-}
 
 static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
 {
        idetape_tape_t *tape = drive->driver_data;
 
-       if (tape->pc->c[0] == REQUEST_SENSE &&
+       if (drive->pc->c[0] == REQUEST_SENSE &&
            pc->c[0] == REQUEST_SENSE) {
                printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
                        "Two request sense in serial were issued\n");
@@ -718,8 +661,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
 
        if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
                tape->failed_pc = pc;
+
        /* Set the current packet command */
-       tape->pc = pc;
+       drive->pc = pc;
 
        if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
                (pc->flags & PC_FLAG_ABORT)) {
@@ -743,15 +687,14 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                        pc->error = IDETAPE_ERROR_GENERAL;
                }
                tape->failed_pc = NULL;
-               drive->pc_callback(drive);
+               drive->pc_callback(drive, 0);
                return ide_stopped;
        }
        debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
 
        pc->retries++;
 
-       return ide_issue_pc(drive, pc, idetape_transfer_pc,
-                           WAIT_TAPE_CMD, NULL);
+       return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
 }
 
 /* A mode sense command is used to "sense" tape parameters. */
@@ -785,7 +728,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
+       struct ide_atapi_pc *pc = drive->pc;
        u8 stat;
 
        stat = hwif->tp_ops->read_status(hwif);
@@ -797,7 +740,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
                                printk(KERN_ERR "ide-tape: %s: I/O error, ",
                                                tape->name);
                        /* Retry operation */
-                       idetape_retry_pc(drive);
+                       ide_retry_pc(drive, tape->disk);
                        return ide_stopped;
                }
                pc->error = 0;
@@ -805,7 +748,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
                pc->error = IDETAPE_ERROR_GENERAL;
                tape->failed_pc = NULL;
        }
-       drive->pc_callback(drive);
+       drive->pc_callback(drive, 0);
        return ide_stopped;
 }
 
@@ -862,7 +805,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        }
 
        /* Retry a failed packet command */
-       if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) {
+       if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
                pc = tape->failed_pc;
                goto out;
        }
@@ -883,12 +826,13 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
         */
        stat = hwif->tp_ops->read_status(hwif);
 
-       if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+       if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
+           (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
                set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
 
-       if (drive->post_reset == 1) {
+       if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
                set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-               drive->post_reset = 0;
+               drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
        }
 
        if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
@@ -1411,7 +1355,7 @@ static int idetape_init_read(ide_drive_t *drive)
                 * No point in issuing this if DSC overlap isn't supported, some
                 * drives (Seagate STT3401A) will return an error.
                 */
-               if (drive->dsc_overlap) {
+               if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
                        bytes_read = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_READ, 0,
                                                        tape->merge_bh);
@@ -1592,7 +1536,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
 static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                                   size_t count, loff_t *ppos)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        ssize_t bytes_read, temp, actually_read = 0, rc;
        ssize_t ret = 0;
@@ -1654,7 +1598,7 @@ finish:
 static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                                     size_t count, loff_t *ppos)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        ssize_t actually_written = 0;
        ssize_t ret = 0;
@@ -1687,7 +1631,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                 * point in issuing this if DSC overlap isn't supported, some
                 * drives (Seagate STT3401A) will return an error.
                 */
-               if (drive->dsc_overlap) {
+               if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
                        ssize_t retval = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_WRITE, 0,
                                                        tape->merge_bh);
@@ -1886,7 +1830,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
 static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
                                unsigned int cmd, unsigned long arg)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        struct mtop mtop;
        struct mtget mtget;
@@ -2063,7 +2007,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
 
 static int idetape_chrdev_release(struct inode *inode, struct file *filp)
 {
-       struct ide_tape_obj *tape = ide_tape_f(filp);
+       struct ide_tape_obj *tape = filp->private_data;
        ide_drive_t *drive = tape->drive;
        unsigned int minor = iminor(inode);
 
@@ -2202,7 +2146,7 @@ static int divf_tdsc(ide_drive_t *drive)  { return   HZ; }
 static int divf_buffer(ide_drive_t *drive)     { return    2; }
 static int divf_buffer_size(ide_drive_t *drive)        { return 1024; }
 
-ide_devset_rw_field(dsc_overlap, dsc_overlap);
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
 
 ide_tape_devset_rw_field(debug_mask, debug_mask);
 ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
@@ -2241,33 +2185,32 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        unsigned long t;
        int speed;
        int buffer_size;
-       u8 gcw[2];
        u16 *ctl = (u16 *)&tape->caps[12];
 
-       drive->pc_callback = ide_tape_callback;
+       drive->pc_callback       = ide_tape_callback;
+       drive->pc_update_buffers = idetape_update_buffers;
+       drive->pc_io_buffers     = ide_tape_io_buffers;
 
        spin_lock_init(&tape->lock);
-       drive->dsc_overlap = 1;
+
+       drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+
        if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
                printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
                                 tape->name);
-               drive->dsc_overlap = 0;
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        }
+
        /* Seagate Travan drives do not support DSC overlap. */
        if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
-               drive->dsc_overlap = 0;
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
        tape->minor = minor;
        tape->name[0] = 'h';
        tape->name[1] = 't';
        tape->name[2] = '0' + minor;
        tape->chrdev_dir = IDETAPE_DIR_NONE;
 
-       *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG];
-
-       /* Command packet DRQ type */
-       if (((gcw[0] & 0x60) >> 5) == 1)
-               set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
-
        idetape_get_inquiry_results(drive);
        idetape_get_mode_sense_results(drive);
        ide_tape_get_bsize_from_bdesc(drive);
@@ -2302,7 +2245,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
                (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
                tape->buffer_size / 1024,
                tape->best_dsc_rw_freq * 1000 / HZ,
-               drive->using_dma ? ", DMA":"");
+               (drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
 
        ide_proc_register_driver(drive, tape->driver);
 }
@@ -2320,13 +2263,13 @@ static void ide_tape_remove(ide_drive_t *drive)
 
 static void ide_tape_release(struct kref *kref)
 {
-       struct ide_tape_obj *tape = to_ide_tape(kref);
+       struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
        ide_drive_t *drive = tape->drive;
        struct gendisk *g = tape->disk;
 
        BUG_ON(tape->merge_bh_size);
 
-       drive->dsc_overlap = 0;
+       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        drive->driver_data = NULL;
        device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
        device_destroy(idetape_sysfs_class,
@@ -2368,7 +2311,6 @@ static ide_driver_t idetape_driver = {
        .probe                  = ide_tape_probe,
        .remove                 = ide_tape_remove,
        .version                = IDETAPE_VERSION,
-       .media                  = ide_tape,
        .do_request             = idetape_do_request,
        .end_request            = idetape_end_request,
        .error                  = __ide_error,
@@ -2403,7 +2345,7 @@ static int idetape_open(struct inode *inode, struct file *filp)
 static int idetape_release(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct ide_tape_obj *tape = ide_tape_g(disk);
+       struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
 
        ide_tape_put(tape);
 
@@ -2414,7 +2356,7 @@ static int idetape_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        struct block_device *bdev = inode->i_bdev;
-       struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
+       struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
        ide_drive_t *drive = tape->drive;
        int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
        if (err == -EINVAL)
@@ -2441,7 +2383,8 @@ static int ide_tape_probe(ide_drive_t *drive)
        if (drive->media != ide_tape)
                goto failed;
 
-       if (drive->id_read == 1 && !ide_check_atapi_device(drive, DRV_NAME)) {
+       if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
+           ide_check_atapi_device(drive, DRV_NAME) == 0) {
                printk(KERN_ERR "ide-tape: %s: not supported by this version of"
                                " the driver\n", drive->name);
                goto failed;
@@ -2477,12 +2420,11 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        idetape_setup(drive, tape, minor);
 
-       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-                             MKDEV(IDETAPE_MAJOR, minor), NULL,
-                             "%s", tape->name);
-       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-                             MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
-                             "n%s", tape->name);
+       device_create(idetape_sysfs_class, &drive->gendev,
+                     MKDEV(IDETAPE_MAJOR, minor), NULL, "%s", tape->name);
+       device_create(idetape_sysfs_class, &drive->gendev,
+                     MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+                     "n%s", tape->name);
 
        g->fops = &idetape_block_ops;
        ide_register_region(g);
index 487b18b3ebae9036d2f794291eb5026f3c59ae0a..bf4fb9d8d176f2f91efa7a91a06d229f80f4d502 100644 (file)
@@ -53,9 +53,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
 }
 
 static ide_startstop_t task_no_data_intr(ide_drive_t *);
-static ide_startstop_t set_geometry_intr(ide_drive_t *);
-static ide_startstop_t recal_intr(ide_drive_t *);
-static ide_startstop_t set_multmode_intr(ide_drive_t *);
 static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
 static ide_startstop_t task_in_intr(ide_drive_t *);
 
@@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
        if (task->tf_flags & IDE_TFLAG_FLAGGED)
                task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
 
+       memcpy(&hwif->task, task, sizeof(*task));
+
        if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
                ide_tf_dump(drive->name, tf);
                tp_ops->set_irq(hwif, 1);
@@ -99,24 +98,12 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
        case TASKFILE_NO_DATA:
                if (handler == NULL)
                        handler = task_no_data_intr;
-               if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
-                       switch (tf->command) {
-                       case ATA_CMD_INIT_DEV_PARAMS:
-                               handler = set_geometry_intr;
-                               break;
-                       case ATA_CMD_RESTORE:
-                               handler = recal_intr;
-                               break;
-                       case ATA_CMD_SET_MULTI:
-                               handler = set_multmode_intr;
-                               break;
-                       }
-               }
                ide_execute_command(drive, tf->command, handler,
                                    WAIT_WORSTCASE, NULL);
                return ide_started;
        default:
-               if (drive->using_dma == 0 || dma_ops->dma_setup(drive))
+               if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 ||
+                   dma_ops->dma_setup(drive))
                        return ide_stopped;
                dma_ops->dma_exec_cmd(drive, tf->command);
                dma_ops->dma_start(drive);
@@ -126,33 +113,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 EXPORT_SYMBOL_GPL(do_rw_taskfile);
 
 /*
- * set_multmode_intr() is invoked on completion of a ATA_CMD_SET_MULTI cmd.
- */
-static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 stat;
-
-       local_irq_enable_in_hardirq();
-       stat = hwif->tp_ops->read_status(hwif);
-
-       if (OK_STAT(stat, ATA_DRDY, BAD_STAT))
-               drive->mult_count = drive->mult_req;
-       else {
-               drive->mult_req = drive->mult_count = 0;
-               drive->special.b.recalibrate = 1;
-               (void) ide_dump_status(drive, "set_multmode", stat);
-       }
-       return ide_stopped;
-}
-
-/*
- * set_geometry_intr() is invoked on completion of a ATA_CMD_INIT_DEV_PARAMS cmd.
+ * Handler for commands without a data phase
  */
-static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
+static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       int retries = 5;
+       ide_task_t *task = &hwif->task;
+       struct ide_taskfile *tf = &task->tf;
+       int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
+       int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
        u8 stat;
 
        local_irq_enable_in_hardirq();
@@ -164,50 +133,36 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
                udelay(10);
        };
 
-       if (OK_STAT(stat, ATA_DRDY, BAD_STAT))
-               return ide_stopped;
-
-       if (stat & (ATA_ERR | ATA_DRQ))
-               return ide_error(drive, "set_geometry_intr", stat);
-
-       ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
-       return ide_started;
-}
-
-/*
- * recal_intr() is invoked on completion of a ATA_CMD_RESTORE (recalibrate) cmd.
- */
-static ide_startstop_t recal_intr(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       u8 stat;
-
-       local_irq_enable_in_hardirq();
-       stat = hwif->tp_ops->read_status(hwif);
-
-       if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
-               return ide_error(drive, "recal_intr", stat);
-       return ide_stopped;
-}
-
-/*
- * Handler for commands without a data phase
- */
-static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_task_t *args = hwif->hwgroup->rq->special;
-       u8 stat;
-
-       local_irq_enable_in_hardirq();
-       stat = hwif->tp_ops->read_status(hwif);
-
-       if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
+       if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
+               if (custom && tf->command == ATA_CMD_SET_MULTI) {
+                       drive->mult_req = drive->mult_count = 0;
+                       drive->special.b.recalibrate = 1;
+                       (void)ide_dump_status(drive, __func__, stat);
+                       return ide_stopped;
+               } else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
+                       if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
+                               ide_set_handler(drive, &task_no_data_intr,
+                                               WAIT_WORSTCASE, NULL);
+                               return ide_started;
+                       }
+               }
                return ide_error(drive, "task_no_data_intr", stat);
                /* calls ide_end_drive_cmd */
+       }
 
-       if (args)
+       if (!custom)
+               ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+       else if (tf->command == ATA_CMD_IDLEIMMEDIATE) {
+               hwif->tp_ops->tf_read(drive, task);
+               if (tf->lbal != 0xc4) {
+                       printk(KERN_ERR "%s: head unload failed!\n",
+                              drive->name);
+                       ide_tf_dump(drive->name, tf);
+               } else
+                       drive->dev_flags |= IDE_DFLAG_PARKED;
                ide_end_drive_cmd(drive, stat, ide_read_error(drive));
+       } else if (tf->command == ATA_CMD_SET_MULTI)
+               drive->mult_count = drive->mult_req;
 
        return ide_stopped;
 }
@@ -469,13 +424,12 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
        if (ide_wait_stat(&startstop, drive, ATA_DRQ,
                          drive->bad_wstat, WAIT_DRQ)) {
                printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
-                               drive->name,
-                               drive->hwif->data_phase ? "MULT" : "",
-                               drive->addressing ? "_EXT" : "");
+                       drive->name, drive->hwif->data_phase ? "MULT" : "",
+                       (drive->dev_flags & IDE_DFLAG_LBA48) ? "_EXT" : "");
                return startstop;
        }
 
-       if (!drive->unmask)
+       if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
                local_irq_disable();
 
        ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
@@ -591,7 +545,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 
        args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
                        IDE_TFLAG_IN_TF;
-       if (drive->addressing == 1)
+       if (drive->dev_flags & IDE_DFLAG_LBA48)
                args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
 
        if (req_task->out_flags.all) {
@@ -694,7 +648,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
        if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
            req_task->in_flags.all == 0) {
                req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
-               if (drive->addressing == 1)
+               if (drive->dev_flags & IDE_DFLAG_LBA48)
                        req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
        }
 
index 9dcf5aed92cbcd1f1bf390cef2678ef7f6d1afa2..04f8f13cb9d74d697f65f3c37bb03117b3bc0057 100644 (file)
@@ -114,7 +114,7 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
                memset(drive, 0, sizeof(*drive));
 
                drive->media                    = ide_disk;
-               drive->select.all               = (unit<<4)|0xa0;
+               drive->select                   = (unit << 4) | ATA_DEVICE_OBS;
                drive->hwif                     = hwif;
                drive->ready_stat               = ATA_DRDY;
                drive->bad_wstat                = BAD_W_STAT;
@@ -138,7 +138,7 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
        for (i = 0; i < MAX_DRIVES; i++) {
                ide_drive_t *drive = &hwif->drives[i];
 
-               if (drive->present) {
+               if (drive->dev_flags & IDE_DFLAG_PRESENT) {
                        spin_unlock_irq(&ide_lock);
                        device_unregister(&drive->gendev);
                        wait_for_completion(&drive->gendev_rel_comp);
@@ -227,8 +227,7 @@ void ide_unregister(ide_hwif_t *hwif)
        kfree(hwif->sg_table);
        unregister_blkdev(hwif->major, hwif->name);
 
-       if (hwif->dma_base)
-               ide_release_dma_engine(hwif);
+       ide_release_dma_engine(hwif);
 
        mutex_unlock(&ide_cfg_mtx);
 }
@@ -254,7 +253,7 @@ ide_devset_get(io_32bit, io_32bit);
 
 static int set_io_32bit(ide_drive_t *drive, int arg)
 {
-       if (drive->no_io_32bit)
+       if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
                return -EPERM;
 
        if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
@@ -265,19 +264,22 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
        return 0;
 }
 
-ide_devset_get(ksettings, keep_settings);
+ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
 
 static int set_ksettings(ide_drive_t *drive, int arg)
 {
        if (arg < 0 || arg > 1)
                return -EINVAL;
 
-       drive->keep_settings = arg;
+       if (arg)
+               drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
 
        return 0;
 }
 
-ide_devset_get(using_dma, using_dma);
+ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
 
 static int set_using_dma(ide_drive_t *drive, int arg)
 {
@@ -311,9 +313,32 @@ out:
 #endif
 }
 
+/*
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
+ */
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
+{
+       switch (req_pio) {
+       case 202:
+       case 201:
+       case 200:
+       case 102:
+       case 101:
+       case 100:
+               return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
+       case 9:
+       case 8:
+               return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
+       case 7:
+       case 6:
+               return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
+       default:
+               return 0;
+       }
+}
+
 static int set_pio_mode(ide_drive_t *drive, int arg)
 {
-       struct request *rq;
        ide_hwif_t *hwif = drive->hwif;
        const struct ide_port_ops *port_ops = hwif->port_ops;
 
@@ -324,56 +349,65 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
            (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
                return -ENOSYS;
 
-       if (drive->special.b.set_tune)
-               return -EBUSY;
+       if (set_pio_mode_abuse(drive->hwif, arg)) {
+               if (arg == 8 || arg == 9) {
+                       unsigned long flags;
 
-       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
-       rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+                       /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
+                       spin_lock_irqsave(&ide_lock, flags);
+                       port_ops->set_pio_mode(drive, arg);
+                       spin_unlock_irqrestore(&ide_lock, flags);
+               } else
+                       port_ops->set_pio_mode(drive, arg);
+       } else {
+               int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
-       drive->tune_req = (u8) arg;
-       drive->special.b.set_tune = 1;
+               ide_set_pio(drive, arg);
 
-       blk_execute_rq(drive->queue, NULL, rq, 0);
-       blk_put_request(rq);
+               if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+                       if (keep_dma)
+                               ide_dma_on(drive);
+               }
+       }
 
        return 0;
 }
 
-ide_devset_get(unmaskirq, unmask);
+ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
 
 static int set_unmaskirq(ide_drive_t *drive, int arg)
 {
-       if (drive->no_unmask)
+       if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
                return -EPERM;
 
        if (arg < 0 || arg > 1)
                return -EINVAL;
 
-       drive->unmask = arg;
+       if (arg)
+               drive->dev_flags |= IDE_DFLAG_UNMASK;
+       else
+               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
 
        return 0;
 }
 
-#define ide_gen_devset_rw(_name, _func) \
-__IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
-
-ide_gen_devset_rw(io_32bit, io_32bit);
-ide_gen_devset_rw(keepsettings, ksettings);
-ide_gen_devset_rw(unmaskirq, unmaskirq);
-ide_gen_devset_rw(using_dma, using_dma);
-__IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode);
+ide_ext_devset_rw_sync(io_32bit, io_32bit);
+ide_ext_devset_rw_sync(keepsettings, ksettings);
+ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
+ide_ext_devset_rw_sync(using_dma, using_dma);
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
 
 static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
-       ide_drive_t *drive = dev->driver_data;
+       ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
        ide_hwif_t *hwif = HWIF(drive);
        struct request *rq;
        struct request_pm_state rqpm;
        ide_task_t args;
        int ret;
 
-       /* Call ACPI _GTM only once */
-       if (!(drive->dn % 2))
+       /* call ACPI _GTM only once */
+       if ((drive->dn & 1) == 0 || pair == NULL)
                ide_acpi_get_timing(hwif);
 
        memset(&rqpm, 0, sizeof(rqpm));
@@ -382,33 +416,32 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        rq->cmd_type = REQ_TYPE_PM_SUSPEND;
        rq->special = &args;
        rq->data = &rqpm;
-       rqpm.pm_step = ide_pm_state_start_suspend;
+       rqpm.pm_step = IDE_PM_START_SUSPEND;
        if (mesg.event == PM_EVENT_PRETHAW)
                mesg.event = PM_EVENT_FREEZE;
        rqpm.pm_state = mesg.event;
 
        ret = blk_execute_rq(drive->queue, NULL, rq, 0);
        blk_put_request(rq);
-       /* only call ACPI _PS3 after both drivers are suspended */
-       if (!ret && (((drive->dn % 2) && hwif->drives[0].present
-                && hwif->drives[1].present)
-                || !hwif->drives[0].present
-                || !hwif->drives[1].present))
+
+       /* call ACPI _PS3 only after both devices are suspended */
+       if (ret == 0 && ((drive->dn & 1) || pair == NULL))
                ide_acpi_set_state(hwif, 0);
+
        return ret;
 }
 
 static int generic_ide_resume(struct device *dev)
 {
-       ide_drive_t *drive = dev->driver_data;
+       ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
        ide_hwif_t *hwif = HWIF(drive);
        struct request *rq;
        struct request_pm_state rqpm;
        ide_task_t args;
        int err;
 
-       /* Call ACPI _STM only once */
-       if (!(drive->dn % 2)) {
+       /* call ACPI _PS0 / _STM only once */
+       if ((drive->dn & 1) == 0 || pair == NULL) {
                ide_acpi_set_state(hwif, 1);
                ide_acpi_push_timing(hwif);
        }
@@ -422,7 +455,7 @@ static int generic_ide_resume(struct device *dev)
        rq->cmd_flags |= REQ_PREEMPT;
        rq->special = &args;
        rq->data = &rqpm;
-       rqpm.pm_step = ide_pm_state_start_resume;
+       rqpm.pm_step = IDE_PM_START_RESUME;
        rqpm.pm_state = PM_EVENT_ON;
 
        err = blk_execute_rq(drive->queue, NULL, rq, 1);
@@ -554,6 +587,7 @@ static struct device_attribute ide_dev_attrs[] = {
        __ATTR_RO(model),
        __ATTR_RO(firmware),
        __ATTR(serial, 0400, serial_show, NULL),
+       __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
        __ATTR_NULL
 };
 
@@ -708,22 +742,22 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
 module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
 MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
 
-static void ide_dev_apply_params(ide_drive_t *drive)
+static void ide_dev_apply_params(ide_drive_t *drive, u8 unit)
 {
-       int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit;
+       int i = drive->hwif->index * MAX_DRIVES + unit;
 
        if (ide_nodma & (1 << i)) {
                printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
-               drive->nodma = 1;
+               drive->dev_flags |= IDE_DFLAG_NODMA;
        }
        if (ide_noflush & (1 << i)) {
                printk(KERN_INFO "ide: disabling flush requests for %s\n",
                                 drive->name);
-               drive->noflush = 1;
+               drive->dev_flags |= IDE_DFLAG_NOFLUSH;
        }
        if (ide_noprobe & (1 << i)) {
                printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
-               drive->noprobe = 1;
+               drive->dev_flags |= IDE_DFLAG_NOPROBE;
        }
        if (ide_nowerr & (1 << i)) {
                printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n",
@@ -732,7 +766,7 @@ static void ide_dev_apply_params(ide_drive_t *drive)
        }
        if (ide_cdroms & (1 << i)) {
                printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
-               drive->present = 1;
+               drive->dev_flags |= IDE_DFLAG_PRESENT;
                drive->media = ide_cdrom;
                /* an ATAPI device ignores DRDY */
                drive->ready_stat = 0;
@@ -741,11 +775,12 @@ static void ide_dev_apply_params(ide_drive_t *drive)
                drive->cyl  = drive->bios_cyl  = ide_disks_chs[i].cyl;
                drive->head = drive->bios_head = ide_disks_chs[i].head;
                drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
-               drive->forced_geom = 1;
+
                printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
                                 drive->name,
                                 drive->cyl, drive->head, drive->sect);
-               drive->present = 1;
+
+               drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT;
                drive->media = ide_disk;
                drive->ready_stat = ATA_DRDY;
        }
@@ -785,7 +820,7 @@ void ide_port_apply_params(ide_hwif_t *hwif)
        }
 
        for (i = 0; i < MAX_DRIVES; i++)
-               ide_dev_apply_params(&hwif->drives[i]);
+               ide_dev_apply_params(&hwif->drives[i], i);
 }
 
 /*
index 7276c96aaa2a88aa8bfd2279da17b21963cd7b9c..90da1f953ed080d0b0fb3ce38ff527398c42d00c 100644 (file)
@@ -131,7 +131,7 @@ static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
                drive->name, pio, time1, time2, param1, param2, param3, param4);
 
        /* stuff timing parameters into controller registers */
-       driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+       driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
        spin_lock_irqsave(&ali14xx_lock, flags);
        outb_p(regOn, basePort);
        outReg(param1, regTab[driveNum].reg1);
index 5123ea291d075a332fe5f652957cb0de0d9744cc..c7e5c2246b79e1b29836055921e116daacafe102 100644 (file)
@@ -120,7 +120,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
         * Need to enforce prefetch sometimes because otherwise
         * it'll hang (hard).
         */
-       if (drive->media != ide_disk || !drive->present)
+       if (drive->media != ide_disk ||
+           (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
                select |= HT_PREFETCH_MODE;
 
        if (select != current_select || timing != current_timing) {
@@ -249,11 +250,11 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
         */
        if (state) {
                drive->drive_data |= t;   /* enable prefetch mode */
-               drive->no_unmask = 1;
-               drive->unmask = 0;
+               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
        } else {
                drive->drive_data &= ~t;  /* disable prefetch mode */
-               drive->no_unmask = 0;
+               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
        }
 
        spin_unlock_irqrestore(&ht6560b_lock, flags);
index c76d55de6996413496ddc9c8d725f3feb633c860..9e85b1ec9607604178a6a99419b2449516027f5d 100644 (file)
@@ -14,7 +14,7 @@ MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port");
 static void ide_4drives_init_dev(ide_drive_t *drive)
 {
        if (drive->hwif->channel)
-               drive->select.all ^= 0x20;
+               drive->select ^= 0x20;
 }
 
 static const struct ide_port_ops ide_4drives_port_ops = {
index ee6fc30d5e2bec793b93099a5068b7c5cccdaa4c..cb199c815b534234bbd115c0ea19df7fea3a48e9 100644 (file)
@@ -219,103 +219,91 @@ out_release:
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+struct pcmcia_config_check {
+       unsigned long ctl_base;
+       int skip_vcc;
+       int is_kme;
+};
+
+static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+                                  cistpl_cftable_entry_t *cfg,
+                                  cistpl_cftable_entry_t *dflt,
+                                  unsigned int vcc,
+                                  void *priv_data)
+{
+       struct pcmcia_config_check *stk = priv_data;
+
+       /* Check for matching Vcc, unless we're desperate */
+       if (!stk->skip_vcc) {
+               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+                               return -ENODEV;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               pdev->conf.ConfigIndex = cfg->index;
+               pdev->io.BasePort1 = io->win[0].base;
+               pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               if (io->nwin == 2) {
+                       pdev->io.NumPorts1 = 8;
+                       pdev->io.BasePort2 = io->win[1].base;
+                       pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort2;
+               } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+                       pdev->io.NumPorts1 = io->win[0].len;
+                       pdev->io.NumPorts2 = 0;
+                       if (pcmcia_request_io(pdev, &pdev->io) != 0)
+                               return -ENODEV;
+                       stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+               } else
+                       return -ENODEV;
+               /* If we've got this far, we're done */
+               return 0;
+       }
+       return -ENODEV;
+}
+
 static int ide_config(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    tuple_t tuple;
-    struct {
-       u_short         buf[128];
-       cisparse_t      parse;
-       config_info_t   conf;
-       cistpl_cftable_entry_t dflt;
-    } *stk = NULL;
-    cistpl_cftable_entry_t *cfg;
-    int pass, last_ret = 0, last_fn = 0, is_kme = 0;
+    struct pcmcia_config_check *stk = NULL;
+    int last_ret = 0, last_fn = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
     struct ide_host *host;
 
     DEBUG(0, "ide_config(0x%p)\n", link);
 
-    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-    if (!stk) goto err_mem;
-    cfg = &stk->parse.cftable_entry;
-
-    tuple.TupleData = (cisdata_t *)&stk->buf;
-    tuple.TupleOffset = 0;
-    tuple.TupleDataMax = 255;
-    tuple.Attributes = 0;
-
     is_kme = ((link->manf_id == MANFID_KME) &&
              ((link->card_id == PRODID_KME_KXLC005_A) ||
               (link->card_id == PRODID_KME_KXLC005_B)));
 
-    /* Not sure if this is right... look up the current Vcc */
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
-
-    pass = io_base = ctl_base = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (1) {
-       if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
-       if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
-
-       /* Check for matching Vcc, unless we're desperate */
-       if (!pass) {
-           if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-                   goto next_entry;
-           } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-               if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
-                   goto next_entry;
-           }
-       }
-
-       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-           link->conf.Vpp =
-               cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-       else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-           link->conf.Vpp =
-               stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-       if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
-           cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
-           link->conf.ConfigIndex = cfg->index;
-           link->io.BasePort1 = io->win[0].base;
-           link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-           if (!(io->flags & CISTPL_IO_16BIT))
-               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-           if (io->nwin == 2) {
-               link->io.NumPorts1 = 8;
-               link->io.BasePort2 = io->win[1].base;
-               link->io.NumPorts2 = (is_kme) ? 2 : 1;
-               if (pcmcia_request_io(link, &link->io) != 0)
-                       goto next_entry;
-               io_base = link->io.BasePort1;
-               ctl_base = link->io.BasePort2;
-           } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-               link->io.NumPorts1 = io->win[0].len;
-               link->io.NumPorts2 = 0;
-               if (pcmcia_request_io(link, &link->io) != 0)
-                       goto next_entry;
-               io_base = link->io.BasePort1;
-               ctl_base = link->io.BasePort1 + 0x0e;
-           } else goto next_entry;
-           /* If we've got this far, we're done */
-           break;
-       }
-
-    next_entry:
-       if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-           memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
-       if (pass) {
-           CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-       } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
-           CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-           memset(&stk->dflt, 0, sizeof(stk->dflt));
-           pass++;
-       }
+    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+    if (!stk)
+           goto err_mem;
+    stk->is_kme = is_kme;
+    stk->skip_vcc = io_base = ctl_base = 0;
+
+    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+           stk->skip_vcc = 1;
+           if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+                   goto failed; /* No suitable config found */
     }
+    io_base = link->io.BasePort1;
+    ctl_base = stk->ctl_base;
 
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@@ -403,8 +391,10 @@ static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000),        /* I-O Data CFA */
        PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001),        /* Mitsubishi CFA */
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+       PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
        PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),        /* SanDisk CFA */
        PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000),        /* Kingston */
+       PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620),        /* TI emulated */
        PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
        PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
index ec408b3a7100ae9eb4492ca1dfcb74ddc888c790..bc27c7aba93612628eff92defc91baaef5657109 100644 (file)
@@ -305,7 +305,7 @@ static void __init qd6580_init_dev(ide_drive_t *drive)
        } else
                t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
 
-       drive->drive_data = drive->select.b.unit ? t2 : t1;
+       drive->drive_data = (drive->dn & 1) ? t2 : t1;
 }
 
 static const struct ide_port_ops qd6500_port_ops = {
index 11b7f61aae40f7a7d7ec8d29be48cd6c5ec78313..0ec8fd1e4dcb3ae37d3fb98966bc936f534fa0d0 100644 (file)
@@ -322,11 +322,7 @@ static int auide_dma_setup(ide_drive_t *drive)
 }
 
 static int auide_dma_test_irq(ide_drive_t *drive)
-{      
-       if (drive->waiting_for_dma == 0)
-               printk(KERN_WARNING "%s: ide_dma_test_irq \
-                                     called while not waiting\n", drive->name);
-
+{
        /* If dbdma didn't execute the STOP command yet, the
         * active bit is still set
         */
@@ -344,11 +340,6 @@ static void auide_dma_host_set(ide_drive_t *drive, int on)
 {
 }
 
-static void auide_dma_lost_irq(ide_drive_t *drive)
-{
-       printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-}
-
 static void auide_ddma_tx_callback(int irq, void *param)
 {
        _auide_hwif *ahwif = (_auide_hwif*)param;
@@ -375,18 +366,6 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
 }
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-static void auide_dma_timeout(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-
-       printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
-
-       if (auide_dma_test_irq(drive))
-               return;
-
-       auide_dma_end(drive);
-}
-
 static const struct ide_dma_ops au1xxx_dma_ops = {
        .dma_host_set           = auide_dma_host_set,
        .dma_setup              = auide_dma_setup,
@@ -394,8 +373,8 @@ static const struct ide_dma_ops au1xxx_dma_ops = {
        .dma_start              = auide_dma_start,
        .dma_end                = auide_dma_end,
        .dma_test_irq           = auide_dma_test_irq,
-       .dma_lost_irq           = auide_dma_lost_irq,
-       .dma_timeout            = auide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
+       .dma_timeout            = ide_dma_timeout,
 };
 
 static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
@@ -448,10 +427,9 @@ static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d)
                                                             NUM_DESCRIPTORS);
        auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
                                                             NUM_DESCRIPTORS);
-       hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
-                                               PRD_ENTRIES * PRD_BYTES,        /* 1 Page */
-                                               &hwif->dmatable_dma, GFP_KERNEL);
+
+       /* FIXME: check return value */
+       (void)ide_allocate_dma_engine(hwif);
        
        au1xxx_dbdma_start( auide->tx_chan );
        au1xxx_dbdma_start( auide->rx_chan );
index e7475ba559c74063543650816335a751864687ac..4142c698e0d3da9fda2db897edf8228fdd8bba12 100644 (file)
@@ -115,7 +115,7 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        struct ide_host *host   = pci_get_drvdata(dev);
        struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
-       u8 unit         = (drive->select.b.unit & 0x01);
+       u8 unit                 = drive->dn & 1;
        u8 tmp1 = 0, tmp2 = 0;
        u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
        unsigned long flags;
@@ -302,7 +302,7 @@ static const struct pci_device_id aec62xx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver aec62xx_pci_driver = {
        .name           = "AEC62xx_IDE",
        .id_table       = aec62xx_pci_tbl,
        .probe          = aec62xx_init_one,
@@ -313,12 +313,12 @@ static struct pci_driver driver = {
 
 static int __init aec62xx_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&aec62xx_pci_driver);
 }
 
 static void __exit aec62xx_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&aec62xx_pci_driver);
 }
 
 module_init(aec62xx_ide_init);
index 053c75263918d592c60a70024ee7ef47c564953d..daf9dce39e522226a83d5433179e414b1c8a4730 100644 (file)
@@ -77,8 +77,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
        int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
        int port = hwif->channel ? 0x5c : 0x58;
        int portFIFO = hwif->channel ? 0x55 : 0x54;
-       u8 cd_dma_fifo = 0;
-       int unit = drive->select.b.unit & 1;
+       u8 cd_dma_fifo = 0, unit = drive->dn & 1;
 
        if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
                s_clc = 0;
@@ -112,7 +111,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
        }
        
        pci_write_config_byte(dev, port, s_clc);
-       pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
+       pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
        local_irq_restore(flags);
 }
 
@@ -154,7 +153,7 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 speed1               = speed;
-       u8 unit                 = (drive->select.b.unit & 0x01);
+       u8 unit                 = drive->dn & 1;
        u8 tmpbyte              = 0x00;
        int m5229_udma          = (hwif->channel) ? 0x57 : 0x56;
 
@@ -508,7 +507,7 @@ static const struct ide_dma_ops ali_dma_ops = {
        .dma_setup              = ali15x3_dma_setup,
        .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
-       .dma_end                = __ide_dma_end,
+       .dma_end                = ide_dma_end,
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
@@ -576,7 +575,7 @@ static const struct pci_device_id alim15x3_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver alim15x3_pci_driver = {
        .name           = "ALI15x3_IDE",
        .id_table       = alim15x3_pci_tbl,
        .probe          = alim15x3_init_one,
@@ -587,12 +586,12 @@ static struct pci_driver driver = {
 
 static int __init ali15x3_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&alim15x3_pci_driver);
 }
 
 static void __exit ali15x3_ide_exit(void)
 {
-       return pci_unregister_driver(&driver);
+       return pci_unregister_driver(&alim15x3_pci_driver);
 }
 
 module_init(ali15x3_ide_init);
index 824471f91bf5f739047e4f962f53605e9c466dee..81ec73134edacfead9286aa479c0a73f1526de05 100644 (file)
@@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
 
        ide_timing_compute(drive, speed, &t, T, UT);
 
-       if (peer->present) {
+       if (peer->dev_flags & IDE_DFLAG_PRESENT) {
                ide_timing_compute(peer, peer->current_speed, &p, T, UT);
                ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
        }
@@ -319,7 +319,7 @@ static const struct pci_device_id amd74xx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver amd74xx_pci_driver = {
        .name           = "AMD_IDE",
        .id_table       = amd74xx_pci_tbl,
        .probe          = amd74xx_probe,
@@ -330,12 +330,12 @@ static struct pci_driver driver = {
 
 static int __init amd74xx_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&amd74xx_pci_driver);
 }
 
 static void __exit amd74xx_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&amd74xx_pci_driver);
 }
 
 module_init(amd74xx_ide_init);
index e4437034dd0820d237c9af8ecae7642374293234..b2735d28f5cc22019b88c8f159da1af91dccbb7e 100644 (file)
@@ -182,7 +182,7 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver atiixp_pci_driver = {
        .name           = "ATIIXP_IDE",
        .id_table       = atiixp_pci_tbl,
        .probe          = atiixp_init_one,
@@ -193,12 +193,12 @@ static struct pci_driver driver = {
 
 static int __init atiixp_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&atiixp_pci_driver);
 }
 
 static void __exit atiixp_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&atiixp_pci_driver);
 }
 
 module_init(atiixp_ide_init);
index 7f39cdb414109ece635ba535e49eb5529a0f51f1..e4306647d00d6782e8db72d40d82827bb085044f 100644 (file)
@@ -378,13 +378,13 @@ static void __set_prefetch_mode(ide_drive_t *drive, int mode)
 {
        if (mode) {     /* want prefetch on? */
 #if CMD640_PREFETCH_MASKS
-               drive->no_unmask = 1;
-               drive->unmask = 0;
+               drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags &= ~IDE_DFLAG_UNMASK;
 #endif
-               drive->no_io_32bit = 0;
+               drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
        } else {
-               drive->no_unmask = 0;
-               drive->no_io_32bit = 1;
+               drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
+               drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
                drive->io_32bit = 0;
        }
 }
@@ -468,10 +468,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
         */
        if (index > 1) {
                ide_hwif_t *hwif = drive->hwif;
-               ide_drive_t *peer = &hwif->drives[!drive->select.b.unit];
+               ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
                unsigned int mate = index ^ 1;
 
-               if (peer->present) {
+               if (peer->dev_flags & IDE_DFLAG_PRESENT) {
                        if (setup_count < setup_counts[mate])
                                setup_count = setup_counts[mate];
                        if (active_count < active_counts[mate])
@@ -607,7 +607,7 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
 
 static void cmd640_init_dev(ide_drive_t *drive)
 {
-       unsigned int i = drive->hwif->channel * 2 + drive->select.b.unit;
+       unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
 
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
        /*
@@ -626,7 +626,7 @@ static void cmd640_init_dev(ide_drive_t *drive)
         */
        check_prefetch(drive, i);
        printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n",
-                                 i, drive->no_io_32bit ? "off" : "on");
+               i, (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) ? "off" : "on");
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 }
 
index 456dee18b660fa94dc72c85877fa598f511c79ca..935385c77e062d12e6ad6061942dfcdd5cbbdd8d 100644 (file)
@@ -228,7 +228,7 @@ static int cmd648_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long base      = hwif->dma_base - (hwif->channel * 8);
-       int err                 = __ide_dma_end(drive);
+       int err                 = ide_dma_end(drive);
        u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
                                                  MRDMODE_INTR_CH0;
        u8  mrdmode             = inb(base + 1);
@@ -248,7 +248,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
        u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
                                                  CFR_INTR_CH0;
        u8  irq_stat            = 0;
-       int err                 = __ide_dma_end(drive);
+       int err                 = ide_dma_end(drive);
 
        (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
        /* clear the interrupt bit */
@@ -505,7 +505,7 @@ static const struct pci_device_id cmd64x_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver cmd64x_pci_driver = {
        .name           = "CMD64x_IDE",
        .id_table       = cmd64x_pci_tbl,
        .probe          = cmd64x_init_one,
@@ -516,12 +516,12 @@ static struct pci_driver driver = {
 
 static int __init cmd64x_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&cmd64x_pci_driver);
 }
 
 static void __exit cmd64x_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&cmd64x_pci_driver);
 }
 
 module_init(cmd64x_ide_init);
index d6341f7c4144b15e08b78372637f5e582266c968..5efb467f8fa0009fa257e9e6a41de1afa3e3f630 100644 (file)
@@ -145,7 +145,7 @@ static const struct pci_device_id cs5520_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver cs5520_pci_driver = {
        .name           = "Cyrix_IDE",
        .id_table       = cs5520_pci_tbl,
        .probe          = cs5520_init_one,
@@ -155,7 +155,7 @@ static struct pci_driver driver = {
 
 static int __init cs5520_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&cs5520_pci_driver);
 }
 
 module_init(cs5520_ide_init);
index da42fa7e9f979ea5d5eed4731d473f96a1d95929..53f079cc00afc010f2cf62b643fe98432feceea8 100644 (file)
@@ -267,7 +267,7 @@ static const struct pci_device_id cs5530_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, cs5530_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver cs5530_pci_driver = {
        .name           = "CS5530 IDE",
        .id_table       = cs5530_pci_tbl,
        .probe          = cs5530_init_one,
@@ -278,12 +278,12 @@ static struct pci_driver driver = {
 
 static int __init cs5530_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&cs5530_pci_driver);
 }
 
 static void __exit cs5530_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&cs5530_pci_driver);
 }
 
 module_init(cs5530_ide_init);
index 1e5bc59ea2fb03074fa9729501660f0e7b33bfcd..983d957a01894a2b207eda57cc6a350430cd3307 100644 (file)
@@ -76,7 +76,7 @@ static unsigned int cs5535_udma_timings[5] =
 static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
 {
        u32 reg = 0, dummy;
-       int unit = drive->select.b.unit;
+       u8 unit = drive->dn & 1;
 
        /* Set the PIO timings */
        if (speed < XFER_SW_DMA_0) {
@@ -192,7 +192,7 @@ static const struct pci_device_id cs5535_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver cs5535_pci_driver = {
        .name           = "CS5535_IDE",
        .id_table       = cs5535_pci_tbl,
        .probe          = cs5535_init_one,
@@ -203,12 +203,12 @@ static struct pci_driver driver = {
 
 static int __init cs5535_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&cs5535_pci_driver);
 }
 
 static void __exit cs5535_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&cs5535_pci_driver);
 }
 
 module_init(cs5535_ide_init);
index 69820e9224d138978a32e8ddc879fe325117633e..5297f07d293300da38f9c1a3f1db7af41068aca1 100644 (file)
 
 #define DRV_NAME "cy82c693"
 
-/* the current version */
-#define CY82_VERSION   "CY82C693U driver v0.34 99-13-12 Andreas S. Krebs (akrebs@altavista.net)"
-
 /*
  *     The following are used to debug the driver.
  */
-#define CY82C693_DEBUG_LOGS    0
 #define CY82C693_DEBUG_INFO    0
 
-/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
-#undef CY82C693_SETDMA_CLOCK
-
 /*
  *     NOTE: the value for busmaster timeout is tricky and I got it by
  *     trial and error!  By using a to low value will cause DMA timeouts
@@ -89,7 +82,6 @@
 #define CY82_INDEX_PORT                0x22
 #define CY82_DATA_PORT         0x23
 
-#define CY82_INDEX_CTRLREG1    0x01
 #define CY82_INDEX_CHANNEL0    0x30
 #define CY82_INDEX_CHANNEL1    0x31
 #define CY82_INDEX_TIMEOUT     0x32
@@ -179,17 +171,6 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
 
        index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
 
-#if CY82C693_DEBUG_LOGS
-       /* for debug let's show the previous values */
-
-       outb(index, CY82_INDEX_PORT);
-       data = inb(CY82_DATA_PORT);
-
-       printk(KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n",
-               drive->name, HWIF(drive)->channel, drive->select.b.unit,
-               (data&0x3), ((data>>2)&1));
-#endif /* CY82C693_DEBUG_LOGS */
-
        data = (mode & 3) | (single << 2);
 
        outb(index, CY82_INDEX_PORT);
@@ -197,8 +178,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
 
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
-               drive->name, HWIF(drive)->channel, drive->select.b.unit,
-               mode & 3, single);
+               drive->name, hwif->channel, drive->dn & 1, mode & 3, single);
 #endif /* CY82C693_DEBUG_INFO */
 
        /*
@@ -239,50 +219,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
                }
        }
 
-#if CY82C693_DEBUG_LOGS
-       /* for debug let's show the register values */
-
-       if (drive->select.b.unit == 0) {
-               /*
-                * get master drive registers
-                * address setup control register
-                * is 32 bit !!!
-                */
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-               addrCtrl &= 0x0F;
-
-               /* now let's get the remaining registers */
-               pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
-               pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
-               pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
-       } else {
-               /*
-                * set slave drive registers
-                * address setup control register
-                * is 32 bit !!!
-                */
-               pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
-
-               addrCtrl &= 0xF0;
-               addrCtrl >>= 4;
-
-               /* now let's get the remaining registers */
-               pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
-               pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
-               pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
-       }
-
-       printk(KERN_INFO "%s (ch=%d, dev=%d): PIO timing is "
-               "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
-               drive->name, hwif->channel, drive->select.b.unit,
-               addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
-#endif /* CY82C693_DEBUG_LOGS */
-
        /* let's calc the values for this PIO mode */
        compute_clocks(pio, &pclk);
 
        /* now let's write  the clocks registers */
-       if (drive->select.b.unit == 0) {
+       if ((drive->dn & 1) == 0) {
                /*
                 * set master drive
                 * address setup control register
@@ -324,63 +265,11 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
 #if CY82C693_DEBUG_INFO
        printk(KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to "
                "(addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n",
-               drive->name, hwif->channel, drive->select.b.unit,
+               drive->name, hwif->channel, drive->dn & 1,
                addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
 #endif /* CY82C693_DEBUG_INFO */
 }
 
-/*
- * this function is called during init and is used to setup the cy82c693 chip
- */
-static unsigned int init_chipset_cy82c693(struct pci_dev *dev)
-{
-       if (PCI_FUNC(dev->devfn) != 1)
-               return 0;
-
-#ifdef CY82C693_SETDMA_CLOCK
-       u8 data = 0;
-#endif /* CY82C693_SETDMA_CLOCK */
-
-       /* write info about this verion of the driver */
-       printk(KERN_INFO CY82_VERSION "\n");
-
-#ifdef CY82C693_SETDMA_CLOCK
-       /* okay let's set the DMA clock speed */
-
-       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-       data = inb(CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
-       printk(KERN_INFO DRV_NAME ": Peripheral Configuration Register: 0x%X\n",
-               data);
-#endif /* CY82C693_DEBUG_INFO */
-
-       /*
-        * for some reason sometimes the DMA controller
-        * speed is set to ATCLK/2 ???? - we fix this here
-        *
-        * note: i don't know what causes this strange behaviour,
-        *       but even changing the dma speed doesn't solve it :-(
-        *       the ide performance is still only half the normal speed
-        *
-        *       if anybody knows what goes wrong with my machine, please
-        *       let me know - ASK
-        */
-
-       data |= 0x03;
-
-       outb(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
-       outb(data, CY82_DATA_PORT);
-
-#if CY82C693_DEBUG_INFO
-       printk(KERN_INFO ": New Peripheral Configuration Register: 0x%X\n",
-               data);
-#endif /* CY82C693_DEBUG_INFO */
-
-#endif /* CY82C693_SETDMA_CLOCK */
-       return 0;
-}
-
 static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
 {
        static ide_hwif_t *primary;
@@ -401,7 +290,6 @@ static const struct ide_port_ops cy82c693_port_ops = {
 
 static const struct ide_port_info cy82c693_chipset __devinitdata = {
        .name           = DRV_NAME,
-       .init_chipset   = init_chipset_cy82c693,
        .init_iops      = init_iops_cy82c693,
        .port_ops       = &cy82c693_port_ops,
        .chipset        = ide_cy82c693,
@@ -443,7 +331,7 @@ static const struct pci_device_id cy82c693_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver cy82c693_pci_driver = {
        .name           = "Cypress_IDE",
        .id_table       = cy82c693_pci_tbl,
        .probe          = cy82c693_init_one,
@@ -454,12 +342,12 @@ static struct pci_driver driver = {
 
 static int __init cy82c693_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&cy82c693_pci_driver);
 }
 
 static void __exit cy82c693_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&cy82c693_pci_driver);
 }
 
 module_init(cy82c693_ide_init);
index 83b63b365e51659ea6c6f934465e3076600c248b..8689a706f537186e46549d2253b51c5c66c3b3a6 100644 (file)
@@ -117,7 +117,7 @@ static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver delkin_cb_pci_driver = {
        .name           = "Delkin-ASKA-Workbit Cardbus IDE",
        .id_table       = delkin_cb_pci_tbl,
        .probe          = delkin_cb_probe,
@@ -126,12 +126,12 @@ static struct pci_driver driver = {
 
 static int __init delkin_cb_init(void)
 {
-       return pci_register_driver(&driver);
+       return pci_register_driver(&delkin_cb_pci_driver);
 }
 
 static void __exit delkin_cb_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&delkin_cb_pci_driver);
 }
 
 module_init(delkin_cb_init);
index 092b238cb250d81d914f8118f587b8d019fcda1d..474f96a7c076a317bd29d72be1f3b181b0b50686 100644 (file)
@@ -166,7 +166,7 @@ static const struct pci_device_id generic_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver generic_pci_driver = {
        .name           = "PCI_IDE",
        .id_table       = generic_pci_tbl,
        .probe          = generic_init_one,
@@ -177,12 +177,12 @@ static struct pci_driver driver = {
 
 static int __init generic_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&generic_pci_driver);
 }
 
 static void __exit generic_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&generic_pci_driver);
 }
 
 module_init(generic_ide_init);
index 644de29f8fe4a9f3ba2732abbc48968ae4a9195d..fb1a3aa57f073681dac953440ecdf9c803d54296 100644 (file)
@@ -166,7 +166,7 @@ static const struct pci_device_id hpt34x_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver hpt34x_pci_driver = {
        .name           = "HPT34x_IDE",
        .id_table       = hpt34x_pci_tbl,
        .probe          = hpt34x_init_one,
@@ -177,12 +177,12 @@ static struct pci_driver driver = {
 
 static int __init hpt34x_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&hpt34x_pci_driver);
 }
 
 static void __exit hpt34x_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&hpt34x_pci_driver);
 }
 
 module_init(hpt34x_ide_init);
index a194022b6a61b39260169d275278cdd5f1cc119b..9cf171cb9376b5265e07f87dfe88cb3a346bdc3f 100644 (file)
@@ -835,7 +835,7 @@ static int hpt370_dma_end(ide_drive_t *drive)
                if (dma_stat & 0x01)
                        hpt370_irq_timeout(drive);
        }
-       return __ide_dma_end(drive);
+       return ide_dma_end(drive);
 }
 
 static void hpt370_dma_timeout(ide_drive_t *drive)
@@ -863,9 +863,6 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
        if (dma_stat & 4)
                return 1;
 
-       if (!drive->waiting_for_dma)
-               printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                               drive->name, __func__);
        return 0;
 }
 
@@ -880,7 +877,7 @@ static int hpt374_dma_end(ide_drive_t *drive)
        pci_read_config_byte(dev, mcr_addr, &mcr);
        if (bwsr & mask)
                pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
-       return __ide_dma_end(drive);
+       return ide_dma_end(drive);
 }
 
 /**
@@ -1456,7 +1453,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
        .dma_setup              = ide_dma_setup,
        .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
-       .dma_end                = __ide_dma_end,
+       .dma_end                = ide_dma_end,
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = hpt366_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
@@ -1622,7 +1619,7 @@ static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver hpt366_pci_driver = {
        .name           = "HPT366_IDE",
        .id_table       = hpt366_pci_tbl,
        .probe          = hpt366_init_one,
@@ -1633,12 +1630,12 @@ static struct pci_driver driver = {
 
 static int __init hpt366_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&hpt366_pci_driver);
 }
 
 static void __exit hpt366_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&hpt366_pci_driver);
 }
 
 module_init(hpt366_ide_init);
index 0954ccd08d6fe718d37dc0fa48bfaa093611c635..7c2feeb3c5ec2f691821ec17e1dddcaec5df9189 100644 (file)
@@ -189,7 +189,7 @@ static const struct pci_device_id it8213_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, it8213_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver it8213_pci_driver = {
        .name           = "ITE8213_IDE",
        .id_table       = it8213_pci_tbl,
        .probe          = it8213_init_one,
@@ -200,12 +200,12 @@ static struct pci_driver driver = {
 
 static int __init it8213_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&it8213_pci_driver);
 }
 
 static void __exit it8213_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&it8213_pci_driver);
 }
 
 module_init(it8213_ide_init);
index 46edd083b3488b4c4ae6da9d31391aeb7c9461b2..995e18bb3139c55cde7bd06f4f7369c6ec3a9e70 100644 (file)
@@ -138,8 +138,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
        int channel = hwif->channel;
-       int unit = drive->select.b.unit;
-       u8 conf;
+       u8 unit = drive->dn & 1, conf;
 
        /* Program UDMA timing bits */
        if(itdev->clock_mode == ATA_66)
@@ -168,13 +167,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+       ide_drive_t *pair;
+       int clock, altclock, sel = 0;
+       u8 unit = drive->dn & 1, v;
 
-       u8 unit = drive->select.b.unit;
-       ide_drive_t *pair = &hwif->drives[1-unit];
-
-       int clock, altclock;
-       u8 v;
-       int sel = 0;
+       pair = &hwif->drives[1 - unit];
 
        if(itdev->want[0][0] > itdev->want[1][0]) {
                clock = itdev->want[0][1];
@@ -240,16 +237,17 @@ static void it821x_clock_strategy(ide_drive_t *drive)
 
 static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t *hwif        = drive->hwif;
+       ide_hwif_t *hwif = drive->hwif;
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int unit = drive->select.b.unit;
-       ide_drive_t *pair = &hwif->drives[1 - unit];
-       u8 set_pio = pio;
+       ide_drive_t *pair;
+       u8 unit = drive->dn & 1, set_pio = pio;
 
        /* Spec says 89 ref driver uses 88 */
        static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
        static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
 
+       pair = &hwif->drives[1 - unit];
+
        /*
         * Compute the best PIO mode we can for a given device. We must
         * pick a speed that does not cause problems with the other device
@@ -286,9 +284,7 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
        ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
-       int unit = drive->select.b.unit;
-       int channel = hwif->channel;
-       u8 conf;
+       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
 
        static u16 dma[]        = { 0x8866, 0x3222, 0x3121 };
        static u8 mwdma_want[]  = { ATA_ANY, ATA_66, ATA_ANY };
@@ -325,9 +321,7 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
        ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(hwif->dev);
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int unit = drive->select.b.unit;
-       int channel = hwif->channel;
-       u8 conf;
+       u8 unit = drive->dn & 1, channel = hwif->channel, conf;
 
        static u16 udma[]       = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 };
        static u8 udma_want[]   = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 };
@@ -369,7 +363,8 @@ static void it821x_dma_start(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int unit = drive->select.b.unit;
+       u8 unit = drive->dn & 1;
+
        if(itdev->mwdma[unit] != MWDMA_OFF)
                it821x_program(drive, itdev->mwdma[unit]);
        else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10)
@@ -389,9 +384,10 @@ static void it821x_dma_start(ide_drive_t *drive)
 static int it821x_dma_end(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
-       int unit = drive->select.b.unit;
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-       int ret = __ide_dma_end(drive);
+       int ret = ide_dma_end(drive);
+       u8 unit = drive->dn & 1;
+
        if(itdev->mwdma[unit] != MWDMA_OFF)
                it821x_program(drive, itdev->pio[unit]);
        return ret;
@@ -454,7 +450,7 @@ static void it821x_quirkproc(ide_drive_t *drive)
                 *      IRQ mask as we may well be in PIO (eg rev 0x10)
                 *      for now and we know unmasking is safe on this chipset.
                 */
-               drive->unmask = 1;
+               drive->dev_flags |= IDE_DFLAG_UNMASK;
        } else {
        /*
         *      Perform fixups on smart mode. We need to "lose" some
@@ -680,7 +676,7 @@ static const struct pci_device_id it821x_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, it821x_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver it821x_pci_driver = {
        .name           = "ITE821x IDE",
        .id_table       = it821x_pci_tbl,
        .probe          = it821x_init_one,
@@ -691,12 +687,12 @@ static struct pci_driver driver = {
 
 static int __init it821x_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&it821x_pci_driver);
 }
 
 static void __exit it821x_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&it821x_pci_driver);
 }
 
 module_init(it821x_ide_init);
index acd647110648628d045e8e6cbf75e7b9faa28c7e..9a68433cf46d38e041c4f5bf9f5a8e1e6927656f 100644 (file)
@@ -149,7 +149,7 @@ static struct pci_device_id jmicron_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, jmicron_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver jmicron_pci_driver = {
        .name           = "JMicron IDE",
        .id_table       = jmicron_pci_tbl,
        .probe          = jmicron_init_one,
@@ -160,12 +160,12 @@ static struct pci_driver driver = {
 
 static int __init jmicron_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&jmicron_pci_driver);
 }
 
 static void __exit jmicron_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&jmicron_pci_driver);
 }
 
 module_init(jmicron_ide_init);
index 53bd645736d965b73eeee8f8ffaeacc12a193cce..13789060f407fd7dc1ff860d40a989e026e1a8ae 100644 (file)
@@ -137,7 +137,7 @@ static void __devinit superio_init_iops(struct hwif_s *hwif)
 static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
 /*
- * This routine either enables/disables (according to drive->present)
+ * This routine either enables/disables (according to IDE_DFLAG_PRESENT)
  * the IRQ associated with the port (HWIF(drive)),
  * and selects either PIO or DMA handshaking for the next I/O operation.
  */
@@ -153,11 +153,15 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 
        /* Adjust IRQ enable bit */
        bit = 1 << (8 + hwif->channel);
-       new = drive->present ? (new & ~bit) : (new | bit);
+
+       if (drive->dev_flags & IDE_DFLAG_PRESENT)
+               new &= ~bit;
+       else
+               new |= bit;
 
        /* Select PIO or DMA, DMA may only be selected for one drive/channel. */
-       bit   = 1 << (20 + drive->select.b.unit       + (hwif->channel << 1));
-       other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+       bit   = 1 << (20 + (drive->dn & 1) + (hwif->channel << 1));
+       other = 1 << (20 + (1 - (drive->dn & 1)) + (hwif->channel << 1));
        new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
 
        if (new != *old) {
@@ -187,7 +191,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 
 static void ns87415_selectproc (ide_drive_t *drive)
 {
-       ns87415_prepare_drive (drive, drive->using_dma);
+       ns87415_prepare_drive(drive,
+                             !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
 }
 
 static int ns87415_dma_end(ide_drive_t *drive)
@@ -334,7 +339,7 @@ static const struct pci_device_id ns87415_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver ns87415_pci_driver = {
        .name           = "NS87415_IDE",
        .id_table       = ns87415_pci_tbl,
        .probe          = ns87415_init_one,
@@ -345,12 +350,12 @@ static struct pci_driver driver = {
 
 static int __init ns87415_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&ns87415_pci_driver);
 }
 
 static void __exit ns87415_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&ns87415_pci_driver);
 }
 
 module_init(ns87415_ide_init);
index 3de11ddcf863f1e1295c1f47d45fd3a6bef33e23..6048eda3cd613711f05fa44226857bb66faff51c 100644 (file)
@@ -179,7 +179,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
        misc = addr_timings[clk][addr_pio];
 
        /* select Index-0/1 for Register-A/B */
-       write_reg(drive->select.b.unit, MISC_REG);
+       write_reg(drive->dn & 1, MISC_REG);
        /* set read cycle timings */
        write_reg(tim, READ_REG);
        /* set write cycle timings */
@@ -220,7 +220,7 @@ static const struct pci_device_id opti621_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver opti621_pci_driver = {
        .name           = "Opti621_IDE",
        .id_table       = opti621_pci_tbl,
        .probe          = opti621_init_one,
@@ -231,12 +231,12 @@ static struct pci_driver driver = {
 
 static int __init opti621_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&opti621_pci_driver);
 }
 
 static void __exit opti621_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&opti621_pci_driver);
 }
 
 module_init(opti621_ide_init);
index 9fc59962553b32fd5f4f72c32ec378d9fb09fe55..211ae46e3e0ca2101d0cf5bb1d8d7039422e95df 100644 (file)
@@ -561,7 +561,7 @@ static const struct pci_device_id pdc202new_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver pdc202new_pci_driver = {
        .name           = "Promise_IDE",
        .id_table       = pdc202new_pci_tbl,
        .probe          = pdc202new_init_one,
@@ -572,12 +572,12 @@ static struct pci_driver driver = {
 
 static int __init pdc202new_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&pdc202new_pci_driver);
 }
 
 static void __exit pdc202new_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&pdc202new_pci_driver);
 }
 
 module_init(pdc202new_ide_init);
index cb6d2a00c514a5624e5e4fa2caf1b0c938b7ab36..799557c25eefede0c583680ccf5fbb39d91510ca 100644 (file)
@@ -168,7 +168,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
 {
        if (drive->current_speed > XFER_UDMA_2)
                pdc_old_enable_66MHz_clock(drive->hwif);
-       if (drive->media != ide_disk || drive->addressing == 1) {
+       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
                struct request *rq      = HWGROUP(drive)->rq;
                ide_hwif_t *hwif        = HWIF(drive);
                unsigned long high_16   = hwif->extra_base - 16;
@@ -188,7 +188,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
 
 static int pdc202xx_dma_end(ide_drive_t *drive)
 {
-       if (drive->media != ide_disk || drive->addressing == 1) {
+       if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
                ide_hwif_t *hwif        = HWIF(drive);
                unsigned long high_16   = hwif->extra_base - 16;
                unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
@@ -200,7 +200,7 @@ static int pdc202xx_dma_end(ide_drive_t *drive)
        }
        if (drive->current_speed > XFER_UDMA_2)
                pdc_old_disable_66MHz_clock(drive->hwif);
-       return __ide_dma_end(drive);
+       return ide_dma_end(drive);
 }
 
 static int pdc202xx_dma_test_irq(ide_drive_t *drive)
@@ -333,7 +333,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = {
        .dma_setup              = ide_dma_setup,
        .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
-       .dma_end                = __ide_dma_end,
+       .dma_end                = ide_dma_end,
        .dma_test_irq           = pdc202xx_dma_test_irq,
        .dma_lost_irq           = pdc202xx_dma_lost_irq,
        .dma_timeout            = pdc202xx_dma_timeout,
@@ -426,7 +426,7 @@ static const struct pci_device_id pdc202xx_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver pdc202xx_pci_driver = {
        .name           = "Promise_Old_IDE",
        .id_table       = pdc202xx_pci_tbl,
        .probe          = pdc202xx_init_one,
@@ -437,12 +437,12 @@ static struct pci_driver driver = {
 
 static int __init pdc202xx_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&pdc202xx_pci_driver);
 }
 
 static void __exit pdc202xx_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&pdc202xx_pci_driver);
 }
 
 module_init(pdc202xx_ide_init);
index a06c03f8e29539da2567dcb8563392d6078bec5a..d63f9fdca76bce87e37f4c6604ade546be5f6ab7 100644 (file)
@@ -215,17 +215,26 @@ static unsigned int init_chipset_ich(struct pci_dev *dev)
 }
 
 /**
- *     piix_dma_clear_irq      -       clear BMDMA status
- *     @drive: IDE drive to clear
+ *     ich_clear_irq   -       clear BMDMA status
+ *     @drive: IDE drive
  *
- *     Called from ide_intr() for PIO interrupts
- *     to clear BMDMA status as needed by ICHx
+ *     ICHx contollers set DMA INTR no matter DMA or PIO.
+ *     BMDMA status might need to be cleared even for
+ *     PIO interrupts to prevent spurious/lost IRQ.
  */
-static void piix_dma_clear_irq(ide_drive_t *drive)
+static void ich_clear_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        u8 dma_stat;
 
+       /*
+        * ide_dma_end() needs BMDMA status for error checking.
+        * So, skip clearing BMDMA status here and leave it
+        * to ide_dma_end() if this is DMA interrupt.
+        */
+       if (drive->waiting_for_dma || hwif->dma_base == 0)
+               return;
+
        /* clear the INTR & ERROR bits */
        dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
        /* Should we force the bit as well ? */
@@ -249,6 +258,7 @@ static const struct ich_laptop ich_laptop[] = {
        { 0x27DF, 0x1025, 0x0110 },     /* ICH7 on Acer 3682WLMi */
        { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
        { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
+       { 0x27DF, 0x1071, 0xD221 },     /* ICH7 on Hercules EC-900 */
        { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on Acer Aspire 2023WLMi */
        { 0x2653, 0x1043, 0x82D8 },     /* ICH6M on Asus Eee 701 */
        /* end marker */
@@ -293,21 +303,19 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
                hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
 }
 
-static void __devinit init_hwif_ich(ide_hwif_t *hwif)
-{
-       init_hwif_piix(hwif);
-
-       /* ICHx need to clear the BMDMA status for all interrupts */
-       if (hwif->dma_base)
-               hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
-}
-
 static const struct ide_port_ops piix_port_ops = {
        .set_pio_mode           = piix_set_pio_mode,
        .set_dma_mode           = piix_set_dma_mode,
        .cable_detect           = piix_cable_detect,
 };
 
+static const struct ide_port_ops ich_port_ops = {
+       .set_pio_mode           = piix_set_pio_mode,
+       .set_dma_mode           = piix_set_dma_mode,
+       .clear_irq              = ich_clear_irq,
+       .cable_detect           = piix_cable_detect,
+};
+
 #ifndef CONFIG_IA64
  #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
 #else
@@ -331,9 +339,9 @@ static const struct ide_port_ops piix_port_ops = {
        { \
                .name           = DRV_NAME, \
                .init_chipset   = init_chipset_ich, \
-               .init_hwif      = init_hwif_ich, \
+               .init_hwif      = init_hwif_piix, \
                .enablebits     = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
-               .port_ops       = &piix_port_ops, \
+               .port_ops       = &ich_port_ops, \
                .host_flags     = IDE_HFLAGS_PIIX, \
                .pio_mask       = ATA_PIO4, \
                .swdma_mask     = ATA_SWDMA2_ONLY, \
@@ -444,7 +452,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver piix_pci_driver = {
        .name           = "PIIX_IDE",
        .id_table       = piix_pci_tbl,
        .probe          = piix_init_one,
@@ -456,12 +464,12 @@ static struct pci_driver driver = {
 static int __init piix_ide_init(void)
 {
        piix_check_450nx();
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&piix_pci_driver);
 }
 
 static void __exit piix_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&piix_pci_driver);
 }
 
 module_init(piix_ide_init);
index c117a068761be47c585c6e259826a658d9c62613..7daf0135cbac678a0e22dcda2c388ceebf843f9b 100644 (file)
@@ -59,7 +59,7 @@ static const struct pci_device_id rz1000_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver rz1000_pci_driver = {
        .name           = "RZ1000_IDE",
        .id_table       = rz1000_pci_tbl,
        .probe          = rz1000_init_one,
@@ -68,12 +68,12 @@ static struct pci_driver driver = {
 
 static int __init rz1000_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&rz1000_pci_driver);
 }
 
 static void __exit rz1000_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&rz1000_pci_driver);
 }
 
 module_init(rz1000_ide_init);
index bdc1fed412604a72b0d206c3a9179d5f8253b2af..f1a8758e3a99f7d8b6953782c4150c35fefb8097 100644 (file)
@@ -126,7 +126,6 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
        ide_hwif_t              *hwif = HWIF(drive);
        struct pci_dev          *dev = to_pci_dev(hwif->dev);
-       int                     unit = drive->select.b.unit;
        unsigned int            reg, timings;
        unsigned short          pci_clock;
        unsigned int            basereg = hwif->channel ? 0x50 : 0x40;
@@ -155,7 +154,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
        else
                timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
 
-       if (unit == 0) {                        /* are we configuring drive0? */
+       if ((drive->dn & 1) == 0) {
                pci_read_config_dword(dev, basereg + 4, &reg);
                timings |= reg & 0x80000000;    /* preserve PIO format bit */
                pci_write_config_dword(dev, basereg + 4, timings);
@@ -216,7 +215,8 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
        if (mode != -1) {
                printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
                ide_dma_off_quietly(drive);
-               if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
+               if (ide_set_dma_mode(drive, mode) == 0 &&
+                   (drive->dev_flags & IDE_DFLAG_USING_DMA))
                        hwif->dma_ops->dma_host_set(drive, 1);
                return;
        }
@@ -328,7 +328,7 @@ static const struct pci_device_id sc1200_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver sc1200_pci_driver = {
        .name           = "SC1200_IDE",
        .id_table       = sc1200_pci_tbl,
        .probe          = sc1200_init_one,
@@ -341,12 +341,12 @@ static struct pci_driver driver = {
 
 static int __init sc1200_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&sc1200_pci_driver);
 }
 
 static void __exit sc1200_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&sc1200_pci_driver);
 }
 
 module_init(sc1200_ide_init);
index e92a874b31dfa07bc7334f6795bacac3927e1258..9ce1d8059921932de41938cc874412088b75b4ee 100644 (file)
@@ -291,7 +291,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
 static void scc_dma_host_set(ide_drive_t *drive, int on)
 {
        ide_hwif_t *hwif = drive->hwif;
-       u8 unit = (drive->select.b.unit & 0x01);
+       u8 unit = drive->dn & 1;
        u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
 
        if (on)
@@ -353,7 +353,6 @@ static void scc_dma_start(ide_drive_t *drive)
 
        /* start DMA */
        scc_ide_outb(dma_cmd | 1, hwif->dma_base);
-       hwif->dma = 1;
        wmb();
 }
 
@@ -374,7 +373,6 @@ static int __scc_dma_end(ide_drive_t *drive)
        /* purge DMA mappings */
        ide_destroy_dmatable(drive);
        /* verify good DMA status */
-       hwif->dma = 0;
        wmb();
        return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
 }
@@ -511,9 +509,6 @@ static int scc_dma_test_irq(ide_drive_t *drive)
        if (int_stat & INTSTS_IOIRQS)
                return 1;
 
-       if (!drive->waiting_for_dma)
-               printk(KERN_WARNING "%s: (%s) called while not waiting\n",
-                       drive->name, __func__);
        return 0;
 }
 
@@ -710,7 +705,7 @@ static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
                scc_ide_outb(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               scc_ide_outb((tf->device & HIHI) | drive->select.all,
+               scc_ide_outb((tf->device & HIHI) | drive->select,
                             io_ports->device_addr);
 }
 
@@ -826,6 +821,12 @@ static void __devinit init_iops_scc(ide_hwif_t *hwif)
        init_mmio_iops_scc(hwif);
 }
 
+static int __devinit scc_init_dma(ide_hwif_t *hwif,
+                                 const struct ide_port_info *d)
+{
+       return ide_allocate_dma_engine(hwif);
+}
+
 static u8 scc_cable_detect(ide_hwif_t *hwif)
 {
        return ATA_CBL_PATA80;
@@ -890,6 +891,7 @@ static const struct ide_dma_ops scc_dma_ops = {
   {                                                    \
       .name            = name_str,                     \
       .init_iops       = init_iops_scc,                \
+      .init_dma                = scc_init_dma,                 \
       .init_hwif       = init_hwif_scc,                \
       .tp_ops          = &scc_tp_ops,          \
       .port_ops                = &scc_port_ops,                \
@@ -927,13 +929,6 @@ static void __devexit scc_remove(struct pci_dev *dev)
 {
        struct scc_ports *ports = pci_get_drvdata(dev);
        struct ide_host *host = ports->host;
-       ide_hwif_t *hwif = host->ports[0];
-
-       if (hwif->dmatable_cpu) {
-               pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
-                                   hwif->dmatable_cpu, hwif->dmatable_dma);
-               hwif->dmatable_cpu = NULL;
-       }
 
        ide_host_remove(host);
 
@@ -949,7 +944,7 @@ static const struct pci_device_id scc_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver scc_pci_driver = {
        .name = "SCC IDE",
        .id_table = scc_pci_tbl,
        .probe = scc_init_one,
@@ -958,14 +953,14 @@ static struct pci_driver driver = {
 
 static int scc_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&scc_pci_driver);
 }
 
 module_init(scc_ide_init);
 /* -- No exit code?
 static void scc_ide_exit(void)
 {
-       ide_pci_unregister_driver(&driver);
+       ide_pci_unregister_driver(&scc_pci_driver);
 }
 module_exit(scc_ide_exit);
  */
index 3dff2aea317e88ae261d5050b9b0ae3c1023dd7e..437bc919dafd8ae52d58e169ce4a2e373ca355b9 100644 (file)
@@ -153,7 +153,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
 
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u8 unit                 = (drive->select.b.unit & 0x01);
+       u8 unit                 = drive->dn & 1;
 
        u8 ultra_enable  = 0, ultra_timing = 0, dma_timing = 0;
 
@@ -443,7 +443,7 @@ static const struct pci_device_id svwks_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver svwks_pci_driver = {
        .name           = "Serverworks_IDE",
        .id_table       = svwks_pci_tbl,
        .probe          = svwks_init_one,
@@ -454,12 +454,12 @@ static struct pci_driver driver = {
 
 static int __init svwks_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&svwks_pci_driver);
 }
 
 static void __exit svwks_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&svwks_pci_driver);
 }
 
 module_init(svwks_ide_init);
index 1017fb4f63173d2891313c636f221c6c4d295d4d..dd634541ce361a62a4789484cdf89fe6a85584f3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2008 MontaVista Software, Inc.
  *
  * 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
@@ -150,7 +151,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
                int count = 0;
 
                stat = sgiioc4_read_status(hwif);
-               while ((stat & 0x80) && (count++ < 100)) {
+               while ((stat & ATA_BUSY) && (count++ < 100)) {
                        udelay(1);
                        stat = sgiioc4_read_status(hwif);
                }
@@ -310,7 +311,7 @@ static u8 sgiioc4_read_status(ide_hwif_t *hwif)
        u8 reg = (u8) readb((void __iomem *) port);
 
        if ((port & 0xFFF) == 0x11C) {  /* Status register of IOC4 */
-               if (reg & 0x51) {       /* Not busy...check for interrupt */
+               if (!(reg & ATA_BUSY)) { /* Not busy... check for interrupt */
                        unsigned long other_ir = port - 0x110;
                        unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
 
@@ -338,35 +339,31 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
        if (dma_base == 0)
                return -1;
 
-       printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
-              dma_base, dma_base + num_ports - 1);
+       printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
 
-       if (!request_mem_region(dma_base, num_ports, hwif->name)) {
-               printk(KERN_ERR
-                      "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
-                      "ALREADY in use\n",
-                      __func__, hwif->name, (void *) dma_base,
-                      (void *) dma_base + num_ports - 1);
+       if (request_mem_region(dma_base, num_ports, hwif->name) == NULL) {
+               printk(KERN_ERR "%s(%s) -- ERROR: addresses 0x%08lx to 0x%08lx "
+                      "already in use\n", __func__, hwif->name,
+                      dma_base, dma_base + num_ports - 1);
                return -1;
        }
 
        virt_dma_base = ioremap(dma_base, num_ports);
        if (virt_dma_base == NULL) {
-               printk(KERN_ERR
-                      "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
-                      __func__, hwif->name, dma_base, dma_base + num_ports - 1);
+               printk(KERN_ERR "%s(%s) -- ERROR: unable to map addresses "
+                      "0x%lx to 0x%lx\n", __func__, hwif->name,
+                      dma_base, dma_base + num_ports - 1);
                goto dma_remap_failure;
        }
        hwif->dma_base = (unsigned long) virt_dma_base;
 
-       hwif->dmatable_cpu = pci_alloc_consistent(dev,
-                                         IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
-                                         &hwif->dmatable_dma);
+       hwif->sg_max_nents = IOC4_PRD_ENTRIES;
 
-       if (!hwif->dmatable_cpu)
-               goto dma_pci_alloc_failure;
+       hwif->prd_max_nents = IOC4_PRD_ENTRIES;
+       hwif->prd_ent_size = IOC4_PRD_BYTES;
 
-       hwif->sg_max_nents = IOC4_PRD_ENTRIES;
+       if (ide_allocate_dma_engine(hwif))
+               goto dma_pci_alloc_failure;
 
        pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
                                   (dma_addr_t *)&hwif->extra_base);
@@ -375,13 +372,11 @@ ide_dma_sgiioc4(ide_hwif_t *hwif, const struct ide_port_info *d)
                return 0;
        }
 
-       pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
-                           hwif->dmatable_cpu, hwif->dmatable_dma);
-       printk(KERN_INFO
-              "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
+       ide_release_dma_engine(hwif);
+
+       printk(KERN_ERR "%s(%s) -- ERROR: Unable to allocate DMA maps\n",
               __func__, hwif->name);
-       printk(KERN_INFO
-              "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
+       printk(KERN_INFO "%s: changing from DMA to PIO mode", hwif->name);
 
 dma_pci_alloc_failure:
        iounmap(virt_dma_base);
@@ -617,14 +612,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
        irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
 
        cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
-       if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
-           DRV_NAME)) {
-               printk(KERN_ERR
-                       "%s %s: -- ERROR, Addresses "
-                       "0x%p to 0x%p ALREADY in use\n",
-                      DRV_NAME, pci_name(dev), (void *)cmd_phys_base,
-                      (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
-               return -ENOMEM;
+       if (request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+                              DRV_NAME) == NULL) {
+               printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx "
+                      "already in use\n", DRV_NAME, pci_name(dev),
+                      cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
+               return -EBUSY;
        }
 
        /* Initialize the IO registers */
index 174a873b4c6405229e48eb2714998cf9bef8ce69..eb4faf92c5719ceb3c95c2f23b8e40bf3a96d9db 100644 (file)
@@ -116,13 +116,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        unsigned long base      = (unsigned long)hwif->hwif_data;
+       u8 unit                 = drive->dn & 1;
 
        base += 0xA0 + r;
        if (hwif->host_flags & IDE_HFLAG_MMIO)
                base += hwif->channel << 6;
        else
                base += hwif->channel << 4;
-       base |= drive->select.b.unit << drive->select.b.unit;
+       base |= unit << unit;
        return base;
 }
 
@@ -255,7 +256,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
        u8 addr_mask            = hwif->channel ? (mmio ? 0xF4 : 0x84)
                                                : (mmio ? 0xB4 : 0x80);
        u8 mode                 = 0;
-       u8 unit                 = drive->select.b.unit;
+       u8 unit                 = drive->dn & 1;
 
        /* trim *taskfile* PIO to the slowest of the master/slave */
        if (pair) {
@@ -301,9 +302,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
 
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       u16 ultra = 0, multi    = 0;
-       u8 mode = 0, unit       = drive->select.b.unit;
        unsigned long base      = (unsigned long)hwif->hwif_data;
+       u16 ultra = 0, multi    = 0;
+       u8 mode = 0, unit       = drive->dn & 1;
        u8 mmio                 = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
        u8 scsc = 0, addr_mask  = hwif->channel ? (mmio ? 0xF4 : 0x84)
                                                : (mmio ? 0xB4 : 0x80);
@@ -712,7 +713,7 @@ static const struct ide_dma_ops sil_dma_ops = {
        .dma_setup              = ide_dma_setup,
        .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
-       .dma_end                = __ide_dma_end,
+       .dma_end                = ide_dma_end,
        .dma_test_irq           = siimage_dma_test_irq,
        .dma_timeout            = ide_dma_timeout,
        .dma_lost_irq           = ide_dma_lost_irq,
@@ -829,7 +830,7 @@ static const struct pci_device_id siimage_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver siimage_pci_driver = {
        .name           = "SiI_IDE",
        .id_table       = siimage_pci_tbl,
        .probe          = siimage_init_one,
@@ -840,12 +841,12 @@ static struct pci_driver driver = {
 
 static int __init siimage_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&siimage_pci_driver);
 }
 
 static void __exit siimage_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&siimage_pci_driver);
 }
 
 module_init(siimage_ide_init);
index 734dd41f1f679c649fc635d169f511eb7661518b..ad32e18c5ba368abbc8f5925181845c78b262df3 100644 (file)
@@ -605,7 +605,7 @@ static const struct pci_device_id sis5513_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver sis5513_pci_driver = {
        .name           = "SIS_IDE",
        .id_table       = sis5513_pci_tbl,
        .probe          = sis5513_init_one,
@@ -616,12 +616,12 @@ static struct pci_driver driver = {
 
 static int __init sis5513_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&sis5513_pci_driver);
 }
 
 static void __exit sis5513_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&sis5513_pci_driver);
 }
 
 module_init(sis5513_ide_init);
index 37a6b7bdc0403ac78ef95b89a1a31217c191aa08..84dc33602ff86277bcc69c39484befda8fca018c 100644 (file)
@@ -207,7 +207,7 @@ static int sl82c105_dma_end(ide_drive_t *drive)
 
        DBG(("%s(drive:%s)\n", __func__, drive->name));
 
-       ret = __ide_dma_end(drive);
+       ret = ide_dma_end(drive);
 
        pci_write_config_word(dev, reg, drive->drive_data);
 
@@ -345,7 +345,7 @@ static const struct pci_device_id sl82c105_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver sl82c105_pci_driver = {
        .name           = "W82C105_IDE",
        .id_table       = sl82c105_pci_tbl,
        .probe          = sl82c105_init_one,
@@ -356,12 +356,12 @@ static struct pci_driver driver = {
 
 static int __init sl82c105_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&sl82c105_pci_driver);
 }
 
 static void __exit sl82c105_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&sl82c105_pci_driver);
 }
 
 module_init(sl82c105_ide_init);
index a9551a13ac5717f014ea6fb0c27c2a7ac6bb1cff..0f759e4ed7799779e4492790b58ebf2147d1dcc5 100644 (file)
@@ -154,7 +154,7 @@ static const struct pci_device_id slc90e66_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver slc90e66_pci_driver = {
        .name           = "SLC90e66_IDE",
        .id_table       = slc90e66_pci_tbl,
        .probe          = slc90e66_init_one,
@@ -165,12 +165,12 @@ static struct pci_driver driver = {
 
 static int __init slc90e66_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&slc90e66_pci_driver);
 }
 
 static void __exit slc90e66_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&slc90e66_pci_driver);
 }
 
 module_init(slc90e66_ide_init);
index 927277c54ec9609d542605234761efa58a7cbce2..93e2cce4b296f5a55c50f32d5f0a4fe9f9133ff5 100644 (file)
@@ -186,7 +186,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
        .dma_setup              = ide_dma_setup,
        .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = tc86c001_dma_start,
-       .dma_end                = __ide_dma_end,
+       .dma_end                = ide_dma_end,
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
        .dma_timeout            = ide_dma_timeout,
@@ -245,7 +245,7 @@ static const struct pci_device_id tc86c001_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver tc86c001_pci_driver = {
        .name           = "TC86C001",
        .id_table       = tc86c001_pci_tbl,
        .probe          = tc86c001_init_one,
@@ -254,12 +254,12 @@ static struct pci_driver driver = {
 
 static int __init tc86c001_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&tc86c001_pci_driver);
 }
 
 static void __exit tc86c001_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&tc86c001_pci_driver);
 }
 
 module_init(tc86c001_ide_init);
index be8715dcee05ec735c35c8b88eb2493f0305736e..b6ff40336aa993c5960bc4754cb0dec40793ee32 100644 (file)
@@ -38,13 +38,12 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif = HWIF(drive);
        struct pci_dev *dev = to_pci_dev(hwif->dev);
-       u8 channel_offset = hwif->channel ? 0x74 : 0x70;
-       u16 timing = 0;
        u32 triflex_timings = 0;
-       u8 unit = (drive->select.b.unit & 0x01);
-       
+       u16 timing = 0;
+       u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1;
+
        pci_read_config_dword(dev, channel_offset, &triflex_timings);
-       
+
        switch(speed) {
                case XFER_MW_DMA_2:
                        timing = 0x0103; 
@@ -114,7 +113,7 @@ static const struct pci_device_id triflex_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver triflex_pci_driver = {
        .name           = "TRIFLEX_IDE",
        .id_table       = triflex_pci_tbl,
        .probe          = triflex_init_one,
@@ -125,12 +124,12 @@ static struct pci_driver driver = {
 
 static int __init triflex_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&triflex_pci_driver);
 }
 
 static void __exit triflex_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&triflex_pci_driver);
 }
 
 module_init(triflex_ide_init);
index 4dfbc6a68b5b371827b8ab355caae6941baffde7..75ea6152656663b6673c536e7903e4d2eb6bafda 100644 (file)
@@ -161,7 +161,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
        }
 
        /* enable IRQ if not probing */
-       if (drive->present) {
+       if (drive->dev_flags & IDE_DFLAG_PRESENT) {
                reg = inw(hwif->config_data + 3);
                reg &= 0x13;
                reg &= ~(1 << hwif->channel);
@@ -173,7 +173,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 
 static void trm290_selectproc (ide_drive_t *drive)
 {
-       trm290_prepare_drive(drive, drive->using_dma);
+       trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA));
 }
 
 static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
@@ -350,7 +350,7 @@ static const struct pci_device_id trm290_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver trm290_pci_driver = {
        .name           = "TRM290_IDE",
        .id_table       = trm290_pci_tbl,
        .probe          = trm290_init_one,
@@ -359,12 +359,12 @@ static struct pci_driver driver = {
 
 static int __init trm290_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&trm290_pci_driver);
 }
 
 static void __exit trm290_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&trm290_pci_driver);
 }
 
 module_init(trm290_ide_init);
index acacdaab69c2345a817b2b048bd19733ee10a072..2a812d3207e97d55be27c5f1363af67f96b90bdb 100644 (file)
@@ -487,7 +487,7 @@ static const struct pci_device_id via_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, via_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver via_pci_driver = {
        .name           = "VIA_IDE",
        .id_table       = via_pci_tbl,
        .probe          = via_init_one,
@@ -498,12 +498,12 @@ static struct pci_driver driver = {
 
 static int __init via_ide_init(void)
 {
-       return ide_pci_register_driver(&driver);
+       return ide_pci_register_driver(&via_pci_driver);
 }
 
 static void __exit via_ide_exit(void)
 {
-       pci_unregister_driver(&driver);
+       pci_unregister_driver(&via_pci_driver);
 }
 
 module_init(via_ide_init);
index c3432da78d5227b46f106ac995af650ac7d2c0fd..2e19d6298536f2fb94d3e0a8a1b5fd08877f3734 100644 (file)
@@ -430,10 +430,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
-       if (pmif == NULL)
-               return;
-
-       if (drive->select.b.unit & 0x01)
+       if (drive->dn & 1)
                writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
        else
                writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
@@ -452,10 +449,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
-       if (pmif == NULL)
-               return;
-
-       if (drive->select.b.unit & 0x01) {
+       if (drive->dn & 1) {
                writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
                writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
        } else {
@@ -475,9 +469,6 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
-       if (pmif == NULL)
-               return;
-
        if (pmif->kind == controller_sh_ata6 ||
            pmif->kind == controller_un_ata6 ||
            pmif->kind == controller_k2_ata6)
@@ -524,11 +515,8 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
        unsigned accessTime, recTime;
        unsigned int cycle_time;
 
-       if (pmif == NULL)
-               return;
-               
        /* which drive is it ? */
-       timings = &pmif->timings[drive->select.b.unit & 0x01];
+       timings = &pmif->timings[drive->dn & 1];
        t = *timings;
 
        cycle_time = ide_pio_cycle_time(drive, pio);
@@ -805,9 +793,9 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
        ide_hwif_t *hwif = drive->hwif;
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       int unit = (drive->select.b.unit & 0x01);
        int ret = 0;
        u32 *timings, *timings2, tl[2];
+       u8 unit = drive->dn & 1;
 
        timings = &pmif->timings[unit];
        timings2 = &pmif->timings[unit+2];
@@ -966,11 +954,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
        if (pmif->mediabay) {
 #ifdef CONFIG_PMAC_MEDIABAY
                if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
-                       drive->noprobe = 0;
+                       drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
                        return;
                }
 #endif
-               drive->noprobe = 1;
+               drive->dev_flags |= IDE_DFLAG_NOPROBE;
        }
 }
 
@@ -1535,18 +1523,6 @@ use_pio_instead:
        return 0; /* revert to PIO for this request */
 }
 
-/* Teardown mappings after DMA has completed.  */
-static void
-pmac_ide_destroy_dmatable (ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       if (hwif->sg_nents) {
-               ide_destroy_dmatable(drive);
-               hwif->sg_nents = 0;
-       }
-}
-
 /*
  * Prepare a DMA transfer. We build the DMA table, adjust the timings for
  * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
@@ -1558,12 +1534,7 @@ pmac_ide_dma_setup(ide_drive_t *drive)
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
        struct request *rq = HWGROUP(drive)->rq;
-       u8 unit = (drive->select.b.unit & 0x01);
-       u8 ata4;
-
-       if (pmif == NULL)
-               return 1;
-       ata4 = (pmif->kind == controller_kl_ata4);      
+       u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
 
        if (!pmac_ide_build_dmatable(drive, rq)) {
                ide_map_sg(drive, rq);
@@ -1617,17 +1588,15 @@ pmac_ide_dma_end (ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma;
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
        u32 dstat;
-       
-       if (pmif == NULL)
-               return 0;
-       dma = pmif->dma_regs;
 
        drive->waiting_for_dma = 0;
        dstat = readl(&dma->status);
        writel(((RUN|WAKE|DEAD) << 16), &dma->control);
-       pmac_ide_destroy_dmatable(drive);
+
+       ide_destroy_dmatable(drive);
+
        /* verify good dma status. we don't check for ACTIVE beeing 0. We should...
         * in theory, but with ATAPI decices doing buffer underruns, that would
         * cause us to disable DMA, which isn't what we want
@@ -1647,13 +1616,9 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma;
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
        unsigned long status, timeout;
 
-       if (pmif == NULL)
-               return 0;
-       dma = pmif->dma_regs;
-
        /* We have to things to deal with here:
         * 
         * - The dbdma won't stop if the command was started
@@ -1672,9 +1637,6 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
        status = readl(&dma->status);
        if (!(status & ACTIVE))
                return 1;
-       if (!drive->waiting_for_dma)
-               printk(KERN_WARNING "ide%d, ide_dma_test_irq \
-                       called while not waiting\n", HWIF(drive)->index);
 
        /* If dbdma didn't execute the STOP command yet, the
         * active bit is still set. We consider that we aren't
@@ -1709,14 +1671,9 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
-       volatile struct dbdma_regs __iomem *dma;
-       unsigned long status;
-
-       if (pmif == NULL)
-               return;
-       dma = pmif->dma_regs;
+       volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
+       unsigned long status = readl(&dma->status);
 
-       status = readl(&dma->status);
        printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
 }
 
index 9f95337139e3144424aba9c2e452939563f24586..5e38a68b8af279b0f6ad5a1280ef74db312f5730 100644 (file)
@@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = {
 
 
 #define quads_to_bytes(_q) ((_q) * sizeof(u32))
-#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32))
+#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32))
 
 static void free_keyval(struct csr1212_keyval *kv)
 {
index b6eb2cf25914479667439fa51e181fca1e986fbd..2f83543a9dfca95c797e42421055497fc1c6f2e0 100644 (file)
@@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
                /* default SYT offset is 3 cycles */
                init->syt_offset = 3;
 
-       if ( (init->channel > 63) || (init->channel < 0) )
+       if (init->channel > 63)
                init->channel = 63;
 
        chan_mask = (u64)1 << init->channel;
@@ -2296,10 +2296,10 @@ static void dv1394_add_host(struct hpsb_host *host)
 
        ohci = (struct ti_ohci *)host->hostdata;
 
-       device_create_drvdata(hpsb_protocol_class, NULL,
-                             MKDEV(IEEE1394_MAJOR,
-                                   IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
-                             "dv1394-%d", id);
+       device_create(hpsb_protocol_class, NULL,
+                     MKDEV(IEEE1394_MAJOR,
+                           IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+                     NULL, "dv1394-%d", id);
 
        dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
        dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
index b166b3575fa6d8904126e8a61ccaf604d5b9739f..20128692b3398be1c3a8556e78b593718894bdc1 100644 (file)
@@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
                hdr->ff.dgl = dgl;
                adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
        }
-       return (dg_size + adj_max_payload - 1) / adj_max_payload;
+       return DIV_ROUND_UP(dg_size, adj_max_payload);
 }
 
 static unsigned int ether1394_encapsulate(struct sk_buff *skb,
index 16240a7896509c024bacf59ff48bd8dd1c227d9d..2376b729e8765c5ca85bb7f1e0acf7201fe3b227 100644 (file)
@@ -154,9 +154,6 @@ struct host_info {
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
 static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
-static void nodemgr_resume_ne(struct node_entry *ne);
-static void nodemgr_remove_ne(struct node_entry *ne);
-static struct node_entry *find_entry_by_guid(u64 guid);
 
 struct bus_type ieee1394_bus_type = {
        .name           = "ieee1394",
@@ -385,27 +382,6 @@ static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute
 static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
 
 
-static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count)
-{
-       struct node_entry *ne;
-       u64 guid = (u64)simple_strtoull(buf, NULL, 16);
-
-       ne = find_entry_by_guid(guid);
-
-       if (ne == NULL || !ne->in_limbo)
-               return -EINVAL;
-
-       nodemgr_remove_ne(ne);
-
-       return count;
-}
-static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n");
-}
-static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
-
-
 static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
                             size_t count)
 {
@@ -442,7 +418,6 @@ static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set
 
 
 struct bus_attribute *const fw_bus_attrs[] = {
-       &bus_attr_destroy_node,
        &bus_attr_rescan,
        &bus_attr_ignore_drivers,
        NULL
@@ -734,10 +709,10 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
 
 static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
 
-static int __match_ne(struct device *dev, void *data)
+static int match_ne(struct device *dev, void *data)
 {
        struct unit_directory *ud;
-       struct node_entry *ne = (struct node_entry *)data;
+       struct node_entry *ne = data;
 
        ud = container_of(dev, struct unit_directory, unit_dev);
        return ud->ne == ne;
@@ -754,8 +729,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
         */
        mutex_lock(&nodemgr_serialize_remove_uds);
        for (;;) {
-               dev = class_find_device(&nodemgr_ud_class, NULL, ne,
-                                       __match_ne);
+               dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne);
                if (!dev)
                        break;
                ud = container_of(dev, struct unit_directory, unit_dev);
@@ -785,7 +759,7 @@ static void nodemgr_remove_ne(struct node_entry *ne)
        put_device(dev);
 }
 
-static int __nodemgr_remove_host_dev(struct device *dev, void *data)
+static int remove_host_dev(struct device *dev, void *data)
 {
        if (dev->bus == &ieee1394_bus_type)
                nodemgr_remove_ne(container_of(dev, struct node_entry,
@@ -795,7 +769,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data)
 
 static void nodemgr_remove_host_dev(struct device *dev)
 {
-       WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev));
+       device_for_each_child(dev, NULL, remove_host_dev);
        sysfs_remove_link(&dev->kobj, "irm_id");
        sysfs_remove_link(&dev->kobj, "busmgr_id");
        sysfs_remove_link(&dev->kobj, "host_id");
@@ -830,11 +804,10 @@ static void nodemgr_update_bus_options(struct node_entry *ne)
 }
 
 
-static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr,
-                                             struct host_info *hi, nodeid_t nodeid,
-                                             unsigned int generation)
+static struct node_entry *nodemgr_create_node(octlet_t guid,
+                               struct csr1212_csr *csr, struct hpsb_host *host,
+                               nodeid_t nodeid, unsigned int generation)
 {
-       struct hpsb_host *host = hi->host;
        struct node_entry *ne;
 
        ne = kzalloc(sizeof(*ne), GFP_KERNEL);
@@ -888,10 +861,10 @@ fail_alloc:
        return NULL;
 }
 
-static int __match_ne_guid(struct device *dev, void *data)
+static int match_ne_guid(struct device *dev, void *data)
 {
        struct node_entry *ne;
-       u64 *guid = (u64 *)data;
+       u64 *guid = data;
 
        ne = container_of(dev, struct node_entry, node_dev);
        return ne->guid == *guid;
@@ -902,8 +875,7 @@ static struct node_entry *find_entry_by_guid(u64 guid)
        struct device *dev;
        struct node_entry *ne;
 
-       dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
-                               __match_ne_guid);
+       dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid);
        if (!dev)
                return NULL;
        ne = container_of(dev, struct node_entry, node_dev);
@@ -912,21 +884,21 @@ static struct node_entry *find_entry_by_guid(u64 guid)
        return ne;
 }
 
-struct match_nodeid_param {
+struct match_nodeid_parameter {
        struct hpsb_host *host;
        nodeid_t nodeid;
 };
 
-static int __match_ne_nodeid(struct device *dev, void *data)
+static int match_ne_nodeid(struct device *dev, void *data)
 {
        int found = 0;
        struct node_entry *ne;
-       struct match_nodeid_param *param = (struct match_nodeid_param *)data;
+       struct match_nodeid_parameter *p = data;
 
        if (!dev)
                goto ret;
        ne = container_of(dev, struct node_entry, node_dev);
-       if (ne->host == param->host && ne->nodeid == param->nodeid)
+       if (ne->host == p->host && ne->nodeid == p->nodeid)
                found = 1;
 ret:
        return found;
@@ -937,13 +909,12 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
 {
        struct device *dev;
        struct node_entry *ne;
-       struct match_nodeid_param param;
+       struct match_nodeid_parameter p;
 
-       param.host = host;
-       param.nodeid = nodeid;
+       p.host = host;
+       p.nodeid = nodeid;
 
-       dev = class_find_device(&nodemgr_ne_class, NULL, &param,
-                               __match_ne_nodeid);
+       dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid);
        if (!dev)
                return NULL;
        ne = container_of(dev, struct node_entry, node_dev);
@@ -990,7 +961,7 @@ fail_devreg:
  * immediate unit directories looking for software_id and
  * software_version entries, in order to get driver autoloading working. */
 static struct unit_directory *nodemgr_process_unit_directory
-       (struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv,
+       (struct node_entry *ne, struct csr1212_keyval *ud_kv,
         unsigned int *id, struct unit_directory *parent)
 {
        struct unit_directory *ud;
@@ -1083,7 +1054,7 @@ static struct unit_directory *nodemgr_process_unit_directory
                                        nodemgr_register_device(ne, ud, &ne->device);
                                
                                /* process the child unit */
-                               ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);
+                               ud_child = nodemgr_process_unit_directory(ne, kv, id, ud);
 
                                if (ud_child == NULL)
                                        break;
@@ -1137,7 +1108,7 @@ unit_directory_error:
 }
 
 
-static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne)
+static void nodemgr_process_root_directory(struct node_entry *ne)
 {
        unsigned int ud_id = 0;
        struct csr1212_dentry *dentry;
@@ -1157,7 +1128,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
                        break;
 
                case CSR1212_KV_ID_UNIT:
-                       nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL);
+                       nodemgr_process_unit_directory(ne, kv, &ud_id, NULL);
                        break;
 
                case CSR1212_KV_ID_DESCRIPTOR:
@@ -1273,8 +1244,7 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
  * the to take whatever actions required.
  */
 static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
-                               struct host_info *hi, nodeid_t nodeid,
-                               unsigned int generation)
+                               nodeid_t nodeid, unsigned int generation)
 {
        if (ne->nodeid != nodeid) {
                HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
@@ -1305,19 +1275,23 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
                csr1212_destroy_csr(csr);
        }
 
-       if (ne->in_limbo)
-               nodemgr_resume_ne(ne);
-
        /* Mark the node current */
        ne->generation = generation;
-}
 
+       if (ne->in_limbo) {
+               device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
+               ne->in_limbo = false;
 
+               HPSB_DEBUG("Node reactivated: "
+                          "ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+                          NODE_BUS_ARGS(ne->host, ne->nodeid),
+                          (unsigned long long)ne->guid);
+       }
+}
 
-static void nodemgr_node_scan_one(struct host_info *hi,
+static void nodemgr_node_scan_one(struct hpsb_host *host,
                                  nodeid_t nodeid, int generation)
 {
-       struct hpsb_host *host = hi->host;
        struct node_entry *ne;
        octlet_t guid;
        struct csr1212_csr *csr;
@@ -1373,16 +1347,15 @@ static void nodemgr_node_scan_one(struct host_info *hi,
        }
 
        if (!ne)
-               nodemgr_create_node(guid, csr, hi, nodeid, generation);
+               nodemgr_create_node(guid, csr, host, nodeid, generation);
        else
-               nodemgr_update_node(ne, csr, hi, nodeid, generation);
+               nodemgr_update_node(ne, csr, nodeid, generation);
 }
 
 
-static void nodemgr_node_scan(struct host_info *hi, int generation)
+static void nodemgr_node_scan(struct hpsb_host *host, int generation)
 {
        int count;
-       struct hpsb_host *host = hi->host;
        struct selfid *sid = (struct selfid *)host->topology_map;
        nodeid_t nodeid = LOCAL_BUS;
 
@@ -1395,89 +1368,26 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
                        nodeid++;
                        continue;
                }
-               nodemgr_node_scan_one(hi, nodeid++, generation);
-       }
-}
-
-static int __nodemgr_driver_suspend(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct node_entry *ne = (struct node_entry *)data;
-       int error;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       error = 1; /* release if suspend is not implemented */
-                       if (drv->suspend) {
-                               down(&ud->device.sem);
-                               error = drv->suspend(&ud->device, PMSG_SUSPEND);
-                               up(&ud->device.sem);
-                       }
-                       if (error)
-                               device_release_driver(&ud->device);
-                       put_driver(drv);
-               }
-       }
-
-       return 0;
-}
-
-static int __nodemgr_driver_resume(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct node_entry *ne = (struct node_entry *)data;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       if (drv->resume) {
-                               down(&ud->device.sem);
-                               drv->resume(&ud->device);
-                               up(&ud->device.sem);
-                       }
-                       put_driver(drv);
-               }
+               nodemgr_node_scan_one(host, nodeid++, generation);
        }
-
-       return 0;
 }
 
-static void nodemgr_suspend_ne(struct node_entry *ne)
+static void nodemgr_pause_ne(struct node_entry *ne)
 {
-       HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+       HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
                   NODE_BUS_ARGS(ne->host, ne->nodeid),
                   (unsigned long long)ne->guid);
 
-       ne->in_limbo = 1;
+       ne->in_limbo = true;
        WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
-
-       class_for_each_device(&nodemgr_ud_class, NULL, ne,
-                             __nodemgr_driver_suspend);
-}
-
-
-static void nodemgr_resume_ne(struct node_entry *ne)
-{
-       ne->in_limbo = 0;
-       device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-
-       class_for_each_device(&nodemgr_ud_class, NULL, ne,
-                             __nodemgr_driver_resume);
-       HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
 }
 
-static int __nodemgr_update_pdrv(struct device *dev, void *data)
+static int update_pdrv(struct device *dev, void *data)
 {
        struct unit_directory *ud;
        struct device_driver *drv;
        struct hpsb_protocol_driver *pdrv;
-       struct node_entry *ne = (struct node_entry *)data;
+       struct node_entry *ne = data;
        int error;
 
        ud = container_of(dev, struct unit_directory, unit_dev);
@@ -1503,11 +1413,9 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data)
 
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
-       class_for_each_device(&nodemgr_ud_class, NULL, ne,
-                             __nodemgr_update_pdrv);
+       class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
 }
 
-
 /* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
  * seems like an optional service but in the end it is practically mandatory
  * as a consequence of these clauses.
@@ -1535,11 +1443,12 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
 }
 
 
-static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
+static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne,
+                            int generation)
 {
        struct device *dev;
 
-       if (ne->host != hi->host || ne->in_limbo)
+       if (ne->host != host || ne->in_limbo)
                return;
 
        dev = get_device(&ne->device);
@@ -1554,40 +1463,40 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
         * down to the drivers. Otherwise, this is a dead node and we
         * suspend it. */
        if (ne->needs_probe)
-               nodemgr_process_root_directory(hi, ne);
+               nodemgr_process_root_directory(ne);
        else if (ne->generation == generation)
                nodemgr_update_pdrv(ne);
        else
-               nodemgr_suspend_ne(ne);
+               nodemgr_pause_ne(ne);
 
        put_device(dev);
 }
 
-struct probe_param {
-       struct host_info *hi;
+struct node_probe_parameter {
+       struct hpsb_host *host;
        int generation;
        bool probe_now;
 };
 
 static int node_probe(struct device *dev, void *data)
 {
-       struct probe_param *p = data;
+       struct node_probe_parameter *p = data;
        struct node_entry *ne;
 
-       if (p->generation != get_hpsb_generation(p->hi->host))
+       if (p->generation != get_hpsb_generation(p->host))
                return -EAGAIN;
 
        ne = container_of(dev, struct node_entry, node_dev);
        if (ne->needs_probe == p->probe_now)
-               nodemgr_probe_ne(p->hi, ne, p->generation);
+               nodemgr_probe_ne(p->host, ne, p->generation);
        return 0;
 }
 
-static void nodemgr_node_probe(struct host_info *hi, int generation)
+static int nodemgr_node_probe(struct hpsb_host *host, int generation)
 {
-       struct probe_param p;
+       struct node_probe_parameter p;
 
-       p.hi = hi;
+       p.host = host;
        p.generation = generation;
        /*
         * Do some processing of the nodes we've probed. This pulls them
@@ -1604,11 +1513,11 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
         */
        p.probe_now = false;
        if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return;
+               return 0;
 
        p.probe_now = true;
        if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return;
+               return 0;
        /*
         * Now let's tell the bus to rescan our devices. This may seem
         * like overhead, but the driver-model core will only scan a
@@ -1620,6 +1529,27 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
         */
        if (bus_rescan_devices(&ieee1394_bus_type) != 0)
                HPSB_DEBUG("bus_rescan_devices had an error");
+
+       return 1;
+}
+
+static int remove_nodes_in_limbo(struct device *dev, void *data)
+{
+       struct node_entry *ne;
+
+       if (dev->bus != &ieee1394_bus_type)
+               return 0;
+
+       ne = container_of(dev, struct node_entry, device);
+       if (ne->in_limbo)
+               nodemgr_remove_ne(ne);
+
+       return 0;
+}
+
+static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
+{
+       device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
 }
 
 static int nodemgr_send_resume_packet(struct hpsb_host *host)
@@ -1730,10 +1660,9 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
        return 1;
 }
 
-static int nodemgr_host_thread(void *__hi)
+static int nodemgr_host_thread(void *data)
 {
-       struct host_info *hi = (struct host_info *)__hi;
-       struct hpsb_host *host = hi->host;
+       struct hpsb_host *host = data;
        unsigned int g, generation = 0;
        int i, reset_cycles = 0;
 
@@ -1787,36 +1716,48 @@ static int nodemgr_host_thread(void *__hi)
                 * entries. This does not do the sysfs stuff, since that
                 * would trigger uevents and such, which is a bad idea at
                 * this point. */
-               nodemgr_node_scan(hi, generation);
+               nodemgr_node_scan(host, generation);
 
                /* This actually does the full probe, with sysfs
                 * registration. */
-               nodemgr_node_probe(hi, generation);
+               if (!nodemgr_node_probe(host, generation))
+                       continue;
 
                /* Update some of our sysfs symlinks */
                nodemgr_update_host_dev_links(host);
+
+               /* Sleep 3 seconds */
+               for (i = 3000/200; i; i--) {
+                       msleep_interruptible(200);
+                       if (kthread_should_stop())
+                               goto exit;
+
+                       if (generation != get_hpsb_generation(host))
+                               break;
+               }
+               /* Remove nodes which are gone, unless a bus reset happened */
+               if (!i)
+                       nodemgr_remove_nodes_in_limbo(host);
        }
 exit:
        HPSB_VERBOSE("NodeMgr: Exiting thread");
        return 0;
 }
 
-struct host_iter_param {
+struct per_host_parameter {
        void *data;
        int (*cb)(struct hpsb_host *, void *);
 };
 
-static int __nodemgr_for_each_host(struct device *dev, void *data)
+static int per_host(struct device *dev, void *data)
 {
        struct hpsb_host *host;
-       struct host_iter_param *hip = (struct host_iter_param *)data;
-       int error = 0;
+       struct per_host_parameter *p = data;
 
        host = container_of(dev, struct hpsb_host, host_dev);
-       error = hip->cb(host, hip->data);
-
-       return error;
+       return p->cb(host, p->data);
 }
+
 /**
  * nodemgr_for_each_host - call a function for each IEEE 1394 host
  * @data: an address to supply to the callback
@@ -1831,15 +1772,11 @@ static int __nodemgr_for_each_host(struct device *dev, void *data)
  */
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
 {
-       struct host_iter_param hip;
-       int error;
-
-       hip.cb = cb;
-       hip.data = data;
-       error = class_for_each_device(&hpsb_host_class, NULL, &hip,
-                                     __nodemgr_for_each_host);
+       struct per_host_parameter p;
 
-       return error;
+       p.cb = cb;
+       p.data = data;
+       return class_for_each_device(&hpsb_host_class, NULL, &p, per_host);
 }
 
 /* The following two convenience functions use a struct node_entry
@@ -1893,7 +1830,7 @@ static void nodemgr_add_host(struct hpsb_host *host)
                return;
        }
        hi->host = host;
-       hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d",
+       hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d",
                                 host->id);
        if (IS_ERR(hi->thread)) {
                HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
index 6eb26465a84ca44029c4d43cc3ba17ba1eb1c378..4f287a3561ba9943b8ecc9c8e33963da15fba9b3 100644 (file)
@@ -110,7 +110,7 @@ struct node_entry {
        struct device node_dev;
 
        /* Means this node is not attached anymore */
-       int in_limbo;
+       bool in_limbo;
 
        struct csr1212_csr *csr;
 };
index a06aaad5b448da6072a0c4469b60cfa64eafa1e3..7a225a4059870b17a43db380f9aa17b784f8cdd0 100644 (file)
@@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
 struct file_info {
         struct list_head list;
 
+       struct mutex state_mutex;
         enum { opened, initialized, connected } state;
         unsigned int protocol_version;
 
index 6fa9e4a21840b5f0cad2ce28b3754b293913e8fc..9f19ac492106a8107a0d9fc2f2af66d92908dfe0 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
                return -EFAULT;
        }
 
+       mutex_lock(&fi->state_mutex);
+
        switch (fi->state) {
        case opened:
                retval = state_opened(fi, req);
@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
                break;
        }
 
+       mutex_unlock(&fi->state_mutex);
+
        if (retval < 0) {
                free_pending_request(req);
        } else {
@@ -2541,109 +2546,120 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
 static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct file_info *fi = file->private_data;
+       int ret;
+
+       mutex_lock(&fi->state_mutex);
 
        if (fi->iso_state == RAW1394_ISO_INACTIVE)
-               return -EINVAL;
+               ret = -EINVAL;
+       else
+               ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
+
+       mutex_unlock(&fi->state_mutex);
 
-       return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
+       return ret;
 }
 
-/* ioctl is only used for rawiso operations */
-static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
+static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
+                                  void __user *argp)
+{
+       switch (cmd) {
+       case RAW1394_IOC_ISO_XMIT_INIT:
+               return raw1394_iso_xmit_init(fi, argp);
+       case RAW1394_IOC_ISO_RECV_INIT:
+               return raw1394_iso_recv_init(fi, argp);
+       default:
+               return -EINVAL;
+       }
+}
+
+static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
+                              unsigned long arg)
 {
-       struct file_info *fi = file->private_data;
        void __user *argp = (void __user *)arg;
 
-       switch (fi->iso_state) {
-       case RAW1394_ISO_INACTIVE:
-               switch (cmd) {
-               case RAW1394_IOC_ISO_XMIT_INIT:
-                       return raw1394_iso_xmit_init(fi, argp);
-               case RAW1394_IOC_ISO_RECV_INIT:
-                       return raw1394_iso_recv_init(fi, argp);
-               default:
-                       break;
+       switch (cmd) {
+       case RAW1394_IOC_ISO_RECV_START:{
+                       int args[3];
+
+                       if (copy_from_user(&args[0], argp, sizeof(args)))
+                               return -EFAULT;
+                       return hpsb_iso_recv_start(fi->iso_handle,
+                                                  args[0], args[1], args[2]);
                }
-               break;
-       case RAW1394_ISO_RECV:
-               switch (cmd) {
-               case RAW1394_IOC_ISO_RECV_START:{
-                               /* copy args from user-space */
-                               int args[3];
-                               if (copy_from_user
-                                   (&args[0], argp, sizeof(args)))
-                                       return -EFAULT;
-                               return hpsb_iso_recv_start(fi->iso_handle,
-                                                          args[0], args[1],
-                                                          args[2]);
-                       }
-               case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-                       hpsb_iso_stop(fi->iso_handle);
-                       return 0;
-               case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-                       return hpsb_iso_recv_listen_channel(fi->iso_handle,
-                                                           arg);
-               case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-                       return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
-                                                             arg);
-               case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
-                               /* copy the u64 from user-space */
-                               u64 mask;
-                               if (copy_from_user(&mask, argp, sizeof(mask)))
-                                       return -EFAULT;
-                               return hpsb_iso_recv_set_channel_mask(fi->
-                                                                     iso_handle,
-                                                                     mask);
-                       }
-               case RAW1394_IOC_ISO_GET_STATUS:
-                       return raw1394_iso_get_status(fi, argp);
-               case RAW1394_IOC_ISO_RECV_PACKETS:
-                       return raw1394_iso_recv_packets(fi, argp);
-               case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-                       return hpsb_iso_recv_release_packets(fi->iso_handle,
-                                                            arg);
-               case RAW1394_IOC_ISO_RECV_FLUSH:
-                       return hpsb_iso_recv_flush(fi->iso_handle);
-               case RAW1394_IOC_ISO_SHUTDOWN:
-                       raw1394_iso_shutdown(fi);
-                       return 0;
-               case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-                       queue_rawiso_event(fi);
-                       return 0;
+       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+               hpsb_iso_stop(fi->iso_handle);
+               return 0;
+       case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+               return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
+       case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+               return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
+       case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
+                       u64 mask;
+
+                       if (copy_from_user(&mask, argp, sizeof(mask)))
+                               return -EFAULT;
+                       return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
+                                                             mask);
                }
-               break;
-       case RAW1394_ISO_XMIT:
-               switch (cmd) {
-               case RAW1394_IOC_ISO_XMIT_START:{
-                               /* copy two ints from user-space */
-                               int args[2];
-                               if (copy_from_user
-                                   (&args[0], argp, sizeof(args)))
-                                       return -EFAULT;
-                               return hpsb_iso_xmit_start(fi->iso_handle,
-                                                          args[0], args[1]);
-                       }
-               case RAW1394_IOC_ISO_XMIT_SYNC:
-                       return hpsb_iso_xmit_sync(fi->iso_handle);
-               case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-                       hpsb_iso_stop(fi->iso_handle);
-                       return 0;
-               case RAW1394_IOC_ISO_GET_STATUS:
-                       return raw1394_iso_get_status(fi, argp);
-               case RAW1394_IOC_ISO_XMIT_PACKETS:
-                       return raw1394_iso_send_packets(fi, argp);
-               case RAW1394_IOC_ISO_SHUTDOWN:
-                       raw1394_iso_shutdown(fi);
-                       return 0;
-               case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-                       queue_rawiso_event(fi);
-                       return 0;
+       case RAW1394_IOC_ISO_GET_STATUS:
+               return raw1394_iso_get_status(fi, argp);
+       case RAW1394_IOC_ISO_RECV_PACKETS:
+               return raw1394_iso_recv_packets(fi, argp);
+       case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+               return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
+       case RAW1394_IOC_ISO_RECV_FLUSH:
+               return hpsb_iso_recv_flush(fi->iso_handle);
+       case RAW1394_IOC_ISO_SHUTDOWN:
+               raw1394_iso_shutdown(fi);
+               return 0;
+       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+               queue_rawiso_event(fi);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
+                              void __user *argp)
+{
+       switch (cmd) {
+       case RAW1394_IOC_ISO_XMIT_START:{
+                       int args[2];
+
+                       if (copy_from_user(&args[0], argp, sizeof(args)))
+                               return -EFAULT;
+                       return hpsb_iso_xmit_start(fi->iso_handle,
+                                                  args[0], args[1]);
                }
-               break;
+       case RAW1394_IOC_ISO_XMIT_SYNC:
+               return hpsb_iso_xmit_sync(fi->iso_handle);
+       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+               hpsb_iso_stop(fi->iso_handle);
+               return 0;
+       case RAW1394_IOC_ISO_GET_STATUS:
+               return raw1394_iso_get_status(fi, argp);
+       case RAW1394_IOC_ISO_XMIT_PACKETS:
+               return raw1394_iso_send_packets(fi, argp);
+       case RAW1394_IOC_ISO_SHUTDOWN:
+               raw1394_iso_shutdown(fi);
+               return 0;
+       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+               queue_rawiso_event(fi);
+               return 0;
        default:
-               break;
+               return -EINVAL;
        }
+}
+
+/* ioctl is only used for rawiso operations */
+static long raw1394_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
+{
+       struct file_info *fi = file->private_data;
+       void __user *argp = (void __user *)arg;
+       long ret;
 
        /* state-independent commands */
        switch(cmd) {
@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
                break;
        }
 
-       return -EINVAL;
-}
+       mutex_lock(&fi->state_mutex);
+
+       switch (fi->iso_state) {
+       case RAW1394_ISO_INACTIVE:
+               ret = raw1394_ioctl_inactive(fi, cmd, argp);
+               break;
+       case RAW1394_ISO_RECV:
+               ret = raw1394_ioctl_recv(fi, cmd, arg);
+               break;
+       case RAW1394_ISO_XMIT:
+               ret = raw1394_ioctl_xmit(fi, cmd, argp);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       mutex_unlock(&fi->state_mutex);
 
-static long raw1394_ioctl(struct file *file, unsigned int cmd,
-                                                       unsigned long arg)
-{
-       long ret;
-       lock_kernel();
-       ret = do_raw1394_ioctl(file, cmd, arg);
-       unlock_kernel();
        return ret;
 }
 
@@ -2700,7 +2725,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
            !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
                infos = compat_ptr(infos32);
                if (!copy_to_user(&dst->infos, &infos, sizeof infos))
-                       err = do_raw1394_ioctl(file, cmd, (unsigned long)dst);
+                       err = raw1394_ioctl(file, cmd, (unsigned long)dst);
        }
        return err;
 }
@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file,
        void __user *argp = (void __user *)arg;
        long err;
 
-       lock_kernel();
        switch (cmd) {
        /* These requests have same format as long as 'int' has same size. */
        case RAW1394_IOC_ISO_RECV_INIT:
@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file,
        case RAW1394_IOC_ISO_GET_STATUS:
        case RAW1394_IOC_ISO_SHUTDOWN:
        case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               err = do_raw1394_ioctl(file, cmd, arg);
+               err = raw1394_ioctl(file, cmd, arg);
                break;
        /* These request have different format. */
        case RAW1394_IOC_ISO_RECV_PACKETS32:
@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file,
                err = -EINVAL;
                break;
        }
-       unlock_kernel();
 
        return err;
 }
@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
        fi->notification = (u8) RAW1394_NOTIFY_ON;      /* busreset notification */
 
        INIT_LIST_HEAD(&fi->list);
+       mutex_init(&fi->state_mutex);
        fi->state = opened;
        INIT_LIST_HEAD(&fi->req_pending);
        INIT_LIST_HEAD(&fi->req_complete);
@@ -3010,10 +3034,10 @@ static int __init init_raw1394(void)
        hpsb_register_highlevel(&raw1394_highlevel);
 
        if (IS_ERR
-           (device_create_drvdata(
-             hpsb_protocol_class, NULL,
-             MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-             NULL, RAW1394_DEVICE_NAME))) {
+           (device_create(hpsb_protocol_class, NULL,
+                          MKDEV(IEEE1394_MAJOR,
+                                IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+                          NULL, RAW1394_DEVICE_NAME))) {
                ret = -EFAULT;
                goto out_unreg;
        }
index 1d6ad34355372f1c492d984e1c8b56f625d0acf6..c52f6e6e8af2a8bacac026e4f9974652ee794661 100644 (file)
@@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work)
 
 static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
 {
-       struct sbp2_fwhost_info *hi = lu->hi;
        struct sbp2_command_info *cmd;
+       struct device *dmadev = lu->hi->host->device.parent;
        int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
 
        for (i = 0; i < orbs; i++) {
                cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
                if (!cmd)
-                       return -ENOMEM;
-               cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
-                                               &cmd->command_orb,
-                                               sizeof(struct sbp2_command_orb),
-                                               DMA_TO_DEVICE);
-               cmd->sge_dma = dma_map_single(hi->host->device.parent,
-                                       &cmd->scatter_gather_element,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
+                       goto failed_alloc;
+
+               cmd->command_orb_dma =
+                   dma_map_single(dmadev, &cmd->command_orb,
+                                  sizeof(struct sbp2_command_orb),
+                                  DMA_TO_DEVICE);
+               if (dma_mapping_error(dmadev, cmd->command_orb_dma))
+                       goto failed_orb;
+
+               cmd->sge_dma =
+                   dma_map_single(dmadev, &cmd->scatter_gather_element,
+                                  sizeof(cmd->scatter_gather_element),
+                                  DMA_TO_DEVICE);
+               if (dma_mapping_error(dmadev, cmd->sge_dma))
+                       goto failed_sge;
+
                INIT_LIST_HEAD(&cmd->list);
                list_add_tail(&cmd->list, &lu->cmd_orb_completed);
        }
        return 0;
+
+failed_sge:
+       dma_unmap_single(dmadev, cmd->command_orb_dma,
+                        sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
+failed_orb:
+       kfree(cmd);
+failed_alloc:
+       return -ENOMEM;
 }
 
 static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
@@ -641,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
 static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
                                            struct sbp2_command_info *cmd)
 {
-       struct hpsb_host *host = lu->ud->ne->host;
-
-       if (cmd->cmd_dma) {
-               if (cmd->dma_type == CMD_DMA_SINGLE)
-                       dma_unmap_single(host->device.parent, cmd->cmd_dma,
-                                        cmd->dma_size, cmd->dma_dir);
-               else if (cmd->dma_type == CMD_DMA_PAGE)
-                       dma_unmap_page(host->device.parent, cmd->cmd_dma,
-                                      cmd->dma_size, cmd->dma_dir);
-               /* XXX: Check for CMD_DMA_NONE bug */
-               cmd->dma_type = CMD_DMA_NONE;
-               cmd->cmd_dma = 0;
-       }
-       if (cmd->sge_buffer) {
-               dma_unmap_sg(host->device.parent, cmd->sge_buffer,
-                            cmd->dma_size, cmd->dma_dir);
-               cmd->sge_buffer = NULL;
-       }
+       if (scsi_sg_count(cmd->Current_SCpnt))
+               dma_unmap_sg(lu->ud->ne->host->device.parent,
+                            scsi_sglist(cmd->Current_SCpnt),
+                            scsi_sg_count(cmd->Current_SCpnt),
+                            cmd->Current_SCpnt->sc_data_direction);
        list_move_tail(&cmd->list, &lu->cmd_orb_completed);
 }
 
@@ -823,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
 #endif
        }
 
+       if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
+               BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
+                                           SBP2_MAX_SEG_SIZE));
+
        /* Prevent unloading of the 1394 host */
        if (!try_module_get(hi->host->driver->owner)) {
                SBP2_ERR("failed to get a reference on 1394 host driver");
@@ -1494,84 +1500,65 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
        return 0;
 }
 
-static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
-                                    struct sbp2_fwhost_info *hi,
-                                    struct sbp2_command_info *cmd,
-                                    unsigned int scsi_use_sg,
-                                    struct scatterlist *sg,
-                                    u32 orb_direction,
-                                    enum dma_data_direction dma_dir)
+static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+                                   struct sbp2_fwhost_info *hi,
+                                   struct sbp2_command_info *cmd,
+                                   unsigned int sg_count,
+                                   struct scatterlist *sg,
+                                   u32 orb_direction,
+                                   enum dma_data_direction dma_dir)
 {
-       cmd->dma_dir = dma_dir;
+       struct device *dmadev = hi->host->device.parent;
+       struct sbp2_unrestricted_page_table *pt;
+       int i, n;
+
+       n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
+       if (n == 0)
+               return -ENOMEM;
+
        orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
        orb->misc |= ORB_SET_DIRECTION(orb_direction);
 
        /* special case if only one element (and less than 64KB in size) */
-       if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
-               cmd->dma_size = sg->length;
-               cmd->dma_type = CMD_DMA_PAGE;
-               cmd->cmd_dma = dma_map_page(hi->host->device.parent,
-                                           sg_page(sg), sg->offset,
-                                           cmd->dma_size, cmd->dma_dir);
-
-               orb->data_descriptor_lo = cmd->cmd_dma;
-               orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
-
+       if (n == 1) {
+               orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
+               orb->data_descriptor_lo = sg_dma_address(sg);
        } else {
-               struct sbp2_unrestricted_page_table *sg_element =
-                                               &cmd->scatter_gather_element[0];
-               u32 sg_count, sg_len;
-               dma_addr_t sg_addr;
-               int i, count = dma_map_sg(hi->host->device.parent, sg,
-                                         scsi_use_sg, dma_dir);
-
-               cmd->dma_size = scsi_use_sg;
-               cmd->sge_buffer = sg;
-
-               /* use page tables (s/g) */
-               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-               orb->data_descriptor_lo = cmd->sge_dma;
+               pt = &cmd->scatter_gather_element[0];
 
-               /* loop through and fill out our SBP-2 page tables
-                * (and split up anything too large) */
-               for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) {
-                       sg_len = sg_dma_len(sg);
-                       sg_addr = sg_dma_address(sg);
-                       while (sg_len) {
-                               sg_element[sg_count].segment_base_lo = sg_addr;
-                               if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-                                       sg_element[sg_count].length_segment_base_hi =
-                                               PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
-                                       sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
-                                       sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
-                               } else {
-                                       sg_element[sg_count].length_segment_base_hi =
-                                               PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
-                                       sg_len = 0;
-                               }
-                               sg_count++;
-                       }
+               dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_TO_DEVICE);
+
+               for_each_sg(sg, sg, n, i) {
+                       pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
+                       pt[i].low = cpu_to_be32(sg_dma_address(sg));
                }
 
-               orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
+                            ORB_SET_DATA_SIZE(n);
+               orb->data_descriptor_lo = cmd->sge_dma;
 
-               sbp2util_cpu_to_be32_buffer(sg_element,
-                               (sizeof(struct sbp2_unrestricted_page_table)) *
-                               sg_count);
+               dma_sync_single_for_device(dmadev, cmd->sge_dma,
+                                          sizeof(cmd->scatter_gather_element),
+                                          DMA_TO_DEVICE);
        }
+       return 0;
 }
 
-static void sbp2_create_command_orb(struct sbp2_lu *lu,
-                                   struct sbp2_command_info *cmd,
-                                   struct scsi_cmnd *SCpnt)
+static int sbp2_create_command_orb(struct sbp2_lu *lu,
+                                  struct sbp2_command_info *cmd,
+                                  struct scsi_cmnd *SCpnt)
 {
-       struct sbp2_fwhost_info *hi = lu->hi;
+       struct device *dmadev = lu->hi->host->device.parent;
        struct sbp2_command_orb *orb = &cmd->command_orb;
-       u32 orb_direction;
        unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
        enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
+       u32 orb_direction;
+       int ret;
 
+       dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
+                               sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
        /*
         * Set-up our command ORB.
         *
@@ -1602,15 +1589,21 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
                orb->data_descriptor_hi = 0x0;
                orb->data_descriptor_lo = 0x0;
                orb->misc |= ORB_SET_DIRECTION(1);
-       } else
-               sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt),
-                                        scsi_sglist(SCpnt),
-                                        orb_direction, dma_dir);
-
+               ret = 0;
+       } else {
+               ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
+                                              scsi_sg_count(SCpnt),
+                                              scsi_sglist(SCpnt),
+                                              orb_direction, dma_dir);
+       }
        sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
 
        memset(orb->cdb, 0, sizeof(orb->cdb));
        memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+       dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
+                       sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
+       return ret;
 }
 
 static void sbp2_link_orb_command(struct sbp2_lu *lu,
@@ -1624,14 +1617,6 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
        size_t length;
        unsigned long flags;
 
-       dma_sync_single_for_device(hi->host->device.parent,
-                                  cmd->command_orb_dma,
-                                  sizeof(struct sbp2_command_orb),
-                                  DMA_TO_DEVICE);
-       dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
-                                  sizeof(cmd->scatter_gather_element),
-                                  DMA_TO_DEVICE);
-
        /* check to see if there are any previous orbs to use */
        spin_lock_irqsave(&lu->cmd_orb_lock, flags);
        last_orb = lu->last_orb;
@@ -1699,9 +1684,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
        if (!cmd)
                return -EIO;
 
-       sbp2_create_command_orb(lu, cmd, SCpnt);
-       sbp2_link_orb_command(lu, cmd);
+       if (sbp2_create_command_orb(lu, cmd, SCpnt))
+               return -ENOMEM;
 
+       sbp2_link_orb_command(lu, cmd);
        return 0;
 }
 
@@ -1789,13 +1775,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
        else
                cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
        if (cmd) {
-               dma_sync_single_for_cpu(hi->host->device.parent,
-                                       cmd->command_orb_dma,
-                                       sizeof(struct sbp2_command_orb),
-                                       DMA_TO_DEVICE);
-               dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
                /* Grab SCSI command pointers and check status. */
                /*
                 * FIXME: If the src field in the status is 1, the ORB DMA must
@@ -1912,7 +1891,6 @@ done:
 
 static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
 {
-       struct sbp2_fwhost_info *hi = lu->hi;
        struct list_head *lh;
        struct sbp2_command_info *cmd;
        unsigned long flags;
@@ -1921,13 +1899,6 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
        while (!list_empty(&lu->cmd_orb_inuse)) {
                lh = lu->cmd_orb_inuse.next;
                cmd = list_entry(lh, struct sbp2_command_info, list);
-               dma_sync_single_for_cpu(hi->host->device.parent,
-                                       cmd->command_orb_dma,
-                                       sizeof(struct sbp2_command_orb),
-                                       DMA_TO_DEVICE);
-               dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
                sbp2util_mark_command_completed(lu, cmd);
                if (cmd->Current_SCpnt) {
                        cmd->Current_SCpnt->result = status << 16;
@@ -2033,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
                sdev->start_stop_pwr_cond = 1;
        if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
                blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+
+       blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
        return 0;
 }
 
@@ -2049,7 +2022,6 @@ static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
 static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
 {
        struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-       struct sbp2_fwhost_info *hi = lu->hi;
        struct sbp2_command_info *cmd;
        unsigned long flags;
 
@@ -2063,14 +2035,6 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                spin_lock_irqsave(&lu->cmd_orb_lock, flags);
                cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
                if (cmd) {
-                       dma_sync_single_for_cpu(hi->host->device.parent,
-                                       cmd->command_orb_dma,
-                                       sizeof(struct sbp2_command_orb),
-                                       DMA_TO_DEVICE);
-                       dma_sync_single_for_cpu(hi->host->device.parent,
-                                       cmd->sge_dma,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
                        sbp2util_mark_command_completed(lu, cmd);
                        if (cmd->Current_SCpnt) {
                                cmd->Current_SCpnt->result = DID_ABORT << 16;
index 875428bc8d2995fc475b332ca596552d1ebbabfa..c5036f1cc5b0d674155ea2a89087e9ba5e981eb5 100644 (file)
@@ -139,13 +139,10 @@ struct sbp2_logout_orb {
        u32 status_fifo_lo;
 } __attribute__((packed));
 
-#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v)      ((v) & 0xffff)
-#define PAGE_TABLE_SET_SEGMENT_LENGTH(v)       (((v) & 0xffff) << 16)
-
 struct sbp2_unrestricted_page_table {
-       u32 length_segment_base_hi;
-       u32 segment_base_lo;
-} __attribute__((packed));
+       __be32 high;
+       __be32 low;
+};
 
 #define RESP_STATUS_REQUEST_COMPLETE           0x0
 #define RESP_STATUS_TRANSPORT_FAILURE          0x1
@@ -216,15 +213,18 @@ struct sbp2_status_block {
 #define SBP2_UNIT_SPEC_ID_ENTRY                        0x0000609e
 #define SBP2_SW_VERSION_ENTRY                  0x00010483
 
-
 /*
- * SCSI specific definitions
+ * The default maximum s/g segment size of a FireWire controller is
+ * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
+ * be quadlet-aligned, we set the length limit to 0xffff & ~3.
  */
+#define SBP2_MAX_SEG_SIZE                      0xfffc
 
-#define SBP2_MAX_SG_ELEMENT_LENGTH             0xf000
-/* There is no real limitation of the queue depth (i.e. length of the linked
+/*
+ * There is no real limitation of the queue depth (i.e. length of the linked
  * list of command ORBs) at the target. The chosen depth is merely an
- * implementation detail of the sbp2 driver. */
+ * implementation detail of the sbp2 driver.
+ */
 #define SBP2_MAX_CMDS                          8
 
 #define SBP2_SCSI_STATUS_GOOD                  0x0
@@ -240,12 +240,6 @@ struct sbp2_status_block {
  * Representations of commands and devices
  */
 
-enum sbp2_dma_types {
-       CMD_DMA_NONE,
-       CMD_DMA_PAGE,
-       CMD_DMA_SINGLE
-};
-
 /* Per SCSI command */
 struct sbp2_command_info {
        struct list_head list;
@@ -258,11 +252,6 @@ struct sbp2_command_info {
        struct sbp2_unrestricted_page_table
                scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
        dma_addr_t sge_dma;
-       void *sge_buffer;
-       dma_addr_t cmd_dma;
-       enum sbp2_dma_types dma_type;
-       unsigned long dma_size;
-       enum dma_data_direction dma_dir;
 };
 
 /* Per FireWire host */
index 25db6e67fa4ea6d123f9a71df2e9c44616e84c3d..679a918a5cc76eae41500b458eef93cc2c06992a 100644 (file)
@@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file,
                if (unlikely(d == NULL))
                        return -EFAULT;
 
-               if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) {
+               if (unlikely(v.buffer >= d->num_desc - 1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file,
                if (unlikely(d == NULL))
                        return -EFAULT;
 
-               if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) {
+               if (unlikely(v.buffer > d->num_desc - 1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file,
                d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
+               if (v.buffer >= d->num_desc - 1) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file,
                d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
+               if (v.buffer >= d->num_desc - 1) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1341,9 +1341,8 @@ static void video1394_add_host (struct hpsb_host *host)
        hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
        minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-       device_create_drvdata(hpsb_protocol_class, NULL,
-                             MKDEV(IEEE1394_MAJOR, minor), NULL,
-                             "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+       device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor),
+                     NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
index 3cab0cedfca21f54d83027a78f1f6c6a3c1a1b8e..a78d35aecee3de339520308358d6ca565d69cdd1 100644 (file)
@@ -3691,9 +3691,9 @@ static void cm_add_one(struct ib_device *ib_device)
        cm_dev->ib_device = ib_device;
        cm_get_ack_delay(cm_dev);
 
-       cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
-                                              MKDEV(0, 0), NULL,
-                                              "%s", ib_device->name);
+       cm_dev->device = device_create(&cm_class, &ib_device->dev,
+                                      MKDEV(0, 0), NULL,
+                                      "%s", ib_device->name);
        if (!cm_dev->device) {
                kfree(cm_dev);
                return;
index 268a2d23b7c9a8e9092877ca319989891e99e90d..8c46f2257098cf2d7e01ba472c31a48dc5ffb77a 100644 (file)
@@ -1016,9 +1016,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
        if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
                goto err_cdev;
 
-       port->dev = device_create_drvdata(umad_class, device->dma_device,
-                                         port->cdev->dev, port,
-                                         "umad%d", port->dev_num);
+       port->dev = device_create(umad_class, device->dma_device,
+                                 port->cdev->dev, port,
+                                 "umad%d", port->dev_num);
        if (IS_ERR(port->dev))
                goto err_cdev;
 
@@ -1036,9 +1036,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
        if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
                goto err_sm_cdev;
 
-       port->sm_dev = device_create_drvdata(umad_class, device->dma_device,
-                                            port->sm_cdev->dev, port,
-                                            "issm%d", port->dev_num);
+       port->sm_dev = device_create(umad_class, device->dma_device,
+                                    port->sm_cdev->dev, port,
+                                    "issm%d", port->dev_num);
        if (IS_ERR(port->sm_dev))
                goto err_sm_cdev;
 
index aeee856c4060648f4898c4014d30ed2c73065bdd..d85af1b670274466f5ec13a518d8011da1cb7da0 100644 (file)
@@ -764,12 +764,9 @@ static void ib_uverbs_add_one(struct ib_device *device)
        if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
                goto err_cdev;
 
-       uverbs_dev->dev = device_create_drvdata(uverbs_class,
-                                               device->dma_device,
-                                               uverbs_dev->cdev->dev,
-                                               uverbs_dev,
-                                               "uverbs%d",
-                                               uverbs_dev->devnum);
+       uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
+                                       uverbs_dev->cdev->dev, uverbs_dev,
+                                       "uverbs%d", uverbs_dev->devnum);
        if (IS_ERR(uverbs_dev->dev))
                goto err_cdev;
 
index 56c0eda3c0772816f09e9b975090707929b826f3..1af1f3a907c6eb25a7930a6fd2e22ca36ad7135b 100644 (file)
@@ -2455,7 +2455,7 @@ static int init_cdev(int minor, char *name, const struct file_operations *fops,
                goto err_cdev;
        }
 
-       device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
+       device = device_create(ipath_class, NULL, dev, NULL, name);
 
        if (IS_ERR(device)) {
                ret = PTR_ERR(device);
index ed7c5f72cb8bc24cc02100a1e7847f88f9b9e5b7..5b8b533f29089a7ccd428abffa65136ae8cb30e0 100644 (file)
@@ -1683,7 +1683,7 @@ enum {
                                   SRP_OPT_SERVICE_ID),
 };
 
-static match_table_t srp_opt_tokens = {
+static const match_table_t srp_opt_tokens = {
        { SRP_OPT_ID_EXT,               "id_ext=%s"             },
        { SRP_OPT_IOC_GUID,             "ioc_guid=%s"           },
        { SRP_OPT_DGID,                 "dgid=%s"               },
index 078e4eed0894ba45a495184bb91b6518935663b9..2880eaae157a90896ce7785cea9b4e2c3c32dd4f 100644 (file)
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport)
 enum gameport_event_type {
        GAMEPORT_REGISTER_PORT,
        GAMEPORT_REGISTER_DRIVER,
+       GAMEPORT_ATTACH_DRIVER,
 };
 
 struct gameport_event {
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list);
 static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
 static struct task_struct *gameport_task;
 
-static void gameport_queue_event(void *object, struct module *owner,
-                             enum gameport_event_type event_type)
+static int gameport_queue_event(void *object, struct module *owner,
+                               enum gameport_event_type event_type)
 {
        unsigned long flags;
        struct gameport_event *event;
+       int retval = 0;
 
        spin_lock_irqsave(&gameport_event_lock, flags);
 
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner,
                }
        }
 
-       if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
-               if (!try_module_get(owner)) {
-                       printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
-                       kfree(event);
-                       goto out;
-               }
-
-               event->type = event_type;
-               event->object = object;
-               event->owner = owner;
+       event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
+       if (!event) {
+               printk(KERN_ERR
+                       "gameport: Not enough memory to queue event %d\n",
+                       event_type);
+               retval = -ENOMEM;
+               goto out;
+       }
 
-               list_add_tail(&event->node, &gameport_event_list);
-               wake_up(&gameport_wait);
-       } else {
-               printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
+       if (!try_module_get(owner)) {
+               printk(KERN_WARNING
+                       "gameport: Can't get module reference, dropping event %d\n",
+                       event_type);
+               kfree(event);
+               retval = -EINVAL;
+               goto out;
        }
+
+       event->type = event_type;
+       event->object = object;
+       event->owner = owner;
+
+       list_add_tail(&event->node, &gameport_event_list);
+       wake_up(&gameport_wait);
+
 out:
        spin_unlock_irqrestore(&gameport_event_lock, flags);
+       return retval;
 }
 
 static void gameport_free_event(struct gameport_event *event)
@@ -378,9 +390,10 @@ static void gameport_handle_event(void)
 }
 
 /*
- * Remove all events that have been submitted for a given gameport port.
+ * Remove all events that have been submitted for a given object,
+ * be it a gameport port or a driver.
  */
-static void gameport_remove_pending_events(struct gameport *gameport)
+static void gameport_remove_pending_events(void *object)
 {
        struct list_head *node, *next;
        struct gameport_event *event;
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport)
 
        list_for_each_safe(node, next, &gameport_event_list) {
                event = list_entry(node, struct gameport_event, node);
-               if (event->object == gameport) {
+               if (event->object == object) {
                        list_del_init(node);
                        gameport_free_event(event);
                }
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv)
                        drv->driver.name, error);
 }
 
-void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
+int __gameport_register_driver(struct gameport_driver *drv, struct module *owner,
+                               const char *mod_name)
 {
+       int error;
+
        drv->driver.bus = &gameport_bus;
-       gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
+       drv->driver.owner = owner;
+       drv->driver.mod_name = mod_name;
+
+       /*
+        * Temporarily disable automatic binding because probing
+        * takes long time and we are better off doing it in kgameportd
+        */
+       drv->ignore = 1;
+
+       error = driver_register(&drv->driver);
+       if (error) {
+               printk(KERN_ERR
+                       "gameport: driver_register() failed for %s, error: %d\n",
+                       drv->driver.name, error);
+               return error;
+       }
+
+       /*
+        * Reset ignore flag and let kgameportd bind the driver to free ports
+        */
+       drv->ignore = 0;
+       error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
+       if (error) {
+               driver_unregister(&drv->driver);
+               return error;
+       }
+
+       return 0;
 }
 
 void gameport_unregister_driver(struct gameport_driver *drv)
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv)
        struct gameport *gameport;
 
        mutex_lock(&gameport_mutex);
+
        drv->ignore = 1;        /* so gameport_find_driver ignores it */
+       gameport_remove_pending_events(drv);
 
 start_over:
        list_for_each_entry(gameport, &gameport_list, node) {
@@ -729,6 +774,7 @@ start_over:
        }
 
        driver_unregister(&drv->driver);
+
        mutex_unlock(&gameport_mutex);
 }
 
index 92498d470b1f7de7323eed8b87dfcd8dffa72d7e..6489f4010c4f2f6944090d8829b264bbd067901d 100644 (file)
@@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = {
 
 static int __init a3d_init(void)
 {
-       gameport_register_driver(&a3d_drv);
-       return 0;
+       return gameport_register_driver(&a3d_drv);
 }
 
 static void __exit a3d_exit(void)
index d1ca8a14950f62f914e9d4f9f81ae34a7eabadfe..89c4c084d4ad8e86789b123302cd0350f0af7113 100644 (file)
@@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = {
 
 static int __init adi_init(void)
 {
-       gameport_register_driver(&adi_drv);
-       return 0;
+       return gameport_register_driver(&adi_drv);
 }
 
 static void __exit adi_exit(void)
index 708c5ae13b24f33cb6b8b323996c2332d84520b7..356b3a25efa24c4568a909c59dedaa7ebcbc040c 100644 (file)
@@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = {
 static int __init analog_init(void)
 {
        analog_parse_options();
-       gameport_register_driver(&analog_drv);
-
-       return 0;
+       return gameport_register_driver(&analog_drv);
 }
 
 static void __exit analog_exit(void)
index 639b975a8ed7a6c64ecb06f315dffa45eb2b5a1a..3497b87c3d0591c12446f16bc232337c3f367981 100644 (file)
@@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = {
 
 static int __init cobra_init(void)
 {
-       gameport_register_driver(&cobra_drv);
-       return 0;
+       return gameport_register_driver(&cobra_drv);
 }
 
 static void __exit cobra_exit(void)
index cb6eef1f2d99f6d7b80a9f5e02d7411ececbd153..67c207f5b1a16cd56e88b140c63bbfdefb8f498b 100644 (file)
@@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = {
 
 static int __init gf2k_init(void)
 {
-       gameport_register_driver(&gf2k_drv);
-       return 0;
+       return gameport_register_driver(&gf2k_drv);
 }
 
 static void __exit gf2k_exit(void)
index 684e07cfccc89a862d25897b9e0c760e5dd79965..fc55899ba6c50a8d5d4c8336d100ca51677d440f 100644 (file)
@@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = {
 
 static int __init grip_init(void)
 {
-       gameport_register_driver(&grip_drv);
-       return 0;
+       return gameport_register_driver(&grip_drv);
 }
 
 static void __exit grip_exit(void)
index 8279481b16e7bbf038b70991dfe1d5ec6f16fff3..2d47baf47769843a98e23d9b47665560ef885e7f 100644 (file)
@@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = {
 
 static int __init grip_init(void)
 {
-       gameport_register_driver(&grip_drv);
-       return 0;
+       return gameport_register_driver(&grip_drv);
 }
 
 static void __exit grip_exit(void)
index 25ec3fad9f2798d5126cec44e6b570a819152270..4058d4b272fe88fed73a2a3f0183b1d2cbeabd9b 100644 (file)
@@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = {
 
 static int __init guillemot_init(void)
 {
-       gameport_register_driver(&guillemot_drv);
-       return 0;
+       return gameport_register_driver(&guillemot_drv);
 }
 
 static void __exit guillemot_exit(void)
index 8c3290b68205b933f76223ab139ed5a71aaeb518..2478289aeeea1b1c7c2cfec1ed8cde3544a1ae16 100644 (file)
@@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = {
 
 static int __init interact_init(void)
 {
-       gameport_register_driver(&interact_drv);
-       return 0;
+       return gameport_register_driver(&interact_drv);
 }
 
 static void __exit interact_exit(void)
index 2a1b82c8b31c155c8c698741317a200b90898dcd..cd894a0564a2f06932954d7dcec2ff6c179a9d92 100644 (file)
@@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = {
 
 static int __init joydump_init(void)
 {
-       gameport_register_driver(&joydump_drv);
-       return 0;
+       return gameport_register_driver(&joydump_drv);
 }
 
 static void __exit joydump_exit(void)
index 7b4865fdee54cdcf48998cff18dc7bdd4316a9c0..ca13a6bec33ef63fd904eaf3bd7b6853b2194dea 100644 (file)
@@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = {
 
 static int __init sw_init(void)
 {
-       gameport_register_driver(&sw_drv);
-       return 0;
+       return gameport_register_driver(&sw_drv);
 }
 
 static void __exit sw_exit(void)
index 60c37bcb938d932d78bbd7a1065be2c6e335564f..d6c6098071150e02a456d1688c71fbf44a78cd91 100644 (file)
@@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = {
 
 static int __init tmdc_init(void)
 {
-       gameport_register_driver(&tmdc_drv);
-       return 0;
+       return gameport_register_driver(&tmdc_drv);
 }
 
 static void __exit tmdc_exit(void)
index 6791be81eb2904b15780da13dac99ce11e5925a6..839d1c9622f66c1f4c1a217bf8a6c3c55503f990 100644 (file)
@@ -455,10 +455,10 @@ static void xpad_bulk_out(struct urb *urb)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __func__, urb->status);
                break;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __func__, urb->status);
        }
 }
 
index b1ce10f50bcfcf7a14eca2c8c4cd9606efaecd90..22016ca153518b8c9535b11f215c59e1d0008880 100644 (file)
@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio)
 }
 
 /*
- * Most special keys (Fn+F?) on Dell Latitudes do not generate release
+ * Most special keys (Fn+F?) on Dell laptops do not generate release
  * events so we have to do it ourselves.
  */
-static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
+static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd)
 {
        const unsigned int forced_release_keys[] = {
                0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93,
@@ -1207,15 +1207,13 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
 {
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
-       char *rest;
        int err;
        unsigned char old_extra, old_set;
 
        if (!atkbd->write)
                return -EIO;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        if (atkbd->extra != value) {
@@ -1264,12 +1262,10 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
 {
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
-       char *rest;
        int err;
        unsigned char old_scroll;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        if (atkbd->scroll != value) {
@@ -1310,15 +1306,13 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 {
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
-       char *rest;
        int err;
        unsigned char old_set, old_extra;
 
        if (!atkbd->write)
                return -EIO;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || (value != 2 && value != 3))
+       if (strict_strtoul(buf, 10, &value) || (value != 2 && value != 3))
                return -EINVAL;
 
        if (atkbd->set != value) {
@@ -1361,15 +1355,13 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
 {
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
-       char *rest;
        int err;
        unsigned char old_softrepeat, old_softraw;
 
        if (!atkbd->write)
                return -EIO;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        if (atkbd->softrepeat != value) {
@@ -1413,12 +1405,10 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
 {
        struct input_dev *old_dev, *new_dev;
        unsigned long value;
-       char *rest;
        int err;
        unsigned char old_softraw;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        if (atkbd->softraw != value) {
@@ -1461,13 +1451,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id)
 
 static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
        {
-               .ident = "Dell Latitude series",
+               .ident = "Dell Laptop",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+                       DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
                },
                .callback = atkbd_setup_fixup,
-               .driver_data = atkbd_latitude_keymap_fixup,
+               .driver_data = atkbd_dell_laptop_keymap_fixup,
        },
        {
                .ident = "HP 2133",
index e348cfccc17a9549105fcab813d644ef6aa322fd..19284016e0f4d1c2ce47e3f86f4a5f59e04445fc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * Modified:
- *               Copyright 2007 Analog Devices Inc.
+ *               Copyright 2007-2008 Analog Devices Inc.
  *
  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
  *
@@ -81,6 +81,9 @@ struct bf54x_kpad {
        unsigned short *keycode;
        struct timer_list timer;
        unsigned int keyup_test_jiffies;
+       unsigned short kpad_msel;
+       unsigned short kpad_prescale;
+       unsigned short kpad_ctl;
 };
 
 static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad,
@@ -360,6 +363,10 @@ static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
 
+       bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL();
+       bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE();
+       bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL();
+
        if (device_may_wakeup(&pdev->dev))
                enable_irq_wake(bf54x_kpad->irq);
 
@@ -370,6 +377,10 @@ static int bfin_kpad_resume(struct platform_device *pdev)
 {
        struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
 
+       bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel);
+       bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale);
+       bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl);
+
        if (device_may_wakeup(&pdev->dev))
                disable_irq_wake(bf54x_kpad->irq);
 
index ec96b369dd7ac02ed3bb49dec3bcfe8e9c649ae1..05f3f43582c2c1e40658e2d8e6e77f8717210f38 100644 (file)
@@ -36,9 +36,10 @@ struct gpio_keys_drvdata {
        struct gpio_button_data data[0];
 };
 
-static void gpio_keys_report_event(struct gpio_keys_button *button,
-                                  struct input_dev *input)
+static void gpio_keys_report_event(struct gpio_button_data *bdata)
 {
+       struct gpio_keys_button *button = bdata->button;
+       struct input_dev *input = bdata->input;
        unsigned int type = button->type ?: EV_KEY;
        int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
 
@@ -50,34 +51,23 @@ static void gpio_check_button(unsigned long _data)
 {
        struct gpio_button_data *data = (struct gpio_button_data *)_data;
 
-       gpio_keys_report_event(data->button, data->input);
+       gpio_keys_report_event(data);
 }
 
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
-       struct platform_device *pdev = dev_id;
-       struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-       struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
-       int i;
+       struct gpio_button_data *bdata = dev_id;
+       struct gpio_keys_button *button = bdata->button;
 
-       for (i = 0; i < pdata->nbuttons; i++) {
-               struct gpio_keys_button *button = &pdata->buttons[i];
+       BUG_ON(irq != gpio_to_irq(button->gpio));
 
-               if (irq == gpio_to_irq(button->gpio)) {
-                       struct gpio_button_data *bdata = &ddata->data[i];
-
-                       if (button->debounce_interval)
-                               mod_timer(&bdata->timer,
-                                         jiffies +
-                                         msecs_to_jiffies(button->debounce_interval));
-                       else
-                               gpio_keys_report_event(button, bdata->input);
-
-                       return IRQ_HANDLED;
-               }
-       }
+       if (button->debounce_interval)
+               mod_timer(&bdata->timer,
+                       jiffies + msecs_to_jiffies(button->debounce_interval));
+       else
+               gpio_keys_report_event(bdata);
 
-       return IRQ_NONE;
+       return IRQ_HANDLED;
 }
 
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
@@ -151,7 +141,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
                                    IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
                                        IRQF_TRIGGER_FALLING,
                                    button->desc ? button->desc : "gpio_keys",
-                                   pdev);
+                                   bdata);
                if (error) {
                        pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
                                irq, error);
@@ -178,7 +168,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 
  fail2:
        while (--i >= 0) {
-               free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+               free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
                if (pdata->buttons[i].debounce_interval)
                        del_timer_sync(&ddata->data[i].timer);
                gpio_free(pdata->buttons[i].gpio);
@@ -203,7 +193,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 
        for (i = 0; i < pdata->nbuttons; i++) {
                int irq = gpio_to_irq(pdata->buttons[i].gpio);
-               free_irq(irq, pdev);
+               free_irq(irq, &ddata->data[i]);
                if (pdata->buttons[i].debounce_interval)
                        del_timer_sync(&ddata->data[i].timer);
                gpio_free(pdata->buttons[i].gpio);
index dcea87a0bc5674e16b88502273b903d684800663..69e674ecf19a1b26ed9f0db46d9c176c5d43d273 100644 (file)
@@ -62,7 +62,7 @@ struct omap_kp {
        unsigned int debounce;
 };
 
-DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
 
 static int *keymap;
 static unsigned int *row_gpios;
@@ -72,12 +72,9 @@ static unsigned int *col_gpios;
 static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value)
 {
        int col;
-       for (col = 0; col < omap_kp->cols; col++) {
-               if (value & (1 << col))
-                       omap_set_gpio_dataout(col_gpios[col], 1);
-               else
-                       omap_set_gpio_dataout(col_gpios[col], 0);
-       }
+
+       for (col = 0; col < omap_kp->cols; col++)
+               gpio_set_value(col_gpios[col], value & (1 << col));
 }
 
 static u8 get_row_gpio_val(struct omap_kp *omap_kp)
@@ -86,7 +83,7 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp)
        u8 value = 0;
 
        for (row = 0; row < omap_kp->rows; row++) {
-               if (omap_get_gpio_datain(row_gpios[row]))
+               if (gpio_get_value(row_gpios[row]))
                        value |= (1 << row);
        }
        return value;
@@ -333,23 +330,23 @@ static int __init omap_kp_probe(struct platform_device *pdev)
        if (cpu_is_omap24xx()) {
                /* Cols: outputs */
                for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
-                       if (omap_request_gpio(col_gpios[col_idx]) < 0) {
+                       if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) {
                                printk(KERN_ERR "Failed to request"
                                       "GPIO%d for keypad\n",
                                       col_gpios[col_idx]);
                                goto err1;
                        }
-                       omap_set_gpio_direction(col_gpios[col_idx], 0);
+                       gpio_direction_output(col_gpios[col_idx], 0);
                }
                /* Rows: inputs */
                for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
-                       if (omap_request_gpio(row_gpios[row_idx]) < 0) {
+                       if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) {
                                printk(KERN_ERR "Failed to request"
                                       "GPIO%d for keypad\n",
                                       row_gpios[row_idx]);
                                goto err2;
                        }
-                       omap_set_gpio_direction(row_gpios[row_idx], 1);
+                       gpio_direction_input(row_gpios[row_idx]);
                }
        } else {
                col_idx = 0;
@@ -418,10 +415,10 @@ err3:
        device_remove_file(&pdev->dev, &dev_attr_enable);
 err2:
        for (i = row_idx - 1; i >=0; i--)
-               omap_free_gpio(row_gpios[i]);
+               gpio_free(row_gpios[i]);
 err1:
        for (i = col_idx - 1; i >=0; i--)
-               omap_free_gpio(col_gpios[i]);
+               gpio_free(col_gpios[i]);
 
        kfree(omap_kp);
        input_free_device(input_dev);
@@ -438,9 +435,9 @@ static int omap_kp_remove(struct platform_device *pdev)
        if (cpu_is_omap24xx()) {
                int i;
                for (i = 0; i < omap_kp->cols; i++)
-                       omap_free_gpio(col_gpios[i]);
+                       gpio_free(col_gpios[i]);
                for (i = 0; i < omap_kp->rows; i++) {
-                       omap_free_gpio(row_gpios[i]);
+                       gpio_free(row_gpios[i]);
                        free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
                }
        } else {
index e99b7882f3826e3d9f4563eb48ece92d8085fb03..199055db5082e8020834e8883e3d502d7319bfb8 100644 (file)
@@ -180,6 +180,19 @@ config INPUT_YEALINK
          To compile this driver as a module, choose M here: the module will be
          called yealink.
 
+config INPUT_CM109
+       tristate "C-Media CM109 USB I/O Controller"
+       depends on EXPERIMENTAL
+       depends on USB_ARCH_HAS_HCD
+       select USB
+       help
+         Say Y here if you want to enable keyboard and buzzer functions of the
+         C-Media CM109 usb phones. The audio part is enabled by the generic
+         usb sound driver, so you might want to enable that as well.
+
+         To compile this driver as a module, choose M here: the module will be
+         called cm109.
+
 config INPUT_UINPUT
        tristate "User level driver support"
        help
index f48009b52226ba94b69965daf1a9eaa968da5764..d7db2aeb8a982e82fe712ed17c3f663c62a2fc35 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2)               += ati_remote2.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)     += keyspan_remote.o
 obj-$(CONFIG_INPUT_POWERMATE)          += powermate.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
+obj-$(CONFIG_INPUT_CM109)              += cm109.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
 obj-$(CONFIG_INPUT_APANEL)             += apanel.o
index a7fabafbd94c6e9fe3691db3b18caea49a835b88..3c9988dc0e9fcc98e05a35fc25744cfce84cdb4f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * ati_remote2 - ATI/Philips USB RF remote driver
  *
- * Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
- * Copyright (C) 2007 Peter Stokes <linux@dadeos.freeserve.co.uk>
+ * Copyright (C) 2005-2008 Ville Syrjala <syrjala@sci.fi>
+ * Copyright (C) 2007-2008 Peter Stokes <linux@dadeos.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
@@ -12,7 +12,7 @@
 #include <linux/usb/input.h>
 
 #define DRIVER_DESC    "ATI/Philips USB RF remote driver"
-#define DRIVER_VERSION "0.2"
+#define DRIVER_VERSION "0.3"
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
@@ -27,7 +27,7 @@ MODULE_LICENSE("GPL");
  * A remote's "channel" may be altered by pressing and holding the "PC" button for
  * approximately 3 seconds, after which the button will slowly flash the count of the
  * currently configured "channel", using the numeric keypad enter a number between 1 and
- * 16 and then the "PC" button again, the button will slowly flash the count of the
+ * 16 and then press the "PC" button again, the button will slowly flash the count of the
  * newly configured "channel".
  */
 
@@ -45,9 +45,25 @@ static struct usb_device_id ati_remote2_id_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
 
-static struct {
-       int hw_code;
-       int key_code;
+static DEFINE_MUTEX(ati_remote2_mutex);
+
+enum {
+       ATI_REMOTE2_OPENED = 0x1,
+       ATI_REMOTE2_SUSPENDED = 0x2,
+};
+
+enum {
+       ATI_REMOTE2_AUX1,
+       ATI_REMOTE2_AUX2,
+       ATI_REMOTE2_AUX3,
+       ATI_REMOTE2_AUX4,
+       ATI_REMOTE2_PC,
+       ATI_REMOTE2_MODES,
+};
+
+static const struct {
+       u8  hw_code;
+       u16 keycode;
 } ati_remote2_key_table[] = {
        { 0x00, KEY_0 },
        { 0x01, KEY_1 },
@@ -73,6 +89,7 @@ static struct {
        { 0x37, KEY_RECORD },
        { 0x38, KEY_DVD },
        { 0x39, KEY_TV },
+       { 0x3f, KEY_PROG1 }, /* AUX1-AUX4 and PC */
        { 0x54, KEY_MENU },
        { 0x58, KEY_UP },
        { 0x59, KEY_DOWN },
@@ -91,15 +108,9 @@ static struct {
        { 0xa9, BTN_LEFT },
        { 0xaa, BTN_RIGHT },
        { 0xbe, KEY_QUESTION },
-       { 0xd5, KEY_FRONT },
        { 0xd0, KEY_EDIT },
+       { 0xd5, KEY_FRONT },
        { 0xf9, KEY_INFO },
-       { (0x00 << 8) | 0x3f, KEY_PROG1 },
-       { (0x01 << 8) | 0x3f, KEY_PROG2 },
-       { (0x02 << 8) | 0x3f, KEY_PROG3 },
-       { (0x03 << 8) | 0x3f, KEY_PROG4 },
-       { (0x04 << 8) | 0x3f, KEY_PC },
-       { 0, KEY_RESERVED }
 };
 
 struct ati_remote2 {
@@ -117,46 +128,106 @@ struct ati_remote2 {
 
        char name[64];
        char phys[64];
+
+       /* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */
+       u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)];
+
+       unsigned int flags;
 };
 
 static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
 static void ati_remote2_disconnect(struct usb_interface *interface);
+static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message);
+static int ati_remote2_resume(struct usb_interface *interface);
 
 static struct usb_driver ati_remote2_driver = {
        .name       = "ati_remote2",
        .probe      = ati_remote2_probe,
        .disconnect = ati_remote2_disconnect,
        .id_table   = ati_remote2_id_table,
+       .suspend    = ati_remote2_suspend,
+       .resume     = ati_remote2_resume,
+       .supports_autosuspend = 1,
 };
 
-static int ati_remote2_open(struct input_dev *idev)
+static int ati_remote2_submit_urbs(struct ati_remote2 *ar2)
 {
-       struct ati_remote2 *ar2 = input_get_drvdata(idev);
        int r;
 
        r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
        if (r) {
                dev_err(&ar2->intf[0]->dev,
-                       "%s: usb_submit_urb() = %d\n", __func__, r);
+                       "%s(): usb_submit_urb() = %d\n", __func__, r);
                return r;
        }
        r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
        if (r) {
                usb_kill_urb(ar2->urb[0]);
                dev_err(&ar2->intf[1]->dev,
-                       "%s: usb_submit_urb() = %d\n", __func__, r);
+                       "%s(): usb_submit_urb() = %d\n", __func__, r);
                return r;
        }
 
        return 0;
 }
 
+static void ati_remote2_kill_urbs(struct ati_remote2 *ar2)
+{
+       usb_kill_urb(ar2->urb[1]);
+       usb_kill_urb(ar2->urb[0]);
+}
+
+static int ati_remote2_open(struct input_dev *idev)
+{
+       struct ati_remote2 *ar2 = input_get_drvdata(idev);
+       int r;
+
+       dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+       r = usb_autopm_get_interface(ar2->intf[0]);
+       if (r) {
+               dev_err(&ar2->intf[0]->dev,
+                       "%s(): usb_autopm_get_interface() = %d\n", __func__, r);
+               goto fail1;
+       }
+
+       mutex_lock(&ati_remote2_mutex);
+
+       if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) {
+               r = ati_remote2_submit_urbs(ar2);
+               if (r)
+                       goto fail2;
+       }
+
+       ar2->flags |= ATI_REMOTE2_OPENED;
+
+       mutex_unlock(&ati_remote2_mutex);
+
+       usb_autopm_put_interface(ar2->intf[0]);
+
+       return 0;
+
+ fail2:
+       mutex_unlock(&ati_remote2_mutex);
+       usb_autopm_put_interface(ar2->intf[0]);
+ fail1:
+       return r;
+}
+
 static void ati_remote2_close(struct input_dev *idev)
 {
        struct ati_remote2 *ar2 = input_get_drvdata(idev);
 
-       usb_kill_urb(ar2->urb[0]);
-       usb_kill_urb(ar2->urb[1]);
+       dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+       mutex_lock(&ati_remote2_mutex);
+
+       if (!(ar2->flags & ATI_REMOTE2_SUSPENDED))
+               ati_remote2_kill_urbs(ar2);
+
+       ar2->flags &= ~ATI_REMOTE2_OPENED;
+
+       mutex_unlock(&ati_remote2_mutex);
 }
 
 static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
@@ -172,7 +243,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
 
        mode = data[0] & 0x0F;
 
-       if (mode > 4) {
+       if (mode > ATI_REMOTE2_PC) {
                dev_err(&ar2->intf[0]->dev,
                        "Unknown mode byte (%02x %02x %02x %02x)\n",
                        data[3], data[2], data[1], data[0]);
@@ -191,7 +262,7 @@ static int ati_remote2_lookup(unsigned int hw_code)
 {
        int i;
 
-       for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+       for (i = 0; i < ARRAY_SIZE(ati_remote2_key_table); i++)
                if (ati_remote2_key_table[i].hw_code == hw_code)
                        return i;
 
@@ -211,7 +282,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
 
        mode = data[0] & 0x0F;
 
-       if (mode > 4) {
+       if (mode > ATI_REMOTE2_PC) {
                dev_err(&ar2->intf[1]->dev,
                        "Unknown mode byte (%02x %02x %02x %02x)\n",
                        data[3], data[2], data[1], data[0]);
@@ -219,10 +290,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
        }
 
        hw_code = data[2];
-       /*
-        * Mode keys (AUX1-AUX4, PC) all generate the same code byte.
-        * Use the mode byte to figure out which one was pressed.
-        */
        if (hw_code == 0x3f) {
                /*
                 * For some incomprehensible reason the mouse pad generates
@@ -236,8 +303,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
 
                if (data[1] == 0)
                        ar2->mode = mode;
-
-               hw_code |= mode << 8;
        }
 
        if (!((1 << mode) & mode_mask))
@@ -260,8 +325,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
        case 2: /* repeat */
 
                /* No repeat for mouse buttons. */
-               if (ati_remote2_key_table[index].key_code == BTN_LEFT ||
-                   ati_remote2_key_table[index].key_code == BTN_RIGHT)
+               if (ar2->keycode[mode][index] == BTN_LEFT ||
+                   ar2->keycode[mode][index] == BTN_RIGHT)
                        return;
 
                if (!time_after_eq(jiffies, ar2->jiffies))
@@ -276,7 +341,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
                return;
        }
 
-       input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
+       input_event(idev, EV_KEY, ar2->keycode[mode][index], data[1]);
        input_sync(idev);
 }
 
@@ -287,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
 
        switch (urb->status) {
        case 0:
+               usb_mark_last_busy(ar2->udev);
                ati_remote2_input_mouse(ar2);
                break;
        case -ENOENT:
@@ -297,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
                        "%s(): urb status = %d\n", __func__, urb->status);
                return;
        default:
+               usb_mark_last_busy(ar2->udev);
                dev_err(&ar2->intf[0]->dev,
                        "%s(): urb status = %d\n", __func__, urb->status);
        }
@@ -314,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb)
 
        switch (urb->status) {
        case 0:
+               usb_mark_last_busy(ar2->udev);
                ati_remote2_input_key(ar2);
                break;
        case -ENOENT:
@@ -324,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb)
                        "%s(): urb status = %d\n", __func__, urb->status);
                return;
        default:
+               usb_mark_last_busy(ar2->udev);
                dev_err(&ar2->intf[1]->dev,
                        "%s(): urb status = %d\n", __func__, urb->status);
        }
@@ -334,10 +403,60 @@ static void ati_remote2_complete_key(struct urb *urb)
                        "%s(): usb_submit_urb() = %d\n", __func__, r);
 }
 
+static int ati_remote2_getkeycode(struct input_dev *idev,
+                                 int scancode, int *keycode)
+{
+       struct ati_remote2 *ar2 = input_get_drvdata(idev);
+       int index, mode;
+
+       mode = scancode >> 8;
+       if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
+               return -EINVAL;
+
+       index = ati_remote2_lookup(scancode & 0xFF);
+       if (index < 0)
+               return -EINVAL;
+
+       *keycode = ar2->keycode[mode][index];
+       return 0;
+}
+
+static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode)
+{
+       struct ati_remote2 *ar2 = input_get_drvdata(idev);
+       int index, mode, old_keycode;
+
+       mode = scancode >> 8;
+       if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask))
+               return -EINVAL;
+
+       index = ati_remote2_lookup(scancode & 0xFF);
+       if (index < 0)
+               return -EINVAL;
+
+       if (keycode < KEY_RESERVED || keycode > KEY_MAX)
+               return -EINVAL;
+
+       old_keycode = ar2->keycode[mode][index];
+       ar2->keycode[mode][index] = keycode;
+       set_bit(keycode, idev->keybit);
+
+       for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
+               for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
+                       if (ar2->keycode[mode][index] == old_keycode)
+                               return 0;
+               }
+       }
+
+       clear_bit(old_keycode, idev->keybit);
+
+       return 0;
+}
+
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
 {
        struct input_dev *idev;
-       int i, retval;
+       int index, mode, retval;
 
        idev = input_allocate_device();
        if (!idev)
@@ -350,8 +469,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
                BIT_MASK(BTN_RIGHT);
        idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-       for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
-               set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
+
+       for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
+               for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
+                       ar2->keycode[mode][index] = ati_remote2_key_table[index].keycode;
+                       set_bit(ar2->keycode[mode][index], idev->keybit);
+               }
+       }
+
+       /* AUX1-AUX4 and PC generate the same scancode. */
+       index = ati_remote2_lookup(0x3f);
+       ar2->keycode[ATI_REMOTE2_AUX1][index] = KEY_PROG1;
+       ar2->keycode[ATI_REMOTE2_AUX2][index] = KEY_PROG2;
+       ar2->keycode[ATI_REMOTE2_AUX3][index] = KEY_PROG3;
+       ar2->keycode[ATI_REMOTE2_AUX4][index] = KEY_PROG4;
+       ar2->keycode[ATI_REMOTE2_PC][index] = KEY_PC;
+       set_bit(KEY_PROG1, idev->keybit);
+       set_bit(KEY_PROG2, idev->keybit);
+       set_bit(KEY_PROG3, idev->keybit);
+       set_bit(KEY_PROG4, idev->keybit);
+       set_bit(KEY_PC, idev->keybit);
 
        idev->rep[REP_DELAY]  = 250;
        idev->rep[REP_PERIOD] = 33;
@@ -359,6 +496,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->open = ati_remote2_open;
        idev->close = ati_remote2_close;
 
+       idev->getkeycode = ati_remote2_getkeycode;
+       idev->setkeycode = ati_remote2_setkeycode;
+
        idev->name = ar2->name;
        idev->phys = ar2->phys;
 
@@ -490,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
 
        usb_set_intfdata(interface, ar2);
 
+       interface->needs_remote_wakeup = 1;
+
        return 0;
 
  fail2:
@@ -522,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface)
        kfree(ar2);
 }
 
+static int ati_remote2_suspend(struct usb_interface *interface,
+                              pm_message_t message)
+{
+       struct ati_remote2 *ar2;
+       struct usb_host_interface *alt = interface->cur_altsetting;
+
+       if (alt->desc.bInterfaceNumber)
+               return 0;
+
+       ar2 = usb_get_intfdata(interface);
+
+       dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+       mutex_lock(&ati_remote2_mutex);
+
+       if (ar2->flags & ATI_REMOTE2_OPENED)
+               ati_remote2_kill_urbs(ar2);
+
+       ar2->flags |= ATI_REMOTE2_SUSPENDED;
+
+       mutex_unlock(&ati_remote2_mutex);
+
+       return 0;
+}
+
+static int ati_remote2_resume(struct usb_interface *interface)
+{
+       struct ati_remote2 *ar2;
+       struct usb_host_interface *alt = interface->cur_altsetting;
+       int r = 0;
+
+       if (alt->desc.bInterfaceNumber)
+               return 0;
+
+       ar2 = usb_get_intfdata(interface);
+
+       dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__);
+
+       mutex_lock(&ati_remote2_mutex);
+
+       if (ar2->flags & ATI_REMOTE2_OPENED)
+               r = ati_remote2_submit_urbs(ar2);
+
+       if (!r)
+               ar2->flags &= ~ATI_REMOTE2_SUSPENDED;
+
+       mutex_unlock(&ati_remote2_mutex);
+
+       return r;
+}
+
 static int __init ati_remote2_init(void)
 {
        int r;
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
new file mode 100644 (file)
index 0000000..bce160f
--- /dev/null
@@ -0,0 +1,882 @@
+/*
+ * Driver for the VoIP USB phones with CM109 chipsets.
+ *
+ * Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.org>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ */
+
+/*
+ *   Tested devices:
+ *     - Komunikate KIP1000
+ *     - Genius G-talk
+ *     - Allied-Telesis Corega USBPH01
+ *     - ...
+ *
+ * This driver is based on the yealink.c driver
+ *
+ * Thanks to:
+ *   - Authors of yealink.c
+ *   - Thomas Reitmayr
+ *   - Oliver Neukum for good review comments and code
+ *   - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap
+ *   - Dmitry Torokhov for valuable input and review
+ *
+ * Todo:
+ *   - Read/write EEPROM
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/rwsem.h>
+#include <linux/usb/input.h>
+
+#define DRIVER_VERSION "20080805"
+#define DRIVER_AUTHOR  "Alfred E. Heggestad"
+#define DRIVER_DESC    "CM109 phone driver"
+
+static char *phone = "kip1000";
+module_param(phone, charp, S_IRUSR);
+MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}");
+
+enum {
+       /* HID Registers */
+       HID_IR0 = 0x00, /* Record/Playback-mute button, Volume up/down  */
+       HID_IR1 = 0x01, /* GPI, generic registers or EEPROM_DATA0       */
+       HID_IR2 = 0x02, /* Generic registers or EEPROM_DATA1            */
+       HID_IR3 = 0x03, /* Generic registers or EEPROM_CTRL             */
+       HID_OR0 = 0x00, /* Mapping control, buzzer, SPDIF (offset 0x04) */
+       HID_OR1 = 0x01, /* GPO - General Purpose Output                 */
+       HID_OR2 = 0x02, /* Set GPIO to input/output mode                */
+       HID_OR3 = 0x03, /* SPDIF status channel or EEPROM_CTRL          */
+
+       /* HID_IR0 */
+       RECORD_MUTE   = 1 << 3,
+       PLAYBACK_MUTE = 1 << 2,
+       VOLUME_DOWN   = 1 << 1,
+       VOLUME_UP     = 1 << 0,
+
+       /* HID_OR0 */
+       /* bits 7-6
+          0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer
+             and SPDIF
+          1: HID_OR0-3 are used as generic HID registers
+          2: Values written to HID_OR0-3 are also mapped to MCU_CTRL,
+             EEPROM_DATA0-1, EEPROM_CTRL (see Note)
+          3: Reserved
+        */
+       HID_OR_GPO_BUZ_SPDIF   = 0 << 6,
+       HID_OR_GENERIC_HID_REG = 1 << 6,
+       HID_OR_MAP_MCU_EEPROM  = 2 << 6,
+
+       BUZZER_ON = 1 << 5,
+
+       /* up to 256 normal keys, up to 16 special keys */
+       KEYMAP_SIZE = 256 + 16,
+};
+
+/* CM109 protocol packet */
+struct cm109_ctl_packet {
+       u8 byte[4];
+} __attribute__ ((packed));
+
+enum { USB_PKT_LEN = sizeof(struct cm109_ctl_packet) };
+
+/* CM109 device structure */
+struct cm109_dev {
+       struct input_dev *idev;  /* input device */
+       struct usb_device *udev; /* usb device */
+       struct usb_interface *intf;
+
+       /* irq input channel */
+       struct cm109_ctl_packet *irq_data;
+       dma_addr_t irq_dma;
+       struct urb *urb_irq;
+
+       /* control output channel */
+       struct cm109_ctl_packet *ctl_data;
+       dma_addr_t ctl_dma;
+       struct usb_ctrlrequest *ctl_req;
+       dma_addr_t ctl_req_dma;
+       struct urb *urb_ctl;
+       /*
+        * The 3 bitfields below are protected by ctl_submit_lock.
+        * They have to be separate since they are accessed from IRQ
+        * context.
+        */
+       unsigned irq_urb_pending:1;     /* irq_urb is in flight */
+       unsigned ctl_urb_pending:1;     /* ctl_urb is in flight */
+       unsigned buzzer_pending:1;      /* need to issue buzz command */
+       spinlock_t ctl_submit_lock;
+
+       unsigned char buzzer_state;     /* on/off */
+
+       /* flags */
+       unsigned open:1;
+       unsigned resetting:1;
+       unsigned shutdown:1;
+
+       /* This mutex protects writes to the above flags */
+       struct mutex pm_mutex;
+
+       unsigned short keymap[KEYMAP_SIZE];
+
+       char phys[64];          /* physical device path */
+       int key_code;           /* last reported key */
+       int keybit;             /* 0=new scan  1,2,4,8=scan columns  */
+       u8 gpi;                 /* Cached value of GPI (high nibble) */
+};
+
+/******************************************************************************
+ * CM109 key interface
+ *****************************************************************************/
+
+static unsigned short special_keymap(int code)
+{
+       if (code > 0xff) {
+               switch (code - 0xff) {
+               case RECORD_MUTE:       return KEY_MUTE;
+               case PLAYBACK_MUTE:     return KEY_MUTE;
+               case VOLUME_DOWN:       return KEY_VOLUMEDOWN;
+               case VOLUME_UP:         return KEY_VOLUMEUP;
+               }
+       }
+       return KEY_RESERVED;
+}
+
+/* Map device buttons to internal key events.
+ *
+ * The "up" and "down" keys, are symbolised by arrows on the button.
+ * The "pickup" and "hangup" keys are symbolised by a green and red phone
+ * on the button.
+
+ Komunikate KIP1000 Keyboard Matrix
+
+     -> -- 1 -- 2 -- 3  --> GPI pin 4 (0x10)
+      |    |    |    |
+     <- -- 4 -- 5 -- 6  --> GPI pin 5 (0x20)
+      |    |    |    |
+     END - 7 -- 8 -- 9  --> GPI pin 6 (0x40)
+      |    |    |    |
+     OK -- * -- 0 -- #  --> GPI pin 7 (0x80)
+      |    |    |    |
+
+     /|\  /|\  /|\  /|\
+      |    |    |    |
+GPO
+pin:  3    2    1    0
+     0x8  0x4  0x2  0x1
+
+ */
+static unsigned short keymap_kip1000(int scancode)
+{
+       switch (scancode) {                             /* phone key:   */
+       case 0x82: return KEY_NUMERIC_0;                /*   0          */
+       case 0x14: return KEY_NUMERIC_1;                /*   1          */
+       case 0x12: return KEY_NUMERIC_2;                /*   2          */
+       case 0x11: return KEY_NUMERIC_3;                /*   3          */
+       case 0x24: return KEY_NUMERIC_4;                /*   4          */
+       case 0x22: return KEY_NUMERIC_5;                /*   5          */
+       case 0x21: return KEY_NUMERIC_6;                /*   6          */
+       case 0x44: return KEY_NUMERIC_7;                /*   7          */
+       case 0x42: return KEY_NUMERIC_8;                /*   8          */
+       case 0x41: return KEY_NUMERIC_9;                /*   9          */
+       case 0x81: return KEY_NUMERIC_POUND;            /*   #          */
+       case 0x84: return KEY_NUMERIC_STAR;             /*   *          */
+       case 0x88: return KEY_ENTER;                    /*   pickup     */
+       case 0x48: return KEY_ESC;                      /*   hangup     */
+       case 0x28: return KEY_LEFT;                     /*   IN         */
+       case 0x18: return KEY_RIGHT;                    /*   OUT        */
+       default:   return special_keymap(scancode);
+       }
+}
+
+/*
+  Contributed by Shaun Jackman <sjackman@gmail.com>
+
+  Genius G-Talk keyboard matrix
+     0 1 2 3
+  4: 0 4 8 Talk
+  5: 1 5 9 End
+  6: 2 6 # Up
+  7: 3 7 * Down
+*/
+static unsigned short keymap_gtalk(int scancode)
+{
+       switch (scancode) {
+       case 0x11: return KEY_NUMERIC_0;
+       case 0x21: return KEY_NUMERIC_1;
+       case 0x41: return KEY_NUMERIC_2;
+       case 0x81: return KEY_NUMERIC_3;
+       case 0x12: return KEY_NUMERIC_4;
+       case 0x22: return KEY_NUMERIC_5;
+       case 0x42: return KEY_NUMERIC_6;
+       case 0x82: return KEY_NUMERIC_7;
+       case 0x14: return KEY_NUMERIC_8;
+       case 0x24: return KEY_NUMERIC_9;
+       case 0x44: return KEY_NUMERIC_POUND;    /* # */
+       case 0x84: return KEY_NUMERIC_STAR;     /* * */
+       case 0x18: return KEY_ENTER;            /* Talk (green handset) */
+       case 0x28: return KEY_ESC;              /* End (red handset) */
+       case 0x48: return KEY_UP;               /* Menu up (rocker switch) */
+       case 0x88: return KEY_DOWN;             /* Menu down (rocker switch) */
+       default:   return special_keymap(scancode);
+       }
+}
+
+/*
+ * Keymap for Allied-Telesis Corega USBPH01
+ * http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html
+ *
+ * Contributed by july@nat.bg
+ */
+static unsigned short keymap_usbph01(int scancode)
+{
+       switch (scancode) {
+       case 0x11: return KEY_NUMERIC_0;                /*   0          */
+       case 0x21: return KEY_NUMERIC_1;                /*   1          */
+       case 0x41: return KEY_NUMERIC_2;                /*   2          */
+       case 0x81: return KEY_NUMERIC_3;                /*   3          */
+       case 0x12: return KEY_NUMERIC_4;                /*   4          */
+       case 0x22: return KEY_NUMERIC_5;                /*   5          */
+       case 0x42: return KEY_NUMERIC_6;                /*   6          */
+       case 0x82: return KEY_NUMERIC_7;                /*   7          */
+       case 0x14: return KEY_NUMERIC_8;                /*   8          */
+       case 0x24: return KEY_NUMERIC_9;                /*   9          */
+       case 0x44: return KEY_NUMERIC_POUND;            /*   #          */
+       case 0x84: return KEY_NUMERIC_STAR;             /*   *          */
+       case 0x18: return KEY_ENTER;                    /*   pickup     */
+       case 0x28: return KEY_ESC;                      /*   hangup     */
+       case 0x48: return KEY_LEFT;                     /*   IN         */
+       case 0x88: return KEY_RIGHT;                    /*   OUT        */
+       default:   return special_keymap(scancode);
+       }
+}
+
+static unsigned short (*keymap)(int) = keymap_kip1000;
+
+/*
+ * Completes a request by converting the data into events for the
+ * input subsystem.
+ */
+static void report_key(struct cm109_dev *dev, int key)
+{
+       struct input_dev *idev = dev->idev;
+
+       if (dev->key_code >= 0) {
+               /* old key up */
+               input_report_key(idev, dev->key_code, 0);
+       }
+
+       dev->key_code = key;
+       if (key >= 0) {
+               /* new valid key */
+               input_report_key(idev, key, 1);
+       }
+
+       input_sync(idev);
+}
+
+/******************************************************************************
+ * CM109 usb communication interface
+ *****************************************************************************/
+
+static void cm109_submit_buzz_toggle(struct cm109_dev *dev)
+{
+       int error;
+
+       if (dev->buzzer_state)
+               dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+       else
+               dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+       error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
+       if (error)
+               err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+}
+
+/*
+ * IRQ handler
+ */
+static void cm109_urb_irq_callback(struct urb *urb)
+{
+       struct cm109_dev *dev = urb->context;
+       const int status = urb->status;
+       int error;
+
+       dev_dbg(&urb->dev->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n",
+            dev->irq_data->byte[0],
+            dev->irq_data->byte[1],
+            dev->irq_data->byte[2],
+            dev->irq_data->byte[3],
+            dev->keybit);
+
+       if (status) {
+               if (status == -ESHUTDOWN)
+                       return;
+               err("%s: urb status %d", __func__, status);
+       }
+
+       /* Special keys */
+       if (dev->irq_data->byte[HID_IR0] & 0x0f) {
+               const int code = (dev->irq_data->byte[HID_IR0] & 0x0f);
+               report_key(dev, dev->keymap[0xff + code]);
+       }
+
+       /* Scan key column */
+       if (dev->keybit == 0xf) {
+
+               /* Any changes ? */
+               if ((dev->gpi & 0xf0) == (dev->irq_data->byte[HID_IR1] & 0xf0))
+                       goto out;
+
+               dev->gpi = dev->irq_data->byte[HID_IR1] & 0xf0;
+               dev->keybit = 0x1;
+       } else {
+               report_key(dev, dev->keymap[dev->irq_data->byte[HID_IR1]]);
+
+               dev->keybit <<= 1;
+               if (dev->keybit > 0x8)
+                       dev->keybit = 0xf;
+       }
+
+ out:
+
+       spin_lock(&dev->ctl_submit_lock);
+
+       dev->irq_urb_pending = 0;
+
+       if (likely(!dev->shutdown)) {
+
+               if (dev->buzzer_state)
+                       dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+               else
+                       dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+               dev->ctl_data->byte[HID_OR1] = dev->keybit;
+               dev->ctl_data->byte[HID_OR2] = dev->keybit;
+
+               dev->buzzer_pending = 0;
+               dev->ctl_urb_pending = 1;
+
+               error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC);
+               if (error)
+                       err("%s: usb_submit_urb (urb_ctl) failed %d",
+                               __func__, error);
+       }
+
+       spin_unlock(&dev->ctl_submit_lock);
+}
+
+static void cm109_urb_ctl_callback(struct urb *urb)
+{
+       struct cm109_dev *dev = urb->context;
+       const int status = urb->status;
+       int error;
+
+       dev_dbg(&urb->dev->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n",
+            dev->ctl_data->byte[0],
+            dev->ctl_data->byte[1],
+            dev->ctl_data->byte[2],
+            dev->ctl_data->byte[3]);
+
+       if (status)
+               err("%s: urb status %d", __func__, status);
+
+       spin_lock(&dev->ctl_submit_lock);
+
+       dev->ctl_urb_pending = 0;
+
+       if (likely(!dev->shutdown)) {
+
+               if (dev->buzzer_pending) {
+                       dev->buzzer_pending = 0;
+                       dev->ctl_urb_pending = 1;
+                       cm109_submit_buzz_toggle(dev);
+               } else if (likely(!dev->irq_urb_pending)) {
+                       /* ask for key data */
+                       dev->irq_urb_pending = 1;
+                       error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC);
+                       if (error)
+                               err("%s: usb_submit_urb (urb_irq) failed %d",
+                                       __func__, error);
+               }
+       }
+
+       spin_unlock(&dev->ctl_submit_lock);
+}
+
+static void cm109_toggle_buzzer_async(struct cm109_dev *dev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->ctl_submit_lock, flags);
+
+       if (dev->ctl_urb_pending) {
+               /* URB completion will resubmit */
+               dev->buzzer_pending = 1;
+       } else {
+               dev->ctl_urb_pending = 1;
+               cm109_submit_buzz_toggle(dev);
+       }
+
+       spin_unlock_irqrestore(&dev->ctl_submit_lock, flags);
+}
+
+static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on)
+{
+       int error;
+
+       if (on)
+               dev->ctl_data->byte[HID_OR0] |= BUZZER_ON;
+       else
+               dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON;
+
+       error = usb_control_msg(dev->udev,
+                               usb_sndctrlpipe(dev->udev, 0),
+                               dev->ctl_req->bRequest,
+                               dev->ctl_req->bRequestType,
+                               le16_to_cpu(dev->ctl_req->wValue),
+                               le16_to_cpu(dev->ctl_req->wIndex),
+                               dev->ctl_data,
+                               USB_PKT_LEN, USB_CTRL_SET_TIMEOUT);
+       if (error && error != EINTR)
+               err("%s: usb_control_msg() failed %d", __func__, error);
+}
+
+static void cm109_stop_traffic(struct cm109_dev *dev)
+{
+       dev->shutdown = 1;
+       /*
+        * Make sure other CPUs see this
+        */
+       smp_wmb();
+
+       usb_kill_urb(dev->urb_ctl);
+       usb_kill_urb(dev->urb_irq);
+
+       cm109_toggle_buzzer_sync(dev, 0);
+
+       dev->shutdown = 0;
+       smp_wmb();
+}
+
+static void cm109_restore_state(struct cm109_dev *dev)
+{
+       if (dev->open) {
+               /*
+                * Restore buzzer state.
+                * This will also kick regular URB submission
+                */
+               cm109_toggle_buzzer_async(dev);
+       }
+}
+
+/******************************************************************************
+ * input event interface
+ *****************************************************************************/
+
+static int cm109_input_open(struct input_dev *idev)
+{
+       struct cm109_dev *dev = input_get_drvdata(idev);
+       int error;
+
+       error = usb_autopm_get_interface(dev->intf);
+       if (error < 0) {
+               err("%s - cannot autoresume, result %d",
+                   __func__, error);
+               return error;
+       }
+
+       mutex_lock(&dev->pm_mutex);
+
+       dev->buzzer_state = 0;
+       dev->key_code = -1;     /* no keys pressed */
+       dev->keybit = 0xf;
+
+       /* issue INIT */
+       dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF;
+       dev->ctl_data->byte[HID_OR1] = dev->keybit;
+       dev->ctl_data->byte[HID_OR2] = dev->keybit;
+       dev->ctl_data->byte[HID_OR3] = 0x00;
+
+       error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
+       if (error)
+               err("%s: usb_submit_urb (urb_ctl) failed %d", __func__, error);
+       else
+               dev->open = 1;
+
+       mutex_unlock(&dev->pm_mutex);
+
+       if (error)
+               usb_autopm_put_interface(dev->intf);
+
+       return error;
+}
+
+static void cm109_input_close(struct input_dev *idev)
+{
+       struct cm109_dev *dev = input_get_drvdata(idev);
+
+       mutex_lock(&dev->pm_mutex);
+
+       /*
+        * Once we are here event delivery is stopped so we
+        * don't need to worry about someone starting buzzer
+        * again
+        */
+       cm109_stop_traffic(dev);
+       dev->open = 0;
+
+       mutex_unlock(&dev->pm_mutex);
+
+       usb_autopm_put_interface(dev->intf);
+}
+
+static int cm109_input_ev(struct input_dev *idev, unsigned int type,
+                         unsigned int code, int value)
+{
+       struct cm109_dev *dev = input_get_drvdata(idev);
+
+       dev_dbg(&dev->udev->dev,
+               "input_ev: type=%u code=%u value=%d\n", type, code, value);
+
+       if (type != EV_SND)
+               return -EINVAL;
+
+       switch (code) {
+       case SND_TONE:
+       case SND_BELL:
+               dev->buzzer_state = !!value;
+               if (!dev->resetting)
+                       cm109_toggle_buzzer_async(dev);
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+
+/******************************************************************************
+ * Linux interface and usb initialisation
+ *****************************************************************************/
+
+struct driver_info {
+       char *name;
+};
+
+static const struct driver_info info_cm109 = {
+       .name = "CM109 USB driver",
+};
+
+enum {
+       VENDOR_ID        = 0x0d8c, /* C-Media Electronics */
+       PRODUCT_ID_CM109 = 0x000e, /* CM109 defines range 0x0008 - 0x000f */
+};
+
+/* table of devices that work with this driver */
+static const struct usb_device_id cm109_usb_table[] = {
+       {
+               .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+                               USB_DEVICE_ID_MATCH_INT_INFO,
+               .idVendor = VENDOR_ID,
+               .idProduct = PRODUCT_ID_CM109,
+               .bInterfaceClass = USB_CLASS_HID,
+               .bInterfaceSubClass = 0,
+               .bInterfaceProtocol = 0,
+               .driver_info = (kernel_ulong_t) &info_cm109
+       },
+       /* you can add more devices here with product ID 0x0008 - 0x000f */
+       { }
+};
+
+static void cm109_usb_cleanup(struct cm109_dev *dev)
+{
+       if (dev->ctl_req)
+               usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)),
+                               dev->ctl_req, dev->ctl_req_dma);
+       if (dev->ctl_data)
+               usb_buffer_free(dev->udev, USB_PKT_LEN,
+                               dev->ctl_data, dev->ctl_dma);
+       if (dev->irq_data)
+               usb_buffer_free(dev->udev, USB_PKT_LEN,
+                               dev->irq_data, dev->irq_dma);
+
+       usb_free_urb(dev->urb_irq);     /* parameter validation in core/urb */
+       usb_free_urb(dev->urb_ctl);     /* parameter validation in core/urb */
+       kfree(dev);
+}
+
+static void cm109_usb_disconnect(struct usb_interface *interface)
+{
+       struct cm109_dev *dev = usb_get_intfdata(interface);
+
+       usb_set_intfdata(interface, NULL);
+       input_unregister_device(dev->idev);
+       cm109_usb_cleanup(dev);
+}
+
+static int cm109_usb_probe(struct usb_interface *intf,
+                          const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct driver_info *nfo = (struct driver_info *)id->driver_info;
+       struct usb_host_interface *interface;
+       struct usb_endpoint_descriptor *endpoint;
+       struct cm109_dev *dev;
+       struct input_dev *input_dev = NULL;
+       int ret, pipe, i;
+       int error = -ENOMEM;
+
+       interface = intf->cur_altsetting;
+       endpoint = &interface->endpoint[0].desc;
+
+       if (!usb_endpoint_is_int_in(endpoint))
+               return -ENODEV;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       spin_lock_init(&dev->ctl_submit_lock);
+       mutex_init(&dev->pm_mutex);
+
+       dev->udev = udev;
+       dev->intf = intf;
+
+       dev->idev = input_dev = input_allocate_device();
+       if (!input_dev)
+               goto err_out;
+
+       /* allocate usb buffers */
+       dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+                                        GFP_KERNEL, &dev->irq_dma);
+       if (!dev->irq_data)
+               goto err_out;
+
+       dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
+                                        GFP_KERNEL, &dev->ctl_dma);
+       if (!dev->ctl_data)
+               goto err_out;
+
+       dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)),
+                                       GFP_KERNEL, &dev->ctl_req_dma);
+       if (!dev->ctl_req)
+               goto err_out;
+
+       /* allocate urb structures */
+       dev->urb_irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->urb_irq)
+               goto err_out;
+
+       dev->urb_ctl = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->urb_ctl)
+               goto err_out;
+
+       /* get a handle to the interrupt data pipe */
+       pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+       ret = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+       if (ret != USB_PKT_LEN)
+               err("invalid payload size %d, expected %d", ret, USB_PKT_LEN);
+
+       /* initialise irq urb */
+       usb_fill_int_urb(dev->urb_irq, udev, pipe, dev->irq_data,
+                        USB_PKT_LEN,
+                        cm109_urb_irq_callback, dev, endpoint->bInterval);
+       dev->urb_irq->transfer_dma = dev->irq_dma;
+       dev->urb_irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       dev->urb_irq->dev = udev;
+
+       /* initialise ctl urb */
+       dev->ctl_req->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE |
+                                       USB_DIR_OUT;
+       dev->ctl_req->bRequest = USB_REQ_SET_CONFIGURATION;
+       dev->ctl_req->wValue = cpu_to_le16(0x200);
+       dev->ctl_req->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber);
+       dev->ctl_req->wLength = cpu_to_le16(USB_PKT_LEN);
+
+       usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0),
+                            (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN,
+                            cm109_urb_ctl_callback, dev);
+       dev->urb_ctl->setup_dma = dev->ctl_req_dma;
+       dev->urb_ctl->transfer_dma = dev->ctl_dma;
+       dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP |
+                                       URB_NO_TRANSFER_DMA_MAP;
+       dev->urb_ctl->dev = udev;
+
+       /* find out the physical bus location */
+       usb_make_path(udev, dev->phys, sizeof(dev->phys));
+       strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+       /* register settings for the input device */
+       input_dev->name = nfo->name;
+       input_dev->phys = dev->phys;
+       usb_to_input_id(udev, &input_dev->id);
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, dev);
+       input_dev->open = cm109_input_open;
+       input_dev->close = cm109_input_close;
+       input_dev->event = cm109_input_ev;
+
+       input_dev->keycode = dev->keymap;
+       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodemax = ARRAY_SIZE(dev->keymap);
+
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_SND);
+       input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+
+       /* register available key events */
+       for (i = 0; i < KEYMAP_SIZE; i++) {
+               unsigned short k = keymap(i);
+               dev->keymap[i] = k;
+               __set_bit(k, input_dev->keybit);
+       }
+       __clear_bit(KEY_RESERVED, input_dev->keybit);
+
+       error = input_register_device(dev->idev);
+       if (error)
+               goto err_out;
+
+       usb_set_intfdata(intf, dev);
+
+       return 0;
+
+ err_out:
+       input_free_device(input_dev);
+       cm109_usb_cleanup(dev);
+       return error;
+}
+
+static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct cm109_dev *dev = usb_get_intfdata(intf);
+
+       dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event);
+
+       mutex_lock(&dev->pm_mutex);
+       cm109_stop_traffic(dev);
+       mutex_unlock(&dev->pm_mutex);
+
+       return 0;
+}
+
+static int cm109_usb_resume(struct usb_interface *intf)
+{
+       struct cm109_dev *dev = usb_get_intfdata(intf);
+
+       dev_info(&intf->dev, "cm109: usb_resume\n");
+
+       mutex_lock(&dev->pm_mutex);
+       cm109_restore_state(dev);
+       mutex_unlock(&dev->pm_mutex);
+
+       return 0;
+}
+
+static int cm109_usb_pre_reset(struct usb_interface *intf)
+{
+       struct cm109_dev *dev = usb_get_intfdata(intf);
+
+       mutex_lock(&dev->pm_mutex);
+
+       /*
+        * Make sure input events don't try to toggle buzzer
+        * while we are resetting
+        */
+       dev->resetting = 1;
+       smp_wmb();
+
+       cm109_stop_traffic(dev);
+
+       return 0;
+}
+
+static int cm109_usb_post_reset(struct usb_interface *intf)
+{
+       struct cm109_dev *dev = usb_get_intfdata(intf);
+
+       dev->resetting = 0;
+       smp_wmb();
+
+       cm109_restore_state(dev);
+
+       mutex_unlock(&dev->pm_mutex);
+
+       return 0;
+}
+
+static struct usb_driver cm109_driver = {
+       .name           = "cm109",
+       .probe          = cm109_usb_probe,
+       .disconnect     = cm109_usb_disconnect,
+       .suspend        = cm109_usb_suspend,
+       .resume         = cm109_usb_resume,
+       .reset_resume   = cm109_usb_resume,
+       .pre_reset      = cm109_usb_pre_reset,
+       .post_reset     = cm109_usb_post_reset,
+       .id_table       = cm109_usb_table,
+       .supports_autosuspend = 1,
+};
+
+static int __init cm109_select_keymap(void)
+{
+       /* Load the phone keymap */
+       if (!strcasecmp(phone, "kip1000")) {
+               keymap = keymap_kip1000;
+               printk(KERN_INFO KBUILD_MODNAME ": "
+                       "Keymap for Komunikate KIP1000 phone loaded\n");
+       } else if (!strcasecmp(phone, "gtalk")) {
+               keymap = keymap_gtalk;
+               printk(KERN_INFO KBUILD_MODNAME ": "
+                       "Keymap for Genius G-talk phone loaded\n");
+       } else if (!strcasecmp(phone, "usbph01")) {
+               keymap = keymap_usbph01;
+               printk(KERN_INFO KBUILD_MODNAME ": "
+                       "Keymap for Allied-Telesis Corega USBPH01 phone loaded\n");
+       } else {
+               printk(KERN_ERR KBUILD_MODNAME ": "
+                       "Unsupported phone: %s\n", phone);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int __init cm109_init(void)
+{
+       int err;
+
+       err = cm109_select_keymap();
+       if (err)
+               return err;
+
+       err = usb_register(&cm109_driver);
+       if (err)
+               return err;
+
+       printk(KERN_INFO KBUILD_MODNAME ": "
+               DRIVER_DESC ": " DRIVER_VERSION " (C) " DRIVER_AUTHOR "\n");
+
+       return 0;
+}
+
+static void __exit cm109_exit(void)
+{
+       usb_deregister(&cm109_driver);
+}
+
+module_init(cm109_init);
+module_exit(cm109_exit);
+
+MODULE_DEVICE_TABLE(usb, cm109_usb_table);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index daa9d4220331b06e68b9100caad9c5e98065a48f..82ec6b1b646782276363f769bc73e96226237459 100644 (file)
@@ -458,35 +458,35 @@ static int hp_sdc_rtc_proc_output (char *buf)
                p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
        } else {
                p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", 
-                            tv.tv_sec, tv.tv_usec/1000);
+                            tv.tv_sec, (int)tv.tv_usec/1000);
        }
 
        if (hp_sdc_rtc_read_fhs(&tv)) {
                p += sprintf(p, "handshake\t: READ FAILED!\n");
        } else {
                p += sprintf(p, "handshake\t: %ld.%02d seconds\n", 
-                            tv.tv_sec, tv.tv_usec/1000);
+                            tv.tv_sec, (int)tv.tv_usec/1000);
        }
 
        if (hp_sdc_rtc_read_mt(&tv)) {
                p += sprintf(p, "alarm\t\t: READ FAILED!\n");
        } else {
                p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", 
-                            tv.tv_sec, tv.tv_usec/1000);
+                            tv.tv_sec, (int)tv.tv_usec/1000);
        }
 
        if (hp_sdc_rtc_read_dt(&tv)) {
                p += sprintf(p, "delay\t\t: READ FAILED!\n");
        } else {
                p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", 
-                            tv.tv_sec, tv.tv_usec/1000);
+                            tv.tv_sec, (int)tv.tv_usec/1000);
        }
 
        if (hp_sdc_rtc_read_ct(&tv)) {
                p += sprintf(p, "periodic\t: READ FAILED!\n");
        } else {
                p += sprintf(p, "periodic\t: %ld.%02d seconds\n", 
-                            tv.tv_sec, tv.tv_usec/1000);
+                            tv.tv_sec, (int)tv.tv_usec/1000);
        }
 
         p += sprintf(p,
diff --git a/drivers/input/misc/map_to_7segment.h b/drivers/input/misc/map_to_7segment.h
deleted file mode 100644 (file)
index a424094..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * drivers/usb/input/map_to_7segment.h
- *
- * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef MAP_TO_7SEGMENT_H
-#define MAP_TO_7SEGMENT_H
-
-/* This file provides translation primitives and tables for the conversion
- * of (ASCII) characters to a 7-segments notation.
- *
- * The 7 segment's wikipedia notation below is used as standard.
- * See: http://en.wikipedia.org/wiki/Seven_segment_display
- *
- * Notation:   +-a-+
- *             f   b
- *             +-g-+
- *             e   c
- *             +-d-+
- *
- * Usage:
- *
- *   Register a map variable, and fill it with a character set:
- *     static SEG7_DEFAULT_MAP(map_seg7);
- *
- *
- *   Then use for conversion:
- *     seg7 = map_to_seg7(&map_seg7, some_char);
- *     ...
- *
- * In device drivers it is recommended, if required, to make the char map
- * accessible via the sysfs interface using the following scheme:
- *
- * static ssize_t show_map(struct device *dev, char *buf) {
- *     memcpy(buf, &map_seg7, sizeof(map_seg7));
- *     return sizeof(map_seg7);
- * }
- * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) {
- *     if(cnt != sizeof(map_seg7))
- *             return -EINVAL;
- *     memcpy(&map_seg7, buf, cnt);
- *     return cnt;
- * }
- * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map);
- *
- * History:
- * 2005-05-31  RFC linux-kernel@vger.kernel.org
- */
-#include <linux/errno.h>
-
-
-#define BIT_SEG7_A             0
-#define BIT_SEG7_B             1
-#define BIT_SEG7_C             2
-#define BIT_SEG7_D             3
-#define BIT_SEG7_E             4
-#define BIT_SEG7_F             5
-#define BIT_SEG7_G             6
-#define BIT_SEG7_RESERVED      7
-
-struct seg7_conversion_map {
-       unsigned char   table[128];
-};
-
-static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
-{
-       return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL;
-}
-
-#define SEG7_CONVERSION_MAP(_name, _map)       \
-       struct seg7_conversion_map _name = { .table = { _map } }
-
-/*
- * It is recommended to use a facility that allows user space to redefine
- * custom character sets for LCD devices. Please use a sysfs interface
- * as described above.
- */
-#define MAP_TO_SEG7_SYSFS_FILE "map_seg7"
-
-/*******************************************************************************
- * ASCII conversion table
- ******************************************************************************/
-
-#define _SEG7(l,a,b,c,d,e,f,g) \
-      (        a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \
-       e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G )
-
-#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE     \
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-
-#define _MAP_33_47_ASCII_SEG7_SYMBOL           \
- _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\
- _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\
- _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\
- _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\
- _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1),
-
-#define _MAP_48_57_ASCII_SEG7_NUMERIC          \
- _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\
- _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\
- _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\
- _SEG7('9',1,1,1,1,0,1,1),
-
-#define _MAP_58_64_ASCII_SEG7_SYMBOL           \
- _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\
- _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\
- _SEG7('@',1,1,0,1,1,1,1),
-
-#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR       \
- _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\
- _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
- _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\
- _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
- _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\
- _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\
- _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\
- _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
- _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
-
-#define _MAP_91_96_ASCII_SEG7_SYMBOL           \
- _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\
- _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0),
-
-#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER     \
- _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\
- _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
- _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\
- _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
- _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\
- _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\
- _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\
- _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
- _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
-
-#define _MAP_123_126_ASCII_SEG7_SYMBOL         \
- _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\
- _SEG7('~',1,0,0,0,0,0,0),
-
-/* Maps */
-
-/* This set tries to map as close as possible to the visible characteristics
- * of the ASCII symbol, lowercase and uppercase letters may differ in
- * presentation on the display.
- */
-#define MAP_ASCII7SEG_ALPHANUM                 \
-       _MAP_0_32_ASCII_SEG7_NON_PRINTABLE      \
-       _MAP_33_47_ASCII_SEG7_SYMBOL            \
-       _MAP_48_57_ASCII_SEG7_NUMERIC           \
-       _MAP_58_64_ASCII_SEG7_SYMBOL            \
-       _MAP_65_90_ASCII_SEG7_ALPHA_UPPR        \
-       _MAP_91_96_ASCII_SEG7_SYMBOL            \
-       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
-       _MAP_123_126_ASCII_SEG7_SYMBOL
-
-/* This set tries to map as close as possible to the symbolic characteristics
- * of the ASCII character for maximum discrimination.
- * For now this means all alpha chars are in lower case representations.
- * (This for example facilitates the use of hex numbers with uppercase input.)
- */
-#define MAP_ASCII7SEG_ALPHANUM_LC                      \
-       _MAP_0_32_ASCII_SEG7_NON_PRINTABLE      \
-       _MAP_33_47_ASCII_SEG7_SYMBOL            \
-       _MAP_48_57_ASCII_SEG7_NUMERIC           \
-       _MAP_58_64_ASCII_SEG7_SYMBOL            \
-       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
-       _MAP_91_96_ASCII_SEG7_SYMBOL            \
-       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
-       _MAP_123_126_ASCII_SEG7_SYMBOL
-
-#define SEG7_DEFAULT_MAP(_name)                \
-       SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM)
-
-#endif /* MAP_TO_7SEGMENT_H */
-
index fe268be3293b666e82b1e567bb645fb5847a3c5f..7c8957dd22c03d42252e410af97e385c78b2c4b7 100644 (file)
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
        { KE_END,  0 }
 };
 
+static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
+       { KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */
+       { KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
+       { KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
+       { KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
+       { KE_KEY,       0x36, {KEY_WWW} },           /* www button */
+       { KE_WIFI,      0x78 },                      /* satelite dish button */
+       { KE_END,       0 }
+};
+
 static struct key_entry keymap_fujitsu_n3510[] __initdata = {
        { KE_KEY, 0x11, {KEY_PROG1} },
        { KE_KEY, 0x12, {KEY_PROG2} },
@@ -616,6 +626,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_fs_amilo_pro_v2000
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Fujitsu-Siemens Amilo Pro Edition V3505",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v3505
+       },
        {
                .callback = dmi_matched,
                .ident = "Fujitsu-Siemens Amilo M7400",
index facefd3dba29a1aab6c4428c6bdef9a2a3aa1b55..11b5c7e84ed139ad9af9fe21fccc04927edd2a31 100644 (file)
@@ -52,8 +52,8 @@
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <linux/usb/input.h>
+#include <linux/map_to_7segment.h>
 
-#include "map_to_7segment.h"
 #include "yealink.h"
 
 #define DRIVER_VERSION "yld-20051230"
index f996546fc443757151f4f7f09f95c996f4c576d9..f488b6852baf78840c31fccf413ca63445965ac2 100644 (file)
@@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
 
          If unsure, say N.
 
+config MOUSE_PS2_OLPC
+       bool "OLPC PS/2 mouse protocol extension"
+       depends on MOUSE_PS2 && OLPC
+       help
+         Say Y here if you have an OLPC XO-1 laptop (with built-in
+         PS/2 touchpad/tablet device).  The manufacturer calls the
+         touchpad an HGPK.
+
+         If unsure, say N.
+
 config MOUSE_SERIAL
        tristate "Serial mouse"
        select SERIO
index d4d202516090be6075afd735663ded497c7b6b0d..8e6e690978016b0dfae3f89276e05273764665b5 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_MOUSE_GPIO)      += gpio_mouse.o
 psmouse-objs := psmouse-base.o synaptics.o
 
 psmouse-$(CONFIG_MOUSE_PS2_ALPS)       += alps.o
+psmouse-$(CONFIG_MOUSE_PS2_OLPC)       += hgpk.o
 psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP)  += logips2pp.o
 psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK)   += lifebook.o
 psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
index 385e32bcf6a6e0ed7328f8c7ffd39badb7e4d45e..cbedf957cc58a380b71dad024b58710f5b2b0912 100644 (file)
@@ -54,6 +54,7 @@ static const struct alps_model_info alps_model_data[] = {
        { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
        { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
        { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
+       { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
        { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
 };
 
index 1f41ae94f26bdf216a5f667e754b3c559831e7ed..079816e6b23b042bff9a883aa984ffea757ee5a6 100644 (file)
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table);
 #define ATP_GEYSER_MODE_REQUEST_INDEX          0
 #define ATP_GEYSER_MODE_VENDOR_VALUE           0x04
 
+/**
+ * enum atp_status_bits - status bit meanings
+ *
+ * These constants represent the meaning of the status bits.
+ * (only Geyser 3/4)
+ *
+ * @ATP_STATUS_BUTTON: The button was pressed
+ * @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad)
+ * @ATP_STATUS_FROM_RESET: Reset previously performed
+ */
+enum atp_status_bits {
+       ATP_STATUS_BUTTON       = BIT(0),
+       ATP_STATUS_BASE_UPDATE  = BIT(2),
+       ATP_STATUS_FROM_RESET   = BIT(4),
+};
+
 /* Structure to hold all of our device specific stuff */
 struct atp {
        char                    phys[64];
        struct usb_device       *udev;          /* usb device */
        struct urb              *urb;           /* usb request block */
-       signed char             *data;          /* transferred data */
+       u8                      *data;          /* transferred data */
        struct input_dev        *input;         /* input dev */
        enum atp_touchpad_type  type;           /* type of touchpad */
        bool                    open;
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work)
        int retval;
 
        dprintk("appletouch: putting appletouch to sleep (reinit)\n");
-       dev->idlecount = 0;
-
        atp_geyser_init(udev);
 
        retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
        input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
 }
 
-static void atp_complete(struct urb *urb)
+/* Check URB status and for correct length of data package */
+
+#define ATP_URB_STATUS_SUCCESS         0
+#define ATP_URB_STATUS_ERROR           1
+#define ATP_URB_STATUS_ERROR_FATAL     2
+
+static int atp_status_check(struct urb *urb)
 {
-       int x, y, x_z, y_z, x_f, y_f;
-       int retval, i, j;
-       int key;
        struct atp *dev = urb->context;
 
        switch (urb->status) {
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb)
                /* This urb is terminated, clean up */
                dbg("atp_complete: urb shutting down with status: %d",
                    urb->status);
-               return;
+               return ATP_URB_STATUS_ERROR_FATAL;
+
        default:
                dbg("atp_complete: nonzero urb status received: %d",
                    urb->status);
-               goto exit;
+               return ATP_URB_STATUS_ERROR;
        }
 
        /* drop incomplete datasets */
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb)
                dprintk("appletouch: incomplete data package"
                        " (first byte: %d, length: %d).\n",
                        dev->data[0], dev->urb->actual_length);
-               goto exit;
+               return ATP_URB_STATUS_ERROR;
        }
 
-       /* reorder the sensors values */
-       if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
-               memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+       return ATP_URB_STATUS_SUCCESS;
+}
 
-               /*
-                * The values are laid out like this:
-                * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
-                * '-' is an unused value.
-                */
+/*
+ * USB interrupt callback functions
+ */
 
-               /* read X values */
-               for (i = 0, j = 19; i < 20; i += 2, j += 3) {
-                       dev->xy_cur[i] = dev->data[j + 1];
-                       dev->xy_cur[i + 1] = dev->data[j + 2];
-               }
-               /* read Y values */
-               for (i = 0, j = 1; i < 9; i += 2, j += 3) {
-                       dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
-                       dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
-               }
-       } else if (dev->type == ATP_GEYSER2) {
+/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */
+
+static void atp_complete_geyser_1_2(struct urb *urb)
+{
+       int x, y, x_z, y_z, x_f, y_f;
+       int retval, i, j;
+       int key;
+       struct atp *dev = urb->context;
+       int status = atp_status_check(urb);
+
+       if (status == ATP_URB_STATUS_ERROR_FATAL)
+               return;
+       else if (status == ATP_URB_STATUS_ERROR)
+               goto exit;
+
+       /* reorder the sensors values */
+       if (dev->type == ATP_GEYSER2) {
                memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
                /*
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb)
                /* first sample */
                dev->valid = true;
                dev->x_old = dev->y_old = -1;
+
+               /* Store first sample */
                memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-               if (dev->size_detect_done ||
-                   dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */
-                       goto exit;
+               /* Perform size detection, if not done already */
+               if (!dev->size_detect_done) {
+
+                       /* 17" Powerbooks have extra X sensors */
+                       for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
+                            i < ATP_XSENSORS; i++) {
+                               if (!dev->xy_cur[i])
+                                       continue;
+
+                               printk(KERN_INFO
+                                       "appletouch: 17\" model detected.\n");
+
+                               if (dev->type == ATP_GEYSER2)
+                                       input_set_abs_params(dev->input, ABS_X,
+                                                            0,
+                                                            (20 - 1) *
+                                                            ATP_XFACT - 1,
+                                                            ATP_FUZZ, 0);
+                               else
+                                       input_set_abs_params(dev->input, ABS_X,
+                                                            0,
+                                                            (26 - 1) *
+                                                            ATP_XFACT - 1,
+                                                            ATP_FUZZ, 0);
+                               break;
+                       }
 
-               /* 17" Powerbooks have extra X sensors */
-               for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
-                    i < ATP_XSENSORS; i++) {
-                       if (!dev->xy_cur[i])
-                               continue;
-
-                       printk(KERN_INFO "appletouch: 17\" model detected.\n");
-                       if (dev->type == ATP_GEYSER2)
-                               input_set_abs_params(dev->input, ABS_X, 0,
-                                                    (20 - 1) *
-                                                    ATP_XFACT - 1,
-                                                    ATP_FUZZ, 0);
-                       else
-                               input_set_abs_params(dev->input, ABS_X, 0,
-                                                    (ATP_XSENSORS - 1) *
-                                                    ATP_XFACT - 1,
-                                                    ATP_FUZZ, 0);
-                       break;
+                       dev->size_detect_done = 1;
+                       goto exit;
                }
-
-               dev->size_detect_done = 1;
-               goto exit;
        }
 
        for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb)
                              ATP_XFACT, &x_z, &x_f);
        y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
                              ATP_YFACT, &y_z, &y_f);
-       key = dev->data[dev->datalen - 1] & 1;
+       key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+
+       if (x && y) {
+               if (dev->x_old != -1) {
+                       x = (dev->x_old * 3 + x) >> 2;
+                       y = (dev->y_old * 3 + y) >> 2;
+                       dev->x_old = x;
+                       dev->y_old = y;
+
+                       if (debug > 1)
+                               printk(KERN_DEBUG "appletouch: "
+                                       "X: %3d Y: %3d Xz: %3d Yz: %3d\n",
+                                       x, y, x_z, y_z);
+
+                       input_report_key(dev->input, BTN_TOUCH, 1);
+                       input_report_abs(dev->input, ABS_X, x);
+                       input_report_abs(dev->input, ABS_Y, y);
+                       input_report_abs(dev->input, ABS_PRESSURE,
+                                        min(ATP_PRESSURE, x_z + y_z));
+                       atp_report_fingers(dev->input, max(x_f, y_f));
+               }
+               dev->x_old = x;
+               dev->y_old = y;
+
+       } else if (!x && !y) {
+
+               dev->x_old = dev->y_old = -1;
+               input_report_key(dev->input, BTN_TOUCH, 0);
+               input_report_abs(dev->input, ABS_PRESSURE, 0);
+               atp_report_fingers(dev->input, 0);
+
+               /* reset the accumulator on release */
+               memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+       }
+
+       input_report_key(dev->input, BTN_LEFT, key);
+       input_sync(dev->input);
+
+ exit:
+       retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+       if (retval)
+               err("atp_complete: usb_submit_urb failed with result %d",
+                   retval);
+}
+
+/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */
+
+static void atp_complete_geyser_3_4(struct urb *urb)
+{
+       int x, y, x_z, y_z, x_f, y_f;
+       int retval, i, j;
+       int key;
+       struct atp *dev = urb->context;
+       int status = atp_status_check(urb);
+
+       if (status == ATP_URB_STATUS_ERROR_FATAL)
+               return;
+       else if (status == ATP_URB_STATUS_ERROR)
+               goto exit;
+
+       /* Reorder the sensors values:
+        *
+        * The values are laid out like this:
+        * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
+        * '-' is an unused value.
+        */
+
+       /* read X values */
+       for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+               dev->xy_cur[i] = dev->data[j + 1];
+               dev->xy_cur[i + 1] = dev->data[j + 2];
+       }
+       /* read Y values */
+       for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+               dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
+               dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
+       }
+
+       dbg_dump("sample", dev->xy_cur);
+
+       /* Just update the base values (i.e. touchpad in untouched state) */
+       if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
+
+               dprintk(KERN_DEBUG "appletouch: updated base values\n");
+
+               memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+               goto exit;
+       }
+
+       for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+               /* calculate the change */
+               dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i];
+
+               /* this is a round-robin value, so couple with that */
+               if (dev->xy_acc[i] > 127)
+                       dev->xy_acc[i] -= 256;
+
+               if (dev->xy_acc[i] < -127)
+                       dev->xy_acc[i] += 256;
+
+               /* prevent down drifting */
+               if (dev->xy_acc[i] < 0)
+                       dev->xy_acc[i] = 0;
+       }
+
+       dbg_dump("accumulator", dev->xy_acc);
+
+       x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+                             ATP_XFACT, &x_z, &x_f);
+       y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+                             ATP_YFACT, &y_z, &y_f);
+       key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
 
        if (x && y) {
                if (dev->x_old != -1) {
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb)
        input_sync(dev->input);
 
        /*
-        * Many Geysers will continue to send packets continually after
+        * Geysers 3/4 will continue to send packets continually after
         * the first touch unless reinitialised. Do so if it's been
         * idle for a while in order to avoid waking the kernel up
-        * several hundred times a second. Re-initialization does not
-        * work on Fountain touchpads.
+        * several hundred times a second.
         */
-       if (dev->type != ATP_FOUNTAIN) {
-               /*
-                * Button must not be pressed when entering suspend,
-                * otherwise we will never release the button.
-                */
-               if (!x && !y && !key) {
-                       dev->idlecount++;
-                       if (dev->idlecount == 10) {
-                               dev->valid = false;
-                               schedule_work(&dev->work);
-                               /* Don't resubmit urb here, wait for reinit */
-                               return;
-                       }
-               } else
+
+       /*
+        * Button must not be pressed when entering suspend,
+        * otherwise we will never release the button.
+        */
+       if (!x && !y && !key) {
+               dev->idlecount++;
+               if (dev->idlecount == 10) {
+                       dev->x_old = dev->y_old = -1;
                        dev->idlecount = 0;
-       }
+                       schedule_work(&dev->work);
+                       /* Don't resubmit urb here, wait for reinit */
+                       return;
+               }
+       } else
+               dev->idlecount = 0;
 
  exit:
        retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface,
        if (!dev->data)
                goto err_free_urb;
 
-       usb_fill_int_urb(dev->urb, udev,
-                        usb_rcvintpipe(udev, int_in_endpointAddr),
-                        dev->data, dev->datalen, atp_complete, dev, 1);
+       /* Select the USB complete (callback) function */
+       if (dev->type == ATP_FOUNTAIN ||
+           dev->type == ATP_GEYSER1 ||
+           dev->type == ATP_GEYSER2)
+               usb_fill_int_urb(dev->urb, udev,
+                                usb_rcvintpipe(udev, int_in_endpointAddr),
+                                dev->data, dev->datalen,
+                                atp_complete_geyser_1_2, dev, 1);
+       else
+               usb_fill_int_urb(dev->urb, udev,
+                                usb_rcvintpipe(udev, int_in_endpointAddr),
+                                dev->data, dev->datalen,
+                                atp_complete_geyser_3_4, dev, 1);
 
        error = atp_handle_geyser(dev);
        if (error)
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message)
        struct atp *dev = usb_get_intfdata(iface);
 
        usb_kill_urb(dev->urb);
-       dev->valid = false;
-
        return 0;
 }
 
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
new file mode 100644 (file)
index 0000000..e82d342
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
+ *
+ * Copyright (c) 2006-2008 One Laptop Per Child
+ * Authors:
+ *   Zephaniah E. Hull
+ *   Andres Salomon <dilinger@debian.org>
+ *
+ * This driver is partly based on the ALPS driver, which is:
+ *
+ * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
+ * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The spec from ALPS is available from
+ * <http://wiki.laptop.org/go/Touch_Pad/Tablet>.  It refers to this
+ * device as HGPK (Hybrid GS, PT, and Keymatrix).
+ *
+ * The earliest versions of the device had simultaneous reporting; that
+ * was removed.  After that, the device used the Advanced Mode GS/PT streaming
+ * stuff.  That turned out to be too buggy to support, so we've finally
+ * switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
+ */
+
+#define DEBUG
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+#include <linux/delay.h>
+#include <asm/olpc.h>
+
+#include "psmouse.h"
+#include "hgpk.h"
+
+static int tpdebug;
+module_param(tpdebug, int, 0644);
+MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG.");
+
+static int recalib_delta = 100;
+module_param(recalib_delta, int, 0644);
+MODULE_PARM_DESC(recalib_delta,
+       "packets containing a delta this large will cause a recalibration.");
+
+/*
+ * When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
+ * above the pad and still have it send packets.  This causes a jump cursor
+ * when one places their finger on the pad.  We can probably detect the
+ * jump as we see a large deltas (>= 100px).  In mouse mode, I've been
+ * unable to even come close to 100px deltas during normal usage, so I think
+ * this threshold is safe.  If a large delta occurs, trigger a recalibration.
+ */
+static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
+{
+       struct hgpk_data *priv = psmouse->private;
+
+       if (abs(x) > recalib_delta || abs(y) > recalib_delta) {
+               hgpk_err(psmouse, ">%dpx jump detected (%d,%d)\n",
+                               recalib_delta, x, y);
+               /* My car gets forty rods to the hogshead and that's the
+                * way I likes it! */
+               psmouse_queue_work(psmouse, &priv->recalib_wq,
+                               msecs_to_jiffies(1000));
+       }
+}
+
+/*
+ * We have no idea why this particular hardware bug occurs.  The touchpad
+ * will randomly start spewing packets without anything touching the
+ * pad.  This wouldn't necessarily be bad, but it's indicative of a
+ * severely miscalibrated pad; attempting to use the touchpad while it's
+ * spewing means the cursor will jump all over the place, and act "drunk".
+ *
+ * The packets that are spewed tend to all have deltas between -2 and 2, and
+ * the cursor will move around without really going very far.  It will
+ * tend to end up in the same location; if we tally up the changes over
+ * 100 packets, we end up w/ a final delta of close to 0.  This happens
+ * pretty regularly when the touchpad is spewing, and is pretty hard to
+ * manually trigger (at least for *my* fingers).  So, it makes a perfect
+ * scheme for detecting spews.
+ */
+static void hgpk_spewing_hack(struct psmouse *psmouse,
+                             int l, int r, int x, int y)
+{
+       struct hgpk_data *priv = psmouse->private;
+
+       /* ignore button press packets; many in a row could trigger
+        * a false-positive! */
+       if (l || r)
+               return;
+
+       priv->x_tally += x;
+       priv->y_tally += y;
+
+       if (++priv->count > 100) {
+               if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) {
+                       hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n",
+                                priv->x_tally, priv->y_tally);
+                       psmouse_queue_work(psmouse, &priv->recalib_wq,
+                                          msecs_to_jiffies(1000));
+               }
+               /* reset every 100 packets */
+               priv->count = 0;
+               priv->x_tally = 0;
+               priv->y_tally = 0;
+       }
+}
+
+/*
+ * HGPK Mouse Mode format (standard mouse format, sans middle button)
+ *
+ * byte 0:     y-over  x-over  y-neg   x-neg   1       0       swr     swl
+ * byte 1:     x7      x6      x5      x4      x3      x2      x1      x0
+ * byte 2:     y7      y6      y5      y4      y3      y2      y1      y0
+ *
+ * swr/swl are the left/right buttons.
+ * x-neg/y-neg are the x and y delta negative bits
+ * x-over/y-over are the x and y overflow bits
+ */
+static int hgpk_validate_byte(unsigned char *packet)
+{
+       return (packet[0] & 0x0C) == 0x08;
+}
+
+static void hgpk_process_packet(struct psmouse *psmouse)
+{
+       struct input_dev *dev = psmouse->dev;
+       unsigned char *packet = psmouse->packet;
+       int x, y, left, right;
+
+       left = packet[0] & 1;
+       right = (packet[0] >> 1) & 1;
+
+       x = packet[1] - ((packet[0] << 4) & 0x100);
+       y = ((packet[0] << 3) & 0x100) - packet[2];
+
+       hgpk_jumpy_hack(psmouse, x, y);
+       hgpk_spewing_hack(psmouse, left, right, x, y);
+
+       if (tpdebug)
+               hgpk_dbg(psmouse, "l=%d r=%d x=%d y=%d\n", left, right, x, y);
+
+       input_report_key(dev, BTN_LEFT, left);
+       input_report_key(dev, BTN_RIGHT, right);
+
+       input_report_rel(dev, REL_X, x);
+       input_report_rel(dev, REL_Y, y);
+
+       input_sync(dev);
+}
+
+static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
+{
+       struct hgpk_data *priv = psmouse->private;
+
+       if (hgpk_validate_byte(psmouse->packet)) {
+               hgpk_dbg(psmouse, "%s: (%d) %02x %02x %02x\n",
+                               __func__, psmouse->pktcnt, psmouse->packet[0],
+                               psmouse->packet[1], psmouse->packet[2]);
+               return PSMOUSE_BAD_DATA;
+       }
+
+       if (psmouse->pktcnt >= psmouse->pktsize) {
+               hgpk_process_packet(psmouse);
+               return PSMOUSE_FULL_PACKET;
+       }
+
+       if (priv->recalib_window) {
+               if (time_before(jiffies, priv->recalib_window)) {
+                       /*
+                        * ugh, got a packet inside our recalibration
+                        * window, schedule another recalibration.
+                        */
+                       hgpk_dbg(psmouse,
+                                "packet inside calibration window, "
+                                "queueing another recalibration\n");
+                       psmouse_queue_work(psmouse, &priv->recalib_wq,
+                                       msecs_to_jiffies(1000));
+               }
+               priv->recalib_window = 0;
+       }
+
+       return PSMOUSE_GOOD_DATA;
+}
+
+static int hgpk_force_recalibrate(struct psmouse *psmouse)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       struct hgpk_data *priv = psmouse->private;
+
+       /* C-series touchpads added the recalibrate command */
+       if (psmouse->model < HGPK_MODEL_C)
+               return 0;
+
+       /* we don't want to race with the irq handler, nor with resyncs */
+       psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+       /* start by resetting the device */
+       psmouse_reset(psmouse);
+
+       /* send the recalibrate request */
+       if (ps2_command(ps2dev, NULL, 0xf5) ||
+           ps2_command(ps2dev, NULL, 0xf5) ||
+           ps2_command(ps2dev, NULL, 0xe6) ||
+           ps2_command(ps2dev, NULL, 0xf5)) {
+               return -1;
+       }
+
+       /* according to ALPS, 150mS is required for recalibration */
+       msleep(150);
+
+       /* XXX: If a finger is down during this delay, recalibration will
+        * detect capacitance incorrectly.  This is a hardware bug, and
+        * we don't have a good way to deal with it.  The 2s window stuff
+        * (below) is our best option for now.
+        */
+
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+               return -1;
+
+       psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+       /* After we recalibrate, we shouldn't get any packets for 2s.  If
+        * we do, it's likely that someone's finger was on the touchpad.
+        * If someone's finger *was* on the touchpad, it's probably
+        * miscalibrated.  So, we should schedule another recalibration
+        */
+       priv->recalib_window = jiffies +  msecs_to_jiffies(2000);
+
+       return 0;
+}
+
+/*
+ * This kills power to the touchpad; according to ALPS, current consumption
+ * goes down to 50uA after running this.  To turn power back on, we drive
+ * MS-DAT low.
+ */
+static int hgpk_toggle_power(struct psmouse *psmouse, int enable)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       int timeo;
+
+       /* Added on D-series touchpads */
+       if (psmouse->model < HGPK_MODEL_D)
+               return 0;
+
+       if (enable) {
+               psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
+               /*
+                * Sending a byte will drive MS-DAT low; this will wake up
+                * the controller.  Once we get an ACK back from it, it
+                * means we can continue with the touchpad re-init.  ALPS
+                * tells us that 1s should be long enough, so set that as
+                * the upper bound.
+                */
+               for (timeo = 20; timeo > 0; timeo--) {
+                       if (!ps2_sendbyte(&psmouse->ps2dev,
+                                       PSMOUSE_CMD_DISABLE, 20))
+                               break;
+                       msleep(50);
+               }
+
+               psmouse_reset(psmouse);
+
+               /* should be all set, enable the touchpad */
+               ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+               psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+       } else {
+               hgpk_dbg(psmouse, "Powering off touchpad.\n");
+               psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+
+               if (ps2_command(ps2dev, NULL, 0xec) ||
+                   ps2_command(ps2dev, NULL, 0xec) ||
+                   ps2_command(ps2dev, NULL, 0xea)) {
+                       return -1;
+               }
+
+               /* probably won't see an ACK, the touchpad will be off */
+               ps2_sendbyte(&psmouse->ps2dev, 0xec, 20);
+       }
+
+       return 0;
+}
+
+static int hgpk_poll(struct psmouse *psmouse)
+{
+       /* We can't poll, so always return failure. */
+       return -1;
+}
+
+static int hgpk_reconnect(struct psmouse *psmouse)
+{
+       /* During suspend/resume the ps2 rails remain powered.  We don't want
+        * to do a reset because it's flush data out of buffers; however,
+        * earlier prototypes (B1) had some brokenness that required a reset. */
+       if (olpc_board_at_least(olpc_board(0xb2)))
+               if (psmouse->ps2dev.serio->dev.power.power_state.event !=
+                               PM_EVENT_ON)
+                       return 0;
+
+       psmouse_reset(psmouse);
+
+       return 0;
+}
+
+static ssize_t hgpk_show_powered(struct psmouse *psmouse, void *data, char *buf)
+{
+       struct hgpk_data *priv = psmouse->private;
+
+       return sprintf(buf, "%d\n", priv->powered);
+}
+
+static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
+                               const char *buf, size_t count)
+{
+       struct hgpk_data *priv = psmouse->private;
+       unsigned long value;
+       int err;
+
+       err = strict_strtoul(buf, 10, &value);
+       if (err || value > 1)
+               return -EINVAL;
+
+       if (value != priv->powered) {
+               /*
+                * hgpk_toggle_power will deal w/ state so
+                * we're not racing w/ irq
+                */
+               err = hgpk_toggle_power(psmouse, value);
+               if (!err)
+                       priv->powered = value;
+       }
+
+       return err ? err : count;
+}
+
+__PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL,
+                     hgpk_show_powered, hgpk_set_powered, 0);
+
+static void hgpk_disconnect(struct psmouse *psmouse)
+{
+       struct hgpk_data *priv = psmouse->private;
+
+       device_remove_file(&psmouse->ps2dev.serio->dev,
+                          &psmouse_attr_powered.dattr);
+       psmouse_reset(psmouse);
+       kfree(priv);
+}
+
+static void hgpk_recalib_work(struct work_struct *work)
+{
+       struct delayed_work *w = container_of(work, struct delayed_work, work);
+       struct hgpk_data *priv = container_of(w, struct hgpk_data, recalib_wq);
+       struct psmouse *psmouse = priv->psmouse;
+
+       hgpk_dbg(psmouse, "recalibrating touchpad..\n");
+
+       if (hgpk_force_recalibrate(psmouse))
+               hgpk_err(psmouse, "recalibration failed!\n");
+}
+
+static int hgpk_register(struct psmouse *psmouse)
+{
+       struct input_dev *dev = psmouse->dev;
+       int err;
+
+       /* unset the things that psmouse-base sets which we don't have */
+       __clear_bit(BTN_MIDDLE, dev->keybit);
+
+       /* set the things we do have */
+       __set_bit(EV_KEY, dev->evbit);
+       __set_bit(EV_REL, dev->evbit);
+
+       __set_bit(REL_X, dev->relbit);
+       __set_bit(REL_Y, dev->relbit);
+
+       __set_bit(BTN_LEFT, dev->keybit);
+       __set_bit(BTN_RIGHT, dev->keybit);
+
+       /* register handlers */
+       psmouse->protocol_handler = hgpk_process_byte;
+       psmouse->poll = hgpk_poll;
+       psmouse->disconnect = hgpk_disconnect;
+       psmouse->reconnect = hgpk_reconnect;
+       psmouse->pktsize = 3;
+
+       /* Disable the idle resync. */
+       psmouse->resync_time = 0;
+       /* Reset after a lot of bad bytes. */
+       psmouse->resetafter = 1024;
+
+       err = device_create_file(&psmouse->ps2dev.serio->dev,
+                                &psmouse_attr_powered.dattr);
+       if (err)
+               hgpk_err(psmouse, "Failed to create sysfs attribute\n");
+
+       return err;
+}
+
+int hgpk_init(struct psmouse *psmouse)
+{
+       struct hgpk_data *priv;
+       int err = -ENOMEM;
+
+       priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL);
+       if (!priv)
+               goto alloc_fail;
+
+       psmouse->private = priv;
+       priv->psmouse = psmouse;
+       priv->powered = 1;
+       INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work);
+
+       err = psmouse_reset(psmouse);
+       if (err)
+               goto init_fail;
+
+       err = hgpk_register(psmouse);
+       if (err)
+               goto init_fail;
+
+       return 0;
+
+init_fail:
+       kfree(priv);
+alloc_fail:
+       return err;
+}
+
+static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char param[3];
+
+       /* E7, E7, E7, E9 gets us a 3 byte identifier */
+       if (ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
+           ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
+           ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
+           ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
+               return -EIO;
+       }
+
+       hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]);
+
+       /* HGPK signature: 0x67, 0x00, 0x<model> */
+       if (param[0] != 0x67 || param[1] != 0x00)
+               return -ENODEV;
+
+       hgpk_info(psmouse, "OLPC touchpad revision 0x%x\n", param[2]);
+
+       return param[2];
+}
+
+int hgpk_detect(struct psmouse *psmouse, int set_properties)
+{
+       int version;
+
+       version = hgpk_get_model(psmouse);
+       if (version < 0)
+               return version;
+
+       if (set_properties) {
+               psmouse->vendor = "ALPS";
+               psmouse->name = "HGPK";
+               psmouse->model = version;
+       }
+
+       return 0;
+}
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h
new file mode 100644 (file)
index 0000000..a4b2a96
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * OLPC HGPK (XO-1) touchpad PS/2 mouse driver
+ */
+
+#ifndef _HGPK_H
+#define _HGPK_H
+
+enum hgpk_model_t {
+       HGPK_MODEL_PREA = 0x0a, /* pre-B1s */
+       HGPK_MODEL_A = 0x14,    /* found on B1s, PT disabled in hardware */
+       HGPK_MODEL_B = 0x28,    /* B2s, has capacitance issues */
+       HGPK_MODEL_C = 0x3c,
+       HGPK_MODEL_D = 0x50,    /* C1, mass production */
+};
+
+struct hgpk_data {
+       struct psmouse *psmouse;
+       int powered;
+       int count, x_tally, y_tally;    /* hardware workaround stuff */
+       unsigned long recalib_window;
+       struct delayed_work recalib_wq;
+};
+
+#define hgpk_dbg(psmouse, format, arg...)              \
+       dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_err(psmouse, format, arg...)              \
+       dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_info(psmouse, format, arg...)             \
+       dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_warn(psmouse, format, arg...)             \
+       dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+#define hgpk_notice(psmouse, format, arg...)           \
+       dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
+
+#ifdef CONFIG_MOUSE_PS2_OLPC
+int hgpk_detect(struct psmouse *psmouse, int set_properties);
+int hgpk_init(struct psmouse *psmouse);
+#else
+static inline int hgpk_detect(struct psmouse *psmouse, int set_properties)
+{
+       return -ENODEV;
+}
+static inline int hgpk_init(struct psmouse *psmouse)
+{
+       return -ENODEV;
+}
+#endif
+
+#endif
index 0c5660d28caa18bafb5d3ab62a9219f3fc1c96ec..390f1dbb98a482d855154119fa45ff52f3ea6bca 100644 (file)
@@ -157,10 +157,8 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data,
 static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        ps2pp_set_smartscroll(psmouse, value);
index f5a6be1d3c46325b2173ff00e2588a9de9ca5d81..126e977e199e00764d3f2ab32aafbd0e26fbe7e8 100644 (file)
@@ -25,6 +25,7 @@
 #include "synaptics.h"
 #include "logips2pp.h"
 #include "alps.h"
+#include "hgpk.h"
 #include "lifebook.h"
 #include "trackpoint.h"
 #include "touchkit_ps2.h"
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
        return PSMOUSE_FULL_PACKET;
 }
 
+void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
+               unsigned long delay)
+{
+       queue_delayed_work(kpsmoused_wq, work, delay);
+}
+
 /*
  * __psmouse_set_state() sets new psmouse state and resets all flags.
  */
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
  * is not a concern.
  */
 
-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
 {
        serio_pause_rx(psmouse->ps2dev.serio);
        __psmouse_set_state(psmouse, new_state);
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
                       psmouse->name, psmouse->phys, psmouse->pktcnt);
                psmouse->badbyte = psmouse->packet[0];
                __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
-               queue_work(kpsmoused_wq, &psmouse->resync_work);
+               psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
                goto out;
        }
 
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
            time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
                psmouse->badbyte = psmouse->packet[0];
                __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
-               queue_work(kpsmoused_wq, &psmouse->resync_work);
+               psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
                goto out;
        }
 
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
                }
        }
 
-       if (max_proto > PSMOUSE_IMEX) {
+/*
+ * Try OLPC HGPK touchpad.
+ */
+       if (max_proto > PSMOUSE_IMEX &&
+                       hgpk_detect(psmouse, set_properties) == 0) {
+               if (!set_properties || hgpk_init(psmouse) == 0)
+                       return PSMOUSE_HGPK;
+/*
+ * Init failed, try basic relative protocols
+ */
+               max_proto = PSMOUSE_IMEX;
+       }
 
+       if (max_proto > PSMOUSE_IMEX) {
                if (genius_detect(psmouse, set_properties) == 0)
                        return PSMOUSE_GENPS;
 
@@ -761,6 +780,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .alias          = "touchkit",
                .detect         = touchkit_ps2_detect,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_OLPC
+       {
+               .type           = PSMOUSE_HGPK,
+               .name           = "OLPC HGPK",
+               .alias          = "hgpk",
+               .detect         = hgpk_detect,
+       },
 #endif
        {
                .type           = PSMOUSE_CORTRON,
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse)
 static void psmouse_resync(struct work_struct *work)
 {
        struct psmouse *parent = NULL, *psmouse =
-               container_of(work, struct psmouse, resync_work);
+               container_of(work, struct psmouse, resync_work.work);
        struct serio *serio = psmouse->ps2dev.serio;
        psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
        int failed = 0, enabled = 0;
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
                goto err_free;
 
        ps2_init(&psmouse->ps2dev, serio);
-       INIT_WORK(&psmouse->resync_work, psmouse_resync);
+       INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
        psmouse->dev = input_dev;
        snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
 
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
 
        psmouse = serio_get_drvdata(serio);
 
-       if (psmouse->state == PSMOUSE_IGNORE) {
-               retval = -ENODEV;
-               goto out_unlock;
-       }
+       if (attr->protect) {
+               if (psmouse->state == PSMOUSE_IGNORE) {
+                       retval = -ENODEV;
+                       goto out_unlock;
+               }
 
-       if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
-               parent = serio_get_drvdata(serio->parent);
-               psmouse_deactivate(parent);
-       }
+               if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+                       parent = serio_get_drvdata(serio->parent);
+                       psmouse_deactivate(parent);
+               }
 
-       psmouse_deactivate(psmouse);
+               psmouse_deactivate(psmouse);
+       }
 
        retval = attr->set(psmouse, attr->data, buf, count);
 
-       if (retval != -ENODEV)
-               psmouse_activate(psmouse);
+       if (attr->protect) {
+               if (retval != -ENODEV)
+                       psmouse_activate(psmouse);
 
-       if (parent)
-               psmouse_activate(parent);
+               if (parent)
+                       psmouse_activate(parent);
+       }
 
  out_unlock:
        mutex_unlock(&psmouse_mutex);
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
 {
        unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        if ((unsigned int)value != value)
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
 static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        psmouse->set_rate(psmouse, value);
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const
 static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
+       if (strict_strtoul(buf, 10, &value))
                return -EINVAL;
 
        psmouse->set_resolution(psmouse, value);
index 1317bdd8cc7c42c935fac9899c5bdcbda0a5a51b..8b608a1cdd12171135f3ca2ec0c7a6487728711a 100644 (file)
@@ -39,7 +39,7 @@ struct psmouse {
        void *private;
        struct input_dev *dev;
        struct ps2dev ps2dev;
-       struct work_struct resync_work;
+       struct delayed_work resync_work;
        char *vendor;
        char *name;
        unsigned char packet[8];
@@ -89,20 +89,24 @@ enum psmouse_type {
        PSMOUSE_TRACKPOINT,
        PSMOUSE_TOUCHKIT_PS2,
        PSMOUSE_CORTRON,
+       PSMOUSE_HGPK,
        PSMOUSE_AUTO            /* This one should always be last */
 };
 
+void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
+               unsigned long delay);
 int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
 int psmouse_reset(struct psmouse *psmouse);
+void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
 
-
 struct psmouse_attribute {
        struct device_attribute dattr;
        void *data;
        ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
        ssize_t (*set)(struct psmouse *psmouse, void *data,
                        const char *buf, size_t count);
+       int protect;
 };
 #define to_psmouse_attr(a)     container_of((a), struct psmouse_attribute, dattr)
 
@@ -111,7 +115,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at
 ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
                                const char *buf, size_t count);
 
-#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set)                  \
+#define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect)      \
 static ssize_t _show(struct psmouse *, void *data, char *);                    \
 static ssize_t _set(struct psmouse *, void *data, const char *, size_t);       \
 static struct psmouse_attribute psmouse_attr_##_name = {                       \
@@ -126,6 +130,10 @@ static struct psmouse_attribute psmouse_attr_##_name = {                   \
        .data   = _data,                                                        \
        .show   = _show,                                                        \
        .set    = _set,                                                         \
+       .protect = _protect,                                                    \
 }
 
+#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set)  \
+               __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1)
+
 #endif /* _PSMOUSE_H */
index 26b845fc186ab7557635d6eafe59c7970c3507cc..e68c814c43612f449d4b9976a1cc45fbb7445efd 100644 (file)
@@ -89,10 +89,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
        struct trackpoint_attr_data *attr = data;
        unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 255)
+       if (strict_strtoul(buf, 10, &value) || value > 255)
                return -EINVAL;
 
        *field = value;
@@ -117,10 +115,8 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
        struct trackpoint_attr_data *attr = data;
        unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
        unsigned long value;
-       char *rest;
 
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest || value > 1)
+       if (strict_strtoul(buf, 10, &value) || value > 1)
                return -EINVAL;
 
        if (attr->inverted)
index 0d395979b2d19c2a35ddb31e6d8c915c363fcfd9..bfe49243f38bf571d5d99e2f36c3d42b569ea6f3 100644 (file)
@@ -323,7 +323,7 @@ static void hp_sdc_tasklet(unsigned long foo)
                         * it back to the application. and be less verbose.
                         */
                        printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
-                              tv.tv_usec - hp_sdc.rtv.tv_usec);
+                              (int)(tv.tv_usec - hp_sdc.rtv.tv_usec));
                        curr->idx += hp_sdc.rqty;
                        hp_sdc.rqty = 0;
                        tmp = curr->seq[curr->actidx];
index f451c7351a9da1b0614e1e04412f65e07116a37c..847f4aad7ed560f2c5d9b91f8ba34079b6c99d7c 100644 (file)
@@ -67,7 +67,7 @@ static inline int i8042_platform_init(void)
  * On some platforms touching the i8042 data register region can do really
  * bad things. Because of this the region is always reserved on such boxes.
  */
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
        if (check_legacy_ioport(I8042_DATA_REG))
                return -ENODEV;
 #endif
index 5aafe24984c598236efdd54dde31e8db9ec6cc60..a321aea2c7b5f4dad1a9822539d2b3abb7700dfc 100644 (file)
@@ -322,6 +322,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
                },
        },
+       {
+               .ident = "IBM 2656",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
+               },
+       },
        { }
 };
 
index c9397c8ee97e8ea44c4f0edc4a6172bd022178ac..470770c09260334fd79c664c2a484ed0384a9f93 100644 (file)
@@ -373,6 +373,12 @@ static struct serio_device_id serio_raw_serio_ids[] = {
                .id     = SERIO_ANY,
                .extra  = SERIO_ANY,
        },
+       {
+               .type   = SERIO_8042_XL,
+               .proto  = SERIO_ANY,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
        { 0 }
 };
 
index 8f037a1d44a63be7586b0ac5f6309522437b290b..e53c838f1866cb69ddc33d2b9def78430777529e 100644 (file)
@@ -1202,16 +1202,22 @@ static ssize_t
 store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct aiptek *aiptek = dev_get_drvdata(dev);
-       int x;
+       long x;
+
+       if (strict_strtol(buf, 10, &x)) {
+               size_t len = buf[count - 1] == '\n' ? count - 1 : count;
+
+               if (strncmp(buf, "disable", len))
+                       return -EINVAL;
 
-       if (strcmp(buf, "disable") == 0) {
                aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
        } else {
-               x = (int)simple_strtol(buf, NULL, 10);
-               if (x >= AIPTEK_TILT_MIN && x <= AIPTEK_TILT_MAX) {
-                       aiptek->newSetting.xTilt = x;
-               }
+               if (x < AIPTEK_TILT_MIN || x > AIPTEK_TILT_MAX)
+                       return -EINVAL;
+
+               aiptek->newSetting.xTilt = x;
        }
+
        return count;
 }
 
@@ -1238,16 +1244,22 @@ static ssize_t
 store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct aiptek *aiptek = dev_get_drvdata(dev);
-       int y;
+       long y;
+
+       if (strict_strtol(buf, 10, &y)) {
+               size_t len = buf[count - 1] == '\n' ? count - 1 : count;
+
+               if (strncmp(buf, "disable", len))
+                       return -EINVAL;
 
-       if (strcmp(buf, "disable") == 0) {
                aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
        } else {
-               y = (int)simple_strtol(buf, NULL, 10);
-               if (y >= AIPTEK_TILT_MIN && y <= AIPTEK_TILT_MAX) {
-                       aiptek->newSetting.yTilt = y;
-               }
+               if (y < AIPTEK_TILT_MIN || y > AIPTEK_TILT_MAX)
+                       return -EINVAL;
+
+               aiptek->newSetting.yTilt = y;
        }
+
        return count;
 }
 
@@ -1269,8 +1281,12 @@ static ssize_t
 store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct aiptek *aiptek = dev_get_drvdata(dev);
+       long j;
+
+       if (strict_strtol(buf, 10, &j))
+               return -EINVAL;
 
-       aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
+       aiptek->newSetting.jitterDelay = (int)j;
        return count;
 }
 
@@ -1294,8 +1310,12 @@ static ssize_t
 store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct aiptek *aiptek = dev_get_drvdata(dev);
+       long d;
 
-       aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
+       if (strict_strtol(buf, 10, &d))
+               return -EINVAL;
+
+       aiptek->newSetting.programmableDelay = (int)d;
        return count;
 }
 
@@ -1541,8 +1561,11 @@ static ssize_t
 store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct aiptek *aiptek = dev_get_drvdata(dev);
+       long w;
+
+       if (strict_strtol(buf, 10, &w)) return -EINVAL;
 
-       aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
+       aiptek->newSetting.wheel = (int)w;
        return count;
 }
 
index 8583c766d565201e224fb21abaedd6c9cb8cadb8..b9b7fc6ff1ebcc657370701e9dcc53d3ce20bfdb 100644 (file)
@@ -69,6 +69,17 @@ struct ts_event {
        int     ignore;
 };
 
+/*
+ * We allocate this separately to avoid cache line sharing issues when
+ * driver is used with DMA-based SPI controllers (like atmel_spi) on
+ * systems where main memory is not DMA-coherent (most non-x86 boards).
+ */
+struct ads7846_packet {
+       u8                      read_x, read_y, read_z1, read_z2, pwrdown;
+       u16                     dummy;          /* for the pwrdown read */
+       struct ts_event         tc;
+};
+
 struct ads7846 {
        struct input_dev        *input;
        char                    phys[32];
@@ -86,9 +97,7 @@ struct ads7846 {
        u16                     x_plate_ohms;
        u16                     pressure_max;
 
-       u8                      read_x, read_y, read_z1, read_z2, pwrdown;
-       u16                     dummy;          /* for the pwrdown read */
-       struct ts_event         tc;
+       struct ads7846_packet   *packet;
 
        struct spi_transfer     xfer[18];
        struct spi_message      msg[5];
@@ -463,10 +472,11 @@ static ssize_t ads7846_disable_store(struct device *dev,
                                     const char *buf, size_t count)
 {
        struct ads7846 *ts = dev_get_drvdata(dev);
-       char *endp;
-       int i;
+       long i;
+
+       if (strict_strtoul(buf, 10, &i))
+               return -EINVAL;
 
-       i = simple_strtoul(buf, &endp, 10);
        spin_lock_irq(&ts->lock);
 
        if (i)
@@ -512,16 +522,17 @@ static int get_pendown_state(struct ads7846 *ts)
 static void ads7846_rx(void *ads)
 {
        struct ads7846          *ts = ads;
+       struct ads7846_packet   *packet = ts->packet;
        unsigned                Rt;
        u16                     x, y, z1, z2;
 
        /* ads7846_rx_val() did in-place conversion (including byteswap) from
         * on-the-wire format as part of debouncing to get stable readings.
         */
-       x = ts->tc.x;
-       y = ts->tc.y;
-       z1 = ts->tc.z1;
-       z2 = ts->tc.z2;
+       x = packet->tc.x;
+       y = packet->tc.y;
+       z1 = packet->tc.z1;
+       z2 = packet->tc.z2;
 
        /* range filtering */
        if (x == MAX_12BIT)
@@ -545,10 +556,10 @@ static void ads7846_rx(void *ads)
         * the maximum. Don't report it to user space, repeat at least
         * once more the measurement
         */
-       if (ts->tc.ignore || Rt > ts->pressure_max) {
+       if (packet->tc.ignore || Rt > ts->pressure_max) {
 #ifdef VERBOSE
                pr_debug("%s: ignored %d pressure %d\n",
-                       ts->spi->dev.bus_id, ts->tc.ignore, Rt);
+                       ts->spi->dev.bus_id, packet->tc.ignore, Rt);
 #endif
                hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
                              HRTIMER_MODE_REL);
@@ -641,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)
 static void ads7846_rx_val(void *ads)
 {
        struct ads7846 *ts = ads;
+       struct ads7846_packet *packet = ts->packet;
        struct spi_message *m;
        struct spi_transfer *t;
        int val;
@@ -660,7 +672,7 @@ static void ads7846_rx_val(void *ads)
        case ADS7846_FILTER_REPEAT:
                break;
        case ADS7846_FILTER_IGNORE:
-               ts->tc.ignore = 1;
+               packet->tc.ignore = 1;
                /* Last message will contain ads7846_rx() as the
                 * completion function.
                 */
@@ -668,7 +680,7 @@ static void ads7846_rx_val(void *ads)
                break;
        case ADS7846_FILTER_OK:
                *(u16 *)t->rx_buf = val;
-               ts->tc.ignore = 0;
+               packet->tc.ignore = 0;
                m = &ts->msg[++ts->msg_idx];
                break;
        default:
@@ -773,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts)
        /* we know the chip's in lowpower mode since we always
         * leave it that way after every request
         */
-
 }
 
 /* Must be called with ts->lock held */
@@ -849,6 +860,7 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 static int __devinit ads7846_probe(struct spi_device *spi)
 {
        struct ads7846                  *ts;
+       struct ads7846_packet           *packet;
        struct input_dev                *input_dev;
        struct ads7846_platform_data    *pdata = spi->dev.platform_data;
        struct spi_message              *m;
@@ -884,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                return err;
 
        ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+       packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!ts || !input_dev) {
+       if (!ts || !packet || !input_dev) {
                err = -ENOMEM;
                goto err_free_mem;
        }
 
        dev_set_drvdata(&spi->dev, ts);
 
+       ts->packet = packet;
        ts->spi = spi;
        ts->input = input_dev;
        ts->vref_mv = pdata->vref_mv;
@@ -963,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        spi_message_init(m);
 
        /* y- still on; turn on only y+ (and ADC) */
-       ts->read_y = READ_Y(vref);
-       x->tx_buf = &ts->read_y;
+       packet->read_y = READ_Y(vref);
+       x->tx_buf = &packet->read_y;
        x->len = 1;
        spi_message_add_tail(x, m);
 
        x++;
-       x->rx_buf = &ts->tc.y;
+       x->rx_buf = &packet->tc.y;
        x->len = 2;
        spi_message_add_tail(x, m);
 
@@ -981,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                x->delay_usecs = pdata->settle_delay_usecs;
 
                x++;
-               x->tx_buf = &ts->read_y;
+               x->tx_buf = &packet->read_y;
                x->len = 1;
                spi_message_add_tail(x, m);
 
                x++;
-               x->rx_buf = &ts->tc.y;
+               x->rx_buf = &packet->tc.y;
                x->len = 2;
                spi_message_add_tail(x, m);
        }
@@ -999,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        /* turn y- off, x+ on, then leave in lowpower */
        x++;
-       ts->read_x = READ_X(vref);
-       x->tx_buf = &ts->read_x;
+       packet->read_x = READ_X(vref);
+       x->tx_buf = &packet->read_x;
        x->len = 1;
        spi_message_add_tail(x, m);
 
        x++;
-       x->rx_buf = &ts->tc.x;
+       x->rx_buf = &packet->tc.x;
        x->len = 2;
        spi_message_add_tail(x, m);
 
@@ -1014,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                x->delay_usecs = pdata->settle_delay_usecs;
 
                x++;
-               x->tx_buf = &ts->read_x;
+               x->tx_buf = &packet->read_x;
                x->len = 1;
                spi_message_add_tail(x, m);
 
                x++;
-               x->rx_buf = &ts->tc.x;
+               x->rx_buf = &packet->tc.x;
                x->len = 2;
                spi_message_add_tail(x, m);
        }
@@ -1033,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_init(m);
 
                x++;
-               ts->read_z1 = READ_Z1(vref);
-               x->tx_buf = &ts->read_z1;
+               packet->read_z1 = READ_Z1(vref);
+               x->tx_buf = &packet->read_z1;
                x->len = 1;
                spi_message_add_tail(x, m);
 
                x++;
-               x->rx_buf = &ts->tc.z1;
+               x->rx_buf = &packet->tc.z1;
                x->len = 2;
                spi_message_add_tail(x, m);
 
@@ -1048,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        x->delay_usecs = pdata->settle_delay_usecs;
 
                        x++;
-                       x->tx_buf = &ts->read_z1;
+                       x->tx_buf = &packet->read_z1;
                        x->len = 1;
                        spi_message_add_tail(x, m);
 
                        x++;
-                       x->rx_buf = &ts->tc.z1;
+                       x->rx_buf = &packet->tc.z1;
                        x->len = 2;
                        spi_message_add_tail(x, m);
                }
@@ -1065,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_init(m);
 
                x++;
-               ts->read_z2 = READ_Z2(vref);
-               x->tx_buf = &ts->read_z2;
+               packet->read_z2 = READ_Z2(vref);
+               x->tx_buf = &packet->read_z2;
                x->len = 1;
                spi_message_add_tail(x, m);
 
                x++;
-               x->rx_buf = &ts->tc.z2;
+               x->rx_buf = &packet->tc.z2;
                x->len = 2;
                spi_message_add_tail(x, m);
 
@@ -1080,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        x->delay_usecs = pdata->settle_delay_usecs;
 
                        x++;
-                       x->tx_buf = &ts->read_z2;
+                       x->tx_buf = &packet->read_z2;
                        x->len = 1;
                        spi_message_add_tail(x, m);
 
                        x++;
-                       x->rx_buf = &ts->tc.z2;
+                       x->rx_buf = &packet->tc.z2;
                        x->len = 2;
                        spi_message_add_tail(x, m);
                }
@@ -1099,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        spi_message_init(m);
 
        x++;
-       ts->pwrdown = PWRDOWN;
-       x->tx_buf = &ts->pwrdown;
+       packet->pwrdown = PWRDOWN;
+       x->tx_buf = &packet->pwrdown;
        x->len = 1;
        spi_message_add_tail(x, m);
 
        x++;
-       x->rx_buf = &ts->dummy;
+       x->rx_buf = &packet->dummy;
        x->len = 2;
        CS_CHANGE(*x);
        spi_message_add_tail(x, m);
@@ -1158,6 +1172,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                ts->filter_cleanup(ts->filter_data);
  err_free_mem:
        input_free_device(input_dev);
+       kfree(packet);
        kfree(ts);
        return err;
 }
@@ -1183,6 +1198,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
        if (ts->filter_cleanup)
                ts->filter_cleanup(ts->filter_data);
 
+       kfree(ts->packet);
        kfree(ts);
 
        dev_dbg(&spi->dev, "unregistered touchscreen\n");
index eee126b19e8b53cc3a8949a3798df9cd13c6d402..a89a6a8f05e6c9631f7368fb2488e080490b6fe0 100644 (file)
@@ -91,6 +91,9 @@ struct atmel_tsadcc {
        char                    phys[32];
        struct clk              *clk;
        int                     irq;
+       unsigned int            prev_absx;
+       unsigned int            prev_absy;
+       unsigned char           bufferedmeasure;
 };
 
 static void __iomem            *tsc_base;
@@ -100,10 +103,9 @@ static void __iomem                *tsc_base;
 
 static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
 {
-       struct input_dev *input_dev = ((struct atmel_tsadcc *)dev)->input;
+       struct atmel_tsadcc     *ts_dev = (struct atmel_tsadcc *)dev;
+       struct input_dev        *input_dev = ts_dev->input;
 
-       unsigned int absx;
-       unsigned int absy;
        unsigned int status;
        unsigned int reg;
 
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
                atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
 
                input_report_key(input_dev, BTN_TOUCH, 0);
+               ts_dev->bufferedmeasure = 0;
                input_sync(input_dev);
 
        } else if (status & ATMEL_TSADCC_PENCNT) {
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
        } else if (status & ATMEL_TSADCC_EOC(3)) {
                /* Conversion finished */
 
-               absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
-               absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
-
-               absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
-               absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
-
-               input_report_abs(input_dev, ABS_X, absx);
-               input_report_abs(input_dev, ABS_Y, absy);
-               input_report_key(input_dev, BTN_TOUCH, 1);
-               input_sync(input_dev);
+               if (ts_dev->bufferedmeasure) {
+                       /* Last measurement is always discarded, since it can
+                        * be erroneous.
+                        * Always report previous measurement */
+                       input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
+                       input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
+                       input_report_key(input_dev, BTN_TOUCH, 1);
+                       input_sync(input_dev);
+               } else
+                       ts_dev->bufferedmeasure = 1;
+
+               /* Now make new measurement */
+               ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
+               ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
+
+               ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
+               ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
        }
 
        return IRQ_HANDLED;
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
        }
 
        ts_dev->input = input_dev;
+       ts_dev->bufferedmeasure = 0;
 
        snprintf(ts_dev->phys, sizeof(ts_dev->phys),
                 "%s/input0", pdev->dev.bus_id);
index 37a555f37306226ff0dae5495bfa45c733d297a2..ba648750a8d927db4a4cade7e2df61cca5348059 100644 (file)
@@ -3,8 +3,7 @@
  *                         Wolfson WM97xx AC97 Codecs.
  *
  * Copyright 2004, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  * Parts Copyright : Ian Molton <spyro@f2s.com>
  *                   Andrew Zabolotny <zap@homelink.ru>
  *
@@ -296,6 +295,6 @@ module_init(mainstone_wm97xx_init);
 module_exit(mainstone_wm97xx_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
 MODULE_LICENSE("GPL");
index 372efbc694ffbf7ebe71e96decefd71060e6d7c8..6b5be742c27dac15fd5b11734b2759638b8046f0 100644 (file)
@@ -2,8 +2,7 @@
  * wm9705.c  --  Codec driver for Wolfson WM9705 AC97 Codec.
  *
  * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  * Parts Copyright : Ian Molton <spyro@f2s.com>
  *                   Andrew Zabolotny <zap@homelink.ru>
  *                   Russell King <rmk@arm.linux.org.uk>
@@ -347,6 +346,6 @@ struct wm97xx_codec_drv wm9705_codec = {
 EXPORT_SYMBOL_GPL(wm9705_codec);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("WM9705 Touch Screen Driver");
 MODULE_LICENSE("GPL");
index c8bb1e7335fcf8f9450c0be194cafc9f014d03fb..7490b05c356651cf8aa6e2d0e1ee1b1621096cd6 100644 (file)
@@ -2,8 +2,7 @@
  * wm9712.c  --  Codec driver for Wolfson WM9712 AC97 Codecs.
  *
  * Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  * Parts Copyright : Ian Molton <spyro@f2s.com>
  *                   Andrew Zabolotny <zap@homelink.ru>
  *                   Russell King <rmk@arm.linux.org.uk>
@@ -462,6 +461,6 @@ struct wm97xx_codec_drv wm9712_codec = {
 EXPORT_SYMBOL_GPL(wm9712_codec);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("WM9712 Touch Screen Driver");
 MODULE_LICENSE("GPL");
index 781ee83547e68374eba1f253a016a26435135e27..238b5132712eef7b4986636b16ce78c070df15b0 100644 (file)
@@ -2,8 +2,7 @@
  * wm9713.c  --  Codec touch driver for Wolfson WM9713 AC97 Codec.
  *
  * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  * Parts Copyright : Ian Molton <spyro@f2s.com>
  *                   Andrew Zabolotny <zap@homelink.ru>
  *                   Russell King <rmk@arm.linux.org.uk>
@@ -476,6 +475,6 @@ struct wm97xx_codec_drv wm9713_codec = {
 EXPORT_SYMBOL_GPL(wm9713_codec);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("WM9713 Touch Screen Driver");
 MODULE_LICENSE("GPL");
index d589ab0e3adc41c0b75eb55c645937afdcdef843..d15aa11d705686adb89203e396577752d44c9cf3 100644 (file)
@@ -3,8 +3,7 @@
  *                    and WM9713 AC97 Codecs.
  *
  * Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  * Parts Copyright : Ian Molton <spyro@f2s.com>
  *                   Andrew Zabolotny <zap@homelink.ru>
  *                   Russell King <rmk@arm.linux.org.uk>
@@ -824,6 +823,6 @@ module_init(wm97xx_init);
 module_exit(wm97xx_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood <liam.girdwood@wolfsonmicro.com>");
+MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 MODULE_DESCRIPTION("WM97xx Core - Touch Screen / AUX ADC / GPIO Driver");
 MODULE_LICENSE("GPL");
index 871b0cbca5e4540299047294d02c40a20326345a..1b5bf87c4cf4719cd66e75575d3b97250e368e06 100644 (file)
@@ -1231,7 +1231,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
        int error = 0;
        switch (cmd) {
        default:
-               error = n_tty_ioctl (tty, file, cmd, arg);
+               error = n_tty_ioctl_helper(tty, file, cmd, arg);
                break;
        }
        return error;
@@ -1553,8 +1553,7 @@ static int __init capi_init(void)
                return PTR_ERR(capi_class);
        }
 
-       device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
-                             "capi");
+       device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
        if (capinc_tty_init() < 0) {
index 5e89fa177816f54b45bce84cf65ba3dd09f01b34..07052ed2a0c56d46480cb04c375df1afc3779d31 100644 (file)
@@ -571,6 +571,7 @@ gigaset_tty_close(struct tty_struct *tty)
        }
 
        /* prevent other callers from entering ldisc methods */
+       /* FIXME: should use the tty state flags */
        tty->disc_data = NULL;
 
        if (!cs->hw.ser)
@@ -642,10 +643,11 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
                return -ENXIO;
 
        switch (cmd) {
-       case TCGETS:
-       case TCGETA:
-               /* pass through to underlying serial device */
-               rc = n_tty_ioctl(tty, file, cmd, arg);
+
+       case FIONREAD:
+               /* unused, always return zero */
+               val = 0;
+               rc = put_user(val, p);
                break;
 
        case TCFLSH:
@@ -659,20 +661,13 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
                        flush_send_queue(cs);
                        break;
                }
-               /* flush the serial port's buffer */
-               rc = n_tty_ioctl(tty, file, cmd, arg);
-               break;
-
-       case FIONREAD:
-               /* unused, always return zero */
-               val = 0;
-               rc = put_user(val, p);
-               break;
+               /* Pass through */
 
        default:
-               rc = -ENOIOCTLCMD;
+               /* pass through to underlying serial device */
+               rc = n_tty_ioctl_helper(tty, file, cmd, arg);
+               break;
        }
-
        cs_put(cs);
        return rc;
 }
@@ -680,6 +675,8 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
 /*
  * Poll on the tty.
  * Unused, always return zero.
+ *
+ * FIXME: should probably return an exception - especially on hangup
  */
 static unsigned int
 gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
index a5b941c327f71477eecda3edb0f9b4c02acd4dda..c72565520e418cdad31796d9f310f4f103636117 100644 (file)
@@ -154,83 +154,50 @@ static void avmcs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
+static int avmcs_configcheck(struct pcmcia_device *p_dev,
+                            cistpl_cftable_entry_t *cf,
+                            cistpl_cftable_entry_t *dflt,
+                            unsigned int vcc,
+                            void *priv_data)
 {
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       if (cf->io.nwin <= 0)
+               return -ENODEV;
+
+       p_dev->io.BasePort1 = cf->io.win[0].base;
+       p_dev->io.NumPorts1 = cf->io.win[0].len;
+       p_dev->io.NumPorts2 = 0;
+       printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
+              p_dev->io.BasePort1,
+              p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+       return pcmcia_request_io(p_dev, &p_dev->io);
 }
 
 static int avmcs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     local_info_t *dev;
     int i;
-    u_char buf[64];
     char devname[128];
     int cardtype;
     int (*addcard)(unsigned int port, unsigned irq);
 
     dev = link->priv;
 
-    do {
-       devname[0] = 0;
-       if (link->prod_id[1])
-               strlcpy(devname, link->prod_id[1], sizeof(devname));
+    devname[0] = 0;
+    if (link->prod_id[1])
+           strlcpy(devname, link->prod_id[1], sizeof(devname));
 
-       /*
-         * find IO port
-         */
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(link, &tuple, &parse);
-       while (i == CS_SUCCESS) {
-           if (cf->io.nwin > 0) {
-               link->conf.ConfigIndex = cf->index;
-               link->io.BasePort1 = cf->io.win[0].base;
-               link->io.NumPorts1 = cf->io.win[0].len;
-               link->io.NumPorts2 = 0;
-                printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
-                       link->io.BasePort1,
-                       link->io.BasePort1+link->io.NumPorts1-1);
-               i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS) goto found_port;
-           }
-           i = next_tuple(link, &tuple, &parse);
-       }
-
-found_port:
-       if (i != CS_SUCCESS) {
-           cs_error(link, RequestIO, i);
-           break;
-       }
+    /*
+     * find IO port
+     */
+    if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
+           return -ENODEV;
 
+    do {
        /*
         * allocate an interrupt line
         */
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
            cs_error(link, RequestIRQ, i);
            /* undo */
            pcmcia_disable_device(link);
@@ -241,7 +208,7 @@ found_port:
          * configure the PCMCIA socket
          */
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
            cs_error(link, RequestConfiguration, i);
            pcmcia_disable_device(link);
            break;
index fc6cc2c065b807ac72c44992bb885a1d92e6ec0d..23560c897ec361d59526ffa1d36fad6264ddadcb 100644 (file)
@@ -174,38 +174,29 @@ static void avma1cs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cf,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
 {
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
+       if (cf->io.nwin <= 0)
+               return -ENODEV;
+
+       p_dev->io.BasePort1 = cf->io.win[0].base;
+       p_dev->io.NumPorts1 = cf->io.win[0].len;
+       p_dev->io.NumPorts2 = 0;
+       printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
+              p_dev->io.BasePort1,
+              p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+       return pcmcia_request_io(p_dev, &p_dev->io);
 }
 
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
 static int avma1cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     local_info_t *dev;
     int i;
-    u_char buf[64];
     char devname[128];
     IsdnCard_t icard;
     int busy = 0;
@@ -214,45 +205,19 @@ static int avma1cs_config(struct pcmcia_device *link)
 
     DEBUG(0, "avma1cs_config(0x%p)\n", link);
 
-    do {
-       devname[0] = 0;
-       if (link->prod_id[1])
-               strlcpy(devname, link->prod_id[1], sizeof(devname));
+    devname[0] = 0;
+    if (link->prod_id[1])
+           strlcpy(devname, link->prod_id[1], sizeof(devname));
 
-       /*
-         * find IO port
-         */
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(link, &tuple, &parse);
-       while (i == CS_SUCCESS) {
-           if (cf->io.nwin > 0) {
-               link->conf.ConfigIndex = cf->index;
-               link->io.BasePort1 = cf->io.win[0].base;
-               link->io.NumPorts1 = cf->io.win[0].len;
-               link->io.NumPorts2 = 0;
-               printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
-                       link->io.BasePort1,
-                       link->io.BasePort1+link->io.NumPorts1 - 1);
-               i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS) goto found_port;
-           }
-           i = next_tuple(link, &tuple, &parse);
-       }
+    if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
+           return -ENODEV;
 
-found_port:
-       if (i != CS_SUCCESS) {
-           cs_error(link, RequestIO, i);
-           break;
-       }
-       
+    do {
        /*
         * allocate an interrupt line
         */
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
            cs_error(link, RequestIRQ, i);
            /* undo */
            pcmcia_disable_device(link);
@@ -263,7 +228,7 @@ found_port:
         * configure the PCMCIA socket
         */
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
            cs_error(link, RequestConfiguration, i);
            pcmcia_disable_device(link);
            break;
index db7e64424afe02fca1896c1b1edefdced2e2ac72..f4d0fe29bcf8b1a855a69fa1c1395a4bd9ee863d 100644 (file)
@@ -203,82 +203,55 @@ static void elsa_cs_detach(struct pcmcia_device *link)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cf,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
 {
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       int j;
+
+       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+               printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       } else {
+               printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
+               for (j = 0x2f0; j > 0x100; j -= 0x10) {
+                       p_dev->io.BasePort1 = j;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int elsa_cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
     local_info_t *dev;
-    int i, j, last_fn;
-    u_short buf[128];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, last_fn;
     IsdnCard_t icard;
 
     DEBUG(0, "elsa_config(0x%p)\n", link);
     dev = link->priv;
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-    tuple.Attributes = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(link, &tuple, &parse);
-    while (i == CS_SUCCESS) {
-        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
-            printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-            link->conf.ConfigIndex = cf->index;
-            link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-        } else {
-          printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
-          link->conf.ConfigIndex = cf->index;
-          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
-            link->io.BasePort1 = j;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-          }
-          break;
-        }
-        i = next_tuple(link, &tuple, &parse);
-    }
-
-    if (i != CS_SUCCESS) {
+    i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
+    if (i != 0) {
        last_fn = RequestIO;
        goto cs_failed;
     }
 
     i = pcmcia_request_irq(link, &link->irq);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
         link->irq.AssignedIRQ = 0;
        last_fn = RequestIRQ;
         goto cs_failed;
     }
 
     i = pcmcia_request_configuration(link, &link->conf);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
       last_fn = RequestConfiguration;
       goto cs_failed;
     }
index 439cb530def8833a7c1e17f9e363d3d8341b3518..9a3c9f5e4fe82b5e132bc426592e603b243a091b 100644 (file)
@@ -217,101 +217,61 @@ static void sedlbauer_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int sedlbauer_config(struct pcmcia_device *link)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev,
+                                 cistpl_cftable_entry_t *cfg,
+                                 cistpl_cftable_entry_t *dflt,
+                                 unsigned int vcc,
+                                 void *priv_data)
 {
-    local_info_t *dev = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    int last_fn, last_ret;
-    u8 buf[64];
-    config_info_t conf;
-    win_req_t req;
-    memreq_t map;
-    IsdnCard_t  icard;
-
-    DEBUG(0, "sedlbauer_config(0x%p)\n", link);
-
-    tuple.Attributes = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
+       win_req_t *req = priv_data;
 
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
+       if (cfg->index == 0)
+               return -ENODEV;
 
-    /*
-      In this loop, we scan the CIS for configuration table entries,
-      each of which describes a valid card configuration, including
-      voltage, IO window, memory window, and interrupt settings.
-
-      We make no assumptions about the card to be configured: we use
-      just the information available in the CIS.  In an ideal world,
-      this would work for any PCMCIA card, but it requires a complete
-      and accurate CIS.  In practice, a driver usually "knows" most of
-      these things without consulting the CIS, and most client drivers
-      will only use the CIS to fill in implementation-defined details.
-    */
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (1) {
-       cistpl_cftable_entry_t dflt = { 0 };
-       cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-           goto next_entry;
-
-       if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-       if (cfg->index == 0) goto next_entry;
-       link->conf.ConfigIndex = cfg->index;
-       
        /* Does this card need audio output? */
        if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-           link->conf.Attributes |= CONF_ENABLE_SPKR;
-           link->conf.Status = CCSR_AUDIO_ENA;
+               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+               p_dev->conf.Status = CCSR_AUDIO_ENA;
        }
-       
+
        /* Use power settings for Vcc and Vpp if present */
        /*  Note that the CIS values need to be rescaled */
        if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-           if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-               goto next_entry;
-       } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
-           if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
-               goto next_entry;
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+                       return -ENODEV;
+       } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
+                       return -ENODEV;
        }
-           
+
        if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-           link->conf.Vpp =
-               cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-       else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-           link->conf.Vpp =
-               dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-       
+               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
        /* Do we need to allocate an interrupt? */
-       if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-           link->conf.Attributes |= CONF_ENABLE_IRQ;
-       
+       if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
        /* IO window settings */
-       link->io.NumPorts1 = link->io.NumPorts2 = 0;
-       if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-           cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-           link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-           if (!(io->flags & CISTPL_IO_8BIT))
-               link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-           if (!(io->flags & CISTPL_IO_16BIT))
-               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-/* new in dummy.cs 2001/01/28 MN 
-            link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-*/
-           link->io.BasePort1 = io->win[0].base;
-           link->io.NumPorts1 = io->win[0].len;
-           if (io->nwin > 1) {
-               link->io.Attributes2 = link->io.Attributes1;
-               link->io.BasePort2 = io->win[1].base;
-               link->io.NumPorts2 = io->win[1].len;
-           }
-           /* This reserves IO space but doesn't actually enable it */
-           if (pcmcia_request_io(link, &link->io) != 0)
-               goto next_entry;
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+               /* This reserves IO space but doesn't actually enable it */
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       return -ENODEV;
        }
 
        /*
@@ -325,30 +285,54 @@ static int sedlbauer_config(struct pcmcia_device *link)
          needs to be mapped to virtual space with ioremap() before it
          is used.
        */
-       if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
-           cistpl_mem_t *mem =
-               (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
-           req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-           req.Attributes |= WIN_ENABLE;
-           req.Base = mem->win[0].host_addr;
-           req.Size = mem->win[0].len;
-/* new in dummy.cs 2001/01/28 MN 
-            if (req.Size < 0x1000)
-                req.Size = 0x1000;
-*/
-           req.AccessSpeed = 0;
-           if (pcmcia_request_window(&link, &req, &link->win) != 0)
-               goto next_entry;
-           map.Page = 0; map.CardOffset = mem->win[0].card_addr;
-           if (pcmcia_map_mem_page(link->win, &map) != 0)
-               goto next_entry;
+       if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+               cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+               memreq_t map;
+               req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+               req->Attributes |= WIN_ENABLE;
+               req->Base = mem->win[0].host_addr;
+               req->Size = mem->win[0].len;
+               req->AccessSpeed = 0;
+               if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0)
+                       return -ENODEV;
+               map.Page = 0;
+               map.CardOffset = mem->win[0].card_addr;
+               if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+                       return -ENODEV;
        }
-       /* If we got this far, we're cool! */
-       break;
+       return 0;
+}
 
-    next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-    }
+
+
+static int sedlbauer_config(struct pcmcia_device *link)
+{
+    local_info_t *dev = link->priv;
+    win_req_t *req;
+    int last_fn, last_ret;
+    IsdnCard_t  icard;
+
+    DEBUG(0, "sedlbauer_config(0x%p)\n", link);
+
+    req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
+    if (!req)
+           return -ENOMEM;
+
+    /*
+      In this loop, we scan the CIS for configuration table entries,
+      each of which describes a valid card configuration, including
+      voltage, IO window, memory window, and interrupt settings.
+
+      We make no assumptions about the card to be configured: we use
+      just the information available in the CIS.  In an ideal world,
+      this would work for any PCMCIA card, but it requires a complete
+      and accurate CIS.  In practice, a driver usually "knows" most of
+      these things without consulting the CIS, and most client drivers
+      will only use the CIS to fill in implementation-defined details.
+    */
+    last_ret = pcmcia_loop_config(link, sedlbauer_config_check, req);
+    if (last_ret)
+           goto failed;
 
     /*
        Allocate an interrupt line.  Note that this does not assign a
@@ -387,8 +371,8 @@ static int sedlbauer_config(struct pcmcia_device *link)
        printk(" & 0x%04x-0x%04x", link->io.BasePort2,
               link->io.BasePort2+link->io.NumPorts2-1);
     if (link->win)
-       printk(", mem 0x%06lx-0x%06lx", req.Base,
-              req.Base+req.Size-1);
+       printk(", mem 0x%06lx-0x%06lx", req->Base,
+              req->Base+req->Size-1);
     printk("\n");
 
     icard.para[0] = link->irq.AssignedIRQ;
@@ -409,6 +393,7 @@ static int sedlbauer_config(struct pcmcia_device *link)
 
 cs_failed:
     cs_error(link, last_fn, last_ret);
+failed:
     sedlbauer_release(link);
     return -ENODEV;
 
index ab4bd455450eef1a7b6f5c39968b9416ac4bc459..623d111544d43dfe7859eef6ca14c82533c64a8c 100644 (file)
@@ -193,82 +193,55 @@ static void teles_detach(struct pcmcia_device *link)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cf,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
 {
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       int j;
+
+       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+               printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       } else {
+               printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
+               for (j = 0x2f0; j > 0x100; j -= 0x10) {
+                       p_dev->io.BasePort1 = j;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int teles_cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
     local_info_t *dev;
-    int i, j, last_fn;
-    u_short buf[128];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, last_fn;
     IsdnCard_t icard;
 
     DEBUG(0, "teles_config(0x%p)\n", link);
     dev = link->priv;
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-    tuple.Attributes = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(link, &tuple, &parse);
-    while (i == CS_SUCCESS) {
-        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
-            printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-            link->conf.ConfigIndex = cf->index;
-            link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-        } else {
-          printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
-          link->conf.ConfigIndex = cf->index;
-          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
-            link->io.BasePort1 = j;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-          }
-          break;
-        }
-        i = next_tuple(link, &tuple, &parse);
-    }
-
-    if (i != CS_SUCCESS) {
+    i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
+    if (i != 0) {
        last_fn = RequestIO;
        goto cs_failed;
     }
 
     i = pcmcia_request_irq(link, &link->irq);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
         link->irq.AssignedIRQ = 0;
        last_fn = RequestIRQ;
         goto cs_failed;
     }
 
     i = pcmcia_request_configuration(link, &link->conf);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
       last_fn = RequestConfiguration;
       goto cs_failed;
     }
index e92b1ba4b45eb836d83ef101564c76311644ed2e..c2f51cc507608bada189220168178d05b34f908a 100644 (file)
@@ -452,10 +452,10 @@ one_member:
                        if (finddsp->features.pcm_id == dsp->features.pcm_id) {
                                if (finddsp->pcm_slot_rx >= 0 &&
                                    finddsp->pcm_slot_rx < sizeof(freeslots))
-                                       freeslots[finddsp->pcm_slot_tx] = 0;
+                                       freeslots[finddsp->pcm_slot_rx] = 0;
                                if (finddsp->pcm_slot_tx >= 0 &&
                                    finddsp->pcm_slot_tx < sizeof(freeslots))
-                                       freeslots[finddsp->pcm_slot_rx] = 0;
+                                       freeslots[finddsp->pcm_slot_tx] = 0;
                        }
                }
                i = 0;
index e7462924b5050fb70cad3ddfd9f607368d61e774..875fabe16e368c32b87f1a2e697accf45369eac6 100644 (file)
@@ -61,7 +61,7 @@ mISDN_open(struct inode *ino, struct file *filep)
        init_waitqueue_head(&dev->wait);
        filep->private_data = dev;
        __module_get(THIS_MODULE);
-       return 0;
+       return nonseekable_open(ino, filep);
 }
 
 static int
index 559a40861c39b2e8e8fd7531acb06dc00a20dde2..ee74ee7b2accab837fc43c0c8cda523795bed5ce 100644 (file)
@@ -103,8 +103,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 {
        int rc;
 
-       led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,
-                                             "%s", led_cdev->name);
+       led_cdev->dev = device_create(leds_class, parent, 0, led_cdev,
+                                     "%s", led_cdev->name);
        if (IS_ERR(led_cdev->dev))
                return PTR_ERR(led_cdev->dev);
 
index cae52485208aaf022bd57689dcf8a4b30173aa2e..23741cec45e3e43210fdbac7e11c6ecc9c4eb1d5 100644 (file)
@@ -862,8 +862,7 @@ adbdev_init(void)
        adb_dev_class = class_create(THIS_MODULE, "adb");
        if (IS_ERR(adb_dev_class))
                return;
-       device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
-                             "adb");
+       device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
 
        platform_device_register(&adb_pfdev);
        platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
index 07d92c11b5d8d935887f0b8361626faaf1abfd46..2281b5098e95455cd1a6d60af7354f7728888185 100644 (file)
@@ -30,6 +30,20 @@ config BLK_DEV_MD
 
          If unsure, say N.
 
+config MD_AUTODETECT
+       bool "Autodetect RAID arrays during kernel boot"
+       depends on BLK_DEV_MD=y
+       default y
+       ---help---
+         If you say Y here, then the kernel will try to autodetect raid
+         arrays as part of its boot process. 
+
+         If you don't use raid and say Y, this autodetection can cause 
+         a several-second delay in the boot time due to various
+         synchronisation steps that are part of this step.
+
+         If unsure, say Y.
+
 config MD_LINEAR
        tristate "Linear (append) mode"
        depends on BLK_DEV_MD
index 268547dbfbd30ce2942b3b5d92c9bbfab793d4b7..f26c1f9a475b8d9cbad5f885016e50723b580cd5 100644 (file)
@@ -287,6 +287,8 @@ static int run(mddev_t *mddev)
        int i;
 
        conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
+       if (!conf)
+               return -ENOMEM;
 
        for (i=0; i<Modes; i++) {
                atomic_set(&conf->counters[i], 0);
index b9cbee688fae9e4d28c9d62f58780d39254e0e3d..190147c79e79fbbe9b0e2c0935aa7ac697464a1b 100644 (file)
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
 
-#include <linux/module.h>
-
-#include <linux/raid/md.h>
-#include <linux/slab.h>
 #include <linux/raid/linear.h>
 
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
 /*
  * find which device holds a particular offset 
  */
@@ -33,16 +25,15 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 {
        dev_info_t *hash;
        linear_conf_t *conf = mddev_to_conf(mddev);
-       sector_t block = sector >> 1;
 
        /*
         * sector_div(a,b) returns the remainer and sets a to a/b
         */
-       block >>= conf->preshift;
-       (void)sector_div(block, conf->hash_spacing);
-       hash = conf->hash_table[block];
+       sector >>= conf->sector_shift;
+       (void)sector_div(sector, conf->spacing);
+       hash = conf->hash_table[sector];
 
-       while ((sector>>1) >= (hash->size + hash->offset))
+       while (sector >= hash->num_sectors + hash->start_sector)
                hash++;
        return hash;
 }
@@ -65,7 +56,7 @@ static int linear_mergeable_bvec(struct request_queue *q,
        sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
        dev0 = which_dev(mddev, sector);
-       maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1));
+       maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
 
        if (maxsectors < bio_sectors)
                maxsectors = 0;
@@ -112,8 +103,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
        dev_info_t **table;
        mdk_rdev_t *rdev;
        int i, nb_zone, cnt;
-       sector_t min_spacing;
-       sector_t curr_offset;
+       sector_t min_sectors;
+       sector_t curr_sector;
        struct list_head *tmp;
 
        conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
@@ -145,7 +136,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                    mddev->queue->max_sectors > (PAGE_SIZE>>9))
                        blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
-               disk->size = rdev->size;
+               disk->num_sectors = rdev->size * 2;
                conf->array_sectors += rdev->size * 2;
 
                cnt++;
@@ -155,34 +146,34 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                goto out;
        }
 
-       min_spacing = conf->array_sectors / 2;
-       sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+       min_sectors = conf->array_sectors;
+       sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
 
-       /* min_spacing is the minimum spacing that will fit the hash
+       /* min_sectors is the minimum spacing that will fit the hash
         * table in one PAGE.  This may be much smaller than needed.
         * We find the smallest non-terminal set of consecutive devices
-        * that is larger than min_spacing as use the size of that as
+        * that is larger than min_sectors and use the size of that as
         * the actual spacing
         */
-       conf->hash_spacing = conf->array_sectors / 2;
+       conf->spacing = conf->array_sectors;
        for (i=0; i < cnt-1 ; i++) {
-               sector_t sz = 0;
+               sector_t tmp = 0;
                int j;
-               for (j = i; j < cnt - 1 && sz < min_spacing; j++)
-                       sz += conf->disks[j].size;
-               if (sz >= min_spacing && sz < conf->hash_spacing)
-                       conf->hash_spacing = sz;
+               for (j = i; j < cnt - 1 && tmp < min_sectors; j++)
+                       tmp += conf->disks[j].num_sectors;
+               if (tmp >= min_sectors && tmp < conf->spacing)
+                       conf->spacing = tmp;
        }
 
-       /* hash_spacing may be too large for sector_div to work with,
+       /* spacing may be too large for sector_div to work with,
         * so we might need to pre-shift
         */
-       conf->preshift = 0;
+       conf->sector_shift = 0;
        if (sizeof(sector_t) > sizeof(u32)) {
-               sector_t space = conf->hash_spacing;
+               sector_t space = conf->spacing;
                while (space > (sector_t)(~(u32)0)) {
                        space >>= 1;
-                       conf->preshift++;
+                       conf->sector_shift++;
                }
        }
        /*
@@ -194,9 +185,9 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                unsigned round;
                unsigned long base;
 
-               sz = conf->array_sectors >> (conf->preshift + 1);
+               sz = conf->array_sectors >> conf->sector_shift;
                sz += 1; /* force round-up */
-               base = conf->hash_spacing >> conf->preshift;
+               base = conf->spacing >> conf->sector_shift;
                round = sector_div(sz, base);
                nb_zone = sz + (round ? 1 : 0);
        }
@@ -211,32 +202,31 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
         * Here we generate the linear hash table
         * First calculate the device offsets.
         */
-       conf->disks[0].offset = 0;
+       conf->disks[0].start_sector = 0;
        for (i = 1; i < raid_disks; i++)
-               conf->disks[i].offset =
-                       conf->disks[i-1].offset +
-                       conf->disks[i-1].size;
+               conf->disks[i].start_sector =
+                       conf->disks[i-1].start_sector +
+                       conf->disks[i-1].num_sectors;
 
        table = conf->hash_table;
-       curr_offset = 0;
        i = 0;
-       for (curr_offset = 0;
-            curr_offset < conf->array_sectors / 2;
-            curr_offset += conf->hash_spacing) {
+       for (curr_sector = 0;
+            curr_sector < conf->array_sectors;
+            curr_sector += conf->spacing) {
 
                while (i < raid_disks-1 &&
-                      curr_offset >= conf->disks[i+1].offset)
+                      curr_sector >= conf->disks[i+1].start_sector)
                        i++;
 
                *table ++ = conf->disks + i;
        }
 
-       if (conf->preshift) {
-               conf->hash_spacing >>= conf->preshift;
-               /* round hash_spacing up so that when we divide by it,
+       if (conf->sector_shift) {
+               conf->spacing >>= conf->sector_shift;
+               /* round spacing up so that when we divide by it,
                 * we err on the side of "too-low", which is safest.
                 */
-               conf->hash_spacing++;
+               conf->spacing++;
        }
 
        BUG_ON(table - conf->hash_table > nb_zone);
@@ -317,7 +307,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
        const int rw = bio_data_dir(bio);
        mddev_t *mddev = q->queuedata;
        dev_info_t *tmp_dev;
-       sector_t block;
        int cpu;
 
        if (unlikely(bio_barrier(bio))) {
@@ -332,29 +321,33 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
        part_stat_unlock();
 
        tmp_dev = which_dev(mddev, bio->bi_sector);
-       block = bio->bi_sector >> 1;
     
-       if (unlikely(block >= (tmp_dev->size + tmp_dev->offset)
-                    || block < tmp_dev->offset)) {
+       if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
+                                       tmp_dev->start_sector)
+                    || (bio->bi_sector <
+                        tmp_dev->start_sector))) {
                char b[BDEVNAME_SIZE];
 
-               printk("linear_make_request: Block %llu out of bounds on "
-                       "dev %s size %llu offset %llu\n",
-                       (unsigned long long)block,
+               printk("linear_make_request: Sector %llu out of bounds on "
+                       "dev %s: %llu sectors, offset %llu\n",
+                       (unsigned long long)bio->bi_sector,
                        bdevname(tmp_dev->rdev->bdev, b),
-                       (unsigned long long)tmp_dev->size,
-                       (unsigned long long)tmp_dev->offset);
+                       (unsigned long long)tmp_dev->num_sectors,
+                       (unsigned long long)tmp_dev->start_sector);
                bio_io_error(bio);
                return 0;
        }
        if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
-                    (tmp_dev->offset + tmp_dev->size)<<1)) {
+                    tmp_dev->start_sector + tmp_dev->num_sectors)) {
                /* This bio crosses a device boundary, so we have to
                 * split it.
                 */
                struct bio_pair *bp;
+
                bp = bio_split(bio,
-                              ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector);
+                              tmp_dev->start_sector + tmp_dev->num_sectors
+                              - bio->bi_sector);
+
                if (linear_make_request(q, &bp->bio1))
                        generic_make_request(&bp->bio1);
                if (linear_make_request(q, &bp->bio2))
@@ -364,7 +357,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
        }
                    
        bio->bi_bdev = tmp_dev->rdev->bdev;
-       bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset;
+       bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
+               + tmp_dev->rdev->data_offset;
 
        return 1;
 }
@@ -372,29 +366,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
 static void linear_status (struct seq_file *seq, mddev_t *mddev)
 {
 
-#undef MD_DEBUG
-#ifdef MD_DEBUG
-       int j;
-       linear_conf_t *conf = mddev_to_conf(mddev);
-       sector_t s = 0;
-  
-       seq_printf(seq, "      ");
-       for (j = 0; j < mddev->raid_disks; j++)
-       {
-               char b[BDEVNAME_SIZE];
-               s += conf->smallest_size;
-               seq_printf(seq, "[%s",
-                          bdevname(conf->hash_table[j][0].rdev->bdev,b));
-
-               while (s > conf->hash_table[j][0].offset +
-                          conf->hash_table[j][0].size)
-                       seq_printf(seq, "/%s] ",
-                                  bdevname(conf->hash_table[j][1].rdev->bdev,b));
-               else
-                       seq_printf(seq, "] ");
-       }
-       seq_printf(seq, "\n");
-#endif
        seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
 }
 
index 0a3a4bdcd4afd55ad52fd08ecc3d99713bcb9a87..aaa3d465de4ece202bd3a18c1c605248ebd40ad7 100644 (file)
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/kthread.h>
-#include <linux/linkage.h>
 #include <linux/raid/md.h>
 #include <linux/raid/bitmap.h>
 #include <linux/sysctl.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/poll.h>
-#include <linux/mutex.h>
 #include <linux/ctype.h>
-#include <linux/freezer.h>
-
-#include <linux/init.h>
-
+#include <linux/hdreg.h>
+#include <linux/proc_fs.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
 #include <linux/file.h>
-
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/unaligned.h>
+#include <linux/delay.h>
 
 #define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
 
 /* 63 partitions with the alternate major number (mdp) */
 #define MdpMinorShift 6
@@ -66,7 +56,7 @@
 
 
 #ifndef MODULE
-static void autostart_arrays (int part);
+static void autostart_arrays(int part);
 #endif
 
 static LIST_HEAD(pers_list);
@@ -212,7 +202,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
                )
 
 
-static int md_fail_request (struct request_queue *q, struct bio *bio)
+static int md_fail_request(struct request_queue *q, struct bio *bio)
 {
        bio_io_error(bio);
        return 0;
@@ -2106,8 +2096,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 
        if (strict_strtoull(buf, 10, &size) < 0)
                return -EINVAL;
-       if (size < my_mddev->size)
-               return -EINVAL;
        if (my_mddev->pers && rdev->raid_disk >= 0) {
                if (my_mddev->persistent) {
                        size = super_types[my_mddev->major_version].
@@ -2118,9 +2106,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
                        size = (rdev->bdev->bd_inode->i_size >> 10);
                        size -= rdev->data_offset/2;
                }
-               if (size < my_mddev->size)
-                       return -EINVAL; /* component must fit device */
        }
+       if (size < my_mddev->size)
+               return -EINVAL; /* component must fit device */
 
        rdev->size = size;
        if (size > oldsize && my_mddev->external) {
@@ -2406,12 +2394,11 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
        int i;
        unsigned long msec;
        char buf[30];
-       char *e;
+
        /* remove a period, and count digits after it */
        if (len >= sizeof(buf))
                return -EINVAL;
-       strlcpy(buf, cbuf, len);
-       buf[len] = 0;
+       strlcpy(buf, cbuf, sizeof(buf));
        for (i=0; i<len; i++) {
                if (dot) {
                        if (isdigit(buf[i])) {
@@ -2424,8 +2411,7 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
                        buf[i] = 0;
                }
        }
-       msec = simple_strtoul(buf, &e, 10);
-       if (e == buf || (*e && *e != '\n'))
+       if (strict_strtoul(buf, 10, &msec) < 0)
                return -EINVAL;
        msec = (msec * 1000) / scale;
        if (msec == 0)
@@ -2727,9 +2713,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                break;
        case read_auto:
                if (mddev->pers) {
-                       if (mddev->ro != 1)
+                       if (mddev->ro == 0)
                                err = do_md_stop(mddev, 1, 0);
-                       else
+                       else if (mddev->ro == 1)
                                err = restart_array(mddev);
                        if (err == 0) {
                                mddev->ro = 2;
@@ -2945,7 +2931,13 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len)
 {
        int major, minor;
        char *e;
-       if (!list_empty(&mddev->disks))
+       /* Changing the details of 'external' metadata is
+        * always permitted.  Otherwise there must be
+        * no devices attached to the array.
+        */
+       if (mddev->external && strncmp(buf, "external:", 9) == 0)
+               ;
+       else if (!list_empty(&mddev->disks))
                return -EBUSY;
 
        if (cmd_match(buf, "none")) {
@@ -3527,17 +3519,12 @@ static int do_md_run(mddev_t * mddev)
                        return -EINVAL;
                }
                /*
-                * chunk-size has to be a power of 2 and multiples of PAGE_SIZE
+                * chunk-size has to be a power of 2
                 */
                if ( (1 << ffz(~chunk_size)) != chunk_size) {
                        printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
                        return -EINVAL;
                }
-               if (chunk_size < PAGE_SIZE) {
-                       printk(KERN_ERR "too small chunk_size: %d < %ld\n",
-                               chunk_size, PAGE_SIZE);
-                       return -EINVAL;
-               }
 
                /* devices must have minimum size of one chunk */
                rdev_for_each(rdev, tmp, mddev) {
@@ -3555,12 +3542,10 @@ static int do_md_run(mddev_t * mddev)
                }
        }
 
-#ifdef CONFIG_KMOD
        if (mddev->level != LEVEL_NONE)
                request_module("md-level-%d", mddev->level);
        else if (mddev->clevel[0])
                request_module("md-%s", mddev->clevel);
-#endif
 
        /*
         * Drop all container device buffers, from now on
@@ -3971,10 +3956,10 @@ static void autorun_array(mddev_t *mddev)
        }
        printk("\n");
 
-       err = do_md_run (mddev);
+       err = do_md_run(mddev);
        if (err) {
                printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
-               do_md_stop (mddev, 0, 0);
+               do_md_stop(mddev, 0, 0);
        }
 }
 
@@ -4333,7 +4318,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 
        if (!(info->state & (1<<MD_DISK_FAULTY))) {
                int err;
-               rdev = md_import_device (dev, -1, 0);
+               rdev = md_import_device(dev, -1, 0);
                if (IS_ERR(rdev)) {
                        printk(KERN_WARNING 
                                "md: error, md_import_device() returned %ld\n",
@@ -4415,7 +4400,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
                return -EINVAL;
        }
 
-       rdev = md_import_device (dev, -1, 0);
+       rdev = md_import_device(dev, -1, 0);
        if (IS_ERR(rdev)) {
                printk(KERN_WARNING 
                        "md: error, md_import_device() returned %ld\n",
@@ -4934,11 +4919,11 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        goto done_unlock;
 
                case STOP_ARRAY:
-                       err = do_md_stop (mddev, 0, 1);
+                       err = do_md_stop(mddev, 0, 1);
                        goto done_unlock;
 
                case STOP_ARRAY_RO:
-                       err = do_md_stop (mddev, 1, 1);
+                       err = do_md_stop(mddev, 1, 1);
                        goto done_unlock;
 
        }
@@ -4987,7 +4972,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        goto done_unlock;
 
                case RUN_ARRAY:
-                       err = do_md_run (mddev);
+                       err = do_md_run(mddev);
                        goto done_unlock;
 
                case SET_BITMAP_FILE:
@@ -5425,11 +5410,11 @@ static int md_seq_show(struct seq_file *seq, void *v)
                        seq_printf(seq, " super non-persistent");
 
                if (mddev->pers) {
-                       mddev->pers->status (seq, mddev);
+                       mddev->pers->status(seq, mddev);
                        seq_printf(seq, "\n      ");
                        if (mddev->pers->sync_request) {
                                if (mddev->curr_resync > 2) {
-                                       status_resync (seq, mddev);
+                                       status_resync(seq, mddev);
                                        seq_printf(seq, "\n      ");
                                } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
                                        seq_printf(seq, "\tresync=DELAYED\n      ");
@@ -6260,7 +6245,7 @@ static int md_notify_reboot(struct notifier_block *this,
                                 * appears to still be in use.  Hence
                                 * the '100'.
                                 */
-                               do_md_stop (mddev, 1, 100);
+                               do_md_stop(mddev, 1, 100);
                                mddev_unlock(mddev);
                        }
                /*
@@ -6304,7 +6289,7 @@ static int __init md_init(void)
        raid_table_header = register_sysctl_table(raid_root_table);
 
        md_geninit();
-       return (0);
+       return 0;
 }
 
 
index 7ae33ebaf7ec9ed63f17e9cb712a673b0e25a30a..d4ac47d112797f4f3343420175b4312397337de2 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/raid/multipath.h>
-#include <linux/buffer_head.h>
-#include <asm/atomic.h>
-
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
 
 #define MAX_WORK_PER_DISK 128
 
index 53508a8a981d70881eb130ef952033435e9b92f1..8ac6488ad0dc6c1a86463c4e732c1205a6cbb9a3 100644 (file)
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
 
-#include <linux/module.h>
 #include <linux/raid/raid0.h>
 
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
 static void raid0_unplug(struct request_queue *q)
 {
        mddev_t *mddev = q->queuedata;
index b9764429d856ead58ec0ffd51bc06da21e0891fc..9c788e2489b18934eadb62cac4d4b33b3c121620 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "dm-bio-list.h"
+#include <linux/delay.h>
 #include <linux/raid/raid1.h>
 #include <linux/raid/bitmap.h>
 
index 8bdc9bfc288703aafbc8b20925f3d9b8e337fd54..da5129a24b18142d39595c86415bdef40612e353 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "dm-bio-list.h"
+#include <linux/delay.h>
 #include <linux/raid/raid10.h>
 #include <linux/raid/bitmap.h>
 
@@ -2028,8 +2029,9 @@ static int run(mddev_t *mddev)
        int nc, fc, fo;
        sector_t stride, size;
 
-       if (mddev->chunk_size == 0) {
-               printk(KERN_ERR "md/raid10: non-zero chunk size required.\n");
+       if (mddev->chunk_size < PAGE_SIZE) {
+               printk(KERN_ERR "md/raid10: chunk size must be "
+                      "at least PAGE_SIZE(%ld).\n", PAGE_SIZE);
                return -EINVAL;
        }
 
index ae16794bef209eeeae6cae8f074c6778674dd068..a36a7435edf51bd29cc32681cb8b211b29a9f8cb 100644 (file)
  * miss any bits.
  */
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/bitops.h>
 #include <linux/kthread.h>
-#include <asm/atomic.h>
 #include "raid6.h"
 
 #include <linux/raid/bitmap.h>
@@ -275,7 +270,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
        return 0;
 }
 
-static void raid5_build_block (struct stripe_head *sh, int i);
+static void raid5_build_block(struct stripe_head *sh, int i);
 
 static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks)
 {
@@ -1151,7 +1146,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
        release_stripe(sh);
 }
 
-static void raid5_end_write_request (struct bio *bi, int error)
+static void raid5_end_write_request(struct bio *bi, int error)
 {
        struct stripe_head *sh = bi->bi_private;
        raid5_conf_t *conf = sh->raid_conf;
@@ -1183,7 +1178,7 @@ static void raid5_end_write_request (struct bio *bi, int error)
 
 static sector_t compute_blocknr(struct stripe_head *sh, int i);
        
-static void raid5_build_block (struct stripe_head *sh, int i)
+static void raid5_build_block(struct stripe_head *sh, int i)
 {
        struct r5dev *dev = &sh->dev[i];
 
@@ -1221,10 +1216,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                }
                set_bit(Faulty, &rdev->flags);
-               printk (KERN_ALERT
-                       "raid5: Disk failure on %s, disabling device.\n"
-                       "raid5: Operation continuing on %d devices.\n",
-                       bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
+               printk(KERN_ALERT
+                      "raid5: Disk failure on %s, disabling device.\n"
+                      "raid5: Operation continuing on %d devices.\n",
+                      bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
        }
 }
 
@@ -1320,8 +1315,8 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
                        *dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
                        break;
                default:
-                       printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
-                               conf->algorithm);
+                       printk(KERN_CRIT "raid6: unsupported algorithm %d\n",
+                              conf->algorithm);
                }
                break;
        }
@@ -1396,8 +1391,8 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
                        }
                        break;
                default:
-                       printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
-                               conf->algorithm);
+                       printk(KERN_CRIT "raid6: unsupported algorithm %d\n",
+                              conf->algorithm);
                }
                break;
        }
@@ -1405,7 +1400,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
        chunk_number = stripe * data_disks + i;
        r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
 
-       check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
+       check = raid5_compute_sector(r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
        if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
                printk(KERN_ERR "compute_blocknr: map not correct\n");
                return 0;
@@ -4012,6 +4007,13 @@ static int run(mddev_t *mddev)
                return -EIO;
        }
 
+       if (mddev->chunk_size < PAGE_SIZE) {
+               printk(KERN_ERR "md/raid5: chunk_size must be at least "
+                      "PAGE_SIZE but %d < %ld\n",
+                      mddev->chunk_size, PAGE_SIZE);
+               return -EINVAL;
+       }
+
        if (mddev->reshape_position != MaxSector) {
                /* Check that we can continue the reshape.
                 * Currently only disks can change, it must
@@ -4289,7 +4291,7 @@ static int stop(mddev_t *mddev)
 }
 
 #ifdef DEBUG
-static void print_sh (struct seq_file *seq, struct stripe_head *sh)
+static void print_sh(struct seq_file *seq, struct stripe_head *sh)
 {
        int i;
 
@@ -4305,7 +4307,7 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
        seq_printf(seq, "\n");
 }
 
-static void printall (struct seq_file *seq, raid5_conf_t *conf)
+static void printall(struct seq_file *seq, raid5_conf_t *conf)
 {
        struct stripe_head *sh;
        struct hlist_node *hn;
@@ -4323,7 +4325,7 @@ static void printall (struct seq_file *seq, raid5_conf_t *conf)
 }
 #endif
 
-static void status (struct seq_file *seq, mddev_t *mddev)
+static void status(struct seq_file *seq, mddev_t *mddev)
 {
        raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
        int i;
index 31cbee71365f4d5ad969e4558b32147020b81173..98dcde88470e4c23b8fc204e46587be0243bfa32 100644 (file)
 /* Set to 1 to use kernel-wide empty_zero_page */
 #define RAID6_USE_EMPTY_ZERO_PAGE 0
 
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mempool.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
 #include <linux/raid/md.h>
 #include <linux/raid/raid5.h>
 
index 8fa91f846d591bcd35d544d87aec42edbbfc5b96..4952aeb5dd80583ba34c4bff94ee319ddf1a4731 100644 (file)
@@ -103,6 +103,56 @@ IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_avermedia_dvbt);
 
+/* Mauro Carvalho Chehab <mchehab@infradead.org> */
+IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = {
+       [0x00] = KEY_POWER2,
+       [0x2e] = KEY_DOT,               /* '.' */
+       [0x01] = KEY_MODE,              /* TV/FM */
+
+       [0x05] = KEY_1,
+       [0x06] = KEY_2,
+       [0x07] = KEY_3,
+       [0x09] = KEY_4,
+       [0x0a] = KEY_5,
+       [0x0b] = KEY_6,
+       [0x0d] = KEY_7,
+       [0x0e] = KEY_8,
+       [0x0f] = KEY_9,
+       [0x11] = KEY_0,
+
+       [0x13] = KEY_RIGHT,             /* -> */
+       [0x12] = KEY_LEFT,              /* <- */
+
+       [0x17] = KEY_SLEEP,             /* Capturar Imagem */
+       [0x10] = KEY_SHUFFLE,           /* Amostra */
+
+       /* FIXME: The keys bellow aren't ok */
+
+       [0x43] = KEY_CHANNELUP,
+       [0x42] = KEY_CHANNELDOWN,
+       [0x1f] = KEY_VOLUMEUP,
+       [0x1e] = KEY_VOLUMEDOWN,
+       [0x0c] = KEY_ENTER,
+
+       [0x14] = KEY_MUTE,
+       [0x08] = KEY_AUDIO,
+
+       [0x03] = KEY_TEXT,
+       [0x04] = KEY_EPG,
+       [0x2b] = KEY_TV2,               /* TV2 */
+
+       [0x1d] = KEY_RED,
+       [0x1c] = KEY_YELLOW,
+       [0x41] = KEY_GREEN,
+       [0x40] = KEY_BLUE,
+
+       [0x1a] = KEY_PLAYPAUSE,
+       [0x19] = KEY_RECORD,
+       [0x18] = KEY_PLAY,
+       [0x1b] = KEY_STOP,
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a);
+
 /* Attila Kondoros <attila.kondoros@chello.hu> */
 IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
 
@@ -467,7 +517,8 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci);
 
 /* ---------------------------------------------------------------------- */
 
-/* MSI TV@nywhere remote */
+/* MSI TV@nywhere MASTER remote */
+
 IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
        /* Keys 0 to 9 */
        [ 0x00 ] = KEY_0,
@@ -501,6 +552,95 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere);
 
 /* ---------------------------------------------------------------------- */
 
+/*
+  Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card
+  is marked "KS003". The controller is I2C at address 0x30, but does not seem
+  to respond to probes until a read is performed from a valid device.
+  I don't know why...
+
+  Note: This remote may be of similar or identical design to the
+  Pixelview remote (?).  The raw codes and duplicate button codes
+  appear to be the same.
+
+  Henry Wong <henry@stuffedcow.net>
+  Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com>
+
+*/
+
+IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = {
+
+/*  ---- Remote Button Layout ----
+
+    POWER   SOURCE  SCAN    MUTE
+    TV/FM   1       2       3
+    |>      4       5       6
+    <|      7       8       9
+    ^^UP    0       +       RECALL
+    vvDN    RECORD  STOP    PLAY
+
+       MINIMIZE          ZOOM
+
+                 CH+
+      VOL-                   VOL+
+                 CH-
+
+       SNAPSHOT           MTS
+
+     <<      FUNC    >>     RESET
+*/
+
+       [0x01] = KEY_KP1,             /* 1 */
+       [0x0b] = KEY_KP2,             /* 2 */
+       [0x1b] = KEY_KP3,             /* 3 */
+       [0x05] = KEY_KP4,             /* 4 */
+       [0x09] = KEY_KP5,             /* 5 */
+       [0x15] = KEY_KP6,             /* 6 */
+       [0x06] = KEY_KP7,             /* 7 */
+       [0x0a] = KEY_KP8,             /* 8 */
+       [0x12] = KEY_KP9,             /* 9 */
+       [0x02] = KEY_KP0,             /* 0 */
+       [0x10] = KEY_KPPLUS,          /* + */
+       [0x13] = KEY_AGAIN,           /* Recall */
+
+       [0x1e] = KEY_POWER,           /* Power */
+       [0x07] = KEY_TUNER,           /* Source */
+       [0x1c] = KEY_SEARCH,          /* Scan */
+       [0x18] = KEY_MUTE,            /* Mute */
+
+       [0x03] = KEY_RADIO,           /* TV/FM */
+       /* The next four keys are duplicates that appear to send the
+          same IR code as Ch+, Ch-, >>, and << .  The raw code assigned
+          to them is the actual code + 0x20 - they will never be
+          detected as such unless some way is discovered to distinguish
+          these buttons from those that have the same code. */
+       [0x3f] = KEY_RIGHT,           /* |> and Ch+ */
+       [0x37] = KEY_LEFT,            /* <| and Ch- */
+       [0x2c] = KEY_UP,              /* ^^Up and >> */
+       [0x24] = KEY_DOWN,            /* vvDn and << */
+
+       [0x00] = KEY_RECORD,          /* Record */
+       [0x08] = KEY_STOP,            /* Stop */
+       [0x11] = KEY_PLAY,            /* Play */
+
+       [0x0f] = KEY_CLOSE,           /* Minimize */
+       [0x19] = KEY_ZOOM,            /* Zoom */
+       [0x1a] = KEY_SHUFFLE,         /* Snapshot */
+       [0x0d] = KEY_LANGUAGE,        /* MTS */
+
+       [0x14] = KEY_VOLUMEDOWN,      /* Vol- */
+       [0x16] = KEY_VOLUMEUP,        /* Vol+ */
+       [0x17] = KEY_CHANNELDOWN,     /* Ch- */
+       [0x1f] = KEY_CHANNELUP,       /* Ch+ */
+
+       [0x04] = KEY_REWIND,          /* << */
+       [0x0e] = KEY_MENU,            /* Function */
+       [0x0c] = KEY_FASTFORWARD,     /* >> */
+       [0x1d] = KEY_RESTART,         /* Reset */
+};
+EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus);
+
+/* ---------------------------------------------------------------------- */
+
 /* Cinergy 1400 DVB-T */
 IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
        [ 0x01 ] = KEY_POWER,
@@ -1792,12 +1932,61 @@ IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE] = {
        [ 0x41 ] = KEY_GREEN,           /* AP2 */
        [ 0x47 ] = KEY_YELLOW,          /* AP3 */
        [ 0x57 ] = KEY_BLUE,            /* AP4 */
-
-
 };
-
 EXPORT_SYMBOL_GPL(ir_codes_encore_enltv);
 
+/* Encore ENLTV2-FM  - silver plastic - "Wand Media" written at the botton
+    Mauro Carvalho Chehab <mchehab@infradead.org> */
+IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE] = {
+       [0x4c] = KEY_POWER2,
+       [0x4a] = KEY_TUNER,
+       [0x40] = KEY_1,
+       [0x60] = KEY_2,
+       [0x50] = KEY_3,
+       [0x70] = KEY_4,
+       [0x48] = KEY_5,
+       [0x68] = KEY_6,
+       [0x58] = KEY_7,
+       [0x78] = KEY_8,
+       [0x44] = KEY_9,
+       [0x54] = KEY_0,
+
+       [0x64] = KEY_LAST,              /* +100 */
+       [0x4e] = KEY_AGAIN,             /* Recall */
+
+       [0x6c] = KEY_SWITCHVIDEOMODE,   /* Video Source */
+       [0x5e] = KEY_MENU,
+       [0x56] = KEY_SCREEN,
+       [0x7a] = KEY_SETUP,
+
+       [0x46] = KEY_MUTE,
+       [0x5c] = KEY_MODE,              /* Stereo */
+       [0x74] = KEY_INFO,
+       [0x7c] = KEY_CLEAR,
+
+       [0x55] = KEY_UP,
+       [0x49] = KEY_DOWN,
+       [0x7e] = KEY_LEFT,
+       [0x59] = KEY_RIGHT,
+       [0x6a] = KEY_ENTER,
+
+       [0x42] = KEY_VOLUMEUP,
+       [0x62] = KEY_VOLUMEDOWN,
+       [0x52] = KEY_CHANNELUP,
+       [0x72] = KEY_CHANNELDOWN,
+
+       [0x41] = KEY_RECORD,
+       [0x51] = KEY_SHUFFLE,   /* Snapshot */
+       [0x75] = KEY_TIME,      /* Timeshift */
+       [0x71] = KEY_TV2,       /* PIP */
+
+       [0x45] = KEY_REWIND,
+       [0x6f] = KEY_PAUSE,
+       [0x7d] = KEY_FORWARD,
+       [0x79] = KEY_STOP,
+};
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2);
+
 /* for the Technotrend 1500 bundled remotes (grey and black): */
 IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
        [ 0x01 ] = KEY_POWER,
@@ -2239,3 +2428,86 @@ IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
        [0x2a] = KEY_MENU,
 };
 EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d);
+
+/* Encore ENLTV-FM v5.3
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE] = {
+       [0x10] = KEY_POWER2,
+       [0x06] = KEY_MUTE,
+
+       [0x09] = KEY_1,
+       [0x1d] = KEY_2,
+       [0x1f] = KEY_3,
+       [0x19] = KEY_4,
+       [0x1b] = KEY_5,
+       [0x11] = KEY_6,
+       [0x17] = KEY_7,
+       [0x12] = KEY_8,
+       [0x16] = KEY_9,
+       [0x48] = KEY_0,
+
+       [0x04] = KEY_LIST,              /* -/-- */
+       [0x40] = KEY_LAST,              /* recall */
+
+       [0x02] = KEY_MODE,              /* TV/AV */
+       [0x05] = KEY_SHUFFLE,           /* SNAPSHOT */
+
+       [0x4c] = KEY_CHANNELUP,         /* UP */
+       [0x00] = KEY_CHANNELDOWN,       /* DOWN */
+       [0x0d] = KEY_VOLUMEUP,          /* RIGHT */
+       [0x15] = KEY_VOLUMEDOWN,        /* LEFT */
+       [0x49] = KEY_ENTER,             /* OK */
+
+       [0x54] = KEY_RECORD,
+       [0x4d] = KEY_PLAY,              /* pause */
+
+       [0x1e] = KEY_UP,                /* video setting */
+       [0x0e] = KEY_RIGHT,             /* <- */
+       [0x1a] = KEY_LEFT,              /* -> */
+
+       [0x0a] = KEY_DOWN,              /* video default */
+       [0x0c] = KEY_ZOOM,              /* hide pannel */
+       [0x47] = KEY_SLEEP,             /* shutdown */
+};
+EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53);
+
+/* Zogis Real Audio 220 - 32 keys IR */
+IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = {
+       [0x1c] = KEY_RADIO,
+       [0x12] = KEY_POWER2,
+
+       [0x01] = KEY_1,
+       [0x02] = KEY_2,
+       [0x03] = KEY_3,
+       [0x04] = KEY_4,
+       [0x05] = KEY_5,
+       [0x06] = KEY_6,
+       [0x07] = KEY_7,
+       [0x08] = KEY_8,
+       [0x09] = KEY_9,
+       [0x00] = KEY_0,
+
+       [0x0c] = KEY_VOLUMEUP,
+       [0x18] = KEY_VOLUMEDOWN,
+       [0x0b] = KEY_CHANNELUP,
+       [0x15] = KEY_CHANNELDOWN,
+       [0x16] = KEY_ENTER,
+
+       [0x11] = KEY_LIST,              /* Source */
+       [0x0d] = KEY_AUDIO,             /* stereo */
+
+       [0x0f] = KEY_PREVIOUS,          /* Prev */
+       [0x1b] = KEY_PAUSE,             /* Timeshift */
+       [0x1a] = KEY_NEXT,              /* Next */
+
+       [0x0e] = KEY_STOP,
+       [0x1f] = KEY_PLAY,
+       [0x1e] = KEY_PLAYPAUSE,         /* Pause */
+
+       [0x1d] = KEY_RECORD,
+       [0x13] = KEY_MUTE,
+       [0x19] = KEY_SHUFFLE,           /* Snapshot */
+
+};
+EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys);
index d01965e96927b2477530ed666d86001eb68be946..d599d360da3fafcbcd26d72c19419683f1f2c4cb 100644 (file)
@@ -234,7 +234,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
 {
        __le32       *cpu;
-       dma_addr_t   dma_addr;
+       dma_addr_t   dma_addr = 0;
 
        cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
        if (NULL == cpu) {
index cf6a817d50594a21f76721f1c386b1b2d798418c..5b34c134aa25147dc118a3cc44a3ba49365166f6 100644 (file)
@@ -533,7 +533,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
        memcpy(vfd, &device_template, sizeof(struct video_device));
        strlcpy(vfd->name, name, sizeof(vfd->name));
        vfd->release = video_device_release;
-       vfd->priv = dev;
+       video_set_drvdata(vfd, dev);
 
        // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
        if (video_register_device(vfd, type, -1) < 0) {
index 1305b0e63ce5a6b268c5203eb035393d746407a3..12206d75dd4ee968d96213ebe31f75b55fb14ba5 100644 (file)
@@ -170,6 +170,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
        b[0] = REG_LO1B1;
        b[1] = 0xFF;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
        mt2060_writeregs(priv,b,2);
 
        freq = params->frequency / 1000; // Hz -> kHz
@@ -233,6 +236,9 @@ static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
                i++;
        } while (i<10);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
        return ret;
 }
 
@@ -296,13 +302,35 @@ static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
 static int mt2060_init(struct dvb_frontend *fe)
 {
        struct mt2060_priv *priv = fe->tuner_priv;
-       return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33);
+       int ret;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+       ret = mt2060_writereg(priv, REG_VGAG,
+                             (priv->cfg->clock_out << 6) | 0x33);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+       return ret;
 }
 
 static int mt2060_sleep(struct dvb_frontend *fe)
 {
        struct mt2060_priv *priv = fe->tuner_priv;
-       return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
+       int ret;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
+       ret = mt2060_writereg(priv, REG_VGAG,
+                             (priv->cfg->clock_out << 6) | 0x30);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
+       return ret;
 }
 
 static int mt2060_release(struct dvb_frontend *fe)
@@ -344,6 +372,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter
        priv->i2c      = i2c;
        priv->if1_freq = if1;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
+
        if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
                kfree(priv);
                return NULL;
@@ -360,6 +391,9 @@ struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter
 
        mt2060_calibrate(priv);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
+
        return fe;
 }
 EXPORT_SYMBOL(mt2060_attach);
index cb25e43502fe5922d69a163c69172a1a32a7ae21..64379f2bf2370eaf221d33aea24a7c946ab75f5a 100644 (file)
@@ -979,7 +979,6 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
        switch (instance) {
        case 0:
                goto fail;
-               break;
        case 1:
                /* new tuner instance */
                state->config = cfg;
index 93063c6fbbf634e42aac29b3502de2b66104e232..1b48b5d0bf1ef7a708a92131d120684c98750b43 100644 (file)
@@ -1155,7 +1155,6 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
        switch (instance) {
        case 0:
                goto fail;
-               break;
        case 1:
                /* new tuner instance */
                priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
index 8555d9cf9051031f7643675b4487e65461553d1b..4a74f65e759aad5bc622ed7178cd13f1e2416f0c 100644 (file)
@@ -447,17 +447,19 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
                        else
                                arg = 0;
                }
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
-                                                               gp_func, arg);
+               if (fe->callback)
+                       fe->callback(priv->i2c_adap->algo_data,
+                                    DVB_FRONTEND_COMPONENT_TUNER,
+                                    gp_func, arg);
                buf[1] = high ? 0 : 1;
                if (priv->cfg->config == 2)
                        buf[1] = high ? 1 : 0;
                i2c_transfer(priv->i2c_adap, &msg, 1);
                break;
        case 3: /* switch with GPIO of saa713x */
-               if (priv->cfg->tuner_callback)
-                       priv->cfg->tuner_callback(priv->i2c_adap->algo_data, 0, high);
+               if (fe->callback)
+                       fe->callback(priv->i2c_adap->algo_data,
+                                    DVB_FRONTEND_COMPONENT_TUNER, 0, high);
                break;
        }
 }
index 7850a9a1dc8f42a04a0e2c19496b894aeb8611a6..7d72ce0a0c2df925263fcfce42d5561990aa7745 100644 (file)
@@ -36,7 +36,6 @@ struct tda827x_config
        /* interface to tda829x driver */
        unsigned int config;
        int          switch_addr;
-       int (*tuner_callback) (void *dev, int command, int arg);
 
        void (*agcf)(struct dvb_frontend *fe);
 };
index 91204d3f282dfc5de1c02c7c9b9ad6c62959ff13..c112bdd4e0f04a89a7ffe60fdaa143e6721339f8 100644 (file)
@@ -672,10 +672,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
        priv->i2c_props.addr     = i2c_addr;
        priv->i2c_props.adap     = i2c_adap;
        priv->i2c_props.name     = "tda829x";
-       if (cfg) {
+       if (cfg)
                priv->cfg.config         = cfg->lna_cfg;
-               priv->cfg.tuner_callback = cfg->tuner_callback;
-       }
 
        if (tda8290_probe(&priv->i2c_props) == 0) {
                priv->ver = TDA8290;
index aa074f3f0c07f247db9e74a6fe4e636488ad0d47..7e288b26fcc3c5f0a9665a8159027c1d8dbd73c7 100644 (file)
@@ -22,7 +22,6 @@
 
 struct tda829x_config {
        unsigned int lna_cfg;
-       int (*tuner_callback) (void *dev, int command, int arg);
 
        unsigned int probe_tuner:1;
 #define TDA829X_PROBE_TUNER 0
index 72abf0b73486d19c3e69e4330b0213f1d963a9f3..ff1788cc5d48ef6068a9759dd61061388e299445 100644 (file)
@@ -686,7 +686,6 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
        case 0:
                mutex_unlock(&tda9887_list_mutex);
                return NULL;
-               break;
        case 1:
                fe->analog_demod_priv = priv;
                priv->mode = T_STANDBY;
index aa773a658a2a3e3c0d7caae7cb2d3b783ff8b10d..2a1aac1cc7552d33ec72e55073d873d72e323ce7 100644 (file)
@@ -142,6 +142,7 @@ static inline int tuner_stereo(const int type, const int status)
        case TUNER_PHILIPS_FM1236_MK3:
        case TUNER_PHILIPS_FM1256_IH3:
        case TUNER_LG_NTSC_TAPE:
+       case TUNER_TCL_MF02GIP_5N:
                return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
        default:
                return status & TUNER_STEREO;
@@ -494,6 +495,7 @@ static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
        case TUNER_PHILIPS_FMD1216ME_MK3:
        case TUNER_LG_NTSC_TAPE:
        case TUNER_PHILIPS_FM1256_IH3:
+       case TUNER_TCL_MF02GIP_5N:
                buffer[3] = 0x19;
                break;
        case TUNER_TNF_5335MF:
@@ -1038,7 +1040,6 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
        case 0:
                mutex_unlock(&tuner_simple_list_mutex);
                return NULL;
-               break;
        case 1:
                fe->tuner_priv = priv;
 
index 10dddca8b5d1817ede0be39bab500c2841c5ea4e..04961a1f44be66145f929dbc1f5cb2599371c41e 100644 (file)
@@ -1216,6 +1216,23 @@ static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
        },
 };
 
+/* ------------ TUNER_TCL_MF02GIP-5N-E - TCL MF02GIP-5N ------------ */
+
+static struct tuner_range tuner_tcl_mf02gip_5n_ntsc_ranges[] = {
+       { 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
+       { 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
+       { 16 * 999.99        , 0x8e, 0x04, },
+};
+
+static struct tuner_params tuner_tcl_mf02gip_5n_params[] = {
+       {
+               .type   = TUNER_PARAM_TYPE_NTSC,
+               .ranges = tuner_tcl_mf02gip_5n_ntsc_ranges,
+               .count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_ntsc_ranges),
+               .cb_first_if_lower_freq = 1,
+       },
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1641,6 +1658,11 @@ struct tunertype tuners[] = {
                .name   = "Xceive 5000 tuner",
                /* see xc5000.c for details */
        },
+       [TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
+               .name   = "TCL tuner MF02GIP-5N-E",
+               .params = tuner_tcl_mf02gip_5n_params,
+               .count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
+       },
 };
 EXPORT_SYMBOL(tuners);
 
index 4dd1d2421cc529fde892a6204b02dd725d25f277..b65e6803e6c64983d07f4d6c7a00d1e2fefbb96e 100644 (file)
@@ -71,9 +71,6 @@ struct firmware_properties {
 struct xc2028_data {
        struct list_head        hybrid_tuner_instance_list;
        struct tuner_i2c_props  i2c_props;
-       int                     (*tuner_callback) (void *dev,
-                                                  int command, int arg);
-       void                    *video_dev;
        __u32                   frequency;
 
        struct firmware_description *firm;
@@ -492,6 +489,23 @@ ret:
        return i;
 }
 
+static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg)
+{
+       struct xc2028_data *priv = fe->tuner_priv;
+
+       /* analog side (tuner-core) uses i2c_adap->algo_data.
+        * digital side is not guaranteed to have algo_data defined.
+        *
+        * digital side will always have fe->dvb defined.
+        * analog side (tuner-core) doesn't (yet) define fe->dvb.
+        */
+
+       return (!fe->callback) ? -EINVAL :
+               fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+                               fe->dvb->priv : priv->i2c_props.adap->algo_data,
+                            DVB_FRONTEND_COMPONENT_TUNER, cmd, arg);
+}
+
 static int load_firmware(struct dvb_frontend *fe, unsigned int type,
                         v4l2_std_id *id)
 {
@@ -530,8 +544,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
 
                if (!size) {
                        /* Special callback command received */
-                       rc = priv->tuner_callback(priv->video_dev,
-                                                 XC2028_TUNER_RESET, 0);
+                       rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
                        if (rc < 0) {
                                tuner_err("Error at RESET code %d\n",
                                           (*p) & 0x7f);
@@ -542,8 +555,7 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
                if (size >= 0xff00) {
                        switch (size) {
                        case 0xff00:
-                               rc = priv->tuner_callback(priv->video_dev,
-                                                       XC2028_RESET_CLK, 0);
+                               rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0);
                                if (rc < 0) {
                                        tuner_err("Error at RESET code %d\n",
                                                  (*p) & 0x7f);
@@ -715,8 +727,7 @@ retry:
        memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
 
        /* Reset is needed before loading firmware */
-       rc = priv->tuner_callback(priv->video_dev,
-                                 XC2028_TUNER_RESET, 0);
+       rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
        if (rc < 0)
                goto fail;
 
@@ -933,7 +944,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
           The reset CLK is needed only with tm6000.
           Driver should work fine even if this fails.
         */
-       priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
+       do_tuner_callback(fe, XC2028_RESET_CLK, 1);
 
        msleep(10);
 
@@ -1002,11 +1013,6 @@ static int xc2028_set_params(struct dvb_frontend *fe,
 
        tuner_dbg("%s called\n", __func__);
 
-       if (priv->ctrl.d2633)
-               type |= D2633;
-       else
-               type |= D2620;
-
        switch(fe->ops.info.type) {
        case FE_OFDM:
                bw = p->u.ofdm.bandwidth;
@@ -1021,10 +1027,8 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                break;
        case FE_ATSC:
                bw = BANDWIDTH_6_MHZ;
-               /* The only ATSC firmware (at least on v2.7) is D2633,
-                  so overrides ctrl->d2633 */
-               type |= ATSC| D2633;
-               type &= ~D2620;
+               /* The only ATSC firmware (at least on v2.7) is D2633 */
+               type |= ATSC | D2633;
                break;
        /* DVB-S is not supported */
        default:
@@ -1057,6 +1061,28 @@ static int xc2028_set_params(struct dvb_frontend *fe,
                tuner_err("error: bandwidth not supported.\n");
        };
 
+       /*
+         Selects between D2633 or D2620 firmware.
+         It doesn't make sense for ATSC, since it should be D2633 on all cases
+        */
+       if (fe->ops.info.type != FE_ATSC) {
+               switch (priv->ctrl.type) {
+               case XC2028_D2633:
+                       type |= D2633;
+                       break;
+               case XC2028_D2620:
+                       type |= D2620;
+                       break;
+               case XC2028_AUTO:
+               default:
+                       /* Zarlink seems to need D2633 */
+                       if (priv->ctrl.demod == XC3028_FE_ZARLINK456)
+                               type |= D2633;
+                       else
+                               type |= D2620;
+               }
+       }
+
        /* All S-code tables need a 200kHz shift */
        if (priv->ctrl.demod)
                demod = priv->ctrl.demod + 200;
@@ -1177,20 +1203,10 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
                break;
        case 1:
                /* new tuner instance */
-               priv->tuner_callback = cfg->callback;
                priv->ctrl.max_len = 13;
 
                mutex_init(&priv->lock);
 
-               /* analog side (tuner-core) uses i2c_adap->algo_data.
-                * digital side is not guaranteed to have algo_data defined.
-                *
-                * digital side will always have fe->dvb defined.
-                * analog side (tuner-core) doesn't (yet) define fe->dvb.
-                */
-               priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
-                                  fe->dvb->priv : cfg->i2c_adap->algo_data;
-
                fe->tuner_priv = priv;
                break;
        case 2:
index 2c5b6282b569203d8551cbcb23ff4e727318d756..19de7928a74eb75b5a01177a633acdf7e7768559 100644 (file)
 #define        XC3028_FE_ZARLINK456    4560
 #define        XC3028_FE_CHINA         5200
 
+enum firmware_type {
+       XC2028_AUTO = 0,        /* By default, auto-detects */
+       XC2028_D2633,
+       XC2028_D2620,
+};
+
 struct xc2028_ctrl {
        char                    *fname;
        int                     max_len;
        unsigned int            scode_table;
        unsigned int            mts   :1;
-       unsigned int            d2633 :1;
        unsigned int            input1:1;
        unsigned int            vhfbw7:1;
        unsigned int            uhfbw8:1;
        unsigned int            demod;
+       enum firmware_type      type:2;
 };
 
 struct xc2028_config {
        struct i2c_adapter *i2c_adap;
        u8                 i2c_addr;
-       void               *video_dev;
        struct xc2028_ctrl *ctrl;
-       int                (*callback) (void *dev, int command, int arg);
 };
 
 /* xc2028 commands for callback */
index dcddfa803a75597b00d97e40f734203a4fdc8952..f9c2bb917f54b5fe701268e527464491d2b19784 100644 (file)
@@ -30,7 +30,7 @@
 #include "dvb_frontend.h"
 
 #include "xc5000.h"
-#include "xc5000_priv.h"
+#include "tuner-i2c.h"
 
 static int debug;
 module_param(debug, int, 0644);
@@ -40,12 +40,26 @@ static int xc5000_load_fw_on_attach;
 module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
 MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
 
+static DEFINE_MUTEX(xc5000_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
 #define dprintk(level,fmt, arg...) if (debug >= level) \
        printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
 
 #define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
 #define XC5000_DEFAULT_FIRMWARE_SIZE 12332
 
+struct xc5000_priv {
+       struct tuner_i2c_props i2c_props;
+       struct list_head hybrid_tuner_instance_list;
+
+       u32 if_khz;
+       u32 freq_hz;
+       u32 bandwidth;
+       u8  video_standard;
+       u8  rf_mode;
+};
+
 /* Misc Defines */
 #define MAX_TV_STANDARD                        23
 #define XC_MAX_I2C_WRITE_LENGTH                64
@@ -216,9 +230,12 @@ static void xc5000_TunerReset(struct dvb_frontend *fe)
 
        dprintk(1, "%s()\n", __func__);
 
-       if (priv->cfg->tuner_callback) {
-               ret = priv->cfg->tuner_callback(priv->devptr,
-                                               XC5000_TUNER_RESET, 0);
+       if (fe->callback) {
+               ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+                                          fe->dvb->priv :
+                                          priv->i2c_props.adap->algo_data,
+                                          DVB_FRONTEND_COMPONENT_TUNER,
+                                          XC5000_TUNER_RESET, 0);
                if (ret)
                        printk(KERN_ERR "xc5000: reset failed\n");
        } else
@@ -509,13 +526,13 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
        u8 buf[2] = { reg >> 8, reg & 0xff };
        u8 bval[2] = { 0, 0 };
        struct i2c_msg msg[2] = {
-               { .addr = priv->cfg->i2c_address,
+               { .addr = priv->i2c_props.addr,
                        .flags = 0, .buf = &buf[0], .len = 2 },
-               { .addr = priv->cfg->i2c_address,
+               { .addr = priv->i2c_props.addr,
                        .flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
        };
 
-       if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+       if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
                printk(KERN_WARNING "xc5000: I2C read failed\n");
                return -EREMOTEIO;
        }
@@ -526,10 +543,10 @@ static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
 
 static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
 {
-       struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+       struct i2c_msg msg = { .addr = priv->i2c_props.addr,
                .flags = 0, .buf = buf, .len = len };
 
-       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+       if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
                printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
                        (int)len);
                return -EREMOTEIO;
@@ -539,10 +556,10 @@ static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
 
 static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
 {
-       struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
+       struct i2c_msg msg = { .addr = priv->i2c_props.addr,
                .flags = I2C_M_RD, .buf = buf, .len = len };
 
-       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+       if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
                printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
                return -EREMOTEIO;
        }
@@ -559,7 +576,7 @@ static int xc5000_fwupload(struct dvb_frontend* fe)
        printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
                XC5000_DEFAULT_FIRMWARE);
 
-       ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
+       ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c_props.adap->dev);
        if (ret) {
                printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
                ret = XC_RESULT_RESET_FAILURE;
@@ -675,10 +692,10 @@ static int xc5000_set_params(struct dvb_frontend *fe,
                return -EREMOTEIO;
        }
 
-       ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
+       ret = xc_set_IF_frequency(priv, priv->if_khz);
        if (ret != XC_RESULT_SUCCESS) {
                printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
-                       priv->cfg->if_khz);
+                      priv->if_khz);
                return -EIO;
        }
 
@@ -897,9 +914,19 @@ static int xc5000_init(struct dvb_frontend *fe)
 
 static int xc5000_release(struct dvb_frontend *fe)
 {
+       struct xc5000_priv *priv = fe->tuner_priv;
+
        dprintk(1, "%s()\n", __func__);
-       kfree(fe->tuner_priv);
+
+       mutex_lock(&xc5000_list_mutex);
+
+       if (priv)
+               hybrid_tuner_release_state(priv);
+
+       mutex_unlock(&xc5000_list_mutex);
+
        fe->tuner_priv = NULL;
+
        return 0;
 }
 
@@ -924,29 +951,43 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
 
 struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                                   struct i2c_adapter *i2c,
-                                  struct xc5000_config *cfg, void *devptr)
+                                  struct xc5000_config *cfg)
 {
        struct xc5000_priv *priv = NULL;
+       int instance;
        u16 id = 0;
 
-       dprintk(1, "%s()\n", __func__);
+       dprintk(1, "%s(%d-%04x)\n", __func__,
+               i2c ? i2c_adapter_id(i2c) : -1,
+               cfg ? cfg->i2c_address : -1);
 
-       priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
-       if (priv == NULL)
-               return NULL;
+       mutex_lock(&xc5000_list_mutex);
 
-       priv->cfg = cfg;
-       priv->bandwidth = BANDWIDTH_6_MHZ;
-       priv->i2c = i2c;
-       priv->devptr = devptr;
+       instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
+                                             hybrid_tuner_instance_list,
+                                             i2c, cfg->i2c_address, "xc5000");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
+               priv->bandwidth = BANDWIDTH_6_MHZ;
+               priv->if_khz = cfg->if_khz;
+
+               fe->tuner_priv = priv;
+               break;
+       default:
+               /* existing tuner instance */
+               fe->tuner_priv = priv;
+               break;
+       }
 
        /* Check if firmware has been loaded. It is possible that another
           instance of the driver has loaded the firmware.
         */
-       if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
-               kfree(priv);
-               return NULL;
-       }
+       if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
+               goto fail;
 
        switch(id) {
        case XC_PRODUCT_ID_FW_LOADED:
@@ -967,19 +1008,23 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                printk(KERN_ERR
                        "xc5000: Device not found at addr 0x%02x (0x%x)\n",
                        cfg->i2c_address, id);
-               kfree(priv);
-               return NULL;
+               goto fail;
        }
 
+       mutex_unlock(&xc5000_list_mutex);
+
        memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
                sizeof(struct dvb_tuner_ops));
 
-       fe->tuner_priv = priv;
-
        if (xc5000_load_fw_on_attach)
                xc5000_init(fe);
 
        return fe;
+fail:
+       mutex_unlock(&xc5000_list_mutex);
+
+       xc5000_release(fe);
+       return NULL;
 }
 EXPORT_SYMBOL(xc5000_attach);
 
index 5389f740945ae82133bf3f53d07872a13d7b59e6..cf1a558e0e7f73c40cd8525f559563496bcef82f 100644 (file)
@@ -30,8 +30,6 @@ struct i2c_adapter;
 struct xc5000_config {
        u8   i2c_address;
        u32  if_khz;
-
-       int  (*tuner_callback) (void *priv, int command, int arg);
 };
 
 /* xc5000 callback command */
@@ -49,13 +47,11 @@ struct xc5000_config {
     (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
 extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
-                                         struct xc5000_config *cfg,
-                                         void *devptr);
+                                         struct xc5000_config *cfg);
 #else
 static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
                                                 struct i2c_adapter *i2c,
-                                                struct xc5000_config *cfg,
-                                                void *devptr)
+                                                struct xc5000_config *cfg)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h
deleted file mode 100644 (file)
index b2a0074..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef XC5000_PRIV_H
-#define XC5000_PRIV_H
-
-struct xc5000_priv {
-       struct xc5000_config *cfg;
-       struct i2c_adapter   *i2c;
-
-       u32 freq_hz;
-       u32 bandwidth;
-       u8  video_standard;
-       u8  rf_mode;
-
-       void *devptr;
-};
-
-#endif
index 8bc1445bd33bda02d7c4d1bc6e5413aa375b51a7..0bcd852576d686a2b556b05e72467d687d49181d 100644 (file)
@@ -20,7 +20,6 @@ comment "Supported USB Adapters"
 source "drivers/media/dvb/dvb-usb/Kconfig"
 source "drivers/media/dvb/ttusb-budget/Kconfig"
 source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/cinergyT2/Kconfig"
 source "drivers/media/dvb/siano/Kconfig"
 
 comment "Supported FlexCopII (B2C2) Adapters"
@@ -35,6 +34,10 @@ comment "Supported Pluto2 Adapters"
        depends on DVB_CORE && PCI && I2C
 source "drivers/media/dvb/pluto2/Kconfig"
 
+comment "Supported SDMC DM1105 Adapters"
+       depends on DVB_CORE && PCI && I2C
+source "drivers/media/dvb/dm1105/Kconfig"
+
 comment "Supported DVB Frontends"
        depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
index d6ba4d19520189b1606d7bedc595c26283e75518..f91e9eb15e52effa8e9f15d1e0e2e4573beeae59 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
index a91ed28f03a41d815f9edc2f32b7805535cf8ce1..26f0011a507813a0564b741ba7040a7c579fe8fc 100644 (file)
@@ -10,7 +10,7 @@
 int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
 {
        u8 *tcpu;
-       dma_addr_t tdma;
+       dma_addr_t tdma = 0;
 
        if (size % 2) {
                err("dma buffersize has to be even.");
index 6afbfbbef0ce304885826365df8a40735c9a5ee7..48762a2b9e42e340c63f94534a171052e5b7f103 100644 (file)
@@ -702,7 +702,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        }
 
        if (card->fe == NULL)
-               printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+               printk("dvb-bt8xx: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       card->bt->dev->vendor,
                       card->bt->dev->device,
                       card->bt->dev->subsystem_vendor,
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
deleted file mode 100644 (file)
index c03513b..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-config DVB_CINERGYT2
-       tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver"
-       depends on DVB_CORE && USB && INPUT
-       help
-         Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
-
-         Say Y if you own such a device and want to use it.
-
-
-config DVB_CINERGYT2_TUNING
-       bool "sophisticated fine-tuning for CinergyT2 cards"
-       depends on DVB_CINERGYT2
-       help
-         Here you can fine-tune some parameters of the CinergyT2 driver.
-
-         Normally you don't need to touch this, but in exotic setups you
-         may fine-tune your setup and adjust e.g. DMA buffer sizes for
-         a particular application.
-
-
-config DVB_CINERGYT2_STREAM_URB_COUNT
-       int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
-       depends on DVB_CINERGYT2_TUNING
-       default "32"
-       help
-         USB Request Blocks for Highspeed Stream transfers are scheduled in
-         a queue for the Host Controller.
-
-         Usually the default value is a safe choice.
-
-         You may increase this number if you are using this device in a
-         Server Environment with many high-traffic USB Highspeed devices
-         sharing the same USB bus.
-
-
-config DVB_CINERGYT2_STREAM_BUF_SIZE
-       int "Size of URB Stream Buffers for Highspeed Transfers"
-       depends on DVB_CINERGYT2_TUNING
-       default "512"
-       help
-         Should be a multiple of native buffer size of 512 bytes.
-         Default value is a safe choice.
-
-         You may increase this number if you are using this device in a
-         Server Environment with many high-traffic USB Highspeed devices
-         sharing the same USB bus.
-
-
-config DVB_CINERGYT2_QUERY_INTERVAL
-       int "Status update interval [milliseconds]"
-       depends on DVB_CINERGYT2_TUNING
-       default "250"
-       help
-         This is the interval for status readouts from the demodulator.
-         You may try lower values if you need more responsive signal quality
-         measurements.
-
-         Please keep in mind that these updates cause traffic on the tuner
-         control bus and thus may or may not affect reception sensitivity.
-
-         The default value should be a safe choice for common applications.
-
-
-config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
-       bool "Register the onboard IR Remote Control Receiver as Input Device"
-       depends on DVB_CINERGYT2_TUNING
-       default y
-       help
-         Enable this option if you want to use the onboard Infrared Remote
-         Control Receiver as Linux-Input device.
-
-         Right now only the keycode table for the default Remote Control
-         delivered with the device is supported, please see the driver
-         source code to find out how to add support for other controls.
-
-
-config DVB_CINERGYT2_RC_QUERY_INTERVAL
-       int "Infrared Remote Controller update interval [milliseconds]"
-       depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
-       default "50"
-       help
-         If you have a very fast-repeating remote control you can try lower
-         values, for normal consumer receivers the default value should be
-         a safe choice.
-
diff --git a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile
deleted file mode 100644 (file)
index d762d8c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o
-
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
deleted file mode 100644 (file)
index a824f37..0000000
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- * TerraTec Cinergy T²/qanu USB2 DVB-T adapter.
- *
- * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
- *                 Holger Waechtler <holger@qanu.de>
- *
- *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/dvb/frontend.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-
-#ifdef CONFIG_DVB_CINERGYT2_TUNING
-       #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
-       #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
-       #define QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_QUERY_INTERVAL)
-       #ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
-               #define RC_QUERY_INTERVAL (CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL)
-               #define ENABLE_RC (1)
-       #endif
-#else
-       #define STREAM_URB_COUNT (32)
-       #define STREAM_BUF_SIZE (512)   /* bytes */
-       #define ENABLE_RC (1)
-       #define RC_QUERY_INTERVAL (50)  /* milliseconds */
-       #define QUERY_INTERVAL (333)    /* milliseconds */
-#endif
-
-#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
-
-static int debug;
-module_param_named(debug, debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk(level, args...)                                                \
-do {                                                                   \
-       if ((debug & level)) {                                          \
-               printk("%s: %s(): ", KBUILD_MODNAME,                    \
-                      __func__);                                       \
-               printk(args); }                                         \
-} while (0)
-
-enum cinergyt2_ep1_cmd {
-       CINERGYT2_EP1_PID_TABLE_RESET           = 0x01,
-       CINERGYT2_EP1_PID_SETUP                 = 0x02,
-       CINERGYT2_EP1_CONTROL_STREAM_TRANSFER   = 0x03,
-       CINERGYT2_EP1_SET_TUNER_PARAMETERS      = 0x04,
-       CINERGYT2_EP1_GET_TUNER_STATUS          = 0x05,
-       CINERGYT2_EP1_START_SCAN                = 0x06,
-       CINERGYT2_EP1_CONTINUE_SCAN             = 0x07,
-       CINERGYT2_EP1_GET_RC_EVENTS             = 0x08,
-       CINERGYT2_EP1_SLEEP_MODE                = 0x09
-};
-
-struct dvbt_set_parameters_msg {
-       uint8_t cmd;
-       __le32 freq;
-       uint8_t bandwidth;
-       __le16 tps;
-       uint8_t flags;
-} __attribute__((packed));
-
-struct dvbt_get_status_msg {
-       __le32 freq;
-       uint8_t bandwidth;
-       __le16 tps;
-       uint8_t flags;
-       __le16 gain;
-       uint8_t snr;
-       __le32 viterbi_error_rate;
-       __le32 rs_error_rate;
-       __le32 uncorrected_block_count;
-       uint8_t lock_bits;
-       uint8_t prev_lock_bits;
-} __attribute__((packed));
-
-static struct dvb_frontend_info cinergyt2_fe_info = {
-       .name = DRIVER_NAME,
-       .type = FE_OFDM,
-       .frequency_min = 174000000,
-       .frequency_max = 862000000,
-       .frequency_stepsize = 166667,
-       .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
-               FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
-               FE_CAN_FEC_AUTO |
-               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-               FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-               FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS
-};
-
-struct cinergyt2 {
-       struct dvb_demux demux;
-       struct usb_device *udev;
-       struct mutex sem;
-       struct mutex wq_sem;
-       struct dvb_adapter adapter;
-       struct dvb_device *fedev;
-       struct dmxdev dmxdev;
-       struct dvb_net dvbnet;
-
-       int streaming;
-       int sleeping;
-
-       struct dvbt_set_parameters_msg param;
-       struct dvbt_get_status_msg status;
-       struct delayed_work query_work;
-
-       wait_queue_head_t poll_wq;
-       int pending_fe_events;
-       int disconnect_pending;
-       unsigned int uncorrected_block_count;
-       atomic_t inuse;
-
-       void *streambuf;
-       dma_addr_t streambuf_dmahandle;
-       struct urb *stream_urb [STREAM_URB_COUNT];
-
-#ifdef ENABLE_RC
-       struct input_dev *rc_input_dev;
-       char phys[64];
-       struct delayed_work rc_query_work;
-       int rc_input_event;
-       __le32 rc_last_code;
-       unsigned long last_event_jiffies;
-#endif
-};
-
-enum {
-       CINERGYT2_RC_EVENT_TYPE_NONE = 0x00,
-       CINERGYT2_RC_EVENT_TYPE_NEC  = 0x01,
-       CINERGYT2_RC_EVENT_TYPE_RC5  = 0x02
-};
-
-struct cinergyt2_rc_event {
-       char type;
-       __le32 value;
-} __attribute__((packed));
-
-static const uint32_t rc_keys[] = {
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xfe01eb04,     KEY_POWER,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xfd02eb04,     KEY_1,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xfc03eb04,     KEY_2,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xfb04eb04,     KEY_3,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xfa05eb04,     KEY_4,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf906eb04,     KEY_5,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf807eb04,     KEY_6,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf708eb04,     KEY_7,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf609eb04,     KEY_8,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf50aeb04,     KEY_9,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf30ceb04,     KEY_0,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf40beb04,     KEY_VIDEO,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf20deb04,     KEY_REFRESH,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf10eeb04,     KEY_SELECT,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xf00feb04,     KEY_EPG,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xef10eb04,     KEY_UP,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xeb14eb04,     KEY_DOWN,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xee11eb04,     KEY_LEFT,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xec13eb04,     KEY_RIGHT,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xed12eb04,     KEY_OK,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xea15eb04,     KEY_TEXT,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe916eb04,     KEY_INFO,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe817eb04,     KEY_RED,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe718eb04,     KEY_GREEN,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe619eb04,     KEY_YELLOW,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe51aeb04,     KEY_BLUE,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe31ceb04,     KEY_VOLUMEUP,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe11eeb04,     KEY_VOLUMEDOWN,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe21deb04,     KEY_MUTE,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe41beb04,     KEY_CHANNELUP,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xe01feb04,     KEY_CHANNELDOWN,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xbf40eb04,     KEY_PAUSE,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xb34ceb04,     KEY_PLAY,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xa758eb04,     KEY_RECORD,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xab54eb04,     KEY_PREVIOUS,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xb748eb04,     KEY_STOP,
-       CINERGYT2_RC_EVENT_TYPE_NEC,    0xa35ceb04,     KEY_NEXT
-};
-
-static int cinergyt2_command (struct cinergyt2 *cinergyt2,
-                             char *send_buf, int send_buf_len,
-                             char *recv_buf, int recv_buf_len)
-{
-       int actual_len;
-       char dummy;
-       int ret;
-
-       ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1),
-                          send_buf, send_buf_len, &actual_len, 1000);
-
-       if (ret)
-               dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret);
-
-       if (!recv_buf)
-               recv_buf = &dummy;
-
-       ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1),
-                          recv_buf, recv_buf_len, &actual_len, 1000);
-
-       if (ret)
-               dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret);
-
-       return ret ? ret : actual_len;
-}
-
-static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable)
-{
-       char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
-       cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
-}
-
-static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep)
-{
-       char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 };
-       cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
-       cinergyt2->sleeping = sleep;
-}
-
-static void cinergyt2_stream_irq (struct urb *urb);
-
-static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb)
-{
-       int err;
-
-       usb_fill_bulk_urb(urb,
-                         cinergyt2->udev,
-                         usb_rcvbulkpipe(cinergyt2->udev, 0x2),
-                         urb->transfer_buffer,
-                         STREAM_BUF_SIZE,
-                         cinergyt2_stream_irq,
-                         cinergyt2);
-
-       if ((err = usb_submit_urb(urb, GFP_ATOMIC)))
-               dprintk(1, "urb submission failed (err = %i)!\n", err);
-
-       return err;
-}
-
-static void cinergyt2_stream_irq (struct urb *urb)
-{
-       struct cinergyt2 *cinergyt2 = urb->context;
-
-       if (urb->actual_length > 0)
-               dvb_dmx_swfilter(&cinergyt2->demux,
-                                urb->transfer_buffer, urb->actual_length);
-
-       if (cinergyt2->streaming)
-               cinergyt2_submit_stream_urb(cinergyt2, urb);
-}
-
-static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
-{
-       int i;
-
-       for (i=0; i<STREAM_URB_COUNT; i++)
-               usb_free_urb(cinergyt2->stream_urb[i]);
-
-       usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
-                           cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
-}
-
-static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
-{
-       int i;
-
-       cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
-                                             GFP_KERNEL, &cinergyt2->streambuf_dmahandle);
-       if (!cinergyt2->streambuf) {
-               dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n");
-               return -ENOMEM;
-       }
-
-       memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE);
-
-       for (i=0; i<STREAM_URB_COUNT; i++) {
-               struct urb *urb;
-
-               if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) {
-                       dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n");
-                       cinergyt2_free_stream_urbs(cinergyt2);
-                       return -ENOMEM;
-               }
-
-               urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE;
-               urb->transfer_buffer_length = STREAM_BUF_SIZE;
-
-               cinergyt2->stream_urb[i] = urb;
-       }
-
-       return 0;
-}
-
-static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
-{
-       int i;
-
-       cinergyt2_control_stream_transfer(cinergyt2, 0);
-
-       for (i=0; i<STREAM_URB_COUNT; i++)
-               usb_kill_urb(cinergyt2->stream_urb[i]);
-}
-
-static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2)
-{
-       int i, err;
-
-       for (i=0; i<STREAM_URB_COUNT; i++) {
-               if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) {
-                       cinergyt2_stop_stream_xfer(cinergyt2);
-                       dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err);
-                       return err;
-               }
-       }
-
-       cinergyt2_control_stream_transfer(cinergyt2, 1);
-       return 0;
-}
-
-static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       struct dvb_demux *demux = dvbdmxfeed->demux;
-       struct cinergyt2 *cinergyt2 = demux->priv;
-
-       if (cinergyt2->disconnect_pending)
-               return -EAGAIN;
-       if (mutex_lock_interruptible(&cinergyt2->sem))
-               return -ERESTARTSYS;
-
-       if (cinergyt2->streaming == 0)
-               cinergyt2_start_stream_xfer(cinergyt2);
-
-       cinergyt2->streaming++;
-       mutex_unlock(&cinergyt2->sem);
-       return 0;
-}
-
-static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       struct dvb_demux *demux = dvbdmxfeed->demux;
-       struct cinergyt2 *cinergyt2 = demux->priv;
-
-       if (cinergyt2->disconnect_pending)
-               return -EAGAIN;
-       if (mutex_lock_interruptible(&cinergyt2->sem))
-               return -ERESTARTSYS;
-
-       if (--cinergyt2->streaming == 0)
-               cinergyt2_stop_stream_xfer(cinergyt2);
-
-       mutex_unlock(&cinergyt2->sem);
-       return 0;
-}
-
-/**
- *  convert linux-dvb frontend parameter set into TPS.
- *  See ETSI ETS-300744, section 4.6.2, table 9 for details.
- *
- *  This function is probably reusable and may better get placed in a support
- *  library.
- *
- *  We replace errornous fields by default TPS fields (the ones with value 0).
- */
-static uint16_t compute_tps (struct dvb_frontend_parameters *p)
-{
-       struct dvb_ofdm_parameters *op = &p->u.ofdm;
-       uint16_t tps = 0;
-
-       switch (op->code_rate_HP) {
-               case FEC_2_3:
-                       tps |= (1 << 7);
-                       break;
-               case FEC_3_4:
-                       tps |= (2 << 7);
-                       break;
-               case FEC_5_6:
-                       tps |= (3 << 7);
-                       break;
-               case FEC_7_8:
-                       tps |= (4 << 7);
-                       break;
-               case FEC_1_2:
-               case FEC_AUTO:
-               default:
-                       /* tps |= (0 << 7) */;
-       }
-
-       switch (op->code_rate_LP) {
-               case FEC_2_3:
-                       tps |= (1 << 4);
-                       break;
-               case FEC_3_4:
-                       tps |= (2 << 4);
-                       break;
-               case FEC_5_6:
-                       tps |= (3 << 4);
-                       break;
-               case FEC_7_8:
-                       tps |= (4 << 4);
-                       break;
-               case FEC_1_2:
-               case FEC_AUTO:
-               default:
-                       /* tps |= (0 << 4) */;
-       }
-
-       switch (op->constellation) {
-               case QAM_16:
-                       tps |= (1 << 13);
-                       break;
-               case QAM_64:
-                       tps |= (2 << 13);
-                       break;
-               case QPSK:
-               default:
-                       /* tps |= (0 << 13) */;
-       }
-
-       switch (op->transmission_mode) {
-               case TRANSMISSION_MODE_8K:
-                       tps |= (1 << 0);
-                       break;
-               case TRANSMISSION_MODE_2K:
-               default:
-                       /* tps |= (0 << 0) */;
-       }
-
-       switch (op->guard_interval) {
-               case GUARD_INTERVAL_1_16:
-                       tps |= (1 << 2);
-                       break;
-               case GUARD_INTERVAL_1_8:
-                       tps |= (2 << 2);
-                       break;
-               case GUARD_INTERVAL_1_4:
-                       tps |= (3 << 2);
-                       break;
-               case GUARD_INTERVAL_1_32:
-               default:
-                       /* tps |= (0 << 2) */;
-       }
-
-       switch (op->hierarchy_information) {
-               case HIERARCHY_1:
-                       tps |= (1 << 10);
-                       break;
-               case HIERARCHY_2:
-                       tps |= (2 << 10);
-                       break;
-               case HIERARCHY_4:
-                       tps |= (3 << 10);
-                       break;
-               case HIERARCHY_NONE:
-               default:
-                       /* tps |= (0 << 10) */;
-       }
-
-       return tps;
-}
-
-static int cinergyt2_open (struct inode *inode, struct file *file)
-{
-       struct dvb_device *dvbdev = file->private_data;
-       struct cinergyt2 *cinergyt2 = dvbdev->priv;
-       int err = -EAGAIN;
-
-       if (cinergyt2->disconnect_pending)
-               goto out;
-       err = mutex_lock_interruptible(&cinergyt2->wq_sem);
-       if (err)
-               goto out;
-
-       err = mutex_lock_interruptible(&cinergyt2->sem);
-       if (err)
-               goto out_unlock1;
-
-       if ((err = dvb_generic_open(inode, file)))
-               goto out_unlock2;
-
-       if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-               cinergyt2_sleep(cinergyt2, 0);
-               schedule_delayed_work(&cinergyt2->query_work, HZ/2);
-       }
-
-       atomic_inc(&cinergyt2->inuse);
-
-out_unlock2:
-       mutex_unlock(&cinergyt2->sem);
-out_unlock1:
-       mutex_unlock(&cinergyt2->wq_sem);
-out:
-       return err;
-}
-
-static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
-{
-       dvb_net_release(&cinergyt2->dvbnet);
-       dvb_dmxdev_release(&cinergyt2->dmxdev);
-       dvb_dmx_release(&cinergyt2->demux);
-       dvb_unregister_device(cinergyt2->fedev);
-       dvb_unregister_adapter(&cinergyt2->adapter);
-
-       cinergyt2_free_stream_urbs(cinergyt2);
-       kfree(cinergyt2);
-}
-
-static int cinergyt2_release (struct inode *inode, struct file *file)
-{
-       struct dvb_device *dvbdev = file->private_data;
-       struct cinergyt2 *cinergyt2 = dvbdev->priv;
-
-       mutex_lock(&cinergyt2->wq_sem);
-
-       if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
-               cancel_rearming_delayed_work(&cinergyt2->query_work);
-
-               mutex_lock(&cinergyt2->sem);
-               cinergyt2_sleep(cinergyt2, 1);
-               mutex_unlock(&cinergyt2->sem);
-       }
-
-       mutex_unlock(&cinergyt2->wq_sem);
-
-       if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
-               warn("delayed unregister in release");
-               cinergyt2_unregister(cinergyt2);
-       }
-
-       return dvb_generic_release(inode, file);
-}
-
-static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait)
-{
-       struct dvb_device *dvbdev = file->private_data;
-       struct cinergyt2 *cinergyt2 = dvbdev->priv;
-       unsigned int mask = 0;
-
-       if (cinergyt2->disconnect_pending)
-               return -EAGAIN;
-       if (mutex_lock_interruptible(&cinergyt2->sem))
-               return -ERESTARTSYS;
-
-       poll_wait(file, &cinergyt2->poll_wq, wait);
-
-       if (cinergyt2->pending_fe_events != 0)
-               mask |= (POLLIN | POLLRDNORM | POLLPRI);
-
-       mutex_unlock(&cinergyt2->sem);
-
-       return mask;
-}
-
-
-static int cinergyt2_ioctl (struct inode *inode, struct file *file,
-                    unsigned cmd, unsigned long arg)
-{
-       struct dvb_device *dvbdev = file->private_data;
-       struct cinergyt2 *cinergyt2 = dvbdev->priv;
-       struct dvbt_get_status_msg *stat = &cinergyt2->status;
-       fe_status_t status = 0;
-
-       switch (cmd) {
-       case FE_GET_INFO:
-               return copy_to_user((void __user*) arg, &cinergyt2_fe_info,
-                                   sizeof(struct dvb_frontend_info));
-
-       case FE_READ_STATUS:
-               if (0xffff - le16_to_cpu(stat->gain) > 30)
-                       status |= FE_HAS_SIGNAL;
-               if (stat->lock_bits & (1 << 6))
-                       status |= FE_HAS_LOCK;
-               if (stat->lock_bits & (1 << 5))
-                       status |= FE_HAS_SYNC;
-               if (stat->lock_bits & (1 << 4))
-                       status |= FE_HAS_CARRIER;
-               if (stat->lock_bits & (1 << 1))
-                       status |= FE_HAS_VITERBI;
-
-               return copy_to_user((void  __user*) arg, &status, sizeof(status));
-
-       case FE_READ_BER:
-               return put_user(le32_to_cpu(stat->viterbi_error_rate),
-                               (__u32 __user *) arg);
-
-       case FE_READ_SIGNAL_STRENGTH:
-               return put_user(0xffff - le16_to_cpu(stat->gain),
-                               (__u16 __user *) arg);
-
-       case FE_READ_SNR:
-               return put_user((stat->snr << 8) | stat->snr,
-                               (__u16 __user *) arg);
-
-       case FE_READ_UNCORRECTED_BLOCKS:
-       {
-               uint32_t unc_count;
-
-               if (mutex_lock_interruptible(&cinergyt2->sem))
-                       return -ERESTARTSYS;
-               unc_count = cinergyt2->uncorrected_block_count;
-               cinergyt2->uncorrected_block_count = 0;
-               mutex_unlock(&cinergyt2->sem);
-
-               /* UNC are already converted to host byte order... */
-               return put_user(unc_count,(__u32 __user *) arg);
-       }
-       case FE_SET_FRONTEND:
-       {
-               struct dvbt_set_parameters_msg *param = &cinergyt2->param;
-               struct dvb_frontend_parameters p;
-               int err;
-
-               if ((file->f_flags & O_ACCMODE) == O_RDONLY)
-                       return -EPERM;
-
-               if (copy_from_user(&p, (void  __user*) arg, sizeof(p)))
-                       return -EFAULT;
-
-               if (cinergyt2->disconnect_pending)
-                       return -EAGAIN;
-               if (mutex_lock_interruptible(&cinergyt2->sem))
-                       return -ERESTARTSYS;
-
-               param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-               param->tps = cpu_to_le16(compute_tps(&p));
-               param->freq = cpu_to_le32(p.frequency / 1000);
-               param->bandwidth = 8 - p.u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
-
-               stat->lock_bits = 0;
-               cinergyt2->pending_fe_events++;
-               wake_up_interruptible(&cinergyt2->poll_wq);
-
-               err = cinergyt2_command(cinergyt2,
-                                       (char *) param, sizeof(*param),
-                                       NULL, 0);
-
-               mutex_unlock(&cinergyt2->sem);
-
-               return (err < 0) ? err : 0;
-       }
-
-       case FE_GET_FRONTEND:
-               /**
-                *  trivial to implement (see struct dvbt_get_status_msg).
-                *  equivalent to FE_READ ioctls, but needs
-                *  TPS -> linux-dvb parameter set conversion. Feel free
-                *  to implement this and send us a patch if you need this
-                *  functionality.
-                */
-               break;
-
-       case FE_GET_EVENT:
-       {
-               /**
-                *  for now we only fill the status field. the parameters
-                *  are trivial to fill as soon FE_GET_FRONTEND is done.
-                */
-               struct dvb_frontend_event __user *e = (void __user *) arg;
-               if (cinergyt2->pending_fe_events == 0) {
-                       if (file->f_flags & O_NONBLOCK)
-                               return -EWOULDBLOCK;
-                       wait_event_interruptible(cinergyt2->poll_wq,
-                                                cinergyt2->pending_fe_events > 0);
-               }
-               cinergyt2->pending_fe_events = 0;
-               return cinergyt2_ioctl(inode, file, FE_READ_STATUS,
-                                       (unsigned long) &e->status);
-       }
-
-       default:
-               ;
-       }
-
-       return -EINVAL;
-}
-
-static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct dvb_device *dvbdev = file->private_data;
-       struct cinergyt2 *cinergyt2 = dvbdev->priv;
-       int ret = 0;
-
-       lock_kernel();
-
-       if (vma->vm_flags & (VM_WRITE | VM_EXEC)) {
-               ret = -EPERM;
-               goto bailout;
-       }
-
-       if (vma->vm_end > vma->vm_start + STREAM_URB_COUNT * STREAM_BUF_SIZE) {
-               ret = -EINVAL;
-               goto bailout;
-       }
-
-       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
-       vma->vm_file = file;
-
-       ret = remap_pfn_range(vma, vma->vm_start,
-                             virt_to_phys(cinergyt2->streambuf) >> PAGE_SHIFT,
-                             vma->vm_end - vma->vm_start,
-                             vma->vm_page_prot) ? -EAGAIN : 0;
-bailout:
-       unlock_kernel();
-       return ret;
-}
-
-static struct file_operations cinergyt2_fops = {
-       .owner          = THIS_MODULE,
-       .ioctl          = cinergyt2_ioctl,
-       .poll           = cinergyt2_poll,
-       .open           = cinergyt2_open,
-       .release        = cinergyt2_release,
-       .mmap           = cinergyt2_mmap
-};
-
-static struct dvb_device cinergyt2_fe_template = {
-       .users = ~0,
-       .writers = 1,
-       .readers = (~0)-1,
-       .fops = &cinergyt2_fops
-};
-
-#ifdef ENABLE_RC
-
-static void cinergyt2_query_rc (struct work_struct *work)
-{
-       struct cinergyt2 *cinergyt2 =
-               container_of(work, struct cinergyt2, rc_query_work.work);
-       char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
-       struct cinergyt2_rc_event rc_events[12];
-       int n, len, i;
-
-       if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
-               return;
-
-       len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
-                               (char *) rc_events, sizeof(rc_events));
-       if (len < 0)
-               goto out;
-       if (len == 0) {
-               if (time_after(jiffies, cinergyt2->last_event_jiffies +
-                              msecs_to_jiffies(150))) {
-                       /* stop key repeat */
-                       if (cinergyt2->rc_input_event != KEY_MAX) {
-                               dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
-                               input_report_key(cinergyt2->rc_input_dev,
-                                                cinergyt2->rc_input_event, 0);
-                               input_sync(cinergyt2->rc_input_dev);
-                               cinergyt2->rc_input_event = KEY_MAX;
-                       }
-                       cinergyt2->rc_last_code = cpu_to_le32(~0);
-               }
-               goto out;
-       }
-       cinergyt2->last_event_jiffies = jiffies;
-
-       for (n = 0; n < (len / sizeof(rc_events[0])); n++) {
-               dprintk(1, "rc_events[%d].value = %x, type=%x\n",
-                       n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
-
-               if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
-                   rc_events[n].value == cpu_to_le32(~0)) {
-                       /* keyrepeat bit -> just repeat last rc_input_event */
-               } else {
-                       cinergyt2->rc_input_event = KEY_MAX;
-                       for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3) {
-                               if (rc_keys[i + 0] == rc_events[n].type &&
-                                   rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
-                                       cinergyt2->rc_input_event = rc_keys[i + 2];
-                                       break;
-                               }
-                       }
-               }
-
-               if (cinergyt2->rc_input_event != KEY_MAX) {
-                       if (rc_events[n].value == cinergyt2->rc_last_code &&
-                           cinergyt2->rc_last_code != cpu_to_le32(~0)) {
-                               /* emit a key-up so the double event is recognized */
-                               dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
-                               input_report_key(cinergyt2->rc_input_dev,
-                                                cinergyt2->rc_input_event, 0);
-                       }
-                       dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
-                       input_report_key(cinergyt2->rc_input_dev,
-                                        cinergyt2->rc_input_event, 1);
-                       input_sync(cinergyt2->rc_input_dev);
-                       cinergyt2->rc_last_code = rc_events[n].value;
-               }
-       }
-
-out:
-       schedule_delayed_work(&cinergyt2->rc_query_work,
-                             msecs_to_jiffies(RC_QUERY_INTERVAL));
-
-       mutex_unlock(&cinergyt2->sem);
-}
-
-static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
-{
-       struct input_dev *input_dev;
-       int i;
-       int err;
-
-       input_dev = input_allocate_device();
-       if (!input_dev)
-               return -ENOMEM;
-
-       usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
-       strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
-       cinergyt2->rc_input_event = KEY_MAX;
-       cinergyt2->rc_last_code = cpu_to_le32(~0);
-       INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc);
-
-       input_dev->name = DRIVER_NAME " remote control";
-       input_dev->phys = cinergyt2->phys;
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-       for (i = 0; i < ARRAY_SIZE(rc_keys); i += 3)
-               set_bit(rc_keys[i + 2], input_dev->keybit);
-       input_dev->keycodesize = 0;
-       input_dev->keycodemax = 0;
-       input_dev->id.bustype = BUS_USB;
-       input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor);
-       input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct);
-       input_dev->id.version = 1;
-       input_dev->dev.parent = &cinergyt2->udev->dev;
-
-       err = input_register_device(input_dev);
-       if (err) {
-               input_free_device(input_dev);
-               return err;
-       }
-
-       cinergyt2->rc_input_dev = input_dev;
-       schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-
-       return 0;
-}
-
-static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
-{
-       cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
-       input_unregister_device(cinergyt2->rc_input_dev);
-}
-
-static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
-{
-       cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
-}
-
-static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
-{
-       schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
-}
-
-#else
-
-static inline int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) { return 0; }
-static inline void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) { }
-static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2) { }
-static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { }
-
-#endif /* ENABLE_RC */
-
-static void cinergyt2_query (struct work_struct *work)
-{
-       struct cinergyt2 *cinergyt2 =
-               container_of(work, struct cinergyt2, query_work.work);
-       char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-       struct dvbt_get_status_msg *s = &cinergyt2->status;
-       uint8_t lock_bits;
-
-       if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
-               return;
-
-       lock_bits = s->lock_bits;
-
-       cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s));
-
-       cinergyt2->uncorrected_block_count +=
-               le32_to_cpu(s->uncorrected_block_count);
-
-       if (lock_bits != s->lock_bits) {
-               wake_up_interruptible(&cinergyt2->poll_wq);
-               cinergyt2->pending_fe_events++;
-       }
-
-       schedule_delayed_work(&cinergyt2->query_work,
-                             msecs_to_jiffies(QUERY_INTERVAL));
-
-       mutex_unlock(&cinergyt2->sem);
-}
-
-static int cinergyt2_probe (struct usb_interface *intf,
-                 const struct usb_device_id *id)
-{
-       struct cinergyt2 *cinergyt2;
-       int err;
-
-       if (!(cinergyt2 = kzalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
-               dprintk(1, "out of memory?!?\n");
-               return -ENOMEM;
-       }
-
-       usb_set_intfdata (intf, (void *) cinergyt2);
-
-       mutex_init(&cinergyt2->sem);
-       mutex_init(&cinergyt2->wq_sem);
-       init_waitqueue_head (&cinergyt2->poll_wq);
-       INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query);
-
-       cinergyt2->udev = interface_to_usbdev(intf);
-       cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-
-       if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) {
-               dprintk(1, "unable to allocate stream urbs\n");
-               kfree(cinergyt2);
-               return -ENOMEM;
-       }
-
-       err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME,
-                                  THIS_MODULE, &cinergyt2->udev->dev,
-                                  adapter_nr);
-       if (err < 0) {
-               kfree(cinergyt2);
-               return err;
-       }
-
-       cinergyt2->demux.priv = cinergyt2;
-       cinergyt2->demux.filternum = 256;
-       cinergyt2->demux.feednum = 256;
-       cinergyt2->demux.start_feed = cinergyt2_start_feed;
-       cinergyt2->demux.stop_feed = cinergyt2_stop_feed;
-       cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING |
-                                           DMX_SECTION_FILTERING |
-                                           DMX_MEMORY_BASED_FILTERING;
-
-       if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) {
-               dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err);
-               goto bailout;
-       }
-
-       cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum;
-       cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx;
-       cinergyt2->dmxdev.capabilities = 0;
-
-       if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) {
-               dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err);
-               goto bailout;
-       }
-
-       if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx))
-               dprintk(1, "dvb_net_init() failed!\n");
-
-       dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev,
-                           &cinergyt2_fe_template, cinergyt2,
-                           DVB_DEVICE_FRONTEND);
-
-       err = cinergyt2_register_rc(cinergyt2);
-       if (err)
-               goto bailout;
-
-       return 0;
-
-bailout:
-       dvb_net_release(&cinergyt2->dvbnet);
-       dvb_dmxdev_release(&cinergyt2->dmxdev);
-       dvb_dmx_release(&cinergyt2->demux);
-       dvb_unregister_adapter(&cinergyt2->adapter);
-       cinergyt2_free_stream_urbs(cinergyt2);
-       kfree(cinergyt2);
-       return -ENOMEM;
-}
-
-static void cinergyt2_disconnect (struct usb_interface *intf)
-{
-       struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
-       cinergyt2_unregister_rc(cinergyt2);
-       cancel_rearming_delayed_work(&cinergyt2->query_work);
-       wake_up_interruptible(&cinergyt2->poll_wq);
-
-       cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
-       cinergyt2->disconnect_pending = 1;
-
-       if (!atomic_read(&cinergyt2->inuse))
-               cinergyt2_unregister(cinergyt2);
-}
-
-static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
-{
-       struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
-       if (cinergyt2->disconnect_pending)
-               return -EAGAIN;
-       if (mutex_lock_interruptible(&cinergyt2->wq_sem))
-               return -ERESTARTSYS;
-
-       cinergyt2_suspend_rc(cinergyt2);
-       cancel_rearming_delayed_work(&cinergyt2->query_work);
-
-       mutex_lock(&cinergyt2->sem);
-       if (cinergyt2->streaming)
-               cinergyt2_stop_stream_xfer(cinergyt2);
-       cinergyt2_sleep(cinergyt2, 1);
-       mutex_unlock(&cinergyt2->sem);
-
-       mutex_unlock(&cinergyt2->wq_sem);
-
-       return 0;
-}
-
-static int cinergyt2_resume (struct usb_interface *intf)
-{
-       struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-       struct dvbt_set_parameters_msg *param = &cinergyt2->param;
-       int err = -EAGAIN;
-
-       if (cinergyt2->disconnect_pending)
-               goto out;
-       err = mutex_lock_interruptible(&cinergyt2->wq_sem);
-       if (err)
-               goto out;
-
-       err = mutex_lock_interruptible(&cinergyt2->sem);
-       if (err)
-               goto out_unlock1;
-
-       if (!cinergyt2->sleeping) {
-               cinergyt2_sleep(cinergyt2, 0);
-               cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0);
-               if (cinergyt2->streaming)
-                       cinergyt2_start_stream_xfer(cinergyt2);
-               schedule_delayed_work(&cinergyt2->query_work, HZ/2);
-       }
-
-       cinergyt2_resume_rc(cinergyt2);
-
-       mutex_unlock(&cinergyt2->sem);
-out_unlock1:
-       mutex_unlock(&cinergyt2->wq_sem);
-out:
-       return err;
-}
-
-static const struct usb_device_id cinergyt2_table [] __devinitdata = {
-       { USB_DEVICE(0x0ccd, 0x0038) },
-       { 0 }
-};
-
-MODULE_DEVICE_TABLE(usb, cinergyt2_table);
-
-static struct usb_driver cinergyt2_driver = {
-       .name   = "cinergyT2",
-       .probe  = cinergyt2_probe,
-       .disconnect     = cinergyt2_disconnect,
-       .suspend        = cinergyt2_suspend,
-       .resume         = cinergyt2_resume,
-       .id_table       = cinergyt2_table
-};
-
-static int __init cinergyt2_init (void)
-{
-       int err;
-
-       if ((err = usb_register(&cinergyt2_driver)) < 0)
-               dprintk(1, "usb_register() failed! (err %i)\n", err);
-
-       return err;
-}
-
-static void __exit cinergyt2_exit (void)
-{
-       usb_deregister(&cinergyt2_driver);
-}
-
-module_init (cinergyt2_init);
-module_exit (cinergyt2_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
new file mode 100644 (file)
index 0000000..1332301
--- /dev/null
@@ -0,0 +1,18 @@
+config DVB_DM1105
+       tristate "SDMC DM1105 based PCI cards"
+       depends on DVB_CORE && PCI && I2C
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_STV0288 if !DVB_FE_CUSTOMISE
+       select DVB_STB6000 if !DVB_FE_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_SI21XX if !DVB_FE_CUSTOMISE
+       help
+         Support for cards based on the SDMC DM1105 PCI chip like
+         DvbWorld 2002
+
+         Since these cards have no MPEG decoder onboard, they transmit
+         only compressed MPEG data over the PCI bus, so you need
+         an external software decoder to watch TV on your computer.
+
+         Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
new file mode 100644 (file)
index 0000000..8ac28b0
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_DM1105) += dm1105.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
new file mode 100644 (file)
index 0000000..f732144
--- /dev/null
@@ -0,0 +1,911 @@
+/*
+ * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip
+ *
+ * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/version.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/input.h>
+#include <media/ir-common.h>
+
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+#include "dvb-pll.h"
+
+#include "stv0299.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "si21xx.h"
+#include "cx24116.h"
+#include "z0194a.h"
+
+/* ----------------------------------------------- */
+/*
+ * PCI ID's
+ */
+#ifndef PCI_VENDOR_ID_TRIGEM
+#define PCI_VENDOR_ID_TRIGEM   0x109f
+#endif
+#ifndef PCI_DEVICE_ID_DM1105
+#define PCI_DEVICE_ID_DM1105   0x036f
+#endif
+#ifndef PCI_DEVICE_ID_DW2002
+#define PCI_DEVICE_ID_DW2002   0x2002
+#endif
+#ifndef PCI_DEVICE_ID_DW2004
+#define PCI_DEVICE_ID_DW2004   0x2004
+#endif
+/* ----------------------------------------------- */
+/* sdmc dm1105 registers */
+
+/* TS Control */
+#define DM1105_TSCTR                           0x00
+#define DM1105_DTALENTH                                0x04
+
+/* GPIO Interface */
+#define DM1105_GPIOVAL                         0x08
+#define DM1105_GPIOCTR                         0x0c
+
+/* PID serial number */
+#define DM1105_PIDN                            0x10
+
+/* Odd-even secret key select */
+#define DM1105_CWSEL                           0x14
+
+/* Host Command Interface */
+#define DM1105_HOST_CTR                                0x18
+#define DM1105_HOST_AD                         0x1c
+
+/* PCI Interface */
+#define DM1105_CR                              0x30
+#define DM1105_RST                             0x34
+#define DM1105_STADR                           0x38
+#define DM1105_RLEN                            0x3c
+#define DM1105_WRP                             0x40
+#define DM1105_INTCNT                          0x44
+#define DM1105_INTMAK                          0x48
+#define DM1105_INTSTS                          0x4c
+
+/* CW Value */
+#define DM1105_ODD                             0x50
+#define DM1105_EVEN                            0x58
+
+/* PID Value */
+#define DM1105_PID                             0x60
+
+/* IR Control */
+#define DM1105_IRCTR                           0x64
+#define DM1105_IRMODE                          0x68
+#define DM1105_SYSTEMCODE                      0x6c
+#define DM1105_IRCODE                          0x70
+
+/* Unknown Values */
+#define DM1105_ENCRYPT                         0x74
+#define DM1105_VER                             0x7c
+
+/* I2C Interface */
+#define DM1105_I2CCTR                          0x80
+#define DM1105_I2CSTS                          0x81
+#define DM1105_I2CDAT                          0x82
+#define DM1105_I2C_RA                          0x83
+/* ----------------------------------------------- */
+/* Interrupt Mask Bits */
+
+#define INTMAK_TSIRQM                          0x01
+#define INTMAK_HIRQM                           0x04
+#define INTMAK_IRM                             0x08
+#define INTMAK_ALLMASK                         (INTMAK_TSIRQM | \
+                                               INTMAK_HIRQM | \
+                                               INTMAK_IRM)
+#define INTMAK_NONEMASK                                0x00
+
+/* Interrupt Status Bits */
+#define INTSTS_TSIRQ                           0x01
+#define INTSTS_HIRQ                            0x04
+#define INTSTS_IR                              0x08
+
+/* IR Control Bits */
+#define DM1105_IR_EN                           0x01
+#define DM1105_SYS_CHK                         0x02
+#define DM1105_REP_FLG                         0x08
+
+/* EEPROM addr */
+#define IIC_24C01_addr                         0xa0
+/* Max board count */
+#define DM1105_MAX                             0x04
+
+#define DRIVER_NAME                            "dm1105"
+
+#define DM1105_DMA_PACKETS                     47
+#define DM1105_DMA_PACKET_LENGTH               (128*4)
+#define DM1105_DMA_BYTES                       (128 * 4 * DM1105_DMA_PACKETS)
+
+/* GPIO's for LNB power control */
+#define DM1105_LNB_MASK                                0x00000000
+#define DM1105_LNB_13V                         0x00010100
+#define DM1105_LNB_18V                         0x00000100
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static u16 ir_codes_dm1105_nec[128] = {
+       [0x0a] = KEY_Q,         /*power*/
+       [0x0c] = KEY_M,         /*mute*/
+       [0x11] = KEY_1,
+       [0x12] = KEY_2,
+       [0x13] = KEY_3,
+       [0x14] = KEY_4,
+       [0x15] = KEY_5,
+       [0x16] = KEY_6,
+       [0x17] = KEY_7,
+       [0x18] = KEY_8,
+       [0x19] = KEY_9,
+       [0x10] = KEY_0,
+       [0x1c] = KEY_PAGEUP,    /*ch+*/
+       [0x0f] = KEY_PAGEDOWN,  /*ch-*/
+       [0x1a] = KEY_O,         /*vol+*/
+       [0x0e] = KEY_Z,         /*vol-*/
+       [0x04] = KEY_R,         /*rec*/
+       [0x09] = KEY_D,         /*fav*/
+       [0x08] = KEY_BACKSPACE, /*rewind*/
+       [0x07] = KEY_A,         /*fast*/
+       [0x0b] = KEY_P,         /*pause*/
+       [0x02] = KEY_ESC,       /*cancel*/
+       [0x03] = KEY_G,         /*tab*/
+       [0x00] = KEY_UP,        /*up*/
+       [0x1f] = KEY_ENTER,     /*ok*/
+       [0x01] = KEY_DOWN,      /*down*/
+       [0x05] = KEY_C,         /*cap*/
+       [0x06] = KEY_S,         /*stop*/
+       [0x40] = KEY_F,         /*full*/
+       [0x1e] = KEY_W,         /*tvmode*/
+       [0x1b] = KEY_B,         /*recall*/
+};
+
+/* infrared remote control */
+struct infrared {
+       u16     key_map[128];
+       struct input_dev        *input_dev;
+       char                    input_phys[32];
+       struct tasklet_struct   ir_tasklet;
+       u32                     ir_command;
+};
+
+struct dm1105dvb {
+       /* pci */
+       struct pci_dev *pdev;
+       u8 __iomem *io_mem;
+
+       /* ir */
+       struct infrared ir;
+
+       /* dvb */
+       struct dmx_frontend hw_frontend;
+       struct dmx_frontend mem_frontend;
+       struct dmxdev dmxdev;
+       struct dvb_adapter dvb_adapter;
+       struct dvb_demux demux;
+       struct dvb_frontend *fe;
+       struct dvb_net dvbnet;
+       unsigned int full_ts_users;
+
+       /* i2c */
+       struct i2c_adapter i2c_adap;
+
+       /* dma */
+       dma_addr_t dma_addr;
+       unsigned char *ts_buf;
+       u32 wrp;
+       u32 buffer_size;
+       unsigned int    PacketErrorCount;
+       unsigned int dmarst;
+       spinlock_t lock;
+
+};
+
+#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
+
+static struct dm1105dvb *dm1105dvb_local;
+
+static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
+                           struct i2c_msg *msgs, int num)
+{
+       struct dm1105dvb *dm1105dvb ;
+
+       int addr, rc, i, j, k, len, byte, data;
+       u8 status;
+
+       dm1105dvb = i2c_adap->algo_data;
+       for (i = 0; i < num; i++) {
+               outb(0x00, dm_io_mem(DM1105_I2CCTR));
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read bytes */
+                       addr  = msgs[i].addr << 1;
+                       addr |= 1;
+                       outb(addr, dm_io_mem(DM1105_I2CDAT));
+                       for (byte = 0; byte < msgs[i].len; byte++)
+                               outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1));
+
+                       outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+                       for (j = 0; j < 55; j++) {
+                               mdelay(10);
+                               status = inb(dm_io_mem(DM1105_I2CSTS));
+                               if ((status & 0xc0) == 0x40)
+                                       break;
+                       }
+                       if (j >= 55)
+                               return -1;
+
+                       for (byte = 0; byte < msgs[i].len; byte++) {
+                               rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1));
+                               if (rc < 0)
+                                       goto err;
+                               msgs[i].buf[byte] = rc;
+                       }
+               } else {
+                       if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
+                               /* prepaired for cx24116 firmware */
+                               /* Write in small blocks */
+                               len = msgs[i].len - 1;
+                               k = 1;
+                               do {
+                                       outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT));
+                                       outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1));
+                                       for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
+                                               data = msgs[i].buf[k+byte];
+                                               outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2));
+                                       }
+                                       outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR));
+                                       for (j = 0; j < 25; j++) {
+                                               mdelay(10);
+                                               status = inb(dm_io_mem(DM1105_I2CSTS));
+                                               if ((status & 0xc0) == 0x40)
+                                                       break;
+                                       }
+
+                                       if (j >= 25)
+                                               return -1;
+
+                                       k += 48;
+                                       len -= 48;
+                               } while (len > 0);
+                       } else {
+                               /* write bytes */
+                               outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT));
+                               for (byte = 0; byte < msgs[i].len; byte++) {
+                                       data = msgs[i].buf[byte];
+                                       outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1));
+                               }
+                               outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+                               for (j = 0; j < 25; j++) {
+                                       mdelay(10);
+                                       status = inb(dm_io_mem(DM1105_I2CSTS));
+                                       if ((status & 0xc0) == 0x40)
+                                               break;
+                               }
+
+                               if (j >= 25)
+                                       return -1;
+                       }
+               }
+       }
+       return num;
+ err:
+       return rc;
+}
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dm1105_algo = {
+       .master_xfer   = dm1105_i2c_xfer,
+       .functionality = functionality,
+};
+
+static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed)
+{
+       return container_of(feed->demux, struct dm1105dvb, demux);
+}
+
+static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
+{
+       return container_of(fe->dvb, struct dm1105dvb, dvb_adapter);
+}
+
+static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+
+               if (voltage == SEC_VOLTAGE_18) {
+                       outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
+                       outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL));
+               } else  {
+               /*LNB ON-13V by default!*/
+                       outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR));
+                       outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL));
+               }
+
+       return 0;
+}
+
+static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb)
+{
+       outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR));
+}
+
+static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
+{
+       dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
+
+       return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr);
+}
+
+static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
+{
+       pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
+}
+
+static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
+{
+       outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
+       outb(1, dm_io_mem(DM1105_CR));
+}
+
+static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb)
+{
+       outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK));
+       outb(0, dm_io_mem(DM1105_CR));
+}
+
+static int dm1105dvb_start_feed(struct dvb_demux_feed *f)
+{
+       struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+
+       if (dm1105dvb->full_ts_users++ == 0)
+               dm1105dvb_enable_irqs(dm1105dvb);
+
+       return 0;
+}
+
+static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
+{
+       struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+
+       if (--dm1105dvb->full_ts_users == 0)
+               dm1105dvb_disable_irqs(dm1105dvb);
+
+       return 0;
+}
+
+/* ir tasklet */
+static void dm1105_emit_key(unsigned long parm)
+{
+       struct infrared *ir = (struct infrared *) parm;
+       u32 ircom = ir->ir_command;
+       u8 data;
+       u16 keycode;
+
+       data = (ircom >> 8) & 0x7f;
+
+       input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
+       input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
+       keycode = ir->key_map[data];
+
+       if (!keycode)
+               return;
+
+       input_event(ir->input_dev, EV_KEY, keycode, 1);
+       input_sync(ir->input_dev);
+       input_event(ir->input_dev, EV_KEY, keycode, 0);
+       input_sync(ir->input_dev);
+
+}
+
+static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
+{
+       struct dm1105dvb *dm1105dvb = dev_id;
+       unsigned int piece;
+       unsigned int nbpackets;
+       u32 command;
+       u32 nextwrp;
+       u32 oldwrp;
+
+       /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
+       unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
+       outb(intsts, dm_io_mem(DM1105_INTSTS));
+
+       switch (intsts) {
+       case INTSTS_TSIRQ:
+       case (INTSTS_TSIRQ | INTSTS_IR):
+               nextwrp = inl(dm_io_mem(DM1105_WRP)) -
+                       inl(dm_io_mem(DM1105_STADR)) ;
+               oldwrp = dm1105dvb->wrp;
+               spin_lock(&dm1105dvb->lock);
+               if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
+                               (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
+                               (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+                       dm1105dvb->PacketErrorCount++;
+                       /* bad packet found */
+                       if ((dm1105dvb->PacketErrorCount >= 2) &&
+                                       (dm1105dvb->dmarst == 0)) {
+                               outb(1, dm_io_mem(DM1105_RST));
+                               dm1105dvb->wrp = 0;
+                               dm1105dvb->PacketErrorCount = 0;
+                               dm1105dvb->dmarst = 0;
+                               spin_unlock(&dm1105dvb->lock);
+                               return IRQ_HANDLED;
+                       }
+               }
+               if (nextwrp < oldwrp) {
+                       piece = dm1105dvb->buffer_size - oldwrp;
+                       memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
+                       nbpackets = (piece + nextwrp)/188;
+               } else  {
+                       nbpackets = (nextwrp - oldwrp)/188;
+               }
+               dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
+               dm1105dvb->wrp = nextwrp;
+               spin_unlock(&dm1105dvb->lock);
+               break;
+       case INTSTS_IR:
+               command = inl(dm_io_mem(DM1105_IRCODE));
+               if (ir_debug)
+                       printk("dm1105: received byte 0x%04x\n", command);
+
+               dm1105dvb->ir.ir_command = command;
+               tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
+               break;
+       }
+       return IRQ_HANDLED;
+
+
+}
+
+/* register with input layer */
+static void input_register_keys(struct infrared *ir)
+{
+       int i;
+
+       memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
+
+       for (i = 0; i < ARRAY_SIZE(ir->key_map); i++)
+                       set_bit(ir->key_map[i], ir->input_dev->keybit);
+
+       ir->input_dev->keycode = ir->key_map;
+       ir->input_dev->keycodesize = sizeof(ir->key_map[0]);
+       ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
+}
+
+int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
+{
+       struct input_dev *input_dev;
+       int err;
+
+       dm1105dvb_local = dm1105;
+
+       input_dev = input_allocate_device();
+       if (!input_dev)
+               return -ENOMEM;
+
+       dm1105->ir.input_dev = input_dev;
+       snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
+               "pci-%s/ir0", pci_name(dm1105->pdev));
+
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->name = "DVB on-card IR receiver";
+
+       input_dev->phys = dm1105->ir.input_phys;
+       input_dev->id.bustype = BUS_PCI;
+       input_dev->id.version = 2;
+       if (dm1105->pdev->subsystem_vendor) {
+               input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
+               input_dev->id.product = dm1105->pdev->subsystem_device;
+       } else {
+               input_dev->id.vendor = dm1105->pdev->vendor;
+               input_dev->id.product = dm1105->pdev->device;
+       }
+       input_dev->dev.parent = &dm1105->pdev->dev;
+       /* initial keymap */
+       memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map);
+       input_register_keys(&dm1105->ir);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
+
+       return 0;
+}
+
+
+void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
+{
+       tasklet_kill(&dm1105->ir.ir_tasklet);
+       input_unregister_device(dm1105->ir.input_dev);
+
+}
+
+static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
+{
+       dm1105dvb_disable_irqs(dm1105dvb);
+
+       outb(0, dm_io_mem(DM1105_HOST_CTR));
+
+       /*DATALEN 188,*/
+       outb(188, dm_io_mem(DM1105_DTALENTH));
+       /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
+       outw(0xc10a, dm_io_mem(DM1105_TSCTR));
+
+       /* map DMA and set address */
+       dm1105dvb_dma_map(dm1105dvb);
+       dm1105dvb_set_dma_addr(dm1105dvb);
+       /* big buffer */
+       outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN));
+       outb(47, dm_io_mem(DM1105_INTCNT));
+
+       /* IR NEC mode enable */
+       outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR));
+       outb(0, dm_io_mem(DM1105_IRMODE));
+       outw(0, dm_io_mem(DM1105_SYSTEMCODE));
+
+       return 0;
+}
+
+static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
+{
+       dm1105dvb_disable_irqs(dm1105dvb);
+
+       /* IR disable */
+       outb(0, dm_io_mem(DM1105_IRCTR));
+       outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK));
+
+       dm1105dvb_dma_unmap(dm1105dvb);
+}
+
+static struct stv0288_config earda_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+};
+
+static struct si21xx_config serit_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+
+};
+
+static struct cx24116_config serit_sp2633_config = {
+       .demod_address = 0x55,
+};
+
+static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
+{
+       int ret;
+
+       switch (dm1105dvb->pdev->subsystem_device) {
+       case PCI_DEVICE_ID_DW2002:
+               dm1105dvb->fe = dvb_attach(
+                       stv0299_attach, &sharp_z0194a_config,
+                       &dm1105dvb->i2c_adap);
+
+               if (dm1105dvb->fe) {
+                       dm1105dvb->fe->ops.set_voltage =
+                                                       dm1105dvb_set_voltage;
+                       dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
+                                       &dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+               }
+
+               if (!dm1105dvb->fe) {
+                       dm1105dvb->fe = dvb_attach(
+                               stv0288_attach, &earda_config,
+                               &dm1105dvb->i2c_adap);
+                       if (dm1105dvb->fe) {
+                               dm1105dvb->fe->ops.set_voltage =
+                                                       dm1105dvb_set_voltage;
+                               dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
+                                               &dm1105dvb->i2c_adap);
+                       }
+               }
+
+               if (!dm1105dvb->fe) {
+                       dm1105dvb->fe = dvb_attach(
+                               si21xx_attach, &serit_config,
+                               &dm1105dvb->i2c_adap);
+                       if (dm1105dvb->fe)
+                               dm1105dvb->fe->ops.set_voltage =
+                                                       dm1105dvb_set_voltage;
+               }
+               break;
+       case PCI_DEVICE_ID_DW2004:
+               dm1105dvb->fe = dvb_attach(
+                       cx24116_attach, &serit_sp2633_config,
+                       &dm1105dvb->i2c_adap);
+               if (dm1105dvb->fe)
+                       dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
+               break;
+       }
+
+       if (!dm1105dvb->fe) {
+               dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n");
+               return -ENODEV;
+       }
+
+       ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe);
+       if (ret < 0) {
+               if (dm1105dvb->fe->ops.release)
+                       dm1105dvb->fe->ops.release(dm1105dvb->fe);
+               dm1105dvb->fe = NULL;
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
+{
+       static u8 command[1] = { 0x28 };
+
+       struct i2c_msg msg[] = {
+               { .addr = IIC_24C01_addr >> 1, .flags = 0,
+                               .buf = command, .len = 1 },
+               { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD,
+                               .buf = mac, .len = 6 },
+       };
+
+       dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
+       dev_info(&dm1105dvb->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+                       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static int __devinit dm1105_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
+{
+       struct dm1105dvb *dm1105dvb;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+       int ret = -ENOMEM;
+
+       dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
+       if (!dm1105dvb)
+               goto out;
+
+       dm1105dvb->pdev = pdev;
+       dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
+       dm1105dvb->PacketErrorCount = 0;
+       dm1105dvb->dmarst = 0;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0)
+               goto err_kfree;
+
+       ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (ret < 0)
+               goto err_pci_disable_device;
+
+       pci_set_master(pdev);
+
+       ret = pci_request_regions(pdev, DRIVER_NAME);
+       if (ret < 0)
+               goto err_pci_disable_device;
+
+       dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+       if (!dm1105dvb->io_mem) {
+               ret = -EIO;
+               goto err_pci_release_regions;
+       }
+
+       spin_lock_init(&dm1105dvb->lock);
+       pci_set_drvdata(pdev, dm1105dvb);
+
+       ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
+       if (ret < 0)
+               goto err_pci_iounmap;
+
+       ret = dm1105dvb_hw_init(dm1105dvb);
+       if (ret < 0)
+               goto err_free_irq;
+
+       /* i2c */
+       i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
+       strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME);
+       dm1105dvb->i2c_adap.owner = THIS_MODULE;
+       dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+       dm1105dvb->i2c_adap.dev.parent = &pdev->dev;
+       dm1105dvb->i2c_adap.algo = &dm1105_algo;
+       dm1105dvb->i2c_adap.algo_data = dm1105dvb;
+       ret = i2c_add_adapter(&dm1105dvb->i2c_adap);
+
+       if (ret < 0)
+               goto err_dm1105dvb_hw_exit;
+
+       /* dvb */
+       ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME,
+                                       THIS_MODULE, &pdev->dev, adapter_nr);
+       if (ret < 0)
+               goto err_i2c_del_adapter;
+
+       dvb_adapter = &dm1105dvb->dvb_adapter;
+
+       dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac);
+
+       dvbdemux = &dm1105dvb->demux;
+       dvbdemux->filternum = 256;
+       dvbdemux->feednum = 256;
+       dvbdemux->start_feed = dm1105dvb_start_feed;
+       dvbdemux->stop_feed = dm1105dvb_stop_feed;
+       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+                       DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+       ret = dvb_dmx_init(dvbdemux);
+       if (ret < 0)
+               goto err_dvb_unregister_adapter;
+
+       dmx = &dvbdemux->dmx;
+       dm1105dvb->dmxdev.filternum = 256;
+       dm1105dvb->dmxdev.demux = dmx;
+       dm1105dvb->dmxdev.capabilities = 0;
+
+       ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter);
+       if (ret < 0)
+               goto err_dvb_dmx_release;
+
+       dm1105dvb->hw_frontend.source = DMX_FRONTEND_0;
+
+       ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend);
+       if (ret < 0)
+               goto err_dvb_dmxdev_release;
+
+       dm1105dvb->mem_frontend.source = DMX_MEMORY_FE;
+
+       ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend);
+       if (ret < 0)
+               goto err_remove_hw_frontend;
+
+       ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend);
+       if (ret < 0)
+               goto err_remove_mem_frontend;
+
+       ret = frontend_init(dm1105dvb);
+       if (ret < 0)
+               goto err_disconnect_frontend;
+
+       dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
+       dm1105_ir_init(dm1105dvb);
+out:
+       return ret;
+
+err_disconnect_frontend:
+       dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+       dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
+err_remove_hw_frontend:
+       dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
+err_dvb_dmxdev_release:
+       dvb_dmxdev_release(&dm1105dvb->dmxdev);
+err_dvb_dmx_release:
+       dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+       dvb_unregister_adapter(dvb_adapter);
+err_i2c_del_adapter:
+       i2c_del_adapter(&dm1105dvb->i2c_adap);
+err_dm1105dvb_hw_exit:
+       dm1105dvb_hw_exit(dm1105dvb);
+err_free_irq:
+       free_irq(pdev->irq, dm1105dvb);
+err_pci_iounmap:
+       pci_iounmap(pdev, dm1105dvb->io_mem);
+err_pci_release_regions:
+       pci_release_regions(pdev);
+err_pci_disable_device:
+       pci_disable_device(pdev);
+err_kfree:
+       pci_set_drvdata(pdev, NULL);
+       kfree(dm1105dvb);
+       goto out;
+}
+
+static void __devexit dm1105_remove(struct pci_dev *pdev)
+{
+       struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev);
+       struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter;
+       struct dvb_demux *dvbdemux = &dm1105dvb->demux;
+       struct dmx_demux *dmx = &dvbdemux->dmx;
+
+       dm1105_ir_exit(dm1105dvb);
+       dmx->close(dmx);
+       dvb_net_release(&dm1105dvb->dvbnet);
+       if (dm1105dvb->fe)
+               dvb_unregister_frontend(dm1105dvb->fe);
+
+       dmx->disconnect_frontend(dmx);
+       dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
+       dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
+       dvb_dmxdev_release(&dm1105dvb->dmxdev);
+       dvb_dmx_release(dvbdemux);
+       dvb_unregister_adapter(dvb_adapter);
+       if (&dm1105dvb->i2c_adap)
+               i2c_del_adapter(&dm1105dvb->i2c_adap);
+
+       dm1105dvb_hw_exit(dm1105dvb);
+       synchronize_irq(pdev->irq);
+       free_irq(pdev->irq, dm1105dvb);
+       pci_iounmap(pdev, dm1105dvb->io_mem);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+       kfree(dm1105dvb);
+}
+
+static struct pci_device_id dm1105_id_table[] __devinitdata = {
+       {
+               .vendor = PCI_VENDOR_ID_TRIGEM,
+               .device = PCI_DEVICE_ID_DM1105,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_DEVICE_ID_DW2002,
+       }, {
+               .vendor = PCI_VENDOR_ID_TRIGEM,
+               .device = PCI_DEVICE_ID_DM1105,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_DEVICE_ID_DW2004,
+       }, {
+               /* empty */
+       },
+};
+
+MODULE_DEVICE_TABLE(pci, dm1105_id_table);
+
+static struct pci_driver dm1105_driver = {
+       .name = DRIVER_NAME,
+       .id_table = dm1105_id_table,
+       .probe = dm1105_probe,
+       .remove = __devexit_p(dm1105_remove),
+};
+
+static int __init dm1105_init(void)
+{
+       return pci_register_driver(&dm1105_driver);
+}
+
+static void __exit dm1105_exit(void)
+{
+       pci_unregister_driver(&dm1105_driver);
+}
+
+module_init(dm1105_init);
+module_exit(dm1105_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_DESCRIPTION("SDMC DM1105 DVB driver");
+MODULE_LICENSE("GPL");
index 3526e3ee9487747788e00ac66b0c978af36a3ad2..f170e822fadce9016eeba24330d23101cbb01927 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "dvb_frontend.h"
 #include "dvbdev.h"
+#include <linux/dvb/version.h>
 
 static int dvb_frontend_debug;
 static int dvb_shutdown_timeout;
@@ -755,6 +756,539 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
        return 0;
 }
 
+struct dtv_cmds_h dtv_cmds[] = {
+       [DTV_TUNE] = {
+               .name   = "DTV_TUNE",
+               .cmd    = DTV_TUNE,
+               .set    = 1,
+       },
+       [DTV_CLEAR] = {
+               .name   = "DTV_CLEAR",
+               .cmd    = DTV_CLEAR,
+               .set    = 1,
+       },
+
+       /* Set */
+       [DTV_FREQUENCY] = {
+               .name   = "DTV_FREQUENCY",
+               .cmd    = DTV_FREQUENCY,
+               .set    = 1,
+       },
+       [DTV_BANDWIDTH_HZ] = {
+               .name   = "DTV_BANDWIDTH_HZ",
+               .cmd    = DTV_BANDWIDTH_HZ,
+               .set    = 1,
+       },
+       [DTV_MODULATION] = {
+               .name   = "DTV_MODULATION",
+               .cmd    = DTV_MODULATION,
+               .set    = 1,
+       },
+       [DTV_INVERSION] = {
+               .name   = "DTV_INVERSION",
+               .cmd    = DTV_INVERSION,
+               .set    = 1,
+       },
+       [DTV_DISEQC_MASTER] = {
+               .name   = "DTV_DISEQC_MASTER",
+               .cmd    = DTV_DISEQC_MASTER,
+               .set    = 1,
+               .buffer = 1,
+       },
+       [DTV_SYMBOL_RATE] = {
+               .name   = "DTV_SYMBOL_RATE",
+               .cmd    = DTV_SYMBOL_RATE,
+               .set    = 1,
+       },
+       [DTV_INNER_FEC] = {
+               .name   = "DTV_INNER_FEC",
+               .cmd    = DTV_INNER_FEC,
+               .set    = 1,
+       },
+       [DTV_VOLTAGE] = {
+               .name   = "DTV_VOLTAGE",
+               .cmd    = DTV_VOLTAGE,
+               .set    = 1,
+       },
+       [DTV_TONE] = {
+               .name   = "DTV_TONE",
+               .cmd    = DTV_TONE,
+               .set    = 1,
+       },
+       [DTV_PILOT] = {
+               .name   = "DTV_PILOT",
+               .cmd    = DTV_PILOT,
+               .set    = 1,
+       },
+       [DTV_ROLLOFF] = {
+               .name   = "DTV_ROLLOFF",
+               .cmd    = DTV_ROLLOFF,
+               .set    = 1,
+       },
+       [DTV_DELIVERY_SYSTEM] = {
+               .name   = "DTV_DELIVERY_SYSTEM",
+               .cmd    = DTV_DELIVERY_SYSTEM,
+               .set    = 1,
+       },
+       [DTV_HIERARCHY] = {
+               .name   = "DTV_HIERARCHY",
+               .cmd    = DTV_HIERARCHY,
+               .set    = 1,
+       },
+       [DTV_CODE_RATE_HP] = {
+               .name   = "DTV_CODE_RATE_HP",
+               .cmd    = DTV_CODE_RATE_HP,
+               .set    = 1,
+       },
+       [DTV_CODE_RATE_LP] = {
+               .name   = "DTV_CODE_RATE_LP",
+               .cmd    = DTV_CODE_RATE_LP,
+               .set    = 1,
+       },
+       [DTV_GUARD_INTERVAL] = {
+               .name   = "DTV_GUARD_INTERVAL",
+               .cmd    = DTV_GUARD_INTERVAL,
+               .set    = 1,
+       },
+       [DTV_TRANSMISSION_MODE] = {
+               .name   = "DTV_TRANSMISSION_MODE",
+               .cmd    = DTV_TRANSMISSION_MODE,
+               .set    = 1,
+       },
+       /* Get */
+       [DTV_DISEQC_SLAVE_REPLY] = {
+               .name   = "DTV_DISEQC_SLAVE_REPLY",
+               .cmd    = DTV_DISEQC_SLAVE_REPLY,
+               .set    = 0,
+               .buffer = 1,
+       },
+       [DTV_API_VERSION] = {
+               .name   = "DTV_API_VERSION",
+               .cmd    = DTV_API_VERSION,
+               .set    = 0,
+       },
+       [DTV_CODE_RATE_HP] = {
+               .name   = "DTV_CODE_RATE_HP",
+               .cmd    = DTV_CODE_RATE_HP,
+               .set    = 0,
+       },
+       [DTV_CODE_RATE_LP] = {
+               .name   = "DTV_CODE_RATE_LP",
+               .cmd    = DTV_CODE_RATE_LP,
+               .set    = 0,
+       },
+       [DTV_GUARD_INTERVAL] = {
+               .name   = "DTV_GUARD_INTERVAL",
+               .cmd    = DTV_GUARD_INTERVAL,
+               .set    = 0,
+       },
+       [DTV_TRANSMISSION_MODE] = {
+               .name   = "DTV_TRANSMISSION_MODE",
+               .cmd    = DTV_TRANSMISSION_MODE,
+               .set    = 0,
+       },
+       [DTV_HIERARCHY] = {
+               .name   = "DTV_HIERARCHY",
+               .cmd    = DTV_HIERARCHY,
+               .set    = 0,
+       },
+};
+
+void dtv_property_dump(struct dtv_property *tvp)
+{
+       int i;
+
+       if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
+               printk("%s: tvp.cmd = 0x%08x (undefined/unknown/invalid)\n",
+                       __func__, tvp->cmd);
+               return;
+       }
+
+       printk("%s() tvp.cmd    = 0x%08x (%s)\n"
+               ,__FUNCTION__
+               ,tvp->cmd
+               ,dtv_cmds[ tvp->cmd ].name);
+
+       if(dtv_cmds[ tvp->cmd ].buffer) {
+
+               printk("%s() tvp.u.buffer.len = 0x%02x\n"
+                       ,__FUNCTION__
+                       ,tvp->u.buffer.len);
+
+               for(i = 0; i < tvp->u.buffer.len; i++)
+                       printk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
+                               ,__FUNCTION__
+                               ,i
+                               ,tvp->u.buffer.data[i]);
+
+       } else
+               printk("%s() tvp.u.data = 0x%08x\n", __FUNCTION__, tvp->u.data);
+}
+
+int is_legacy_delivery_system(fe_delivery_system_t s)
+{
+       if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
+               (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS))
+               return 1;
+
+       return 0;
+}
+
+/* Synchronise the legacy tuning parameters into the cache, so that demodulator
+ * drivers can use a single set_frontend tuning function, regardless of whether
+ * it's being used for the legacy or new API, reducing code and complexity.
+ */
+void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+       printk("%s()\n", __FUNCTION__);
+
+       c->frequency = p->frequency;
+       c->inversion = p->inversion;
+
+       switch (fe->ops.info.type) {
+       case FE_QPSK:
+               c->modulation = QPSK;   /* implied for DVB-S in legacy API */
+               c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+               c->symbol_rate = p->u.qpsk.symbol_rate;
+               c->fec_inner = p->u.qpsk.fec_inner;
+               c->delivery_system = SYS_DVBS;
+               break;
+       case FE_QAM:
+               c->symbol_rate = p->u.qam.symbol_rate;
+               c->fec_inner = p->u.qam.fec_inner;
+               c->modulation = p->u.qam.modulation;
+               c->delivery_system = SYS_DVBC_ANNEX_AC;
+               break;
+       case FE_OFDM:
+               if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
+                       c->bandwidth_hz = 6000000;
+               else if (p->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
+                       c->bandwidth_hz = 7000000;
+               else if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+                       c->bandwidth_hz = 8000000;
+               else
+                       /* Including BANDWIDTH_AUTO */
+                       c->bandwidth_hz = 0;
+               c->code_rate_HP = p->u.ofdm.code_rate_HP;
+               c->code_rate_LP = p->u.ofdm.code_rate_LP;
+               c->modulation = p->u.ofdm.constellation;
+               c->transmission_mode = p->u.ofdm.transmission_mode;
+               c->guard_interval = p->u.ofdm.guard_interval;
+               c->hierarchy = p->u.ofdm.hierarchy_information;
+               c->delivery_system = SYS_DVBT;
+               break;
+       case FE_ATSC:
+               c->modulation = p->u.vsb.modulation;
+               if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
+                       c->delivery_system = SYS_ATSC;
+               else
+                       c->delivery_system = SYS_DVBC_ANNEX_B;
+               break;
+       }
+}
+
+/* Ensure the cached values are set correctly in the frontend
+ * legacy tuning structures, for the advanced tuning API.
+ */
+void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dvb_frontend_parameters *p = &fepriv->parameters;
+
+       printk("%s()\n", __FUNCTION__);
+
+       p->frequency = c->frequency;
+       p->inversion = c->inversion;
+
+       switch (fe->ops.info.type) {
+       case FE_QPSK:
+               printk("%s() Preparing QPSK req\n", __FUNCTION__);
+               p->u.qpsk.symbol_rate = c->symbol_rate;
+               p->u.qpsk.fec_inner = c->fec_inner;
+               c->delivery_system = SYS_DVBS;
+               break;
+       case FE_QAM:
+               printk("%s() Preparing QAM req\n", __FUNCTION__);
+               p->u.qam.symbol_rate = c->symbol_rate;
+               p->u.qam.fec_inner = c->fec_inner;
+               p->u.qam.modulation = c->modulation;
+               c->delivery_system = SYS_DVBC_ANNEX_AC;
+               break;
+       case FE_OFDM:
+               printk("%s() Preparing OFDM req\n", __FUNCTION__);
+               if (c->bandwidth_hz == 6000000)
+                       p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+               else if (c->bandwidth_hz == 7000000)
+                       p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+               else if (c->bandwidth_hz == 8000000)
+                       p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+               else
+                       p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+               p->u.ofdm.code_rate_HP = c->code_rate_HP;
+               p->u.ofdm.code_rate_LP = c->code_rate_LP;
+               p->u.ofdm.constellation = c->modulation;
+               p->u.ofdm.transmission_mode = c->transmission_mode;
+               p->u.ofdm.guard_interval = c->guard_interval;
+               p->u.ofdm.hierarchy_information = c->hierarchy;
+               c->delivery_system = SYS_DVBT;
+               break;
+       case FE_ATSC:
+               printk("%s() Preparing VSB req\n", __FUNCTION__);
+               p->u.vsb.modulation = c->modulation;
+               if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
+                       c->delivery_system = SYS_ATSC;
+               else
+                       c->delivery_system = SYS_DVBC_ANNEX_B;
+               break;
+       }
+}
+
+/* Ensure the cached values are set correctly in the frontend
+ * legacy tuning structures, for the legacy tuning API.
+ */
+void dtv_property_adv_params_sync(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dvb_frontend_parameters *p = &fepriv->parameters;
+
+       printk("%s()\n", __FUNCTION__);
+
+       p->frequency = c->frequency;
+       p->inversion = c->inversion;
+
+       switch(c->modulation) {
+       case PSK_8:
+       case APSK_16:
+       case QPSK:
+               p->u.qpsk.symbol_rate = c->symbol_rate;
+               p->u.qpsk.fec_inner = c->fec_inner;
+               break;
+       default:
+               break;
+       }
+
+       if(c->delivery_system == SYS_ISDBT) {
+               /* Fake out a generic DVB-T request so we pass validation in the ioctl */
+               p->frequency = c->frequency;
+               p->inversion = INVERSION_AUTO;
+               p->u.ofdm.constellation = QAM_AUTO;
+               p->u.ofdm.code_rate_HP = FEC_AUTO;
+               p->u.ofdm.code_rate_LP = FEC_AUTO;
+               p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+               p->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+               p->u.ofdm.hierarchy_information = HIERARCHY_AUTO;
+       }
+}
+
+void dtv_property_cache_submit(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+       printk("%s()\n", __FUNCTION__);
+
+       /* For legacy delivery systems we don't need the delivery_system to
+        * be specified, but we populate the older structures from the cache
+        * so we can call set_frontend on older drivers.
+        */
+       if(is_legacy_delivery_system(c->delivery_system)) {
+
+               printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation);
+               dtv_property_legacy_params_sync(fe);
+
+       } else {
+               printk("%s() adv, modulation = %d\n", __FUNCTION__, c->modulation);
+
+               /* For advanced delivery systems / modulation types ...
+                * we seed the lecacy dvb_frontend_parameters structure
+                * so that the sanity checking code later in the IOCTL processing
+                * can validate our basic frequency ranges, symbolrates, modulation
+                * etc.
+                */
+               dtv_property_adv_params_sync(fe);
+       }
+}
+
+static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *parg);
+static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *parg);
+
+int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp,
+       struct inode *inode, struct file *file)
+{
+       int r = 0;
+
+       printk("%s()\n", __FUNCTION__);
+
+       dtv_property_dump(tvp);
+
+       /* Allow the frontend to validate incoming properties */
+       if (fe->ops.get_property)
+               r = fe->ops.get_property(fe, tvp);
+
+       if (r < 0)
+               return r;
+
+       switch(tvp->cmd) {
+       case DTV_FREQUENCY:
+               tvp->u.data = fe->dtv_property_cache.frequency;
+               break;
+       case DTV_MODULATION:
+               tvp->u.data = fe->dtv_property_cache.modulation;
+               break;
+       case DTV_BANDWIDTH_HZ:
+               tvp->u.data = fe->dtv_property_cache.bandwidth_hz;
+               break;
+       case DTV_INVERSION:
+               tvp->u.data = fe->dtv_property_cache.inversion;
+               break;
+       case DTV_SYMBOL_RATE:
+               tvp->u.data = fe->dtv_property_cache.symbol_rate;
+               break;
+       case DTV_INNER_FEC:
+               tvp->u.data = fe->dtv_property_cache.fec_inner;
+               break;
+       case DTV_PILOT:
+               tvp->u.data = fe->dtv_property_cache.pilot;
+               break;
+       case DTV_ROLLOFF:
+               tvp->u.data = fe->dtv_property_cache.rolloff;
+               break;
+       case DTV_DELIVERY_SYSTEM:
+               tvp->u.data = fe->dtv_property_cache.delivery_system;
+               break;
+       case DTV_VOLTAGE:
+               tvp->u.data = fe->dtv_property_cache.voltage;
+               break;
+       case DTV_TONE:
+               tvp->u.data = fe->dtv_property_cache.sectone;
+               break;
+       case DTV_API_VERSION:
+               tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
+               break;
+       case DTV_CODE_RATE_HP:
+               tvp->u.data = fe->dtv_property_cache.code_rate_HP;
+               break;
+       case DTV_CODE_RATE_LP:
+               tvp->u.data = fe->dtv_property_cache.code_rate_LP;
+               break;
+       case DTV_GUARD_INTERVAL:
+               tvp->u.data = fe->dtv_property_cache.guard_interval;
+               break;
+       case DTV_TRANSMISSION_MODE:
+               tvp->u.data = fe->dtv_property_cache.transmission_mode;
+               break;
+       case DTV_HIERARCHY:
+               tvp->u.data = fe->dtv_property_cache.hierarchy;
+               break;
+       default:
+               r = -1;
+       }
+
+       return r;
+}
+
+int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
+       struct inode *inode, struct file *file)
+{
+       int r = 0;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       printk("%s()\n", __FUNCTION__);
+       dtv_property_dump(tvp);
+
+       /* Allow the frontend to validate incoming properties */
+       if (fe->ops.set_property)
+               r = fe->ops.set_property(fe, tvp);
+
+       if (r < 0)
+               return r;
+
+       switch(tvp->cmd) {
+       case DTV_CLEAR:
+               /* Reset a cache of data specific to the frontend here. This does
+                * not effect hardware.
+                */
+               printk("%s() Flushing property cache\n", __FUNCTION__);
+               memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties));
+               fe->dtv_property_cache.state = tvp->cmd;
+               fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
+               break;
+       case DTV_TUNE:
+               /* interpret the cache of data, build either a traditional frontend
+                * tunerequest so we can pass validation in the FE_SET_FRONTEND
+                * ioctl.
+                */
+               fe->dtv_property_cache.state = tvp->cmd;
+               printk("%s() Finalised property cache\n", __FUNCTION__);
+               dtv_property_cache_submit(fe);
+
+               r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
+                       &fepriv->parameters);
+               break;
+       case DTV_FREQUENCY:
+               fe->dtv_property_cache.frequency = tvp->u.data;
+               break;
+       case DTV_MODULATION:
+               fe->dtv_property_cache.modulation = tvp->u.data;
+               break;
+       case DTV_BANDWIDTH_HZ:
+               fe->dtv_property_cache.bandwidth_hz = tvp->u.data;
+               break;
+       case DTV_INVERSION:
+               fe->dtv_property_cache.inversion = tvp->u.data;
+               break;
+       case DTV_SYMBOL_RATE:
+               fe->dtv_property_cache.symbol_rate = tvp->u.data;
+               break;
+       case DTV_INNER_FEC:
+               fe->dtv_property_cache.fec_inner = tvp->u.data;
+               break;
+       case DTV_PILOT:
+               fe->dtv_property_cache.pilot = tvp->u.data;
+               break;
+       case DTV_ROLLOFF:
+               fe->dtv_property_cache.rolloff = tvp->u.data;
+               break;
+       case DTV_DELIVERY_SYSTEM:
+               fe->dtv_property_cache.delivery_system = tvp->u.data;
+               break;
+       case DTV_VOLTAGE:
+               fe->dtv_property_cache.voltage = tvp->u.data;
+               r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_VOLTAGE,
+                       (void *)fe->dtv_property_cache.voltage);
+               break;
+       case DTV_TONE:
+               fe->dtv_property_cache.sectone = tvp->u.data;
+               r = dvb_frontend_ioctl_legacy(inode, file, FE_SET_TONE,
+                       (void *)fe->dtv_property_cache.sectone);
+               break;
+       case DTV_CODE_RATE_HP:
+               fe->dtv_property_cache.code_rate_HP = tvp->u.data;
+               break;
+       case DTV_CODE_RATE_LP:
+               fe->dtv_property_cache.code_rate_LP = tvp->u.data;
+               break;
+       case DTV_GUARD_INTERVAL:
+               fe->dtv_property_cache.guard_interval = tvp->u.data;
+               break;
+       case DTV_TRANSMISSION_MODE:
+               fe->dtv_property_cache.transmission_mode = tvp->u.data;
+               break;
+       case DTV_HIERARCHY:
+               fe->dtv_property_cache.hierarchy = tvp->u.data;
+               break;
+       default:
+               r = -1;
+       }
+
+       return r;
+}
+
 static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, void *parg)
 {
@@ -776,6 +1310,116 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        if (down_interruptible (&fepriv->sem))
                return -ERESTARTSYS;
 
+       if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
+               err = dvb_frontend_ioctl_properties(inode, file, cmd, parg);
+       else {
+               fe->dtv_property_cache.state = DTV_UNDEFINED;
+               err = dvb_frontend_ioctl_legacy(inode, file, cmd, parg);
+       }
+
+       up(&fepriv->sem);
+       return err;
+}
+
+static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *parg)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_frontend *fe = dvbdev->priv;
+       int err = 0;
+
+       struct dtv_properties *tvps = NULL;
+       struct dtv_property *tvp = NULL;
+       int i;
+
+       dprintk("%s\n", __func__);
+
+       if(cmd == FE_SET_PROPERTY) {
+               printk("%s() FE_SET_PROPERTY\n", __FUNCTION__);
+
+               tvps = (struct dtv_properties __user *)parg;
+
+               printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
+               printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+
+               /* Put an arbitrary limit on the number of messages that can
+                * be sent at once */
+               if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+                       return -EINVAL;
+
+               tvp = (struct dtv_property *) kmalloc(tvps->num *
+                       sizeof(struct dtv_property), GFP_KERNEL);
+               if (!tvp) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+
+               if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
+               for (i = 0; i < tvps->num; i++) {
+                       (tvp + i)->result = dtv_property_process_set(fe, tvp + i, inode, file);
+                       err |= (tvp + i)->result;
+               }
+
+               if(fe->dtv_property_cache.state == DTV_TUNE) {
+                       printk("%s() Property cache is full, tuning\n", __FUNCTION__);
+               }
+
+       } else
+       if(cmd == FE_GET_PROPERTY) {
+               printk("%s() FE_GET_PROPERTY\n", __FUNCTION__);
+
+               tvps = (struct dtv_properties __user *)parg;
+
+               printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
+               printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+
+               /* Put an arbitrary limit on the number of messages that can
+                * be sent at once */
+               if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+                       return -EINVAL;
+
+               tvp = (struct dtv_property *) kmalloc(tvps->num *
+                       sizeof(struct dtv_property), GFP_KERNEL);
+               if (!tvp) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+
+               if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
+               for (i = 0; i < tvps->num; i++) {
+                       (tvp + i)->result = dtv_property_process_get(fe, tvp + i, inode, file);
+                       err |= (tvp + i)->result;
+               }
+
+               if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
+       } else
+               err = -EOPNOTSUPP;
+
+out:
+       kfree(tvp);
+       return err;
+}
+
+static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *parg)
+{
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_frontend *fe = dvbdev->priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       int err = -EOPNOTSUPP;
+
        switch (cmd) {
        case FE_GET_INFO: {
                struct dvb_frontend_info* info = parg;
@@ -942,13 +1586,21 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        case FE_SET_FRONTEND: {
                struct dvb_frontend_tune_settings fetunesettings;
 
-               if (dvb_frontend_check_parameters(fe, parg) < 0) {
-                       err = -EINVAL;
-                       break;
-               }
+               if(fe->dtv_property_cache.state == DTV_TUNE) {
+                       if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
+                               err = -EINVAL;
+                               break;
+                       }
+               } else {
+                       if (dvb_frontend_check_parameters(fe, parg) < 0) {
+                               err = -EINVAL;
+                               break;
+                       }
 
-               memcpy (&fepriv->parameters, parg,
-                       sizeof (struct dvb_frontend_parameters));
+                       memcpy (&fepriv->parameters, parg,
+                               sizeof (struct dvb_frontend_parameters));
+                       dtv_property_cache_sync(fe, &fepriv->parameters);
+               }
 
                memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
                memcpy(&fetunesettings.parameters, parg,
@@ -1027,10 +1679,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
        };
 
-       up (&fepriv->sem);
        return err;
 }
 
+
 static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct dvb_device *dvbdev = file->private_data;
index aa4133f0bd1911d093b4e386aba4ab0c965f6ba8..3055301ff3cab3da0ee4a8ef555b9aa09c4a459d 100644 (file)
@@ -169,6 +169,9 @@ struct dvb_frontend_ops {
 
        struct dvb_tuner_ops tuner_ops;
        struct analog_demod_ops analog_ops;
+
+       int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+       int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
 };
 
 #define MAX_EVENT 8
@@ -182,6 +185,32 @@ struct dvb_fe_events {
        struct mutex              mtx;
 };
 
+struct dtv_frontend_properties {
+
+       /* Cache State */
+       u32                     state;
+
+       u32                     frequency;
+       fe_modulation_t         modulation;
+
+       fe_sec_voltage_t        voltage;
+       fe_sec_tone_mode_t      sectone;
+       fe_spectral_inversion_t inversion;
+       fe_code_rate_t          fec_inner;
+       fe_transmit_mode_t      transmission_mode;
+       u32                     bandwidth_hz;   /* 0 = AUTO */
+       fe_guard_interval_t     guard_interval;
+       fe_hierarchy_t          hierarchy;
+       u32                     symbol_rate;
+       fe_code_rate_t          code_rate_HP;
+       fe_code_rate_t          code_rate_LP;
+
+       fe_pilot_t              pilot;
+       fe_rolloff_t            rolloff;
+
+       fe_delivery_system_t    delivery_system;
+};
+
 struct dvb_frontend {
        struct dvb_frontend_ops ops;
        struct dvb_adapter *dvb;
@@ -190,6 +219,9 @@ struct dvb_frontend {
        void *frontend_priv;
        void *sec_priv;
        void *analog_demod_priv;
+       struct dtv_frontend_properties dtv_property_cache;
+#define DVB_FRONTEND_COMPONENT_TUNER 0
+       int (*callback)(void *adapter_priv, int component, int cmd, int arg);
 };
 
 extern int dvb_register_frontend(struct dvb_adapter *dvb,
index e7132770a3bfdd656117890d11ff4ee6c9195302..665776d72a48c0456b712b25894760e60f48e4e8 100644 (file)
@@ -233,7 +233,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 
        mutex_unlock(&dvbdev_register_lock);
 
-       clsdev = device_create_drvdata(dvb_class, adap->device,
+       clsdev = device_create(dvb_class, adap->device,
                               MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
                               NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
        if (IS_ERR(clsdev)) {
index e84152b7576d731940fc957b22c77b0e42f67a4f..3c13bcfa6385719e6f1388a4682e9e0c767dd1ea 100644 (file)
@@ -72,9 +72,11 @@ config DVB_USB_DIB0700
        select DVB_DIB7000P
        select DVB_DIB7000M
        select DVB_DIB3000MC
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
        select DVB_TUNER_DIB0070
        help
          Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -108,6 +110,8 @@ config DVB_USB_CXUSB
        select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+       select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -245,12 +249,25 @@ config DVB_USB_AF9005_REMOTE
          Afatech AF9005 based receiver.
 
 config DVB_USB_DW2102
-       tristate "DvbWorld 2102 DVB-S USB2.0 receiver"
+       tristate "DvbWorld DVB-S/S2 USB2.0 support"
        depends on DVB_USB
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
        select DVB_PLL if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_STV0288 if !DVB_FE_CUSTOMISE
+       select DVB_STB6000 if !DVB_FE_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_SI21XX if !DVB_FE_CUSTOMISE
        help
-          Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver.
+         Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
+         and the TeVii S650.
+
+config         DVB_USB_CINERGY_T2
+       tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
+       depends on DVB_USB
+       help
+         Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
+
+         Say Y if you own such a device and want to use it.
 
 config DVB_USB_ANYSEE
        tristate "Anysee DVB-T/C USB2.0 support"
@@ -262,3 +279,22 @@ config DVB_USB_ANYSEE
        help
          Say Y here to support the Anysee E30, Anysee E30 Plus or
          Anysee E30 C Plus DVB USB2.0 receiver.
+
+config DVB_USB_DTV5100
+       tristate "AME DTV-5100 USB2.0 DVB-T support"
+       depends on DVB_USB
+       select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
+
+config DVB_USB_AF9015
+       tristate "Afatech AF9015 DVB-T USB2.0 support"
+       depends on DVB_USB && EXPERIMENTAL
+       select DVB_AF9013
+       select DVB_PLL              if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060   if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_QT1010   if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
index e206f1ea0027c9804789525fa9a558c3bcaf6be1..3122b7cc2c239b74514339398d29ccd2fbb5809e 100644 (file)
@@ -67,6 +67,16 @@ obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
 dvb-usb-dw2102-objs = dw2102.o
 obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
 
+dvb-usb-dtv5100-objs = dtv5100.o
+obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
+
+dvb-usb-af9015-objs = af9015.o
+obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
+
+dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
+obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
+
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
index ff00c0e8f4a1ce34c28000c481af51012852c260..7c596f926764376d8ebfdd24c5f7f8f9f576d4e0 100644 (file)
@@ -25,7 +25,7 @@
  */
 #include "af9005.h"
 /* debug */
-int dvb_usb_af9005_remote_debug;
+static int dvb_usb_af9005_remote_debug;
 module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644);
 MODULE_PARM_DESC(debug,
                 "enable (1) or disable (0) debug messages."
index 6eeaae51b1ca585ec9ad9962f58d8ea19aa29b15..4d69045426ddd3e7c394f3486849ab1c6c8e9543 100644 (file)
@@ -14,7 +14,7 @@ typedef struct {
        u8 val;
 } RegDesc;
 
-RegDesc script[] = {
+static RegDesc script[] = {
        {0xa180, 0x0, 0x8, 0xa},
        {0xa181, 0x0, 0x8, 0xd7},
        {0xa182, 0x0, 0x8, 0xa3},
index cfe71feefcad27a8e64598316a366bda99ae8985..ca5a0a4d2a47c9ba9bc21ce4ce2173665eac66b4 100644 (file)
@@ -35,17 +35,17 @@ module_param_named(led, dvb_usb_af9005_led, bool, 0644);
 MODULE_PARM_DESC(led, "enable led (default: 1).");
 
 /* eeprom dump */
-int dvb_usb_af9005_dump_eeprom = 0;
+static int dvb_usb_af9005_dump_eeprom;
 module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
 MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 /* remote control decoder */
-int (*rc_decode) (struct dvb_usb_device * d, u8 * data, int len, u32 * event,
-                 int *state);
-void *rc_keys;
-int *rc_keys_size;
+static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len,
+               u32 *event, int *state);
+static void *rc_keys;
+static int *rc_keys_size;
 
 u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
 
@@ -54,8 +54,8 @@ struct af9005_device_state {
        int led_state;
 };
 
-int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen,
-                         u8 * rbuf, u16 rlen, int delay_ms)
+static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen,
+                         u8 *rbuf, u16 rlen, int delay_ms)
 {
        int actlen, ret = -ENOMEM;
 
@@ -98,12 +98,7 @@ int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 * wbuf, u16 wlen,
        return ret;
 }
 
-int af9005_usb_generic_write(struct dvb_usb_device *d, u8 * buf, u16 len)
-{
-       return af9005_usb_generic_rw(d, buf, len, NULL, 0, 0);
-}
-
-int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
+static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
                              int readwrite, int type, u8 * values, int len)
 {
        struct af9005_device_state *st = d->priv;
@@ -765,7 +760,7 @@ static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
        return 0;
 }
 
-int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
+static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
 {
        int i, packets, ret, act_len;
 
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
new file mode 100644 (file)
index 0000000..cb0829c
--- /dev/null
@@ -0,0 +1,1474 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided 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 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 "af9015.h"
+#include "af9013.h"
+#include "mt2060.h"
+#include "qt1010.h"
+#include "tda18271.h"
+#include "mxl5005s.h"
+#if 0
+#include "mc44s80x.h"
+#endif
+
+int dvb_usb_af9015_debug;
+module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+int dvb_usb_af9015_remote;
+module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
+MODULE_PARM_DESC(remote, "select remote");
+int dvb_usb_af9015_dual_mode;
+module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);
+MODULE_PARM_DESC(dual_mode, "enable dual mode");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static DEFINE_MUTEX(af9015_usb_mutex);
+
+static struct af9015_config af9015_config;
+static struct dvb_usb_device_properties af9015_properties[2];
+int af9015_properties_count = ARRAY_SIZE(af9015_properties);
+
+static struct af9013_config af9015_af9013_config[] = {
+       {
+               .demod_address = AF9015_I2C_DEMOD,
+               .output_mode = AF9013_OUTPUT_MODE_USB,
+               .api_version = { 0, 1, 9, 0 },
+               .gpio[0] = AF9013_GPIO_HI,
+               .gpio[3] = AF9013_GPIO_TUNER_ON,
+
+       }, {
+               .output_mode = AF9013_OUTPUT_MODE_SERIAL,
+               .api_version = { 0, 1, 9, 0 },
+               .gpio[0] = AF9013_GPIO_TUNER_ON,
+               .gpio[1] = AF9013_GPIO_LO,
+       }
+};
+
+static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
+{
+       int act_len, ret;
+       u8 buf[64];
+       u8 write = 1;
+       u8 msg_len = 8;
+       static u8 seq; /* packet sequence number */
+
+       if (mutex_lock_interruptible(&af9015_usb_mutex) < 0)
+               return -EAGAIN;
+
+       buf[0] = req->cmd;
+       buf[1] = seq++;
+       buf[2] = req->i2c_addr;
+       buf[3] = req->addr >> 8;
+       buf[4] = req->addr & 0xff;
+       buf[5] = req->mbox;
+       buf[6] = req->addr_len;
+       buf[7] = req->data_len;
+
+       switch (req->cmd) {
+       case GET_CONFIG:
+       case BOOT:
+       case READ_MEMORY:
+       case RECONNECT_USB:
+       case GET_IR_CODE:
+               write = 0;
+               break;
+       case READ_I2C:
+               write = 0;
+               buf[2] |= 0x01; /* set I2C direction */
+       case WRITE_I2C:
+               buf[0] = READ_WRITE_I2C;
+               break;
+       case WRITE_MEMORY:
+               if (((req->addr & 0xff00) == 0xff00) ||
+                   ((req->addr & 0xae00) == 0xae00))
+                       buf[0] = WRITE_VIRTUAL_MEMORY;
+       case WRITE_VIRTUAL_MEMORY:
+       case COPY_FIRMWARE:
+       case DOWNLOAD_FIRMWARE:
+               break;
+       default:
+               err("unknown command:%d", req->cmd);
+               ret = -1;
+               goto error_unlock;
+       }
+
+       /* write requested */
+       if (write) {
+               memcpy(&buf[8], req->data, req->data_len);
+               msg_len += req->data_len;
+       }
+       deb_xfer(">>> ");
+       debug_dump(buf, msg_len, deb_xfer);
+
+       /* send req */
+       ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
+       &act_len, AF9015_USB_TIMEOUT);
+       if (ret)
+               err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len);
+       else
+               if (act_len != msg_len)
+                       ret = -1; /* all data is not send */
+       if (ret)
+               goto error_unlock;
+
+       /* no ack for those packets */
+       if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
+               goto exit_unlock;
+
+       /* receive ack and data if read req */
+       msg_len = 1 + 1 + req->data_len;  /* seq + status + data len */
+       ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
+                          &act_len, AF9015_USB_TIMEOUT);
+       if (ret) {
+               err("recv bulk message failed:%d", ret);
+               ret = -1;
+               goto error_unlock;
+       }
+
+       deb_xfer("<<< ");
+       debug_dump(buf, act_len, deb_xfer);
+
+       /* remote controller query status is 1 if remote code is not received */
+       if (req->cmd == GET_IR_CODE && buf[1] == 1) {
+               buf[1] = 0; /* clear command "error" status */
+               memset(&buf[2], 0, req->data_len);
+               buf[3] = 1; /* no remote code received mark */
+       }
+
+       /* check status */
+       if (buf[1]) {
+               err("command failed:%d", buf[1]);
+               ret = -1;
+               goto error_unlock;
+       }
+
+       /* read request, copy returned data to return buf */
+       if (!write)
+               memcpy(req->data, &buf[2], req->data_len);
+
+error_unlock:
+exit_unlock:
+       mutex_unlock(&af9015_usb_mutex);
+
+       return ret;
+}
+
+static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
+{
+       return af9015_rw_udev(d->udev, req);
+}
+
+static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
+       u8 len)
+{
+       struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
+               val};
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
+{
+       return af9015_write_regs(d, addr, &val, 1);
+}
+
+static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
+{
+       struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val};
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+       u8 val)
+{
+       struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
+
+       if (addr == af9015_af9013_config[0].demod_address ||
+           addr == af9015_af9013_config[1].demod_address)
+               req.addr_len = 3;
+
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+       u8 *val)
+{
+       struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
+
+       if (addr == af9015_af9013_config[0].demod_address ||
+           addr == af9015_af9013_config[1].demod_address)
+               req.addr_len = 3;
+
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+       int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int ret = 0, i = 0;
+       u16 addr;
+       u8 mbox, addr_len;
+       struct req_t req;
+
+/* TODO: implement bus lock
+
+The bus lock is needed because there is two tuners both using same I2C-address.
+Due to that the only way to select correct tuner is use demodulator I2C-gate.
+
+................................................
+. AF9015 includes integrated AF9013 demodulator.
+. ____________                   ____________  .                ____________
+.|     uC     |                 |   demod    | .               |    tuner   |
+.|------------|                 |------------| .               |------------|
+.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |
+.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |
+.|            |  |              | addr 0x38  | .               |  addr 0xc6 |
+.|____________|  |              |____________| .               |____________|
+.................|..............................
+                |               ____________                   ____________
+                |              |   demod    |                 |    tuner   |
+                |              |------------|                 |------------|
+                |              |   AF9013   |                 |   MXL5003  |
+                +----I2C-------|-----/ -----|-------I2C-------|            |
+                               | addr 0x3a  |                 |  addr 0xc6 |
+                               |____________|                 |____________|
+*/
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       while (i < num) {
+               if (msg[i].addr == af9015_af9013_config[0].demod_address ||
+                   msg[i].addr == af9015_af9013_config[1].demod_address) {
+                       addr = msg[i].buf[0] << 8;
+                       addr += msg[i].buf[1];
+                       mbox = msg[i].buf[2];
+                       addr_len = 3;
+               } else {
+                       addr = msg[i].buf[0];
+                       addr_len = 1;
+                       mbox = 0;
+               }
+
+               if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+                       if (msg[i].addr ==
+                               af9015_af9013_config[0].demod_address)
+                               req.cmd = READ_MEMORY;
+                       else
+                               req.cmd = READ_I2C;
+                       req.i2c_addr = msg[i].addr;
+                       req.addr = addr;
+                       req.mbox = mbox;
+                       req.addr_len = addr_len;
+                       req.data_len = msg[i+1].len;
+                       req.data = &msg[i+1].buf[0];
+                       ret = af9015_ctrl_msg(d, &req);
+                       i += 2;
+               } else {
+                       if (msg[i].addr ==
+                               af9015_af9013_config[0].demod_address)
+                               req.cmd = WRITE_MEMORY;
+                       else
+                               req.cmd = WRITE_I2C;
+                       req.i2c_addr = msg[i].addr;
+                       req.addr = addr;
+                       req.mbox = mbox;
+                       req.addr_len = addr_len;
+                       req.data_len = msg[i].len-addr_len;
+                       req.data = &msg[i].buf[addr_len];
+                       ret = af9015_ctrl_msg(d, &req);
+                       i += 1;
+               }
+               if (ret)
+                       goto error;
+
+       }
+       ret = i;
+
+error:
+       mutex_unlock(&d->i2c_mutex);
+
+       return ret;
+}
+
+static u32 af9015_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm af9015_i2c_algo = {
+       .master_xfer = af9015_i2c_xfer,
+       .functionality = af9015_i2c_func,
+};
+
+static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
+{
+       int ret;
+       u8 val, mask = 0x01;
+
+       ret = af9015_read_reg(d, addr, &val);
+       if (ret)
+               return ret;
+
+       mask <<= bit;
+       if (op) {
+               /* set bit */
+               val |= mask;
+       } else {
+               /* clear bit */
+               mask ^= 0xff;
+               val &= mask;
+       }
+
+       return af9015_write_reg(d, addr, val);
+}
+
+static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+       return af9015_do_reg_bit(d, addr, bit, 1);
+}
+
+static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+       return af9015_do_reg_bit(d, addr, bit, 0);
+}
+
+static int af9015_init_endpoint(struct dvb_usb_device *d)
+{
+       int ret;
+       u16 frame_size;
+       u8  packet_size;
+       deb_info("%s: USB speed:%d\n", __func__, d->udev->speed);
+
+#define TS_PACKET_SIZE            188
+
+#define TS_USB20_PACKET_COUNT     348
+#define TS_USB20_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)
+
+#define TS_USB11_PACKET_COUNT      21
+#define TS_USB11_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)
+
+#define TS_USB20_MAX_PACKET_SIZE  512
+#define TS_USB11_MAX_PACKET_SIZE   64
+
+       if (d->udev->speed == USB_SPEED_FULL) {
+               frame_size = TS_USB11_FRAME_SIZE/4;
+               packet_size = TS_USB11_MAX_PACKET_SIZE/4;
+       } else {
+               frame_size = TS_USB20_FRAME_SIZE/4;
+               packet_size = TS_USB20_MAX_PACKET_SIZE/4;
+       }
+
+       ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */
+       if (ret)
+               goto error;
+       ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */
+       if (ret)
+               goto error;
+       ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */
+       if (ret)
+               goto error;
+       if (af9015_config.dual_mode) {
+               ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */
+               if (ret)
+                       goto error;
+       }
+       ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */
+       if (ret)
+               goto error;
+       if (af9015_config.dual_mode) {
+               ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */
+               if (ret)
+                       goto error;
+       }
+       /* EP4 xfer length */
+       ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);
+       if (ret)
+               goto error;
+       /* EP5 xfer length */
+       ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */
+       if (ret)
+               goto error;
+       if (af9015_config.dual_mode) {
+               ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */
+               if (ret)
+                       goto error;
+       }
+
+       /* enable / disable mp2if2 */
+       if (af9015_config.dual_mode)
+               ret = af9015_set_reg_bit(d, 0xd50b, 0);
+       else
+               ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+error:
+       if (ret)
+               err("endpoint init failed:%d", ret);
+       return ret;
+}
+
+static int af9015_copy_firmware(struct dvb_usb_device *d)
+{
+       int ret;
+       u8 fw_params[4];
+       u8 val, i;
+       struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
+               fw_params };
+       deb_info("%s:\n", __func__);
+
+       fw_params[0] = af9015_config.firmware_size >> 8;
+       fw_params[1] = af9015_config.firmware_size & 0xff;
+       fw_params[2] = af9015_config.firmware_checksum >> 8;
+       fw_params[3] = af9015_config.firmware_checksum & 0xff;
+
+       /* wait 2nd demodulator ready */
+       msleep(100);
+
+       ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val);
+       if (ret)
+               goto error;
+       else
+               deb_info("%s: firmware status:%02x\n", __func__, val);
+
+       if (val == 0x0c) /* fw is running, no need for download */
+               goto exit;
+
+       /* set I2C master clock to fast (to speed up firmware copy) */
+       ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
+       if (ret)
+               goto error;
+
+       msleep(50);
+
+       /* copy firmware */
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret)
+               err("firmware copy cmd failed:%d", ret);
+       deb_info("%s: firmware copy done\n", __func__);
+
+       /* set I2C master clock back to normal */
+       ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
+       if (ret)
+               goto error;
+
+       /* request boot firmware */
+       ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].demod_address,
+               0xe205, 1);
+       deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
+       if (ret)
+               goto error;
+
+       for (i = 0; i < 15; i++) {
+               msleep(100);
+
+               /* check firmware status */
+               ret = af9015_read_reg_i2c(d,
+                       af9015_af9013_config[1].demod_address, 0x98be, &val);
+               deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
+                       __func__, ret, val);
+               if (ret)
+                       goto error;
+
+               if (val == 0x0c || val == 0x04) /* success or fail */
+                       break;
+       }
+
+       if (val == 0x04) {
+               err("firmware did not run");
+               ret = -1;
+       } else if (val != 0x0c) {
+               err("firmware boot timeout");
+               ret = -1;
+       }
+
+error:
+exit:
+       return ret;
+}
+
+/* dump eeprom */
+static int af9015_eeprom_dump(struct dvb_usb_device *d)
+{
+       char buf[52], buf2[4];
+       u8 reg, val;
+
+       for (reg = 0; ; reg++) {
+               if (reg % 16 == 0) {
+                       if (reg)
+                               deb_info("%s\n", buf);
+                       sprintf(buf, "%02x: ", reg);
+               }
+               if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0)
+                       sprintf(buf2, "%02x ", val);
+               else
+                       strcpy(buf2, "-- ");
+               strcat(buf, buf2);
+               if (reg == 0xff)
+                       break;
+       }
+       deb_info("%s\n", buf);
+       return 0;
+}
+
+int af9015_download_ir_table(struct dvb_usb_device *d)
+{
+       int i, packets = 0, ret;
+       u16 addr = 0x9a56; /* ir-table start address */
+       struct req_t req = {WRITE_MEMORY, 0, 0, 0, 0, 1, NULL};
+       u8 *data = NULL;
+       deb_info("%s:\n", __func__);
+
+       data = af9015_config.ir_table;
+       packets = af9015_config.ir_table_size;
+
+       /* no remote */
+       if (!packets)
+               goto exit;
+
+       /* load remote ir-table */
+       for (i = 0; i < packets; i++) {
+               req.addr = addr + i;
+               req.data = &data[i];
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret) {
+                       err("ir-table download failed at packet %d with " \
+                               "code %d", i, ret);
+                       return ret;
+               }
+       }
+
+exit:
+       return 0;
+}
+
+static int af9015_init(struct dvb_usb_device *d)
+{
+       int ret;
+       deb_info("%s:\n", __func__);
+
+       ret = af9015_init_endpoint(d);
+       if (ret)
+               goto error;
+
+       ret = af9015_download_ir_table(d);
+       if (ret)
+               goto error;
+
+error:
+       return ret;
+}
+
+static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       int ret;
+       deb_info("%s: onoff:%d\n", __func__, onoff);
+
+       if (onoff)
+               ret = af9015_set_reg_bit(adap->dev, 0xd503, 0);
+       else
+               ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0);
+
+       return ret;
+}
+
+static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+       int onoff)
+{
+       int ret;
+       u8 idx;
+
+       deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n",
+               __func__, index, pid, onoff);
+
+       ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff));
+       if (ret)
+               goto error;
+
+       ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8));
+       if (ret)
+               goto error;
+
+       idx = ((index & 0x1f) | (1 << 5));
+       ret = af9015_write_reg(adap->dev, 0xd504, idx);
+
+error:
+       return ret;
+}
+
+static int af9015_download_firmware(struct usb_device *udev,
+       const struct firmware *fw)
+{
+       int i, len, packets, remainder, ret;
+       struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
+       u16 addr = 0x5100; /* firmware start address */
+       u16 checksum = 0;
+
+       deb_info("%s:\n", __func__);
+
+       /* calc checksum */
+       for (i = 0; i < fw->size; i++)
+               checksum += fw->data[i];
+
+       af9015_config.firmware_size = fw->size;
+       af9015_config.firmware_checksum = checksum;
+
+       #define FW_PACKET_MAX_DATA  55
+
+       packets = fw->size / FW_PACKET_MAX_DATA;
+       remainder = fw->size % FW_PACKET_MAX_DATA;
+       len = FW_PACKET_MAX_DATA;
+       for (i = 0; i <= packets; i++) {
+               if (i == packets)  /* set size of the last packet */
+                       len = remainder;
+
+               req.data_len = len;
+               req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
+               req.addr = addr;
+               addr += FW_PACKET_MAX_DATA;
+
+               ret = af9015_rw_udev(udev, &req);
+               if (ret) {
+                       err("firmware download failed at packet %d with " \
+                               "code %d", i, ret);
+                       goto error;
+               }
+       }
+
+       /* firmware loaded, request boot */
+       req.cmd = BOOT;
+       ret = af9015_rw_udev(udev, &req);
+       if (ret) {
+               err("firmware boot failed:%d", ret);
+               goto error;
+       }
+
+       /* firmware is running, reconnect device in the usb bus */
+       req.cmd = RECONNECT_USB;
+       ret = af9015_rw_udev(udev, &req);
+       if (ret)
+               err("reconnect failed: %d", ret);
+
+error:
+       return ret;
+}
+
+static int af9015_read_config(struct usb_device *udev)
+{
+       int ret;
+       u8 val, i, offset = 0;
+       struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
+       char manufacturer[10];
+
+       /* IR remote controller */
+       req.addr = AF9015_EEPROM_IR_MODE;
+       ret = af9015_rw_udev(udev, &req);
+       if (ret)
+               goto error;
+       deb_info("%s: IR mode:%d\n", __func__, val);
+       for (i = 0; i < af9015_properties_count; i++) {
+               if (val == AF9015_IR_MODE_DISABLED || val == 0x04) {
+                       af9015_properties[i].rc_key_map = NULL;
+                       af9015_properties[i].rc_key_map_size  = 0;
+               } else if (dvb_usb_af9015_remote) {
+                       /* load remote defined as module param */
+                       switch (dvb_usb_af9015_remote) {
+                       case AF9015_REMOTE_A_LINK_DTU_M:
+                               af9015_properties[i].rc_key_map =
+                                 af9015_rc_keys_a_link;
+                               af9015_properties[i].rc_key_map_size =
+                                 ARRAY_SIZE(af9015_rc_keys_a_link);
+                               af9015_config.ir_table = af9015_ir_table_a_link;
+                               af9015_config.ir_table_size =
+                                 ARRAY_SIZE(af9015_ir_table_a_link);
+                               break;
+                       case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
+                               af9015_properties[i].rc_key_map =
+                                 af9015_rc_keys_msi;
+                               af9015_properties[i].rc_key_map_size =
+                                 ARRAY_SIZE(af9015_rc_keys_msi);
+                               af9015_config.ir_table = af9015_ir_table_msi;
+                               af9015_config.ir_table_size =
+                                 ARRAY_SIZE(af9015_ir_table_msi);
+                               break;
+                       case AF9015_REMOTE_MYGICTV_U718:
+                               af9015_properties[i].rc_key_map =
+                                 af9015_rc_keys_mygictv;
+                               af9015_properties[i].rc_key_map_size =
+                                 ARRAY_SIZE(af9015_rc_keys_mygictv);
+                               af9015_config.ir_table =
+                                 af9015_ir_table_mygictv;
+                               af9015_config.ir_table_size =
+                                 ARRAY_SIZE(af9015_ir_table_mygictv);
+                               break;
+                       }
+               } else {
+                       switch (udev->descriptor.idVendor) {
+                       case USB_VID_LEADTEK:
+                               af9015_properties[i].rc_key_map =
+                                 af9015_rc_keys_leadtek;
+                               af9015_properties[i].rc_key_map_size =
+                                 ARRAY_SIZE(af9015_rc_keys_leadtek);
+                               af9015_config.ir_table =
+                                 af9015_ir_table_leadtek;
+                               af9015_config.ir_table_size =
+                                 ARRAY_SIZE(af9015_ir_table_leadtek);
+                               break;
+                       case USB_VID_VISIONPLUS:
+                               if (udev->descriptor.idProduct ==
+                               USB_PID_AZUREWAVE_AD_TU700) {
+                                       af9015_properties[i].rc_key_map =
+                                         af9015_rc_keys_twinhan;
+                                       af9015_properties[i].rc_key_map_size =
+                                         ARRAY_SIZE(af9015_rc_keys_twinhan);
+                                       af9015_config.ir_table =
+                                         af9015_ir_table_twinhan;
+                                       af9015_config.ir_table_size =
+                                         ARRAY_SIZE(af9015_ir_table_twinhan);
+                               }
+                               break;
+                       case USB_VID_KWORLD_2:
+                               /* TODO: use correct rc keys */
+                               af9015_properties[i].rc_key_map =
+                                 af9015_rc_keys_twinhan;
+                               af9015_properties[i].rc_key_map_size =
+                                 ARRAY_SIZE(af9015_rc_keys_twinhan);
+                               af9015_config.ir_table = af9015_ir_table_kworld;
+                               af9015_config.ir_table_size =
+                                 ARRAY_SIZE(af9015_ir_table_kworld);
+                               break;
+                       /* Check USB manufacturer and product strings and try
+                          to determine correct remote in case of chip vendor
+                          reference IDs are used. */
+                       case USB_VID_AFATECH:
+                               memset(manufacturer, 0, sizeof(manufacturer));
+                               usb_string(udev, udev->descriptor.iManufacturer,
+                                       manufacturer, sizeof(manufacturer));
+                               if (!strcmp("Geniatech", manufacturer)) {
+                                       /* iManufacturer 1 Geniatech
+                                          iProduct      2 AF9015 */
+                                       af9015_properties[i].rc_key_map =
+                                         af9015_rc_keys_mygictv;
+                                       af9015_properties[i].rc_key_map_size =
+                                         ARRAY_SIZE(af9015_rc_keys_mygictv);
+                                       af9015_config.ir_table =
+                                         af9015_ir_table_mygictv;
+                                       af9015_config.ir_table_size =
+                                         ARRAY_SIZE(af9015_ir_table_mygictv);
+                               } else if (!strcmp("MSI", manufacturer)) {
+                                       /* iManufacturer 1 MSI
+                                          iProduct      2 MSI K-VOX */
+                                       af9015_properties[i].rc_key_map =
+                                         af9015_rc_keys_msi;
+                                       af9015_properties[i].rc_key_map_size =
+                                         ARRAY_SIZE(af9015_rc_keys_msi);
+                                       af9015_config.ir_table =
+                                         af9015_ir_table_msi;
+                                       af9015_config.ir_table_size =
+                                         ARRAY_SIZE(af9015_ir_table_msi);
+                               }
+                               break;
+                       }
+               }
+       }
+
+       /* TS mode - one or two receivers */
+       req.addr = AF9015_EEPROM_TS_MODE;
+       ret = af9015_rw_udev(udev, &req);
+       if (ret)
+               goto error;
+       af9015_config.dual_mode = val;
+       deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
+       /* disable dual mode by default because it is buggy */
+       if (!dvb_usb_af9015_dual_mode)
+               af9015_config.dual_mode = 0;
+
+       /* set buffer size according to USB port speed */
+       for (i = 0; i < af9015_properties_count; i++) {
+               /* USB1.1 set smaller buffersize and disable 2nd adapter */
+               if (udev->speed == USB_SPEED_FULL) {
+                       af9015_properties[i].adapter->stream.u.bulk.buffersize =
+                               TS_USB11_MAX_PACKET_SIZE;
+                       /* disable 2nd adapter because we don't have
+                          PID-filters */
+                       af9015_config.dual_mode = 0;
+               } else {
+                       af9015_properties[i].adapter->stream.u.bulk.buffersize =
+                               TS_USB20_MAX_PACKET_SIZE;
+               }
+       }
+
+       if (af9015_config.dual_mode) {
+               /* read 2nd demodulator I2C address */
+               req.addr = AF9015_EEPROM_DEMOD2_I2C;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               af9015_af9013_config[1].demod_address = val;
+
+               /* enable 2nd adapter */
+               for (i = 0; i < af9015_properties_count; i++)
+                       af9015_properties[i].num_adapters = 2;
+
+       } else {
+                /* disable 2nd adapter */
+               for (i = 0; i < af9015_properties_count; i++)
+                       af9015_properties[i].num_adapters = 1;
+       }
+
+       for (i = 0; i < af9015_properties[0].num_adapters; i++) {
+               if (i == 1)
+                       offset = AF9015_EEPROM_OFFSET;
+               /* xtal */
+               req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               switch (val) {
+               case 0:
+                       af9015_af9013_config[i].adc_clock = 28800;
+                       break;
+               case 1:
+                       af9015_af9013_config[i].adc_clock = 20480;
+                       break;
+               case 2:
+                       af9015_af9013_config[i].adc_clock = 28000;
+                       break;
+               case 3:
+                       af9015_af9013_config[i].adc_clock = 25000;
+                       break;
+               };
+               deb_info("%s: [%d] xtal:%d set adc_clock:%d\n", __func__, i,
+                       val, af9015_af9013_config[i].adc_clock);
+
+               /* tuner IF */
+               req.addr = AF9015_EEPROM_IF1H + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               af9015_af9013_config[i].tuner_if = val << 8;
+               req.addr = AF9015_EEPROM_IF1L + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               af9015_af9013_config[i].tuner_if += val;
+               deb_info("%s: [%d] IF1:%d\n", __func__, i,
+                       af9015_af9013_config[0].tuner_if);
+
+               /* MT2060 IF1 */
+               req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               af9015_config.mt2060_if1[i] = val << 8;
+               req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               af9015_config.mt2060_if1[i] += val;
+               deb_info("%s: [%d] MT2060 IF1:%d\n", __func__, i,
+                       af9015_config.mt2060_if1[i]);
+
+               /* tuner */
+               req.addr =  AF9015_EEPROM_TUNER_ID1 + offset;
+               ret = af9015_rw_udev(udev, &req);
+               if (ret)
+                       goto error;
+               switch (val) {
+               case AF9013_TUNER_ENV77H11D5:
+               case AF9013_TUNER_MT2060:
+               case AF9013_TUNER_MC44S803:
+               case AF9013_TUNER_QT1010:
+               case AF9013_TUNER_UNKNOWN:
+               case AF9013_TUNER_MT2060_2:
+               case AF9013_TUNER_TDA18271:
+               case AF9013_TUNER_QT1010A:
+                       af9015_af9013_config[i].rf_spec_inv = 1;
+                       break;
+               case AF9013_TUNER_MXL5003D:
+               case AF9013_TUNER_MXL5005D:
+               case AF9013_TUNER_MXL5005R:
+                       af9015_af9013_config[i].rf_spec_inv = 0;
+                       break;
+               default:
+                       warn("tuner id:%d not supported, please report!", val);
+                       return -ENODEV;
+               };
+
+               af9015_af9013_config[i].tuner = val;
+               deb_info("%s: [%d] tuner id:%d\n", __func__, i, val);
+       }
+
+error:
+       if (ret)
+               err("eeprom read failed:%d", ret);
+
+       return ret;
+}
+
+static int af9015_identify_state(struct usb_device *udev,
+                                struct dvb_usb_device_properties *props,
+                                struct dvb_usb_device_description **desc,
+                                int *cold)
+{
+       int ret;
+       u8 reply;
+       struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};
+
+       ret = af9015_rw_udev(udev, &req);
+       if (ret)
+               return ret;
+
+       deb_info("%s: reply:%02x\n", __func__, reply);
+       if (reply == 0x02)
+               *cold = 0;
+       else
+               *cold = 1;
+
+       return ret;
+}
+
+static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       u8 buf[8];
+       struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf};
+       struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+       int i, ret;
+
+       memset(buf, 0, sizeof(buf));
+
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret)
+               return ret;
+
+       *event = 0;
+       *state = REMOTE_NO_KEY_PRESSED;
+
+       for (i = 0; i < d->props.rc_key_map_size; i++) {
+               if (!buf[1] && keymap[i].custom == buf[0] &&
+                   keymap[i].data == buf[2]) {
+                       *event = keymap[i].event;
+                       *state = REMOTE_KEY_PRESSED;
+                       break;
+               }
+       }
+       if (!buf[1])
+               deb_rc("%s: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+                       __func__, buf[0], buf[1], buf[2], buf[3], buf[4],
+                       buf[5], buf[6], buf[7]);
+
+       return 0;
+}
+
+/* init 2nd I2C adapter */
+int af9015_i2c_init(struct dvb_usb_device *d)
+{
+       int ret;
+       struct af9015_state *state = d->priv;
+       deb_info("%s:\n", __func__);
+
+       strncpy(state->i2c_adap.name, d->desc->name,
+               sizeof(state->i2c_adap.name));
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+       state->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
+#else
+       state->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
+#endif
+       state->i2c_adap.algo      = d->props.i2c_algo;
+       state->i2c_adap.algo_data = NULL;
+       state->i2c_adap.dev.parent = &d->udev->dev;
+
+       i2c_set_adapdata(&state->i2c_adap, d);
+
+       ret = i2c_add_adapter(&state->i2c_adap);
+       if (ret < 0)
+               err("could not add i2c adapter");
+
+       return ret;
+}
+
+static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       struct af9015_state *state = adap->dev->priv;
+       struct i2c_adapter *i2c_adap;
+
+       if (adap->id == 0) {
+               /* select I2C adapter */
+               i2c_adap = &adap->dev->i2c_adap;
+
+               deb_info("%s: init I2C\n", __func__);
+               ret = af9015_i2c_init(adap->dev);
+
+               /* dump eeprom (debug) */
+               ret = af9015_eeprom_dump(adap->dev);
+               if (ret)
+                       return ret;
+       } else {
+               /* select I2C adapter */
+               i2c_adap = &state->i2c_adap;
+
+               /* copy firmware to 2nd demodulator */
+               if (af9015_config.dual_mode) {
+                       ret = af9015_copy_firmware(adap->dev);
+                       if (ret) {
+                               err("firmware copy to 2nd frontend " \
+                                       "failed, will disable it");
+                               af9015_config.dual_mode = 0;
+                               return -ENODEV;
+                       }
+               } else {
+                       return -ENODEV;
+               }
+       }
+
+       /* attach demodulator */
+       adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
+               i2c_adap);
+
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static struct mt2060_config af9015_mt2060_config = {
+       .i2c_address = 0xc0,
+       .clock_out = 0,
+};
+
+static struct qt1010_config af9015_qt1010_config = {
+       .i2c_address = 0xc4,
+};
+
+static struct tda18271_config af9015_tda18271_config = {
+       .gate = TDA18271_GATE_DIGITAL,
+       .small_i2c = 1,
+};
+
+static struct mxl5005s_config af9015_mxl5003_config = {
+       .i2c_address     = 0xc6,
+       .if_freq         = IF_FREQ_4570000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_DEFAULT,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
+static struct mxl5005s_config af9015_mxl5005_config = {
+       .i2c_address     = 0xc6,
+       .if_freq         = IF_FREQ_4570000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_OFF,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
+static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct af9015_state *state = adap->dev->priv;
+       struct i2c_adapter *i2c_adap;
+       int ret;
+       deb_info("%s: \n", __func__);
+
+       /* select I2C adapter */
+       if (adap->id == 0)
+               i2c_adap = &adap->dev->i2c_adap;
+       else
+               i2c_adap = &state->i2c_adap;
+
+       switch (af9015_af9013_config[adap->id].tuner) {
+       case AF9013_TUNER_MT2060:
+       case AF9013_TUNER_MT2060_2:
+               ret = dvb_attach(mt2060_attach, adap->fe, i2c_adap,
+                       &af9015_mt2060_config,
+                       af9015_config.mt2060_if1[adap->id])
+                       == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_QT1010:
+       case AF9013_TUNER_QT1010A:
+               ret = dvb_attach(qt1010_attach, adap->fe, i2c_adap,
+                       &af9015_qt1010_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_TDA18271:
+               ret = dvb_attach(tda18271_attach, adap->fe, 0xc0, i2c_adap,
+                       &af9015_tda18271_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MXL5003D:
+               ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+                       &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MXL5005D:
+       case AF9013_TUNER_MXL5005R:
+               ret = dvb_attach(mxl5005s_attach, adap->fe, i2c_adap,
+                       &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_ENV77H11D5:
+               ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0, i2c_adap,
+                       DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MC44S803:
+#if 0
+               ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap)
+                       == NULL ? -ENODEV : 0;
+#else
+               ret = -ENODEV;
+               info("Freescale MC44S803 tuner found but no driver for that" \
+                       "tuner. Look at the Linuxtv.org for tuner driver" \
+                       "status.");
+#endif
+               break;
+       case AF9013_TUNER_UNKNOWN:
+       default:
+               ret = -ENODEV;
+               err("Unknown tuner id:%d",
+                       af9015_af9013_config[adap->id].tuner);
+       }
+       return ret;
+}
+
+static struct usb_device_id af9015_usb_table[] = {
+/*  0 */{USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9015_9015)},
+       {USB_DEVICE(USB_VID_AFATECH,   USB_PID_AFATECH_AF9015_9016)},
+       {USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_GOLD)},
+       {USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV71E)},
+       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_399U)},
+/*  5 */{USB_DEVICE(USB_VID_VISIONPLUS,
+               USB_PID_TINYTWIN)},
+       {USB_DEVICE(USB_VID_VISIONPLUS,
+               USB_PID_AZUREWAVE_AD_TU700)},
+       {USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
+       {USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_PC160_2T)},
+       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
+/* 10 */{USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
+       {USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGIVOX_DUO)},
+       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
+       {USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
+       {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
+/* 15 */{USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGI_VOX_MINI_III)},
+       {0},
+};
+MODULE_DEVICE_TABLE(usb, af9015_usb_table);
+
+static struct dvb_usb_device_properties af9015_properties[] = {
+       {
+               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+               .usb_ctrl = DEVICE_SPECIFIC,
+               .download_firmware = af9015_download_firmware,
+               .firmware = "dvb-usb-af9015.fw",
+
+               .size_of_priv = sizeof(struct af9015_state), \
+
+               .num_adapters = 2,
+               .adapter = {
+                       {
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+                               .pid_filter_count = 32,
+                               .pid_filter       = af9015_pid_filter,
+                               .pid_filter_ctrl  = af9015_pid_filter_ctrl,
+
+                               .frontend_attach =
+                                       af9015_af9013_frontend_attach,
+                               .tuner_attach    = af9015_tuner_attach,
+                               .stream = {
+                                       .type = USB_BULK,
+                                       .count = 6,
+                                       .endpoint = 0x84,
+                               },
+                       },
+                       {
+                               .frontend_attach =
+                                       af9015_af9013_frontend_attach,
+                               .tuner_attach    = af9015_tuner_attach,
+                               .stream = {
+                                       .type = USB_BULK,
+                                       .count = 6,
+                                       .endpoint = 0x85,
+                               },
+                       }
+               },
+
+               .identify_state = af9015_identify_state,
+
+               .rc_query         = af9015_rc_query,
+               .rc_interval      = 150,
+
+               .i2c_algo = &af9015_i2c_algo,
+
+               .num_device_descs = 9,
+               .devices = {
+                       {
+                               .name = "Afatech AF9015 DVB-T USB2.0 stick",
+                               .cold_ids = {&af9015_usb_table[0],
+                                            &af9015_usb_table[1], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "Leadtek WinFast DTV Dongle Gold",
+                               .cold_ids = {&af9015_usb_table[2], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "Pinnacle PCTV 71e",
+                               .cold_ids = {&af9015_usb_table[3], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "KWorld PlusTV Dual DVB-T Stick " \
+                                       "(DVB-T 399U)",
+                               .cold_ids = {&af9015_usb_table[4], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "DigitalNow TinyTwin DVB-T Receiver",
+                               .cold_ids = {&af9015_usb_table[5], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "TwinHan AzureWave AD-TU700(704J)",
+                               .cold_ids = {&af9015_usb_table[6], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "TerraTec Cinergy T USB XE",
+                               .cold_ids = {&af9015_usb_table[7], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "KWorld PlusTV Dual DVB-T PCI " \
+                                       "(DVB-T PC160-2T)",
+                               .cold_ids = {&af9015_usb_table[8], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "AVerMedia AVerTV DVB-T Volar X",
+                               .cold_ids = {&af9015_usb_table[9], NULL},
+                               .warm_ids = {NULL},
+                       },
+               }
+       }, {
+               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+               .usb_ctrl = DEVICE_SPECIFIC,
+               .download_firmware = af9015_download_firmware,
+               .firmware = "dvb-usb-af9015.fw",
+
+               .size_of_priv = sizeof(struct af9015_state), \
+
+               .num_adapters = 2,
+               .adapter = {
+                       {
+                               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+                               .pid_filter_count = 32,
+                               .pid_filter       = af9015_pid_filter,
+                               .pid_filter_ctrl  = af9015_pid_filter_ctrl,
+
+                               .frontend_attach =
+                                       af9015_af9013_frontend_attach,
+                               .tuner_attach    = af9015_tuner_attach,
+                               .stream = {
+                                       .type = USB_BULK,
+                                       .count = 6,
+                                       .endpoint = 0x84,
+                               },
+                       },
+                       {
+                               .frontend_attach =
+                                       af9015_af9013_frontend_attach,
+                               .tuner_attach    = af9015_tuner_attach,
+                               .stream = {
+                                       .type = USB_BULK,
+                                       .count = 6,
+                                       .endpoint = 0x85,
+                               },
+                       }
+               },
+
+               .identify_state = af9015_identify_state,
+
+               .rc_query         = af9015_rc_query,
+               .rc_interval      = 150,
+
+               .i2c_algo = &af9015_i2c_algo,
+
+               .num_device_descs = 6,
+               .devices = {
+                       {
+                               .name = "Xtensions XD-380",
+                               .cold_ids = {&af9015_usb_table[10], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "MSI DIGIVOX Duo",
+                               .cold_ids = {&af9015_usb_table[11], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
+                               .cold_ids = {&af9015_usb_table[12], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "Telestar Starstick 2",
+                               .cold_ids = {&af9015_usb_table[13], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "AVerMedia A309",
+                               .cold_ids = {&af9015_usb_table[14], NULL},
+                               .warm_ids = {NULL},
+                       },
+                       {
+                               .name = "MSI Digi VOX mini III",
+                               .cold_ids = {&af9015_usb_table[15], NULL},
+                               .warm_ids = {NULL},
+                       },
+               }
+       }
+};
+
+static int af9015_usb_probe(struct usb_interface *intf,
+                           const struct usb_device_id *id)
+{
+       int ret = 0;
+       struct dvb_usb_device *d = NULL;
+       struct usb_device *udev = interface_to_usbdev(intf);
+       u8 i;
+
+       deb_info("%s: interface:%d\n", __func__,
+               intf->cur_altsetting->desc.bInterfaceNumber);
+
+       /* interface 0 is used by DVB-T receiver and
+          interface 1 is for remote controller (HID) */
+       if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+               ret = af9015_read_config(udev);
+               if (ret)
+                       return ret;
+
+               for (i = 0; i < af9015_properties_count; i++) {
+                       ret = dvb_usb_device_init(intf, &af9015_properties[i],
+                               THIS_MODULE, &d, adapter_nr);
+                       if (!ret)
+                               break;
+                       if (ret != -ENODEV)
+                               return ret;
+               }
+               if (ret)
+                       return ret;
+
+               if (d)
+                       ret = af9015_init(d);
+       }
+
+       return ret;
+}
+
+void af9015_i2c_exit(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d->priv;
+       deb_info("%s: \n", __func__);
+
+       /* remove 2nd I2C adapter */
+       if (d->state & DVB_USB_STATE_I2C)
+               i2c_del_adapter(&state->i2c_adap);
+}
+
+static void af9015_usb_device_exit(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       deb_info("%s: \n", __func__);
+
+       /* remove 2nd I2C adapter */
+       if (d != NULL && d->desc != NULL)
+               af9015_i2c_exit(d);
+
+       dvb_usb_device_exit(intf);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver af9015_usb_driver = {
+       .name = "dvb_usb_af9015",
+       .probe = af9015_usb_probe,
+       .disconnect = af9015_usb_device_exit,
+       .id_table = af9015_usb_table,
+};
+
+/* module stuff */
+static int __init af9015_usb_module_init(void)
+{
+       int ret;
+       ret = usb_register(&af9015_usb_driver);
+       if (ret)
+               err("module init failed:%d", ret);
+
+       return ret;
+}
+
+static void __exit af9015_usb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&af9015_usb_driver);
+}
+
+module_init(af9015_usb_module_init);
+module_exit(af9015_usb_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver for Afatech AF9015 DVB-T");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
new file mode 100644 (file)
index 0000000..882e8a4
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided 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 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 _DVB_USB_AF9015_H_
+#define _DVB_USB_AF9015_H_
+
+#define DVB_USB_LOG_PREFIX "af9015"
+#include "dvb-usb.h"
+
+extern int dvb_usb_af9015_debug;
+#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args)
+#define deb_rc(args...)   dprintk(dvb_usb_af9015_debug, 0x02, args)
+#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args)
+#define deb_reg(args...)  dprintk(dvb_usb_af9015_debug, 0x08, args)
+#define deb_i2c(args...)  dprintk(dvb_usb_af9015_debug, 0x10, args)
+#define deb_fw(args...)   dprintk(dvb_usb_af9015_debug, 0x20, args)
+
+#define AF9015_I2C_EEPROM  0xa0
+#define AF9015_I2C_DEMOD   0x38
+#define AF9015_USB_TIMEOUT 2000
+
+/* EEPROM locations */
+#define AF9015_EEPROM_IR_MODE        0x18
+#define AF9015_EEPROM_IR_REMOTE_TYPE 0x34
+#define AF9015_EEPROM_TS_MODE        0x31
+#define AF9015_EEPROM_DEMOD2_I2C     0x32
+
+#define AF9015_EEPROM_SAW_BW1        0x35
+#define AF9015_EEPROM_XTAL_TYPE1     0x36
+#define AF9015_EEPROM_SPEC_INV1      0x37
+#define AF9015_EEPROM_IF1L           0x38
+#define AF9015_EEPROM_IF1H           0x39
+#define AF9015_EEPROM_MT2060_IF1L    0x3a
+#define AF9015_EEPROM_MT2060_IF1H    0x3b
+#define AF9015_EEPROM_TUNER_ID1      0x3c
+
+#define AF9015_EEPROM_SAW_BW2        0x45
+#define AF9015_EEPROM_XTAL_TYPE2     0x46
+#define AF9015_EEPROM_SPEC_INV2      0x47
+#define AF9015_EEPROM_IF2L           0x48
+#define AF9015_EEPROM_IF2H           0x49
+#define AF9015_EEPROM_MT2060_IF2L    0x4a
+#define AF9015_EEPROM_MT2060_IF2H    0x4b
+#define AF9015_EEPROM_TUNER_ID2      0x4c
+
+#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1)
+
+#define AF9015_GPIO_ON (1 << 0)
+#define AF9015_GPIO_EN (1 << 1)
+#define AF9015_GPIO_O  (1 << 2)
+#define AF9015_GPIO_I  (1 << 3)
+
+#define AF9015_GPIO_TUNER_ON  (AF9015_GPIO_ON|AF9015_GPIO_EN)
+#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O)
+
+struct req_t {
+       u8  cmd;       /* [0] */
+       /*  seq */     /* [1] */
+       u8  i2c_addr;  /* [2] */
+       u16 addr;      /* [3|4] */
+       u8  mbox;      /* [5] */
+       u8  addr_len;  /* [6] */
+       u8  data_len;  /* [7] */
+       u8  *data;
+};
+
+enum af9015_cmd {
+       GET_CONFIG           = 0x10,
+       DOWNLOAD_FIRMWARE    = 0x11,
+       BOOT                 = 0x13,
+       READ_MEMORY          = 0x20,
+       WRITE_MEMORY         = 0x21,
+       READ_WRITE_I2C       = 0x22,
+       COPY_FIRMWARE        = 0x23,
+       RECONNECT_USB        = 0x5a,
+       WRITE_VIRTUAL_MEMORY = 0x26,
+       GET_IR_CODE          = 0x27,
+       READ_I2C,
+       WRITE_I2C,
+};
+
+enum af9015_ir_mode {
+       AF9015_IR_MODE_DISABLED = 0,
+       AF9015_IR_MODE_HID,
+       AF9015_IR_MODE_RLC,
+       AF9015_IR_MODE_RC6,
+};
+
+struct af9015_state {
+       struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
+};
+
+struct af9015_config {
+       u8  dual_mode:1;
+       u16 mt2060_if1[2];
+       u16 firmware_size;
+       u16 firmware_checksum;
+       u8  *ir_table;
+       u16 ir_table_size;
+};
+
+enum af9015_remote {
+       AF9015_REMOTE_NONE                    = 0,
+       AF9015_REMOTE_A_LINK_DTU_M,
+       AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
+       AF9015_REMOTE_MYGICTV_U718,
+};
+
+/* Leadtek WinFast DTV Dongle Gold */
+static struct dvb_usb_rc_key af9015_rc_keys_leadtek[] = {
+       { 0x00, 0x1e, KEY_1 },
+       { 0x00, 0x1f, KEY_2 },
+       { 0x00, 0x20, KEY_3 },
+       { 0x00, 0x21, KEY_4 },
+       { 0x00, 0x22, KEY_5 },
+       { 0x00, 0x23, KEY_6 },
+       { 0x00, 0x24, KEY_7 },
+       { 0x00, 0x25, KEY_8 },
+       { 0x00, 0x26, KEY_9 },
+       { 0x00, 0x27, KEY_0 },
+       { 0x00, 0x28, KEY_ENTER },
+       { 0x00, 0x4f, KEY_VOLUMEUP },
+       { 0x00, 0x50, KEY_VOLUMEDOWN },
+       { 0x00, 0x51, KEY_CHANNELDOWN },
+       { 0x00, 0x52, KEY_CHANNELUP },
+};
+
+static u8 af9015_ir_table_leadtek[] = {
+       0x03, 0xfc, 0x00, 0xff, 0x1a, 0x01, 0x00,
+       0x03, 0xfc, 0x56, 0xa9, 0x00, 0x00, 0x00,
+       0x03, 0xfc, 0x4b, 0xb4, 0x00, 0x00, 0x00,
+       0x03, 0xfc, 0x4c, 0xb3, 0xb2, 0x04, 0x00,
+       0x03, 0xfc, 0x4d, 0xb2, 0x00, 0x00, 0x00,
+       0x03, 0xfc, 0x4e, 0xb1, 0x00, 0x00, 0x00,
+       0x03, 0xfc, 0x1f, 0xe0, 0x3d, 0x00, 0x00,
+       0x03, 0xfc, 0x40, 0xbf, 0x13, 0x01, 0x00,
+       0x03, 0xfc, 0x14, 0xeb, 0x10, 0x00, 0x00,
+       0x03, 0xfc, 0x49, 0xb6, 0x05, 0x01, 0x00,
+       0x03, 0xfc, 0x50, 0xaf, 0x29, 0x00, 0x00,
+       0x03, 0xfc, 0x0c, 0xf3, 0x52, 0x00, 0x00,
+       0x03, 0xfc, 0x03, 0xfc, 0x09, 0x00, 0x00,
+       0x03, 0xfc, 0x08, 0xf7, 0x50, 0x00, 0x00,
+       0x03, 0xfc, 0x13, 0xec, 0x28, 0x00, 0x00,
+       0x03, 0xfc, 0x04, 0xfb, 0x4f, 0x00, 0x00,
+       0x03, 0xfc, 0x4f, 0xb0, 0x0f, 0x01, 0x00,
+       0x03, 0xfc, 0x10, 0xef, 0x51, 0x00, 0x00,
+       0x03, 0xfc, 0x51, 0xae, 0x3f, 0x00, 0x00,
+       0x03, 0xfc, 0x42, 0xbd, 0x13, 0x00, 0x00,
+       0x03, 0xfc, 0x43, 0xbc, 0x00, 0x00, 0x00,
+       0x03, 0xfc, 0x44, 0xbb, 0x11, 0x00, 0x00,
+       0x03, 0xfc, 0x52, 0xad, 0x19, 0x00, 0x00,
+       0x03, 0xfc, 0x54, 0xab, 0x05, 0x00, 0x00,
+       0x03, 0xfc, 0x46, 0xb9, 0x29, 0x00, 0x00,
+       0x03, 0xfc, 0x55, 0xaa, 0x2b, 0x00, 0x00,
+       0x03, 0xfc, 0x53, 0xac, 0x41, 0x00, 0x00,
+       0x03, 0xfc, 0x05, 0xfa, 0x1e, 0x00, 0x00,
+       0x03, 0xfc, 0x06, 0xf9, 0x1f, 0x00, 0x00,
+       0x03, 0xfc, 0x07, 0xf8, 0x20, 0x00, 0x00,
+       0x03, 0xfc, 0x1e, 0xe1, 0x19, 0x00, 0x00,
+       0x03, 0xfc, 0x09, 0xf6, 0x21, 0x00, 0x00,
+       0x03, 0xfc, 0x0a, 0xf5, 0x22, 0x00, 0x00,
+       0x03, 0xfc, 0x0b, 0xf4, 0x23, 0x00, 0x00,
+       0x03, 0xfc, 0x1b, 0xe4, 0x16, 0x00, 0x00,
+       0x03, 0xfc, 0x0d, 0xf2, 0x24, 0x00, 0x00,
+       0x03, 0xfc, 0x0e, 0xf1, 0x25, 0x00, 0x00,
+       0x03, 0xfc, 0x0f, 0xf0, 0x26, 0x00, 0x00,
+       0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00,
+       0x03, 0xfc, 0x41, 0xbe, 0x37, 0x00, 0x00,
+       0x03, 0xfc, 0x12, 0xed, 0x27, 0x00, 0x00,
+       0x03, 0xfc, 0x11, 0xee, 0x2a, 0x00, 0x00,
+       0x03, 0xfc, 0x48, 0xb7, 0x2c, 0x00, 0x00,
+       0x03, 0xfc, 0x4a, 0xb5, 0x3c, 0x00, 0x00,
+       0x03, 0xfc, 0x47, 0xb8, 0x15, 0x01, 0x00,
+       0x03, 0xfc, 0x45, 0xba, 0x0b, 0x01, 0x00,
+       0x03, 0xfc, 0x5e, 0xa1, 0x43, 0x00, 0x00,
+       0x03, 0xfc, 0x5a, 0xa5, 0x42, 0x00, 0x00,
+       0x03, 0xfc, 0x5b, 0xa4, 0x4b, 0x00, 0x00,
+       0x03, 0xfc, 0x5f, 0xa0, 0x4e, 0x00, 0x00,
+};
+
+/* TwinHan AzureWave AD-TU700(704J) */
+static struct dvb_usb_rc_key af9015_rc_keys_twinhan[] = {
+       { 0x05, 0x3f, KEY_POWER },
+       { 0x00, 0x19, KEY_FAVORITES },    /* Favorite List */
+       { 0x00, 0x04, KEY_TEXT },         /* Teletext */
+       { 0x00, 0x0e, KEY_POWER },
+       { 0x00, 0x0e, KEY_INFO },         /* Preview */
+       { 0x00, 0x08, KEY_EPG },          /* Info/EPG */
+       { 0x00, 0x0f, KEY_LIST },         /* Record List */
+       { 0x00, 0x1e, KEY_1 },
+       { 0x00, 0x1f, KEY_2 },
+       { 0x00, 0x20, KEY_3 },
+       { 0x00, 0x21, KEY_4 },
+       { 0x00, 0x22, KEY_5 },
+       { 0x00, 0x23, KEY_6 },
+       { 0x00, 0x24, KEY_7 },
+       { 0x00, 0x25, KEY_8 },
+       { 0x00, 0x26, KEY_9 },
+       { 0x00, 0x27, KEY_0 },
+       { 0x00, 0x29, KEY_CANCEL },       /* Cancel */
+       { 0x00, 0x4c, KEY_CLEAR },        /* Clear */
+       { 0x00, 0x2a, KEY_BACK },         /* Back */
+       { 0x00, 0x2b, KEY_TAB },          /* Tab */
+       { 0x00, 0x52, KEY_UP },           /* up arrow */
+       { 0x00, 0x51, KEY_DOWN },         /* down arrow */
+       { 0x00, 0x4f, KEY_RIGHT },        /* right arrow */
+       { 0x00, 0x50, KEY_LEFT },         /* left arrow */
+       { 0x00, 0x28, KEY_ENTER },        /* Enter / ok */
+       { 0x02, 0x52, KEY_VOLUMEUP },
+       { 0x02, 0x51, KEY_VOLUMEDOWN },
+       { 0x00, 0x4e, KEY_CHANNELDOWN },
+       { 0x00, 0x4b, KEY_CHANNELUP },
+       { 0x00, 0x4a, KEY_RECORD },
+       { 0x01, 0x11, KEY_PLAY },
+       { 0x00, 0x17, KEY_PAUSE },
+       { 0x00, 0x0c, KEY_REWIND },       /* FR << */
+       { 0x00, 0x11, KEY_FASTFORWARD },  /* FF >> */
+       { 0x01, 0x15, KEY_PREVIOUS },     /* Replay */
+       { 0x01, 0x0e, KEY_NEXT },         /* Skip */
+       { 0x00, 0x13, KEY_CAMERA },       /* Capture */
+       { 0x01, 0x0f, KEY_LANGUAGE },     /* SAP */
+       { 0x01, 0x13, KEY_TV2 },          /* PIP */
+       { 0x00, 0x1d, KEY_ZOOM },         /* Full Screen */
+       { 0x01, 0x17, KEY_SUBTITLE },     /* Subtitle / CC */
+       { 0x00, 0x10, KEY_MUTE },
+       { 0x01, 0x19, KEY_AUDIO },        /* L/R */ /* TODO better event */
+       { 0x01, 0x16, KEY_SLEEP },        /* Hibernate */
+       { 0x01, 0x16, KEY_SWITCHVIDEOMODE },
+                                         /* A/V */ /* TODO does not work */
+       { 0x00, 0x06, KEY_AGAIN },        /* Recall */
+       { 0x01, 0x16, KEY_KPPLUS },       /* Zoom+ */ /* TODO does not work */
+       { 0x01, 0x16, KEY_KPMINUS },      /* Zoom- */ /* TODO does not work */
+       { 0x02, 0x15, KEY_RED },
+       { 0x02, 0x0a, KEY_GREEN },
+       { 0x02, 0x1c, KEY_YELLOW },
+       { 0x02, 0x05, KEY_BLUE },
+};
+
+static u8 af9015_ir_table_twinhan[] = {
+       0x00, 0xff, 0x16, 0xe9, 0x3f, 0x05, 0x00,
+       0x00, 0xff, 0x07, 0xf8, 0x16, 0x01, 0x00,
+       0x00, 0xff, 0x14, 0xeb, 0x11, 0x01, 0x00,
+       0x00, 0xff, 0x1a, 0xe5, 0x4d, 0x00, 0x00,
+       0x00, 0xff, 0x4c, 0xb3, 0x17, 0x00, 0x00,
+       0x00, 0xff, 0x12, 0xed, 0x11, 0x00, 0x00,
+       0x00, 0xff, 0x40, 0xbf, 0x0c, 0x00, 0x00,
+       0x00, 0xff, 0x11, 0xee, 0x4a, 0x00, 0x00,
+       0x00, 0xff, 0x54, 0xab, 0x13, 0x00, 0x00,
+       0x00, 0xff, 0x41, 0xbe, 0x15, 0x01, 0x00,
+       0x00, 0xff, 0x42, 0xbd, 0x0e, 0x01, 0x00,
+       0x00, 0xff, 0x43, 0xbc, 0x17, 0x01, 0x00,
+       0x00, 0xff, 0x50, 0xaf, 0x0f, 0x01, 0x00,
+       0x00, 0xff, 0x4d, 0xb2, 0x1d, 0x00, 0x00,
+       0x00, 0xff, 0x47, 0xb8, 0x13, 0x01, 0x00,
+       0x00, 0xff, 0x05, 0xfa, 0x4b, 0x00, 0x00,
+       0x00, 0xff, 0x02, 0xfd, 0x4e, 0x00, 0x00,
+       0x00, 0xff, 0x0e, 0xf1, 0x06, 0x00, 0x00,
+       0x00, 0xff, 0x1e, 0xe1, 0x52, 0x02, 0x00,
+       0x00, 0xff, 0x0a, 0xf5, 0x51, 0x02, 0x00,
+       0x00, 0xff, 0x10, 0xef, 0x10, 0x00, 0x00,
+       0x00, 0xff, 0x49, 0xb6, 0x19, 0x01, 0x00,
+       0x00, 0xff, 0x15, 0xea, 0x27, 0x00, 0x00,
+       0x00, 0xff, 0x03, 0xfc, 0x1e, 0x00, 0x00,
+       0x00, 0xff, 0x01, 0xfe, 0x1f, 0x00, 0x00,
+       0x00, 0xff, 0x06, 0xf9, 0x20, 0x00, 0x00,
+       0x00, 0xff, 0x09, 0xf6, 0x21, 0x00, 0x00,
+       0x00, 0xff, 0x1d, 0xe2, 0x22, 0x00, 0x00,
+       0x00, 0xff, 0x1f, 0xe0, 0x23, 0x00, 0x00,
+       0x00, 0xff, 0x0d, 0xf2, 0x24, 0x00, 0x00,
+       0x00, 0xff, 0x19, 0xe6, 0x25, 0x00, 0x00,
+       0x00, 0xff, 0x1b, 0xe4, 0x26, 0x00, 0x00,
+       0x00, 0xff, 0x00, 0xff, 0x2b, 0x00, 0x00,
+       0x00, 0xff, 0x4a, 0xb5, 0x4c, 0x00, 0x00,
+       0x00, 0xff, 0x4b, 0xb4, 0x52, 0x00, 0x00,
+       0x00, 0xff, 0x51, 0xae, 0x51, 0x00, 0x00,
+       0x00, 0xff, 0x52, 0xad, 0x4f, 0x00, 0x00,
+       0x00, 0xff, 0x4e, 0xb1, 0x50, 0x00, 0x00,
+       0x00, 0xff, 0x0c, 0xf3, 0x29, 0x00, 0x00,
+       0x00, 0xff, 0x4f, 0xb0, 0x28, 0x00, 0x00,
+       0x00, 0xff, 0x13, 0xec, 0x2a, 0x00, 0x00,
+       0x00, 0xff, 0x17, 0xe8, 0x19, 0x00, 0x00,
+       0x00, 0xff, 0x04, 0xfb, 0x0f, 0x00, 0x00,
+       0x00, 0xff, 0x48, 0xb7, 0x0e, 0x00, 0x00,
+       0x00, 0xff, 0x0f, 0xf0, 0x04, 0x00, 0x00,
+       0x00, 0xff, 0x1c, 0xe3, 0x08, 0x00, 0x00,
+       0x00, 0xff, 0x18, 0xe7, 0x15, 0x02, 0x00,
+       0x00, 0xff, 0x53, 0xac, 0x0a, 0x02, 0x00,
+       0x00, 0xff, 0x5e, 0xa1, 0x1c, 0x02, 0x00,
+       0x00, 0xff, 0x5f, 0xa0, 0x05, 0x02, 0x00,
+};
+
+/* A-Link DTU(m) */
+static struct dvb_usb_rc_key af9015_rc_keys_a_link[] = {
+       { 0x00, 0x1e, KEY_1 },
+       { 0x00, 0x1f, KEY_2 },
+       { 0x00, 0x20, KEY_3 },
+       { 0x00, 0x21, KEY_4 },
+       { 0x00, 0x22, KEY_5 },
+       { 0x00, 0x23, KEY_6 },
+       { 0x00, 0x24, KEY_7 },
+       { 0x00, 0x25, KEY_8 },
+       { 0x00, 0x26, KEY_9 },
+       { 0x00, 0x27, KEY_0 },
+       { 0x00, 0x2e, KEY_CHANNELUP },
+       { 0x00, 0x2d, KEY_CHANNELDOWN },
+       { 0x04, 0x28, KEY_ZOOM },
+       { 0x00, 0x41, KEY_MUTE },
+       { 0x00, 0x42, KEY_VOLUMEDOWN },
+       { 0x00, 0x43, KEY_VOLUMEUP },
+       { 0x00, 0x44, KEY_GOTO },         /* jump */
+       { 0x05, 0x45, KEY_POWER },
+};
+
+static u8 af9015_ir_table_a_link[] = {
+       0x08, 0xf7, 0x12, 0xed, 0x45, 0x05, 0x00, /* power */
+       0x08, 0xf7, 0x1a, 0xe5, 0x41, 0x00, 0x00, /* mute */
+       0x08, 0xf7, 0x01, 0xfe, 0x1e, 0x00, 0x00, /* 1 */
+       0x08, 0xf7, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */
+       0x08, 0xf7, 0x03, 0xfc, 0x24, 0x00, 0x00, /* 7 */
+       0x08, 0xf7, 0x05, 0xfa, 0x28, 0x04, 0x00, /* zoom */
+       0x08, 0xf7, 0x00, 0xff, 0x43, 0x00, 0x00, /* volume up */
+       0x08, 0xf7, 0x16, 0xe9, 0x42, 0x00, 0x00, /* volume down */
+       0x08, 0xf7, 0x0f, 0xf0, 0x1f, 0x00, 0x00, /* 2 */
+       0x08, 0xf7, 0x0d, 0xf2, 0x22, 0x00, 0x00, /* 5 */
+       0x08, 0xf7, 0x1b, 0xe4, 0x25, 0x00, 0x00, /* 8 */
+       0x08, 0xf7, 0x06, 0xf9, 0x27, 0x00, 0x00, /* 0 */
+       0x08, 0xf7, 0x14, 0xeb, 0x2e, 0x00, 0x00, /* channel up */
+       0x08, 0xf7, 0x1d, 0xe2, 0x2d, 0x00, 0x00, /* channel down */
+       0x08, 0xf7, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */
+       0x08, 0xf7, 0x18, 0xe7, 0x23, 0x00, 0x00, /* 6 */
+       0x08, 0xf7, 0x04, 0xfb, 0x26, 0x00, 0x00, /* 9 */
+       0x08, 0xf7, 0x07, 0xf8, 0x44, 0x00, 0x00, /* jump */
+};
+
+/* MSI DIGIVOX mini II V3.0 */
+static struct dvb_usb_rc_key af9015_rc_keys_msi[] = {
+       { 0x00, 0x1e, KEY_1 },
+       { 0x00, 0x1f, KEY_2 },
+       { 0x00, 0x20, KEY_3 },
+       { 0x00, 0x21, KEY_4 },
+       { 0x00, 0x22, KEY_5 },
+       { 0x00, 0x23, KEY_6 },
+       { 0x00, 0x24, KEY_7 },
+       { 0x00, 0x25, KEY_8 },
+       { 0x00, 0x26, KEY_9 },
+       { 0x00, 0x27, KEY_0 },
+       { 0x03, 0x0f, KEY_CHANNELUP },
+       { 0x03, 0x0e, KEY_CHANNELDOWN },
+       { 0x00, 0x42, KEY_VOLUMEDOWN },
+       { 0x00, 0x43, KEY_VOLUMEUP },
+       { 0x05, 0x45, KEY_POWER },
+       { 0x00, 0x52, KEY_UP },           /* up */
+       { 0x00, 0x51, KEY_DOWN },         /* down */
+       { 0x00, 0x28, KEY_ENTER },
+};
+
+static u8 af9015_ir_table_msi[] = {
+       0x03, 0xfc, 0x17, 0xe8, 0x45, 0x05, 0x00, /* power */
+       0x03, 0xfc, 0x0d, 0xf2, 0x51, 0x00, 0x00, /* down */
+       0x03, 0xfc, 0x03, 0xfc, 0x52, 0x00, 0x00, /* up */
+       0x03, 0xfc, 0x1a, 0xe5, 0x1e, 0x00, 0x00, /* 1 */
+       0x03, 0xfc, 0x02, 0xfd, 0x1f, 0x00, 0x00, /* 2 */
+       0x03, 0xfc, 0x04, 0xfb, 0x20, 0x00, 0x00, /* 3 */
+       0x03, 0xfc, 0x1c, 0xe3, 0x21, 0x00, 0x00, /* 4 */
+       0x03, 0xfc, 0x08, 0xf7, 0x22, 0x00, 0x00, /* 5 */
+       0x03, 0xfc, 0x1d, 0xe2, 0x23, 0x00, 0x00, /* 6 */
+       0x03, 0xfc, 0x11, 0xee, 0x24, 0x00, 0x00, /* 7 */
+       0x03, 0xfc, 0x0b, 0xf4, 0x25, 0x00, 0x00, /* 8 */
+       0x03, 0xfc, 0x10, 0xef, 0x26, 0x00, 0x00, /* 9 */
+       0x03, 0xfc, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */
+       0x03, 0xfc, 0x14, 0xeb, 0x43, 0x00, 0x00, /* volume up */
+       0x03, 0xfc, 0x1f, 0xe0, 0x42, 0x00, 0x00, /* volume down */
+       0x03, 0xfc, 0x15, 0xea, 0x0f, 0x03, 0x00, /* channel up */
+       0x03, 0xfc, 0x05, 0xfa, 0x0e, 0x03, 0x00, /* channel down */
+       0x03, 0xfc, 0x16, 0xe9, 0x28, 0x00, 0x00, /* enter */
+};
+
+/* MYGICTV U718 */
+static struct dvb_usb_rc_key af9015_rc_keys_mygictv[] = {
+       { 0x00, 0x3d, KEY_SWITCHVIDEOMODE },
+                                         /* TV / AV */
+       { 0x05, 0x45, KEY_POWER },
+       { 0x00, 0x1e, KEY_1 },
+       { 0x00, 0x1f, KEY_2 },
+       { 0x00, 0x20, KEY_3 },
+       { 0x00, 0x21, KEY_4 },
+       { 0x00, 0x22, KEY_5 },
+       { 0x00, 0x23, KEY_6 },
+       { 0x00, 0x24, KEY_7 },
+       { 0x00, 0x25, KEY_8 },
+       { 0x00, 0x26, KEY_9 },
+       { 0x00, 0x27, KEY_0 },
+       { 0x00, 0x41, KEY_MUTE },
+       { 0x00, 0x2a, KEY_ESC },          /* Esc */
+       { 0x00, 0x2e, KEY_CHANNELUP },
+       { 0x00, 0x2d, KEY_CHANNELDOWN },
+       { 0x00, 0x42, KEY_VOLUMEDOWN },
+       { 0x00, 0x43, KEY_VOLUMEUP },
+       { 0x00, 0x52, KEY_UP },           /* up arrow */
+       { 0x00, 0x51, KEY_DOWN },         /* down arrow */
+       { 0x00, 0x4f, KEY_RIGHT },        /* right arrow */
+       { 0x00, 0x50, KEY_LEFT },         /* left arrow */
+       { 0x00, 0x28, KEY_ENTER },        /* ok */
+       { 0x01, 0x15, KEY_RECORD },
+       { 0x03, 0x13, KEY_PLAY },
+       { 0x01, 0x13, KEY_PAUSE },
+       { 0x01, 0x16, KEY_STOP },
+       { 0x03, 0x07, KEY_REWIND },       /* FR << */
+       { 0x03, 0x09, KEY_FASTFORWARD },  /* FF >> */
+       { 0x00, 0x3b, KEY_TIME },         /* TimeShift */
+       { 0x00, 0x3e, KEY_CAMERA },       /* Snapshot */
+       { 0x03, 0x16, KEY_CYCLEWINDOWS }, /* yellow, min / max */
+       { 0x00, 0x00, KEY_ZOOM },         /* 'select' (?) */
+       { 0x03, 0x16, KEY_SHUFFLE },      /* Shuffle */
+       { 0x03, 0x45, KEY_POWER },
+};
+
+static u8 af9015_ir_table_mygictv[] = {
+       0x02, 0xbd, 0x0c, 0xf3, 0x3d, 0x00, 0x00, /* TV / AV */
+       0x02, 0xbd, 0x14, 0xeb, 0x45, 0x05, 0x00, /* power */
+       0x02, 0xbd, 0x00, 0xff, 0x1e, 0x00, 0x00, /* 1 */
+       0x02, 0xbd, 0x01, 0xfe, 0x1f, 0x00, 0x00, /* 2 */
+       0x02, 0xbd, 0x02, 0xfd, 0x20, 0x00, 0x00, /* 3 */
+       0x02, 0xbd, 0x03, 0xfc, 0x21, 0x00, 0x00, /* 4 */
+       0x02, 0xbd, 0x04, 0xfb, 0x22, 0x00, 0x00, /* 5 */
+       0x02, 0xbd, 0x05, 0xfa, 0x23, 0x00, 0x00, /* 6 */
+       0x02, 0xbd, 0x06, 0xf9, 0x24, 0x00, 0x00, /* 7 */
+       0x02, 0xbd, 0x07, 0xf8, 0x25, 0x00, 0x00, /* 8 */
+       0x02, 0xbd, 0x08, 0xf7, 0x26, 0x00, 0x00, /* 9 */
+       0x02, 0xbd, 0x09, 0xf6, 0x27, 0x00, 0x00, /* 0 */
+       0x02, 0xbd, 0x0a, 0xf5, 0x41, 0x00, 0x00, /* mute */
+       0x02, 0xbd, 0x1c, 0xe3, 0x2a, 0x00, 0x00, /* esc */
+       0x02, 0xbd, 0x1f, 0xe0, 0x43, 0x00, 0x00, /* volume up */
+       0x02, 0xbd, 0x12, 0xed, 0x52, 0x00, 0x00, /* up arrow */
+       0x02, 0xbd, 0x11, 0xee, 0x50, 0x00, 0x00, /* left arrow */
+       0x02, 0xbd, 0x15, 0xea, 0x28, 0x00, 0x00, /* ok */
+       0x02, 0xbd, 0x10, 0xef, 0x4f, 0x00, 0x00, /* right arrow */
+       0x02, 0xbd, 0x13, 0xec, 0x51, 0x00, 0x00, /* down arrow */
+       0x02, 0xbd, 0x0e, 0xf1, 0x42, 0x00, 0x00, /* volume down */
+       0x02, 0xbd, 0x19, 0xe6, 0x15, 0x01, 0x00, /* record */
+       0x02, 0xbd, 0x1e, 0xe1, 0x13, 0x03, 0x00, /* play */
+       0x02, 0xbd, 0x16, 0xe9, 0x16, 0x01, 0x00, /* stop */
+       0x02, 0xbd, 0x0b, 0xf4, 0x28, 0x04, 0x00, /* yellow, min / max */
+       0x02, 0xbd, 0x0f, 0xf0, 0x3b, 0x00, 0x00, /* time shift */
+       0x02, 0xbd, 0x18, 0xe7, 0x2e, 0x00, 0x00, /* channel up */
+       0x02, 0xbd, 0x1a, 0xe5, 0x2d, 0x00, 0x00, /* channel down */
+       0x02, 0xbd, 0x17, 0xe8, 0x3e, 0x00, 0x00, /* snapshot */
+       0x02, 0xbd, 0x40, 0xbf, 0x13, 0x01, 0x00, /* pause */
+       0x02, 0xbd, 0x41, 0xbe, 0x09, 0x03, 0x00, /* FF >> */
+       0x02, 0xbd, 0x42, 0xbd, 0x07, 0x03, 0x00, /* FR << */
+       0x02, 0xbd, 0x43, 0xbc, 0x00, 0x00, 0x00, /* 'select' (?) */
+       0x02, 0xbd, 0x44, 0xbb, 0x16, 0x03, 0x00, /* shuffle */
+       0x02, 0xbd, 0x45, 0xba, 0x45, 0x03, 0x00, /* power */
+};
+
+/* KWorld PlusTV Dual DVB-T Stick (DVB-T 399U) */
+static u8 af9015_ir_table_kworld[] = {
+       0x86, 0x6b, 0x0c, 0xf3, 0x2e, 0x07, 0x00,
+       0x86, 0x6b, 0x16, 0xe9, 0x2d, 0x07, 0x00,
+       0x86, 0x6b, 0x1d, 0xe2, 0x37, 0x07, 0x00,
+       0x86, 0x6b, 0x00, 0xff, 0x1e, 0x07, 0x00,
+       0x86, 0x6b, 0x01, 0xfe, 0x1f, 0x07, 0x00,
+       0x86, 0x6b, 0x02, 0xfd, 0x20, 0x07, 0x00,
+       0x86, 0x6b, 0x03, 0xfc, 0x21, 0x07, 0x00,
+       0x86, 0x6b, 0x04, 0xfb, 0x22, 0x07, 0x00,
+       0x86, 0x6b, 0x05, 0xfa, 0x23, 0x07, 0x00,
+       0x86, 0x6b, 0x06, 0xf9, 0x24, 0x07, 0x00,
+       0x86, 0x6b, 0x07, 0xf8, 0x25, 0x07, 0x00,
+       0x86, 0x6b, 0x08, 0xf7, 0x26, 0x07, 0x00,
+       0x86, 0x6b, 0x09, 0xf6, 0x4d, 0x07, 0x00,
+       0x86, 0x6b, 0x0a, 0xf5, 0x4e, 0x07, 0x00,
+       0x86, 0x6b, 0x14, 0xeb, 0x4f, 0x07, 0x00,
+       0x86, 0x6b, 0x1e, 0xe1, 0x50, 0x07, 0x00,
+       0x86, 0x6b, 0x17, 0xe8, 0x52, 0x07, 0x00,
+       0x86, 0x6b, 0x1f, 0xe0, 0x51, 0x07, 0x00,
+       0x86, 0x6b, 0x0e, 0xf1, 0x0b, 0x07, 0x00,
+       0x86, 0x6b, 0x20, 0xdf, 0x0c, 0x07, 0x00,
+       0x86, 0x6b, 0x42, 0xbd, 0x0d, 0x07, 0x00,
+       0x86, 0x6b, 0x0b, 0xf4, 0x0e, 0x07, 0x00,
+       0x86, 0x6b, 0x43, 0xbc, 0x0f, 0x07, 0x00,
+       0x86, 0x6b, 0x10, 0xef, 0x10, 0x07, 0x00,
+       0x86, 0x6b, 0x21, 0xde, 0x11, 0x07, 0x00,
+       0x86, 0x6b, 0x13, 0xec, 0x12, 0x07, 0x00,
+       0x86, 0x6b, 0x11, 0xee, 0x13, 0x07, 0x00,
+       0x86, 0x6b, 0x12, 0xed, 0x14, 0x07, 0x00,
+       0x86, 0x6b, 0x19, 0xe6, 0x15, 0x07, 0x00,
+       0x86, 0x6b, 0x1a, 0xe5, 0x16, 0x07, 0x00,
+       0x86, 0x6b, 0x1b, 0xe4, 0x17, 0x07, 0x00,
+       0x86, 0x6b, 0x4b, 0xb4, 0x18, 0x07, 0x00,
+       0x86, 0x6b, 0x40, 0xbf, 0x19, 0x07, 0x00,
+       0x86, 0x6b, 0x44, 0xbb, 0x1a, 0x07, 0x00,
+       0x86, 0x6b, 0x41, 0xbe, 0x1b, 0x07, 0x00,
+       0x86, 0x6b, 0x22, 0xdd, 0x1c, 0x07, 0x00,
+       0x86, 0x6b, 0x15, 0xea, 0x1d, 0x07, 0x00,
+       0x86, 0x6b, 0x0f, 0xf0, 0x3f, 0x07, 0x00,
+       0x86, 0x6b, 0x1c, 0xe3, 0x40, 0x07, 0x00,
+       0x86, 0x6b, 0x4a, 0xb5, 0x41, 0x07, 0x00,
+       0x86, 0x6b, 0x48, 0xb7, 0x42, 0x07, 0x00,
+       0x86, 0x6b, 0x49, 0xb6, 0x43, 0x07, 0x00,
+       0x86, 0x6b, 0x18, 0xe7, 0x44, 0x07, 0x00,
+       0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00,
+};
+
+#endif
index 2f408d2e1ef349be29c3ae6ba97ee09df9b49bc5..c786359fba03fea99bbceb52a1d15bee5e8684ad 100644 (file)
@@ -41,6 +41,9 @@
 static int dvb_usb_anysee_debug;
 module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+int dvb_usb_anysee_delsys;
+module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
+MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static struct mutex anysee_usb_mutex;
@@ -178,14 +181,14 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
                        inc = 1;
                }
                if (ret)
-                       return ret;
+                       break;
 
                i += inc;
        }
 
        mutex_unlock(&d->i2c_mutex);
 
-       return i;
+       return ret ? ret : i;
 }
 
 static u32 anysee_i2c_func(struct i2c_adapter *adapter)
@@ -272,9 +275,11 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
              model      demod     hw  firmware
           1. E30        MT352     02  0.2.1
           2. E30        ZL10353   02  0.2.1
-          3. E30 Plus   ZL10353   06  0.1.0
-          4. E30C Plus  TDA10023  0a  0.1.0    rev 0.2
-          4. E30C Plus  TDA10023  0f  0.1.2    rev 0.4
+          3. E30 Combo  ZL10353   0f  0.1.2    DVB-T/C combo
+          4. E30 Plus   ZL10353   06  0.1.0
+          5. E30C Plus  TDA10023  0a  0.1.0    rev 0.2
+             E30C Plus  TDA10023  0f  0.1.2    rev 0.4
+             E30 Combo  TDA10023  0f  0.1.2    DVB-T/C combo
        */
 
        /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
@@ -293,6 +298,21 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                return 0;
        }
 
+       /* for E30 Combo Plus DVB-T demodulator */
+       if (dvb_usb_anysee_delsys) {
+               ret = anysee_write_reg(adap->dev, 0xb0, 0x01);
+               if (ret)
+                       return ret;
+
+               /* Zarlink ZL10353 DVB-T demod */
+               adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                                     &adap->dev->i2c_adap);
+               if (adap->fe != NULL) {
+                       state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
+                       return 0;
+               }
+       }
+
        /* connect demod on IO port D for TDA10023 & ZL10353 */
        ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
        if (ret)
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
new file mode 100644 (file)
index 0000000..3ac9f74
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ *                 Holger Waechtler <holger@qanu.de>
+ *
+ *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "cinergyT2.h"
+
+
+/* debug */
+int dvb_usb_cinergyt2_debug;
+int disable_remote;
+
+module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
+               "(or-able)).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct cinergyt2_state {
+       u8 rc_counter;
+};
+
+/* We are missing a release hook with usb_device data */
+struct dvb_usb_device *cinergyt2_usb_device;
+
+static struct dvb_usb_device_properties cinergyt2_properties;
+
+static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
+{
+       char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
+       char result[64];
+       return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
+                               sizeof(result), 0);
+}
+
+static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
+{
+       char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
+       char state[3];
+       return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
+}
+
+static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
+       char state[3];
+       int ret;
+
+       adap->fe = cinergyt2_fe_attach(adap->dev);
+
+       ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
+                               sizeof(state), 0);
+       if (ret < 0) {
+               deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
+                       "state info\n");
+       }
+
+       /* Copy this pointer as we are gonna need it in the release phase */
+       cinergyt2_usb_device = adap->dev;
+
+       return 0;
+}
+
+static struct dvb_usb_rc_key cinergyt2_rc_keys[] = {
+       { 0x04, 0x01,   KEY_POWER },
+       { 0x04, 0x02,   KEY_1 },
+       { 0x04, 0x03,   KEY_2 },
+       { 0x04, 0x04,   KEY_3 },
+       { 0x04, 0x05,   KEY_4 },
+       { 0x04, 0x06,   KEY_5 },
+       { 0x04, 0x07,   KEY_6 },
+       { 0x04, 0x08,   KEY_7 },
+       { 0x04, 0x09,   KEY_8 },
+       { 0x04, 0x0a,   KEY_9 },
+       { 0x04, 0x0c,   KEY_0 },
+       { 0x04, 0x0b,   KEY_VIDEO },
+       { 0x04, 0x0d,   KEY_REFRESH },
+       { 0x04, 0x0e,   KEY_SELECT },
+       { 0x04, 0x0f,   KEY_EPG },
+       { 0x04, 0x10,   KEY_UP },
+       { 0x04, 0x14,   KEY_DOWN },
+       { 0x04, 0x11,   KEY_LEFT },
+       { 0x04, 0x13,   KEY_RIGHT },
+       { 0x04, 0x12,   KEY_OK },
+       { 0x04, 0x15,   KEY_TEXT },
+       { 0x04, 0x16,   KEY_INFO },
+       { 0x04, 0x17,   KEY_RED },
+       { 0x04, 0x18,   KEY_GREEN },
+       { 0x04, 0x19,   KEY_YELLOW },
+       { 0x04, 0x1a,   KEY_BLUE },
+       { 0x04, 0x1c,   KEY_VOLUMEUP },
+       { 0x04, 0x1e,   KEY_VOLUMEDOWN },
+       { 0x04, 0x1d,   KEY_MUTE },
+       { 0x04, 0x1b,   KEY_CHANNELUP },
+       { 0x04, 0x1f,   KEY_CHANNELDOWN },
+       { 0x04, 0x40,   KEY_PAUSE },
+       { 0x04, 0x4c,   KEY_PLAY },
+       { 0x04, 0x58,   KEY_RECORD },
+       { 0x04, 0x54,   KEY_PREVIOUS },
+       { 0x04, 0x48,   KEY_STOP },
+       { 0x04, 0x5c,   KEY_NEXT }
+};
+
+/* Number of keypresses to ignore before detect repeating */
+#define RC_REPEAT_DELAY 3
+
+static int repeatable_keys[] = {
+       KEY_UP,
+       KEY_DOWN,
+       KEY_LEFT,
+       KEY_RIGHT,
+       KEY_VOLUMEUP,
+       KEY_VOLUMEDOWN,
+       KEY_CHANNELUP,
+       KEY_CHANNELDOWN
+};
+
+static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       struct cinergyt2_state *st = d->priv;
+       u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
+       int i;
+
+       *state = REMOTE_NO_KEY_PRESSED;
+
+       dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
+       if (key[4] == 0xff) {
+               /* key repeat */
+               st->rc_counter++;
+               if (st->rc_counter > RC_REPEAT_DELAY) {
+                       for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
+                               if (d->last_event == repeatable_keys[i]) {
+                                       *state = REMOTE_KEY_REPEAT;
+                                       *event = d->last_event;
+                                       deb_rc("repeat key, event %x\n",
+                                                  *event);
+                                       return 0;
+                               }
+                       }
+                       deb_rc("repeated key (non repeatable)\n");
+               }
+               return 0;
+       }
+
+       /* hack to pass checksum on the custom field */
+       key[2] = ~key[1];
+       dvb_usb_nec_rc_key_to_event(d, key, event, state);
+       if (key[0] != 0) {
+               if (*event != d->last_event)
+                       st->rc_counter = 0;
+
+               deb_rc("key: %x %x %x %x %x\n",
+                      key[0], key[1], key[2], key[3], key[4]);
+       }
+       return 0;
+}
+
+static int cinergyt2_usb_probe(struct usb_interface *intf,
+                               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf, &cinergyt2_properties,
+                                       THIS_MODULE, NULL, adapter_nr);
+}
+
+
+static struct usb_device_id cinergyt2_usb_table[] = {
+       { USB_DEVICE(USB_VID_TERRATEC, 0x0038) },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table);
+
+static struct dvb_usb_device_properties cinergyt2_properties = {
+       .size_of_priv = sizeof(struct cinergyt2_state),
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = cinergyt2_streaming_ctrl,
+                       .frontend_attach  = cinergyt2_frontend_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 512,
+                                       }
+                               }
+                       },
+               }
+       },
+
+       .power_ctrl       = cinergyt2_power_ctrl,
+
+       .rc_interval      = 50,
+       .rc_key_map       = cinergyt2_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(cinergyt2_rc_keys),
+       .rc_query         = cinergyt2_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 1,
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver",
+                 .cold_ids = {NULL},
+                 .warm_ids = { &cinergyt2_usb_table[0], NULL },
+               },
+               { NULL },
+       }
+};
+
+
+static struct usb_driver cinergyt2_driver = {
+       .name           = "cinergyT2",
+       .probe          = cinergyt2_usb_probe,
+       .disconnect     = dvb_usb_device_exit,
+       .id_table       = cinergyt2_usb_table
+};
+
+static int __init cinergyt2_usb_init(void)
+{
+       int err;
+
+       err = usb_register(&cinergyt2_driver);
+       if (err) {
+               err("usb_register() failed! (err %i)\n", err);
+               return err;
+       }
+       return 0;
+}
+
+static void __exit cinergyt2_usb_exit(void)
+{
+       usb_deregister(&cinergyt2_driver);
+}
+
+module_init(cinergyt2_usb_init);
+module_exit(cinergyt2_usb_exit);
+
+MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tomi Orava");
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
new file mode 100644 (file)
index 0000000..649f25c
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ *                  Holger Waechtler <holger@qanu.de>
+ *
+ *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "cinergyT2.h"
+
+
+/**
+ *  convert linux-dvb frontend parameter set into TPS.
+ *  See ETSI ETS-300744, section 4.6.2, table 9 for details.
+ *
+ *  This function is probably reusable and may better get placed in a support
+ *  library.
+ *
+ *  We replace errornous fields by default TPS fields (the ones with value 0).
+ */
+
+static uint16_t compute_tps(struct dvb_frontend_parameters *p)
+{
+       struct dvb_ofdm_parameters *op = &p->u.ofdm;
+       uint16_t tps = 0;
+
+       switch (op->code_rate_HP) {
+       case FEC_2_3:
+               tps |= (1 << 7);
+               break;
+       case FEC_3_4:
+               tps |= (2 << 7);
+               break;
+       case FEC_5_6:
+               tps |= (3 << 7);
+               break;
+       case FEC_7_8:
+               tps |= (4 << 7);
+               break;
+       case FEC_1_2:
+       case FEC_AUTO:
+       default:
+               /* tps |= (0 << 7) */;
+       }
+
+       switch (op->code_rate_LP) {
+       case FEC_2_3:
+               tps |= (1 << 4);
+               break;
+       case FEC_3_4:
+               tps |= (2 << 4);
+               break;
+       case FEC_5_6:
+               tps |= (3 << 4);
+               break;
+       case FEC_7_8:
+               tps |= (4 << 4);
+               break;
+       case FEC_1_2:
+       case FEC_AUTO:
+       default:
+               /* tps |= (0 << 4) */;
+       }
+
+       switch (op->constellation) {
+       case QAM_16:
+               tps |= (1 << 13);
+               break;
+       case QAM_64:
+               tps |= (2 << 13);
+               break;
+       case QPSK:
+       default:
+               /* tps |= (0 << 13) */;
+       }
+
+       switch (op->transmission_mode) {
+       case TRANSMISSION_MODE_8K:
+               tps |= (1 << 0);
+               break;
+       case TRANSMISSION_MODE_2K:
+       default:
+               /* tps |= (0 << 0) */;
+       }
+
+       switch (op->guard_interval) {
+       case GUARD_INTERVAL_1_16:
+               tps |= (1 << 2);
+               break;
+       case GUARD_INTERVAL_1_8:
+               tps |= (2 << 2);
+               break;
+       case GUARD_INTERVAL_1_4:
+               tps |= (3 << 2);
+               break;
+       case GUARD_INTERVAL_1_32:
+       default:
+               /* tps |= (0 << 2) */;
+       }
+
+       switch (op->hierarchy_information) {
+       case HIERARCHY_1:
+               tps |= (1 << 10);
+               break;
+       case HIERARCHY_2:
+               tps |= (2 << 10);
+               break;
+       case HIERARCHY_4:
+               tps |= (3 << 10);
+               break;
+       case HIERARCHY_NONE:
+       default:
+               /* tps |= (0 << 10) */;
+       }
+
+       return tps;
+}
+
+struct cinergyt2_fe_state {
+       struct dvb_frontend fe;
+       struct dvb_usb_device *d;
+};
+
+static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
+                                       fe_status_t *status)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_get_status_msg result;
+       u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+       int ret;
+
+       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
+                       sizeof(result), 0);
+       if (ret < 0)
+               return ret;
+
+       *status = 0;
+
+       if (0xffff - le16_to_cpu(result.gain) > 30)
+               *status |= FE_HAS_SIGNAL;
+       if (result.lock_bits & (1 << 6))
+               *status |= FE_HAS_LOCK;
+       if (result.lock_bits & (1 << 5))
+               *status |= FE_HAS_SYNC;
+       if (result.lock_bits & (1 << 4))
+               *status |= FE_HAS_CARRIER;
+       if (result.lock_bits & (1 << 1))
+               *status |= FE_HAS_VITERBI;
+
+       if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+                       (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+               *status &= ~FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_get_status_msg status;
+       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+       int ret;
+
+       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+                               sizeof(status), 0);
+       if (ret < 0)
+               return ret;
+
+       *ber = le32_to_cpu(status.viterbi_error_rate);
+       return 0;
+}
+
+static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_get_status_msg status;
+       u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+       int ret;
+
+       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status,
+                               sizeof(status), 0);
+       if (ret < 0) {
+               err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
+                       ret);
+               return ret;
+       }
+       *unc = le32_to_cpu(status.uncorrected_block_count);
+       return 0;
+}
+
+static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
+                                               u16 *strength)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_get_status_msg status;
+       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+       int ret;
+
+       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+                               sizeof(status), 0);
+       if (ret < 0) {
+               err("cinergyt2_fe_read_signal_strength() Failed!"
+                       " (Error=%d)\n", ret);
+               return ret;
+       }
+       *strength = (0xffff - le16_to_cpu(status.gain));
+       return 0;
+}
+
+static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_get_status_msg status;
+       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
+       int ret;
+
+       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
+                               sizeof(status), 0);
+       if (ret < 0) {
+               err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
+               return ret;
+       }
+       *snr = (status.snr << 8) | status.snr;
+       return 0;
+}
+
+static int cinergyt2_fe_init(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static int cinergyt2_fe_sleep(struct dvb_frontend *fe)
+{
+       deb_info("cinergyt2_fe_sleep() Called\n");
+       return 0;
+}
+
+static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
+                               struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 800;
+       return 0;
+}
+
+static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       struct dvbt_set_parameters_msg param;
+       char result[2];
+       int err;
+
+       param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
+       param.tps = cpu_to_le16(compute_tps(fep));
+       param.freq = cpu_to_le32(fep->frequency / 1000);
+       param.bandwidth = 8 - fep->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
+
+       err = dvb_usb_generic_rw(state->d,
+                       (char *)&param, sizeof(param),
+                       result, sizeof(result), 0);
+       if (err < 0)
+               err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
+
+       return (err < 0) ? err : 0;
+}
+
+static int cinergyt2_fe_get_frontend(struct dvb_frontend *fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       return 0;
+}
+
+static void cinergyt2_fe_release(struct dvb_frontend *fe)
+{
+       struct cinergyt2_fe_state *state = fe->demodulator_priv;
+       if (state != NULL)
+               kfree(state);
+}
+
+static struct dvb_frontend_ops cinergyt2_fe_ops;
+
+struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
+{
+       struct cinergyt2_fe_state *s = kzalloc(sizeof(
+                                       struct cinergyt2_fe_state), GFP_KERNEL);
+       if (s == NULL)
+               return NULL;
+
+       s->d = d;
+       memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
+       s->fe.demodulator_priv = s;
+       return &s->fe;
+}
+
+
+static struct dvb_frontend_ops cinergyt2_fe_ops = {
+       .info = {
+               .name                   = DRIVER_NAME,
+               .type                   = FE_OFDM,
+               .frequency_min          = 174000000,
+               .frequency_max          = 862000000,
+               .frequency_stepsize     = 166667,
+               .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2
+                       | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4
+                       | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8
+                       | FE_CAN_FEC_AUTO | FE_CAN_QPSK
+                       | FE_CAN_QAM_16 | FE_CAN_QAM_64
+                       | FE_CAN_QAM_AUTO
+                       | FE_CAN_TRANSMISSION_MODE_AUTO
+                       | FE_CAN_GUARD_INTERVAL_AUTO
+                       | FE_CAN_HIERARCHY_AUTO
+                       | FE_CAN_RECOVER
+                       | FE_CAN_MUTE_TS
+       },
+
+       .release                = cinergyt2_fe_release,
+
+       .init                   = cinergyt2_fe_init,
+       .sleep                  = cinergyt2_fe_sleep,
+
+       .set_frontend           = cinergyt2_fe_set_frontend,
+       .get_frontend           = cinergyt2_fe_get_frontend,
+       .get_tune_settings      = cinergyt2_fe_get_tune_settings,
+
+       .read_status            = cinergyt2_fe_read_status,
+       .read_ber               = cinergyt2_fe_read_ber,
+       .read_signal_strength   = cinergyt2_fe_read_signal_strength,
+       .read_snr               = cinergyt2_fe_read_snr,
+       .read_ucblocks          = cinergyt2_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h
new file mode 100644 (file)
index 0000000..11d79eb
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
+ *
+ * Based on the dvb-usb-framework code and the
+ * original Terratec Cinergy T2 driver by:
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ *                  Holger Waechtler <holger@qanu.de>
+ *
+ *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 _DVB_USB_CINERGYT2_H_
+#define _DVB_USB_CINERGYT2_H_
+
+#include <linux/usb/input.h>
+
+#define DVB_USB_LOG_PREFIX "cinergyT2"
+#include "dvb-usb.h"
+
+#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
+
+extern int dvb_usb_cinergyt2_debug;
+
+#define deb_info(args...)  dprintk(dvb_usb_cinergyt2_debug,  0x001, args)
+#define deb_xfer(args...)  dprintk(dvb_usb_cinergyt2_debug,  0x002, args)
+#define deb_pll(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x004, args)
+#define deb_ts(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x008, args)
+#define deb_err(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x010, args)
+#define deb_rc(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x020, args)
+#define deb_fw(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x040, args)
+#define deb_mem(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x080, args)
+#define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug,  0x100, args)
+
+
+
+enum cinergyt2_ep1_cmd {
+       CINERGYT2_EP1_PID_TABLE_RESET           = 0x01,
+       CINERGYT2_EP1_PID_SETUP                 = 0x02,
+       CINERGYT2_EP1_CONTROL_STREAM_TRANSFER   = 0x03,
+       CINERGYT2_EP1_SET_TUNER_PARAMETERS      = 0x04,
+       CINERGYT2_EP1_GET_TUNER_STATUS          = 0x05,
+       CINERGYT2_EP1_START_SCAN                = 0x06,
+       CINERGYT2_EP1_CONTINUE_SCAN             = 0x07,
+       CINERGYT2_EP1_GET_RC_EVENTS             = 0x08,
+       CINERGYT2_EP1_SLEEP_MODE                = 0x09,
+       CINERGYT2_EP1_GET_FIRMWARE_VERSION      = 0x0A
+};
+
+
+struct dvbt_get_status_msg {
+       uint32_t freq;
+       uint8_t bandwidth;
+       uint16_t tps;
+       uint8_t flags;
+       uint16_t gain;
+       uint8_t snr;
+       uint32_t viterbi_error_rate;
+       uint32_t rs_error_rate;
+       uint32_t uncorrected_block_count;
+       uint8_t lock_bits;
+       uint8_t prev_lock_bits;
+} __attribute__((packed));
+
+
+struct dvbt_set_parameters_msg {
+       uint8_t cmd;
+       uint32_t freq;
+       uint8_t bandwidth;
+       uint16_t tps;
+       uint8_t flags;
+} __attribute__((packed));
+
+
+extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d);
+
+#endif /* _DVB_USB_CINERGYT2_H_ */
+
index 563400277a426a5455e0d9036fdb5d608a0e416e..406d7fba369d6b702e5db34fef48fd133e89c2da 100644 (file)
@@ -36,6 +36,9 @@
 #include "tuner-xc2028.h"
 #include "tuner-simple.h"
 #include "mxl5005s.h"
+#include "dib7000p.h"
+#include "dib0070.h"
+#include "lgs8gl5.h"
 
 /* debug */
 static int dvb_usb_cxusb_debug;
@@ -109,6 +112,25 @@ static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
        cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
 }
 
+static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
+               u8 addr, int onoff)
+{
+       u8  o[2] = {addr, onoff};
+       u8  i;
+       int rc;
+
+       rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+       if (rc < 0)
+               return rc;
+       if (i == 0x01)
+               return 0;
+       else {
+               deb_info("gpio_write failed.\n");
+               return -EIO;
+       }
+}
+
 /* I2C */
 static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                          int num)
@@ -262,6 +284,20 @@ static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
        return rc;
 }
 
+static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       int ret;
+       u8  b;
+       ret = cxusb_power_ctrl(d, onoff);
+       if (!onoff)
+               return ret;
+
+       msleep(128);
+       cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1);
+       msleep(100);
+       return ret;
+}
+
 static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
        u8 buf[2] = { 0x03, 0x00 };
@@ -283,6 +319,67 @@ static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return 0;
 }
 
+static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
+{
+       int       ep = d->props.generic_bulk_ctrl_endpoint;
+       const int timeout = 100;
+       const int junk_len = 32;
+       u8        *junk;
+       int       rd_count;
+
+       /* Discard remaining data in video pipe */
+       junk = kmalloc(junk_len, GFP_KERNEL);
+       if (!junk)
+               return;
+       while (1) {
+               if (usb_bulk_msg(d->udev,
+                       usb_rcvbulkpipe(d->udev, ep),
+                       junk, junk_len, &rd_count, timeout) < 0)
+                       break;
+               if (!rd_count)
+                       break;
+       }
+       kfree(junk);
+}
+
+static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
+{
+       struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
+       const int timeout = 100;
+       const int junk_len = p->u.bulk.buffersize;
+       u8        *junk;
+       int       rd_count;
+
+       /* Discard remaining data in video pipe */
+       junk = kmalloc(junk_len, GFP_KERNEL);
+       if (!junk)
+               return;
+       while (1) {
+               if (usb_bulk_msg(d->udev,
+                       usb_rcvbulkpipe(d->udev, p->endpoint),
+                       junk, junk_len, &rd_count, timeout) < 0)
+                       break;
+               if (!rd_count)
+                       break;
+       }
+       kfree(junk);
+}
+
+static int cxusb_d680_dmb_streaming_ctrl(
+               struct dvb_usb_adapter *adap, int onoff)
+{
+       if (onoff) {
+               u8 buf[2] = { 0x03, 0x00 };
+               cxusb_d680_dmb_drain_video(adap->dev);
+               return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON,
+                       buf, sizeof(buf), NULL, 0);
+       } else {
+               int ret = cxusb_ctrl_msg(adap->dev,
+                       CMD_STREAMING_OFF, NULL, 0, NULL, 0);
+               return ret;
+       }
+}
+
 static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
@@ -335,6 +432,32 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
        return 0;
 }
 
+static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
+               int *state)
+{
+       struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+       u8 ircode[2];
+       int i;
+
+       *event = 0;
+       *state = REMOTE_NO_KEY_PRESSED;
+
+       if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
+               return 0;
+
+       for (i = 0; i < d->props.rc_key_map_size; i++) {
+               if (keymap[i].custom == ircode[0] &&
+                   keymap[i].data == ircode[1]) {
+                       *event = keymap[i].event;
+                       *state = REMOTE_KEY_PRESSED;
+
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
 static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
        { 0xfe, 0x02, KEY_TV },
        { 0xfe, 0x0e, KEY_MP3 },
@@ -422,6 +545,44 @@ static struct dvb_usb_rc_key dvico_portable_rc_keys[] = {
        { 0xfc, 0x00, KEY_UNKNOWN },    /* HD */
 };
 
+static struct dvb_usb_rc_key d680_dmb_rc_keys[] = {
+       { 0x00, 0x38, KEY_UNKNOWN },    /* TV/AV */
+       { 0x08, 0x0c, KEY_ZOOM },
+       { 0x08, 0x00, KEY_0 },
+       { 0x00, 0x01, KEY_1 },
+       { 0x08, 0x02, KEY_2 },
+       { 0x00, 0x03, KEY_3 },
+       { 0x08, 0x04, KEY_4 },
+       { 0x00, 0x05, KEY_5 },
+       { 0x08, 0x06, KEY_6 },
+       { 0x00, 0x07, KEY_7 },
+       { 0x08, 0x08, KEY_8 },
+       { 0x00, 0x09, KEY_9 },
+       { 0x00, 0x0a, KEY_MUTE },
+       { 0x08, 0x29, KEY_BACK },
+       { 0x00, 0x12, KEY_CHANNELUP },
+       { 0x08, 0x13, KEY_CHANNELDOWN },
+       { 0x00, 0x2b, KEY_VOLUMEUP },
+       { 0x08, 0x2c, KEY_VOLUMEDOWN },
+       { 0x00, 0x20, KEY_UP },
+       { 0x08, 0x21, KEY_DOWN },
+       { 0x00, 0x11, KEY_LEFT },
+       { 0x08, 0x10, KEY_RIGHT },
+       { 0x00, 0x0d, KEY_OK },
+       { 0x08, 0x1f, KEY_RECORD },
+       { 0x00, 0x17, KEY_PLAYPAUSE },
+       { 0x08, 0x16, KEY_PLAYPAUSE },
+       { 0x00, 0x0b, KEY_STOP },
+       { 0x08, 0x27, KEY_FASTFORWARD },
+       { 0x00, 0x26, KEY_REWIND },
+       { 0x08, 0x1e, KEY_UNKNOWN },    /* Time Shift */
+       { 0x00, 0x0e, KEY_UNKNOWN },    /* Snapshot */
+       { 0x08, 0x2d, KEY_UNKNOWN },    /* Mouse Cursor */
+       { 0x00, 0x0f, KEY_UNKNOWN },    /* Minimize/Maximize */
+       { 0x08, 0x14, KEY_UNKNOWN },    /* Shuffle */
+       { 0x00, 0x25, KEY_POWER },
+};
+
 static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
@@ -527,6 +688,24 @@ static struct mxl5005s_config aver_a868r_tuner = {
        .AgcMasterByte   = 0x00,
 };
 
+/* FIXME: needs tweaking */
+static struct mxl5005s_config d680_dmb_tuner = {
+       .i2c_address     = 0x63,
+       .if_freq         = 36125000UL,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_C,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
@@ -563,7 +742,8 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
-static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
+static int dvico_bluebird_xc2028_callback(void *ptr, int component,
+                                         int command, int arg)
 {
        struct dvb_usb_adapter *adap = ptr;
        struct dvb_usb_device *d = adap->dev;
@@ -591,14 +771,16 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
        struct xc2028_config      cfg = {
                .i2c_adap  = &adap->dev->i2c_adap,
                .i2c_addr  = 0x61,
-               .callback  = dvico_bluebird_xc2028_callback,
        };
        static struct xc2028_ctrl ctl = {
-               .fname       = "xc3028-v27.fw",
+               .fname       = XC2028_DEFAULT_FIRMWARE,
                .max_len     = 64,
                .demod       = XC3028_FE_ZARLINK456,
        };
 
+       /* FIXME: generalize & move to common area */
+       adap->fe->callback = dvico_bluebird_xc2028_callback;
+
        fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
        if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
                return -EIO;
@@ -615,6 +797,14 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
+static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_frontend *fe;
+       fe = dvb_attach(mxl5005s_attach, adap->fe,
+                       &adap->dev->i2c_adap, &d680_dmb_tuner);
+       return (fe == NULL) ? -EIO : 0;
+}
+
 static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
 {
        u8 b;
@@ -726,6 +916,159 @@ no_IR:
        return 0;
 }
 
+static struct dibx000_agc_config dib7070_agc_config = {
+       .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+
+       /*
+        * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
+        * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+        * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
+        */
+       .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
+                (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+       .inv_gain = 600,
+       .time_stabiliz = 10,
+       .alpha_level = 0,
+       .thlock = 118,
+       .wbd_inv = 0,
+       .wbd_ref = 3530,
+       .wbd_sel = 1,
+       .wbd_alpha = 5,
+       .agc1_max = 65535,
+       .agc1_min = 0,
+       .agc2_max = 65535,
+       .agc2_min = 0,
+       .agc1_pt1 = 0,
+       .agc1_pt2 = 40,
+       .agc1_pt3 = 183,
+       .agc1_slope1 = 206,
+       .agc1_slope2 = 255,
+       .agc2_pt1 = 72,
+       .agc2_pt2 = 152,
+       .agc2_slope1 = 88,
+       .agc2_slope2 = 90,
+       .alpha_mant = 17,
+       .alpha_exp = 27,
+       .beta_mant = 23,
+       .beta_exp = 51,
+       .perform_agc_softsplit = 0,
+};
+
+static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
+       .internal = 60000,
+       .sampling = 15000,
+       .pll_prediv = 1,
+       .pll_ratio = 20,
+       .pll_range = 3,
+       .pll_reset = 1,
+       .pll_bypass = 0,
+       .enable_refdiv = 0,
+       .bypclk_div = 0,
+       .IO_CLK_en_core = 1,
+       .ADClkSrc = 1,
+       .modulo = 2,
+       /* refsel, sel, freq_15k */
+       .sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
+       .ifreq = (0 << 25) | 0,
+       .timf = 20452225,
+       .xtal_hz = 12000000,
+};
+
+static struct dib7000p_config cxusb_dualdig4_rev2_config = {
+       .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
+       .output_mpeg2_in_188_bytes = 1,
+
+       .agc_config_count = 1,
+       .agc = &dib7070_agc_config,
+       .bw  = &dib7070_bw_config_12_mhz,
+       .tuner_is_baseband = 1,
+       .spur_protect = 1,
+
+       .gpio_dir = 0xfcef,
+       .gpio_val = 0x0110,
+
+       .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+       .hostbus_diversity = 1,
+};
+
+static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
+               err("set interface failed");
+
+       cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
+
+       cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
+
+       dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+                                &cxusb_dualdig4_rev2_config);
+
+       adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+                             &cxusb_dualdig4_rev2_config);
+       if (adap->fe == NULL)
+               return -EIO;
+
+       return 0;
+}
+
+static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+       return dib7000p_set_gpio(fe, 8, 0, !onoff);
+}
+
+static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+       return 0;
+}
+
+static struct dib0070_config dib7070p_dib0070_config = {
+       .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
+       .reset = dib7070_tuner_reset,
+       .sleep = dib7070_tuner_sleep,
+       .clock_khz = 12000,
+};
+
+struct dib0700_adapter_state {
+       int (*set_param_save) (struct dvb_frontend *,
+                              struct dvb_frontend_parameters *);
+};
+
+static int dib7070_set_param_override(struct dvb_frontend *fe,
+                                     struct dvb_frontend_parameters *fep)
+{
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dib0700_adapter_state *state = adap->priv;
+
+       u16 offset;
+       u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+       switch (band) {
+       case BAND_VHF: offset = 950; break;
+       default:
+       case BAND_UHF: offset = 550; break;
+       }
+
+       dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+
+       return state->set_param_save(fe, fep);
+}
+
+static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_adapter_state *st = adap->priv;
+       struct i2c_adapter *tun_i2c =
+               dib7000p_get_i2c_master(adap->fe,
+                                       DIBX000_I2C_INTERFACE_TUNER, 1);
+
+       if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
+           &dib7070p_dib0070_config) == NULL)
+               return -ENODEV;
+
+       st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+       adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
+       return 0;
+}
+
 static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
 {
        if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
@@ -751,6 +1094,54 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
        return -EIO;
 }
 
+static struct lgs8gl5_config lgs8gl5_cfg = {
+       .demod_address = 0x19,
+};
+
+static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap->dev;
+       int n;
+
+       /* Select required USB configuration */
+       if (usb_set_interface(d->udev, 0, 0) < 0)
+               err("set interface failed");
+
+       /* Unblock all USB pipes */
+       usb_clear_halt(d->udev,
+               usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+       usb_clear_halt(d->udev,
+               usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+       usb_clear_halt(d->udev,
+               usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
+
+       /* Drain USB pipes to avoid hang after reboot */
+       for (n = 0;  n < 5;  n++) {
+               cxusb_d680_dmb_drain_message(d);
+               cxusb_d680_dmb_drain_video(d);
+               msleep(200);
+       }
+
+       /* Reset the tuner */
+       if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
+               err("clear tuner gpio failed");
+               return -EIO;
+       }
+       msleep(100);
+       if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
+               err("set tuner gpio failed");
+               return -EIO;
+       }
+       msleep(100);
+
+       /* Attach frontend */
+       adap->fe = dvb_attach(lgs8gl5_attach, &lgs8gl5_cfg, &d->i2c_adap);
+       if (adap->fe == NULL)
+               return -EIO;
+
+       return 0;
+}
+
 /*
  * DViCO has shipped two devices with the same USB ID, but only one of them
  * needs a firmware download.  Check the device class details to see if they
@@ -826,9 +1217,11 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
 static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
+static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
@@ -852,6 +1245,11 @@ static int cxusb_probe(struct usb_interface *intf,
                                     THIS_MODULE, NULL, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
                                     THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf,
+                                    &cxusb_bluebird_dualdig4_rev2_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
            0)
                return 0;
 
@@ -876,6 +1274,8 @@ static struct usb_device_id cxusb_table [] = {
        { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
        { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
        { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
+       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
+       { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
        {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1321,6 +1721,104 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
        }
 };
 
+static
+struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl         = CYPRESS_FX2,
+
+       .size_of_priv     = sizeof(struct cxusb_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl  = cxusb_streaming_ctrl,
+                       .frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
+                       .tuner_attach    = cxusb_dualdig4_rev2_tuner_attach,
+                       .size_of_priv    = sizeof(struct dib0700_adapter_state),
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 7,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
+               },
+       },
+
+       .power_ctrl       = cxusb_bluebird_power_ctrl,
+
+       .i2c_algo         = &cxusb_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .rc_interval      = 100,
+       .rc_key_map       = dvico_mce_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(dvico_mce_rc_keys),
+       .rc_query         = cxusb_rc_query,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
+                       { NULL },
+                       { &cxusb_table[17], NULL },
+               },
+       }
+};
+
+static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl         = CYPRESS_FX2,
+
+       .size_of_priv     = sizeof(struct cxusb_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
+                       .frontend_attach  = cxusb_d680_dmb_frontend_attach,
+                       .tuner_attach     = cxusb_d680_dmb_tuner_attach,
+
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 5,
+                               .endpoint = 0x02,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
+               },
+       },
+
+       .power_ctrl       = cxusb_d680_dmb_power_ctrl,
+
+       .i2c_algo         = &cxusb_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .rc_interval      = 100,
+       .rc_key_map       = d680_dmb_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(d680_dmb_rc_keys),
+       .rc_query         = cxusb_d680_dmb_rc_query,
+
+       .num_device_descs = 1,
+       .devices = {
+               {
+                       "Conexant DMB-TH Stick",
+                       { NULL },
+                       { &cxusb_table[18], NULL },
+               },
+       }
+};
+
 static struct usb_driver cxusb_driver = {
        .name           = "dvb_usb_cxusb",
        .probe          = cxusb_probe,
index 66d4dc6ba46fe8a78a9d597f3d45bdb6e6c5cf01..739193943c17ccbabe5c6af9c1b4a1e3d77c4cc8 100644 (file)
@@ -31,6 +31,8 @@ extern int dvb_usb_dib0700_debug;
        // 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
        // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
 #define REQUEST_SET_RC       0x11
+#define REQUEST_NEW_I2C_READ 0x12
+#define REQUEST_NEW_I2C_WRITE 0x13
 #define REQUEST_GET_VERSION  0x15
 
 struct dib0700_state {
@@ -39,6 +41,8 @@ struct dib0700_state {
        u8 rc_toggle;
        u8 rc_counter;
        u8 is_dib7000pc;
+       u8 fw_use_new_i2c_api;
+       u8 disable_streaming_master_mode;
 };
 
 extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
index 595a04696c87af2590588bf87013a44b8e44aa7c..dd53cee3896de0d3857569ce08af9d39bc9d308d 100644 (file)
@@ -82,9 +82,98 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
 }
 
 /*
- * I2C master xfer function
+ * I2C master xfer function (supported in 1.20 firmware)
  */
-static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
+static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
+                               int num)
+{
+       /* The new i2c firmware messages are more reliable and in particular
+          properly support i2c read calls not preceded by a write */
+
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       uint8_t bus_mode = 1;  /* 0=eeprom bus, 1=frontend bus */
+       uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
+       uint8_t en_start = 0;
+       uint8_t en_stop = 0;
+       uint8_t buf[255]; /* TBV: malloc ? */
+       int result, i;
+
+       /* Ensure nobody else hits the i2c bus while we're sending our
+          sequence of messages, (such as the remote control thread) */
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       for (i = 0; i < num; i++) {
+               if (i == 0) {
+                       /* First message in the transaction */
+                       en_start = 1;
+               } else if (!(msg[i].flags & I2C_M_NOSTART)) {
+                       /* Device supports repeated-start */
+                       en_start = 1;
+               } else {
+                       /* Not the first packet and device doesn't support
+                          repeated start */
+                       en_start = 0;
+               }
+               if (i == (num - 1)) {
+                       /* Last message in the transaction */
+                       en_stop = 1;
+               }
+
+               if (msg[i].flags & I2C_M_RD) {
+                       /* Read request */
+                       u16 index, value;
+                       uint8_t i2c_dest;
+
+                       i2c_dest = (msg[i].addr << 1);
+                       value = ((en_start << 7) | (en_stop << 6) |
+                                (msg[i].len & 0x3F)) << 8 | i2c_dest;
+                       /* I2C ctrl + FE bus; */
+                       index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+
+                       result = usb_control_msg(d->udev,
+                                                usb_rcvctrlpipe(d->udev, 0),
+                                                REQUEST_NEW_I2C_READ,
+                                                USB_TYPE_VENDOR | USB_DIR_IN,
+                                                value, index, msg[i].buf,
+                                                msg[i].len,
+                                                USB_CTRL_GET_TIMEOUT);
+                       if (result < 0) {
+                               err("i2c read error (status = %d)\n", result);
+                               break;
+                       }
+               } else {
+                       /* Write request */
+                       buf[0] = REQUEST_NEW_I2C_WRITE;
+                       buf[1] = (msg[i].addr << 1);
+                       buf[2] = (en_start << 7) | (en_stop << 6) |
+                               (msg[i].len & 0x3F);
+                       /* I2C ctrl + FE bus; */
+                       buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+                       /* The Actual i2c payload */
+                       memcpy(&buf[4], msg[i].buf, msg[i].len);
+
+                       result = usb_control_msg(d->udev,
+                                                usb_sndctrlpipe(d->udev, 0),
+                                                REQUEST_NEW_I2C_WRITE,
+                                                USB_TYPE_VENDOR | USB_DIR_OUT,
+                                                0, 0, buf, msg[i].len + 4,
+                                                USB_CTRL_GET_TIMEOUT);
+                       if (result < 0) {
+                               err("i2c write error (status = %d)\n", result);
+                               break;
+                       }
+               }
+       }
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+}
+
+/*
+ * I2C master xfer function (pre-1.20 firmware)
+ */
+static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
+                                  struct i2c_msg *msg, int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
        int i,len;
@@ -124,6 +213,21 @@ static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num
        return i;
 }
 
+static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+                           int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       struct dib0700_state *st = d->priv;
+
+       if (st->fw_use_new_i2c_api == 1) {
+               /* User running at least fw 1.20 */
+               return dib0700_i2c_xfer_new(adap, msg, num);
+       } else {
+               /* Use legacy calls */
+               return dib0700_i2c_xfer_legacy(adap, msg, num);
+       }
+}
+
 static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C;
@@ -246,7 +350,12 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 
        b[0] = REQUEST_ENABLE_VIDEO;
        b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
-       b[2] = (0x01 << 4); /* Master mode */
+
+       if (st->disable_streaming_master_mode == 1)
+               b[2] = 0x00;
+       else
+               b[2] = (0x01 << 4); /* Master mode */
+
        b[3] = 0x00;
 
        deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
index 6c0e5c5f4362fbed72c8ccdd3d10c7a0098bf056..0cfccc24b1907acad9d4db7ea6f3d77b5a6e7a1a 100644 (file)
@@ -14,6 +14,8 @@
 #include "mt2060.h"
 #include "mt2266.h"
 #include "tuner-xc2028.h"
+#include "xc5000.h"
+#include "s5h1411.h"
 #include "dib0070.h"
 
 static int force_lna_activation;
@@ -366,7 +368,8 @@ static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
        .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
 };
 
-static int stk7700ph_xc3028_callback(void *ptr, int command, int arg)
+static int stk7700ph_xc3028_callback(void *ptr, int component,
+                                    int command, int arg)
 {
        struct dvb_usb_adapter *adap = ptr;
 
@@ -394,7 +397,6 @@ static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
 
 static struct xc2028_config stk7700ph_xc3028_config = {
        .i2c_addr = 0x61,
-       .callback = stk7700ph_xc3028_callback,
        .ctrl = &stk7700ph_xc3028_ctrl,
 };
 
@@ -435,7 +437,9 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
                DIBX000_I2C_INTERFACE_TUNER, 1);
 
        stk7700ph_xc3028_config.i2c_adap = tun_i2c;
-       stk7700ph_xc3028_config.video_dev = adap;
+
+       /* FIXME: generalize & move to common area */
+       adap->fe->callback = stk7700ph_xc3028_callback;
 
        return dvb_attach(xc2028_attach, adap->fe, &stk7700ph_xc3028_config)
                == NULL ? -ENODEV : 0;
@@ -677,6 +681,43 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
        { 0x01, 0x7d, KEY_VOLUMEDOWN },
        { 0x02, 0x42, KEY_CHANNELUP },
        { 0x00, 0x7d, KEY_CHANNELDOWN },
+
+       /* Key codes for Nova-TD "credit card" remote control. */
+       { 0x1d, 0x00, KEY_0 },
+       { 0x1d, 0x01, KEY_1 },
+       { 0x1d, 0x02, KEY_2 },
+       { 0x1d, 0x03, KEY_3 },
+       { 0x1d, 0x04, KEY_4 },
+       { 0x1d, 0x05, KEY_5 },
+       { 0x1d, 0x06, KEY_6 },
+       { 0x1d, 0x07, KEY_7 },
+       { 0x1d, 0x08, KEY_8 },
+       { 0x1d, 0x09, KEY_9 },
+       { 0x1d, 0x0a, KEY_TEXT },
+       { 0x1d, 0x0d, KEY_MENU },
+       { 0x1d, 0x0f, KEY_MUTE },
+       { 0x1d, 0x10, KEY_VOLUMEUP },
+       { 0x1d, 0x11, KEY_VOLUMEDOWN },
+       { 0x1d, 0x12, KEY_CHANNEL },
+       { 0x1d, 0x14, KEY_UP },
+       { 0x1d, 0x15, KEY_DOWN },
+       { 0x1d, 0x16, KEY_LEFT },
+       { 0x1d, 0x17, KEY_RIGHT },
+       { 0x1d, 0x1c, KEY_TV },
+       { 0x1d, 0x1e, KEY_NEXT },
+       { 0x1d, 0x1f, KEY_BACK },
+       { 0x1d, 0x20, KEY_CHANNELUP },
+       { 0x1d, 0x21, KEY_CHANNELDOWN },
+       { 0x1d, 0x24, KEY_LAST },
+       { 0x1d, 0x25, KEY_OK },
+       { 0x1d, 0x30, KEY_PAUSE },
+       { 0x1d, 0x32, KEY_REWIND },
+       { 0x1d, 0x34, KEY_FASTFORWARD },
+       { 0x1d, 0x35, KEY_PLAY },
+       { 0x1d, 0x36, KEY_STOP },
+       { 0x1d, 0x37, KEY_RECORD },
+       { 0x1d, 0x3b, KEY_GOTO },
+       { 0x1d, 0x3d, KEY_POWER },
 };
 
 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@@ -1078,6 +1119,97 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
        return adap->fe == NULL ? -ENODEV : 0;
 }
 
+/* S5H1411 */
+static struct s5h1411_config pinnacle_801e_config = {
+       .output_mode   = S5H1411_PARALLEL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .mpeg_timing   = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+       .qam_if        = S5H1411_IF_44000,
+       .vsb_if        = S5H1411_IF_44000,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING
+};
+
+/* Pinnacle PCTV HD Pro 801e GPIOs map:
+   GPIO0  - currently unknown
+   GPIO1  - xc5000 tuner reset
+   GPIO2  - CX25843 sleep
+   GPIO3  - currently unknown
+   GPIO4  - currently unknown
+   GPIO6  - currently unknown
+   GPIO7  - currently unknown
+   GPIO9  - currently unknown
+   GPIO10 - CX25843 reset
+ */
+static int s5h1411_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dib0700_state *st = adap->dev->priv;
+
+       /* Make use of the new i2c functions from FW 1.20 */
+       st->fw_use_new_i2c_api = 1;
+
+       /* The s5h1411 requires the dib0700 to not be in master mode */
+       st->disable_streaming_master_mode = 1;
+
+       /* All msleep values taken from Windows USB trace */
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
+       dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0);
+       dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+       msleep(400);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+       msleep(60);
+       dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+       msleep(30);
+       dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+       dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0);
+       msleep(30);
+
+       /* Put the CX25843 to sleep for now since we're in digital mode */
+       dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
+
+       /* GPIOs are initialized, do the attach */
+       adap->fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
+                             &adap->dev->i2c_adap);
+       return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int dib0700_xc5000_tuner_callback(void *priv, int component,
+                                        int command, int arg)
+{
+       struct dvb_usb_adapter *adap = priv;
+
+       if (command == XC5000_TUNER_RESET) {
+               /* Reset the tuner */
+               dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
+               msleep(330); /* from Windows USB trace */
+               dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
+               msleep(330); /* from Windows USB trace */
+       } else {
+               err("xc5000: unknown tuner callback command: %d\n", command);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct xc5000_config s5h1411_xc5000_tunerconfig = {
+       .i2c_address      = 0x64,
+       .if_khz           = 5380,
+};
+
+static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       /* FIXME: generalize & move to common area */
+       adap->fe->callback = dib0700_xc5000_tuner_callback;
+
+       return dvb_attach(xc5000_attach, adap->fe, &adap->dev->i2c_adap,
+                         &s5h1411_xc5000_tunerconfig)
+               == NULL ? -ENODEV : 0;
+}
+
 /* DVB-USB and USB stuff follows */
 struct usb_device_id dib0700_usb_id_table[] = {
 /* 0 */        { USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
@@ -1119,6 +1251,11 @@ struct usb_device_id dib0700_usb_id_table[] = {
        { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
 /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
        { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) },
+       { USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U8000) },
+       { USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_STK7700PH) },
+       { USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000H) },
+/* 40 */{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV801E) },
+       { USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV801E_SE) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1126,7 +1263,7 @@ MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
 #define DIB0700_DEFAULT_DEVICE_PROPERTIES \
        .caps              = DVB_USB_IS_AN_I2C_ADAPTER, \
        .usb_ctrl          = DEVICE_SPECIFIC, \
-       .firmware          = "dvb-usb-dib0700-1.10.fw", \
+       .firmware          = "dvb-usb-dib0700-1.20.fw", \
        .download_firmware = dib0700_download_firmware, \
        .no_reconnect      = 1, \
        .size_of_priv      = sizeof(struct dib0700_state), \
@@ -1293,7 +1430,12 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[31], NULL },
                                { NULL },
                        }
-               }
+               },
+
+               .rc_interval      = DEFAULT_RC_INTERVAL,
+               .rc_key_map       = dib0700_rc_keys,
+               .rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+               .rc_query         = dib0700_rc_query
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
                .num_adapters = 1,
@@ -1408,7 +1550,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        },
                },
 
-               .num_device_descs = 3,
+               .num_device_descs = 5,
                .devices = {
                        {   "Terratec Cinergy HT USB XE",
                                { &dib0700_usb_id_table[27], NULL },
@@ -1422,6 +1564,47 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                                { &dib0700_usb_id_table[32], NULL },
                                { NULL },
                        },
+                       {   "Gigabyte U8000-RH",
+                               { &dib0700_usb_id_table[37], NULL },
+                               { NULL },
+                       },
+                       {   "YUAN High-Tech STK7700PH",
+                               { &dib0700_usb_id_table[38], NULL },
+                               { NULL },
+                       },
+                       {   "Asus My Cinema-U3000Hybrid",
+                               { &dib0700_usb_id_table[39], NULL },
+                               { NULL },
+                       },
+               },
+               .rc_interval      = DEFAULT_RC_INTERVAL,
+               .rc_key_map       = dib0700_rc_keys,
+               .rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+               .rc_query         = dib0700_rc_query
+       }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+               .num_adapters = 1,
+               .adapter = {
+                       {
+                               .frontend_attach  = s5h1411_frontend_attach,
+                               .tuner_attach     = xc5000_tuner_attach,
+
+                               DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+                               .size_of_priv = sizeof(struct
+                                               dib0700_adapter_state),
+                       },
+               },
+
+               .num_device_descs = 2,
+               .devices = {
+                       {   "Pinnacle PCTV HD Pro USB Stick",
+                               { &dib0700_usb_id_table[40], NULL },
+                               { NULL },
+                       },
+                       {   "Pinnacle PCTV HD USB Stick",
+                               { &dib0700_usb_id_table[41], NULL },
+                               { NULL },
+                       },
                },
                .rc_interval      = DEFAULT_RC_INTERVAL,
                .rc_key_map       = dib0700_rc_keys,
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c
new file mode 100644 (file)
index 0000000..078ce92
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
+ *
+ * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
+ * http://royale.zerezo.com/dtv5100/
+ *
+ * Inspired by gl861.c and au6610.c drivers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "dtv5100.h"
+#include "zl10353.h"
+#include "qt1010.h"
+
+/* debug */
+static int dvb_usb_dtv5100_debug;
+module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
+                          u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+       u8 request;
+       u8 type;
+       u16 value;
+       u16 index;
+
+       switch (wlen) {
+       case 1:
+               /* write { reg }, read { value } */
+               request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
+                                                       DTV5100_TUNER_READ);
+               type = USB_TYPE_VENDOR | USB_DIR_IN;
+               value = 0;
+               break;
+       case 2:
+               /* write { reg, value } */
+               request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
+                                                       DTV5100_TUNER_WRITE);
+               type = USB_TYPE_VENDOR | USB_DIR_OUT;
+               value = wbuf[1];
+               break;
+       default:
+               warn("wlen = %x, aborting.", wlen);
+               return -EINVAL;
+       }
+       index = (addr << 8) + wbuf[0];
+
+       msleep(1); /* avoid I2C errors */
+       return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
+                              type, value, index, rbuf, rlen,
+                              DTV5100_USB_TIMEOUT);
+}
+
+/* I2C */
+static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                           int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i;
+
+       if (num > 2)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       for (i = 0; i < num; i++) {
+               /* write/read request */
+               if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+                       if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                           msg[i].len, msg[i+1].buf,
+                                           msg[i+1].len) < 0)
+                               break;
+                       i++;
+               } else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
+                                          msg[i].len, NULL, 0) < 0)
+                               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return i;
+}
+
+static u32 dtv5100_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dtv5100_i2c_algo = {
+       .master_xfer   = dtv5100_i2c_xfer,
+       .functionality = dtv5100_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static struct zl10353_config dtv5100_zl10353_config = {
+       .demod_address = DTV5100_DEMOD_ADDR,
+       .no_tuner = 1,
+       .parallel_ts = 1,
+};
+
+static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
+                             &adap->dev->i2c_adap);
+       if (adap->fe == NULL)
+               return -EIO;
+
+       /* disable i2c gate, or it won't work... is this safe? */
+       adap->fe->ops.i2c_gate_ctrl = NULL;
+
+       return 0;
+}
+
+static struct qt1010_config dtv5100_qt1010_config = {
+       .i2c_address = DTV5100_TUNER_ADDR
+};
+
+static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       return dvb_attach(qt1010_attach,
+                         adap->fe, &adap->dev->i2c_adap,
+                         &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties dtv5100_properties;
+
+static int dtv5100_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       int i, ret;
+       struct usb_device *udev = interface_to_usbdev(intf);
+
+       /* initialize non qt1010/zl10353 part? */
+       for (i = 0; dtv5100_init[i].request; i++) {
+               ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                     dtv5100_init[i].request,
+                                     USB_TYPE_VENDOR | USB_DIR_OUT,
+                                     dtv5100_init[i].value,
+                                     dtv5100_init[i].index, NULL, 0,
+                                     DTV5100_USB_TIMEOUT);
+               if (ret)
+                       return ret;
+       }
+
+       ret = dvb_usb_device_init(intf, &dtv5100_properties,
+                                 THIS_MODULE, NULL, adapter_nr);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static struct usb_device_id dtv5100_table[] = {
+       { USB_DEVICE(0x06be, 0xa232) },
+       { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, dtv5100_table);
+
+static struct dvb_usb_device_properties dtv5100_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+
+       .size_of_priv = 0,
+
+       .num_adapters = 1,
+       .adapter = {{
+               .frontend_attach = dtv5100_frontend_attach,
+               .tuner_attach    = dtv5100_tuner_attach,
+
+               .stream = {
+                       .type = USB_BULK,
+                       .count = 8,
+                       .endpoint = 0x82,
+                       .u = {
+                               .bulk = {
+                                       .buffersize = 4096,
+                               }
+                       }
+               },
+       } },
+
+       .i2c_algo = &dtv5100_i2c_algo,
+
+       .num_device_descs = 1,
+       .devices = {
+               {
+                       .name = "AME DTV-5100 USB2.0 DVB-T",
+                       .cold_ids = { NULL },
+                       .warm_ids = { &dtv5100_table[0], NULL },
+               },
+       }
+};
+
+static struct usb_driver dtv5100_driver = {
+       .name           = "dvb_usb_dtv5100",
+       .probe          = dtv5100_probe,
+       .disconnect     = dvb_usb_device_exit,
+       .id_table       = dtv5100_table,
+};
+
+/* module stuff */
+static int __init dtv5100_module_init(void)
+{
+       int ret;
+
+       ret = usb_register(&dtv5100_driver);
+       if (ret)
+               err("usb_register failed. Error number %d", ret);
+
+       return ret;
+}
+
+static void __exit dtv5100_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&dtv5100_driver);
+}
+
+module_init(dtv5100_module_init);
+module_exit(dtv5100_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h
new file mode 100644 (file)
index 0000000..93e96e0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
+ *
+ * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
+ * http://royale.zerezo.com/dtv5100/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 _DVB_USB_DTV5100_H_
+#define _DVB_USB_DTV5100_H_
+
+#define DVB_USB_LOG_PREFIX "dtv5100"
+#include "dvb-usb.h"
+
+#define DTV5100_USB_TIMEOUT 500
+
+#define DTV5100_DEMOD_ADDR     0x00
+#define DTV5100_DEMOD_WRITE    0xc0
+#define DTV5100_DEMOD_READ     0xc1
+
+#define DTV5100_TUNER_ADDR     0xc4
+#define DTV5100_TUNER_WRITE    0xc7
+#define DTV5100_TUNER_READ     0xc8
+
+#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
+#define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T"
+
+static struct {
+       u8 request;
+       u8 value;
+       u16 index;
+} dtv5100_init[] = {
+       { 0x000000c5, 0x00000000, 0x00000001 },
+       { 0x000000c5, 0x00000001, 0x00000001 },
+       { }             /* Terminating entry */
+};
+
+#endif
index 03dfb9f2fe30eacd73aadbcf01b8aa9c5230ccd5..7380b94b3b36065af00051e7f5f965fb18f3afc1 100644 (file)
@@ -22,6 +22,7 @@
 #define USB_VID_AVERMEDIA                      0x07ca
 #define USB_VID_COMPRO                         0x185b
 #define USB_VID_COMPRO_UNK                     0x145f
+#define USB_VID_CONEXANT                       0x0572
 #define USB_VID_CYPRESS                                0x04b4
 #define USB_VID_DIBCOM                         0x10b8
 #define USB_VID_DPOSH                          0x1498
 #define USB_VID_HAUPPAUGE                      0x2040
 #define USB_VID_HYPER_PALTEK                   0x1025
 #define USB_VID_KWORLD                         0xeb2a
+#define USB_VID_KWORLD_2                       0x1b80
 #define USB_VID_KYE                            0x0458
 #define USB_VID_LEADTEK                                0x0413
 #define USB_VID_LITEON                         0x04ca
 #define USB_VID_MEDION                         0x1660
 #define USB_VID_MIGLIA                         0x18f3
 #define USB_VID_MSI                            0x0db0
+#define USB_VID_MSI_2                          0x1462
 #define USB_VID_OPERA1                         0x695c
 #define USB_VID_PINNACLE                       0x2304
 #define USB_VID_TECHNOTREND                    0x0b48
 #define USB_VID_TERRATEC                       0x0ccd
+#define USB_VID_TELESTAR                       0x10b9
 #define USB_VID_VISIONPLUS                     0x13d3
 #define USB_VID_TWINHAN                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC              0x05d8
 #define USB_VID_WIDEVIEW                       0x14aa
 #define USB_VID_GIGABYTE                       0x1044
 #define USB_VID_YUAN                           0x1164
-
+#define USB_VID_XTENSIONS                      0x1ae7
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD                      0xa333
 #define USB_PID_ADSTECH_USB2_WARM                      0xa334
 #define USB_PID_AFATECH_AF9005                         0x9020
+#define USB_PID_AFATECH_AF9015_9015                    0x9015
+#define USB_PID_AFATECH_AF9015_9016                    0x9016
 #define USB_VID_ALINK_DTU                              0xf170
 #define USB_PID_ANSONIC_DVBT_USB                       0x6000
 #define USB_PID_ANYSEE                                 0x861f
+#define USB_PID_AZUREWAVE_AD_TU700                     0x3237
 #define USB_PID_AVERMEDIA_DVBT_USB_COLD                        0x0001
 #define USB_PID_AVERMEDIA_DVBT_USB_WARM                        0x0002
 #define USB_PID_AVERMEDIA_DVBT_USB2_COLD               0xa800
@@ -69,6 +76,7 @@
 #define USB_PID_COMPRO_DVBU2000_UNK_WARM               0x010d
 #define USB_PID_COMPRO_VIDEOMATE_U500                  0x1e78
 #define USB_PID_COMPRO_VIDEOMATE_U500_PC               0x1e80
+#define USB_PID_CONEXANT_D680_DMB                      0x86d6
 #define USB_PID_DIBCOM_HOOK_DEFAULT                    0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM             0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD                    0x0bb8
 #define USB_PID_UNIWILL_STK7700P                       0x6003
 #define USB_PID_GRANDTEC_DVBT_USB_COLD                 0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
+#define USB_PID_KWORLD_399U                            0xe399
+#define USB_PID_KWORLD_PC160_2T                                0xc160
 #define USB_PID_KWORLD_VSTREAM_COLD                    0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM                    0x17df
 #define USB_PID_TERRATEC_CINERGY_T_USB_XE              0x0055
+#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2         0x0069
 #define USB_PID_TWINHAN_VP7041_COLD                    0x3201
 #define USB_PID_TWINHAN_VP7041_WARM                    0x3202
 #define USB_PID_TWINHAN_VP7020_COLD                    0x3203
 #define USB_PID_TWINHAN_VP7045_WARM                    0x3206
 #define USB_PID_TWINHAN_VP7021_COLD                    0x3207
 #define USB_PID_TWINHAN_VP7021_WARM                    0x3208
+#define USB_PID_TINYTWIN                               0x3226
 #define USB_PID_DNTV_TINYUSB2_COLD                     0x3223
 #define USB_PID_DNTV_TINYUSB2_WARM                     0x3224
 #define USB_PID_ULTIMA_TVBOX_COLD                      0x8105
 #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R       0x0039
 #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC  0x1039
 #define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT  0x2039
+#define USB_PID_AVERMEDIA_VOLAR_X                      0xa815
+#define USB_PID_AVERMEDIA_VOLAR_X_2                    0x8150
+#define USB_PID_AVERMEDIA_A309                         0xa309
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE             0x0058
 #define USB_PID_PINNACLE_PCTV2000E                     0x022c
 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH              0x0228
 #define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T     0x0229
+#define USB_PID_PINNACLE_PCTV71E                       0x022b
 #define USB_PID_PINNACLE_PCTV72E                       0x0236
 #define USB_PID_PINNACLE_PCTV73E                       0x0237
+#define USB_PID_PINNACLE_PCTV801E                      0x023a
+#define USB_PID_PINNACLE_PCTV801E_SE                   0x023b
 #define USB_PID_PCTV_200E                              0x020e
 #define USB_PID_PCTV_400E                              0x020f
 #define USB_PID_PCTV_450E                              0x0222
 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD             0xdb58
 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM             0xdb59
 #define USB_PID_DVICO_BLUEBIRD_DUAL_4                  0xdb78
+#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2            0xdb98
 #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2            0xdb70
 #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM   0xdb71
 #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD                0xdb54
 #define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2          0x6f01
+#define USB_PID_WINFAST_DTV_DONGLE_GOLD                        0x6029
 #define USB_PID_GENPIX_8PSK_REV_1_COLD                 0x0200
 #define USB_PID_GENPIX_8PSK_REV_1_WARM                 0x0201
 #define USB_PID_GENPIX_8PSK_REV_2                      0x0202
 #define USB_PID_GENPIX_SKYWALKER_CW3K                  0x0204
 #define USB_PID_SIGMATEK_DVB_110                       0x6610
 #define USB_PID_MSI_DIGI_VOX_MINI_II                   0x1513
+#define USB_PID_MSI_DIGIVOX_DUO                                0x8801
 #define USB_PID_OPERA1_COLD                            0x2830
 #define USB_PID_OPERA1_WARM                            0x3829
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD           0x0514
 #define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM           0x0513
 #define USB_PID_GIGABYTE_U7000                         0x7001
+#define USB_PID_GIGABYTE_U8000                         0x7002
 #define USB_PID_ASUS_U3000                             0x171f
+#define USB_PID_ASUS_U3000H                            0x1736
 #define USB_PID_ASUS_U3100                             0x173f
 #define USB_PID_YUAN_EC372S                            0x1edc
+#define USB_PID_YUAN_STK7700PH                         0x1f08
 #define USB_PID_DW2102                                 0x2102
+#define USB_PID_XTENSIONS_XD_380                       0x0381
+#define USB_PID_TELESTAR_STARSTICK_2                   0x8000
+#define USB_PID_MSI_DIGI_VOX_MINI_III                   0x8807
 
 #endif
index a4d898b44e55c40eb9cf5b7cccfdfe496cdcfa62..ca53df61caa8fbc9d7e3b84c2a27c2b1bace533e 100644 (file)
@@ -1,4 +1,5 @@
-/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card
+/* DVB USB framework compliant Linux driver for the
+*      DVBWorld DVB-S 2101, 2102, DVB-S2 2104 Card
 *
 * Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
 *
 */
 #include <linux/version.h>
 #include "dw2102.h"
+#include "si21xx.h"
 #include "stv0299.h"
 #include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "eds1547.h"
+#include "cx24116.h"
 
 #ifndef USB_PID_DW2102
 #define USB_PID_DW2102 0x2102
 #endif
 
-#define DW2102_READ_MSG 0
-#define DW2102_WRITE_MSG 1
+#ifndef USB_PID_DW2104
+#define USB_PID_DW2104 0x2104
+#endif
+
+#define DW210X_READ_MSG 0
+#define DW210X_WRITE_MSG 1
 
 #define REG_1F_SYMBOLRATE_BYTE0 0x1f
 #define REG_20_SYMBOLRATE_BYTE1 0x20
 #define REG_21_SYMBOLRATE_BYTE2 0x21
-
+/* on my own*/
 #define DW2102_VOLTAGE_CTRL (0x1800)
 #define DW2102_RC_QUERY (0x1a00)
 
-struct dw2102_state {
+struct dw210x_state {
        u32 last_key_pressed;
 };
-struct dw2102_rc_keys {
+struct dw210x_rc_keys {
        u32 keycode;
        u32 event;
 };
 
+/* debug */
+static int dvb_usb_dw2102_debug;
+module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
+
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value,
-               u8 *data, u16 len, int flags)
+static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
+                       u16 index, u8 * data, u16 len, int flags)
 {
        int ret;
        u8 u8buf[len];
 
-       unsigned int pipe = (flags == DW2102_READ_MSG) ?
-               usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
-       u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+       unsigned int pipe = (flags == DW210X_READ_MSG) ?
+                               usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
+       u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
 
-       if (flags == DW2102_WRITE_MSG)
+       if (flags == DW210X_WRITE_MSG)
                memcpy(u8buf, data, len);
-       ret = usb_control_msg(dev, pipe, request,
-               request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000);
+       ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
+                               value, index , u8buf, len, 2000);
 
-       if (flags == DW2102_READ_MSG)
+       if (flags == DW210X_READ_MSG)
                memcpy(data, u8buf, len);
        return ret;
 }
 
 /* I2C */
-
 static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                int num)
 {
 struct dvb_usb_device *d = i2c_get_adapdata(adap);
        int i = 0, ret = 0;
        u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
-       u8 request;
        u16 value;
 
        if (!d)
@@ -76,14 +89,12 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
        switch (num) {
        case 2:
                /* read stv0299 register */
-               request = 0xb5;
                value = msg[0].buf[0];/* register */
                for (i = 0; i < msg[1].len; i++) {
                        value = value + i;
-                       ret = dw2102_op_rw(d->udev, 0xb5,
-                               value, buf6, 2, DW2102_READ_MSG);
+                       ret = dw210x_op_rw(d->udev, 0xb5, value, 0,
+                                       buf6, 2, DW210X_READ_MSG);
                        msg[1].buf[i] = buf6[0];
-
                }
                break;
        case 1:
@@ -93,8 +104,8 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
                        buf6[0] = 0x2a;
                        buf6[1] = msg[0].buf[0];
                        buf6[2] = msg[0].buf[1];
-                       ret = dw2102_op_rw(d->udev, 0xb2,
-                               0, buf6, 3, DW2102_WRITE_MSG);
+                       ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                       buf6, 3, DW210X_WRITE_MSG);
                        break;
                case 0x60:
                        if (msg[0].flags == 0) {
@@ -106,26 +117,26 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
                                buf6[4] = msg[0].buf[1];
                                buf6[5] = msg[0].buf[2];
                                buf6[6] = msg[0].buf[3];
-                               ret = dw2102_op_rw(d->udev, 0xb2,
-                               0, buf6, 7, DW2102_WRITE_MSG);
+                               ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                               buf6, 7, DW210X_WRITE_MSG);
                        } else {
-                       /* write to tuner pll */
-                               ret = dw2102_op_rw(d->udev, 0xb5,
-                               0, buf6, 1, DW2102_READ_MSG);
+                       /* read from tuner */
+                               ret = dw210x_op_rw(d->udev, 0xb5, 0, 0,
+                                               buf6, 1, DW210X_READ_MSG);
                                msg[0].buf[0] = buf6[0];
                        }
                        break;
                case (DW2102_RC_QUERY):
-                       ret  = dw2102_op_rw(d->udev, 0xb8,
-                               0, buf6, 2, DW2102_READ_MSG);
+                       ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+                                       buf6, 2, DW210X_READ_MSG);
                        msg[0].buf[0] = buf6[0];
                        msg[0].buf[1] = buf6[1];
                        break;
                case (DW2102_VOLTAGE_CTRL):
                        buf6[0] = 0x30;
                        buf6[1] = msg[0].buf[0];
-                       ret = dw2102_op_rw(d->udev, 0xb2,
-                               0, buf6, 2, DW2102_WRITE_MSG);
+                       ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                       buf6, 2, DW210X_WRITE_MSG);
                        break;
                }
 
@@ -136,17 +147,265 @@ struct dvb_usb_device *d = i2c_get_adapdata(adap);
        return num;
 }
 
-static u32 dw2102_i2c_func(struct i2c_adapter *adapter)
+static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
+                                               struct i2c_msg msg[], int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int ret = 0;
+       u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
+
+       if (!d)
+               return -ENODEV;
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       switch (num) {
+       case 2:
+               /* read si2109 register by number */
+               buf6[0] = 0xd0;
+               buf6[1] = msg[0].len;
+               buf6[2] = msg[0].buf[0];
+               ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                               buf6, msg[0].len + 2, DW210X_WRITE_MSG);
+               /* read si2109 register */
+               ret = dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
+                               buf6, msg[1].len + 2, DW210X_READ_MSG);
+               memcpy(msg[1].buf, buf6 + 2, msg[1].len);
+
+               break;
+       case 1:
+               switch (msg[0].addr) {
+               case 0x68:
+                       /* write to si2109 register */
+                       buf6[0] = 0xd0;
+                       buf6[1] = msg[0].len;
+                       memcpy(buf6 + 2, msg[0].buf, msg[0].len);
+                       ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
+                                       msg[0].len + 2, DW210X_WRITE_MSG);
+                       break;
+               case(DW2102_RC_QUERY):
+                       ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+                                       buf6, 2, DW210X_READ_MSG);
+                       msg[0].buf[0] = buf6[0];
+                       msg[0].buf[1] = buf6[1];
+                       break;
+               case(DW2102_VOLTAGE_CTRL):
+                       buf6[0] = 0x30;
+                       buf6[1] = msg[0].buf[0];
+                       ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                       buf6, 2, DW210X_WRITE_MSG);
+                       break;
+               }
+               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return num;
+}
+static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int ret = 0;
+
+       if (!d)
+               return -ENODEV;
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       switch (num) {
+       case 2: {
+               /* read */
+               /* first write first register number */
+               u8 ibuf [msg[1].len + 2], obuf[3];
+               obuf[0] = 0xd0;
+               obuf[1] = msg[0].len;
+               obuf[2] = msg[0].buf[0];
+               ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                               obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+               /* second read registers */
+               ret = dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
+                               ibuf, msg[1].len + 2, DW210X_READ_MSG);
+               memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+               break;
+       }
+       case 1:
+               switch (msg[0].addr) {
+               case 0x68: {
+                       /* write to register */
+                       u8 obuf[msg[0].len + 2];
+                       obuf[0] = 0xd0;
+                       obuf[1] = msg[0].len;
+                       memcpy(obuf + 2, msg[0].buf, msg[0].len);
+                       ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                                       obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+                       break;
+               }
+               case 0x61: {
+                       /* write to tuner */
+                       u8 obuf[msg[0].len + 2];
+                       obuf[0] = 0xc2;
+                       obuf[1] = msg[0].len;
+                       memcpy(obuf + 2, msg[0].buf, msg[0].len);
+                       ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                                       obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+                       break;
+               }
+               case(DW2102_RC_QUERY): {
+                       u8 ibuf[2];
+                       ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+                                       ibuf, 2, DW210X_READ_MSG);
+                       memcpy(msg[0].buf, ibuf , 2);
+                       break;
+               }
+               case(DW2102_VOLTAGE_CTRL): {
+                       u8 obuf[2];
+                       obuf[0] = 0x30;
+                       obuf[1] = msg[0].buf[0];
+                       ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                       obuf, 2, DW210X_WRITE_MSG);
+                       break;
+               }
+               }
+
+               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return num;
+}
+
+static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int ret = 0;
+       int len, i;
+
+       if (!d)
+               return -ENODEV;
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       switch (num) {
+       case 2: {
+               /* read */
+               /* first write first register number */
+               u8 ibuf [msg[1].len + 2], obuf[3];
+               obuf[0] = 0xaa;
+               obuf[1] = msg[0].len;
+               obuf[2] = msg[0].buf[0];
+               ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                               obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+               /* second read registers */
+               ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0,
+                               ibuf, msg[1].len + 2, DW210X_READ_MSG);
+               memcpy(msg[1].buf, ibuf + 2, msg[1].len);
+
+               break;
+       }
+       case 1:
+               switch (msg[0].addr) {
+               case 0x55: {
+                       if (msg[0].buf[0] == 0xf7) {
+                               /* firmware */
+                               /* Write in small blocks */
+                               u8 obuf[19];
+                               obuf[0] = 0xaa;
+                               obuf[1] = 0x11;
+                               obuf[2] = 0xf7;
+                               len = msg[0].len - 1;
+                               i = 1;
+                               do {
+                                       memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
+                                       ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                                               obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG);
+                                       i += 16;
+                                       len -= 16;
+                               } while (len > 0);
+                       } else {
+                               /* write to register */
+                               u8 obuf[msg[0].len + 2];
+                               obuf[0] = 0xaa;
+                               obuf[1] = msg[0].len;
+                               memcpy(obuf + 2, msg[0].buf, msg[0].len);
+                               ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+                                               obuf, msg[0].len + 2, DW210X_WRITE_MSG);
+                       }
+                       break;
+               }
+               case(DW2102_RC_QUERY): {
+                       u8 ibuf[2];
+                       ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
+                                       ibuf, 2, DW210X_READ_MSG);
+                       memcpy(msg[0].buf, ibuf , 2);
+                       break;
+               }
+               case(DW2102_VOLTAGE_CTRL): {
+                       u8 obuf[2];
+                       obuf[0] = 0x30;
+                       obuf[1] = msg[0].buf[0];
+                       ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                       obuf, 2, DW210X_WRITE_MSG);
+                       break;
+               }
+               }
+
+               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return num;
+}
+
+static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C;
 }
 
 static struct i2c_algorithm dw2102_i2c_algo = {
        .master_xfer = dw2102_i2c_transfer,
-       .functionality = dw2102_i2c_func,
+       .functionality = dw210x_i2c_func,
+};
+
+static struct i2c_algorithm dw2102_serit_i2c_algo = {
+       .master_xfer = dw2102_serit_i2c_transfer,
+       .functionality = dw210x_i2c_func,
+};
+
+static struct i2c_algorithm dw2102_earda_i2c_algo = {
+       .master_xfer = dw2102_earda_i2c_transfer,
+       .functionality = dw210x_i2c_func,
+};
+
+static struct i2c_algorithm dw2104_i2c_algo = {
+       .master_xfer = dw2104_i2c_transfer,
+       .functionality = dw210x_i2c_func,
 };
 
-static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+       int i;
+       u8 ibuf[] = {0, 0};
+       u8 eeprom[256], eepromline[16];
+
+       for (i = 0; i < 256; i++) {
+               if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
+                       err("read eeprom failed.");
+                       return -1;
+               } else {
+                       eepromline[i%16] = ibuf[0];
+                       eeprom[i] = ibuf[0];
+               }
+               if ((i % 16) == 15) {
+                       deb_xfer("%02x: ", i - 15);
+                       debug_dump(eepromline, 16, deb_xfer);
+               }
+       }
+       memcpy(mac, eeprom + 8, 6);
+       return 0;
+};
+
+static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
        static u8 command_13v[1] = {0x00};
        static u8 command_18v[1] = {0x01};
@@ -163,18 +422,66 @@ static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
        return 0;
 }
 
-static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+static struct cx24116_config dw2104_config = {
+       .demod_address = 0x55,
+       .mpg_clk_pos_pol = 0x01,
+};
+
+static struct si21xx_config serit_sp1511lhb_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+
+};
+
+static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
 {
-       d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
-               &d->dev->i2c_adap);
-       if (d->fe != NULL) {
-               d->fe->ops.set_voltage = dw2102_set_voltage;
-               info("Attached stv0299!\n");
+       if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+                       &d->dev->i2c_adap)) != NULL) {
+               d->fe->ops.set_voltage = dw210x_set_voltage;
+               info("Attached cx24116!\n");
                return 0;
        }
        return -EIO;
 }
 
+static struct dvb_usb_device_properties dw2102_properties;
+
+static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+{
+       if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
+               /*dw2102_properties.adapter->tuner_attach = NULL;*/
+               d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
+                                       &d->dev->i2c_adap);
+               if (d->fe != NULL) {
+                       d->fe->ops.set_voltage = dw210x_set_voltage;
+                       info("Attached si21xx!\n");
+                       return 0;
+               }
+       }
+       if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
+               /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
+               d->fe = dvb_attach(stv0288_attach, &earda_config,
+                                       &d->dev->i2c_adap);
+               if (d->fe != NULL) {
+                       d->fe->ops.set_voltage = dw210x_set_voltage;
+                       info("Attached stv0288!\n");
+                       return 0;
+               }
+       }
+
+       if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
+               /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
+               d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+                                       &d->dev->i2c_adap);
+               if (d->fe != NULL) {
+                       d->fe->ops.set_voltage = dw210x_set_voltage;
+                       info("Attached stv0299!\n");
+                       return 0;
+               }
+       }
+       return -EIO;
+}
+
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
        dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -182,7 +489,15 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
-static struct dvb_usb_rc_key dw2102_rc_keys[] = {
+static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       dvb_attach(stb6000_attach, adap->fe, 0x61,
+               &adap->dev->i2c_adap);
+
+       return 0;
+}
+
+static struct dvb_usb_rc_key dw210x_rc_keys[] = {
        { 0xf8, 0x0a, KEY_Q },          /*power*/
        { 0xf8, 0x0c, KEY_M },          /*mute*/
        { 0xf8, 0x11, KEY_1 },
@@ -221,7 +536,7 @@ static struct dvb_usb_rc_key dw2102_rc_keys[] = {
 
 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       struct dw2102_state *st = d->priv;
+       struct dw210x_state *st = d->priv;
        u8 key[2];
        struct i2c_msg msg[] = {
                {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
@@ -231,12 +546,12 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 
        *state = REMOTE_NO_KEY_PRESSED;
        if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
-               for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) {
-                       if (dw2102_rc_keys[i].data == msg[0].buf[0]) {
+               for (i = 0; i < ARRAY_SIZE(dw210x_rc_keys); i++) {
+                       if (dw210x_rc_keys[i].data == msg[0].buf[0]) {
                                *state = REMOTE_KEY_PRESSED;
-                               *event = dw2102_rc_keys[i].event;
+                               *event = dw210x_rc_keys[i].event;
                                st->last_key_pressed =
-                                       dw2102_rc_keys[i].event;
+                                       dw210x_rc_keys[i].event;
                                break;
                        }
                st->last_key_pressed = 0;
@@ -249,6 +564,8 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 static struct usb_device_id dw2102_table[] = {
        {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
        {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+       {USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
+       {USB_DEVICE(0x9022, 0xd650)},
        { }
 };
 
@@ -260,7 +577,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
        u8 *b, *p;
        int ret = 0, i;
        u8 reset;
-       u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0};
+       u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
        const struct firmware *fw;
        const char *filename = "dvb-usb-dw2101.fw";
        switch (dev->descriptor.idProduct) {
@@ -273,25 +590,23 @@ static int dw2102_load_firmware(struct usb_device *dev,
                        return ret;
                }
                break;
-       case USB_PID_DW2102:
+       default:
                fw = frmwr;
                break;
        }
-       info("start downloading DW2102 firmware");
+       info("start downloading DW210X firmware");
        p = kmalloc(fw->size, GFP_KERNEL);
        reset = 1;
        /*stop the CPU*/
-       dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG);
-       dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG);
+       dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
+       dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
 
        if (p != NULL) {
                memcpy(p, fw->data, fw->size);
                for (i = 0; i < fw->size; i += 0x40) {
                        b = (u8 *) p + i;
-                       if (dw2102_op_rw
-                               (dev, 0xa0, i, b , 0x40,
-                                       DW2102_WRITE_MSG) != 0x40
-                               ) {
+                       if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
+                                       DW210X_WRITE_MSG) != 0x40) {
                                err("error while transferring firmware");
                                ret = -EINVAL;
                                break;
@@ -299,43 +614,66 @@ static int dw2102_load_firmware(struct usb_device *dev,
                }
                /* restart the CPU */
                reset = 0;
-               if (ret || dw2102_op_rw
-                       (dev, 0xa0, 0x7f92, &reset, 1,
-                       DW2102_WRITE_MSG) != 1) {
+               if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
+                                       DW210X_WRITE_MSG) != 1) {
                        err("could not restart the USB controller CPU.");
                        ret = -EINVAL;
                }
-               if (ret || dw2102_op_rw
-                       (dev, 0xa0, 0xe600, &reset, 1,
-                       DW2102_WRITE_MSG) != 1) {
+               if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
+                                       DW210X_WRITE_MSG) != 1) {
                        err("could not restart the USB controller CPU.");
                        ret = -EINVAL;
                }
                /* init registers */
                switch (dev->descriptor.idProduct) {
-               case USB_PID_DW2102:
-                       dw2102_op_rw
-                               (dev, 0xbf, 0x0040, &reset, 0,
-                               DW2102_WRITE_MSG);
-                       dw2102_op_rw
-                               (dev, 0xb9, 0x0000, &reset16[0], 2,
-                               DW2102_READ_MSG);
+               case USB_PID_DW2104:
+               case 0xd650:
+                       reset = 1;
+                       dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
+                                       DW210X_WRITE_MSG);
+                       reset = 0;
+                       dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
+                                       DW210X_WRITE_MSG);
                        break;
+               case USB_PID_DW2102:
+                       dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
+                                       DW210X_WRITE_MSG);
+                       dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
+                                       DW210X_READ_MSG);
+                       /* check STV0299 frontend  */
+                       dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
+                                       DW210X_READ_MSG);
+                       if (reset16[0] == 0xa1) {
+                               dw2102_properties.i2c_algo = &dw2102_i2c_algo;
+                               dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
+                               break;
+                       } else {
+                               /* check STV0288 frontend  */
+                               reset16[0] = 0xd0;
+                               reset16[1] = 1;
+                               reset16[2] = 0;
+                               dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
+                                               DW210X_WRITE_MSG);
+                               dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
+                                               DW210X_READ_MSG);
+                               if (reset16[2] == 0x11) {
+                                       dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
+                                       dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;
+                                       break;
+                               }
+                       }
                case 0x2101:
-                       dw2102_op_rw
-                               (dev, 0xbc, 0x0030, &reset16[0], 2,
-                               DW2102_READ_MSG);
-                       dw2102_op_rw
-                               (dev, 0xba, 0x0000, &reset16[0], 7,
-                               DW2102_READ_MSG);
-                       dw2102_op_rw
-                               (dev, 0xba, 0x0000, &reset16[0], 7,
-                               DW2102_READ_MSG);
-                       dw2102_op_rw
-                               (dev, 0xb9, 0x0000, &reset16[0], 2,
-                               DW2102_READ_MSG);
+                       dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
+                                       DW210X_READ_MSG);
+                       dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
+                                       DW210X_READ_MSG);
+                       dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
+                                       DW210X_READ_MSG);
+                       dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
+                                       DW210X_READ_MSG);
                        break;
                }
+               msleep(100);
                kfree(p);
        }
        return ret;
@@ -345,12 +683,12 @@ static struct dvb_usb_device_properties dw2102_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
        .firmware = "dvb-usb-dw2102.fw",
-       .size_of_priv = sizeof(struct dw2102_state),
+       .size_of_priv = sizeof(struct dw210x_state),
        .no_reconnect = 1,
 
-       .i2c_algo = &dw2102_i2c_algo,
-       .rc_key_map = dw2102_rc_keys,
-       .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys),
+       .i2c_algo = &dw2102_serit_i2c_algo,
+       .rc_key_map = dw210x_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
        .rc_interval = 150,
        .rc_query = dw2102_rc_query,
 
@@ -358,11 +696,12 @@ static struct dvb_usb_device_properties dw2102_properties = {
        /* parameter for the MPEG2-data transfer */
        .num_adapters = 1,
        .download_firmware = dw2102_load_firmware,
-       .adapter = {
+       .read_mac_address = dw210x_read_mac_address,
+               .adapter = {
                {
                        .frontend_attach = dw2102_frontend_attach,
                        .streaming_ctrl = NULL,
-                       .tuner_attach = dw2102_tuner_attach,
+                       .tuner_attach = NULL,
                        .stream = {
                                .type = USB_BULK,
                                .count = 8,
@@ -388,11 +727,64 @@ static struct dvb_usb_device_properties dw2102_properties = {
        }
 };
 
+static struct dvb_usb_device_properties dw2104_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .firmware = "dvb-usb-dw2104.fw",
+       .size_of_priv = sizeof(struct dw210x_state),
+       .no_reconnect = 1,
+
+       .i2c_algo = &dw2104_i2c_algo,
+       .rc_key_map = dw210x_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dw210x_rc_keys),
+       .rc_interval = 150,
+       .rc_query = dw2102_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x81,
+       /* parameter for the MPEG2-data transfer */
+       .num_adapters = 1,
+       .download_firmware = dw2102_load_firmware,
+       .read_mac_address = dw210x_read_mac_address,
+       .adapter = {
+               {
+                       .frontend_attach = dw2104_frontend_attach,
+                       .streaming_ctrl = NULL,
+                       /*.tuner_attach = dw2104_tuner_attach,*/
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 8,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
+               }
+       },
+       .num_device_descs = 2,
+       .devices = {
+               { "DVBWorld DW2104 USB2.0",
+                       {&dw2102_table[2], NULL},
+                       {NULL},
+               },
+               { "TeVii S650 USB2.0",
+                       {&dw2102_table[3], NULL},
+                       {NULL},
+               },
+       }
+};
+
 static int dw2102_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &dw2102_properties,
-               THIS_MODULE, NULL, adapter_nr);
+       if (0 == dvb_usb_device_init(intf, &dw2102_properties,
+                       THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &dw2104_properties,
+                       THIS_MODULE, NULL, adapter_nr)) {
+               return 0;
+       }
+       return -ENODEV;
 }
 
 static struct usb_driver dw2102_driver = {
@@ -420,6 +812,6 @@ module_init(dw2102_module_init);
 module_exit(dw2102_module_exit);
 
 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104 USB2.0 device");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
index 7a310f906837c9fdbe24ef822a9fea9f2fc51e2d..e3370734e95a2d625e736a8718de9d671ab759e1 100644 (file)
@@ -4,6 +4,5 @@
 #define DVB_USB_LOG_PREFIX "dw2102"
 #include "dvb-usb.h"
 
-extern int dvb_usb_dw2102_debug;
 #define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
 #endif
index 7dbb4a223c99829d0dbf88abf94d72ad5529ed6e..96b93e21a84bdbb6ddeb9ea2e3635b50ca0da149 100644 (file)
@@ -43,6 +43,20 @@ config DVB_S5H1420
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_STV0288
+       tristate "ST STV0288 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STB6000
+       tristate "ST STB6000 silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+         help
+         A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
 config DVB_STV0299
        tristate "ST STV0299 based"
        depends on DVB_CORE && I2C
@@ -92,6 +106,20 @@ config DVB_TUA6100
        help
          A DVB-S PLL chip.
 
+config DVB_CX24116
+       tristate "Conexant CX24116 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+
+config DVB_SI21XX
+       tristate "Silicon Labs SI21XX based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
 comment "DVB-T (terrestrial) frontends"
        depends on DVB_CORE
 
@@ -385,4 +413,23 @@ config DVB_ISL6421
        help
          An SEC control chip.
 
+config DVB_LGS8GL5
+       tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DMB-TH tuner module. Say Y when you want to support this frontend.
+
+comment "Tools to develop new frontends"
+
+config DVB_DUMMY_FE
+       tristate "Dummy frontend driver"
+       default n
+
+config DVB_AF9013
+       tristate "Afatech AF9013 demodulator"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         Say Y when you want to support this frontend.
 endmenu
index 028da55611c02cbad0c1b20404ad7326de2066e0..aba79f4a63a7217475079e694cb9fc4fbb052d34 100644 (file)
@@ -48,3 +48,10 @@ obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
 obj-$(CONFIG_DVB_AU8522) += au8522.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
 obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
+obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
+obj-$(CONFIG_DVB_AF9013) += af9013.o
+obj-$(CONFIG_DVB_CX24116) += cx24116.o
+obj-$(CONFIG_DVB_SI21XX) += si21xx.o
+obj-$(CONFIG_DVB_STV0288) += stv0288.o
+obj-$(CONFIG_DVB_STB6000) += stb6000.o
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
new file mode 100644 (file)
index 0000000..21c1060
--- /dev/null
@@ -0,0 +1,1685 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided 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 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/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "af9013_priv.h"
+#include "af9013.h"
+
+int af9013_debug;
+
+struct af9013_state {
+       struct i2c_adapter *i2c;
+       struct dvb_frontend frontend;
+
+       struct af9013_config config;
+
+       u16 signal_strength;
+       u32 ber;
+       u32 ucblocks;
+       u16 snr;
+       u32 frequency;
+       unsigned long next_statistics_check;
+};
+
+static u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+
+static int af9013_write_regs(struct af9013_state *state, u8 mbox, u16 reg,
+       u8 *val, u8 len)
+{
+       u8 buf[3+len];
+       struct i2c_msg msg = {
+               .addr = state->config.demod_address,
+               .flags = 0,
+               .len = sizeof(buf),
+               .buf = buf };
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xff;
+       buf[2] = mbox;
+       memcpy(&buf[3], val, len);
+
+       if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+               warn("I2C write failed reg:%04x len:%d", reg, len);
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int af9013_write_ofdm_regs(struct af9013_state *state, u16 reg, u8 *val,
+       u8 len)
+{
+       u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(0 << 6)|(0 << 7);
+       return af9013_write_regs(state, mbox, reg, val, len);
+}
+
+static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
+       u8 len)
+{
+       u8 mbox = (1 << 0)|(1 << 1)|((len - 1) << 2)|(1 << 6)|(1 << 7);
+       return af9013_write_regs(state, mbox, reg, val, len);
+}
+
+/* write single register */
+static int af9013_write_reg(struct af9013_state *state, u16 reg, u8 val)
+{
+       return af9013_write_ofdm_regs(state, reg, &val, 1);
+}
+
+/* read single register */
+static int af9013_read_reg(struct af9013_state *state, u16 reg, u8 *val)
+{
+       u8 obuf[3] = { reg >> 8, reg & 0xff, 0 };
+       u8 ibuf[1];
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = state->config.demod_address,
+                       .flags = 0,
+                       .len = sizeof(obuf),
+                       .buf = obuf
+               }, {
+                       .addr = state->config.demod_address,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(ibuf),
+                       .buf = ibuf
+               }
+       };
+
+       if (i2c_transfer(state->i2c, msg, 2) != 2) {
+               warn("I2C read failed reg:%04x", reg);
+               return -EREMOTEIO;
+       }
+       *val = ibuf[0];
+       return 0;
+}
+
+static int af9013_write_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
+       u8 len, u8 val)
+{
+       int ret;
+       u8 tmp, mask;
+
+       ret = af9013_read_reg(state, reg, &tmp);
+       if (ret)
+               return ret;
+
+       mask = regmask[len - 1] << pos;
+       tmp = (tmp & ~mask) | ((val << pos) & mask);
+
+       return af9013_write_reg(state, reg, tmp);
+}
+
+static int af9013_read_reg_bits(struct af9013_state *state, u16 reg, u8 pos,
+       u8 len, u8 *val)
+{
+       int ret;
+       u8 tmp;
+
+       ret = af9013_read_reg(state, reg, &tmp);
+       if (ret)
+               return ret;
+       *val = (tmp >> pos) & regmask[len - 1];
+       return 0;
+}
+
+static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
+{
+       int ret;
+       u8 pos;
+       u16 addr;
+       deb_info("%s: gpio:%d gpioval:%02x\n", __func__, gpio, gpioval);
+
+/* GPIO0 & GPIO1 0xd735
+   GPIO2 & GPIO3 0xd736 */
+
+       switch (gpio) {
+       case 0:
+       case 1:
+               addr = 0xd735;
+               break;
+       case 2:
+       case 3:
+               addr = 0xd736;
+               break;
+
+       default:
+               err("invalid gpio:%d\n", gpio);
+               ret = -EINVAL;
+               goto error;
+       };
+
+       switch (gpio) {
+       case 0:
+       case 2:
+               pos = 0;
+               break;
+       case 1:
+       case 3:
+       default:
+               pos = 4;
+               break;
+       };
+
+       ret = af9013_write_reg_bits(state, addr, pos, 4, gpioval);
+
+error:
+       return ret;
+}
+
+static u32 af913_div(u32 a, u32 b, u32 x)
+{
+       u32 r = 0, c = 0, i;
+       deb_info("%s: a:%d b:%d x:%d\n", __func__, a, b, x);
+
+       if (a > b) {
+               c = a / b;
+               a = a - c * b;
+       }
+
+       for (i = 0; i < x; i++) {
+               if (a >= b) {
+                       r += 1;
+                       a -= b;
+               }
+               a <<= 1;
+               r <<= 1;
+       }
+       r = (c << (u32)x) + r;
+
+       deb_info("%s: a:%d b:%d x:%d r:%d r:%x\n", __func__, a, b, x, r, r);
+       return r;
+}
+
+static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw)
+{
+       int ret = 0;
+       u8 i = 0;
+       u8 buf[24];
+       u32 ns_coeff1_2048nu;
+       u32 ns_coeff1_8191nu;
+       u32 ns_coeff1_8192nu;
+       u32 ns_coeff1_8193nu;
+       u32 ns_coeff2_2k;
+       u32 ns_coeff2_8k;
+
+       deb_info("%s: adc_clock:%d bw:%d\n", __func__,
+               state->config.adc_clock, bw);
+
+       switch (state->config.adc_clock) {
+       case 28800: /* 28.800 MHz */
+               switch (bw) {
+               case BANDWIDTH_6_MHZ:
+                       ns_coeff1_2048nu = 0x01e79e7a;
+                       ns_coeff1_8191nu = 0x0079eb6e;
+                       ns_coeff1_8192nu = 0x0079e79e;
+                       ns_coeff1_8193nu = 0x0079e3cf;
+                       ns_coeff2_2k     = 0x00f3cf3d;
+                       ns_coeff2_8k     = 0x003cf3cf;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       ns_coeff1_2048nu = 0x0238e38e;
+                       ns_coeff1_8191nu = 0x008e3d55;
+                       ns_coeff1_8192nu = 0x008e38e4;
+                       ns_coeff1_8193nu = 0x008e3472;
+                       ns_coeff2_2k     = 0x011c71c7;
+                       ns_coeff2_8k     = 0x00471c72;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       ns_coeff1_2048nu = 0x028a28a3;
+                       ns_coeff1_8191nu = 0x00a28f3d;
+                       ns_coeff1_8192nu = 0x00a28a29;
+                       ns_coeff1_8193nu = 0x00a28514;
+                       ns_coeff2_2k     = 0x01451451;
+                       ns_coeff2_8k     = 0x00514514;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case 20480: /* 20.480 MHz */
+               switch (bw) {
+               case BANDWIDTH_6_MHZ:
+                       ns_coeff1_2048nu = 0x02adb6dc;
+                       ns_coeff1_8191nu = 0x00ab7313;
+                       ns_coeff1_8192nu = 0x00ab6db7;
+                       ns_coeff1_8193nu = 0x00ab685c;
+                       ns_coeff2_2k     = 0x0156db6e;
+                       ns_coeff2_8k     = 0x0055b6dc;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       ns_coeff1_2048nu = 0x03200001;
+                       ns_coeff1_8191nu = 0x00c80640;
+                       ns_coeff1_8192nu = 0x00c80000;
+                       ns_coeff1_8193nu = 0x00c7f9c0;
+                       ns_coeff2_2k     = 0x01900000;
+                       ns_coeff2_8k     = 0x00640000;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       ns_coeff1_2048nu = 0x03924926;
+                       ns_coeff1_8191nu = 0x00e4996e;
+                       ns_coeff1_8192nu = 0x00e49249;
+                       ns_coeff1_8193nu = 0x00e48b25;
+                       ns_coeff2_2k     = 0x01c92493;
+                       ns_coeff2_8k     = 0x00724925;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case 28000: /* 28.000 MHz */
+               switch (bw) {
+               case BANDWIDTH_6_MHZ:
+                       ns_coeff1_2048nu = 0x01f58d10;
+                       ns_coeff1_8191nu = 0x007d672f;
+                       ns_coeff1_8192nu = 0x007d6344;
+                       ns_coeff1_8193nu = 0x007d5f59;
+                       ns_coeff2_2k     = 0x00fac688;
+                       ns_coeff2_8k     = 0x003eb1a2;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       ns_coeff1_2048nu = 0x02492492;
+                       ns_coeff1_8191nu = 0x00924db7;
+                       ns_coeff1_8192nu = 0x00924925;
+                       ns_coeff1_8193nu = 0x00924492;
+                       ns_coeff2_2k     = 0x01249249;
+                       ns_coeff2_8k     = 0x00492492;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       ns_coeff1_2048nu = 0x029cbc15;
+                       ns_coeff1_8191nu = 0x00a7343f;
+                       ns_coeff1_8192nu = 0x00a72f05;
+                       ns_coeff1_8193nu = 0x00a729cc;
+                       ns_coeff2_2k     = 0x014e5e0a;
+                       ns_coeff2_8k     = 0x00539783;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case 25000: /* 25.000 MHz */
+               switch (bw) {
+               case BANDWIDTH_6_MHZ:
+                       ns_coeff1_2048nu = 0x0231bcb5;
+                       ns_coeff1_8191nu = 0x008c7391;
+                       ns_coeff1_8192nu = 0x008c6f2d;
+                       ns_coeff1_8193nu = 0x008c6aca;
+                       ns_coeff2_2k     = 0x0118de5b;
+                       ns_coeff2_8k     = 0x00463797;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       ns_coeff1_2048nu = 0x028f5c29;
+                       ns_coeff1_8191nu = 0x00a3dc29;
+                       ns_coeff1_8192nu = 0x00a3d70a;
+                       ns_coeff1_8193nu = 0x00a3d1ec;
+                       ns_coeff2_2k     = 0x0147ae14;
+                       ns_coeff2_8k     = 0x0051eb85;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       ns_coeff1_2048nu = 0x02ecfb9d;
+                       ns_coeff1_8191nu = 0x00bb44c1;
+                       ns_coeff1_8192nu = 0x00bb3ee7;
+                       ns_coeff1_8193nu = 0x00bb390d;
+                       ns_coeff2_2k     = 0x01767dce;
+                       ns_coeff2_8k     = 0x005d9f74;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       default:
+               err("invalid xtal");
+               return -EINVAL;
+       }
+       if (ret) {
+               err("invalid bandwidth");
+               return ret;
+       }
+
+       buf[i++] = (u8) ((ns_coeff1_2048nu & 0x03000000) >> 24);
+       buf[i++] = (u8) ((ns_coeff1_2048nu & 0x00ff0000) >> 16);
+       buf[i++] = (u8) ((ns_coeff1_2048nu & 0x0000ff00) >> 8);
+       buf[i++] = (u8) ((ns_coeff1_2048nu & 0x000000ff));
+       buf[i++] = (u8) ((ns_coeff2_2k     & 0x01c00000) >> 22);
+       buf[i++] = (u8) ((ns_coeff2_2k     & 0x003fc000) >> 14);
+       buf[i++] = (u8) ((ns_coeff2_2k     & 0x00003fc0) >> 6);
+       buf[i++] = (u8) ((ns_coeff2_2k     & 0x0000003f));
+       buf[i++] = (u8) ((ns_coeff1_8191nu & 0x03000000) >> 24);
+       buf[i++] = (u8) ((ns_coeff1_8191nu & 0x00ffc000) >> 16);
+       buf[i++] = (u8) ((ns_coeff1_8191nu & 0x0000ff00) >> 8);
+       buf[i++] = (u8) ((ns_coeff1_8191nu & 0x000000ff));
+       buf[i++] = (u8) ((ns_coeff1_8192nu & 0x03000000) >> 24);
+       buf[i++] = (u8) ((ns_coeff1_8192nu & 0x00ffc000) >> 16);
+       buf[i++] = (u8) ((ns_coeff1_8192nu & 0x0000ff00) >> 8);
+       buf[i++] = (u8) ((ns_coeff1_8192nu & 0x000000ff));
+       buf[i++] = (u8) ((ns_coeff1_8193nu & 0x03000000) >> 24);
+       buf[i++] = (u8) ((ns_coeff1_8193nu & 0x00ffc000) >> 16);
+       buf[i++] = (u8) ((ns_coeff1_8193nu & 0x0000ff00) >> 8);
+       buf[i++] = (u8) ((ns_coeff1_8193nu & 0x000000ff));
+       buf[i++] = (u8) ((ns_coeff2_8k     & 0x01c00000) >> 22);
+       buf[i++] = (u8) ((ns_coeff2_8k     & 0x003fc000) >> 14);
+       buf[i++] = (u8) ((ns_coeff2_8k     & 0x00003fc0) >> 6);
+       buf[i++] = (u8) ((ns_coeff2_8k     & 0x0000003f));
+
+       deb_info("%s: coeff:", __func__);
+       debug_dump(buf, sizeof(buf), deb_info);
+
+       /* program */
+       for (i = 0; i < sizeof(buf); i++) {
+               ret = af9013_write_reg(state, 0xae00 + i, buf[i]);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+static int af9013_set_adc_ctrl(struct af9013_state *state)
+{
+       int ret;
+       u8 buf[3], tmp, i;
+       u32 adc_cw;
+
+       deb_info("%s: adc_clock:%d\n", __func__, state->config.adc_clock);
+
+       /* adc frequency type */
+       switch (state->config.adc_clock) {
+       case 28800: /* 28.800 MHz */
+               tmp = 0;
+               break;
+       case 20480: /* 20.480 MHz */
+               tmp = 1;
+               break;
+       case 28000: /* 28.000 MHz */
+               tmp = 2;
+               break;
+       case 25000: /* 25.000 MHz */
+               tmp = 3;
+               break;
+       default:
+               err("invalid xtal");
+               return -EINVAL;
+       }
+
+       adc_cw = af913_div(state->config.adc_clock*1000, 1000000ul, 19ul);
+
+       buf[0] = (u8) ((adc_cw & 0x000000ff));
+       buf[1] = (u8) ((adc_cw & 0x0000ff00) >> 8);
+       buf[2] = (u8) ((adc_cw & 0x00ff0000) >> 16);
+
+       deb_info("%s: adc_cw:", __func__);
+       debug_dump(buf, sizeof(buf), deb_info);
+
+       /* program */
+       for (i = 0; i < sizeof(buf); i++) {
+               ret = af9013_write_reg(state, 0xd180 + i, buf[i]);
+               if (ret)
+                       goto error;
+       }
+       ret = af9013_write_reg_bits(state, 0x9bd2, 0, 4, tmp);
+error:
+       return ret;
+}
+
+static int af9013_set_freq_ctrl(struct af9013_state *state, fe_bandwidth_t bw)
+{
+       int ret;
+       u16 addr;
+       u8 buf[3], i, j;
+       u32 adc_freq, freq_cw;
+       s8 bfs_spec_inv;
+       int if_sample_freq;
+
+       for (j = 0; j < 3; j++) {
+               if (j == 0) {
+                       addr = 0xd140; /* fcw normal */
+                       bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
+               } else if (j == 1) {
+                       addr = 0x9be7; /* fcw dummy ram */
+                       bfs_spec_inv = state->config.rf_spec_inv ? -1 : 1;
+               } else {
+                       addr = 0x9bea; /* fcw inverted */
+                       bfs_spec_inv = state->config.rf_spec_inv ? 1 : -1;
+               }
+
+               adc_freq       = state->config.adc_clock * 1000;
+               if_sample_freq = state->config.tuner_if * 1000;
+
+               /* TDA18271 uses different sampling freq for every bw */
+               if (state->config.tuner == AF9013_TUNER_TDA18271) {
+                       switch (bw) {
+                       case BANDWIDTH_6_MHZ:
+                               if_sample_freq = 3300000; /* 3.3 MHz */
+                               break;
+                       case BANDWIDTH_7_MHZ:
+                               if_sample_freq = 3800000; /* 3.8 MHz */
+                               break;
+                       case BANDWIDTH_8_MHZ:
+                       default:
+                               if_sample_freq = 4300000; /* 4.3 MHz */
+                               break;
+                       }
+               }
+
+               while (if_sample_freq > (adc_freq / 2))
+                       if_sample_freq = if_sample_freq - adc_freq;
+
+               if (if_sample_freq >= 0)
+                       bfs_spec_inv = bfs_spec_inv * (-1);
+               else
+                       if_sample_freq = if_sample_freq * (-1);
+
+               freq_cw = af913_div(if_sample_freq, adc_freq, 23ul);
+
+               if (bfs_spec_inv == -1)
+                       freq_cw = 0x00800000 - freq_cw;
+
+               buf[0] = (u8) ((freq_cw & 0x000000ff));
+               buf[1] = (u8) ((freq_cw & 0x0000ff00) >> 8);
+               buf[2] = (u8) ((freq_cw & 0x007f0000) >> 16);
+
+
+               deb_info("%s: freq_cw:", __func__);
+               debug_dump(buf, sizeof(buf), deb_info);
+
+               /* program */
+               for (i = 0; i < sizeof(buf); i++) {
+                       ret = af9013_write_reg(state, addr++, buf[i]);
+                       if (ret)
+                               goto error;
+               }
+       }
+error:
+       return ret;
+}
+
+static int af9013_set_ofdm_params(struct af9013_state *state,
+       struct dvb_ofdm_parameters *params, u8 *auto_mode)
+{
+       int ret;
+       u8 i, buf[3] = {0, 0, 0};
+       *auto_mode = 0; /* set if parameters are requested to auto set */
+
+       switch (params->transmission_mode) {
+       case TRANSMISSION_MODE_AUTO:
+               *auto_mode = 1;
+       case TRANSMISSION_MODE_2K:
+               break;
+       case TRANSMISSION_MODE_8K:
+               buf[0] |= (1 << 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (params->guard_interval) {
+       case GUARD_INTERVAL_AUTO:
+               *auto_mode = 1;
+       case GUARD_INTERVAL_1_32:
+               break;
+       case GUARD_INTERVAL_1_16:
+               buf[0] |= (1 << 2);
+               break;
+       case GUARD_INTERVAL_1_8:
+               buf[0] |= (2 << 2);
+               break;
+       case GUARD_INTERVAL_1_4:
+               buf[0] |= (3 << 2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (params->hierarchy_information) {
+       case HIERARCHY_AUTO:
+               *auto_mode = 1;
+       case HIERARCHY_NONE:
+               break;
+       case HIERARCHY_1:
+               buf[0] |= (1 << 4);
+               break;
+       case HIERARCHY_2:
+               buf[0] |= (2 << 4);
+               break;
+       case HIERARCHY_4:
+               buf[0] |= (3 << 4);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       switch (params->constellation) {
+       case QAM_AUTO:
+               *auto_mode = 1;
+       case QPSK:
+               break;
+       case QAM_16:
+               buf[1] |= (1 << 6);
+               break;
+       case QAM_64:
+               buf[1] |= (2 << 6);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Use HP. How and which case we can switch to LP? */
+       buf[1] |= (1 << 4);
+
+       switch (params->code_rate_HP) {
+       case FEC_AUTO:
+               *auto_mode = 1;
+       case FEC_1_2:
+               break;
+       case FEC_2_3:
+               buf[2] |= (1 << 0);
+               break;
+       case FEC_3_4:
+               buf[2] |= (2 << 0);
+               break;
+       case FEC_5_6:
+               buf[2] |= (3 << 0);
+               break;
+       case FEC_7_8:
+               buf[2] |= (4 << 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (params->code_rate_LP) {
+       case FEC_AUTO:
+       /* if HIERARCHY_NONE and FEC_NONE then LP FEC is set to FEC_AUTO
+          by dvb_frontend.c for compatibility */
+               if (params->hierarchy_information != HIERARCHY_NONE)
+                       *auto_mode = 1;
+       case FEC_1_2:
+               break;
+       case FEC_2_3:
+               buf[2] |= (1 << 3);
+               break;
+       case FEC_3_4:
+               buf[2] |= (2 << 3);
+               break;
+       case FEC_5_6:
+               buf[2] |= (3 << 3);
+               break;
+       case FEC_7_8:
+               buf[2] |= (4 << 3);
+               break;
+       case FEC_NONE:
+               if (params->hierarchy_information == HIERARCHY_AUTO)
+                       break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (params->bandwidth) {
+       case BANDWIDTH_6_MHZ:
+               break;
+       case BANDWIDTH_7_MHZ:
+               buf[1] |= (1 << 2);
+               break;
+       case BANDWIDTH_8_MHZ:
+               buf[1] |= (2 << 2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* program */
+       for (i = 0; i < sizeof(buf); i++) {
+               ret = af9013_write_reg(state, 0xd3c0 + i, buf[i]);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+static int af9013_reset(struct af9013_state *state, u8 sleep)
+{
+       int ret;
+       u8 tmp, i;
+       deb_info("%s\n", __func__);
+
+       /* enable OFDM reset */
+       ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 1);
+       if (ret)
+               goto error;
+
+       /* start reset mechanism */
+       ret = af9013_write_reg(state, 0xaeff, 1);
+       if (ret)
+               goto error;
+
+       /* reset is done when bit 1 is set */
+       for (i = 0; i < 150; i++) {
+               ret = af9013_read_reg_bits(state, 0xd417, 1, 1, &tmp);
+               if (ret)
+                       goto error;
+               if (tmp)
+                       break; /* reset done */
+               msleep(10);
+       }
+       if (!tmp)
+               return -ETIMEDOUT;
+
+       /* don't clear reset when going to sleep */
+       if (!sleep) {
+               /* clear OFDM reset */
+               ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+               if (ret)
+                       goto error;
+
+               /* disable OFDM reset */
+               ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+       }
+error:
+       return ret;
+}
+
+static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
+{
+       int ret;
+       deb_info("%s: onoff:%d\n", __func__, onoff);
+
+       if (onoff) {
+               /* power on */
+               ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 0);
+               if (ret)
+                       goto error;
+               ret = af9013_write_reg_bits(state, 0xd417, 1, 1, 0);
+               if (ret)
+                       goto error;
+               ret = af9013_write_reg_bits(state, 0xd417, 4, 1, 0);
+       } else {
+               /* power off */
+               ret = af9013_reset(state, 1);
+               if (ret)
+                       goto error;
+               ret = af9013_write_reg_bits(state, 0xd73a, 3, 1, 1);
+       }
+error:
+       return ret;
+}
+
+static int af9013_lock_led(struct af9013_state *state, u8 onoff)
+{
+       deb_info("%s: onoff:%d\n", __func__, onoff);
+
+       return af9013_write_reg_bits(state, 0xd730, 0, 1, onoff);
+}
+
+static int af9013_set_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *params)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 auto_mode; /* auto set TPS */
+
+       deb_info("%s: freq:%d bw:%d\n", __func__, params->frequency,
+               params->u.ofdm.bandwidth);
+
+       state->frequency = params->frequency;
+
+       /* program CFOE coefficients */
+       ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
+       if (ret)
+               goto error;
+
+       /* program frequency control */
+       ret = af9013_set_freq_ctrl(state, params->u.ofdm.bandwidth);
+       if (ret)
+               goto error;
+
+       /* clear TPS lock flag (inverted flag) */
+       ret = af9013_write_reg_bits(state, 0xd330, 3, 1, 1);
+       if (ret)
+               goto error;
+
+       /* clear MPEG2 lock flag */
+       ret = af9013_write_reg_bits(state, 0xd507, 6, 1, 0);
+       if (ret)
+               goto error;
+
+       /* empty channel function */
+       ret = af9013_write_reg_bits(state, 0x9bfe, 0, 1, 0);
+       if (ret)
+               goto error;
+
+       /* empty DVB-T channel function */
+       ret = af9013_write_reg_bits(state, 0x9bc2, 0, 1, 0);
+       if (ret)
+               goto error;
+
+       /* program tuner */
+       if (fe->ops.tuner_ops.set_params)
+               fe->ops.tuner_ops.set_params(fe, params);
+
+       /* program TPS and bandwidth, check if auto mode needed */
+       ret = af9013_set_ofdm_params(state, &params->u.ofdm, &auto_mode);
+       if (ret)
+               goto error;
+
+       if (auto_mode) {
+               /* clear easy mode flag */
+               ret = af9013_write_reg(state, 0xaefd, 0);
+               deb_info("%s: auto TPS\n", __func__);
+       } else {
+               /* set easy mode flag */
+               ret = af9013_write_reg(state, 0xaefd, 1);
+               if (ret)
+                       goto error;
+               ret = af9013_write_reg(state, 0xaefe, 0);
+               deb_info("%s: manual TPS\n", __func__);
+       }
+       if (ret)
+               goto error;
+
+       /* everything is set, lets try to receive channel - OFSM GO! */
+       ret = af9013_write_reg(state, 0xffff, 0);
+       if (ret)
+               goto error;
+
+error:
+       return ret;
+}
+
+static int af9013_get_frontend(struct dvb_frontend *fe,
+       struct dvb_frontend_parameters *p)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 i, buf[3];
+       deb_info("%s\n", __func__);
+
+       /* read TPS registers */
+       for (i = 0; i < 3; i++) {
+               ret = af9013_read_reg(state, 0xd3c0 + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+
+       switch ((buf[1] >> 6) & 3) {
+       case 0:
+               p->u.ofdm.constellation = QPSK;
+               break;
+       case 1:
+               p->u.ofdm.constellation = QAM_16;
+               break;
+       case 2:
+               p->u.ofdm.constellation = QAM_64;
+               break;
+       }
+
+       switch ((buf[0] >> 0) & 3) {
+       case 0:
+               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+               break;
+       case 1:
+               p->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+       }
+
+       switch ((buf[0] >> 2) & 3) {
+       case 0:
+               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+               break;
+       case 1:
+               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+               break;
+       case 2:
+               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+               break;
+       case 3:
+               p->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+               break;
+       }
+
+       switch ((buf[0] >> 4) & 7) {
+       case 0:
+               p->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+               break;
+       case 1:
+               p->u.ofdm.hierarchy_information = HIERARCHY_1;
+               break;
+       case 2:
+               p->u.ofdm.hierarchy_information = HIERARCHY_2;
+               break;
+       case 3:
+               p->u.ofdm.hierarchy_information = HIERARCHY_4;
+               break;
+       }
+
+       switch ((buf[2] >> 0) & 7) {
+       case 0:
+               p->u.ofdm.code_rate_HP = FEC_1_2;
+               break;
+       case 1:
+               p->u.ofdm.code_rate_HP = FEC_2_3;
+               break;
+       case 2:
+               p->u.ofdm.code_rate_HP = FEC_3_4;
+               break;
+       case 3:
+               p->u.ofdm.code_rate_HP = FEC_5_6;
+               break;
+       case 4:
+               p->u.ofdm.code_rate_HP = FEC_7_8;
+               break;
+       }
+
+       switch ((buf[2] >> 3) & 7) {
+       case 0:
+               p->u.ofdm.code_rate_LP = FEC_1_2;
+               break;
+       case 1:
+               p->u.ofdm.code_rate_LP = FEC_2_3;
+               break;
+       case 2:
+               p->u.ofdm.code_rate_LP = FEC_3_4;
+               break;
+       case 3:
+               p->u.ofdm.code_rate_LP = FEC_5_6;
+               break;
+       case 4:
+               p->u.ofdm.code_rate_LP = FEC_7_8;
+               break;
+       }
+
+       switch ((buf[1] >> 2) & 3) {
+       case 0:
+               p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+               break;
+       case 1:
+               p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+               break;
+       case 2:
+               p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+               break;
+       }
+
+       p->inversion = INVERSION_AUTO;
+       p->frequency = state->frequency;
+
+error:
+       return ret;
+}
+
+static int af9013_update_ber_unc(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 buf[3], i;
+       u32 error_bit_count = 0;
+       u32 total_bit_count = 0;
+       u32 abort_packet_count = 0;
+
+       state->ber = 0;
+
+       /* check if error bit count is ready */
+       ret = af9013_read_reg_bits(state, 0xd391, 4, 1, &buf[0]);
+       if (ret)
+               goto error;
+       if (!buf[0])
+               goto exit;
+
+       /* get RSD packet abort count */
+       for (i = 0; i < 2; i++) {
+               ret = af9013_read_reg(state, 0xd38a + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+       abort_packet_count = (buf[1] << 8) + buf[0];
+
+       /* get error bit count */
+       for (i = 0; i < 3; i++) {
+               ret = af9013_read_reg(state, 0xd387 + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+       error_bit_count = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+       error_bit_count = error_bit_count - abort_packet_count * 8 * 8;
+
+       /* get used RSD counting period (10000 RSD packets used) */
+       for (i = 0; i < 2; i++) {
+               ret = af9013_read_reg(state, 0xd385 + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+       total_bit_count = (buf[1] << 8) + buf[0];
+       total_bit_count = total_bit_count - abort_packet_count;
+       total_bit_count = total_bit_count * 204 * 8;
+
+       if (total_bit_count)
+               state->ber = error_bit_count * 1000000000 / total_bit_count;
+
+       state->ucblocks += abort_packet_count;
+
+       deb_info("%s: err bits:%d total bits:%d abort count:%d\n", __func__,
+               error_bit_count, total_bit_count, abort_packet_count);
+
+       /* set BER counting range */
+       ret = af9013_write_reg(state, 0xd385, 10000 & 0xff);
+       if (ret)
+               goto error;
+       ret = af9013_write_reg(state, 0xd386, 10000 >> 8);
+       if (ret)
+               goto error;
+       /* reset and start BER counter */
+       ret = af9013_write_reg_bits(state, 0xd391, 4, 1, 1);
+       if (ret)
+               goto error;
+
+exit:
+error:
+       return ret;
+}
+
+static int af9013_update_snr(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 buf[3], i, len;
+       u32 quant = 0;
+       struct snr_table *snr_table;
+
+       /* check if quantizer ready (for snr) */
+       ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]);
+       if (ret)
+               goto error;
+       if (buf[0]) {
+               /* quantizer ready - read it */
+               for (i = 0; i < 3; i++) {
+                       ret = af9013_read_reg(state, 0xd2e3 + i, &buf[i]);
+                       if (ret)
+                               goto error;
+               }
+               quant = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+               /* read current constellation */
+               ret = af9013_read_reg(state, 0xd3c1, &buf[0]);
+               if (ret)
+                       goto error;
+
+               switch ((buf[0] >> 6) & 3) {
+               case 0:
+                       len = ARRAY_SIZE(qpsk_snr_table);
+                       snr_table = qpsk_snr_table;
+                       break;
+               case 1:
+                       len = ARRAY_SIZE(qam16_snr_table);
+                       snr_table = qam16_snr_table;
+                       break;
+               case 2:
+                       len = ARRAY_SIZE(qam64_snr_table);
+                       snr_table = qam64_snr_table;
+                       break;
+               default:
+                       len = 0;
+                       break;
+               }
+
+               if (len) {
+                       for (i = 0; i < len; i++) {
+                               if (quant < snr_table[i].val) {
+                                       state->snr = snr_table[i].snr * 10;
+                                       break;
+                               }
+                       }
+               }
+
+               /* set quantizer super frame count */
+               ret = af9013_write_reg(state, 0xd2e2, 1);
+               if (ret)
+                       goto error;
+
+               /* check quantizer availability */
+               for (i = 0; i < 10; i++) {
+                       msleep(10);
+                       ret = af9013_read_reg_bits(state, 0xd2e6, 0, 1,
+                               &buf[0]);
+                       if (ret)
+                               goto error;
+                       if (!buf[0])
+                               break;
+               }
+
+               /* reset quantizer */
+               ret = af9013_write_reg_bits(state, 0xd2e1, 3, 1, 1);
+               if (ret)
+                       goto error;
+       }
+
+error:
+       return ret;
+}
+
+static int af9013_update_signal_strength(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       u8 tmp0;
+       u8 rf_gain, rf_50, rf_80, if_gain, if_50, if_80;
+       int signal_strength;
+
+       deb_info("%s\n", __func__);
+
+       state->signal_strength = 0;
+
+       ret = af9013_read_reg_bits(state, 0x9bee, 0, 1, &tmp0);
+       if (ret)
+               goto error;
+       if (tmp0) {
+               ret = af9013_read_reg(state, 0x9bbd, &rf_50);
+               if (ret)
+                       goto error;
+               ret = af9013_read_reg(state, 0x9bd0, &rf_80);
+               if (ret)
+                       goto error;
+               ret = af9013_read_reg(state, 0x9be2, &if_50);
+               if (ret)
+                       goto error;
+               ret = af9013_read_reg(state, 0x9be4, &if_80);
+               if (ret)
+                       goto error;
+               ret = af9013_read_reg(state, 0xd07c, &rf_gain);
+               if (ret)
+                       goto error;
+               ret = af9013_read_reg(state, 0xd07d, &if_gain);
+               if (ret)
+                       goto error;
+               signal_strength = (0xffff / (9 * (rf_50 + if_50) - \
+                       11 * (rf_80 + if_80))) * (10 * (rf_gain + if_gain) - \
+                       11 * (rf_80 + if_80));
+               if (signal_strength < 0)
+                       signal_strength = 0;
+               else if (signal_strength > 0xffff)
+                       signal_strength = 0xffff;
+
+               state->signal_strength = signal_strength;
+       }
+
+error:
+       return ret;
+}
+
+static int af9013_update_statistics(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+
+       if (time_before(jiffies, state->next_statistics_check))
+               return 0;
+
+       /* set minimum statistic update interval */
+       state->next_statistics_check = jiffies + msecs_to_jiffies(1200);
+
+       ret = af9013_update_signal_strength(fe);
+       if (ret)
+               goto error;
+       ret = af9013_update_snr(fe);
+       if (ret)
+               goto error;
+       ret = af9013_update_ber_unc(fe);
+       if (ret)
+               goto error;
+
+error:
+       return ret;
+}
+
+static int af9013_get_tune_settings(struct dvb_frontend *fe,
+       struct dvb_frontend_tune_settings *fesettings)
+{
+       fesettings->min_delay_ms = 800;
+       fesettings->step_size = 0;
+       fesettings->max_drift = 0;
+
+       return 0;
+}
+
+static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret = 0;
+       u8 tmp;
+       *status = 0;
+
+       /* TPS lock */
+       ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
+       if (ret)
+               goto error;
+       if (tmp)
+               *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+       /* MPEG2 lock */
+       ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
+       if (ret)
+               goto error;
+       if (tmp)
+               *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+       if (!*status & FE_HAS_SIGNAL) {
+               /* AGC lock */
+               ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
+               if (ret)
+                       goto error;
+               if (tmp)
+                       *status |= FE_HAS_SIGNAL;
+       }
+
+       if (!*status & FE_HAS_CARRIER) {
+               /* CFO lock */
+               ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
+               if (ret)
+                       goto error;
+               if (tmp)
+                       *status |= FE_HAS_CARRIER;
+       }
+
+       if (!*status & FE_HAS_CARRIER) {
+               /* SFOE lock */
+               ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
+               if (ret)
+                       goto error;
+               if (tmp)
+                       *status |= FE_HAS_CARRIER;
+       }
+
+       ret = af9013_update_statistics(fe);
+
+error:
+       return ret;
+}
+
+
+static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       ret = af9013_update_statistics(fe);
+       *ber = state->ber;
+       return ret;
+}
+
+static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       ret = af9013_update_statistics(fe);
+       *strength = state->signal_strength;
+       return ret;
+}
+
+static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       ret = af9013_update_statistics(fe);
+       *snr = state->snr;
+       return ret;
+}
+
+static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       ret = af9013_update_statistics(fe);
+       *ucblocks = state->ucblocks;
+       return ret;
+}
+
+static int af9013_sleep(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret;
+       deb_info("%s\n", __func__);
+
+       ret = af9013_lock_led(state, 0);
+       if (ret)
+               goto error;
+
+       ret = af9013_power_ctrl(state, 0);
+error:
+       return ret;
+}
+
+static int af9013_init(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       int ret, i, len;
+       u8 tmp0, tmp1;
+       struct regdesc *init;
+       deb_info("%s\n", __func__);
+
+       /* reset OFDM */
+       ret = af9013_reset(state, 0);
+       if (ret)
+               goto error;
+
+       /* power on */
+       ret = af9013_power_ctrl(state, 1);
+       if (ret)
+               goto error;
+
+       /* enable ADC */
+       ret = af9013_write_reg(state, 0xd73a, 0xa4);
+       if (ret)
+               goto error;
+
+       /* write API version to firmware */
+       for (i = 0; i < sizeof(state->config.api_version); i++) {
+               ret = af9013_write_reg(state, 0x9bf2 + i,
+                       state->config.api_version[i]);
+               if (ret)
+                       goto error;
+       }
+
+       /* program ADC control */
+       ret = af9013_set_adc_ctrl(state);
+       if (ret)
+               goto error;
+
+       /* set I2C master clock */
+       ret = af9013_write_reg(state, 0xd416, 0x14);
+       if (ret)
+               goto error;
+
+       /* set 16 embx */
+       ret = af9013_write_reg_bits(state, 0xd700, 1, 1, 1);
+       if (ret)
+               goto error;
+
+       /* set no trigger */
+       ret = af9013_write_reg_bits(state, 0xd700, 2, 1, 0);
+       if (ret)
+               goto error;
+
+       /* set read-update bit for constellation */
+       ret = af9013_write_reg_bits(state, 0xd371, 1, 1, 1);
+       if (ret)
+               goto error;
+
+       /* enable FEC monitor */
+       ret = af9013_write_reg_bits(state, 0xd392, 1, 1, 1);
+       if (ret)
+               goto error;
+
+       /* load OFSM settings */
+       deb_info("%s: load ofsm settings\n", __func__);
+       len = ARRAY_SIZE(ofsm_init);
+       init = ofsm_init;
+       for (i = 0; i < len; i++) {
+               ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+                       init[i].len, init[i].val);
+               if (ret)
+                       goto error;
+       }
+
+       /* load tuner specific settings */
+       deb_info("%s: load tuner specific settings\n", __func__);
+       switch (state->config.tuner) {
+       case AF9013_TUNER_MXL5003D:
+               len = ARRAY_SIZE(tuner_init_mxl5003d);
+               init = tuner_init_mxl5003d;
+               break;
+       case AF9013_TUNER_MXL5005D:
+       case AF9013_TUNER_MXL5005R:
+               len = ARRAY_SIZE(tuner_init_mxl5005);
+               init = tuner_init_mxl5005;
+               break;
+       case AF9013_TUNER_ENV77H11D5:
+               len = ARRAY_SIZE(tuner_init_env77h11d5);
+               init = tuner_init_env77h11d5;
+               break;
+       case AF9013_TUNER_MT2060:
+               len = ARRAY_SIZE(tuner_init_mt2060);
+               init = tuner_init_mt2060;
+               break;
+       case AF9013_TUNER_MC44S803:
+               len = ARRAY_SIZE(tuner_init_mc44s803);
+               init = tuner_init_mc44s803;
+               break;
+       case AF9013_TUNER_QT1010:
+       case AF9013_TUNER_QT1010A:
+               len = ARRAY_SIZE(tuner_init_qt1010);
+               init = tuner_init_qt1010;
+               break;
+       case AF9013_TUNER_MT2060_2:
+               len = ARRAY_SIZE(tuner_init_mt2060_2);
+               init = tuner_init_mt2060_2;
+               break;
+       case AF9013_TUNER_TDA18271:
+               len = ARRAY_SIZE(tuner_init_tda18271);
+               init = tuner_init_tda18271;
+               break;
+       case AF9013_TUNER_UNKNOWN:
+       default:
+               len = ARRAY_SIZE(tuner_init_unknown);
+               init = tuner_init_unknown;
+               break;
+       }
+
+       for (i = 0; i < len; i++) {
+               ret = af9013_write_reg_bits(state, init[i].addr, init[i].pos,
+                       init[i].len, init[i].val);
+               if (ret)
+                       goto error;
+       }
+
+       /* set TS mode */
+       deb_info("%s: setting ts mode\n", __func__);
+       tmp0 = 0; /* parallel mode */
+       tmp1 = 0; /* serial mode */
+       switch (state->config.output_mode) {
+       case AF9013_OUTPUT_MODE_PARALLEL:
+               tmp0 = 1;
+               break;
+       case AF9013_OUTPUT_MODE_SERIAL:
+               tmp1 = 1;
+               break;
+       case AF9013_OUTPUT_MODE_USB:
+               /* usb mode for AF9015 */
+       default:
+               break;
+       }
+       ret = af9013_write_reg_bits(state, 0xd500, 1, 1, tmp0); /* parallel */
+       if (ret)
+               goto error;
+       ret = af9013_write_reg_bits(state, 0xd500, 2, 1, tmp1); /* serial */
+       if (ret)
+               goto error;
+
+       /* enable lock led */
+       ret = af9013_lock_led(state, 1);
+       if (ret)
+               goto error;
+
+error:
+       return ret;
+}
+
+static struct dvb_frontend_ops af9013_ops;
+
+static int af9013_download_firmware(struct af9013_state *state)
+{
+       int i, len, packets, remainder, ret;
+       const struct firmware *fw;
+       u16 addr = 0x5100; /* firmware start address */
+       u16 checksum = 0;
+       u8 val;
+       u8 fw_params[4];
+       u8 *data;
+       u8 *fw_file = AF9013_DEFAULT_FIRMWARE;
+
+       msleep(100);
+       /* check whether firmware is already running */
+       ret = af9013_read_reg(state, 0x98be, &val);
+       if (ret)
+               goto error;
+       else
+               deb_info("%s: firmware status:%02x\n", __func__, val);
+
+       if (val == 0x0c) /* fw is running, no need for download */
+               goto exit;
+
+       info("found a '%s' in cold state, will try to load a firmware",
+               af9013_ops.info.name);
+
+       /* request the firmware, this will block and timeout */
+       ret = request_firmware(&fw, fw_file,  &state->i2c->dev);
+       if (ret) {
+               err("did not find the firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details" \
+                       " on firmware-problems. (%d)",
+                       fw_file, ret);
+               goto error;
+       }
+
+       info("downloading firmware from file '%s'", fw_file);
+
+       /* calc checksum */
+       for (i = 0; i < fw->size; i++)
+               checksum += fw->data[i];
+
+       fw_params[0] = checksum >> 8;
+       fw_params[1] = checksum & 0xff;
+       fw_params[2] = fw->size >> 8;
+       fw_params[3] = fw->size & 0xff;
+
+       /* write fw checksum & size */
+       ret = af9013_write_ofsm_regs(state, 0x50fc,
+               fw_params, sizeof(fw_params));
+       if (ret)
+               goto error_release;
+
+       #define FW_PACKET_MAX_DATA  16
+
+       packets = fw->size / FW_PACKET_MAX_DATA;
+       remainder = fw->size % FW_PACKET_MAX_DATA;
+       len = FW_PACKET_MAX_DATA;
+       for (i = 0; i <= packets; i++) {
+               if (i == packets)  /* set size of the last packet */
+                       len = remainder;
+
+               data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
+               ret = af9013_write_ofsm_regs(state, addr, data, len);
+               addr += FW_PACKET_MAX_DATA;
+
+               if (ret) {
+                       err("firmware download failed at %d with %d", i, ret);
+                       goto error_release;
+               }
+       }
+
+       /* request boot firmware */
+       ret = af9013_write_reg(state, 0xe205, 1);
+       if (ret)
+               goto error_release;
+
+       for (i = 0; i < 15; i++) {
+               msleep(100);
+
+               /* check firmware status */
+               ret = af9013_read_reg(state, 0x98be, &val);
+               if (ret)
+                       goto error_release;
+
+               deb_info("%s: firmware status:%02x\n", __func__, val);
+
+               if (val == 0x0c || val == 0x04) /* success or fail */
+                       break;
+       }
+
+       if (val == 0x04) {
+               err("firmware did not run");
+               ret = -1;
+       } else if (val != 0x0c) {
+               err("firmware boot timeout");
+               ret = -1;
+       }
+
+error_release:
+       release_firmware(fw);
+error:
+exit:
+       if (!ret)
+               info("found a '%s' in warm state.", af9013_ops.info.name);
+       return ret;
+}
+
+static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       int ret;
+       struct af9013_state *state = fe->demodulator_priv;
+       deb_info("%s: enable:%d\n", __func__, enable);
+
+       if (state->config.output_mode == AF9013_OUTPUT_MODE_USB)
+               ret = af9013_write_reg_bits(state, 0xd417, 3, 1, enable);
+       else
+               ret = af9013_write_reg_bits(state, 0xd607, 2, 1, enable);
+
+       return ret;
+}
+
+static void af9013_release(struct dvb_frontend *fe)
+{
+       struct af9013_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops af9013_ops;
+
+struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+       struct i2c_adapter *i2c)
+{
+       int ret;
+       struct af9013_state *state = NULL;
+       u8 buf[3], i;
+
+       /* allocate memory for the internal state */
+       state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->i2c = i2c;
+       memcpy(&state->config, config, sizeof(struct af9013_config));
+
+       /* chip version */
+       ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
+       if (ret)
+               goto error;
+
+       /* ROM version */
+       for (i = 0; i < 2; i++) {
+               ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+       deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
+               buf[2], buf[0], buf[1]);
+
+       /* download firmware */
+       if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
+               ret = af9013_download_firmware(state);
+               if (ret)
+                       goto error;
+       }
+
+       /* firmware version */
+       for (i = 0; i < 3; i++) {
+               ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
+               if (ret)
+                       goto error;
+       }
+       info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]);
+
+       /* settings for mp2if */
+       if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
+               /* AF9015 split PSB to 1.5k + 0.5k */
+               ret = af9013_write_reg_bits(state, 0xd50b, 2, 1, 1);
+       } else {
+               /* AF9013 change the output bit to data7 */
+               ret = af9013_write_reg_bits(state, 0xd500, 3, 1, 1);
+               if (ret)
+                       goto error;
+               /* AF9013 set mpeg to full speed */
+               ret = af9013_write_reg_bits(state, 0xd502, 4, 1, 1);
+       }
+       if (ret)
+               goto error;
+       ret = af9013_write_reg_bits(state, 0xd520, 4, 1, 1);
+       if (ret)
+               goto error;
+
+       /* set GPIOs */
+       for (i = 0; i < sizeof(state->config.gpio); i++) {
+               ret = af9013_set_gpio(state, i, state->config.gpio[i]);
+               if (ret)
+                       goto error;
+       }
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &af9013_ops,
+               sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       return &state->frontend;
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(af9013_attach);
+
+static struct dvb_frontend_ops af9013_ops = {
+       .info = {
+               .name = "Afatech AF9013 DVB-T",
+               .type = FE_OFDM,
+               .frequency_min = 174000000,
+               .frequency_max = 862000000,
+               .frequency_stepsize = 250000,
+               .frequency_tolerance = 0,
+               .caps =
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 |
+                       FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_HIERARCHY_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_MUTE_TS
+       },
+
+       .release = af9013_release,
+       .init = af9013_init,
+       .sleep = af9013_sleep,
+       .i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+
+       .set_frontend = af9013_set_frontend,
+       .get_frontend = af9013_get_frontend,
+
+       .get_tune_settings = af9013_get_tune_settings,
+
+       .read_status = af9013_read_status,
+       .read_ber = af9013_read_ber,
+       .read_signal_strength = af9013_read_signal_strength,
+       .read_snr = af9013_read_snr,
+       .read_ucblocks = af9013_read_ucblocks,
+};
+
+module_param_named(debug, af9013_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h
new file mode 100644 (file)
index 0000000..28b90c9
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided 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 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 _AF9013_H_
+#define _AF9013_H_
+
+#include <linux/dvb/frontend.h>
+
+enum af9013_ts_mode {
+       AF9013_OUTPUT_MODE_PARALLEL,
+       AF9013_OUTPUT_MODE_SERIAL,
+       AF9013_OUTPUT_MODE_USB, /* only for AF9015 */
+};
+
+enum af9013_tuner {
+       AF9013_TUNER_MXL5003D   =   3, /* MaxLinear */
+       AF9013_TUNER_MXL5005D   =  13, /* MaxLinear */
+       AF9013_TUNER_MXL5005R   =  30, /* MaxLinear */
+       AF9013_TUNER_ENV77H11D5 = 129, /* Panasonic */
+       AF9013_TUNER_MT2060     = 130, /* Microtune */
+       AF9013_TUNER_MC44S803   = 133, /* Freescale */
+       AF9013_TUNER_QT1010     = 134, /* Quantek */
+       AF9013_TUNER_UNKNOWN    = 140, /* for can tuners ? */
+       AF9013_TUNER_MT2060_2   = 147, /* Microtune */
+       AF9013_TUNER_TDA18271   = 156, /* NXP */
+       AF9013_TUNER_QT1010A    = 162, /* Quantek */
+};
+
+/* AF9013/5 GPIOs (mostly guessed)
+   demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
+   demod#1-gpio#1 - xtal setting (?)
+   demod#1-gpio#3 - tuner#1
+   demod#2-gpio#0 - tuner#2
+   demod#2-gpio#1 - xtal setting (?)
+*/
+#define AF9013_GPIO_ON (1 << 0)
+#define AF9013_GPIO_EN (1 << 1)
+#define AF9013_GPIO_O  (1 << 2)
+#define AF9013_GPIO_I  (1 << 3)
+
+#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+
+#define AF9013_GPIO_TUNER_ON  (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+
+struct af9013_config {
+       /* demodulator's I2C address */
+       u8 demod_address;
+
+       /* frequencies in kHz */
+       u32 adc_clock;
+
+       /* tuner ID */
+       u8 tuner;
+
+       /* tuner IF */
+       u16 tuner_if;
+
+       /* TS data output mode */
+       u8 output_mode:2;
+
+       /* RF spectrum inversion */
+       u8 rf_spec_inv:1;
+
+       /* API version */
+       u8 api_version[4];
+
+       /* GPIOs */
+       u8 gpio[4];
+};
+
+
+#if defined(CONFIG_DVB_AF9013) || \
+       (defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
+extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+       struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *af9013_attach(
+const struct af9013_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_AF9013 */
+
+#endif /* _AF9013_H_ */
diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h
new file mode 100644 (file)
index 0000000..163e251
--- /dev/null
@@ -0,0 +1,869 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided 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 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 _AF9013_PRIV_
+#define _AF9013_PRIV_
+
+#define LOG_PREFIX "af9013"
+extern int af9013_debug;
+
+#define dprintk(var, level, args...) \
+           do { if ((var & level)) printk(args); } while (0)
+
+#define debug_dump(b, l, func) {\
+       int loop_; \
+       for (loop_ = 0; loop_ < l; loop_++) \
+               func("%02x ", b[loop_]); \
+       func("\n");\
+}
+
+#define deb_info(args...) dprintk(af9013_debug, 0x01, args)
+
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+#define AF9013_DEFAULT_FIRMWARE     "dvb-fe-af9013.fw"
+
+struct regdesc {
+       u16 addr;
+       u8  pos:4;
+       u8  len:4;
+       u8  val;
+};
+
+struct snr_table {
+       u32 val;
+       u8 snr;
+};
+
+/* QPSK SNR lookup table */
+static struct snr_table qpsk_snr_table[] = {
+       { 0x0b4771,  0 },
+       { 0x0c1aed,  1 },
+       { 0x0d0d27,  2 },
+       { 0x0e4d19,  3 },
+       { 0x0e5da8,  4 },
+       { 0x107097,  5 },
+       { 0x116975,  6 },
+       { 0x1252d9,  7 },
+       { 0x131fa4,  8 },
+       { 0x13d5e1,  9 },
+       { 0x148e53, 10 },
+       { 0x15358b, 11 },
+       { 0x15dd29, 12 },
+       { 0x168112, 13 },
+       { 0x170b61, 14 },
+       { 0xffffff, 15 },
+};
+
+/* QAM16 SNR lookup table */
+static struct snr_table qam16_snr_table[] = {
+       { 0x05eb62,  5 },
+       { 0x05fecf,  6 },
+       { 0x060b80,  7 },
+       { 0x062501,  8 },
+       { 0x064865,  9 },
+       { 0x069604, 10 },
+       { 0x06f356, 11 },
+       { 0x07706a, 12 },
+       { 0x0804d3, 13 },
+       { 0x089d1a, 14 },
+       { 0x093e3d, 15 },
+       { 0x09e35d, 16 },
+       { 0x0a7c3c, 17 },
+       { 0x0afaf8, 18 },
+       { 0x0b719d, 19 },
+       { 0xffffff, 20 },
+};
+
+/* QAM64 SNR lookup table */
+static struct snr_table qam64_snr_table[] = {
+       { 0x03109b, 12 },
+       { 0x0310d4, 13 },
+       { 0x031920, 14 },
+       { 0x0322d0, 15 },
+       { 0x0339fc, 16 },
+       { 0x0364a1, 17 },
+       { 0x038bcc, 18 },
+       { 0x03c7d3, 19 },
+       { 0x0408cc, 20 },
+       { 0x043bed, 21 },
+       { 0x048061, 22 },
+       { 0x04be95, 23 },
+       { 0x04fa7d, 24 },
+       { 0x052405, 25 },
+       { 0x05570d, 26 },
+       { 0xffffff, 27 },
+};
+
+static struct regdesc ofsm_init[] = {
+       { 0xd73a, 0, 8, 0xa1 },
+       { 0xd73b, 0, 8, 0x1f },
+       { 0xd73c, 4, 4, 0x0a },
+       { 0xd732, 3, 1, 0x00 },
+       { 0xd731, 4, 2, 0x03 },
+       { 0xd73d, 7, 1, 0x01 },
+       { 0xd740, 0, 1, 0x00 },
+       { 0xd740, 1, 1, 0x00 },
+       { 0xd740, 2, 1, 0x00 },
+       { 0xd740, 3, 1, 0x01 },
+       { 0xd3c1, 4, 1, 0x01 },
+       { 0xd3a2, 0, 8, 0x00 },
+       { 0xd3a3, 0, 8, 0x04 },
+       { 0xd305, 0, 8, 0x32 },
+       { 0xd306, 0, 8, 0x10 },
+       { 0xd304, 0, 8, 0x04 },
+       { 0x9112, 0, 1, 0x01 },
+       { 0x911d, 0, 1, 0x01 },
+       { 0x911a, 0, 1, 0x01 },
+       { 0x911b, 0, 1, 0x01 },
+       { 0x9bce, 0, 4, 0x02 },
+       { 0x9116, 0, 1, 0x01 },
+       { 0x9bd1, 0, 1, 0x01 },
+       { 0xd2e0, 0, 8, 0xd0 },
+       { 0xd2e9, 0, 4, 0x0d },
+       { 0xd38c, 0, 8, 0xfc },
+       { 0xd38d, 0, 8, 0x00 },
+       { 0xd38e, 0, 8, 0x7e },
+       { 0xd38f, 0, 8, 0x00 },
+       { 0xd390, 0, 8, 0x2f },
+       { 0xd145, 4, 1, 0x01 },
+       { 0xd1a9, 4, 1, 0x01 },
+       { 0xd158, 5, 3, 0x01 },
+       { 0xd159, 0, 6, 0x06 },
+       { 0xd167, 0, 8, 0x00 },
+       { 0xd168, 0, 4, 0x07 },
+       { 0xd1c3, 5, 3, 0x00 },
+       { 0xd1c4, 0, 6, 0x00 },
+       { 0xd1c5, 0, 7, 0x10 },
+       { 0xd1c6, 0, 3, 0x02 },
+       { 0xd080, 2, 5, 0x03 },
+       { 0xd081, 4, 4, 0x09 },
+       { 0xd098, 4, 4, 0x0f },
+       { 0xd098, 0, 4, 0x03 },
+       { 0xdbc0, 3, 1, 0x01 },
+       { 0xdbc0, 4, 1, 0x01 },
+       { 0xdbc7, 0, 8, 0x08 },
+       { 0xdbc8, 4, 4, 0x00 },
+       { 0xdbc9, 0, 5, 0x01 },
+       { 0xd280, 0, 8, 0xe0 },
+       { 0xd281, 0, 8, 0xff },
+       { 0xd282, 0, 8, 0xff },
+       { 0xd283, 0, 8, 0xc3 },
+       { 0xd284, 0, 8, 0xff },
+       { 0xd285, 0, 4, 0x01 },
+       { 0xd0f0, 0, 7, 0x1a },
+       { 0xd0f1, 4, 1, 0x01 },
+       { 0xd0f2, 0, 8, 0x0c },
+       { 0xd103, 0, 4, 0x08 },
+       { 0xd0f8, 0, 7, 0x20 },
+       { 0xd111, 5, 1, 0x00 },
+       { 0xd111, 6, 1, 0x00 },
+       { 0x910b, 0, 8, 0x0a },
+       { 0x9115, 0, 8, 0x02 },
+       { 0x910c, 0, 8, 0x02 },
+       { 0x910d, 0, 8, 0x08 },
+       { 0x910e, 0, 8, 0x0a },
+       { 0x9bf6, 0, 8, 0x06 },
+       { 0x9bf8, 0, 8, 0x02 },
+       { 0x9bf7, 0, 8, 0x05 },
+       { 0x9bf9, 0, 8, 0x0f },
+       { 0x9bfc, 0, 8, 0x13 },
+       { 0x9bd3, 0, 8, 0xff },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+};
+
+/* Panasonic ENV77H11D5 tuner init
+   AF9013_TUNER_ENV77H11D5 = 129 */
+static struct regdesc tuner_init_env77h11d5[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x03 },
+       { 0x9bbe, 0, 8, 0x01 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x00 },
+       { 0x9be3, 0, 8, 0x00 },
+       { 0xd015, 0, 8, 0x50 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0xdf },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x44 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0xeb },
+       { 0xd00d, 0, 2, 0x02 },
+       { 0xd00a, 0, 8, 0xf4 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bba, 0, 8, 0xf9 },
+       { 0x9bc3, 0, 8, 0xdf },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0xeb },
+       { 0x9bc6, 0, 8, 0x02 },
+       { 0x9bc9, 0, 8, 0x52 },
+       { 0xd011, 0, 8, 0x3c },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0xf7 },
+       { 0xd014, 0, 2, 0x02 },
+       { 0xd040, 0, 8, 0x0b },
+       { 0xd041, 0, 2, 0x02 },
+       { 0xd042, 0, 8, 0x4d },
+       { 0xd043, 0, 2, 0x00 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* Microtune MT2060 tuner init
+   AF9013_TUNER_MT2060     = 130 */
+static struct regdesc tuner_init_mt2060[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x07 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x00 },
+       { 0x9be3, 0, 8, 0x00 },
+       { 0x9bbe, 0, 1, 0x00 },
+       { 0x9bcc, 0, 1, 0x00 },
+       { 0x9bb9, 0, 8, 0x75 },
+       { 0x9bcd, 0, 8, 0x24 },
+       { 0x9bff, 0, 8, 0x30 },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0x0f },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x32 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0x36 },
+       { 0xd00d, 0, 2, 0x03 },
+       { 0xd00a, 0, 8, 0x35 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x07 },
+       { 0x9bc8, 0, 8, 0x90 },
+       { 0x9bc3, 0, 8, 0x0f },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x36 },
+       { 0x9bc6, 0, 8, 0x03 },
+       { 0x9bba, 0, 8, 0xc9 },
+       { 0x9bc9, 0, 8, 0x79 },
+       { 0xd011, 0, 8, 0x10 },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0x45 },
+       { 0xd014, 0, 2, 0x03 },
+       { 0xd040, 0, 8, 0x98 },
+       { 0xd041, 0, 2, 0x00 },
+       { 0xd042, 0, 8, 0xcf },
+       { 0xd043, 0, 2, 0x03 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+       { 0x9bd0, 0, 8, 0xcc },
+       { 0x9be4, 0, 8, 0xa0 },
+       { 0x9bbd, 0, 8, 0x8e },
+       { 0x9be2, 0, 8, 0x4d },
+       { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Microtune MT2060 tuner init
+   AF9013_TUNER_MT2060_2   = 147 */
+static struct regdesc tuner_init_mt2060_2[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x06 },
+       { 0x9bbe, 0, 8, 0x01 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0x0f },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x32 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0x36 },
+       { 0xd00d, 0, 2, 0x03 },
+       { 0xd00a, 0, 8, 0x35 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x07 },
+       { 0x9bc8, 0, 8, 0x90 },
+       { 0x9bc3, 0, 8, 0x0f },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x36 },
+       { 0x9bc6, 0, 8, 0x03 },
+       { 0x9bba, 0, 8, 0xc9 },
+       { 0x9bc9, 0, 8, 0x79 },
+       { 0xd011, 0, 8, 0x10 },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0x45 },
+       { 0xd014, 0, 2, 0x03 },
+       { 0xd040, 0, 8, 0x98 },
+       { 0xd041, 0, 2, 0x00 },
+       { 0xd042, 0, 8, 0xcf },
+       { 0xd043, 0, 2, 0x03 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 8, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x96 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0xd045, 7, 1, 0x00 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5003 tuner init
+   AF9013_TUNER_MXL5003D   =   3 */
+static struct regdesc tuner_init_mxl5003d[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x09 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x00 },
+       { 0x9be3, 0, 8, 0x00 },
+       { 0x9bfc, 0, 8, 0x0f },
+       { 0x9bf6, 0, 8, 0x01 },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0xd015, 0, 8, 0x33 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x40 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0x0f },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x6c },
+       { 0xd007, 0, 2, 0x00 },
+       { 0xd00c, 0, 8, 0x3d },
+       { 0xd00d, 0, 2, 0x00 },
+       { 0xd00a, 0, 8, 0x45 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x07 },
+       { 0x9bc8, 0, 8, 0x52 },
+       { 0x9bc3, 0, 8, 0x0f },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x3d },
+       { 0x9bc6, 0, 8, 0x00 },
+       { 0x9bba, 0, 8, 0xa2 },
+       { 0x9bc9, 0, 8, 0xa0 },
+       { 0xd011, 0, 8, 0x56 },
+       { 0xd012, 0, 2, 0x00 },
+       { 0xd013, 0, 8, 0x50 },
+       { 0xd014, 0, 2, 0x00 },
+       { 0xd040, 0, 8, 0x56 },
+       { 0xd041, 0, 2, 0x00 },
+       { 0xd042, 0, 8, 0x50 },
+       { 0xd043, 0, 2, 0x00 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 8, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5005 tuner init
+   AF9013_TUNER_MXL5005D   =  13
+   AF9013_TUNER_MXL5005R   =  30 */
+static struct regdesc tuner_init_mxl5005[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x07 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x01 },
+       { 0x9be3, 0, 8, 0x01 },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+       { 0x9bb9, 0, 8, 0x00 },
+       { 0x9bcd, 0, 8, 0x28 },
+       { 0x9bff, 0, 8, 0x24 },
+       { 0xd015, 0, 8, 0x40 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x40 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0x0f },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x73 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0xfa },
+       { 0xd00d, 0, 2, 0x01 },
+       { 0xd00a, 0, 8, 0xff },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x23 },
+       { 0x9bc8, 0, 8, 0x55 },
+       { 0x9bc3, 0, 8, 0x01 },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0xfa },
+       { 0x9bc6, 0, 8, 0x01 },
+       { 0x9bba, 0, 8, 0xff },
+       { 0x9bc9, 0, 8, 0xff },
+       { 0x9bd3, 0, 8, 0x95 },
+       { 0xd011, 0, 8, 0x70 },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0xfb },
+       { 0xd014, 0, 2, 0x01 },
+       { 0xd040, 0, 8, 0x70 },
+       { 0xd041, 0, 2, 0x01 },
+       { 0xd042, 0, 8, 0xfb },
+       { 0xd043, 0, 2, 0x01 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+       { 0x9bd0, 0, 8, 0x93 },
+       { 0x9be4, 0, 8, 0xfe },
+       { 0x9bbd, 0, 8, 0x63 },
+       { 0x9be2, 0, 8, 0xfe },
+       { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Quantek QT1010 tuner init
+   AF9013_TUNER_QT1010     = 134
+   AF9013_TUNER_QT1010A    = 162 */
+static struct regdesc tuner_init_qt1010[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x09 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x01 },
+       { 0x9be3, 0, 8, 0x01 },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+       { 0x9bb9, 0, 8, 0x00 },
+       { 0x9bcd, 0, 8, 0x28 },
+       { 0x9bff, 0, 8, 0x20 },
+       { 0xd008, 0, 8, 0x0f },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x99 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0x0f },
+       { 0xd00d, 0, 2, 0x02 },
+       { 0xd00a, 0, 8, 0x50 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x00 },
+       { 0x9bc8, 0, 8, 0x00 },
+       { 0x9bc3, 0, 8, 0x0f },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x0f },
+       { 0x9bc6, 0, 8, 0x02 },
+       { 0x9bba, 0, 8, 0xc5 },
+       { 0x9bc9, 0, 8, 0xff },
+       { 0xd011, 0, 8, 0x58 },
+       { 0xd012, 0, 2, 0x02 },
+       { 0xd013, 0, 8, 0x89 },
+       { 0xd014, 0, 2, 0x01 },
+       { 0xd040, 0, 8, 0x58 },
+       { 0xd041, 0, 2, 0x02 },
+       { 0xd042, 0, 8, 0x89 },
+       { 0xd043, 0, 2, 0x01 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+       { 0x9bd0, 0, 8, 0xcd },
+       { 0x9be4, 0, 8, 0xbb },
+       { 0x9bbd, 0, 8, 0x93 },
+       { 0x9be2, 0, 8, 0x80 },
+       { 0x9bee, 0, 1, 0x01 },
+};
+
+/* Freescale MC44S803 tuner init
+   AF9013_TUNER_MC44S803   = 133 */
+static struct regdesc tuner_init_mc44s803[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x06 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x00 },
+       { 0x9be3, 0, 8, 0x00 },
+       { 0x9bf6, 0, 8, 0x01 },
+       { 0x9bf8, 0, 8, 0x02 },
+       { 0x9bf9, 0, 8, 0x02 },
+       { 0x9bfc, 0, 8, 0x1f },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+       { 0x9bb9, 0, 8, 0x00 },
+       { 0x9bcd, 0, 8, 0x24 },
+       { 0x9bff, 0, 8, 0x24 },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0x01 },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x7b },
+       { 0xd007, 0, 2, 0x00 },
+       { 0xd00c, 0, 8, 0x7c },
+       { 0xd00d, 0, 2, 0x02 },
+       { 0xd00a, 0, 8, 0xfe },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bc7, 0, 8, 0x08 },
+       { 0x9bc8, 0, 8, 0x9a },
+       { 0x9bc3, 0, 8, 0x01 },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x7c },
+       { 0x9bc6, 0, 8, 0x02 },
+       { 0x9bba, 0, 8, 0xfc },
+       { 0x9bc9, 0, 8, 0xaa },
+       { 0xd011, 0, 8, 0x6b },
+       { 0xd012, 0, 2, 0x00 },
+       { 0xd013, 0, 8, 0x88 },
+       { 0xd014, 0, 2, 0x02 },
+       { 0xd040, 0, 8, 0x6b },
+       { 0xd041, 0, 2, 0x00 },
+       { 0xd042, 0, 8, 0x7c },
+       { 0xd043, 0, 2, 0x02 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+       { 0x9bd0, 0, 8, 0x9e },
+       { 0x9be4, 0, 8, 0xff },
+       { 0x9bbd, 0, 8, 0x9e },
+       { 0x9be2, 0, 8, 0x25 },
+       { 0x9bee, 0, 1, 0x01 },
+       { 0xd73b, 3, 1, 0x00 },
+};
+
+/* unknown, probably for tin can tuner, tuner init
+   AF9013_TUNER_UNKNOWN   = 140 */
+static struct regdesc tuner_init_unknown[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x02 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x01 },
+       { 0x9be3, 0, 8, 0x01 },
+       { 0xd1a0, 1, 1, 0x00 },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+       { 0x9bb9, 0, 8, 0x00 },
+       { 0x9bcd, 0, 8, 0x18 },
+       { 0x9bff, 0, 8, 0x2c },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0xdf },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x44 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0x00 },
+       { 0xd00d, 0, 2, 0x02 },
+       { 0xd00a, 0, 8, 0xf6 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bba, 0, 8, 0xf9 },
+       { 0x9bc8, 0, 8, 0xaa },
+       { 0x9bc3, 0, 8, 0xdf },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x00 },
+       { 0x9bc6, 0, 8, 0x02 },
+       { 0x9bc9, 0, 8, 0xf0 },
+       { 0xd011, 0, 8, 0x3c },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0xf7 },
+       { 0xd014, 0, 2, 0x02 },
+       { 0xd040, 0, 8, 0x0b },
+       { 0xd041, 0, 2, 0x02 },
+       { 0xd042, 0, 8, 0x4d },
+       { 0xd043, 0, 2, 0x00 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+};
+
+/* NXP TDA18271 tuner init
+   AF9013_TUNER_TDA18271   = 156 */
+static struct regdesc tuner_init_tda18271[] = {
+       { 0x9bd5, 0, 8, 0x01 },
+       { 0x9bd6, 0, 8, 0x04 },
+       { 0xd1a0, 1, 1, 0x01 },
+       { 0xd000, 0, 1, 0x01 },
+       { 0xd000, 1, 1, 0x00 },
+       { 0xd001, 1, 1, 0x01 },
+       { 0xd001, 0, 1, 0x00 },
+       { 0xd001, 5, 1, 0x00 },
+       { 0xd002, 0, 5, 0x19 },
+       { 0xd003, 0, 5, 0x1a },
+       { 0xd004, 0, 5, 0x19 },
+       { 0xd005, 0, 5, 0x1a },
+       { 0xd00e, 0, 5, 0x10 },
+       { 0xd00f, 0, 3, 0x04 },
+       { 0xd00f, 3, 3, 0x05 },
+       { 0xd010, 0, 3, 0x04 },
+       { 0xd010, 3, 3, 0x05 },
+       { 0xd016, 4, 4, 0x03 },
+       { 0xd01f, 0, 6, 0x0a },
+       { 0xd020, 0, 6, 0x0a },
+       { 0x9bda, 0, 8, 0x01 },
+       { 0x9be3, 0, 8, 0x01 },
+       { 0xd1a0, 1, 1, 0x00 },
+       { 0x9bbe, 0, 1, 0x01 },
+       { 0x9bcc, 0, 1, 0x01 },
+       { 0x9bb9, 0, 8, 0x00 },
+       { 0x9bcd, 0, 8, 0x18 },
+       { 0x9bff, 0, 8, 0x2c },
+       { 0xd015, 0, 8, 0x46 },
+       { 0xd016, 0, 1, 0x00 },
+       { 0xd044, 0, 8, 0x46 },
+       { 0xd045, 0, 1, 0x00 },
+       { 0xd008, 0, 8, 0xdf },
+       { 0xd009, 0, 2, 0x02 },
+       { 0xd006, 0, 8, 0x44 },
+       { 0xd007, 0, 2, 0x01 },
+       { 0xd00c, 0, 8, 0x00 },
+       { 0xd00d, 0, 2, 0x02 },
+       { 0xd00a, 0, 8, 0xf6 },
+       { 0xd00b, 0, 2, 0x01 },
+       { 0x9bba, 0, 8, 0xf9 },
+       { 0x9bc8, 0, 8, 0xaa },
+       { 0x9bc3, 0, 8, 0xdf },
+       { 0x9bc4, 0, 8, 0x02 },
+       { 0x9bc5, 0, 8, 0x00 },
+       { 0x9bc6, 0, 8, 0x02 },
+       { 0x9bc9, 0, 8, 0xf0 },
+       { 0xd011, 0, 8, 0x3c },
+       { 0xd012, 0, 2, 0x01 },
+       { 0xd013, 0, 8, 0xf7 },
+       { 0xd014, 0, 2, 0x02 },
+       { 0xd040, 0, 8, 0x0b },
+       { 0xd041, 0, 2, 0x02 },
+       { 0xd042, 0, 8, 0x4d },
+       { 0xd043, 0, 2, 0x00 },
+       { 0xd045, 1, 1, 0x00 },
+       { 0x9bcf, 0, 1, 0x01 },
+       { 0xd045, 2, 1, 0x01 },
+       { 0xd04f, 0, 8, 0x9a },
+       { 0xd050, 0, 1, 0x01 },
+       { 0xd051, 0, 8, 0x5a },
+       { 0xd052, 0, 1, 0x01 },
+       { 0xd053, 0, 8, 0x50 },
+       { 0xd054, 0, 8, 0x46 },
+       { 0x9bd7, 0, 8, 0x0a },
+       { 0x9bd8, 0, 8, 0x14 },
+       { 0x9bd9, 0, 8, 0x08 },
+       { 0x9bd0, 0, 8, 0xa8 },
+       { 0x9be4, 0, 8, 0x7f },
+       { 0x9bbd, 0, 8, 0xa8 },
+       { 0x9be2, 0, 8, 0x20 },
+       { 0x9bee, 0, 1, 0x01 },
+};
+
+#endif /* _AF9013_PRIV_ */
index 0b82cc2a1e161c7603e900ab6bff8d4ffc9effee..eabf9a68e7ec36362ec3aab2c46f076ebfa54273 100644 (file)
@@ -40,6 +40,8 @@ struct au8522_state {
        u32 current_frequency;
        fe_modulation_t current_modulation;
 
+       u32 fe_status;
+       unsigned int led_state;
 };
 
 static int debug;
@@ -538,11 +540,98 @@ static int au8522_init(struct dvb_frontend *fe)
        return 0;
 }
 
+static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
+{
+       struct au8522_led_config *led_config = state->config->led_cfg;
+       u8 val;
+
+       /* bail out if we cant control an LED */
+       if (!led_config || !led_config->gpio_output ||
+           !led_config->gpio_output_enable || !led_config->gpio_output_disable)
+               return 0;
+
+       val = au8522_readreg(state, 0x4000 |
+                            (led_config->gpio_output & ~0xc000));
+       if (onoff) {
+               /* enable GPIO output */
+               val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
+               val |=  (led_config->gpio_output_enable & 0xff);
+       } else {
+               /* disable GPIO output */
+               val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
+               val |=  (led_config->gpio_output_disable & 0xff);
+       }
+       return au8522_writereg(state, 0x8000 |
+                              (led_config->gpio_output & ~0xc000), val);
+}
+
+/* led = 0 | off
+ * led = 1 | signal ok
+ * led = 2 | signal strong
+ * led < 0 | only light led if leds are currently off
+ */
+static int au8522_led_ctrl(struct au8522_state *state, int led)
+{
+       struct au8522_led_config *led_config = state->config->led_cfg;
+       int i, ret = 0;
+
+       /* bail out if we cant control an LED */
+       if (!led_config || !led_config->gpio_leds ||
+           !led_config->num_led_states || !led_config->led_states)
+               return 0;
+
+       if (led < 0) {
+               /* if LED is already lit, then leave it as-is */
+               if (state->led_state)
+                       return 0;
+               else
+                       led *= -1;
+       }
+
+       /* toggle LED if changing state */
+       if (state->led_state != led) {
+               u8 val;
+
+               dprintk("%s: %d\n", __func__, led);
+
+               au8522_led_gpio_enable(state, 1);
+
+               val = au8522_readreg(state, 0x4000 |
+                                    (led_config->gpio_leds & ~0xc000));
+
+               /* start with all leds off */
+               for (i = 0; i < led_config->num_led_states; i++)
+                       val &= ~led_config->led_states[i];
+
+               /* set selected LED state */
+               if (led < led_config->num_led_states)
+                       val |= led_config->led_states[led];
+               else if (led_config->num_led_states)
+                       val |=
+                       led_config->led_states[led_config->num_led_states - 1];
+
+               ret = au8522_writereg(state, 0x8000 |
+                                     (led_config->gpio_leds & ~0xc000), val);
+               if (ret < 0)
+                       return ret;
+
+               state->led_state = led;
+
+               if (led == 0)
+                       au8522_led_gpio_enable(state, 0);
+       }
+
+       return 0;
+}
+
 static int au8522_sleep(struct dvb_frontend *fe)
 {
        struct au8522_state *state = fe->demodulator_priv;
        dprintk("%s()\n", __func__);
 
+       /* turn off led */
+       au8522_led_ctrl(state, 0);
+
        state->current_frequency = 0;
 
        return 0;
@@ -592,12 +681,53 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
                        *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
                break;
        }
+       state->fe_status = *status;
+
+       if (*status & FE_HAS_LOCK)
+               /* turn on LED, if it isn't on already */
+               au8522_led_ctrl(state, -1);
+       else
+               /* turn off LED */
+               au8522_led_ctrl(state, 0);
 
        dprintk("%s() status 0x%08x\n", __func__, *status);
 
        return 0;
 }
 
+static int au8522_led_status(struct au8522_state *state, const u16 *snr)
+{
+       struct au8522_led_config *led_config = state->config->led_cfg;
+       int led;
+       u16 strong;
+
+       /* bail out if we cant control an LED */
+       if (!led_config)
+               return 0;
+
+       if (0 == (state->fe_status & FE_HAS_LOCK))
+               return au8522_led_ctrl(state, 0);
+       else if (state->current_modulation == QAM_256)
+               strong = led_config->qam256_strong;
+       else if (state->current_modulation == QAM_64)
+               strong = led_config->qam64_strong;
+       else /* (state->current_modulation == VSB_8) */
+               strong = led_config->vsb8_strong;
+
+       if (*snr >= strong)
+               led = 2;
+       else
+               led = 1;
+
+       if ((state->led_state) &&
+           (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10))
+               /* snr didn't change enough to bother
+                * changing the color of the led */
+               return 0;
+
+       return au8522_led_ctrl(state, led);
+}
+
 static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct au8522_state *state = fe->demodulator_priv;
@@ -621,6 +751,9 @@ static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
                                            au8522_readreg(state, 0x4311),
                                            snr);
 
+       if (state->config->led_cfg)
+               au8522_led_status(state, snr);
+
        return ret;
 }
 
index 595915ade8c3681b5158e0ed0bf56da36ab25d4f..7b94f554a09344d02c9bb97122783fe4ca39947b 100644 (file)
@@ -30,6 +30,21 @@ enum au8522_if_freq {
        AU8522_IF_3_25MHZ,
 };
 
+struct au8522_led_config {
+       u16 vsb8_strong;
+       u16 qam64_strong;
+       u16 qam256_strong;
+
+       u16 gpio_output;
+       /* unset hi bits, set low bits */
+       u16 gpio_output_enable;
+       u16 gpio_output_disable;
+
+       u16 gpio_leds;
+       u8 *led_states;
+       unsigned int num_led_states;
+};
+
 struct au8522_config {
        /* the demodulator's i2c address */
        u8 demod_address;
@@ -39,6 +54,8 @@ struct au8522_config {
 #define AU8522_DEMODLOCKING 1
        u8 status_mode;
 
+       struct au8522_led_config *led_cfg;
+
        enum au8522_if_freq vsb_if;
        enum au8522_if_freq qam_if;
 };
index 1792adb23c4d527d89bbb4bd859e01ea4732e854..fdcceee91f3ac44cc1000201f3ebca32f7e46c0e 100644 (file)
@@ -33,12 +33,17 @@ struct cx24110_config
        u8 demod_address;
 };
 
-static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
-       int r = 0;
-       u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
+{
+       u8 buf[] = {
+               (u8)((val >> 24) & 0xff),
+               (u8)((val >> 16) & 0xff),
+               (u8)((val >> 8) & 0xff)
+       };
+
        if (fe->ops.write)
-               r = fe->ops.write(fe, buf, 3);
-       return r;
+               return fe->ops.write(fe, buf, 3);
+       return 0;
 }
 
 #if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE))
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
new file mode 100644 (file)
index 0000000..deb36f4
--- /dev/null
@@ -0,0 +1,1423 @@
+/*
+    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+    Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2006-2007 Georg Acher
+    Copyright (C) 2007-2008 Darron Broad
+       March 2007
+           Fixed some bugs.
+           Added diseqc support.
+           Added corrected signal strength support.
+       August 2007
+           Sync with legacy version.
+           Some clean ups.
+    Copyright (C) 2008 Igor Liplianin
+       September, 9th 2008
+           Fixed locking on high symbol rates (>30000).
+           Implement MPEG initialization parameter.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "cx24116.h"
+
+static int debug = 0;
+#define dprintk(args...) \
+       do { \
+               if (debug) printk ("cx24116: " args); \
+       } while (0)
+
+#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
+#define CX24116_SEARCH_RANGE_KHZ 5000
+
+/* known registers */
+#define CX24116_REG_COMMAND (0x00)      /* command args 0x00..0x1e */
+#define CX24116_REG_EXECUTE (0x1f)      /* execute command */
+#define CX24116_REG_MAILBOX (0x96)      /* FW or multipurpose mailbox? */
+#define CX24116_REG_RESET   (0x20)      /* reset status > 0     */
+#define CX24116_REG_SIGNAL  (0x9e)      /* signal low           */
+#define CX24116_REG_SSTATUS (0x9d)      /* signal high / status */
+#define CX24116_REG_QUALITY8 (0xa3)
+#define CX24116_REG_QSTATUS (0xbc)
+#define CX24116_REG_QUALITY0 (0xd5)
+#define CX24116_REG_BER0    (0xc9)
+#define CX24116_REG_BER8    (0xc8)
+#define CX24116_REG_BER16   (0xc7)
+#define CX24116_REG_BER24   (0xc6)
+#define CX24116_REG_UCB0    (0xcb)
+#define CX24116_REG_UCB8    (0xca)
+#define CX24116_REG_CLKDIV  (0xf3)
+#define CX24116_REG_RATEDIV (0xf9)
+#define CX24116_REG_FECSTATUS (0x9c)    /* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+
+/* FECSTATUS bits */
+#define CX24116_FEC_FECMASK   (0x1f)    /* mask to determine configured fec (not tuned) or actual fec (tuned) */
+#define CX24116_FEC_DVBS      (0x20)    /* Select DVB-S demodulator, else DVB-S2 */
+#define CX24116_FEC_UNKNOWN   (0x40)    /* Unknown/unused */
+#define CX24116_FEC_PILOT     (0x80)    /* Pilot mode requested when tuning else always reset when tuned */
+
+/* arg buffer size */
+#define CX24116_ARGLEN (0x1e)
+
+/* rolloff */
+#define CX24116_ROLLOFF_020 (0x00)
+#define CX24116_ROLLOFF_025 (0x01)
+#define CX24116_ROLLOFF_035 (0x02)
+
+/* pilot bit */
+#define CX24116_PILOT_OFF (0x00)
+#define CX24116_PILOT_ON (0x40)
+
+/* signal status */
+#define CX24116_HAS_SIGNAL   (0x01)
+#define CX24116_HAS_CARRIER  (0x02)
+#define CX24116_HAS_VITERBI  (0x04)
+#define CX24116_HAS_SYNCLOCK (0x08)
+#define CX24116_HAS_UNKNOWN1 (0x10)
+#define CX24116_HAS_UNKNOWN2 (0x20)
+#define CX24116_STATUS_MASK  (0x3f)
+#define CX24116_SIGNAL_MASK  (0xc0)
+
+#define CX24116_DISEQC_TONEOFF   (0)    /* toneburst never sent */
+#define CX24116_DISEQC_TONECACHE (1)    /* toneburst cached     */
+#define CX24116_DISEQC_MESGCACHE (2)    /* message cached       */
+
+/* arg offset for DiSEqC */
+#define CX24116_DISEQC_BURST  (1)
+#define CX24116_DISEQC_ARG2_2 (2)   /* unknown value=2 */
+#define CX24116_DISEQC_ARG3_0 (3)   /* unknown value=0 */
+#define CX24116_DISEQC_ARG4_0 (4)   /* unknown value=0 */
+#define CX24116_DISEQC_MSGLEN (5)
+#define CX24116_DISEQC_MSGOFS (6)
+
+/* DiSEqC burst */
+#define CX24116_DISEQC_MINI_A (0)
+#define CX24116_DISEQC_MINI_B (1)
+
+/* DiSEqC tone burst */
+static int toneburst = 1;
+
+/* SNR measurements */
+static int esno_snr = 0;
+
+enum cmds
+{
+       CMD_SET_VCO     = 0x10,
+       CMD_TUNEREQUEST = 0x11,
+       CMD_MPEGCONFIG  = 0x13,
+       CMD_TUNERINIT   = 0x14,
+       CMD_BANDWIDTH   = 0x15,
+       CMD_GETAGC      = 0x19,
+       CMD_LNBCONFIG   = 0x20,
+       CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */
+       CMD_SET_TONEPRE = 0x22,
+       CMD_SET_TONE    = 0x23,
+       CMD_UPDFWVERS   = 0x35,
+       CMD_TUNERSLEEP  = 0x36,
+       CMD_AGCCONTROL  = 0x3b, /* Unknown */
+};
+
+/* The Demod/Tuner can't easily provide these, we cache them */
+struct cx24116_tuning
+{
+       u32 frequency;
+       u32 symbol_rate;
+       fe_spectral_inversion_t inversion;
+       fe_code_rate_t fec;
+
+       fe_modulation_t modulation;
+       fe_pilot_t pilot;
+       fe_rolloff_t rolloff;
+
+       /* Demod values */
+       u8 fec_val;
+       u8 fec_mask;
+       u8 inversion_val;
+       u8 pilot_val;
+       u8 rolloff_val;
+};
+
+/* Basic commands that are sent to the firmware */
+struct cx24116_cmd
+{
+       u8 len;
+       u8 args[CX24116_ARGLEN];
+};
+
+struct cx24116_state
+{
+       struct i2c_adapter* i2c;
+       const struct cx24116_config* config;
+
+       struct dvb_frontend frontend;
+
+       struct cx24116_tuning dcur;
+       struct cx24116_tuning dnxt;
+
+       u8 skip_fw_load;
+       u8 burst;
+       struct cx24116_cmd dsec_cmd;
+};
+
+static int cx24116_writereg(struct cx24116_state* state, int reg, int data)
+{
+       u8 buf[] = { reg, data };
+       struct i2c_msg msg = { .addr = state->config->demod_address,
+               .flags = 0, .buf = buf, .len = 2 };
+       int err;
+
+       if (debug>1)
+               printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
+                                               __func__,reg, data);
+
+       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+               printk("%s: writereg error(err == %i, reg == 0x%02x,"
+                        " value == 0x%02x)\n", __func__, err, reg, data);
+               return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+/* Bulk byte writes to a single I2C address, for 32k firmware load */
+static int cx24116_writeregN(struct cx24116_state* state, int reg, u8 *data, u16 len)
+{
+       int ret = -EREMOTEIO;
+       struct i2c_msg msg;
+       u8 *buf;
+
+       buf = kmalloc(len + 1, GFP_KERNEL);
+       if (buf == NULL) {
+               printk("Unable to kmalloc\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       *(buf) = reg;
+       memcpy(buf + 1, data, len);
+
+       msg.addr = state->config->demod_address;
+       msg.flags = 0;
+       msg.buf = buf;
+       msg.len = len + 1;
+
+       if (debug>1)
+               printk("cx24116: %s:  write regN 0x%02x, len = %d\n",
+                                               __func__,reg, len);
+
+       if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+               printk("%s: writereg error(err == %i, reg == 0x%02x\n",
+                        __func__, ret, reg);
+               ret = -EREMOTEIO;
+       }
+
+error:
+       kfree(buf);
+
+       return ret;
+}
+
+static int cx24116_readreg(struct cx24116_state* state, u8 reg)
+{
+       int ret;
+       u8 b0[] = { reg };
+       u8 b1[] = { 0 };
+       struct i2c_msg msg[] = {
+               { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+               { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2) {
+               printk("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+               return ret;
+       }
+
+       if (debug>1)
+               printk("cx24116: read reg 0x%02x, value 0x%02x\n",reg, b1[0]);
+
+       return b1[0];
+}
+
+static int cx24116_set_inversion(struct cx24116_state* state, fe_spectral_inversion_t inversion)
+{
+       dprintk("%s(%d)\n", __func__, inversion);
+
+       switch (inversion) {
+       case INVERSION_OFF:
+               state->dnxt.inversion_val = 0x00;
+               break;
+       case INVERSION_ON:
+               state->dnxt.inversion_val = 0x04;
+               break;
+       case INVERSION_AUTO:
+               state->dnxt.inversion_val = 0x0C;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       state->dnxt.inversion = inversion;
+
+       return 0;
+}
+
+/*
+ * modfec (modulation and FEC)
+ * ===========================
+ *
+ * MOD          FEC             mask/val    standard
+ * ----         --------        ----------- --------
+ * QPSK         FEC_1_2         0x02 0x02+X DVB-S
+ * QPSK         FEC_2_3         0x04 0x02+X DVB-S
+ * QPSK         FEC_3_4         0x08 0x02+X DVB-S
+ * QPSK         FEC_4_5         0x10 0x02+X DVB-S (?)
+ * QPSK         FEC_5_6         0x20 0x02+X DVB-S
+ * QPSK         FEC_6_7         0x40 0x02+X DVB-S
+ * QPSK         FEC_7_8         0x80 0x02+X DVB-S
+ * QPSK         FEC_8_9         0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
+ * QPSK         AUTO            0xff 0x02+X DVB-S
+ *
+ * For DVB-S high byte probably represents FEC
+ * and low byte selects the modulator. The high
+ * byte is search range mask. Bit 5 may turn
+ * on DVB-S and remaining bits represent some
+ * kind of calibration (how/what i do not know).
+ *
+ * Eg.(2/3) szap "Zone Horror"
+ *
+ * mask/val = 0x04, 0x20
+ * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 00000000 | FE_HAS_LOCK
+ *
+ * mask/val = 0x04, 0x30
+ * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 00000000 | FE_HAS_LOCK
+ *
+ * After tuning FECSTATUS contains actual FEC
+ * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
+ *
+ * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
+ *
+ * NBC-QPSK     FEC_1_2         0x00, 0x04      DVB-S2
+ * NBC-QPSK     FEC_3_5         0x00, 0x05      DVB-S2
+ * NBC-QPSK     FEC_2_3         0x00, 0x06      DVB-S2
+ * NBC-QPSK     FEC_3_4         0x00, 0x07      DVB-S2
+ * NBC-QPSK     FEC_4_5         0x00, 0x08      DVB-S2
+ * NBC-QPSK     FEC_5_6         0x00, 0x09      DVB-S2
+ * NBC-QPSK     FEC_8_9         0x00, 0x0a      DVB-S2
+ * NBC-QPSK     FEC_9_10        0x00, 0x0b      DVB-S2
+ *
+ * NBC-8PSK     FEC_3_5         0x00, 0x0c      DVB-S2
+ * NBC-8PSK     FEC_2_3         0x00, 0x0d      DVB-S2
+ * NBC-8PSK     FEC_3_4         0x00, 0x0e      DVB-S2
+ * NBC-8PSK     FEC_5_6         0x00, 0x0f      DVB-S2
+ * NBC-8PSK     FEC_8_9         0x00, 0x10      DVB-S2
+ * NBC-8PSK     FEC_9_10        0x00, 0x11      DVB-S2
+ *
+ * For DVB-S2 low bytes selects both modulator
+ * and FEC. High byte is meaningless here. To
+ * set pilot, bit 6 (0x40) is set. When inspecting
+ * FECSTATUS bit 7 (0x80) represents the pilot
+ * selection whilst not tuned. When tuned, actual FEC
+ * in use is found in FECSTATUS as per above. Pilot
+ * value is reset.
+ */
+
+/* A table of modulation, fec and configuration bytes for the demod.
+ * Not all S2 mmodulation schemes are support and not all rates with
+ * a scheme are support. Especially, no auto detect when in S2 mode.
+ */
+struct cx24116_modfec {
+       fe_delivery_system_t delivery_system;
+       fe_modulation_t modulation;
+       fe_code_rate_t fec;
+       u8 mask;        /* In DVBS mode this is used to autodetect */
+       u8 val;         /* Passed to the firmware to indicate mode selection */
+} CX24116_MODFEC_MODES[] = {
+ /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
+
+ /*mod   fec       mask  val */
+ { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
+ { SYS_DVBS, QPSK, FEC_1_2,  0x02, 0x2e }, /* 00000010 00101110 */
+ { SYS_DVBS, QPSK, FEC_2_3,  0x04, 0x2f }, /* 00000100 00101111 */
+ { SYS_DVBS, QPSK, FEC_3_4,  0x08, 0x30 }, /* 00001000 00110000 */
+ { SYS_DVBS, QPSK, FEC_4_5,  0xfe, 0x30 }, /* 000?0000 ?        */
+ { SYS_DVBS, QPSK, FEC_5_6,  0x20, 0x31 }, /* 00100000 00110001 */
+ { SYS_DVBS, QPSK, FEC_6_7,  0xfe, 0x30 }, /* 0?000000 ?        */
+ { SYS_DVBS, QPSK, FEC_7_8,  0x80, 0x32 }, /* 10000000 00110010 */
+ { SYS_DVBS, QPSK, FEC_8_9,  0xfe, 0x30 }, /* 0000000? ?        */
+ { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
+ /* NBC-QPSK */
+ { SYS_DVBS2, QPSK, FEC_1_2,  0x00, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5,  0x00, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3,  0x00, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4,  0x00, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5,  0x00, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6,  0x00, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9,  0x00, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
+ /* 8PSK */
+ { SYS_DVBS2, PSK_8, FEC_3_5,  0x00, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3,  0x00, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4,  0x00, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6,  0x00, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9,  0x00, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
+ /*
+  * `val' can be found in the FECSTATUS register when tuning.
+  * FECSTATUS will give the actual FEC in use if tuning was successful.
+  */
+};
+
+static int cx24116_lookup_fecmod(struct cx24116_state* state,
+       fe_modulation_t m, fe_code_rate_t f)
+{
+       int i, ret = -EOPNOTSUPP;
+
+       dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
+
+       for(i=0 ; i < sizeof(CX24116_MODFEC_MODES) / sizeof(struct cx24116_modfec) ; i++)
+       {
+               if( (m == CX24116_MODFEC_MODES[i].modulation) &&
+                       (f == CX24116_MODFEC_MODES[i].fec) )
+                       {
+                               ret = i;
+                               break;
+                       }
+       }
+
+       return ret;
+}
+
+static int cx24116_set_fec(struct cx24116_state* state, fe_modulation_t mod, fe_code_rate_t fec)
+{
+       int ret = 0;
+
+       dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
+
+       ret = cx24116_lookup_fecmod(state, mod, fec);
+
+       if(ret < 0)
+               return ret;
+
+       state->dnxt.fec = fec;
+       state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
+       state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
+       dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
+               state->dnxt.fec_mask, state->dnxt.fec_val);
+
+       return 0;
+}
+
+static int cx24116_set_symbolrate(struct cx24116_state* state, u32 rate)
+{
+       dprintk("%s(%d)\n", __func__, rate);
+
+       /*  check if symbol rate is within limits */
+       if ((rate > state->frontend.ops.info.symbol_rate_max) ||
+           (rate < state->frontend.ops.info.symbol_rate_min)) {
+               dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
+               return -EOPNOTSUPP;
+       }
+
+       state->dnxt.symbol_rate = rate;
+       dprintk("%s() symbol_rate = %d\n", __func__, rate);
+
+       return 0;
+}
+
+static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw);
+
+static int cx24116_firmware_ondemand(struct dvb_frontend* fe)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       const struct firmware *fw;
+       int ret = 0;
+
+       dprintk("%s()\n",__func__);
+
+       if (cx24116_readreg(state, 0x20) > 0)
+       {
+
+               if (state->skip_fw_load)
+                       return 0;
+
+               /* Load firmware */
+               /* request the firmware, this will block until someone uploads it */
+               printk("%s: Waiting for firmware upload (%s)...\n", __func__, CX24116_DEFAULT_FIRMWARE);
+               ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE, &state->i2c->dev);
+               printk("%s: Waiting for firmware upload(2)...\n", __func__);
+               if (ret) {
+                       printk("%s: No firmware uploaded (timeout or file not found?)\n", __func__);
+                       return ret;
+               }
+
+               /* Make sure we don't recurse back through here during loading */
+               state->skip_fw_load = 1;
+
+               ret = cx24116_load_firmware(fe, fw);
+               if (ret)
+                       printk("%s: Writing firmware to device failed\n", __func__);
+
+               release_firmware(fw);
+
+               printk("%s: Firmware upload %s\n", __func__, ret == 0 ? "complete" : "failed");
+
+               /* Ensure firmware is always loaded if required */
+               state->skip_fw_load = 0;
+       }
+
+       return ret;
+}
+
+/* Take a basic firmware command structure, format it and forward it for processing */
+static int cx24116_cmd_execute(struct dvb_frontend* fe, struct cx24116_cmd *cmd)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       int i, ret;
+
+       dprintk("%s()\n", __func__);
+
+       /* Load the firmware if required */
+       if ( (ret = cx24116_firmware_ondemand(fe)) != 0)
+       {
+               printk("%s(): Unable initialise the firmware\n", __func__);
+               return ret;
+       }
+
+       /* Write the command */
+       for(i = 0; i < cmd->len ; i++)
+       {
+               dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
+               cx24116_writereg(state, i, cmd->args[i]);
+       }
+
+       /* Start execution and wait for cmd to terminate */
+       cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
+       while( cx24116_readreg(state, CX24116_REG_EXECUTE) )
+       {
+               msleep(10);
+               if(i++ > 64)
+               {
+                       /* Avoid looping forever if the firmware does no respond */
+                       printk("%s() Firmware not responding\n", __func__);
+                       return -EREMOTEIO;
+               }
+       }
+       return 0;
+}
+
+static int cx24116_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+       struct cx24116_state* state = fe->demodulator_priv;
+       struct cx24116_cmd cmd;
+       int i, ret;
+       unsigned char vers[4];
+
+       dprintk("%s\n", __func__);
+       dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n"
+                       ,fw->size
+                       ,fw->data[0]
+                       ,fw->data[1]
+                       ,fw->data[ fw->size-2 ]
+                       ,fw->data[ fw->size-1 ]
+                       );
+
+       /* Toggle 88x SRST pin to reset demod */
+       if (state->config->reset_device)
+               state->config->reset_device(fe);
+
+       /* Begin the firmware load process */
+       /* Prepare the demod, load the firmware, cleanup after load */
+
+       /* Init PLL */
+       cx24116_writereg(state, 0xE5, 0x00);
+       cx24116_writereg(state, 0xF1, 0x08);
+       cx24116_writereg(state, 0xF2, 0x13);
+
+       /* Start PLL */
+       cx24116_writereg(state, 0xe0, 0x03);
+       cx24116_writereg(state, 0xe0, 0x00);
+
+       /* Unknown */
+       cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+       cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+
+       /* Unknown */
+       cx24116_writereg(state, 0xF0, 0x03);
+       cx24116_writereg(state, 0xF4, 0x81);
+       cx24116_writereg(state, 0xF5, 0x00);
+       cx24116_writereg(state, 0xF6, 0x00);
+
+       /* write the entire firmware as one transaction */
+       cx24116_writeregN(state, 0xF7, fw->data, fw->size);
+
+       cx24116_writereg(state, 0xF4, 0x10);
+       cx24116_writereg(state, 0xF0, 0x00);
+       cx24116_writereg(state, 0xF8, 0x06);
+
+       /* Firmware CMD 10: VCO config */
+       cmd.args[0x00] = CMD_SET_VCO;
+       cmd.args[0x01] = 0x05;
+       cmd.args[0x02] = 0xdc;
+       cmd.args[0x03] = 0xda;
+       cmd.args[0x04] = 0xae;
+       cmd.args[0x05] = 0xaa;
+       cmd.args[0x06] = 0x04;
+       cmd.args[0x07] = 0x9d;
+       cmd.args[0x08] = 0xfc;
+       cmd.args[0x09] = 0x06;
+       cmd.len= 0x0a;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
+
+       /* Firmware CMD 14: Tuner config */
+       cmd.args[0x00] = CMD_TUNERINIT;
+       cmd.args[0x01] = 0x00;
+       cmd.args[0x02] = 0x00;
+       cmd.len= 0x03;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       cx24116_writereg(state, 0xe5, 0x00);
+
+       /* Firmware CMD 13: MPEG config */
+       cmd.args[0x00] = CMD_MPEGCONFIG;
+       cmd.args[0x01] = 0x01;
+       cmd.args[0x02] = 0x75;
+       cmd.args[0x03] = 0x00;
+       if (state->config->mpg_clk_pos_pol)
+               cmd.args[0x04] = state->config->mpg_clk_pos_pol;
+       else
+               cmd.args[0x04] = 0x02;
+       cmd.args[0x05] = 0x00;
+       cmd.len= 0x06;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       /* Firmware CMD 35: Get firmware version */
+       cmd.args[0x00] = CMD_UPDFWVERS;
+       cmd.len= 0x02;
+       for(i=0; i<4; i++) {
+               cmd.args[0x01] = i;
+               ret = cx24116_cmd_execute(fe, &cmd);
+               if (ret != 0)
+                       return ret;
+               vers[i]= cx24116_readreg(state, CX24116_REG_MAILBOX);
+       }
+       printk("%s: FW version %i.%i.%i.%i\n", __func__,
+               vers[0], vers[1], vers[2], vers[3]);
+
+       return 0;
+}
+
+static int cx24116_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+       /* The isl6421 module will override this function in the fops. */
+       dprintk("%s() This should never appear if the isl6421 module is loaded correctly\n",__func__);
+
+       return -EOPNOTSUPP;
+}
+
+static int cx24116_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+
+       int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
+
+       dprintk("%s: status = 0x%02x\n", __func__, lock);
+
+       *status = 0;
+
+       if (lock & CX24116_HAS_SIGNAL)
+               *status |= FE_HAS_SIGNAL;
+       if (lock & CX24116_HAS_CARRIER)
+               *status |= FE_HAS_CARRIER;
+       if (lock & CX24116_HAS_VITERBI)
+               *status |= FE_HAS_VITERBI;
+       if (lock & CX24116_HAS_SYNCLOCK)
+               *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int cx24116_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       *ber =  ( cx24116_readreg(state, CX24116_REG_BER24) << 24 ) |
+               ( cx24116_readreg(state, CX24116_REG_BER16) << 16 ) |
+               ( cx24116_readreg(state, CX24116_REG_BER8 ) << 8  ) |
+                 cx24116_readreg(state, CX24116_REG_BER0 );
+
+       return 0;
+}
+
+/* TODO Determine function and scale appropriately */
+static int cx24116_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       struct cx24116_cmd cmd;
+       int ret;
+       u16 sig_reading;
+
+       dprintk("%s()\n", __func__);
+
+       /* Firmware CMD 19: Get AGC */
+       cmd.args[0x00] = CMD_GETAGC;
+       cmd.len= 0x01;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       sig_reading = ( cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK ) |
+               ( cx24116_readreg(state, CX24116_REG_SIGNAL) << 6 );
+       *signal_strength= 0 - sig_reading;
+
+       dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__, sig_reading, *signal_strength);
+
+       return 0;
+}
+
+/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
+static int cx24116_read_snr_pct(struct dvb_frontend* fe, u16* snr)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       u8 snr_reading;
+       static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
+               0x00000,0x0199A,0x03333,0x04ccD,0x06667,
+                       0x08000,0x0999A,0x0b333,0x0cccD,0x0e667,
+               0x10000,0x1199A,0x13333,0x14ccD,0x16667,0x18000 };
+
+       dprintk("%s()\n", __func__);
+
+       snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+       if(snr_reading >= 0xa0 /* 100% */)
+               *snr = 0xffff;
+       else
+               *snr = snr_tab [ ( snr_reading & 0xf0 )   >> 4 ] +
+                       ( snr_tab [ ( snr_reading & 0x0f ) ] >> 4 );
+
+       dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
+               snr_reading, *snr);
+
+       return 0;
+}
+
+/* The reelbox patches show the value in the registers represents
+ * ESNO, from 0->30db (values 0->300). We provide this value by
+ * default.
+ */
+static int cx24116_read_snr_esno(struct dvb_frontend* fe, u16* snr)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       *snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
+               cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+       dprintk("%s: raw 0x%04x\n", __func__, *snr);
+
+       return 0;
+}
+
+static int cx24116_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+       if (esno_snr == 1)
+               return cx24116_read_snr_esno(fe, snr);
+       else
+               return cx24116_read_snr_pct(fe, snr);
+}
+
+static int cx24116_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+
+       dprintk("%s()\n", __func__);
+
+       *ucblocks = ( cx24116_readreg(state, CX24116_REG_UCB8) << 8 ) |
+               cx24116_readreg(state, CX24116_REG_UCB0);
+
+       return 0;
+}
+
+/* Overwrite the current tuning params, we are about to tune */
+static void cx24116_clone_params(struct dvb_frontend* fe)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
+}
+
+/* Wait for LNB */
+static int cx24116_wait_for_lnb(struct dvb_frontend* fe)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       int i;
+
+       dprintk("%s() qstatus = 0x%02x\n", __func__,
+               cx24116_readreg(state, CX24116_REG_QSTATUS));
+
+       /* Wait for up to 300 ms */
+       for(i = 0; i < 30 ; i++) {
+               if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
+                       return 0;
+               msleep(10);
+       }
+
+       dprintk("%s(): LNB not ready\n", __func__);
+
+       return -ETIMEDOUT; /* -EBUSY ? */
+}
+
+static int cx24116_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct cx24116_cmd cmd;
+       int ret;
+
+       dprintk("%s(%d)\n", __func__, tone);
+       if ( (tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF) ) {
+               printk("%s: Invalid, tone=%d\n", __func__, tone);
+               return -EINVAL;
+       }
+
+       /* Wait for LNB ready */
+       ret = cx24116_wait_for_lnb(fe);
+       if(ret != 0)
+               return ret;
+
+       /* Min delay time after DiSEqC send */
+       msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+       /* This is always done before the tone is set */
+       cmd.args[0x00] = CMD_SET_TONEPRE;
+       cmd.args[0x01] = 0x00;
+       cmd.len= 0x02;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       /* Now we set the tone */
+       cmd.args[0x00] = CMD_SET_TONE;
+       cmd.args[0x01] = 0x00;
+       cmd.args[0x02] = 0x00;
+
+       switch (tone) {
+       case SEC_TONE_ON:
+               dprintk("%s: setting tone on\n", __func__);
+               cmd.args[0x03] = 0x01;
+               break;
+       case SEC_TONE_OFF:
+               dprintk("%s: setting tone off\n",__func__);
+               cmd.args[0x03] = 0x00;
+               break;
+       }
+       cmd.len= 0x04;
+
+       /* Min delay time before DiSEqC send */
+       msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+       return cx24116_cmd_execute(fe, &cmd);
+}
+
+/* Initialise DiSEqC */
+static int cx24116_diseqc_init(struct dvb_frontend* fe)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       struct cx24116_cmd cmd;
+       int ret;
+
+       /* Firmware CMD 20: LNB/DiSEqC config */
+       cmd.args[0x00] = CMD_LNBCONFIG;
+       cmd.args[0x01] = 0x00;
+       cmd.args[0x02] = 0x10;
+       cmd.args[0x03] = 0x00;
+       cmd.args[0x04] = 0x8f;
+       cmd.args[0x05] = 0x28;
+       cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
+       cmd.args[0x07] = 0x01;
+       cmd.len= 0x08;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       /* Prepare a DiSEqC command */
+       state->dsec_cmd.args[0x00] = CMD_LNBSEND;
+
+       /* DiSEqC burst */
+       state->dsec_cmd.args[CX24116_DISEQC_BURST]  = CX24116_DISEQC_MINI_A;
+
+       /* Unknown */
+       state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
+       state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
+       state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00; /* Continuation flag? */
+
+       /* DiSEqC message length */
+       state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
+
+       /* Command length */
+       state->dsec_cmd.len= CX24116_DISEQC_MSGOFS;
+
+       return 0;
+}
+
+/* Send DiSEqC message with derived burst (hack) || previous burst */
+static int cx24116_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *d)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       int i, ret;
+
+       /* Dump DiSEqC message */
+       if (debug) {
+               printk("cx24116: %s(", __func__);
+               for(i = 0 ; i < d->msg_len ;) {
+                       printk("0x%02x", d->msg[i]);
+                       if(++i < d->msg_len)
+                               printk(", ");
+                       }
+               printk(") toneburst=%d\n", toneburst);
+       }
+
+       /* Validate length */
+       if(d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
+               return -EINVAL;
+
+       /* DiSEqC message */
+       for (i = 0; i < d->msg_len; i++)
+               state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
+
+       /* DiSEqC message length */
+       state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
+
+       /* Command length */
+       state->dsec_cmd.len= CX24116_DISEQC_MSGOFS + state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
+
+       /* DiSEqC toneburst */
+       if(toneburst == CX24116_DISEQC_MESGCACHE)
+               /* Message is cached */
+               return 0;
+
+       else if(toneburst == CX24116_DISEQC_TONEOFF)
+               /* Message is sent without burst */
+               state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
+
+       else if(toneburst == CX24116_DISEQC_TONECACHE) {
+               /*
+                * Message is sent with derived else cached burst
+                *
+                * WRITE PORT GROUP COMMAND 38
+                *
+                * 0/A/A: E0 10 38 F0..F3
+                * 1/B/B: E0 10 38 F4..F7
+                * 2/C/A: E0 10 38 F8..FB
+                * 3/D/B: E0 10 38 FC..FF
+                *
+                * databyte[3]= 8421:8421
+                *              ABCD:WXYZ
+                *              CLR :SET
+                *
+                *              WX= PORT SELECT 0..3    (X=TONEBURST)
+                *              Y = VOLTAGE             (0=13V, 1=18V)
+                *              Z = BAND                (0=LOW, 1=HIGH(22K))
+                */
+               if(d->msg_len >= 4 && d->msg[2] == 0x38)
+                       state->dsec_cmd.args[CX24116_DISEQC_BURST] = ((d->msg[3] & 4) >> 2);
+               if(debug)
+                       dprintk("%s burst=%d\n", __func__, state->dsec_cmd.args[CX24116_DISEQC_BURST]);
+       }
+
+       /* Wait for LNB ready */
+       ret = cx24116_wait_for_lnb(fe);
+       if(ret != 0)
+               return ret;
+
+       /* Wait for voltage/min repeat delay */
+       msleep(100);
+
+       /* Command */
+       ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+       if(ret != 0)
+               return ret;
+       /*
+        * Wait for send
+        *
+        * Eutelsat spec:
+        * >15ms delay          + (XXX determine if FW does this, see set_tone)
+        *  13.5ms per byte     +
+        * >15ms delay          +
+        *  12.5ms burst        +
+        * >15ms delay            (XXX determine if FW does this, see set_tone)
+        */
+       msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + ((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60) );
+
+       return 0;
+}
+
+/* Send DiSEqC burst */
+static int cx24116_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       int ret;
+
+       dprintk("%s(%d) toneburst=%d\n",__func__, burst, toneburst);
+
+       /* DiSEqC burst */
+       if (burst == SEC_MINI_A)
+               state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_A;
+       else if(burst == SEC_MINI_B)
+               state->dsec_cmd.args[CX24116_DISEQC_BURST] = CX24116_DISEQC_MINI_B;
+       else
+               return -EINVAL;
+
+       /* DiSEqC toneburst */
+       if(toneburst != CX24116_DISEQC_MESGCACHE)
+               /* Burst is cached */
+               return 0;
+
+       /* Burst is to be sent with cached message */
+
+       /* Wait for LNB ready */
+       ret = cx24116_wait_for_lnb(fe);
+       if(ret != 0)
+               return ret;
+
+       /* Wait for voltage/min repeat delay */
+       msleep(100);
+
+       /* Command */
+       ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+       if(ret != 0)
+               return ret;
+
+       /*
+        * Wait for send
+        *
+        * Eutelsat spec:
+        * >15ms delay          + (XXX determine if FW does this, see set_tone)
+        *  13.5ms per byte     +
+        * >15ms delay          +
+        *  12.5ms burst        +
+        * >15ms delay            (XXX determine if FW does this, see set_tone)
+        */
+       msleep( (state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60 );
+
+       return 0;
+}
+
+static void cx24116_release(struct dvb_frontend* fe)
+{
+       struct cx24116_state* state = fe->demodulator_priv;
+       dprintk("%s\n",__func__);
+       kfree(state);
+}
+
+static struct dvb_frontend_ops cx24116_ops;
+
+struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
+                                   struct i2c_adapter* i2c)
+{
+       struct cx24116_state* state = NULL;
+       int ret;
+
+       dprintk("%s\n",__func__);
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL);
+       if (state == NULL) {
+               printk("Unable to kmalloc\n");
+               goto error1;
+       }
+
+       /* setup the state */
+       memset(state, 0, sizeof(struct cx24116_state));
+
+       state->config = config;
+       state->i2c = i2c;
+
+       /* check if the demod is present */
+       ret = (cx24116_readreg(state, 0xFF) << 8) | cx24116_readreg(state, 0xFE);
+       if (ret != 0x0501) {
+               printk("Invalid probe, probably not a CX24116 device\n");
+               goto error2;
+       }
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &cx24116_ops, sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error2: kfree(state);
+error1: return NULL;
+}
+/*
+ * Initialise or wake up device
+ *
+ * Power config will reset and load initial firmware if required
+ */
+static int cx24116_initfe(struct dvb_frontend* fe)
+{
+       struct cx24116_state* state = fe->demodulator_priv;
+       struct cx24116_cmd cmd;
+       int ret;
+
+       dprintk("%s()\n",__func__);
+
+       /* Power on */
+       cx24116_writereg(state, 0xe0, 0);
+       cx24116_writereg(state, 0xe1, 0);
+       cx24116_writereg(state, 0xea, 0);
+
+       /* Firmware CMD 36: Power config */
+       cmd.args[0x00] = CMD_TUNERSLEEP;
+       cmd.args[0x01] = 0;
+       cmd.len= 0x02;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if(ret != 0)
+               return ret;
+
+       return cx24116_diseqc_init(fe);
+}
+
+/*
+ * Put device to sleep
+ */
+static int cx24116_sleep(struct dvb_frontend* fe)
+{
+       struct cx24116_state* state = fe->demodulator_priv;
+       struct cx24116_cmd cmd;
+       int ret;
+
+       dprintk("%s()\n",__func__);
+
+       /* Firmware CMD 36: Power config */
+       cmd.args[0x00] = CMD_TUNERSLEEP;
+       cmd.args[0x01] = 1;
+       cmd.len= 0x02;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if(ret != 0)
+               return ret;
+
+       /* Power off (Shutdown clocks) */
+       cx24116_writereg(state, 0xea, 0xff);
+       cx24116_writereg(state, 0xe1, 1);
+       cx24116_writereg(state, 0xe0, 1);
+
+       return 0;
+}
+
+static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+static int cx24116_get_property(struct dvb_frontend *fe, struct dtv_property* tvp)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+/* dvb-core told us to tune, the tv property cache will be complete,
+ * it's safe for is to pull values and use them for tuning purposes.
+ */
+static int cx24116_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+       struct cx24116_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct cx24116_cmd cmd;
+       fe_status_t tunerstat;
+       int i, status, ret, retune;
+
+       dprintk("%s()\n",__func__);
+
+       switch(c->delivery_system) {
+               case SYS_DVBS:
+                       dprintk("%s: DVB-S delivery system selected\n",__func__);
+
+                       /* Only QPSK is supported for DVB-S */
+                       if(c->modulation != QPSK) {
+                               dprintk("%s: unsupported modulation selected (%d)\n",
+                                       __func__, c->modulation);
+                               return -EOPNOTSUPP;
+                       }
+
+                       /* Pilot doesn't exist in DVB-S, turn bit off */
+                       state->dnxt.pilot_val = CX24116_PILOT_OFF;
+                       retune = 1;
+
+                       /* DVB-S only supports 0.35 */
+                       if(c->rolloff != ROLLOFF_35) {
+                               dprintk("%s: unsupported rolloff selected (%d)\n",
+                                       __func__, c->rolloff);
+                               return -EOPNOTSUPP;
+                       }
+                       state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+                       break;
+
+               case SYS_DVBS2:
+                       dprintk("%s: DVB-S2 delivery system selected\n",__func__);
+
+                       /*
+                        * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
+                        * but not hardware auto detection
+                        */
+                       if(c->modulation != PSK_8 && c->modulation != QPSK) {
+                               dprintk("%s: unsupported modulation selected (%d)\n",
+                                       __func__, c->modulation);
+                               return -EOPNOTSUPP;
+                       }
+
+                       switch(c->pilot) {
+                               case PILOT_AUTO:        /* Not supported but emulated */
+                                       retune = 2;     /* Fall-through */
+                               case PILOT_OFF:
+                                       state->dnxt.pilot_val = CX24116_PILOT_OFF;
+                                       break;
+                               case PILOT_ON:
+                                       state->dnxt.pilot_val = CX24116_PILOT_ON;
+                                       break;
+                               default:
+                                       dprintk("%s: unsupported pilot mode selected (%d)\n",
+                                               __func__, c->pilot);
+                                       return -EOPNOTSUPP;
+                       }
+
+                       switch(c->rolloff) {
+                               case ROLLOFF_20:
+                                       state->dnxt.rolloff_val= CX24116_ROLLOFF_020;
+                                       break;
+                               case ROLLOFF_25:
+                                       state->dnxt.rolloff_val= CX24116_ROLLOFF_025;
+                                       break;
+                               case ROLLOFF_35:
+                                       state->dnxt.rolloff_val= CX24116_ROLLOFF_035;
+                                       break;
+                               case ROLLOFF_AUTO:      /* Rolloff must be explicit */
+                               default:
+                                       dprintk("%s: unsupported rolloff selected (%d)\n",
+                                               __func__, c->rolloff);
+                                       return -EOPNOTSUPP;
+                       }
+                       break;
+
+               default:
+                       dprintk("%s: unsupported delivery system selected (%d)\n",
+                               __func__, c->delivery_system);
+                       return -EOPNOTSUPP;
+       }
+       state->dnxt.modulation = c->modulation;
+       state->dnxt.frequency = c->frequency;
+       state->dnxt.pilot = c->pilot;
+       state->dnxt.rolloff = c->rolloff;
+
+       if ((ret = cx24116_set_inversion(state, c->inversion)) !=  0)
+               return ret;
+
+       /* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
+       if ((ret = cx24116_set_fec(state, c->modulation, c->fec_inner)) !=  0)
+               return ret;
+
+       if ((ret = cx24116_set_symbolrate(state, c->symbol_rate)) !=  0)
+               return ret;
+
+       /* discard the 'current' tuning parameters and prepare to tune */
+       cx24116_clone_params(fe);
+
+       dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);
+       dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
+       dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,
+               state->dcur.pilot, state->dcur.pilot_val);
+       dprintk("%s:   retune      = %d\n", __func__, retune);
+       dprintk("%s:   rolloff     = %d (val = 0x%02x)\n", __func__,
+               state->dcur.rolloff, state->dcur.rolloff_val);
+       dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
+       dprintk("%s:   FEC         = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
+               state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
+       dprintk("%s:   Inversion   = %d (val = 0x%02x)\n", __func__,
+               state->dcur.inversion, state->dcur.inversion_val);
+
+       /* This is also done in advise/acquire on HVR4000 but not on LITE */
+       if (state->config->set_ts_params)
+               state->config->set_ts_params(fe, 0);
+
+       /* Set/Reset B/W */
+       cmd.args[0x00] = CMD_BANDWIDTH;
+       cmd.args[0x01] = 0x01;
+       cmd.len= 0x02;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       /* Prepare a tune request */
+       cmd.args[0x00] = CMD_TUNEREQUEST;
+
+       /* Frequency */
+       cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
+       cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
+       cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
+
+       /* Symbol Rate */
+       cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
+       cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
+
+       /* Automatic Inversion */
+       cmd.args[0x06] = state->dcur.inversion_val;
+
+       /* Modulation / FEC / Pilot */
+       cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
+
+       cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
+       cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
+       cmd.args[0x0a] = 0x00;
+       cmd.args[0x0b] = 0x00;
+       cmd.args[0x0c] = state->dcur.rolloff_val;
+       cmd.args[0x0d] = state->dcur.fec_mask;
+
+       if (state->dcur.symbol_rate > 30000000) {
+               cmd.args[0x0e] = 0x04;
+               cmd.args[0x0f] = 0x00;
+               cmd.args[0x10] = 0x01;
+               cmd.args[0x11] = 0x77;
+               cmd.args[0x12] = 0x36;
+               cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
+               cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
+       } else {
+               cmd.args[0x0e] = 0x06;
+               cmd.args[0x0f] = 0x00;
+               cmd.args[0x10] = 0x00;
+               cmd.args[0x11] = 0xFA;
+               cmd.args[0x12] = 0x24;
+               cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+               cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+       }
+
+       cmd.len= 0x13;
+
+       /* We need to support pilot and non-pilot tuning in the
+        * driver automatically. This is a workaround for because
+        * the demod does not support autodetect.
+        */
+       do {
+               /* Reset status register */
+               status = cx24116_readreg(state, CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK;
+               cx24116_writereg(state, CX24116_REG_SSTATUS, status);
+
+               /* Tune */
+               ret = cx24116_cmd_execute(fe, &cmd);
+               if( ret != 0 )
+                       break;
+
+               /*
+                * Wait for up to 500 ms before retrying
+                *
+                * If we are able to tune then generally it occurs within 100ms.
+                * If it takes longer, try a different toneburst setting.
+                */
+               for(i = 0; i < 50 ; i++) {
+                       cx24116_read_status(fe, &tunerstat);
+                       status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
+                       if(status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
+                               dprintk("%s: Tuned\n",__func__);
+                               goto tuned;
+                       }
+                       msleep(10);
+               }
+
+               dprintk("%s: Not tuned\n",__func__);
+
+               /* Toggle pilot bit when in auto-pilot */
+               if(state->dcur.pilot == PILOT_AUTO)
+                       cmd.args[0x07] ^= CX24116_PILOT_ON;
+       }
+       while(--retune);
+
+tuned:  /* Set/Reset B/W */
+       cmd.args[0x00] = CMD_BANDWIDTH;
+       cmd.args[0x01] = 0x00;
+       cmd.len= 0x02;
+       ret = cx24116_cmd_execute(fe, &cmd);
+       if (ret != 0)
+               return ret;
+
+       return ret;
+}
+
+static struct dvb_frontend_ops cx24116_ops = {
+
+       .info = {
+               .name = "Conexant CX24116/CX24118",
+               .type = FE_QPSK,
+               .frequency_min = 950000,
+               .frequency_max = 2150000,
+               .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+               .frequency_tolerance = 5000,
+               .symbol_rate_min = 1000000,
+               .symbol_rate_max = 45000000,
+               .caps = FE_CAN_INVERSION_AUTO |
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+                       FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_RECOVER
+       },
+
+       .release = cx24116_release,
+
+       .init = cx24116_initfe,
+       .sleep = cx24116_sleep,
+       .read_status = cx24116_read_status,
+       .read_ber = cx24116_read_ber,
+       .read_signal_strength = cx24116_read_signal_strength,
+       .read_snr = cx24116_read_snr,
+       .read_ucblocks = cx24116_read_ucblocks,
+       .set_tone = cx24116_set_tone,
+       .set_voltage = cx24116_set_voltage,
+       .diseqc_send_master_cmd = cx24116_send_diseqc_msg,
+       .diseqc_send_burst = cx24116_diseqc_send_burst,
+
+       .set_property = cx24116_set_property,
+       .get_property = cx24116_get_property,
+       .set_frontend = cx24116_set_frontend,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+module_param(toneburst, int, 0644);
+MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, 2=MESSAGE CACHE (default:1)");
+
+module_param(esno_snr, int, 0644);
+MODULE_PARM_DESC(debug, "SNR return units, 0=PERCENTAGE 0-100, 1=ESNO(db * 10) (default:0)");
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx24116_attach);
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h
new file mode 100644 (file)
index 0000000..8dbcec2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+    Copyright (C) 2006 Steven Toth <stoth@linuxtv.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.
+*/
+
+#ifndef CX24116_H
+#define CX24116_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24116_config
+{
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* Need to set device param for start_dma */
+       int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+       /* Need to reset device during firmware loading */
+       int (*reset_device)(struct dvb_frontend* fe);
+
+       /* Need to set MPEG parameters */
+       u8 mpg_clk_pos_pol:0x02;
+};
+
+#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
+extern struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
+                                          struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx24116_attach(const struct cx24116_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX24116
+
+#endif /* CX24116_H */
index 3eedfdf505bc5d49f6551268dc966544bc17fa83..21f2c5161af4887c2a8e7ff9dc7b4c98762f01f7 100644 (file)
@@ -41,6 +41,7 @@ struct dib0070_config {
 extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
                                           struct i2c_adapter *i2c,
                                           struct dib0070_config *cfg);
+extern u16 dib0070_wbd_offset(struct dvb_frontend *);
 #else
 static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
                                                  struct i2c_adapter *i2c,
@@ -49,9 +50,14 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
+
+static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
 #endif
 
 extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
-extern u16 dib0070_wbd_offset(struct dvb_frontend *);
 
 #endif
index 5f1375e30dfc25e3bff127b8bf6ebbf4ef2e420e..0109720353bd475e6458c347ea42dfca0663d3de 100644 (file)
@@ -1284,7 +1284,10 @@ struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum di
 }
 EXPORT_SYMBOL(dib7000m_get_i2c_master);
 
-int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[])
+#if 0
+/* used with some prototype boards */
+int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
+               u8 default_addr, struct dib7000m_config cfg[])
 {
        struct dib7000m_state st = { .i2c_adap = i2c };
        int k = 0;
@@ -1329,6 +1332,7 @@ int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
        return 0;
 }
 EXPORT_SYMBOL(dib7000m_i2c_enumeration);
+#endif
 
 static struct dvb_frontend_ops dib7000m_ops;
 struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
index 1a0142e0d74166a5576d11f27f4159403fcd78f0..8217e5b38f47064e464942ff3b75fa3b8e8ce53c 100644 (file)
@@ -1333,7 +1333,8 @@ struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
        /* Ensure the output mode remains at the previous default if it's
         * not specifically set by the caller.
         */
-       if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
+       if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
+           (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
                st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
 
        demod                   = &st->demod;
index 07c4d12ed5b7846bf3e9589cd2236fe49668fa9f..3e81268571276f895e2c1d6075d2ba44209953f7 100644 (file)
@@ -41,6 +41,14 @@ struct dib7000p_config {
 extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
                                            u8 i2c_addr,
                                            struct dib7000p_config *cfg);
+extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *,
+                                                  enum dibx000_i2c_interface,
+                                                  int);
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+                                   int no_of_demods, u8 default_addr,
+                                   struct dib7000p_config cfg[]);
+extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
+extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
 #else
 static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
                                                   u8 i2c_addr,
@@ -49,13 +57,36 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif
 
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+static inline
+struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
+                                           enum dibx000_i2c_interface i, int x)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+                                   int no_of_demods, u8 default_addr,
+                                   struct dib7000p_config cfg[])
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+
+extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+
+extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return -ENODEV;
+}
+#endif
 
-extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
 extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
 
 #endif
index 3cbed874a6f8346b28e63e74ac004dc59f29bc1a..b9ca5c8d2dd9400814f64566a24952b541126a0a 100644 (file)
@@ -38,35 +38,32 @@ static const char mod_name[] = "drx397xD";
 #define F_SET_0D0h     1
 #define F_SET_0D4h     2
 
-typedef enum fw_ix {
+enum fw_ix {
 #define _FW_ENTRY(a, b)                b
 #include "drx397xD_fw.h"
-} fw_ix_t;
+};
 
 /* chip specifics */
 struct drx397xD_state {
        struct i2c_adapter *i2c;
        struct dvb_frontend frontend;
        struct drx397xD_config config;
-       fw_ix_t chip_rev;
+       enum fw_ix chip_rev;
        int flags;
        u32 bandwidth_parm;     /* internal bandwidth conversions */
        u32 f_osc;              /* w90: actual osc frequency [Hz] */
 };
 
-/*******************************************************************************
- * Firmware
- ******************************************************************************/
-
+/* Firmware */
 static const char *blob_name[] = {
 #define _BLOB_ENTRY(a, b)              a
 #include "drx397xD_fw.h"
 };
 
-typedef enum blob_ix {
+enum blob_ix {
 #define _BLOB_ENTRY(a, b)              b
 #include "drx397xD_fw.h"
-} blob_ix_t;
+};
 
 static struct {
        const char *name;
@@ -85,7 +82,7 @@ static struct {
 };
 
 /* use only with writer lock aquired */
-static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+static void _drx_release_fw(struct drx397xD_state *s, enum fw_ix ix)
 {
        memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
        if (fw[ix].file)
@@ -94,9 +91,9 @@ static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
 
 static void drx_release_fw(struct drx397xD_state *s)
 {
-       fw_ix_t ix = s->chip_rev;
+       enum fw_ix ix = s->chip_rev;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        write_lock(&fw[ix].lock);
        if (fw[ix].refcnt) {
@@ -107,13 +104,13 @@ static void drx_release_fw(struct drx397xD_state *s)
        write_unlock(&fw[ix].lock);
 }
 
-static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+static int drx_load_fw(struct drx397xD_state *s, enum fw_ix ix)
 {
        const u8 *data;
        size_t size, len;
        int i = 0, j, rc = -EINVAL;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if (ix < 0 || ix >= ARRAY_SIZE(fw))
                return -EINVAL;
@@ -175,32 +172,34 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
                        goto exit_corrupt;
                }
        } while (i < size);
-      exit_corrupt:
+
+exit_corrupt:
        printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
-      exit_err:
+exit_err:
        _drx_release_fw(s, ix);
        fw[ix].refcnt--;
-      exit_ok:
+exit_ok:
        fw[ix].refcnt++;
        write_unlock(&fw[ix].lock);
+
        return rc;
 }
 
-/*******************************************************************************
- * i2c bus IO
- ******************************************************************************/
-
-static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+/* i2c bus IO */
+static int write_fw(struct drx397xD_state *s, enum blob_ix ix)
 {
-       struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
        const u8 *data;
        int len, rc = 0, i = 0;
+       struct i2c_msg msg = {
+               .addr = s->config.demod_address,
+               .flags = 0
+       };
 
        if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
-               pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+               pr_debug("%s drx_fw_ix_t out of range\n", __func__);
                return -EINVAL;
        }
-       pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+       pr_debug("%s %s\n", __func__, blob_name[ix]);
 
        read_lock(&fw[s->chip_rev].lock);
        data = fw[s->chip_rev].data[ix];
@@ -229,33 +228,33 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
                        goto exit_rc;
                }
        }
-      exit_rc:
+exit_rc:
        read_unlock(&fw[s->chip_rev].lock);
+
        return 0;
 }
 
 /* Function is not endian safe, use the RD16 wrapper below */
-static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+static int _read16(struct drx397xD_state *s, __le32 i2c_adr)
 {
        int rc;
        u8 a[4];
-       u16 v;
+       __le16 v;
        struct i2c_msg msg[2] = {
                {
-                .addr = s->config.demod_address,
-                .flags = 0,
-                .buf = a,
-                .len = sizeof(a)
-                }
-               , {
-                  .addr = s->config.demod_address,
-                  .flags = I2C_M_RD,
-                  .buf = (u8 *) & v,
-                  .len = sizeof(v)
-                  }
+                       .addr = s->config.demod_address,
+                       .flags = 0,
+                       .buf = a,
+                       .len = sizeof(a)
+               }, {
+                       .addr = s->config.demod_address,
+                       .flags = I2C_M_RD,
+                       .buf = (u8 *)&v,
+                       .len = sizeof(v)
+               }
        };
 
-       *(u32 *) a = i2c_adr;
+       *(__le32 *) a = i2c_adr;
 
        rc = i2c_transfer(s->i2c, msg, 2);
        if (rc != 2)
@@ -265,7 +264,7 @@ static int _read16(struct drx397xD_state *s, u32 i2c_adr)
 }
 
 /* Function is not endian safe, use the WR16.. wrappers below */
-static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+static int _write16(struct drx397xD_state *s, __le32 i2c_adr, __le16 val)
 {
        u8 a[6];
        int rc;
@@ -276,28 +275,28 @@ static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
                .len = sizeof(a)
        };
 
-       *(u32 *) a = i2c_adr;
-       *(u16 *) & a[4] = val;
+       *(__le32 *)a = i2c_adr;
+       *(__le16 *)&a[4] = val;
 
        rc = i2c_transfer(s->i2c, &msg, 1);
        if (rc != 1)
                return -EIO;
+
        return 0;
 }
 
-#define WR16(ss,adr, val) \
+#define WR16(ss, adr, val) \
                _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
-#define WR16_E0(ss,adr, val) \
+#define WR16_E0(ss, adr, val) \
                _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
-#define RD16(ss,adr) \
+#define RD16(ss, adr) \
                _read16(ss, I2C_ADR_C0(adr))
 
-#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
-
-/*******************************************************************************
- * Tuner callback
- ******************************************************************************/
+#define EXIT_RC(cmd)   \
+       if ((rc = (cmd)) < 0)   \
+               goto exit_rc
 
+/* Tuner callback */
 static int PLL_Set(struct drx397xD_state *s,
                   struct dvb_frontend_parameters *fep, int *df_tuner)
 {
@@ -305,7 +304,7 @@ static int PLL_Set(struct drx397xD_state *s,
        u32 f_tuner, f = fep->frequency;
        int rc;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
            (f < s->frontend.ops.tuner_ops.info.frequency_min))
@@ -325,28 +324,26 @@ static int PLL_Set(struct drx397xD_state *s,
                return rc;
 
        *df_tuner = f_tuner - f;
-       pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+       pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __func__, f,
                 f_tuner);
 
        return 0;
 }
 
-/*******************************************************************************
- * Demodulator helper functions
- ******************************************************************************/
-
+/* Demodulator helper functions */
 static int SC_WaitForReady(struct drx397xD_state *s)
 {
        int cnt = 1000;
        int rc;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        while (cnt--) {
                rc = RD16(s, 0x820043);
                if (rc == 0)
                        return 0;
        }
+
        return -1;
 }
 
@@ -354,13 +351,14 @@ static int SC_SendCommand(struct drx397xD_state *s, int cmd)
 {
        int rc;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        WR16(s, 0x820043, cmd);
        SC_WaitForReady(s);
        rc = RD16(s, 0x820042);
        if ((rc & 0xffff) == 0xffff)
                return -1;
+
        return 0;
 }
 
@@ -368,7 +366,7 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd)
 {
        int rc, cnt = 1000;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        rc = WR16(s, 0x420032, cmd);
        if (rc < 0)
@@ -383,22 +381,24 @@ static int HI_Command(struct drx397xD_state *s, u16 cmd)
                if (rc < 0)
                        return rc;
        } while (--cnt);
+
        return rc;
 }
 
 static int HI_CfgCommand(struct drx397xD_state *s)
 {
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        WR16(s, 0x420033, 0x3973);
-       WR16(s, 0x420034, s->config.w50);       // code 4, log 4
-       WR16(s, 0x420035, s->config.w52);       // code 15,  log 9
+       WR16(s, 0x420034, s->config.w50);       /* code 4, log 4 */
+       WR16(s, 0x420035, s->config.w52);       /* code 15,  log 9 */
        WR16(s, 0x420036, s->config.demod_address << 1);
-       WR16(s, 0x420037, s->config.w56);       // code (set_i2c ??  initX 1 ), log 1
-//      WR16(s, 0x420033, 0x3973);
+       WR16(s, 0x420037, s->config.w56);       /* code (set_i2c ??  initX 1 ), log 1 */
+       /* WR16(s, 0x420033, 0x3973); */
        if ((s->config.w56 & 8) == 0)
                return HI_Command(s, 3);
+
        return WR16(s, 0x420032, 0x3);
 }
 
@@ -419,7 +419,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
        u16 w0C = agc->w0C;
        int quot, rem, i, rc = -EINVAL;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if (agc->w04 > 0x3ff)
                goto exit_rc;
@@ -468,7 +468,7 @@ static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
        i = slowIncrDecLUT_15272[rem / 28];
        EXIT_RC(WR16(s, 0x0c2002b, i));
        rc = WR16(s, 0x0c2002c, i);
-      exit_rc:
+exit_rc:
        return rc;
 }
 
@@ -478,7 +478,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
        u16 w06 = agc->w06;
        int rc = -1;
 
-       pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+       pr_debug("%s %d 0x%x 0x%x\n", __func__, agc->d00, w04, w06);
 
        if (w04 > 0x3ff)
                goto exit_rc;
@@ -498,7 +498,7 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
                rc &= ~2;
                break;
        case 0:
-               // loc_8000659
+               /* loc_8000659 */
                s->config.w9C &= ~2;
                EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
                EXIT_RC(RD16(s, 0x0c20010));
@@ -522,7 +522,8 @@ static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
                rc |= 2;
        }
        rc = WR16(s, 0x0c20013, rc);
-      exit_rc:
+
+exit_rc:
        return rc;
 }
 
@@ -554,7 +555,7 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s)
        int lockstat;
        u32 clk, clk_limit;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if (s->config.d5C == 0) {
                EXIT_RC(WR16(s, 0x08200e8, 0x010));
@@ -598,11 +599,12 @@ static int CorrectSysClockDeviation(struct drx397xD_state *s)
 
        if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
                s->f_osc = clk;
-               pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+               pr_debug("%s: osc %d %d [Hz]\n", __func__,
                         s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
        }
        rc = WR16(s, 0x08200e8, 0);
-      exit_rc:
+
+exit_rc:
        return rc;
 }
 
@@ -610,7 +612,7 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
 {
        int rc, si, bp;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        si = s->config.wA0;
        if (s->config.w98 == 0) {
@@ -620,17 +622,17 @@ static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
                si &= ~1;
                bp = 0x200;
        }
-       if (s->config.w9A == 0) {
+       if (s->config.w9A == 0)
                si |= 0x80;
-       } else {
+       else
                si &= ~0x80;
-       }
 
        EXIT_RC(WR16(s, 0x2150045, 0));
        EXIT_RC(WR16(s, 0x2150010, si));
        EXIT_RC(WR16(s, 0x2150011, bp));
        rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
-      exit_rc:
+
+exit_rc:
        return rc;
 }
 
@@ -646,7 +648,7 @@ static int drx_tune(struct drx397xD_state *s,
 
        int rc, df_tuner;
        int a, b, c, d;
-       pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+       pr_debug("%s %d\n", __func__, s->config.d60);
 
        if (s->config.d60 != 2)
                goto set_tuner;
@@ -658,7 +660,7 @@ static int drx_tune(struct drx397xD_state *s,
        rc = ConfigureMPEGOutput(s, 0);
        if (rc < 0)
                goto set_tuner;
-      set_tuner:
+set_tuner:
 
        rc = PLL_Set(s, fep, &df_tuner);
        if (rc < 0) {
@@ -835,16 +837,16 @@ static int drx_tune(struct drx397xD_state *s,
                rc = WR16(s, 0x2010012, 0);
                if (rc < 0)
                        goto exit_rc;
-               //              QPSK    QAM16   QAM64
-               ebx = 0x19f;    //                 62
-               ebp = 0x1fb;    //                 15
-               v20 = 0x16a;    //  62
-               v1E = 0x195;    //         62
-               v16 = 0x1bb;    //  15
-               v14 = 0x1ef;    //         15
-               v12 = 5;        //  16
-               v10 = 5;        //         16
-               v0E = 5;        //                 16
+                               /* QPSK    QAM16  QAM64 */
+               ebx = 0x19f;    /*                 62   */
+               ebp = 0x1fb;    /*                 15   */
+               v20 = 0x16a;    /*  62                  */
+               v1E = 0x195;    /*         62           */
+               v16 = 0x1bb;    /*  15                  */
+               v14 = 0x1ef;    /*         15           */
+               v12 = 5;        /*  16                  */
+               v10 = 5;        /*         16           */
+               v0E = 5;        /*                 16   */
        }
 
        switch (fep->u.ofdm.constellation) {
@@ -997,17 +999,17 @@ static int drx_tune(struct drx397xD_state *s,
        case BANDWIDTH_8_MHZ:   /* 0 */
        case BANDWIDTH_AUTO:
                rc = WR16(s, 0x0c2003f, 0x32);
-               s->bandwidth_parm = ebx = 0x8b8249;     // 9142857
+               s->bandwidth_parm = ebx = 0x8b8249;
                edx = 0;
                break;
        case BANDWIDTH_7_MHZ:
                rc = WR16(s, 0x0c2003f, 0x3b);
-               s->bandwidth_parm = ebx = 0x7a1200;     // 8000000
+               s->bandwidth_parm = ebx = 0x7a1200;
                edx = 0x4807;
                break;
        case BANDWIDTH_6_MHZ:
                rc = WR16(s, 0x0c2003f, 0x47);
-               s->bandwidth_parm = ebx = 0x68a1b6;     // 6857142
+               s->bandwidth_parm = ebx = 0x68a1b6;
                edx = 0x0f07;
                break;
        };
@@ -1060,8 +1062,6 @@ static int drx_tune(struct drx397xD_state *s,
        WR16(s, 0x0820040, 1);
        SC_SendCommand(s, 1);
 
-//      rc = WR16(s, 0x2150000, 1);
-//      if (rc < 0) goto exit_rc;
 
        rc = WR16(s, 0x2150000, 2);
        rc = WR16(s, 0x2150016, a);
@@ -1069,7 +1069,8 @@ static int drx_tune(struct drx397xD_state *s,
        rc = WR16(s, 0x2150036, 0);
        rc = WR16(s, 0x2150000, 1);
        s->config.d60 = 2;
-      exit_rc:
+
+exit_rc:
        return rc;
 }
 
@@ -1082,7 +1083,7 @@ static int drx397x_init(struct dvb_frontend *fe)
        struct drx397xD_state *s = fe->demodulator_priv;
        int rc;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        s->config.rfagc.d00 = 2;        /* 0x7c */
        s->config.rfagc.w04 = 0;
@@ -1102,18 +1103,18 @@ static int drx397x_init(struct dvb_frontend *fe)
 
        /* HI_CfgCommand */
        s->config.w50 = 4;
-       s->config.w52 = 9;      // 0xf;
+       s->config.w52 = 9;
 
-       s->config.f_if = 42800000;      /* d14: intermediate frequency [Hz]     */
-       s->config.f_osc = 48000;        /* s66 : oscillator frequency [kHz]     */
-       s->config.w92 = 12000;  // 20000;
+       s->config.f_if = 42800000;      /* d14: intermediate frequency [Hz] */
+       s->config.f_osc = 48000;        /* s66 : oscillator frequency [kHz] */
+       s->config.w92 = 12000;
 
        s->config.w9C = 0x000e;
        s->config.w9E = 0x0000;
 
        /* ConfigureMPEGOutput params */
        s->config.wA0 = 4;
-       s->config.w98 = 1;      // 0;
+       s->config.w98 = 1;
        s->config.w9A = 1;
 
        /* get chip revision */
@@ -1248,7 +1249,7 @@ static int drx397x_init(struct dvb_frontend *fe)
                rc = WR16(s, 0x0c20012, 1);
        }
 
-      write_DRXD_InitFE_1:
+write_DRXD_InitFE_1:
 
        rc = write_fw(s, DRXD_InitFE_1);
        if (rc < 0)
@@ -1311,7 +1312,8 @@ static int drx397x_init(struct dvb_frontend *fe)
        s->config.d5C = 0;
        s->config.d60 = 1;
        s->config.d48 = 1;
-      error:
+
+error:
        return rc;
 }
 
@@ -1326,7 +1328,8 @@ static int drx397x_set_frontend(struct dvb_frontend *fe,
 {
        struct drx397xD_state *s = fe->demodulator_priv;
 
-       s->config.s20d24 = 1;   // 0;
+       s->config.s20d24 = 1;
+
        return drx_tune(s, params);
 }
 
@@ -1337,18 +1340,16 @@ static int drx397x_get_tune_settings(struct dvb_frontend *fe,
        fe_tune_settings->min_delay_ms = 10000;
        fe_tune_settings->step_size = 0;
        fe_tune_settings->max_drift = 0;
+
        return 0;
 }
 
-static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct drx397xD_state *s = fe->demodulator_priv;
        int lockstat;
 
        GetLockStatus(s, &lockstat);
-       /* TODO */
-//      if (lockstat & 1)
-//      CorrectSysClockDeviation(s);
 
        *status = 0;
        if (lockstat & 2) {
@@ -1356,9 +1357,8 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
                ConfigureMPEGOutput(s, 1);
                *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
        }
-       if (lockstat & 4) {
+       if (lockstat & 4)
                *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-       }
 
        return 0;
 }
@@ -1366,16 +1366,18 @@ static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
 static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
 {
        *ber = 0;
+
        return 0;
 }
 
-static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        *snr = 0;
+
        return 0;
 }
 
-static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct drx397xD_state *s = fe->demodulator_priv;
        int rc;
@@ -1401,6 +1403,7 @@ static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
         * The following does the same but with less rounding errors:
         */
        *strength = ~(7720 + (rc * 30744 >> 10));
+
        return 0;
 }
 
@@ -1408,6 +1411,7 @@ static int drx397x_read_ucblocks(struct dvb_frontend *fe,
                                 unsigned int *ucblocks)
 {
        *ucblocks = 0;
+
        return 0;
 }
 
@@ -1436,22 +1440,22 @@ static struct dvb_frontend_ops drx397x_ops = {
                 .frequency_max         = 855250000,
                 .frequency_stepsize    = 166667,
                 .frequency_tolerance   = 0,
-                .caps =                                        /* 0x0C01B2EAE */
-                        FE_CAN_FEC_1_2                 |       // = 0x2,
-                        FE_CAN_FEC_2_3                 |       // = 0x4,
-                        FE_CAN_FEC_3_4                 |       // = 0x8,
-                        FE_CAN_FEC_5_6                 |       // = 0x20,
-                        FE_CAN_FEC_7_8                 |       // = 0x80,
-                        FE_CAN_FEC_AUTO                |       // = 0x200,
-                        FE_CAN_QPSK                    |       // = 0x400,
-                        FE_CAN_QAM_16                  |       // = 0x800,
-                        FE_CAN_QAM_64                  |       // = 0x2000,
-                        FE_CAN_QAM_AUTO                |       // = 0x10000,
-                        FE_CAN_TRANSMISSION_MODE_AUTO  |       // = 0x20000,
-                        FE_CAN_GUARD_INTERVAL_AUTO     |       // = 0x80000,
-                        FE_CAN_HIERARCHY_AUTO          |       // = 0x100000,
-                        FE_CAN_RECOVER                 |       // = 0x40000000,
-                        FE_CAN_MUTE_TS                         // = 0x80000000
+                .caps =                                  /* 0x0C01B2EAE */
+                        FE_CAN_FEC_1_2                 | /* = 0x2, */
+                        FE_CAN_FEC_2_3                 | /* = 0x4, */
+                        FE_CAN_FEC_3_4                 | /* = 0x8, */
+                        FE_CAN_FEC_5_6                 | /* = 0x20, */
+                        FE_CAN_FEC_7_8                 | /* = 0x80, */
+                        FE_CAN_FEC_AUTO                | /* = 0x200, */
+                        FE_CAN_QPSK                    | /* = 0x400, */
+                        FE_CAN_QAM_16                  | /* = 0x800, */
+                        FE_CAN_QAM_64                  | /* = 0x2000, */
+                        FE_CAN_QAM_AUTO                | /* = 0x10000, */
+                        FE_CAN_TRANSMISSION_MODE_AUTO  | /* = 0x20000, */
+                        FE_CAN_GUARD_INTERVAL_AUTO     | /* = 0x80000, */
+                        FE_CAN_HIERARCHY_AUTO          | /* = 0x100000, */
+                        FE_CAN_RECOVER                 | /* = 0x40000000, */
+                        FE_CAN_MUTE_TS                   /* = 0x80000000 */
         },
 
        .release = drx397x_release,
@@ -1472,33 +1476,35 @@ static struct dvb_frontend_ops drx397x_ops = {
 struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
                                     struct i2c_adapter *i2c)
 {
-       struct drx397xD_state *s = NULL;
+       struct drx397xD_state *state;
 
        /* allocate memory for the internal state */
-       s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
-       if (s == NULL)
+       state = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+       if (!state)
                goto error;
 
        /* setup the state */
-       s->i2c = i2c;
-       memcpy(&s->config, config, sizeof(struct drx397xD_config));
+       state->i2c = i2c;
+       memcpy(&state->config, config, sizeof(struct drx397xD_config));
 
        /* check if the demod is there */
-       if (RD16(s, 0x2410019) < 0)
+       if (RD16(state, 0x2410019) < 0)
                goto error;
 
        /* create dvb_frontend */
-       memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
-       s->frontend.demodulator_priv = s;
+       memcpy(&state->frontend.ops, &drx397x_ops,
+                       sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       return &state->frontend;
+error:
+       kfree(state);
 
-       return &s->frontend;
-      error:
-       kfree(s);
        return NULL;
 }
+EXPORT_SYMBOL(drx397xD_attach);
 
 MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
 MODULE_AUTHOR("Henk Vergonet");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(drx397xD_attach);
index ddc7a07971b73473c4c9fd428f9a038a2768fe0c..ba05d17290c633e51fdc30e0dc0055d9702affeb 100644 (file)
@@ -28,7 +28,7 @@
 #define DRX_F_OFFSET   36000000
 
 #define I2C_ADR_C0(x) \
-(      (u32)cpu_to_le32( \
+(      cpu_to_le32( \
                (u32)( \
                        (((u32)(x) & (u32)0x000000ffUL)      ) | \
                        (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
@@ -38,7 +38,7 @@
 )
 
 #define I2C_ADR_E0(x) \
-(      (u32)cpu_to_le32( \
+(      cpu_to_le32( \
                (u32)( \
                        (((u32)(x) & (u32)0x000000ffUL)      ) | \
                        (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
@@ -122,7 +122,7 @@ extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config
 static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
                                           struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_DRX397XD */
index fed09dfb2b7c64eb2c90b5ebd9ec64a913512b47..db8a937cc63008dbabe4a1225810f03e80916d31 100644 (file)
@@ -75,9 +75,10 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
 
 static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
-       if (fe->ops->tuner_ops->set_params) {
-               fe->ops->tuner_ops->set_params(fe, p);
-               if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        return 0;
@@ -131,7 +132,7 @@ error:
 
 static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
 
-struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
+struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
 {
        struct dvb_dummy_fe_state* state = NULL;
 
@@ -151,7 +152,7 @@ error:
 
 static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
 
-struct dvb_frontend* dvb_dummy_fe_qam_attach()
+struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
 {
        struct dvb_dummy_fe_state* state = NULL;
 
diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb/frontends/eds1547.h
new file mode 100644 (file)
index 0000000..fa79b7c
--- /dev/null
@@ -0,0 +1,133 @@
+/* eds1547.h Earda EDS-1547 tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      This program is free software; 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.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef EDS1547
+#define EDS1547
+
+static u8 stv0288_earda_inittab[] = {
+       0x01, 0x57,
+       0x02, 0x20,
+       0x03, 0x8e,
+       0x04, 0x8e,
+       0x05, 0x12,
+       0x06, 0x00,
+       0x07, 0x00,
+       0x09, 0x00,
+       0x0a, 0x04,
+       0x0b, 0x00,
+       0x0c, 0x00,
+       0x0d, 0x00,
+       0x0e, 0xd4,
+       0x0f, 0x30,
+       0x11, 0x44,
+       0x12, 0x03,
+       0x13, 0x48,
+       0x14, 0x84,
+       0x15, 0x45,
+       0x16, 0xb7,
+       0x17, 0x9c,
+       0x18, 0x00,
+       0x19, 0xa6,
+       0x1a, 0x88,
+       0x1b, 0x8f,
+       0x1c, 0xf0,
+       0x20, 0x0b,
+       0x21, 0x54,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x2b, 0xff,
+       0x2c, 0xf7,
+       0x30, 0x00,
+       0x31, 0x1e,
+       0x32, 0x14,
+       0x33, 0x0f,
+       0x34, 0x09,
+       0x35, 0x0c,
+       0x36, 0x05,
+       0x37, 0x2f,
+       0x38, 0x16,
+       0x39, 0xbd,
+       0x3a, 0x00,
+       0x3b, 0x13,
+       0x3c, 0x11,
+       0x3d, 0x30,
+       0x40, 0x63,
+       0x41, 0x04,
+       0x42, 0x60,
+       0x43, 0x00,
+       0x44, 0x00,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x47, 0x00,
+       0x4a, 0x00,
+       0x50, 0x10,
+       0x51, 0x36,
+       0x52, 0x09,
+       0x53, 0x94,
+       0x54, 0x62,
+       0x55, 0x29,
+       0x56, 0x64,
+       0x57, 0x2b,
+       0x58, 0x54,
+       0x59, 0x86,
+       0x5a, 0x00,
+       0x5b, 0x9b,
+       0x5c, 0x08,
+       0x5d, 0x7f,
+       0x5e, 0x00,
+       0x5f, 0xff,
+       0x70, 0x00,
+       0x71, 0x00,
+       0x72, 0x00,
+       0x74, 0x00,
+       0x75, 0x00,
+       0x76, 0x00,
+       0x81, 0x00,
+       0x82, 0x3f,
+       0x83, 0x3f,
+       0x84, 0x00,
+       0x85, 0x00,
+       0x88, 0x00,
+       0x89, 0x00,
+       0x8a, 0x00,
+       0x8b, 0x00,
+       0x8c, 0x00,
+       0x90, 0x00,
+       0x91, 0x00,
+       0x92, 0x00,
+       0x93, 0x00,
+       0x94, 0x1c,
+       0x97, 0x00,
+       0xa0, 0x48,
+       0xa1, 0x00,
+       0xb0, 0xb8,
+       0xb1, 0x3a,
+       0xb2, 0x10,
+       0xb3, 0x82,
+       0xb4, 0x80,
+       0xb5, 0x82,
+       0xb6, 0x82,
+       0xb7, 0x82,
+       0xb8, 0x20,
+       0xb9, 0x00,
+       0xf0, 0x00,
+       0xf1, 0x00,
+       0xf2, 0xc0,
+       0xff,0xff,
+};
+
+static struct stv0288_config earda_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+       .inittab = stv0288_earda_inittab,
+};
+
+#endif
diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c
new file mode 100644 (file)
index 0000000..855852f
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+       Timothy Lee <timothy.lee@siriushk.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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "dvb_frontend.h"
+#include "lgs8gl5.h"
+
+
+#define REG_RESET              0x02
+#define REG_RESET_OFF                  0x01
+#define REG_03                 0x03
+#define REG_04                 0x04
+#define REG_07                 0x07
+#define REG_09                 0x09
+#define REG_0A                 0x0a
+#define REG_0B                 0x0b
+#define REG_0C                 0x0c
+#define REG_37                 0x37
+#define REG_STRENGTH           0x4b
+#define REG_STRENGTH_MASK              0x7f
+#define REG_STRENGTH_CARRIER           0x80
+#define REG_INVERSION          0x7c
+#define REG_INVERSION_ON               0x80
+#define REG_7D                 0x7d
+#define REG_7E                 0x7e
+#define REG_A2                 0xa2
+#define REG_STATUS             0xa4
+#define REG_STATUS_SYNC                0x04
+#define REG_STATUS_LOCK                0x01
+
+
+struct lgs8gl5_state {
+       struct i2c_adapter *i2c;
+       const struct lgs8gl5_config *config;
+       struct dvb_frontend frontend;
+};
+
+
+static int debug;
+#define dprintk(args...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "lgs8gl5: " args); \
+       } while (0)
+
+
+/* Writes into demod's register */
+static int
+lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 buf[] = {reg, data};
+       struct i2c_msg msg = {
+               .addr  = state->config->demod_address,
+               .flags = 0,
+               .buf   = buf,
+               .len   = 2
+       };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+       if (ret != 1)
+               dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n",
+                       __func__, reg, data, ret);
+       return (ret != 1) ? -1 : 0;
+}
+
+
+/* Reads from demod's register */
+static int
+lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg)
+{
+       int ret;
+       u8 b0[] = {reg};
+       u8 b1[] = {0};
+       struct i2c_msg msg[2] = {
+               {
+                       .addr  = state->config->demod_address,
+                       .flags = 0,
+                       .buf   = b0,
+                       .len   = 1
+               },
+               {
+                       .addr  = state->config->demod_address,
+                       .flags = I2C_M_RD,
+                       .buf   = b1,
+                       .len   = 1
+               }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+       if (ret != 2)
+               return -EIO;
+
+       return b1[0];
+}
+
+
+static int
+lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+       lgs8gl5_read_reg(state, reg);
+       lgs8gl5_write_reg(state, reg, data);
+       return 0;
+}
+
+
+/* Writes into alternate device's register */
+/* TODO:  Find out what that device is for! */
+static int
+lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 b0[] = {reg};
+       u8 b1[] = {0};
+       u8 b2[] = {reg, data};
+       struct i2c_msg msg[3] = {
+               {
+                       .addr  = state->config->demod_address + 2,
+                       .flags = 0,
+                       .buf   = b0,
+                       .len   = 1
+               },
+               {
+                       .addr  = state->config->demod_address + 2,
+                       .flags = I2C_M_RD,
+                       .buf   = b1,
+                       .len   = 1
+               },
+               {
+                       .addr  = state->config->demod_address + 2,
+                       .flags = 0,
+                       .buf   = b2,
+                       .len   = 2
+               },
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 3);
+       return (ret != 3) ? -1 : 0;
+}
+
+
+static void
+lgs8gl5_soft_reset(struct lgs8gl5_state *state)
+{
+       u8 val;
+
+       dprintk("%s\n", __func__);
+
+       val = lgs8gl5_read_reg(state, REG_RESET);
+       lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF);
+       lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF);
+       msleep(5);
+}
+
+
+/* Starts demodulation */
+static void
+lgs8gl5_start_demod(struct lgs8gl5_state *state)
+{
+       u8  val;
+       int n;
+
+       dprintk("%s\n", __func__);
+
+       lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+       lgs8gl5_soft_reset(state);
+       lgs8gl5_update_reg(state, REG_07, 0x10);
+       lgs8gl5_update_reg(state, REG_07, 0x10);
+       lgs8gl5_write_reg(state, REG_09, 0x0e);
+       lgs8gl5_write_reg(state, REG_0A, 0xe5);
+       lgs8gl5_write_reg(state, REG_0B, 0x35);
+       lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+       lgs8gl5_update_reg(state, REG_03, 0x00);
+       lgs8gl5_update_reg(state, REG_7E, 0x01);
+       lgs8gl5_update_alt_reg(state, 0xc5, 0x00);
+       lgs8gl5_update_reg(state, REG_04, 0x02);
+       lgs8gl5_update_reg(state, REG_37, 0x01);
+       lgs8gl5_soft_reset(state);
+
+       /* Wait for carrier */
+       for (n = 0;  n < 10;  n++) {
+               val = lgs8gl5_read_reg(state, REG_STRENGTH);
+               dprintk("Wait for carrier[%d] 0x%02X\n", n, val);
+               if (val & REG_STRENGTH_CARRIER)
+                       break;
+               msleep(4);
+       }
+       if (!(val & REG_STRENGTH_CARRIER))
+               return;
+
+       /* Wait for lock */
+       for (n = 0;  n < 20;  n++) {
+               val = lgs8gl5_read_reg(state, REG_STATUS);
+               dprintk("Wait for lock[%d] 0x%02X\n", n, val);
+               if (val & REG_STATUS_LOCK)
+                       break;
+               msleep(12);
+       }
+       if (!(val & REG_STATUS_LOCK))
+               return;
+
+       lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2));
+       lgs8gl5_soft_reset(state);
+}
+
+
+static int
+lgs8gl5_init(struct dvb_frontend *fe)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+       lgs8gl5_soft_reset(state);
+       lgs8gl5_update_reg(state, REG_07, 0x10);
+       lgs8gl5_update_reg(state, REG_07, 0x10);
+       lgs8gl5_write_reg(state, REG_09, 0x0e);
+       lgs8gl5_write_reg(state, REG_0A, 0xe5);
+       lgs8gl5_write_reg(state, REG_0B, 0x35);
+       lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+       u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+       u8 flags = lgs8gl5_read_reg(state, REG_STATUS);
+
+       *status = 0;
+
+       if ((level & REG_STRENGTH_MASK) > 0)
+               *status |= FE_HAS_SIGNAL;
+       if (level & REG_STRENGTH_CARRIER)
+               *status |= FE_HAS_CARRIER;
+       if (flags & REG_STATUS_SYNC)
+               *status |= FE_HAS_SYNC;
+       if (flags & REG_STATUS_LOCK)
+               *status |= FE_HAS_LOCK;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       *ber = 0;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+       u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+       *signal_strength = (level & REG_STRENGTH_MASK) << 8;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+       u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+       *snr = (level & REG_STRENGTH_MASK) << 8;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       *ucblocks = 0;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_set_frontend(struct dvb_frontend *fe,
+               struct dvb_frontend_parameters *p)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ)
+               return -EINVAL;
+
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       /* lgs8gl5_set_inversion(state, p->inversion); */
+
+       lgs8gl5_start_demod(state);
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_get_frontend(struct dvb_frontend *fe,
+               struct dvb_frontend_parameters *p)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+       u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
+       struct dvb_ofdm_parameters *o = &p->u.ofdm;
+
+       p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
+
+       o->code_rate_HP = FEC_1_2;
+       o->code_rate_LP = FEC_7_8;
+       o->guard_interval = GUARD_INTERVAL_1_32;
+       o->transmission_mode = TRANSMISSION_MODE_2K;
+       o->constellation = QAM_64;
+       o->hierarchy_information = HIERARCHY_NONE;
+       o->bandwidth = BANDWIDTH_8_MHZ;
+
+       return 0;
+}
+
+
+static int
+lgs8gl5_get_tune_settings(struct dvb_frontend *fe,
+               struct dvb_frontend_tune_settings *fesettings)
+{
+       fesettings->min_delay_ms = 240;
+       fesettings->step_size    = 0;
+       fesettings->max_drift    = 0;
+       return 0;
+}
+
+
+static void
+lgs8gl5_release(struct dvb_frontend *fe)
+{
+       struct lgs8gl5_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+
+static struct dvb_frontend_ops lgs8gl5_ops;
+
+
+struct dvb_frontend*
+lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c)
+{
+       struct lgs8gl5_state *state = NULL;
+
+       dprintk("%s\n", __func__);
+
+       /* Allocate memory for the internal state */
+       state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* Setup the state */
+       state->config = config;
+       state->i2c    = i2c;
+
+       /* Check if the demod is there */
+       if (lgs8gl5_read_reg(state, REG_RESET) < 0)
+               goto error;
+
+       /* Create dvb_frontend */
+       memcpy(&state->frontend.ops, &lgs8gl5_ops,
+               sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(lgs8gl5_attach);
+
+
+static struct dvb_frontend_ops lgs8gl5_ops = {
+       .info = {
+               .name                   = "Legend Silicon LGS-8GL5 DMB-TH",
+               .type                   = FE_OFDM,
+               .frequency_min          = 474000000,
+               .frequency_max          = 858000000,
+               .frequency_stepsize     = 10000,
+               .frequency_tolerance    = 0,
+               .caps = FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
+                       FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_BANDWIDTH_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_HIERARCHY_AUTO |
+                       FE_CAN_RECOVER
+       },
+
+       .release = lgs8gl5_release,
+
+       .init = lgs8gl5_init,
+
+       .set_frontend = lgs8gl5_set_frontend,
+       .get_frontend = lgs8gl5_get_frontend,
+       .get_tune_settings = lgs8gl5_get_tune_settings,
+
+       .read_status = lgs8gl5_read_status,
+       .read_ber = lgs8gl5_read_ber,
+       .read_signal_strength = lgs8gl5_read_signal_strength,
+       .read_snr = lgs8gl5_read_snr,
+       .read_ucblocks = lgs8gl5_read_ucblocks,
+};
+
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver");
+MODULE_AUTHOR("Timothy Lee");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb/frontends/lgs8gl5.h
new file mode 100644 (file)
index 0000000..d141767
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+       Timothy Lee <timothy.lee@siriushk.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.
+
+*/
+
+#ifndef LGS8GL5_H
+#define LGS8GL5_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgs8gl5_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_LGS8GL5) || \
+       (defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
+extern struct dvb_frontend *lgs8gl5_attach(
+       const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lgs8gl5_attach(
+       const struct lgs8gl5_config *config, struct i2c_adapter *i2c) {
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_LGS8GL5 */
+
+#endif /* LGS8GL5_H */
index af298358e822e4048cf7b03c312cf5abb73e7312..a8429ebfa8a2e6da67208e926d5644f74e583a02 100644 (file)
@@ -80,7 +80,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
        return 0;
 }
 
-static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
+static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
 {
        int err;
        struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
@@ -111,7 +111,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
        return 0;
 }
 
-static u8 nxt200x_readbytes (struct nxt200x_state* state, u8 reg, u8* buf, u8 len)
+static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)
 {
        u8 reg2 [] = { reg };
 
index 6afe12aaca4e53d6ab417279c5c143e69d271c72..16cf2fdd5d7d1c6a14189a5b56312a4b4acb3f99 100644 (file)
@@ -88,7 +88,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
        return 0;
 }
 
-static u8 i2c_readbytes (struct or51211_state* state, u8 reg, u8* buf, int len)
+static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
 {
        int err;
        struct i2c_msg msg;
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c
new file mode 100644 (file)
index 0000000..3ddbe69
--- /dev/null
@@ -0,0 +1,974 @@
+/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      This program is free software; you can redistribute it and/or modify
+*      it under the terms of the 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/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "si21xx.h"
+
+#define        REVISION_REG                    0x00
+#define        SYSTEM_MODE_REG                 0x01
+#define        TS_CTRL_REG_1                   0x02
+#define        TS_CTRL_REG_2                   0x03
+#define        PIN_CTRL_REG_1                  0x04
+#define        PIN_CTRL_REG_2                  0x05
+#define        LOCK_STATUS_REG_1               0x0f
+#define        LOCK_STATUS_REG_2               0x10
+#define        ACQ_STATUS_REG                  0x11
+#define        ACQ_CTRL_REG_1                  0x13
+#define        ACQ_CTRL_REG_2                  0x14
+#define        PLL_DIVISOR_REG                 0x15
+#define        COARSE_TUNE_REG                 0x16
+#define        FINE_TUNE_REG_L                 0x17
+#define        FINE_TUNE_REG_H                 0x18
+
+#define        ANALOG_AGC_POWER_LEVEL_REG      0x28
+#define        CFO_ESTIMATOR_CTRL_REG_1        0x29
+#define        CFO_ESTIMATOR_CTRL_REG_2        0x2a
+#define        CFO_ESTIMATOR_CTRL_REG_3        0x2b
+
+#define        SYM_RATE_ESTIMATE_REG_L         0x31
+#define        SYM_RATE_ESTIMATE_REG_M         0x32
+#define        SYM_RATE_ESTIMATE_REG_H         0x33
+
+#define        CFO_ESTIMATOR_OFFSET_REG_L      0x36
+#define        CFO_ESTIMATOR_OFFSET_REG_H      0x37
+#define        CFO_ERROR_REG_L                 0x38
+#define        CFO_ERROR_REG_H                 0x39
+#define        SYM_RATE_ESTIMATOR_CTRL_REG     0x3a
+
+#define        SYM_RATE_REG_L                  0x3f
+#define        SYM_RATE_REG_M                  0x40
+#define        SYM_RATE_REG_H                  0x41
+#define        SYM_RATE_ESTIMATOR_MAXIMUM_REG  0x42
+#define        SYM_RATE_ESTIMATOR_MINIMUM_REG  0x43
+
+#define        C_N_ESTIMATOR_CTRL_REG          0x7c
+#define        C_N_ESTIMATOR_THRSHLD_REG       0x7d
+#define        C_N_ESTIMATOR_LEVEL_REG_L       0x7e
+#define        C_N_ESTIMATOR_LEVEL_REG_H       0x7f
+
+#define        BLIND_SCAN_CTRL_REG             0x80
+
+#define        LSA_CTRL_REG_1                  0x8D
+#define        SPCTRM_TILT_CORR_THRSHLD_REG    0x8f
+#define        ONE_DB_BNDWDTH_THRSHLD_REG      0x90
+#define        TWO_DB_BNDWDTH_THRSHLD_REG      0x91
+#define        THREE_DB_BNDWDTH_THRSHLD_REG    0x92
+#define        INBAND_POWER_THRSHLD_REG        0x93
+#define        REF_NOISE_LVL_MRGN_THRSHLD_REG  0x94
+
+#define        VIT_SRCH_CTRL_REG_1             0xa0
+#define        VIT_SRCH_CTRL_REG_2             0xa1
+#define        VIT_SRCH_CTRL_REG_3             0xa2
+#define        VIT_SRCH_STATUS_REG             0xa3
+#define        VITERBI_BER_COUNT_REG_L         0xab
+#define        REED_SOLOMON_CTRL_REG           0xb0
+#define        REED_SOLOMON_ERROR_COUNT_REG_L  0xb1
+#define        PRBS_CTRL_REG                   0xb5
+
+#define        LNB_CTRL_REG_1                  0xc0
+#define        LNB_CTRL_REG_2                  0xc1
+#define        LNB_CTRL_REG_3                  0xc2
+#define        LNB_CTRL_REG_4                  0xc3
+#define        LNB_CTRL_STATUS_REG             0xc4
+#define        LNB_FIFO_REGS_0                 0xc5
+#define        LNB_FIFO_REGS_1                 0xc6
+#define        LNB_FIFO_REGS_2                 0xc7
+#define        LNB_FIFO_REGS_3                 0xc8
+#define        LNB_FIFO_REGS_4                 0xc9
+#define        LNB_FIFO_REGS_5                 0xca
+#define        LNB_SUPPLY_CTRL_REG_1           0xcb
+#define        LNB_SUPPLY_CTRL_REG_2           0xcc
+#define        LNB_SUPPLY_CTRL_REG_3           0xcd
+#define        LNB_SUPPLY_CTRL_REG_4           0xce
+#define        LNB_SUPPLY_STATUS_REG           0xcf
+
+#define FALSE  0
+#define TRUE   1
+#define FAIL   -1
+#define PASS   0
+
+#define ALLOWABLE_FS_COUNT     10
+#define STATUS_BER             0
+#define STATUS_UCBLOCKS                1
+
+static int debug;
+#define dprintk(args...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "si21xx: " args); \
+       } while (0)
+
+enum {
+       ACTIVE_HIGH,
+       ACTIVE_LOW
+};
+enum {
+       BYTE_WIDE,
+       BIT_WIDE
+};
+enum {
+       CLK_GAPPED_MODE,
+       CLK_CONTINUOUS_MODE
+};
+enum {
+       RISING_EDGE,
+       FALLING_EDGE
+};
+enum {
+       MSB_FIRST,
+       LSB_FIRST
+};
+enum {
+       SERIAL,
+       PARALLEL
+};
+
+struct si21xx_state {
+       struct i2c_adapter *i2c;
+       const struct si21xx_config *config;
+       struct dvb_frontend frontend;
+       u8 initialised:1;
+       int errmode;
+       int fs;                 /*Sampling rate of the ADC in MHz*/
+};
+
+/*     register default initialization */
+static u8 serit_sp1511lhb_inittab[] = {
+       0x01, 0x28,     /* set i2c_inc_disable */
+       0x20, 0x03,
+       0x27, 0x20,
+       0xe0, 0x45,
+       0xe1, 0x08,
+       0xfe, 0x01,
+       0x01, 0x28,
+       0x89, 0x09,
+       0x04, 0x80,
+       0x05, 0x01,
+       0x06, 0x00,
+       0x20, 0x03,
+       0x24, 0x88,
+       0x29, 0x09,
+       0x2a, 0x0f,
+       0x2c, 0x10,
+       0x2d, 0x19,
+       0x2e, 0x08,
+       0x2f, 0x10,
+       0x30, 0x19,
+       0x34, 0x20,
+       0x35, 0x03,
+       0x45, 0x02,
+       0x46, 0x45,
+       0x47, 0xd0,
+       0x48, 0x00,
+       0x49, 0x40,
+       0x4a, 0x03,
+       0x4c, 0xfd,
+       0x4f, 0x2e,
+       0x50, 0x2e,
+       0x51, 0x10,
+       0x52, 0x10,
+       0x56, 0x92,
+       0x59, 0x00,
+       0x5a, 0x2d,
+       0x5b, 0x33,
+       0x5c, 0x1f,
+       0x5f, 0x76,
+       0x62, 0xc0,
+       0x63, 0xc0,
+       0x64, 0xf3,
+       0x65, 0xf3,
+       0x79, 0x40,
+       0x6a, 0x40,
+       0x6b, 0x0a,
+       0x6c, 0x80,
+       0x6d, 0x27,
+       0x71, 0x06,
+       0x75, 0x60,
+       0x78, 0x00,
+       0x79, 0xb5,
+       0x7c, 0x05,
+       0x7d, 0x1a,
+       0x87, 0x55,
+       0x88, 0x72,
+       0x8f, 0x08,
+       0x90, 0xe0,
+       0x94, 0x40,
+       0xa0, 0x3f,
+       0xa1, 0xc0,
+       0xa4, 0xcc,
+       0xa5, 0x66,
+       0xa6, 0x66,
+       0xa7, 0x7b,
+       0xa8, 0x7b,
+       0xa9, 0x7b,
+       0xaa, 0x9a,
+       0xed, 0x04,
+       0xad, 0x00,
+       0xae, 0x03,
+       0xcc, 0xab,
+       0x01, 0x08,
+       0xff, 0xff
+};
+
+/*     low level read/writes */
+static int si21_writeregs(struct si21xx_state *state, u8 reg1,
+                                                       u8 *data, int len)
+{
+       int ret;
+       u8 buf[60];/* = { reg1, data };*/
+       struct i2c_msg msg = {
+                               .addr = state->config->demod_address,
+                               .flags = 0,
+                               .buf = buf,
+                               .len = len + 1
+       };
+
+       msg.buf[0] =  reg1;
+       memcpy(msg.buf + 1, data, len);
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
+                       "ret == %i)\n", __func__, reg1, data[0], ret);
+
+       return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 buf[] = { reg, data };
+       struct i2c_msg msg = {
+                               .addr = state->config->demod_address,
+                               .flags = 0,
+                               .buf = buf,
+                               .len = 2
+       };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
+                       "ret == %i)\n", __func__, reg, data, ret);
+
+       return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_write(struct dvb_frontend *fe, u8 *buf, int len)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       if (len != 2)
+               return -EINVAL;
+
+       return si21_writereg(state, buf[0], buf[1]);
+}
+
+static u8 si21_readreg(struct si21xx_state *state, u8 reg)
+{
+       int ret;
+       u8 b0[] = { reg };
+       u8 b1[] = { 0 };
+       struct i2c_msg msg[] = {
+               {
+                       .addr = state->config->demod_address,
+                       .flags = 0,
+                       .buf = b0,
+                       .len = 1
+               }, {
+                       .addr = state->config->demod_address,
+                       .flags = I2C_M_RD,
+                       .buf = b1,
+                       .len = 1
+               }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+                       __func__, reg, ret);
+
+       return b1[0];
+}
+
+static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
+{
+       int ret;
+       struct i2c_msg msg[] = {
+               {
+                       .addr = state->config->demod_address,
+                       .flags = 0,
+                       .buf = &reg1,
+                       .len = 1
+               }, {
+                       .addr = state->config->demod_address,
+                       .flags = I2C_M_RD,
+                       .buf = b,
+                       .len = len
+               }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+       return ret == 2 ? 0 : -1;
+}
+
+static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
+{
+       unsigned long start = jiffies;
+
+       dprintk("%s\n", __func__);
+
+       while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
+               if (jiffies - start > timeout) {
+                       dprintk("%s: timeout!!\n", __func__);
+                       return -ETIMEDOUT;
+               }
+               msleep(10);
+       };
+
+       return 0;
+}
+
+static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u32 sym_rate, data_rate;
+       int i;
+       u8 sym_rate_bytes[3];
+
+       dprintk("%s : srate = %i\n", __func__ , srate);
+
+       if ((srate < 1000000) || (srate > 45000000))
+               return -EINVAL;
+
+       data_rate = srate;
+       sym_rate = 0;
+
+       for (i = 0; i < 4; ++i) {
+               sym_rate /= 100;
+               sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
+                                                               state->fs;
+               data_rate /= 100;
+       }
+       for (i = 0; i < 3; ++i)
+               sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
+
+       si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
+
+       return 0;
+}
+
+static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
+                                       struct dvb_diseqc_master_cmd *m)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 lnb_status;
+       u8 LNB_CTRL_1;
+       int status;
+
+       dprintk("%s\n", __func__);
+
+       status = PASS;
+       LNB_CTRL_1 = 0;
+
+       status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
+       status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
+
+       /*fill the FIFO*/
+       status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
+
+       LNB_CTRL_1 = (lnb_status & 0x70);
+       LNB_CTRL_1 |= m->msg_len;
+
+       LNB_CTRL_1 |= 0x80;     /* begin LNB signaling */
+
+       status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
+
+       return status;
+}
+
+static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
+                                               fe_sec_mini_cmd_t burst)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 val;
+
+       dprintk("%s\n", __func__);
+
+       if (si21xx_wait_diseqc_idle(state, 100) < 0)
+               return -ETIMEDOUT;
+
+       val = (0x80 | si21_readreg(state, 0xc1));
+       if (si21_writereg(state, LNB_CTRL_REG_1,
+                       burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
+               return -EREMOTEIO;
+
+       if (si21xx_wait_diseqc_idle(state, 100) < 0)
+               return -ETIMEDOUT;
+
+       if (si21_writereg(state, LNB_CTRL_REG_1, val))
+               return -EREMOTEIO;
+
+       return 0;
+}
+/*     30.06.2008 */
+static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 val;
+
+       dprintk("%s\n", __func__);
+       val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+       switch (tone) {
+       case SEC_TONE_ON:
+               return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
+
+       case SEC_TONE_OFF:
+               return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       u8 val;
+       dprintk("%s: %s\n", __func__,
+               volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+               volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+
+       val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+       switch (volt) {
+       case SEC_VOLTAGE_18:
+               return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
+               break;
+       case SEC_VOLTAGE_13:
+               return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
+               break;
+       default:
+               return -EINVAL;
+       };
+}
+
+static int si21xx_init(struct dvb_frontend *fe)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       int i;
+       int status = 0;
+       u8 reg1;
+       u8 val;
+       u8 reg2[2];
+
+       dprintk("%s\n", __func__);
+
+       for (i = 0; ; i += 2) {
+               reg1 = serit_sp1511lhb_inittab[i];
+               val = serit_sp1511lhb_inittab[i+1];
+               if (reg1 == 0xff && val == 0xff)
+                       break;
+               si21_writeregs(state, reg1, &val, 1);
+       }
+
+       /*DVB QPSK SYSTEM MODE REG*/
+       reg1 = 0x08;
+       si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
+
+       /*transport stream config*/
+       /*
+       mode = PARALLEL;
+       sdata_form = LSB_FIRST;
+       clk_edge = FALLING_EDGE;
+       clk_mode = CLK_GAPPED_MODE;
+       strt_len = BYTE_WIDE;
+       sync_pol = ACTIVE_HIGH;
+       val_pol = ACTIVE_HIGH;
+       err_pol = ACTIVE_HIGH;
+       sclk_rate = 0x00;
+       parity = 0x00 ;
+       data_delay = 0x00;
+       clk_delay = 0x00;
+       pclk_smooth = 0x00;
+       */
+       reg2[0] =
+               PARALLEL + (LSB_FIRST << 1)
+               + (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
+               + (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
+               + (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
+
+       reg2[1] = 0;
+       /*      sclk_rate + (parity << 2)
+               + (data_delay << 3) + (clk_delay << 4)
+               + (pclk_smooth << 5);
+       */
+       status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
+       if (status != 0)
+               dprintk(" %s : TS Set Error\n", __func__);
+
+       return 0;
+
+}
+
+static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 regs_read[2];
+       u8 reg_read;
+       u8 i;
+       u8 lock;
+       u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
+
+       si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
+       reg_read = 0;
+
+       for (i = 0; i < 7; ++i)
+               reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
+
+       lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
+
+       dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
+       *status = 0;
+
+       if (signal > 10)
+               *status |= FE_HAS_SIGNAL;
+
+       if (lock & 0x2)
+               *status |= FE_HAS_CARRIER;
+
+       if (lock & 0x20)
+               *status |= FE_HAS_VITERBI;
+
+       if (lock & 0x40)
+               *status |= FE_HAS_SYNC;
+
+       if ((lock & 0x7b) == 0x7b)
+               *status |= FE_HAS_LOCK;
+
+       return 0;
+}
+
+static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       /*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
+                                               (u8*)agclevel, 0x01);*/
+
+       u16 signal = (3 * si21_readreg(state, 0x27) *
+                                       si21_readreg(state, 0x28));
+
+       dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
+               si21_readreg(state, 0x27),
+               si21_readreg(state, 0x28), (int) signal);
+
+       signal  <<= 4;
+       *strength = signal;
+
+       return 0;
+}
+
+static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       if (state->errmode != STATUS_BER)
+               return 0;
+
+       *ber = (si21_readreg(state, 0x1d) << 8) |
+                               si21_readreg(state, 0x1e);
+
+       return 0;
+}
+
+static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
+                                       si21_readreg(state, 0x25));
+       xsnr = 3 * (xsnr - 0xa100);
+       *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+
+       dprintk("%s\n", __func__);
+
+       return 0;
+}
+
+static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       if (state->errmode != STATUS_UCBLOCKS)
+               *ucblocks = 0;
+       else
+               *ucblocks = (si21_readreg(state, 0x1d) << 8) |
+                                       si21_readreg(state, 0x1e);
+
+       return 0;
+}
+
+/*     initiates a channel acquisition sequence
+       using the specified symbol rate and code rate */
+static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
+                                               fe_code_rate_t crate)
+{
+
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 coderates[] = {
+                               0x0, 0x01, 0x02, 0x04, 0x00,
+                               0x8, 0x10, 0x20, 0x00, 0x3f
+       };
+
+       u8 coderate_ptr;
+       int status;
+       u8 start_acq = 0x80;
+       u8 reg, regs[3];
+
+       dprintk("%s\n", __func__);
+
+       status = PASS;
+       coderate_ptr = coderates[crate];
+
+       si21xx_set_symbolrate(fe, symbrate);
+
+       /* write code rates to use in the Viterbi search */
+       status |= si21_writeregs(state,
+                               VIT_SRCH_CTRL_REG_1,
+                               &coderate_ptr, 0x01);
+
+       /* clear acq_start bit */
+       status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+       reg &= ~start_acq;
+       status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+
+       /* use new Carrier Frequency Offset Estimator (QuickLock) */
+       regs[0] = 0xCB;
+       regs[1] = 0x40;
+       regs[2] = 0xCB;
+
+       status |= si21_writeregs(state,
+                               TWO_DB_BNDWDTH_THRSHLD_REG,
+                               &regs[0], 0x03);
+       reg = 0x56;
+       status |= si21_writeregs(state,
+                               LSA_CTRL_REG_1, &reg, 1);
+       reg = 0x05;
+       status |= si21_writeregs(state,
+                               BLIND_SCAN_CTRL_REG, &reg, 1);
+       /* start automatic acq */
+       status |= si21_writeregs(state,
+                               ACQ_CTRL_REG_2, &start_acq, 0x01);
+
+       return status;
+}
+
+static int si21xx_set_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+static int si21xx_get_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+static int si21xx_set_frontend(struct dvb_frontend *fe,
+                                       struct dvb_frontend_parameters *dfp)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+       /* freq         Channel carrier frequency in KHz (i.e. 1550000 KHz)
+        datarate       Channel symbol rate in Sps (i.e. 22500000 Sps)*/
+
+       /* in MHz */
+       unsigned char coarse_tune_freq;
+       int fine_tune_freq;
+       unsigned char sample_rate = 0;
+       /* boolean */
+       unsigned int inband_interferer_ind;
+
+       /* INTERMEDIATE VALUES */
+       int icoarse_tune_freq; /* MHz */
+       int ifine_tune_freq; /* MHz */
+       unsigned int band_high;
+       unsigned int band_low;
+       unsigned int x1;
+       unsigned int x2;
+       int i;
+       unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = {
+                       FALSE, FALSE, FALSE, FALSE, FALSE,
+                       FALSE, FALSE, FALSE, FALSE, FALSE
+       };
+       unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = {
+                       FALSE, FALSE, FALSE, FALSE, FALSE,
+                       FALSE, FALSE, FALSE, FALSE, FALSE
+       };
+
+       int status;
+
+       /* allowable sample rates for ADC in MHz */
+       int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
+                                       196, 204, 205, 206, 207
+       };
+       /* in MHz */
+       int if_limit_high;
+       int if_limit_low;
+       int lnb_lo;
+       int lnb_uncertanity;
+
+       int rf_freq;
+       int data_rate;
+       unsigned char regs[4];
+
+       dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+       if (c->delivery_system != SYS_DVBS) {
+                       dprintk("%s: unsupported delivery system selected (%d)\n",
+                               __func__, c->delivery_system);
+                       return -EOPNOTSUPP;
+       }
+
+       for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
+               inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE;
+
+       if_limit_high = -700000;
+       if_limit_low = -100000;
+       /* in MHz */
+       lnb_lo = 0;
+       lnb_uncertanity = 0;
+
+       rf_freq = 10 * c->frequency ;
+       data_rate = c->symbol_rate / 100;
+
+       status = PASS;
+
+       band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
+                                       + (data_rate * 135)) / 200;
+
+       band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
+                                       + (data_rate * 135)) / 200;
+
+
+       icoarse_tune_freq = 100000 *
+                               (((rf_freq - lnb_lo) -
+                                       (if_limit_low + if_limit_high) / 2)
+                                                               / 100000);
+
+       ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
+
+       for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+               x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+                                       (afs[i] * 2500) + afs[i] * 2500;
+
+               x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+                                                       (afs[i] * 2500);
+
+               if (((band_low < x1) && (x1 < band_high)) ||
+                                       ((band_low < x2) && (x2 < band_high)))
+                                       inband_interferer_div4[i] = TRUE;
+
+       }
+
+       for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+               x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+                                       (afs[i] * 5000) + afs[i] * 5000;
+
+               x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+                                       (afs[i] * 5000);
+
+               if (((band_low < x1) && (x1 < band_high)) ||
+                                       ((band_low < x2) && (x2 < band_high)))
+                                       inband_interferer_div2[i] = TRUE;
+       }
+
+       inband_interferer_ind = TRUE;
+       for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
+               inband_interferer_ind &= inband_interferer_div2[i] |
+                                               inband_interferer_div4[i];
+
+       if (inband_interferer_ind) {
+               for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+                       if (inband_interferer_div2[i] == FALSE) {
+                               sample_rate = (u8) afs[i];
+                               break;
+                       }
+               }
+       } else {
+               for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+                       if ((inband_interferer_div2[i] |
+                                       inband_interferer_div4[i]) == FALSE) {
+                               sample_rate = (u8) afs[i];
+                               break;
+                       }
+               }
+
+       }
+
+       if (sample_rate > 207 || sample_rate < 192)
+               sample_rate = 200;
+
+       fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
+                                       ((sample_rate) * 1000));
+
+       coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
+
+       regs[0] = sample_rate;
+       regs[1] = coarse_tune_freq;
+       regs[2] = fine_tune_freq & 0xFF;
+       regs[3] = fine_tune_freq >> 8 & 0xFF;
+
+       status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
+
+       state->fs = sample_rate;/*ADC MHz*/
+       si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
+
+       return 0;
+}
+
+static int si21xx_sleep(struct dvb_frontend *fe)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+       u8 regdata;
+
+       dprintk("%s\n", __func__);
+
+       si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+       regdata |= 1 << 6;
+       si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+       state->initialised = 0;
+
+       return 0;
+}
+
+static void si21xx_release(struct dvb_frontend *fe)
+{
+       struct si21xx_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       kfree(state);
+}
+
+static struct dvb_frontend_ops si21xx_ops = {
+
+       .info = {
+               .name                   = "SL SI21XX DVB-S",
+               .type                   = FE_QPSK,
+               .frequency_min          = 950000,
+               .frequency_max          = 2150000,
+               .frequency_stepsize     = 125,   /* kHz for QPSK frontends */
+               .frequency_tolerance    = 0,
+               .symbol_rate_min        = 1000000,
+               .symbol_rate_max        = 45000000,
+               .symbol_rate_tolerance  = 500,  /* ppm */
+               .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+               FE_CAN_QPSK |
+               FE_CAN_FEC_AUTO
+       },
+
+       .release = si21xx_release,
+       .init = si21xx_init,
+       .sleep = si21xx_sleep,
+       .write = si21_write,
+       .read_status = si21_read_status,
+       .read_ber = si21_read_ber,
+       .read_signal_strength = si21_read_signal_strength,
+       .read_snr = si21_read_snr,
+       .read_ucblocks = si21_read_ucblocks,
+       .diseqc_send_master_cmd = si21xx_send_diseqc_msg,
+       .diseqc_send_burst = si21xx_send_diseqc_burst,
+       .set_tone = si21xx_set_tone,
+       .set_voltage = si21xx_set_voltage,
+
+       .set_property = si21xx_set_property,
+       .get_property = si21xx_get_property,
+       .set_frontend = si21xx_set_frontend,
+};
+
+struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+                                               struct i2c_adapter *i2c)
+{
+       struct si21xx_state *state = NULL;
+       int id;
+
+       dprintk("%s\n", __func__);
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->initialised = 0;
+       state->errmode = STATUS_BER;
+
+       /* check if the demod is there */
+       id = si21_readreg(state, SYSTEM_MODE_REG);
+       si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
+       msleep(200);
+       id = si21_readreg(state, 0x00);
+
+       /* register 0x00 contains:
+               0x34 for SI2107
+               0x24 for SI2108
+               0x14 for SI2109
+               0x04 for SI2110
+       */
+       if (id != 0x04 && id != 0x14)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &si21xx_ops,
+                                       sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(si21xx_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb/frontends/si21xx.h
new file mode 100644 (file)
index 0000000..141b5b8
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef SI21XX_H
+#define SI21XX_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct si21xx_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* minimum delay before retuning */
+       int min_delay_ms;
+};
+
+#if defined(CONFIG_DVB_SI21XX) || \
+               (defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
+extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+                                               struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *si21xx_attach(
+               const struct si21xx_config *config, struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+       int r = 0;
+       u8 buf[] = {reg, val};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 2);
+       return r;
+}
+
+#endif
index 4543609e181619aae2b7746855e88c346112901a..559509ab4dabfc2f4376bb0b46d58315defb74fd 100644 (file)
@@ -337,7 +337,8 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
                                             struct dvb_frontend_parameters *p)
 {
        struct sp887x_state* state = fe->demodulator_priv;
-       int actual_freq, err;
+       unsigned actual_freq;
+       int err;
        u16 val, reg0xc05;
 
        if (p->u.ofdm.bandwidth != BANDWIDTH_8_MHZ &&
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c
new file mode 100644 (file)
index 0000000..0e2cb0d
--- /dev/null
@@ -0,0 +1,255 @@
+  /*
+     Driver for ST STB6000 DVBS Silicon tuner
+
+     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "stb6000.h"
+
+static int debug;
+#define dprintk(args...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "stb6000: " args); \
+       } while (0)
+
+struct stb6000_priv {
+       /* i2c details */
+       int i2c_address;
+       struct i2c_adapter *i2c;
+       u32 frequency;
+};
+
+static int stb6000_release(struct dvb_frontend *fe)
+{
+       kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int stb6000_sleep(struct dvb_frontend *fe)
+{
+       struct stb6000_priv *priv = fe->tuner_priv;
+       int ret;
+       u8 buf[] = { 10, 0 };
+       struct i2c_msg msg = {
+               .addr = priv->i2c_address,
+               .flags = 0,
+               .buf = buf,
+               .len = 2
+       };
+
+       dprintk("%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = i2c_transfer(priv->i2c, &msg, 1);
+       if (ret != 1)
+               dprintk("%s: i2c error\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return (ret == 1) ? 0 : ret;
+}
+
+static int stb6000_set_params(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params)
+{
+       struct stb6000_priv *priv = fe->tuner_priv;
+       unsigned int n, m;
+       int ret;
+       u32 freq_mhz;
+       int bandwidth;
+       u8 buf[12];
+       struct i2c_msg msg = {
+               .addr = priv->i2c_address,
+               .flags = 0,
+               .buf = buf,
+               .len = 12
+       };
+
+       dprintk("%s:\n", __func__);
+
+       freq_mhz = params->frequency / 1000;
+       bandwidth = params->u.qpsk.symbol_rate / 1000000;
+
+       if (bandwidth > 31)
+               bandwidth = 31;
+
+       if ((freq_mhz > 949) && (freq_mhz < 2151)) {
+               buf[0] = 0x01;
+               buf[1] = 0xac;
+               if (freq_mhz < 1950)
+                       buf[1] = 0xaa;
+               if (freq_mhz < 1800)
+                       buf[1] = 0xa8;
+               if (freq_mhz < 1650)
+                       buf[1] = 0xa6;
+               if (freq_mhz < 1530)
+                       buf[1] = 0xa5;
+               if (freq_mhz < 1470)
+                       buf[1] = 0xa4;
+               if (freq_mhz < 1370)
+                       buf[1] = 0xa2;
+               if (freq_mhz < 1300)
+                       buf[1] = 0xa1;
+               if (freq_mhz < 1200)
+                       buf[1] = 0xa0;
+               if (freq_mhz < 1075)
+                       buf[1] = 0xbc;
+               if (freq_mhz < 1000)
+                       buf[1] = 0xba;
+               if (freq_mhz < 1075) {
+                       n = freq_mhz / 8; /* vco=lo*4 */
+                       m = 2;
+               } else {
+                       n = freq_mhz / 16; /* vco=lo*2 */
+                       m = 1;
+               }
+               buf[2] = n >> 1;
+               buf[3] = (unsigned char)(((n & 1) << 7) |
+                                       (m * freq_mhz - n * 16) | 0x60);
+               buf[4] = 0x04;
+               buf[5] = 0x0e;
+
+               buf[6] = (unsigned char)(bandwidth);
+
+               buf[7] = 0xd8;
+               buf[8] = 0xd0;
+               buf[9] = 0x50;
+               buf[10] = 0xeb;
+               buf[11] = 0x4f;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = i2c_transfer(priv->i2c, &msg, 1);
+               if (ret != 1)
+                       dprintk("%s: i2c error\n", __func__);
+
+               udelay(10);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+
+               buf[0] = 0x07;
+               buf[1] = 0xdf;
+               buf[2] = 0xd0;
+               buf[3] = 0x50;
+               buf[4] = 0xfb;
+               msg.len = 5;
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = i2c_transfer(priv->i2c, &msg, 1);
+               if (ret != 1)
+                       dprintk("%s: i2c error\n", __func__);
+
+               udelay(10);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+
+               priv->frequency = freq_mhz * 1000;
+
+               return (ret == 1) ? 0 : ret;
+       }
+       return -1;
+}
+
+static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct stb6000_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static struct dvb_tuner_ops stb6000_tuner_ops = {
+       .info = {
+               .name = "ST STB6000",
+               .frequency_min = 950000,
+               .frequency_max = 2150000
+       },
+       .release = stb6000_release,
+       .sleep = stb6000_sleep,
+       .set_params = stb6000_set_params,
+       .get_frequency = stb6000_get_frequency,
+};
+
+struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+                                               struct i2c_adapter *i2c)
+{
+       struct stb6000_priv *priv = NULL;
+       u8 b0[] = { 0 };
+       u8 b1[] = { 0, 0 };
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = addr,
+                       .flags = 0,
+                       .buf = b0,
+                       .len = 0
+               }, {
+                       .addr = addr,
+                       .flags = I2C_M_RD,
+                       .buf = b1,
+                       .len = 2
+               }
+       };
+       int ret;
+
+       dprintk("%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* is some i2c device here ? */
+       ret = i2c_transfer(i2c, msg, 2);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       if (ret != 2)
+               return NULL;
+
+       priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return NULL;
+
+       priv->i2c_address = addr;
+       priv->i2c = i2c;
+
+       memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
+                               sizeof(struct dvb_tuner_ops));
+
+       fe->tuner_priv = priv;
+
+       return fe;
+}
+EXPORT_SYMBOL(stb6000_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB STB6000 driver");
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h
new file mode 100644 (file)
index 0000000..7be479c
--- /dev/null
@@ -0,0 +1,51 @@
+  /*
+     Driver for ST stb6000 DVBS Silicon tuner
+
+     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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 __DVB_STB6000_H__
+#define __DVB_STB6000_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a stb6000 tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param addr i2c address of the tuner.
+ * @param i2c i2c adapter to use.
+ * @return FE pointer on success, NULL on failure.
+ */
+#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
+                                                       && defined(MODULE))
+extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe,
+                                                 int addr,
+                                                 struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_STB6000 */
+
+#endif /* __DVB_STB6000_H__ */
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
new file mode 100644 (file)
index 0000000..ff1194d
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+       Driver for ST STV0288 demodulator
+       Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+               for Reel Multimedia
+       Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
+       Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+               Removed stb6000 specific tuner code and revised some
+               procedures.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0288.h"
+
+struct stv0288_state {
+       struct i2c_adapter *i2c;
+       const struct stv0288_config *config;
+       struct dvb_frontend frontend;
+
+       u8 initialised:1;
+       u32 tuner_frequency;
+       u32 symbol_rate;
+       fe_code_rate_t fec_inner;
+       int errmode;
+};
+
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
+static int debug;
+static int debug_legacy_dish_switch;
+#define dprintk(args...) \
+       do { \
+               if (debug) \
+                       printk(KERN_DEBUG "stv0288: " args); \
+       } while (0)
+
+
+static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
+{
+       int ret;
+       u8 buf[] = { reg, data };
+       struct i2c_msg msg = {
+               .addr = state->config->demod_address,
+               .flags = 0,
+               .buf = buf,
+               .len = 2
+       };
+
+       ret = i2c_transfer(state->i2c, &msg, 1);
+
+       if (ret != 1)
+               dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+                       "ret == %i)\n", __func__, reg, data, ret);
+
+       return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0288_write(struct dvb_frontend *fe, u8 *buf, int len)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       if (len != 2)
+               return -EINVAL;
+
+       return stv0288_writeregI(state, buf[0], buf[1]);
+}
+
+static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
+{
+       int ret;
+       u8 b0[] = { reg };
+       u8 b1[] = { 0 };
+       struct i2c_msg msg[] = {
+               {
+                       .addr = state->config->demod_address,
+                       .flags = 0,
+                       .buf = b0,
+                       .len = 1
+               }, {
+                       .addr = state->config->demod_address,
+                       .flags = I2C_M_RD,
+                       .buf = b1,
+                       .len = 1
+               }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 2);
+
+       if (ret != 2)
+               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+                               __func__, reg, ret);
+
+       return b1[0];
+}
+
+static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+       unsigned int temp;
+       unsigned char b[3];
+
+       if ((srate < 1000000) || (srate > 45000000))
+               return -EINVAL;
+
+       temp = (unsigned int)srate / 1000;
+
+               temp = temp * 32768;
+               temp = temp / 25;
+               temp = temp / 125;
+               b[0] = (unsigned char)((temp >> 12) & 0xff);
+               b[1] = (unsigned char)((temp >> 4) & 0xff);
+               b[2] = (unsigned char)((temp << 4) & 0xf0);
+               stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
+               stv0288_writeregI(state, 0x29, 0); /* SFRM */
+               stv0288_writeregI(state, 0x2a, 0); /* SFRL */
+
+               stv0288_writeregI(state, 0x28, b[0]);
+               stv0288_writeregI(state, 0x29, b[1]);
+               stv0288_writeregI(state, 0x2a, b[2]);
+               dprintk("stv0288: stv0288_set_symbolrate\n");
+
+       return 0;
+}
+
+static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
+                                   struct dvb_diseqc_master_cmd *m)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       int i;
+
+       dprintk("%s\n", __func__);
+
+       stv0288_writeregI(state, 0x09, 0);
+       msleep(30);
+       stv0288_writeregI(state, 0x05, 0x16);
+
+       for (i = 0; i < m->msg_len; i++) {
+               if (stv0288_writeregI(state, 0x06, m->msg[i]))
+                       return -EREMOTEIO;
+               msleep(12);
+       }
+
+       return 0;
+}
+
+static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
+                                               fe_sec_mini_cmd_t burst)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       dprintk("%s\n", __func__);
+
+       if (stv0288_writeregI(state, 0x05, 0x16))/* burst mode */
+               return -EREMOTEIO;
+
+       if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
+               return -EREMOTEIO;
+
+       if (stv0288_writeregI(state, 0x06, 0x12))
+               return -EREMOTEIO;
+
+       return 0;
+}
+
+static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       switch (tone) {
+       case SEC_TONE_ON:
+               if (stv0288_writeregI(state, 0x05, 0x10))/* burst mode */
+                       return -EREMOTEIO;
+               return stv0288_writeregI(state, 0x06, 0xff);
+
+       case SEC_TONE_OFF:
+               if (stv0288_writeregI(state, 0x05, 0x13))/* burst mode */
+                       return -EREMOTEIO;
+               return stv0288_writeregI(state, 0x06, 0x00);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static u8 stv0288_inittab[] = {
+       0x01, 0x15,
+       0x02, 0x20,
+       0x09, 0x0,
+       0x0a, 0x4,
+       0x0b, 0x0,
+       0x0c, 0x0,
+       0x0d, 0x0,
+       0x0e, 0xd4,
+       0x0f, 0x30,
+       0x11, 0x80,
+       0x12, 0x03,
+       0x13, 0x48,
+       0x14, 0x84,
+       0x15, 0x45,
+       0x16, 0xb7,
+       0x17, 0x9c,
+       0x18, 0x0,
+       0x19, 0xa6,
+       0x1a, 0x88,
+       0x1b, 0x8f,
+       0x1c, 0xf0,
+       0x20, 0x0b,
+       0x21, 0x54,
+       0x22, 0x0,
+       0x23, 0x0,
+       0x2b, 0xff,
+       0x2c, 0xf7,
+       0x30, 0x0,
+       0x31, 0x1e,
+       0x32, 0x14,
+       0x33, 0x0f,
+       0x34, 0x09,
+       0x35, 0x0c,
+       0x36, 0x05,
+       0x37, 0x2f,
+       0x38, 0x16,
+       0x39, 0xbe,
+       0x3a, 0x0,
+       0x3b, 0x13,
+       0x3c, 0x11,
+       0x3d, 0x30,
+       0x40, 0x63,
+       0x41, 0x04,
+       0x42, 0x60,
+       0x43, 0x00,
+       0x44, 0x00,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x47, 0x00,
+       0x4a, 0x00,
+       0x50, 0x10,
+       0x51, 0x38,
+       0x52, 0x21,
+       0x58, 0x54,
+       0x59, 0x86,
+       0x5a, 0x0,
+       0x5b, 0x9b,
+       0x5c, 0x08,
+       0x5d, 0x7f,
+       0x5e, 0x0,
+       0x5f, 0xff,
+       0x70, 0x0,
+       0x71, 0x0,
+       0x72, 0x0,
+       0x74, 0x0,
+       0x75, 0x0,
+       0x76, 0x0,
+       0x81, 0x0,
+       0x82, 0x3f,
+       0x83, 0x3f,
+       0x84, 0x0,
+       0x85, 0x0,
+       0x88, 0x0,
+       0x89, 0x0,
+       0x8a, 0x0,
+       0x8b, 0x0,
+       0x8c, 0x0,
+       0x90, 0x0,
+       0x91, 0x0,
+       0x92, 0x0,
+       0x93, 0x0,
+       0x94, 0x1c,
+       0x97, 0x0,
+       0xa0, 0x48,
+       0xa1, 0x0,
+       0xb0, 0xb8,
+       0xb1, 0x3a,
+       0xb2, 0x10,
+       0xb3, 0x82,
+       0xb4, 0x80,
+       0xb5, 0x82,
+       0xb6, 0x82,
+       0xb7, 0x82,
+       0xb8, 0x20,
+       0xb9, 0x0,
+       0xf0, 0x0,
+       0xf1, 0x0,
+       0xf2, 0xc0,
+       0x51, 0x36,
+       0x52, 0x09,
+       0x53, 0x94,
+       0x54, 0x62,
+       0x55, 0x29,
+       0x56, 0x64,
+       0x57, 0x2b,
+       0xff, 0xff,
+};
+
+static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+       dprintk("%s: %s\n", __func__,
+               volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+               volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+       return 0;
+}
+
+static int stv0288_init(struct dvb_frontend *fe)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+       int i;
+       u8 reg;
+       u8 val;
+
+       dprintk("stv0288: init chip\n");
+       stv0288_writeregI(state, 0x41, 0x04);
+       msleep(50);
+
+       /* we have default inittab */
+       if (state->config->inittab == NULL) {
+               for (i = 0; !(stv0288_inittab[i] == 0xff &&
+                               stv0288_inittab[i + 1] == 0xff); i += 2)
+                       stv0288_writeregI(state, stv0288_inittab[i],
+                                       stv0288_inittab[i + 1]);
+       } else {
+               for (i = 0; ; i += 2)  {
+                       reg = state->config->inittab[i];
+                       val = state->config->inittab[i+1];
+                       if (reg == 0xff && val == 0xff)
+                               break;
+                       stv0288_writeregI(state, reg, val);
+               }
+       }
+       return 0;
+}
+
+static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       u8 sync = stv0288_readreg(state, 0x24);
+       if (sync == 255)
+               sync = 0;
+
+       dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+
+       *status = 0;
+
+       if ((sync & 0x08) == 0x08) {
+               *status |= FE_HAS_LOCK;
+               dprintk("stv0288 has locked\n");
+       }
+
+       return 0;
+}
+
+static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       if (state->errmode != STATUS_BER)
+               return 0;
+       *ber = (stv0288_readreg(state, 0x26) << 8) |
+                                       stv0288_readreg(state, 0x27);
+       dprintk("stv0288_read_ber %d\n", *ber);
+
+       return 0;
+}
+
+
+static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       s32 signal =  0xffff - ((stv0288_readreg(state, 0x10) << 8));
+
+
+       signal = signal * 5 / 4;
+       *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
+       dprintk("stv0288_read_signal_strength %d\n", *strength);
+
+       return 0;
+}
+static int stv0288_sleep(struct dvb_frontend *fe)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       stv0288_writeregI(state, 0x41, 0x84);
+       state->initialised = 0;
+
+       return 0;
+}
+static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
+                          | stv0288_readreg(state, 0x2e));
+       xsnr = 3 * (xsnr - 0xa100);
+       *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+       dprintk("stv0288_read_snr %d\n", *snr);
+
+       return 0;
+}
+
+static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       if (state->errmode != STATUS_BER)
+               return 0;
+       *ucblocks = (stv0288_readreg(state, 0x26) << 8) |
+                                       stv0288_readreg(state, 0x27);
+       dprintk("stv0288_read_ber %d\n", *ucblocks);
+
+       return 0;
+}
+
+static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+       dprintk("%s(..)\n", __func__);
+       return 0;
+}
+
+static int stv0288_set_frontend(struct dvb_frontend *fe,
+                                       struct dvb_frontend_parameters *dfp)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+       char tm;
+       unsigned char tda[3];
+
+       dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+       if (c->delivery_system != SYS_DVBS) {
+                       dprintk("%s: unsupported delivery "
+                               "system selected (%d)\n",
+                               __func__, c->delivery_system);
+                       return -EOPNOTSUPP;
+       }
+
+       if (state->config->set_ts_params)
+               state->config->set_ts_params(fe, 0);
+
+       /* only frequency & symbol_rate are used for tuner*/
+       dfp->frequency = c->frequency;
+       dfp->u.qpsk.symbol_rate = c->symbol_rate;
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, dfp);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
+       udelay(10);
+       stv0288_set_symbolrate(fe, c->symbol_rate);
+       /* Carrier lock control register */
+       stv0288_writeregI(state, 0x15, 0xc5);
+
+       tda[0] = 0x2b; /* CFRM */
+       tda[2] = 0x0; /* CFRL */
+       for (tm = -6; tm < 7;) {
+               /* Viterbi status */
+               if (stv0288_readreg(state, 0x24) & 0x80)
+                       break;
+
+               tda[2] += 40;
+               if (tda[2] < 40)
+                       tm++;
+               tda[1] = (unsigned char)tm;
+               stv0288_writeregI(state, 0x2b, tda[1]);
+               stv0288_writeregI(state, 0x2c, tda[2]);
+               udelay(30);
+       }
+
+       state->tuner_frequency = c->frequency;
+       state->fec_inner = FEC_AUTO;
+       state->symbol_rate = c->symbol_rate;
+
+       return 0;
+}
+
+static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+
+       if (enable)
+               stv0288_writeregI(state, 0x01, 0xb5);
+       else
+               stv0288_writeregI(state, 0x01, 0x35);
+
+       udelay(1);
+
+       return 0;
+}
+
+static void stv0288_release(struct dvb_frontend *fe)
+{
+       struct stv0288_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops stv0288_ops = {
+
+       .info = {
+               .name                   = "ST STV0288 DVB-S",
+               .type                   = FE_QPSK,
+               .frequency_min          = 950000,
+               .frequency_max          = 2150000,
+               .frequency_stepsize     = 1000,  /* kHz for QPSK frontends */
+               .frequency_tolerance    = 0,
+               .symbol_rate_min        = 1000000,
+               .symbol_rate_max        = 45000000,
+               .symbol_rate_tolerance  = 500,  /* ppm */
+               .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                     FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+                     FE_CAN_QPSK |
+                     FE_CAN_FEC_AUTO
+       },
+
+       .release = stv0288_release,
+       .init = stv0288_init,
+       .sleep = stv0288_sleep,
+       .write = stv0288_write,
+       .i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
+       .read_status = stv0288_read_status,
+       .read_ber = stv0288_read_ber,
+       .read_signal_strength = stv0288_read_signal_strength,
+       .read_snr = stv0288_read_snr,
+       .read_ucblocks = stv0288_read_ucblocks,
+       .diseqc_send_master_cmd = stv0288_send_diseqc_msg,
+       .diseqc_send_burst = stv0288_send_diseqc_burst,
+       .set_tone = stv0288_set_tone,
+       .set_voltage = stv0288_set_voltage,
+
+       .set_property = stv0288_set_property,
+       .get_property = stv0288_get_property,
+       .set_frontend = stv0288_set_frontend,
+};
+
+struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+                                   struct i2c_adapter *i2c)
+{
+       struct stv0288_state *state = NULL;
+       int id;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       state->initialised = 0;
+       state->tuner_frequency = 0;
+       state->symbol_rate = 0;
+       state->fec_inner = 0;
+       state->errmode = STATUS_BER;
+
+       stv0288_writeregI(state, 0x41, 0x04);
+       msleep(200);
+       id = stv0288_readreg(state, 0x00);
+       dprintk("stv0288 id %x\n", id);
+
+       /* register 0x00 contains 0x11 for STV0288  */
+       if (id != 0x11)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &stv0288_ops,
+                       sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error:
+       kfree(state);
+
+       return NULL;
+}
+EXPORT_SYMBOL(stv0288_attach);
+
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch,
+               "Enable timing analysis for Dish Network legacy switches");
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
+MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h
new file mode 100644 (file)
index 0000000..f2b53db
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+       Driver for ST STV0288 demodulator
+
+       Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+               for Reel Multimedia
+       Copyright (C) 2008 TurboSight.com, <bob@turbosight.com>
+       Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+               Removed stb6000 specific tuner code and revised some
+               procedures.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the 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 STV0288_H
+#define STV0288_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0288_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       u8* inittab;
+
+       /* minimum delay before retuning */
+       int min_delay_ms;
+
+       int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
+                                                       defined(MODULE))
+extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_STV0288 */
+
+static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+       int r = 0;
+       u8 buf[] = { reg, val };
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 2);
+       return r;
+}
+
+#endif /* STV0288_H */
index 35435bef8e7992af4e1e8648a8c408b0f2d62f18..6c1cb1973c6e09c90010a7ec0167a9e50ae5b23e 100644 (file)
@@ -559,6 +559,8 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        int invval = 0;
 
        dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+       if (state->config->set_ts_params)
+               state->config->set_ts_params(fe, 0);
 
        // set the inversion
        if (p->inversion == INVERSION_OFF) invval = 0;
index 3282f43022f5da37d2681e34a20c235e94828176..0fd96e22b650abec41ab65692770a8238d7c43c9 100644 (file)
@@ -89,15 +89,18 @@ struct stv0299_config
        int min_delay_ms;
 
        /* Set the symbol rate */
-       int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
+       int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio);
+
+       /* Set device param to start dma */
+       int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 };
 
 #if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE))
-extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
-                                          struct i2c_adapteri2c);
+extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+                                          struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
-                                          struct i2c_adapteri2c)
+static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+                                          struct i2c_adapter *i2c)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h
new file mode 100644 (file)
index 0000000..51f1706
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * tdhd1.h - ALPS TDHD1-204A tuner support
+ *
+ * Copyright (C) 2008 Oliver Endriss <o.endriss@gmx.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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * The project's page is at http://www.linuxtv.org
+ */
+
+#ifndef TDHD1_H
+#define TDHD1_H
+
+#include "tda1004x.h"
+
+static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name);
+
+static struct tda1004x_config alps_tdhd1_204a_config = {
+       .demod_address = 0x8,
+       .invert = 1,
+       .invert_oclk = 0,
+       .xtal_freq = TDA10046_XTAL_4M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
+       .request_firmware = alps_tdhd1_204_request_firmware
+};
+
+static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct i2c_adapter *i2c = fe->tuner_priv;
+       u8 data[4];
+       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+       u32 div;
+
+       div = (params->frequency + 36166666) / 166666;
+
+       data[0] = (div >> 8) & 0x7f;
+       data[1] = div & 0xff;
+       data[2] = 0x85;
+
+       if (params->frequency >= 174000000 && params->frequency <= 230000000)
+               data[3] = 0x02;
+       else if (params->frequency >= 470000000 && params->frequency <= 823000000)
+               data[3] = 0x0C;
+       else if (params->frequency > 823000000 && params->frequency <= 862000000)
+               data[3] = 0x8C;
+       else
+               return -EINVAL;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(i2c, &msg, 1) != 1)
+               return -EIO;
+
+       return 0;
+}
+
+#endif /* TDHD1_H */
index 41b5a988b619fb8016485a7e50e512c1a66b9356..867027ceab3e71d29ce43b3944104043670eeb99 100644 (file)
@@ -86,6 +86,7 @@ config DVB_BUDGET
        select DVB_TDA10086 if !DVB_FE_CUSTOMISE
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        help
          Support for simple SAA7146 based DVB cards (so called Budget-
          or Nova-PCI cards) without onboard MPEG2 decoder, and without
index 0777e8f9544ba66d63402a7f7bc5facd2a73c08c..c7c770c2898825c8a06c65400b880ea817c90cdc 100644 (file)
@@ -88,6 +88,7 @@ static int budgetpatch;
 static int wss_cfg_4_3 = 0x4008;
 static int wss_cfg_16_9 = 0x0007;
 static int tv_standard;
+static int full_ts;
 
 module_param_named(debug, av7110_debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -106,6 +107,8 @@ module_param(volume, int, 0444);
 MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
 module_param(budgetpatch, int, 0444);
 MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
+module_param(full_ts, int, 0444);
+MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
 module_param(wss_cfg_4_3, int, 0444);
 MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
 module_param(wss_cfg_16_9, int, 0444);
@@ -116,6 +119,8 @@ MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static void restart_feeds(struct av7110 *av7110);
+static int budget_start_feed(struct dvb_demux_feed *feed);
+static int budget_stop_feed(struct dvb_demux_feed *feed);
 
 static int av7110_num;
 
@@ -376,9 +381,9 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
                irdebi(av7110, DEBISWAB, addr, 0, len);
 }
 
-static void debiirq(unsigned long data)
+static void debiirq(unsigned long cookie)
 {
-       struct av7110 *av7110 = (struct av7110 *) data;
+       struct av7110 *av7110 = (struct av7110 *)cookie;
        int type = av7110->debitype;
        int handle = (type >> 8) & 0x1f;
        unsigned int xfer = 0;
@@ -487,9 +492,9 @@ debi_done:
 }
 
 /* irq from av7110 firmware writing the mailbox register in the DPRAM */
-static void gpioirq(unsigned long data)
+static void gpioirq(unsigned long cookie)
 {
-       struct av7110 *av7110 = (struct av7110 *) data;
+       struct av7110 *av7110 = (struct av7110 *)cookie;
        u32 rxbuf, txbuf;
        int len;
 
@@ -806,6 +811,9 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 
        dprintk(4, "%p\n", av7110);
 
+       if (av7110->full_ts)
+               return 0;
+
        if (dvbdmxfilter->type == DMX_TYPE_SEC) {
                if (hw_sections) {
                        buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
@@ -854,6 +862,9 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
 
        dprintk(4, "%p\n", av7110);
 
+       if (av7110->full_ts)
+               return 0;
+
        handle = dvbdmxfilter->hw_handle;
        if (handle >= 32) {
                printk("%s tried to stop invalid filter %04x, filter type = %x\n",
@@ -913,7 +924,7 @@ static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
                                return ret;
                }
 
-       if ((dvbdmxfeed->ts_type & TS_PACKET)) {
+       if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
                if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
                        ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
                if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
@@ -974,7 +985,7 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
        if (!demux->dmx.frontend)
                return -EINVAL;
 
-       if (feed->pid > 0x1fff)
+       if (!av7110->full_ts && feed->pid > 0x1fff)
                return -EINVAL;
 
        if (feed->type == DMX_TYPE_TS) {
@@ -1003,7 +1014,12 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
                }
        }
 
-       else if (feed->type == DMX_TYPE_SEC) {
+       if (av7110->full_ts) {
+               budget_start_feed(feed);
+               return ret;
+       }
+
+       if (feed->type == DMX_TYPE_SEC) {
                int i;
 
                for (i = 0; i < demux->filternum; i++) {
@@ -1050,7 +1066,12 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
                                ret = StopHWFilter(feed->filter);
        }
 
-       if (!ret && feed->type == DMX_TYPE_SEC) {
+       if (av7110->full_ts) {
+               budget_stop_feed(feed);
+               return ret;
+       }
+
+       if (feed->type == DMX_TYPE_SEC) {
                for (i = 0; i<demux->filternum; i++) {
                        if (demux->filter[i].state == DMX_STATE_GO &&
                            demux->filter[i].filter.parent == &feed->feed.sec) {
@@ -1074,6 +1095,7 @@ static void restart_feeds(struct av7110 *av7110)
        struct dvb_demux *dvbdmx = &av7110->demux;
        struct dvb_demux_feed *feed;
        int mode;
+       int feeding;
        int i, j;
 
        dprintk(4, "%p\n", av7110);
@@ -1082,6 +1104,8 @@ static void restart_feeds(struct av7110 *av7110)
        av7110->playing = 0;
        av7110->rec_mode = 0;
 
+       feeding = av7110->feeding1; /* full_ts mod */
+
        for (i = 0; i < dvbdmx->feednum; i++) {
                feed = &dvbdmx->feed[i];
                if (feed->state == DMX_STATE_GO) {
@@ -1099,6 +1123,8 @@ static void restart_feeds(struct av7110 *av7110)
                }
        }
 
+       av7110->feeding1 = feeding; /* full_ts mod */
+
        if (mode)
                av7110_av_start_play(av7110, mode);
 }
@@ -1197,8 +1223,9 @@ static int start_ts_capture(struct av7110 *budget)
 
        if (budget->feeding1)
                return ++budget->feeding1;
-       memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
+       memset(budget->grabbing, 0x00, TS_BUFLEN);
        budget->ttbp = 0;
+       SAA7146_ISR_CLEAR(budget->dev, MASK_10);  /* VPE */
        SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
        saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
        return ++budget->feeding1;
@@ -1233,18 +1260,14 @@ static int budget_stop_feed(struct dvb_demux_feed *feed)
        return status;
 }
 
-static void vpeirq(unsigned long data)
+static void vpeirq(unsigned long cookie)
 {
-       struct av7110 *budget = (struct av7110 *) data;
+       struct av7110 *budget = (struct av7110 *)cookie;
        u8 *mem = (u8 *) (budget->grabbing);
        u32 olddma = budget->ttbp;
        u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+       struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
 
-       if (!budgetpatch) {
-               printk("av7110.c: vpeirq() called while budgetpatch disabled!"
-                      " check saa7146 IER register\n");
-               BUG();
-       }
        /* nearest lower position divisible by 188 */
        newdma -= newdma % 188;
 
@@ -1268,11 +1291,11 @@ static void vpeirq(unsigned long data)
 
        if (newdma > olddma)
                /* no wraparound, dump olddma..newdma */
-               dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (newdma - olddma) / 188);
+               dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
        else {
                /* wraparound, dump olddma..buflen and 0..newdma */
-               dvb_dmx_swfilter_packets(&budget->demux1, mem + olddma, (TS_BUFLEN - olddma) / 188);
-               dvb_dmx_swfilter_packets(&budget->demux1, mem, newdma / 188);
+               dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
+               dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
        }
 }
 
@@ -1294,8 +1317,8 @@ static int av7110_register(struct av7110 *av7110)
        for (i = 0; i < 32; i++)
                av7110->handle2filter[i] = NULL;
 
-       dvbdemux->filternum = 32;
-       dvbdemux->feednum = 32;
+       dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
+       dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
        dvbdemux->start_feed = av7110_start_feed;
        dvbdemux->stop_feed = av7110_stop_feed;
        dvbdemux->write_to_decoder = av7110_write_to_decoder;
@@ -1305,7 +1328,7 @@ static int av7110_register(struct av7110 *av7110)
        dvb_dmx_init(&av7110->demux);
        av7110->demux.dmx.get_stc = dvb_get_stc;
 
-       av7110->dmxdev.filternum = 32;
+       av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
        av7110->dmxdev.demux = &dvbdemux->dmx;
        av7110->dmxdev.capabilities = 0;
 
@@ -1422,7 +1445,6 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
        return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
 }
 
-#if 0
 u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
 {
        u8 mm1[] = {0x00};
@@ -1439,7 +1461,6 @@ u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
 
        return mm2[0];
 }
-#endif
 
 /****************************************************************************
  * INITIALIZATION
@@ -2256,7 +2277,7 @@ static int frontend_init(struct av7110 *av7110)
        if (!av7110->fe) {
                /* FIXME: propagate the failure code from the lower layers */
                ret = -ENOMEM;
-               printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+               printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       av7110->dev->pci->vendor,
                       av7110->dev->pci->device,
                       av7110->dev->pci->subsystem_vendor,
@@ -2484,7 +2505,47 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                               av7110->dvb_adapter.proposed_mac);
        ret = -ENOMEM;
 
-       if (budgetpatch) {
+       /* full-ts mod? */
+       if (full_ts)
+               av7110->full_ts = true;
+
+       /* check for full-ts flag in eeprom */
+       if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
+               u8 flags = i2c_readreg(av7110, 0xaa, 2);
+               if (flags != 0xff && (flags & 0x01))
+                       av7110->full_ts = true;
+       }
+
+       if (av7110->full_ts) {
+               printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
+               spin_lock_init(&av7110->feedlock1);
+               av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+                                                                &av7110->pt);
+               if (!av7110->grabbing)
+                       goto err_i2c_del_3;
+
+               saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+               saa7146_write(dev, MC2, (MASK_10 | MASK_26));
+
+               saa7146_write(dev, DD1_INIT, 0x00000600);
+               saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+               saa7146_write(dev, BRS_CTRL, 0x60000000);
+               saa7146_write(dev, MC2, MASK_08 | MASK_24);
+
+               /* dma3 */
+               saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
+               saa7146_write(dev, BASE_ODD3, 0);
+               saa7146_write(dev, BASE_EVEN3, 0);
+               saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+               saa7146_write(dev, PITCH3, TS_WIDTH);
+               saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
+               saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
+               saa7146_write(dev, MC2, MASK_04 | MASK_20);
+
+               tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
+
+       } else if (budgetpatch) {
                spin_lock_init(&av7110->feedlock1);
                av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
                                                                 &av7110->pt);
@@ -2710,11 +2771,13 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
 #if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
        av7110_ir_exit(av7110);
 #endif
-       if (budgetpatch) {
-               /* Disable RPS1 */
-               saa7146_write(saa, MC1, MASK_29);
-               /* VSYNC LOW (inactive) */
-               saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+       if (budgetpatch || av7110->full_ts) {
+               if (budgetpatch) {
+                       /* Disable RPS1 */
+                       saa7146_write(saa, MC1, MASK_29);
+                       /* VSYNC LOW (inactive) */
+                       saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+               }
                saa7146_write(saa, MC1, MASK_20);       /* DMA3 off */
                SAA7146_IER_DISABLE(saa, MASK_10);
                SAA7146_ISR_CLEAR(saa, MASK_10);
@@ -2794,7 +2857,7 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
                tasklet_schedule(&av7110->gpio_tasklet);
        }
 
-       if ((*isr & MASK_10) && budgetpatch)
+       if (*isr & MASK_10)
                tasklet_schedule(&av7110->vpe_tasklet);
 }
 
index 55f23ddcb994e259fa56fe45f646019bf7e916da..d85b8512ac307cb2bfa59f3d695036a1a6a35515 100644 (file)
@@ -192,6 +192,7 @@ struct av7110 {
        unsigned char           *grabbing;
        struct saa7146_pgtable  pt;
        struct tasklet_struct   vpe_tasklet;
+       bool                    full_ts;
 
        int                     fe_synced;
        struct mutex            pid_mutex;
index 184647ad1c7c041fb5aa890c4b9cadbb6c979571..bdc62acf2099ea431f5303f1336d6e2a78902bba 100644 (file)
@@ -788,6 +788,9 @@ int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t l
 
        dprintk(2, "av7110:%p, \n", av7110);
 
+       if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE)
+               return 0;
+
        switch (feed->pes_type) {
        case 0:
                if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
index b7d1f2f18d3a45e1939b61e69ea1dd9ff6448cc9..1032ea77837e356766cb27aaa2bb3f3295688b84 100644 (file)
@@ -57,6 +57,8 @@
 #define SLOTSTATUS_READY        8
 #define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct budget_av {
        struct budget budget;
        struct video_device *vd;
@@ -1049,7 +1051,7 @@ static void frontend_init(struct budget_av *budget_av)
 
        if (fe == NULL) {
                printk(KERN_ERR "budget-av: A frontend driver was not found "
-                               "for device %04x/%04x subsystem %04x/%04x\n",
+                               "for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       saa->pci->vendor,
                       saa->pci->device,
                       saa->pci->subsystem_vendor,
@@ -1127,7 +1129,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
 
        dev->ext_priv = budget_av;
 
-       if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
+       err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
+                               adapter_nr);
+       if (err) {
                kfree(budget_av);
                return err;
        }
index 060e7c7853266f9a2ae6fd514748a6e10b67182c..0a5aad45435d2c0bb37209b8fb2341513f38e21e 100644 (file)
@@ -92,6 +92,8 @@ static int ir_debug;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 struct budget_ci_ir {
        struct input_dev *dev;
        struct tasklet_struct msp430_irq_tasklet;
@@ -1153,7 +1155,7 @@ static void frontend_init(struct budget_ci *budget_ci)
        }
 
        if (budget_ci->budget.dvb_frontend == NULL) {
-               printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+               printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       budget_ci->budget.dev->pci->vendor,
                       budget_ci->budget.dev->pci->device,
                       budget_ci->budget.dev->pci->subsystem_vendor,
@@ -1183,7 +1185,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
 
        dev->ext_priv = budget_ci;
 
-       err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
+       err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
+                               adapter_nr);
        if (err)
                goto out2;
 
index 6f4ddb643fee12482ae84ab0f76939a4fd91999c..ba18e56d5f11295bb8bb79b9ce7d4e5d4a608b4b 100644 (file)
@@ -57,8 +57,6 @@ module_param_named(bufsize, dma_buffer_size, int, 0444);
 MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
 MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
 
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
 /****************************************************************************
  * TT budget / WinTV Nova
  ****************************************************************************/
@@ -411,7 +409,7 @@ static void budget_unregister(struct budget *budget)
 
 int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
                      struct saa7146_pci_extension_data *info,
-                     struct module *owner)
+                     struct module *owner, short *adapter_nums)
 {
        int ret = 0;
        struct budget_info *bi = info->ext_priv;
@@ -474,7 +472,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
        printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 
        ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
-                                  owner, &budget->dev->pci->dev, adapter_nr);
+                                  owner, &budget->dev->pci->dev, adapter_nums);
        if (ret < 0)
                return ret;
 
index aa5ed4ef19f24cfcf68eb8282cb369317c9478d3..60136688a9a4c07dd104fe58ee641b46afd5000c 100644 (file)
@@ -39,6 +39,8 @@
 
 #include "bsru6.h"
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 #define budget_patch budget
 
 static struct saa7146_extension budget_extension;
@@ -360,7 +362,7 @@ static void frontend_init(struct budget_patch* budget)
        }
 
        if (budget->dvb_frontend == NULL) {
-               printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+               printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       budget->dev->pci->vendor,
                       budget->dev->pci->device,
                       budget->dev->pci->subsystem_vendor,
@@ -592,8 +594,9 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
 
        dprintk(2, "budget: %p\n", budget);
 
-       if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
-               kfree (budget);
+       err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
+       if (err) {
+               kfree(budget);
                return err;
        }
 
index f0068996ac07eb907e4042ed01be74e5c0bdd462..1638e1d9f538011e49a193b6ce52dbf86464d274 100644 (file)
 #include "lnbp21.h"
 #include "bsru6.h"
 #include "bsbe1.h"
+#include "tdhd1.h"
 
 static int diseqc_method;
 module_param(diseqc_method, int, 0444);
 MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
 
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
 static void Set22K (struct budget *budget, int state)
 {
        struct saa7146_dev *dev=budget->dev;
@@ -390,6 +393,13 @@ static struct stv0299_config alps_bsbe1_config_activy = {
        .set_symbol_rate = alps_bsbe1_set_symbol_rate,
 };
 
+static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
+{
+       struct budget *budget = (struct budget *)fe->dvb->priv;
+
+       return request_firmware(fw, name, &budget->dev->pci->dev);
+}
+
 
 static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
 {
@@ -511,6 +521,14 @@ static void frontend_init(struct budget *budget)
                }
                break;
 
+       case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
+               budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
+                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+               }
+               break;
+
        case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
                budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
                if (budget->dvb_frontend) {
@@ -550,7 +568,7 @@ static void frontend_init(struct budget *budget)
        }
 
        if (budget->dvb_frontend == NULL) {
-               printk("budget: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+               printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
                       budget->dev->pci->vendor,
                       budget->dev->pci->device,
                       budget->dev->pci->subsystem_vendor,
@@ -582,7 +600,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
 
        dev->ext_priv = budget;
 
-       if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
+       err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
+       if (err) {
                printk("==> failed\n");
                kfree (budget);
                return err;
@@ -624,6 +643,7 @@ MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsact,         "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
@@ -634,6 +654,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
+       MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
        MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
        {
                .vendor    = 0,
index dd450b739bff9bb21d56c2bc8d2dae3d6c4dab54..86435bf162601661381d33f323d1e0176cac4774 100644 (file)
@@ -109,7 +109,7 @@ static struct saa7146_pci_extension_data x_var = { \
 
 extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
                             struct saa7146_pci_extension_data *info,
-                            struct module *owner);
+                            struct module *owner, short *adapter_nums);
 extern void ttpci_budget_init_hooks(struct budget *budget);
 extern int ttpci_budget_deinit(struct budget *budget);
 extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
index e6c9cd2e3b94514784a4ee423553e2f94987ca35..66ab0c6e9783da4f8a99cca3699c3a32dd51ec58 100644 (file)
@@ -1614,7 +1614,7 @@ static void frontend_init(struct ttusb* ttusb)
        }
 
        if (ttusb->fe == NULL) {
-               printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n",
+               printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n",
                       le16_to_cpu(ttusb->dev->descriptor.idVendor),
                       le16_to_cpu(ttusb->dev->descriptor.idProduct));
        } else {
index de5829b863fd26edd62923cf6168bf9e883bb6ef..ab33fec8a19fbcef75855786f5dadc44c2bf721f 100644 (file)
@@ -1665,7 +1665,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
        }
 
        if (dec->fe == NULL) {
-               printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n",
+               printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n",
                       le16_to_cpu(dec->udev->descriptor.idVendor),
                       le16_to_cpu(dec->udev->descriptor.idProduct));
        } else {
index 443af24097f34118fe51c66aa7bb80aa12d17c1f..21260aad1e54684a46c82248dc0bee8681327c21 100644 (file)
@@ -38,7 +38,17 @@ struct ttusbdecfe_state {
 };
 
 
-static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
+       fe_status_t *status)
+{
+       *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+               FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+       return 0;
+}
+
+
+static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
+       fe_status_t *status)
 {
        struct ttusbdecfe_state* state = fe->demodulator_priv;
        u8 b[] = { 0x00, 0x00, 0x00, 0x00,
@@ -251,7 +261,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
 
        .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
 
-       .read_status = ttusbdecfe_read_status,
+       .read_status = ttusbdecfe_dvbt_read_status,
 };
 
 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
@@ -273,7 +283,7 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
 
        .set_frontend = ttusbdecfe_dvbs_set_frontend,
 
-       .read_status = ttusbdecfe_read_status,
+       .read_status = ttusbdecfe_dvbs_read_status,
 
        .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
        .set_voltage = ttusbdecfe_dvbs_set_voltage,
index 1b41b3f77cf95c2b6f28394cf1eb378a2fefe0ec..e51d707e58d35aa7acc905cc0f017f07584be16b 100644 (file)
@@ -361,4 +361,16 @@ config USB_SI470X
          To compile this driver as a module, choose M here: the
          module will be called radio-silabs.
 
+config USB_MR800
+       tristate "AverMedia MR 800 USB FM radio support"
+       depends on USB && VIDEO_V4L2
+       ---help---
+         Say Y here if you want to connect this type of radio to your
+         computer's USB port. Note that the audio is not digital, and
+         you must connect the line out connector to a sound card or a
+         set of speakers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-mr800.
+
 endif # RADIO_ADAPTERS
index 7ca71ab96b43021d5edd3080f118b7fe2f072f44..240ec63cdafc490c88612dbc091742cfe714ff32 100644 (file)
@@ -18,5 +18,6 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
 obj-$(CONFIG_USB_DSBR) += dsbr100.o
 obj-$(CONFIG_USB_SI470X) += radio-si470x.o
+obj-$(CONFIG_USB_MR800) += radio-mr800.o
 
 EXTRA_CFLAGS += -Isound
index 70c65a745923f088b96e2e8d0da59e3f7865ef25..66783fffe4c1c34dc0e57e9b32feb775c8da3fc2 100644 (file)
@@ -274,7 +274,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                struct v4l2_tuner *v)
 {
-       struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -306,7 +306,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        radio->curfreq = f->frequency;
        if (dsbr100_setfreq(radio, radio->curfreq)==-1)
@@ -317,7 +317,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = radio->curfreq;
@@ -342,7 +342,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -355,16 +355,20 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                if (ctrl->value) {
-                       if (dsbr100_stop(radio)==-1)
+                       if (dsbr100_stop(radio) == -1) {
                                warn("Radio did not respond properly");
+                               return -EBUSY;
+                       }
                } else {
-                       if (dsbr100_start(radio)==-1)
+                       if (dsbr100_start(radio) == -1) {
                                warn("Radio did not respond properly");
+                               return -EBUSY;
+                       }
                }
                return 0;
        }
@@ -405,23 +409,26 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static int usb_dsbr100_open(struct inode *inode, struct file *file)
 {
-       struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
+       lock_kernel();
        radio->users = 1;
        radio->muted = 1;
 
        if (dsbr100_start(radio)<0) {
                warn("Radio did not start up properly");
                radio->users = 0;
+               unlock_kernel();
                return -EIO;
        }
        dsbr100_setfreq(radio, radio->curfreq);
+       unlock_kernel();
        return 0;
 }
 
 static int usb_dsbr100_close(struct inode *inode, struct file *file)
 {
-       struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+       struct dsbr100_device *radio = video_drvdata(file);
 
        if (!radio)
                return -ENODEV;
@@ -507,7 +514,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
 static int __init dsbr100_init(void)
 {
        int retval = usb_register(&usb_dsbr100_driver);
-       info(DRIVER_VERSION ":" DRIVER_DESC);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
        return retval;
 }
 
index 1f064f4b32df6945c0d20262471784ddb94f7204..9305e958fc665399e5dd7454d9b56f5939d76709 100644 (file)
@@ -51,6 +51,7 @@ static struct mutex lock;
 
 struct rt_device
 {
+       unsigned long in_use;
        int port;
        int curvol;
        unsigned long curfreq;
@@ -245,8 +246,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -273,8 +273,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        rt->curfreq = f->frequency;
        rt_setfreq(rt, rt->curfreq);
@@ -284,8 +283,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = rt->curfreq;
@@ -310,8 +308,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -327,8 +324,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -378,10 +374,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct rt_device rtrack_unit;
 
+static int rtrack_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &rtrack_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = rtrack_exclusive_open,
+       .release        = rtrack_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -408,6 +415,7 @@ static struct video_device rtrack_radio = {
        .name           = "RadioTrack radio",
        .fops           = &rtrack_fops,
        .ioctl_ops      = &rtrack_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init rtrack_init(void)
@@ -424,7 +432,7 @@ static int __init rtrack_init(void)
                return -EBUSY;
        }
 
-       rtrack_radio.priv=&rtrack_unit;
+       video_set_drvdata(&rtrack_radio, &rtrack_unit);
 
        if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 2);
index 628c689e3ffe1779c422bdbc11883207a15d7c9e..d78489573230c259086711245d35775af57ed94a 100644 (file)
@@ -70,6 +70,7 @@ static struct mutex lock;
 
 struct az_device
 {
+       unsigned long in_use;
        int curvol;
        unsigned long curfreq;
        int stereo;
@@ -195,8 +196,7 @@ static int vidioc_querycap (struct file *file, void  *priv,
 static int vidioc_g_tuner (struct file *file, void *priv,
                                struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct az_device *az = dev->priv;
+       struct az_device *az = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -264,8 +264,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
 static int vidioc_s_frequency (struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct az_device *az = dev->priv;
+       struct az_device *az = video_drvdata(file);
 
        az->curfreq = f->frequency;
        az_setfreq(az, az->curfreq);
@@ -275,8 +274,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
 static int vidioc_g_frequency (struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct az_device *az = dev->priv;
+       struct az_device *az = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = az->curfreq;
@@ -302,8 +300,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
 static int vidioc_g_ctrl (struct file *file, void *priv,
                            struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct az_device *az = dev->priv;
+       struct az_device *az = video_drvdata(file);
 
        switch (ctrl->id) {
                case V4L2_CID_AUDIO_MUTE:
@@ -322,8 +319,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
 static int vidioc_s_ctrl (struct file *file, void *priv,
                            struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct az_device *az = dev->priv;
+       struct az_device *az = video_drvdata(file);
 
        switch (ctrl->id) {
                case V4L2_CID_AUDIO_MUTE:
@@ -342,10 +338,21 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
 
 static struct az_device aztech_unit;
 
+static int aztech_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
+}
+
+static int aztech_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &aztech_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations aztech_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = aztech_exclusive_open,
+       .release        = aztech_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -369,9 +376,10 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
 };
 
 static struct video_device aztech_radio = {
-       .name               = "Aztech radio",
-       .fops               = &aztech_fops,
-       .ioctl_ops          = &aztech_ioctl_ops,
+       .name           = "Aztech radio",
+       .fops           = &aztech_fops,
+       .ioctl_ops      = &aztech_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 module_param_named(debug,aztech_radio.debug, int, 0644);
@@ -392,7 +400,7 @@ static int __init aztech_init(void)
        }
 
        mutex_init(&lock);
-       aztech_radio.priv=&aztech_unit;
+       video_set_drvdata(&aztech_radio, &aztech_unit);
 
        if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io,2);
index 04c3698d32e4b77e3b28f81d104b0dcbe23dfe59..0490a1fa999db04d63a21def52448396b00dfa55 100644 (file)
@@ -589,6 +589,7 @@ static struct video_device cadet_radio = {
        .name           = "Cadet radio",
        .fops           = &cadet_fops,
        .ioctl_ops      = &cadet_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 #ifdef CONFIG_PNP
index 5cd7f032298d28e1af01a35342b9f332f8e9faa7..e15bee6d7cfcb874fedab31a35730af81a75b19b 100644 (file)
@@ -100,9 +100,8 @@ struct gemtek_pci_card {
        u8  mute;
 };
 
-static const char rcsid[] = "$Id: radio-gemtek-pci.c,v 1.1 2001/07/23 08:08:16 ted Exp ted $";
-
 static int nr_radio = -1;
+static unsigned long in_use;
 
 static inline u8 gemtek_pci_out( u16 value, u32 port )
 {
@@ -205,8 +204,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_pci_card *card = dev->priv;
+       struct gemtek_pci_card *card = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -233,8 +231,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_pci_card *card = dev->priv;
+       struct gemtek_pci_card *card = video_drvdata(file);
 
        if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) ||
                        (f->frequency > GEMTEK_PCI_RANGE_HIGH) )
@@ -248,8 +245,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_pci_card *card = dev->priv;
+       struct gemtek_pci_card *card = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = card->current_frequency;
@@ -273,8 +269,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_pci_card *card = dev->priv;
+       struct gemtek_pci_card *card = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -293,8 +288,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_pci_card *card = dev->priv;
+       struct gemtek_pci_card *card = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -364,10 +358,21 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
 
 static int mx = 1;
 
+static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &in_use);
+       return 0;
+}
+
 static const struct file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = gemtek_pci_exclusive_open,
+       .release        = gemtek_pci_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -391,9 +396,10 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
 };
 
 static struct video_device vdev_template = {
-       .name          = "Gemtek PCI Radio",
-       .fops          = &gemtek_pci_fops,
-       .ioctl_ops     = &gemtek_pci_ioctl_ops,
+       .name           = "Gemtek PCI Radio",
+       .fops           = &gemtek_pci_fops,
+       .ioctl_ops      = &gemtek_pci_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
@@ -431,7 +437,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
        }
 
        card->videodev = devradio;
-       devradio->priv = card;
+       video_set_drvdata(devradio, card);
        gemtek_pci_mute( card );
 
        printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
index 0a0f956bb308387dc7c9334f150bef5b855448b9..d131a5d381287b0069d4e83dad2615feb115adf7 100644 (file)
@@ -57,6 +57,7 @@ static int shutdown   = 1;
 static int keepmuted   = 1;
 static int initmute    = 1;
 static int radio_nr    = -1;
+static unsigned long in_use;
 
 module_param(io, int, 0444);
 MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
@@ -393,10 +394,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
        }
 };
 
+static int gemtek_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &in_use);
+       return 0;
+}
+
 static const struct file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = gemtek_exclusive_open,
+       .release        = gemtek_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -447,8 +459,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
 static int vidioc_s_frequency(struct file *file, void *priv,
                              struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_device *rt = dev->priv;
+       struct gemtek_device *rt = video_drvdata(file);
 
        gemtek_setfreq(rt, f->frequency);
 
@@ -458,8 +469,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                              struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_device *rt = dev->priv;
+       struct gemtek_device *rt = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = rt->lastfreq;
@@ -483,8 +493,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                         struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_device *rt = dev->priv;
+       struct gemtek_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -503,8 +512,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                         struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct gemtek_device *rt = dev->priv;
+       struct gemtek_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -569,9 +577,10 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
 };
 
 static struct video_device gemtek_radio = {
-       .name                   = "GemTek Radio card",
-       .fops                   = &gemtek_fops,
-       .ioctl_ops              = &gemtek_ioctl_ops,
+       .name           = "GemTek Radio card",
+       .fops           = &gemtek_fops,
+       .ioctl_ops      = &gemtek_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 /*
@@ -610,7 +619,7 @@ static int __init gemtek_init(void)
                return -EINVAL;
        }
 
-       gemtek_radio.priv = &gemtek_unit;
+       video_set_drvdata(&gemtek_radio, &gemtek_unit);
 
        if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 1);
index 9ef0a763eeb72a54570324a7b3112a549cdfdcb6..4bf4d007bcfa2b62db846c29f3c035831c5f0433 100644 (file)
@@ -75,7 +75,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
 
+static unsigned long in_use;
+
 static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static int maestro_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maestro_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &in_use);
+       return 0;
+}
+
 static void maestro_remove(struct pci_dev *pdev);
 
 static struct pci_device_id maestro_r_pci_tbl[] = {
@@ -98,8 +112,8 @@ static struct pci_driver maestro_r_driver = {
 
 static const struct file_operations maestro_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = maestro_exclusive_open,
+       .release        = maestro_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -196,8 +210,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card = video_get_drvdata(dev);
+       struct radio_device *card = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -229,8 +242,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card = video_get_drvdata(dev);
+       struct radio_device *card = video_drvdata(file);
 
        if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
                return -EINVAL;
@@ -241,8 +253,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card = video_get_drvdata(dev);
+       struct radio_device *card = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = BITS2FREQ(radio_bits_get(card));
@@ -267,8 +278,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card = video_get_drvdata(dev);
+       struct radio_device *card = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -281,8 +291,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card = video_get_drvdata(dev);
+       struct radio_device *card = video_drvdata(file);
        register u16 io = card->io;
        register u16 omask = inw(io + IO_MASK);
 
@@ -374,6 +383,7 @@ static struct video_device maestro_radio = {
        .name           = "Maestro radio",
        .fops           = &maestro_fops,
        .ioctl_ops      = &maestro_ioctl_ops,
+       .release        = video_device_release,
 };
 
 static int __devinit maestro_probe(struct pci_dev *pdev,
index 0cc6fcb041fd9773c56088ed50de1406f8030a27..c777a17b00bc21c986b08b756080a995eeeb990e 100644 (file)
@@ -85,6 +85,7 @@ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ;
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
 
+static unsigned long in_use;
 
 #define FREQ_LO                 50*16000
 #define FREQ_HI                150*16000
@@ -99,10 +100,21 @@ module_param(radio_nr, int, 0);
 #define BITS2FREQ(x)   ((x) * FREQ_STEP - FREQ_IF)
 
 
+static int maxiradio_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maxiradio_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &in_use);
+       return 0;
+}
+
 static const struct file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = maxiradio_exclusive_open,
+       .release        = maxiradio_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -219,8 +231,7 @@ static int vidioc_querycap (struct file *file, void  *priv,
 static int vidioc_g_tuner (struct file *file, void *priv,
                           struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card=dev->priv;
+       struct radio_device *card = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -290,8 +301,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
 static int vidioc_s_frequency (struct file *file, void *priv,
                               struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card=dev->priv;
+       struct radio_device *card = video_drvdata(file);
 
        if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
                dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
@@ -312,8 +322,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
 static int vidioc_g_frequency (struct file *file, void *priv,
                               struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card=dev->priv;
+       struct radio_device *card = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = card->freq;
@@ -343,8 +352,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
 static int vidioc_g_ctrl (struct file *file, void *priv,
                            struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card=dev->priv;
+       struct radio_device *card = video_drvdata(file);
 
        switch (ctrl->id) {
                case V4L2_CID_AUDIO_MUTE:
@@ -358,8 +366,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
 static int vidioc_s_ctrl (struct file *file, void *priv,
                          struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct radio_device *card=dev->priv;
+       struct radio_device *card = video_drvdata(file);
 
        switch (ctrl->id) {
                case V4L2_CID_AUDIO_MUTE:
@@ -390,9 +397,10 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
 };
 
 static struct video_device maxiradio_radio = {
-       .name               = "Maxi Radio FM2000 radio",
-       .fops               = &maxiradio_fops,
-       .ioctl_ops          = &maxiradio_ioctl_ops,
+       .name           = "Maxi Radio FM2000 radio",
+       .fops           = &maxiradio_fops,
+       .ioctl_ops      = &maxiradio_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -408,7 +416,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d
 
        radio_unit.io = pci_resource_start(pdev, 0);
        mutex_init(&radio_unit.lock);
-       maxiradio_radio.priv = &radio_unit;
+       video_set_drvdata(&maxiradio_radio, &radio_unit);
 
        if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                printk("radio-maxiradio: can't register device!");
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
new file mode 100644 (file)
index 0000000..a33717c
--- /dev/null
@@ -0,0 +1,628 @@
+/*
+ * A driver for the AverMedia MR 800 USB FM radio. This device plugs
+ * into both the USB and an analog audio input, so this thing
+ * only deals with initialization and frequency setting, the
+ * audio data has to be handled by a sound driver.
+ *
+ * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Big thanks to authors of dsbr100.c and radio-si470x.c
+ *
+ * When work was looked pretty good, i discover this:
+ * http://av-usbradio.sourceforge.net/index.php
+ * http://sourceforge.net/projects/av-usbradio/
+ * Latest release of theirs project was in 2005.
+ * Probably, this driver could be improved trough using their
+ * achievements (specifications given).
+ * So, we have smth to begin with.
+ *
+ * History:
+ * Version 0.01:       First working version.
+ *                     It's required to blacklist AverMedia USB Radio
+ *                     in usbhid/hid-quirks.c
+ *
+ * Many things to do:
+ *     - Correct power managment of device (suspend & resume)
+ *     - Make x86 independance (little-endian and big-endian stuff)
+ *     - Add code for scanning and smooth tuning
+ *     - Checked and add stereo&mono stuff
+ *     - Add code for sensitivity value
+ *     - Correct mistakes
+ *     - In Japan another FREQ_MIN and FREQ_MAX
+ */
+
+/* kernel includes */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/usb.h>
+#include <linux/version.h>     /* for KERNEL_VERSION MACRO */
+
+/* driver and module definitions */
+#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
+#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
+#define DRIVER_VERSION "0.01"
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define USB_AMRADIO_VENDOR 0x07ca
+#define USB_AMRADIO_PRODUCT 0xb800
+
+/* Probably USB_TIMEOUT should be modified in module parameter */
+#define BUFFER_LENGTH 8
+#define USB_TIMEOUT 500
+
+/* Frequency limits in MHz -- these are European values.  For Japanese
+devices, that would be 76 and 91.  */
+#define FREQ_MIN  87.5
+#define FREQ_MAX 108.0
+#define FREQ_MUL 16000
+
+/* module parameter */
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .step          = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },
+/* HINT: the disabled controls are only here to satify kradio and such apps */
+       {       .id             = V4L2_CID_AUDIO_VOLUME,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_BALANCE,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_BASS,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_TREBLE,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_LOUDNESS,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+};
+
+static int usb_amradio_probe(struct usb_interface *intf,
+                            const struct usb_device_id *id);
+static void usb_amradio_disconnect(struct usb_interface *intf);
+static int usb_amradio_open(struct inode *inode, struct file *file);
+static int usb_amradio_close(struct inode *inode, struct file *file);
+static int usb_amradio_suspend(struct usb_interface *intf,
+                               pm_message_t message);
+static int usb_amradio_resume(struct usb_interface *intf);
+
+/* Data for one (physical) device */
+struct amradio_device {
+       /* reference to USB and video device */
+       struct usb_device *usbdev;
+       struct video_device *videodev;
+
+       unsigned char *buffer;
+       struct mutex lock;      /* buffer locking */
+       int curfreq;
+       int stereo;
+       int users;
+       int removed;
+       int muted;
+};
+
+/* USB Device ID List */
+static struct usb_device_id usb_amradio_device_table[] = {
+       {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
+                                                       USB_CLASS_HID, 0, 0) },
+       { }                                             /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
+
+/* USB subsystem interface */
+static struct usb_driver usb_amradio_driver = {
+       .name                   = "radio-mr800",
+       .probe                  = usb_amradio_probe,
+       .disconnect             = usb_amradio_disconnect,
+       .suspend                = usb_amradio_suspend,
+       .resume                 = usb_amradio_resume,
+       .reset_resume           = usb_amradio_resume,
+       .id_table               = usb_amradio_device_table,
+       .supports_autosuspend   = 1,
+};
+
+/* switch on radio. Send 8 bytes to device. */
+static int amradio_start(struct amradio_device *radio)
+{
+       int retval;
+       int size;
+
+       mutex_lock(&radio->lock);
+
+       radio->buffer[0] = 0x00;
+       radio->buffer[1] = 0x55;
+       radio->buffer[2] = 0xaa;
+       radio->buffer[3] = 0x00;
+       radio->buffer[4] = 0xab;
+       radio->buffer[5] = 0x00;
+       radio->buffer[6] = 0x00;
+       radio->buffer[7] = 0x00;
+
+       retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+               (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+       if (retval) {
+               mutex_unlock(&radio->lock);
+               return retval;
+       }
+
+       mutex_unlock(&radio->lock);
+
+       radio->muted = 0;
+
+       return retval;
+}
+
+/* switch off radio */
+static int amradio_stop(struct amradio_device *radio)
+{
+       int retval;
+       int size;
+
+       mutex_lock(&radio->lock);
+
+       radio->buffer[0] = 0x00;
+       radio->buffer[1] = 0x55;
+       radio->buffer[2] = 0xaa;
+       radio->buffer[3] = 0x00;
+       radio->buffer[4] = 0xab;
+       radio->buffer[5] = 0x01;
+       radio->buffer[6] = 0x00;
+       radio->buffer[7] = 0x00;
+
+       retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+               (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+       if (retval) {
+               mutex_unlock(&radio->lock);
+               return retval;
+       }
+
+       mutex_unlock(&radio->lock);
+
+       radio->muted = 1;
+
+       return retval;
+}
+
+/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static int amradio_setfreq(struct amradio_device *radio, int freq)
+{
+       int retval;
+       int size;
+       unsigned short freq_send = 0x13 + (freq >> 3) / 25;
+
+       mutex_lock(&radio->lock);
+
+       radio->buffer[0] = 0x00;
+       radio->buffer[1] = 0x55;
+       radio->buffer[2] = 0xaa;
+       radio->buffer[3] = 0x03;
+       radio->buffer[4] = 0xa4;
+       radio->buffer[5] = 0x00;
+       radio->buffer[6] = 0x00;
+       radio->buffer[7] = 0x08;
+
+       retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+               (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+       if (retval) {
+               mutex_unlock(&radio->lock);
+               return retval;
+       }
+
+       /* frequency is calculated from freq_send and placed in first 2 bytes */
+       radio->buffer[0] = (freq_send >> 8) & 0xff;
+       radio->buffer[1] = freq_send & 0xff;
+       radio->buffer[2] = 0x01;
+       radio->buffer[3] = 0x00;
+       radio->buffer[4] = 0x00;
+       /* 5 and 6 bytes of buffer already = 0x00 */
+       radio->buffer[7] = 0x00;
+
+       retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+               (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+       if (retval) {
+               mutex_unlock(&radio->lock);
+               return retval;
+       }
+
+       mutex_unlock(&radio->lock);
+
+       radio->stereo = 0;
+
+       return retval;
+}
+
+/* USB subsystem interface begins here */
+
+/* handle unplugging of the device, release data structures
+if nothing keeps us from doing it.  If something is still
+keeping us busy, the release callback of v4l will take care
+of releasing it. */
+static void usb_amradio_disconnect(struct usb_interface *intf)
+{
+       struct amradio_device *radio = usb_get_intfdata(intf);
+
+       usb_set_intfdata(intf, NULL);
+
+       if (radio) {
+               video_unregister_device(radio->videodev);
+               radio->videodev = NULL;
+               if (radio->users) {
+                       kfree(radio->buffer);
+                       kfree(radio);
+               } else {
+                       radio->removed = 1;
+               }
+       }
+}
+
+/* vidioc_querycap - query device capabilities */
+static int vidioc_querycap(struct file *file, void *priv,
+                                       struct v4l2_capability *v)
+{
+       strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
+       strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
+       sprintf(v->bus_info, "USB");
+       v->version = RADIO_VERSION;
+       v->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
+
+/* vidioc_g_tuner - get tuner attributes */
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *v)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       if (v->index > 0)
+               return -EINVAL;
+
+/* TODO: Add function which look is signal stereo or not
+ *     amradio_getstat(radio);
+ */
+       radio->stereo = -1;
+       strcpy(v->name, "FM");
+       v->type = V4L2_TUNER_RADIO;
+       v->rangelow = FREQ_MIN * FREQ_MUL;
+       v->rangehigh = FREQ_MAX * FREQ_MUL;
+       v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+       v->capability = V4L2_TUNER_CAP_LOW;
+       if (radio->stereo)
+               v->audmode = V4L2_TUNER_MODE_STEREO;
+       else
+               v->audmode = V4L2_TUNER_MODE_MONO;
+       v->signal = 0xffff;     /* Can't get the signal strength, sad.. */
+       v->afc = 0; /* Don't know what is this */
+       return 0;
+}
+
+/* vidioc_s_tuner - set tuner attributes */
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *v)
+{
+       if (v->index > 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* vidioc_s_frequency - set tuner radio frequency */
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       radio->curfreq = f->frequency;
+       if (amradio_setfreq(radio, radio->curfreq) < 0)
+               warn("Set frequency failed");
+       return 0;
+}
+
+/* vidioc_g_frequency - get tuner radio frequency */
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       f->type = V4L2_TUNER_RADIO;
+       f->frequency = radio->curfreq;
+       return 0;
+}
+
+/* vidioc_queryctrl - enumerate control items */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+               if (qc->id && qc->id == radio_qctrl[i].id) {
+                       memcpy(qc, &(radio_qctrl[i]),
+                                               sizeof(*qc));
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+/* vidioc_g_ctrl - get the value of a control */
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               ctrl->value = radio->muted;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+/* vidioc_s_ctrl - set the value of a control */
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               if (ctrl->value) {
+                       if (amradio_stop(radio) < 0) {
+                               warn("amradio_stop() failed");
+                               return -1;
+                       }
+               } else {
+                       if (amradio_start(radio) < 0) {
+                               warn("amradio_start() failed");
+                               return -1;
+                       }
+               }
+               return 0;
+       }
+       return -EINVAL;
+}
+
+/* vidioc_g_audio - get audio attributes */
+static int vidioc_g_audio(struct file *file, void *priv,
+                               struct v4l2_audio *a)
+{
+       if (a->index > 1)
+               return -EINVAL;
+
+       strcpy(a->name, "Radio");
+       a->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+/* vidioc_s_audio - set audio attributes  */
+static int vidioc_s_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       if (a->index != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* vidioc_g_input - get input */
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+/* vidioc_s_input - set input */
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+       return 0;
+}
+
+/* open device - amradio_start() and amradio_setfreq() */
+static int usb_amradio_open(struct inode *inode, struct file *file)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       radio->users = 1;
+       radio->muted = 1;
+
+       if (amradio_start(radio) < 0) {
+               warn("Radio did not start up properly");
+               radio->users = 0;
+               return -EIO;
+       }
+       if (amradio_setfreq(radio, radio->curfreq) < 0)
+               warn("Set frequency failed");
+       return 0;
+}
+
+/*close device - free driver structures */
+static int usb_amradio_close(struct inode *inode, struct file *file)
+{
+       struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+       if (!radio)
+               return -ENODEV;
+       radio->users = 0;
+       if (radio->removed) {
+               kfree(radio->buffer);
+               kfree(radio);
+       }
+       return 0;
+}
+
+/* Suspend device - stop device. Need to be checked and fixed */
+static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct amradio_device *radio = usb_get_intfdata(intf);
+
+       if (amradio_stop(radio) < 0)
+               warn("amradio_stop() failed");
+
+       info("radio-mr800: Going into suspend..");
+
+       return 0;
+}
+
+/* Resume device - start device. Need to be checked and fixed */
+static int usb_amradio_resume(struct usb_interface *intf)
+{
+       struct amradio_device *radio = usb_get_intfdata(intf);
+
+       if (amradio_start(radio) < 0)
+               warn("amradio_start() failed");
+
+       info("radio-mr800: Coming out of suspend..");
+
+       return 0;
+}
+
+/* File system interface */
+static const struct file_operations usb_amradio_fops = {
+       .owner          = THIS_MODULE,
+       .open           = usb_amradio_open,
+       .release        = usb_amradio_close,
+       .ioctl          = video_ioctl2,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = v4l_compat_ioctl32,
+#endif
+       .llseek         = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
+       .vidioc_querycap    = vidioc_querycap,
+       .vidioc_g_tuner     = vidioc_g_tuner,
+       .vidioc_s_tuner     = vidioc_s_tuner,
+       .vidioc_g_frequency = vidioc_g_frequency,
+       .vidioc_s_frequency = vidioc_s_frequency,
+       .vidioc_queryctrl   = vidioc_queryctrl,
+       .vidioc_g_ctrl      = vidioc_g_ctrl,
+       .vidioc_s_ctrl      = vidioc_s_ctrl,
+       .vidioc_g_audio     = vidioc_g_audio,
+       .vidioc_s_audio     = vidioc_s_audio,
+       .vidioc_g_input     = vidioc_g_input,
+       .vidioc_s_input     = vidioc_s_input,
+};
+
+/* V4L2 interface */
+static struct video_device amradio_videodev_template = {
+       .name           = "AverMedia MR 800 USB FM Radio",
+       .fops           = &usb_amradio_fops,
+       .ioctl_ops      = &usb_amradio_ioctl_ops,
+       .release        = video_device_release,
+};
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_amradio_probe(struct usb_interface *intf,
+                               const struct usb_device_id *id)
+{
+       struct amradio_device *radio;
+
+       radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
+
+       if (!(radio))
+               return -ENOMEM;
+
+       radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
+
+       if (!(radio->buffer)) {
+               kfree(radio);
+               return -ENOMEM;
+       }
+
+       radio->videodev = video_device_alloc();
+
+       if (!(radio->videodev)) {
+               kfree(radio->buffer);
+               kfree(radio);
+               return -ENOMEM;
+       }
+
+       memcpy(radio->videodev, &amradio_videodev_template,
+               sizeof(amradio_videodev_template));
+
+       radio->removed = 0;
+       radio->users = 0;
+       radio->usbdev = interface_to_usbdev(intf);
+       radio->curfreq = 95.16 * FREQ_MUL;
+
+       mutex_init(&radio->lock);
+
+       video_set_drvdata(radio->videodev, radio);
+       if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+               warn("Could not register video device");
+               video_device_release(radio->videodev);
+               kfree(radio->buffer);
+               kfree(radio);
+               return -EIO;
+       }
+
+       usb_set_intfdata(intf, radio);
+       return 0;
+}
+
+static int __init amradio_init(void)
+{
+       int retval = usb_register(&usb_amradio_driver);
+
+       info(DRIVER_VERSION " " DRIVER_DESC);
+       if (retval)
+               err("usb_register failed. Error number %d", retval);
+       return retval;
+}
+
+static void __exit amradio_exit(void)
+{
+       usb_deregister(&usb_amradio_driver);
+}
+
+module_init(amradio_init);
+module_exit(amradio_exit);
+
index 6d820e2481e7cc0e9e8b1d02a93f974289e35ce5..a67079777419571e875100f6d488e9c0178d939c 100644 (file)
@@ -52,6 +52,7 @@ static spinlock_t lock;
 
 struct rt_device
 {
+       unsigned long in_use;
        int port;
        unsigned long curfreq;
        int muted;
@@ -153,8 +154,7 @@ static int rt_getsigstr(struct rt_device *dev)
 static int vidioc_g_tuner(struct file *file, void *priv,
                                struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -173,8 +173,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        rt->curfreq = f->frequency;
        rt_setfreq(rt, rt->curfreq);
@@ -184,8 +183,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = rt->curfreq;
@@ -210,8 +208,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -230,8 +227,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct rt_device *rt = dev->priv;
+       struct rt_device *rt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct rt_device rtrack2_unit;
 
+static int rtrack2_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack2_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &rtrack2_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = rtrack2_exclusive_open,
+       .release        = rtrack2_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device rtrack2_radio = {
        .name           = "RadioTrack II radio",
        .fops           = &rtrack2_fops,
        .ioctl_ops      = &rtrack2_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init rtrack2_init(void)
@@ -329,7 +337,7 @@ static int __init rtrack2_init(void)
                return -EBUSY;
        }
 
-       rtrack2_radio.priv=&rtrack2_unit;
+       video_set_drvdata(&rtrack2_radio, &rtrack2_unit);
 
        spin_lock_init(&lock);
        if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
index 0d478f54a90770810198a3e14551ac287b807353..329c90bddadd953836b25cd10dd9668bf2e99329 100644 (file)
@@ -45,6 +45,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 
 struct fmi_device
 {
+       unsigned long in_use;
        int port;
        int curvol; /* 1 or 0 */
        unsigned long curfreq; /* freq in kHz */
@@ -146,8 +147,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
        int mult;
-       struct video_device *dev = video_devdata(file);
-       struct fmi_device *fmi = dev->priv;
+       struct fmi_device *fmi = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -175,8 +175,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmi_device *fmi = dev->priv;
+       struct fmi_device *fmi = video_drvdata(file);
 
        if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
                f->frequency *= 1000;
@@ -193,8 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmi_device *fmi = dev->priv;
+       struct fmi_device *fmi = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = fmi->curfreq;
@@ -221,8 +219,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmi_device *fmi = dev->priv;
+       struct fmi_device *fmi = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -235,8 +232,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmi_device *fmi = dev->priv;
+       struct fmi_device *fmi = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct fmi_device fmi_unit;
 
+static int fmi_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmi_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &fmi_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations fmi_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = fmi_exclusive_open,
+       .release        = fmi_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device fmi_radio = {
        .name           = "SF16FMx radio",
        .fops           = &fmi_fops,
        .ioctl_ops      = &fmi_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 /* ladis: this is my card. does any other types exist? */
@@ -373,7 +381,7 @@ static int __init fmi_init(void)
        fmi_unit.curvol = 0;
        fmi_unit.curfreq = 0;
        fmi_unit.flags = V4L2_TUNER_CAP_LOW;
-       fmi_radio.priv = &fmi_unit;
+       video_set_drvdata(&fmi_radio, &fmi_unit);
 
        mutex_init(&lock);
 
index 6290553d24beef56cf55ecfbe55aab32ae0ad620..b1f47c322e02637e58b2117a3c7df2e51656dd76 100644 (file)
@@ -64,6 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 /* this should be static vars for module size */
 struct fmr2_device
 {
+       unsigned long in_use;
        int port;
        int curvol; /* 0-15 */
        int mute;
@@ -229,8 +230,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
        int mult;
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
+       struct fmr2_device *fmr2 = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -262,8 +262,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
+       struct fmr2_device *fmr2 = video_drvdata(file);
 
        if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
                f->frequency *= 1000;
@@ -286,8 +285,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
+       struct fmr2_device *fmr2 = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = fmr2->curfreq;
@@ -313,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
+       struct fmr2_device *fmr2 = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct fmr2_device *fmr2 = dev->priv;
+       struct fmr2_device *fmr2 = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -400,10 +396,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct fmr2_device fmr2_unit;
 
+static int fmr2_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmr2_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &fmr2_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = fmr2_exclusive_open,
+       .release        = fmr2_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -430,6 +437,7 @@ static struct video_device fmr2_radio = {
        .name           = "SF16FMR2 radio",
        .fops           = &fmr2_fops,
        .ioctl_ops      = &fmr2_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init fmr2_init(void)
@@ -441,7 +449,7 @@ static int __init fmr2_init(void)
        fmr2_unit.stereo = 1;
        fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
        fmr2_unit.card_type = 0;
-       fmr2_radio.priv = &fmr2_unit;
+       video_set_drvdata(&fmr2_radio, &fmr2_unit);
 
        mutex_init(&lock);
 
index 16c7ef20265c4c34e3782baead264700797923dd..f6cedcd3ab97b82b532b16a03137eb0fd5c7e75f 100644 (file)
@@ -986,7 +986,7 @@ static void si470x_work(struct work_struct *work)
 static ssize_t si470x_fops_read(struct file *file, char __user *buf,
                size_t count, loff_t *ppos)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
        unsigned int block_count = 0;
 
@@ -1047,7 +1047,7 @@ done:
 static unsigned int si470x_fops_poll(struct file *file,
                struct poll_table_struct *pts)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* switch on rds reception */
@@ -1071,9 +1071,10 @@ static unsigned int si470x_fops_poll(struct file *file,
  */
 static int si470x_fops_open(struct inode *inode, struct file *file)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval;
 
+       lock_kernel();
        radio->users++;
 
        retval = usb_autopm_get_interface(radio->intf);
@@ -1090,6 +1091,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
        }
 
 done:
+       unlock_kernel();
        return retval;
 }
 
@@ -1099,7 +1101,7 @@ done:
  */
 static int si470x_fops_release(struct inode *inode, struct file *file)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety check */
@@ -1282,7 +1284,7 @@ done:
 static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
                struct v4l2_control *ctrl)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1318,7 +1320,7 @@ done:
 static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
                struct v4l2_control *ctrl)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1405,7 +1407,7 @@ done:
 static int si470x_vidioc_g_tuner(struct file *file, void *priv,
                struct v4l2_tuner *tuner)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1471,7 +1473,7 @@ done:
 static int si470x_vidioc_s_tuner(struct file *file, void *priv,
                struct v4l2_tuner *tuner)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1505,7 +1507,7 @@ done:
 static int si470x_vidioc_g_frequency(struct file *file, void *priv,
                struct v4l2_frequency *freq)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1534,7 +1536,7 @@ done:
 static int si470x_vidioc_s_frequency(struct file *file, void *priv,
                struct v4l2_frequency *freq)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
@@ -1563,7 +1565,7 @@ done:
 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
                struct v4l2_hw_freq_seek *seek)
 {
-       struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+       struct si470x_device *radio = video_drvdata(file);
        int retval = 0;
 
        /* safety checks */
index 0876fecc5f275de8bf61bf1ab5d3713c90349c0f..0abb186a9473e5661dd1a117e83acdc9fe034a98 100644 (file)
@@ -79,6 +79,7 @@ static spinlock_t lock;
 
 struct tt_device
 {
+       unsigned long in_use;
        int port;
        int curvol;
        unsigned long curfreq;
@@ -220,8 +221,7 @@ static int vidioc_querycap(struct file *file, void *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct tt_device *tt = dev->priv;
+       struct tt_device *tt = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -248,8 +248,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct tt_device *tt = dev->priv;
+       struct tt_device *tt = video_drvdata(file);
 
        tt->curfreq = f->frequency;
        tt_setfreq(tt, tt->curfreq);
@@ -259,8 +258,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct tt_device *tt = dev->priv;
+       struct tt_device *tt = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = tt->curfreq;
@@ -285,8 +283,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct tt_device *tt = dev->priv;
+       struct tt_device *tt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -305,8 +302,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct tt_device *tt = dev->priv;
+       struct tt_device *tt = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -356,10 +352,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct tt_device terratec_unit;
 
+static int terratec_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
+}
+
+static int terratec_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &terratec_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations terratec_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = terratec_exclusive_open,
+       .release        = terratec_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -386,6 +393,7 @@ static struct video_device terratec_radio = {
        .name           = "TerraTec ActiveRadio",
        .fops           = &terratec_fops,
        .ioctl_ops      = &terratec_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init terratec_init(void)
@@ -401,7 +409,7 @@ static int __init terratec_init(void)
                return -EBUSY;
        }
 
-       terratec_radio.priv=&terratec_unit;
+       video_set_drvdata(&terratec_radio, &terratec_unit);
 
        spin_lock_init(&lock);
 
index 193161956253422121f906d46729013c114716a4..e7b111fcd105b6fc79a3a11c922d6edf2a0542e1 100644 (file)
@@ -78,6 +78,7 @@ static __u16 curtreble;
 static unsigned long curfreq;
 static int curstereo;
 static int curmute;
+static unsigned long in_use;
 
 /* i2c addresses */
 #define TDA7318_ADDR 0x88
@@ -336,10 +337,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
+static int trust_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int trust_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &in_use);
+       return 0;
+}
+
 static const struct file_operations trust_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = trust_exclusive_open,
+       .release        = trust_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -366,6 +378,7 @@ static struct video_device trust_radio = {
        .name           = "Trust FM Radio",
        .fops           = &trust_fops,
        .ioctl_ops      = &trust_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init trust_init(void)
index f8d62cfea7745d28cdda0c5be81667e4fb571c09..952ec35a8415129100ae56564ee2e956facbccd7 100644 (file)
@@ -79,7 +79,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 #endif
 
 struct typhoon_device {
-       int users;
+       unsigned long in_use;
        int iobase;
        int curvol;
        int muted;
@@ -223,8 +223,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct typhoon_device *typhoon = dev->priv;
+       struct typhoon_device *typhoon = video_drvdata(file);
 
        typhoon->curfreq = f->frequency;
        typhoon_setfreq(typhoon, typhoon->curfreq);
@@ -234,8 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct typhoon_device *typhoon = dev->priv;
+       struct typhoon_device *typhoon = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = typhoon->curfreq;
@@ -261,8 +259,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct typhoon_device *typhoon = dev->priv;
+       struct typhoon_device *typhoon = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -278,8 +275,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl (struct file *file, void *priv,
                                        struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct typhoon_device *typhoon = dev->priv;
+       struct typhoon_device *typhoon = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -334,10 +330,21 @@ static struct typhoon_device typhoon_unit =
        .mutefreq       = CONFIG_RADIO_TYPHOON_MUTEFREQ,
 };
 
+static int typhoon_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
+}
+
+static int typhoon_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &typhoon_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = typhoon_exclusive_open,
+       .release        = typhoon_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -364,6 +371,7 @@ static struct video_device typhoon_radio = {
        .name           = "Typhoon Radio",
        .fops           = &typhoon_fops,
        .ioctl_ops      = &typhoon_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
@@ -446,9 +454,8 @@ static int __init typhoon_init(void)
                return -EBUSY;
        }
 
-       typhoon_radio.priv = &typhoon_unit;
-       if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1)
-       {
+       video_set_drvdata(&typhoon_radio, &typhoon_unit);
+       if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
                release_region(io, 8);
                return -EINVAL;
        }
index 51d57ed3b3e12a5db805f09cb93acc9c39560e7c..15b10bad679660efa22b59bc3d70f161841c07f0 100644 (file)
@@ -69,6 +69,7 @@ static int io = CONFIG_RADIO_ZOLTRIX_PORT;
 static int radio_nr = -1;
 
 struct zol_device {
+       unsigned long in_use;
        int port;
        int curvol;
        unsigned long curfreq;
@@ -122,8 +123,11 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
        unsigned int stereo = dev->stereo;
        int i;
 
-       if (freq == 0)
-               return 1;
+       if (freq == 0) {
+               printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n");
+               return -EINVAL;
+       }
+
        m = (freq / 160 - 8800) * 2;
        f = (unsigned long long) m + 0x4d1c;
 
@@ -245,8 +249,7 @@ static int vidioc_querycap(struct file *file, void  *priv,
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
-       struct video_device *dev = video_devdata(file);
-       struct zol_device *zol = dev->priv;
+       struct zol_device *zol = video_drvdata(file);
 
        if (v->index > 0)
                return -EINVAL;
@@ -276,19 +279,20 @@ static int vidioc_s_tuner(struct file *file, void *priv,
 static int vidioc_s_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct zol_device *zol = dev->priv;
+       struct zol_device *zol = video_drvdata(file);
 
        zol->curfreq = f->frequency;
-       zol_setfreq(zol, zol->curfreq);
+       if (zol_setfreq(zol, zol->curfreq) != 0) {
+               printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+               return -EINVAL;
+       }
        return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
                                        struct v4l2_frequency *f)
 {
-       struct video_device *dev = video_devdata(file);
-       struct zol_device *zol = dev->priv;
+       struct zol_device *zol = video_drvdata(file);
 
        f->type = V4L2_TUNER_RADIO;
        f->frequency = zol->curfreq;
@@ -313,8 +317,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 static int vidioc_g_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct zol_device *zol = dev->priv;
+       struct zol_device *zol = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +333,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct zol_device *zol = dev->priv;
+       struct zol_device *zol = video_drvdata(file);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
@@ -347,7 +349,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
                return 0;
        }
        zol->stereo = 1;
-       zol_setfreq(zol, zol->curfreq);
+       if (zol_setfreq(zol, zol->curfreq) != 0) {
+               printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+               return -EINVAL;
+       }
 #if 0
 /* FIXME: Implement stereo/mono switch on V4L2 */
                        if (v->mode & VIDEO_SOUND_STEREO) {
@@ -396,11 +401,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static struct zol_device zoltrix_unit;
 
+static int zoltrix_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
+}
+
+static int zoltrix_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &zoltrix_unit.in_use);
+       return 0;
+}
+
 static const struct file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = zoltrix_exclusive_open,
+       .release        = zoltrix_exclusive_release,
        .ioctl          = video_ioctl2,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -427,6 +443,7 @@ static struct video_device zoltrix_radio = {
        .name           = "Zoltrix Radio Plus",
        .fops           = &zoltrix_fops,
        .ioctl_ops      = &zoltrix_ioctl_ops,
+       .release        = video_device_release_empty,
 };
 
 static int __init zoltrix_init(void)
@@ -440,7 +457,7 @@ static int __init zoltrix_init(void)
                return -ENXIO;
        }
 
-       zoltrix_radio.priv = &zoltrix_unit;
+       video_set_drvdata(&zoltrix_radio, &zoltrix_unit);
        if (!request_region(io, 2, "zoltrix")) {
                printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
                return -EBUSY;
index 3e9e0dcd217ecfaf278cdef11f6cb8cb18f666a2..47102c2c8250fc51df410059ba5b52c24ea5f510 100644 (file)
@@ -34,6 +34,7 @@ config VIDEOBUF_DVB
        select VIDEOBUF_GEN
 
 config VIDEO_BTCX
+       depends on PCI
        tristate
 
 config VIDEO_IR
@@ -71,6 +72,15 @@ config VIDEO_ADV_DEBUG
          V4L devices.
          In doubt, say N.
 
+config VIDEO_FIXED_MINOR_RANGES
+       bool "Enable old-style fixed minor ranges for video devices"
+       default n
+       ---help---
+         Say Y here to enable the old-style fixed-range minor assignments.
+         Only useful if you rely on the old behavior and use mknod instead of udev.
+
+         When in doubt, say N.
+
 config VIDEO_HELPER_CHIPS_AUTO
        bool "Autoselect pertinent encoders/decoders and other helper chips"
        default y
@@ -578,13 +588,6 @@ config VIDEO_SAA5249
          To compile this driver as a module, choose M here: the
          module will be called saa5249.
 
-config TUNER_3036
-       tristate "SAB3036 tuner"
-       depends on I2C && VIDEO_V4L1
-       help
-         Say Y here to include support for Philips SAB3036 compatible tuners.
-         If in doubt, say N.
-
 config VIDEO_VINO
        tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
        depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
@@ -602,79 +605,7 @@ config VIDEO_STRADIS
          driver for PCI.  There is a product page at
          <http://www.stradis.com/>.
 
-config VIDEO_ZORAN
-       tristate "Zoran ZR36057/36067 Video For Linux"
-       depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
-       help
-         Say Y for support for MJPEG capture cards based on the Zoran
-         36057/36067 PCI controller chipset. This includes the Iomega
-         Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
-         a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
-         more information, check <file:Documentation/video4linux/Zoran>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr36067.
-
-config VIDEO_ZORAN_DC30
-       tristate "Pinnacle/Miro DC30(+) support"
-       depends on VIDEO_ZORAN
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
-         card. This also supports really old DC10 cards based on the
-         zr36050 MJPEG codec and zr36016 VFE.
-
-config VIDEO_ZORAN_ZR36060
-       tristate "Zoran ZR36060"
-       depends on VIDEO_ZORAN
-       help
-         Say Y to support Zoran boards based on 36060 chips.
-         This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
-         and 33 R10 and AverMedia 6 boards.
-
-config VIDEO_ZORAN_BUZ
-       tristate "Iomega Buz support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Iomega Buz MJPEG capture/playback card.
-
-config VIDEO_ZORAN_DC10
-       tristate "Pinnacle/Miro DC10(+) support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_LML33
-       tristate "Linux Media Labs LML33 support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Linux Media Labs LML33 MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_LML33R10
-       tristate "Linux Media Labs LML33R10 support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         support for the Linux Media Labs LML33R10 MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_AVS6EYES
-       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
-       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the AverMedia 6 Eyes video surveillance card.
+source "drivers/media/video/zoran/Kconfig"
 
 config VIDEO_MEYE
        tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
@@ -697,7 +628,7 @@ config VIDEO_MXB
        depends on PCI && VIDEO_V4L1 && I2C
        select VIDEO_SAA7146_VV
        select VIDEO_TUNER
-       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
@@ -708,21 +639,6 @@ config VIDEO_MXB
          To compile this driver as a module, choose M here: the
          module will be called mxb.
 
-config VIDEO_DPC
-       tristate "Philips-Semiconductors 'dpc7146 demonstration board'"
-       depends on PCI && VIDEO_V4L1 && I2C
-       select VIDEO_SAA7146_VV
-       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         This is a video4linux driver for the 'dpc7146 demonstration
-         board' by Philips-Semiconductors. It's the reference design
-         for SAA7146 bases boards, so if you have some unsupported
-         saa7146 based, analog video card, chances are good that it
-         will work with this skeleton driver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called dpc7146.
-
 config VIDEO_HEXIUM_ORION
        tristate "Hexium HV-PCI6 and Orion frame grabber"
        depends on PCI && VIDEO_V4L2 && I2C
@@ -784,6 +700,70 @@ config VIDEO_CAFE_CCIC
          CMOS camera controller.  This is the controller found on first-
          generation OLPC systems.
 
+config SOC_CAMERA
+       tristate "SoC camera support"
+       depends on VIDEO_V4L2 && HAS_DMA
+       select VIDEOBUF_GEN
+       help
+         SoC Camera is a common API to several cameras, not connecting
+         over a bus like PCI or USB. For example some i2c camera connected
+         directly to the data bus of an SoC.
+
+config SOC_CAMERA_MT9M001
+       tristate "mt9m001 support"
+       depends on SOC_CAMERA && I2C
+       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+       help
+         This driver supports MT9M001 cameras from Micron, monochrome
+         and colour models.
+
+config MT9M001_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9m001"
+       depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
+       help
+         Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_MT9M111
+       tristate "mt9m111 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports MT9M111 cameras from Micron
+
+config SOC_CAMERA_MT9V022
+       tristate "mt9v022 support"
+       depends on SOC_CAMERA && I2C
+       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+       help
+         This driver supports MT9V022 cameras from Micron
+
+config MT9V022_PCA9536_SWITCH
+       bool "pca9536 datawidth switch for mt9v022"
+       depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
+       help
+         Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
+         extender to switch between 8 and 10 bit datawidth modes
+
+config SOC_CAMERA_PLATFORM
+       tristate "platform camera support"
+       depends on SOC_CAMERA
+       help
+         This is a generic SoC camera platform driver, useful for testing
+
+config VIDEO_PXA27x
+       tristate "PXA27x Quick Capture Interface driver"
+       depends on VIDEO_DEV && PXA27x && SOC_CAMERA
+       select VIDEOBUF_DMA_SG
+       ---help---
+         This is a v4l2 driver for the PXA27x Quick Capture Interface
+
+config VIDEO_SH_MOBILE_CEU
+       tristate "SuperH Mobile CEU Interface driver"
+       depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA
+       select VIDEOBUF_DMA_CONTIG
+       ---help---
+         This is a v4l2 driver for the SuperH Mobile CEU Interface
+
 #
 # USB Multimedia device configuration
 #
@@ -822,8 +802,7 @@ config VIDEO_OVCAMCHIP
 
 config USB_W9968CF
        tristate "USB W996[87]CF JPEG Dual Mode Camera support"
-       depends on VIDEO_V4L1 && I2C
-       select VIDEO_OVCAMCHIP
+       depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
        ---help---
          Say Y here if you want support for cameras based on OV681 or
          Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
@@ -914,64 +893,4 @@ config USB_S2255
 
 endif # V4L_USB_DRIVERS
 
-config SOC_CAMERA
-       tristate "SoC camera support"
-       depends on VIDEO_V4L2 && HAS_DMA
-       select VIDEOBUF_GEN
-       help
-         SoC Camera is a common API to several cameras, not connecting
-         over a bus like PCI or USB. For example some i2c camera connected
-         directly to the data bus of an SoC.
-
-config SOC_CAMERA_MT9M001
-       tristate "mt9m001 support"
-       depends on SOC_CAMERA && I2C
-       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
-       help
-         This driver supports MT9M001 cameras from Micron, monochrome
-         and colour models.
-
-config MT9M001_PCA9536_SWITCH
-       bool "pca9536 datawidth switch for mt9m001"
-       depends on SOC_CAMERA_MT9M001 && GENERIC_GPIO
-       help
-         Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
-         extender to switch between 8 and 10 bit datawidth modes
-
-config SOC_CAMERA_MT9V022
-       tristate "mt9v022 support"
-       depends on SOC_CAMERA && I2C
-       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
-       help
-         This driver supports MT9V022 cameras from Micron
-
-config MT9V022_PCA9536_SWITCH
-       bool "pca9536 datawidth switch for mt9v022"
-       depends on SOC_CAMERA_MT9V022 && GENERIC_GPIO
-       help
-         Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
-         extender to switch between 8 and 10 bit datawidth modes
-
-config SOC_CAMERA_PLATFORM
-       tristate "platform camera support"
-       depends on SOC_CAMERA
-       help
-         This is a generic SoC camera platform driver, useful for testing
-
-config VIDEO_PXA27x
-       tristate "PXA27x Quick Capture Interface driver"
-       depends on VIDEO_DEV && PXA27x
-       select SOC_CAMERA
-       select VIDEOBUF_DMA_SG
-       ---help---
-         This is a v4l2 driver for the PXA27x Quick Capture Interface
-
-config VIDEO_SH_MOBILE_CEU
-       tristate "SuperH Mobile CEU Interface driver"
-       depends on VIDEO_DEV && HAS_DMA
-       select SOC_CAMERA
-       select VIDEOBUF_DMA_CONTIG
-       ---help---
-         This is a v4l2 driver for the SuperH Mobile CEU Interface
-
 endif # VIDEO_CAPTURE_DRIVERS
index ef7c8d3ffb18bba4e3930668285a30883fc1fc10..16962f3aa15767f09d71ffaa492e2d6f3db562c4 100644 (file)
@@ -2,8 +2,6 @@
 # Makefile for the video capture/playback device drivers.
 #
 
-zr36067-objs   :=      zoran_procfs.o zoran_device.o \
-                       zoran_driver.o zoran_card.o
 tuner-objs     :=      tuner-core.o
 
 msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
@@ -54,9 +52,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o
 obj-$(CONFIG_VIDEO_BT866) += bt866.o
 obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
 
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
-obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
-obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
 
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
@@ -84,8 +80,6 @@ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
-obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
-obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
 obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
 obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@@ -137,6 +131,7 @@ obj-$(CONFIG_VIDEO_PXA27x)  += pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)      += sh_mobile_ceu_camera.o
 obj-$(CONFIG_SOC_CAMERA)       += soc_camera.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111)       += mt9m111.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
 obj-$(CONFIG_SOC_CAMERA_PLATFORM)      += soc_camera_platform.o
 
index 9e436ad3d34b64b9d695346b238eae9438a329e9..218754b4906a7a4fee61b7840dc4b8ed1db92ad4 100644 (file)
@@ -116,6 +116,7 @@ struct ar_device {
        int width, height;
        int frame_bytes, line_bytes;
        wait_queue_head_t wait;
+       unsigned long in_use;
        struct mutex lock;
 };
 
@@ -269,7 +270,7 @@ static inline void wait_for_vertical_sync(int exp_line)
 static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
        struct video_device *v = video_devdata(file);
-       struct ar_device *ar = v->priv;
+       struct ar_device *ar = video_get_drvdata(v);
        long ret = ar->frame_bytes;             /* return read bytes */
        unsigned long arvcr1 = 0;
        unsigned long flags;
@@ -399,7 +400,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
-       struct ar_device *ar = dev->priv;
+       struct ar_device *ar = video_get_drvdata(dev);
 
        DEBUG(1, "ar_ioctl()\n");
        switch(cmd) {
@@ -625,7 +626,7 @@ static void ar_interrupt(int irq, void *dev)
  */
 static int ar_initialize(struct video_device *dev)
 {
-       struct ar_device *ar = dev->priv;
+       struct ar_device *ar = video_get_drvdata(dev);
        unsigned long cr = 0;
        int i,found=0;
 
@@ -732,7 +733,7 @@ static int ar_initialize(struct video_device *dev)
 
 void ar_release(struct video_device *vfd)
 {
-       struct ar_device *ar = vfd->priv;
+       struct ar_device *ar = video_get_drvdata(vfd);
        mutex_lock(&ar->lock);
        video_device_release(vfd);
 }
@@ -742,10 +743,23 @@ void ar_release(struct video_device *vfd)
  * Video4Linux Module functions
  *
  ****************************************************************************/
+static struct ar_device ardev;
+
+static int ar_exclusive_open(struct inode *inode, struct file *file)
+{
+       return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0;
+}
+
+static int ar_exclusive_release(struct inode *inode, struct file *file)
+{
+       clear_bit(0, &ardev.in_use);
+       return 0;
+}
+
 static const struct file_operations ar_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = ar_exclusive_open,
+       .release        = ar_exclusive_release,
        .read           = ar_read,
        .ioctl          = ar_ioctl,
 #ifdef CONFIG_COMPAT
@@ -762,7 +776,6 @@ static struct video_device ar_template = {
 };
 
 #define ALIGN4(x)      ((((int)(x)) & 0x3) == 0)
-static struct ar_device ardev;
 
 static int __init ar_init(void)
 {
@@ -802,7 +815,7 @@ static int __init ar_init(void)
                return -ENOMEM;
        }
        memcpy(ar->vdev, &ar_template, sizeof(ar_template));
-       ar->vdev->priv = ar;
+       video_set_drvdata(ar->vdev, ar);
 
        if (vga) {
                ar->width       = AR_WIDTH_VGA;
index ed48908a90340666f0726a77fc8b59c48e3e758f..5f07a8a072b64ed119c7c7b39e760c7bd985ea8e 100644 (file)
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = {
 /* Tuner callback function for au0828 boards. Currently only needed
  * for HVR1500Q, which has an xc5000 tuner.
  */
-int au0828_tuner_callback(void *priv, int command, int arg)
+int au0828_tuner_callback(void *priv, int component, int command, int arg)
 {
        struct au0828_dev *dev = priv;
 
index ba94be7e0ac1cdc65fb767d28cb8466e85cf9767..f0fcdb4769d73697e8d8a4ac9381854f2b9208f0 100644 (file)
@@ -36,11 +36,39 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 #define _AU0828_BULKPIPE 0x83
 #define _BULKPIPESIZE 0xe522
 
+static u8 hauppauge_hvr950q_led_states[] = {
+       0x00, /* off */
+       0x02, /* yellow */
+       0x04, /* green */
+};
+
+static struct au8522_led_config hauppauge_hvr950q_led_cfg = {
+       .gpio_output = 0x00e0,
+       .gpio_output_enable  = 0x6006,
+       .gpio_output_disable = 0x0660,
+
+       .gpio_leds = 0x00e2,
+       .led_states  = hauppauge_hvr950q_led_states,
+       .num_led_states = sizeof(hauppauge_hvr950q_led_states),
+
+       .vsb8_strong   = 20 /* dB */ * 10,
+       .qam64_strong  = 25 /* dB */ * 10,
+       .qam256_strong = 32 /* dB */ * 10,
+};
+
 static struct au8522_config hauppauge_hvr950q_config = {
        .demod_address = 0x8e >> 1,
        .status_mode   = AU8522_DEMODLOCKING,
        .qam_if        = AU8522_IF_6MHZ,
        .vsb_if        = AU8522_IF_6MHZ,
+       .led_cfg       = &hauppauge_hvr950q_led_cfg,
+};
+
+static struct au8522_config fusionhdtv7usb_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_6MHZ,
+       .vsb_if        = AU8522_IF_6MHZ,
 };
 
 static struct au8522_config hauppauge_woodbury_config = {
@@ -53,7 +81,6 @@ static struct au8522_config hauppauge_woodbury_config = {
 static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
        .i2c_address      = 0x61,
        .if_khz           = 6000,
-       .tuner_callback   = au0828_tuner_callback
 };
 
 static struct mxl5007t_config mxl5007t_hvr950q_config = {
@@ -353,14 +380,12 @@ int au0828_dvb_register(struct au0828_dev *dev)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-       case AU0828_BOARD_DVICO_FUSIONHDTV7:
                dvb->frontend = dvb_attach(au8522_attach,
                                &hauppauge_hvr950q_config,
                                &dev->i2c_adap);
                if (dvb->frontend != NULL)
-                       dvb_attach(xc5000_attach, dvb->frontend,
-                               &dev->i2c_adap,
-                               &hauppauge_hvr950q_tunerconfig, dev);
+                       dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap,
+                                  &hauppauge_hvr950q_tunerconfig);
                break;
        case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
                dvb->frontend = dvb_attach(au8522_attach,
@@ -380,6 +405,16 @@ int au0828_dvb_register(struct au0828_dev *dev)
                                   0x60, &dev->i2c_adap,
                                   &hauppauge_woodbury_tunerconfig);
                break;
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &fusionhdtv7usb_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL) {
+                       dvb_attach(xc5000_attach, dvb->frontend,
+                               &dev->i2c_adap,
+                               &hauppauge_hvr950q_tunerconfig);
+               }
+               break;
        default:
                printk(KERN_WARNING "The frontend of your DVB/ATSC card "
                       "isn't supported yet\n");
@@ -390,6 +425,8 @@ int au0828_dvb_register(struct au0828_dev *dev)
                       __func__);
                return -1;
        }
+       /* define general-purpose callback pointer */
+       dvb->frontend->callback = au0828_tuner_callback;
 
        /* register everything */
        ret = dvb_register(dev);
index 4f10ff300135fcedec9f9c5d5362bc2b7ec0cb65..9d6a1161dc98f3801bdee3cf614c88696f7b7e5f 100644 (file)
@@ -103,7 +103,8 @@ extern int au0828_debug;
 extern struct au0828_board au0828_boards[];
 extern struct usb_device_id au0828_usb_id_table[];
 extern void au0828_gpio_setup(struct au0828_dev *dev);
-extern int au0828_tuner_callback(void *priv, int command, int arg);
+extern int au0828_tuner_callback(void *priv, int component,
+                                int command, int arg);
 extern void au0828_card_setup(struct au0828_dev *dev);
 
 /* ----------------------------------------------------------- */
index 98ee2d8feb34ecbcb5282112e1b49a0e7b5957f6..ab2ce4d7b5de0dc3d822dd9b97d23f1bd358d807 100644 (file)
@@ -68,8 +68,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 /* ----------------------------------------------------------------------- */
 
-#define REG_OFFSET     0xDA
-#define BT856_NR_REG   6
+#define BT856_REG_OFFSET       0xDA
+#define BT856_NR_REG           6
 
 struct bt856 {
        unsigned char reg[BT856_NR_REG];
@@ -89,7 +89,7 @@ bt856_write (struct i2c_client *client,
 {
        struct bt856 *encoder = i2c_get_clientdata(client);
 
-       encoder->reg[reg - REG_OFFSET] = value;
+       encoder->reg[reg - BT856_REG_OFFSET] = value;
        return i2c_smbus_write_byte_data(client, reg, value);
 }
 
@@ -103,7 +103,7 @@ bt856_setbit (struct i2c_client *client,
 
        return bt856_write(client, reg,
                           (encoder->
-                           reg[reg - REG_OFFSET] & ~(1 << bit)) |
+                           reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
                            (value ? (1 << bit) : 0));
 }
 
index 6081edc362df4fb8adad2d87794cc2ba8990bb21..13742b0bbe3e10d61fa4970a445dd749a3702850 100644 (file)
@@ -305,7 +305,7 @@ static struct CARD {
        { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
        { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2,    "DViCO FusionHDTV 2" },
        { 0x763c008a, BTTV_BOARD_GEOVISION_GV600,       "GeoVision GV-600" },
-
+       { 0x18011000, BTTV_BOARD_ENLTV_FM_2,    "Encore ENL TV-FM-2" },
        { 0, -1, NULL }
 };
 
@@ -3037,6 +3037,31 @@ struct tvcard bttv_tvcards[] = {
                .has_radio      = 1,
                .has_remote     = 1,
        },
+       [BTTV_BOARD_ENLTV_FM_2] = {
+               /* Encore TV Tuner Pro ENL TV-FM-2
+                  Mauro Carvalho Chehab <mchehab@infradead.org */
+               .name           = "Encore ENL TV-FM-2",
+               .video_inputs   = 3,
+               .audio_inputs   = 1,
+               .tuner          = 0,
+               .svhs           = 2,
+               /* bit 6          -> IR disabled
+                  bit 18/17 = 00 -> mute
+                              01 -> enable external audio input
+                              10 -> internal audio input (mono?)
+                              11 -> internal audio input
+                */
+               .gpiomask       = 0x060040,
+               .muxsel         = { 2, 3, 3 },
+               .gpiomux        = { 0x60000, 0x60000, 0x20000, 0x20000 },
+               .gpiomute       = 0,
+               .tuner_type     = TUNER_TCL_MF02GIP_5N,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .pll            = PLL_28,
+               .has_radio      = 1,
+               .has_remote     = 1,
+       }
 };
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
index 933eaef41eadd4b3be9e404924d22fb316c1bd70..5858bf5ff41c3da1392bb21d337d13713bf56c45 100644 (file)
@@ -76,9 +76,9 @@ static unsigned int gbuffers = 8;
 static unsigned int gbufsize = 0x208000;
 static unsigned int reset_crop = 1;
 
-static int video_nr = -1;
-static int radio_nr = -1;
-static int vbi_nr = -1;
+static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
 static int debug_latency;
 
 static unsigned int fdsr;
@@ -108,9 +108,6 @@ module_param(irq_debug,         int, 0644);
 module_param(debug_latency,     int, 0644);
 
 module_param(fdsr,              int, 0444);
-module_param(video_nr,          int, 0444);
-module_param(radio_nr,          int, 0444);
-module_param(vbi_nr,            int, 0444);
 module_param(gbuffers,          int, 0444);
 module_param(gbufsize,          int, 0444);
 module_param(reset_crop,        int, 0444);
@@ -130,7 +127,10 @@ module_param(uv_ratio,          int, 0444);
 module_param(full_luma_range,   int, 0444);
 module_param(coring,            int, 0444);
 
-module_param_array(radio, int, NULL, 0444);
+module_param_array(radio,       int, NULL, 0444);
+module_param_array(video_nr,    int, NULL, 0444);
+module_param_array(radio_nr,    int, NULL, 0444);
+module_param_array(vbi_nr,      int, NULL, 0444);
 
 MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
 MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
@@ -152,6 +152,9 @@ MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
 MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
 MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
 MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
 
 MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
 MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
@@ -1367,7 +1370,7 @@ static void init_irqreg(struct bttv *btv)
                        (btv->gpioirq ? BT848_INT_GPINT : 0) |
                        BT848_INT_SCERR |
                        (fdsr ? BT848_INT_FDSR : 0) |
-                       BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
+                       BT848_INT_RISCI | BT848_INT_OCERR |
                        BT848_INT_FMTCHG|BT848_INT_HLOCK|
                        BT848_INT_I2CDONE,
                        BT848_INT_MASK);
@@ -2661,18 +2664,6 @@ static int bttv_querycap(struct file *file, void  *priv,
        return 0;
 }
 
-static int bttv_enum_fmt_vbi_cap(struct file *file, void  *priv,
-                               struct v4l2_fmtdesc *f)
-{
-       if (0 != f->index)
-               return -EINVAL;
-
-       f->pixelformat = V4L2_PIX_FMT_GREY;
-       strcpy(f->description, "vbi data");
-
-       return 0;
-}
-
 static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
 {
        int index = -1, i;
@@ -3227,6 +3218,7 @@ static int bttv_open(struct inode *inode, struct file *file)
 
        dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
 
+       lock_kernel();
        for (i = 0; i < bttv_num; i++) {
                if (bttvs[i].video_dev &&
                    bttvs[i].video_dev->minor == minor) {
@@ -3241,16 +3233,20 @@ static int bttv_open(struct inode *inode, struct file *file)
                        break;
                }
        }
-       if (NULL == btv)
+       if (NULL == btv) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
                btv->c.nr,v4l2_type_names[type]);
 
        /* allocate per filehandle data */
        fh = kmalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        *fh = btv->init;
        fh->type = type;
@@ -3270,6 +3266,7 @@ static int bttv_open(struct inode *inode, struct file *file)
                            sizeof(struct bttv_buffer),
                            fh);
        set_tvnorm(btv,btv->tvnorm);
+       set_input(btv, btv->input, btv->tvnorm);
 
        btv->users++;
 
@@ -3290,6 +3287,7 @@ static int bttv_open(struct inode *inode, struct file *file)
        bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
        bttv_field_count(btv);
+       unlock_kernel();
        return 0;
 }
 
@@ -3330,6 +3328,10 @@ static int bttv_release(struct inode *inode, struct file *file)
 
        btv->users--;
        bttv_field_count(btv);
+
+       if (!btv->users)
+               audio_mute(btv, 1);
+
        return 0;
 }
 
@@ -3367,7 +3369,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
        .vidioc_g_fmt_vid_overlay       = bttv_g_fmt_vid_overlay,
        .vidioc_try_fmt_vid_overlay     = bttv_try_fmt_vid_overlay,
        .vidioc_s_fmt_vid_overlay       = bttv_s_fmt_vid_overlay,
-       .vidioc_enum_fmt_vbi_cap        = bttv_enum_fmt_vbi_cap,
        .vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
        .vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
        .vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
@@ -3430,21 +3431,26 @@ static int radio_open(struct inode *inode, struct file *file)
 
        dprintk("bttv: open minor=%d\n",minor);
 
+       lock_kernel();
        for (i = 0; i < bttv_num; i++) {
                if (bttvs[i].radio_dev && bttvs[i].radio_dev->minor == minor) {
                        btv = &bttvs[i];
                        break;
                }
        }
-       if (NULL == btv)
+       if (NULL == btv) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        dprintk("bttv%d: open called (radio)\n",btv->c.nr);
 
        /* allocate per filehandle data */
        fh = kmalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        *fh = btv->init;
        v4l2_prio_open(&btv->prio, &fh->prio);
@@ -3457,6 +3463,7 @@ static int radio_open(struct inode *inode, struct file *file)
        audio_input(btv,TVAUDIO_INPUT_RADIO);
 
        mutex_unlock(&btv->lock);
+       unlock_kernel();
        return 0;
 }
 
@@ -4235,7 +4242,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
 
        if (NULL == btv->video_dev)
                goto err;
-       if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
+       if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
+                                 video_nr[btv->c.nr]) < 0)
                goto err;
        printk(KERN_INFO "bttv%d: registered device video%d\n",
               btv->c.nr,btv->video_dev->minor & 0x1f);
@@ -4251,7 +4259,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
 
        if (NULL == btv->vbi_dev)
                goto err;
-       if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
+       if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
+                                 vbi_nr[btv->c.nr]) < 0)
                goto err;
        printk(KERN_INFO "bttv%d: registered device vbi%d\n",
               btv->c.nr,btv->vbi_dev->minor & 0x1f);
@@ -4262,7 +4271,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
        btv->radio_dev = vdev_init(btv, &radio_template, "radio");
        if (NULL == btv->radio_dev)
                goto err;
-       if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
+       if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
+                                 radio_nr[btv->c.nr]) < 0)
                goto err;
        printk(KERN_INFO "bttv%d: registered device radio%d\n",
               btv->c.nr,btv->radio_dev->minor & 0x1f);
index a38af98f4cae9e33ad4f47cd1873407a47c34dab..2f289d981fe62d3b3b2fba62ccc824e3d303935d 100644 (file)
@@ -28,8 +28,8 @@
 #include "bttvp.h"
 
 
-static int debug;
-module_param(debug, int, 0644);    /* debug level (0,1,2) */
+static int ir_debug;
+module_param(ir_debug, int, 0644);
 static int repeat_delay = 500;
 module_param(repeat_delay, int, 0644);
 static int repeat_period = 33;
@@ -40,6 +40,12 @@ module_param(ir_rc5_remote_gap, int, 0644);
 static int ir_rc5_key_timeout = 200;
 module_param(ir_rc5_key_timeout, int, 0644);
 
+#undef dprintk
+#define dprintk(arg...) do {   \
+       if (ir_debug >= 1)      \
+               printk(arg);    \
+} while (0)
+
 #define DEVNAME "bttv-input"
 
 /* ---------------------------------------------------------------------- */
@@ -79,6 +85,45 @@ static void ir_handle_key(struct bttv *btv)
 
 }
 
+static void ir_enltv_handle_key(struct bttv *btv)
+{
+       struct card_ir *ir = btv->remote;
+       u32 gpio, data, keyup;
+
+       /* read gpio value */
+       gpio = bttv_gpio_read(&btv->c);
+
+       /* extract data */
+       data = ir_extract_bits(gpio, ir->mask_keycode);
+
+       /* Check if it is keyup */
+       keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
+
+       if ((ir->last_gpio & 0x7f) != data) {
+               dprintk(KERN_INFO DEVNAME ": gpio=0x%x code=%d | %s\n",
+                       gpio, data,
+                       (gpio & ir->mask_keyup) ? " up" : "up/down");
+
+               ir_input_keydown(ir->dev, &ir->ir, data, data);
+               if (keyup)
+                       ir_input_nokey(ir->dev, &ir->ir);
+       } else {
+               if ((ir->last_gpio & 1 << 31) == keyup)
+                       return;
+
+               dprintk(KERN_INFO DEVNAME ":(cnt) gpio=0x%x code=%d | %s\n",
+                       gpio, data,
+                       (gpio & ir->mask_keyup) ? " up" : "down");
+
+               if (keyup)
+                       ir_input_nokey(ir->dev, &ir->ir);
+               else
+                       ir_input_keydown(ir->dev, &ir->ir, data, data);
+       }
+
+       ir->last_gpio = data | keyup;
+}
+
 void bttv_input_irq(struct bttv *btv)
 {
        struct card_ir *ir = btv->remote;
@@ -92,7 +137,10 @@ static void bttv_input_timer(unsigned long data)
        struct bttv *btv = (struct bttv*)data;
        struct card_ir *ir = btv->remote;
 
-       ir_handle_key(btv);
+       if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
+               ir_enltv_handle_key(btv);
+       else
+               ir_handle_key(btv);
        mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
 }
 
@@ -284,6 +332,14 @@ int bttv_input_init(struct bttv *btv)
                ir->mask_keyup   = 0x006000;
                ir->polling      = 50; /* ms */
                break;
+       case BTTV_BOARD_ENLTV_FM_2:
+               ir_codes         = ir_codes_encore_enltv2;
+               ir->mask_keycode = 0x00fd00;
+               ir->mask_keyup   = 0x000080;
+               ir->polling      = 1; /* ms */
+               ir->last_gpio    = ir_extract_bits(bttv_gpio_read(&btv->c),
+                                                  ir->mask_keycode);
+               break;
        }
        if (NULL == ir_codes) {
                dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
index 6d93d16c96e4609cb899da64f4fc12364705cb52..46cb90e0985b2ad7bbe8193da8291d16eaf6a38b 100644 (file)
 #define BTTV_BOARD_TYPHOON_TVTUNERPCI     0x95
 #define BTTV_BOARD_GEOVISION_GV600        0x96
 #define BTTV_BOARD_KOZUMI_KTV_01C          0x97
-
+#define BTTV_BOARD_ENLTV_FM_2             0x98
 
 /* more card-specific defines */
 #define PT2254_L_CHANNEL 0x10
index 3324ab38f58c3b395f617e00c9a9c4bd957ff820..ac1b2687a20d7feca68b8ebce0758b0c5e29411c 100644 (file)
@@ -64,7 +64,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
                       unsigned int size)
 {
        __le32 *cpu;
-       dma_addr_t dma;
+       dma_addr_t dma = 0;
 
        if (NULL != risc->cpu && risc->size < size)
                btcx_riscmem_free(pci,risc);
index 6e39e253ce5361a5d99644e7b93d96474759b966..ace4ff9ea023b69732568db94093fbf3396682ae 100644 (file)
@@ -495,7 +495,7 @@ static void qc_set(struct qcam_device *q)
                val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
                    q->transfer_scale;
        }
-       val = (val + val2 - 1) / val2;
+       val = DIV_ROUND_UP(val, val2);
        qc_command(q, 0x13);
        qc_command(q, val);
 
@@ -651,7 +651,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
        transperline = q->width * q->bpp;
        divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
            q->transfer_scale;
-       transperline = (transperline + divisor - 1) / divisor;
+       transperline = DIV_ROUND_UP(transperline, divisor);
 
        for (i = 0, yield = yieldlines; i < linestotrans; i++)
        {
@@ -894,10 +894,27 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
+static int qcam_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+}
+
+static int qcam_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       clear_bit(0, &qcam->in_use);
+       return 0;
+}
+
 static const struct file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = qcam_exclusive_open,
+       .release        = qcam_exclusive_release,
        .ioctl          = qcam_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -909,6 +926,7 @@ static struct video_device qcam_template=
 {
        .name           = "Connectix Quickcam",
        .fops           = &qcam_fops,
+       .release        = video_device_release_empty,
 };
 
 #define MAX_CAMS 4
index 6701dafbc0da82deca9579837464c94e3db426e0..8a60c5de09350a842dda12cae7a910d83161d35e 100644 (file)
@@ -65,4 +65,5 @@ struct qcam_device {
        int top, left;
        int status;
        unsigned int saved_bits;
+       unsigned long in_use;
 };
index 7f6c6b4bec10e7f3470d8452e1ee71b9cd90ab0e..17aa0adb346703938b650c8c8164e3789eab5f88 100644 (file)
@@ -51,6 +51,7 @@ struct qcam_device {
        int contrast, brightness, whitebal;
        int top, left;
        unsigned int bidirectional;
+       unsigned long in_use;
        struct mutex lock;
 };
 
@@ -687,11 +688,28 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
        return len;
 }
 
+static int qcam_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
+}
+
+static int qcam_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct qcam_device *qcam = (struct qcam_device *)dev;
+
+       clear_bit(0, &qcam->in_use);
+       return 0;
+}
+
 /* video device template */
 static const struct file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = qcam_exclusive_open,
+       .release        = qcam_exclusive_release,
        .ioctl          = qcam_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -704,6 +722,7 @@ static struct video_device qcam_template=
 {
        .name           = "Colour QuickCam",
        .fops           = &qcam_fops,
+       .release        = video_device_release_empty,
 };
 
 /* Initialize the QuickCam driver control structure. */
index 5405c30dbb041748b47941c5e9b0fd19842915c4..fc9497bdd322f008c6673ada3c7468be051c3706 100644 (file)
@@ -1476,9 +1476,12 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
 {
        struct cafe_camera *cam;
 
+       lock_kernel();
        cam = cafe_find_dev(iminor(inode));
-       if (cam == NULL)
+       if (cam == NULL) {
+               unlock_kernel();
                return -ENODEV;
+       }
        filp->private_data = cam;
 
        mutex_lock(&cam->s_mutex);
@@ -1490,6 +1493,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
        }
        (cam->users)++;
        mutex_unlock(&cam->s_mutex);
+       unlock_kernel();
        return 0;
 }
 
@@ -2092,15 +2096,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
                const struct pci_device_id *id)
 {
        int ret;
-       u16 classword;
        struct cafe_camera *cam;
-       /*
-        * Make sure we have a camera here - we'll get calls for
-        * the other cafe devices as well.
-        */
-       pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword);
-       if (classword != PCI_CLASS_MULTIMEDIA_VIDEO)
-               return -ENODEV;
+
        /*
         * Start putting together one of our big camera structures.
         */
@@ -2288,8 +2285,8 @@ static int cafe_pci_resume(struct pci_dev *pdev)
 
 
 static struct pci_device_id cafe_ids[] = {
-       { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
-       { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL,
+                    PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) },
        { 0, }
 };
 
index a661800b0e69fdefec154a23b69462fc448da2c1..1798b779a25a10993e767a469ee860317016a992 100644 (file)
 #include <asm/io.h>
 #include <linux/mutex.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #include "cpia.h"
 
 static int video_nr = -1;
@@ -3155,7 +3151,7 @@ static void put_cam(struct cpia_camera_ops* ops)
 static int cpia_open(struct inode *inode, struct file *file)
 {
        struct video_device *dev = video_devdata(file);
-       struct cam_data *cam = dev->priv;
+       struct cam_data *cam = video_get_drvdata(dev);
        int err;
 
        if (!cam) {
@@ -3202,7 +3198,7 @@ static int cpia_open(struct inode *inode, struct file *file)
 
        /* Set ownership of /proc/cpia/videoX to current user */
        if(cam->proc_entry)
-               cam->proc_entry->uid = current->uid;
+               cam->proc_entry->uid = current_uid();
 
        /* set mark for loading first frame uncompressed */
        cam->first_frame = 1;
@@ -3232,7 +3228,7 @@ static int cpia_open(struct inode *inode, struct file *file)
 static int cpia_close(struct inode *inode, struct file *file)
 {
        struct  video_device *dev = file->private_data;
-       struct cam_data *cam = dev->priv;
+       struct cam_data *cam = video_get_drvdata(dev);
 
        if (cam->ops) {
                /* Return ownership of /proc/cpia/videoX to root */
@@ -3284,7 +3280,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
                         size_t count, loff_t *ppos)
 {
        struct video_device *dev = file->private_data;
-       struct cam_data *cam = dev->priv;
+       struct cam_data *cam = video_get_drvdata(dev);
        int err;
 
        /* make this _really_ smp and multithread-safe */
@@ -3341,7 +3337,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
                         unsigned int ioctlnr, void *arg)
 {
        struct video_device *dev = file->private_data;
-       struct cam_data *cam = dev->priv;
+       struct cam_data *cam = video_get_drvdata(dev);
        int retval = 0;
 
        if (!cam || !cam->ops)
@@ -3739,7 +3735,7 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
        unsigned long start = vma->vm_start;
        unsigned long size  = vma->vm_end - vma->vm_start;
        unsigned long page, pos;
-       struct cam_data *cam = dev->priv;
+       struct cam_data *cam = video_get_drvdata(dev);
        int retval;
 
        if (!cam || !cam->ops)
@@ -3801,6 +3797,7 @@ static const struct file_operations cpia_fops = {
 static struct video_device cpia_template = {
        .name           = "CPiA Camera",
        .fops           = &cpia_fops,
+       .release        = video_device_release_empty,
 };
 
 /* initialise cam_data structure  */
@@ -3928,7 +3925,7 @@ static void init_camera_struct(struct cam_data *cam,
        cam->proc_entry = NULL;
 
        memcpy(&cam->vdev, &cpia_template, sizeof(cpia_template));
-       cam->vdev.priv = cam;
+       video_set_drvdata(&cam->vdev, cam);
 
        cam->curframe = 0;
        for (i = 0; i < FRAME_NUM; i++) {
index af8b9ec8e3587bd64ff37cf2c29a4df1fe5118fa..7e791b6923f986913095339ec5392d420fcc88a0 100644 (file)
@@ -1537,7 +1537,7 @@ static int config_sensor_500(struct camera_data *cam,
  *
  *  This sets all user changeable properties to the values in cam->params.
  *****************************************************************************/
-int set_all_properties(struct camera_data *cam)
+static int set_all_properties(struct camera_data *cam)
 {
        /**
         * Don't set target_kb here, it will be set later.
@@ -1588,7 +1588,7 @@ void cpia2_save_camera_state(struct camera_data *cam)
  *  get_color_params
  *
  *****************************************************************************/
-void get_color_params(struct camera_data *cam)
+static void get_color_params(struct camera_data *cam)
 {
        cpia2_do_command(cam, CPIA2_CMD_GET_VP_BRIGHTNESS, TRANSFER_READ, 0);
        cpia2_do_command(cam, CPIA2_CMD_GET_VP_SATURATION, TRANSFER_READ, 0);
@@ -1881,7 +1881,7 @@ void cpia2_set_saturation(struct camera_data *cam, unsigned char value)
  *  wake_system
  *
  *****************************************************************************/
-void wake_system(struct camera_data *cam)
+static void wake_system(struct camera_data *cam)
 {
        cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0);
 }
@@ -1892,7 +1892,7 @@ void wake_system(struct camera_data *cam)
  *
  *  Valid for STV500 sensor only
  *****************************************************************************/
-void set_lowlight_boost(struct camera_data *cam)
+static void set_lowlight_boost(struct camera_data *cam)
 {
        struct cpia2_command cmd;
 
@@ -2169,7 +2169,7 @@ void cpia2_dbg_dump_registers(struct camera_data *cam)
  *
  *  Sets all values to the defaults
  *****************************************************************************/
-void reset_camera_struct(struct camera_data *cam)
+static void reset_camera_struct(struct camera_data *cam)
 {
        /***
         * The following parameter values are the defaults from the register map.
index a8a199047cbde4c448dbfb736beedbb78d3c4e08..73511a542077b40c9c7ff32e795fc15789a557b9 100644 (file)
@@ -478,7 +478,7 @@ int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
  * set_alternate
  *
  *****************************************************************************/
-int set_alternate(struct camera_data *cam, unsigned int alt)
+static int set_alternate(struct camera_data *cam, unsigned int alt)
 {
        int ret = 0;
 
index eb9f15cd4c45c9884170fb9599e99f6544e4e288..897e8d1a5c3c0a08cadc5dfa470767c90095573d 100644 (file)
@@ -241,8 +241,7 @@ static struct v4l2_queryctrl controls[] = {
  *****************************************************************************/
 static int cpia2_open(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct camera_data *cam = video_get_drvdata(dev);
+       struct camera_data *cam = video_drvdata(file);
        int retval = 0;
 
        if (!cam) {
@@ -357,8 +356,7 @@ static int cpia2_close(struct inode *inode, struct file *file)
 static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
                              loff_t *off)
 {
-       struct video_device *dev = video_devdata(file);
-       struct camera_data *cam = video_get_drvdata(dev);
+       struct camera_data *cam = video_drvdata(file);
        int noblock = file->f_flags&O_NONBLOCK;
 
        struct cpia2_fh *fh = file->private_data;
@@ -382,9 +380,7 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
  *****************************************************************************/
 static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
 {
-       struct video_device *dev = video_devdata(filp);
-       struct camera_data *cam = video_get_drvdata(dev);
-
+       struct camera_data *cam = video_drvdata(filp);
        struct cpia2_fh *fh = filp->private_data;
 
        if(!cam)
@@ -1579,8 +1575,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
 static int cpia2_do_ioctl(struct inode *inode, struct file *file,
                          unsigned int ioctl_nr, void *arg)
 {
-       struct video_device *dev = video_devdata(file);
-       struct camera_data *cam = video_get_drvdata(dev);
+       struct camera_data *cam = video_drvdata(file);
        int retval = 0;
 
        if (!cam)
@@ -1860,9 +1855,8 @@ static int cpia2_ioctl(struct inode *inode, struct file *file,
  *****************************************************************************/
 static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
 {
+       struct camera_data *cam = video_drvdata(file);
        int retval;
-       struct video_device *dev = video_devdata(file);
-       struct camera_data *cam = video_get_drvdata(dev);
 
        /* Priority check */
        struct cpia2_fh *fh = file->private_data;
index b23d2e26120f7f80cf6ad66113cf346700fea432..f7bf0edf93f9dbf9beceac7fddf5f2a07f79dbf7 100644 (file)
@@ -2,7 +2,7 @@ cx18-objs    := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.
        cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
        cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
        cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
-       cx18-dvb.o
+       cx18-dvb.o cx18-io.o
 
 obj-$(CONFIG_VIDEO_CX18) += cx18.o
 
index 6d5b94fc70879eec06835a8c958481019a3440bf..57beddf0af4df2d3936c69c3044d60c200ca67c2 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-i2c.h"
 #include "cx18-cards.h"
 #include "cx18-audio.h"
@@ -60,10 +61,10 @@ int cx18_audio_set_io(struct cx18 *cx)
        if (err)
                return err;
 
-       val = read_reg(CX18_AUDIO_ENABLE) & ~0x30;
+       val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30;
        val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
                                        (audio_input << 4);
-       write_reg(val | 0xb00, CX18_AUDIO_ENABLE);
+       cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE);
        cx18_vapi(cx, CX18_APU_RESETAI, 1, 0);
        return 0;
 }
index 3b0a2c450605e84415289a1cc21e667f0ba7b531..73f5141a42d1270608f4017787230e52a49752c0 100644 (file)
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
 {
-       u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+       u32 reg = 0xc40000 + (addr & ~3);
        u32 mask = 0xff;
        int shift = (addr & 3) * 8;
+       u32 x = cx18_read_reg(cx, reg);
 
        x = (x & ~(mask << shift)) | ((u32)value << shift);
-       writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
+       cx18_write_reg(cx, x, reg);
        return 0;
 }
 
 int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
 {
-       writel(value, cx->reg_mem + 0xc40000 + addr);
+       cx18_write_reg(cx, value, 0xc40000 + addr);
+       return 0;
+}
+
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
+{
+       cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
        return 0;
 }
 
 u8 cx18_av_read(struct cx18 *cx, u16 addr)
 {
-       u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+       u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
        int shift = (addr & 3) * 8;
 
        return (x >> shift) & 0xff;
@@ -50,7 +58,12 @@ u8 cx18_av_read(struct cx18 *cx, u16 addr)
 
 u32 cx18_av_read4(struct cx18 *cx, u16 addr)
 {
-       return readl(cx->reg_mem + 0xc40000 + addr);
+       return cx18_read_reg(cx, 0xc40000 + addr);
+}
+
+u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr)
+{
+       return cx18_read_reg_noretry(cx, 0xc40000 + addr);
 }
 
 int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
index eb61fa1e0965bbbcebccbcc0ee86ec4b9939ed55..b67d8df20cc66a7533a34e93c95982a91ac6accb 100644 (file)
@@ -301,8 +301,10 @@ struct cx18_av_state {
 /* cx18_av-core.c                                                         */
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
 int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
 u8 cx18_av_read(struct cx18 *cx, u16 addr);
 u32 cx18_av_read4(struct cx18 *cx, u16 addr);
+u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
 int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
 int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
 int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
index e996a4e3123a3a01a2cae74a152d6131f79e594a..522a035b2e8fb5c065e334ad3fc2482af654c000 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include <linux/firmware.h>
 
 #define CX18_AUDIO_ENABLE 0xc72014
@@ -49,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx)
                cx18_av_write4(cx, 0x8100, 0x00010000);
 
                /* Put the 8051 in reset and enable firmware upload */
-               cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+               cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
 
                ptr = fw->data;
                size = fw->size;
@@ -58,22 +59,28 @@ int cx18_av_loadfw(struct cx18 *cx)
                        u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
                        u32 value = 0;
                        int retries2;
+                       int unrec_err = 0;
 
-                       for (retries2 = 0; retries2 < 5; retries2++) {
-                               cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
+                       for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES;
+                            retries2++) {
+                               cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
+                                                      dl_control);
                                udelay(10);
-                               value = cx18_av_read4(cx, CXADEC_DL_CTL);
+                               value = cx18_av_read4_noretry(cx,
+                                                             CXADEC_DL_CTL);
                                if (value == dl_control)
                                        break;
                                /* Check if we can correct the byte by changing
                                   the address.  We can only write the lower
                                   address byte of the address. */
                                if ((value & 0x3F00) != (dl_control & 0x3F00)) {
-                                       retries2 = 5;
+                                       unrec_err = 1;
                                        break;
                                }
                        }
-                       if (retries2 >= 5)
+                       cx18_log_write_retries(cx, retries2,
+                                       cx->reg_mem + 0xc40000 + CXADEC_DL_CTL);
+                       if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES)
                                break;
                }
                if (i == size)
@@ -119,10 +126,10 @@ int cx18_av_loadfw(struct cx18 *cx)
           have a name in the spec. */
        cx18_av_write4(cx, 0x09CC, 1);
 
-       v = read_reg(CX18_AUDIO_ENABLE);
-       /* If bit 11 is 1 */
+       v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+       /* If bit 11 is 1, clear bit 10 */
        if (v & 0x800)
-               write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
+               cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE);
 
        /* Enable WW auto audio standard detection */
        v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
index 3cb9734ec07bf7f6314f84590430ce3ee93b7432..5efe01ebe9db368e258f8716525223d3ee1425c6 100644 (file)
@@ -292,12 +292,111 @@ static const struct cx18_card cx18_card_cnxt_raptor_pal = {
 
 /* ------------------------------------------------------------------------- */
 
+/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */
+
+static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
+       .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT,
+       .name = "Toshiba Qosmio DVB-T/Analog",
+       .comment = "Experimenters and photos needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_all = CX18_HW_TUNER,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE6 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+       },
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .ddr = {
+               .chip_config = 0x202,
+               .refresh = 0x3bb,
+               .timing1 = 0x33320a63,
+               .timing2 = 0x0a,
+               .tune_lane = 0,
+               .initial_emrs = 0x42,
+       },
+       .xceive_pin = 15,
+       .pci_list = cx18_pci_toshiba_qosmio_dvbt,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast PVR2100 */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_pvr2100 = {
+       .type = CX18_CARD_LEADTEK_PVR2100,
+       .name = "Leadtek WinFast PVR2100",
+       .comment = "Experimenters and photos needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_muxer = CX18_HW_GPIO,
+       .hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+       },
+       .tuners = {
+               /* XC3028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+       .ddr = {
+               /*
+                * Pointer to proper DDR config values provided by
+                * Terry Wu <terrywu at leadtek.com.tw>
+                */
+               .chip_config = 0x303,
+               .refresh = 0x3bb,
+               .timing1 = 0x24220e83,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 0x2,
+       },
+       .gpio_init.initial_value = 0x6,
+       .gpio_init.direction = 0x7,
+       .gpio_audio_input = { .mask   = 0x7,
+                             .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+       .xceive_pin = 15,
+       .pci_list = cx18_pci_leadtek_pvr2100,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
 static const struct cx18_card *cx18_card_list[] = {
        &cx18_card_hvr1600_esmt,
        &cx18_card_hvr1600_samsung,
        &cx18_card_h900,
        &cx18_card_mpc718,
        &cx18_card_cnxt_raptor_pal,
+       &cx18_card_toshiba_qosmio_dvbt,
+       &cx18_card_leadtek_pvr2100,
 };
 
 const struct cx18_card *cx18_get_card(u16 index)
index bd18afebbf860565292b212bde83361486761d8e..085121c2b47f3844aa07e60b21f7b5e4843437b6 100644 (file)
@@ -4,6 +4,7 @@
  *  Derived from ivtv-driver.c
  *
  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -22,6 +23,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-version.h"
 #include "cx18-cards.h"
 #include "cx18-i2c.h"
@@ -73,10 +75,14 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
                                     -1, -1, -1, -1, -1, -1, -1, -1,
                                     -1, -1, -1, -1, -1, -1, -1, -1,
                                     -1, -1, -1, -1, -1, -1, -1, -1 };
-
+static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                          -1, -1, -1, -1, -1, -1, -1, -1,
+                                          -1, -1, -1, -1, -1, -1, -1, -1,
+                                          -1, -1, -1, -1, -1, -1, -1, -1 };
 static unsigned cardtype_c = 1;
 static unsigned tuner_c = 1;
 static unsigned radio_c = 1;
+static unsigned mmio_ndelay_c = 1;
 static char pal[] = "--";
 static char secam[] = "--";
 static char ntsc[] = "-";
@@ -90,15 +96,18 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
 
 static int cx18_pci_latency = 1;
 
+int cx18_retry_mmio = 1;
 int cx18_debug;
 
 module_param_array(tuner, int, &tuner_c, 0644);
 module_param_array(radio, bool, &radio_c, 0644);
 module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644);
 module_param_string(pal, pal, sizeof(pal), 0644);
 module_param_string(secam, secam, sizeof(secam), 0644);
 module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
 module_param_named(debug, cx18_debug, int, 0644);
+module_param_named(retry_mmio, cx18_retry_mmio, int, 0644);
 module_param(cx18_pci_latency, int, 0644);
 module_param(cx18_first_minor, int, 0644);
 
@@ -121,6 +130,8 @@ MODULE_PARM_DESC(cardtype,
                 "\t\t\t 3 = Compro VideoMate H900\n"
                 "\t\t\t 4 = Yuan MPC718\n"
                 "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
+                "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
+                "\t\t\t 7 = Leadtek WinFast PVR2100\n"
                 "\t\t\t 0 = Autodetect (default)\n"
                 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -140,6 +151,14 @@ MODULE_PARM_DESC(debug,
 MODULE_PARM_DESC(cx18_pci_latency,
                 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
                 "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(retry_mmio,
+                "Check and retry memory mapped IO accesses\n"
+                "\t\t\tDefault: 1 [Yes]");
+MODULE_PARM_DESC(mmio_ndelay,
+                "Delay (ns) for each CX23418 memory mapped IO access.\n"
+                "\t\t\tTry larger values that are close to a multiple of the\n"
+                "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY));
 MODULE_PARM_DESC(enc_mpg_buffers,
                 "Encoder MPG Buffers (in MB)\n"
                 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
@@ -156,7 +175,7 @@ MODULE_PARM_DESC(enc_pcm_buffers,
                 "Encoder PCM buffers (in MB)\n"
                 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
 
-MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card");
+MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card");
 
 MODULE_AUTHOR("Hans Verkuil");
 MODULE_DESCRIPTION("CX23418 driver");
@@ -356,6 +375,11 @@ static void cx18_process_options(struct cx18 *cx)
        cx->options.tuner = tuner[cx->num];
        cx->options.radio = radio[cx->num];
 
+       if (mmio_ndelay[cx->num] < 0)
+               cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY;
+       else
+               cx->options.mmio_ndelay = mmio_ndelay[cx->num];
+
        cx->std = cx18_parse_std(cx);
        if (cx->options.cardtype == -1) {
                CX18_INFO("Ignore card\n");
@@ -395,9 +419,9 @@ done:
 
        if (cx->card == NULL) {
                cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
-               CX18_ERR("Unknown card: vendor/device: %04x/%04x\n",
+               CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
                     cx->dev->vendor, cx->dev->device);
-               CX18_ERR("              subsystem vendor/device: %04x/%04x\n",
+               CX18_ERR("              subsystem vendor/device: [%04x:%04x]\n",
                     cx->dev->subsystem_vendor, cx->dev->subsystem_device);
                CX18_ERR("Defaulting to %s card\n", cx->card->name);
                CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
@@ -511,9 +535,9 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
                return -EIO;
        }
 
-       /* Check for bus mastering */
+       /* Enable bus mastering and memory mapped IO for the CX23418 */
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+       cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
        pci_write_config_word(dev, PCI_COMMAND, cmd);
 
        pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
@@ -525,11 +549,6 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
                pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
        }
-       /* This config space value relates to DMA latencies. The
-          default value 0x8080 is too low however and will lead
-          to DMA errors. 0xffff is the max value which solves
-          these problems. */
-       pci_write_config_dword(dev, 0x40, 0xffff);
 
        CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
                   "irq: %d, latency: %d, memory: 0x%lx\n",
@@ -656,7 +675,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
                goto free_mem;
        }
        cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
-       devtype = read_reg(0xC72028);
+       devtype = cx18_read_reg(cx, 0xC72028);
        switch (devtype & 0xff000000) {
        case 0xff000000:
                CX18_INFO("cx23418 revision %08x (A)\n", devtype);
@@ -815,6 +834,7 @@ err:
        if (retval == 0)
                retval = -ENODEV;
        CX18_ERR("Error %d on initialization\n", retval);
+       cx18_log_statistics(cx);
 
        kfree(cx18_cards[cx18_cards_active]);
        cx18_cards[cx18_cards_active] = NULL;
@@ -902,8 +922,8 @@ static void cx18_remove(struct pci_dev *pci_dev)
                cx18_stop_all_captures(cx);
 
        /* Interrupts */
-       sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
-       sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+       cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+       cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
 
        cx18_halt_firmware(cx);
 
@@ -919,6 +939,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
 
        pci_disable_device(cx->dev);
 
+       cx18_log_statistics(cx);
        CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
 }
 
@@ -938,7 +959,7 @@ static int module_start(void)
 
        /* Validate parameters */
        if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
-               printk(KERN_ERR "cx18:  Exiting, ivtv_first_minor must be between 0 and %d\n",
+               printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
                     CX18_MAX_CARDS - 1);
                return -1;
        }
index 4801bc7fb5b224336c2cd4ba609df9fde7368bb6..fa8be0731a3f70ee3d6ca40a6301af86d7930a86 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/list.h>
 #include <linux/unistd.h>
-#include <linux/byteorder/swab.h>
 #include <linux/pagemap.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
@@ -64,6 +63,9 @@
 #  error "This driver requires kernel PCI support."
 #endif
 
+/* Default delay to throttle mmio access to the CX23418 */
+#define CX18_DEFAULT_MMIO_NDELAY 0 /* 0 ns = 0 PCI clock(s) / 33 MHz */
+
 #define CX18_MEM_OFFSET        0x00000000
 #define CX18_MEM_SIZE  0x04000000
 #define CX18_REG_OFFSET        0x02000000
@@ -77,7 +79,9 @@
 #define CX18_CARD_COMPRO_H900        2 /* Compro VideoMate H900 */
 #define CX18_CARD_YUAN_MPC718        3 /* Yuan MPC718 */
 #define CX18_CARD_CNXT_RAPTOR_PAL     4        /* Conexant Raptor PAL */
-#define CX18_CARD_LAST                       4
+#define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
+#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LAST                       6
 
 #define CX18_ENC_STREAM_TYPE_MPG  0
 #define CX18_ENC_STREAM_TYPE_TS   1
 #define CX18_PCI_ID_COMPRO             0x185b
 #define CX18_PCI_ID_YUAN               0x12ab
 #define CX18_PCI_ID_CONEXANT           0x14f1
+#define CX18_PCI_ID_TOSHIBA            0x1179
+#define CX18_PCI_ID_LEADTEK            0x107D
 
 /* ======================================================================== */
 /* ========================== START USER SETTABLE DMA VARIABLES =========== */
 
 #define CX18_MAX_PGM_INDEX (400)
 
+extern int cx18_retry_mmio;    /* enable check & retry of mmio accesses */
 extern int cx18_debug;
 
 
@@ -177,6 +184,7 @@ struct cx18_options {
        int cardtype;           /* force card type on load */
        int tuner;              /* set tuner on load */
        int radio;              /* enable/disable radio */
+       unsigned long mmio_ndelay; /* delay in ns after every PCI mmio access */
 };
 
 /* per-buffer bit flags */
@@ -216,8 +224,7 @@ struct cx18_buffer {
 
 struct cx18_queue {
        struct list_head list;
-       u32 buffers;
-       u32 length;
+       atomic_t buffers;
        u32 bytesused;
 };
 
@@ -237,6 +244,8 @@ struct cx18_dvb {
 struct cx18;    /* forward reference */
 struct cx18_scb; /* forward reference */
 
+#define CX18_INVALID_TASK_HANDLE 0xffffffff
+
 struct cx18_stream {
        /* These first four fields are always set, even if the stream
           is not actually created. */
@@ -259,7 +268,6 @@ struct cx18_stream {
        /* Buffer Stats */
        u32 buffers;
        u32 buf_size;
-       u32 buffers_stolen;
 
        /* Buffer Queues */
        struct cx18_queue q_free;       /* free buffers */
@@ -341,6 +349,13 @@ struct cx18_i2c_algo_callback_data {
        int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
 };
 
+#define CX18_MAX_MMIO_RETRIES 10
+
+struct cx18_mmio_stats {
+       atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1];
+       atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1];
+};
+
 /* Struct to hold info about cx18 cards */
 struct cx18 {
        int num;                /* board number, -1 during init! */
@@ -430,6 +445,9 @@ struct cx18 {
        u32 gpio_val;
        struct mutex gpio_lock;
 
+       /* Statistics */
+       struct cx18_mmio_stats mmio_stats;
+
        /* v4l2 and User settings */
 
        /* codec settings */
@@ -458,47 +476,4 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
 /* First-open initialization: load firmware, etc. */
 int cx18_init_on_first_open(struct cx18 *cx);
 
-/* This is a PCI post thing, where if the pci register is not read, then
-   the write doesn't always take effect right away. By reading back the
-   register any pending PCI writes will be performed (in order), and so
-   you can be sure that the writes are guaranteed to be done.
-
-   Rarely needed, only in some timing sensitive cases.
-   Apparently if this is not done some motherboards seem
-   to kill the firmware and get into the broken state until computer is
-   rebooted. */
-#define write_sync(val, reg) \
-       do { writel(val, reg); readl(reg); } while (0)
-
-#define read_reg(reg) readl(cx->reg_mem + (reg))
-#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
-#define write_reg_sync(val, reg) \
-       do { write_reg(val, reg); read_reg(reg); } while (0)
-
-#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
-#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
-#define write_enc_sync(val, addr) \
-       do { write_enc(val, addr); read_enc(addr); } while (0)
-
-#define sw1_irq_enable(val) do { \
-       write_reg(val, SW1_INT_STATUS); \
-       write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
-} while (0)
-
-#define sw1_irq_disable(val) \
-       write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
-
-#define sw2_irq_enable(val) do { \
-       write_reg(val, SW2_INT_STATUS); \
-       write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
-} while (0)
-
-#define sw2_irq_disable(val) \
-       write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
-
-#define setup_page(addr) do { \
-    u32 val = read_reg(0xD000F8) & ~0x1f00; \
-    write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
-} while (0)
-
 #endif /* CX18_DRIVER_H */
index 1e420a804fc96ddf24c3632b83e136d8755dc163..afc694e7bdb297f672944c3ba66b828aae6b16ad 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "cx18-version.h"
 #include "cx18-dvb.h"
+#include "cx18-io.h"
 #include "cx18-streams.h"
 #include "cx18-cards.h"
 #include "s5h1409.h"
@@ -87,13 +88,13 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
        switch (cx->card->type) {
        case CX18_CARD_HVR_1600_ESMT:
        case CX18_CARD_HVR_1600_SAMSUNG:
-               v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
                v |= 0x00400000; /* Serial Mode */
                v |= 0x00002000; /* Data Length - Byte */
                v |= 0x00010000; /* Error - Polarity */
                v |= 0x00020000; /* Error - Passthru */
                v |= 0x000c0000; /* Error - Ignore */
-               write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
                break;
 
        default:
index 1e537fe04a2372196254aa35e6846131f136c02e..5f9089907544c091f1e276eee7601a81a946ca77 100644 (file)
@@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx)
        u16 new_stereo_mode;
        const u16 stereo_mask = 0x0300;
        const u16 dual = 0x0200;
+       u32 h;
 
        new_stereo_mode = cx->params.audio_properties & stereo_mask;
        memset(&vt, 0, sizeof(vt));
@@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx)
        if (new_stereo_mode == cx->dualwatch_stereo_mode)
                return;
 
-       new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+       new_bitmap = new_stereo_mode
+                       | (cx->params.audio_properties & ~stereo_mask);
 
-       CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
-                          cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+       CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
+                       "new audio_bitmask=0x%ux\n",
+                       cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
 
-       if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
-                               cx18_find_handle(cx), new_bitmap) == 0) {
+       h = cx18_find_handle(cx);
+       if (h == CX18_INVALID_TASK_HANDLE) {
+               CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
+               return;
+       }
+
+       if (cx18_vapi(cx,
+                     CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
                cx->dualwatch_stereo_mode = new_stereo_mode;
                return;
        }
@@ -223,7 +232,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block,
                prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
                /* New buffers might have become available before we were added
                   to the waitqueue */
-               if (!s->q_full.buffers)
+               if (!atomic_read(&s->q_full.buffers))
                        schedule();
                finish_wait(&s->waitq, &wait);
                if (signal_pending(current)) {
@@ -509,7 +518,7 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
        CX18_DEBUG_HI_FILE("Encoder poll\n");
        poll_wait(filp, &s->waitq, wait);
 
-       if (s->q_full.length || s->q_io.length)
+       if (atomic_read(&s->q_full.buffers) || atomic_read(&s->q_io.buffers))
                return POLLIN | POLLRDNORM;
        if (eof)
                return POLLHUP;
@@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
 
 void cx18_mute(struct cx18 *cx)
 {
-       if (atomic_read(&cx->ana_capturing))
-               cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
-                               cx18_find_handle(cx), 1);
+       u32 h;
+       if (atomic_read(&cx->ana_capturing)) {
+               h = cx18_find_handle(cx);
+               if (h != CX18_INVALID_TASK_HANDLE)
+                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
+               else
+                       CX18_ERR("Can't find valid task handle for mute\n");
+       }
        CX18_DEBUG_INFO("Mute\n");
 }
 
 void cx18_unmute(struct cx18 *cx)
 {
+       u32 h;
        if (atomic_read(&cx->ana_capturing)) {
-               cx18_msleep_timeout(100, 0);
-               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
-                               cx18_find_handle(cx), 12);
-               cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
-                               cx18_find_handle(cx), 0);
+               h = cx18_find_handle(cx);
+               if (h != CX18_INVALID_TASK_HANDLE) {
+                       cx18_msleep_timeout(100, 0);
+                       cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
+                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
+               } else
+                       CX18_ERR("Can't find valid task handle for unmute\n");
        }
        CX18_DEBUG_INFO("Unmute\n");
 }
index 78fadd2ada5d72a4a1d45708ebe352e03cb099d0..51534428cd00c9dbe1b231516ccf2df078bc9f16 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-scb.h"
 #include "cx18-irq.h"
 #include "cx18-firmware.h"
@@ -113,11 +114,11 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
        src = (const u32 *)fw->data;
 
        for (i = 0; i < fw->size; i += 4096) {
-               setup_page(i);
+               cx18_setup_page(cx, i);
                for (j = i; j < fw->size && j < i + 4096; j += 4) {
                        /* no need for endianness conversion on the ppc */
-                       __raw_writel(*src, dst);
-                       if (__raw_readl(dst) != *src) {
+                       cx18_raw_writel(cx, *src, dst);
+                       if (cx18_raw_readl(cx, dst) != *src) {
                                CX18_ERR("Mismatch at offset %x\n", i);
                                release_firmware(fw);
                                return -EIO;
@@ -170,12 +171,15 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
                if (offset + seghdr.size > sz)
                        break;
                for (i = 0; i < seghdr.size; i += 4096) {
-                       setup_page(offset + i);
+                       cx18_setup_page(cx, offset + i);
                        for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
                                /* no need for endianness conversion on the ppc */
-                               __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
-                               if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
-                                       CX18_ERR("Mismatch at offset %x\n", offset + j);
+                               cx18_raw_writel(cx, src[(offset + j) / 4],
+                                               dst + seghdr.addr + j);
+                               if (cx18_raw_readl(cx, dst + seghdr.addr + j)
+                                   != src[(offset + j) / 4]) {
+                                       CX18_ERR("Mismatch at offset %x\n",
+                                                offset + j);
                                        release_firmware(fw);
                                        return -EIO;
                                }
@@ -189,43 +193,45 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
        size = fw->size;
        release_firmware(fw);
        /* Clear bit0 for APU to start from 0 */
-       write_reg(read_reg(0xc72030) & ~1, 0xc72030);
+       cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030);
        return size;
 }
 
 void cx18_halt_firmware(struct cx18 *cx)
 {
        CX18_DEBUG_INFO("Preparing for firmware halt.\n");
-       write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
-       write_reg(0x00020002, CX18_ADEC_CONTROL);
+       cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+       cx18_write_reg(cx, 0x00020002, CX18_ADEC_CONTROL);
 }
 
 void cx18_init_power(struct cx18 *cx, int lowpwr)
 {
        /* power-down Spare and AOM PLLs */
        /* power-up fast, slow and mpeg PLLs */
-       write_reg(0x00000008, CX18_PLL_POWER_DOWN);
+       cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
 
        /* ADEC out of sleep */
-       write_reg(0x00020000, CX18_ADEC_CONTROL);
+       cx18_write_reg(cx, 0x00020000, CX18_ADEC_CONTROL);
 
        /* The fast clock is at 200/245 MHz */
-       write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
-       write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
+       cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+       cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
+                                               CX18_FAST_CLOCK_PLL_FRAC);
 
-       write_reg(2, CX18_FAST_CLOCK_PLL_POST);
-       write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
-       write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+       cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
+       cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
+       cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
 
        /* set slow clock to 125/120 MHz */
-       write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
-       write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
-       write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
+       cx18_write_reg(cx, lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
+       cx18_write_reg(cx, lowpwr ? 0xEBAF05 : 0x18618A8,
+                                               CX18_SLOW_CLOCK_PLL_FRAC);
+       cx18_write_reg(cx, 4, CX18_SLOW_CLOCK_PLL_POST);
 
        /* mpeg clock pll 54MHz */
-       write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
-       write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
-       write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
+       cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
+       cx18_write_reg(cx, 0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
+       cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
 
        /* Defaults */
        /* APU = SC or SC/2 = 125/62.5 */
@@ -242,81 +248,84 @@ void cx18_init_power(struct cx18 *cx, int lowpwr)
        /* VFC = disabled */
        /* USB = disabled */
 
-       write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
-       write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
+       cx18_write_reg(cx, lowpwr ? 0xFFFF0020 : 0x00060004,
+                                                       CX18_CLOCK_SELECT1);
+       cx18_write_reg(cx, lowpwr ? 0xFFFF0004 : 0x00060006,
+                                                       CX18_CLOCK_SELECT2);
 
-       write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
-       write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
+       cx18_write_reg(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
+       cx18_write_reg(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
 
-       write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
-       write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
+       cx18_write_reg(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1);
+       cx18_write_reg(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2);
 }
 
 void cx18_init_memory(struct cx18 *cx)
 {
        cx18_msleep_timeout(10, 0);
-       write_reg(0x10000, CX18_DDR_SOFT_RESET);
+       cx18_write_reg(cx, 0x10000, CX18_DDR_SOFT_RESET);
        cx18_msleep_timeout(10, 0);
 
-       write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+       cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
 
        cx18_msleep_timeout(10, 0);
 
-       write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
-       write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
-       write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
+       cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
+       cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
+       cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
 
        cx18_msleep_timeout(10, 0);
 
        /* Initialize DQS pad time */
-       write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
-       write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+       cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+       cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
 
        cx18_msleep_timeout(10, 0);
 
-       write_reg(0x20000, CX18_DDR_SOFT_RESET);
+       cx18_write_reg(cx, 0x20000, CX18_DDR_SOFT_RESET);
        cx18_msleep_timeout(10, 0);
 
        /* use power-down mode when idle */
-       write_reg(0x00000010, CX18_DDR_POWER_REG);
-
-       write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
-
-       write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
-       write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
-
-       write_reg(0x00000101, CX18_WMB_CLIENT02);  /* AO */
-       write_reg(0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
-       write_reg(0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
-       write_reg(0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
-       write_reg(0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
-       write_reg(0x00000101, CX18_WMB_CLIENT10);  /* ME */
-       write_reg(0x00000101, CX18_WMB_CLIENT12);  /* ENC */
-       write_reg(0x00000101, CX18_WMB_CLIENT13);  /* PK */
-       write_reg(0x00000101, CX18_WMB_CLIENT11);  /* RC */
-       write_reg(0x00000101, CX18_WMB_CLIENT14);  /* AVO */
+       cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
+
+       cx18_write_reg(cx, 0x10001, CX18_REG_BUS_TIMEOUT_EN);
+
+       cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
+       cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
+
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);  /* AO */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);  /* ME */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);  /* ENC */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);  /* PK */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);  /* RC */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */
 }
 
 int cx18_firmware_init(struct cx18 *cx)
 {
        /* Allow chip to control CLKRUN */
-       write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
+       cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
 
-       write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+       cx18_write_reg(cx, 0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
 
        cx18_msleep_timeout(1, 0);
 
-       sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
-       sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+       cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+       cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
 
        /* Only if the processor is not running */
-       if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
+       if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) {
                int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
                               cx->enc_mem, cx);
 
-               write_enc(0xE51FF004, 0);
-               write_enc(0xa00000, 4);  /* todo: not hardcoded */
-               write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */
+               cx18_write_enc(cx, 0xE51FF004, 0);
+               cx18_write_enc(cx, 0xa00000, 4);  /* todo: not hardcoded */
+               /* Start APU */
+               cx18_write_reg(cx, 0x00010000, CX18_PROC_SOFT_RESET);
                cx18_msleep_timeout(500, 0);
 
                sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
@@ -326,9 +335,10 @@ int cx18_firmware_init(struct cx18 *cx)
                        int retries = 0;
 
                        /* start the CPU */
-                       write_reg(0x00080000, CX18_PROC_SOFT_RESET);
+                       cx18_write_reg(cx, 0x00080000, CX18_PROC_SOFT_RESET);
                        while (retries++ < 50) { /* Loop for max 500mS */
-                               if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
+                               if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET)
+                                    & 1) == 0)
                                        break;
                                cx18_msleep_timeout(10, 0);
                        }
@@ -342,6 +352,6 @@ int cx18_firmware_init(struct cx18 *cx)
                        return -EIO;
        }
        /* initialize GPIO */
-       write_reg(0x14001400, 0xC78110);
+       cx18_write_reg(cx, 0x14001400, 0xC78110);
        return 0;
 }
index 3d495dba4983d1662b2c2973ca97a1bb87b0ec54..0e560421989e4bb69f124a0ce28047d7c10665a3 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-cards.h"
 #include "cx18-gpio.h"
 #include "tuner-xc2028.h"
@@ -49,11 +50,11 @@ static void gpio_write(struct cx18 *cx)
        u32 dir = cx->gpio_dir;
        u32 val = cx->gpio_val;
 
-       write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
-       write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
+       cx18_write_reg(cx, (dir & 0xffff) << 16, CX18_REG_GPIO_DIR1);
+       cx18_write_reg(cx, ((dir & 0xffff) << 16) | (val & 0xffff),
                        CX18_REG_GPIO_OUT1);
-       write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
-       write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
+       cx18_write_reg(cx, dir & 0xffff0000, CX18_REG_GPIO_DIR2);
+       cx18_write_reg_sync(cx, (dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
                        CX18_REG_GPIO_OUT2);
 }
 
@@ -141,15 +142,17 @@ void cx18_gpio_init(struct cx18 *cx)
        }
 
        CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
-                  read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
-                  read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
+                       cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
+                       cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
+                       cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
+                       cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
 
        gpio_write(cx);
        mutex_unlock(&cx->gpio_lock);
 }
 
 /* Xceive tuner reset function */
-int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
 {
        struct i2c_algo_bit_data *algo = dev;
        struct cx18_i2c_algo_callback_data *cb_data = algo->data;
index 22cd7ddf8554ba36dc6c8f1e97772ec17bb679d6..beb7424b9944f928b7239be5a162d9114486b112 100644 (file)
@@ -23,5 +23,5 @@
 void cx18_gpio_init(struct cx18 *cx);
 void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
 void cx18_reset_ir_gpio(void *data);
-int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
 int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
index 6023ba3bd3a63d79d967fdbb86a2fa67611a391c..aa09e557b195ceef2d2e0bfc506e1a59412e8c80 100644 (file)
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-cards.h"
 #include "cx18-gpio.h"
 #include "cx18-av-core.h"
 #include "cx18-i2c.h"
 
-#include <media/ir-kbd-i2c.h>
-
 #define CX18_REG_I2C_1_WR   0xf15000
 #define CX18_REG_I2C_1_RD   0xf15008
 #define CX18_REG_I2C_2_WR   0xf25100
@@ -158,12 +157,12 @@ static void cx18_setscl(void *data, int state)
        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
        u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
-       u32 r = read_reg(addr);
+       u32 r = cx18_read_reg(cx, addr);
 
        if (state)
-               write_reg_sync(r | SETSCL_BIT, addr);
+               cx18_write_reg_sync(cx, r | SETSCL_BIT, addr);
        else
-               write_reg_sync(r & ~SETSCL_BIT, addr);
+               cx18_write_reg_sync(cx, r & ~SETSCL_BIT, addr);
 }
 
 static void cx18_setsda(void *data, int state)
@@ -171,12 +170,12 @@ static void cx18_setsda(void *data, int state)
        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
        u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
-       u32 r = read_reg(addr);
+       u32 r = cx18_read_reg(cx, addr);
 
        if (state)
-               write_reg_sync(r | SETSDL_BIT, addr);
+               cx18_write_reg_sync(cx, r | SETSDL_BIT, addr);
        else
-               write_reg_sync(r & ~SETSDL_BIT, addr);
+               cx18_write_reg_sync(cx, r & ~SETSDL_BIT, addr);
 }
 
 static int cx18_getscl(void *data)
@@ -185,7 +184,7 @@ static int cx18_getscl(void *data)
        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
        u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
 
-       return read_reg(addr) & GETSCL_BIT;
+       return cx18_read_reg(cx, addr) & GETSCL_BIT;
 }
 
 static int cx18_getsda(void *data)
@@ -194,7 +193,7 @@ static int cx18_getsda(void *data)
        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
        u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
 
-       return read_reg(addr) & GETSDL_BIT;
+       return cx18_read_reg(cx, addr) & GETSDL_BIT;
 }
 
 /* template for i2c-bit-algo */
@@ -394,29 +393,33 @@ int init_cx18_i2c(struct cx18 *cx)
                cx->i2c_adap[i].dev.parent = &cx->dev->dev;
        }
 
-       if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
+       if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
                /* Reset/Unreset I2C hardware block */
-               write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
-               write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
+               /* Clock select 220MHz */
+               cx18_write_reg(cx, 0x10000000, 0xc71004);
+               /* Clock Enable */
+               cx18_write_reg_sync(cx, 0x10001000, 0xc71024);
        }
        /* courtesy of Steven Toth <stoth@hauppauge.com> */
-       write_reg_sync(0x00c00000, 0xc7001c);
+       cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
        mdelay(10);
-       write_reg_sync(0x00c000c0, 0xc7001c);
+       cx18_write_reg_sync(cx, 0x00c000c0, 0xc7001c);
        mdelay(10);
-       write_reg_sync(0x00c00000, 0xc7001c);
+       cx18_write_reg_sync(cx, 0x00c00000, 0xc7001c);
        mdelay(10);
 
-       write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
-       write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
+       /* Set to edge-triggered intrs. */
+       cx18_write_reg_sync(cx, 0x00c00000, 0xc730c8);
+       /* Clear any stale intrs */
+       cx18_write_reg_sync(cx, 0x00c00000, 0xc730c4);
 
        /* Hw I2C1 Clock Freq ~100kHz */
-       write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+       cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
        cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
        cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
 
        /* Hw I2C2 Clock Freq ~100kHz */
-       write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+       cx18_write_reg_sync(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
        cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
        cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 
@@ -430,8 +433,10 @@ void exit_cx18_i2c(struct cx18 *cx)
 {
        int i;
        CX18_DEBUG_I2C("i2c exit\n");
-       write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
-       write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
+       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
+                                                       CX18_REG_I2C_1_WR);
+       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
+                                                       CX18_REG_I2C_2_WR);
 
        for (i = 0; i < 2; i++) {
                i2c_del_adapter(&cx->i2c_adap[i]);
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
new file mode 100644 (file)
index 0000000..700ab94
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+
+void cx18_log_statistics(struct cx18 *cx)
+{
+       int i;
+
+       if (!(cx18_debug & CX18_DBGFLG_INFO))
+               return;
+
+       for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+               CX18_DEBUG_INFO("retried_write[%d] = %d\n", i,
+                               atomic_read(&cx->mmio_stats.retried_write[i]));
+       for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
+               CX18_DEBUG_INFO("retried_read[%d] = %d\n", i,
+                               atomic_read(&cx->mmio_stats.retried_read[i]));
+       return;
+}
+
+void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               cx18_raw_writel_noretry(cx, val, addr);
+               if (val == cx18_raw_readl_noretry(cx, addr))
+                       break;
+       }
+       cx18_log_write_retries(cx, i, addr);
+}
+
+u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr)
+{
+       int i;
+       u32 val;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               val = cx18_raw_readl_noretry(cx, addr);
+               if (val != 0xffffffff) /* PCI bus read error */
+                       break;
+       }
+       cx18_log_read_retries(cx, i, addr);
+       return val;
+}
+
+u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr)
+{
+       int i;
+       u16 val;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               val = cx18_raw_readw_noretry(cx, addr);
+               if (val != 0xffff) /* PCI bus read error */
+                       break;
+       }
+       cx18_log_read_retries(cx, i, addr);
+       return val;
+}
+
+void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               cx18_writel_noretry(cx, val, addr);
+               if (val == cx18_readl_noretry(cx, addr))
+                       break;
+       }
+       cx18_log_write_retries(cx, i, addr);
+}
+
+void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               cx18_writew_noretry(cx, val, addr);
+               if (val == cx18_readw_noretry(cx, addr))
+                       break;
+       }
+       cx18_log_write_retries(cx, i, addr);
+}
+
+void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               cx18_writeb_noretry(cx, val, addr);
+               if (val == cx18_readb_noretry(cx, addr))
+                       break;
+       }
+       cx18_log_write_retries(cx, i, addr);
+}
+
+u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr)
+{
+       int i;
+       u32 val;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               val = cx18_readl_noretry(cx, addr);
+               if (val != 0xffffffff) /* PCI bus read error */
+                       break;
+       }
+       cx18_log_read_retries(cx, i, addr);
+       return val;
+}
+
+u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr)
+{
+       int i;
+       u16 val;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               val = cx18_readw_noretry(cx, addr);
+               if (val != 0xffff) /* PCI bus read error */
+                       break;
+       }
+       cx18_log_read_retries(cx, i, addr);
+       return val;
+}
+
+u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr)
+{
+       int i;
+       u8 val;
+       for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
+               val = cx18_readb_noretry(cx, addr);
+               if (val != 0xff) /* PCI bus read error */
+                       break;
+       }
+       cx18_log_read_retries(cx, i, addr);
+       return val;
+}
+
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+                       const void __iomem *from, unsigned int len)
+{
+       const u8 __iomem *src = from;
+       u8 *dst = to;
+
+       /* Align reads on the CX23418's addresses */
+       if ((len > 0) && ((unsigned long) src & 1)) {
+               *dst = cx18_readb(cx, src);
+               len--;
+               dst++;
+               src++;
+       }
+       if ((len > 1) && ((unsigned long) src & 2)) {
+               *((u16 *)dst) = cx18_raw_readw(cx, src);
+               len -= 2;
+               dst += 2;
+               src += 2;
+       }
+       while (len > 3) {
+               *((u32 *)dst) = cx18_raw_readl(cx, src);
+               len -= 4;
+               dst += 4;
+               src += 4;
+       }
+       if (len > 1) {
+               *((u16 *)dst) = cx18_raw_readw(cx, src);
+               len -= 2;
+               dst += 2;
+               src += 2;
+       }
+       if (len > 0)
+               *dst = cx18_readb(cx, src);
+}
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
+{
+       u8 __iomem *dst = addr;
+       u16 val2 = val | (val << 8);
+       u32 val4 = val2 | (val2 << 16);
+
+       /* Align writes on the CX23418's addresses */
+       if ((count > 0) && ((unsigned long)dst & 1)) {
+               cx18_writeb(cx, (u8) val, dst);
+               count--;
+               dst++;
+       }
+       if ((count > 1) && ((unsigned long)dst & 2)) {
+               cx18_writew(cx, val2, dst);
+               count -= 2;
+               dst += 2;
+       }
+       while (count > 3) {
+               cx18_writel(cx, val4, dst);
+               count -= 4;
+               dst += 4;
+       }
+       if (count > 1) {
+               cx18_writew(cx, val2, dst);
+               count -= 2;
+               dst += 2;
+       }
+       if (count > 0)
+               cx18_writeb(cx, (u8) val, dst);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
+{
+       u32 r;
+       cx18_write_reg(cx, val, SW1_INT_STATUS);
+       r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
+       cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
+{
+       u32 r;
+       r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
+       cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
+{
+       u32 r;
+       cx18_write_reg(cx, val, SW2_INT_STATUS);
+       r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
+       cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
+{
+       u32 r;
+       r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
+       cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_setup_page(struct cx18 *cx, u32 addr)
+{
+       u32 val;
+       val = cx18_read_reg(cx, 0xD000F8);
+       val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
+       cx18_write_reg(cx, val, 0xD000F8);
+}
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
new file mode 100644 (file)
index 0000000..197d4fb
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@radix.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 CX18_IO_H
+#define CX18_IO_H
+
+#include "cx18-driver.h"
+
+static inline void cx18_io_delay(struct cx18 *cx)
+{
+       if (cx->options.mmio_ndelay)
+               ndelay(cx->options.mmio_ndelay);
+}
+
+/*
+ * Readback and retry of MMIO access for reliability:
+ * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
+ * The implmentation is the fault of Andy Walls <awalls@radix.net>.
+ */
+
+/* Statistics gathering */
+static inline
+void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
+{
+       if (i > CX18_MAX_MMIO_RETRIES)
+               i = CX18_MAX_MMIO_RETRIES;
+       atomic_inc(&cx->mmio_stats.retried_write[i]);
+       return;
+}
+
+static inline
+void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr)
+{
+       if (i > CX18_MAX_MMIO_RETRIES)
+               i = CX18_MAX_MMIO_RETRIES;
+       atomic_inc(&cx->mmio_stats.retried_read[i]);
+       return;
+}
+
+void cx18_log_statistics(struct cx18 *cx);
+
+/* Non byteswapping memory mapped IO */
+static inline
+void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       __raw_writel(val, addr);
+       cx18_io_delay(cx);
+}
+
+void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
+
+static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               cx18_raw_writel_retry(cx, val, addr);
+       else
+               cx18_raw_writel_noretry(cx, val, addr);
+}
+
+
+static inline
+u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+       u32 ret = __raw_readl(addr);
+       cx18_io_delay(cx);
+       return ret;
+}
+
+u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_raw_readl_retry(cx, addr);
+
+       return cx18_raw_readl_noretry(cx, addr);
+}
+
+
+static inline
+u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+       u16 ret = __raw_readw(addr);
+       cx18_io_delay(cx);
+       return ret;
+}
+
+u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_raw_readw_retry(cx, addr);
+
+       return cx18_raw_readw_noretry(cx, addr);
+}
+
+
+/* Normal memory mapped IO */
+static inline
+void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+       cx18_io_delay(cx);
+}
+
+void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
+
+static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               cx18_writel_retry(cx, val, addr);
+       else
+               cx18_writel_noretry(cx, val, addr);
+}
+
+
+static inline
+void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+       writew(val, addr);
+       cx18_io_delay(cx);
+}
+
+void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr);
+
+static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               cx18_writew_retry(cx, val, addr);
+       else
+               cx18_writew_noretry(cx, val, addr);
+}
+
+
+static inline
+void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+       writeb(val, addr);
+       cx18_io_delay(cx);
+}
+
+void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr);
+
+static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               cx18_writeb_retry(cx, val, addr);
+       else
+               cx18_writeb_noretry(cx, val, addr);
+}
+
+
+static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+       u32 ret = readl(addr);
+       cx18_io_delay(cx);
+       return ret;
+}
+
+u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_readl_retry(cx, addr);
+
+       return cx18_readl_noretry(cx, addr);
+}
+
+
+static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+       u16 ret = readw(addr);
+       cx18_io_delay(cx);
+       return ret;
+}
+
+u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_readw_retry(cx, addr);
+
+       return cx18_readw_noretry(cx, addr);
+}
+
+
+static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr)
+{
+       u8 ret = readb(addr);
+       cx18_io_delay(cx);
+       return ret;
+}
+
+u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr);
+
+static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_readb_retry(cx, addr);
+
+       return cx18_readb_noretry(cx, addr);
+}
+
+
+static inline
+u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       cx18_writel_noretry(cx, val, addr);
+       return cx18_readl_noretry(cx, addr);
+}
+
+static inline
+u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       cx18_writel_retry(cx, val, addr);
+       return cx18_readl_retry(cx, addr);
+}
+
+static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_write_sync_retry(cx, val, addr);
+
+       return cx18_write_sync_noretry(cx, val, addr);
+}
+
+
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+                       const void __iomem *from, unsigned int len);
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
+
+
+/* Access "register" region of CX23418 memory mapped I/O */
+static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+       cx18_writel_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg)
+{
+       cx18_writel_retry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
+{
+       if (cx18_retry_mmio)
+               cx18_write_reg_retry(cx, val, reg);
+       else
+               cx18_write_reg_noretry(cx, val, reg);
+}
+
+
+static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg)
+{
+       return cx18_readl_noretry(cx, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg)
+{
+       return cx18_readl_retry(cx, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
+{
+       if (cx18_retry_mmio)
+               return cx18_read_reg_retry(cx, reg);
+
+       return cx18_read_reg_noretry(cx, reg);
+}
+
+
+static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+       return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg)
+{
+       return cx18_write_sync_retry(cx, val, cx->reg_mem + reg);
+}
+
+static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg)
+{
+       if (cx18_retry_mmio)
+               return cx18_write_reg_sync_retry(cx, val, reg);
+
+       return cx18_write_reg_sync_noretry(cx, val, reg);
+}
+
+
+/* Access "encoder memory" region of CX23418 memory mapped I/O */
+static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr)
+{
+       cx18_writel_noretry(cx, val, cx->enc_mem + addr);
+}
+
+static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr)
+{
+       cx18_writel_retry(cx, val, cx->enc_mem + addr);
+}
+
+static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
+{
+       if (cx18_retry_mmio)
+               cx18_write_enc_retry(cx, val, addr);
+       else
+               cx18_write_enc_noretry(cx, val, addr);
+}
+
+
+static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr)
+{
+       return cx18_readl_noretry(cx, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr)
+{
+       return cx18_readl_retry(cx, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_read_enc_retry(cx, addr);
+
+       return cx18_read_enc_noretry(cx, addr);
+}
+
+static inline
+u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr)
+{
+       return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr);
+}
+
+static inline
+u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr)
+{
+       return cx18_write_sync_retry(cx, val, cx->enc_mem + addr);
+}
+
+static inline
+u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr)
+{
+       if (cx18_retry_mmio)
+               return cx18_write_enc_sync_retry(cx, val, addr);
+
+       return cx18_write_enc_sync_noretry(cx, val, addr);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
+void cx18_setup_page(struct cx18 *cx, u32 addr);
+
+#endif /* CX18_IO_H */
index a7f839631d6a6a5c2932385e956b6716b8059309..f0ca50f5fddeb3d290d1567f8d27a4e9d1378230 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-version.h"
 #include "cx18-mailbox.h"
 #include "cx18-i2c.h"
@@ -170,7 +171,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
 {
        struct cx18_open_id *id = fh;
        struct cx18 *cx = id->cx;
-
        int w = fmt->fmt.pix.width;
        int h = fmt->fmt.pix.height;
 
@@ -202,8 +202,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
        struct cx18_open_id *id = fh;
        struct cx18 *cx = id->cx;
        int ret;
-       int w = fmt->fmt.pix.width;
-       int h = fmt->fmt.pix.height;
+       int w, h;
 
        ret = v4l2_prio_check(&cx->prio, &id->prio);
        if (ret)
@@ -212,6 +211,8 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
        ret = cx18_try_fmt_vid_cap(file, fh, fmt);
        if (ret)
                return ret;
+       w = fmt->fmt.pix.width;
+       h = fmt->fmt.pix.height;
 
        if (cx->params.width == w && cx->params.height == h)
                return 0;
@@ -286,9 +287,9 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
 
        spin_lock_irqsave(&cx18_cards_lock, flags);
        if (cmd == VIDIOC_DBG_G_REGISTER)
-               regs->val = read_enc(regs->reg);
+               regs->val = cx18_read_enc(cx, regs->reg);
        else
-               write_enc(regs->val, regs->reg);
+               cx18_write_enc(cx, regs->val, regs->reg);
        spin_unlock_irqrestore(&cx18_cards_lock, flags);
        return 0;
 }
@@ -345,7 +346,7 @@ static int cx18_querycap(struct file *file, void *fh,
 
        strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
        strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
-       strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
+       snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->dev));
        vcap->version = CX18_DRIVER_VERSION;        /* version */
        vcap->capabilities = cx->v4l2_cap;          /* capabilities */
        return 0;
@@ -622,6 +623,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
 {
        struct cx18_open_id *id = fh;
        struct cx18 *cx = id->cx;
+       u32 h;
 
        switch (enc->cmd) {
        case V4L2_ENC_CMD_START:
@@ -643,8 +645,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
                        return -EPERM;
                if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
                        return 0;
+               h = cx18_find_handle(cx);
+               if (h == CX18_INVALID_TASK_HANDLE) {
+                       CX18_ERR("Can't find valid task handle for "
+                                "V4L2_ENC_CMD_PAUSE\n");
+                       return -EBADFD;
+               }
                cx18_mute(cx);
-               cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
+               cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
                break;
 
        case V4L2_ENC_CMD_RESUME:
@@ -654,7 +662,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
                        return -EPERM;
                if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
                        return 0;
-               cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
+               h = cx18_find_handle(cx);
+               if (h == CX18_INVALID_TASK_HANDLE) {
+                       CX18_ERR("Can't find valid task handle for "
+                                "V4L2_ENC_CMD_RESUME\n");
+                       return -EBADFD;
+               }
+               cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
                cx18_unmute(cx);
                break;
 
@@ -731,12 +745,14 @@ static int cx18_log_status(struct file *file, void *fh)
                        continue;
                CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
                          s->name, s->s_flags,
-                         (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+                         (s->buffers - atomic_read(&s->q_free.buffers))
+                               * 100 / s->buffers,
                          (s->buffers * s->buf_size) / 1024, s->buffers);
        }
        CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
                        (long long)cx->mpg_data_received,
                        (long long)cx->vbi_data_inserted);
+       cx18_log_statistics(cx);
        CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
        return 0;
 }
index ab218315c84bb384fd71865392254c54fe9f9fbb..360330f5463f9ce985d4e835d84d9b5e12536b6d 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-firmware.h"
 #include "cx18-fileops.h"
 #include "cx18-queue.h"
@@ -48,8 +49,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
                        break;
        }
        if (i == CX18_MAX_STREAMS) {
-               CX18_WARN("DMA done for unknown handle %d for stream %s\n",
-                       handle, s->name);
+               CX18_WARN("Got DMA done notification for unknown/inactive"
+                         " handle %d\n", handle);
                mb->error = CXERR_NOT_OPEN;
                mb->cmd = 0;
                cx18_mb_ack(cx, mb);
@@ -60,8 +61,8 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
        if (mb->args[2] != 1)
                CX18_WARN("Ack struct = %d for %s\n",
                        mb->args[2], s->name);
-       id = read_enc(off);
-       buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4));
+       id = cx18_read_enc(cx, off);
+       buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4));
        CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
        if (buf) {
                cx18_buf_sync_for_cpu(s, buf);
@@ -81,7 +82,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
                        set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
        } else {
                CX18_WARN("Could not find buf %d for stream %s\n",
-                               read_enc(off), s->name);
+                               cx18_read_enc(cx, off), s->name);
        }
        mb->error = 0;
        mb->cmd = 0;
@@ -97,8 +98,8 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
        char *p;
 
        if (mb->args[1]) {
-               setup_page(mb->args[1]);
-               memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
+               cx18_setup_page(cx, mb->args[1]);
+               cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252);
                str[252] = 0;
        }
        cx18_mb_ack(cx, mb);
@@ -113,7 +114,7 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1)
        struct cx18_mailbox mb;
 
        if (sw1 & IRQ_CPU_TO_EPU) {
-               memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
+               cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb));
                mb.error = 0;
 
                switch (mb.cmd) {
@@ -141,16 +142,16 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
 
        spin_lock(&cx->dma_reg_lock);
 
-       hw2_mask = read_reg(HW2_INT_MASK5_PCI);
-       hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
-       sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
-       sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
-       sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
-       sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
+       hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
+       hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
+       sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
+       sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
+       sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
+       sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
 
-       write_reg(sw2&sw2_mask, SW2_INT_STATUS);
-       write_reg(sw1&sw1_mask, SW1_INT_STATUS);
-       write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
+       cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS);
+       cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS);
+       cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS);
 
        if (sw1 || sw2 || hw2)
                CX18_DEBUG_HI_IRQ("SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
@@ -161,15 +162,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
        */
 
        if (sw2) {
-               if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) |
-                          readl(&cx->scb->cpu2epu_irq_ack)))
+               if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) |
+                          cx18_readl(cx, &cx->scb->cpu2epu_irq_ack)))
                        wake_up(&cx->mb_cpu_waitq);
-               if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) |
-                          readl(&cx->scb->apu2epu_irq_ack)))
+               if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) |
+                          cx18_readl(cx, &cx->scb->apu2epu_irq_ack)))
                        wake_up(&cx->mb_apu_waitq);
-               if (sw2 & readl(&cx->scb->epu2hpu_irq_ack))
+               if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack))
                        wake_up(&cx->mb_epu_waitq);
-               if (sw2 & readl(&cx->scb->hpu2epu_irq_ack))
+               if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack))
                        wake_up(&cx->mb_hpu_waitq);
        }
 
index 93177514e846e8c5ab73ce485976ac8b424e773f..9d18dd22de76e9f1866fb27264159fb5b9798bce 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-scb.h"
 #include "cx18-irq.h"
 #include "cx18-mailbox.h"
@@ -82,6 +83,7 @@ static const struct cx18_api_info api_info[] = {
        API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,                 0),
        API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,                     API_FAST),
        API_ENTRY(CPU, CX18_APU_RESETAI,                        API_FAST),
+       API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,                 0),
        API_ENTRY(0, 0,                                         0),
 };
 
@@ -105,20 +107,20 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
        switch (rpu) {
        case APU:
                mb = &cx->scb->epu2apu_mb;
-               *state = readl(&cx->scb->apu_state);
-               *irq = readl(&cx->scb->epu2apu_irq);
+               *state = cx18_readl(cx, &cx->scb->apu_state);
+               *irq = cx18_readl(cx, &cx->scb->epu2apu_irq);
                break;
 
        case CPU:
                mb = &cx->scb->epu2cpu_mb;
-               *state = readl(&cx->scb->cpu_state);
-               *irq = readl(&cx->scb->epu2cpu_irq);
+               *state = cx18_readl(cx, &cx->scb->cpu_state);
+               *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
                break;
 
        case HPU:
                mb = &cx->scb->epu2hpu_mb;
-               *state = readl(&cx->scb->hpu_state);
-               *irq = readl(&cx->scb->epu2hpu_irq);
+               *state = cx18_readl(cx, &cx->scb->hpu_state);
+               *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq);
                break;
        }
 
@@ -126,8 +128,8 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
                return mb;
 
        do {
-               *req = readl(&mb->request);
-               ack = readl(&mb->ack);
+               *req = cx18_readl(cx, &mb->request);
+               ack = cx18_readl(cx, &mb->ack);
                wait_count++;
        } while (*req != ack && wait_count < 600);
 
@@ -172,9 +174,9 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
                return -EINVAL;
        }
 
-       setup_page(SCB_OFFSET);
-       write_sync(mb->request, &ack_mb->ack);
-       write_reg(ack_irq, SW2_INT_SET);
+       cx18_setup_page(cx, SCB_OFFSET);
+       cx18_write_sync(cx, mb->request, &ack_mb->ack);
+       cx18_write_reg(cx, ack_irq, SW2_INT_SET);
        return 0;
 }
 
@@ -199,7 +201,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
                CX18_DEBUG_HI_API("%s\n", info->name);
        else
                CX18_DEBUG_API("%s\n", info->name);
-       setup_page(SCB_OFFSET);
+       cx18_setup_page(cx, SCB_OFFSET);
        mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
 
        if (mb == NULL) {
@@ -208,11 +210,11 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
        }
 
        oldreq = req - 1;
-       writel(cmd, &mb->cmd);
+       cx18_writel(cx, cmd, &mb->cmd);
        for (i = 0; i < args; i++)
-               writel(data[i], &mb->args[i]);
-       writel(0, &mb->error);
-       writel(req, &mb->request);
+               cx18_writel(cx, data[i], &mb->args[i]);
+       cx18_writel(cx, 0, &mb->error);
+       cx18_writel(cx, req, &mb->request);
 
        switch (info->rpu) {
        case APU: waitq = &cx->mb_apu_waitq; break;
@@ -223,9 +225,10 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
        }
        if (info->flags & API_FAST)
                timeout /= 2;
-       write_reg(irq, SW1_INT_SET);
+       cx18_write_reg(cx, irq, SW1_INT_SET);
 
-       while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
+       while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request)
+              && cnt < 660) {
                if (cnt > 200 && !in_atomic())
                        sig = cx18_msleep_timeout(10, 1);
                cnt++;
@@ -233,13 +236,13 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
        if (sig)
                return -EINTR;
        if (cnt == 660) {
-               writel(oldreq, &mb->request);
+               cx18_writel(cx, oldreq, &mb->request);
                CX18_ERR("mb %s failed\n", info->name);
                return -EINVAL;
        }
        for (i = 0; i < MAX_MB_ARGUMENTS; i++)
-               data[i] = readl(&mb->args[i]);
-       err = readl(&mb->error);
+               data[i] = cx18_readl(cx, &mb->args[i]);
+       err = cx18_readl(cx, &mb->error);
        if (!in_atomic() && (info->flags & API_SLOW))
                cx18_msleep_timeout(300, 0);
        if (err)
index dbe792ac30015d68c760a1d42b2731f7a043042e..a33ba04a2686aa3ec73d0d705ddc1aa1bb3abad8 100644 (file)
@@ -37,8 +37,7 @@ void cx18_buf_swap(struct cx18_buffer *buf)
 void cx18_queue_init(struct cx18_queue *q)
 {
        INIT_LIST_HEAD(&q->list);
-       q->buffers = 0;
-       q->length = 0;
+       atomic_set(&q->buffers, 0);
        q->bytesused = 0;
 }
 
@@ -55,8 +54,7 @@ void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
        }
        spin_lock_irqsave(&s->qlock, flags);
        list_add_tail(&buf->list, &q->list);
-       q->buffers++;
-       q->length += s->buf_size;
+       atomic_inc(&q->buffers);
        q->bytesused += buf->bytesused - buf->readpos;
        spin_unlock_irqrestore(&s->qlock, flags);
 }
@@ -70,8 +68,7 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
        if (!list_empty(&q->list)) {
                buf = list_entry(q->list.next, struct cx18_buffer, list);
                list_del_init(q->list.next);
-               q->buffers--;
-               q->length -= s->buf_size;
+               atomic_dec(&q->buffers);
                q->bytesused -= buf->bytesused - buf->readpos;
        }
        spin_unlock_irqrestore(&s->qlock, flags);
@@ -95,10 +92,8 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id,
                /* the transport buffers are handled differently,
                   they are not moved to the full queue */
                if (s->type != CX18_ENC_STREAM_TYPE_TS) {
-                       s->q_free.buffers--;
-                       s->q_free.length -= s->buf_size;
-                       s->q_full.buffers++;
-                       s->q_full.length += s->buf_size;
+                       atomic_dec(&s->q_free.buffers);
+                       atomic_inc(&s->q_full.buffers);
                        s->q_full.bytesused += buf->bytesused;
                        list_move_tail(&buf->list, &s->q_full.list);
                }
@@ -124,8 +119,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q)
                buf = list_entry(q->list.next, struct cx18_buffer, list);
                list_move_tail(q->list.next, &s->q_free.list);
                buf->bytesused = buf->readpos = buf->b_flags = 0;
-               s->q_free.buffers++;
-               s->q_free.length += s->buf_size;
+               atomic_inc(&s->q_free.buffers);
        }
        cx18_queue_init(q);
        spin_unlock_irqrestore(&s->qlock, flags);
index 30bc803e30da5b31460fe04e374f3c716ce64b3f..f56d3772aa675bdb60464fc14ff3f4052ea7cb0b 100644 (file)
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-scb.h"
 
 void cx18_init_scb(struct cx18 *cx)
 {
-       setup_page(SCB_OFFSET);
-       memset_io(cx->scb, 0, 0x10000);
+       cx18_setup_page(cx, SCB_OFFSET);
+       cx18_memset_io(cx, cx->scb, 0, 0x10000);
 
-       writel(IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
-       writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
-       writel(IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
-       writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
-       writel(IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
-       writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
-       writel(IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
-       writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
 
-       writel(IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
-       writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
-       writel(IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
-       writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
-       writel(IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
-       writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
-       writel(IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
-       writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+       cx18_writel(cx, IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
 
-       writel(IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
-       writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
-       writel(IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
-       writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
-       writel(IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
-       writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
-       writel(IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
-       writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+       cx18_writel(cx, IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
 
-       writel(IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
-       writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
-       writel(IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
-       writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
-       writel(IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
-       writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
-       writel(IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
-       writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+       cx18_writel(cx, IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
 
-       writel(IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
-       writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
-       writel(IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
-       writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
-       writel(IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
-       writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
-       writel(IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
-       writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
 
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
                        &cx->scb->apu2cpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
                        &cx->scb->hpu2cpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
                        &cx->scb->ppu2cpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
                        &cx->scb->epu2cpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
                        &cx->scb->cpu2apu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
                        &cx->scb->hpu2apu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
                        &cx->scb->ppu2apu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
                        &cx->scb->epu2apu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
                        &cx->scb->cpu2hpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
                        &cx->scb->apu2hpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
                        &cx->scb->ppu2hpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
                        &cx->scb->epu2hpu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
                        &cx->scb->cpu2ppu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
                        &cx->scb->apu2ppu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
                        &cx->scb->hpu2ppu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
                        &cx->scb->epu2ppu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
                        &cx->scb->cpu2epu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
                        &cx->scb->apu2epu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
                        &cx->scb->hpu2epu_mb_offset);
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
                        &cx->scb->ppu2epu_mb_offset);
 
-       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
                        &cx->scb->ipc_offset);
 
-       writel(1, &cx->scb->hpu_state);
-       writel(1, &cx->scb->epu_state);
+       cx18_writel(cx, 1, &cx->scb->hpu_state);
+       cx18_writel(cx, 1, &cx->scb->epu_state);
 }
index 0da57f583bf75a90207b6b82bd5b762f95c742c6..0c8e7542cf6044ec86fbe8e0c6eb8931240c8e25 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "cx18-driver.h"
+#include "cx18-io.h"
 #include "cx18-fileops.h"
 #include "cx18-mailbox.h"
 #include "cx18-i2c.h"
@@ -56,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = {
 static struct {
        const char *name;
        int vfl_type;
-       int minor_offset;
+       int num_offset;
        int dma;
        enum v4l2_buf_type buf_type;
        struct file_operations *fops;
@@ -119,7 +120,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
        s->cx = cx;
        s->type = type;
        s->name = cx18_stream_info[type].name;
-       s->handle = 0xffffffff;
+       s->handle = CX18_INVALID_TASK_HANDLE;
 
        s->dma = cx18_stream_info[type].dma;
        s->buf_size = cx->stream_buf_size[type];
@@ -143,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 {
        struct cx18_stream *s = &cx->streams[type];
        u32 cap = cx->v4l2_cap;
-       int minor_offset = cx18_stream_info[type].minor_offset;
-       int minor;
+       int num_offset = cx18_stream_info[type].num_offset;
+       int num = cx->num + cx18_first_minor + num_offset;
 
        /* These four fields are always initialized. If v4l2dev == NULL, then
           this stream is not in use. In that case no other fields but these
@@ -163,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
            !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
                return 0;
 
-       /* card number + user defined offset + device offset */
-       minor = cx->num + cx18_first_minor + minor_offset;
-
        /* User explicitly selected 0 buffers for these streams, so don't
           create them. */
        if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
@@ -176,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 
        cx18_stream_init(cx, type);
 
-       if (minor_offset == -1)
+       if (num_offset == -1)
                return 0;
 
        /* allocate and initialize the v4l2 video device structure */
@@ -190,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
        snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
                        cx->num);
 
-       s->v4l2dev->minor = minor;
+       s->v4l2dev->num = num;
        s->v4l2dev->parent = &cx->dev->dev;
        s->v4l2dev->fops = cx18_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
@@ -226,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
 {
        struct cx18_stream *s = &cx->streams[type];
        int vfl_type = cx18_stream_info[type].vfl_type;
-       int minor;
+       int num;
 
        /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
         * We need a VFL_TYPE_TS defined.
@@ -244,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
        if (s->v4l2dev == NULL)
                return 0;
 
-       minor = s->v4l2dev->minor;
+       num = s->v4l2dev->num;
+       /* card number + user defined offset + device offset */
+       if (type != CX18_ENC_STREAM_TYPE_MPG) {
+               struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
+               if (s_mpg->v4l2dev)
+                       num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset;
+       }
 
        /* Register device. First try the desired minor, then any free one. */
-       if (video_register_device(s->v4l2dev, vfl_type, minor) &&
-                       video_register_device(s->v4l2dev, vfl_type, -1)) {
-               CX18_ERR("Couldn't register v4l2 device for %s minor %d\n",
-                       s->name, minor);
+       if (video_register_device(s->v4l2dev, vfl_type, num)) {
+               CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
+                       s->name, num);
                video_device_release(s->v4l2dev);
                s->v4l2dev = NULL;
                return -ENOMEM;
        }
-       minor = s->v4l2dev->minor;
+       num = s->v4l2dev->num;
 
        switch (vfl_type) {
        case VFL_TYPE_GRABBER:
                CX18_INFO("Registered device video%d for %s (%d MB)\n",
-                       minor, s->name, cx->options.megabytes[type]);
+                       num, s->name, cx->options.megabytes[type]);
                break;
 
        case VFL_TYPE_RADIO:
                CX18_INFO("Registered device radio%d for %s\n",
-                       minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+                       num, s->name);
                break;
 
        case VFL_TYPE_VBI:
                if (cx->options.megabytes[type])
                        CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
-                               minor - MINOR_VFL_TYPE_VBI_MIN,
+                               num,
                                s->name, cx->options.megabytes[type]);
                else
                        CX18_INFO("Registered device vbi%d for %s\n",
-                               minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+                               num, s->name);
                break;
        }
 
@@ -432,7 +436,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
        default:
                return -EINVAL;
        }
-       s->buffers_stolen = 0;
 
        /* mute/unmute video */
        cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
@@ -470,7 +473,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
 
        if (atomic_read(&cx->tot_capturing) == 0) {
                clear_bit(CX18_F_I_EOS, &cx->i_flags);
-               write_reg(7, CX18_DSP0_INTERRUPT_MASK);
+               cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
        }
 
        cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
@@ -480,8 +483,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
        list_for_each(p, &s->q_free.list) {
                struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
 
-               writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
-               writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
+               cx18_writel(cx, buf->dma_handle,
+                                       &cx->scb->cpu_mdl[buf->id].paddr);
+               cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
                cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
                        (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
                        1, buf->id, s->buf_size);
@@ -489,7 +493,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
        /* begin_capture */
        if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
                CX18_DEBUG_WARN("Error starting capture!\n");
+               /* Ensure we're really not capturing before releasing MDLs */
+               if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
+               else
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+               cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
                cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+               /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */
                return -EINVAL;
        }
 
@@ -541,6 +552,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
                CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
        }
 
+       /* Tell the CX23418 it can't use our buffers anymore */
+       cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
        if (s->type != CX18_ENC_STREAM_TYPE_TS)
                atomic_dec(&cx->ana_capturing);
        atomic_dec(&cx->tot_capturing);
@@ -549,12 +563,12 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
        clear_bit(CX18_F_S_STREAMING, &s->s_flags);
 
        cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
-       s->handle = 0xffffffff;
+       s->handle = CX18_INVALID_TASK_HANDLE;
 
        if (atomic_read(&cx->tot_capturing) > 0)
                return 0;
 
-       write_reg(5, CX18_DSP0_INTERRUPT_MASK);
+       cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
        wake_up(&s->waitq);
 
        return 0;
@@ -568,8 +582,8 @@ u32 cx18_find_handle(struct cx18 *cx)
        for (i = 0; i < CX18_MAX_STREAMS; i++) {
                struct cx18_stream *s = &cx->streams[i];
 
-               if (s->v4l2dev && s->handle)
+               if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE))
                        return s->handle;
        }
-       return 0;
+       return CX18_INVALID_TASK_HANDLE;
 }
index d5c7a6f968dda201b154d4d2d06563b8ca1bd44b..9f6be2d457fb727cc26f8bb0720729f2f7bd2677 100644 (file)
@@ -25,7 +25,7 @@
 #define CX18_DRIVER_NAME "cx18"
 #define CX18_DRIVER_VERSION_MAJOR 1
 #define CX18_DRIVER_VERSION_MINOR 0
-#define CX18_DRIVER_VERSION_PATCHLEVEL 0
+#define CX18_DRIVER_VERSION_PATCHLEVEL 1
 
 #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
 #define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
index e7ed053059a8fdb4dc28a7cf5a7057b86e89971e..668f968d7761846cb17ae5d046f9154ca68be08f 100644 (file)
    Descriptor Lists to the driver
    IN[0] - Task handle. Handle of the task to start
    ReturnCode - One of the ERR_DE_... */
-/* #define CX18_CPU_DE_ReleaseMDL               (CPU_CMD_MASK_DE | 0x0006) */
+#define CX18_CPU_DE_RELEASE_MDL                (CPU_CMD_MASK_DE | 0x0006)
 
 /* Description: This command signals the cpu that the dat buffer has been
    consumed and ready for re-use.
index 22847a0444f59d051acd3e3d68bcbc2ad6852c50..cbbe47fb87b7a7c6a836f0fee5e2422cb6e41a95 100644 (file)
@@ -508,7 +508,10 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
                /* this setting is read-only for the cx2341x since the
                   V4L2_CID_MPEG_STREAM_TYPE really determines the
                   MPEG-1/2 setting */
-               err = v4l2_ctrl_query_fill_std(qctrl);
+               err = v4l2_ctrl_query_fill(qctrl,
+                                          V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+                                          V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+                                          V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
                if (err == 0)
                        qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
                return err;
index e60bd31b51a359cbc98857383cc76be0cfa0bc51..8c1b7fa47a41cc36f35d3f4c763ff65c190e792c 100644 (file)
@@ -15,6 +15,7 @@ config VIDEO_CX23885
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
        select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
index 7b0e8c01692efab12f289c2fc3f843cdff733548..395c11fa47ceb486206eaf37f44145644762bc31 100644 (file)
@@ -36,7 +36,6 @@
 #include <media/cx2341x.h>
 
 #include "cx23885.h"
-#include "media/cx2341x.h"
 
 #define CX23885_FIRM_IMAGE_SIZE 376836
 #define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -632,7 +631,7 @@ int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
 /* ------------------------------------------------------------------ */
 
 /* MPEG encoder API */
-char *cmd_to_str(int cmd)
+static char *cmd_to_str(int cmd)
 {
        switch (cmd) {
        case CX2341X_ENC_PING_FW:
@@ -1583,6 +1582,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
 
        dprintk(2, "%s()\n", __func__);
 
+       lock_kernel();
        list_for_each(list, &cx23885_devlist) {
                h = list_entry(list, struct cx23885_dev, devlist);
                if (h->v4l_device->minor == minor) {
@@ -1591,13 +1591,17 @@ static int mpeg_open(struct inode *inode, struct file *file)
                }
        }
 
-       if (dev == NULL)
+       if (dev == NULL) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -1608,6 +1612,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx23885_buffer),
                            fh);
+       unlock_kernel();
 
        return 0;
 }
index c36d3f632104a22c37b408805f056ccddec936c8..2cda15f829fdda6fb434b60f78e8b9e78cff22f7 100644 (file)
@@ -26,6 +26,7 @@
 #include <media/cx25840.h>
 
 #include "cx23885.h"
+#include "tuner-xc2028.h"
 
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
@@ -148,6 +149,15 @@ struct cx23885_board cx23885_boards[] = {
                .portb          = CX23885_MPEG_DVB,
                .portc          = CX23885_MPEG_DVB,
        },
+       [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = {
+               .name           = "DViCO FusionHDTV DVB-T Dual Express",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
+               .name           = "Leadtek Winfast PxDVR3200 H",
+               .portc          = CX23885_MPEG_DVB,
+       },
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -219,6 +229,14 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0x18ac,
                .subdevice = 0xd618,
                .card      = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb78,
+               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6681,
+               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -319,15 +337,15 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
                        dev->name, tv.model);
 }
 
-/* Tuner callback function for cx23885 boards. Currently only needed
- * for HVR1500Q, which has an xc5000 tuner.
- */
-int cx23885_tuner_callback(void *priv, int command, int arg)
+int cx23885_tuner_callback(void *priv, int component, int command, int arg)
 {
-       struct cx23885_i2c *bus = priv;
-       struct cx23885_dev *dev = bus->dev;
+       struct cx23885_tsport *port = priv;
+       struct cx23885_dev *dev = port->dev;
        u32 bitmask = 0;
 
+       if (command == XC2028_RESET_CLK)
+               return 0;
+
        if (command != 0) {
                printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
                        __func__, command);
@@ -335,21 +353,21 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
        }
 
        switch(dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+       case CX23885_BOARD_HAUPPAUGE_HVR1500:
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-               /* Tuner Reset Command from xc5000 */
-               if (command == 0)
-                       bitmask = 0x04;
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+               /* Tuner Reset Command */
+               bitmask = 0x04;
                break;
        case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
-               if (command == 0) {
-
-                       /* Two identical tuners on two different i2c buses,
-                        * we need to reset the correct gpio. */
-                       if (bus->nr == 0)
-                               bitmask = 0x01;
-                       else if (bus->nr == 1)
-                               bitmask = 0x04;
-               }
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               /* Two identical tuners on two different i2c buses,
+                * we need to reset the correct gpio. */
+               if (port->nr == 0)
+                       bitmask = 0x01;
+               else if (port->nr == 1)
+                       bitmask = 0x04;
                break;
        }
 
@@ -465,6 +483,32 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                mdelay(20);
                cx_set(GP0_IO, 0x000f000f);
                break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               /* GPIO-0 portb xc3028 reset */
+               /* GPIO-1 portb zl10353 reset */
+               /* GPIO-2 portc xc3028 reset */
+               /* GPIO-3 portc zl10353 reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x000f0000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x0000000f);
+               mdelay(20);
+               cx_set(GP0_IO, 0x000f000f);
+               break;
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+               /* GPIO-2  xc3028 tuner reset */
+
+               /* The following GPIO's are on the internal AVCore (cx25840) */
+               /* GPIO-?  zl10353 demod reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00040000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000004);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00040004);
+               break;
        }
 }
 
@@ -479,6 +523,9 @@ int cx23885_ir_init(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1400:
                /* FIXME: Implement me */
                break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               request_module("ir-kbd-i2c");
+               break;
        }
 
        return 0;
@@ -516,6 +563,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
 
        switch (dev->board) {
        case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
                ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
                ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts2->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -548,6 +596,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1200:
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
        case CX23885_BOARD_HAUPPAUGE_HVR1400:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
        default:
                ts2->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
                ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
@@ -561,6 +610,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_HAUPPAUGE_HVR1800:
        case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
        case CX23885_BOARD_HAUPPAUGE_HVR1700:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
                request_module("cx25840");
                break;
        }
index 25fb09938744b67fdcece9661983e827daeda1db..beb3e61669a3373af706781717081aedf4dfa489 100644 (file)
@@ -1442,7 +1442,7 @@ void cx23885_cancel_buffers(struct cx23885_tsport *port)
        struct cx23885_dev *dev = port->dev;
        struct cx23885_dmaqueue *q = &port->mpegq;
 
-       dprintk(1, "%s()\n", __FUNCTION__);
+       dprintk(1, "%s()\n", __func__);
        del_timer_sync(&q->timeout);
        cx23885_stop_dma(port);
        do_cancel_buffers(port, "cancel", 0);
index 291b9d008da87f17897390b09cbcbf785201d5a1..24bd18327aa0f50b924bdf69527a5e373937c7fb 100644 (file)
@@ -42,6 +42,7 @@
 #include "tuner-simple.h"
 #include "dib7000p.h"
 #include "dibx000_common.h"
+#include "zl10353.h"
 
 static unsigned int debug;
 
@@ -188,13 +189,11 @@ static struct s5h1411_config dvico_s5h1411_config = {
 static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
        .i2c_address      = 0x61,
        .if_khz           = 5380,
-       .tuner_callback   = cx23885_tuner_callback
 };
 
 static struct xc5000_config dvico_xc5000_tunerconfig = {
        .i2c_address      = 0x64,
        .if_khz           = 5380,
-       .tuner_callback   = cx23885_tuner_callback
 };
 
 static struct tda829x_config tda829x_no_probe = {
@@ -303,35 +302,11 @@ static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
        .output_mode = OUTMODE_MPEG2_SERIAL,
 };
 
-static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg)
-{
-       struct cx23885_tsport *port = ptr;
-       struct cx23885_dev *dev = port->dev;
-
-       switch (command) {
-       case XC2028_TUNER_RESET:
-               /* Send the tuner in then out of reset */
-               /* GPIO-2 xc3028 tuner */
-               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
-
-               cx_set(GP0_IO, 0x00040000);
-               cx_clear(GP0_IO, 0x00000004);
-               msleep(5);
-
-               cx_set(GP0_IO, 0x00040004);
-               msleep(5);
-               break;
-       case XC2028_RESET_CLK:
-               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
-               break;
-       default:
-               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
-                       command, arg);
-               return -EINVAL;
-       }
-
-       return 0;
-}
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+       .demod_address = 0x0f,
+       .if2           = 45600,
+       .no_tuner      = 1,
+};
 
 static int dvb_register(struct cx23885_tsport *port)
 {
@@ -413,8 +388,8 @@ static int dvb_register(struct cx23885_tsport *port)
                                                &dev->i2c_bus[0].i2c_adap);
                if (port->dvb.frontend != NULL)
                        dvb_attach(xc5000_attach, port->dvb.frontend,
-                               &i2c_bus->i2c_adap,
-                               &hauppauge_hvr1500q_tunerconfig, i2c_bus);
+                                  &i2c_bus->i2c_adap,
+                                  &hauppauge_hvr1500q_tunerconfig);
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1500:
                i2c_bus = &dev->i2c_bus[1];
@@ -426,10 +401,9 @@ static int dvb_register(struct cx23885_tsport *port)
                        struct xc2028_config cfg = {
                                .i2c_adap  = &i2c_bus->i2c_adap,
                                .i2c_addr  = 0x61,
-                               .callback  = cx23885_hvr1500_xc3028_callback,
                        };
                        static struct xc2028_ctrl ctl = {
-                               .fname       = "xc3028-v27.fw",
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
                                .max_len     = 64,
                                .scode_table = XC3028_FE_OREN538,
                        };
@@ -465,13 +439,13 @@ static int dvb_register(struct cx23885_tsport *port)
                        struct xc2028_config cfg = {
                                .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
                                .i2c_addr  = 0x64,
-                               .callback  = cx23885_hvr1500_xc3028_callback,
                        };
                        static struct xc2028_ctrl ctl = {
-                               .fname   = "xc3028L-v36.fw",
+                               .fname   = XC3028L_DEFAULT_FIRMWARE,
                                .max_len = 64,
                                .demod   = 5000,
-                               .d2633   = 1
+                               /* This is true for all demods with v36 firmware? */
+                               .type    = XC2028_D2633,
                        };
 
                        fe = dvb_attach(xc2028_attach,
@@ -492,8 +466,57 @@ static int dvb_register(struct cx23885_tsport *port)
                                                        &i2c_bus->i2c_adap);
                if (port->dvb.frontend != NULL)
                        dvb_attach(xc5000_attach, port->dvb.frontend,
-                               &i2c_bus->i2c_adap,
-                               &dvico_xc5000_tunerconfig, i2c_bus);
+                                  &i2c_bus->i2c_adap,
+                                  &dvico_xc5000_tunerconfig);
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
+               i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+               port->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &i2c_bus->i2c_adap);
+               if (port->dvb.frontend != NULL) {
+                       struct dvb_frontend      *fe;
+                       struct xc2028_config      cfg = {
+                               .i2c_adap  = &i2c_bus->i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .demod       = XC3028_FE_ZARLINK456,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, port->dvb.frontend,
+                                       &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
+               break;
+       }
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+               i2c_bus = &dev->i2c_bus[0];
+
+               port->dvb.frontend = dvb_attach(zl10353_attach,
+                       &dvico_fusionhdtv_xc3028,
+                       &i2c_bus->i2c_adap);
+               if (port->dvb.frontend != NULL) {
+                       struct dvb_frontend      *fe;
+                       struct xc2028_config      cfg = {
+                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .demod       = XC3028_FE_ZARLINK456,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, port->dvb.frontend,
+                               &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctl);
+               }
                break;
        default:
                printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
@@ -504,6 +527,8 @@ static int dvb_register(struct cx23885_tsport *port)
                printk("%s: frontend initialization failed\n", dev->name);
                return -1;
        }
+       /* define general-purpose callback pointer */
+       port->dvb.frontend->callback = cx23885_tuner_callback;
 
        /* Put the analog decoder in standby to keep it quiet */
        cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL);
index 35e61cd112fc8c09be763df9b14eca51ff26e2ad..5b297f0323b6485a5099a255d9bf8511414db848 100644 (file)
@@ -85,18 +85,8 @@ static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
        return 0;
 }
 
-int cx23885_stop_vbi_dma(struct cx23885_dev *dev)
-{
-       /* stop dma */
-       cx_clear(VID_A_DMA_CTL, 0x00000022);
-
-       /* disable irqs */
-       cx_clear(PCI_INT_MSK, 0x000001);
-       cx_clear(VID_A_INT_MSK, 0x00000022);
-       return 0;
-}
 
-int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
+static int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
                             struct cx23885_dmaqueue *q)
 {
        struct cx23885_buffer *buf;
index 6047c78d84bf5c2b26576e734e73e04f2724eb6c..f75ed1c9b71a28ec3f5791d80139f00c2605e2b0 100644 (file)
@@ -244,7 +244,7 @@ static struct cx23885_ctrl cx23885_ctls[] = {
 };
 static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
 
-const u32 cx23885_user_ctrls[] = {
+static const u32 cx23885_user_ctrls[] = {
        V4L2_CID_USER_CLASS,
        V4L2_CID_BRIGHTNESS,
        V4L2_CID_CONTRAST,
@@ -254,14 +254,13 @@ const u32 cx23885_user_ctrls[] = {
        V4L2_CID_AUDIO_MUTE,
        0
 };
-EXPORT_SYMBOL(cx23885_user_ctrls);
 
 static const u32 *ctrl_classes[] = {
        cx23885_user_ctrls,
        NULL
 };
 
-void cx23885_video_wakeup(struct cx23885_dev *dev,
+static void cx23885_video_wakeup(struct cx23885_dev *dev,
                 struct cx23885_dmaqueue *q, u32 count)
 {
        struct cx23885_buffer *buf;
@@ -296,7 +295,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
                        __func__, bc);
 }
 
-int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
 {
        dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
                __func__,
@@ -314,7 +313,7 @@ int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
        return 0;
 }
 
-struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
                                    struct pci_dev *pci,
                                    struct video_device *template,
                                    char *type)
@@ -334,7 +333,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
        return vfd;
 }
 
-int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
+static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
 {
        int i;
 
@@ -351,7 +350,6 @@ int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
        *qctrl = cx23885_ctls[i].v;
        return 0;
 }
-EXPORT_SYMBOL(cx23885_ctrl_query);
 
 /* ------------------------------------------------------------------- */
 /* resource management                                                 */
@@ -402,7 +400,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
        mutex_unlock(&dev->lock);
 }
 
-int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 {
        struct v4l2_routing route;
        memset(&route, 0, sizeof(route));
@@ -422,10 +420,9 @@ int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 
        return 0;
 }
-EXPORT_SYMBOL(cx23885_video_mux);
 
 /* ------------------------------------------------------------------ */
-int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
+static int cx23885_set_scale(struct cx23885_dev *dev, unsigned int width,
        unsigned int height, enum v4l2_field field)
 {
        dprintk(1, "%s()\n", __func__);
@@ -731,6 +728,7 @@ static int video_open(struct inode *inode, struct file *file)
        enum v4l2_buf_type type = 0;
        int radio = 0;
 
+       lock_kernel();
        list_for_each(list, &cx23885_devlist) {
                h = list_entry(list, struct cx23885_dev, devlist);
                if (h->video_dev->minor == minor) {
@@ -748,16 +746,20 @@ static int video_open(struct inode *inode, struct file *file)
                        dev   = h;
                }
        }
-       if (NULL == dev)
+       if (NULL == dev) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        dprintk(1, "open minor=%d radio=%d type=%s\n",
                minor, radio, v4l2_type_names[type]);
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -775,6 +777,7 @@ static int video_open(struct inode *inode, struct file *file)
 
        dprintk(1, "post videobuf_queue_init()\n");
 
+       unlock_kernel();
 
        return 0;
 }
@@ -884,21 +887,19 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma)
 /* ------------------------------------------------------------------ */
 /* VIDEO CTRL IOCTLS                                                  */
 
-int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
        cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl);
        return 0;
 }
-EXPORT_SYMBOL(cx23885_get_control);
 
-int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
+static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl)
 {
        dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)"
                " (disabled - no action)\n", __func__);
        return 0;
 }
-EXPORT_SYMBOL(cx23885_set_control);
 
 static void init_controls(struct cx23885_dev *dev)
 {
@@ -1146,7 +1147,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
        return 0;
 }
 
-int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
 {
        static const char *iname[] = {
                [CX23885_VMUX_COMPOSITE1] = "Composite1",
@@ -1179,7 +1180,6 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
                i->std = CX23885_NORMS;
        return 0;
 }
-EXPORT_SYMBOL(cx23885_enum_input);
 
 static int vidioc_enum_input(struct file *file, void *priv,
                                struct v4l2_input *i)
@@ -1288,7 +1288,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
        return 0;
 }
 
-int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
+static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
 {
        if (unlikely(UNSET == dev->tuner_type))
                return -EINVAL;
@@ -1307,7 +1307,6 @@ int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
 
        return 0;
 }
-EXPORT_SYMBOL(cx23885_set_freq);
 
 static int vidioc_s_frequency(struct file *file, void *priv,
                                struct v4l2_frequency *f)
index e23d97c071e05d49c2ad15dafc10cc33e15d636a..ba4e0aaed4633985dabe58919afef9dddfb9b228 100644 (file)
@@ -64,6 +64,8 @@
 #define CX23885_BOARD_HAUPPAUGE_HVR1700        8
 #define CX23885_BOARD_HAUPPAUGE_HVR1400        9
 #define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
+#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
 #define CX23885_NORMS (\
@@ -409,7 +411,7 @@ extern const unsigned int cx23885_bcount;
 extern struct cx23885_subid cx23885_subids[];
 extern const unsigned int cx23885_idcount;
 
-extern int cx23885_tuner_callback(void *priv, int command, int arg);
+extern int cx23885_tuner_callback(void *priv, int component, int command, int arg);
 extern void cx23885_card_list(struct cx23885_dev *dev);
 extern int  cx23885_ir_init(struct cx23885_dev *dev);
 extern void cx23885_gpio_setup(struct cx23885_dev *dev);
index 69f2bbdbb929b1a9c41dad93cdfa97caca0d9122..58e6ef1c28a093d849b88f7111f5120a27b9b6aa 100644 (file)
@@ -141,10 +141,11 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                u8 lcr[24];
 
                fmt = arg;
-               if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+               if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
+                   fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
                        return -EINVAL;
                svbi = &fmt->fmt.sliced;
-               if (svbi->service_set == 0) {
+               if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                        /* raw VBI */
                        memset(svbi, 0, sizeof(*svbi));
 
index 9dd7bdf659b96a066d05dee8d6f87d0dcc4e85ed..0b9e5fac6239f5783e0f42e24f8eb9d1c700dfed 100644 (file)
@@ -58,6 +58,10 @@ config VIDEO_CX88_DVB
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_STV0288 if !DVB_FE_CUSTOMISE
+       select DVB_STB6000 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
index 9a1374a38ec75a315463c02e83f5c6ad113b6fb4..e71369754305cdfe21cab45990120115079aafa7 100644 (file)
@@ -1057,12 +1057,15 @@ static int mpeg_open(struct inode *inode, struct file *file)
        struct cx8802_driver *drv = NULL;
        int err;
 
+       lock_kernel();
        dev = cx8802_get_device(inode);
 
        dprintk( 1, "%s\n", __func__);
 
-       if (dev == NULL)
+       if (dev == NULL) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        /* Make sure we can acquire the hardware */
        drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
@@ -1070,6 +1073,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
                err = drv->request_acquire(drv);
                if(err != 0) {
                        dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+                       unlock_kernel();
                        return err;
                }
        }
@@ -1077,6 +1081,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        if (blackbird_initialize_codec(dev) < 0) {
                if (drv)
                        drv->request_release(drv);
+               unlock_kernel();
                return -EINVAL;
        }
        dprintk(1,"open minor=%d\n",minor);
@@ -1086,6 +1091,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        if (NULL == fh) {
                if (drv)
                        drv->request_release(drv);
+               unlock_kernel();
                return -ENOMEM;
        }
        file->private_data = fh;
@@ -1101,6 +1107,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
        /* FIXME: locking against other video device */
        cx88_set_scale(dev->core, dev->width, dev->height,
                        fh->mpegq.field);
+       unlock_kernel();
 
        return 0;
 }
index de199a206a152bdc7e9a9fa381f2c623fd76a775..5da04e811ca20b3941b086e73566c91d081d27e6 100644 (file)
@@ -1349,27 +1349,30 @@ static const struct cx88_board cx88_boards[] = {
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
                .audio_chip     = V4L2_IDENT_WM8775,
+               /*
+                * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
+                */
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
-                       .gpio0  = 0xe780,
+                       .gpio0  = 0xef88,
                        .audioroute = 1,
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
-                       .gpio0  = 0xe780,
+                       .gpio0  = 0xef88,
                        .audioroute = 2,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
-                       .gpio0  = 0xe780,
+                       .gpio0  = 0xef88,
                        .audioroute = 2,
                }},
                /* fixme: Add radio support */
                .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
                .radio = {
                        .type   = CX88_RADIO,
-                       .gpio0  = 0xe780,
+                       .gpio0  = 0xef88,
                },
        },
        [CX88_BOARD_ADSTECH_PTV_390] = {
@@ -1446,15 +1449,26 @@ static const struct cx88_board cx88_boards[] = {
                .name           = "Pinnacle Hybrid PCTV",
                .tuner_type     = TUNER_XC2028,
                .tuner_addr     = 0x61,
+               .radio_type     = TUNER_XC2028,
+               .radio_addr     = 0x61,
                .input          = { {
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x00001,
                }, {
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
                }, {
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
                } },
                .radio = {
                        .type   = CX88_RADIO,
@@ -1462,6 +1476,7 @@ static const struct cx88_board cx88_boards[] = {
                        .gpio1  = 0x010ff,
                        .gpio2  = 0x0ff,
                },
+               .mpeg           = CX88_MPEG_DVB,
        },
        [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
                .name           = "Winfast TV2000 XP Global",
@@ -1566,9 +1581,9 @@ static const struct cx88_board cx88_boards[] = {
        },
        [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
                .name           = "DViCO FusionHDTV DVB-T PRO",
-               .tuner_type     = TUNER_ABSENT, /* XXX: Has XC3028 */
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
                .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .input          = { {
                        .type   = CX88_VMUX_COMPOSITE1,
@@ -1625,6 +1640,36 @@ static const struct cx88_board cx88_boards[] = {
                        .gpio2 = 0x0cfb,
                },
        },
+       [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
+               .name           = "Prolink Pixelview Global Extreme",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cf7,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cfb,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0 = 0x04ff,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cf7,
+               },
+       },
        /* Both radio, analog and ATSC work with this board.
           However, for analog to work, s5h1409 gate should be open,
           otherwise, tuner-xc3028 won't be detected.
@@ -1664,6 +1709,131 @@ static const struct cx88_board cx88_boards[] = {
                },
                .mpeg           = CX88_MPEG_DVB,
        },
+       [CX88_BOARD_HAUPPAUGE_HVR4000] = {
+               .name           = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               /*
+                * GPIO0 (WINTV2000)
+                *
+                * Analogue     SAT     DVB-T
+                * Antenna      0xc4bf  0xc4bb
+                * Composite    0xc4bf  0xc4bb
+                * S-Video      0xc4bf  0xc4bb
+                * Composite1   0xc4ff  0xc4fb
+                * S-Video1     0xc4ff  0xc4fb
+                *
+                * BIT  VALUE   FUNCTION GP{x}_IO
+                * 0    1       I:?
+                * 1    1       I:?
+                * 2    1       O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH
+                * 3    1       I:?
+                * 4    1       I:?
+                * 5    1       I:?
+                * 6    0       O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
+                * 7    1       O:DVB-T DEMOD RESET LOW
+                *
+                * BIT  VALUE   FUNCTION GP{x}_OE
+                * 8    0       I
+                * 9    0       I
+                * a    1       O
+                * b    0       I
+                * c    0       I
+                * d    0       I
+                * e    1       O
+                * f    1       O
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xc4bf,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xc4bf,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xc4bf,
+               } },
+               /* fixme: Add radio support */
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
+               .name           = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TEVII_S420] = {
+               .name           = "TeVii S420 DVB-S",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TEVII_S460] = {
+               .name           = "TeVii S460 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_OMICOM_SS4_PCI] = {
+               .name           = "Omicom SS4 DVB-S/S2 PCI",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TBS_8920] = {
+               .name           = "TBS 8920 DVB-S/S2",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 1,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PROF_7300] = {
+               .name           = "PROF 7300 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
 };
 
 /* ------------------------------------------------------------------ */
@@ -2009,10 +2179,54 @@ static const struct cx88_subid cx88_subids[] = {
                .subvendor = 0x1554,
                .subdevice = 0x4935,
                .card      = CX88_BOARD_PROLINK_PV_8000GT,
+       }, {
+               .subvendor = 0x1554,
+               .subdevice = 0x4976,
+               .card      = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
        }, {
                .subvendor = 0x17de,
                .subdevice = 0x08c1,
                .card      = CX88_BOARD_KWORLD_ATSC_120,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6900,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6904,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6902,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6905,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6906,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+       }, {
+               .subvendor = 0xd420,
+               .subdevice = 0x9022,
+               .card      = CX88_BOARD_TEVII_S420,
+       }, {
+               .subvendor = 0xd460,
+               .subdevice = 0x9022,
+               .card      = CX88_BOARD_TEVII_S460,
+       }, {
+               .subvendor = 0xA044,
+               .subdevice = 0x2011,
+               .card      = CX88_BOARD_OMICOM_SS4_PCI,
+       }, {
+               .subvendor = 0x8920,
+               .subdevice = 0x8888,
+               .card      = CX88_BOARD_TBS_8920,
+       }, {
+               .subvendor = 0xB033,
+               .subdevice = 0x3033,
+               .card      = CX88_BOARD_PROF_7300,
        },
 };
 
@@ -2065,6 +2279,13 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
        case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
        case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
        case 34519: /* WinTV-PCI-FM */
+       case 69009:
+               /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
+       case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
+       case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
+       case 69559:
+               /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
+       case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
        case 90002: /* Nova-T-PCI (9002) */
        case 92001: /* Nova-S-Plus (Video and IR) */
        case 92002: /* Nova-S-Plus (Video and IR) */
@@ -2149,9 +2370,21 @@ static int cx88_dvico_xc2028_callback(struct cx88_core *core,
 {
        switch (command) {
        case XC2028_TUNER_RESET:
-               cx_write(MO_GP0_IO, 0x101000);
-               mdelay(5);
-               cx_set(MO_GP0_IO, 0x101010);
+               switch (core->boardnr) {
+               case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+                       /* GPIO-4 xc3028 tuner */
+
+                       cx_set(MO_GP0_IO, 0x00001000);
+                       cx_clear(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       cx_set(MO_GP0_IO, 0x00000010);
+                       msleep(100);
+                       break;
+               default:
+                       cx_write(MO_GP0_IO, 0x101000);
+                       mdelay(5);
+                       cx_set(MO_GP0_IO, 0x101010);
+               }
                break;
        default:
                return -EINVAL;
@@ -2258,8 +2491,10 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core,
                return cx88_xc3028_geniatech_tuner_callback(core,
                                                        command, arg);
        case CX88_BOARD_PROLINK_PV_8000GT:
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
                return cx88_pv_8000gt_callback(core, command, arg);
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
                return cx88_dvico_xc2028_callback(core, command, arg);
        }
 
@@ -2327,7 +2562,7 @@ static int cx88_xc5000_tuner_callback(struct cx88_core *core,
        return 0; /* Should never be here */
 }
 
-int cx88_tuner_callback(void *priv, int command, int arg)
+int cx88_tuner_callback(void *priv, int component, int command, int arg)
 {
        struct i2c_algo_bit_data *i2c_algo = priv;
        struct cx88_core *core;
@@ -2344,6 +2579,9 @@ int cx88_tuner_callback(void *priv, int command, int arg)
                return -EINVAL;
        }
 
+       if (component != DVB_FRONTEND_COMPONENT_TUNER)
+               return -EINVAL;
+
        switch (core->board.tuner_type) {
                case TUNER_XC2028:
                        info_printk(core, "Calling XC2028/3028 callback\n");
@@ -2392,16 +2630,22 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
 {
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /* Bring the 702 demod up before i2c scanning/attach or devices are hidden */
-               /* We leave here with the 702 on the bus */
-               cx_write(MO_GP0_IO, 0x0000e780);
+               /*
+                * Bring the 702 demod up before i2c scanning/attach or devices are hidden
+                * We leave here with the 702 on the bus
+                *
+                * "reset the IR receiver on GPIO[3]"
+                * Reported by Mike Crash <mike AT mikecrash.com>
+                */
+               cx_write(MO_GP0_IO, 0x0000ef88);
                udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000080);
+               cx_clear(MO_GP0_IO, 0x00000088);
                udelay(50);
-               cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+               cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
                udelay(1000);
                break;
 
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
        case CX88_BOARD_PROLINK_PV_8000GT:
                cx_write(MO_GP2_IO, 0xcf7);
                mdelay(50);
@@ -2411,10 +2655,18 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core)
                msleep(10);
                break;
 
-        case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
                /* Enable the xc5000 tuner */
                cx_set(MO_GP0_IO, 0x00001010);
                break;
+
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+               /* Init GPIO */
+               cx_write(MO_GP0_IO, core->board.input[0].gpio0);
+               udelay(1000);
+               break;
        }
 }
 
@@ -2435,17 +2687,22 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
                        core->i2c_algo.udelay = 16;
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
-               ctl->scode_table = XC3028_FE_ZARLINK456;
+               ctl->demod = XC3028_FE_ZARLINK456;
                break;
        case CX88_BOARD_KWORLD_ATSC_120:
        case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
                ctl->demod = XC3028_FE_OREN538;
                break;
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
        case CX88_BOARD_PROLINK_PV_8000GT:
                /*
-                * This board uses non-MTS firmware
+                * Those boards uses non-MTS firmware
                 */
                break;
+       case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+               ctl->demod = XC3028_FE_ZARLINK456;
+               ctl->mts = 1;
+               break;
        default:
                ctl->demod = XC3028_FE_OREN538;
                ctl->mts = 1;
@@ -2489,6 +2746,8 @@ static void cx88_card_setup(struct cx88_core *core)
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
        case CX88_BOARD_HAUPPAUGE_HVR3000:
        case CX88_BOARD_HAUPPAUGE_HVR1300:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
                if (0 == core->i2c_rc)
                        hauppauge_eeprom(core, eeprom);
                break;
@@ -2570,7 +2829,18 @@ static void cx88_card_setup(struct cx88_core *core)
                tea5767_cfg.priv  = &ctl;
 
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
+               break;
        }
+       case  CX88_BOARD_TEVII_S420:
+       case  CX88_BOARD_TEVII_S460:
+       case  CX88_BOARD_OMICOM_SS4_PCI:
+       case  CX88_BOARD_TBS_8920:
+       case  CX88_BOARD_PROF_7300:
+               cx_write(MO_SRST_IO, 0);
+               msleep(100);
+               cx_write(MO_SRST_IO, 1);
+               msleep(100);
+               break;
        } /*end switch() */
 
 
index d96173ff1dbac4a0096f854cdb0cc8008d4b8f7e..344ed2626e597e3a47c0e0307ee1f5001bae92da 100644 (file)
 #include "tuner-simple.h"
 #include "tda9887.h"
 #include "s5h1411.h"
+#include "stv0299.h"
+#include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "cx24116.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -375,37 +380,28 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
        return 0;
 }
 
-static int cx88_pci_nano_callback(void *ptr, int command, int arg)
+static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
+                                     fe_sec_voltage_t voltage)
 {
-       struct cx88_core *core = ptr;
-
-       switch (command) {
-       case XC2028_TUNER_RESET:
-               /* Send the tuner in then out of reset */
-               dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __func__, arg);
-
-               switch (core->boardnr) {
-               case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
-                       /* GPIO-4 xc3028 tuner */
-
-                       cx_set(MO_GP0_IO, 0x00001000);
-                       cx_clear(MO_GP0_IO, 0x00000010);
-                       msleep(100);
-                       cx_set(MO_GP0_IO, 0x00000010);
-                       msleep(100);
-                       break;
-               }
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
 
-               break;
-       case XC2028_RESET_CLK:
-               dprintk(1, "%s: XC2028_RESET_CLK %d\n", __func__, arg);
-               break;
-       default:
-               dprintk(1, "%s: unknown command %d, arg %d\n", __func__,
-                       command, arg);
-               return -EINVAL;
+       switch (voltage) {
+               case SEC_VOLTAGE_13:
+                       printk("LNB Voltage SEC_VOLTAGE_13\n");
+                       cx_write(MO_GP0_IO, 0x00006040);
+                       break;
+               case SEC_VOLTAGE_18:
+                       printk("LNB Voltage SEC_VOLTAGE_18\n");
+                       cx_write(MO_GP0_IO, 0x00006060);
+                       break;
+               case SEC_VOLTAGE_OFF:
+                       printk("LNB Voltage SEC_VOLTAGE_off\n");
+                       break;
        }
 
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
        return 0;
 }
 
@@ -456,7 +452,12 @@ static struct s5h1409_config kworld_atsc_120_config = {
 static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
        .i2c_address    = 0x64,
        .if_khz         = 5380,
-       .tuner_callback = cx88_tuner_callback,
+};
+
+static struct zl10353_config cx88_pinnacle_hybrid_pctv = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner      = 1,
+       .if2           = 45600,
 };
 
 static struct zl10353_config cx88_geniatech_x8000_mt = {
@@ -477,7 +478,6 @@ static struct s5h1411_config dvico_fusionhdtv7_config = {
 static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
        .i2c_address    = 0xc2 >> 1,
        .if_khz         = 5380,
-       .tuner_callback = cx88_tuner_callback,
 };
 
 static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
@@ -488,7 +488,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
                .i2c_adap  = &dev->core->i2c_adap,
                .i2c_addr  = addr,
                .ctrl      = &ctl,
-               .callback  = cx88_tuner_callback,
        };
 
        if (!dev->dvb.frontend) {
@@ -518,6 +517,60 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
        return 0;
 }
 
+static int cx24116_set_ts_param(struct dvb_frontend *fe,
+       int is_punctured)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       dev->ts_gen_cntrl = 0x2;
+
+       return 0;
+}
+
+static int cx24116_reset_device(struct dvb_frontend *fe)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       /* Reset the part */
+       cx_write(MO_SRST_IO, 0);
+       msleep(10);
+       cx_write(MO_SRST_IO, 1);
+       msleep(10);
+
+       return 0;
+}
+
+static struct cx24116_config hauppauge_hvr4000_config = {
+       .demod_address          = 0x05,
+       .set_ts_params          = cx24116_set_ts_param,
+       .reset_device           = cx24116_reset_device,
+};
+
+static struct cx24116_config tevii_s460_config = {
+       .demod_address = 0x55,
+       .set_ts_params = cx24116_set_ts_param,
+       .reset_device  = cx24116_reset_device,
+};
+
+static struct stv0299_config tevii_tuner_sharp_config = {
+       .demod_address = 0x68,
+       .inittab = sharp_z0194a__inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .skip_reinit = 0,
+       .lock_output = 1,
+       .volt13_op0_op1 = STV0299_VOLT13_OP1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = sharp_z0194a__set_symbol_rate,
+       .set_ts_params = cx24116_set_ts_param,
+};
+
+static struct stv0288_config tevii_tuner_earda_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+       .set_ts_params = cx24116_set_ts_param,
+};
+
 static int dvb_register(struct cx8802_dev *dev)
 {
        struct cx88_core *core = dev->core;
@@ -786,7 +839,7 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &core->i2c_adap);
                if (dev->dvb.frontend) {
                        if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
-                                       &core->i2c_adap, 0x08, 0x00, 0x00))
+                                       &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
                                goto frontend_detach;
                }
                break;
@@ -813,13 +866,9 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &pinnacle_pctv_hd_800i_config,
                                               &core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       /* tuner_config.video_dev must point to
-                        * i2c_adap.algo_data
-                        */
                        if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
                                        &core->i2c_adap,
-                                       &pinnacle_pctv_hd_800i_tuner_config,
-                                       core->i2c_adap.algo_data))
+                                       &pinnacle_pctv_hd_800i_tuner_config))
                                goto frontend_detach;
                }
                break;
@@ -832,10 +881,9 @@ static int dvb_register(struct cx8802_dev *dev)
                        struct xc2028_config cfg = {
                                .i2c_adap  = &core->i2c_adap,
                                .i2c_addr  = 0x61,
-                               .callback  = cx88_pci_nano_callback,
                        };
                        static struct xc2028_ctrl ctl = {
-                               .fname       = "xc3028-v27.fw",
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
                                .max_len     = 64,
                                .scode_table = XC3028_FE_OREN538,
                        };
@@ -848,10 +896,13 @@ static int dvb_register(struct cx8802_dev *dev)
                break;
         case CX88_BOARD_PINNACLE_HYBRID_PCTV:
                dev->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &cx88_geniatech_x8000_mt,
+                                              &cx88_pinnacle_hybrid_pctv,
                                               &core->i2c_adap);
-               if (attach_xc3028(0x61, dev) < 0)
-                       goto frontend_detach;
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+                       if (attach_xc3028(0x61, dev) < 0)
+                               goto frontend_detach;
+               }
                break;
         case CX88_BOARD_GENIATECH_X8000_MT:
                dev->ts_gen_cntrl = 0x00;
@@ -874,16 +925,69 @@ static int dvb_register(struct cx8802_dev *dev)
                                               &dvico_fusionhdtv7_config,
                                               &core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       /* tuner_config.video_dev must point to
-                        * i2c_adap.algo_data
-                        */
                        if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
                                        &core->i2c_adap,
-                                       &dvico_fusionhdtv7_tuner_config,
-                                       core->i2c_adap.algo_data))
+                                       &dvico_fusionhdtv7_tuner_config))
                                goto frontend_detach;
                }
                break;
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+               /* Support for DVB-S only, not DVB-T support */
+               dev->dvb.frontend = dvb_attach(cx24116_attach,
+                       &hauppauge_hvr4000_config,
+                       &dev->core->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dvb_attach(isl6421_attach, dev->dvb.frontend,
+                               &dev->core->i2c_adap,
+                               0x08, ISL6421_DCL, 0x00);
+               }
+               break;
+       case CX88_BOARD_TEVII_S420:
+               dev->dvb.frontend = dvb_attach(stv0299_attach,
+                                               &tevii_tuner_sharp_config,
+                                               &core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+                                       &core->i2c_adap, DVB_PLL_OPERA1))
+                               goto frontend_detach;
+                       core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+                       dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+               } else {
+                       dev->dvb.frontend = dvb_attach(stv0288_attach,
+                                                           &tevii_tuner_earda_config,
+                                                           &core->i2c_adap);
+                               if (dev->dvb.frontend != NULL) {
+                                       if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61,
+                                               &core->i2c_adap))
+                                       goto frontend_detach;
+                               core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+                               dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+                       }
+               }
+               break;
+       case CX88_BOARD_TEVII_S460:
+               dev->dvb.frontend = dvb_attach(cx24116_attach,
+                                              &tevii_s460_config,
+                                              &core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+                       dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+               }
+               break;
+       case CX88_BOARD_OMICOM_SS4_PCI:
+       case CX88_BOARD_TBS_8920:
+       case CX88_BOARD_PROF_7300:
+               dev->dvb.frontend = dvb_attach(cx24116_attach,
+                                              &hauppauge_hvr4000_config,
+                                              &core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+                       dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+               }
+               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
                       core->name);
@@ -895,6 +999,8 @@ static int dvb_register(struct cx8802_dev *dev)
                       core->name);
                return -EINVAL;
        }
+       /* define general-purpose callback pointer */
+       dev->dvb.frontend->callback = cx88_tuner_callback;
 
        /* Ensure all frontends negotiate bus access */
        dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
index d7406a994f094942924b3726e3b41ba31ac1f19b..8e74d64fdcd2e5324e38af6db7002341154e3d8d 100644 (file)
@@ -201,7 +201,23 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
 
        core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
        if (0 == core->i2c_rc) {
+               static u8 tuner_data[] =
+                       { 0x0b, 0xdc, 0x86, 0x52 };
+               static struct i2c_msg tuner_msg =
+                       { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
+
                dprintk(1, "i2c register ok\n");
+               switch( core->boardnr ) {
+                       case CX88_BOARD_HAUPPAUGE_HVR1300:
+                       case CX88_BOARD_HAUPPAUGE_HVR3000:
+                       case CX88_BOARD_HAUPPAUGE_HVR4000:
+                               printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
+                                       core->name);
+                               i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
+                               break;
+                       default:
+                               break;
+               }
                if (i2c_scan)
                        do_i2c_scan(core->name,&core->i2c_client);
        } else
index 53526d997a4e97923231ead7736fa2f9c9c089cf..8683d104de72a4113587bff03440d38749ce048b 100644 (file)
@@ -224,6 +224,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
                ir_codes = ir_codes_hauppauge_new;
                ir_type = IR_TYPE_RC5;
                ir->sampling = 1;
@@ -259,6 +261,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->polling = 1; /* ms */
                break;
        case CX88_BOARD_PROLINK_PV_8000GT:
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
                ir_codes = ir_codes_pixelview_new;
                ir->gpio_addr = MO_GP1_IO;
                ir->mask_keycode = 0x3f;
@@ -392,7 +395,7 @@ void cx88_ir_irq(struct cx88_core *core)
 {
        struct cx88_IR *ir = core->ir;
        u32 samples, ircode;
-       int i;
+       int i, start, range, toggle, dev, code;
 
        if (NULL == ir)
                return;
@@ -461,6 +464,34 @@ void cx88_ir_irq(struct cx88_core *core)
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+               ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+               ir_dprintk("biphase decoded: %x\n", ircode);
+               /*
+                * RC5 has an extension bit which adds a new range
+                * of available codes, this is detected here. Also
+                * hauppauge remotes (black/silver) always use
+                * specific device ids. If we do not filter the
+                * device ids then messages destined for devices
+                * such as TVs (id=0) will get through to the
+                * device causing mis-fired events.
+                */
+               /* split rc5 data block ... */
+               start = (ircode & 0x2000) >> 13;
+               range = (ircode & 0x1000) >> 12;
+               toggle= (ircode & 0x0800) >> 11;
+               dev   = (ircode & 0x07c0) >> 6;
+               code  = (ircode & 0x003f) | ((range << 6) ^ 0x0040);
+               if( start != 1)
+                       /* no key pressed */
+                       break;
+               if ( dev != 0x1e && dev != 0x1f )
+                       /* not a hauppauge remote */
+                       break;
+               ir_input_keydown(ir->input, &ir->ir, code, ircode);
+               ir->release = jiffies + msecs_to_jiffies(120);
+               break;
        case CX88_BOARD_PINNACLE_PCTV_HD_800i:
                ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
                ir_dprintk("biphase decoded: %x\n", ircode);
index ef4d56ea00278bf4183ac932fd7f46edda8b1618..be45955dff686ebb38d598c8fb7e86d62ef6ca2f 100644 (file)
@@ -773,6 +773,7 @@ static int video_open(struct inode *inode, struct file *file)
        enum v4l2_buf_type type = 0;
        int radio = 0;
 
+       lock_kernel();
        list_for_each_entry(h, &cx8800_devlist, devlist) {
                if (h->video_dev->minor == minor) {
                        dev  = h;
@@ -788,8 +789,10 @@ static int video_open(struct inode *inode, struct file *file)
                        dev   = h;
                }
        }
-       if (NULL == dev)
+       if (NULL == dev) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        core = dev->core;
 
@@ -798,8 +801,10 @@ static int video_open(struct inode *inode, struct file *file)
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -832,6 +837,9 @@ static int video_open(struct inode *inode, struct file *file)
                cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
                cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
        }
+       unlock_kernel();
+
+       atomic_inc(&core->users);
 
        return 0;
 }
@@ -920,7 +928,8 @@ static int video_release(struct inode *inode, struct file *file)
        file->private_data = NULL;
        kfree(fh);
 
-       cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+       if(atomic_dec_and_test(&dev->core->users))
+               cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
        return 0;
 }
index 54fe650947115e490c6334ff489451e5f98576ca..dbf01b8b57a52876b0cfe7ae67f4e3665f6c0a1d 100644 (file)
@@ -221,6 +221,14 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
 #define CX88_BOARD_PROLINK_PV_8000GT       66
 #define CX88_BOARD_KWORLD_ATSC_120         67
+#define CX88_BOARD_HAUPPAUGE_HVR4000       68
+#define CX88_BOARD_HAUPPAUGE_HVR4000LITE   69
+#define CX88_BOARD_TEVII_S460              70
+#define CX88_BOARD_OMICOM_SS4_PCI          71
+#define CX88_BOARD_TBS_8920                72
+#define CX88_BOARD_TEVII_S420              73
+#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
+#define CX88_BOARD_PROF_7300               75
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -342,6 +350,7 @@ struct cx88_core {
        struct mutex               lock;
        /* various v4l controls */
        u32                        freq;
+       atomic_t                   users;
 
        /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
        struct cx8802_dev          *dvbdev;
@@ -601,7 +610,7 @@ extern void cx88_call_i2c_clients(struct cx88_core *core,
 /* ----------------------------------------------------------- */
 /* cx88-cards.c                                                */
 
-extern int cx88_tuner_callback(void *dev, int command, int arg);
+extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
 extern int cx88_get_resources(const struct cx88_core *core,
                              struct pci_dev *pci);
 extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
index 79faedf585217f0e5cda3ac6902ce567dc9918c7..3aa538afcc0b3ab2343c2c29833cfe02621370f3 100644 (file)
@@ -866,7 +866,8 @@ static int __init dabusb_init (void)
 
        dbg("dabusb_init: driver registered");
 
-       info(DRIVER_VERSION ":" DRIVER_DESC);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
 
 out:
        return retval;
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
deleted file mode 100644 (file)
index 88d6df7..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
-    dpc7146.c - v4l2 driver for the dpc7146 demonstration board
-
-    Copyright (C) 2000-2003 Michael Hunold <michael@mihu.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#define DEBUG_VARIABLE debug
-
-#include <media/saa7146_vv.h>
-#include <linux/video_decoder.h>       /* for saa7111a */
-
-#define I2C_SAA7111A            0x24
-
-/* All unused bytes are reserverd. */
-#define SAA711X_CHIP_VERSION            0x00
-#define SAA711X_ANALOG_INPUT_CONTROL_1  0x02
-#define SAA711X_ANALOG_INPUT_CONTROL_2  0x03
-#define SAA711X_ANALOG_INPUT_CONTROL_3  0x04
-#define SAA711X_ANALOG_INPUT_CONTROL_4  0x05
-#define SAA711X_HORIZONTAL_SYNC_START   0x06
-#define SAA711X_HORIZONTAL_SYNC_STOP    0x07
-#define SAA711X_SYNC_CONTROL            0x08
-#define SAA711X_LUMINANCE_CONTROL       0x09
-#define SAA711X_LUMINANCE_BRIGHTNESS    0x0A
-#define SAA711X_LUMINANCE_CONTRAST      0x0B
-#define SAA711X_CHROMA_SATURATION       0x0C
-#define SAA711X_CHROMA_HUE_CONTROL      0x0D
-#define SAA711X_CHROMA_CONTROL          0x0E
-#define SAA711X_FORMAT_DELAY_CONTROL    0x10
-#define SAA711X_OUTPUT_CONTROL_1        0x11
-#define SAA711X_OUTPUT_CONTROL_2        0x12
-#define SAA711X_OUTPUT_CONTROL_3        0x13
-#define SAA711X_V_GATE_1_START          0x15
-#define SAA711X_V_GATE_1_STOP           0x16
-#define SAA711X_V_GATE_1_MSB            0x17
-#define SAA711X_TEXT_SLICER_STATUS      0x1A
-#define SAA711X_DECODED_BYTES_OF_TS_1   0x1B
-#define SAA711X_DECODED_BYTES_OF_TS_2   0x1C
-#define SAA711X_STATUS_BYTE             0x1F
-
-#define DPC_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "debug verbosity");
-
-static int dpc_num;
-
-#define DPC_INPUTS     2
-static struct v4l2_input dpc_inputs[DPC_INPUTS] = {
-       { 0, "Port A",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-       { 1, "Port B",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
-};
-
-#define DPC_AUDIOS     0
-
-static struct saa7146_extension_ioctls ioctls[] = {
-       { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
-       { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
-       { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
-       { VIDIOC_S_STD,         SAA7146_AFTER },
-       { 0,                    0 }
-};
-
-struct dpc
-{
-       struct video_device     *video_dev;
-       struct video_device     *vbi_dev;
-
-       struct i2c_adapter      i2c_adapter;
-       struct i2c_client       *saa7111a;
-
-       int cur_input;  /* current input */
-};
-
-static int dpc_check_clients(struct device *dev, void *data)
-{
-       struct dpc* dpc = data;
-       struct i2c_client *client = i2c_verify_client(dev);
-
-       if( !client )
-               return 0;
-
-       if( I2C_SAA7111A == client->addr )
-               dpc->saa7111a = client;
-
-       return 0;
-}
-
-/* fixme: add vbi stuff here */
-static int dpc_probe(struct saa7146_dev* dev)
-{
-       struct dpc* dpc = NULL;
-
-       dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
-       if( NULL == dpc ) {
-               printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
-               return -ENOMEM;
-       }
-
-       /* FIXME: enable i2c-port pins, video-port-pins
-          video port pins should be enabled here ?! */
-       saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
-
-       dpc->i2c_adapter = (struct i2c_adapter) {
-               .class = I2C_CLASS_TV_ANALOG,
-               .name = "dpc7146",
-       };
-       saa7146_i2c_adapter_prepare(dev, &dpc->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
-       if(i2c_add_adapter(&dpc->i2c_adapter) < 0) {
-               DEB_S(("cannot register i2c-device. skipping.\n"));
-               kfree(dpc);
-               return -EFAULT;
-       }
-
-       /* loop through all i2c-devices on the bus and look who is there */
-       device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients);
-
-       /* check if all devices are present */
-       if (!dpc->saa7111a) {
-               DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));
-               i2c_del_adapter(&dpc->i2c_adapter);
-               kfree(dpc);
-               return -ENODEV;
-       }
-
-       /* all devices are present, probe was successful */
-       DEB_D(("dpc_v4l2.o: dpc_probe succeeded for this device.\n"));
-
-       /* we store the pointer in our private data field */
-       dev->ext_priv = dpc;
-
-       return 0;
-}
-
-/* bring hardware to a sane state. this has to be done, just in case someone
-   wants to capture from this device before it has been properly initialized.
-   the capture engine would badly fail, because no valid signal arrives on the
-   saa7146, thus leading to timeouts and stuff. */
-static int dpc_init_done(struct saa7146_dev* dev)
-{
-       struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
-       DEB_D(("dpc_v4l2.o: dpc_init_done called.\n"));
-
-       /* initialize the helper ics to useful values */
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x00, 0x11);
-
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x02, 0xc0);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x03, 0x30);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x04, 0x00);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x05, 0x00);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x06, 0xde);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x07, 0xad);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x08, 0xa8);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x09, 0x00);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x0a, 0x80);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x0b, 0x47);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x0c, 0x40);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x0d, 0x00);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x0e, 0x03);
-
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x10, 0xd0);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x11, 0x1c);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x12, 0xc1);
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x13, 0x30);
-
-       i2c_smbus_write_byte_data(dpc->saa7111a, 0x1f, 0x81);
-
-       return 0;
-}
-
-static struct saa7146_ext_vv vv_data;
-
-/* this function only gets called when the probing was successful */
-static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
-{
-       struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
-       DEB_D(("dpc_v4l2.o: dpc_attach called.\n"));
-
-       /* checking for i2c-devices can be omitted here, because we
-          already did this in "dpc_vl42_probe" */
-
-       saa7146_vv_init(dev,&vv_data);
-       if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
-               ERR(("cannot register capture v4l2 device. skipping.\n"));
-               return -1;
-       }
-
-       /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
-       if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
-               if( 0 != saa7146_register_device(&dpc->vbi_dev, dev, "dpc", VFL_TYPE_VBI)) {
-                       ERR(("cannot register vbi v4l2 device. skipping.\n"));
-               }
-       }
-
-       i2c_use_client(dpc->saa7111a);
-
-       printk("dpc: found 'dpc7146 demonstration board'-%d.\n",dpc_num);
-       dpc_num++;
-
-       /* the rest */
-       dpc->cur_input = 0;
-       dpc_init_done(dev);
-
-       return 0;
-}
-
-static int dpc_detach(struct saa7146_dev* dev)
-{
-       struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
-       DEB_EE(("dev:%p\n",dev));
-
-       i2c_release_client(dpc->saa7111a);
-
-       saa7146_unregister_device(&dpc->video_dev,dev);
-       if( 0 != DPC_BOARD_CAN_DO_VBI(dev)) {
-               saa7146_unregister_device(&dpc->vbi_dev,dev);
-       }
-       saa7146_vv_release(dev);
-
-       dpc_num--;
-
-       i2c_del_adapter(&dpc->i2c_adapter);
-       kfree(dpc);
-       return 0;
-}
-
-#ifdef axa
-int dpc_vbi_bypass(struct saa7146_dev* dev)
-{
-       struct dpc* dpc = (struct dpc*)dev->ext_priv;
-
-       int i = 1;
-
-       /* switch bypass in saa7111a */
-       if ( 0 != dpc->saa7111a->driver->command(dpc->saa7111a,SAA711X_VBI_BYPASS, &i)) {
-               printk("dpc_v4l2.o: VBI_BYPASS: could not address saa7111a.\n");
-               return -1;
-       }
-
-       return 0;
-}
-#endif
-
-static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
-{
-       struct saa7146_dev *dev = fh->dev;
-       struct dpc* dpc = (struct dpc*)dev->ext_priv;
-/*
-       struct saa7146_vv *vv = dev->vv_data;
-*/
-       switch(cmd)
-       {
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input *i = arg;
-               DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
-
-               if( i->index < 0 || i->index >= DPC_INPUTS) {
-                       return -EINVAL;
-               }
-
-               memcpy(i, &dpc_inputs[i->index], sizeof(struct v4l2_input));
-
-               DEB_D(("dpc_v4l2.o: v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n",i->index));
-               return 0;
-       }
-       case VIDIOC_G_INPUT:
-       {
-               int *input = (int *)arg;
-               *input = dpc->cur_input;
-
-               DEB_D(("dpc_v4l2.o: VIDIOC_G_INPUT: %d\n",*input));
-               return 0;
-       }
-       case VIDIOC_S_INPUT:
-       {
-               int     input = *(int *)arg;
-
-               if (input < 0 || input >= DPC_INPUTS) {
-                       return -EINVAL;
-               }
-
-               dpc->cur_input = input;
-
-               /* fixme: switch input here, switch audio, too! */
-//             saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
-               printk("dpc_v4l2.o: VIDIOC_S_INPUT: fixme switch input.\n");
-
-               return 0;
-       }
-       default:
-/*
-               DEB_D(("dpc_v4l2.o: v4l2_ioctl does not handle this ioctl.\n"));
-*/
-               return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
-{
-       return 0;
-}
-
-static struct saa7146_standard standard[] = {
-       {
-               .name   = "PAL",        .id     = V4L2_STD_PAL,
-               .v_offset       = 0x17, .v_field        = 288,
-               .h_offset       = 0x14, .h_pixels       = 680,
-               .v_max_out      = 576,  .h_max_out      = 768,
-       }, {
-               .name   = "NTSC",       .id     = V4L2_STD_NTSC,
-               .v_offset       = 0x16, .v_field        = 240,
-               .h_offset       = 0x06, .h_pixels       = 708,
-               .v_max_out      = 480,  .h_max_out      = 640,
-       }, {
-               .name   = "SECAM",      .id     = V4L2_STD_SECAM,
-               .v_offset       = 0x14, .v_field        = 288,
-               .h_offset       = 0x14, .h_pixels       = 720,
-               .v_max_out      = 576,  .h_max_out      = 768,
-       }
-};
-
-static struct saa7146_extension extension;
-
-static struct saa7146_pci_extension_data dpc = {
-       .ext_priv = "Multimedia eXtension Board",
-       .ext = &extension,
-};
-
-static struct pci_device_id pci_tbl[] = {
-       {
-               .vendor    = PCI_VENDOR_ID_PHILIPS,
-               .device    = PCI_DEVICE_ID_PHILIPS_SAA7146,
-               .subvendor = 0x0000,
-               .subdevice = 0x0000,
-               .driver_data = (unsigned long)&dpc,
-       }, {
-               .vendor = 0,
-       }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_ext_vv vv_data = {
-       .inputs         = DPC_INPUTS,
-       .capabilities   = V4L2_CAP_VBI_CAPTURE,
-       .stds           = &standard[0],
-       .num_stds       = sizeof(standard)/sizeof(struct saa7146_standard),
-       .std_callback   = &std_callback,
-       .ioctls         = &ioctls[0],
-       .ioctl          = dpc_ioctl,
-};
-
-static struct saa7146_extension extension = {
-       .name           = "dpc7146 demonstration board",
-       .flags          = SAA7146_USE_I2C_IRQ,
-
-       .pci_tbl        = &pci_tbl[0],
-       .module         = THIS_MODULE,
-
-       .probe          = dpc_probe,
-       .attach         = dpc_attach,
-       .detach         = dpc_detach,
-
-       .irq_mask       = 0,
-       .irq_func       = NULL,
-};
-
-static int __init dpc_init_module(void)
-{
-       if( 0 != saa7146_register_extension(&extension)) {
-               DEB_S(("failed to register extension.\n"));
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static void __exit dpc_cleanup_module(void)
-{
-       saa7146_unregister_extension(&extension);
-}
-
-module_init(dpc_init_module);
-module_exit(dpc_cleanup_module);
-
-MODULE_DESCRIPTION("video4linux-2 driver for the 'dpc7146 demonstration board'");
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_LICENSE("GPL");
index de943cf6c169aa58eb5eb319cab4f0909a2fe27d..d65d0572403bbd29f77675bcaf995284e0cdd466 100644 (file)
@@ -1101,7 +1101,7 @@ struct usb_device_id em28xx_id_table [] = {
        { USB_DEVICE(0xeb1a, 0x2820),
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2821),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
+                       .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 },
        { USB_DEVICE(0xeb1a, 0x2860),
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2861),
@@ -1271,7 +1271,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
        {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
 };
 
-int em28xx_tuner_callback(void *ptr, int command, int arg)
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
 {
        int rc = 0;
        struct em28xx *dev = ptr;
index d2b1a1a52689f57fe5d9b423887d0c169818f347..c99e2383b7ec994cf92532bd2135812ecdda822d 100644 (file)
@@ -249,7 +249,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
        memset(&cfg, 0, sizeof(cfg));
        cfg.i2c_adap  = &dev->i2c_adap;
        cfg.i2c_addr  = addr;
-       cfg.callback  = em28xx_tuner_callback;
 
        if (!dev->dvb->frontend) {
                printk(KERN_ERR "%s/2: dvb frontend not attached. "
@@ -274,7 +273,7 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
 
 /* ------------------------------------------------------------------ */
 
-int register_dvb(struct em28xx_dvb *dvb,
+static int register_dvb(struct em28xx_dvb *dvb,
                 struct module *module,
                 struct em28xx *dev,
                 struct device *device)
@@ -422,6 +421,8 @@ static int dvb_init(struct em28xx *dev)
                }
                break;
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2880_BOARD_KWORLD_DVB_310U:
                dvb->frontend = dvb_attach(zl10353_attach,
                                           &em28xx_zl10353_with_xc3028,
                                           &dev->i2c_adap);
@@ -443,24 +444,6 @@ static int dvb_init(struct em28xx *dev)
                }
                break;
 #endif
-       case EM2880_BOARD_TERRATEC_HYBRID_XS:
-               dvb->frontend = dvb_attach(zl10353_attach,
-                                               &em28xx_zl10353_with_xc3028,
-                                               &dev->i2c_adap);
-               if (attach_xc3028(0x61, dev) < 0) {
-                        result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2880_BOARD_KWORLD_DVB_310U:
-               dvb->frontend = dvb_attach(zl10353_attach,
-                                               &em28xx_zl10353_with_xc3028,
-                                               &dev->i2c_adap);
-               if (attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
        default:
                printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
                                " isn't supported yet\n",
@@ -474,6 +457,8 @@ static int dvb_init(struct em28xx *dev)
                result = -EINVAL;
                goto out_free;
        }
+       /* define general-purpose callback pointer */
+       dvb->frontend->callback = em28xx_tuner_callback;
 
        /* register everything */
        result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
index 97853384c9436f0d198d668bb3cdca789125e5ae..3bab56b997fc391033b47e262f6d72855d11e15b 100644 (file)
@@ -143,10 +143,11 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
        }
        for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
             write_timeout -= 5) {
-               unsigned msg = dev->em28xx_read_reg(dev, 0x5);
-               if (msg == 0x94)
+               unsigned reg = dev->em28xx_read_reg(dev, 0x5);
+
+               if (reg == 0x94)
                        return -ENODEV;
-               else if (msg == 0x84)
+               else if (reg == 0x84)
                        return 0;
                msleep(5);
        }
@@ -335,8 +336,11 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
 
        /* Check if board has eeprom */
        err = i2c_master_recv(&dev->i2c_client, &buf, 0);
-       if (err < 0)
-               return -1;
+       if (err < 0) {
+               em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n",
+                       __func__, err);
+               return err;
+       }
 
        buf = 0;
 
@@ -344,7 +348,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
        if (err != 1) {
                printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
                       dev->name, err);
-               return -1;
+               return err;
        }
        while (size > 0) {
                if (size > 16)
@@ -357,7 +361,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
                        printk(KERN_WARNING
                               "%s: i2c eeprom read error (err=%d)\n",
                               dev->name, err);
-                       return -1;
+                       return err;
                }
                size -= block;
                p += block;
@@ -585,18 +589,31 @@ void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg)
  */
 int em28xx_i2c_register(struct em28xx *dev)
 {
+       int retval;
+
        BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
        BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
        dev->i2c_adap = em28xx_adap_template;
        dev->i2c_adap.dev.parent = &dev->udev->dev;
        strcpy(dev->i2c_adap.name, dev->name);
        dev->i2c_adap.algo_data = dev;
-       i2c_add_adapter(&dev->i2c_adap);
+
+       retval = i2c_add_adapter(&dev->i2c_adap);
+       if (retval < 0) {
+               em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
+                       __func__, retval);
+               return retval;
+       }
 
        dev->i2c_client = em28xx_client_template;
        dev->i2c_client.adapter = &dev->i2c_adap;
 
-       em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+       retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+       if (retval < 0) {
+               em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
+                       __func__, retval);
+               return retval;
+       }
 
        if (i2c_scan)
                em28xx_do_i2c_scan(dev);
index 49ab0629702e289bb2a8360a00c0703e3d60f694..c53649e5315b0a815cd09633578dfcea263b41cd 100644 (file)
@@ -513,10 +513,17 @@ static struct videobuf_queue_ops em28xx_video_qops = {
  */
 static int em28xx_config(struct em28xx *dev)
 {
+       int retval;
 
        /* Sets I2C speed to 100 KHz */
-       if (!dev->is_em2800)
-               em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1);
+       if (!dev->is_em2800) {
+               retval = em28xx_write_regs_req(dev, 0x00, 0x06, "\x40", 1);
+               if (retval < 0) {
+                       em28xx_errdev("%s: em28xx_write_regs_req failed! retval [%d]\n",
+                               __func__, retval);
+                       return retval;
+               }
+       }
 
        /* enable vbi capturing */
 
@@ -1512,6 +1519,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
        struct em28xx_fh *fh;
        enum v4l2_buf_type fh_type = 0;
 
+       lock_kernel();
        list_for_each_entry(h, &em28xx_devlist, devlist) {
                if (h->vdev->minor == minor) {
                        dev  = h;
@@ -1527,8 +1535,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
                        dev   = h;
                }
        }
-       if (NULL == dev)
+       if (NULL == dev) {
+               unlock_kernel();
                return -ENODEV;
+       }
 
        em28xx_videodbg("open minor=%d type=%s users=%d\n",
                                minor, v4l2_type_names[fh_type], dev->users);
@@ -1537,6 +1547,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
        fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
        if (!fh) {
                em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+               unlock_kernel();
                return -ENOMEM;
        }
        mutex_lock(&dev->lock);
@@ -1573,6 +1584,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
                        sizeof(struct em28xx_buffer), fh);
 
        mutex_unlock(&dev->lock);
+       unlock_kernel();
 
        return errCode;
 }
@@ -1588,8 +1600,7 @@ static void em28xx_release_resources(struct em28xx *dev)
        /*FIXME: I2C IR should be disconnected */
 
        em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n",
-                               dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
-                               dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
+                               dev->vdev->num, dev->vbi_dev->num);
        list_del(&dev->devlist);
        if (dev->sbutton_input_dev)
                em28xx_deregister_snapshot_button(dev);
@@ -1948,13 +1959,23 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        }
 
        /* register i2c bus */
-       em28xx_i2c_register(dev);
+       errCode = em28xx_i2c_register(dev);
+       if (errCode < 0) {
+               em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
 
        /* Do board specific init and eeprom reading */
        em28xx_card_setup(dev);
 
        /* Configure audio */
-       em28xx_audio_analog_set(dev);
+       errCode = em28xx_audio_analog_set(dev);
+       if (errCode < 0) {
+               em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
 
        /* configure the device */
        em28xx_config_i2c(dev);
@@ -1974,6 +1995,11 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->ctl_input = 2;
 
        errCode = em28xx_config(dev);
+       if (errCode < 0) {
+               em28xx_errdev("%s: em28xx_config - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
 
        list_add_tail(&dev->devlist, &em28xx_devlist);
 
@@ -2026,17 +2052,27 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
 
        if (dev->has_msp34xx) {
                /* Send a reset to other chips via gpio */
-               em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
+               errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);
+               if (errCode < 0) {
+                       em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n",
+                               __func__, errCode);
+                       return errCode;
+               }
                msleep(3);
-               em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
+
+               errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);
+               if (errCode < 0) {
+                       em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n",
+                               __func__, errCode);
+                       return errCode;
+               }
                msleep(3);
        }
 
        video_mux(dev, 0);
 
        em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
-                               dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
-                               dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
+                               dev->vdev->num, dev->vbi_dev->num);
 
        mutex_lock(&em28xx_extension_devlist_lock);
        if (!list_empty(&em28xx_extension_devlist)) {
@@ -2236,7 +2272,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
                em28xx_warn
                    ("device /dev/video%d is open! Deregistration and memory "
                     "deallocation are deferred on close.\n",
-                               dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN);
+                               dev->vdev->num);
 
                dev->state |= DEV_MISCONFIGURED;
                em28xx_uninit_isoc(dev);
index 9a3310748685c9c3ec63c84522272b463d491287..82781178e0a3e23c7514a09bf6600c02d658ae36 100644 (file)
@@ -411,8 +411,8 @@ struct em28xx {
        /* frame properties */
        int width;              /* current frame width */
        int height;             /* current frame height */
-       int hscale;             /* horizontal scale factor (see datasheet) */
-       int vscale;             /* vertical scale factor (see datasheet) */
+       unsigned hscale;        /* horizontal scale factor (see datasheet) */
+       unsigned vscale;        /* vertical scale factor (see datasheet) */
        int interlaced;         /* 1=interlace fileds, 0=just top fileds */
        unsigned int video_bytesread;   /* Number of bytes read */
 
@@ -528,7 +528,7 @@ extern struct em28xx_board em28xx_boards[];
 extern struct usb_device_id em28xx_id_table[];
 extern const unsigned int em28xx_bcount;
 void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
-int em28xx_tuner_callback(void *ptr, int command, int arg);
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
 
 /* Provided by em28xx-input.c */
 /* TODO: Check if the standard get_key handlers on ir-common can be used */
index 8db2a05bf9c542544b3a3bf9bc1c4fdd5cc217bf..7a85c41b0eea3b592ccc7554707421a40d70aaa3 100644 (file)
@@ -1214,7 +1214,7 @@ static int et61x251_open(struct inode* inode, struct file* filp)
        if (!down_read_trylock(&et61x251_dev_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        if (wait_for_completion_interruptible(&cam->probe)) {
                up_read(&et61x251_dev_lock);
@@ -1297,7 +1297,7 @@ static int et61x251_release(struct inode* inode, struct file* filp)
 
        down_write(&et61x251_dev_lock);
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        et61x251_stop_transfer(cam);
        et61x251_release_buffers(cam);
@@ -1318,7 +1318,7 @@ static ssize_t
 et61x251_read(struct file* filp, char __user * buf,
              size_t count, loff_t* f_pos)
 {
-       struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+       struct et61x251_device *cam = video_drvdata(filp);
        struct et61x251_frame_t* f, * i;
        unsigned long lock_flags;
        long timeout;
@@ -1426,7 +1426,7 @@ exit:
 
 static unsigned int et61x251_poll(struct file *filp, poll_table *wait)
 {
-       struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+       struct et61x251_device *cam = video_drvdata(filp);
        struct et61x251_frame_t* f;
        unsigned long lock_flags;
        unsigned int mask = 0;
@@ -1502,7 +1502,7 @@ static struct vm_operations_struct et61x251_vm_ops = {
 
 static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma)
 {
-       struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+       struct et61x251_device *cam = video_drvdata(filp);
        unsigned long size = vma->vm_end - vma->vm_start,
                      start = vma->vm_start;
        void *pos;
@@ -2395,7 +2395,7 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
 static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
                               unsigned int cmd, void __user * arg)
 {
-       struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+       struct et61x251_device *cam = video_drvdata(filp);
 
        switch (cmd) {
 
@@ -2490,7 +2490,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
 static int et61x251_ioctl(struct inode* inode, struct file* filp,
                         unsigned int cmd, unsigned long arg)
 {
-       struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));
+       struct et61x251_device *cam = video_drvdata(filp);
        int err = 0;
 
        if (mutex_lock_interruptible(&cam->fileop_mutex))
index 42b90742b40be6b4abc42d0f89d1928d5c4625c0..4d0817471c9f6a5c6bd11f6d5c3ef21710e205ab 100644 (file)
-config USB_GSPCA
-       tristate "USB GSPCA driver"
+menuconfig USB_GSPCA
+       tristate "GSPCA based webcams"
        depends on VIDEO_V4L2
+       default m
        ---help---
-         Say Y here if you want support for various USB webcams.
+       Say Y here if you want to enable selecting webcams based
+       on the GSPCA framework.
 
-         See <file:Documentation/video4linux/gspca.txt> for more info.
+       See <file:Documentation/video4linux/gspca.txt> for more info.
 
-         This driver uses the Video For Linux API. You must say Y or M to
-         "Video For Linux" to use this driver.
+       This driver uses the Video For Linux API. You must say Y or M to
+       "Video For Linux" to use this driver.
 
-         To compile this driver as modules, choose M here: the
-         modules will be called gspca_xxxx.
+       To compile this driver as modules, choose M here: the
+       modules will be called gspca_main.
+
+
+if USB_GSPCA && VIDEO_V4L2
+
+source "drivers/media/video/gspca/m5602/Kconfig"
+
+config USB_GSPCA_CONEX
+       tristate "Conexant Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the Conexant chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_conex.
+
+config USB_GSPCA_ETOMS
+       tristate "Etoms USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the Etoms chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_etoms.
+
+config USB_GSPCA_FINEPIX
+       tristate "Fujifilm FinePix USB V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the FinePix chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_finepix.
+
+config USB_GSPCA_MARS
+       tristate "Mars USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the Mars chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_mars.
+
+config USB_GSPCA_OV519
+       tristate "OV519 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the OV519 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_ov519.
+
+config USB_GSPCA_PAC207
+       tristate "Pixart PAC207 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the PAC207 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_pac207.
+
+config USB_GSPCA_PAC7311
+       tristate "Pixart PAC7311 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the PAC7311 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_pac7311.
+
+config USB_GSPCA_SONIXB
+       tristate "SN9C102 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SONIXB chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_sonixb.
+
+config USB_GSPCA_SONIXJ
+       tristate "SONIX JPEG USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SONIXJ chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_sonixj
+
+config USB_GSPCA_SPCA500
+       tristate "SPCA500 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA500 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca500.
+
+config USB_GSPCA_SPCA501
+       tristate "SPCA501 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA501 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca501.
+
+config USB_GSPCA_SPCA505
+       tristate "SPCA505 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA505 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca505.
+
+config USB_GSPCA_SPCA506
+       tristate "SPCA506 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA506 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca506.
+
+config USB_GSPCA_SPCA508
+       tristate "SPCA508 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA508 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca508.
+
+config USB_GSPCA_SPCA561
+       tristate "SPCA561 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the SPCA561 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca561.
+
+config USB_GSPCA_STK014
+       tristate "Syntek DV4000 (STK014) USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the STK014 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_stk014.
+
+config USB_GSPCA_SUNPLUS
+       tristate "SUNPLUS USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the Sunplus
+       SPCA504(abc) SPCA533 SPCA536 chips.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_spca5xx.
+
+config USB_GSPCA_T613
+       tristate "T613 (JPEG Compliance) USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the T613 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_t613.
+
+config USB_GSPCA_TV8532
+       tristate "TV8532 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the TV8531 chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_tv8532.
+
+config USB_GSPCA_VC032X
+       tristate "VC032X USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the VC032X chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_vc032x.
+
+config USB_GSPCA_ZC3XX
+       tristate "VC3xx USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+       Say Y here if you want support for cameras based on the ZC3XX chip.
+
+       To compile this driver as a module, choose M here: the
+       module will be called gspca_zc3xx.
+
+endif
index e68a8965297a70d7cff5ba6fb33ea83a32d4ee96..22734f5a6c3216b52cd0fb867832da939ced7bf6 100644 (file)
@@ -1,29 +1,48 @@
-obj-$(CONFIG_USB_GSPCA)        += gspca_main.o \
-       gspca_conex.o gspca_etoms.o gspca_mars.o \
-       gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
-       gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
-       gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
-       gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
-       gspca_vc032x.o gspca_zc3xx.o
+obj-$(CONFIG_USB_GSPCA)                += gspca_main.o
+obj-$(CONFIG_USB_GSPCA_CONEX)  += gspca_conex.o
+obj-$(CONFIG_USB_GSPCA_ETOMS)  += gspca_etoms.o
+obj-$(CONFIG_USB_GSPCA_FINEPIX)        += gspca_finepix.o
+obj-$(CONFIG_USB_GSPCA_MARS)   += gspca_mars.o
+obj-$(CONFIG_USB_GSPCA_OV519)  += gspca_ov519.o
+obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
+obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
+obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
+obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
+obj-$(CONFIG_USB_GSPCA_SPCA501) += gspca_spca501.o
+obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
+obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
+obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
+obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
+obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
+obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
+obj-$(CONFIG_USB_GSPCA_T613)   += gspca_t613.o
+obj-$(CONFIG_USB_GSPCA_TV8532) += gspca_tv8532.o
+obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o
+obj-$(CONFIG_USB_GSPCA_ZC3XX)  += gspca_zc3xx.o
+
+gspca_main-objs                        := gspca.o
+gspca_conex-objs               := conex.o
+gspca_etoms-objs               := etoms.o
+gspca_finepix-objs             := finepix.o
+gspca_mars-objs                        := mars.o
+gspca_ov519-objs               := ov519.o
+gspca_pac207-objs              := pac207.o
+gspca_pac7311-objs             := pac7311.o
+gspca_sonixb-objs              := sonixb.o
+gspca_sonixj-objs              := sonixj.o
+gspca_spca500-objs             := spca500.o
+gspca_spca501-objs             := spca501.o
+gspca_spca505-objs             := spca505.o
+gspca_spca506-objs             := spca506.o
+gspca_spca508-objs             := spca508.o
+gspca_spca561-objs             := spca561.o
+gspca_stk014-objs              := stk014.o
+gspca_sunplus-objs             := sunplus.o
+gspca_t613-objs                        := t613.o
+gspca_tv8532-objs              := tv8532.o
+gspca_vc032x-objs              := vc032x.o
+gspca_zc3xx-objs               := zc3xx.o
+
+obj-$(CONFIG_USB_M5602)                += m5602/
 
-gspca_main-objs := gspca.o
-gspca_conex-objs := conex.o
-gspca_etoms-objs := etoms.o
-gspca_mars-objs := mars.o
-gspca_ov519-objs := ov519.o
-gspca_pac207-objs := pac207.o
-gspca_pac7311-objs := pac7311.o
-gspca_sonixb-objs := sonixb.o
-gspca_sonixj-objs := sonixj.o
-gspca_spca500-objs := spca500.o
-gspca_spca501-objs := spca501.o
-gspca_spca505-objs := spca505.o
-gspca_spca506-objs := spca506.o
-gspca_spca508-objs := spca508.o
-gspca_spca561-objs := spca561.o
-gspca_stk014-objs := stk014.o
-gspca_sunplus-objs := sunplus.o
-gspca_t613-objs := t613.o
-gspca_tv8532-objs := tv8532.o
-gspca_vc032x-objs := vc032x.o
-gspca_zc3xx-objs := zc3xx.o
index 4d9f4cc255a9540fe13e1fb36806f36cd7af6f7e..a9d51ba7c57ce7f79f736f3e1cf462afeea75ac3 100644 (file)
@@ -837,12 +837,13 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        cx11646_initsize(gspca_dev);
        cx11646_fw(gspca_dev);
        cx_sensor(gspca_dev);
        cx11646_jpeg(gspca_dev);
+       return 0;
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
index 4ff0e386914baf87d37482f0abdb7611c66720a2..3be30b420a26fea30eb09674c82798152f0519b2 100644 (file)
@@ -691,7 +691,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -704,6 +704,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
        reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
        et_video(gspca_dev, 1);         /* video on */
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
new file mode 100644 (file)
index 0000000..65d3cbf
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * Fujifilm Finepix subdriver
+ *
+ * Copyright (C) 2008 Frank Zago
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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 MODULE_NAME "finepix"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Frank Zago <frank@zago.net>");
+MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeout, in ms */
+#define FPIX_TIMEOUT (HZ / 10)
+
+/* Maximum transfer size to use. The windows driver reads by chunks of
+ * 0x2000 bytes, so do the same. Note: reading more seems to work
+ * too. */
+#define FPIX_MAX_TRANSFER 0x2000
+
+/* Structure to hold all of our device specific stuff */
+struct usb_fpix {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       /*
+        * USB stuff
+        */
+       struct usb_ctrlrequest ctrlreq;
+       struct urb *control_urb;
+       struct timer_list bulk_timer;
+
+       enum {
+               FPIX_NOP,       /* inactive, else streaming */
+               FPIX_RESET,     /* must reset */
+               FPIX_REQ_FRAME, /* requesting a frame */
+               FPIX_READ_FRAME,        /* reading frame */
+       } state;
+
+       /*
+        * Driver stuff
+        */
+       struct delayed_work wqe;
+       struct completion can_close;
+       int streaming;
+};
+
+/* Delay after which claim the next frame. If the delay is too small,
+ * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
+ * will fail every 4 or 5 frames, but 30ms is perfect. */
+#define NEXT_FRAME_DELAY  (((HZ * 30) + 999) / 1000)
+
+#define dev_new_state(new_state) {                             \
+               PDEBUG(D_STREAM, "new state from %d to %d at %s:%d",    \
+                       dev->state, new_state, __func__, __LINE__);     \
+               dev->state = new_state;                                 \
+}
+
+/* These cameras only support 320x200. */
+static struct v4l2_pix_format fpix_mode[1] = {
+       { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0}
+};
+
+/* Reads part of a frame */
+static void read_frame_part(struct usb_fpix *dev)
+{
+       int ret;
+
+       PDEBUG(D_STREAM, "read_frame_part");
+
+       /* Reads part of a frame */
+       ret = usb_submit_urb(dev->gspca_dev.urb[0], GFP_ATOMIC);
+       if (ret) {
+               dev_new_state(FPIX_RESET);
+               schedule_delayed_work(&dev->wqe, 1);
+               PDEBUG(D_STREAM, "usb_submit_urb failed with %d",
+                       ret);
+       } else {
+               /* Sometimes we never get a callback, so use a timer.
+                * Is this masking a bug somewhere else? */
+               dev->bulk_timer.expires = jiffies + msecs_to_jiffies(150);
+               add_timer(&dev->bulk_timer);
+       }
+}
+
+/* Callback for URBs. */
+static void urb_callback(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = urb->context;
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+       PDEBUG(D_PACK,
+               "enter urb_callback - status=%d, length=%d",
+               urb->status, urb->actual_length);
+
+       if (dev->state == FPIX_READ_FRAME)
+               del_timer(&dev->bulk_timer);
+
+       if (urb->status != 0) {
+               /* We kill a stuck urb every 50 frames on average, so don't
+                * display a log message for that. */
+               if (urb->status != -ECONNRESET)
+                       PDEBUG(D_STREAM, "bad URB status %d", urb->status);
+               dev_new_state(FPIX_RESET);
+               schedule_delayed_work(&dev->wqe, 1);
+       }
+
+       switch (dev->state) {
+       case FPIX_REQ_FRAME:
+               dev_new_state(FPIX_READ_FRAME);
+               read_frame_part(dev);
+               break;
+
+       case FPIX_READ_FRAME: {
+               unsigned char *data = urb->transfer_buffer;
+               struct gspca_frame *frame;
+
+               frame = gspca_get_i_frame(&dev->gspca_dev);
+               if (frame == NULL)
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+               if (urb->actual_length < FPIX_MAX_TRANSFER ||
+                       (data[urb->actual_length-2] == 0xff &&
+                               data[urb->actual_length-1] == 0xd9)) {
+
+                       /* If the result is less than what was asked
+                        * for, then it's the end of the
+                        * frame. Sometime the jpeg is not complete,
+                        * but there's nothing we can do. We also end
+                        * here if the the jpeg ends right at the end
+                        * of the frame. */
+                       if (frame)
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               frame,
+                                               data, urb->actual_length);
+                       dev_new_state(FPIX_REQ_FRAME);
+                       schedule_delayed_work(&dev->wqe, NEXT_FRAME_DELAY);
+               } else {
+
+                       /* got a partial image */
+                       if (frame)
+                               gspca_frame_add(gspca_dev,
+                                               gspca_dev->last_packet_type
+                                                               == LAST_PACKET
+                                               ? FIRST_PACKET : INTER_PACKET,
+                                               frame,
+                                       data, urb->actual_length);
+                       read_frame_part(dev);
+               }
+               break;
+           }
+
+       case FPIX_NOP:
+       case FPIX_RESET:
+               PDEBUG(D_STREAM, "invalid state %d", dev->state);
+               break;
+       }
+}
+
+/* Request a new frame */
+static void request_frame(struct usb_fpix *dev)
+{
+       int ret;
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+
+       /* Setup command packet */
+       memset(gspca_dev->usb_buf, 0, 12);
+       gspca_dev->usb_buf[0] = 0xd3;
+       gspca_dev->usb_buf[7] = 0x01;
+
+       /* Request a frame */
+       dev->ctrlreq.bRequestType =
+               USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+       dev->ctrlreq.bRequest = USB_REQ_GET_STATUS;
+       dev->ctrlreq.wValue = 0;
+       dev->ctrlreq.wIndex = 0;
+       dev->ctrlreq.wLength = cpu_to_le16(12);
+
+       usb_fill_control_urb(dev->control_urb,
+                            gspca_dev->dev,
+                            usb_sndctrlpipe(gspca_dev->dev, 0),
+                            (unsigned char *) &dev->ctrlreq,
+                            gspca_dev->usb_buf,
+                            12, urb_callback, gspca_dev);
+
+       ret = usb_submit_urb(dev->control_urb, GFP_ATOMIC);
+       if (ret) {
+               dev_new_state(FPIX_RESET);
+               schedule_delayed_work(&dev->wqe, 1);
+               PDEBUG(D_STREAM, "usb_submit_urb failed with %d", ret);
+       }
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* State machine. */
+static void fpix_sm(struct work_struct *work)
+{
+       struct usb_fpix *dev = container_of(work, struct usb_fpix, wqe.work);
+
+       PDEBUG(D_STREAM, "fpix_sm state %d", dev->state);
+
+       /* verify that the device wasn't unplugged */
+       if (!dev->gspca_dev.present) {
+               PDEBUG(D_STREAM, "device is gone");
+               dev_new_state(FPIX_NOP);
+               complete(&dev->can_close);
+               return;
+       }
+
+       if (!dev->streaming) {
+               PDEBUG(D_STREAM, "stopping state machine");
+               dev_new_state(FPIX_NOP);
+               complete(&dev->can_close);
+               return;
+       }
+
+       switch (dev->state) {
+       case FPIX_RESET:
+               dev_new_state(FPIX_REQ_FRAME);
+               schedule_delayed_work(&dev->wqe, HZ / 10);
+               break;
+
+       case FPIX_REQ_FRAME:
+               /* get an image */
+               request_frame(dev);
+               break;
+
+       case FPIX_NOP:
+       case FPIX_READ_FRAME:
+               PDEBUG(D_STREAM, "invalid state %d", dev->state);
+               break;
+       }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+
+       cam->cam_mode = fpix_mode;
+       cam->nmodes = 1;
+       cam->epaddr = 0x01;     /* todo: correct for all cams? */
+       cam->bulk_size = FPIX_MAX_TRANSFER;
+
+/*     gspca_dev->nbalt = 1;    * use bulk transfer */
+       return 0;
+}
+
+/* Stop streaming and free the ressources allocated by sd_start. */
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+       dev->streaming = 0;
+
+       /* Stop the state machine */
+       if (dev->state != FPIX_NOP)
+               wait_for_completion(&dev->can_close);
+
+       usb_free_urb(dev->control_urb);
+       dev->control_urb = NULL;
+}
+
+/* Kill an URB that hasn't completed. */
+static void timeout_kill(unsigned long data)
+{
+       struct urb *urb = (struct urb *) data;
+
+       usb_unlink_urb(urb);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+       INIT_DELAYED_WORK(&dev->wqe, fpix_sm);
+
+       init_timer(&dev->bulk_timer);
+       dev->bulk_timer.function = timeout_kill;
+
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+       int ret;
+       int size_ret;
+
+       /* Reset bulk in endpoint */
+       usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
+
+       /* Init the device */
+       memset(gspca_dev->usb_buf, 0, 12);
+       gspca_dev->usb_buf[0] = 0xc6;
+       gspca_dev->usb_buf[8] = 0x20;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_DIR_OUT | USB_TYPE_CLASS |
+                       USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+                       12, FPIX_TIMEOUT);
+
+       if (ret != 12) {
+               PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* Read the result of the command. Ignore the result, for it
+        * varies with the device. */
+       ret = usb_bulk_msg(gspca_dev->dev,
+                       usb_rcvbulkpipe(gspca_dev->dev,
+                                       gspca_dev->cam.epaddr),
+                       gspca_dev->usb_buf, FPIX_MAX_TRANSFER, &size_ret,
+                       FPIX_TIMEOUT);
+       if (ret != 0) {
+               PDEBUG(D_STREAM, "usb_bulk_msg failed (%d)", ret);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* Request a frame, but don't read it */
+       memset(gspca_dev->usb_buf, 0, 12);
+       gspca_dev->usb_buf[0] = 0xd3;
+       gspca_dev->usb_buf[7] = 0x01;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_DIR_OUT | USB_TYPE_CLASS |
+                       USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+                       12, FPIX_TIMEOUT);
+       if (ret != 12) {
+               PDEBUG(D_STREAM, "usb_control_msg failed (%d)", ret);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* Again, reset bulk in endpoint */
+       usb_clear_halt(gspca_dev->dev, gspca_dev->cam.epaddr);
+
+       /* Allocate a control URB */
+       dev->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->control_urb) {
+               PDEBUG(D_STREAM, "No free urbs available");
+               ret = -EIO;
+               goto error;
+       }
+
+       /* Various initializations. */
+       init_completion(&dev->can_close);
+       dev->bulk_timer.data = (unsigned long)dev->gspca_dev.urb[0];
+       dev->gspca_dev.urb[0]->complete = urb_callback;
+       dev->streaming = 1;
+
+       /* Schedule a frame request. */
+       dev_new_state(FPIX_REQ_FRAME);
+       schedule_delayed_work(&dev->wqe, 1);
+
+       return 0;
+
+error:
+       /* Free the ressources */
+       sd_stopN(gspca_dev);
+       return ret;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04cb, 0x0104)},
+       {USB_DEVICE(0x04cb, 0x0109)},
+       {USB_DEVICE(0x04cb, 0x010b)},
+       {USB_DEVICE(0x04cb, 0x010f)},
+       {USB_DEVICE(0x04cb, 0x0111)},
+       {USB_DEVICE(0x04cb, 0x0113)},
+       {USB_DEVICE(0x04cb, 0x0115)},
+       {USB_DEVICE(0x04cb, 0x0117)},
+       {USB_DEVICE(0x04cb, 0x0119)},
+       {USB_DEVICE(0x04cb, 0x011b)},
+       {USB_DEVICE(0x04cb, 0x011d)},
+       {USB_DEVICE(0x04cb, 0x0121)},
+       {USB_DEVICE(0x04cb, 0x0123)},
+       {USB_DEVICE(0x04cb, 0x0125)},
+       {USB_DEVICE(0x04cb, 0x0127)},
+       {USB_DEVICE(0x04cb, 0x0129)},
+       {USB_DEVICE(0x04cb, 0x012b)},
+       {USB_DEVICE(0x04cb, 0x012d)},
+       {USB_DEVICE(0x04cb, 0x012f)},
+       {USB_DEVICE(0x04cb, 0x0131)},
+       {USB_DEVICE(0x04cb, 0x013b)},
+       {USB_DEVICE(0x04cb, 0x013d)},
+       {USB_DEVICE(0x04cb, 0x013f)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id,
+                       &sd_desc,
+                       sizeof(struct usb_fpix),
+                       THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+       if (usb_register(&sd_driver) < 0)
+               return -1;
+       PDEBUG(D_PROBE, "registered");
+       return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+       usb_deregister(&sd_driver);
+       PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
index ac95c55887df4b38eb1cd8c4478538c53e042aef..c21af312ee7c496782a792fd1f29a33946a6277c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/io.h>
+#include <linux/kref.h>
 #include <asm/page.h>
 #include <linux/uaccess.h>
 #include <linux/jiffies.h>
@@ -43,7 +44,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 2, 0)
+#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 3, 0)
 
 static int video_nr = -1;
 
@@ -102,6 +103,22 @@ static struct vm_operations_struct gspca_vm_ops = {
        .close          = gspca_vm_close,
 };
 
+/* get the current input frame buffer */
+struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev)
+{
+       struct gspca_frame *frame;
+       int i;
+
+       i = gspca_dev->fr_i;
+       i = gspca_dev->fr_queue[i];
+       frame = &gspca_dev->frame[i];
+       if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
+                               != V4L2_BUF_FLAG_QUEUED)
+               return NULL;
+       return frame;
+}
+EXPORT_SYMBOL(gspca_get_i_frame);
+
 /*
  * fill a video frame from an URB and resubmit
  */
@@ -110,7 +127,7 @@ static void fill_frame(struct gspca_dev *gspca_dev,
 {
        struct gspca_frame *frame;
        __u8 *data;             /* address of data in the iso message */
-       int i, j, len, st;
+       int i, len, st;
        cam_pkt_op pkt_scan;
 
        if (urb->status != 0) {
@@ -124,11 +141,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
        for (i = 0; i < urb->number_of_packets; i++) {
 
                /* check the availability of the frame buffer */
-               j = gspca_dev->fr_i;
-               j = gspca_dev->fr_queue[j];
-               frame = &gspca_dev->frame[j];
-               if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
-                                       != V4L2_BUF_FLAG_QUEUED) {
+               frame = gspca_get_i_frame(gspca_dev);
+               if (!frame) {
                        gspca_dev->last_packet_type = DISCARD_PACKET;
                        break;
                }
@@ -177,6 +191,39 @@ static void isoc_irq(struct urb *urb
        fill_frame(gspca_dev, urb);
 }
 
+/*
+ * bulk message interrupt from the USB device
+ */
+static void bulk_irq(struct urb *urb
+)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+       struct gspca_frame *frame;
+
+       PDEBUG(D_PACK, "bulk irq");
+       if (!gspca_dev->streaming)
+               return;
+       if (urb->status != 0 && urb->status != -ECONNRESET) {
+#ifdef CONFIG_PM
+               if (!gspca_dev->frozen)
+#endif
+                       PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+               return;         /* disconnection ? */
+       }
+
+       /* check the availability of the frame buffer */
+       frame = gspca_get_i_frame(gspca_dev);
+       if (!frame) {
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+       } else {
+               PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
+               gspca_dev->sd_desc->pkt_scan(gspca_dev,
+                                       frame,
+                                       urb->transfer_buffer,
+                                       urb->actual_length);
+       }
+}
+
 /*
  * add data to the current frame
  *
@@ -190,7 +237,7 @@ static void isoc_irq(struct urb *urb
  * On LAST_PACKET, a new frame is returned.
  */
 struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
-                                   int packet_type,
+                                   enum gspca_packet_type packet_type,
                                    struct gspca_frame *frame,
                                    const __u8 *data,
                                    int len)
@@ -232,7 +279,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
        }
        gspca_dev->last_packet_type = packet_type;
 
-       /* if last packet, wake the application and advance in the queue */
+       /* if last packet, wake up the application and advance in the queue */
        if (packet_type == LAST_PACKET) {
                frame->v4l2_buf.bytesused = frame->data_end - frame->data;
                frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
@@ -270,7 +317,6 @@ static void *rvmalloc(unsigned long size)
        void *mem;
        unsigned long adr;
 
-/*     size = PAGE_ALIGN(size);        (already done) */
        mem = vmalloc_32(size);
        if (mem != NULL) {
                adr = (unsigned long) mem;
@@ -374,10 +420,11 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
 }
 
 /*
- * search an input isochronous endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting
  */
-static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
-                                         __u8 epaddr)
+static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
+                                         __u8 epaddr,
+                                         __u8 xfer)
 {
        struct usb_host_endpoint *ep;
        int i, attr;
@@ -388,7 +435,7 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
                if (ep->desc.bEndpointAddress == epaddr) {
                        attr = ep->desc.bmAttributes
                                                & USB_ENDPOINT_XFERTYPE_MASK;
-                       if (attr == USB_ENDPOINT_XFER_ISOC)
+                       if (attr == xfer)
                                return ep;
                        break;
                }
@@ -397,14 +444,14 @@ static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
 }
 
 /*
- * search an input isochronous endpoint
+ * look for an input (isoc or bulk) endpoint
  *
  * The endpoint is defined by the subdriver.
  * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
  * This routine may be called many times when the bandwidth is too small
  * (the bandwidth is checked on urb submit).
  */
-static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
+static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
 {
        struct usb_interface *intf;
        struct usb_host_endpoint *ep;
@@ -413,28 +460,41 @@ static struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
        intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
        ep = NULL;
        i = gspca_dev->alt;                     /* previous alt setting */
+
+       /* try isoc */
        while (--i > 0) {                       /* alt 0 is unusable */
-               ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
+               ep = alt_xfer(&intf->altsetting[i],
+                               gspca_dev->cam.epaddr,
+                               USB_ENDPOINT_XFER_ISOC);
                if (ep)
                        break;
        }
+
+       /* if no isoc, try bulk */
        if (ep == NULL) {
-               err("no ISOC endpoint found");
-               return NULL;
+               ep = alt_xfer(&intf->altsetting[0],
+                               gspca_dev->cam.epaddr,
+                               USB_ENDPOINT_XFER_BULK);
+               if (ep == NULL) {
+                       err("no transfer endpoint found");
+                       return NULL;
+               }
        }
-       PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
+       PDEBUG(D_STREAM, "use alt %d ep 0x%02x",
                        i, ep->desc.bEndpointAddress);
-       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
-       if (ret < 0) {
-               err("set interface err %d", ret);
-               return NULL;
+       if (i > 0) {
+               ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
+               if (ret < 0) {
+                       err("set interface err %d", ret);
+                       return NULL;
+               }
        }
        gspca_dev->alt = i;             /* memorize the current alt setting */
        return ep;
 }
 
 /*
- * create the isochronous URBs
+ * create the URBs for image transfer
  */
 static int create_urbs(struct gspca_dev *gspca_dev,
                        struct usb_host_endpoint *ep)
@@ -445,15 +505,27 @@ static int create_urbs(struct gspca_dev *gspca_dev,
        /* calculate the packet size and the number of packets */
        psize = le16_to_cpu(ep->desc.wMaxPacketSize);
 
-       /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
-       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-       npkt = ISO_MAX_SIZE / psize;
-       if (npkt > ISO_MAX_PKT)
-               npkt = ISO_MAX_PKT;
-       bsize = psize * npkt;
-       PDEBUG(D_STREAM,
-               "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
-       nurbs = DEF_NURBS;
+       if (gspca_dev->alt != 0) {              /* isoc */
+
+               /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
+               psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+               npkt = ISO_MAX_SIZE / psize;
+               if (npkt > ISO_MAX_PKT)
+                       npkt = ISO_MAX_PKT;
+               bsize = psize * npkt;
+               PDEBUG(D_STREAM,
+                       "isoc %d pkts size %d = bsize:%d",
+                       npkt, psize, bsize);
+               nurbs = DEF_NURBS;
+       } else {                                /* bulk */
+               npkt = 0;
+               bsize = gspca_dev->cam. bulk_size;
+               if (bsize == 0)
+                       bsize = psize;
+               PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
+               nurbs = 1;
+       }
+
        gspca_dev->nurbs = nurbs;
        for (n = 0; n < nurbs; n++) {
                urb = usb_alloc_urb(npkt, GFP_KERNEL);
@@ -476,17 +548,24 @@ static int create_urbs(struct gspca_dev *gspca_dev,
                gspca_dev->urb[n] = urb;
                urb->dev = gspca_dev->dev;
                urb->context = gspca_dev;
-               urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
-                                           ep->desc.bEndpointAddress);
-               urb->transfer_flags = URB_ISO_ASAP
-                                       | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = ep->desc.bInterval;
-               urb->complete = isoc_irq;
-               urb->number_of_packets = npkt;
                urb->transfer_buffer_length = bsize;
-               for (i = 0; i < npkt; i++) {
-                       urb->iso_frame_desc[i].length = psize;
-                       urb->iso_frame_desc[i].offset = psize * i;
+               if (npkt != 0) {                /* ISOC */
+                       urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
+                                                   ep->desc.bEndpointAddress);
+                       urb->transfer_flags = URB_ISO_ASAP
+                                       | URB_NO_TRANSFER_DMA_MAP;
+                       urb->interval = ep->desc.bInterval;
+                       urb->complete = isoc_irq;
+                       urb->number_of_packets = npkt;
+                       for (i = 0; i < npkt; i++) {
+                               urb->iso_frame_desc[i].length = psize;
+                               urb->iso_frame_desc[i].offset = psize * i;
+                       }
+               } else {                /* bulk */
+                       urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
+                                               ep->desc.bEndpointAddress),
+                       urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+                       urb->complete = bulk_irq;
                }
        }
        return 0;
@@ -508,7 +587,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
        gspca_dev->alt = gspca_dev->nbalt;
        for (;;) {
                PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
-               ep = get_isoc_ep(gspca_dev);
+               ep = get_ep(gspca_dev);
                if (ep == NULL) {
                        ret = -EIO;
                        goto out;
@@ -518,10 +597,18 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
                        goto out;
 
                /* start the cam */
-               gspca_dev->sd_desc->start(gspca_dev);
+               ret = gspca_dev->sd_desc->start(gspca_dev);
+               if (ret < 0) {
+                       destroy_urbs(gspca_dev);
+                       goto out;
+               }
                gspca_dev->streaming = 1;
                atomic_set(&gspca_dev->nevent, 0);
 
+               /* bulk transfers are started by the subdriver */
+               if (gspca_dev->alt == 0)
+                       break;
+
                /* submit the URBs */
                for (n = 0; n < gspca_dev->nurbs; n++) {
                        ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
@@ -553,7 +640,7 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
        return ret;
 }
 
-/* Note both the queue and the usb lock should be hold when calling this */
+/* Note: both the queue and the usb locks should be held when calling this */
 static void gspca_stream_off(struct gspca_dev *gspca_dev)
 {
        gspca_dev->streaming = 0;
@@ -759,6 +846,16 @@ out:
        return ret;
 }
 
+static void gspca_delete(struct kref *kref)
+{
+       struct gspca_dev *gspca_dev = container_of(kref, struct gspca_dev, kref);
+
+       PDEBUG(D_STREAM, "device deleted");
+
+       kfree(gspca_dev->usb_buf);
+       kfree(gspca_dev);
+}
+
 static int dev_open(struct inode *inode, struct file *file)
 {
        struct gspca_dev *gspca_dev;
@@ -778,13 +875,19 @@ static int dev_open(struct inode *inode, struct file *file)
                goto out;
        }
        gspca_dev->users++;
+
+       /* one more user */
+       kref_get(&gspca_dev->kref);
+
        file->private_data = gspca_dev;
 #ifdef GSPCA_DEBUG
        /* activate the v4l2 debug */
        if (gspca_debug & D_V4L2)
-               gspca_dev->vdev.debug |= 3;
+               gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+                                       | V4L2_DEBUG_IOCTL_ARG;
        else
-               gspca_dev->vdev.debug &= ~3;
+               gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+                                       | V4L2_DEBUG_IOCTL_ARG);
 #endif
        ret = 0;
 out:
@@ -818,7 +921,11 @@ static int dev_close(struct inode *inode, struct file *file)
        }
        file->private_data = NULL;
        mutex_unlock(&gspca_dev->queue_lock);
+
        PDEBUG(D_STREAM, "close done");
+
+       kref_put(&gspca_dev->kref, gspca_delete);
+
        return 0;
 }
 
@@ -829,7 +936,6 @@ static int vidioc_querycap(struct file *file, void  *priv,
 
        memset(cap, 0, sizeof *cap);
        strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
-/*     strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card); */
        if (gspca_dev->dev->product != NULL) {
                strncpy(cap->card, gspca_dev->dev->product,
                        sizeof cap->card);
@@ -1463,7 +1569,6 @@ static int vidioc_qbuf(struct file *file, void *priv,
        }
 
        frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
-/*     frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
 
        if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
                frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
@@ -1610,7 +1715,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
                }
 
                /* if the process slept for more than 1 second,
-                * get anewer frame */
+                * get a newer frame */
                frame = &gspca_dev->frame[v4l2_buf.index];
                if (--n < 0)
                        break;                  /* avoid infinite loop */
@@ -1728,21 +1833,21 @@ int gspca_dev_probe(struct usb_interface *intf,
        if (dev_size < sizeof *gspca_dev)
                dev_size = sizeof *gspca_dev;
        gspca_dev = kzalloc(dev_size, GFP_KERNEL);
-       if (gspca_dev == NULL) {
+       if (!gspca_dev) {
                err("couldn't kzalloc gspca struct");
-               return -EIO;
+               return -ENOMEM;
        }
+       kref_init(&gspca_dev->kref);
        gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
        if (!gspca_dev->usb_buf) {
                err("out of memory");
-               ret = -EIO;
+               ret = -ENOMEM;
                goto out;
        }
        gspca_dev->dev = dev;
        gspca_dev->iface = interface->bInterfaceNumber;
        gspca_dev->nbalt = intf->num_altsetting;
        gspca_dev->sd_desc = sd_desc;
-/*     gspca_dev->users = 0;                   (done by kzalloc) */
        gspca_dev->nbufread = 2;
 
        /* configure the subdriver and initialize the USB device */
@@ -1781,8 +1886,7 @@ int gspca_dev_probe(struct usb_interface *intf,
        PDEBUG(D_PROBE, "probe ok");
        return 0;
 out:
-       kfree(gspca_dev->usb_buf);
-       kfree(gspca_dev);
+       kref_put(&gspca_dev->kref, gspca_delete);
        return ret;
 }
 EXPORT_SYMBOL(gspca_dev_probe);
@@ -1797,25 +1901,16 @@ void gspca_disconnect(struct usb_interface *intf)
 {
        struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
 
-       if (!gspca_dev)
-               return;
-       gspca_dev->present = 0;
-       mutex_lock(&gspca_dev->queue_lock);
-       mutex_lock(&gspca_dev->usb_lock);
-       gspca_dev->streaming = 0;
-       destroy_urbs(gspca_dev);
-       mutex_unlock(&gspca_dev->usb_lock);
-       mutex_unlock(&gspca_dev->queue_lock);
-       while (gspca_dev->users != 0) {         /* wait until fully closed */
-               atomic_inc(&gspca_dev->nevent);
-               wake_up_interruptible(&gspca_dev->wq);  /* wake processes */
-               schedule();
-       }
+       usb_set_intfdata(intf, NULL);
+
 /* We don't want people trying to open up the device */
        video_unregister_device(&gspca_dev->vdev);
-/* Free the memory */
-       kfree(gspca_dev->usb_buf);
-       kfree(gspca_dev);
+
+       gspca_dev->present = 0;
+       gspca_dev->streaming = 0;
+
+       kref_put(&gspca_dev->kref, gspca_delete);
+
        PDEBUG(D_PROBE, "disconnect complete");
 }
 EXPORT_SYMBOL(gspca_disconnect);
index c17625cff9ba2dbf35003ab4220363441fe6585d..4779dd0b06da0145eeee191f4e0e2d3fe198446a 100644 (file)
@@ -49,13 +49,14 @@ extern int gspca_debug;
        } while (0)
 
 #define GSPCA_MAX_FRAMES 16    /* maximum number of video frame buffers */
-/* ISOC transfers */
-#define MAX_NURBS 16           /* max number of URBs */
+/* image transfers */
+#define MAX_NURBS            /* max number of URBs */
 #define ISO_MAX_PKT 32         /* max number of packets in an ISOC transfer */
 #define ISO_MAX_SIZE 0x8000    /* max size of one URB buffer (32 Kb) */
 
 /* device information - set at probe time */
 struct cam {
+       int bulk_size;          /* buffer size when image transfer by bulk */
        struct v4l2_pix_format *cam_mode;       /* size nmodes */
        char nmodes;
        __u8 epaddr;
@@ -93,7 +94,7 @@ struct sd_desc {
 /* mandatory operations */
        cam_cf_op config;       /* called on probe */
        cam_op init;            /* called on probe and resume */
-       cam_v_op start;         /* called on stream on */
+       cam_op start;           /* called on stream on */
        cam_pkt_op pkt_scan;
 /* optional operations */
        cam_v_op stopN;         /* called on stream off - main alt */
@@ -105,10 +106,12 @@ struct sd_desc {
 };
 
 /* packet types when moving from iso buf to frame buf */
-#define DISCARD_PACKET 0
-#define FIRST_PACKET   1
-#define INTER_PACKET   2
-#define LAST_PACKET    3
+enum gspca_packet_type {
+       DISCARD_PACKET,
+       FIRST_PACKET,
+       INTER_PACKET,
+       LAST_PACKET
+};
 
 struct gspca_frame {
        __u8 *data;                     /* frame buffer */
@@ -121,6 +124,7 @@ struct gspca_dev {
        struct video_device vdev;       /* !! must be the first item */
        struct file_operations fops;
        struct usb_device *dev;
+       struct kref kref;
        struct file *capt_file;         /* file doing video capture */
 
        struct cam cam;                         /* device information */
@@ -173,10 +177,11 @@ int gspca_dev_probe(struct usb_interface *intf,
                struct module *module);
 void gspca_disconnect(struct usb_interface *intf);
 struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
-                                   int packet_type,
+                                   enum gspca_packet_type packet_type,
                                    struct gspca_frame *frame,
                                    const __u8 *data,
                                    int len);
+struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev);
 #ifdef CONFIG_PM
 int gspca_suspend(struct usb_interface *intf, pm_message_t message);
 int gspca_resume(struct usb_interface *intf);
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig
new file mode 100644 (file)
index 0000000..5a69016
--- /dev/null
@@ -0,0 +1,11 @@
+config USB_M5602
+       tristate "ALi USB m5602 Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the
+         ALi m5602 connected to various image sensors.
+
+         See <file:Documentation/video4linux/m5602.txt> for more info.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_m5602.
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
new file mode 100644 (file)
index 0000000..226ab4f
--- /dev/null
@@ -0,0 +1,11 @@
+obj-$(CONFIG_USB_M5602) += gspca_m5602.o
+
+gspca_m5602-objs := m5602_core.o \
+                   m5602_ov9650.o \
+                   m5602_mt9m111.o \
+                   m5602_po1030.o \
+                   m5602_s5k83a.o \
+                   m5602_s5k4aa.o
+
+EXTRA_CFLAGS += -Idrivers/media/video/gspca
+
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
new file mode 100644 (file)
index 0000000..c786d7d
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_BRIDGE_H_
+#define M5602_BRIDGE_H_
+
+#include "gspca.h"
+
+#define MODULE_NAME "ALi m5602"
+
+/*****************************************************************************/
+
+#undef PDEBUG
+#undef info
+#undef err
+
+#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
+       format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \
+       format "\n" , ## arg)
+
+/* Debug parameters */
+#define DBG_INIT 0x1
+#define DBG_PROBE 0x2
+#define DBG_V4L2 0x4
+#define DBG_TRACE 0x8
+#define DBG_DATA 0x10
+#define DBG_V4L2_CID 0x20
+#define DBG_GSPCA 0x40
+
+#define PDEBUG(level, fmt, args...) \
+       do { \
+               if (m5602_debug & level)     \
+                       info("[%s:%d] " fmt, __func__, __LINE__ , \
+                       ## args); \
+       } while (0)
+
+/*****************************************************************************/
+
+#define M5602_XB_SENSOR_TYPE 0x00
+#define M5602_XB_SENSOR_CTRL 0x01
+#define M5602_XB_LINE_OF_FRAME_H 0x02
+#define M5602_XB_LINE_OF_FRAME_L 0x03
+#define M5602_XB_PIX_OF_LINE_H 0x04
+#define M5602_XB_PIX_OF_LINE_L 0x05
+#define M5602_XB_VSYNC_PARA 0x06
+#define M5602_XB_HSYNC_PARA 0x07
+#define M5602_XB_TEST_MODE_1 0x08
+#define M5602_XB_TEST_MODE_2 0x09
+#define M5602_XB_SIG_INI 0x0a
+#define M5602_XB_DS_PARA 0x0e
+#define M5602_XB_TRIG_PARA 0x0f
+#define M5602_XB_CLK_PD 0x10
+#define M5602_XB_MCU_CLK_CTRL 0x12
+#define M5602_XB_MCU_CLK_DIV 0x13
+#define M5602_XB_SEN_CLK_CTRL 0x14
+#define M5602_XB_SEN_CLK_DIV 0x15
+#define M5602_XB_AUD_CLK_CTRL 0x16
+#define M5602_XB_AUD_CLK_DIV 0x17
+#define M5602_XB_DEVCTR1 0x41
+#define M5602_XB_EPSETR0 0x42
+#define M5602_XB_EPAFCTR 0x47
+#define M5602_XB_EPBFCTR 0x49
+#define M5602_XB_EPEFCTR 0x4f
+#define M5602_XB_TEST_REG 0x53
+#define M5602_XB_ALT2SIZE 0x54
+#define M5602_XB_ALT3SIZE 0x55
+#define M5602_XB_OBSFRAME 0x56
+#define M5602_XB_PWR_CTL 0x59
+#define M5602_XB_ADC_CTRL 0x60
+#define M5602_XB_ADC_DATA 0x61
+#define M5602_XB_MISC_CTRL 0x62
+#define M5602_XB_SNAPSHOT 0x63
+#define M5602_XB_SCRATCH_1 0x64
+#define M5602_XB_SCRATCH_2 0x65
+#define M5602_XB_SCRATCH_3 0x66
+#define M5602_XB_SCRATCH_4 0x67
+#define M5602_XB_I2C_CTRL 0x68
+#define M5602_XB_I2C_CLK_DIV 0x69
+#define M5602_XB_I2C_DEV_ADDR 0x6a
+#define M5602_XB_I2C_REG_ADDR 0x6b
+#define M5602_XB_I2C_DATA 0x6c
+#define M5602_XB_I2C_STATUS 0x6d
+#define M5602_XB_GPIO_DAT_H 0x70
+#define M5602_XB_GPIO_DAT_L 0x71
+#define M5602_XB_GPIO_DIR_H 0x72
+#define M5602_XB_GPIO_DIR_L 0x73
+#define M5602_XB_GPIO_EN_H 0x74
+#define M5602_XB_GPIO_EN_L 0x75
+#define M5602_XB_GPIO_DAT 0x76
+#define M5602_XB_GPIO_DIR 0x77
+#define M5602_XB_MISC_CTL 0x70
+
+#define I2C_BUSY 0x80
+
+/*****************************************************************************/
+
+/* Driver info */
+#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
+#define DRIVER_DESC "ALi m5602 webcam driver"
+
+#define M5602_ISOC_ENDPOINT_ADDR 0x81
+#define M5602_INTR_ENDPOINT_ADDR 0x82
+
+#define M5602_MAX_FRAMES       32
+#define M5602_URBS             2
+#define M5602_ISOC_PACKETS     14
+
+#define M5602_URB_TIMEOUT      msecs_to_jiffies(2 * M5602_ISOC_PACKETS)
+#define M5602_URB_MSG_TIMEOUT   5000
+#define M5602_FRAME_TIMEOUT    2
+
+/*****************************************************************************/
+
+/* A skeleton used for sending messages to the m5602 bridge */
+static const unsigned char bridge_urb_skeleton[] = {
+       0x13, 0x00, 0x81, 0x00
+};
+
+/* A skeleton used for sending messages to the sensor */
+static const unsigned char sensor_urb_skeleton[] = {
+       0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
+       0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
+       0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
+       0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
+       0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
+       0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
+};
+
+/* m5602 device descriptor, currently it just wraps the m5602_camera struct */
+struct sd {
+       struct gspca_dev gspca_dev;
+
+       /* The name of the m5602 camera */
+       char *name;
+
+       /* A pointer to the currently connected sensor */
+       struct m5602_sensor *sensor;
+
+       struct sd_desc *desc;
+
+       /* The current frame's id, used to detect frame boundaries */
+       u8 frame_id;
+
+       /* The current frame count */
+       u32 frame_count;
+};
+
+int m5602_read_bridge(
+       struct sd *sd, u8 address, u8 *i2c_data);
+
+int m5602_write_bridge(
+       struct sd *sd, u8 address, u8 i2c_data);
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
new file mode 100644 (file)
index 0000000..19d5e35
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_ov9650.h"
+#include "m5602_mt9m111.h"
+#include "m5602_po1030.h"
+#include "m5602_s5k83a.h"
+#include "m5602_s5k4aa.h"
+
+/* Kernel module parameters */
+int force_sensor;
+int dump_bridge;
+int dump_sensor;
+unsigned int m5602_debug;
+
+static const __devinitdata struct usb_device_id m5602_table[] = {
+       {USB_DEVICE(0x0402, 0x5602)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, m5602_table);
+
+/* Reads a byte from the m5602 */
+int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             0x04, 0xc0, 0x14,
+                             0x8100 + address, buf,
+                             1, M5602_URB_MSG_TIMEOUT);
+       *i2c_data = buf[0];
+
+       PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x",
+              address, *i2c_data);
+
+       /* usb_control_msg(...) returns the number of bytes sent upon success,
+       mask that and return zero upon success instead*/
+       return (err < 0) ? err : 0;
+}
+
+/* Writes a byte to to the m5602 */
+int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x",
+              address, i2c_data);
+
+       memcpy(buf, bridge_urb_skeleton,
+              sizeof(bridge_urb_skeleton));
+       buf[1] = address;
+       buf[3] = i2c_data;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               0x04, 0x40, 0x19,
+                               0x0000, buf,
+                               4, M5602_URB_MSG_TIMEOUT);
+
+       /* usb_control_msg(...) returns the number of bytes sent upon success,
+          mask that and return zero upon success instead */
+       return (err < 0) ? err : 0;
+}
+
+/* Dump all the registers of the m5602 bridge,
+   unfortunately this breaks the camera until it's power cycled */
+static void m5602_dump_bridge(struct sd *sd)
+{
+       int i;
+       for (i = 0; i < 0x80; i++) {
+               unsigned char val = 0;
+               m5602_read_bridge(sd, i, &val);
+               info("ALi m5602 address 0x%x contains 0x%x", i, val);
+       }
+       info("Warning: The camera probably won't work until it's power cycled");
+}
+
+static int m5602_probe_sensor(struct sd *sd)
+{
+       /* Try the po1030 */
+       sd->sensor = &po1030;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the mt9m111 sensor */
+       sd->sensor = &mt9m111;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the s5k4aa */
+       sd->sensor = &s5k4aa;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the ov9650 */
+       sd->sensor = &ov9650;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the s5k83a */
+       sd->sensor = &s5k83a;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* More sensor probe function goes here */
+       info("Failed to find a sensor");
+       sd->sensor = NULL;
+       return -ENODEV;
+}
+
+static int m5602_configure(struct gspca_dev *gspca_dev,
+                          const struct usb_device_id *id);
+
+static int m5602_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err;
+
+       PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam");
+       /* Run the init sequence */
+       err = sd->sensor->init(sd);
+
+       return err;
+}
+
+static int m5602_start_transfer(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* Send start command to the camera */
+       const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
+       memcpy(buf, buffer, sizeof(buffer));
+       usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x04, 0x40, 0x19, 0x0000, buf,
+                       4, M5602_URB_MSG_TIMEOUT);
+
+       PDEBUG(DBG_V4L2, "Transfer started");
+       return 0;
+}
+
+static void m5602_urb_complete(struct gspca_dev *gspca_dev,
+                       struct gspca_frame *frame,
+                       __u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (len < 6) {
+               PDEBUG(DBG_DATA, "Packet is less than 6 bytes");
+               return;
+       }
+
+       /* Frame delimiter: ff xx xx xx ff ff */
+       if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
+           data[2] != sd->frame_id) {
+               PDEBUG(DBG_DATA, "Frame delimiter detected");
+               sd->frame_id = data[2];
+
+               /* Remove the extra fluff appended on each header */
+               data += 6;
+               len -= 6;
+
+               /* Complete the last frame (if any) */
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       frame, data, 0);
+               sd->frame_count++;
+
+               /* Create a new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
+
+               PDEBUG(DBG_V4L2, "Starting new frame %d",
+                      sd->frame_count);
+
+       } else {
+               int cur_frame_len = frame->data_end - frame->data;
+
+               /* Remove urb header */
+               data += 4;
+               len -= 4;
+
+               if (cur_frame_len + len <= frame->v4l2_buf.length) {
+                       PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes",
+                              sd->frame_count, len);
+
+                       gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                                       data, len);
+               } else if (frame->v4l2_buf.length - cur_frame_len > 0) {
+                       /* Add the remaining data up to frame size */
+                       gspca_frame_add(gspca_dev, INTER_PACKET, frame, data,
+                                       frame->v4l2_buf.length - cur_frame_len);
+               }
+       }
+}
+
+static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
+{
+       /* Is there are a command to stop a data transfer? */
+}
+
+/* sub-driver description, the ctrl and nctrl is filled at probe time */
+static struct sd_desc sd_desc = {
+       .name           = MODULE_NAME,
+       .config         = m5602_configure,
+       .init           = m5602_init,
+       .start          = m5602_start_transfer,
+       .stopN          = m5602_stop_transfer,
+       .pkt_scan       = m5602_urb_complete
+};
+
+/* this function is called at probe time */
+static int m5602_configure(struct gspca_dev *gspca_dev,
+                          const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       int err;
+
+       PDEBUG(DBG_GSPCA, "m5602_configure start");
+
+       cam = &gspca_dev->cam;
+       cam->epaddr = M5602_ISOC_ENDPOINT_ADDR;
+       sd->desc = &sd_desc;
+
+       if (dump_bridge)
+               m5602_dump_bridge(sd);
+
+       /* Probe sensor */
+       err = m5602_probe_sensor(sd);
+       if (err)
+               goto fail;
+
+       PDEBUG(DBG_GSPCA, "m5602_configure end");
+       return 0;
+
+fail:
+       PDEBUG(DBG_GSPCA, "m5602_configure failed");
+       cam->cam_mode = NULL;
+       cam->nmodes = 0;
+
+       return err;
+}
+
+static int m5602_probe(struct usb_interface *intf,
+                      const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+                              THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = m5602_table,
+       .probe = m5602_probe,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
+       .disconnect = gspca_disconnect
+};
+
+/* -- module insert / remove -- */
+static int __init mod_m5602_init(void)
+{
+       if (usb_register(&sd_driver) < 0)
+               return -1;
+       PDEBUG(D_PROBE, "m5602 module registered");
+       return 0;
+}
+static void __exit mod_m5602_exit(void)
+{
+       usb_deregister(&sd_driver);
+       PDEBUG(D_PROBE, "m5602 module deregistered");
+}
+
+module_init(mod_m5602_init);
+module_exit(mod_m5602_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "toggles debug on/off");
+
+module_param(force_sensor, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(force_sensor,
+               "force detection of sensor, "
+               "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030");
+
+module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
+
+module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
+               "at startup providing a sensor is found");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
new file mode 100644 (file)
index 0000000..566d492
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_mt9m111.h"
+
+int mt9m111_probe(struct sd *sd)
+{
+       u8 data[2] = {0x00, 0x00};
+       int i;
+
+       if (force_sensor) {
+               if (force_sensor == MT9M111_SENSOR) {
+                       info("Forcing a %s sensor", mt9m111.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       info("Probing for a mt9m111 sensor");
+
+       /* Do the preinit */
+       for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
+               if (preinit_mt9m111[i][0] == BRIDGE) {
+                       m5602_write_bridge(sd,
+                               preinit_mt9m111[i][1],
+                               preinit_mt9m111[i][2]);
+               } else {
+                       data[0] = preinit_mt9m111[i][2];
+                       data[1] = preinit_mt9m111[i][3];
+                       mt9m111_write_sensor(sd,
+                               preinit_mt9m111[i][1], data, 2);
+               }
+       }
+
+       if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+               return -ENODEV;
+
+       if ((data[0] == 0x14) && (data[1] == 0x3a)) {
+               info("Detected a mt9m111 sensor");
+               goto sensor_found;
+       }
+
+       return -ENODEV;
+
+sensor_found:
+       sd->gspca_dev.cam.cam_mode = mt9m111.modes;
+       sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
+       sd->desc->ctrls = mt9m111.ctrls;
+       sd->desc->nctrls = mt9m111.nctrls;
+       return 0;
+}
+
+int mt9m111_init(struct sd *sd)
+{
+       int i, err = 0;
+
+       /* Init the sensor */
+       for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
+               u8 data[2];
+
+               if (init_mt9m111[i][0] == BRIDGE) {
+                       err = m5602_write_bridge(sd,
+                               init_mt9m111[i][1],
+                               init_mt9m111[i][2]);
+               } else {
+                       data[0] = init_mt9m111[i][2];
+                       data[1] = init_mt9m111[i][3];
+                       err = mt9m111_write_sensor(sd,
+                               init_mt9m111[i][1], data, 2);
+               }
+       }
+
+       if (dump_sensor)
+               mt9m111_dump_registers(sd);
+
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_power_down(struct sd *sd)
+{
+       return 0;
+}
+
+int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                 data, 2);
+       *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
+       PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+
+       /* Set the correct page map */
+       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               goto out;
+
+       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       if (err < 0)
+               goto out;
+
+       data[0] = (data[0] & 0xfe) | val;
+       err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                  data, 2);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                 data, 2);
+       *val = data[0] & MT9M111_RMB_MIRROR_COLS;
+       PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
+
+       /* Set the correct page map */
+       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               goto out;
+
+       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       if (err < 0)
+               goto out;
+
+       data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
+       err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                       data, 2);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err, tmp;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
+       tmp = ((data[1] << 8) | data[0]);
+
+       *val = ((tmp & (1 << 10)) * 2) |
+             ((tmp & (1 <<  9)) * 2) |
+             ((tmp & (1 <<  8)) * 2) |
+              (tmp & 0x7f);
+
+       PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err, tmp;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Set the correct page map */
+       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               goto out;
+
+       if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
+               return -EINVAL;
+
+       if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
+           (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
+               tmp = (1 << 10) | (val << 9) |
+                               (val << 8) | (val / 8);
+       else if ((val >= INITIAL_MAX_GAIN * 2) &&
+                (val <  INITIAL_MAX_GAIN * 2 * 2))
+               tmp = (1 << 9) | (1 << 8) | (val / 4);
+       else if ((val >= INITIAL_MAX_GAIN) &&
+                (val < INITIAL_MAX_GAIN * 2))
+               tmp = (1 << 8) | (val / 2);
+       else
+               tmp = val;
+
+       data[1] = (tmp & 0xff00) >> 8;
+       data[0] = (tmp & 0xff);
+       PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+              data[1], data[0]);
+
+       err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+                                  data, 2);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_read_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len) {
+       int err, i;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                                sd->sensor->i2c_slave_id);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
+       if (err < 0)
+               goto out;
+
+       for (i = 0; i < len && !err; i++) {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(DBG_TRACE, "Reading sensor register "
+                      "0x%x contains 0x%x ", address, *i2c_data);
+       }
+out:
+       return (err < 0) ? err : 0;
+}
+
+int mt9m111_write_sensor(struct sd *sd, const u8 address,
+                               u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* No sensor with a data width larger
+          than 16 bits has yet been seen, nor with 0 :p*/
+       if (len > 2 || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton,
+              sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the tailer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+void mt9m111_dump_registers(struct sd *sd)
+{
+       u8 address, value[2] = {0x00, 0x00};
+
+       info("Dumping the mt9m111 register state");
+
+       info("Dumping the mt9m111 sensor core registers");
+       value[1] = MT9M111_SENSOR_CORE;
+       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               mt9m111_read_sensor(sd, address, value, 2);
+               info("register 0x%x contains 0x%x%x",
+                    address, value[0], value[1]);
+       }
+
+       info("Dumping the mt9m111 color pipeline registers");
+       value[1] = MT9M111_COLORPIPE;
+       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               mt9m111_read_sensor(sd, address, value, 2);
+               info("register 0x%x contains 0x%x%x",
+                    address, value[0], value[1]);
+       }
+
+       info("Dumping the mt9m111 camera control registers");
+       value[1] = MT9M111_CAMERA_CONTROL;
+       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               mt9m111_read_sensor(sd, address, value, 2);
+               info("register 0x%x contains 0x%x%x",
+                    address, value[0], value[1]);
+       }
+
+       info("mt9m111 register state dump complete");
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
new file mode 100644 (file)
index 0000000..79a5d88
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Some defines taken from the mt9m111 sensor driver
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_MT9M111_H_
+#define M5602_MT9M111_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define MT9M111_SC_CHIPVER                     0x00
+#define MT9M111_SC_ROWSTART                    0x01
+#define MT9M111_SC_COLSTART                    0x02
+#define MT9M111_SC_WINDOW_HEIGHT               0x03
+#define MT9M111_SC_WINDOW_WIDTH                        0x04
+#define MT9M111_SC_HBLANK_CONTEXT_B            0x05
+#define MT9M111_SC_VBLANK_CONTEXT_B            0x06
+#define MT9M111_SC_HBLANK_CONTEXT_A            0x07
+#define MT9M111_SC_VBLANK_CONTEXT_A            0x08
+#define MT9M111_SC_SHUTTER_WIDTH               0x09
+#define MT9M111_SC_ROW_SPEED                   0x0a
+
+#define MT9M111_SC_EXTRA_DELAY                 0x0b
+#define MT9M111_SC_SHUTTER_DELAY               0x0c
+#define MT9M111_SC_RESET                       0x0d
+#define MT9M111_SC_R_MODE_CONTEXT_B            0x20
+#define MT9M111_SC_R_MODE_CONTEXT_A            0x21
+#define MT9M111_SC_FLASH_CONTROL               0x23
+#define MT9M111_SC_GREEN_1_GAIN                        0x2b
+#define MT9M111_SC_BLUE_GAIN                   0x2c
+#define MT9M111_SC_RED_GAIN                    0x2d
+#define MT9M111_SC_GREEN_2_GAIN                        0x2e
+#define MT9M111_SC_GLOBAL_GAIN                 0x2f
+
+#define MT9M111_RMB_MIRROR_ROWS                        (1 << 0)
+#define MT9M111_RMB_MIRROR_COLS                        (1 << 1)
+
+#define MT9M111_CONTEXT_CONTROL                        0xc8
+#define MT9M111_PAGE_MAP                       0xf0
+#define MT9M111_BYTEWISE_ADDRESS               0xf1
+
+#define MT9M111_CP_OPERATING_MODE_CTL          0x06
+#define MT9M111_CP_LUMA_OFFSET                 0x34
+#define MT9M111_CP_LUMA_CLIP                   0x35
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
+#define MT9M111_CP_LENS_CORRECTION_1           0x3b
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_A       0x4c
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_B       0x4d
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
+#define MT9M111_CP_GLOBAL_CLK_CONTROL          0xb3
+
+#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18   0x65
+#define MT9M111_CC_AWB_PARAMETER_7             0x28
+
+#define MT9M111_SENSOR_CORE                    0x00
+#define MT9M111_COLORPIPE                      0x01
+#define MT9M111_CAMERA_CONTROL                 0x02
+
+#define INITIAL_MAX_GAIN                       64
+#define DEFAULT_GAIN                           283
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+extern unsigned int m5602_debug;
+
+int mt9m111_probe(struct sd *sd);
+int mt9m111_init(struct sd *sd);
+int mt9m111_power_down(struct sd *sd);
+
+int mt9m111_read_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len);
+
+int mt9m111_write_sensor(struct sd *sd, const u8 address,
+                        u8 *i2c_data, const u8 len);
+
+void mt9m111_dump_registers(struct sd *sd);
+
+int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor mt9m111 = {
+       .name = "MT9M111",
+
+       .i2c_slave_id = 0xba,
+
+       .probe = mt9m111_probe,
+       .init = mt9m111_init,
+       .power_down = mt9m111_power_down,
+
+       .read_sensor = mt9m111_read_sensor,
+       .write_sensor = mt9m111_write_sensor,
+
+       .nctrls = 3,
+       .ctrls = {
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_vflip,
+               .get = mt9m111_get_vflip
+       }, {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_hflip,
+               .get = mt9m111_get_hflip
+       }, {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0,
+                       .maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
+                       .step           = 1,
+                       .default_value  = DEFAULT_GAIN,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_hflip,
+               .get = mt9m111_get_hflip
+       }
+       },
+
+       .nmodes = 1,
+       .modes = {
+       {
+               M5602_DEFAULT_FRAME_WIDTH,
+               M5602_DEFAULT_FRAME_HEIGHT,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+               .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+       }
+};
+
+static const unsigned char preinit_mt9m111[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
+};
+
+static const unsigned char init_mt9m111[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xde},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xff},
+       {SENSOR, MT9M111_SC_RESET, 0xff, 0xf7},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+
+       {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0xff, 0xff},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+       {SENSOR, 0xd0, 0x00, 0x40},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+       {SENSOR, 0x30, 0x04, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+       {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+       {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+       {SENSOR, 0xd0, 0x00, 0x40},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+       {SENSOR, 0x30, 0x04, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+       {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+       {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+       {SENSOR, 0xd0, 0x00, 0x40},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x18},
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x04},
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x08},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x38},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x03},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x03},
+       {SENSOR, 0x30, 0x04, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x07, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0xf4},
+       {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xea},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0xd0, 0x00, 0x40},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+       {SENSOR, 0x30, 0x04, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe3, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+       {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x00, 0xe6},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x09},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x0c},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x04},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xb3, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CP_GLOBAL_CLK_CONTROL, 0x00, 0x03},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x05},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00, 0x10},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xcd, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0xd0, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0xd0, 0x00, 0x40},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x07},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x28, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {BRIDGE, M5602_XB_I2C_DEV_ADDR, 0xba, 0x00},
+       {BRIDGE, M5602_XB_I2C_REG_ADDR, 0x33, 0x00},
+       {BRIDGE, M5602_XB_I2C_CTRL, 0x1a, 0x00},
+
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, 0x08},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d},
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12},
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00},
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60},
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_B, 0x01, 0x0f},
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f},
+       {SENSOR, 0x30, 0x04, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       /* Set number of blank rows chosen to 400 */
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+       /* Set the global gain to 283 (of 512) */
+       {SENSOR, MT9M111_SC_GLOBAL_GAIN, 0x03, 0x63}
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
new file mode 100644 (file)
index 0000000..31c5896
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_ov9650.h"
+
+int ov9650_read_sensor(struct sd *sd, const u8 address,
+                     u8 *i2c_data, const u8 len)
+{
+       int err, i;
+
+       /* The ov9650 registers have a max depth of one byte */
+       if (len > 1 || !len)
+               return -EINVAL;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+
+       m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                          ov9650.i2c_slave_id);
+       m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
+       m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+
+       for (i = 0; i < len; i++) {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(DBG_TRACE, "Reading sensor register "
+                               "0x%x containing 0x%x ", address, *i2c_data);
+       }
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* The ov9650 only supports one byte writes */
+       if (len > 1 || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton,
+              sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       /* Special case larger sensor writes */
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the tailer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_probe(struct sd *sd)
+{
+       u8 prod_id = 0, ver_id = 0, i;
+
+       if (force_sensor) {
+               if (force_sensor == OV9650_SENSOR) {
+                       info("Forcing an %s sensor", ov9650.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor,
+                  don't try to probe this one */
+               return -ENODEV;
+       }
+
+       info("Probing for an ov9650 sensor");
+
+       /* Run the pre-init to actually probe the unit */
+       for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) {
+               u8 data = preinit_ov9650[i][2];
+               if (preinit_ov9650[i][0] == SENSOR)
+                       ov9650_write_sensor(sd,
+                                           preinit_ov9650[i][1], &data, 1);
+               else
+                       m5602_write_bridge(sd, preinit_ov9650[i][1], data);
+       }
+
+       if (ov9650_read_sensor(sd, OV9650_PID, &prod_id, 1))
+               return -ENODEV;
+
+       if (ov9650_read_sensor(sd, OV9650_VER, &ver_id, 1))
+               return -ENODEV;
+
+       if ((prod_id == 0x96) && (ver_id == 0x52)) {
+               info("Detected an ov9650 sensor");
+               goto sensor_found;
+       }
+
+       return -ENODEV;
+
+sensor_found:
+       sd->gspca_dev.cam.cam_mode = ov9650.modes;
+       sd->gspca_dev.cam.nmodes = ov9650.nmodes;
+       sd->desc->ctrls = ov9650.ctrls;
+       sd->desc->nctrls = ov9650.nctrls;
+       return 0;
+}
+
+int ov9650_init(struct sd *sd)
+{
+       int i, err = 0;
+       u8 data;
+
+       if (dump_sensor)
+               ov9650_dump_registers(sd);
+
+       for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
+               data = init_ov9650[i][2];
+               if (init_ov9650[i][0] == SENSOR)
+                       err = ov9650_write_sensor(sd, init_ov9650[i][1],
+                                                 &data, 1);
+               else
+                       err = m5602_write_bridge(sd, init_ov9650[i][1], data);
+       }
+
+       if (!err && dmi_check_system(ov9650_flip_dmi_table)) {
+               info("vflip quirk active");
+               data = 0x30;
+               err = ov9650_write_sensor(sd, OV9650_MVFP, &data, 1);
+       }
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_power_down(struct sd *sd)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(power_down_ov9650); i++) {
+               u8 data = power_down_ov9650[i][2];
+               if (power_down_ov9650[i][0] == SENSOR)
+                       ov9650_write_sensor(sd,
+                                           power_down_ov9650[i][1], &data, 1);
+               else
+                       m5602_write_bridge(sd, power_down_ov9650[i][1], data);
+       }
+
+       return 0;
+}
+
+int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       err = ov9650_read_sensor(sd, OV9650_COM1, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+       *val = i2c_data & 0x03;
+
+       err = ov9650_read_sensor(sd, OV9650_AECH, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+       *val |= (i2c_data << 2);
+
+       err = ov9650_read_sensor(sd, OV9650_AECHM, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+       *val |= (i2c_data & 0x3f) << 10;
+
+       PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       PDEBUG(DBG_V4L2_CID, "Set exposure to %d",
+              val & 0xffff);
+
+       /* The 6 MSBs */
+       i2c_data = (val >> 10) & 0x3f;
+       err = ov9650_write_sensor(sd, OV9650_AECHM,
+                                 &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       /* The 8 middle bits */
+       i2c_data = (val >> 2) & 0xff;
+       err = ov9650_write_sensor(sd, OV9650_AECH,
+                                 &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       /* The 2 LSBs */
+       i2c_data = val & 0x03;
+       err = ov9650_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       *val = (i2c_data & 0x03) << 8;
+
+       err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+       *val |= i2c_data;
+       PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* The 2 MSB */
+       /* Read the OV9650_VREF register first to avoid
+          corrupting the VREF high and low bits */
+       ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       /* Mask away all uninteresting bits */
+       i2c_data = ((val & 0x0300) >> 2) |
+                       (i2c_data & 0x3F);
+       err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+
+       /* The 8 LSBs */
+       i2c_data = val & 0xff;
+       err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1);
+       *val = i2c_data;
+
+       PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set red gain to %d",
+                            val & 0xff);
+
+       i2c_data = val & 0xff;
+       err = ov9650_write_sensor(sd, OV9650_RED, &i2c_data, 1);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+       *val = i2c_data;
+
+       PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set blue gain to %d",
+              val & 0xff);
+
+       i2c_data = val & 0xff;
+       err = ov9650_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+       if (dmi_check_system(ov9650_flip_dmi_table))
+               *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1;
+       else
+               *val = (i2c_data & OV9650_HFLIP) >> 5;
+       PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val);
+       err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       if (dmi_check_system(ov9650_flip_dmi_table))
+               i2c_data = ((i2c_data & 0xdf) |
+                               (((val ? 0 : 1) & 0x01) << 5));
+       else
+               i2c_data = ((i2c_data & 0xdf) |
+                               ((val & 0x01) << 5));
+
+       err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+       if (dmi_check_system(ov9650_flip_dmi_table))
+               *val = ((i2c_data & 0x10) >> 4) ? 0 : 1;
+       else
+               *val = (i2c_data & 0x10) >> 4;
+       PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+       err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       if (dmi_check_system(ov9650_flip_dmi_table))
+               i2c_data = ((i2c_data & 0xef) |
+                               (((val ? 0 : 1) & 0x01) << 4));
+       else
+               i2c_data = ((i2c_data & 0xef) |
+                               ((val & 0x01) << 4));
+
+       err = ov9650_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+       *val = (i2c_data & 0x03) << 8;
+
+       err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+       *val |= i2c_data;
+       PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff);
+
+       /* Read the OV9650_VREF register first to avoid
+               corrupting the VREF high and low bits */
+       err = ov9650_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       /* Mask away all uninteresting bits */
+       i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F);
+       err = ov9650_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       /* The 8 LSBs */
+       i2c_data = val & 0xff;
+       err = ov9650_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       *val = (i2c_data & OV9650_AWB_EN) >> 1;
+       PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val);
+       err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
+       err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       *val = (i2c_data & OV9650_AGC_EN) >> 2;
+       PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val);
+       err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
+       err = ov9650_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+out:
+       return (err < 0) ? err : 0;
+}
+
+void ov9650_dump_registers(struct sd *sd)
+{
+       int address;
+       info("Dumping the ov9650 register state");
+       for (address = 0; address < 0xa9; address++) {
+               u8 value;
+               ov9650_read_sensor(sd, address, &value, 1);
+               info("register 0x%x contains 0x%x",
+                    address, value);
+       }
+
+       info("ov9650 register state dump complete");
+
+       info("Probing for which registers that are read/write");
+       for (address = 0; address < 0xff; address++) {
+               u8 old_value, ctrl_value;
+               u8 test_value[2] = {0xff, 0xff};
+
+               ov9650_read_sensor(sd, address, &old_value, 1);
+               ov9650_write_sensor(sd, address, test_value, 1);
+               ov9650_read_sensor(sd, address, &ctrl_value, 1);
+
+               if (ctrl_value == test_value[0])
+                       info("register 0x%x is writeable", address);
+               else
+                       info("register 0x%x is read only", address);
+
+               /* Restore original value */
+               ov9650_write_sensor(sd, address, &old_value, 1);
+       }
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
new file mode 100644 (file)
index 0000000..2f29cb0
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_OV9650_H_
+#define M5602_OV9650_H_
+
+#include <linux/dmi.h>
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define OV9650_GAIN                    0x00
+#define OV9650_BLUE                    0x01
+#define OV9650_RED                     0x02
+#define OV9650_VREF                    0x03
+#define OV9650_COM1                    0x04
+#define OV9650_BAVE                    0x05
+#define OV9650_GEAVE                   0x06
+#define OV9650_RSVD7                   0x07
+#define OV9650_PID                     0x0a
+#define OV9650_VER                     0x0b
+#define OV9650_COM3                    0x0c
+#define OV9650_COM5                    0x0e
+#define OV9650_COM6                    0x0f
+#define OV9650_AECH                    0x10
+#define OV9650_CLKRC                   0x11
+#define OV9650_COM7                    0x12
+#define OV9650_COM8                    0x13
+#define OV9650_COM9                    0x14
+#define OV9650_COM10                   0x15
+#define OV9650_RSVD16                  0x16
+#define OV9650_HSTART                  0x17
+#define OV9650_HSTOP                   0x18
+#define OV9650_VSTRT                   0x19
+#define OV9650_VSTOP                   0x1a
+#define OV9650_PSHFT                   0x1b
+#define OV9650_MVFP                    0x1e
+#define OV9650_AEW                     0x24
+#define OV9650_AEB                     0x25
+#define OV9650_VPT                     0x26
+#define OV9650_BBIAS                   0x27
+#define OV9650_GbBIAS                  0x28
+#define OV9650_Gr_COM                  0x29
+#define OV9650_RBIAS                   0x2c
+#define OV9650_HREF                    0x32
+#define OV9650_CHLF                    0x33
+#define OV9650_ARBLM                   0x34
+#define OV9650_RSVD35                  0x35
+#define OV9650_RSVD36                  0x36
+#define OV9650_ADC                     0x37
+#define OV9650_ACOM38                  0x38
+#define OV9650_OFON                    0x39
+#define OV9650_TSLB                    0x3a
+#define OV9650_COM12                   0x3c
+#define OV9650_COM13                   0x3d
+#define OV9650_COM15                   0x40
+#define OV9650_COM16                   0x41
+#define OV9650_LCC1                    0x62
+#define OV9650_LCC2                    0x63
+#define OV9650_LCC3                    0x64
+#define OV9650_LCC4                    0x65
+#define OV9650_LCC5                    0x66
+#define OV9650_HV                      0x69
+#define OV9650_DBLV                    0x6b
+#define OV9650_COM21                   0x8b
+#define OV9650_COM22                   0x8c
+#define OV9650_COM24                   0x8e
+#define OV9650_DBLC1                   0x8f
+#define OV9650_RSVD94                  0x94
+#define OV9650_RSVD95                  0x95
+#define OV9650_RSVD96                  0x96
+#define OV9650_LCCFB                   0x9d
+#define OV9650_LCCFR                   0x9e
+#define OV9650_AECHM                   0xa1
+#define OV9650_COM26                   0xa5
+#define OV9650_ACOMA8                  0xa8
+#define OV9650_ACOMA9                  0xa9
+
+#define OV9650_REGISTER_RESET          (1 << 7)
+#define OV9650_VGA_SELECT              (1 << 6)
+#define OV9650_RGB_SELECT              (1 << 2)
+#define OV9650_RAW_RGB_SELECT          (1 << 0)
+
+#define OV9650_FAST_AGC_AEC            (1 << 7)
+#define OV9650_AEC_UNLIM_STEP_SIZE     (1 << 6)
+#define OV9650_BANDING                 (1 << 5)
+#define OV9650_AGC_EN                  (1 << 2)
+#define OV9650_AWB_EN                  (1 << 1)
+#define OV9650_AEC_EN                  (1 << 0)
+
+#define OV9650_VARIOPIXEL              (1 << 2)
+#define OV9650_SYSTEM_CLK_SEL          (1 << 7)
+#define OV9650_SLAM_MODE               (1 << 4)
+
+#define OV9650_VFLIP                   (1 << 4)
+#define OV9650_HFLIP                   (1 << 5)
+
+#define GAIN_DEFAULT                   0x14
+#define RED_GAIN_DEFAULT               0x70
+#define BLUE_GAIN_DEFAULT              0x20
+#define EXPOSURE_DEFAULT               0x5003
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+extern unsigned int m5602_debug;
+
+int ov9650_probe(struct sd *sd);
+int ov9650_init(struct sd *sd);
+int ov9650_power_down(struct sd *sd);
+
+int ov9650_read_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len);
+int ov9650_write_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len);
+
+void ov9650_dump_registers(struct sd *sd);
+
+int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val);
+int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor ov9650 = {
+       .name = "OV9650",
+       .i2c_slave_id = 0x60,
+       .probe = ov9650_probe,
+       .init = ov9650_init,
+       .power_down = ov9650_power_down,
+       .read_sensor = ov9650_read_sensor,
+       .write_sensor = ov9650_write_sensor,
+
+       .nctrls = 8,
+       .ctrls = {
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "exposure",
+                       .minimum        = 0x00,
+                       .maximum        = 0xffff,
+                       .step           = 0x1,
+                       .default_value  = EXPOSURE_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_exposure,
+               .get = ov9650_get_exposure
+       }, {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0x00,
+                       .maximum        = 0x3ff,
+                       .step           = 0x1,
+                       .default_value  = GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_gain,
+               .get = ov9650_get_gain
+       }, {
+               {
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "red balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = RED_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_red_balance,
+               .get = ov9650_get_red_balance
+       }, {
+               {
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "blue balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = BLUE_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_blue_balance,
+               .get = ov9650_get_blue_balance
+       }, {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_hflip,
+               .get = ov9650_get_hflip
+       }, {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_vflip,
+               .get = ov9650_get_vflip
+       }, {
+               {
+                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto white balance",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_auto_white_balance,
+               .get = ov9650_get_auto_white_balance
+       }, {
+               {
+                       .id             = V4L2_CID_AUTOGAIN,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto gain control",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_auto_gain,
+               .get = ov9650_get_auto_gain
+       }
+       },
+
+       .nmodes = 1,
+       .modes = {
+       {
+               M5602_DEFAULT_FRAME_WIDTH,
+               M5602_DEFAULT_FRAME_HEIGHT,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+               .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+       }
+};
+
+static const unsigned char preinit_ov9650[][3] =
+{
+       /* [INITCAM] */
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+       /* Reset chip */
+       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+       /* Enable double clock */
+       {SENSOR, OV9650_CLKRC, 0x80},
+       /* Do something out of spec with the power */
+       {SENSOR, OV9650_OFON, 0x40}
+};
+
+static const unsigned char init_ov9650[][3] =
+{
+       /* [INITCAM] */
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+       /* Reset chip */
+       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+       /* Enable double clock */
+       {SENSOR, OV9650_CLKRC, 0x80},
+       /* Do something out of spec with the power */
+       {SENSOR, OV9650_OFON, 0x40},
+
+       /* Set QQVGA */
+       {SENSOR, OV9650_COM1, 0x20},
+       /* Set fast AGC/AEC algorithm with unlimited step size */
+       {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
+                             OV9650_AEC_UNLIM_STEP_SIZE |
+                             OV9650_AWB_EN | OV9650_AGC_EN},
+
+       {SENSOR, OV9650_CHLF, 0x10},
+       {SENSOR, OV9650_ARBLM, 0xbf},
+       {SENSOR, OV9650_ACOM38, 0x81},
+       /* Turn off color matrix coefficient double option */
+       {SENSOR, OV9650_COM16, 0x00},
+               /* Enable color matrix for RGB/YUV, Delay Y channel,
+       set output Y/UV delay to 1 */
+       {SENSOR, OV9650_COM13, 0x19},
+       /* Enable digital BLC, Set output mode to U Y V Y */
+       {SENSOR, OV9650_TSLB, 0x0c},
+       /* Limit the AGC/AEC stable upper region */
+       {SENSOR, OV9650_COM24, 0x00},
+       /* Enable HREF and some out of spec things */
+       {SENSOR, OV9650_COM12, 0x73},
+               /* Set all DBLC offset signs to positive and
+       do some out of spec stuff */
+       {SENSOR, OV9650_DBLC1, 0xdf},
+       {SENSOR, OV9650_COM21, 0x06},
+       {SENSOR, OV9650_RSVD35, 0x91},
+       /* Necessary, no camera stream without it */
+       {SENSOR, OV9650_RSVD16, 0x06},
+       {SENSOR, OV9650_RSVD94, 0x99},
+       {SENSOR, OV9650_RSVD95, 0x99},
+       {SENSOR, OV9650_RSVD96, 0x04},
+       /* Enable full range output */
+       {SENSOR, OV9650_COM15, 0x0},
+               /* Enable HREF at optical black, enable ADBLC bias,
+       enable ADBLC, reset timings at format change */
+       {SENSOR, OV9650_COM6, 0x4b},
+       /* Subtract 32 from the B channel bias */
+       {SENSOR, OV9650_BBIAS, 0xa0},
+       /* Subtract 32 from the Gb channel bias */
+       {SENSOR, OV9650_GbBIAS, 0xa0},
+       /* Do not bypass the analog BLC and to some out of spec stuff */
+       {SENSOR, OV9650_Gr_COM, 0x00},
+       /* Subtract 32 from the R channel bias */
+       {SENSOR, OV9650_RBIAS, 0xa0},
+       /* Subtract 32 from the R channel bias */
+       {SENSOR, OV9650_RBIAS, 0x0},
+       {SENSOR, OV9650_COM26, 0x80},
+       {SENSOR, OV9650_ACOMA9, 0x98},
+       /* Set the AGC/AEC stable region upper limit */
+       {SENSOR, OV9650_AEW, 0x68},
+       /* Set the AGC/AEC stable region lower limit */
+       {SENSOR, OV9650_AEB, 0x5c},
+       /* Set the high and low limit nibbles to 3 */
+       {SENSOR, OV9650_VPT, 0xc3},
+               /* Set the Automatic Gain Ceiling (AGC) to 128x,
+       drop VSYNC at frame drop,
+       limit exposure timing,
+       drop frame when the AEC step is larger than the exposure gap */
+       {SENSOR, OV9650_COM9, 0x6e},
+       /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
+       and set PWDN to SLVS (slave mode vertical sync) */
+       {SENSOR, OV9650_COM10, 0x42},
+       /* Set horizontal column start high to default value */
+       {SENSOR, OV9650_HSTART, 0x1a},
+       /* Set horizontal column end */
+       {SENSOR, OV9650_HSTOP, 0xbf},
+       /* Complementing register to the two writes above */
+       {SENSOR, OV9650_HREF, 0xb2},
+       /* Set vertical row start high bits */
+       {SENSOR, OV9650_VSTRT, 0x02},
+       /* Set vertical row end low bits */
+       {SENSOR, OV9650_VSTOP, 0x7e},
+       /* Set complementing vertical frame control */
+       {SENSOR, OV9650_VREF, 0x10},
+       /* Set raw RGB output format with VGA resolution */
+       {SENSOR, OV9650_COM7, OV9650_VGA_SELECT |
+                             OV9650_RGB_SELECT |
+                             OV9650_RAW_RGB_SELECT},
+       {SENSOR, OV9650_ADC, 0x04},
+       {SENSOR, OV9650_HV, 0x40},
+       /* Enable denoise, and white-pixel erase */
+       {SENSOR, OV9650_COM22, 0x23},
+
+       /* Set the high bits of the exposure value */
+       {SENSOR, OV9650_AECH, ((EXPOSURE_DEFAULT & 0xff00) >> 8)},
+
+       /* Set the low bits of the exposure value */
+       {SENSOR, OV9650_COM1, (EXPOSURE_DEFAULT & 0xff)},
+       {SENSOR, OV9650_GAIN, GAIN_DEFAULT},
+       {SENSOR, OV9650_BLUE, BLUE_GAIN_DEFAULT},
+       {SENSOR, OV9650_RED, RED_GAIN_DEFAULT},
+
+       {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
+       {SENSOR, OV9650_COM5, OV9650_SYSTEM_CLK_SEL},
+
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x09},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x5e},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0xde}
+};
+
+static const unsigned char power_down_ov9650[][3] =
+{
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {SENSOR, OV9650_COM7, 0x80},
+       {SENSOR, OV9650_OFON, 0xf4},
+       {SENSOR, OV9650_MVFP, 0x80},
+       {SENSOR, OV9650_DBLV, 0x3f},
+       {SENSOR, OV9650_RSVD36, 0x49},
+       {SENSOR, OV9650_COM7, 0x05},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0}
+};
+
+/* Vertically and horizontally flips the image if matched, needed for machines
+   where the sensor is mounted upside down */
+static
+    const
+       struct dmi_system_id ov9650_flip_dmi_table[] = {
+       {
+               .ident = "ASUS A6VC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+               }
+       },
+       {
+               .ident = "ASUS A6VM",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+               }
+       },
+       {
+               .ident = "ASUS A6JC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
+               }
+       },
+       {
+               .ident = "ASUS A6Kt",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
+               }
+       },
+       { }
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
new file mode 100644 (file)
index 0000000..08c015b
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Driver for the po1030 sensor
+ *
+ * Copyright (c) 2008 Erik Andren
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_po1030.h"
+
+int po1030_probe(struct sd *sd)
+{
+       u8 prod_id = 0, ver_id = 0, i;
+
+       if (force_sensor) {
+               if (force_sensor == PO1030_SENSOR) {
+                       info("Forcing a %s sensor", po1030.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       info("Probing for a po1030 sensor");
+
+       /* Run the pre-init to actually probe the unit */
+       for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
+               u8 data = preinit_po1030[i][2];
+               if (preinit_po1030[i][0] == SENSOR)
+                       po1030_write_sensor(sd,
+                               preinit_po1030[i][1], &data, 1);
+               else
+                       m5602_write_bridge(sd, preinit_po1030[i][1], data);
+       }
+
+       if (po1030_read_sensor(sd, 0x3, &prod_id, 1))
+               return -ENODEV;
+
+       if (po1030_read_sensor(sd, 0x4, &ver_id, 1))
+               return -ENODEV;
+
+       if ((prod_id == 0x02) && (ver_id == 0xef)) {
+               info("Detected a po1030 sensor");
+               goto sensor_found;
+       }
+       return -ENODEV;
+
+sensor_found:
+       sd->gspca_dev.cam.cam_mode = po1030.modes;
+       sd->gspca_dev.cam.nmodes = po1030.nmodes;
+       sd->desc->ctrls = po1030.ctrls;
+       sd->desc->nctrls = po1030.nctrls;
+       return 0;
+}
+
+int po1030_read_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len)
+{
+       int err, i;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+
+       m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                          sd->sensor->i2c_slave_id);
+       m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x10 + len);
+       m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+
+       for (i = 0; i < len; i++) {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(DBG_TRACE, "Reading sensor register "
+                               "0x%x containing 0x%x ", address, *i2c_data);
+       }
+       return (err < 0) ? err : 0;
+}
+
+int po1030_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* The po1030 only supports one byte writes */
+       if (len > 1 || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton, sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the footer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+int po1030_init(struct sd *sd)
+{
+       int i, err = 0;
+
+       /* Init the sensor */
+       for (i = 0; i < ARRAY_SIZE(init_po1030); i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_po1030[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                               init_po1030[i][1],
+                               init_po1030[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_po1030[i][2];
+                       err = po1030_write_sensor(sd,
+                               init_po1030[i][1], data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = init_po1030[i][2];
+                       data[1] = init_po1030[i][3];
+                       err = po1030_write_sensor(sd,
+                               init_po1030[i][1], data, 2);
+                       break;
+               default:
+                       info("Invalid stream command, exiting init");
+                       return -EINVAL;
+               }
+       }
+
+       if (dump_sensor)
+               po1030_dump_registers(sd);
+
+       return (err < 0) ? err : 0;
+}
+
+int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_H,
+                                &i2c_data, 1);
+       if (err < 0)
+               goto out;
+       *val = (i2c_data << 8);
+
+       err = po1030_read_sensor(sd, PO1030_REG_INTEGLINES_M,
+                                &i2c_data, 1);
+       *val |= i2c_data;
+
+       PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff);
+
+       i2c_data = ((val & 0xff00) >> 8);
+       PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x",
+              i2c_data);
+
+       err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H,
+                                 &i2c_data, 1);
+       if (err < 0)
+               goto out;
+
+       i2c_data = (val & 0xff);
+       PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x",
+              i2c_data);
+       err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M,
+                                 &i2c_data, 1);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN,
+                                &i2c_data, 1);
+       *val = i2c_data;
+       PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       i2c_data = val & 0xff;
+       PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data);
+       err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN,
+                                 &i2c_data, 1);
+       return (err < 0) ? err : 0;
+}
+
+int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN,
+                                &i2c_data, 1);
+       *val = i2c_data;
+       PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val);
+       return (err < 0) ? err : 0;
+}
+
+int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       i2c_data = val & 0xff;
+       PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data);
+       err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN,
+                                 &i2c_data, 1);
+       return (err < 0) ? err : 0;
+}
+
+int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+
+       err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN,
+                                &i2c_data, 1);
+       *val = i2c_data;
+       PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val);
+
+       return (err < 0) ? err : 0;
+}
+
+int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 i2c_data;
+       int err;
+       i2c_data = val & 0xff;
+       PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data);
+       err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN,
+                                 &i2c_data, 1);
+
+       return (err < 0) ? err : 0;
+}
+
+int po1030_power_down(struct sd *sd)
+{
+       return 0;
+}
+
+void po1030_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 value = 0;
+
+       info("Dumping the po1030 sensor core registers");
+       for (address = 0; address < 0x7f; address++) {
+               po1030_read_sensor(sd, address, &value, 1);
+               info("register 0x%x contains 0x%x",
+                    address, value);
+       }
+
+       info("po1030 register state dump complete");
+
+       info("Probing for which registers that are read/write");
+       for (address = 0; address < 0xff; address++) {
+               u8 old_value, ctrl_value;
+               u8 test_value[2] = {0xff, 0xff};
+
+               po1030_read_sensor(sd, address, &old_value, 1);
+               po1030_write_sensor(sd, address, test_value, 1);
+               po1030_read_sensor(sd, address, &ctrl_value, 1);
+
+               if (ctrl_value == test_value[0])
+                       info("register 0x%x is writeable", address);
+               else
+                       info("register 0x%x is read only", address);
+
+               /* Restore original value */
+               po1030_write_sensor(sd, address, &old_value, 1);
+       }
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
new file mode 100644 (file)
index 0000000..68f34c9
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Driver for the po1030 sensor.
+ * This is probably a pixel plus sensor but we haven't identified it yet
+ *
+ * Copyright (c) 2008 Erik Andren
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Register defines taken from Pascal Stangs Proxycon Armlib
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_PO1030_H_
+#define M5602_PO1030_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define PO1030_REG_DEVID_H             0x00
+#define PO1030_REG_DEVID_L             0x01
+#define PO1030_REG_FRAMEWIDTH_H                0x04
+#define PO1030_REG_FRAMEWIDTH_L                0x05
+#define PO1030_REG_FRAMEHEIGHT_H       0x06
+#define PO1030_REG_FRAMEHEIGHT_L       0x07
+#define PO1030_REG_WINDOWX_H           0x08
+#define PO1030_REG_WINDOWX_L           0x09
+#define PO1030_REG_WINDOWY_H           0x0a
+#define PO1030_REG_WINDOWY_L           0x0b
+#define PO1030_REG_WINDOWWIDTH_H       0x0c
+#define PO1030_REG_WINDOWWIDTH_L       0x0d
+#define PO1030_REG_WINDOWHEIGHT_H      0x0e
+#define PO1030_REG_WINDOWHEIGHT_L      0x0f
+
+#define PO1030_REG_GLOBALIBIAS         0x12
+#define PO1030_REG_PIXELIBIAS          0x13
+
+#define PO1030_REG_GLOBALGAIN          0x15
+#define PO1030_REG_RED_GAIN            0x16
+#define PO1030_REG_GREEN_1_GAIN                0x17
+#define PO1030_REG_BLUE_GAIN           0x18
+#define PO1030_REG_GREEN_2_GAIN                0x19
+
+#define PO1030_REG_INTEGLINES_H                0x1a
+#define PO1030_REG_INTEGLINES_M                0x1b
+#define PO1030_REG_INTEGLINES_L                0x1c
+
+#define PO1030_REG_CONTROL1            0x1d
+#define PO1030_REG_CONTROL2            0x1e
+#define PO1030_REG_CONTROL3            0x1f
+#define PO1030_REG_CONTROL4            0x20
+
+#define PO1030_REG_PERIOD50_H          0x23
+#define PO1030_REG_PERIOD50_L          0x24
+#define PO1030_REG_PERIOD60_H          0x25
+#define PO1030_REG_PERIOD60_L          0x26
+#define PO1030_REG_REGCLK167           0x27
+#define PO1030_REG_DELTA50             0x28
+#define PO1030_REG_DELTA60             0x29
+
+#define PO1030_REG_ADCOFFSET           0x2c
+
+/* Gamma Correction Coeffs */
+#define PO1030_REG_GC0                 0x2d
+#define PO1030_REG_GC1                 0x2e
+#define PO1030_REG_GC2                 0x2f
+#define PO1030_REG_GC3                 0x30
+#define PO1030_REG_GC4                 0x31
+#define PO1030_REG_GC5                 0x32
+#define PO1030_REG_GC6                 0x33
+#define PO1030_REG_GC7                 0x34
+
+/* Color Transform Matrix */
+#define PO1030_REG_CT0                 0x35
+#define PO1030_REG_CT1                 0x36
+#define PO1030_REG_CT2                 0x37
+#define PO1030_REG_CT3                 0x38
+#define PO1030_REG_CT4                 0x39
+#define PO1030_REG_CT5                 0x3a
+#define PO1030_REG_CT6                 0x3b
+#define PO1030_REG_CT7                 0x3c
+#define PO1030_REG_CT8                 0x3d
+
+#define PO1030_REG_AUTOCTRL1           0x3e
+#define PO1030_REG_AUTOCTRL2           0x3f
+
+#define PO1030_REG_YTARGET             0x40
+#define PO1030_REG_GLOBALGAINMIN       0x41
+#define PO1030_REG_GLOBALGAINMAX       0x42
+
+/* Output format control */
+#define PO1030_REG_OUTFORMCTRL1                0x5a
+#define PO1030_REG_OUTFORMCTRL2                0x5b
+#define PO1030_REG_OUTFORMCTRL3                0x5c
+#define PO1030_REG_OUTFORMCTRL4                0x5d
+#define PO1030_REG_OUTFORMCTRL5                0x5e
+
+/* Imaging coefficients */
+#define PO1030_REG_YBRIGHT             0x73
+#define PO1030_REG_YCONTRAST           0x74
+#define PO1030_REG_YSATURATION         0x75
+
+/*****************************************************************************/
+
+#define PO1030_GLOBAL_GAIN_DEFAULT     0x12
+#define PO1030_EXPOSURE_DEFAULT                0xf0ff
+#define PO1030_BLUE_GAIN_DEFAULT       0x40
+#define PO1030_RED_GAIN_DEFAULT        0x40
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+extern unsigned int m5602_debug;
+
+int po1030_probe(struct sd *sd);
+int po1030_init(struct sd *sd);
+int po1030_power_down(struct sd *sd);
+
+void po1030_dump_registers(struct sd *sd);
+
+int po1030_read_sensor(struct sd *sd, const u8 address,
+                             u8 *i2c_data, const u8 len);
+int po1030_write_sensor(struct sd *sd, const u8 address,
+                              u8 *i2c_data, const u8 len);
+
+int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor po1030 = {
+       .name = "PO1030",
+
+       .i2c_slave_id = 0xdc,
+
+       .probe = po1030_probe,
+       .init = po1030_init,
+       .power_down = po1030_power_down,
+
+       .nctrls = 4,
+       .ctrls = {
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_GLOBAL_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_gain,
+               .get = po1030_get_gain
+       }, {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "exposure",
+                       .minimum        = 0x00,
+                       .maximum        = 0xffff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_EXPOSURE_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_exposure,
+               .get = po1030_get_exposure
+       }, {
+               {
+                       .id             = V4L2_CID_RED_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "red balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_RED_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_red_balance,
+               .get = po1030_get_red_balance
+       }, {
+               {
+                       .id             = V4L2_CID_BLUE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "blue balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_BLUE_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_blue_balance,
+               .get = po1030_get_blue_balance
+       }
+       },
+       .nmodes = 1,
+       .modes = {
+       {
+               M5602_DEFAULT_FRAME_WIDTH,
+               M5602_DEFAULT_FRAME_HEIGHT,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+               .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+       }
+};
+
+static const unsigned char preinit_po1030[][3] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+       {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+
+       {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
+};
+
+static const unsigned char init_po1030[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       /*sequence 1*/
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       /*end of sequence 1*/
+
+       /*sequence 2 (same as stop sequence)*/
+       {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       /*end of sequence 2*/
+
+       /*sequence 5*/
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x87},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       /*end of sequence 5*/
+
+       /*sequence 2 stop */
+       {SENSOR, PO1030_REG_AUTOCTRL2, 0x24},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       /*end of sequence 2 stop */
+
+/* ---------------------------------
+ * end of init - begin of start
+ * --------------------------------- */
+
+       /*sequence 3*/
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       /*end of sequence 3*/
+       /*sequence 4*/
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+       {SENSOR, PO1030_REG_AUTOCTRL2, 0x04},
+
+       /* Set the width to 751 */
+       {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
+       {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef},
+
+       /* Set the height to 540 */
+       {SENSOR, PO1030_REG_FRAMEHEIGHT_H, 0x02},
+       {SENSOR, PO1030_REG_FRAMEHEIGHT_L, 0x1c},
+
+       /* Set the x window to 1 */
+       {SENSOR, PO1030_REG_WINDOWX_H, 0x00},
+       {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+
+       /* Set the y window to 1 */
+       {SENSOR, PO1030_REG_WINDOWY_H, 0x00},
+       {SENSOR, PO1030_REG_WINDOWX_L, 0x01},
+
+       {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02},
+       {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87},
+       {SENSOR, PO1030_REG_WINDOWHEIGHT_H, 0x01},
+       {SENSOR, PO1030_REG_WINDOWHEIGHT_L, 0xe3},
+
+       {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
+       {SENSOR, PO1030_REG_OUTFORMCTRL2, 0x04},
+       {SENSOR, PO1030_REG_AUTOCTRL1, 0x08},
+       {SENSOR, PO1030_REG_CONTROL2, 0x03},
+       {SENSOR, 0x21, 0x90},
+       {SENSOR, PO1030_REG_YTARGET, 0x60},
+       {SENSOR, 0x59, 0x13},
+       {SENSOR, PO1030_REG_OUTFORMCTRL1, 0x40},
+       {SENSOR, 0x5f, 0x00},
+       {SENSOR, 0x60, 0x80},
+       {SENSOR, 0x78, 0x14},
+       {SENSOR, 0x6f, 0x01},
+       {SENSOR, PO1030_REG_CONTROL1, 0x18},
+       {SENSOR, PO1030_REG_GLOBALGAINMAX, 0x14},
+       {SENSOR, 0x63, 0x38},
+       {SENSOR, 0x64, 0x38},
+       {SENSOR, PO1030_REG_CONTROL1, 0x58},
+       {SENSOR, PO1030_REG_RED_GAIN, 0x30},
+       {SENSOR, PO1030_REG_GREEN_1_GAIN, 0x30},
+       {SENSOR, PO1030_REG_BLUE_GAIN, 0x30},
+       {SENSOR, PO1030_REG_GREEN_2_GAIN, 0x30},
+       {SENSOR, PO1030_REG_GC0, 0x10},
+       {SENSOR, PO1030_REG_GC1, 0x20},
+       {SENSOR, PO1030_REG_GC2, 0x40},
+       {SENSOR, PO1030_REG_GC3, 0x60},
+       {SENSOR, PO1030_REG_GC4, 0x80},
+       {SENSOR, PO1030_REG_GC5, 0xa0},
+       {SENSOR, PO1030_REG_GC6, 0xc0},
+       {SENSOR, PO1030_REG_GC7, 0xff},
+       /*end of sequence 4*/
+       /*sequence 5*/
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7e},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       /*end of sequence 5*/
+
+       /*sequence 6*/
+       /* Changing 40 in f0 the image becomes green in bayer mode and red in
+        * rgb mode */
+       {SENSOR, PO1030_REG_RED_GAIN, PO1030_RED_GAIN_DEFAULT},
+       /* in changing 40 in f0 the image becomes green in bayer mode and red in
+        * rgb mode */
+       {SENSOR, PO1030_REG_BLUE_GAIN, PO1030_BLUE_GAIN_DEFAULT},
+
+       /* with a very low lighted environment increase the exposure but
+        * decrease the FPS (Frame Per Second) */
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+       /* Controls high exposure more than SENSOR_LOW_EXPOSURE, use only in
+        * low lighted environment (f0 is more than ff ?)*/
+       {SENSOR, PO1030_REG_INTEGLINES_H, ((PO1030_EXPOSURE_DEFAULT >> 2)
+               & 0xff)},
+
+       /* Controls middle exposure, use only in high lighted environment */
+       {SENSOR, PO1030_REG_INTEGLINES_M, PO1030_EXPOSURE_DEFAULT & 0xff},
+
+       /* Controls clarity (not sure) */
+       {SENSOR, PO1030_REG_INTEGLINES_L, 0x00},
+       /* Controls gain (the image is more lighted) */
+       {SENSOR, PO1030_REG_GLOBALGAIN, PO1030_GLOBAL_GAIN_DEFAULT},
+
+       /* Sets the width */
+       {SENSOR, PO1030_REG_FRAMEWIDTH_H, 0x02},
+       {SENSOR, PO1030_REG_FRAMEWIDTH_L, 0xef}
+       /*end of sequence 6*/
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
new file mode 100644 (file)
index 0000000..6820256
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_s5k4aa.h"
+
+int s5k4aa_probe(struct sd *sd)
+{
+       u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
+       int i, err = 0;
+
+       if (force_sensor) {
+               if (force_sensor == S5K4AA_SENSOR) {
+                       info("Forcing a %s sensor", s5k4aa.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       info("Probing for a s5k4aa sensor");
+
+       /* Preinit the sensor */
+       for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (preinit_s5k4aa[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                                                preinit_s5k4aa[i][1],
+                                                preinit_s5k4aa[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = preinit_s5k4aa[i][2];
+                       err = s5k4aa_write_sensor(sd,
+                                                 preinit_s5k4aa[i][1],
+                                                 data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = preinit_s5k4aa[i][2];
+                       data[1] = preinit_s5k4aa[i][3];
+                       err = s5k4aa_write_sensor(sd,
+                                                 preinit_s5k4aa[i][1],
+                                                 data, 2);
+                       break;
+               default:
+                       info("Invalid stream command, exiting init");
+                       return -EINVAL;
+               }
+       }
+
+       /* Test some registers, but we don't know their exact meaning yet */
+       if (s5k4aa_read_sensor(sd, 0x00, prod_id, sizeof(prod_id)))
+               return -ENODEV;
+
+       if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
+               return -ENODEV;
+       else
+               info("Detected a s5k4aa sensor");
+sensor_found:
+       sd->gspca_dev.cam.cam_mode = s5k4aa.modes;
+       sd->gspca_dev.cam.nmodes = s5k4aa.nmodes;
+       sd->desc->ctrls = s5k4aa.ctrls;
+       sd->desc->nctrls = s5k4aa.nctrls;
+
+       return 0;
+}
+
+int s5k4aa_read_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len)
+{
+       int err, i;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                                sd->sensor->i2c_slave_id);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+       if (err < 0)
+               goto out;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+       if (err < 0)
+               goto out;
+
+       for (i = 0; (i < len) & !err; i++) {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(DBG_TRACE, "Reading sensor register "
+                                 "0x%x containing 0x%x ", address, *i2c_data);
+       }
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* No sensor with a data width larger than 16 bits has yet been seen */
+       if (len > 2 || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton,
+              sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       /* Special case larger sensor writes */
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the tailer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_init(struct sd *sd)
+{
+       int i, err = 0;
+
+       for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_s5k4aa[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                               init_s5k4aa[i][1],
+                               init_s5k4aa[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_s5k4aa[i][2];
+                       err = s5k4aa_write_sensor(sd,
+                               init_s5k4aa[i][1], data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = init_s5k4aa[i][2];
+                       data[1] = init_s5k4aa[i][3];
+                       err = s5k4aa_write_sensor(sd,
+                               init_s5k4aa[i][1], data, 2);
+                       break;
+               default:
+                       info("Invalid stream command, exiting init");
+                       return -EINVAL;
+               }
+       }
+
+       if (dump_sensor)
+               s5k4aa_dump_registers(sd);
+
+       if (!err && dmi_check_system(s5k4aa_vflip_dmi_table)) {
+               u8 data = 0x02;
+               info("vertical flip quirk active");
+               s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+               s5k4aa_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+               data |= S5K4AA_RM_V_FLIP;
+               data &= ~S5K4AA_RM_H_FLIP;
+               s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+
+               /* Decrement COLSTART to preserve color order (BGGR) */
+               s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+               data--;
+               s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+
+               /* Increment ROWSTART to preserve color order (BGGR) */
+               s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+               data++;
+               s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+       }
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_power_down(struct sd *sd)
+{
+       return 0;
+}
+
+int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+
+       err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+       if (err < 0)
+               goto out;
+
+       *val = data << 8;
+       err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+       *val |= data;
+       PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val);
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+       data = (val >> 8) & 0xff;
+       err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+       if (err < 0)
+               goto out;
+       data = val & 0xff;
+       err = s5k4aa_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+
+       err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       *val = (data & S5K4AA_RM_V_FLIP) >> 7;
+       PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val);
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+       err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               goto out;
+       data = ((data & ~S5K4AA_RM_V_FLIP)
+                       | ((val & 0x01) << 7));
+       err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               goto out;
+
+       if (val) {
+               err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+               if (err < 0)
+                       goto out;
+
+               data++;
+               err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+       } else {
+               err = s5k4aa_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+               if (err < 0)
+                       goto out;
+
+               data--;
+               err = s5k4aa_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+       }
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+
+       err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       *val = (data & S5K4AA_RM_H_FLIP) >> 6;
+       PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val);
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d",
+              val);
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+       err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               goto out;
+
+       data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
+       err = s5k4aa_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               goto out;
+
+       if (val) {
+               err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+               if (err < 0)
+                       goto out;
+               data++;
+               err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+               if (err < 0)
+                       goto out;
+       } else {
+               err = s5k4aa_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+               if (err < 0)
+                       goto out;
+               data--;
+               err = s5k4aa_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+       }
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+
+       err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+       *val = data;
+       PDEBUG(DBG_V4L2_CID, "Read gain %d", *val);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       PDEBUG(DBG_V4L2_CID, "Set gain to %d", val);
+       err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               goto out;
+
+       data = val & 0xff;
+       err = s5k4aa_write_sensor(sd, S5K4AA_GAIN_2, &data, 1);
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+void s5k4aa_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 page, old_page;
+       s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+       for (page = 0; page < 16; page++) {
+               s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+               info("Dumping the s5k4aa register state for page 0x%x", page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 value = 0;
+                       s5k4aa_read_sensor(sd, address, &value, 1);
+                       info("register 0x%x contains 0x%x",
+                            address, value);
+               }
+       }
+       info("s5k4aa register state dump complete");
+
+       for (page = 0; page < 16; page++) {
+               s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+               info("Probing for which registers that are "
+                    "read/write for page 0x%x", page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 old_value, ctrl_value, test_value = 0xff;
+
+                       s5k4aa_read_sensor(sd, address, &old_value, 1);
+                       s5k4aa_write_sensor(sd, address, &test_value, 1);
+                       s5k4aa_read_sensor(sd, address, &ctrl_value, 1);
+
+                       if (ctrl_value == test_value)
+                               info("register 0x%x is writeable", address);
+                       else
+                               info("register 0x%x is read only", address);
+
+                       /* Restore original value */
+                       s5k4aa_write_sensor(sd, address, &old_value, 1);
+               }
+       }
+       info("Read/write register probing complete");
+       s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
new file mode 100644 (file)
index 0000000..bb7f7e3
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_S5K4AA_H_
+#define M5602_S5K4AA_H_
+
+#include <linux/dmi.h>
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define S5K4AA_PAGE_MAP                        0xec
+
+#define S5K4AA_PAGE_MAP_0              0x00
+#define S5K4AA_PAGE_MAP_1              0x01
+#define S5K4AA_PAGE_MAP_2              0x02
+
+/* Sensor register definitions for page 0x02 */
+#define S5K4AA_READ_MODE               0x03
+#define S5K4AA_ROWSTART_HI             0x04
+#define S5K4AA_ROWSTART_LO             0x05
+#define S5K4AA_COLSTART_HI             0x06
+#define S5K4AA_COLSTART_LO             0x07
+#define S5K4AA_WINDOW_HEIGHT_HI                0x08
+#define S5K4AA_WINDOW_HEIGHT_LO                0x09
+#define S5K4AA_WINDOW_WIDTH_HI         0x0a
+#define S5K4AA_WINDOW_WIDTH_LO         0x0b
+#define S5K4AA_GLOBAL_GAIN__           0x0f /* Only a guess ATM !!! */
+#define S5K4AA_H_BLANK_HI__            0x1d /* Only a guess ATM !!! sync lost
+                                               if too low, reduces frame rate
+                                               if too high */
+#define S5K4AA_H_BLANK_LO__            0x1e /* Only a guess ATM !!! */
+#define S5K4AA_EXPOSURE_HI             0x17
+#define S5K4AA_EXPOSURE_LO             0x18
+#define S5K4AA_GAIN_1                  0x1f /* (digital?) gain : 5 bits */
+#define S5K4AA_GAIN_2                  0x20 /* (analogue?) gain : 7 bits */
+
+#define S5K4AA_RM_ROW_SKIP_4X          0x08
+#define S5K4AA_RM_ROW_SKIP_2X          0x04
+#define S5K4AA_RM_COL_SKIP_4X          0x02
+#define S5K4AA_RM_COL_SKIP_2X          0x01
+#define S5K4AA_RM_H_FLIP               0x40
+#define S5K4AA_RM_V_FLIP               0x80
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+extern unsigned int m5602_debug;
+
+int s5k4aa_probe(struct sd *sd);
+int s5k4aa_init(struct sd *sd);
+int s5k4aa_power_down(struct sd *sd);
+
+void s5k4aa_dump_registers(struct sd *sd);
+
+int s5k4aa_read_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len);
+int s5k4aa_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len);
+
+int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct m5602_sensor s5k4aa = {
+       .name = "S5K4AA",
+       .probe = s5k4aa_probe,
+       .init = s5k4aa_init,
+       .power_down = s5k4aa_power_down,
+       .read_sensor = s5k4aa_read_sensor,
+       .write_sensor = s5k4aa_write_sensor,
+       .i2c_slave_id = 0x5a,
+       .nctrls = 4,
+       .ctrls = {
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = s5k4aa_set_vflip,
+               .get = s5k4aa_get_vflip
+
+       }, {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = s5k4aa_set_hflip,
+               .get = s5k4aa_get_hflip
+
+       }, {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "Gain",
+                       .minimum        = 0,
+                       .maximum        = 127,
+                       .step           = 1,
+                       .default_value  = 0xa0,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = s5k4aa_set_gain,
+               .get = s5k4aa_get_gain
+       }, {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "Exposure",
+                       .minimum        = 13,
+                       .maximum        = 0xfff,
+                       .step           = 1,
+                       .default_value  = 0x100,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = s5k4aa_set_exposure,
+               .get = s5k4aa_get_exposure
+       }
+       },
+
+       .nmodes = 1,
+       .modes = {
+       {
+               M5602_DEFAULT_FRAME_WIDTH,
+               M5602_DEFAULT_FRAME_HEIGHT,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+               .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+       }
+};
+
+static const unsigned char preinit_s5k4aa[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
+};
+
+static const unsigned char init_s5k4aa[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
+       {SENSOR, 0x36, 0x01, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, 0x0c, 0x05, 0x00},
+       {SENSOR, 0x02, 0x0e, 0x00},
+       {SENSOR, S5K4AA_GAIN_1, 0x0f, 0x00},
+       {SENSOR, S5K4AA_GAIN_2, 0x00, 0x00},
+       {SENSOR, S5K4AA_GLOBAL_GAIN__, 0x01, 0x00},
+       {SENSOR, 0x11, 0x00, 0x00},
+       {SENSOR, 0x12, 0x00, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
+       {SENSOR, 0x37, 0x00, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_COLSTART_LO, 0x0b, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc4, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x08, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_LO__, 0x48, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_LO, 0x43, 0x00},
+       {SENSOR, 0x11, 0x04, 0x00},
+       {SENSOR, 0x12, 0xc3, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
+               | S5K4AA_RM_COL_SKIP_2X, 0x00},
+       /* 0x37 : Fix image stability when light is too bright and improves
+        * image quality in 640x480, but worsens it in 1280x1024 */
+       {SENSOR, 0x37, 0x01, 0x00},
+       /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
+       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_LO, 0x2a, 0x00},
+       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
+       /* window_height_hi, window_height_lo : 960 = 0x03c0 */
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
+       /* window_width_hi, window_width_lo : 1280 = 0x0500 */
+       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
+       {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
+       {SENSOR, 0x11, 0x04, 0x00},
+       {SENSOR, 0x12, 0xc3, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, 0x02, 0x0e, 0x00},
+       {SENSOR_LONG, S5K4AA_GLOBAL_GAIN__, 0x0f, 0x00},
+       {SENSOR, S5K4AA_GAIN_1, 0x0b, 0x00},
+       {SENSOR, S5K4AA_GAIN_2, 0xa0, 0x00}
+};
+
+static
+    const
+       struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
+       {
+               .ident = "Fujitsu-Siemens Amilo Xa 2528",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
+               }
+       },
+       {
+               .ident = "Fujitsu-Siemens Amilo Xi 2550",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
+               }
+       },
+               {
+               .ident = "MSI GX700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+                       DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
+               }
+       },
+       { }
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
new file mode 100644 (file)
index 0000000..b4b33c2
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include "m5602_s5k83a.h"
+
+int s5k83a_probe(struct sd *sd)
+{
+       u8 prod_id = 0, ver_id = 0;
+       int i, err = 0;
+
+       if (force_sensor) {
+               if (force_sensor == S5K83A_SENSOR) {
+                       info("Forcing a %s sensor", s5k83a.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       info("Probing for a s5k83a sensor");
+
+       /* Preinit the sensor */
+       for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
+               u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
+               if (preinit_s5k83a[i][0] == SENSOR)
+                       err = s5k83a_write_sensor(sd, preinit_s5k83a[i][1],
+                               data, 2);
+               else
+                       err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
+                               data[0]);
+       }
+
+       /* We don't know what register (if any) that contain the product id
+        * Just pick the first addresses that seem to produce the same results
+        * on multiple machines */
+       if (s5k83a_read_sensor(sd, 0x00, &prod_id, 1))
+               return -ENODEV;
+
+       if (s5k83a_read_sensor(sd, 0x01, &ver_id, 1))
+               return -ENODEV;
+
+       if ((prod_id == 0xff) || (ver_id == 0xff))
+               return -ENODEV;
+       else
+               info("Detected a s5k83a sensor");
+
+sensor_found:
+       sd->gspca_dev.cam.cam_mode = s5k83a.modes;
+       sd->gspca_dev.cam.nmodes = s5k83a.nmodes;
+       sd->desc->ctrls = s5k83a.ctrls;
+       sd->desc->nctrls = s5k83a.nctrls;
+       return 0;
+}
+
+int s5k83a_read_sensor(struct sd *sd, const u8 address,
+                             u8 *i2c_data, const u8 len)
+{
+       int err, i;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                                sd->sensor->i2c_slave_id);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       if (err < 0)
+               goto out;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+       if (err < 0)
+               goto out;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
+       } while ((*i2c_data & I2C_BUSY) && !err);
+
+       if (err < 0)
+               goto out;
+       for (i = 0; i < len && !len; i++) {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(DBG_TRACE, "Reading sensor register "
+                                 "0x%x containing 0x%x ", address, *i2c_data);
+       }
+
+out:
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_write_sensor(struct sd *sd, const u8 address,
+                              u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* No sensor with a data width larger than 16 bits has yet been seen */
+       if (len > 2 || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton,
+              sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       /* Special case larger sensor writes */
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the tailer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_init(struct sd *sd)
+{
+       int i, err = 0;
+
+       for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_s5k83a[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                                       init_s5k83a[i][1],
+                                       init_s5k83a[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_s5k83a[i][2];
+                       err = s5k83a_write_sensor(sd,
+                               init_s5k83a[i][1], data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = init_s5k83a[i][2];
+                       data[1] = init_s5k83a[i][3];
+                       err = s5k83a_write_sensor(sd,
+                               init_s5k83a[i][1], data, 2);
+                       break;
+               default:
+                       info("Invalid stream command, exiting init");
+                       return -EINVAL;
+               }
+       }
+
+       if (dump_sensor)
+               s5k83a_dump_registers(sd);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_power_down(struct sd *sd)
+{
+       return 0;
+}
+
+void s5k83a_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 page, old_page;
+       s5k83a_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+
+       for (page = 0; page < 16; page++) {
+               s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+               info("Dumping the s5k83a register state for page 0x%x", page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 val = 0;
+                       s5k83a_read_sensor(sd, address, &val, 1);
+                       info("register 0x%x contains 0x%x",
+                            address, val);
+               }
+       }
+       info("s5k83a register state dump complete");
+
+       for (page = 0; page < 16; page++) {
+               s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+               info("Probing for which registers that are read/write "
+                     "for page 0x%x", page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 old_val, ctrl_val, test_val = 0xff;
+
+                       s5k83a_read_sensor(sd, address, &old_val, 1);
+                       s5k83a_write_sensor(sd, address, &test_val, 1);
+                       s5k83a_read_sensor(sd, address, &ctrl_val, 1);
+
+                       if (ctrl_val == test_val)
+                               info("register 0x%x is writeable", address);
+                       else
+                               info("register 0x%x is read only", address);
+
+                       /* Restore original val */
+                       s5k83a_write_sensor(sd, address, &old_val, 1);
+               }
+       }
+       info("Read/write register probing complete");
+       s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+}
+
+int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = s5k83a_read_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+       data[1] = data[1] << 1;
+       *val = data[1];
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x00;
+       data[1] = 0x20;
+       err = s5k83a_write_sensor(sd, 0x14, data, 2);
+       if (err < 0)
+               return err;
+
+       data[0] = 0x01;
+       data[1] = 0x00;
+       err = s5k83a_write_sensor(sd, 0x0d, data, 2);
+       if (err < 0)
+               return err;
+
+       /* FIXME: This is not sane, we need to figure out the composition
+                 of these registers */
+       data[0] = val >> 3; /* brightness, high 5 bits */
+       data[1] = val >> 1; /* brightness, high 7 bits */
+       err = s5k83a_write_sensor(sd, S5K83A_BRIGHTNESS, data, 2);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = s5k83a_read_sensor(sd, S5K83A_WHITENESS, &data, 1);
+
+       *val = data;
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = val;
+       err = s5k83a_write_sensor(sd, S5K83A_WHITENESS, data, 1);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = s5k83a_read_sensor(sd, S5K83A_GAIN, data, 2);
+
+       data[1] = data[1] & 0x3f;
+       if (data[1] > S5K83A_MAXIMUM_GAIN)
+               data[1] = S5K83A_MAXIMUM_GAIN;
+
+       *val = data[1];
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0;
+       data[1] = val;
+       err = s5k83a_write_sensor(sd, S5K83A_GAIN, data, 2);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x05;
+       err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+       *val = (data[0] | 0x40) ? 1 : 0;
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x05;
+       err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+       if (err < 0)
+               return err;
+
+       /* set or zero six bit, seven is hflip */
+       data[0] = (val) ? (data[0] & 0x80) | 0x40 | S5K83A_FLIP_MASK
+                       : (data[0] & 0x80) | S5K83A_FLIP_MASK;
+       err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+       if (err < 0)
+               return err;
+
+       data[0] = (val) ? 0x0b : 0x0a;
+       err = s5k83a_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x05;
+       err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+       *val = (data[0] | 0x80) ? 1 : 0;
+
+       return (err < 0) ? err : 0;
+}
+
+int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x05;
+       err = s5k83a_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_read_sensor(sd, S5K83A_FLIP, data, 1);
+       if (err < 0)
+               return err;
+
+       /* set or zero seven bit, six is vflip */
+       data[0] = (val) ? (data[0] & 0x40) | 0x80 | S5K83A_FLIP_MASK
+                       : (data[0] & 0x40) | S5K83A_FLIP_MASK;
+       err = s5k83a_write_sensor(sd, S5K83A_FLIP, data, 1);
+       if (err < 0)
+               return err;
+
+       data[0] = (val) ? 0x0a : 0x0b;
+       err = s5k83a_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
+
+       return (err < 0) ? err : 0;
+}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
new file mode 100644 (file)
index 0000000..833708e
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_S5K83A_H_
+#define M5602_S5K83A_H_
+
+#include "m5602_sensor.h"
+
+#define S5K83A_FLIP                            0x01
+#define S5K83A_HFLIP_TUNE              0x03
+#define S5K83A_VFLIP_TUNE              0x05
+#define S5K83A_WHITENESS               0x0a
+#define S5K83A_GAIN                            0x18
+#define S5K83A_BRIGHTNESS              0x1b
+#define S5K83A_PAGE_MAP                        0xec
+
+#define S5K83A_DEFAULT_BRIGHTNESS      0x71
+#define S5K83A_DEFAULT_WHITENESS       0x7e
+#define S5K83A_DEFAULT_GAIN                    0x00
+#define S5K83A_MAXIMUM_GAIN                    0x3c
+#define S5K83A_FLIP_MASK                       0x10
+
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern int dump_sensor;
+extern unsigned int m5602_debug;
+
+
+int s5k83a_probe(struct sd *sd);
+int s5k83a_init(struct sd *sd);
+int s5k83a_power_down(struct sd *sd);
+
+void s5k83a_dump_registers(struct sd *sd);
+
+int s5k83a_read_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len);
+int s5k83a_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len);
+
+int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_whiteness(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_whiteness(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+
+
+static struct m5602_sensor s5k83a = {
+       .name = "S5K83A",
+       .probe = s5k83a_probe,
+       .init = s5k83a_init,
+       .power_down = s5k83a_power_down,
+       .read_sensor = s5k83a_read_sensor,
+       .write_sensor = s5k83a_write_sensor,
+       .i2c_slave_id = 0x5a,
+       .nctrls = 5,
+       .ctrls = {
+       {
+               {
+                       .id = V4L2_CID_BRIGHTNESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "brightness",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_BRIGHTNESS,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_brightness,
+                       .get = s5k83a_get_brightness
+
+       }, {
+               {
+                       .id = V4L2_CID_WHITENESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "whiteness",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_WHITENESS,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_whiteness,
+                       .get = s5k83a_get_whiteness,
+       }, {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "gain",
+                       .minimum = 0x00,
+                       .maximum = S5K83A_MAXIMUM_GAIN,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_GAIN,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_gain,
+                       .get = s5k83a_get_gain
+       }, {
+               {
+                       .id         = V4L2_CID_HFLIP,
+                       .type       = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name       = "horizontal flip",
+                       .minimum    = 0,
+                       .maximum    = 1,
+                       .step       = 1,
+                       .default_value  = 0
+               },
+                       .set = s5k83a_set_hflip,
+                       .get = s5k83a_get_hflip
+       }, {
+               {
+                .id         = V4L2_CID_VFLIP,
+               .type       = V4L2_CTRL_TYPE_BOOLEAN,
+               .name       = "vertical flip",
+               .minimum    = 0,
+               .maximum    = 1,
+               .step       = 1,
+               .default_value  = 0
+               },
+               .set = s5k83a_set_vflip,
+               .get = s5k83a_get_vflip
+               }
+       },
+       .nmodes = 1,
+       .modes = {
+       {
+               M5602_DEFAULT_FRAME_WIDTH,
+               M5602_DEFAULT_FRAME_HEIGHT,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       M5602_DEFAULT_FRAME_WIDTH * M5602_DEFAULT_FRAME_HEIGHT,
+               .bytesperline = M5602_DEFAULT_FRAME_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+       }
+};
+
+static const unsigned char preinit_s5k83a[][4] =
+{
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00}
+};
+
+/* This could probably be considerably shortened.
+   I don't have the hardware to experiment with it, patches welcome
+*/
+static const unsigned char init_s5k83a[][4] =
+{
+       {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+       {SENSOR, 0xaf, 0x01, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x01, 0x50, 0x00},
+       {SENSOR, 0x12, 0x20, 0x00},
+       {SENSOR, 0x17, 0x40, 0x00},
+       {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+       {SENSOR, 0x1c, 0x00, 0x00},
+       {SENSOR, 0x02, 0x70, 0x00},
+       {SENSOR, 0x03, 0x0b, 0x00},
+       {SENSOR, 0x04, 0xf0, 0x00},
+       {SENSOR, 0x05, 0x0b, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x06, 0x71, 0x00},
+       {SENSOR, 0x07, 0xe8, 0x00},
+       {SENSOR, 0x08, 0x02, 0x00},
+       {SENSOR, 0x09, 0x88, 0x00},
+       {SENSOR, 0x14, 0x00, 0x00},
+       {SENSOR, 0x15, 0x20, 0x00},
+       {SENSOR, 0x19, 0x00, 0x00},
+       {SENSOR, 0x1a, 0x98, 0x00},
+       {SENSOR, 0x0f, 0x02, 0x00},
+       {SENSOR, 0x10, 0xe5, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR_LONG, 0x14, 0x00, 0x20},
+       {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+       {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
+
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+       {SENSOR, 0xaf, 0x01, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       /* ff ( init value )is very dark) || 71 and f0 better */
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x01, 0x50, 0x00},
+       {SENSOR, 0x12, 0x20, 0x00},
+       {SENSOR, 0x17, 0x40, 0x00},
+       {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+       {SENSOR, 0x1c, 0x00, 0x00},
+       {SENSOR, 0x02, 0x70, 0x00},
+       /* some values like 0x10 give a blue-purple image */
+       {SENSOR, 0x03, 0x0b, 0x00},
+       {SENSOR, 0x04, 0xf0, 0x00},
+       {SENSOR, 0x05, 0x0b, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       /* under 80 don't work, highter depend on value */
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x06, 0x71, 0x00},
+       {SENSOR, 0x07, 0xe8, 0x00},
+       {SENSOR, 0x08, 0x02, 0x00},
+       {SENSOR, 0x09, 0x88, 0x00},
+       {SENSOR, 0x14, 0x00, 0x00},
+       {SENSOR, 0x15, 0x20, 0x00},
+       {SENSOR, 0x19, 0x00, 0x00},
+       {SENSOR, 0x1a, 0x98, 0x00},
+       {SENSOR, 0x0f, 0x02, 0x00},
+       {SENSOR, 0x10, 0xe5, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR_LONG, 0x14, 0x00, 0x20},
+       {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+       {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+       /* The following sequence is useless after a clean boot
+          but is necessary after resume from suspend */
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+       {SENSOR, 0xaf, 0x01, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x01, 0x50, 0x00},
+       {SENSOR, 0x12, 0x20, 0x00},
+       {SENSOR, 0x17, 0x40, 0x00},
+       {SENSOR, S5K83A_BRIGHTNESS, 0x0f, 0x00},
+       {SENSOR, 0x1c, 0x00, 0x00},
+       {SENSOR, 0x02, 0x70, 0x00},
+       {SENSOR, 0x03, 0x0b, 0x00},
+       {SENSOR, 0x04, 0xf0, 0x00},
+       {SENSOR, 0x05, 0x0b, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x06, 0x71, 0x00},
+       {SENSOR, 0x07, 0xe8, 0x00},
+       {SENSOR, 0x08, 0x02, 0x00},
+       {SENSOR, 0x09, 0x88, 0x00},
+       {SENSOR, 0x14, 0x00, 0x00},
+       {SENSOR, 0x15, 0x20, 0x00},
+       {SENSOR, 0x19, 0x00, 0x00},
+       {SENSOR, 0x1a, 0x98, 0x00},
+       {SENSOR, 0x0f, 0x02, 0x00},
+
+       {SENSOR, 0x10, 0xe5, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR_LONG, 0x14, 0x00, 0x20},
+       {SENSOR_LONG, 0x0d, 0x00, 0x7d},
+       {SENSOR_LONG, 0x1b, 0x0d, 0x05},
+
+       /* normal colors
+          (this is value after boot, but after tries can be different) */
+       {SENSOR, 0x00, 0x06, 0x00},
+
+       /* set default brightness */
+       {SENSOR_LONG, 0x14, 0x00, 0x20},
+       {SENSOR_LONG, 0x0d, 0x01, 0x00},
+       {SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3,
+                           S5K83A_DEFAULT_BRIGHTNESS >> 1},
+
+       /* set default whiteness */
+       {SENSOR, S5K83A_WHITENESS, S5K83A_DEFAULT_WHITENESS, 0x00},
+
+       /* set default gain */
+       {SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN},
+
+       /* set default flip */
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, S5K83A_FLIP, 0x00 | S5K83A_FLIP_MASK, 0x00},
+       {SENSOR, S5K83A_HFLIP_TUNE, 0x0b, 0x00},
+       {SENSOR, S5K83A_VFLIP_TUNE, 0x0a, 0x00}
+
+};
+
+#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
new file mode 100644 (file)
index 0000000..930fcaa
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andren
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; 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.
+ *
+ */
+
+#ifndef M5602_SENSOR_H_
+#define M5602_SENSOR_H_
+
+#include "m5602_bridge.h"
+
+#define M5602_DEFAULT_FRAME_WIDTH  640
+#define M5602_DEFAULT_FRAME_HEIGHT 480
+
+#define M5602_MAX_CTRLS                (V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)
+
+/* Enumerates all supported sensors */
+enum sensors {
+       OV9650_SENSOR   = 1,
+       S5K83A_SENSOR   = 2,
+       S5K4AA_SENSOR   = 3,
+       MT9M111_SENSOR  = 4,
+       PO1030_SENSOR   = 5
+};
+
+/* Enumerates all possible instruction types */
+enum instruction {
+       BRIDGE,
+       SENSOR,
+       SENSOR_LONG
+};
+
+struct m5602_sensor {
+       /* Defines the name of a sensor */
+       char name[32];
+
+       /* What i2c address the sensor is connected to */
+       u8 i2c_slave_id;
+
+       /* Probes if the sensor is connected */
+       int (*probe)(struct sd *sd);
+
+       /* Performs a initialization sequence */
+       int (*init)(struct sd *sd);
+
+       /* Performs a power down sequence */
+       int (*power_down)(struct sd *sd);
+
+       /* Reads a sensor register */
+       int (*read_sensor)(struct sd *sd, const u8 address,
+             u8 *i2c_data, const u8 len);
+
+       /* Writes to a sensor register */
+       int (*write_sensor)(struct sd *sd, const u8 address,
+             u8 *i2c_data, const u8 len);
+
+       int nctrls;
+       struct ctrl ctrls[M5602_MAX_CTRLS];
+
+       char nmodes;
+       struct v4l2_pix_format modes[];
+};
+
+#endif
index 4d5db47ba8cbf3564d9287a86153e4f46733f2e8..277ca34a881775cf8ee72a7801bb4202e2864f5c 100644 (file)
@@ -134,7 +134,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        int err_code;
        __u8 *data;
@@ -143,9 +143,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
        int intpipe;
 
        PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
-       if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) {
+       err_code = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8);
+       if (err_code < 0) {
                PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
-               return;
+               return err_code;
        }
 
        data = gspca_dev->usb_buf;
@@ -154,7 +155,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
        err_code = reg_w(gspca_dev, data[0], 2);
        if (err_code < 0)
-               return;
+               return err_code;
 
        /*
           Initialize the MR97113 chip register
@@ -180,14 +181,14 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
        err_code = reg_w(gspca_dev, data[0], 11);
        if (err_code < 0)
-               return;
+               return err_code;
 
        data[0] = 0x23;         /* address */
        data[1] = 0x09;         /* reg 35, append frame header */
 
        err_code = reg_w(gspca_dev, data[0], 2);
        if (err_code < 0)
-               return;
+               return err_code;
 
        data[0] = 0x3c;         /* address */
 /*     if (gspca_dev->width == 1280) */
@@ -198,7 +199,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                                 *      (unit: 4KB) 200KB */
        err_code = reg_w(gspca_dev, data[0], 2);
        if (err_code < 0)
-               return;
+               return err_code;
 
        if (0) {                        /* fixed dark-gain */
                data[1] = 0;            /* reg 94, Y Gain (1.75) */
@@ -240,13 +241,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
 
        err_code = reg_w(gspca_dev, data[0], 6);
        if (err_code < 0)
-               return;
+               return err_code;
 
        data[0] = 0x67;
        data[1] = 0x13;         /* reg 103, first pixel B, disable sharpness */
        err_code = reg_w(gspca_dev, data[0], 2);
        if (err_code < 0)
-               return;
+               return err_code;
 
        /*
         * initialize the value of MI sensor...
@@ -326,6 +327,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        data[0] = 0x00;
        data[1] = 0x4d;         /* ISOC transfering enable... */
        reg_w(gspca_dev, data[0], 2);
+       return err_code;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 4df4eec9f7e71163fe35950bf02a303ca5a3272c..ca671194679e3adef083dbbe3f3e20df8956ebf2 100644 (file)
@@ -1854,7 +1854,7 @@ static int set_ov_sensor_window(struct sd *sd)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int ret;
@@ -1871,9 +1871,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
                goto out;
        PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
        ov51x_led_control(sd, 1);
-       return;
+       return 0;
 out:
        PDEBUG(D_ERR, "camera start error:%d", ret);
+       return ret;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 83b5f740c9470960b3bf42aef54472726bbce098..0b0c573d06da1ee3da37fed3d3f74948375845c4 100644 (file)
@@ -281,7 +281,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 mode;
@@ -323,6 +323,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        sd->sof_read = 0;
        sd->autogain_ignore_frames = 0;
        atomic_set(&sd->avg_lum, -1);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -534,6 +535,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x093a, 0x2470)},
        {USB_DEVICE(0x093a, 0x2471)},
        {USB_DEVICE(0x093a, 0x2472)},
+       {USB_DEVICE(0x093a, 0x2476)},
        {USB_DEVICE(0x2001, 0xf115)},
        {}
 };
index ba865b7f1ed81710e902fdf86eb2ae1c1cf06e8a..e5ff9a6199ef16261e85faec7d9ab85d97ebfc49 100644 (file)
@@ -675,7 +675,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -724,6 +724,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                reg_w(gspca_dev, 0x78, 0x01);
        else
                reg_w(gspca_dev, 0x78, 0x05);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 12b81ae526b7206c0e982e3a845e20c4d1386ca2..6c69bc7778fc2f9cf322d0282a3151a91bcc9f82 100644 (file)
@@ -490,7 +490,7 @@ static const __u8 tas5130_sensor_init[][8] = {
        {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
 };
 
-struct sensor_data sensor_data[] = {
+static struct sensor_data sensor_data[] = {
 SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
 SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
 SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
@@ -892,7 +892,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
@@ -976,6 +976,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        sd->frames_to_drop = 0;
        sd->autogain_ignore_frames = 0;
        atomic_set(&sd->avg_lum, -1);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 572b0f363b640ccb407b7d312716c75c4da85e95..53cb82d9e7c6a28909636595968ae335c9809698 100644 (file)
@@ -39,6 +39,7 @@ struct sd {
        unsigned char contrast;
        unsigned char colors;
        unsigned char autogain;
+       __u8 vflip;                     /* ov7630 only */
 
        signed char ag_cnt;
 #define AG_CNT_START 13
@@ -70,6 +71,8 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
        {
@@ -131,6 +134,22 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setautogain,
            .get = sd_getautogain,
        },
+/* ov7630 only */
+#define VFLIP_IDX 4
+       {
+           {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vflip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define VFLIP_DEF 1
+               .default_value = VFLIP_DEF,
+           },
+           .set = sd_setvflip,
+           .get = sd_getvflip,
+       },
 };
 
 static struct v4l2_pix_format vga_mode[] = {
@@ -248,10 +267,12 @@ static const __u8 gamma_def[] = {
        0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
 };
 
+/* color matrix and offsets */
 static const __u8 reg84[] = {
-       0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
-       0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
-       0xf7, 0x0f, 0x00, 0x00, 0x00
+       0x14, 0x00, 0x27, 0x00, 0x07, 0x00,     /* YR YG YB gains */
+       0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,     /* UR UG UB */
+       0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,     /* VR VG VB */
+       0x00, 0x00, 0x00                        /* YUV offsets */
 };
 static const __u8 hv7131r_sensor_init[][8] = {
        {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
@@ -434,7 +455,8 @@ static const __u8 ov7630_sensor_init[][8] = {
        {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
        {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
 /*fixme: + 0x12, 0x04*/
-       {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},
+/*     {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
+                                                        * set by setvflip */
        {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
        {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
        {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
@@ -949,6 +971,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
                gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
                break;
        }
+       if (sd->sensor != SENSOR_OV7630)
+               gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
 
        return 0;
 }
@@ -1080,20 +1104,17 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
 static void setbrightcont(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       unsigned val;
+       int val;
        __u8 reg84_full[0x15];
 
-       memset(reg84_full, 0, sizeof reg84_full);
-       val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10;        /* 10..30 */
-       reg84_full[2] = val;
-       reg84_full[0] = (val + 1) / 2;
-       reg84_full[4] = (val + 1) / 5;
-       if (val > BRIGHTNESS_DEF)
-               val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
+       memcpy(reg84_full, reg84, sizeof reg84_full);
+       val = sd->contrast * 0x30 / CONTRAST_MAX + 0x10;        /* 10..40 */
+       reg84_full[0] = (val + 1) / 2;          /* red */
+       reg84_full[2] = val;                    /* green */
+       reg84_full[4] = (val + 1) / 5;          /* blue */
+       val = (sd->brightness - BRIGHTNESS_DEF) * 0x10
                        / BRIGHTNESS_MAX;
-       else
-               val = 0;
-       reg84_full[0x12] = val;                 /* 00..1f */
+       reg84_full[0x12] = val & 0x1f;          /* 5:0 signed value */
        reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
 }
 
@@ -1172,8 +1193,16 @@ static void setautogain(struct gspca_dev *gspca_dev)
                sd->ag_cnt = -1;
 }
 
+static void setvflip(struct sd *sd)
+{
+       if (sd->sensor != SENSOR_OV7630)
+               return;
+       i2c_w1(&sd->gspca_dev, 0x75,                    /* COMN */
+               sd->vflip ? 0x82 : 0x02);
+}
+
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
@@ -1263,6 +1292,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                break;
        case SENSOR_OV7630:
                ov7630_InitSensor(gspca_dev);
+               setvflip(sd);
                reg17 = 0xe2;
                reg1 = 0x44;
                break;
@@ -1320,12 +1350,16 @@ static void sd_start(struct gspca_dev *gspca_dev)
                setbrightness(gspca_dev);
                setcontrast(gspca_dev);
                break;
+       case SENSOR_OV7630:
+               setvflip(sd);
+               /* fall thru */
        default:                        /* OV76xx */
                setbrightcont(gspca_dev);
                break;
        }
        setautogain(gspca_dev);
        reg_w1(gspca_dev, 0x01, reg1);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1546,6 +1580,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vflip = val;
+       if (gspca_dev->streaming)
+               setvflip(sd);
+       return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->vflip;
+       return 0;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
        .name = MODULE_NAME,
@@ -1567,6 +1619,7 @@ static const struct sd_desc sd_desc = {
 static const __devinitdata struct usb_device_id device_table[] = {
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
+       {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
        {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
        {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
        {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
@@ -1588,7 +1641,9 @@ static const __devinitdata struct usb_device_id device_table[] = {
 /*     {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
        {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
        {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
-/*     {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x??)}, */
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
+#endif
 /*     {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
 /*     {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
 /*     {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
index 6e733901fcca24129457aba26946e4229af6ca0f..bca106c153faa3dc4708ad77a6e33eac2c73615d 100644 (file)
@@ -660,7 +660,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int err;
@@ -867,6 +867,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                write_vector(gspca_dev, Clicksmart510_defaults);
                break;
        }
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index e9eb59bae4fbf1b82effe0d21d5496213a86db80..b742f260c7caa6bb4fd8b1769be95c87988bafcb 100644 (file)
@@ -1980,7 +1980,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
        int mode;
@@ -2012,6 +2012,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        setbrightness(gspca_dev);
        setcontrast(gspca_dev);
        setcolors(gspca_dev);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index f601daf19ebeabacaf044af300f1914ed69caa61..b345749213cf16e9e0bd9e5cf2703d4cb9c9388f 100644 (file)
@@ -688,7 +688,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
        int ret;
@@ -733,6 +733,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
 /*     reg_write(dev, 0x5, 0x0, 0x0); */
 /*     reg_write(dev, 0x5, 0x0, 0x1); */
 /*     reg_write(dev, 0x5, 0x11, 0x2); */
+       return ret;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 195dce96ef068d5579b1cd896c623ed242619378..645ee9d44d0267dbb908ddf2e9beea692b413d05 100644 (file)
@@ -422,7 +422,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
        __u16 norme;
@@ -549,6 +549,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        PDEBUG(D_STREAM, "webcam started");
        spca506_GetNormeInput(gspca_dev, &norme, &channel);
        spca506_SetNormeInput(gspca_dev, norme, channel);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 281ce02103a336ced7a1d10042b3c830fdcf1155..63ec902c895d0398116f30732e098d8d74daeb69 100644 (file)
@@ -1528,7 +1528,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        int mode;
 
@@ -1546,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                break;
        }
        reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 95fcfcb9e31b51c8d2ce871fdae89b0096df1862..020a03c466c10f75042fcd090d0f1be7643e7fdc 100644 (file)
@@ -152,7 +152,7 @@ static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
 
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                              0,                /* request */
-                             USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                              value, index, NULL, 0, 500);
        PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
        if (ret < 0)
@@ -699,7 +699,7 @@ static void setautogain(struct gspca_dev *gspca_dev)
                sd->ag_cnt = -1;
 }
 
-static void sd_start_12a(struct gspca_dev *gspca_dev)
+static int sd_start_12a(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
        int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */
@@ -725,8 +725,9 @@ static void sd_start_12a(struct gspca_dev *gspca_dev)
        setwhite(gspca_dev);
        setautogain(gspca_dev);
        setexposure(gspca_dev);
+       return 0;
 }
-static void sd_start_72a(struct gspca_dev *gspca_dev)
+static int sd_start_72a(struct gspca_dev *gspca_dev)
 {
        struct usb_device *dev = gspca_dev->dev;
        int Clck;
@@ -750,6 +751,7 @@ static void sd_start_72a(struct gspca_dev *gspca_dev)
        reg_w_val(dev, 0x8700, Clck);   /* 0x27 clock */
        reg_w_val(dev, 0x8112, 0x10 | 0x20);
        setautogain(gspca_dev);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1064,7 +1066,7 @@ static struct ctrl sd_ctrls_12a[] = {
            {
                .id = V4L2_CID_DO_WHITE_BALANCE,
                .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "While Balance",
+               .name = "White Balance",
                .minimum = WHITE_MIN,
                .maximum = WHITE_MAX,
                .step = 1,
index 2f2de429e273470669c42aa7d25749add1a33800..d9d64911f22a21220e73f0aa05ea5e415419ea87 100644 (file)
@@ -324,7 +324,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        int ret, value;
 
@@ -374,9 +374,10 @@ static void sd_start(struct gspca_dev *gspca_dev)
        set_par(gspca_dev, 0x01000000);
        set_par(gspca_dev, 0x01000000);
        PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
-       return;
+       return 0;
 out:
        PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
+       return ret;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index 1cfcc6c4955874ab0bb05da32ef387136967c701..bd9288665a80c26c9e98e8bd451643652c19b023 100644 (file)
@@ -961,7 +961,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct usb_device *dev = gspca_dev->dev;
@@ -1042,6 +1042,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                break;
        }
        sp5xx_initContBrigHueRegisters(gspca_dev);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index f034c748fc7ef5c3a608ff88e6ca1ab18e94261e..b561f7c4f066632571d8b12265b1ed776dc49231 100644 (file)
@@ -28,8 +28,6 @@
 
 #include "gspca.h"
 
-#define MAX_GAMMA 0x10         /* 0 to 15 */
-
 #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
 
 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
@@ -49,6 +47,10 @@ struct sd {
        unsigned char whitebalance;
        unsigned char mirror;
        unsigned char effect;
+
+       __u8 sensor;
+#define SENSOR_TAS5130A 0
+#define SENSOR_OTHER 1
 };
 
 /* V4L2 controls supported by the driver */
@@ -83,9 +85,9 @@ static struct ctrl sd_ctrls[] = {
          .type = V4L2_CTRL_TYPE_INTEGER,
          .name = "Brightness",
          .minimum = 0,
-         .maximum = 0x0f,
+         .maximum = 14,
          .step = 1,
-         .default_value = 0x09,
+         .default_value = 8,
          },
         .set = sd_setbrightness,
         .get = sd_getbrightness,
@@ -118,16 +120,17 @@ static struct ctrl sd_ctrls[] = {
         .set = sd_setcolors,
         .get = sd_getcolors,
         },
-#define SD_GAMMA 3
+#define GAMMA_MAX 16
+#define GAMMA_DEF 10
        {
         {
          .id = V4L2_CID_GAMMA, /* (gamma on win) */
          .type = V4L2_CTRL_TYPE_INTEGER,
-         .name = "Gamma (Untested)",
+         .name = "Gamma",
          .minimum = 0,
-         .maximum = MAX_GAMMA,
+         .maximum = GAMMA_MAX - 1,
          .step = 1,
-         .default_value = 0x09,
+         .default_value = GAMMA_DEF,
          },
         .set = sd_setgamma,
         .get = sd_getgamma,
@@ -197,7 +200,7 @@ static struct ctrl sd_ctrls[] = {
          .type = V4L2_CTRL_TYPE_INTEGER,
          .name = "Sharpness",
          .minimum = 0,
-         .maximum = MAX_GAMMA, /* 0 to 16 */
+         .maximum = 15,
          .step = 1,
          .default_value = 0x06,
          },
@@ -258,7 +261,6 @@ static struct v4l2_pix_format vga_mode_t16[] = {
                .priv = 0},
 };
 
-#define T16_OFFSET_DATA 631
 #define MAX_EFFECTS 7
 /* easily done by soft, this table could be removed,
  * i keep it here just in case */
@@ -272,87 +274,87 @@ static const __u8 effects_table[MAX_EFFECTS][6] = {
        {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},   /* Negative */
 };
 
-static const __u8 gamma_table[MAX_GAMMA][34] = {
-       {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
+static const __u8 gamma_table[GAMMA_MAX][34] = {
+       {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,        /* 0 */
         0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
         0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
         0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
-        0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
-        0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
-        0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
+       {0x90, 0x00, 0x91, 0x33, 0x92, 0x5a, 0x93, 0x75,        /* 1 */
+        0x94, 0x85, 0x95, 0x93, 0x96, 0xa1, 0x97, 0xad,
+        0x98, 0xb7, 0x99, 0xc2, 0x9a, 0xcb, 0x9b, 0xd4,
+        0x9c, 0xde, 0x9D, 0xe7, 0x9e, 0xf0, 0x9f, 0xf7,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
-        0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
-        0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
-        0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
+       {0x90, 0x00, 0x91, 0x2f, 0x92, 0x51, 0x93, 0x6b,        /* 2 */
+        0x94, 0x7c, 0x95, 0x8a, 0x96, 0x99, 0x97, 0xa6,
+        0x98, 0xb1, 0x99, 0xbc, 0x9a, 0xc6, 0x9b, 0xd0,
+        0x9c, 0xdb, 0x9d, 0xe4, 0x9e, 0xed, 0x9f, 0xf6,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
-        0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
-        0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
-        0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
+       {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,        /* 3 */
+        0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9e,
+        0x98, 0xaa, 0x99, 0xb5, 0x9a, 0xbf, 0x9b, 0xcb,
+        0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
+       {0x90, 0x00, 0x91, 0x23, 0x92, 0x3f, 0x93, 0x55,        /* 4 */
         0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
-        0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
-        0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
+        0x98, 0xa2, 0x99, 0xad, 0x9a, 0xb9, 0x9b, 0xc6,
+        0x9c, 0xd2, 0x9d, 0xde, 0x9e, 0xe9, 0x9f, 0xf4,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
+       {0x90, 0x00, 0x91, 0x1b, 0x92, 0x33, 0x93, 0x48,        /* 5 */
         0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
-        0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
-        0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
+        0x98, 0x96, 0x99, 0xa3, 0x9a, 0xb1, 0x9b, 0xbe,
+        0x9c, 0xcc, 0x9d, 0xda, 0x9e, 0xe7, 0x9f, 0xf3,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
+       {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,        /* 6 */
         0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
         0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
         0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
-        0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
-        0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
-        0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
+       {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,        /* 7 */
+        0x94, 0x38, 0x95, 0x4a, 0x96, 0x60, 0x97, 0x70,
+        0x98, 0x80, 0x99, 0x90, 0x9a, 0xa0, 0x9b, 0xb0,
+        0x9c, 0xc0, 0x9D, 0xd0, 0x9e, 0xe0, 0x9f, 0xf0,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
-        0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
-        0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
-        0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
+       {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,        /* 8 */
+        0x94, 0x47, 0x95, 0x5a, 0x96, 0x69, 0x97, 0x79,
+        0x98, 0x88, 0x99, 0x97, 0x9a, 0xa7, 0x9b, 0xb6,
+        0x9c, 0xc4, 0x9d, 0xd3, 0x9e, 0xe0, 0x9f, 0xf0,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
+       {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,        /* 9 */
         0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
         0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
         0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
-        0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
-        0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
-        0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
+       {0x90, 0x00, 0x91, 0x18, 0x92, 0x2b, 0x93, 0x44,        /* 10 */
+        0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8e,
+        0x98, 0x9c, 0x99, 0xaa, 0x9a, 0xb7, 0x9b, 0xc4,
+        0x9c, 0xd0, 0x9d, 0xd8, 0x9e, 0xe2, 0x9f, 0xf0,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
-        0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
-        0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
-        0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
+       {0x90, 0x00, 0x91, 0x1a, 0x92, 0x34, 0x93, 0x52,        /* 11 */
+        0x94, 0x66, 0x95, 0x7e, 0x96, 0x8D, 0x97, 0x9B,
+        0x98, 0xa8, 0x99, 0xb4, 0x9a, 0xc0, 0x9b, 0xcb,
+        0x9c, 0xd6, 0x9d, 0xe1, 0x9e, 0xeb, 0x9f, 0xf5,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
-        0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
-        0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
-        0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
-        0xA0, 0xFF},
-       {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
-        0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
-        0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
-        0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
+       {0x90, 0x00, 0x91, 0x3f, 0x92, 0x5a, 0x93, 0x6e,        /* 12 */
+        0x94, 0x7f, 0x95, 0x8e, 0x96, 0x9c, 0x97, 0xa8,
+        0x98, 0xb4, 0x99, 0xbf, 0x9a, 0xc9, 0x9b, 0xd3,
+        0x9c, 0xdc, 0x9d, 0xe5, 0x9e, 0xee, 0x9f, 0xf6,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
-        0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
-        0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
-        0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
+       {0x90, 0x00, 0x91, 0x54, 0x92, 0x6f, 0x93, 0x83,        /* 13 */
+        0x94, 0x93, 0x95, 0xa0, 0x96, 0xad, 0x97, 0xb7,
+        0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdc,
+        0x9c, 0xe4, 0x9d, 0xeb, 0x9e, 0xf2, 0x9f, 0xf9,
         0xa0, 0xff},
-       {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
-        0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
-        0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
-        0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
-        0xA0, 0xFF}
+       {0x90, 0x00, 0x91, 0x6e, 0x92, 0x88, 0x93, 0x9a,        /* 14 */
+        0x94, 0xa8, 0x95, 0xb3, 0x96, 0xbd, 0x97, 0xc6,
+        0x98, 0xcf, 0x99, 0xd6, 0x9a, 0xdd, 0x9b, 0xe3,
+        0x9c, 0xe9, 0x9d, 0xef, 0x9e, 0xf4, 0x9f, 0xfa,
+        0xa0, 0xff},
+       {0x90, 0x00, 0x91, 0x93, 0x92, 0xa8, 0x93, 0xb7,        /* 15 */
+        0x94, 0xc1, 0x95, 0xca, 0x96, 0xd2, 0x97, 0xd8,
+        0x98, 0xde, 0x99, 0xe3, 0x9a, 0xe8, 0x9b, 0xed,
+        0x9c, 0xf1, 0x9d, 0xf5, 0x9e, 0xf8, 0x9f, 0xfc,
+        0xa0, 0xff}
 };
 
 static const __u8 tas5130a_sensor_init[][8] = {
@@ -364,7 +366,7 @@ static const __u8 tas5130a_sensor_init[][8] = {
 };
 
 /* read 1 byte */
-static int reg_r_1(struct gspca_dev *gspca_dev,
+static int reg_r(struct gspca_dev *gspca_dev,
                   __u16 index)
 {
        usb_control_msg(gspca_dev->dev,
@@ -378,26 +380,26 @@ static int reg_r_1(struct gspca_dev *gspca_dev,
 }
 
 static void reg_w(struct gspca_dev *gspca_dev,
-                       __u16 value,
-                       __u16 index,
-                       const __u8 *buffer, __u16 len)
+                 __u16 index)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0, index,
+                       NULL, 0, 500);
+}
+
+static void i2c_w(struct gspca_dev *gspca_dev,
+                 const __u8 *buffer, __u16 len)
 {
-       if (buffer == NULL) {
-               usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0,
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                               value, index,
-                               NULL, 0, 500);
-               return;
-       }
        if (len <= USB_BUF_SZ) {
                memcpy(gspca_dev->usb_buf, buffer, len);
                usb_control_msg(gspca_dev->dev,
                                usb_sndctrlpipe(gspca_dev->dev, 0),
                                0,
                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                               value, index,
+                               0x01, 0,
                                gspca_dev->usb_buf, len, 500);
        } else {
                __u8 *tmpbuf;
@@ -408,12 +410,56 @@ static void reg_w(struct gspca_dev *gspca_dev,
                                usb_sndctrlpipe(gspca_dev->dev, 0),
                                0,
                           USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                               value, index,
+                               0x01, 0,
                                tmpbuf, len, 500);
                kfree(tmpbuf);
        }
 }
 
+static void other_sensor_init(struct gspca_dev *gspca_dev)
+{
+       int i;
+       const __u8 *p;
+       __u8 byte;
+       __u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
+       static const __u8 sensor_init[] = {
+               0xdf, 0x6d,
+               0xdd, 0x18,
+               0x5a, 0xe0,
+               0x5c, 0x07,
+               0x5d, 0xb0,
+               0x5e, 0x1e,
+               0x60, 0x71,
+               0xef, 0x00,
+               0xe9, 0x00,
+               0xea, 0x00,
+               0x90, 0x24,
+               0x91, 0xb2,
+               0x82, 0x32,
+               0xfd, 0x00,
+               0xfd, 0x01,
+               0xfd, 0x41,
+               0x00                    /* table end */
+       };
+
+       p = sensor_init;
+       while (*p != 0) {
+               val[1] = *p++;
+               val[3] = *p++;
+               if (*p == 0)
+                       reg_w(gspca_dev, 0x3c80);
+               i2c_w(gspca_dev, val, sizeof val);
+               i = 4;
+               while (--i >= 0) {
+                       msleep(15);
+                       byte = reg_r(gspca_dev, 0x60);
+                       if (!(byte & 0x01))
+                               break;
+               }
+       }
+                       reg_w(gspca_dev, 0x3c80);
+}
+
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
                     const struct usb_device_id *id)
@@ -430,7 +476,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
        sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
        sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
-       sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
+       sd->gamma = GAMMA_DEF;
        sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
        sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
        sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
@@ -439,27 +485,37 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;
 }
 
-static int init_default_parameters(struct gspca_dev *gspca_dev)
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
+       i2c_w(gspca_dev, gamma_table[sd->gamma], sizeof gamma_table[0]);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        /* some of this registers are not really neded, because
         * they are overriden by setbrigthness, setcontrast, etc,
         * but wont hurt anyway, and can help someone with similar webcam
         * to see the initial parameters.*/
-       int i = 0;
-       __u8 test_byte;
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       __u8 byte, test_byte;
 
        static const __u8 read_indexs[] =
                { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
                  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
-       static const __u8 n1[6] =
+       static const __u8 n1[] =
                        {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
-       static const __u8 n2[2] =
+       static const __u8 n2[] =
                        {0x08, 0x00};
-       static const __u8 nset[6] =
-               { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
-       static const __u8 n3[6] =
+       static const __u8 nset[] =
+                       { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
+       static const __u8 n3[] =
                        {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
-       static const __u8 n4[0x46] =
+       static const __u8 n4[] =
                {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
                 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
                 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
@@ -469,33 +525,26 @@ static int init_default_parameters(struct gspca_dev *gspca_dev)
                 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
                 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
                 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
-       static const __u8 nset4[18] = {
+       static const __u8 nset4[] = {
                0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
                0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
                0xe8, 0xe0
        };
        /* ojo puede ser 0xe6 en vez de 0xe9 */
-       static const __u8 nset2[20] = {
+       static const __u8 nset2[] = {
                0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
                0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
                0xd8, 0xc8, 0xd9, 0xfc
        };
-       static const __u8 missing[8] =
+       static const __u8 missing[] =
                { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
-       static const __u8 nset3[18] = {
+       static const __u8 nset3[] = {
                0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
                0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
                0xcf, 0xe0
        };
-       static const __u8 nset5[4] =
-               { 0x8f, 0x24, 0xc3, 0x00 };     /* bright */
-       static const __u8 nset6[34] = {
-               0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
-               0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
-               0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
-               0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
-               0xa0, 0xff
-       };                      /* Gamma */
+       static const __u8 nset5[] =
+                       { 0x8f, 0x24, 0xc3, 0x00 };     /* bright */
        static const __u8 nset7[4] =
                        { 0x66, 0xca, 0xa8, 0xf8 };     /* 50/60 Hz */
        static const __u8 nset9[4] =
@@ -505,95 +554,111 @@ static int init_default_parameters(struct gspca_dev *gspca_dev)
        static const __u8 nset10[6] =
                        { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
 
-       reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
-       reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
-       reg_r_1(gspca_dev, 0x0063);
-       reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
+       byte = reg_r(gspca_dev, 0x06);
+       test_byte = reg_r(gspca_dev, 0x07);
+       if (byte == 0x08 && test_byte == 0x07) {
+               PDEBUG(D_CONF, "other sensor");
+               sd->sensor = SENSOR_OTHER;
+       } else {
+               PDEBUG(D_CONF, "sensor %02x %02x", byte, test_byte);
+               sd->sensor = SENSOR_TAS5130A;
+       }
+
+       i2c_w(gspca_dev, n1, sizeof n1);
+       test_byte = 0;
+       i = 5;
+       while (--i >= 0) {
+               i2c_w(gspca_dev, nset, sizeof nset);
+               msleep(5);
+               test_byte = reg_r(gspca_dev, 0x0063);
+               msleep(100);
+               if (test_byte == 0x17)
+                       break;          /* OK */
+       }
+       if (i < 0) {
+               err("Bad sensor reset %02x", test_byte);
+/*             return -EIO; */
+/*fixme: test - continue */
+       }
+       i2c_w(gspca_dev, n2, sizeof n2);
 
+       i = 0;
        while (read_indexs[i] != 0x00) {
-               test_byte = reg_r_1(gspca_dev, read_indexs[i]);
-               PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
+               test_byte = reg_r(gspca_dev, read_indexs[i]);
+               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
                       test_byte);
                i++;
        }
 
-       reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
-       reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
-       reg_r_1(gspca_dev, 0x0080);
-       reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
-       reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
-       reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
-       reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
-       reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
-       reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
-       reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
-       reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
-       reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
-       reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
-       reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
-       reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
-
-       reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
-
-       reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
-       reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
-       reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
-
-       reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
-       reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
-       reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
-       reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
-
-       reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
-       reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
-       reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
-       reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
+       i2c_w(gspca_dev, n3, sizeof n3);
+       i2c_w(gspca_dev, n4, sizeof n4);
+       reg_r(gspca_dev, 0x0080);
+       reg_w(gspca_dev, 0x2c80);
+       i2c_w(gspca_dev, nset2, sizeof nset2);
+       i2c_w(gspca_dev, nset3, sizeof nset3);
+       i2c_w(gspca_dev, nset4, sizeof nset4);
+       reg_w(gspca_dev, 0x3880);
+       reg_w(gspca_dev, 0x3880);
+       reg_w(gspca_dev, 0x338e);
+       i2c_w(gspca_dev, nset5, sizeof nset5);
+       reg_w(gspca_dev, 0x00a9);
+       setgamma(gspca_dev);
+       reg_w(gspca_dev, 0x86bb);
+       reg_w(gspca_dev, 0x4aa6);
+
+       i2c_w(gspca_dev, missing, sizeof missing);
+
+       reg_w(gspca_dev, 0x2087);
+       reg_w(gspca_dev, 0x2088);
+       reg_w(gspca_dev, 0x2089);
+
+       i2c_w(gspca_dev, nset7, sizeof nset7);
+       i2c_w(gspca_dev, nset10, sizeof nset10);
+       i2c_w(gspca_dev, nset8, sizeof nset8);
+       i2c_w(gspca_dev, nset9, sizeof nset9);
+
+       reg_w(gspca_dev, 0x2880);
+       i2c_w(gspca_dev, nset2, sizeof nset2);
+       i2c_w(gspca_dev, nset3, sizeof nset3);
+       i2c_w(gspca_dev, nset4, sizeof nset4);
 
        return 0;
 }
 
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       init_default_parameters(gspca_dev);
-       return 0;
-}
-
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        unsigned int brightness;
-       __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
-       brightness = sd->brightness;
+       __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x00 };
 
+       brightness = sd->brightness;
        if (brightness < 7) {
-               set6[3] = 0x70 - (brightness * 0xa);
+               set6[3] = 0x70 - brightness * 0x10;
        } else {
                set6[1] = 0x24;
-               set6[3] = 0x00 + ((brightness - 7) * 0xa);
+               set6[3] = 0x00 + ((brightness - 7) * 0x10);
        }
 
-       reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
+       i2c_w(gspca_dev, set6, sizeof set6);
 }
 
 static void setflip(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-
        __u8 flipcmd[8] =
-           { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
+               {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
 
-       if (sd->mirror == 1)
+       if (sd->mirror)
                flipcmd[3] = 0x01;
 
-       reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
+       i2c_w(gspca_dev, flipcmd, sizeof flipcmd);
 }
 
 static void seteffect(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
+       i2c_w(gspca_dev, effects_table[sd->effect], sizeof effects_table[0]);
        if (sd->effect == 1 || sd->effect == 5) {
                PDEBUG(D_CONF,
                       "This effect have been disabled for webcam \"safety\"");
@@ -601,9 +666,9 @@ static void seteffect(struct gspca_dev *gspca_dev)
        }
 
        if (sd->effect == 1 || sd->effect == 4)
-               reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
+               reg_w(gspca_dev, 0x4aa6);
        else
-               reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
+               reg_w(gspca_dev, 0xfaa6);
 }
 
 static void setwhitebalance(struct gspca_dev *gspca_dev)
@@ -616,7 +681,7 @@ static void setwhitebalance(struct gspca_dev *gspca_dev)
        if (sd->whitebalance == 1)
                white_balance[7] = 0x3c;
 
-       reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
+       i2c_w(gspca_dev, white_balance, sizeof white_balance);
 }
 
 static void setlightfreq(struct gspca_dev *gspca_dev)
@@ -627,21 +692,21 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
        if (sd->freq == 2)      /* 60hz */
                freq[1] = 0x00;
 
-       reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
+       i2c_w(gspca_dev, freq, sizeof freq);
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        unsigned int contrast = sd->contrast;
-       __u16 reg_to_write = 0x00;
+       __u16 reg_to_write;
 
        if (contrast < 7)
                reg_to_write = 0x8ea9 - (0x200 * contrast);
        else
                reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
 
-       reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
+       reg_w(gspca_dev, reg_to_write);
 }
 
 static void setcolors(struct gspca_dev *gspca_dev)
@@ -650,11 +715,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
        __u16 reg_to_write;
 
        reg_to_write = 0xc0bb + sd->colors * 0x100;
-       reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
-}
-
-static void setgamma(struct gspca_dev *gspca_dev)
-{
+       reg_w(gspca_dev, reg_to_write);
 }
 
 static void setsharpness(struct gspca_dev *gspca_dev)
@@ -664,7 +725,99 @@ static void setsharpness(struct gspca_dev *gspca_dev)
 
        reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
 
-       reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
+       reg_w(gspca_dev, reg_to_write);
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, mode;
+       static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
+       __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
+       static const __u8 t3[] =
+               { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
+                 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
+       static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
+       switch (mode) {
+       case 1:         /* 352x288 */
+               t2[1] = 0x40;
+               break;
+       case 2:         /* 320x240 */
+               t2[1] = 0x10;
+               break;
+       case 3:         /* 176x144 */
+               t2[1] = 0x50;
+               break;
+       case 4:         /* 160x120 */
+               t2[1] = 0x20;
+               break;
+       default:        /* 640x480 (0x00) */
+               break;
+       }
+
+       if (sd->sensor == SENSOR_TAS5130A) {
+               i = 0;
+               while (tas5130a_sensor_init[i][0] != 0) {
+                       i2c_w(gspca_dev, tas5130a_sensor_init[i],
+                                        sizeof tas5130a_sensor_init[0]);
+                       i++;
+               }
+               reg_w(gspca_dev, 0x3c80);
+               /* just in case and to keep sync with logs (for mine) */
+               i2c_w(gspca_dev, tas5130a_sensor_init[3],
+                                sizeof tas5130a_sensor_init[0]);
+               reg_w(gspca_dev, 0x3c80);
+       } else {
+               other_sensor_init(gspca_dev);
+       }
+       /* just in case and to keep sync with logs  (for mine) */
+       i2c_w(gspca_dev, t1, sizeof t1);
+       i2c_w(gspca_dev, t2, sizeof t2);
+       reg_r(gspca_dev, 0x0012);
+       i2c_w(gspca_dev, t3, sizeof t3);
+       reg_w(gspca_dev, 0x0013);
+       i2c_w(gspca_dev, t4, sizeof t4);
+       /* restart on each start, just in case, sometimes regs goes wrong
+        * when using controls from app */
+       setbrightness(gspca_dev);
+       setcontrast(gspca_dev);
+       setcolors(gspca_dev);
+       return 0;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       struct gspca_frame *frame,      /* target */
+                       __u8 *data,                     /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       static __u8 ffd9[] = { 0xff, 0xd9 };
+
+       if (data[0] == 0x5a) {
+               /* Control Packet, after this came the header again,
+                * but extra bytes came in the packet before this,
+                * sometimes an EOF arrives, sometimes not... */
+               return;
+       }
+       data += 2;
+       len -= 2;
+       if (data[0] == 0xff && data[1] == 0xd8) {
+               /* extra bytes....., could be processed too but would be
+                * a waste of time, right now leave the application and
+                * libjpeg do it for ourserlves.. */
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       ffd9, 2);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
+               return;
+       }
+
+       if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+               /* Just in case, i have seen packets with the marker,
+                * other's do not include it... */
+               len -= 2;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -788,6 +941,7 @@ static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
 static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
+
        *val = sd->gamma;
        return 0;
 }
@@ -835,9 +989,9 @@ static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
 
        sd->autogain = val;
        if (val != 0)
-               reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
+               reg_w(gspca_dev, 0xf48e);
        else
-               reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
+               reg_w(gspca_dev, 0xb48e);
        return 0;
 }
 
@@ -849,99 +1003,6 @@ static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
-{
-       int mode;
-
-       static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
-       __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
-       static const __u8 t3[] =
-               { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
-                 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
-       static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
-       switch (mode) {
-       case 1:         /* 352x288 */
-               t2[1] = 0x40;
-               break;
-       case 2:         /* 320x240 */
-               t2[1] = 0x10;
-               break;
-       case 3:         /* 176x144 */
-               t2[1] = 0x50;
-               break;
-       case 4:         /* 160x120 */
-               t2[1] = 0x20;
-               break;
-       default:        /* 640x480 (0x00) */
-               break;
-       }
-
-       reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
-       reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
-       reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
-       reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
-       reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
-               /* just in case and to keep sync with logs  (for mine) */
-       reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
-       reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
-               /* just in case and to keep sync with logs  (for mine) */
-       reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
-       reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
-       reg_r_1(gspca_dev, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
-       reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
-       reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
-       /* restart on each start, just in case, sometimes regs goes wrong
-        * when using controls from app */
-       setbrightness(gspca_dev);
-       setcontrast(gspca_dev);
-       setcolors(gspca_dev);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       struct gspca_frame *frame,      /* target */
-                       __u8 *data,                     /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       int sof = 0;
-       static __u8 ffd9[] = { 0xff, 0xd9 };
-
-       if (data[0] == 0x5a) {
-               /* Control Packet, after this came the header again,
-                * but extra bytes came in the packet before this,
-                * sometimes an EOF arrives, sometimes not... */
-               return;
-       }
-
-       if (data[len - 1] == 0xff && data[len] == 0xd9) {
-               /* Just in case, i have seen packets with the marker,
-                * other's do not include it... */
-               data += 2;
-               len -= 4;
-       } else if (data[2] == 0xff && data[3] == 0xd8) {
-               sof = 1;
-               data += 2;
-               len -= 2;
-       } else {
-               data += 2;
-               len -= 2;
-       }
-
-       if (sof) {
-               /* extra bytes....., could be processed too but would be
-                * a waste of time, right now leave the application and
-                * libjpeg do it for ourserlves.. */
-               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
-                                       ffd9, 2);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
-               return;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
-}
-
 static int sd_querymenu(struct gspca_dev *gspca_dev,
                        struct v4l2_querymenu *menu)
 {
index 084af05302a0399f7e84e993437557d7433e3a3e..968a5911704fd381c2fe8ac67ead6b49d361b72f 100644 (file)
@@ -390,7 +390,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
 }
 
 /* -- start the camera -- */
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
        reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
@@ -443,6 +443,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        /************************************************/
        tv_8532_PollReg(gspca_dev);
        reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00);    /* 0x31 */
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index bd4c226c9a077843d2b787210cf227574c8dedea..be46d92325404d66b48c6e527005c736c5102812 100644 (file)
@@ -80,7 +80,6 @@ static struct ctrl sd_ctrls[] = {
                .step    = 1,
 #define FREQ_DEF 1
                .default_value = FREQ_DEF,
-               .default_value = 1,
            },
            .set = sd_setfreq,
            .get = sd_getfreq,
@@ -1502,7 +1501,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev)
        usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        const __u8 *GammaT = NULL;
@@ -1586,7 +1585,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                break;
        default:
                PDEBUG(D_PROBE, "Damned !! no sensor found Bye");
-               return;
+               return -EMEDIUMTYPE;
        }
        if (GammaT && MatrixT) {
                put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
@@ -1622,6 +1621,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                setautogain(gspca_dev);
                setlightfreq(gspca_dev);
        }
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
index d61ef727e0c241e08fe65b4f972450c154828da3..d0a4451dc46f2cf48ff3e73bba6e415aed9f086b 100644 (file)
@@ -7178,7 +7178,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct usb_device *dev = gspca_dev->dev;
@@ -7331,6 +7331,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                reg_w(dev, 0x02, 0x0008);
                break;
        }
+       return 0;
 }
 
 static void sd_stop0(struct gspca_dev *gspca_dev)
index a30254bed3119ed8483270d7f6e8cdb79624da6f..efe849981ab7c3766bb61efe78e437ebc1bb6ff1 100644 (file)
  *      Markus Rechberger <mrechberger@gmail.com>
  * modified for DViCO Fusion HDTV 5 RT GOLD by
  *      Chaogui Zhang <czhang1974@gmail.com>
+ * modified for MSI TV@nywhere Plus by
+ *      Henry Wong <henry@stuffedcow.net>
+ *      Mark Schultz <n9xmj@yahoo.com>
+ *      Brian Rogers <brian_rogers@comcast.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,7 +69,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
                               int size, int offset)
 {
        unsigned char buf[6];
-       int start, range, toggle, dev, code;
+       int start, range, toggle, dev, code, ircode;
 
        /* poll IR chip */
        if (size != i2c_master_recv(&ir->c,buf,size))
@@ -85,6 +89,24 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
        if (!start)
                /* no key pressed */
                return 0;
+       /*
+        * Hauppauge remotes (black/silver) always use
+        * specific device ids. If we do not filter the
+        * device ids then messages destined for devices
+        * such as TVs (id=0) will get through causing
+        * mis-fired events.
+        *
+        * We also filter out invalid key presses which
+        * produce annoying debug log entries.
+        */
+       ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
+       if ((ircode & 0x1fff)==0x1fff)
+               /* invalid key press */
+               return 0;
+
+       if (dev!=0x1e && dev!=0x1f)
+               /* not a hauppauge remote */
+               return 0;
 
        if (!range)
                code += 64;
@@ -94,7 +116,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
 
        /* return key */
        *ir_key = code;
-       *ir_raw = (start << 12) | (toggle << 11) | (dev << 6) | code;
+       *ir_raw = ircode;
        return 1;
 }
 
@@ -224,9 +246,15 @@ static void ir_timer(unsigned long data)
 static void ir_work(struct work_struct *work)
 {
        struct IR_i2c *ir = container_of(work, struct IR_i2c, work);
+       int polling_interval = 100;
+
+       /* MSI TV@nywhere Plus requires more frequent polling
+          otherwise it will miss some keypresses */
+       if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
+               polling_interval = 50;
 
        ir_key_poll(ir);
-       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100));
+       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval));
 }
 
 /* ----------------------------------------------------------------------- */
@@ -465,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap)
                        (1 == rc) ? "yes" : "no");
                if (1 == rc) {
                        ir_attach(adap, probe[i], 0, 0);
-                       break;
+                       return 0;
                }
        }
+
+       /* Special case for MSI TV@nywhere Plus remote */
+       if (adap->id == I2C_HW_SAA7134) {
+               u8 temp;
+
+               /* MSI TV@nywhere Plus controller doesn't seem to
+                  respond to probes unless we read something from
+                  an existing device. Weird... */
+
+               msg.addr = 0x50;
+               rc = i2c_transfer(adap, &msg, 1);
+                       dprintk(1, "probe 0x%02x @ %s: %s\n",
+                       msg.addr, adap->name,
+                       (1 == rc) ? "yes" : "no");
+
+               /* Now do the probe. The controller does not respond
+                  to 0-byte reads, so we use a 1-byte read instead. */
+               msg.addr = 0x30;
+               msg.len = 1;
+               msg.buf = &temp;
+               rc = i2c_transfer(adap, &msg, 1);
+               dprintk(1, "probe 0x%02x @ %s: %s\n",
+                       msg.addr, adap->name,
+                       (1 == rc) ? "yes" : "no");
+               if (1 == rc)
+                       ir_attach(adap, msg.addr, 0, 0);
+       }
+
        return 0;
 }
 
index 381af1bceef84c9924ee69b0c33f31a64a78820e..0b8fe85fb697972aae85181a36e09fe86f99e946 100644 (file)
 #define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
                          V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
                          V4L2_CAP_SLICED_VBI_CAPTURE)
-#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
+#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \
                          V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
 
 struct ivtv_card_video_input {
index 4afc7ea07e86ec16866862c4c4e118367dd8116a..aeaa13f6cb3639edda26bbc3178e4105fcdb283b 100644 (file)
 #include "tuner-xc2028.h"
 
 /* var to keep track of the number of array elements in use */
-int ivtv_cards_active = 0;
+int ivtv_cards_active;
 
 /* If you have already X v4l cards, then set this to X. This way
    the device numbers stay matched. Example: you have a WinTV card
    without radio and a PVR-350 with. Normally this would give a
    video1 device together with a radio0 device for the PVR. By
    setting this to 1 you ensure that radio0 is now also radio1. */
-int ivtv_first_minor = 0;
+int ivtv_first_minor;
 
 /* Master variable for all ivtv info */
 struct ivtv *ivtv_cards[IVTV_MAX_CARDS];
@@ -251,7 +251,7 @@ MODULE_PARM_DESC(newi2c,
                 "\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
                 "\t\t\tDefault is autodetect");
 
-MODULE_PARM_DESC(ivtv_first_minor, "Set minor assigned to first card");
+MODULE_PARM_DESC(ivtv_first_minor, "Set kernel number assigned to first card");
 
 MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
 MODULE_DESCRIPTION("CX23415/CX23416 driver");
@@ -655,9 +655,9 @@ done:
 
        if (itv->card == NULL) {
                itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
-               IVTV_ERR("Unknown card: vendor/device: %04x/%04x\n",
+               IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
                     itv->dev->vendor, itv->dev->device);
-               IVTV_ERR("              subsystem vendor/device: %04x/%04x\n",
+               IVTV_ERR("              subsystem vendor/device: [%04x:%04x]\n",
                     itv->dev->subsystem_vendor, itv->dev->subsystem_device);
                IVTV_ERR("              %s based\n", chipname);
                IVTV_ERR("Defaulting to %s card\n", itv->card->name);
@@ -720,7 +720,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
        itv->speed = 1000;
 
        /* VBI */
-       itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
        itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
 
        /* Init the sg table for osd/yuv output */
index 2ceb5227637c86e3a268323741b72f5fd021effb..bc29436e8a3cd4c3acc93a3c62df8b884d88d478 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/list.h>
 #include <linux/unistd.h>
-#include <linux/byteorder/swab.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #include <linux/workqueue.h>
@@ -507,6 +506,8 @@ struct yuv_playback_info
        struct v4l2_rect main_rect;
        u32 v4l2_src_w;
        u32 v4l2_src_h;
+
+       u8 running; /* Have any frames been displayed */
 };
 
 #define IVTV_VBI_FRAMES 32
@@ -751,6 +752,12 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
 /* First-open initialization: load firmware, init cx25840, etc. */
 int ivtv_init_on_first_open(struct ivtv *itv);
 
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int ivtv_raw_vbi(const struct ivtv *itv)
+{
+       return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
+}
+
 /* This is a PCI post thing, where if the pci register is not read, then
    the write doesn't always take effect right away. By reading back the
    register any pending PCI writes will be performed (in order), and so
index 7ec5c99f9ad1211c73d6004b3bbe12a4f822c2f4..b7457fc60ba5964c5131cc5282c1b2f29f831411 100644 (file)
@@ -39,7 +39,7 @@
    associated VBI streams are also automatically claimed.
    Possible error returns: -EBUSY if someone else has claimed
    the stream or 0 on success. */
-int ivtv_claim_stream(struct ivtv_open_id *id, int type)
+static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
 {
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[type];
@@ -78,7 +78,7 @@ int ivtv_claim_stream(struct ivtv_open_id *id, int type)
        if (type == IVTV_DEC_STREAM_TYPE_MPG) {
                vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
        } else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
-                  itv->vbi.insert_mpeg && itv->vbi.sliced_in->service_set) {
+                  itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
                vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
        } else {
                return 0;
@@ -305,7 +305,7 @@ static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *b
 
        if (len > ucount) len = ucount;
        if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
-           itv->vbi.sliced_in->service_set && buf != &itv->vbi.sliced_mpeg_buf) {
+           !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
                const char *start = buf->buf + buf->readpos;
                const char *p = start + 1;
                const u8 *q;
@@ -372,7 +372,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
        /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
           arrive one-by-one, so make sure we never output more than one VBI frame at a time */
        if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
-                       (s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set))
+           (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
                single_frame = 1;
 
        for (;;) {
index 2c8d5186c9c3cca56f09021a633066f473674cbf..df81e790147f71a9e839d5efda508a614778ef77 100644 (file)
@@ -38,11 +38,6 @@ void ivtv_unmute(struct ivtv *itv);
 
 /* Utilities */
 
-/* Try to claim a stream for the filehandle. Return 0 on success,
-   -EBUSY if stream already claimed. Once a stream is claimed, it
-   remains claimed until the associated filehandle is closed. */
-int ivtv_claim_stream(struct ivtv_open_id *id, int type);
-
 /* Release a previously claimed stream. */
 void ivtv_release_stream(struct ivtv_stream *s);
 
index bc22905ea20fa58c5f890a58a418361d495a46ef..74a44844ccaf346a1a46c05941178f728b261fbf 100644 (file)
@@ -124,7 +124,7 @@ void ivtv_reset_ir_gpio(struct ivtv *itv)
 }
 
 /* Xceive tuner reset function */
-int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
 {
        struct i2c_algo_bit_data *algo = dev;
        struct ivtv *itv = algo->data;
index 964a265d91a9c27c4cf0f54238ec122104210aaa..48b6291613a23397065bae0699f3809aef1093e4 100644 (file)
@@ -24,7 +24,7 @@
 /* GPIO stuff */
 void ivtv_gpio_init(struct ivtv *itv);
 void ivtv_reset_ir_gpio(struct ivtv *itv);
-int ivtv_reset_tuner_gpio(void *dev, int cmd, int value);
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
 int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg);
 
 #endif
index af154238fb9afdc7817bc8e685923aa18e607950..24700c211d5264e660696e64cf92373d69e82793 100644 (file)
@@ -64,8 +64,6 @@
 #include "ivtv-gpio.h"
 #include "ivtv-i2c.h"
 
-#include <media/ir-kbd-i2c.h>
-
 /* i2c implementation for cx23415/6 chip, ivtv project.
  * Author: Kevin Thayer (nufan_wfk at yahoo.com)
  */
index 61030309d0ad876b696478355b5ba683eb832879..8696527ab134bfb6daaee2e49eb7911a5c0cbf44 100644 (file)
@@ -101,18 +101,15 @@ void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
        }
 }
 
-static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
 {
        int f, l;
-       u16 set = 0;
 
        for (f = 0; f < 2; f++) {
                for (l = 0; l < 24; l++) {
                        fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
-                       set |= fmt->service_lines[f][l];
                }
        }
-       return set != 0;
 }
 
 u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
@@ -474,7 +471,7 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
        int h = fmt->fmt.pix.height;
 
        w = min(w, 720);
-       w = max(w, 1);
+       w = max(w, 2);
        h = min(h, itv->is_50hz ? 576 : 480);
        h = max(h, 2);
        ivtv_g_fmt_vid_cap(file, fh, fmt);
@@ -512,27 +509,20 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_
 static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
        struct ivtv_open_id *id = fh;
-       s32 w, h;
-       int field;
-       int ret;
+       struct ivtv *itv = id->itv;
+       s32 w = fmt->fmt.pix.width;
+       s32 h = fmt->fmt.pix.height;
+       int field = fmt->fmt.pix.field;
+       int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
 
-       w = fmt->fmt.pix.width;
-       h = fmt->fmt.pix.height;
-       field = fmt->fmt.pix.field;
-       ret = ivtv_g_fmt_vid_out(file, fh, fmt);
+       w = min(w, 720);
+       w = max(w, 2);
+       h = min(h, itv->is_out_50hz ? 576 : 480);
+       h = max(h, 2);
+       if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
+               fmt->fmt.pix.field = field;
        fmt->fmt.pix.width = w;
        fmt->fmt.pix.height = h;
-       if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               fmt->fmt.pix.field = field;
-               if (fmt->fmt.pix.width < 2)
-                       fmt->fmt.pix.width = 2;
-               if (fmt->fmt.pix.width > 720)
-                       fmt->fmt.pix.width = 720;
-               if (fmt->fmt.pix.height < 2)
-                       fmt->fmt.pix.height = 2;
-               if (fmt->fmt.pix.height > 576)
-                       fmt->fmt.pix.height = 576;
-       }
        return ret;
 }
 
@@ -560,9 +550,9 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
        struct ivtv_open_id *id = fh;
        struct ivtv *itv = id->itv;
        struct cx2341x_mpeg_params *p = &itv->params;
+       int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
        int w = fmt->fmt.pix.width;
        int h = fmt->fmt.pix.height;
-       int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
 
        if (ret)
                return ret;
@@ -585,8 +575,11 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f
 {
        struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
 
+       if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+               return -EBUSY;
        itv->vbi.sliced_in->service_set = 0;
-       itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
+       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
        return ivtv_g_fmt_vbi_cap(file, fh, fmt);
 }
 
@@ -600,10 +593,10 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
        if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
                return ret;
 
-       if (check_service_set(vbifmt, itv->is_50hz) == 0)
-               return -EINVAL;
-       if (atomic_read(&itv->capturing) > 0)
+       check_service_set(vbifmt, itv->is_50hz);
+       if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
                return -EBUSY;
+       itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
        itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
        memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
        return 0;
@@ -651,8 +644,6 @@ static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
                itv->dma_data_req_size =
                        1080 * ((yi->v4l2_src_h + 31) & ~31);
 
-       /* Force update of yuv registers */
-       yi->yuv_forced_update = 1;
        return 0;
 }
 
@@ -761,7 +752,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
 
        strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
        strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
-       strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
+       snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev));
        vcap->version = IVTV_DRIVER_VERSION;        /* version */
        vcap->capabilities = itv->v4l2_cap;         /* capabilities */
        return 0;
@@ -1370,6 +1361,9 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
        if (itv->osd_global_alpha_state)
                fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
 
+       if (yi->track_osd)
+               fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+
        pixfmt &= 7;
 
        /* no local alpha for RGB565 or unknown formats */
@@ -1389,8 +1383,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
                else
                        fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
        }
-       if (yi->track_osd)
-               fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
 
        return 0;
 }
index 34f3ab82785853634bc3c47deb7587d7590508d3..f5d00ec5da73501cb2b99ad93404b9b5dc63a881 100644 (file)
@@ -753,7 +753,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
         */
        unsigned int frame = read_reg(0x28c0) & 1;
        struct yuv_playback_info *yi = &itv->yuv_info;
-       int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame);
+       int last_dma_frame = atomic_read(&yi->next_dma_frame);
        struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
 
        if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
@@ -772,6 +772,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
                                next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
                                atomic_set(&yi->next_dma_frame, next_dma_frame);
                                yi->fields_lapsed = -1;
+                               yi->running = 1;
                        }
                }
        }
@@ -804,9 +805,11 @@ static void ivtv_irq_vsync(struct ivtv *itv)
                }
 
                /* Check if we need to update the yuv registers */
-               if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) {
+               if (yi->running && (yi->yuv_forced_update || f->update)) {
                        if (!f->update) {
-                               last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS;
+                               last_dma_frame =
+                                       (u8)(atomic_read(&yi->next_dma_frame) -
+                                                1) % IVTV_YUV_BUFFERS;
                                f = &yi->new_frame_info[last_dma_frame];
                        }
 
index 730e85d86fc82d0c27e7351ea4b4689dbcb5bd89..5bbf31e393048fd6b1cd6740a4c02b9ace8f051b 100644 (file)
@@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = {
 static struct {
        const char *name;
        int vfl_type;
-       int minor_offset;
+       int num_offset;
        int dma, pio;
        enum v4l2_buf_type buf_type;
        const struct file_operations *fops;
@@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
 static int ivtv_prep_dev(struct ivtv *itv, int type)
 {
        struct ivtv_stream *s = &itv->streams[type];
-       int minor_offset = ivtv_stream_info[type].minor_offset;
-       int minor;
+       int num_offset = ivtv_stream_info[type].num_offset;
+       int num = itv->num + ivtv_first_minor + num_offset;
 
        /* These four fields are always initialized. If v4l2dev == NULL, then
           this stream is not in use. In that case no other fields but these
@@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
        if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
                return 0;
 
-       /* card number + user defined offset + device offset */
-       minor = itv->num + ivtv_first_minor + minor_offset;
-
        /* User explicitly selected 0 buffers for these streams, so don't
           create them. */
        if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
@@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
        snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s",
                        itv->num, s->name);
 
-       s->v4l2dev->minor = minor;
+       s->v4l2dev->num = num;
        s->v4l2dev->parent = &itv->dev->dev;
        s->v4l2dev->fops = ivtv_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
@@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
 {
        struct ivtv_stream *s = &itv->streams[type];
        int vfl_type = ivtv_stream_info[type].vfl_type;
-       int minor;
+       int num;
 
        if (s->v4l2dev == NULL)
                return 0;
 
-       minor = s->v4l2dev->minor;
+       num = s->v4l2dev->num;
+       /* card number + user defined offset + device offset */
+       if (type != IVTV_ENC_STREAM_TYPE_MPG) {
+               struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
+
+               if (s_mpg->v4l2dev)
+                       num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
+       }
+
        /* Register device. First try the desired minor, then any free one. */
-       if (video_register_device(s->v4l2dev, vfl_type, minor) &&
-                       video_register_device(s->v4l2dev, vfl_type, -1)) {
-               IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n",
-                               s->name, minor);
+       if (video_register_device(s->v4l2dev, vfl_type, num)) {
+               IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
+                               s->name, num);
                video_device_release(s->v4l2dev);
                s->v4l2dev = NULL;
                return -ENOMEM;
        }
+       num = s->v4l2dev->num;
 
        switch (vfl_type) {
        case VFL_TYPE_GRABBER:
                IVTV_INFO("Registered device video%d for %s (%d kB)\n",
-                       s->v4l2dev->minor, s->name, itv->options.kilobytes[type]);
+                       num, s->name, itv->options.kilobytes[type]);
                break;
        case VFL_TYPE_RADIO:
                IVTV_INFO("Registered device radio%d for %s\n",
-                       s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+                       num, s->name);
                break;
        case VFL_TYPE_VBI:
                if (itv->options.kilobytes[type])
                        IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
-                               s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN,
-                               s->name, itv->options.kilobytes[type]);
+                               num, s->name, itv->options.kilobytes[type]);
                else
                        IVTV_INFO("Registered device vbi%d for %s\n",
-                               s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+                               num, s->name);
                break;
        }
        return 0;
@@ -330,7 +334,7 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
 
 static void ivtv_vbi_setup(struct ivtv *itv)
 {
-       int raw = itv->vbi.sliced_in->service_set == 0;
+       int raw = ivtv_raw_vbi(itv);
        u32 data[CX2341X_MBOX_MAX_DATA];
        int lines;
        int i;
index 1ce9deb1104fc1bdc970811d65ea52a346087570..4a37a7d2e69d53332341dd2f7cda8f66e6d6bc3e 100644 (file)
@@ -334,7 +334,7 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
        int y;
 
        /* Raw VBI data */
-       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set == 0) {
+       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
                u8 type;
 
                ivtv_buf_swap(buf);
index 3092ff1d00a066a24a4d04b3de06f1999159a299..ee91107376c75440ca56f6620924724a2267c5ab 100644 (file)
@@ -1147,6 +1147,7 @@ void ivtv_yuv_close(struct ivtv *itv)
        IVTV_DEBUG_YUV("ivtv_yuv_close\n");
        ivtv_waitq(&itv->vsync_waitq);
 
+       yi->running = 0;
        atomic_set(&yi->next_dma_frame, -1);
        atomic_set(&yi->next_fill_frame, 0);
 
index bdfda48e56bf55e0b5ea3af83404348053fd26b8..8a4a150b12fb1083c787da3fb3ddcbdb9ab9a51c 100644 (file)
@@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
                                  int size_in_bytes)
 {
        DEFINE_WAIT(wait);
-       int ret = 0;
        int got_sig = 0;
 
        mutex_lock(&itv->udma.lock);
@@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
                return -EINTR;
        }
 
-       return ret;
+       return 0;
 }
 
 static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
@@ -368,11 +367,12 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
 }
 
 static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
-                    size_t count, loff_t *ppos)
+                                               size_t count, loff_t *ppos)
 {
        unsigned long p = *ppos;
        void *dst;
        int err = 0;
+       int dma_err;
        unsigned long total_size;
        struct ivtv *itv = (struct ivtv *) info->par;
        unsigned long dma_offset =
@@ -399,7 +399,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
        if (count + p > total_size) {
                if (!err)
                        err = -ENOSPC;
-
                count = total_size - p;
        }
 
@@ -408,39 +407,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
        if (info->fbops->fb_sync)
                info->fbops->fb_sync(info);
 
-       if (!access_ok(VERIFY_READ, buf, count)) {
-               IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
-                       (unsigned long)buf);
-               err = -EFAULT;
-       }
-
-       if (!err) {
-               /* If transfer size > threshold and both src/dst
-               addresses are aligned, use DMA */
-               if (count >= 4096 &&
-                   ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
-                       /* Odd address = can't DMA. Align */
-                       if ((unsigned long)dst & 3) {
-                               lead = 4 - ((unsigned long)dst & 3);
-                               memcpy(dst, buf, lead);
-                               buf += lead;
-                               dst += lead;
-                       }
-                       /* DMA resolution is 32 bits */
-                       if ((count - lead) & 3)
-                               tail = (count - lead) & 3;
-                       /* DMA the data */
-                       dma_size = count - lead - tail;
-                       err = ivtvfb_prep_dec_dma_to_device(itv,
-                              p + lead + dma_offset, (void *)buf, dma_size);
-                       dst += dma_size;
-                       buf += dma_size;
-                       /* Copy any leftover data */
-                       if (tail)
-                               memcpy(dst, buf, tail);
-               } else {
-                       memcpy(dst, buf, count);
+       /* If transfer size > threshold and both src/dst
+       addresses are aligned, use DMA */
+       if (count >= 4096 &&
+           ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
+               /* Odd address = can't DMA. Align */
+               if ((unsigned long)dst & 3) {
+                       lead = 4 - ((unsigned long)dst & 3);
+                       if (copy_from_user(dst, buf, lead))
+                               return -EFAULT;
+                       buf += lead;
+                       dst += lead;
                }
+               /* DMA resolution is 32 bits */
+               if ((count - lead) & 3)
+                       tail = (count - lead) & 3;
+               /* DMA the data */
+               dma_size = count - lead - tail;
+               dma_err = ivtvfb_prep_dec_dma_to_device(itv,
+                      p + lead + dma_offset, (void __user *)buf, dma_size);
+               if (dma_err)
+                       return dma_err;
+               dst += dma_size;
+               buf += dma_size;
+               /* Copy any leftover data */
+               if (tail && copy_from_user(dst, buf, tail))
+                       return -EFAULT;
+       } else if (copy_from_user(dst, buf, count)) {
+               return -EFAULT;
        }
 
        if  (!err)
@@ -463,9 +457,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
                        vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
                                        FB_VBLANK_HAVE_VSYNC;
                        trace = read_reg(0x028c0) >> 16;
-                       if (itv->is_50hz && trace > 312) trace -= 312;
-                       else if (itv->is_60hz && trace > 262) trace -= 262;
-                       if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
+                       if (itv->is_50hz && trace > 312)
+                               trace -= 312;
+                       else if (itv->is_60hz && trace > 262)
+                               trace -= 262;
+                       if (trace == 1)
+                               vblank.flags |= FB_VBLANK_VSYNCING;
                        vblank.count = itv->last_vsync_field;
                        vblank.vcount = trace;
                        vblank.hcount = 0;
@@ -476,7 +473,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
 
                case FBIO_WAITFORVSYNC:
                        prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
-                       if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT;
+                       if (!schedule_timeout(msecs_to_jiffies(50)))
+                               rc = -ETIMEDOUT;
                        finish_wait(&itv->vsync_waitq, &wait);
                        return rc;
 
index a9ef7802eb5fcdaf793d8f695d4ecc35e0ddb903..6418f4a78f2a86afc716ff9e6e4d377ceceb434d 100644 (file)
@@ -843,17 +843,16 @@ again:
 
 static int meye_open(struct inode *inode, struct file *file)
 {
-       int i, err;
+       int i;
 
-       err = video_exclusive_open(inode, file);
-       if (err < 0)
-               return err;
+       if (test_and_set_bit(0, &meye.in_use))
+               return -EBUSY;
 
        mchip_hic_stop();
 
        if (mchip_dma_alloc()) {
                printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
-               video_exclusive_release(inode, file);
+               clear_bit(0, &meye.in_use);
                return -ENOBUFS;
        }
 
@@ -868,7 +867,7 @@ static int meye_release(struct inode *inode, struct file *file)
 {
        mchip_hic_stop();
        mchip_dma_free();
-       video_exclusive_release(inode, file);
+       clear_bit(0, &meye.in_use);
        return 0;
 }
 
@@ -1774,6 +1773,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
                goto outnotdev;
        }
 
+       ret = -ENOMEM;
        meye.mchip_dev = pcidev;
        meye.video_dev = video_device_alloc();
        if (!meye.video_dev) {
@@ -1781,7 +1781,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
                goto outnotdev;
        }
 
-       ret = -ENOMEM;
        meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
        if (!meye.grab_temp) {
                printk(KERN_ERR "meye: grab buffer allocation failed\n");
index d535748df445a9d50f121addae83dd9e92d8b617..5f70a106ba2bbc8597256a8d0443d75fbb98416b 100644 (file)
@@ -311,6 +311,7 @@ struct meye {
        struct video_device *video_dev; /* video device parameters */
        struct video_picture picture;   /* video picture parameters */
        struct meye_params params;      /* additional parameters */
+       unsigned long in_use;           /* set to 1 if the device is in use */
 #ifdef CONFIG_PM
        u8 pm_mchip_mode;               /* old mchip mode */
 #endif
index 554d2295484e5f1b02f7fec28c34768fa596d0dd..0c524376b67e66baa4f67ddcf262a647a02143e1 100644 (file)
@@ -117,24 +117,51 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg,
 
 static int mt9m001_init(struct soc_camera_device *icd)
 {
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
        int ret;
 
-       /* Disable chip, synchronous option update */
        dev_dbg(icd->vdev->parent, "%s\n", __func__);
 
-       ret = reg_write(icd, MT9M001_RESET, 1);
-       if (ret >= 0)
-               ret = reg_write(icd, MT9M001_RESET, 0);
-       if (ret >= 0)
+       if (icl->power) {
+               ret = icl->power(&mt9m001->client->dev, 1);
+               if (ret < 0) {
+                       dev_err(icd->vdev->parent,
+                               "Platform failed to power-on the camera.\n");
+                       return ret;
+               }
+       }
+
+       /* The camera could have been already on, we reset it additionally */
+       if (icl->reset)
+               ret = icl->reset(&mt9m001->client->dev);
+       else
+               ret = -ENODEV;
+
+       if (ret < 0) {
+               /* Either no platform reset, or platform reset failed */
+               ret = reg_write(icd, MT9M001_RESET, 1);
+               if (!ret)
+                       ret = reg_write(icd, MT9M001_RESET, 0);
+       }
+       /* Disable chip, synchronous option update */
+       if (!ret)
                ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
 
-       return ret >= 0 ? 0 : -EIO;
+       return ret;
 }
 
 static int mt9m001_release(struct soc_camera_device *icd)
 {
+       struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+       struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+
        /* Disable the chip */
        reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+
+       if (icl->power)
+               icl->power(&mt9m001->client->dev, 0);
+
        return 0;
 }
 
@@ -267,24 +294,24 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
 
        /* Blanking and start values - default... */
        ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
 
        /* The caller provides a supported format, as verified per
         * call to icd->try_fmt_cap() */
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9M001_ROW_START, rect->top);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
                                rect->height + icd->y_skip_top - 1);
-       if (ret >= 0 && mt9m001->autoexposure) {
+       if (!ret && mt9m001->autoexposure) {
                ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
                                rect->height + icd->y_skip_top + vblank);
-               if (ret >= 0) {
+               if (!ret) {
                        const struct v4l2_queryctrl *qctrl =
                                soc_camera_find_qctrl(icd->ops,
                                                      V4L2_CID_EXPOSURE);
@@ -295,7 +322,7 @@ static int mt9m001_set_fmt_cap(struct soc_camera_device *icd,
                }
        }
 
-       return ret < 0 ? ret : 0;
+       return ret;
 }
 
 static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
new file mode 100644 (file)
index 0000000..da0b2d5
--- /dev/null
@@ -0,0 +1,973 @@
+/*
+ * Driver for MT9M111 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * This program is free software; you can 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+/*
+ * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin)
+ * The platform has to define i2c_board_info and call i2c_register_board_info()
+ */
+
+/* mt9m111: Sensor register addresses */
+#define MT9M111_CHIP_VERSION           0x000
+#define MT9M111_ROW_START              0x001
+#define MT9M111_COLUMN_START           0x002
+#define MT9M111_WINDOW_HEIGHT          0x003
+#define MT9M111_WINDOW_WIDTH           0x004
+#define MT9M111_HORIZONTAL_BLANKING_B  0x005
+#define MT9M111_VERTICAL_BLANKING_B    0x006
+#define MT9M111_HORIZONTAL_BLANKING_A  0x007
+#define MT9M111_VERTICAL_BLANKING_A    0x008
+#define MT9M111_SHUTTER_WIDTH          0x009
+#define MT9M111_ROW_SPEED              0x00a
+#define MT9M111_EXTRA_DELAY            0x00b
+#define MT9M111_SHUTTER_DELAY          0x00c
+#define MT9M111_RESET                  0x00d
+#define MT9M111_READ_MODE_B            0x020
+#define MT9M111_READ_MODE_A            0x021
+#define MT9M111_FLASH_CONTROL          0x023
+#define MT9M111_GREEN1_GAIN            0x02b
+#define MT9M111_BLUE_GAIN              0x02c
+#define MT9M111_RED_GAIN               0x02d
+#define MT9M111_GREEN2_GAIN            0x02e
+#define MT9M111_GLOBAL_GAIN            0x02f
+#define MT9M111_CONTEXT_CONTROL                0x0c8
+#define MT9M111_PAGE_MAP               0x0f0
+#define MT9M111_BYTE_WISE_ADDR         0x0f1
+
+#define MT9M111_RESET_SYNC_CHANGES     (1 << 15)
+#define MT9M111_RESET_RESTART_BAD_FRAME        (1 << 9)
+#define MT9M111_RESET_SHOW_BAD_FRAMES  (1 << 8)
+#define MT9M111_RESET_RESET_SOC                (1 << 5)
+#define MT9M111_RESET_OUTPUT_DISABLE   (1 << 4)
+#define MT9M111_RESET_CHIP_ENABLE      (1 << 3)
+#define MT9M111_RESET_ANALOG_STANDBY   (1 << 2)
+#define MT9M111_RESET_RESTART_FRAME    (1 << 1)
+#define MT9M111_RESET_RESET_MODE       (1 << 0)
+
+#define MT9M111_RMB_MIRROR_COLS                (1 << 1)
+#define MT9M111_RMB_MIRROR_ROWS                (1 << 0)
+#define MT9M111_CTXT_CTRL_RESTART      (1 << 15)
+#define MT9M111_CTXT_CTRL_DEFECTCOR_B  (1 << 12)
+#define MT9M111_CTXT_CTRL_RESIZE_B     (1 << 10)
+#define MT9M111_CTXT_CTRL_CTRL2_B      (1 << 9)
+#define MT9M111_CTXT_CTRL_GAMMA_B      (1 << 8)
+#define MT9M111_CTXT_CTRL_XENON_EN     (1 << 7)
+#define MT9M111_CTXT_CTRL_READ_MODE_B  (1 << 3)
+#define MT9M111_CTXT_CTRL_LED_FLASH_EN (1 << 2)
+#define MT9M111_CTXT_CTRL_VBLANK_SEL_B (1 << 1)
+#define MT9M111_CTXT_CTRL_HBLANK_SEL_B (1 << 0)
+/*
+ * mt9m111: Colorpipe register addresses (0x100..0x1ff)
+ */
+#define MT9M111_OPER_MODE_CTRL         0x106
+#define MT9M111_OUTPUT_FORMAT_CTRL     0x108
+#define MT9M111_REDUCER_XZOOM_B                0x1a0
+#define MT9M111_REDUCER_XSIZE_B                0x1a1
+#define MT9M111_REDUCER_YZOOM_B                0x1a3
+#define MT9M111_REDUCER_YSIZE_B                0x1a4
+#define MT9M111_REDUCER_XZOOM_A                0x1a6
+#define MT9M111_REDUCER_XSIZE_A                0x1a7
+#define MT9M111_REDUCER_YZOOM_A                0x1a9
+#define MT9M111_REDUCER_YSIZE_A                0x1aa
+
+#define MT9M111_OUTPUT_FORMAT_CTRL2_A  0x13a
+#define MT9M111_OUTPUT_FORMAT_CTRL2_B  0x19b
+
+#define MT9M111_OPMODE_AUTOEXPO_EN     (1 << 14)
+
+
+#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)
+#define MT9M111_OUTFMT_BYPASS_IFP      (1 << 10)
+#define MT9M111_OUTFMT_INV_PIX_CLOCK   (1 << 9)
+#define MT9M111_OUTFMT_RGB             (1 << 8)
+#define MT9M111_OUTFMT_RGB565          (0x0 << 6)
+#define MT9M111_OUTFMT_RGB555          (0x1 << 6)
+#define MT9M111_OUTFMT_RGB444x         (0x2 << 6)
+#define MT9M111_OUTFMT_RGBx444         (0x3 << 6)
+#define MT9M111_OUTFMT_TST_RAMP_OFF    (0x0 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_COL    (0x1 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_ROW    (0x2 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_FRAME  (0x3 << 4)
+#define MT9M111_OUTFMT_SHIFT_3_UP      (1 << 3)
+#define MT9M111_OUTFMT_AVG_CHROMA      (1 << 2)
+#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y  (1 << 1)
+#define MT9M111_OUTFMT_SWAP_RGB_EVEN   (1 << 1)
+#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr        (1 << 0)
+/*
+ * mt9m111: Camera control register addresses (0x200..0x2ff not implemented)
+ */
+
+#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val))
+
+#define MT9M111_MIN_DARK_ROWS  8
+#define MT9M111_MIN_DARK_COLS  24
+#define MT9M111_MAX_HEIGHT     1024
+#define MT9M111_MAX_WIDTH      1280
+
+#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
+       { .name = _name, .depth = _depth, .fourcc = _fourcc, \
+       .colorspace = _colorspace }
+#define RGB_FMT(_name, _depth, _fourcc) \
+       COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB)
+
+static const struct soc_camera_data_format mt9m111_colour_formats[] = {
+       COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG),
+       RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565),
+       RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555),
+       RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16),
+       RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8),
+};
+
+enum mt9m111_context {
+       HIGHPOWER = 0,
+       LOWPOWER,
+};
+
+struct mt9m111 {
+       struct i2c_client *client;
+       struct soc_camera_device icd;
+       int model;      /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */
+       enum mt9m111_context context;
+       unsigned int left, top, width, height;
+       u32 pixfmt;
+       unsigned char autoexposure;
+       unsigned char datawidth;
+       unsigned int powered:1;
+       unsigned int hflip:1;
+       unsigned int vflip:1;
+       unsigned int swap_rgb_even_odd:1;
+       unsigned int swap_rgb_red_blue:1;
+       unsigned int swap_yuv_y_chromas:1;
+       unsigned int swap_yuv_cb_cr:1;
+};
+
+static int reg_page_map_set(struct i2c_client *client, const u16 reg)
+{
+       int ret;
+       u16 page;
+       static int lastpage = -1;       /* PageMap cache value */
+
+       page = (reg >> 8);
+       if (page == lastpage)
+               return 0;
+       if (page > 2)
+               return -EINVAL;
+
+       ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page));
+       if (!ret)
+               lastpage = page;
+       return ret;
+}
+
+static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       struct i2c_client *client = mt9m111->client;
+       int ret;
+
+       ret = reg_page_map_set(client, reg);
+       if (!ret)
+               ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff)));
+
+       dev_dbg(&icd->dev, "read  reg.%03x -> %04x\n", reg, ret);
+       return ret;
+}
+
+static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg,
+                            const u16 data)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       struct i2c_client *client = mt9m111->client;
+       int ret;
+
+       ret = reg_page_map_set(client, reg);
+       if (!ret)
+               ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff),
+                                               swab16(data));
+       dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+       return ret;
+}
+
+static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg,
+                          const u16 data)
+{
+       int ret;
+
+       ret = mt9m111_reg_read(icd, reg);
+       if (ret >= 0)
+               ret = mt9m111_reg_write(icd, reg, ret | data);
+       return ret;
+}
+
+static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg,
+                            const u16 data)
+{
+       int ret;
+
+       ret = mt9m111_reg_read(icd, reg);
+       return mt9m111_reg_write(icd, reg, ret & ~data);
+}
+
+static int mt9m111_set_context(struct soc_camera_device *icd,
+                              enum mt9m111_context ctxt)
+{
+       int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
+               | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
+               | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
+               | MT9M111_CTXT_CTRL_VBLANK_SEL_B
+               | MT9M111_CTXT_CTRL_HBLANK_SEL_B;
+       int valA = MT9M111_CTXT_CTRL_RESTART;
+
+       if (ctxt == HIGHPOWER)
+               return reg_write(CONTEXT_CONTROL, valB);
+       else
+               return reg_write(CONTEXT_CONTROL, valA);
+}
+
+static int mt9m111_setup_rect(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret, is_raw_format;
+       int width = mt9m111->width;
+       int height = mt9m111->height;
+
+       if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8)
+           || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16))
+               is_raw_format = 1;
+       else
+               is_raw_format = 0;
+
+       ret = reg_write(COLUMN_START, mt9m111->left);
+       if (!ret)
+               ret = reg_write(ROW_START, mt9m111->top);
+
+       if (is_raw_format) {
+               if (!ret)
+                       ret = reg_write(WINDOW_WIDTH, width);
+               if (!ret)
+                       ret = reg_write(WINDOW_HEIGHT, height);
+       } else {
+               if (!ret)
+                       ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH);
+               if (!ret)
+                       ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT);
+               if (!ret)
+                       ret = reg_write(REDUCER_XSIZE_B, width);
+               if (!ret)
+                       ret = reg_write(REDUCER_YSIZE_B, height);
+               if (!ret)
+                       ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH);
+               if (!ret)
+                       ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT);
+               if (!ret)
+                       ret = reg_write(REDUCER_XSIZE_A, width);
+               if (!ret)
+                       ret = reg_write(REDUCER_YSIZE_A, height);
+       }
+
+       return ret;
+}
+
+static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
+{
+       int ret;
+
+       ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
+       if (!ret)
+               ret = reg_write(OUTPUT_FORMAT_CTRL2_B, outfmt);
+       return ret;
+}
+
+static int mt9m111_setfmt_bayer8(struct soc_camera_device *icd)
+{
+       return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_PROCESSED_BAYER);
+}
+
+static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
+{
+       return mt9m111_setup_pixfmt(icd, MT9M111_OUTFMT_BYPASS_IFP);
+}
+
+static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int val = 0;
+
+       if (mt9m111->swap_rgb_red_blue)
+               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+       if (mt9m111->swap_rgb_even_odd)
+               val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
+       val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
+
+       return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int val = 0;
+
+       if (mt9m111->swap_rgb_red_blue)
+               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+       if (mt9m111->swap_rgb_even_odd)
+               val |= MT9M111_OUTFMT_SWAP_RGB_EVEN;
+       val |= MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
+
+       return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int val = 0;
+
+       if (mt9m111->swap_yuv_cb_cr)
+               val |= MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr;
+       if (mt9m111->swap_yuv_y_chromas)
+               val |= MT9M111_OUTFMT_SWAP_YCbCr_C_Y;
+
+       return mt9m111_setup_pixfmt(icd, val);
+}
+
+static int mt9m111_enable(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+       int ret;
+
+       if (icl->power) {
+               ret = icl->power(&mt9m111->client->dev, 1);
+               if (ret < 0) {
+                       dev_err(icd->vdev->parent,
+                               "Platform failed to power-on the camera.\n");
+                       return ret;
+               }
+       }
+
+       ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE);
+       if (!ret)
+               mt9m111->powered = 1;
+       return ret;
+}
+
+static int mt9m111_disable(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+       int ret;
+
+       ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
+       if (!ret)
+               mt9m111->powered = 0;
+
+       if (icl->power)
+               icl->power(&mt9m111->client->dev, 0);
+
+       return ret;
+}
+
+static int mt9m111_reset(struct soc_camera_device *icd)
+{
+       int ret;
+
+       ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+       if (!ret)
+               ret = reg_set(RESET, MT9M111_RESET_RESET_SOC);
+       if (!ret)
+               ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE
+                               | MT9M111_RESET_RESET_SOC);
+       return ret;
+}
+
+static int mt9m111_start_capture(struct soc_camera_device *icd)
+{
+       return 0;
+}
+
+static int mt9m111_stop_capture(struct soc_camera_device *icd)
+{
+       return 0;
+}
+
+static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
+{
+       return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
+               SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
+               SOCAM_DATAWIDTH_8;
+}
+
+static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
+{
+       return 0;
+}
+
+static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret;
+
+       switch (pixfmt) {
+       case V4L2_PIX_FMT_SBGGR8:
+               ret = mt9m111_setfmt_bayer8(icd);
+               break;
+       case V4L2_PIX_FMT_SBGGR16:
+               ret = mt9m111_setfmt_bayer10(icd);
+               break;
+       case V4L2_PIX_FMT_RGB555:
+               ret = mt9m111_setfmt_rgb555(icd);
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               ret = mt9m111_setfmt_rgb565(icd);
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               ret = mt9m111_setfmt_yuv(icd);
+               break;
+       default:
+               dev_err(&icd->dev, "Pixel format not handled : %x\n", pixfmt);
+               ret = -EINVAL;
+       }
+
+       if (!ret)
+               mt9m111->pixfmt = pixfmt;
+
+       return ret;
+}
+
+static int mt9m111_set_fmt_cap(struct soc_camera_device *icd,
+                              __u32 pixfmt, struct v4l2_rect *rect)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret;
+
+       mt9m111->left = rect->left;
+       mt9m111->top = rect->top;
+       mt9m111->width = rect->width;
+       mt9m111->height = rect->height;
+
+       dev_dbg(&icd->dev, "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n",
+               __func__, pixfmt, mt9m111->left, mt9m111->top, mt9m111->width,
+               mt9m111->height);
+
+       ret = mt9m111_setup_rect(icd);
+       if (!ret)
+               ret = mt9m111_set_pixfmt(icd, pixfmt);
+       return ret;
+}
+
+static int mt9m111_try_fmt_cap(struct soc_camera_device *icd,
+                              struct v4l2_format *f)
+{
+       if (f->fmt.pix.height > MT9M111_MAX_HEIGHT)
+               f->fmt.pix.height = MT9M111_MAX_HEIGHT;
+       if (f->fmt.pix.width > MT9M111_MAX_WIDTH)
+               f->fmt.pix.width = MT9M111_MAX_WIDTH;
+
+       return 0;
+}
+
+static int mt9m111_get_chip_id(struct soc_camera_device *icd,
+                              struct v4l2_chip_ident *id)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+       if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+
+       if (id->match_chip != mt9m111->client->addr)
+               return -ENODEV;
+
+       id->ident       = mt9m111->model;
+       id->revision    = 0;
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m111_get_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       int val;
+
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+               return -EINVAL;
+       if (reg->match_chip != mt9m111->client->addr)
+               return -ENODEV;
+
+       val = mt9m111_reg_read(icd, reg->reg);
+       reg->val = (u64)val;
+
+       if (reg->val > 0xffff)
+               return -EIO;
+
+       return 0;
+}
+
+static int mt9m111_set_register(struct soc_camera_device *icd,
+                               struct v4l2_register *reg)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+       if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+               return -EINVAL;
+
+       if (reg->match_chip != mt9m111->client->addr)
+               return -ENODEV;
+
+       if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+static const struct v4l2_queryctrl mt9m111_controls[] = {
+       {
+               .id             = V4L2_CID_VFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Verticaly",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {
+               .id             = V4L2_CID_HFLIP,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Flip Horizontaly",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 0,
+       }, {    /* gain = 1/32*val (=>gain=1 if val==32) */
+               .id             = V4L2_CID_GAIN,
+               .type           = V4L2_CTRL_TYPE_INTEGER,
+               .name           = "Gain",
+               .minimum        = 0,
+               .maximum        = 63 * 2 * 2,
+               .step           = 1,
+               .default_value  = 32,
+               .flags          = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Auto Exposure",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       }
+};
+
+static int mt9m111_video_probe(struct soc_camera_device *);
+static void mt9m111_video_remove(struct soc_camera_device *);
+static int mt9m111_get_control(struct soc_camera_device *,
+                              struct v4l2_control *);
+static int mt9m111_set_control(struct soc_camera_device *,
+                              struct v4l2_control *);
+static int mt9m111_resume(struct soc_camera_device *icd);
+static int mt9m111_init(struct soc_camera_device *icd);
+static int mt9m111_release(struct soc_camera_device *icd);
+
+static struct soc_camera_ops mt9m111_ops = {
+       .owner                  = THIS_MODULE,
+       .probe                  = mt9m111_video_probe,
+       .remove                 = mt9m111_video_remove,
+       .init                   = mt9m111_init,
+       .resume                 = mt9m111_resume,
+       .release                = mt9m111_release,
+       .start_capture          = mt9m111_start_capture,
+       .stop_capture           = mt9m111_stop_capture,
+       .set_fmt_cap            = mt9m111_set_fmt_cap,
+       .try_fmt_cap            = mt9m111_try_fmt_cap,
+       .query_bus_param        = mt9m111_query_bus_param,
+       .set_bus_param          = mt9m111_set_bus_param,
+       .controls               = mt9m111_controls,
+       .num_controls           = ARRAY_SIZE(mt9m111_controls),
+       .get_control            = mt9m111_get_control,
+       .set_control            = mt9m111_set_control,
+       .get_chip_id            = mt9m111_get_chip_id,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .get_register           = mt9m111_get_register,
+       .set_register           = mt9m111_set_register,
+#endif
+};
+
+static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret;
+
+       if (mt9m111->context == HIGHPOWER) {
+               if (flip)
+                       ret = reg_set(READ_MODE_B, mask);
+               else
+                       ret = reg_clear(READ_MODE_B, mask);
+       } else {
+               if (flip)
+                       ret = reg_set(READ_MODE_A, mask);
+               else
+                       ret = reg_clear(READ_MODE_A, mask);
+       }
+
+       return ret;
+}
+
+static int mt9m111_get_global_gain(struct soc_camera_device *icd)
+{
+       unsigned int data, gain;
+
+       data = reg_read(GLOBAL_GAIN);
+       if (data >= 0)
+               gain = ((data & (1 << 10)) * 2)
+                       | ((data & (1 << 9)) * 2)
+                       | (data & 0x2f);
+       else
+               gain = data;
+
+       return gain;
+}
+static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
+{
+       u16 val;
+
+       if (gain > 63 * 2 * 2)
+               return -EINVAL;
+
+       icd->gain = gain;
+       if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
+               val = (1 << 10) | (1 << 9) | (gain / 4);
+       else if ((gain >= 64) && (gain < 64 * 2))
+               val = (1 << 9) | (gain / 2);
+       else
+               val = gain;
+
+       return reg_write(GLOBAL_GAIN, val);
+}
+
+static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret;
+
+       if (on)
+               ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+       else
+               ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+
+       if (!ret)
+               mt9m111->autoexposure = on;
+
+       return ret;
+}
+static int mt9m111_get_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (mt9m111->context == HIGHPOWER)
+                       data = reg_read(READ_MODE_B);
+               else
+                       data = reg_read(READ_MODE_A);
+
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & MT9M111_RMB_MIRROR_ROWS);
+               break;
+       case V4L2_CID_HFLIP:
+               if (mt9m111->context == HIGHPOWER)
+                       data = reg_read(READ_MODE_B);
+               else
+                       data = reg_read(READ_MODE_A);
+
+               if (data < 0)
+                       return -EIO;
+               ctrl->value = !!(data & MT9M111_RMB_MIRROR_COLS);
+               break;
+       case V4L2_CID_GAIN:
+               data = mt9m111_get_global_gain(icd);
+               if (data < 0)
+                       return data;
+               ctrl->value = data;
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               ctrl->value = mt9m111->autoexposure;
+               break;
+       }
+       return 0;
+}
+
+static int mt9m111_set_control(struct soc_camera_device *icd,
+                              struct v4l2_control *ctrl)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       const struct v4l2_queryctrl *qctrl;
+       int ret;
+
+       qctrl = soc_camera_find_qctrl(&mt9m111_ops, ctrl->id);
+
+       if (!qctrl)
+               return -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               mt9m111->vflip = ctrl->value;
+               ret = mt9m111_set_flip(icd, ctrl->value,
+                                       MT9M111_RMB_MIRROR_ROWS);
+               break;
+       case V4L2_CID_HFLIP:
+               mt9m111->hflip = ctrl->value;
+               ret = mt9m111_set_flip(icd, ctrl->value,
+                                       MT9M111_RMB_MIRROR_COLS);
+               break;
+       case V4L2_CID_GAIN:
+               ret = mt9m111_set_global_gain(icd, ctrl->value);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               ret =  mt9m111_set_autoexposure(icd, ctrl->value);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int mt9m111_restore_state(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+       mt9m111_set_context(icd, mt9m111->context);
+       mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
+       mt9m111_setup_rect(icd);
+       mt9m111_set_flip(icd, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
+       mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
+       mt9m111_set_global_gain(icd, icd->gain);
+       mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
+       return 0;
+}
+
+static int mt9m111_resume(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret = 0;
+
+       if (mt9m111->powered) {
+               ret = mt9m111_enable(icd);
+               if (!ret)
+                       ret = mt9m111_reset(icd);
+               if (!ret)
+                       ret = mt9m111_restore_state(icd);
+       }
+       return ret;
+}
+
+static int mt9m111_init(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       int ret;
+
+       mt9m111->context = HIGHPOWER;
+       ret = mt9m111_enable(icd);
+       if (!ret)
+               ret = mt9m111_reset(icd);
+       if (!ret)
+               ret = mt9m111_set_context(icd, mt9m111->context);
+       if (!ret)
+               ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
+       if (ret)
+               dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret);
+       return ret;
+}
+
+static int mt9m111_release(struct soc_camera_device *icd)
+{
+       int ret;
+
+       ret = mt9m111_disable(icd);
+       if (ret < 0)
+               dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret);
+
+       return ret;
+}
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9m111_video_probe(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+       s32 data;
+       int ret;
+
+       /*
+        * We must have a parent by now. And it cannot be a wrong one.
+        * So this entire test is completely redundant.
+        */
+       if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       ret = mt9m111_enable(icd);
+       if (ret)
+               goto ei2c;
+       ret = mt9m111_reset(icd);
+       if (ret)
+               goto ei2c;
+
+       data = reg_read(CHIP_VERSION);
+
+       switch (data) {
+       case 0x143a:
+               mt9m111->model = V4L2_IDENT_MT9M111;
+               icd->formats = mt9m111_colour_formats;
+               icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats);
+               break;
+       default:
+               ret = -ENODEV;
+               dev_err(&icd->dev,
+                       "No MT9M111 chip detected, register read %x\n", data);
+               goto ei2c;
+       }
+
+       dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n");
+
+       ret = soc_camera_video_start(icd);
+       if (ret)
+               goto eisis;
+
+       mt9m111->autoexposure = 1;
+
+       mt9m111->swap_rgb_even_odd = 1;
+       mt9m111->swap_rgb_red_blue = 1;
+
+       return 0;
+eisis:
+ei2c:
+       return ret;
+}
+
+static void mt9m111_video_remove(struct soc_camera_device *icd)
+{
+       struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+
+       dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
+               mt9m111->icd.dev.parent, mt9m111->icd.vdev);
+       soc_camera_video_stop(&mt9m111->icd);
+}
+
+static int mt9m111_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
+{
+       struct mt9m111 *mt9m111;
+       struct soc_camera_device *icd;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_link *icl = client->dev.platform_data;
+       int ret;
+
+       if (!icl) {
+               dev_err(&client->dev, "MT9M111 driver needs platform data\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+               return -EIO;
+       }
+
+       mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL);
+       if (!mt9m111)
+               return -ENOMEM;
+
+       mt9m111->client = client;
+       i2c_set_clientdata(client, mt9m111);
+
+       /* Second stage probe - when a capture adapter is there */
+       icd             = &mt9m111->icd;
+       icd->ops        = &mt9m111_ops;
+       icd->control    = &client->dev;
+       icd->x_min      = MT9M111_MIN_DARK_COLS;
+       icd->y_min      = MT9M111_MIN_DARK_ROWS;
+       icd->x_current  = icd->x_min;
+       icd->y_current  = icd->y_min;
+       icd->width_min  = MT9M111_MIN_DARK_ROWS;
+       icd->width_max  = MT9M111_MAX_WIDTH;
+       icd->height_min = MT9M111_MIN_DARK_COLS;
+       icd->height_max = MT9M111_MAX_HEIGHT;
+       icd->y_skip_top = 0;
+       icd->iface      = icl->bus_id;
+
+       ret = soc_camera_device_register(icd);
+       if (ret)
+               goto eisdr;
+       return 0;
+
+eisdr:
+       kfree(mt9m111);
+       return ret;
+}
+
+static int mt9m111_remove(struct i2c_client *client)
+{
+       struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
+       soc_camera_device_unregister(&mt9m111->icd);
+       kfree(mt9m111);
+
+       return 0;
+}
+
+static const struct i2c_device_id mt9m111_id[] = {
+       { "mt9m111", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m111_id);
+
+static struct i2c_driver mt9m111_i2c_driver = {
+       .driver = {
+               .name = "mt9m111",
+       },
+       .probe          = mt9m111_probe,
+       .remove         = mt9m111_remove,
+       .id_table       = mt9m111_id,
+};
+
+static int __init mt9m111_mod_init(void)
+{
+       return i2c_add_driver(&mt9m111_i2c_driver);
+}
+
+static void __exit mt9m111_mod_exit(void)
+{
+       i2c_del_driver(&mt9m111_i2c_driver);
+}
+
+module_init(mt9m111_mod_init);
+module_exit(mt9m111_mod_exit);
+
+MODULE_DESCRIPTION("Micron MT9M111 Camera driver");
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
index 56808cd2f8a96ac1079db1dbb2d33782194feaf9..2584201059d8570efff3d72a59325e9a11a9d82a 100644 (file)
@@ -134,34 +134,56 @@ static int reg_clear(struct soc_camera_device *icd, const u8 reg,
 static int mt9v022_init(struct soc_camera_device *icd)
 {
        struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
        int ret;
 
+       if (icl->power) {
+               ret = icl->power(&mt9v022->client->dev, 1);
+               if (ret < 0) {
+                       dev_err(icd->vdev->parent,
+                               "Platform failed to power-on the camera.\n");
+                       return ret;
+               }
+       }
+
+       /*
+        * The camera could have been already on, we hard-reset it additionally,
+        * if available. Soft reset is done in video_probe().
+        */
+       if (icl->reset)
+               icl->reset(&mt9v022->client->dev);
+
        /* Almost the default mode: master, parallel, simultaneous, and an
         * undocumented bit 0x200, which is present in table 7, but not in 8,
         * plus snapshot mode to disable scan for now */
        mt9v022->chip_control |= 0x10;
        ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
-       if (ret >= 0)
-               reg_write(icd, MT9V022_READ_MODE, 0x300);
+       if (!ret)
+               ret = reg_write(icd, MT9V022_READ_MODE, 0x300);
 
        /* All defaults */
-       if (ret >= 0)
+       if (!ret)
                /* AEC, AGC on */
                ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
-       if (ret >= 0)
+       if (!ret)
                /* default - auto */
                ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
 
-       return ret >= 0 ? 0 : -EIO;
+       return ret;
 }
 
 static int mt9v022_release(struct soc_camera_device *icd)
 {
-       /* Nothing? */
+       struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+       struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+
+       if (icl->power)
+               icl->power(&mt9v022->client->dev, 0);
+
        return 0;
 }
 
@@ -352,21 +374,21 @@ static int mt9v022_set_fmt_cap(struct soc_camera_device *icd,
                                        rect->height + icd->y_skip_top + 43);
        }
        /* Setup frame format: defaults apart from width and height */
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_ROW_START, rect->top);
-       if (ret >= 0)
+       if (!ret)
                /* Default 94, Phytec driver says:
                 * "width + horizontal blank >= 660" */
                ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
                                rect->width > 660 - 43 ? 43 :
                                660 - rect->width);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
-       if (ret >= 0)
+       if (!ret)
                ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
                                rect->height + icd->y_skip_top);
 
@@ -717,7 +739,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
                        icd->num_formats = 1;
        }
 
-       if (ret >= 0)
+       if (!ret)
                ret = soc_camera_video_start(icd);
        if (ret < 0)
                goto eisis;
index 8ef578caba3b982c8d63f1047b4c300ac11b45ee..7f130284b5c730a0573bcc0c10c9cd925cb5dfec 100644 (file)
@@ -27,6 +27,7 @@
 #include <media/tuner.h>
 #include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
+#include <media/saa7115.h>
 
 #include "mxb.h"
 #include "tea6415c.h"
@@ -122,6 +123,8 @@ static struct saa7146_extension_ioctls ioctls[] = {
        { VIDIOC_S_FREQUENCY,   SAA7146_EXCLUSIVE },
        { VIDIOC_G_AUDIO,       SAA7146_EXCLUSIVE },
        { VIDIOC_S_AUDIO,       SAA7146_EXCLUSIVE },
+       { VIDIOC_DBG_G_REGISTER,        SAA7146_EXCLUSIVE },
+       { VIDIOC_DBG_S_REGISTER,        SAA7146_EXCLUSIVE },
        { MXB_S_AUDIO_CD,       SAA7146_EXCLUSIVE },    /* custom control */
        { MXB_S_AUDIO_LINE,     SAA7146_EXCLUSIVE },    /* custom control */
        { 0,                    0 }
@@ -134,12 +137,12 @@ struct mxb
 
        struct i2c_adapter      i2c_adapter;
 
-       struct i2c_client*      saa7111a;
-       struct i2c_client*      tda9840;
-       struct i2c_client*      tea6415c;
-       struct i2c_client*      tuner;
-       struct i2c_client*      tea6420_1;
-       struct i2c_client*      tea6420_2;
+       struct i2c_client       *saa7111a;
+       struct i2c_client       *tda9840;
+       struct i2c_client       *tea6415c;
+       struct i2c_client       *tuner;
+       struct i2c_client       *tea6420_1;
+       struct i2c_client       *tea6420_2;
 
        int     cur_mode;       /* current audio mode (mono, stereo, ...) */
        int     cur_input;      /* current input */
@@ -151,23 +154,23 @@ static struct saa7146_extension extension;
 
 static int mxb_check_clients(struct device *dev, void *data)
 {
-       struct mxbmxb = data;
+       struct mxb *mxb = data;
        struct i2c_client *client = i2c_verify_client(dev);
 
-       if( !client )
+       if (!client)
                return 0;
 
-       if( I2C_ADDR_TEA6420_1 == client->addr )
+       if (I2C_ADDR_TEA6420_1 == client->addr)
                mxb->tea6420_1 = client;
-       if( I2C_ADDR_TEA6420_2 == client->addr )
+       if (I2C_ADDR_TEA6420_2 == client->addr)
                mxb->tea6420_2 = client;
-       if( I2C_TEA6415C_2 == client->addr )
+       if (I2C_TEA6415C_2 == client->addr)
                mxb->tea6415c = client;
-       if( I2C_ADDR_TDA9840 == client->addr )
+       if (I2C_ADDR_TDA9840 == client->addr)
                mxb->tda9840 = client;
-       if( I2C_SAA7111 == client->addr )
+       if (I2C_SAA7111 == client->addr)
                mxb->saa7111a = client;
-       if( 0x60 == client->addr )
+       if (0x60 == client->addr)
                mxb->tuner = client;
 
        return 0;
@@ -178,23 +181,28 @@ static int mxb_probe(struct saa7146_dev* dev)
        struct mxb* mxb = NULL;
        int result;
 
-       if ((result = request_module("saa7111")) < 0) {
+       result = request_module("saa7115");
+       if (result < 0) {
                printk("mxb: saa7111 i2c module not available.\n");
                return -ENODEV;
        }
-       if ((result = request_module("tea6420")) < 0) {
+       result = request_module("tea6420");
+       if (result < 0) {
                printk("mxb: tea6420 i2c module not available.\n");
                return -ENODEV;
        }
-       if ((result = request_module("tea6415c")) < 0) {
+       result = request_module("tea6415c");
+       if (result < 0) {
                printk("mxb: tea6415c i2c module not available.\n");
                return -ENODEV;
        }
-       if ((result = request_module("tda9840")) < 0) {
+       result = request_module("tda9840");
+       if (result < 0) {
                printk("mxb: tda9840 i2c module not available.\n");
                return -ENODEV;
        }
-       if ((result = request_module("tuner")) < 0) {
+       result = request_module("tuner");
+       if (result < 0) {
                printk("mxb: tuner i2c module not available.\n");
                return -ENODEV;
        }
@@ -207,9 +215,10 @@ static int mxb_probe(struct saa7146_dev* dev)
 
        mxb->i2c_adapter = (struct i2c_adapter) {
                .class = I2C_CLASS_TV_ANALOG,
-               .name = "mxb",
        };
 
+       snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
+
        saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
        if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
                DEB_S(("cannot register i2c-device. skipping.\n"));
@@ -290,38 +299,7 @@ static struct {
        { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
        { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
        { 3, { 0x80, 0xb3, 0x0a } },
-       {-1, { 0} }
-};
-
-static const unsigned char mxb_saa7111_init[] = {
-       0x00, 0x00,       /* 00 - ID byte */
-       0x01, 0x00,       /* 01 - reserved */
-
-       /*front end */
-       0x02, 0xd8,       /* 02 - FUSE=x, GUDL=x, MODE=x */
-       0x03, 0x23,       /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
-       0x04, 0x00,       /* 04 - GAI1=256 */
-       0x05, 0x00,       /* 05 - GAI2=256 */
-
-       /* decoder */
-       0x06, 0xf0,       /* 06 - HSB at  xx(50Hz) /  xx(60Hz) pixels after end of last line */
-       0x07, 0x30,       /* 07 - HSS at  xx(50Hz) /  xx(60Hz) pixels after end of last line */
-       0x08, 0xa8,       /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */
-       0x09, 0x02,       /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */
-       0x0a, 0x80,       /* 0a - BRIG=128 */
-       0x0b, 0x47,       /* 0b - CONT=1.109 */
-       0x0c, 0x40,       /* 0c - SATN=1.0 */
-       0x0d, 0x00,       /* 0d - HUE=0 */
-       0x0e, 0x01,       /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
-       0x0f, 0x00,       /* 0f - reserved */
-       0x10, 0xd0,       /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */
-       0x11, 0x8c,       /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
-       0x12, 0x80,       /* 12 - xx output control 2 */
-       0x13, 0x30,       /* 13 - xx output control 3 */
-       0x14, 0x00,       /* 14 - reserved */
-       0x15, 0x15,       /* 15 - VBI */
-       0x16, 0x04,       /* 16 - VBI */
-       0x17, 0x00,       /* 17 - VBI */
+       {-1, { 0 } }
 };
 
 /* bring hardware to a sane state. this has to be done, just in case someone
@@ -331,37 +309,28 @@ static const unsigned char mxb_saa7111_init[] = {
 static int mxb_init_done(struct saa7146_dev* dev)
 {
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
-       struct video_decoder_init init;
        struct i2c_msg msg;
        struct tuner_setup tun_setup;
        v4l2_std_id std = V4L2_STD_PAL_BG;
+       struct v4l2_routing route;
 
        int i = 0, err = 0;
-       struct  tea6415c_multiplex vm;
+       struct tea6415c_multiplex vm;
 
        /* select video mode in saa7111a */
-       i = VIDEO_MODE_PAL;
-       /* fixme: currently pointless: gets overwritten by configuration below */
-       mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
-
-       /* write configuration to saa7111a */
-       init.data = mxb_saa7111_init;
-       init.len = sizeof(mxb_saa7111_init);
-       mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init);
+       mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std);
 
        /* select tuner-output on saa7111a */
        i = 0;
-       mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
-
-       /* enable vbi bypass */
-       i = 1;
-       mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i);
+       route.input = SAA7115_COMPOSITE0;
+       route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
+       mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
        /* select a tuner type */
        tun_setup.mode_mask = T_ANALOG_TV;
        tun_setup.addr = ADDR_UNSET;
        tun_setup.type = TUNER_PHILIPS_PAL;
-       mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE_ADDR, &tun_setup);
+       mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup);
        /* tune in some frequency on tuner */
        mxb->cur_freq.tuner = 0;
        mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
@@ -373,27 +342,26 @@ static int mxb_init_done(struct saa7146_dev* dev)
        mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
 
        /* mute audio on tea6420s */
-       mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
-       mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
-       mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
-       mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
+       mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]);
+       mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]);
+       mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]);
+       mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]);
 
        /* switch to tuner-channel on tea6415c*/
        vm.out = 17;
        vm.in  = 3;
-       mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
+       mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
 
        /* select tuner-output on multicable on tea6415c*/
        vm.in  = 3;
        vm.out = 13;
-       mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
+       mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
 
        /* the rest for mxb */
        mxb->cur_input = 0;
        mxb->cur_mute = 1;
 
        mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
-       mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
 
        /* check if the saa7740 (aka 'sound arena module') is present
           on the mxb. if so, we must initialize it. due to lack of
@@ -404,21 +372,22 @@ static int mxb_init_done(struct saa7146_dev* dev)
        msg.len = mxb_saa7740_init[0].length;
        msg.buf = &mxb_saa7740_init[0].data[0];
 
-       if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
+       err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
+       if (err == 1) {
                /* the sound arena module is a pos, that's probably the reason
                   philips refuses to hand out a datasheet for the saa7740...
                   it seems to screw up the i2c bus, so we disable fast irq
                   based i2c transactions here and rely on the slow and safe
                   polling method ... */
                extension.flags &= ~SAA7146_USE_I2C_IRQ;
-               for(i = 1;;i++) {
-                       if( -1 == mxb_saa7740_init[i].length ) {
+               for (i = 1; ; i++) {
+                       if (-1 == mxb_saa7740_init[i].length)
                                break;
-                       }
 
                        msg.len = mxb_saa7740_init[i].length;
                        msg.buf = &mxb_saa7740_init[i].data[0];
-                       if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
+                       err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
+                       if (err != 1) {
                                DEB_D(("failed to initialize 'sound arena module'.\n"));
                                goto err;
                        }
@@ -432,7 +401,8 @@ err:
        /* ext->saa has been filled by the core driver */
 
        /* some stuff is done via variables */
-       saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
+       saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
+                       input_port_selection[mxb->cur_input].hps_sync);
 
        /* some stuff is done via direct write to the registers */
 
@@ -457,24 +427,24 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
 static struct saa7146_ext_vv vv_data;
 
 /* this function only gets called when the probing was successful */
-static int mxb_attach(struct saa7146_devdev, struct saa7146_pci_extension_data *info)
+static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
 {
-       struct mxb* mxb = (struct mxb*)dev->ext_priv;
+       struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
-       DEB_EE(("dev:%p\n",dev));
+       DEB_EE(("dev:%p\n", dev));
 
        /* checking for i2c-devices can be omitted here, because we
           already did this in "mxb_vl42_probe" */
 
-       saa7146_vv_init(dev,&vv_data);
-       if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
+       saa7146_vv_init(dev, &vv_data);
+       if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
                ERR(("cannot register capture v4l2 device. skipping.\n"));
                return -1;
        }
 
        /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
-       if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
-               if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
+       if (MXB_BOARD_CAN_DO_VBI(dev)) {
+               if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
                        ERR(("cannot register vbi v4l2 device. skipping.\n"));
                }
        }
@@ -486,18 +456,18 @@ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data
        i2c_use_client(mxb->saa7111a);
        i2c_use_client(mxb->tuner);
 
-       printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
+       printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
 
        mxb_num++;
        mxb_init_done(dev);
        return 0;
 }
 
-static int mxb_detach(struct saa7146_devdev)
+static int mxb_detach(struct saa7146_dev *dev)
 {
-       struct mxb* mxb = (struct mxb*)dev->ext_priv;
+       struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
-       DEB_EE(("dev:%p\n",dev));
+       DEB_EE(("dev:%p\n", dev));
 
        i2c_release_client(mxb->tea6420_1);
        i2c_release_client(mxb->tea6420_2);
@@ -507,9 +477,8 @@ static int mxb_detach(struct saa7146_dev* dev)
        i2c_release_client(mxb->tuner);
 
        saa7146_unregister_device(&mxb->video_dev,dev);
-       if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
-               saa7146_unregister_device(&mxb->vbi_dev,dev);
-       }
+       if (MXB_BOARD_CAN_DO_VBI(dev))
+               saa7146_unregister_device(&mxb->vbi_dev, dev);
        saa7146_vv_release(dev);
 
        mxb_num--;
@@ -523,7 +492,7 @@ static int mxb_detach(struct saa7146_dev* dev)
 static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
 {
        struct saa7146_dev *dev = fh->dev;
-       struct mxb* mxb = (struct mxb*)dev->ext_priv;
+       struct mxb *mxb = (struct mxb *)dev->ext_priv;
        struct saa7146_vv *vv = dev->vv_data;
 
        switch(cmd) {
@@ -532,11 +501,9 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                struct v4l2_input *i = arg;
 
                DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
-               if( i->index < 0 || i->index >= MXB_INPUTS) {
+               if (i->index < 0 || i->index >= MXB_INPUTS)
                        return -EINVAL;
-               }
                memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
-
                return 0;
        }
        /* the saa7146 provides some controls (brightness, contrast, saturation)
@@ -550,7 +517,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
                        if (mxb_controls[i].id == qc->id) {
                                *qc = mxb_controls[i];
-                               DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
+                               DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
                                return 0;
                        }
                }
@@ -562,56 +529,51 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                int i;
 
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
-                       if (mxb_controls[i].id == vc->id) {
+                       if (mxb_controls[i].id == vc->id)
                                break;
-                       }
                }
 
-               if( i < 0 ) {
+               if (i < 0)
                        return -EAGAIN;
-               }
 
-               switch (vc->id ) {
-                       case V4L2_CID_AUDIO_MUTE: {
-                               vc->value = mxb->cur_mute;
-                               DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
-                               return 0;
-                       }
+               if (vc->id == V4L2_CID_AUDIO_MUTE) {
+                       vc->value = mxb->cur_mute;
+                       DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
+                       return 0;
                }
 
-               DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
+               DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
                return 0;
        }
 
        case VIDIOC_S_CTRL:
        {
-               struct  v4l2_control    *vc = arg;
+               struct v4l2_control *vc = arg;
                int i = 0;
 
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
-                       if (mxb_controls[i].id == vc->id) {
+                       if (mxb_controls[i].id == vc->id)
                                break;
-                       }
                }
 
-               if( i < 0 ) {
+               if (i < 0)
                        return -EAGAIN;
-               }
 
-               switch (vc->id ) {
-                       case V4L2_CID_AUDIO_MUTE: {
-                               mxb->cur_mute = vc->value;
-                               if( 0 == vc->value ) {
-                                       /* switch the audio-source */
-                                       mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
-                                       mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
-                               } else {
-                                       mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
-                                       mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
-                               }
-                               DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
-                               break;
+               if (vc->id == V4L2_CID_AUDIO_MUTE) {
+                       mxb->cur_mute = vc->value;
+                       if (!vc->value) {
+                               /* switch the audio-source */
+                               mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+                                               &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
+                               mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+                                               &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
+                       } else {
+                               mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+                                               &TEA6420_line[6][0]);
+                               mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+                                               &TEA6420_line[6][1]);
                        }
+                       DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
                }
                return 0;
        }
@@ -620,106 +582,84 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                int *input = (int *)arg;
                *input = mxb->cur_input;
 
-               DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
+               DEB_EE(("VIDIOC_G_INPUT %d.\n", *input));
                return 0;
        }
        case VIDIOC_S_INPUT:
        {
                int input = *(int *)arg;
-               struct  tea6415c_multiplex vm;
+               struct tea6415c_multiplex vm;
+               struct v4l2_routing route;
                int i = 0;
 
-               DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
+               DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
 
-               if (input < 0 || input >= MXB_INPUTS) {
+               if (input < 0 || input >= MXB_INPUTS)
                        return -EINVAL;
-               }
-
-               /* fixme: locke das setzen des inputs mit hilfe des mutexes
-               mutex_lock(&dev->lock);
-               video_mux(dev,*i);
-               mutex_unlock(&dev->lock);
-               */
-
-               /* fixme: check if streaming capture
-               if ( 0 != dev->streaming ) {
-                       DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
-                       return -EPERM;
-               }
-               */
 
                mxb->cur_input = input;
 
-               saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
+               saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
+                               input_port_selection[input].hps_sync);
 
                /* prepare switching of tea6415c and saa7111a;
                   have a look at the 'background'-file for further informations  */
-               switch( input ) {
-
-                       case TUNER:
-                       {
-                               i = 0;
-                               vm.in  = 3;
-                               vm.out = 17;
-
-                       if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
-                                       printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
-                                       return -EFAULT;
-                               }
-                               /* connect tuner-output always to multicable */
-                               vm.in  = 3;
-                               vm.out = 13;
-                               break;
-                       }
-                       case AUX3_YC:
-                       {
-                               /* nothing to be done here. aux3_yc is
-                                  directly connected to the saa711a */
-                               i = 5;
-                               break;
-                       }
-                       case AUX3:
-                       {
-                               /* nothing to be done here. aux3 is
-                                  directly connected to the saa711a */
-                               i = 1;
-                               break;
-                       }
-                       case AUX1:
-                       {
-                               i = 0;
-                               vm.in  = 1;
-                               vm.out = 17;
-                               break;
+               switch (input) {
+               case TUNER:
+                       i = SAA7115_COMPOSITE0;
+                       vm.in  = 3;
+                       vm.out = 17;
+
+                       if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
+                               printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
+                               return -EFAULT;
                        }
+                       /* connect tuner-output always to multicable */
+                       vm.in  = 3;
+                       vm.out = 13;
+                       break;
+               case AUX3_YC:
+                       /* nothing to be done here. aux3_yc is
+                          directly connected to the saa711a */
+                       i = SAA7115_SVIDEO1;
+                       break;
+               case AUX3:
+                       /* nothing to be done here. aux3 is
+                          directly connected to the saa711a */
+                       i = SAA7115_COMPOSITE1;
+                       break;
+               case AUX1:
+                       i = SAA7115_COMPOSITE0;
+                       vm.in  = 1;
+                       vm.out = 17;
+                       break;
                }
 
                /* switch video in tea6415c only if necessary */
-               switch( input ) {
-                       case TUNER:
-                       case AUX1:
-                       {
-                               if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
-                                       printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
-                                       return -EFAULT;
-                               }
-                               break;
-                       }
-                       default:
-                       {
-                               break;
+               switch (input) {
+               case TUNER:
+               case AUX1:
+                       if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
+                               printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
+                               return -EFAULT;
                        }
+                       break;
+               default:
+                       break;
                }
 
                /* switch video in saa7111a */
-               if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
+               route.input = i;
+               route.output = 0;
+               if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route))
                        printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
-               }
 
                /* switch the audio-source only if necessary */
                if( 0 == mxb->cur_mute ) {
-                       mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
-                       mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
+                       mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
+                                       &TEA6420_line[video_audio_connect[input]][0]);
+                       mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
+                                      &TEA6420_line[video_audio_connect[input]][1]);
                }
 
                return 0;
@@ -727,114 +667,44 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        case VIDIOC_G_TUNER:
        {
                struct v4l2_tuner *t = arg;
-               int byte = 0;
 
-               if( 0 != t->index ) {
+               if (t->index) {
                        DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
                        return -EINVAL;
                }
 
                DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
 
-               memset(t,0,sizeof(*t));
-               strcpy(t->name, "Television");
+               memset(t, 0, sizeof(*t));
+               i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
 
+               strlcpy(t->name, "TV Tuner", sizeof(t->name));
                t->type = V4L2_TUNER_ANALOG_TV;
-               t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-               t->rangelow = 772;      /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
-               t->rangehigh = 13684;   /* 855.25 MHz / 62.5 kHz = 13684 */
-               /* FIXME: add the real signal strength here */
-               t->signal = 0xffff;
-               t->afc = 0;
-
-               mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, &byte);
+               t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | \
+                       V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
                t->audmode = mxb->cur_mode;
-
-               if( byte < 0 ) {
-                       t->rxsubchans  = V4L2_TUNER_SUB_MONO;
-               } else {
-                       switch(byte) {
-                               case TDA9840_MONO_DETECT: {
-                                       t->rxsubchans   = V4L2_TUNER_SUB_MONO;
-                                       DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
-                                       break;
-                               }
-                               case TDA9840_DUAL_DETECT: {
-                                       t->rxsubchans   = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-                                       DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
-                                       break;
-                               }
-                               case TDA9840_STEREO_DETECT: {
-                                       t->rxsubchans   = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
-                                       DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
-                                       break;
-                               }
-                               default: { /* TDA9840_INCORRECT_DETECT */
-                                       t->rxsubchans   = V4L2_TUNER_MODE_MONO;
-                                       DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
-                                       break;
-                               }
-                       }
-               }
-
                return 0;
        }
        case VIDIOC_S_TUNER:
        {
                struct v4l2_tuner *t = arg;
-               int result = 0;
-               int byte = 0;
 
-               if( 0 != t->index ) {
+               if (t->index) {
                        DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
                        return -EINVAL;
                }
 
-               switch(t->audmode) {
-                       case V4L2_TUNER_MODE_STEREO: {
-                               mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
-                               byte = TDA9840_SET_STEREO;
-                               DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
-                               break;
-                       }
-                       case V4L2_TUNER_MODE_LANG1_LANG2: {
-                               mxb->cur_mode = V4L2_TUNER_MODE_LANG1_LANG2;
-                               byte = TDA9840_SET_BOTH;
-                               DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1_LANG2\n"));
-                               break;
-                       }
-                       case V4L2_TUNER_MODE_LANG1: {
-                               mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
-                               byte = TDA9840_SET_LANG1;
-                               DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
-                               break;
-                       }
-                       case V4L2_TUNER_MODE_LANG2: {
-                               mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
-                               byte = TDA9840_SET_LANG2;
-                               DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
-                               break;
-                       }
-                       default: { /* case V4L2_TUNER_MODE_MONO: {*/
-                               mxb->cur_mode = V4L2_TUNER_MODE_MONO;
-                               byte = TDA9840_SET_MONO;
-                               DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
-                               break;
-                       }
-               }
-
-               if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
-                       printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
-               }
-
+               mxb->cur_mode = t->audmode;
+               i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
                return 0;
        }
        case VIDIOC_G_FREQUENCY:
        {
                struct v4l2_frequency *f = arg;
 
-               if(0 != mxb->cur_input) {
-                       DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
+               if (mxb->cur_input) {
+                       DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
+                                               mxb->cur_input));
                        return -EINVAL;
                }
 
@@ -847,14 +717,14 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        {
                struct v4l2_frequency *f = arg;
 
-               if (0 != f->tuner)
+               if (f->tuner)
                        return -EINVAL;
 
                if (V4L2_TUNER_ANALOG_TV != f->type)
                        return -EINVAL;
 
-               if(0 != mxb->cur_input) {
-                       DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
+               if (mxb->cur_input) {
+                       DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
                        return -EINVAL;
                }
 
@@ -875,7 +745,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        {
                int i = *(int*)arg;
 
-               if( i < 0 || i >= MXB_AUDIOS ) {
+               if (i < 0 || i >= MXB_AUDIOS) {
                        DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
                        return -EINVAL;
                }
@@ -891,7 +761,7 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        {
                int i = *(int*)arg;
 
-               if( i < 0 || i >= MXB_AUDIOS ) {
+               if (i < 0 || i >= MXB_AUDIOS) {
                        DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
                        return -EINVAL;
                }
@@ -906,12 +776,12 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        {
                struct v4l2_audio *a = arg;
 
-               if( a->index < 0 || a->index > MXB_INPUTS ) {
-                       DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
+               if (a->index < 0 || a->index > MXB_INPUTS) {
+                       DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
                        return -EINVAL;
                }
 
-               DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
+               DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
                memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
 
                return 0;
@@ -919,9 +789,16 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
        case VIDIOC_S_AUDIO:
        {
                struct v4l2_audio *a = arg;
-               DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
+
+               DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
                return 0;
        }
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       case VIDIOC_DBG_S_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+               i2c_clients_command(&mxb->i2c_adapter, cmd, arg);
+               return 0;
+#endif
        default:
 /*
                DEB2(printk("does not handle this ioctl.\n"));
@@ -944,7 +821,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa
                /* set the 7146 gpio register -- I don't know what this does exactly */
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
                /* unset the 7111 gpio register -- I don't know what this does exactly */
-               mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero);
+               mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero);
                mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
        } else {
                v4l2_std_id std = V4L2_STD_PAL_BG;
@@ -953,7 +830,7 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa
                /* set the 7146 gpio register -- I don't know what this does exactly */
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
                /* set the 7111 gpio register -- I don't know what this does exactly */
-               mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one);
+               mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one);
                mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
        }
        return 0;
@@ -1029,7 +906,7 @@ static struct saa7146_extension extension = {
 
 static int __init mxb_init_module(void)
 {
-       if( 0 != saa7146_register_extension(&extension)) {
+       if (saa7146_register_extension(&extension)) {
                DEB_S(("failed to register extension.\n"));
                return -ENODEV;
        }
index c6852402c5e986d3b93161b636db049789f5b6a4..935d73de57bd3c8cf78ade18ff9245c2ab4c4799 100644 (file)
@@ -974,14 +974,14 @@ dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
 
        for (i = reg1; i <= regn; i++) {
                rc = i2c_r(ov, i);
-               info("Sensor[0x%02X] = 0x%02X", i, rc);
+               dev_info(&ov->dev->dev, "Sensor[0x%02X] = 0x%02X\n", i, rc);
        }
 }
 
 static void
 dump_i2c_regs(struct usb_ov511 *ov)
 {
-       info("I2C REGS");
+       dev_info(&ov->dev->dev, "I2C REGS\n");
        dump_i2c_range(ov, 0x00, 0x7C);
 }
 
@@ -992,28 +992,28 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
 
        for (i = reg1; i <= regn; i++) {
                rc = reg_r(ov, i);
-               info("OV511[0x%02X] = 0x%02X", i, rc);
+               dev_info(&ov->dev->dev, "OV511[0x%02X] = 0x%02X\n", i, rc);
        }
 }
 
 static void
 ov511_dump_regs(struct usb_ov511 *ov)
 {
-       info("CAMERA INTERFACE REGS");
+       dev_info(&ov->dev->dev, "CAMERA INTERFACE REGS\n");
        dump_reg_range(ov, 0x10, 0x1f);
-       info("DRAM INTERFACE REGS");
+       dev_info(&ov->dev->dev, "DRAM INTERFACE REGS\n");
        dump_reg_range(ov, 0x20, 0x23);
-       info("ISO FIFO REGS");
+       dev_info(&ov->dev->dev, "ISO FIFO REGS\n");
        dump_reg_range(ov, 0x30, 0x31);
-       info("PIO REGS");
+       dev_info(&ov->dev->dev, "PIO REGS\n");
        dump_reg_range(ov, 0x38, 0x39);
        dump_reg_range(ov, 0x3e, 0x3e);
-       info("I2C REGS");
+       dev_info(&ov->dev->dev, "I2C REGS\n");
        dump_reg_range(ov, 0x40, 0x49);
-       info("SYSTEM CONTROL REGS");
+       dev_info(&ov->dev->dev, "SYSTEM CONTROL REGS\n");
        dump_reg_range(ov, 0x50, 0x55);
        dump_reg_range(ov, 0x5e, 0x5f);
-       info("OmniCE REGS");
+       dev_info(&ov->dev->dev, "OmniCE REGS\n");
        dump_reg_range(ov, 0x70, 0x79);
        /* NOTE: Quantization tables are not readable. You will get the value
         * in reg. 0x79 for every table register */
@@ -1025,25 +1025,25 @@ ov511_dump_regs(struct usb_ov511 *ov)
 static void
 ov518_dump_regs(struct usb_ov511 *ov)
 {
-       info("VIDEO MODE REGS");
+       dev_info(&ov->dev->dev, "VIDEO MODE REGS\n");
        dump_reg_range(ov, 0x20, 0x2f);
-       info("DATA PUMP AND SNAPSHOT REGS");
+       dev_info(&ov->dev->dev, "DATA PUMP AND SNAPSHOT REGS\n");
        dump_reg_range(ov, 0x30, 0x3f);
-       info("I2C REGS");
+       dev_info(&ov->dev->dev, "I2C REGS\n");
        dump_reg_range(ov, 0x40, 0x4f);
-       info("SYSTEM CONTROL AND VENDOR REGS");
+       dev_info(&ov->dev->dev, "SYSTEM CONTROL AND VENDOR REGS\n");
        dump_reg_range(ov, 0x50, 0x5f);
-       info("60 - 6F");
+       dev_info(&ov->dev->dev, "60 - 6F\n");
        dump_reg_range(ov, 0x60, 0x6f);
-       info("70 - 7F");
+       dev_info(&ov->dev->dev, "70 - 7F\n");
        dump_reg_range(ov, 0x70, 0x7f);
-       info("Y QUANTIZATION TABLE");
+       dev_info(&ov->dev->dev, "Y QUANTIZATION TABLE\n");
        dump_reg_range(ov, 0x80, 0x8f);
-       info("UV QUANTIZATION TABLE");
+       dev_info(&ov->dev->dev, "UV QUANTIZATION TABLE\n");
        dump_reg_range(ov, 0x90, 0x9f);
-       info("A0 - BF");
+       dev_info(&ov->dev->dev, "A0 - BF\n");
        dump_reg_range(ov, 0xa0, 0xbf);
-       info("CBR");
+       dev_info(&ov->dev->dev, "CBR\n");
        dump_reg_range(ov, 0xc0, 0xcf);
 }
 #endif
@@ -3205,9 +3205,10 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
         */
 
        if (printph) {
-               info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
-                    pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
-                    in[7], in[8], in[9], in[10], in[11]);
+               dev_info(&ov->dev->dev,
+                        "ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n",
+                        pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
+                        in[7], in[8], in[9], in[10], in[11]);
        }
 
        /* Check for SOF/EOF packet */
@@ -3366,8 +3367,10 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
         * the definitive SOF/EOF format */
        if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
                if (printph) {
-                       info("ph: %2x %2x %2x %2x %2x %2x %2x %2x", in[0],
-                            in[1], in[2], in[3], in[4], in[5], in[6], in[7]);
+                       dev_info(&ov->dev->dev,
+                                "ph: %2x %2x %2x %2x %2x %2x %2x %2x\n",
+                                in[0], in[1], in[2], in[3], in[4], in[5],
+                                in[6], in[7]);
                }
 
                if (frame->scanstate == STATE_LINES) {
@@ -3646,14 +3649,16 @@ ov51x_init_isoc(struct usb_ov511 *ov)
                if (packetsize == -1) {
                        ov518_set_packet_size(ov, 640);
                } else {
-                       info("Forcing packet size to %d", packetsize);
+                       dev_info(&ov->dev->dev, "Forcing packet size to %d\n",
+                                packetsize);
                        ov518_set_packet_size(ov, packetsize);
                }
        } else {
                if (packetsize == -1) {
                        ov511_set_packet_size(ov, size);
                } else {
-                       info("Forcing packet size to %d", packetsize);
+                       dev_info(&ov->dev->dev, "Forcing packet size to %d\n",
+                                packetsize);
                        ov511_set_packet_size(ov, packetsize);
                }
        }
@@ -4121,7 +4126,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
                        return -EIO;
 
                if (force_palette && p->palette != force_palette) {
-                       info("Palette rejected (%s)",
+                       dev_info(&ov->dev->dev, "Palette rejected (%s)\n",
                             symbolic(v4l1_plist, p->palette));
                        return -EINVAL;
                }
@@ -4849,26 +4854,27 @@ ov7xx0_configure(struct usb_ov511 *ov)
                err("Error detecting sensor type");
                return -1;
        } else if ((rc & 3) == 3) {
-               info("Sensor is an OV7610");
+               dev_info(&ov->dev->dev, "Sensor is an OV7610\n");
                ov->sensor = SEN_OV7610;
        } else if ((rc & 3) == 1) {
                /* I don't know what's different about the 76BE yet. */
                if (i2c_r(ov, 0x15) & 1)
-                       info("Sensor is an OV7620AE");
+                       dev_info(&ov->dev->dev, "Sensor is an OV7620AE\n");
                else
-                       info("Sensor is an OV76BE");
+                       dev_info(&ov->dev->dev, "Sensor is an OV76BE\n");
 
                /* OV511+ will return all zero isoc data unless we
                 * configure the sensor as a 7620. Someone needs to
                 * find the exact reg. setting that causes this. */
                if (ov->bridge == BRG_OV511PLUS) {
-                       info("Enabling 511+/7620AE workaround");
+                       dev_info(&ov->dev->dev,
+                                "Enabling 511+/7620AE workaround\n");
                        ov->sensor = SEN_OV7620;
                } else {
                        ov->sensor = SEN_OV76BE;
                }
        } else if ((rc & 3) == 0) {
-               info("Sensor is an OV7620");
+               dev_info(&ov->dev->dev, "Sensor is an OV7620\n");
                ov->sensor = SEN_OV7620;
        } else {
                err("Unknown image sensor version: %d", rc & 3);
@@ -5024,16 +5030,16 @@ ov6xx0_configure(struct usb_ov511 *ov)
 
        if ((rc & 3) == 0) {
                ov->sensor = SEN_OV6630;
-               info("Sensor is an OV6630");
+               dev_info(&ov->dev->dev, "Sensor is an OV6630\n");
        } else if ((rc & 3) == 1) {
                ov->sensor = SEN_OV6620;
-               info("Sensor is an OV6620");
+               dev_info(&ov->dev->dev, "Sensor is an OV6620\n");
        } else if ((rc & 3) == 2) {
                ov->sensor = SEN_OV6630;
-               info("Sensor is an OV6630AE");
+               dev_info(&ov->dev->dev, "Sensor is an OV6630AE\n");
        } else if ((rc & 3) == 3) {
                ov->sensor = SEN_OV6630;
-               info("Sensor is an OV6630AF");
+               dev_info(&ov->dev->dev, "Sensor is an OV6630AF\n");
        }
 
        /* Set sensor-specific vars */
@@ -5088,10 +5094,10 @@ ks0127_configure(struct usb_ov511 *ov)
                        err("Error detecting sensor type");
                        return -1;
                } else if ((rc & 0x0f) == 0) {
-                       info("Sensor is a KS0127");
+                       dev_info(&ov->dev->dev, "Sensor is a KS0127\n");
                        ov->sensor = SEN_KS0127;
                } else if ((rc & 0x0f) == 9) {
-                       info("Sensor is a KS0127B Rev. A");
+                       dev_info(&ov->dev->dev, "Sensor is a KS0127B Rev. A\n");
                        ov->sensor = SEN_KS0127B;
                }
        } else {
@@ -5200,7 +5206,8 @@ saa7111a_configure(struct usb_ov511 *ov)
                err("Error detecting sensor version");
                return -1;
        } else {
-               info("Sensor is an SAA7111A (version 0x%x)", rc);
+               dev_info(&ov->dev->dev,
+                        "Sensor is an SAA7111A (version 0x%x)\n", rc);
                ov->sensor = SEN_SAA7111A;
        }
 
@@ -5262,7 +5269,7 @@ ov511_configure(struct usb_ov511 *ov)
 
        PDEBUG (1, "CustomID = %d", ov->customid);
        ov->desc = symbolic(camlist, ov->customid);
-       info("model: %s", ov->desc);
+       dev_info(&ov->dev->dev, "model: %s\n", ov->desc);
 
        if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
                err("Camera type (%d) not recognized", ov->customid);
@@ -5426,7 +5433,8 @@ ov518_configure(struct usb_ov511 *ov)
        PDEBUG(4, "");
 
        /* First 5 bits of custom ID reg are a revision ID on OV518 */
-       info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
+       dev_info(&ov->dev->dev, "Device revision %d\n",
+                0x1F & reg_r(ov, R511_SYS_CUST_ID));
 
        /* Give it the default description */
        ov->desc = symbolic(camlist, 0);
@@ -5773,7 +5781,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
        }
 
-       info("USB %s video device found", symbolic(brglist, ov->bridge));
+       dev_info(&intf->dev, "USB %s video device found\n",
+                symbolic(brglist, ov->bridge));
 
        init_waitqueue_head(&ov->wq);
 
@@ -5854,8 +5863,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
                goto error;
        }
 
-       info("Device at %s registered to minor %d", ov->usb_path,
-            ov->vdev->minor);
+       dev_info(&intf->dev, "Device at %s registered to minor %d\n",
+                ov->usb_path, ov->vdev->minor);
 
        usb_set_intfdata(intf, ov);
        if (ov_create_sysfs(ov->vdev)) {
@@ -5958,7 +5967,8 @@ usb_ov511_init(void)
        if (retval)
                goto out;
 
-       info(DRIVER_VERSION " : " DRIVER_DESC);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
 
 out:
        return retval;
@@ -5968,8 +5978,7 @@ static void __exit
 usb_ov511_exit(void)
 {
        usb_deregister(&ov511_driver);
-       info("driver deregistered");
-
+       printk(KERN_INFO KBUILD_MODNAME ": driver deregistered\n");
 }
 
 module_init(usb_ov511_init);
index baded1262ca9f68b675ca72d3ad18d045d8f2f41..70d99e52329d53ff457d9d335982808e92171d8f 100644 (file)
@@ -12,7 +12,8 @@
 
 #ifdef OV511_DEBUG
        #define PDEBUG(level, fmt, args...) \
-               if (debug >= (level)) info("[%s:%d] " fmt, \
+               if (debug >= (level))   \
+                       printk(KERN_INFO KBUILD_MODNAME "[%s:%d] \n" fmt, \
                __func__, __LINE__ , ## args)
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
index 065c2454113e717ddb2cb6fd276b5e16e3382c0f..2c4acbf5a4feae2f5f425c8d9f8b925ec4cdcbd9 100644 (file)
@@ -49,12 +49,6 @@ MODULE_LICENSE("GPL");
 #define GENERIC_REG_ID_LOW        0x1D /* manufacturer ID LSB */
 #define GENERIC_REG_COM_I         0x29 /* misc ID bits */
 
-extern struct ovcamchip_ops ov6x20_ops;
-extern struct ovcamchip_ops ov6x30_ops;
-extern struct ovcamchip_ops ov7x10_ops;
-extern struct ovcamchip_ops ov7x20_ops;
-extern struct ovcamchip_ops ov76be_ops;
-
 static char *chip_names[NUM_CC_TYPES] = {
        [CC_UNKNOWN]    = "Unknown chip",
        [CC_OV76BE]     = "OV76BE",
index 9afa4fe47726011f4e78edb87fd97095d3410c35..a05650faedda435363e6bfeb5339b51fe896541e 100644 (file)
@@ -53,6 +53,12 @@ struct ovcamchip {
        int initialized;           /* OVCAMCHIP_CMD_INITIALIZE was successful */
 };
 
+extern struct ovcamchip_ops ov6x20_ops;
+extern struct ovcamchip_ops ov6x30_ops;
+extern struct ovcamchip_ops ov7x10_ops;
+extern struct ovcamchip_ops ov7x20_ops;
+extern struct ovcamchip_ops ov76be_ops;
+
 /* --------------------------------- */
 /*              I2C I/O              */
 /* --------------------------------- */
index 7c84f795db54bcb188d39b541cb0f1f673246c8c..994807818aa26eacd2ffc09920445d2cc69f58d9 100644 (file)
@@ -47,6 +47,7 @@ struct pms_device
        struct video_picture picture;
        int height;
        int width;
+       unsigned long in_use;
        struct mutex lock;
 };
 
@@ -881,10 +882,27 @@ static ssize_t pms_read(struct file *file, char __user *buf,
        return len;
 }
 
+static int pms_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct video_device *v = video_devdata(file);
+       struct pms_device *pd = (struct pms_device *)v;
+
+       return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0;
+}
+
+static int pms_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct video_device *v = video_devdata(file);
+       struct pms_device *pd = (struct pms_device *)v;
+
+       clear_bit(0, &pd->in_use);
+       return 0;
+}
+
 static const struct file_operations pms_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = pms_exclusive_open,
+       .release        = pms_exclusive_release,
        .ioctl          = pms_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -897,6 +915,7 @@ static struct video_device pms_template=
 {
        .name           = "Mediavision PMS",
        .fops           = &pms_fops,
+       .release        = video_device_release_empty,
 };
 
 static struct pms_device pms_device;
index 0764fbfffb73b036c0687b34c94afd1a9d3b58a3..203f54cd18a16ac164e151166743b3a45327a95a 100644 (file)
@@ -134,13 +134,17 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
 
 
 /* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
 {
        int ret = 0;
        if (!cptr) return 0;
        LOCK_TAKE(cptr->hdw->big_lock); do {
                if (cptr->info->type == pvr2_ctl_int) {
-                       ret = cptr->info->default_value;
+                       if (cptr->info->get_def_value) {
+                               ret = cptr->info->get_def_value(cptr, valptr);
+                       } else {
+                               *valptr = cptr->info->default_value;
+                       }
                }
        } while(0); LOCK_GIVE(cptr->hdw->big_lock);
        return ret;
index 0371ae6e6e4eb61b1e42e8799f92598d5a86e1ff..794ff90121c7d367ee221507f72a12d4ea8aca58 100644 (file)
@@ -49,7 +49,7 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl *);
 int pvr2_ctrl_get_min(struct pvr2_ctrl *);
 
 /* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *);
+int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr);
 
 /* Retrieve control's enumeration count (enum only) */
 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
index 657f861593b352516c324fa7da471462c7250a67..de7ee7264be63bc8855380942b1e14ae222ca7d6 100644 (file)
@@ -82,6 +82,7 @@ struct pvr2_ctl_info {
 
        /* Control's implementation */
        pvr2_ctlf_get_value get_value;      /* Get its value */
+       pvr2_ctlf_get_value get_def_value;  /* Get its default value */
        pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
        pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
        pvr2_ctlf_set_value set_value;      /* Set its value */
@@ -307,6 +308,10 @@ struct pvr2_hdw {
        struct v4l2_tuner tuner_signal_info;
        int tuner_signal_stale;
 
+       /* Cropping capability info */
+       struct v4l2_cropcap cropcap_info;
+       int cropcap_stale;
+
        /* Video standard handling */
        v4l2_std_id std_mask_eeprom; // Hardware supported selections
        v4l2_std_id std_mask_avail;  // Which standards we may select from
@@ -367,6 +372,10 @@ struct pvr2_hdw {
        VCREATE_DATA(bass);
        VCREATE_DATA(treble);
        VCREATE_DATA(mute);
+       VCREATE_DATA(cropl);
+       VCREATE_DATA(cropt);
+       VCREATE_DATA(cropw);
+       VCREATE_DATA(croph);
        VCREATE_DATA(input);
        VCREATE_DATA(audiomode);
        VCREATE_DATA(res_hor);
index f051c6aa7f1f223cd36744df1b6cc2af4b26d82a..94265bd3d926c1b2a8960ae743a05f962aec75c2 100644 (file)
@@ -298,6 +298,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
                                unsigned int timeout,int probe_fl,
                                void *write_data,unsigned int write_len,
                                void *read_data,unsigned int read_len);
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw);
 
 
 static void trace_stbit(const char *name,int val)
@@ -402,6 +403,194 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
        return 0;
 }
 
+static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *left = cap->bounds.left;
+       return 0;
+}
+
+static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *left = cap->bounds.left;
+       if (cap->bounds.width > cptr->hdw->cropw_val) {
+               *left += cap->bounds.width - cptr->hdw->cropw_val;
+       }
+       return 0;
+}
+
+static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *top = cap->bounds.top;
+       return 0;
+}
+
+static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *top = cap->bounds.top;
+       if (cap->bounds.height > cptr->hdw->croph_val) {
+               *top += cap->bounds.height - cptr->hdw->croph_val;
+       }
+       return 0;
+}
+
+static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = 0;
+       if (cap->bounds.width > cptr->hdw->cropl_val) {
+               *val = cap->bounds.width - cptr->hdw->cropl_val;
+       }
+       return 0;
+}
+
+static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = 0;
+       if (cap->bounds.height > cptr->hdw->cropt_val) {
+               *val = cap->bounds.height - cptr->hdw->cropt_val;
+       }
+       return 0;
+}
+
+static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.left;
+       return 0;
+}
+
+static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.top;
+       return 0;
+}
+
+static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.width;
+       return 0;
+}
+
+static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.height;
+       return 0;
+}
+
+static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.left;
+       return 0;
+}
+
+static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.top;
+       return 0;
+}
+
+static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.width;
+       return 0;
+}
+
+static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.height;
+       return 0;
+}
+
+static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->pixelaspect.numerator;
+       return 0;
+}
+
+static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->pixelaspect.denominator;
+       return 0;
+}
+
 static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
 {
        /* Actual maximum depends on the video standard in effect. */
@@ -779,6 +968,10 @@ VCREATE_FUNCS(balance)
 VCREATE_FUNCS(bass)
 VCREATE_FUNCS(treble)
 VCREATE_FUNCS(mute)
+VCREATE_FUNCS(cropl)
+VCREATE_FUNCS(cropt)
+VCREATE_FUNCS(cropw)
+VCREATE_FUNCS(croph)
 VCREATE_FUNCS(audiomode)
 VCREATE_FUNCS(res_hor)
 VCREATE_FUNCS(res_ver)
@@ -849,6 +1042,72 @@ static const struct pvr2_ctl_info control_defs[] = {
                .default_value = 0,
                DEFREF(mute),
                DEFBOOL,
+       }, {
+               .desc = "Capture crop left margin",
+               .name = "crop_left",
+               .internal_id = PVR2_CID_CROPL,
+               .default_value = 0,
+               DEFREF(cropl),
+               DEFINT(-129, 340),
+               .get_min_value = ctrl_cropl_min_get,
+               .get_max_value = ctrl_cropl_max_get,
+               .get_def_value = ctrl_get_cropcapdl,
+       }, {
+               .desc = "Capture crop top margin",
+               .name = "crop_top",
+               .internal_id = PVR2_CID_CROPT,
+               .default_value = 0,
+               DEFREF(cropt),
+               DEFINT(-35, 544),
+               .get_min_value = ctrl_cropt_min_get,
+               .get_max_value = ctrl_cropt_max_get,
+               .get_def_value = ctrl_get_cropcapdt,
+       }, {
+               .desc = "Capture crop width",
+               .name = "crop_width",
+               .internal_id = PVR2_CID_CROPW,
+               .default_value = 720,
+               DEFREF(cropw),
+               .get_max_value = ctrl_cropw_max_get,
+               .get_def_value = ctrl_get_cropcapdw,
+       }, {
+               .desc = "Capture crop height",
+               .name = "crop_height",
+               .internal_id = PVR2_CID_CROPH,
+               .default_value = 480,
+               DEFREF(croph),
+               .get_max_value = ctrl_croph_max_get,
+               .get_def_value = ctrl_get_cropcapdh,
+       }, {
+               .desc = "Capture capability pixel aspect numerator",
+               .name = "cropcap_pixel_numerator",
+               .internal_id = PVR2_CID_CROPCAPPAN,
+               .get_value = ctrl_get_cropcappan,
+       }, {
+               .desc = "Capture capability pixel aspect denominator",
+               .name = "cropcap_pixel_denominator",
+               .internal_id = PVR2_CID_CROPCAPPAD,
+               .get_value = ctrl_get_cropcappad,
+       }, {
+               .desc = "Capture capability bounds top",
+               .name = "cropcap_bounds_top",
+               .internal_id = PVR2_CID_CROPCAPBT,
+               .get_value = ctrl_get_cropcapbt,
+       }, {
+               .desc = "Capture capability bounds left",
+               .name = "cropcap_bounds_left",
+               .internal_id = PVR2_CID_CROPCAPBL,
+               .get_value = ctrl_get_cropcapbl,
+       }, {
+               .desc = "Capture capability bounds width",
+               .name = "cropcap_bounds_width",
+               .internal_id = PVR2_CID_CROPCAPBW,
+               .get_value = ctrl_get_cropcapbw,
+       }, {
+               .desc = "Capture capability bounds height",
+               .name = "cropcap_bounds_height",
+               .internal_id = PVR2_CID_CROPCAPBH,
+               .get_value = ctrl_get_cropcapbh,
        },{
                .desc = "Video Source",
                .name = "input",
@@ -1313,9 +1572,19 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
                if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
                memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
                /* Usbsnoop log shows that we must swap bytes... */
+               /* Some background info: The data being swapped here is a
+                  firmware image destined for the mpeg encoder chip that
+                  lives at the other end of a USB endpoint.  The encoder
+                  chip always talks in 32 bit chunks and its storage is
+                  organized into 32 bit words.  However from the file
+                  system to the encoder chip everything is purely a byte
+                  stream.  The firmware file's contents are always 32 bit
+                  swapped from what the encoder expects.  Thus the need
+                  always exists to swap the bytes regardless of the endian
+                  type of the host processor and therefore swab32() makes
+                  the most sense. */
                for (icnt = 0; icnt < bcnt/4 ; icnt++)
-                       ((u32 *)fw_ptr)[icnt] =
-                               ___swab32(((u32 *)fw_ptr)[icnt]);
+                       ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
 
                ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
                                    &actual_length, HZ);
@@ -1905,7 +2174,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                                 const struct usb_device_id *devid)
 {
        unsigned int idx,cnt1,cnt2,m;
-       struct pvr2_hdw *hdw;
+       struct pvr2_hdw *hdw = NULL;
        int valid_std_mask;
        struct pvr2_ctrl *cptr;
        const struct pvr2_device_desc *hdw_desc;
@@ -1915,6 +2184,16 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 
        hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
 
+       if (hdw_desc == NULL) {
+               pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:"
+                          " No device description pointer,"
+                          " unable to continue.");
+               pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type,"
+                          " please contact Mike Isely <isely@pobox.com>"
+                          " to get it included in the driver\n");
+               goto fail;
+       }
+
        hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
        pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
                   hdw,hdw_desc->description);
@@ -2072,6 +2351,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
                        valid_std_mask;
        }
 
+       hdw->cropcap_stale = !0;
        hdw->eeprom_addr = -1;
        hdw->unit_number = -1;
        hdw->v4l_minor_number_video = -1;
@@ -2508,6 +2788,28 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                /* Can't commit anything until pathway is ok. */
                return 0;
        }
+       /* The broadcast decoder can only scale down, so if
+        * res_*_dirty && crop window < output format ==> enlarge crop.
+        *
+        * The mpeg encoder receives fields of res_hor_val dots and
+        * res_ver_val halflines.  Limits: hor<=720, ver<=576.
+        */
+       if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
+               hdw->cropw_val = hdw->res_hor_val;
+               hdw->cropw_dirty = !0;
+       } else if (hdw->cropw_dirty) {
+               hdw->res_hor_dirty = !0;           /* must rescale */
+               hdw->res_hor_val = min(720, hdw->cropw_val);
+       }
+       if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
+               hdw->croph_val = hdw->res_ver_val;
+               hdw->croph_dirty = !0;
+       } else if (hdw->croph_dirty) {
+               int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
+               hdw->res_ver_dirty = !0;
+               hdw->res_ver_val = min(nvres, hdw->croph_val);
+       }
+
        /* If any of the below has changed, then we can't do the update
           while the pipeline is running.  Pipeline must be paused first
           and decoder -> encoder connection be made quiescent before we
@@ -2518,6 +2820,8 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
                 hdw->srate_dirty ||
                 hdw->res_ver_dirty ||
                 hdw->res_hor_dirty ||
+                hdw->cropw_dirty ||
+                hdw->croph_dirty ||
                 hdw->input_dirty ||
                 (hdw->active_stream_type != hdw->desired_stream_type));
        if (disruptive_change && !hdw->state_pipeline_idle) {
@@ -2587,6 +2891,9 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
        }
 
        hdw->state_pipeline_config = !0;
+       /* Hardware state may have changed in a way to cause the cropping
+          capabilities to have changed.  So mark it stale, which will
+          cause a later re-fetch. */
        trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
        return !0;
 }
@@ -2677,6 +2984,33 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
 }
 
 
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
+{
+       if (!hdw->cropcap_stale) {
+               return 0;
+       }
+       pvr2_i2c_core_status_poll(hdw);
+       if (hdw->cropcap_stale) {
+               return -EIO;
+       }
+       return 0;
+}
+
+
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp)
+{
+       int stat = 0;
+       LOCK_TAKE(hdw->big_lock);
+       stat = pvr2_hdw_check_cropcap(hdw);
+       if (!stat) {
+               memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info));
+       }
+       LOCK_GIVE(hdw->big_lock);
+       return stat;
+}
+
+
 /* Return information about the tuner */
 int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
 {
index c04956d304a7da07814030a29543fcf1c0d55651..49482d1f2b28d71b87ccd3318e3b0b45afeda2e1 100644 (file)
 #define PVR2_CID_FREQUENCY 6
 #define PVR2_CID_HRES 7
 #define PVR2_CID_VRES 8
+#define PVR2_CID_CROPL 9
+#define PVR2_CID_CROPT 10
+#define PVR2_CID_CROPW 11
+#define PVR2_CID_CROPH 12
+#define PVR2_CID_CROPCAPPAN 13
+#define PVR2_CID_CROPCAPPAD 14
+#define PVR2_CID_CROPCAPBL 15
+#define PVR2_CID_CROPCAPBT 16
+#define PVR2_CID_CROPCAPBW 17
+#define PVR2_CID_CROPCAPBH 18
 
 /* Legal values for the INPUT state variable */
 #define PVR2_CVAL_INPUT_TV 0
@@ -170,6 +180,9 @@ void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
 /* Return information about the tuner */
 int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
 
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *);
+
 /* Query device and see if it thinks it is on a high-speed USB link */
 int pvr2_hdw_is_hsm(struct pvr2_hdw *);
 
index ccdb429fc7afc8f5b91fa1574aeb417a0a194b41..94a47718e88eb0dcd275f9c080d23440dfbdad85 100644 (file)
@@ -37,8 +37,9 @@
 #define OP_VOLUME 3
 #define OP_FREQ 4
 #define OP_AUDIORATE 5
-#define OP_SIZE 6
-#define OP_LOG 7
+#define OP_CROP 6
+#define OP_SIZE 7
+#define OP_LOG 8
 
 static const struct pvr2_i2c_op * const ops[] = {
        [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
@@ -46,6 +47,7 @@ static const struct pvr2_i2c_op * const ops[] = {
        [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
        [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
        [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
+       [OP_CROP] = &pvr2_i2c_op_v4l2_crop,
        [OP_SIZE] = &pvr2_i2c_op_v4l2_size,
        [OP_LOG] = &pvr2_i2c_op_v4l2_log,
 };
@@ -59,6 +61,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
                        (1 << OP_BCSH) |
                        (1 << OP_VOLUME) |
                        (1 << OP_FREQ) |
+                       (1 << OP_CROP) |
                        (1 << OP_SIZE) |
                        (1 << OP_LOG));
        cp->status_poll = pvr2_v4l2_cmd_status_poll;
index 55f04a0b2047eca152455e7a87c3db1d22e86f4f..16bb11902a522ef0881e44e47aacc4779c4a57e3 100644 (file)
@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw)
                pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
        }
        hdw->tuner_signal_stale = !0;
+       hdw->cropcap_stale = !0;
 }
 
 
@@ -233,6 +234,37 @@ const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
 };
 
 
+static void set_crop(struct pvr2_hdw *hdw)
+{
+       struct v4l2_crop crop;
+
+       memset(&crop, 0, sizeof crop);
+       crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       crop.c.left = hdw->cropl_val;
+       crop.c.top = hdw->cropt_val;
+       crop.c.height = hdw->croph_val;
+       crop.c.width = hdw->cropw_val;
+
+       pvr2_trace(PVR2_TRACE_CHIPS,
+                  "i2c v4l2 set_crop crop=%d:%d:%d:%d",
+                  crop.c.width, crop.c.height, crop.c.left, crop.c.top);
+
+       pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop);
+}
+
+static int check_crop(struct pvr2_hdw *hdw)
+{
+       return (hdw->cropl_dirty || hdw->cropt_dirty ||
+               hdw->cropw_dirty || hdw->croph_dirty);
+}
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = {
+       .check = check_crop,
+       .update = set_crop,
+       .name = "v4l2_crop",
+};
+
+
 static void do_log(struct pvr2_hdw *hdw)
 {
        pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
@@ -263,7 +295,19 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
 
 void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp)
 {
-       pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info);
+       int stat;
+       struct pvr2_hdw *hdw = cp->hdw;
+       if (hdw->cropcap_stale) {
+               hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP,
+                                          &hdw->cropcap_info);
+               if (stat == 0) {
+                       /* Check was successful, so the data is no
+                          longer considered stale. */
+                       hdw->cropcap_stale = 0;
+               }
+       }
+       pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info);
 }
 
 
index 7fa38683b3b1f309bc2f23835cf63d7d05a308c4..eb744a20610d4ec15d68f648626e268487172619 100644 (file)
@@ -29,6 +29,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode;
 extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
index e600576a6c4b5b7092293052230e54ff3a857cec..d6a35401fefb78186ad40e758003a4c34b77ce84 100644 (file)
@@ -827,7 +827,7 @@ static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
        if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
                unsigned int idx;
                unsigned long msk,sm;
-               int spcfl;
+
                bcnt = scnprintf(buf,maxlen," [");
                ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
                sm = 0;
@@ -891,6 +891,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client)
        INIT_LIST_HEAD(&cp->list);
        cp->client = client;
        mutex_lock(&hdw->i2c_list_lock); do {
+               hdw->cropcap_stale = !0;
                list_add_tail(&cp->list,&hdw->i2c_clients);
                hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
        } while (0); mutex_unlock(&hdw->i2c_list_lock);
@@ -905,6 +906,7 @@ static int pvr2_i2c_detach_inform(struct i2c_client *client)
        unsigned long amask = 0;
        int foundfl = 0;
        mutex_lock(&hdw->i2c_list_lock); do {
+               hdw->cropcap_stale = !0;
                list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
                        if (cp->client == client) {
                                trace_i2c("pvr2_i2c_detach"
@@ -946,22 +948,32 @@ static struct i2c_adapter pvr2_i2c_adap_template = {
        .client_unregister = pvr2_i2c_detach_inform,
 };
 
-static void do_i2c_scan(struct pvr2_hdw *hdw)
+
+/* Return true if device exists at given address */
+static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
 {
        struct i2c_msg msg[1];
-       int i,rc;
+       int rc;
        msg[0].addr = 0;
        msg[0].flags = I2C_M_RD;
        msg[0].len = 0;
        msg[0].buf = NULL;
-       printk("%s: i2c scan beginning\n",hdw->name);
+       msg[0].addr = addr;
+       rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg));
+       return rc == 1;
+}
+
+static void do_i2c_scan(struct pvr2_hdw *hdw)
+{
+       int i;
+       printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
        for (i = 0; i < 128; i++) {
-               msg[0].addr = i;
-               rc = i2c_transfer(&hdw->i2c_adap,msg, ARRAY_SIZE(msg));
-               if (rc != 1) continue;
-               printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
+               if (do_i2c_probe(hdw, i)) {
+                       printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
+                              hdw->name, i);
+               }
        }
-       printk("%s: i2c scan done.\n",hdw->name);
+       printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
 }
 
 void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
@@ -980,8 +992,6 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
                hdw->i2c_func[0x18] = i2c_black_hole;
        } else if (ir_mode[hdw->unit_number] == 1) {
                if (hdw->hdw_desc->ir_scheme == PVR2_IR_SCHEME_24XXX) {
-                       /* This comment is present PURELY to get
-                          checkpatch.pl to STFU.  Lovely, eh? */
                        hdw->i2c_func[0x18] = i2c_24xxx_ir;
                }
        }
@@ -1006,6 +1016,16 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
        mutex_init(&hdw->i2c_list_lock);
        hdw->i2c_linked = !0;
        i2c_add_adapter(&hdw->i2c_adap);
+       if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
+               /* Probe for a different type of IR receiver on this
+                  device.  If present, disable the emulated IR receiver. */
+               if (do_i2c_probe(hdw, 0x71)) {
+                       pvr2_trace(PVR2_TRACE_INFO,
+                                  "Device has newer IR hardware;"
+                                  " disabling unneeded virtual IR device");
+                       hdw->i2c_func[0x18] = NULL;
+               }
+       }
        if (i2c_scan) do_i2c_scan(hdw);
 }
 
index ad0d98c2ebb4165ab34ef638f7786bd89463a30e..9b3c874d96d612c18bc07a9e72fb88f2fb78caad 100644 (file)
@@ -137,9 +137,11 @@ static int __init pvr_init(void)
        ret = usb_register(&pvr_driver);
 
        if (ret == 0)
-               info(DRIVER_DESC " : " DRIVER_VERSION);
-       if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
-                               pvrusb2_debug,pvrusb2_debug);
+               printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+                      DRIVER_DESC "\n");
+       if (pvrusb2_debug)
+               printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n",
+                      pvrusb2_debug,pvrusb2_debug);
 
        pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
 
index 46a8c39ba03028fc07ecd7392d2fd44522779869..733680f2131714a7f1642cf0f36655f28695b024 100644 (file)
@@ -65,6 +65,7 @@ struct pvr2_sysfs_ctl_item {
        struct device_attribute attr_type;
        struct device_attribute attr_min;
        struct device_attribute attr_max;
+       struct device_attribute attr_def;
        struct device_attribute attr_enum;
        struct device_attribute attr_bits;
        struct device_attribute attr_val;
@@ -145,6 +146,23 @@ static ssize_t show_max(struct device *class_dev,
        return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
 }
 
+static ssize_t show_def(struct device *class_dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int val;
+       int ret;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
+       ret = pvr2_ctrl_get_def(cip->cptr, &val);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %d, stat=%d",
+                        cip->chptr, cip->ctl_id, val, ret);
+       if (ret < 0) {
+               return ret;
+       }
+       return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
 static ssize_t show_val_norm(struct device *class_dev,
                             struct device_attribute *attr,
                             char *buf)
@@ -320,6 +338,10 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cip->attr_max.attr.mode = S_IRUGO;
        cip->attr_max.show = show_max;
 
+       cip->attr_def.attr.name = "def_val";
+       cip->attr_def.attr.mode = S_IRUGO;
+       cip->attr_def.show = show_def;
+
        cip->attr_val.attr.name = "cur_val";
        cip->attr_val.attr.mode = S_IRUGO;
 
@@ -343,6 +365,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cip->attr_gen[acnt++] = &cip->attr_name.attr;
        cip->attr_gen[acnt++] = &cip->attr_type.attr;
        cip->attr_gen[acnt++] = &cip->attr_val.attr;
+       cip->attr_gen[acnt++] = &cip->attr_def.attr;
        cip->attr_val.show = show_val_norm;
        cip->attr_val.store = store_val_norm;
        if (pvr2_ctrl_has_custom_symbols(cptr)) {
index 00306faeac015f1ab9a99c8aaf32b894032bc444..f048d80b77e58b8e7e5e05ff9c2fec798929e135 100644 (file)
@@ -533,7 +533,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
 
                        lmin = pvr2_ctrl_get_min(hcp);
                        lmax = pvr2_ctrl_get_max(hcp);
-                       ldef = pvr2_ctrl_get_def(hcp);
+                       pvr2_ctrl_get_def(hcp, &ldef);
                        if (w == -1) {
                                w = ldef;
                        } else if (w < lmin) {
@@ -543,7 +543,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        }
                        lmin = pvr2_ctrl_get_min(vcp);
                        lmax = pvr2_ctrl_get_max(vcp);
-                       ldef = pvr2_ctrl_get_def(vcp);
+                       pvr2_ctrl_get_def(vcp, &ldef);
                        if (h == -1) {
                                h = ldef;
                        } else if (h < lmin) {
@@ -604,6 +604,7 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_QUERYCTRL:
        {
                struct pvr2_ctrl *cptr;
+               int val;
                struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
                ret = 0;
                if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
@@ -627,7 +628,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                           pvr2_ctrl_get_desc(cptr));
                strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
                vc->flags = pvr2_ctrl_get_v4lflags(cptr);
-               vc->default_value = pvr2_ctrl_get_def(cptr);
+               pvr2_ctrl_get_def(cptr, &val);
+               vc->default_value = val;
                switch (pvr2_ctrl_get_type(cptr)) {
                case pvr2_ctl_enum:
                        vc->type = V4L2_CTRL_TYPE_MENU;
@@ -753,6 +755,92 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
+               if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = pvr2_hdw_get_cropcap(hdw, cap);
+               cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
+               break;
+       }
+       case VIDIOC_G_CROP:
+       {
+               struct v4l2_crop *crop = (struct v4l2_crop *)arg;
+               int val = 0;
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               crop->c.left = val;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               crop->c.top = val;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               crop->c.width = val;
+               ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               crop->c.height = val;
+       }
+       case VIDIOC_S_CROP:
+       {
+               struct v4l2_crop *crop = (struct v4l2_crop *)arg;
+               struct v4l2_cropcap cap;
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       ret = -EINVAL;
+                       break;
+               }
+               cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
+                       crop->c.left);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
+                       crop->c.top);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
+                       crop->c.width);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
+                       crop->c.height);
+               if (ret != 0) {
+                       ret = -EINVAL;
+                       break;
+               }
+       }
        case VIDIOC_LOG_STATUS:
        {
                pvr2_hdw_trigger_module_log(hdw);
index dbc560742553ec98b3c5aa2e487f0e2e05d232a5..c6653021019224c697053b869d62a656333a89d5 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/uaccess.h>
 #endif
 #include <asm/errno.h>
-#include <linux/version.h>
 
 #include "pwc.h"
 #include "pwc-uncompress.h"
index 9aee7cb6f79a9e310e57021ac7d50a1fb73d0dc9..ab28389b4cdadf17d0e28282dd6c186237c2fe14 100644 (file)
@@ -1112,7 +1112,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
 
        PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
 
-       pdev = (struct pwc_device *)vdev->priv;
+       pdev = video_get_drvdata(vdev);
        BUG_ON(!pdev);
        if (pdev->vopen) {
                PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
@@ -1233,7 +1233,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
        PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
        lock_kernel();
-       pdev = (struct pwc_device *)vdev->priv;
+       pdev = video_get_drvdata(vdev);
        if (pdev->vopen == 0)
                PWC_DEBUG_MODULE("video_close() called on closed device?\n");
 
@@ -1304,7 +1304,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
                        vdev, buf, count);
        if (vdev == NULL)
                return -EFAULT;
-       pdev = vdev->priv;
+       pdev = video_get_drvdata(vdev);
        if (pdev == NULL)
                return -EFAULT;
 
@@ -1386,7 +1386,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
 
        if (vdev == NULL)
                return -EFAULT;
-       pdev = vdev->priv;
+       pdev = video_get_drvdata(vdev);
        if (pdev == NULL)
                return -EFAULT;
 
@@ -1408,7 +1408,7 @@ static int pwc_video_ioctl(struct inode *inode, struct file *file,
 
        if (!vdev)
                goto out;
-       pdev = vdev->priv;
+       pdev = video_get_drvdata(vdev);
 
        mutex_lock(&pdev->modlock);
        if (!pdev->unplugged)
@@ -1428,7 +1428,7 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
        int index;
 
        PWC_DEBUG_MEMORY(">> %s\n", __func__);
-       pdev = vdev->priv;
+       pdev = video_get_drvdata(vdev);
        size = vma->vm_end - vma->vm_start;
        start = vma->vm_start;
 
index 1742889874df08c6f944b4b066fa1111fcff2e4a..76a1376c9751dd1c06acacc766af6676a36efe40 100644 (file)
@@ -346,7 +346,7 @@ int pwc_video_do_ioctl(struct inode *inode, struct file *file,
 
        if (vdev == NULL)
                return -EFAULT;
-       pdev = vdev->priv;
+       pdev = video_get_drvdata(vdev);
        if (pdev == NULL)
                return -EFAULT;
 
index cf96b2cc4f1c4b70f59ef279ad8cfee8b4535f1a..eb6be580292899ed8a6b5d0fa41b204f52d9f07d 100644 (file)
@@ -629,17 +629,6 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
                pdata->init(pcdev->dev);
        }
 
-       if (pdata && pdata->power) {
-               dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__);
-               pdata->power(pcdev->dev, 1);
-       }
-
-       if (pdata && pdata->reset) {
-               dev_dbg(pcdev->dev, "%s: Releasing camera reset\n",
-                       __func__);
-               pdata->reset(pcdev->dev, 1);
-       }
-
        CICR0 = 0x3FF;   /* disable all interrupts */
 
        if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
@@ -660,20 +649,7 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
 
 static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev)
 {
-       struct pxacamera_platform_data *board = pcdev->pdata;
-
        clk_disable(pcdev->clk);
-
-       if (board && board->reset) {
-               dev_dbg(pcdev->dev, "%s: Asserting camera reset\n",
-                       __func__);
-               board->reset(pcdev->dev, 0);
-       }
-
-       if (board && board->power) {
-               dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__);
-               board->power(pcdev->dev, 0);
-       }
 }
 
 static irqreturn_t pxa_camera_irq(int irq, void *data)
@@ -1144,31 +1120,31 @@ static int pxa_camera_probe(struct platform_device *pdev)
        pcdev->dev = &pdev->dev;
 
        /* request dma */
-       pcdev->dma_chans[0] = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
-                                             pxa_camera_dma_irq_y, pcdev);
-       if (pcdev->dma_chans[0] < 0) {
+       err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
+                             pxa_camera_dma_irq_y, pcdev);
+       if (err < 0) {
                dev_err(pcdev->dev, "Can't request DMA for Y\n");
-               err = -ENOMEM;
                goto exit_iounmap;
        }
+       pcdev->dma_chans[0] = err;
        dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
 
-       pcdev->dma_chans[1] = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
-                                             pxa_camera_dma_irq_u, pcdev);
-       if (pcdev->dma_chans[1] < 0) {
+       err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
+                             pxa_camera_dma_irq_u, pcdev);
+       if (err < 0) {
                dev_err(pcdev->dev, "Can't request DMA for U\n");
-               err = -ENOMEM;
                goto exit_free_dma_y;
        }
+       pcdev->dma_chans[1] = err;
        dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
 
-       pcdev->dma_chans[2] = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
-                                             pxa_camera_dma_irq_v, pcdev);
-       if (pcdev->dma_chans[0] < 0) {
+       err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
+                             pxa_camera_dma_irq_v, pcdev);
+       if (err < 0) {
                dev_err(pcdev->dev, "Can't request DMA for V\n");
-               err = -ENOMEM;
                goto exit_free_dma_u;
        }
+       pcdev->dma_chans[2] = err;
        dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
 
        DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
index 92b83feae3668d2bca19f32a956962c2107de7f7..5272926db73e93763f21aaf8ecc746fbb88f93f9 100644 (file)
@@ -58,6 +58,8 @@
 
 
 
+/* default JPEG quality */
+#define S2255_DEF_JPEG_QUAL     50
 /* vendor request in */
 #define S2255_VR_IN            0
 /* vendor request out */
 /* USB endpoint number for configuring the device */
 #define S2255_CONFIG_EP         2
 /* maximum time for DSP to start responding after last FW word loaded(ms) */
-#define S2255_DSP_BOOTTIME      400
+#define S2255_DSP_BOOTTIME      800
 /* maximum time to wait for firmware to load (ms) */
 #define S2255_LOAD_TIMEOUT      (5000 + S2255_DSP_BOOTTIME)
 #define S2255_DEF_BUFS          16
+#define S2255_SETMODE_TIMEOUT   500
 #define MAX_CHANNELS           4
-#define FRAME_MARKER           0x2255DA4AL
-#define MAX_PIPE_USBBLOCK      (40 * 1024)
-#define DEFAULT_PIPE_USBBLOCK  (16 * 1024)
+#define S2255_MARKER_FRAME     0x2255DA4AL
+#define S2255_MARKER_RESPONSE  0x2255ACACL
+#define S2255_USB_XFER_SIZE    (16 * 1024)
 #define MAX_CHANNELS           4
 #define MAX_PIPE_BUFFERS       1
 #define SYS_FRAMES             4
 /* maximum size is PAL full size plus room for the marker header(s) */
-#define SYS_FRAMES_MAXSIZE     (720 * 288 * 2 * 2 + 4096)
-#define DEF_USB_BLOCK          (4096)
+#define SYS_FRAMES_MAXSIZE     (720*288*2*2 + 4096)
+#define DEF_USB_BLOCK          S2255_USB_XFER_SIZE
 #define LINE_SZ_4CIFS_NTSC     640
 #define LINE_SZ_2CIFS_NTSC     640
 #define LINE_SZ_1CIFS_NTSC     320
 #define COLOR_YUVPL    1       /* YUV planar */
 #define COLOR_YUVPK    2       /* YUV packed */
 #define COLOR_Y8       4       /* monochrome */
+#define COLOR_JPG       5       /* JPEG */
+#define MASK_COLOR      0xff
+#define MASK_JPG_QUALITY 0xff00
 
 /* frame decimation. Not implemented by V4L yet(experimental in V4L) */
 #define FDEC_1         1       /* capture every frame. default */
@@ -148,16 +154,14 @@ struct s2255_mode {
        u32 restart;    /* if DSP requires restart */
 };
 
-/* frame structure */
-#define FRAME_STATE_UNUSED     0
-#define FRAME_STATE_FILLING    1
-#define FRAME_STATE_FULL       2
 
+#define S2255_READ_IDLE                0
+#define S2255_READ_FRAME       1
 
+/* frame structure */
 struct s2255_framei {
        unsigned long size;
-
-       unsigned long ulState;  /* ulState ==0 unused, 1 being filled, 2 full */
+       unsigned long ulState;  /* ulState:S2255_READ_IDLE, S2255_READ_FRAME*/
        void *lpvbits;          /* image data */
        unsigned long cur_size; /* current data copied to it */
 };
@@ -188,6 +192,10 @@ struct s2255_dmaqueue {
 #define S2255_FW_FAILED                3
 #define S2255_FW_DISCONNECTING  4
 
+#define S2255_FW_MARKER         0x22552f2f
+/* 2255 read states */
+#define S2255_READ_IDLE         0
+#define S2255_READ_FRAME        1
 struct s2255_fw {
        int                   fw_loaded;
        int                   fw_size;
@@ -195,7 +203,6 @@ struct s2255_fw {
        atomic_t              fw_state;
        void                  *pfw_data;
        wait_queue_head_t     wait_fw;
-       struct timer_list     dsp_wait;
        const struct firmware *fw;
 };
 
@@ -237,15 +244,27 @@ struct s2255_dev {
        struct s2255_pipeinfo   pipes[MAX_PIPE_BUFFERS];
        struct s2255_bufferi            buffer[MAX_CHANNELS];
        struct s2255_mode       mode[MAX_CHANNELS];
+       /* jpeg compression */
+       struct v4l2_jpegcompression jc[MAX_CHANNELS];
        const struct s2255_fmt  *cur_fmt[MAX_CHANNELS];
        int                     cur_frame[MAX_CHANNELS];
        int                     last_frame[MAX_CHANNELS];
        u32                     cc;     /* current channel */
        int                     b_acquire[MAX_CHANNELS];
+       /* allocated image size */
        unsigned long           req_image_size[MAX_CHANNELS];
+       /* received packet size */
+       unsigned long           pkt_size[MAX_CHANNELS];
        int                     bad_payload[MAX_CHANNELS];
        unsigned long           frame_count[MAX_CHANNELS];
        int                     frame_ready;
+       /* if JPEG image */
+       int                     jpg_size[MAX_CHANNELS];
+       /* if channel configured to default state */
+       int                     chn_configured[MAX_CHANNELS];
+       wait_queue_head_t       wait_setmode[MAX_CHANNELS];
+       int                     setmode_ready[MAX_CHANNELS];
+       int                     chn_ready;
        struct kref             kref;
        spinlock_t              slock;
 };
@@ -306,12 +325,16 @@ static void s2255_stop_readpipe(struct s2255_dev *dev);
 static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn);
 static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
 static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
-                          int chn);
+                          int chn, int jpgsize);
 static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
                          struct s2255_mode *mode);
 static int s2255_board_shutdown(struct s2255_dev *dev);
 static void s2255_exit_v4l(struct s2255_dev *dev);
-static void s2255_fwload_start(struct s2255_dev *dev);
+static void s2255_fwload_start(struct s2255_dev *dev, int reset);
+static void s2255_destroy(struct kref *kref);
+static long s2255_vendor_req(struct s2255_dev *dev, unsigned char req,
+                            u16 index, u16 value, void *buf,
+                            s32 buf_len, int bOut);
 
 #define dprintk(level, fmt, arg...)                                    \
        do {                                                            \
@@ -406,6 +429,10 @@ static const struct s2255_fmt formats[] = {
                .name = "4:2:2, packed, UYVY",
                .fourcc = V4L2_PIX_FMT_UYVY,
                .depth = 16
+       }, {
+               .name = "JPG",
+               .fourcc = V4L2_PIX_FMT_JPEG,
+               .depth = 24
        }, {
                .name = "8bpp GREY",
                .fourcc = V4L2_PIX_FMT_GREY,
@@ -464,6 +491,13 @@ static void planar422p_to_yuv_packed(const unsigned char *in,
        return;
 }
 
+static void s2255_reset_dsppower(struct s2255_dev *dev)
+{
+       s2255_vendor_req(dev, 0x40, 0x0b0b, 0x0b0b, NULL, 0, 1);
+       msleep(10);
+       s2255_vendor_req(dev, 0x50, 0x0000, 0x0000, NULL, 0, 1);
+       return;
+}
 
 /* kickstarts the firmware loading. from probe
  */
@@ -480,18 +514,6 @@ static void s2255_timer(unsigned long user_data)
        }
 }
 
-/* called when DSP is up and running.  DSP is guaranteed to
-   be running after S2255_DSP_BOOTTIME */
-static void s2255_dsp_running(unsigned long user_data)
-{
-       struct s2255_fw *data = (struct s2255_fw *)user_data;
-       dprintk(1, "dsp running\n");
-       atomic_set(&data->fw_state, S2255_FW_SUCCESS);
-       wake_up(&data->wait_fw);
-       printk(KERN_INFO "s2255: firmware loaded successfully\n");
-       return;
-}
-
 
 /* this loads the firmware asynchronously.
    Originally this was done synchroously in probe.
@@ -549,19 +571,14 @@ static void s2255_fwchunk_complete(struct urb *urb)
                }
                data->fw_loaded += len;
        } else {
-               init_timer(&data->dsp_wait);
-               data->dsp_wait.function = s2255_dsp_running;
-               data->dsp_wait.data = (unsigned long)data;
                atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
-               mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME)
-                         + jiffies);
        }
        dprintk(100, "2255 complete done\n");
        return;
 
 }
 
-static int s2255_got_frame(struct s2255_dev *dev, int chn)
+static int s2255_got_frame(struct s2255_dev *dev, int chn, int jpgsize)
 {
        struct s2255_dmaqueue *dma_q = &dev->vidq[chn];
        struct s2255_buffer *buf;
@@ -586,8 +603,7 @@ static int s2255_got_frame(struct s2255_dev *dev, int chn)
        list_del(&buf->vb.queue);
        do_gettimeofday(&buf->vb.ts);
        dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
-
-       s2255_fillbuff(dev, buf, dma_q->channel);
+       s2255_fillbuff(dev, buf, dma_q->channel, jpgsize);
        wake_up(&buf->vb.done);
        dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
 unlock:
@@ -621,7 +637,7 @@ static const struct s2255_fmt *format_by_fourcc(int fourcc)
  *
  */
 static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
-                          int chn)
+                          int chn, int jpgsize)
 {
        int pos = 0;
        struct timeval ts;
@@ -649,6 +665,10 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
                case V4L2_PIX_FMT_GREY:
                        memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
                        break;
+               case V4L2_PIX_FMT_JPEG:
+                       buf->vb.size = jpgsize;
+                       memcpy(vbuf, tmpbuf, buf->vb.size);
+                       break;
                case V4L2_PIX_FMT_YUV422P:
                        memcpy(vbuf, tmpbuf,
                               buf->vb.width * buf->vb.height * 2);
@@ -657,9 +677,6 @@ static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
                        printk(KERN_DEBUG "s2255: unknown format?\n");
                }
                dev->last_frame[chn] = -1;
-               /* done with the frame, free it */
-               frm->ulState = 0;
-               dprintk(4, "freeing buffer\n");
        } else {
                printk(KERN_ERR "s2255: =======no frame\n");
                return;
@@ -1021,6 +1038,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        case V4L2_PIX_FMT_GREY:
                fh->mode.color = COLOR_Y8;
                break;
+       case V4L2_PIX_FMT_JPEG:
+               fh->mode.color = COLOR_JPG |
+                       (fh->dev->jc[fh->channel].quality << 8);
+               break;
        case V4L2_PIX_FMT_YUV422P:
                fh->mode.color = COLOR_YUVPL;
                break;
@@ -1139,7 +1160,7 @@ static u32 get_transfer_size(struct s2255_mode *mode)
                }
        }
        outImageSize = linesPerFrame * pixelsPerLine;
-       if (mode->color != COLOR_Y8) {
+       if ((mode->color & MASK_COLOR) != COLOR_Y8) {
                /* 2 bytes/pixel if not monochrome */
                outImageSize *= 2;
        }
@@ -1185,12 +1206,17 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
        u32 *buffer;
        unsigned long chn_rev;
 
+       mutex_lock(&dev->lock);
        chn_rev = G_chnmap[chn];
        dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
        dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
                dev->mode[chn].scale);
        dprintk(2, "mode contrast %x\n", mode->contrast);
 
+       /* if JPEG, set the quality */
+       if ((mode->color & MASK_COLOR) == COLOR_JPG)
+               mode->color = (dev->jc[chn].quality << 8) | COLOR_JPG;
+
        /* save the mode */
        dev->mode[chn] = *mode;
        dev->req_image_size[chn] = get_transfer_size(mode);
@@ -1199,6 +1225,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
        buffer = kzalloc(512, GFP_KERNEL);
        if (buffer == NULL) {
                dev_err(&dev->udev->dev, "out of mem\n");
+               mutex_unlock(&dev->lock);
                return -ENOMEM;
        }
 
@@ -1214,12 +1241,20 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
        dprintk(1, "set mode done chn %lu, %d\n", chn, res);
 
        /* wait at least 3 frames before continuing */
-       if (mode->restart)
-               msleep(125);
+       if (mode->restart) {
+               dev->setmode_ready[chn] = 0;
+               wait_event_timeout(dev->wait_setmode[chn],
+                                  (dev->setmode_ready[chn] != 0),
+                                  msecs_to_jiffies(S2255_SETMODE_TIMEOUT));
+               if (dev->setmode_ready[chn] != 1) {
+                       printk(KERN_DEBUG "s2255: no set mode response\n");
+                       res = -EFAULT;
+               }
+       }
 
        /* clear the restart flag */
        dev->mode[chn].restart = 0;
-
+       mutex_unlock(&dev->lock);
        return res;
 }
 
@@ -1270,7 +1305,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
        dev->cur_frame[chn] = 0;
        dev->frame_count[chn] = 0;
        for (j = 0; j < SYS_FRAMES; j++) {
-               dev->buffer[chn].frame[j].ulState = 0;
+               dev->buffer[chn].frame[j].ulState = S2255_READ_IDLE;
                dev->buffer[chn].frame[j].cur_size = 0;
        }
        res = videobuf_streamon(&fh->vb_vidq);
@@ -1446,6 +1481,27 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
        return -EINVAL;
 }
 
+static int vidioc_g_jpegcomp(struct file *file, void *priv,
+                        struct v4l2_jpegcompression *jc)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_dev *dev = fh->dev;
+       *jc = dev->jc[fh->channel];
+       dprintk(2, "getting jpegcompression, quality %d\n", jc->quality);
+       return 0;
+}
+
+static int vidioc_s_jpegcomp(struct file *file, void *priv,
+                        struct v4l2_jpegcompression *jc)
+{
+       struct s2255_fh *fh = priv;
+       struct s2255_dev *dev = fh->dev;
+       if (jc->quality < 0 || jc->quality > 100)
+               return -EINVAL;
+       dev->jc[fh->channel].quality = jc->quality;
+       dprintk(2, "setting jpeg quality %d\n", jc->quality);
+       return 0;
+}
 static int s2255_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
@@ -1455,8 +1511,10 @@ static int s2255_open(struct inode *inode, struct file *file)
        enum v4l2_buf_type type = 0;
        int i = 0;
        int cur_channel = -1;
+       int state;
        dprintk(1, "s2255: open called (minor=%d)\n", minor);
 
+       lock_kernel();
        list_for_each(list, &s2255_devlist) {
                h = list_entry(list, struct s2255_dev, s2255_devlist);
                for (i = 0; i < MAX_CHANNELS; i++) {
@@ -1469,45 +1527,78 @@ static int s2255_open(struct inode *inode, struct file *file)
        }
 
        if ((NULL == dev) || (cur_channel == -1)) {
-               dprintk(1, "s2255: openv4l no dev\n");
+               unlock_kernel();
+               printk(KERN_INFO "s2255: openv4l no dev\n");
                return -ENODEV;
        }
 
+       if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) {
+               unlock_kernel();
+               printk(KERN_INFO "disconnecting\n");
+               return -ENODEV;
+       }
+       kref_get(&dev->kref);
        mutex_lock(&dev->open_lock);
 
        dev->users[cur_channel]++;
        dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
 
-       if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
+       switch (atomic_read(&dev->fw_data->fw_state)) {
+       case S2255_FW_FAILED:
                err("2255 firmware load failed. retrying.\n");
-               s2255_fwload_start(dev);
+               s2255_fwload_start(dev, 1);
                wait_event_timeout(dev->fw_data->wait_fw,
-                                  (atomic_read(&dev->fw_data->fw_state)
-                                   != S2255_FW_NOTLOADED),
+                                  ((atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_SUCCESS) ||
+                                   (atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_DISCONNECTING)),
                                   msecs_to_jiffies(S2255_LOAD_TIMEOUT));
-               if (atomic_read(&dev->fw_data->fw_state)
-                   != S2255_FW_SUCCESS) {
-                       printk(KERN_INFO "2255 FW load failed.\n");
-                       dev->users[cur_channel]--;
-                       mutex_unlock(&dev->open_lock);
-                       return -EFAULT;
-               }
-       } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) {
+               break;
+       case S2255_FW_NOTLOADED:
+       case S2255_FW_LOADED_DSPWAIT:
                /* give S2255_LOAD_TIMEOUT time for firmware to load in case
                   driver loaded and then device immediately opened */
                printk(KERN_INFO "%s waiting for firmware load\n", __func__);
                wait_event_timeout(dev->fw_data->wait_fw,
-                                  (atomic_read(&dev->fw_data->fw_state)
-                                  != S2255_FW_NOTLOADED),
-                                  msecs_to_jiffies(S2255_LOAD_TIMEOUT));
-               if (atomic_read(&dev->fw_data->fw_state)
-                   != S2255_FW_SUCCESS) {
-                       printk(KERN_INFO "2255 firmware not loaded"
-                              "try again\n");
-                       dev->users[cur_channel]--;
-                       mutex_unlock(&dev->open_lock);
-                       return -EBUSY;
+                                  ((atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_SUCCESS) ||
+                                   (atomic_read(&dev->fw_data->fw_state)
+                                    == S2255_FW_DISCONNECTING)),
+                       msecs_to_jiffies(S2255_LOAD_TIMEOUT));
+               break;
+       case S2255_FW_SUCCESS:
+       default:
+               break;
+       }
+       state = atomic_read(&dev->fw_data->fw_state);
+       if (state != S2255_FW_SUCCESS) {
+               int rc;
+               switch (state) {
+               case S2255_FW_FAILED:
+                       printk(KERN_INFO "2255 FW load failed. %d\n", state);
+                       rc = -ENODEV;
+                       break;
+               case S2255_FW_DISCONNECTING:
+                       printk(KERN_INFO "%s: disconnecting\n", __func__);
+                       rc = -ENODEV;
+                       break;
+               case S2255_FW_LOADED_DSPWAIT:
+               case S2255_FW_NOTLOADED:
+                       printk(KERN_INFO "%s: firmware not loaded yet"
+                              "please try again later\n",
+                              __func__);
+                       rc = -EAGAIN;
+                       break;
+               default:
+                       printk(KERN_INFO "%s: unknown state\n", __func__);
+                       rc = -EFAULT;
+                       break;
                }
+               dev->users[cur_channel]--;
+               mutex_unlock(&dev->open_lock);
+               kref_put(&dev->kref, s2255_destroy);
+               unlock_kernel();
+               return rc;
        }
 
        /* allocate + initialize per filehandle data */
@@ -1515,6 +1606,8 @@ static int s2255_open(struct inode *inode, struct file *file)
        if (NULL == fh) {
                dev->users[cur_channel]--;
                mutex_unlock(&dev->open_lock);
+               kref_put(&dev->kref, s2255_destroy);
+               unlock_kernel();
                return -ENOMEM;
        }
 
@@ -1528,6 +1621,13 @@ static int s2255_open(struct inode *inode, struct file *file)
        fh->height = NUM_LINES_4CIFS_NTSC * 2;
        fh->channel = cur_channel;
 
+       /* configure channel to default state */
+       if (!dev->chn_configured[cur_channel]) {
+               s2255_set_mode(dev, cur_channel, &fh->mode);
+               dev->chn_configured[cur_channel] = 1;
+       }
+
+
        /* Put all controls at a sane state */
        for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
                qctl_regs[i] = s2255_qctrl[i].default_value;
@@ -1546,8 +1646,8 @@ static int s2255_open(struct inode *inode, struct file *file)
                                    V4L2_FIELD_INTERLACED,
                                    sizeof(struct s2255_buffer), fh);
 
-       kref_get(&dev->kref);
        mutex_unlock(&dev->open_lock);
+       unlock_kernel();
        return 0;
 }
 
@@ -1569,30 +1669,24 @@ static unsigned int s2255_poll(struct file *file,
 static void s2255_destroy(struct kref *kref)
 {
        struct s2255_dev *dev = to_s2255_dev(kref);
+       struct list_head *list;
+       int i;
        if (!dev) {
                printk(KERN_ERR "s2255drv: kref problem\n");
                return;
        }
-
-       /*
-        * Wake up any firmware load waiting (only done in .open,
-        * which holds the open_lock mutex)
-        */
        atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
        wake_up(&dev->fw_data->wait_fw);
-
-       /* prevent s2255_disconnect from racing s2255_open */
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               dev->setmode_ready[i] = 1;
+               wake_up(&dev->wait_setmode[i]);
+       }
        mutex_lock(&dev->open_lock);
+       /* reset the DSP so firmware can be reload next time */
+       s2255_reset_dsppower(dev);
        s2255_exit_v4l(dev);
-       /*
-        * device unregistered so no longer possible to open. open_mutex
-        *  can be unlocked and timers deleted afterwards.
-        */
-       mutex_unlock(&dev->open_lock);
-
        /* board shutdown stops the read pipe if it is running */
        s2255_board_shutdown(dev);
-
        /* make sure firmware still not trying to load */
        del_timer(&dev->timer);  /* only started in .probe and .open */
 
@@ -1602,23 +1696,19 @@ static void s2255_destroy(struct kref *kref)
                usb_free_urb(dev->fw_data->fw_urb);
                dev->fw_data->fw_urb = NULL;
        }
-
-       /*
-        * delete the dsp_wait timer, which sets the firmware
-        * state on completion.  This is done before fw_data
-        * is freed below.
-        */
-
-       del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
-
        if (dev->fw_data->fw)
                release_firmware(dev->fw_data->fw);
        kfree(dev->fw_data->pfw_data);
        kfree(dev->fw_data);
-
        usb_put_dev(dev->udev);
        dprintk(1, "%s", __func__);
        kfree(dev);
+
+       while (!list_empty(&s2255_devlist)) {
+               list = s2255_devlist.next;
+               list_del(list);
+       }
+       mutex_unlock(&dev->open_lock);
 }
 
 static int s2255_close(struct inode *inode, struct file *file)
@@ -1702,6 +1792,8 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf = vidioc_cgmbuf,
 #endif
+       .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
+       .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
 };
 
 static struct video_device template = {
@@ -1740,7 +1832,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
                        ret = video_register_device(dev->vdev[i],
                                                    VFL_TYPE_GRABBER,
                                                    cur_nr + i);
-               dev->vdev[i]->priv = dev;
+               video_set_drvdata(dev->vdev[i], dev);
 
                if (ret != 0) {
                        dev_err(&dev->udev->dev,
@@ -1754,18 +1846,16 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
 
 static void s2255_exit_v4l(struct s2255_dev *dev)
 {
-       struct list_head *list;
+
        int i;
-       /* unregister the video devices */
-       while (!list_empty(&s2255_devlist)) {
-               list = s2255_devlist.next;
-               list_del(list);
-       }
        for (i = 0; i < MAX_CHANNELS; i++) {
-               if (-1 != dev->vdev[i]->minor)
+               if (-1 != dev->vdev[i]->minor) {
                        video_unregister_device(dev->vdev[i]);
-               else
+                       printk(KERN_INFO "s2255 unregistered\n");
+               } else {
                        video_device_release(dev->vdev[i]);
+                       printk(KERN_INFO "s2255 released\n");
+               }
        }
 }
 
@@ -1775,134 +1865,123 @@ static void s2255_exit_v4l(struct s2255_dev *dev)
  * function again).
  *
  * Received frame structure:
- * bytes 0-3:  marker : 0x2255DA4AL (FRAME_MARKER)
+ * bytes 0-3:  marker : 0x2255DA4AL (S2255_MARKER_FRAME)
  * bytes 4-7:  channel: 0-3
  * bytes 8-11: payload size:  size of the frame
  * bytes 12-payloadsize+12:  frame data
  */
 static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 {
-       static int dbgsync; /* = 0; */
        char *pdest;
        u32 offset = 0;
-       int bsync = 0;
-       int btrunc = 0;
+       int bframe = 0;
        char *psrc;
        unsigned long copy_size;
        unsigned long size;
        s32 idx = -1;
        struct s2255_framei *frm;
        unsigned char *pdata;
-       unsigned long cur_size;
-       int bsearch = 0;
-       struct s2255_bufferi *buf;
+
        dprintk(100, "buffer to user\n");
 
        idx = dev->cur_frame[dev->cc];
-       buf = &dev->buffer[dev->cc];
-       frm = &buf->frame[idx];
-
-       if (frm->ulState == 0) {
-               frm->ulState = 1;
-               frm->cur_size = 0;
-               bsearch = 1;
-       } else if (frm->ulState == 2) {
-               /* system frame was not freed */
-               dprintk(2, "sys frame not free.  overrun ringbuf\n");
-               bsearch = 1;
-               frm->ulState = 1;
-               frm->cur_size = 0;
-       }
-
-       if (bsearch) {
-               if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) {
-                       u32 jj;
-                       if (dbgsync == 0) {
-                               dprintk(3, "not synched, discarding all packets"
-                                       "until marker\n");
+       frm = &dev->buffer[dev->cc].frame[idx];
 
-                               dbgsync++;
-                       }
-                       pdata = (unsigned char *)pipe_info->transfer_buffer;
-                       for (jj = 0; jj < (pipe_info->cur_transfer_size - 12);
-                            jj++) {
-                               if (*(s32 *) pdata == FRAME_MARKER) {
-                                       int cc;
-                                       dprintk(3,
-                                               "found frame marker at offset:"
-                                               " %d [%x %x]\n", jj, pdata[0],
-                                               pdata[1]);
-                                       offset = jj;
-                                       bsync = 1;
-                                       cc = *(u32 *) (pdata + sizeof(u32));
-                                       if (cc >= MAX_CHANNELS) {
-                                               printk(KERN_ERR
-                                                      "bad channel\n");
-                                               return -EINVAL;
-                                       }
-                                       /* reverse it */
-                                       dev->cc = G_chnmap[cc];
+       if (frm->ulState == S2255_READ_IDLE) {
+               int jj;
+               unsigned int cc;
+               s32 *pdword;
+               int payload;
+               /* search for marker codes */
+               pdata = (unsigned char *)pipe_info->transfer_buffer;
+               for (jj = 0; jj < (pipe_info->cur_transfer_size - 12); jj++) {
+                       switch (*(s32 *) pdata) {
+                       case S2255_MARKER_FRAME:
+                               pdword = (s32 *)pdata;
+                               dprintk(4, "found frame marker at offset:"
+                                       " %d [%x %x]\n", jj, pdata[0],
+                                       pdata[1]);
+                               offset = jj + PREFIX_SIZE;
+                               bframe = 1;
+                               cc = pdword[1];
+                               if (cc >= MAX_CHANNELS) {
+                                       printk(KERN_ERR
+                                              "bad channel\n");
+                                       return -EINVAL;
+                               }
+                               /* reverse it */
+                               dev->cc = G_chnmap[cc];
+                               payload =  pdword[3];
+                               if (payload > dev->req_image_size[dev->cc]) {
+                                       dev->bad_payload[dev->cc]++;
+                                       /* discard the bad frame */
+                                       return -EINVAL;
+                               }
+                               dev->pkt_size[dev->cc] = payload;
+                               dev->jpg_size[dev->cc] = pdword[4];
+                               break;
+                       case S2255_MARKER_RESPONSE:
+                               pdword = (s32 *)pdata;
+                               pdata += DEF_USB_BLOCK;
+                               jj += DEF_USB_BLOCK;
+                               if (pdword[1] >= MAX_CHANNELS)
+                                       break;
+                               cc = G_chnmap[pdword[1]];
+                               if (!(cc >= 0 && cc < MAX_CHANNELS))
+                                       break;
+                               switch (pdword[2]) {
+                               case 0x01:
+                                       /* check if channel valid */
+                                       /* set mode ready */
+                                       dev->setmode_ready[cc] = 1;
+                                       wake_up(&dev->wait_setmode[cc]);
+                                       dprintk(5, "setmode ready %d\n", cc);
                                        break;
+                               case 0x10:
+
+                                       dev->chn_ready |= (1 << cc);
+                                       if ((dev->chn_ready & 0x0f) != 0x0f)
+                                               break;
+                                       /* all channels ready */
+                                       printk(KERN_INFO "s2255: fw loaded\n");
+                                       atomic_set(&dev->fw_data->fw_state,
+                                                  S2255_FW_SUCCESS);
+                                       wake_up(&dev->fw_data->wait_fw);
+                                       break;
+                               default:
+                                       printk(KERN_INFO "s2255 unknwn resp\n");
                                }
+                       default:
                                pdata++;
+                               break;
                        }
-                       if (bsync == 0)
-                               return -EINVAL;
-               } else {
-                       u32 *pword;
-                       u32 payload;
-                       int cc;
-                       dbgsync = 0;
-                       bsync = 1;
-                       pword = (u32 *) pipe_info->transfer_buffer;
-                       cc = pword[1];
-
-                       if (cc >= MAX_CHANNELS) {
-                               printk("invalid channel found. "
-                                       "throwing out data!\n");
-                               return -EINVAL;
-                       }
-                       dev->cc = G_chnmap[cc];
-                       payload = pword[2];
-                       if (payload != dev->req_image_size[dev->cc]) {
-                               dprintk(1, "[%d][%d]unexpected payload: %d"
-                                       "required: %lu \n", cc, dev->cc,
-                                       payload, dev->req_image_size[dev->cc]);
-                               dev->bad_payload[dev->cc]++;
-                               /* discard the bad frame */
-                               return -EINVAL;
-                       }
-
-               }
-       }
-       /* search done.  now find out if should be acquiring
-          on this channel */
-       if (!dev->b_acquire[dev->cc]) {
-               frm->ulState = 0;
-               return -EINVAL;
+                       if (bframe)
+                               break;
+               } /* for */
+               if (!bframe)
+                       return -EINVAL;
        }
 
+
        idx = dev->cur_frame[dev->cc];
        frm = &dev->buffer[dev->cc].frame[idx];
 
-       if (frm->ulState == 0) {
-               frm->ulState = 1;
-               frm->cur_size = 0;
-       } else if (frm->ulState == 2) {
-               /* system frame ring buffer overrun */
-               dprintk(2, "sys frame overrun.  overwriting frame %d %d\n",
-                       dev->cc, idx);
-               frm->ulState = 1;
-               frm->cur_size = 0;
+       /* search done.  now find out if should be acquiring on this channel */
+       if (!dev->b_acquire[dev->cc]) {
+               /* we found a frame, but this channel is turned off */
+               frm->ulState = S2255_READ_IDLE;
+               return -EINVAL;
        }
 
-       if (bsync) {
-               /* skip the marker 512 bytes (and offset if out of sync) */
-               psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE;
-       } else {
-               psrc = (u8 *)pipe_info->transfer_buffer;
+       if (frm->ulState == S2255_READ_IDLE) {
+               frm->ulState = S2255_READ_FRAME;
+               frm->cur_size = 0;
        }
 
+       /* skip the marker 512 bytes (and offset if out of sync) */
+       psrc = (u8 *)pipe_info->transfer_buffer + offset;
+
+
        if (frm->lpvbits == NULL) {
                dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
                        frm, dev, dev->cc, idx);
@@ -1911,33 +1990,20 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
 
        pdest = frm->lpvbits + frm->cur_size;
 
-       if (bsync) {
-               copy_size =
-                   (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE;
-               if (copy_size > pipe_info->cur_transfer_size) {
-                       printk("invalid copy size, overflow!\n");
-                       return -ENOMEM;
-               }
-       } else {
-               copy_size = pipe_info->cur_transfer_size;
-       }
+       copy_size = (pipe_info->cur_transfer_size - offset);
 
-       cur_size = frm->cur_size;
-       size = dev->req_image_size[dev->cc];
+       size = dev->pkt_size[dev->cc] - PREFIX_SIZE;
 
-       if ((copy_size + cur_size) > size) {
-               copy_size = size - cur_size;
-               btrunc = 1;
-       }
+       /* sanity check on pdest */
+       if ((copy_size + frm->cur_size) < dev->req_image_size[dev->cc])
+               memcpy(pdest, psrc, copy_size);
 
-       memcpy(pdest, psrc, copy_size);
-       cur_size += copy_size;
        frm->cur_size += copy_size;
-       dprintk(50, "cur_size size %lu size %lu \n", cur_size, size);
+       dprintk(4, "cur_size size %lu size %lu \n", frm->cur_size, size);
+
+       if (frm->cur_size >= size) {
 
-       if (cur_size >= (size - PREFIX_SIZE)) {
                u32 cc = dev->cc;
-               frm->ulState = 2;
                dprintk(2, "****************[%d]Buffer[%d]full*************\n",
                        cc, idx);
                dev->last_frame[cc] = dev->cur_frame[cc];
@@ -1946,16 +2012,13 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
                if ((dev->cur_frame[cc] == SYS_FRAMES) ||
                    (dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
                        dev->cur_frame[cc] = 0;
-
-               /* signal the semaphore for this channel */
+               /* frame ready */
                if (dev->b_acquire[cc])
-                       s2255_got_frame(dev, cc);
+                       s2255_got_frame(dev, cc, dev->jpg_size[cc]);
                dev->frame_count[cc]++;
-       }
-       /* frame was truncated */
-       if (btrunc) {
-               /* return more data to process */
-               return EAGAIN;
+               frm->ulState = S2255_READ_IDLE;
+               frm->cur_size = 0;
+
        }
        /* done successfully */
        return 0;
@@ -1974,8 +2037,8 @@ static void s2255_read_video_callback(struct s2255_dev *dev,
        }
        /* otherwise copy to the system buffers */
        res = save_frame(dev, pipe_info);
-       if (res == EAGAIN)
-               save_frame(dev, pipe_info);
+       if (res != 0)
+               dprintk(4, "s2255: read callback failed\n");
 
        dprintk(50, "callback read video done\n");
        return;
@@ -2095,11 +2158,9 @@ static int s2255_board_init(struct s2255_dev *dev)
 
                memset(pipe, 0, sizeof(*pipe));
                pipe->dev = dev;
-               pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
-               pipe->max_transfer_size = MAX_PIPE_USBBLOCK;
+               pipe->cur_transfer_size = S2255_USB_XFER_SIZE;
+               pipe->max_transfer_size = S2255_USB_XFER_SIZE;
 
-               if (pipe->cur_transfer_size > pipe->max_transfer_size)
-                       pipe->cur_transfer_size = pipe->max_transfer_size;
                pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
                                                GFP_KERNEL);
                if (pipe->transfer_buffer == NULL) {
@@ -2119,6 +2180,7 @@ static int s2255_board_init(struct s2255_dev *dev)
        for (j = 0; j < MAX_CHANNELS; j++) {
                dev->b_acquire[j] = 0;
                dev->mode[j] = mode_def;
+               dev->jc[j].quality = S2255_DEF_JPEG_QUAL;
                dev->cur_fmt[j] = &formats[0];
                dev->mode[j].restart = 1;
                dev->req_image_size[j] = get_transfer_size(&mode_def);
@@ -2323,7 +2385,7 @@ static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
        kfree(buffer);
        dev->b_acquire[chn] = 0;
 
-       return 0;
+       return res;
 }
 
 static void s2255_stop_readpipe(struct s2255_dev *dev)
@@ -2359,8 +2421,10 @@ static void s2255_stop_readpipe(struct s2255_dev *dev)
        return;
 }
 
-static void s2255_fwload_start(struct s2255_dev *dev)
+static void s2255_fwload_start(struct s2255_dev *dev, int reset)
 {
+       if (reset)
+               s2255_reset_dsppower(dev);
        dev->fw_data->fw_size = dev->fw_data->fw->size;
        atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
        memcpy(dev->fw_data->pfw_data,
@@ -2383,6 +2447,8 @@ static int s2255_probe(struct usb_interface *interface,
        struct usb_endpoint_descriptor *endpoint;
        int i;
        int retval = -ENOMEM;
+       __le32 *pdata;
+       int fw_size;
 
        dprintk(2, "s2255: probe\n");
 
@@ -2437,6 +2503,8 @@ static int s2255_probe(struct usb_interface *interface,
        dev->timer.data = (unsigned long)dev->fw_data;
 
        init_waitqueue_head(&dev->fw_data->wait_fw);
+       for (i = 0; i < MAX_CHANNELS; i++)
+               init_waitqueue_head(&dev->wait_setmode[i]);
 
 
        dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -2456,16 +2524,30 @@ static int s2255_probe(struct usb_interface *interface,
                printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
                goto error;
        }
+       /* check the firmware is valid */
+       fw_size = dev->fw_data->fw->size;
+       pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
 
+       if (*pdata != S2255_FW_MARKER) {
+               printk(KERN_INFO "Firmware invalid.\n");
+               retval = -ENODEV;
+               goto error;
+       } else {
+               /* make sure firmware is the latest */
+               __le32 *pRel;
+               pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4];
+               printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel);
+       }
        /* loads v4l specific */
        s2255_probe_v4l(dev);
+       usb_reset_device(dev->udev);
        /* load 2255 board specific */
        s2255_board_init(dev);
 
        dprintk(4, "before probe done %p\n", dev);
        spin_lock_init(&dev->slock);
 
-       s2255_fwload_start(dev);
+       s2255_fwload_start(dev, 0);
        dev_info(&interface->dev, "Sensoray 2255 detected\n");
        return 0;
 error:
@@ -2476,14 +2558,30 @@ error:
 static void s2255_disconnect(struct usb_interface *interface)
 {
        struct s2255_dev *dev = NULL;
+       int i;
        dprintk(1, "s2255: disconnect interface %p\n", interface);
        dev = usb_get_intfdata(interface);
+
+       /*
+        * wake up any of the timers to allow open_lock to be
+        * acquired sooner
+        */
+       atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
+       wake_up(&dev->fw_data->wait_fw);
+       for (i = 0; i < MAX_CHANNELS; i++) {
+               dev->setmode_ready[i] = 1;
+               wake_up(&dev->wait_setmode[i]);
+       }
+
+       mutex_lock(&dev->open_lock);
+       usb_set_intfdata(interface, NULL);
+       mutex_unlock(&dev->open_lock);
+
        if (dev) {
                kref_put(&dev->kref, s2255_destroy);
                dprintk(1, "s2255drv: disconnect\n");
                dev_info(&interface->dev, "s2255usb now disconnected\n");
        }
-       usb_set_intfdata(interface, NULL);
 }
 
 static struct usb_driver s2255_driver = {
index 6ee63e69b36c4d7106fd0b2bcafb0433df47d64b..4a21b8a6a7091a844c98e27b3090fb93f5c3cf9e 100644 (file)
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
-#include "saa5246a.h"
+#include <media/v4l2-i2c-drv-legacy.h>
 
 MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
 MODULE_DESCRIPTION("Philips SAA5246A, SAA5281 Teletext decoder driver");
 MODULE_LICENSE("GPL");
 
-struct saa5246a_device
-{
-       u8     pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
-       int    is_searching[NUM_DAUS];
-       struct i2c_client *client;
-       struct mutex lock;
-};
+#define MAJOR_VERSION 1                /* driver major version number */
+#define MINOR_VERSION 8                /* driver minor version number */
+
+/* Number of DAUs = number of pages that can be searched at the same time. */
+#define NUM_DAUS 4
+
+#define NUM_ROWS_PER_PAGE 40
+
+/* first column is 0 (not 1) */
+#define POS_TIME_START 32
+#define POS_TIME_END 39
+
+#define POS_HEADER_START 7
+#define POS_HEADER_END 31
+
+/* Returns 'true' if the part of the videotext page described with req contains
+   (at least parts of) the time field */
+#define REQ_CONTAINS_TIME(p_req) \
+       ((p_req)->start <= POS_TIME_END && \
+        (p_req)->end   >= POS_TIME_START)
+
+/* Returns 'true' if the part of the videotext page described with req contains
+   (at least parts of) the page header */
+#define REQ_CONTAINS_HEADER(p_req) \
+       ((p_req)->start <= POS_HEADER_END && \
+        (p_req)->end   >= POS_HEADER_START)
+
+/*****************************************************************************/
+/* Mode register numbers of the SAA5246A                                    */
+/*****************************************************************************/
+#define SAA5246A_REGISTER_R0    0
+#define SAA5246A_REGISTER_R1    1
+#define SAA5246A_REGISTER_R2    2
+#define SAA5246A_REGISTER_R3    3
+#define SAA5246A_REGISTER_R4    4
+#define SAA5246A_REGISTER_R5    5
+#define SAA5246A_REGISTER_R6    6
+#define SAA5246A_REGISTER_R7    7
+#define SAA5246A_REGISTER_R8    8
+#define SAA5246A_REGISTER_R9    9
+#define SAA5246A_REGISTER_R10  10
+#define SAA5246A_REGISTER_R11  11
+#define SAA5246A_REGISTER_R11B 11
+
+/* SAA5246A mode registers often autoincrement to the next register.
+   Therefore we use variable argument lists. The following macro indicates
+   the end of a command list. */
+#define COMMAND_END (-1)
+
+/*****************************************************************************/
+/* Contents of the mode registers of the SAA5246A                           */
+/*****************************************************************************/
+/* Register R0 (Advanced Control) */
+#define R0_SELECT_R11                                     0x00
+#define R0_SELECT_R11B                                    0x01
+
+#define R0_PLL_TIME_CONSTANT_LONG                         0x00
+#define R0_PLL_TIME_CONSTANT_SHORT                        0x02
+
+#define R0_ENABLE_nODD_EVEN_OUTPUT                        0x00
+#define R0_DISABLE_nODD_EVEN_OUTPUT                       0x04
+
+#define R0_ENABLE_HDR_POLL                                0x00
+#define R0_DISABLE_HDR_POLL                               0x10
+
+#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00
+#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED       0x20
+
+#define R0_NO_FREE_RUN_PLL                                0x00
+#define R0_FREE_RUN_PLL                                           0x40
+
+#define R0_NO_AUTOMATIC_FASTEXT_PROMPT                    0x00
+#define R0_AUTOMATIC_FASTEXT_PROMPT                       0x80
+
+/* Register R1 (Mode) */
+#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES     0x00
+#define R1_NON_INTERLACED_312_313_LINES                           0x01
+#define R1_NON_INTERLACED_312_312_LINES                           0x02
+#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE          0x03
+#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE         0x07
+
+#define R1_DEW                                            0x00
+#define R1_FULL_FIELD                                     0x08
+
+#define R1_EXTENDED_PACKET_DISABLE                        0x00
+#define R1_EXTENDED_PACKET_ENABLE                         0x10
+
+#define R1_DAUS_ALL_ON                                    0x00
+#define R1_DAUS_ALL_OFF                                           0x20
+
+#define R1_7_BITS_PLUS_PARITY                             0x00
+#define R1_8_BITS_NO_PARITY                               0x40
+
+#define R1_VCS_TO_SCS                                     0x00
+#define R1_NO_VCS_TO_SCS                                  0x80
+
+/* Register R2 (Page request address) */
+#define R2_IN_R3_SELECT_PAGE_HUNDREDS                     0x00
+#define R2_IN_R3_SELECT_PAGE_TENS                         0x01
+#define R2_IN_R3_SELECT_PAGE_UNITS                        0x02
+#define R2_IN_R3_SELECT_HOURS_TENS                        0x03
+#define R2_IN_R3_SELECT_HOURS_UNITS                       0x04
+#define R2_IN_R3_SELECT_MINUTES_TENS                      0x05
+#define R2_IN_R3_SELECT_MINUTES_UNITS                     0x06
+
+#define R2_DAU_0                                          0x00
+#define R2_DAU_1                                          0x10
+#define R2_DAU_2                                          0x20
+#define R2_DAU_3                                          0x30
+
+#define R2_BANK_0                                         0x00
+#define R2_BANK 1                                         0x40
+
+#define R2_HAMMING_CHECK_ON                               0x80
+#define R2_HAMMING_CHECK_OFF                              0x00
+
+/* Register R3 (Page request data) */
+#define R3_PAGE_HUNDREDS_0                                0x00
+#define R3_PAGE_HUNDREDS_1                                0x01
+#define R3_PAGE_HUNDREDS_2                                0x02
+#define R3_PAGE_HUNDREDS_3                                0x03
+#define R3_PAGE_HUNDREDS_4                                0x04
+#define R3_PAGE_HUNDREDS_5                                0x05
+#define R3_PAGE_HUNDREDS_6                                0x06
+#define R3_PAGE_HUNDREDS_7                                0x07
 
-static struct video_device saa_template;       /* Declared near bottom */
+#define R3_HOLD_PAGE                                      0x00
+#define R3_UPDATE_PAGE                                    0x08
 
-/* Addresses to scan */
-static unsigned short normal_i2c[]      = { I2C_ADDRESS, I2C_CLIENT_END };
+#define R3_PAGE_HUNDREDS_DO_NOT_CARE                      0x00
+#define R3_PAGE_HUNDREDS_DO_CARE                          0x10
 
-I2C_CLIENT_INSMOD;
+#define R3_PAGE_TENS_DO_NOT_CARE                          0x00
+#define R3_PAGE_TENS_DO_CARE                              0x10
 
-static struct i2c_client client_template;
+#define R3_PAGE_UNITS_DO_NOT_CARE                         0x00
+#define R3_PAGE_UNITS_DO_CARE                             0x10
 
-static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-       int pgbuf;
-       int err;
-       struct i2c_client *client;
-       struct video_device *vd;
-       struct saa5246a_device *t;
+#define R3_HOURS_TENS_DO_NOT_CARE                         0x00
+#define R3_HOURS_TENS_DO_CARE                             0x10
 
-       printk(KERN_INFO "saa5246a: teletext chip found.\n");
-       client=kmalloc(sizeof(*client), GFP_KERNEL);
-       if(client==NULL)
-               return -ENOMEM;
-       client_template.adapter = adap;
-       client_template.addr = addr;
-       memcpy(client, &client_template, sizeof(*client));
-       t = kzalloc(sizeof(*t), GFP_KERNEL);
-       if(t==NULL)
-       {
-               kfree(client);
-               return -ENOMEM;
-       }
-       strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
-       mutex_init(&t->lock);
+#define R3_HOURS_UNITS_DO_NOT_CARE                        0x00
+#define R3_HOURS_UNITS_DO_CARE                            0x10
 
-       /*
-        *      Now create a video4linux device
-        */
+#define R3_MINUTES_TENS_DO_NOT_CARE                       0x00
+#define R3_MINUTES_TENS_DO_CARE                                   0x10
 
-       vd = video_device_alloc();
-       if(vd==NULL)
-       {
-               kfree(t);
-               kfree(client);
-               return -ENOMEM;
-       }
-       i2c_set_clientdata(client, vd);
-       memcpy(vd, &saa_template, sizeof(*vd));
+#define R3_MINUTES_UNITS_DO_NOT_CARE                      0x00
+#define R3_MINUTES_UNITS_DO_CARE                          0x10
 
-       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
-       {
-               memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
-               t->is_searching[pgbuf] = false;
-       }
-       vd->priv=t;
+/* Register R4 (Display chapter) */
+#define R4_DISPLAY_PAGE_0                                 0x00
+#define R4_DISPLAY_PAGE_1                                 0x01
+#define R4_DISPLAY_PAGE_2                                 0x02
+#define R4_DISPLAY_PAGE_3                                 0x03
+#define R4_DISPLAY_PAGE_4                                 0x04
+#define R4_DISPLAY_PAGE_5                                 0x05
+#define R4_DISPLAY_PAGE_6                                 0x06
+#define R4_DISPLAY_PAGE_7                                 0x07
 
+/* Register R5 (Normal display control) */
+#define R5_PICTURE_INSIDE_BOXING_OFF                      0x00
+#define R5_PICTURE_INSIDE_BOXING_ON                       0x01
 
-       /*
-        *      Register it
-        */
+#define R5_PICTURE_OUTSIDE_BOXING_OFF                     0x00
+#define R5_PICTURE_OUTSIDE_BOXING_ON                      0x02
 
-       if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
-       {
-               kfree(t);
-               kfree(client);
-               video_device_release(vd);
-               return err;
-       }
-       t->client = client;
-       i2c_attach_client(client);
-       return 0;
-}
+#define R5_TEXT_INSIDE_BOXING_OFF                         0x00
+#define R5_TEXT_INSIDE_BOXING_ON                          0x04
 
-/*
- *     We do most of the hard work when we become a device on the i2c.
- */
-static int saa5246a_probe(struct i2c_adapter *adap)
-{
-       if (adap->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adap, &addr_data, saa5246a_attach);
-       return 0;
-}
+#define R5_TEXT_OUTSIDE_BOXING_OFF                        0x00
+#define R5_TEXT_OUTSIDE_BOXING_ON                         0x08
 
-static int saa5246a_detach(struct i2c_client *client)
-{
-       struct video_device *vd = i2c_get_clientdata(client);
-       i2c_detach_client(client);
-       video_unregister_device(vd);
-       kfree(vd->priv);
-       kfree(client);
-       return 0;
-}
+#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF                   0x00
+#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON            0x10
 
-/*
- *     I2C interfaces
- */
+#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF          0x00
+#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON                   0x20
+
+#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF             0x00
+#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON              0x40
+
+#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF            0x00
+#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON             0x80
+
+/* Register R6 (Newsflash display) */
+#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF            0x00
+#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON             0x01
+
+#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF                   0x00
+#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON            0x02
+
+#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF               0x00
+#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON                0x04
+
+#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF              0x00
+#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON               0x08
+
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF  0x00
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON   0x10
+
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
+#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON  0x20
+
+#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF    0x00
+#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON    0x40
+
+#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF   0x00
+#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON    0x80
+
+/* Register R7 (Display mode) */
+#define R7_BOX_OFF_ROW_0                                  0x00
+#define R7_BOX_ON_ROW_0                                           0x01
+
+#define R7_BOX_OFF_ROW_1_TO_23                            0x00
+#define R7_BOX_ON_ROW_1_TO_23                             0x02
+
+#define R7_BOX_OFF_ROW_24                                 0x00
+#define R7_BOX_ON_ROW_24                                  0x04
+
+#define R7_SINGLE_HEIGHT                                  0x00
+#define R7_DOUBLE_HEIGHT                                  0x08
+
+#define R7_TOP_HALF                                       0x00
+#define R7_BOTTOM_HALF                                    0x10
+
+#define R7_REVEAL_OFF                                     0x00
+#define R7_REVEAL_ON                                      0x20
+
+#define R7_CURSER_OFF                                     0x00
+#define R7_CURSER_ON                                      0x40
+
+#define R7_STATUS_BOTTOM                                  0x00
+#define R7_STATUS_TOP                                     0x80
+
+/* Register R8 (Active chapter) */
+#define R8_ACTIVE_CHAPTER_0                               0x00
+#define R8_ACTIVE_CHAPTER_1                               0x01
+#define R8_ACTIVE_CHAPTER_2                               0x02
+#define R8_ACTIVE_CHAPTER_3                               0x03
+#define R8_ACTIVE_CHAPTER_4                               0x04
+#define R8_ACTIVE_CHAPTER_5                               0x05
+#define R8_ACTIVE_CHAPTER_6                               0x06
+#define R8_ACTIVE_CHAPTER_7                               0x07
+
+#define R8_CLEAR_MEMORY                                           0x08
+#define R8_DO_NOT_CLEAR_MEMORY                            0x00
+
+/* Register R9 (Curser row) */
+#define R9_CURSER_ROW_0                                           0x00
+#define R9_CURSER_ROW_1                                           0x01
+#define R9_CURSER_ROW_2                                           0x02
+#define R9_CURSER_ROW_25                                  0x19
+
+/* Register R10 (Curser column) */
+#define R10_CURSER_COLUMN_0                               0x00
+#define R10_CURSER_COLUMN_6                               0x06
+#define R10_CURSER_COLUMN_8                               0x08
+
+/*****************************************************************************/
+/* Row 25 control data in column 0 to 9                                             */
+/*****************************************************************************/
+#define ROW25_COLUMN0_PAGE_UNITS                          0x0F
+
+#define ROW25_COLUMN1_PAGE_TENS                                   0x0F
+
+#define ROW25_COLUMN2_MINUTES_UNITS                       0x0F
 
-static struct i2c_driver i2c_driver_videotext =
+#define ROW25_COLUMN3_MINUTES_TENS                        0x07
+#define ROW25_COLUMN3_DELETE_PAGE                         0x08
+
+#define ROW25_COLUMN4_HOUR_UNITS                          0x0F
+
+#define ROW25_COLUMN5_HOUR_TENS                                   0x03
+#define ROW25_COLUMN5_INSERT_HEADLINE                     0x04
+#define ROW25_COLUMN5_INSERT_SUBTITLE                     0x08
+
+#define ROW25_COLUMN6_SUPPRESS_HEADER                     0x01
+#define ROW25_COLUMN6_UPDATE_PAGE                         0x02
+#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE                0x04
+#define ROW25_COLUMN6_SUPPRESS_DISPLAY                    0x08
+
+#define ROW25_COLUMN7_SERIAL_MODE                         0x01
+#define ROW25_COLUMN7_CHARACTER_SET                       0x0E
+
+#define ROW25_COLUMN8_PAGE_HUNDREDS                       0x07
+#define ROW25_COLUMN8_PAGE_NOT_FOUND                      0x10
+
+#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR               0x20
+
+#define ROW25_COLUMN0_TO_7_HAMMING_ERROR                  0x10
+
+/*****************************************************************************/
+/* Helper macros for extracting page, hour and minute digits                */
+/*****************************************************************************/
+/* BYTE_POS  0 is at row 0, column 0,
+   BYTE_POS  1 is at row 0, column 1,
+   BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40)
+   BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40),
+   ... */
+#define ROW(BYTE_POS)    (BYTE_POS / NUM_ROWS_PER_PAGE)
+#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE)
+
+/*****************************************************************************/
+/* Helper macros for extracting page, hour and minute digits                */
+/*****************************************************************************/
+/* Macros for extracting hundreds, tens and units of a page number which
+   must be in the range 0 ... 0x799.
+   Note that page is coded in hexadecimal, i.e. 0x123 means page 123.
+   page 0x.. means page 8.. */
+#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7)
+#define TENS_OF_PAGE(page)     (((page) / 0x10)  & 0xF)
+#define UNITS_OF_PAGE(page)     ((page) & 0xF)
+
+/* Macros for extracting tens and units of a hour information which
+   must be in the range 0 ... 0x24.
+   Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */
+#define TENS_OF_HOUR(hour)  ((hour) / 0x10)
+#define UNITS_OF_HOUR(hour) ((hour) & 0xF)
+
+/* Macros for extracting tens and units of a minute information which
+   must be in the range 0 ... 0x59.
+   Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */
+#define TENS_OF_MINUTE(minute)  ((minute) / 0x10)
+#define UNITS_OF_MINUTE(minute) ((minute) & 0xF)
+
+#define HOUR_MAX   0x23
+#define MINUTE_MAX 0x59
+#define PAGE_MAX   0x8FF
+
+
+struct saa5246a_device
 {
-       .driver = {
-               .name   = IF_NAME,              /* name */
-       },
-       .id             = I2C_DRIVERID_SAA5249, /* in i2c.h */
-       .attach_adapter = saa5246a_probe,
-       .detach_client  = saa5246a_detach,
+       u8     pgbuf[NUM_DAUS][VTX_VIRTUALSIZE];
+       int    is_searching[NUM_DAUS];
+       struct i2c_client *client;
+       unsigned long in_use;
+       struct mutex lock;
 };
 
-static struct i2c_client client_template = {
-       .driver         = &i2c_driver_videotext,
-       .name           = "(unset)",
-};
+static struct video_device saa_template;       /* Declared near bottom */
+
+/*
+ *     I2C interfaces
+ */
 
 static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data)
 {
@@ -579,8 +807,8 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
 static int do_saa5246a_ioctl(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5246a_device *t=vd->priv;
+       struct saa5246a_device *t = video_drvdata(file);
+
        switch(cmd)
        {
                case VTXIOCGETINFO:
@@ -720,8 +948,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
 static int saa5246a_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5246a_device *t = vd->priv;
+       struct saa5246a_device *t = video_drvdata(file);
        int err;
 
        cmd = vtx_fix_command(cmd);
@@ -733,21 +960,15 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file,
 
 static int saa5246a_open(struct inode *inode, struct file *file)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5246a_device *t = vd->priv;
-       int err;
+       struct saa5246a_device *t = video_drvdata(file);
 
-       err = video_exclusive_open(inode,file);
-       if (err < 0)
-               return err;
+       if (t->client == NULL)
+               return -ENODEV;
 
-       if (t->client==NULL) {
-               err = -ENODEV;
-               goto fail;
-       }
+       if (test_and_set_bit(0, &t->in_use))
+               return -EBUSY;
 
        if (i2c_senddata(t, SAA5246A_REGISTER_R0,
-
                R0_SELECT_R11 |
                R0_PLL_TIME_CONSTANT_LONG |
                R0_ENABLE_nODD_EVEN_OUTPUT |
@@ -773,21 +994,15 @@ static int saa5246a_open(struct inode *inode, struct file *file)
 
                COMMAND_END))
        {
-               err = -EIO;
-               goto fail;
+               clear_bit(0, &t->in_use);
+               return -EIO;
        }
-
        return 0;
-
-fail:
-       video_exclusive_release(inode,file);
-       return err;
 }
 
 static int saa5246a_release(struct inode *inode, struct file *file)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5246a_device *t = vd->priv;
+       struct saa5246a_device *t = video_drvdata(file);
 
        /* Stop all acquisition circuits. */
        i2c_senddata(t, SAA5246A_REGISTER_R1,
@@ -800,26 +1015,10 @@ static int saa5246a_release(struct inode *inode, struct file *file)
                R1_VCS_TO_SCS,
 
                COMMAND_END);
-       video_exclusive_release(inode,file);
+       clear_bit(0, &t->in_use);
        return 0;
 }
 
-static int __init init_saa_5246a (void)
-{
-       printk(KERN_INFO
-               "SAA5246A (or compatible) Teletext decoder driver version %d.%d\n",
-               MAJOR_VERSION, MINOR_VERSION);
-       return i2c_add_driver(&i2c_driver_videotext);
-}
-
-static void __exit cleanup_saa_5246a (void)
-{
-       i2c_del_driver(&i2c_driver_videotext);
-}
-
-module_init(init_saa_5246a);
-module_exit(cleanup_saa_5246a);
-
 static const struct file_operations saa_fops = {
        .owner   = THIS_MODULE,
        .open    = saa5246a_open,
@@ -830,8 +1029,79 @@ static const struct file_operations saa_fops = {
 
 static struct video_device saa_template =
 {
-       .name     = IF_NAME,
+       .name     = "saa5246a",
        .fops     = &saa_fops,
        .release  = video_device_release,
        .minor    = -1,
 };
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int saa5246a_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int pgbuf;
+       int err;
+       struct video_device *vd;
+       struct saa5246a_device *t;
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
+       v4l_info(client, "VideoText version %d.%d\n",
+                       MAJOR_VERSION, MINOR_VERSION);
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (t == NULL)
+               return -ENOMEM;
+       mutex_init(&t->lock);
+
+       /* Now create a video4linux device */
+       vd = video_device_alloc();
+       if (vd == NULL) {
+               kfree(t);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(client, vd);
+       memcpy(vd, &saa_template, sizeof(*vd));
+
+       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
+               memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0]));
+               t->is_searching[pgbuf] = false;
+       }
+       video_set_drvdata(vd, t);
+
+       /* Register it */
+       err = video_register_device(vd, VFL_TYPE_VTX, -1);
+       if (err < 0) {
+               kfree(t);
+               video_device_release(vd);
+               return err;
+       }
+       t->client = client;
+       return 0;
+}
+
+static int saa5246a_remove(struct i2c_client *client)
+{
+       struct video_device *vd = i2c_get_clientdata(client);
+
+       video_unregister_device(vd);
+       kfree(video_get_drvdata(vd));
+       return 0;
+}
+
+static const struct i2c_device_id saa5246a_id[] = {
+       { "saa5246a", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, saa5246a_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "saa5246a",
+       .driverid = I2C_DRIVERID_SAA5249,
+       .probe = saa5246a_probe,
+       .remove = saa5246a_remove,
+       .id_table = saa5246a_id,
+};
diff --git a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h
deleted file mode 100644 (file)
index 64394c0..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
-   Driver for the SAA5246A or SAA5281 Teletext (=Videotext) decoder chips from
-   Philips.
-
-   Copyright (C) 2004 Michael Geng (linux@MichaelGeng.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-#ifndef __SAA5246A_H__
-#define __SAA5246A_H__
-
-#define MAJOR_VERSION 1                /* driver major version number */
-#define MINOR_VERSION 8                /* driver minor version number */
-
-#define IF_NAME "SAA5246A"
-
-#define I2C_ADDRESS 17
-
-/* Number of DAUs = number of pages that can be searched at the same time. */
-#define NUM_DAUS 4
-
-#define NUM_ROWS_PER_PAGE 40
-
-/* first column is 0 (not 1) */
-#define POS_TIME_START 32
-#define POS_TIME_END 39
-
-#define POS_HEADER_START 7
-#define POS_HEADER_END 31
-
-/* Returns 'true' if the part of the videotext page described with req contains
-   (at least parts of) the time field */
-#define REQ_CONTAINS_TIME(p_req) \
-       ((p_req)->start <= POS_TIME_END && \
-        (p_req)->end   >= POS_TIME_START)
-
-/* Returns 'true' if the part of the videotext page described with req contains
-   (at least parts of) the page header */
-#define REQ_CONTAINS_HEADER(p_req) \
-       ((p_req)->start <= POS_HEADER_END && \
-        (p_req)->end   >= POS_HEADER_START)
-
-/*****************************************************************************/
-/* Mode register numbers of the SAA5246A                                    */
-/*****************************************************************************/
-#define SAA5246A_REGISTER_R0    0
-#define SAA5246A_REGISTER_R1    1
-#define SAA5246A_REGISTER_R2    2
-#define SAA5246A_REGISTER_R3    3
-#define SAA5246A_REGISTER_R4    4
-#define SAA5246A_REGISTER_R5    5
-#define SAA5246A_REGISTER_R6    6
-#define SAA5246A_REGISTER_R7    7
-#define SAA5246A_REGISTER_R8    8
-#define SAA5246A_REGISTER_R9    9
-#define SAA5246A_REGISTER_R10  10
-#define SAA5246A_REGISTER_R11  11
-#define SAA5246A_REGISTER_R11B 11
-
-/* SAA5246A mode registers often autoincrement to the next register.
-   Therefore we use variable argument lists. The following macro indicates
-   the end of a command list. */
-#define COMMAND_END (- 1)
-
-/*****************************************************************************/
-/* Contents of the mode registers of the SAA5246A                           */
-/*****************************************************************************/
-/* Register R0 (Advanced Control) */
-#define R0_SELECT_R11                                     0x00
-#define R0_SELECT_R11B                                    0x01
-
-#define R0_PLL_TIME_CONSTANT_LONG                         0x00
-#define R0_PLL_TIME_CONSTANT_SHORT                        0x02
-
-#define R0_ENABLE_nODD_EVEN_OUTPUT                        0x00
-#define R0_DISABLE_nODD_EVEN_OUTPUT                       0x04
-
-#define R0_ENABLE_HDR_POLL                                0x00
-#define R0_DISABLE_HDR_POLL                               0x10
-
-#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00
-#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED       0x20
-
-#define R0_NO_FREE_RUN_PLL                                0x00
-#define R0_FREE_RUN_PLL                                           0x40
-
-#define R0_NO_AUTOMATIC_FASTEXT_PROMPT                    0x00
-#define R0_AUTOMATIC_FASTEXT_PROMPT                       0x80
-
-/* Register R1 (Mode) */
-#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES     0x00
-#define R1_NON_INTERLACED_312_313_LINES                           0x01
-#define R1_NON_INTERLACED_312_312_LINES                           0x02
-#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE          0x03
-#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE         0x07
-
-#define R1_DEW                                            0x00
-#define R1_FULL_FIELD                                     0x08
-
-#define R1_EXTENDED_PACKET_DISABLE                        0x00
-#define R1_EXTENDED_PACKET_ENABLE                         0x10
-
-#define R1_DAUS_ALL_ON                                    0x00
-#define R1_DAUS_ALL_OFF                                           0x20
-
-#define R1_7_BITS_PLUS_PARITY                             0x00
-#define R1_8_BITS_NO_PARITY                               0x40
-
-#define R1_VCS_TO_SCS                                     0x00
-#define R1_NO_VCS_TO_SCS                                  0x80
-
-/* Register R2 (Page request address) */
-#define R2_IN_R3_SELECT_PAGE_HUNDREDS                     0x00
-#define R2_IN_R3_SELECT_PAGE_TENS                         0x01
-#define R2_IN_R3_SELECT_PAGE_UNITS                        0x02
-#define R2_IN_R3_SELECT_HOURS_TENS                        0x03
-#define R2_IN_R3_SELECT_HOURS_UNITS                       0x04
-#define R2_IN_R3_SELECT_MINUTES_TENS                      0x05
-#define R2_IN_R3_SELECT_MINUTES_UNITS                     0x06
-
-#define R2_DAU_0                                          0x00
-#define R2_DAU_1                                          0x10
-#define R2_DAU_2                                          0x20
-#define R2_DAU_3                                          0x30
-
-#define R2_BANK_0                                         0x00
-#define R2_BANK 1                                         0x40
-
-#define R2_HAMMING_CHECK_ON                               0x80
-#define R2_HAMMING_CHECK_OFF                              0x00
-
-/* Register R3 (Page request data) */
-#define R3_PAGE_HUNDREDS_0                                0x00
-#define R3_PAGE_HUNDREDS_1                                0x01
-#define R3_PAGE_HUNDREDS_2                                0x02
-#define R3_PAGE_HUNDREDS_3                                0x03
-#define R3_PAGE_HUNDREDS_4                                0x04
-#define R3_PAGE_HUNDREDS_5                                0x05
-#define R3_PAGE_HUNDREDS_6                                0x06
-#define R3_PAGE_HUNDREDS_7                                0x07
-
-#define R3_HOLD_PAGE                                      0x00
-#define R3_UPDATE_PAGE                                    0x08
-
-#define R3_PAGE_HUNDREDS_DO_NOT_CARE                      0x00
-#define R3_PAGE_HUNDREDS_DO_CARE                          0x10
-
-#define R3_PAGE_TENS_DO_NOT_CARE                          0x00
-#define R3_PAGE_TENS_DO_CARE                              0x10
-
-#define R3_PAGE_UNITS_DO_NOT_CARE                         0x00
-#define R3_PAGE_UNITS_DO_CARE                             0x10
-
-#define R3_HOURS_TENS_DO_NOT_CARE                         0x00
-#define R3_HOURS_TENS_DO_CARE                             0x10
-
-#define R3_HOURS_UNITS_DO_NOT_CARE                        0x00
-#define R3_HOURS_UNITS_DO_CARE                            0x10
-
-#define R3_MINUTES_TENS_DO_NOT_CARE                       0x00
-#define R3_MINUTES_TENS_DO_CARE                                   0x10
-
-#define R3_MINUTES_UNITS_DO_NOT_CARE                      0x00
-#define R3_MINUTES_UNITS_DO_CARE                          0x10
-
-/* Register R4 (Display chapter) */
-#define R4_DISPLAY_PAGE_0                                 0x00
-#define R4_DISPLAY_PAGE_1                                 0x01
-#define R4_DISPLAY_PAGE_2                                 0x02
-#define R4_DISPLAY_PAGE_3                                 0x03
-#define R4_DISPLAY_PAGE_4                                 0x04
-#define R4_DISPLAY_PAGE_5                                 0x05
-#define R4_DISPLAY_PAGE_6                                 0x06
-#define R4_DISPLAY_PAGE_7                                 0x07
-
-/* Register R5 (Normal display control) */
-#define R5_PICTURE_INSIDE_BOXING_OFF                      0x00
-#define R5_PICTURE_INSIDE_BOXING_ON                       0x01
-
-#define R5_PICTURE_OUTSIDE_BOXING_OFF                     0x00
-#define R5_PICTURE_OUTSIDE_BOXING_ON                      0x02
-
-#define R5_TEXT_INSIDE_BOXING_OFF                         0x00
-#define R5_TEXT_INSIDE_BOXING_ON                          0x04
-
-#define R5_TEXT_OUTSIDE_BOXING_OFF                        0x00
-#define R5_TEXT_OUTSIDE_BOXING_ON                         0x08
-
-#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF                   0x00
-#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON            0x10
-
-#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF          0x00
-#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON                   0x20
-
-#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF             0x00
-#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON              0x40
-
-#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF            0x00
-#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON             0x80
-
-/* Register R6 (Newsflash display) */
-#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF            0x00
-#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON             0x01
-
-#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF                   0x00
-#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON            0x02
-
-#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF               0x00
-#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON                0x04
-
-#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF              0x00
-#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON               0x08
-
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF  0x00
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON   0x10
-
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00
-#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON  0x20
-
-#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF    0x00
-#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON    0x40
-
-#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF   0x00
-#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON    0x80
-
-/* Register R7 (Display mode) */
-#define R7_BOX_OFF_ROW_0                                  0x00
-#define R7_BOX_ON_ROW_0                                           0x01
-
-#define R7_BOX_OFF_ROW_1_TO_23                            0x00
-#define R7_BOX_ON_ROW_1_TO_23                             0x02
-
-#define R7_BOX_OFF_ROW_24                                 0x00
-#define R7_BOX_ON_ROW_24                                  0x04
-
-#define R7_SINGLE_HEIGHT                                  0x00
-#define R7_DOUBLE_HEIGHT                                  0x08
-
-#define R7_TOP_HALF                                       0x00
-#define R7_BOTTOM_HALF                                    0x10
-
-#define R7_REVEAL_OFF                                     0x00
-#define R7_REVEAL_ON                                      0x20
-
-#define R7_CURSER_OFF                                     0x00
-#define R7_CURSER_ON                                      0x40
-
-#define R7_STATUS_BOTTOM                                  0x00
-#define R7_STATUS_TOP                                     0x80
-
-/* Register R8 (Active chapter) */
-#define R8_ACTIVE_CHAPTER_0                               0x00
-#define R8_ACTIVE_CHAPTER_1                               0x01
-#define R8_ACTIVE_CHAPTER_2                               0x02
-#define R8_ACTIVE_CHAPTER_3                               0x03
-#define R8_ACTIVE_CHAPTER_4                               0x04
-#define R8_ACTIVE_CHAPTER_5                               0x05
-#define R8_ACTIVE_CHAPTER_6                               0x06
-#define R8_ACTIVE_CHAPTER_7                               0x07
-
-#define R8_CLEAR_MEMORY                                           0x08
-#define R8_DO_NOT_CLEAR_MEMORY                            0x00
-
-/* Register R9 (Curser row) */
-#define R9_CURSER_ROW_0                                           0x00
-#define R9_CURSER_ROW_1                                           0x01
-#define R9_CURSER_ROW_2                                           0x02
-#define R9_CURSER_ROW_25                                  0x19
-
-/* Register R10 (Curser column) */
-#define R10_CURSER_COLUMN_0                               0x00
-#define R10_CURSER_COLUMN_6                               0x06
-#define R10_CURSER_COLUMN_8                               0x08
-
-/*****************************************************************************/
-/* Row 25 control data in column 0 to 9                                             */
-/*****************************************************************************/
-#define ROW25_COLUMN0_PAGE_UNITS                          0x0F
-
-#define ROW25_COLUMN1_PAGE_TENS                                   0x0F
-
-#define ROW25_COLUMN2_MINUTES_UNITS                       0x0F
-
-#define ROW25_COLUMN3_MINUTES_TENS                        0x07
-#define ROW25_COLUMN3_DELETE_PAGE                         0x08
-
-#define ROW25_COLUMN4_HOUR_UNITS                          0x0F
-
-#define ROW25_COLUMN5_HOUR_TENS                                   0x03
-#define ROW25_COLUMN5_INSERT_HEADLINE                     0x04
-#define ROW25_COLUMN5_INSERT_SUBTITLE                     0x08
-
-#define ROW25_COLUMN6_SUPPRESS_HEADER                     0x01
-#define ROW25_COLUMN6_UPDATE_PAGE                         0x02
-#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE                0x04
-#define ROW25_COLUMN6_SUPPRESS_DISPLAY                    0x08
-
-#define ROW25_COLUMN7_SERIAL_MODE                         0x01
-#define ROW25_COLUMN7_CHARACTER_SET                       0x0E
-
-#define ROW25_COLUMN8_PAGE_HUNDREDS                       0x07
-#define ROW25_COLUMN8_PAGE_NOT_FOUND                      0x10
-
-#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR               0x20
-
-#define ROW25_COLUMN0_TO_7_HAMMING_ERROR                  0x10
-
-/*****************************************************************************/
-/* Helper macros for extracting page, hour and minute digits                */
-/*****************************************************************************/
-/* BYTE_POS  0 is at row 0, column 0,
-   BYTE_POS  1 is at row 0, column 1,
-   BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40)
-   BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40),
-   ... */
-#define ROW(BYTE_POS)    (BYTE_POS / NUM_ROWS_PER_PAGE)
-#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE)
-
-/*****************************************************************************/
-/* Helper macros for extracting page, hour and minute digits                */
-/*****************************************************************************/
-/* Macros for extracting hundreds, tens and units of a page number which
-   must be in the range 0 ... 0x799.
-   Note that page is coded in hexadecimal, i.e. 0x123 means page 123.
-   page 0x.. means page 8.. */
-#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7)
-#define TENS_OF_PAGE(page)     (((page) / 0x10)  & 0xF)
-#define UNITS_OF_PAGE(page)     ((page) & 0xF)
-
-/* Macros for extracting tens and units of a hour information which
-   must be in the range 0 ... 0x24.
-   Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */
-#define TENS_OF_HOUR(hour)  ((hour) / 0x10)
-#define UNITS_OF_HOUR(hour) ((hour) & 0xF)
-
-/* Macros for extracting tens and units of a minute information which
-   must be in the range 0 ... 0x59.
-   Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */
-#define TENS_OF_MINUTE(minute)  ((minute) / 0x10)
-#define UNITS_OF_MINUTE(minute) ((minute) & 0xF)
-
-#define HOUR_MAX   0x23
-#define MINUTE_MAX 0x59
-#define PAGE_MAX   0x8FF
-
-#endif  /* __SAA5246A_H__ */
index 0d639738d4e68044f4fa651b97d35573b820da83..3bb959c25d9d5724e720cec199538d609d340073 100644 (file)
@@ -15,8 +15,6 @@
  *
  *     Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de>
  *
- * $Id: saa5249.c,v 1.1 1998/03/30 22:23:23 alan Exp $
- *
  *     Derived From
  *
  * vtx.c:
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <stdarg.h>
 #include <linux/i2c.h>
+#include <linux/smp_lock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <linux/mutex.h>
-
+#include <media/v4l2-i2c-drv-legacy.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
+MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
+MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver");
+MODULE_LICENSE("GPL");
 
 #define VTX_VER_MAJ 1
 #define VTX_VER_MIN 8
 
 
-
 #define NUM_DAUS 4
 #define NUM_BUFS 8
-#define IF_NAME "SAA5249"
 
 static const int disp_modes[8][3] =
 {
@@ -109,6 +102,7 @@ struct saa5249_device
        int disp_mode;
        int virtual_mode;
        struct i2c_client *client;
+       unsigned long in_use;
        struct mutex lock;
 };
 
@@ -123,125 +117,8 @@ struct saa5249_device
 
 #define VTX_DEV_MINOR 0
 
-/* General defines and debugging support */
-
-#define RESCHED do { cond_resched(); } while(0)
-
 static struct video_device saa_template;       /* Declared near bottom */
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
-
-I2C_CLIENT_INSMOD;
-
-static struct i2c_client client_template;
-
-static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-       int pgbuf;
-       int err;
-       struct i2c_client *client;
-       struct video_device *vd;
-       struct saa5249_device *t;
-
-       printk(KERN_INFO "saa5249: teletext chip found.\n");
-       client=kmalloc(sizeof(*client), GFP_KERNEL);
-       if(client==NULL)
-               return -ENOMEM;
-       client_template.adapter = adap;
-       client_template.addr = addr;
-       memcpy(client, &client_template, sizeof(*client));
-       t = kzalloc(sizeof(*t), GFP_KERNEL);
-       if(t==NULL)
-       {
-               kfree(client);
-               return -ENOMEM;
-       }
-       strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
-       mutex_init(&t->lock);
-
-       /*
-        *      Now create a video4linux device
-        */
-
-       vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
-       if(vd==NULL)
-       {
-               kfree(t);
-               kfree(client);
-               return -ENOMEM;
-       }
-       i2c_set_clientdata(client, vd);
-       memcpy(vd, &saa_template, sizeof(*vd));
-
-       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
-       {
-               memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
-               memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
-               memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
-               t->vdau[pgbuf].expire = 0;
-               t->vdau[pgbuf].clrfound = true;
-               t->vdau[pgbuf].stopped = true;
-               t->is_searching[pgbuf] = false;
-       }
-       vd->priv=t;
-
-
-       /*
-        *      Register it
-        */
-
-       if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0)
-       {
-               kfree(t);
-               kfree(vd);
-               kfree(client);
-               return err;
-       }
-       t->client = client;
-       i2c_attach_client(client);
-       return 0;
-}
-
-/*
- *     We do most of the hard work when we become a device on the i2c.
- */
-
-static int saa5249_probe(struct i2c_adapter *adap)
-{
-       if (adap->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adap, &addr_data, saa5249_attach);
-       return 0;
-}
-
-static int saa5249_detach(struct i2c_client *client)
-{
-       struct video_device *vd = i2c_get_clientdata(client);
-       i2c_detach_client(client);
-       video_unregister_device(vd);
-       kfree(vd->priv);
-       kfree(vd);
-       kfree(client);
-       return 0;
-}
-
-/* new I2C driver support */
-
-static struct i2c_driver i2c_driver_videotext =
-{
-       .driver = {
-               .name   = IF_NAME,              /* name */
-       },
-       .id             = I2C_DRIVERID_SAA5249, /* in i2c.h */
-       .attach_adapter = saa5249_probe,
-       .detach_client  = saa5249_detach,
-};
-
-static struct i2c_client client_template = {
-       .driver         = &i2c_driver_videotext,
-       .name           = "(unset)",
-};
-
 /*
  *     Wait the given number of jiffies (10ms). This calls the scheduler, so the actual
  *     delay may be longer.
@@ -275,7 +152,7 @@ static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
        buf[0] = reg;
        memcpy(buf+1, data, count);
 
-       if(i2c_master_send(t->client, buf, count+1)==count+1)
+       if (i2c_master_send(t->client, buf, count + 1) == count + 1)
                return 0;
        return -1;
 }
@@ -317,246 +194,236 @@ static int do_saa5249_ioctl(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg)
 {
        static int virtual_mode = false;
-       struct video_device *vd = video_devdata(file);
-       struct saa5249_device *t=vd->priv;
+       struct saa5249_device *t = video_drvdata(file);
 
-       switch(cmd)
+       switch (cmd) {
+       case VTXIOCGETINFO:
        {
-               case VTXIOCGETINFO:
-               {
-                       vtx_info_t *info = arg;
-                       info->version_major = VTX_VER_MAJ;
-                       info->version_minor = VTX_VER_MIN;
-                       info->numpages = NUM_DAUS;
-                       /*info->cct_type = CCT_TYPE;*/
-                       return 0;
-               }
+               vtx_info_t *info = arg;
+               info->version_major = VTX_VER_MAJ;
+               info->version_minor = VTX_VER_MIN;
+               info->numpages = NUM_DAUS;
+               /*info->cct_type = CCT_TYPE;*/
+               return 0;
+       }
 
-               case VTXIOCCLRPAGE:
-               {
-                       vtx_pagereq_t *req = arg;
+       case VTXIOCCLRPAGE:
+       {
+               vtx_pagereq_t *req = arg;
 
-                       if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
-                               return -EINVAL;
-                       memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
-                       t->vdau[req->pgbuf].clrfound = true;
-                       return 0;
-               }
+               if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+                       return -EINVAL;
+               memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
+               t->vdau[req->pgbuf].clrfound = true;
+               return 0;
+       }
 
-               case VTXIOCCLRFOUND:
-               {
-                       vtx_pagereq_t *req = arg;
+       case VTXIOCCLRFOUND:
+       {
+               vtx_pagereq_t *req = arg;
 
-                       if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
-                               return -EINVAL;
-                       t->vdau[req->pgbuf].clrfound = true;
-                       return 0;
-               }
+               if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+                       return -EINVAL;
+               t->vdau[req->pgbuf].clrfound = true;
+               return 0;
+       }
 
-               case VTXIOCPAGEREQ:
-               {
-                       vtx_pagereq_t *req = arg;
-                       if (!(req->pagemask & PGMASK_PAGE))
-                               req->page = 0;
-                       if (!(req->pagemask & PGMASK_HOUR))
-                               req->hour = 0;
-                       if (!(req->pagemask & PGMASK_MINUTE))
-                               req->minute = 0;
-                       if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */
-                               return -EINVAL;
-                       req->page &= 0x7ff;
-                       if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f ||
-                               req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
-                               return -EINVAL;
-                       t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100);
-                       t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf);
-                       t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf);
-                       t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10);
-                       t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
-                       t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
-                       t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
-                       t->vdau[req->pgbuf].stopped = false;
-                       t->vdau[req->pgbuf].clrfound = true;
-                       t->is_searching[req->pgbuf] = true;
-                       return 0;
-               }
+       case VTXIOCPAGEREQ:
+       {
+               vtx_pagereq_t *req = arg;
+               if (!(req->pagemask & PGMASK_PAGE))
+                       req->page = 0;
+               if (!(req->pagemask & PGMASK_HOUR))
+                       req->hour = 0;
+               if (!(req->pagemask & PGMASK_MINUTE))
+                       req->minute = 0;
+               if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */
+                       return -EINVAL;
+               req->page &= 0x7ff;
+               if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f ||
+                       req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+                       return -EINVAL;
+               t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100);
+               t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf);
+               t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf);
+               t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10);
+               t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
+               t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
+               t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
+               t->vdau[req->pgbuf].stopped = false;
+               t->vdau[req->pgbuf].clrfound = true;
+               t->is_searching[req->pgbuf] = true;
+               return 0;
+       }
 
-               case VTXIOCGETSTAT:
-               {
-                       vtx_pagereq_t *req = arg;
-                       u8 infobits[10];
-                       vtx_pageinfo_t info;
-                       int a;
-
-                       if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
-                               return -EINVAL;
-                       if (!t->vdau[req->pgbuf].stopped)
-                       {
-                               if (i2c_senddata(t, 2, 0, -1) ||
-                                       i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
-                                       i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
-                                       i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) ||
-                                       i2c_senddata(t, 8, 0, 25, 0, -1))
-                                       return -EIO;
-                               jdelay(PAGE_WAIT);
-                               if (i2c_getdata(t, 10, infobits))
-                                       return -EIO;
+       case VTXIOCGETSTAT:
+       {
+               vtx_pagereq_t *req = arg;
+               u8 infobits[10];
+               vtx_pageinfo_t info;
+               int a;
+
+               if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+                       return -EINVAL;
+               if (!t->vdau[req->pgbuf].stopped) {
+                       if (i2c_senddata(t, 2, 0, -1) ||
+                               i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
+                               i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
+                               i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) ||
+                               i2c_senddata(t, 8, 0, 25, 0, -1))
+                               return -EIO;
+                       jdelay(PAGE_WAIT);
+                       if (i2c_getdata(t, 10, infobits))
+                               return -EIO;
 
-                               if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) &&   /* check FOUND-bit */
-                                       (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
-                                       time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
-                               {               /* check if new page arrived */
-                                       if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
-                                               i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf))
+                       if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) &&   /* check FOUND-bit */
+                               (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
+                               time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
+                       {               /* check if new page arrived */
+                               if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
+                                       i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf))
+                                       return -EIO;
+                               t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
+                               memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
+                               if (t->virtual_mode) {
+                                       /* Packet X/24 */
+                                       if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
+                                               i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40))
+                                               return -EIO;
+                                       /* Packet X/27/0 */
+                                       if (i2c_senddata(t, 8, 0, 0x21, 0, -1) ||
+                                               i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40))
+                                               return -EIO;
+                                       /* Packet 8/30/0...8/30/15
+                                        * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
+                                        *        so we should undo this here.
+                                        */
+                                       if (i2c_senddata(t, 8, 0, 0x22, 0, -1) ||
+                                               i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
                                                return -EIO;
-                                       t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
-                                       memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
-                                       if (t->virtual_mode)
-                                       {
-                                               /* Packet X/24 */
-                                               if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
-                                                       i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40))
-                                                       return -EIO;
-                                               /* Packet X/27/0 */
-                                               if (i2c_senddata(t, 8, 0, 0x21, 0, -1) ||
-                                                       i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40))
-                                                       return -EIO;
-                                               /* Packet 8/30/0...8/30/15
-                                                * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
-                                                *        so we should undo this here.
-                                                */
-                                               if (i2c_senddata(t, 8, 0, 0x22, 0, -1) ||
-                                                       i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
-                                                       return -EIO;
-                                       }
-                                       t->vdau[req->pgbuf].clrfound = false;
-                                       memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
-                               }
-                               else
-                               {
-                                       memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
                                }
-                       }
-                       else
-                       {
+                               t->vdau[req->pgbuf].clrfound = false;
+                               memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
+                       } else {
                                memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
                        }
+               } else {
+                       memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
+               }
 
-                       info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f);
-                       if (info.pagenum < 0x100)
-                               info.pagenum += 0x800;
-                       info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
-                       info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
-                       info.charset = ((infobits[7] >> 1) & 7);
-                       info.delete = !!(infobits[3] & 8);
-                       info.headline = !!(infobits[5] & 4);
-                       info.subtitle = !!(infobits[5] & 8);
-                       info.supp_header = !!(infobits[6] & 1);
-                       info.update = !!(infobits[6] & 2);
-                       info.inter_seq = !!(infobits[6] & 4);
-                       info.dis_disp = !!(infobits[6] & 8);
-                       info.serial = !!(infobits[7] & 1);
-                       info.notfound = !!(infobits[8] & 0x10);
-                       info.pblf = !!(infobits[9] & 0x20);
-                       info.hamming = 0;
-                       for (a = 0; a <= 7; a++)
-                       {
-                               if (infobits[a] & 0xf0)
-                               {
-                                       info.hamming = 1;
-                                       break;
-                               }
-                       }
-                       if (t->vdau[req->pgbuf].clrfound)
-                               info.notfound = 1;
-                       if(copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
-                               return -EFAULT;
-                       if (!info.hamming && !info.notfound)
-                       {
-                               t->is_searching[req->pgbuf] = false;
+               info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f);
+               if (info.pagenum < 0x100)
+                       info.pagenum += 0x800;
+               info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
+               info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
+               info.charset = ((infobits[7] >> 1) & 7);
+               info.delete = !!(infobits[3] & 8);
+               info.headline = !!(infobits[5] & 4);
+               info.subtitle = !!(infobits[5] & 8);
+               info.supp_header = !!(infobits[6] & 1);
+               info.update = !!(infobits[6] & 2);
+               info.inter_seq = !!(infobits[6] & 4);
+               info.dis_disp = !!(infobits[6] & 8);
+               info.serial = !!(infobits[7] & 1);
+               info.notfound = !!(infobits[8] & 0x10);
+               info.pblf = !!(infobits[9] & 0x20);
+               info.hamming = 0;
+               for (a = 0; a <= 7; a++) {
+                       if (infobits[a] & 0xf0) {
+                               info.hamming = 1;
+                               break;
                        }
-                       return 0;
                }
+               if (t->vdau[req->pgbuf].clrfound)
+                       info.notfound = 1;
+               if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
+                       return -EFAULT;
+               if (!info.hamming && !info.notfound)
+                       t->is_searching[req->pgbuf] = false;
+               return 0;
+       }
 
-               case VTXIOCGETPAGE:
-               {
-                       vtx_pagereq_t *req = arg;
-                       int start, end;
-
-                       if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 ||
-                               req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
-                               return -EINVAL;
-                       if(copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
+       case VTXIOCGETPAGE:
+       {
+               vtx_pagereq_t *req = arg;
+               int start, end;
+
+               if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 ||
+                       req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
+                       return -EINVAL;
+               if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
+                       return -EFAULT;
+
+                /*
+                 *     Always read the time directly from SAA5249
+                 */
+
+               if (req->start <= 39 && req->end >= 32) {
+                       int len;
+                       char buf[16];
+                       start = max(req->start, 32);
+                       end = min(req->end, 39);
+                       len = end - start + 1;
+                       if (i2c_senddata(t, 8, 0, 0, start, -1) ||
+                               i2c_getdata(t, len, buf))
+                               return -EIO;
+                       if (copy_to_user(req->buffer + start - req->start, buf, len))
+                               return -EFAULT;
+               }
+               /* Insert the current header if DAU is still searching for a page */
+               if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) {
+                       char buf[32];
+                       int len;
+
+                       start = max(req->start, 7);
+                       end = min(req->end, 31);
+                       len = end - start + 1;
+                       if (i2c_senddata(t, 8, 0, 0, start, -1) ||
+                               i2c_getdata(t, len, buf))
+                               return -EIO;
+                       if (copy_to_user(req->buffer + start - req->start, buf, len))
                                return -EFAULT;
-
-                        /*
-                         *     Always read the time directly from SAA5249
-                         */
-
-                       if (req->start <= 39 && req->end >= 32)
-                       {
-                               int len;
-                               char buf[16];
-                               start = max(req->start, 32);
-                               end = min(req->end, 39);
-                               len=end-start+1;
-                               if (i2c_senddata(t, 8, 0, 0, start, -1) ||
-                                       i2c_getdata(t, len, buf))
-                                       return -EIO;
-                               if(copy_to_user(req->buffer+start-req->start, buf, len))
-                                       return -EFAULT;
-                       }
-                       /* Insert the current header if DAU is still searching for a page */
-                       if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf])
-                       {
-                               char buf[32];
-                               int len;
-                               start = max(req->start, 7);
-                               end = min(req->end, 31);
-                               len=end-start+1;
-                               if (i2c_senddata(t, 8, 0, 0, start, -1) ||
-                                       i2c_getdata(t, len, buf))
-                                       return -EIO;
-                               if(copy_to_user(req->buffer+start-req->start, buf, len))
-                                       return -EFAULT;
-                       }
-                       return 0;
                }
+               return 0;
+       }
 
-               case VTXIOCSTOPDAU:
-               {
-                       vtx_pagereq_t *req = arg;
+       case VTXIOCSTOPDAU:
+       {
+               vtx_pagereq_t *req = arg;
 
-                       if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
-                               return -EINVAL;
-                       t->vdau[req->pgbuf].stopped = true;
-                       t->is_searching[req->pgbuf] = false;
-                       return 0;
-               }
+               if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
+                       return -EINVAL;
+               t->vdau[req->pgbuf].stopped = true;
+               t->is_searching[req->pgbuf] = false;
+               return 0;
+       }
 
-               case VTXIOCPUTPAGE:
-               case VTXIOCSETDISP:
-               case VTXIOCPUTSTAT:
-                       return 0;
+       case VTXIOCPUTPAGE:
+       case VTXIOCSETDISP:
+       case VTXIOCPUTSTAT:
+               return 0;
 
-               case VTXIOCCLRCACHE:
-               {
-                       if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
-                               ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
-                               ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1))
-                               return -EIO;
-                       if (i2c_senddata(t, 3, 0x20, -1))
-                               return -EIO;
-                       jdelay(10 * CLEAR_DELAY);                       /* I have no idea how long we have to wait here */
-                       return 0;
-               }
+       case VTXIOCCLRCACHE:
+       {
+               if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
+                       ' ', ' ', ' ', ' ', ' ', ' ',
+                       ' ', ' ', ' ', ' ', ' ', ' ',
+                       ' ', ' ', ' ', ' ', ' ', ' ',
+                       ' ', ' ', ' ', ' ', ' ', ' ',
+                       -1))
+                       return -EIO;
+               if (i2c_senddata(t, 3, 0x20, -1))
+                       return -EIO;
+               jdelay(10 * CLEAR_DELAY);                       /* I have no idea how long we have to wait here */
+               return 0;
+       }
 
-               case VTXIOCSETVIRT:
-               {
-                       /* The SAA5249 has virtual-row reception turned on always */
-                       t->virtual_mode = (int)(long)arg;
-                       return 0;
-               }
+       case VTXIOCSETVIRT:
+       {
+               /* The SAA5249 has virtual-row reception turned on always */
+               t->virtual_mode = (int)(long)arg;
+               return 0;
+       }
        }
        return -EINVAL;
 }
@@ -616,8 +483,7 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
 static int saa5249_ioctl(struct inode *inode, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5249_device *t=vd->priv;
+       struct saa5249_device *t = video_drvdata(file);
        int err;
 
        cmd = vtx_fix_command(cmd);
@@ -629,32 +495,27 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
 
 static int saa5249_open(struct inode *inode, struct file *file)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5249_device *t=vd->priv;
-       int err,pgbuf;
+       struct saa5249_device *t = video_drvdata(file);
+       int pgbuf;
 
-       err = video_exclusive_open(inode,file);
-       if (err < 0)
-               return err;
+       if (t->client == NULL)
+               return -ENODEV;
 
-       if (t->client==NULL) {
-               err = -ENODEV;
-               goto fail;
-       }
+       if (test_and_set_bit(0, &t->in_use))
+               return -EBUSY;
 
-       if (i2c_senddata(t, 0, 0, -1) ||                /* Select R11 */
-                                               /* Turn off parity checks (we do this ourselves) */
+       if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */
+               /* Turn off parity checks (we do this ourselves) */
                i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) ||
-                                               /* Display TV-picture, no virtual rows */
-               i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1)) /* Set display to page 4 */
-
+               /* Display TV-picture, no virtual rows */
+               i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1))
+               /* Set display to page 4 */
        {
-               err = -EIO;
-               goto fail;
+               clear_bit(0, &t->in_use);
+               return -EIO;
        }
 
-       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++)
-       {
+       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
                memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
                memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
                memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
@@ -665,39 +526,20 @@ static int saa5249_open(struct inode *inode, struct file *file)
        }
        t->virtual_mode = false;
        return 0;
-
- fail:
-       video_exclusive_release(inode,file);
-       return err;
 }
 
 
 
 static int saa5249_release(struct inode *inode, struct file *file)
 {
-       struct video_device *vd = video_devdata(file);
-       struct saa5249_device *t=vd->priv;
+       struct saa5249_device *t = video_drvdata(file);
+
        i2c_senddata(t, 1, 0x20, -1);           /* Turn off CCT */
        i2c_senddata(t, 5, 3, 3, -1);           /* Turn off TV-display */
-       video_exclusive_release(inode,file);
+       clear_bit(0, &t->in_use);
        return 0;
 }
 
-static int __init init_saa_5249 (void)
-{
-       printk(KERN_INFO "SAA5249 driver (" IF_NAME " interface) for VideoText version %d.%d\n",
-                       VTX_VER_MAJ, VTX_VER_MIN);
-       return i2c_add_driver(&i2c_driver_videotext);
-}
-
-static void __exit cleanup_saa_5249 (void)
-{
-       i2c_del_driver(&i2c_driver_videotext);
-}
-
-module_init(init_saa_5249);
-module_exit(cleanup_saa_5249);
-
 static const struct file_operations saa_fops = {
        .owner          = THIS_MODULE,
        .open           = saa5249_open,
@@ -711,8 +553,84 @@ static const struct file_operations saa_fops = {
 
 static struct video_device saa_template =
 {
-       .name           = IF_NAME,
+       .name           = "saa5249",
        .fops           = &saa_fops,
+       .release        = video_device_release,
 };
 
-MODULE_LICENSE("GPL");
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static int saa5249_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       int pgbuf;
+       int err;
+       struct video_device *vd;
+       struct saa5249_device *t;
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
+       v4l_info(client, "VideoText version %d.%d\n",
+                       VTX_VER_MAJ, VTX_VER_MIN);
+       t = kzalloc(sizeof(*t), GFP_KERNEL);
+       if (t == NULL)
+               return -ENOMEM;
+       mutex_init(&t->lock);
+
+       /* Now create a video4linux device */
+       vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+       if (vd == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(client, vd);
+       memcpy(vd, &saa_template, sizeof(*vd));
+
+       for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
+               memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
+               memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
+               memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
+               t->vdau[pgbuf].expire = 0;
+               t->vdau[pgbuf].clrfound = true;
+               t->vdau[pgbuf].stopped = true;
+               t->is_searching[pgbuf] = false;
+       }
+       video_set_drvdata(vd, t);
+
+       /* Register it */
+       err = video_register_device(vd, VFL_TYPE_VTX, -1);
+       if (err < 0) {
+               kfree(t);
+               kfree(vd);
+               return err;
+       }
+       t->client = client;
+       return 0;
+}
+
+static int saa5249_remove(struct i2c_client *client)
+{
+       struct video_device *vd = i2c_get_clientdata(client);
+
+       video_unregister_device(vd);
+       kfree(video_get_drvdata(vd));
+       kfree(vd);
+       return 0;
+}
+
+static const struct i2c_device_id saa5249_id[] = {
+       { "saa5249", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, saa5249_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "saa5249",
+       .driverid = I2C_DRIVERID_SAA5249,
+       .probe = saa5249_probe,
+       .remove = saa5249_remove,
+       .id_table = saa5249_id,
+};
index ad733caec720f1b782921f5b4718ea56fdf246f7..c8e9cb3db30a9651692e3c4d732cca6a82643c06 100644 (file)
@@ -1057,7 +1057,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
        for (i = 0; i <= 23; i++)
                lcr[i] = 0xff;
 
-       if (fmt->service_set == 0) {
+       if (fmt == NULL) {
                /* raw VBI */
                if (is_50hz)
                        for (i = 6; i <= 23; i++)
@@ -1113,7 +1113,7 @@ static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo
        }
 
        /* enable/disable raw VBI capturing */
-       saa711x_writeregs(client, fmt->service_set == 0 ?
+       saa711x_writeregs(client, fmt == NULL ?
                                saa7115_cfg_vbi_on :
                                saa7115_cfg_vbi_off);
 }
@@ -1153,6 +1153,10 @@ static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
                saa711x_set_lcr(client, &fmt->fmt.sliced);
                return 0;
        }
+       if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               saa711x_set_lcr(client, NULL);
+               return 0;
+       }
        if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
@@ -1309,10 +1313,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
        case VIDIOC_INT_S_VIDEO_ROUTING:
        {
                struct v4l2_routing *route = arg;
+               u32 input = route->input;
+               u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;
 
                v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);
-               /* saa7113 does not have these inputs */
-               if (state->ident == V4L2_IDENT_SAA7113 &&
+               /* saa7111/3 does not have these inputs */
+               if ((state->ident == V4L2_IDENT_SAA7113 ||
+                    state->ident == V4L2_IDENT_SAA7111) &&
                    (route->input == SAA7115_COMPOSITE4 ||
                     route->input == SAA7115_COMPOSITE5)) {
                        return -EINVAL;
@@ -1327,10 +1334,23 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                        (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
                state->input = route->input;
 
+               /* saa7111 has slightly different input numbering */
+               if (state->ident == V4L2_IDENT_SAA7111) {
+                       if (input >= SAA7115_COMPOSITE4)
+                               input -= 2;
+                       /* saa7111 specific */
+                       saa711x_write(client, R_10_CHROMA_CNTL_2,
+                                       (saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) |
+                                       ((route->output & 0xc0) ^ 0x40));
+                       saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL,
+                                       (saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
+                                       ((route->output & 2) ? 0x0a : 0));
+               }
+
                /* select mode */
                saa711x_write(client, R_02_INPUT_CNTL_1,
-                             (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |
-                              state->input);
+                             (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) |
+                              input);
 
                /* bypass chrominance trap for S-Video modes */
                saa711x_write(client, R_09_LUMA_CNTL,
@@ -1384,6 +1404,13 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                saa711x_writeregs(client, saa7115_cfg_reset_scaler);
                break;
 
+       case VIDIOC_INT_S_GPIO:
+               if (state->ident != V4L2_IDENT_SAA7111)
+                       return -EINVAL;
+               saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) |
+                       (*(u32 *)arg ? 0x80 : 0));
+               break;
+
        case VIDIOC_INT_G_VBI_DATA:
        {
                struct v4l2_sliced_vbi_data *data = arg;
@@ -1539,7 +1566,8 @@ static int saa7115_probe(struct i2c_client *client,
                state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
                saa711x_writeregs(client, saa7115_init_auto_input);
        }
-       saa711x_writeregs(client, saa7115_init_misc);
+       if (state->ident != V4L2_IDENT_SAA7111)
+               saa711x_writeregs(client, saa7115_init_misc);
        saa711x_set_v4lstd(client, V4L2_STD_NTSC);
 
        v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
index 707be175509dbebcf00f1833ae7fc622e43c7c0d..1fb6eccdade32ac5f22a1c6493914e6ce041bc8c 100644 (file)
@@ -1,3 +1,27 @@
+ /*
+    saa6752hs - i2c-driver for the saa6752hs by Philips
+
+    Copyright (C) 2004 Andrew de Quincey
+
+    AC-3 support:
+
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -10,6 +34,8 @@
 #include <linux/types.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 #include <linux/init.h>
 #include <linux/crc32.h>
 
@@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
 MODULE_AUTHOR("Andrew de Quincey");
 MODULE_LICENSE("GPL");
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 enum saa6752hs_videoformat {
        SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
        SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
@@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params {
        __u16                           ts_pid_pcr;
 
        /* audio */
-       enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+       enum v4l2_mpeg_audio_encoding    au_encoding;
+       enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
+       enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
 
        /* video */
        enum v4l2_mpeg_video_aspect     vi_aspect;
@@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] =
 };
 
 struct saa6752hs_state {
-       struct i2c_client             client;
+       int                           chip;
+       u32                           revision;
+       int                           has_ac3;
        struct saa6752hs_mpeg_params  params;
        enum saa6752hs_videoformat    video_format;
        v4l2_std_id                   standard;
@@ -145,6 +172,39 @@ static u8 PMT[] = {
        0x00, 0x00, 0x00, 0x00 /* CRC32 */
 };
 
+static u8 PMT_AC3[] = {
+       0xc2, /* i2c register */
+       0x01, /* table number for encoder(1) */
+       0x47, /* sync */
+
+       0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
+       0x10, /* PMT PID (0x0010) */
+       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+       0x00, /* PSI pointer to start of table */
+
+       0x02, /* TID (2) */
+       0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
+
+       0x00, 0x01, /* program_number(1) */
+
+       0xc1, /* version_number(0), current_next_indicator(1) */
+
+       0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+       0xe1, 0x04, /* PCR_PID (0x0104) */
+
+       0xf0, 0x00, /* program_info_length(0) */
+
+       0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+       0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
+       0x6a, /* AC3 */
+       0x01, /* Descriptor_length(1) */
+       0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
+
+       0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
+};
+
 static struct saa6752hs_mpeg_params param_defaults =
 {
        .ts_pid_pmt      = 16,
@@ -157,12 +217,14 @@ static struct saa6752hs_mpeg_params param_defaults =
        .vi_bitrate_peak = 6000,
        .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
 
+       .au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
        .au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+       .au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
 };
 
 /* ---------------------------------------------------------------------- */
 
-static int saa6752hs_chip_command(struct i2c_clientclient,
+static int saa6752hs_chip_command(struct i2c_client *client,
                                  enum saa6752hs_command command)
 {
        unsigned char buf[3];
@@ -229,45 +291,61 @@ static int saa6752hs_chip_command(struct i2c_client* client,
 }
 
 
-static int saa6752hs_set_bitrate(struct i2c_client* client,
-                                struct saa6752hs_mpeg_params* params)
+static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
+{
+       u8 buf[2];
+
+       buf[0] = reg;
+       buf[1] = val;
+       i2c_master_send(client, buf, 2);
+}
+
+static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
 {
        u8 buf[3];
+
+       buf[0] = reg;
+       buf[1] = val >> 8;
+       buf[2] = val & 0xff;
+       i2c_master_send(client, buf, 3);
+}
+
+static int saa6752hs_set_bitrate(struct i2c_client *client,
+                                struct saa6752hs_state *h)
+{
+       struct saa6752hs_mpeg_params *params = &h->params;
        int tot_bitrate;
+       int is_384k;
 
        /* set the bitrate mode */
-       buf[0] = 0x71;
-       buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
-       i2c_master_send(client, buf, 2);
+       set_reg8(client, 0x71,
+               params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
 
        /* set the video bitrate */
        if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
                /* set the target bitrate */
-               buf[0] = 0x80;
-               buf[1] = params->vi_bitrate >> 8;
-               buf[2] = params->vi_bitrate & 0xff;
-               i2c_master_send(client, buf, 3);
+               set_reg16(client, 0x80, params->vi_bitrate);
 
                /* set the max bitrate */
-               buf[0] = 0x81;
-               buf[1] = params->vi_bitrate_peak >> 8;
-               buf[2] = params->vi_bitrate_peak & 0xff;
-               i2c_master_send(client, buf, 3);
+               set_reg16(client, 0x81, params->vi_bitrate_peak);
                tot_bitrate = params->vi_bitrate_peak;
        } else {
                /* set the target bitrate (no max bitrate for CBR) */
-               buf[0] = 0x81;
-               buf[1] = params->vi_bitrate >> 8;
-               buf[2] = params->vi_bitrate & 0xff;
-               i2c_master_send(client, buf, 3);
+               set_reg16(client, 0x81, params->vi_bitrate);
                tot_bitrate = params->vi_bitrate;
        }
 
+       /* set the audio encoding */
+       set_reg8(client, 0x93,
+                       params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
+
        /* set the audio bitrate */
-       buf[0] = 0x94;
-       buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
-       i2c_master_send(client, buf, 2);
-       tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
+       if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
+               is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
+       else
+               is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
+       set_reg8(client, 0x94, is_384k);
+       tot_bitrate += is_384k ? 384 : 256;
 
        /* Note: the total max bitrate is determined by adding the video and audio
           bitrates together and also adding an extra 768kbit/s to stay on the
@@ -278,16 +356,12 @@ static int saa6752hs_set_bitrate(struct i2c_client* client,
                tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
 
        /* set the total bitrate */
-       buf[0] = 0xb1;
-       buf[1] = tot_bitrate >> 8;
-       buf[2] = tot_bitrate & 0xff;
-       i2c_master_send(client, buf, 3);
-
+       set_reg16(client, 0xb1, tot_bitrate);
        return 0;
 }
 
-static void saa6752hs_set_subsampling(struct i2c_clientclient,
-                                     struct v4l2_formatf)
+static void saa6752hs_set_subsampling(struct i2c_client *client,
+                                     struct v4l2_format *f)
 {
        struct saa6752hs_state *h = i2c_get_clientdata(client);
        int dist_352, dist_480, dist_720;
@@ -332,7 +406,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client,
 }
 
 
-static int handle_ctrl(struct saa6752hs_mpeg_params *params,
+static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
                struct v4l2_ext_control *ctrl, unsigned int cmd)
 {
        int old = 0, new;
@@ -379,8 +453,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
                        params->ts_pid_pcr = new;
                        break;
                case V4L2_CID_MPEG_AUDIO_ENCODING:
-                       old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
-                       if (set && new != old)
+                       old = params->au_encoding;
+                       if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+                           (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
                                return -ERANGE;
                        new = old;
                        break;
@@ -395,6 +470,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
                                new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
                        params->au_l2_bitrate = new;
                        break;
+               case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+                       if (!has_ac3)
+                               return -EINVAL;
+                       old = params->au_ac3_bitrate;
+                       if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
+                                  new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
+                               return -ERANGE;
+                       if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
+                               new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
+                       else
+                               new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
+                       params->au_ac3_bitrate = new;
+                       break;
                case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
                        old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
                        if (set && new != old)
@@ -448,17 +536,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
        return 0;
 }
 
-static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qctrl(struct saa6752hs_state *h,
                struct v4l2_queryctrl *qctrl)
 {
+       struct saa6752hs_mpeg_params *params = &h->params;
        int err;
 
        switch (qctrl->id) {
        case V4L2_CID_MPEG_AUDIO_ENCODING:
                return v4l2_ctrl_query_fill(qctrl,
                                V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
-                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+                               h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+                                       V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+                               1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
 
        case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
                return v4l2_ctrl_query_fill(qctrl,
@@ -466,6 +556,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
                                V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
                                V4L2_MPEG_AUDIO_L2_BITRATE_256K);
 
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!h->has_ac3)
+                       return -EINVAL;
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
                return v4l2_ctrl_query_fill(qctrl,
                                V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
@@ -512,44 +610,57 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
        return -EINVAL;
 }
 
-static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
+static int saa6752hs_qmenu(struct saa6752hs_state *h,
                struct v4l2_querymenu *qmenu)
 {
-       static const char *mpeg_audio_l2_bitrate[] = {
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "",
-               "256 kbps",
-               "",
-               "384 kbps",
-               NULL
+       static const u32 mpeg_audio_encoding[] = {
+               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static const u32 mpeg_audio_ac3_encoding[] = {
+               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+               V4L2_MPEG_AUDIO_ENCODING_AC3,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static u32 mpeg_audio_l2_bitrate[] = {
+               V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+               V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static u32 mpeg_audio_ac3_bitrate[] = {
+               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+               V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+               V4L2_CTRL_MENU_IDS_END
        };
        struct v4l2_queryctrl qctrl;
        int err;
 
        qctrl.id = qmenu->id;
-       err = saa6752hs_qctrl(params, &qctrl);
+       err = saa6752hs_qctrl(h, &qctrl);
        if (err)
                return err;
-       if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
-               return v4l2_ctrl_query_menu(qmenu, &qctrl,
+       switch (qmenu->id) {
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
                                mpeg_audio_l2_bitrate);
-       return v4l2_ctrl_query_menu(qmenu, &qctrl,
-                       v4l2_ctrl_get_menu(qmenu->id));
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!h->has_ac3)
+                       return -EINVAL;
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
+                               mpeg_audio_ac3_bitrate);
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
+                       h->has_ac3 ? mpeg_audio_ac3_encoding :
+                               mpeg_audio_encoding);
+       }
+       return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
 }
 
-static int saa6752hs_init(struct i2c_client* client)
+static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes)
 {
        unsigned char buf[9], buf2[4];
        struct saa6752hs_state *h;
+       unsigned size;
        u32 crc;
        unsigned char localPAT[256];
        unsigned char localPMT[256];
@@ -557,45 +668,31 @@ static int saa6752hs_init(struct i2c_client* client)
        h = i2c_get_clientdata(client);
 
        /* Set video format - must be done first as it resets other settings */
-       buf[0] = 0x41;
-       buf[1] = h->video_format;
-       i2c_master_send(client, buf, 2);
+       set_reg8(client, 0x41, h->video_format);
 
        /* Set number of lines in input signal */
-       buf[0] = 0x40;
-       buf[1] = 0x00;
-       if (h->standard & V4L2_STD_525_60)
-               buf[1] = 0x01;
-       i2c_master_send(client, buf, 2);
+       set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
 
        /* set bitrate */
-       saa6752hs_set_bitrate(client, &h->params);
+       saa6752hs_set_bitrate(client, h);
 
        /* Set GOP structure {3, 13} */
-       buf[0] = 0x72;
-       buf[1] = 0x03;
-       buf[2] = 0x0D;
-       i2c_master_send(client,buf,3);
+       set_reg16(client, 0x72, 0x030d);
 
        /* Set minimum Q-scale {4} */
-       buf[0] = 0x82;
-       buf[1] = 0x04;
-       i2c_master_send(client,buf,2);
+       set_reg8(client, 0x82, 0x04);
 
        /* Set maximum Q-scale {12} */
-       buf[0] = 0x83;
-       buf[1] = 0x0C;
-       i2c_master_send(client,buf,2);
+       set_reg8(client, 0x83, 0x0c);
 
        /* Set Output Protocol */
-       buf[0] = 0xD0;
-       buf[1] = 0x81;
-       i2c_master_send(client,buf,2);
+       set_reg8(client, 0xd0, 0x81);
 
        /* Set video output stream format {TS} */
-       buf[0] = 0xB0;
-       buf[1] = 0x05;
-       i2c_master_send(client,buf,2);
+       set_reg8(client, 0xb0, 0x05);
+
+       /* Set leading null byte for TS */
+       set_reg16(client, 0xf6, leading_null_bytes);
 
        /* compute PAT */
        memcpy(localPAT, PAT, sizeof(PAT));
@@ -608,7 +705,13 @@ static int saa6752hs_init(struct i2c_client* client)
        localPAT[sizeof(PAT) - 1] = crc & 0xFF;
 
        /* compute PMT */
-       memcpy(localPMT, PMT, sizeof(PMT));
+       if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+               size = sizeof(PMT_AC3);
+               memcpy(localPMT, PMT_AC3, size);
+       } else {
+               size = sizeof(PMT);
+               memcpy(localPMT, PMT, size);
+       }
        localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
        localPMT[4] = h->params.ts_pid_pmt & 0xff;
        localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
@@ -617,40 +720,28 @@ static int saa6752hs_init(struct i2c_client* client)
        localPMT[21] = h->params.ts_pid_video & 0xFF;
        localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
        localPMT[26] = h->params.ts_pid_audio & 0xFF;
-       crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
-       localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
-       localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
-       localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
-       localPMT[sizeof(PMT) - 1] = crc & 0xFF;
+       crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
+       localPMT[size - 4] = (crc >> 24) & 0xFF;
+       localPMT[size - 3] = (crc >> 16) & 0xFF;
+       localPMT[size - 2] = (crc >> 8) & 0xFF;
+       localPMT[size - 1] = crc & 0xFF;
 
        /* Set Audio PID */
-       buf[0] = 0xC1;
-       buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
-       buf[2] = h->params.ts_pid_audio & 0xFF;
-       i2c_master_send(client,buf,3);
+       set_reg16(client, 0xc1, h->params.ts_pid_audio);
 
        /* Set Video PID */
-       buf[0] = 0xC0;
-       buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
-       buf[2] = h->params.ts_pid_video & 0xFF;
-       i2c_master_send(client,buf,3);
+       set_reg16(client, 0xc0, h->params.ts_pid_video);
 
        /* Set PCR PID */
-       buf[0] = 0xC4;
-       buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
-       buf[2] = h->params.ts_pid_pcr & 0xFF;
-       i2c_master_send(client,buf,3);
+       set_reg16(client, 0xc4, h->params.ts_pid_pcr);
 
        /* Send SI tables */
-       i2c_master_send(client,localPAT,sizeof(PAT));
-       i2c_master_send(client,localPMT,sizeof(PMT));
+       i2c_master_send(client, localPAT, sizeof(PAT));
+       i2c_master_send(client, localPMT, size);
 
        /* mute then unmute audio. This removes buzzing artefacts */
-       buf[0] = 0xa4;
-       buf[1] = 1;
-       i2c_master_send(client, buf, 2);
-       buf[1] = 0;
-       i2c_master_send(client, buf, 2);
+       set_reg8(client, 0xa4, 1);
+       set_reg8(client, 0xa4, 0);
 
        /* start it going */
        saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
@@ -688,45 +779,6 @@ static int saa6752hs_init(struct i2c_client* client)
        return 0;
 }
 
-static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-       struct saa6752hs_state *h;
-
-
-       if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
-               return -ENOMEM;
-       h->client = client_template;
-       h->params = param_defaults;
-       h->client.adapter = adap;
-       h->client.addr = addr;
-
-       /* Assume 625 input lines */
-       h->standard = 0;
-
-       i2c_set_clientdata(&h->client, h);
-       i2c_attach_client(&h->client);
-
-       v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
-       return 0;
-}
-
-static int saa6752hs_probe(struct i2c_adapter *adap)
-{
-       if (adap->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adap, &addr_data, saa6752hs_attach);
-       return 0;
-}
-
-static int saa6752hs_detach(struct i2c_client *client)
-{
-       struct saa6752hs_state *h;
-
-       h = i2c_get_clientdata(client);
-       i2c_detach_client(client);
-       kfree(h);
-       return 0;
-}
-
 static int
 saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
@@ -737,14 +789,13 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
        int i;
 
        switch (cmd) {
+       case VIDIOC_INT_INIT:
+               /* apply settings and start encoder */
+               saa6752hs_init(client, *(u32 *)arg);
+               break;
        case VIDIOC_S_EXT_CTRLS:
                if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
                        return -EINVAL;
-               if (ctrls->count == 0) {
-                       /* apply settings and start encoder */
-                       saa6752hs_init(client);
-                       break;
-               }
                /* fall through */
        case VIDIOC_TRY_EXT_CTRLS:
        case VIDIOC_G_EXT_CTRLS:
@@ -752,7 +803,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        return -EINVAL;
                params = h->params;
                for (i = 0; i < ctrls->count; i++) {
-                       if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
+                       err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, cmd);
+                       if (err) {
                                ctrls->error_idx = i;
                                return err;
                        }
@@ -760,9 +812,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
                h->params = params;
                break;
        case VIDIOC_QUERYCTRL:
-               return saa6752hs_qctrl(&h->params, arg);
+               return saa6752hs_qctrl(h, arg);
        case VIDIOC_QUERYMENU:
-               return saa6752hs_qmenu(&h->params, arg);
+               return saa6752hs_qmenu(h, arg);
        case VIDIOC_G_FMT:
        {
           struct v4l2_format *f = arg;
@@ -785,6 +837,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case VIDIOC_S_STD:
                h->standard = *((v4l2_std_id *) arg);
                break;
+
+       case VIDIOC_G_CHIP_IDENT:
+               return v4l2_chip_ident_i2c_client(client,
+                               arg, h->chip, h->revision);
+
        default:
                /* nothing */
                break;
@@ -793,36 +850,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
        return err;
 }
 
-/* ----------------------------------------------------------------------- */
+static int saa6752hs_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+       u8 addr = 0x13;
+       u8 data[12];
 
-static struct i2c_driver driver = {
-       .driver = {
-               .name   = "saa6752hs",
-       },
-       .id             = I2C_DRIVERID_SAA6752HS,
-       .attach_adapter = saa6752hs_probe,
-       .detach_client  = saa6752hs_detach,
-       .command        = saa6752hs_command,
-};
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
+       if (h == NULL)
+               return -ENOMEM;
 
-static struct i2c_client client_template =
-{
-       .name       = "saa6752hs",
-       .driver     = &driver,
-};
+       i2c_master_send(client, &addr, 1);
+       i2c_master_recv(client, data, sizeof(data));
+       h->chip = V4L2_IDENT_SAA6752HS;
+       h->revision = (data[8] << 8) | data[9];
+       h->has_ac3 = 0;
+       if (h->revision == 0x0206) {
+               h->chip = V4L2_IDENT_SAA6752HS_AC3;
+               h->has_ac3 = 1;
+               v4l_info(client, "support AC-3\n");
+       }
+       h->params = param_defaults;
+       h->standard = 0; /* Assume 625 input lines */
 
-static int __init saa6752hs_init_module(void)
-{
-       return i2c_add_driver(&driver);
+       i2c_set_clientdata(client, h);
+       return 0;
 }
 
-static void __exit saa6752hs_cleanup_module(void)
+static int saa6752hs_remove(struct i2c_client *client)
 {
-       i2c_del_driver(&driver);
+       kfree(i2c_get_clientdata(client));
+       return 0;
 }
 
-module_init(saa6752hs_init_module);
-module_exit(saa6752hs_cleanup_module);
+static const struct i2c_device_id saa6752hs_id[] = {
+       { "saa6752hs", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "saa6752hs",
+       .driverid = I2C_DRIVERID_SAA6752HS,
+       .command = saa6752hs_command,
+       .probe = saa6752hs_probe,
+       .remove = saa6752hs_remove,
+       .id_table = saa6752hs_id,
+};
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 98364d171def6ba442c92b28e60125649d6cb7e6..ddc5402c5fb071c1db008c77e506d009fbcd4915 100644 (file)
@@ -3260,6 +3260,7 @@ struct saa7134_board saa7134_boards[] = {
        },
        [SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
                /* Thomas Genty <tomlohave@gmail.com> */
+               /* David Bentham <db260179@hotmail.com> */
                .name           = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
@@ -3268,23 +3269,26 @@ struct saa7134_board saa7134_boards[] = {
                .radio_addr     = ADDR_UNSET,
                .tuner_config   = 1,
                .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x0200100,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 1,
                        .amux = TV,
                        .tv   = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE2, /* FIXME: audio doesn't work on svideo/composite */
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2, /* FIXME: audio doesn't work on svideo/composite */
-               }},
+                       .gpio = 0x0000100,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
                .radio = {
                        .name = name_radio,
-                       .amux   = TV,
+                       .amux = TV,
+                       .gpio = 0x0200100,
                },
        },
        [SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
@@ -3388,6 +3392,42 @@ struct saa7134_board saa7134_boards[] = {
                        .amux = 0,
                },
        },
+       [SAA7134_BOARD_ENCORE_ENLTV_FM53] = {
+               .name           = "Encore ENLTV-FM v5.3",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x7000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 1,
+                       .tv   = 1,
+                       .gpio = 0x50000,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+                       .gpio = 0x2000,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = 2,
+                       .gpio = 0x2000,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .vmux = 1,
+                       .amux = 1,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .gpio = 0xf000,
+                       .amux = 0,
+               },
+       },
        [SAA7134_BOARD_CINERGY_HT_PCI] = {
                .name           = "Terratec Cinergy HT PCI",
                .audio_clock    = 0x00187de7,
@@ -3631,6 +3671,40 @@ struct saa7134_board saa7134_boards[] = {
                        .tv     = 1,
                }},
        },
+       [SAA7134_BOARD_AVERMEDIA_M135A] = {
+               .name           = "Avermedia PCI pure analog (M135A)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 0x020200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00200000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
        [SAA7134_BOARD_BEHOLD_401] = {
                /*       Beholder Intl. Ltd. 2008      */
                /*Dmitry Belimov <d.belimov@gmail.com> */
@@ -4409,6 +4483,129 @@ struct saa7134_board saa7134_boards[] = {
                /* no DVB support for now */
                /* .mpeg           = SAA7134_MPEG_DVB, */
        },
+       [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
+               .name           = "Asus Tiger 3in1",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 1 << 21,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 0,
+                       .amux = LINE2,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_REAL_ANGEL_220] = {
+               .name           = "Zogis Real Angel 220",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x801a8087,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = LINE2,
+                       .tv     = 1,
+                       .gpio   = 0x624000,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x624000,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x624000,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+                       .gpio   = 0x624001,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = {
+               .name           = "ADS Tech Instant HDTV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TUV1236D,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 4,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_ASUSTeK_TIGER] = {
+               .name           = "Asus Tiger Rev:1.00",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 0,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x0200000,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_comp2,
+                       .vmux   = 0,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -4776,6 +4973,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
 
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf11d,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M135A,
+       }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
                .subvendor    = PCI_VENDOR_ID_PHILIPS,
@@ -5156,6 +5359,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subdevice    = 0x230f,
                .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
        },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1a7f,
+               .subdevice    = 0x2008,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM53,
+       }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x153b,
@@ -5183,8 +5392,8 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x1043,
-               .subdevice    = 0x4857,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+               .subdevice    = 0x4857,         /* REV:1.00 */
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5413,6 +5622,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x185b,
                .subdevice    = 0xc900,
                .driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+               .subvendor    = 0x1421,
+               .subdevice    = 0x0380,
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI,
        }, {
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5431,6 +5646,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x1461, /* Avermedia Technologies Inc */
                .subdevice    = 0xf636,
                .driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4878, /* REV:1.02G */
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
        }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -5540,7 +5761,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev,
        return 0;
 }
 
-int saa7134_tuner_callback(void *priv, int command, int arg)
+int saa7134_tuner_callback(void *priv, int component, int command, int arg)
 {
        struct saa7134_dev *dev = priv;
        if (dev != NULL) {
@@ -5620,6 +5841,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
        case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
        case SAA7134_BOARD_AVERMEDIA_777:
+       case SAA7134_BOARD_AVERMEDIA_M135A:
 /*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
        case SAA7134_BOARD_VIDEOMATE_TV_PVR:
        case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
@@ -5644,6 +5866,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_A16AR:
        case SAA7134_BOARD_ENCORE_ENLTV:
        case SAA7134_BOARD_ENCORE_ENLTV_FM:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
        case SAA7134_BOARD_10MOONSTVMASTER3:
        case SAA7134_BOARD_BEHOLD_401:
        case SAA7134_BOARD_BEHOLD_403:
@@ -5656,6 +5879,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_BEHOLD_505FM:
        case SAA7134_BOARD_BEHOLD_507_9FM:
        case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
+       case SAA7134_BOARD_REAL_ANGEL_220:
                dev->has_remote = SAA7134_REMOTE_GPIO;
                break;
        case SAA7134_BOARD_FLYDVBS_LR300:
@@ -5745,6 +5969,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        case SAA7134_BOARD_PINNACLE_PCTV_110i:
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
        case SAA7134_BOARD_UPMOST_PURPLE_TV:
+       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
        case SAA7134_BOARD_BEHOLD_607_9FM:
        case SAA7134_BOARD_BEHOLD_M6:
@@ -5987,6 +6212,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        case SAA7134_BOARD_PINNACLE_PCTV_310i:
        case SAA7134_BOARD_KWORLD_DVBT_210:
        case SAA7134_BOARD_TEVION_DVBT_220RF:
+       case SAA7134_BOARD_ASUSTeK_TIGER:
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
        case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
        case SAA7134_BOARD_MEDION_MD8800_QUADRO:
@@ -6002,6 +6228,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                i2c_transfer(&dev->i2c_adap, &msg, 1);
                break;
        }
+       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+       {
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+                                                       .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
        case SAA7134_BOARD_FLYDVB_TRIO:
        {
                u8 data[] = { 0x3c, 0x33, 0x62};
@@ -6027,6 +6261,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                i2c_transfer(&dev->i2c_adap, &msg, 1);
                break;
        }
+       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
        case SAA7134_BOARD_KWORLD_ATSC110:
        {
                /* enable tuner */
index 75d618415f4f401e9b9239e8d936ef8d8d0647eb..b686bfabbde0defb53a765a8b3bf8978e1f21b0a 100644 (file)
@@ -215,7 +215,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
 int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
 {
        __le32       *cpu;
-       dma_addr_t   dma_addr;
+       dma_addr_t   dma_addr = 0;
 
        cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
        if (NULL == cpu)
@@ -359,32 +359,6 @@ void saa7134_buffer_timeout(unsigned long data)
        spin_unlock_irqrestore(&dev->slock,flags);
 }
 
-/* resends a current buffer in queue after resume */
-
-static int saa7134_buffer_requeue(struct saa7134_dev *dev,
-                                 struct saa7134_dmaqueue *q)
-{
-       struct saa7134_buf *buf, *next;
-
-       assert_spin_locked(&dev->slock);
-
-       buf  = q->curr;
-       next = buf;
-       dprintk("buffer_requeue\n");
-
-       if (!buf)
-               return 0;
-
-       dprintk("buffer_requeue : resending active buffers \n");
-
-       if (!list_empty(&q->queue))
-               next = list_entry(q->queue.next, struct saa7134_buf,
-                                         vb.queue);
-       buf->activate(dev, buf, next);
-
-       return 0;
-}
-
 /* ------------------------------------------------------------------ */
 
 int saa7134_set_dmabits(struct saa7134_dev *dev)
@@ -442,9 +416,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
        /* TS capture -- dma 5 */
        if (dev->ts_q.curr) {
                ctrl |= SAA7134_MAIN_CTRL_TE5;
-               irq  |= SAA7134_IRQ1_INTE_RA2_3 |
-                       SAA7134_IRQ1_INTE_RA2_2 |
-                       SAA7134_IRQ1_INTE_RA2_1 |
+               irq  |= SAA7134_IRQ1_INTE_RA2_1 |
                        SAA7134_IRQ1_INTE_RA2_0;
        }
 
@@ -727,6 +699,10 @@ static int saa7134_hw_enable2(struct saa7134_dev *dev)
                        irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
        }
 
+       if (dev->has_remote == SAA7134_REMOTE_I2C) {
+               request_module("ir-kbd-i2c");
+       }
+
        saa_writel(SAA7134_IRQ1, 0);
        saa_writel(SAA7134_IRQ2, irq2_mask);
 
@@ -1139,6 +1115,32 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
 }
 
 #ifdef CONFIG_PM
+
+/* resends a current buffer in queue after resume */
+static int saa7134_buffer_requeue(struct saa7134_dev *dev,
+                                 struct saa7134_dmaqueue *q)
+{
+       struct saa7134_buf *buf, *next;
+
+       assert_spin_locked(&dev->slock);
+
+       buf  = q->curr;
+       next = buf;
+       dprintk("buffer_requeue\n");
+
+       if (!buf)
+               return 0;
+
+       dprintk("buffer_requeue : resending active buffers \n");
+
+       if (!list_empty(&q->queue))
+               next = list_entry(q->queue.next, struct saa7134_buf,
+                                         vb.queue);
+       buf->activate(dev, buf, next);
+
+       return 0;
+}
+
 static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
 {
 
index be48b9b66a67ef9833daaeb3a4709b1dbddbb39d..87c10983266f3392f3f4fa173e6046bd60e77e71 100644 (file)
@@ -553,7 +553,6 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
 /* ------------------------------------------------------------------ */
 
 static struct tda827x_config tda827x_cfg_0 = {
-       .tuner_callback = saa7134_tuner_callback,
        .init = philips_tda827x_tuner_init,
        .sleep = philips_tda827x_tuner_sleep,
        .config = 0,
@@ -561,7 +560,6 @@ static struct tda827x_config tda827x_cfg_0 = {
 };
 
 static struct tda827x_config tda827x_cfg_1 = {
-       .tuner_callback = saa7134_tuner_callback,
        .init = philips_tda827x_tuner_init,
        .sleep = philips_tda827x_tuner_sleep,
        .config = 1,
@@ -569,7 +567,6 @@ static struct tda827x_config tda827x_cfg_1 = {
 };
 
 static struct tda827x_config tda827x_cfg_2 = {
-       .tuner_callback = saa7134_tuner_callback,
        .init = philips_tda827x_tuner_init,
        .sleep = philips_tda827x_tuner_sleep,
        .config = 2,
@@ -577,7 +574,6 @@ static struct tda827x_config tda827x_cfg_2 = {
 };
 
 static struct tda827x_config tda827x_cfg_2_sw42 = {
-       .tuner_callback = saa7134_tuner_callback,
        .init = philips_tda827x_tuner_init,
        .sleep = philips_tda827x_tuner_sleep,
        .config = 2,
@@ -799,6 +795,20 @@ static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
        .request_firmware = philips_tda1004x_request_firmware
 };
 
+static struct tda1004x_config asus_tiger_3in1_config = {
+       .demod_address = 0x0b,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
 /* ------------------------------------------------------------------
  * special case: this card uses saa713x GPIO22 for the mode switch
  */
@@ -822,7 +832,6 @@ static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 }
 
 static struct tda827x_config ads_duo_cfg = {
-       .tuner_callback = saa7134_tuner_callback,
        .init = ads_duo_tuner_init,
        .sleep = ads_duo_tuner_sleep,
        .config = 0
@@ -1147,6 +1156,7 @@ static int dvb_init(struct saa7134_dev *dev)
                        dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                   NULL, DVB_PLL_TDHU2);
                break;
+       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
        case SAA7134_BOARD_KWORLD_ATSC110:
                dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
                                               &dev->i2c_adap);
@@ -1300,6 +1310,36 @@ static int dvb_init(struct saa7134_dev *dev)
                                                &dev->i2c_adap);
                attach_xc3028 = 1;
                break;
+       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &asus_tiger_3in1_config,
+                                                       &tda827x_cfg_2) < 0)
+                               goto dettach_frontend;
+               } else {                /* satellite */
+                       dev->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &flydvbs, &dev->i2c_adap);
+                       if (dev->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach,
+                                               dev->dvb.frontend, 0x60,
+                                               &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no "
+                                               "tda826x found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                               if (dvb_attach(lnbp21_attach, dev->dvb.frontend,
+                                               &dev->i2c_adap, 0, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no lnbp21"
+                                               " found!\n", __func__);
+                                       goto dettach_frontend;
+                               }
+                       }
+               }
+               break;
+       case SAA7134_BOARD_ASUSTeK_TIGER:
+               if (configure_tda827x_fe(dev, &philips_tiger_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto dettach_frontend;
+               break;
        default:
                wprintk("Huh? unknown DVB card?\n");
                break;
@@ -1327,6 +1367,8 @@ static int dvb_init(struct saa7134_dev *dev)
                printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
                return -1;
        }
+       /* define general-purpose callback pointer */
+       dev->dvb.frontend->callback = saa7134_tuner_callback;
 
        /* register everything else */
        ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev,
index c0c5d7509c25a81c9fb5fda2c79b74cf2314617a..9a8766a78a0c31f45ddadeb561d4d837662730ba 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <media/saa6752hs.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
 
 /* ------------------------------------------------------------------ */
 
@@ -63,10 +64,19 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
 
 static int ts_init_encoder(struct saa7134_dev* dev)
 {
-       struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 };
+       u32 leading_null_bytes = 0;
 
+       /* If more cards start to need this, then this
+          should probably be added to the card definitions. */
+       switch (dev->board) {
+       case SAA7134_BOARD_BEHOLD_M6:
+       case SAA7134_BOARD_BEHOLD_M63:
+       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+               leading_null_bytes = 1;
+               break;
+       }
        ts_reset_encoder(dev);
-       saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls);
+       saa7134_i2c_call_clients(dev, VIDIOC_INT_INIT, &leading_null_bytes);
        dev->empress_started = 1;
        return 0;
 }
@@ -79,9 +89,11 @@ static int ts_open(struct inode *inode, struct file *file)
        struct saa7134_dev *dev;
        int err;
 
+       lock_kernel();
        list_for_each_entry(dev, &saa7134_devlist, devlist)
                if (dev->empress_dev && dev->empress_dev->minor == minor)
                        goto found;
+       unlock_kernel();
        return -ENODEV;
  found:
 
@@ -103,6 +115,7 @@ static int ts_open(struct inode *inode, struct file *file)
 done_up:
        mutex_unlock(&dev->empress_tsq.vb_lock);
 done:
+       unlock_kernel();
        return err;
 }
 
@@ -290,15 +303,6 @@ static int empress_streamoff(struct file *file, void *priv,
        return videobuf_streamoff(&dev->empress_tsq);
 }
 
-static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
-                                             unsigned int cmd, void *arg)
-{
-       if (dev->mpeg_i2c_client == NULL)
-               return -EINVAL;
-       return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
-                                                               cmd, arg);
-}
-
 static int empress_s_ext_ctrls(struct file *file, void *priv,
                               struct v4l2_ext_controls *ctrls)
 {
@@ -400,6 +404,39 @@ static int empress_querymenu(struct file *file, void *priv,
        return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
 }
 
+static int empress_g_chip_ident(struct file *file, void *fh,
+              struct v4l2_chip_ident *chip)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       if (dev->mpeg_i2c_client == NULL)
+               return -EINVAL;
+       if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+           chip->match_chip == I2C_DRIVERID_SAA6752HS)
+               return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+       if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR &&
+           chip->match_chip == dev->mpeg_i2c_client->addr)
+               return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+       return -EINVAL;
+}
+
+static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_s_std_internal(dev, NULL, id);
+}
+
+static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
+
 static const struct file_operations ts_fops =
 {
        .owner    = THIS_MODULE,
@@ -428,11 +465,13 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
        .vidioc_enum_input              = empress_enum_input,
        .vidioc_g_input                 = empress_g_input,
        .vidioc_s_input                 = empress_s_input,
-
        .vidioc_queryctrl               = empress_queryctrl,
        .vidioc_querymenu               = empress_querymenu,
        .vidioc_g_ctrl                  = empress_g_ctrl,
        .vidioc_s_ctrl                  = empress_s_ctrl,
+       .vidioc_g_chip_ident            = empress_g_chip_ident,
+       .vidioc_s_std                   = empress_s_std,
+       .vidioc_g_std                   = empress_g_std,
 };
 
 /* ----------------------------------------------------------- */
index 5f713e6376839a3cac595821c736866bf1cbcc65..20c1b33caf7b64bbd551a929db1f2a52bbf3da32 100644 (file)
@@ -337,6 +337,7 @@ static int attach_inform(struct i2c_client *client)
                case 0x47:
                case 0x71:
                case 0x2d:
+               case 0x30:
                {
                        struct IR_i2c *ir = i2c_get_clientdata(client);
                        d1printk("%s i2c IR detected (%s).\n",
@@ -427,6 +428,16 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev,
        i2c_clients_command(&dev->i2c_adap, cmd, arg);
 }
 
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+                                             unsigned int cmd, void *arg)
+{
+       if (dev->mpeg_i2c_client == NULL)
+               return -EINVAL;
+       return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
+                                                               cmd, arg);
+}
+EXPORT_SYMBOL_GPL(saa7134_i2c_call_saa6752);
+
 int saa7134_i2c_register(struct saa7134_dev *dev)
 {
        dev->i2c_adap = saa7134_adap_template;
index ad08d13dffdd8eaba60feb65d5d9bfd2c521888b..c53fd5f9f6b553bac073483b5c69ced28f7d6967 100644 (file)
@@ -62,8 +62,11 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
        printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg)
 
-/** rc5 functions */
+/* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
 static int saa7134_rc5_irq(struct saa7134_dev *dev);
+static int saa7134_nec_irq(struct saa7134_dev *dev);
+static void nec_task(unsigned long data);
+static void saa7134_nec_timer(unsigned long data);
 
 /* -------------------- GPIO generic keycode builder -------------------- */
 
@@ -115,6 +118,53 @@ static int build_key(struct saa7134_dev *dev)
 
 /* --------------------- Chip specific I2C key builders ----------------- */
 
+static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
+                                      u32 *ir_raw)
+{
+       unsigned char b;
+       int gpio;
+
+       /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
+       struct saa7134_dev *dev = ir->c.adapter->algo_data;
+       if (dev == NULL) {
+               dprintk("get_key_msi_tvanywhere_plus: "
+                       "gir->c.adapter->algo_data is NULL!\n");
+               return -EIO;
+       }
+
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+       /* GPIO&0x40 is pulsed low when a button is pressed. Don't do
+          I2C receive if gpio&0x40 is not low. */
+
+       if (gpio & 0x40)
+               return 0;       /* No button press */
+
+       /* GPIO says there is a button press. Get it. */
+
+       if (1 != i2c_master_recv(&ir->c, &b, 1)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       /* No button press */
+
+       if (b == 0xff)
+               return 0;
+
+       /* Button pressed */
+
+       dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
 static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
        unsigned char b;
@@ -280,7 +330,9 @@ void saa7134_input_irq(struct saa7134_dev *dev)
 {
        struct card_ir *ir = dev->remote;
 
-       if (!ir->polling && !ir->rc5_gpio) {
+       if (ir->nec_gpio) {
+               saa7134_nec_irq(dev);
+       } else if (!ir->polling && !ir->rc5_gpio) {
                build_key(dev);
        } else if (ir->rc5_gpio) {
                saa7134_rc5_irq(dev);
@@ -316,6 +368,10 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
                ir->addr = 0x17;
                ir->rc5_key_timeout = ir_rc5_key_timeout;
                ir->rc5_remote_gap = ir_rc5_remote_gap;
+       } else if (ir->nec_gpio) {
+               setup_timer(&ir->timer_keyup, saa7134_nec_timer,
+                           (unsigned long)dev);
+               tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
        }
 }
 
@@ -335,6 +391,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        u32 mask_keyup   = 0;
        int polling      = 0;
        int rc5_gpio     = 0;
+       int nec_gpio     = 0;
        int ir_type      = IR_TYPE_OTHER;
        int err;
 
@@ -391,6 +448,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
                saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
                break;
+       case SAA7134_BOARD_AVERMEDIA_M135A:
+               ir_codes     = ir_codes_avermedia_m135a;
+               mask_keydown = 0x0040000;
+               mask_keycode = 0x00013f;
+               nec_gpio     = 1;
+               break;
        case SAA7134_BOARD_AVERMEDIA_777:
        case SAA7134_BOARD_AVERMEDIA_A16AR:
                ir_codes     = ir_codes_avermedia;
@@ -499,6 +562,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                mask_keyup   = 0x040000;
                polling      = 50; // ms
                break;
+       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+               ir_codes     = ir_codes_encore_enltv_fm53;
+               mask_keydown = 0x0040000;
+               mask_keycode = 0x00007f;
+               nec_gpio = 1;
+               break;
        case SAA7134_BOARD_10MOONSTVMASTER3:
                ir_codes     = ir_codes_encore_enltv;
                mask_keycode = 0x5f80000;
@@ -511,6 +580,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                mask_keydown = 0xf00000;
                polling = 50; /* ms */
                break;
+       case SAA7134_BOARD_REAL_ANGEL_220:
+               ir_codes     = ir_codes_real_audio_220_32_keys;
+               mask_keycode = 0x3f00;
+               mask_keyup   = 0x4000;
+               polling = 50; /* ms */
+               break;
        }
        if (NULL == ir_codes) {
                printk("%s: Oops: IR config error [card=%d]\n",
@@ -533,6 +608,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        ir->mask_keyup   = mask_keyup;
        ir->polling      = polling;
        ir->rc5_gpio     = rc5_gpio;
+       ir->nec_gpio     = nec_gpio;
 
        /* init input device */
        snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
@@ -612,6 +688,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
                ir->get_key   = get_key_purpletv;
                ir->ir_codes  = ir_codes_purpletv;
                break;
+       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
+               snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus");
+               ir->get_key  = get_key_msi_tvanywhere_plus;
+               ir->ir_codes = ir_codes_msi_tvanywhere_plus;
+               break;
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
                snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
                ir->get_key   = get_key_hvr1110;
@@ -675,8 +756,125 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev)
        return 1;
 }
 
-/* ----------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
+
+/* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
+   The first pulse (start) has 9 + 4.5 ms
  */
+
+static void saa7134_nec_timer(unsigned long data)
+{
+       struct saa7134_dev *dev = (struct saa7134_dev *) data;
+       struct card_ir *ir = dev->remote;
+
+       dprintk("Cancel key repeat\n");
+
+       ir_input_nokey(ir->dev, &ir->ir);
+}
+
+static void nec_task(unsigned long data)
+{
+       struct saa7134_dev *dev = (struct saa7134_dev *) data;
+       struct card_ir *ir;
+       struct timeval tv;
+       int count, pulse, oldpulse, gap;
+       u32 ircode = 0, not_code = 0;
+       int ngap = 0;
+
+       if (!data) {
+               printk(KERN_ERR "saa713x/ir: Can't recover dev struct\n");
+               /* GPIO will be kept disabled */
+               return;
+       }
+
+       ir = dev->remote;
+
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       oldpulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
+       pulse = oldpulse;
+
+       do_gettimeofday(&tv);
+       ir->base_time = tv;
+
+       /* Decode NEC pulsecode. This code can take up to 76.5 ms to run.
+          Unfortunately, using IRQ to decode pulse didn't work, since it uses
+          a pulse train of 38KHz. This means one pulse on each 52 us
+        */
+       do {
+               /* Wait until the end of pulse/space or 5 ms */
+               for (count = 0; count < 500; count++)  {
+                       udelay(10);
+                       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+                       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+                       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+                       pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
+                               & ir->mask_keydown;
+                       if (pulse != oldpulse)
+                               break;
+               }
+
+               do_gettimeofday(&tv);
+               gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+                               tv.tv_usec - ir->base_time.tv_usec;
+
+               if (!pulse) {
+                       /* Bit 0 has 560 us, while bit 1 has 1120 us.
+                          Do something only if bit == 1
+                        */
+                       if (ngap && (gap > 560 + 280)) {
+                               unsigned int shift = ngap - 1;
+
+                               /* Address first, then command */
+                               if (shift < 8) {
+                                       shift += 8;
+                                       ircode |= 1 << shift;
+                               } else if (shift < 16) {
+                                       not_code |= 1 << shift;
+                               } else if (shift < 24) {
+                                       shift -= 16;
+                                       ircode |= 1 << shift;
+                               } else {
+                                       shift -= 24;
+                                       not_code |= 1 << shift;
+                               }
+                       }
+                       ngap++;
+               }
+
+
+               ir->base_time = tv;
+
+               /* TIMEOUT - Long pulse */
+               if (gap >= 5000)
+                       break;
+               oldpulse = pulse;
+       } while (ngap < 32);
+
+       if (ngap == 32) {
+               /* FIXME: should check if not_code == ~ircode */
+               ir->code = ir_extract_bits(ircode, ir->mask_keycode);
+
+               dprintk("scancode = 0x%02x (code = 0x%02x, notcode= 0x%02x)\n",
+                        ir->code, ircode, not_code);
+
+               ir_input_keydown(ir->dev, &ir->ir, ir->code, ir->code);
+       } else
+               dprintk("Repeat last key\n");
+
+       /* Keep repeating the last key */
+       mod_timer(&ir->timer_keyup, jiffies + msecs_to_jiffies(150));
+
+       saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
+}
+
+static int saa7134_nec_irq(struct saa7134_dev *dev)
+{
+       struct card_ir *ir = dev->remote;
+
+       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
+       tasklet_schedule(&ir->tlet);
+
+       return 1;
+}
index eae72fd60cec6f6b3aa888d4bb380cb62cc10209..ef55a59f0cda59623cec062bea0a313051d8857a 100644 (file)
@@ -66,11 +66,29 @@ static int buffer_activate(struct saa7134_dev *dev,
        saa7134_set_dmabits(dev);
 
        mod_timer(&dev->ts_q.timeout, jiffies+BUFFER_TIMEOUT);
+
+       if (dev->ts_state == SAA7134_TS_BUFF_DONE) {
+               /* Clear TS cache */
+               dev->buff_cnt = 0;
+               saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+               saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+               saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+               saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+               /* TS clock non-inverted */
+               saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+               /* Start TS stream */
+               saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+               saa_writeb(SAA7134_TS_PARALLEL, 0xEC);
+               dev->ts_state = SAA7134_TS_STARTED;
+       }
+
        return 0;
 }
 
 static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-                         enum v4l2_field field)
+               enum v4l2_field field)
 {
        struct saa7134_dev *dev = q->priv_data;
        struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
@@ -110,16 +128,22 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
                        goto oops;
        }
 
-       /* dma: setup channel 5 (= TS) */
-       control = SAA7134_RS_CONTROL_BURST_16 |
-                 SAA7134_RS_CONTROL_ME |
-                 (buf->pt->dma >> 12);
-
-       saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff));
-       saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff));
-       saa_writeb(SAA7134_TS_DMA2, ((((lines-1)>>16)&0x3f) | 0x00)); /* TSNOPIT=0, TSCOLAP=0 */
-       saa_writel(SAA7134_RS_PITCH(5),TS_PACKET_SIZE);
-       saa_writel(SAA7134_RS_CONTROL(5),control);
+       dev->buff_cnt++;
+
+       if (dev->buff_cnt == dev->ts.nr_bufs) {
+               dev->ts_state = SAA7134_TS_BUFF_DONE;
+               /* dma: setup channel 5 (= TS) */
+               control = SAA7134_RS_CONTROL_BURST_16 |
+                       SAA7134_RS_CONTROL_ME |
+                       (buf->pt->dma >> 12);
+
+               saa_writeb(SAA7134_TS_DMA0, (lines - 1) & 0xff);
+               saa_writeb(SAA7134_TS_DMA1, ((lines - 1) >> 8) & 0xff);
+               /* TSNOPIT=0, TSCOLAP=0 */
+               saa_writeb(SAA7134_TS_DMA2, (((lines - 1) >> 16) & 0x3f) | 0x00);
+               saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+               saa_writel(SAA7134_RS_CONTROL(5), control);
+       }
 
        buf->vb.state = VIDEOBUF_PREPARED;
        buf->activate = buffer_activate;
@@ -140,6 +164,8 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
        if (0 == *count)
                *count = dev->ts.nr_bufs;
        *count = saa7134_buffer_count(*size,*count);
+       dev->buff_cnt = 0;
+       dev->ts_state = SAA7134_TS_STOPPED;
        return 0;
 }
 
@@ -154,7 +180,13 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 {
        struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+       struct saa7134_dev *dev = q->priv_data;
 
+       if (dev->ts_state == SAA7134_TS_STARTED) {
+               /* Stop TS transport */
+               saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+               dev->ts_state = SAA7134_TS_STOPPED;
+       }
        saa7134_dma_free(q,buf);
 }
 
@@ -182,7 +214,7 @@ int saa7134_ts_init_hw(struct saa7134_dev *dev)
        /* deactivate TS softreset */
        saa_writeb(SAA7134_TS_SERIAL1, 0x00);
        /* TSSOP high active, TSVAL high active, TSLOCK ignored */
-       saa_writeb(SAA7134_TS_PARALLEL, 0xec);
+       saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
        saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
        saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
        saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
index 68c268981861dee9e8abc93e640a036480eecce8..02bb6747a39c846fa7c19c288e9703054c1c40d5 100644 (file)
@@ -628,6 +628,9 @@ void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
 
        if (card_in(dev, dev->ctl_input).tv)
                saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
+       /* Set the correct norm for the saa6752hs. This function
+          does nothing if there is no saa6752hs. */
+       saa7134_i2c_call_saa6752(dev, VIDIOC_S_STD, &dev->tvnorm->id);
 }
 
 static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
@@ -1330,6 +1333,8 @@ static int video_open(struct inode *inode, struct file *file)
        struct saa7134_fh *fh;
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        int radio = 0;
+
+       lock_kernel();
        list_for_each_entry(dev, &saa7134_devlist, devlist) {
                if (dev->video_dev && (dev->video_dev->minor == minor))
                        goto found;
@@ -1342,6 +1347,7 @@ static int video_open(struct inode *inode, struct file *file)
                        goto found;
                }
        }
+       unlock_kernel();
        return -ENODEV;
  found:
 
@@ -1350,8 +1356,10 @@ static int video_open(struct inode *inode, struct file *file)
 
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
+       if (NULL == fh) {
+               unlock_kernel();
                return -ENOMEM;
+       }
        file->private_data = fh;
        fh->dev      = dev;
        fh->radio    = radio;
@@ -1384,6 +1392,7 @@ static int video_open(struct inode *inode, struct file *file)
                /* switch to video/vbi mode */
                video_mux(dev,dev->ctl_input);
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1790,18 +1799,25 @@ static int saa7134_querycap(struct file *file, void  *priv,
                return 0;
 }
 
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
        unsigned long flags;
        unsigned int i;
        v4l2_std_id fixup;
        int err;
 
-       err = v4l2_prio_check(&dev->prio, &fh->prio);
-       if (0 != err)
-               return err;
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       } else if (res_locked(dev, RESOURCE_OVERLAY)) {
+               /* Don't change the std from the mpeg device
+                  if overlay is active. */
+               return -EBUSY;
+       }
 
        for (i = 0; i < TVNORMS; i++)
                if (*id == tvnorms[i].id)
@@ -1834,7 +1850,7 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
        *id = tvnorms[i].id;
 
        mutex_lock(&dev->lock);
-       if (res_check(fh, RESOURCE_OVERLAY)) {
+       if (fh && res_check(fh, RESOURCE_OVERLAY)) {
                spin_lock_irqsave(&dev->slock, flags);
                stop_preview(dev, fh);
                spin_unlock_irqrestore(&dev->slock, flags);
@@ -1851,6 +1867,23 @@ static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
        mutex_unlock(&dev->lock);
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_s_std_internal(fh->dev, fh, id);
+}
+
+static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
 
 static int saa7134_cropcap(struct file *file, void *priv,
                                        struct v4l2_cropcap *cap)
@@ -2077,18 +2110,6 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
        return 0;
 }
 
-static int saa7134_enum_fmt_vbi_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (0 != f->index)
-               return -EINVAL;
-
-       f->pixelformat = V4L2_PIX_FMT_GREY;
-       strcpy(f->description, "vbi data");
-
-       return 0;
-}
-
 static int saa7134_g_fbuf(struct file *file, void *f,
                                struct v4l2_framebuffer *fb)
 {
@@ -2379,7 +2400,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_g_fmt_vid_overlay       = saa7134_g_fmt_vid_overlay,
        .vidioc_try_fmt_vid_overlay     = saa7134_try_fmt_vid_overlay,
        .vidioc_s_fmt_vid_overlay       = saa7134_s_fmt_vid_overlay,
-       .vidioc_enum_fmt_vbi_cap        = saa7134_enum_fmt_vbi_cap,
        .vidioc_g_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
        .vidioc_try_fmt_vbi_cap         = saa7134_try_get_set_fmt_vbi_cap,
        .vidioc_s_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
@@ -2391,6 +2411,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_qbuf                    = saa7134_qbuf,
        .vidioc_dqbuf                   = saa7134_dqbuf,
        .vidioc_s_std                   = saa7134_s_std,
+       .vidioc_g_std                   = saa7134_g_std,
        .vidioc_enum_input              = saa7134_enum_input,
        .vidioc_g_input                 = saa7134_g_input,
        .vidioc_s_input                 = saa7134_s_input,
index a0884f639f6504b6826c9e791107f3bbe3f9f06c..491ab1f8fdd3cbadba1a3421e8dfc2cd30bb6340 100644 (file)
@@ -269,6 +269,12 @@ struct saa7134_format {
 #define SAA7134_BOARD_BEHOLD_M6_EXTRA    144
 #define SAA7134_BOARD_AVERMEDIA_M103    145
 #define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
+#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1   147
+#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148
+#define SAA7134_BOARD_AVERMEDIA_M135A    149
+#define SAA7134_BOARD_REAL_ANGEL_220     150
+#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI  151
+#define SAA7134_BOARD_ASUSTeK_TIGER         152
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -462,6 +468,12 @@ struct saa7134_mpeg_ops {
        void                       (*signal_change)(struct saa7134_dev *dev);
 };
 
+enum saa7134_ts_status {
+       SAA7134_TS_STOPPED,
+       SAA7134_TS_BUFF_DONE,
+       SAA7134_TS_STARTED,
+};
+
 /* global device status */
 struct saa7134_dev {
        struct list_head           devlist;
@@ -555,6 +567,8 @@ struct saa7134_dev {
        /* SAA7134_MPEG_* */
        struct saa7134_ts          ts;
        struct saa7134_dmaqueue    ts_q;
+       enum saa7134_ts_status     ts_state;
+       unsigned int               buff_cnt;
        struct saa7134_mpeg_ops    *mops;
        struct i2c_client          *mpeg_i2c_client;
 
@@ -644,7 +658,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[];
 
 extern int saa7134_board_init1(struct saa7134_dev *dev);
 extern int saa7134_board_init2(struct saa7134_dev *dev);
-int saa7134_tuner_callback(void *priv, int command, int arg);
+int saa7134_tuner_callback(void *priv, int component, int command, int arg);
 
 
 /* ----------------------------------------------------------- */
@@ -654,6 +668,8 @@ int saa7134_i2c_register(struct saa7134_dev *dev);
 int saa7134_i2c_unregister(struct saa7134_dev *dev);
 void saa7134_i2c_call_clients(struct saa7134_dev *dev,
                              unsigned int cmd, void *arg);
+int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
+                             unsigned int cmd, void *arg);
 
 
 /* ----------------------------------------------------------- */
@@ -666,6 +682,7 @@ extern struct video_device saa7134_radio_template;
 int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
 int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
+int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id *id);
 
 int saa7134_videoport_init(struct saa7134_dev *dev);
 void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
index acceed5d04aee9f9a0aa1b0abb4cb1fef52d90f3..ae3949180c4ed3ace8801f67b94c24899e0b916f 100644 (file)
@@ -288,7 +288,7 @@ static void se401_button_irq(struct urb *urb)
        int status;
 
        if (!se401->dev) {
-               info("ohoh: device vapourished");
+               dev_info(&urb->dev->dev, "device vapourished\n");
                return;
        }
 
@@ -328,7 +328,7 @@ static void se401_video_irq(struct urb *urb)
                return;
 
        if (!se401->dev) {
-               info ("ohoh: device vapourished");
+               dev_info(&urb->dev->dev, "device vapourished\n");
                return;
        }
 
@@ -375,7 +375,7 @@ static void se401_video_irq(struct urb *urb)
        urb->status=0;
        urb->dev=se401->dev;
        if(usb_submit_urb(urb, GFP_KERNEL))
-               info("urb burned down");
+               dev_info(&urb->dev->dev, "urb burned down\n");
        return;
 }
 
@@ -860,7 +860,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr)
                );
                if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
                        se401->nullpackets=0;
-                       info("to many null length packets, restarting capture");
+                       dev_info(&se401->dev->dev,
+                                "too many null length packets, restarting capture\n");
                        se401_stop_stream(se401);
                        se401_start_stream(se401);
                } else {
@@ -880,7 +881,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr)
                                se401->scratch_use=0;
                        if (errors > SE401_MAX_ERRORS) {
                                errors=0;
-                               info("to much errors, restarting capture");
+                               dev_info(&se401->dev->dev,
+                                        "too many errors, restarting capture\n");
                                se401_stop_stream(se401);
                                se401_start_stream(se401);
                        }
@@ -913,7 +915,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
                usb_kill_urb(se401->inturb);
                usb_free_urb(se401->inturb);
        }
-       info("%s disconnected", se401->camera_name);
+       dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name);
 
        /* Free the memory */
        kfree(se401->width);
@@ -936,14 +938,18 @@ static int se401_open(struct inode *inode, struct file *file)
        struct usb_se401 *se401 = (struct usb_se401 *)dev;
        int err = 0;
 
-       if (se401->user)
+       lock_kernel();
+       if (se401->user) {
+               unlock_kernel();
                return -EBUSY;
+       }
        se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
        if (se401->fbuf)
                file->private_data = dev;
        else
                err = -ENOMEM;
        se401->user = !err;
+       unlock_kernel();
 
        return err;
 }
@@ -956,8 +962,8 @@ static int se401_close(struct inode *inode, struct file *file)
 
        rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
        if (se401->removed) {
+               dev_info(&se401->dev->dev, "device unregistered\n");
                usb_se401_remove_disconnected(se401);
-               info("device unregistered");
        } else {
                for (i=0; i<SE401_NUMFRAMES; i++)
                        se401->frame[i].grabstate=FRAME_UNUSED;
@@ -1232,6 +1238,7 @@ static const struct file_operations se401_fops = {
 static struct video_device se401_template = {
        .name =         "se401 USB camera",
        .fops =         &se401_fops,
+       .release = video_device_release_empty,
 };
 
 
@@ -1271,7 +1278,7 @@ static int se401_init(struct usb_se401 *se401, int button)
        for (i=0; i<se401->sizes; i++) {
                sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
        }
-       info("%s", temp);
+       dev_info(&se401->dev->dev, "%s\n", temp);
        se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
 
        rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
@@ -1305,7 +1312,8 @@ static int se401_init(struct usb_se401 *se401, int button)
        if (button) {
                se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
                if (!se401->inturb) {
-                       info("Allocation of inturb failed");
+                       dev_info(&se401->dev->dev,
+                                "Allocation of inturb failed\n");
                        return 1;
                }
                usb_fill_int_urb(se401->inturb, se401->dev,
@@ -1316,7 +1324,7 @@ static int se401_init(struct usb_se401 *se401, int button)
                    8
                );
                if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
-                       info("int urb burned down");
+                       dev_info(&se401->dev->dev, "int urb burned down\n");
                        return 1;
                }
        } else
@@ -1373,7 +1381,7 @@ static int se401_probe(struct usb_interface *intf,
                return -ENODEV;
 
        /* We found one */
-       info("SE401 camera found: %s", camera_name);
+       dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
 
        if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
                err("couldn't kmalloc se401 struct");
@@ -1384,7 +1392,8 @@ static int se401_probe(struct usb_interface *intf,
        se401->iface = interface->bInterfaceNumber;
        se401->camera_name = camera_name;
 
-       info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
+       dev_info(&intf->dev, "firmware version: %02x\n",
+                le16_to_cpu(dev->descriptor.bcdDevice) & 255);
 
        if (se401_init(se401, button)) {
                kfree(se401);
@@ -1402,7 +1411,8 @@ static int se401_probe(struct usb_interface *intf,
                err("video_register_device failed");
                return -EIO;
        }
-       info("registered new video device: video%d", se401->vdev.minor);
+       dev_info(&intf->dev, "registered new video device: video%d\n",
+                se401->vdev.minor);
 
        usb_set_intfdata (intf, se401);
        return 0;
@@ -1446,10 +1456,10 @@ static struct usb_driver se401_driver = {
 
 static int __init usb_se401_init(void)
 {
-       info("SE401 usb camera driver version %s registering", version);
+       printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version);
        if (flickerless)
                if (flickerless!=50 && flickerless!=60) {
-                       info("Invallid flickerless value, use 0, 50 or 60.");
+                       printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
                        return -1;
        }
        return usb_register(&se401_driver);
@@ -1458,7 +1468,7 @@ static int __init usb_se401_init(void)
 static void __exit usb_se401_exit(void)
 {
        usb_deregister(&se401_driver);
-       info("SE401 driver deregistered");
+       printk(KERN_INFO "SE401 driver deregistered\frame");
 }
 
 module_init(usb_se401_init);
index 318754e731326ee1bdd92a76b829d23736e1cf79..76838091dc66ce05140b63912ec106422e2bc542 100644 (file)
@@ -304,9 +304,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
                 "SuperH Mobile CEU driver attached to camera %d\n",
                 icd->devnum);
 
-       if (pcdev->pdata->enable_camera)
-               pcdev->pdata->enable_camera();
-
        ret = icd->ops->init(icd);
        if (ret)
                goto err;
@@ -333,8 +330,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
        ceu_write(pcdev, CEIER, 0);
        ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
        icd->ops->release(icd);
-       if (pcdev->pdata->disable_camera)
-               pcdev->pdata->disable_camera();
 
        dev_info(&icd->dev,
                 "SuperH Mobile CEU driver detached from camera %d\n",
index 2da6938718f2c1a7969065f24b575d4615afdea5..20e30bd9364be9eb3d988079e8764029ed8543c9 100644 (file)
@@ -116,6 +116,26 @@ MODULE_PARM_DESC(debug,
                 "\n");
 #endif
 
+/*
+   Add the probe 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.
+*/
+static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
+       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+       &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
+       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
+};
+
 /*****************************************************************************/
 
 static u32
@@ -1746,7 +1766,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
        if (!down_read_trylock(&sn9c102_dev_lock))
                return -ERESTARTSYS;
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        if (wait_for_completion_interruptible(&cam->probe)) {
                up_read(&sn9c102_dev_lock);
@@ -1843,7 +1863,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 
        down_write(&sn9c102_dev_lock);
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        sn9c102_stop_transfer(cam);
        sn9c102_release_buffers(cam);
@@ -1863,7 +1883,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 static ssize_t
 sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
 {
-       struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+       struct sn9c102_device *cam = video_drvdata(filp);
        struct sn9c102_frame_t* f, * i;
        unsigned long lock_flags;
        long timeout;
@@ -1987,7 +2007,7 @@ exit:
 
 static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
 {
-       struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+       struct sn9c102_device *cam = video_drvdata(filp);
        struct sn9c102_frame_t* f;
        unsigned long lock_flags;
        unsigned int mask = 0;
@@ -2063,7 +2083,7 @@ static struct vm_operations_struct sn9c102_vm_ops = {
 
 static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
 {
-       struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+       struct sn9c102_device *cam = video_drvdata(filp);
        unsigned long size = vma->vm_end - vma->vm_start,
                      start = vma->vm_start;
        void *pos;
@@ -3075,7 +3095,7 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
 static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
                              unsigned int cmd, void __user * arg)
 {
-       struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+       struct sn9c102_device *cam = video_drvdata(filp);
 
        switch (cmd) {
 
@@ -3179,7 +3199,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
 static int sn9c102_ioctl(struct inode* inode, struct file* filp,
                         unsigned int cmd, unsigned long arg)
 {
-       struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
+       struct sn9c102_device *cam = video_drvdata(filp);
        int err = 0;
 
        if (mutex_lock_interruptible(&cam->fileop_mutex))
index 90a401dc38849b20cba1fe16cffba82e2f3fe16f..e23734f6d6e2255535875b297204585ebb8d0478 100644 (file)
@@ -140,24 +140,4 @@ extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5110d(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
-   place, since, on failure, the next probing routine is called according to
-   the order of the list below, from top to bottom.
-*/
-static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
-       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
-       &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
-       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-};
-
 #endif /* _SN9C102_DEVTABLE_H_ */
index eaf9ad0dc8a65596a8b5836a161a4d334d34fa87..db2434948939f226c228c110250ec8affd69a868 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int hv7131d_init(struct sn9c102_device* cam)
index 0fc401223cfc9c08741fa3595b93cadf7811f5b3..4295887ff6098b610a50acddfd46a8a3e2f023d4 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int hv7131r_init(struct sn9c102_device* cam)
index 00b134ca0a3d56ac0d122bc15040c9f38cb99633..1f5b09bec89c7ec2f729e18c57848f965fa4ef76 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int mi0343_init(struct sn9c102_device* cam)
index f8d81d82e8d50e537ea85004b897e086aa1e4a97..d973fc1973d999fafb44a1434a0b8daf5208c515 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int mi0360_init(struct sn9c102_device* cam)
index 3b98ac3bbc38013a8276202a1ae89db8c3d425ae..95986eb492e4b9b065d95e413ff4e80dd2911954 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int mt9v111_init(struct sn9c102_device *cam)
index e4856fd779823af7c0bd508f1c313b1673453245..803712c29f020edd0dc2bbbd00483a334e89d93b 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int ov7630_init(struct sn9c102_device* cam)
index 8aae416ba8ec236bf06c88cc67ffbfb32e6a575c..7977795d342b73b7d8d0f20773cf61e29ab0a934 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int ov7660_init(struct sn9c102_device* cam)
index 360f2a848bc018212b8b8a3052f91d5787400cfe..81cd969c1b7b19d7e1472071403d1427dfec8bb6 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/delay.h>
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int pas106b_init(struct sn9c102_device* cam)
index ca4a1506ed3df7cee74976afb2973d41152bf15e..2782f94cf6f80e7c04cb84b93c2994f2bb018d7b 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/delay.h>
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int pas202bcb_init(struct sn9c102_device* cam)
index e7d2de2bace1096d837f16de2d03c39ce6c92f95..04cdfdde8564d3f9697cf2f772c136ad11c0ebd5 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int tas5110c1b_init(struct sn9c102_device* cam)
index d32fdbccdc5eb3fbbcc8fe5f083887f8049d284f..9372e6f9fcff72ecf620dc5f4fdb188661468070 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int tas5110d_init(struct sn9c102_device* cam)
index 56fb1d575a8a6fd74a247de569a5e3d323c97080..a30bbc4389f5d9d2cbb8d98391784897a32292be 100644 (file)
@@ -20,6 +20,7 @@
  ***************************************************************************/
 
 #include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
 
 
 static int tas5130d1b_init(struct sn9c102_device* cam)
index ad36af30e0992195fa1f72da85428f394d4251a4..db69bc5556d6776c84a51c78f7460f927d04d350 100644 (file)
@@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, stkwebcam_table);
 
-static void stk_camera_cleanup(struct kref *kref)
-{
-       struct stk_camera *dev = to_stk_camera(kref);
-
-       STK_INFO("Syntek USB2.0 Camera release resources"
-               " video device /dev/video%d\n", dev->vdev.minor);
-       video_unregister_device(&dev->vdev);
-       dev->vdev.priv = NULL;
-
-       if (dev->sio_bufs != NULL || dev->isobufs != NULL)
-               STK_ERROR("We are leaking memory\n");
-       usb_put_intf(dev->interface);
-       kfree(dev);
-}
-
-
 /*
  * Basic stuff
  */
@@ -689,34 +673,24 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
        vdev = video_devdata(fp);
        dev = vdev_to_camera(vdev);
 
-       if (dev == NULL || !is_present(dev))
+       lock_kernel();
+       if (dev == NULL || !is_present(dev)) {
+               unlock_kernel();
                return -ENXIO;
-       fp->private_data = vdev;
-       kref_get(&dev->kref);
+       }
+       fp->private_data = dev;
        usb_autopm_get_interface(dev->interface);
+       unlock_kernel();
 
        return 0;
 }
 
 static int v4l_stk_release(struct inode *inode, struct file *fp)
 {
-       struct stk_camera *dev;
-       struct video_device *vdev;
-
-       vdev = video_devdata(fp);
-       if (vdev == NULL) {
-               STK_ERROR("v4l_release called w/o video devdata\n");
-               return -EFAULT;
-       }
-       dev = vdev_to_camera(vdev);
-       if (dev == NULL) {
-               STK_ERROR("v4l_release called on removed device\n");
-               return -ENODEV;
-       }
+       struct stk_camera *dev = fp->private_data;
 
        if (dev->owner != fp) {
                usb_autopm_put_interface(dev->interface);
-               kref_put(&dev->kref, stk_camera_cleanup);
                return 0;
        }
 
@@ -727,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
        dev->owner = NULL;
 
        usb_autopm_put_interface(dev->interface);
-       kref_put(&dev->kref, stk_camera_cleanup);
 
        return 0;
 }
@@ -738,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
        int i;
        int ret;
        unsigned long flags;
-       struct stk_camera *dev;
-       struct video_device *vdev;
        struct stk_sio_buffer *sbuf;
-
-       vdev = video_devdata(fp);
-       if (vdev == NULL)
-               return -EFAULT;
-       dev = vdev_to_camera(vdev);
+       struct stk_camera *dev = fp->private_data;
 
        if (dev == NULL)
                return -EIO;
@@ -804,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
 
 static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
 {
-       struct stk_camera *dev;
-       struct video_device *vdev;
-
-       vdev = video_devdata(fp);
-
-       if (vdev == NULL)
-               return -EFAULT;
+       struct stk_camera *dev = fp->private_data;
 
-       dev = vdev_to_camera(vdev);
        if (dev == NULL)
                return -ENODEV;
 
@@ -850,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
        unsigned int i;
        int ret;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       struct stk_camera *dev;
-       struct video_device *vdev;
+       struct stk_camera *dev = fp->private_data;
        struct stk_sio_buffer *sbuf = NULL;
 
        if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
                return -EINVAL;
 
-       vdev = video_devdata(fp);
-       dev = vdev_to_camera(vdev);
-
        for (i = 0; i < dev->n_sbufs; i++) {
                if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
                        sbuf = dev->sio_bufs + i;
@@ -1355,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
 
 static void stk_v4l_dev_release(struct video_device *vd)
 {
+       struct stk_camera *dev = vdev_to_camera(vd);
+
+       if (dev->sio_bufs != NULL || dev->isobufs != NULL)
+               STK_ERROR("We are leaking memory\n");
+       usb_put_intf(dev->interface);
+       kfree(dev);
 }
 
 static struct video_device stk_v4l_data = {
@@ -1375,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev)
        dev->vdev = stk_v4l_data;
        dev->vdev.debug = debug;
        dev->vdev.parent = &dev->interface->dev;
-       dev->vdev.priv = dev;
        err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
        if (err)
                STK_ERROR("v4l registration failed\n");
@@ -1392,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface,
                const struct usb_device_id *id)
 {
        int i;
-       int err;
+       int err = 0;
 
        struct stk_camera *dev = NULL;
        struct usb_device *udev = interface_to_usbdev(interface);
@@ -1405,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface,
                return -ENOMEM;
        }
 
-       kref_init(&dev->kref);
        spin_lock_init(&dev->spinlock);
        init_waitqueue_head(&dev->wait_frame);
 
@@ -1438,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface,
        }
        if (!dev->isoc_ep) {
                STK_ERROR("Could not find isoc-in endpoint");
-               kref_put(&dev->kref, stk_camera_cleanup);
-               return -ENODEV;
+               err = -ENODEV;
+               goto error;
        }
        dev->vsettings.brightness = 0x7fff;
        dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
@@ -1453,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface,
 
        err = stk_register_video_device(dev);
        if (err) {
-               kref_put(&dev->kref, stk_camera_cleanup);
-               return err;
+               goto error;
        }
 
        stk_create_sysfs_files(&dev->vdev);
        usb_autopm_enable(dev->interface);
 
        return 0;
+
+error:
+       kfree(dev);
+       return err;
 }
 
 static void stk_camera_disconnect(struct usb_interface *interface)
@@ -1473,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface)
        wake_up_interruptible(&dev->wait_frame);
        stk_remove_sysfs_files(&dev->vdev);
 
-       kref_put(&dev->kref, stk_camera_cleanup);
+       STK_INFO("Syntek USB2.0 Camera release resources"
+               "video device /dev/video%d\n", dev->vdev.minor);
+
+       video_unregister_device(&dev->vdev);
 }
 
 #ifdef CONFIG_PM
index df4dfefc5327e1652ae607c6fb903af214092b10..084a85bdd16e642a49d27175a68677cbd2d8bda2 100644 (file)
@@ -99,7 +99,6 @@ struct stk_camera {
 
        u8 isoc_ep;
 
-       struct kref kref;
        /* Not sure if this is right */
        atomic_t urbs_used;
 
@@ -121,7 +120,6 @@ struct stk_camera {
        unsigned sequence;
 };
 
-#define to_stk_camera(d) container_of(d, struct stk_camera, kref)
 #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
 
 void stk_camera_delete(struct kref *);
index 276bded06ab3eb9ac9b7f9414000b1918d81ce24..bbad54f85c83c83a92d8d4d41cdedf70af3b1803 100644 (file)
@@ -1882,12 +1882,16 @@ static int saa_open(struct inode *inode, struct file *file)
        struct video_device *vdev = video_devdata(file);
        struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
 
+       lock_kernel();
        file->private_data = saa;
 
        saa->user++;
-       if (saa->user > 1)
+       if (saa->user > 1) {
+               unlock_kernel();
                return 0;       /* device open already, don't reset */
+       }
        saa->writemode = VID_WRITE_MPEG_VID;    /* default to video */
+       unlock_kernel();
        return 0;
 }
 
@@ -1921,6 +1925,7 @@ static struct video_device saa_template = {
        .name = "SAA7146A",
        .fops = &saa_fops,
        .minor = -1,
+       .release = video_device_release_empty,
 };
 
 static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
index dce947439459ca46e2d020b49440a318a6c9e20c..9c549d93599426c3d0ad53348b481edeb8decb52 100644 (file)
@@ -84,7 +84,8 @@ static unsigned int debug;
 #define PDEBUG(level, fmt, args...) \
        do { \
        if (debug >= level)     \
-               info("[%s:%d] " fmt, __func__, __LINE__ , ## args);     \
+               printk(KERN_INFO KBUILD_MODNAME " [%s:%d] \n" fmt,      \
+                       __func__, __LINE__ , ## args);  \
        } while (0)
 
 
@@ -1086,6 +1087,7 @@ static int stv_open (struct inode *inode, struct file *file)
        int err = 0;
 
        /* we are called with the BKL held */
+       lock_kernel();
        stv680->user = 1;
        err = stv_init (stv680);        /* main initialization routine for camera */
 
@@ -1099,6 +1101,7 @@ static int stv_open (struct inode *inode, struct file *file)
        }
        if (err)
                stv680->user = 0;
+       unlock_kernel();
 
        return err;
 }
@@ -1550,7 +1553,8 @@ static int __init usb_stv680_init (void)
        }
        PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
 
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
        return 0;
 }
 
index 2437c1a269c58e98890ecf3f91c811c5d577938f..1c391f0328fd195c1f977956cae06d5ab02428fa 100644 (file)
@@ -2,6 +2,7 @@
     tda9840 - i2c-driver for the tda9840 by SGS Thomson
 
     Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
 
     The tda9840 is a stereo/dual sound processor with digital
     identification. It can be found at address 0x84 on the i2c-bus.
 #include <linux/module.h>
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 #include "tda9840.h"
 
-static int debug;              /* insmod parameter */
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tda9840 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
-#define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 #define        SWITCH          0x00
 #define        LEVEL_ADJUST    0x02
 #define        STEREO_ADJUST   0x03
 #define        TEST            0x04
 
+#define TDA9840_SET_MUTE                0x00
+#define TDA9840_SET_MONO                0x10
+#define TDA9840_SET_STEREO              0x2a
+#define TDA9840_SET_LANG1               0x12
+#define TDA9840_SET_LANG2               0x1e
+#define TDA9840_SET_BOTH                0x1a
+#define TDA9840_SET_BOTH_R              0x16
+#define TDA9840_SET_EXTERNAL            0x7a
+
 /* addresses to scan, found only at 0x42 (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
+static void tda9840_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       if (i2c_smbus_write_byte_data(client, reg, val))
+               v4l_dbg(1, debug, client, "error writing %02x to %02x\n",
+                               val, reg);
+}
 
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
-       int result;
        int byte = *(int *)arg;
 
        switch (cmd) {
-       case TDA9840_SWITCH:
-
-               dprintk("TDA9840_SWITCH: 0x%02x\n", byte);
-
-               if (byte != TDA9840_SET_MONO
-                   && byte != TDA9840_SET_MUTE
-                   && byte != TDA9840_SET_STEREO
-                   && byte != TDA9840_SET_LANG1
-                   && byte != TDA9840_SET_LANG2
-                   && byte != TDA9840_SET_BOTH
-                   && byte != TDA9840_SET_BOTH_R
-                   && byte != TDA9840_SET_EXTERNAL) {
+       case VIDIOC_S_TUNER: {
+               struct v4l2_tuner *t = arg;
+               int byte;
+
+               if (t->index)
                        return -EINVAL;
+
+               switch (t->audmode) {
+               case V4L2_TUNER_MODE_STEREO:
+                       byte = TDA9840_SET_STEREO;
+                       break;
+               case V4L2_TUNER_MODE_LANG1_LANG2:
+                       byte = TDA9840_SET_BOTH;
+                       break;
+               case V4L2_TUNER_MODE_LANG1:
+                       byte = TDA9840_SET_LANG1;
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       byte = TDA9840_SET_LANG2;
+                       break;
+               default:
+                       byte = TDA9840_SET_MONO;
+                       break;
+               }
+               v4l_dbg(1, debug, client, "TDA9840_SWITCH: 0x%02x\n", byte);
+               tda9840_write(client, SWITCH, byte);
+               break;
+       }
+
+       case VIDIOC_G_TUNER: {
+               struct v4l2_tuner *t = arg;
+               u8 byte;
+
+               t->rxsubchans = V4L2_TUNER_SUB_MONO;
+               if (1 != i2c_master_recv(client, &byte, 1)) {
+                       v4l_dbg(1, debug, client,
+                               "i2c_master_recv() failed\n");
+                       return -EIO;
                }
 
-               result = i2c_smbus_write_byte_data(client, SWITCH, byte);
-               if (result)
-                       dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+               if (byte & 0x80) {
+                       v4l_dbg(1, debug, client,
+                               "TDA9840_DETECT: register contents invalid\n");
+                       return -EINVAL;
+               }
+
+               v4l_dbg(1, debug, client, "TDA9840_DETECT: byte: 0x%02x\n", byte);
+
+               switch (byte & 0x60) {
+               case 0x00:
+                       t->rxsubchans = V4L2_TUNER_SUB_MONO;
+                       break;
+               case 0x20:
+                       t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+                       break;
+               case 0x40:
+                       t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+                       break;
+               default: /* Incorrect detect */
+                       t->rxsubchans = V4L2_TUNER_MODE_MONO;
+                       break;
+               }
                break;
+       }
 
        case TDA9840_LEVEL_ADJUST:
-
-               dprintk("TDA9840_LEVEL_ADJUST: %d\n", byte);
+               v4l_dbg(1, debug, client, "TDA9840_LEVEL_ADJUST: %d\n", byte);
 
                /* check for correct range */
                if (byte > 25 || byte < -20)
@@ -92,15 +152,11 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
                        byte += 0x8;
                else
                        byte = -byte;
-
-               result = i2c_smbus_write_byte_data(client, LEVEL_ADJUST, byte);
-               if (result)
-                       dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+               tda9840_write(client, LEVEL_ADJUST, byte);
                break;
 
        case TDA9840_STEREO_ADJUST:
-
-               dprintk("TDA9840_STEREO_ADJUST: %d\n", byte);
+               v4l_dbg(1, debug, client, "TDA9840_STEREO_ADJUST: %d\n", byte);
 
                /* check for correct range */
                if (byte > 25 || byte < -24)
@@ -113,143 +169,59 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
                else
                        byte = -byte;
 
-               result = i2c_smbus_write_byte_data(client, STEREO_ADJUST, byte);
-               if (result)
-                       dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
-               break;
-
-       case TDA9840_DETECT: {
-               int *ret = (int *)arg;
-
-               byte = i2c_smbus_read_byte_data(client, STEREO_ADJUST);
-               if (byte == -1) {
-                       dprintk("i2c_smbus_read_byte_data() failed\n");
-                       return -EIO;
-               }
-
-               if (0 != (byte & 0x80)) {
-                       dprintk("TDA9840_DETECT: register contents invalid\n");
-                       return -EINVAL;
-               }
-
-               dprintk("TDA9840_DETECT: byte: 0x%02x\n", byte);
-               *ret = ((byte & 0x60) >> 5);
-               result = 0;
-               break;
-       }
-       case TDA9840_TEST:
-               dprintk("TDA9840_TEST: 0x%02x\n", byte);
-
-               /* mask out irrelevant bits */
-               byte &= 0x3;
-
-               result = i2c_smbus_write_byte_data(client, TEST, byte);
-               if (result)
-                       dprintk("i2c_smbus_write_byte() failed, ret:%d\n", result);
+               tda9840_write(client, STEREO_ADJUST, byte);
                break;
        default:
                return -ENOIOCTLCMD;
        }
 
-       if (result)
-               return -EIO;
-
        return 0;
 }
 
-static int detect(struct i2c_adapter *adapter, int address, int kind)
+static int tda9840_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
-       struct i2c_client *client;
-       int result = 0;
-
-       int byte = 0x0;
+       int result;
+       int byte;
 
        /* let's see whether this adapter can support what we need */
-       if (0 == i2c_check_functionality(adapter,
-                                   I2C_FUNC_SMBUS_READ_BYTE_DATA |
-                                   I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
+       if (!i2c_check_functionality(client->adapter,
+                       I2C_FUNC_SMBUS_READ_BYTE_DATA |
+                       I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
                return 0;
-       }
-
-       /* allocate memory for client structure */
-       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (!client) {
-               printk("not enough kernel memory\n");
-               return -ENOMEM;
-       }
-
-       /* fill client structure */
-       memcpy(client, &client_template, sizeof(struct i2c_client));
-       client->addr = address;
-       client->adapter = adapter;
 
-       /* tell the i2c layer a new client has arrived */
-       if (0 != (result = i2c_attach_client(client))) {
-               kfree(client);
-               return result;
-       }
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
 
        /* set initial values for level & stereo - adjustment, mode */
        byte = 0;
-       result  = command(client, TDA9840_LEVEL_ADJUST, &byte);
-       result += command(client, TDA9840_STEREO_ADJUST, &byte);
-       byte = TDA9840_SET_MONO;
-       result = command(client, TDA9840_SWITCH, &byte);
+       result = tda9840_command(client, TDA9840_LEVEL_ADJUST, &byte);
+       result += tda9840_command(client, TDA9840_STEREO_ADJUST, &byte);
+       tda9840_write(client, SWITCH, TDA9840_SET_STEREO);
        if (result) {
-               dprintk("could not initialize tda9840\n");
+               v4l_dbg(1, debug, client, "could not initialize tda9840\n");
                return -ENODEV;
        }
-
-       printk("tda9840: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
        return 0;
 }
 
-static int attach(struct i2c_adapter *adapter)
-{
-       /* let's see whether this is a know adapter we can attach to */
-       if (adapter->id != I2C_HW_SAA7146) {
-               dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
-               return -ENODEV;
-       }
-
-       return i2c_probe(adapter, &addr_data, &detect);
-}
-
-static int detach(struct i2c_client *client)
+static int tda9840_legacy_probe(struct i2c_adapter *adapter)
 {
-       int ret = i2c_detach_client(client);
-       kfree(client);
-       return ret;
+       /* Let's see whether this is a known adapter we can attach to.
+          Prevents conflicts with tvaudio.c. */
+       return adapter->id == I2C_HW_SAA7146;
 }
-
-static struct i2c_driver driver = {
-       .driver = {
-               .name = "tda9840",
-       },
-       .id     = I2C_DRIVERID_TDA9840,
-       .attach_adapter = attach,
-       .detach_client  = detach,
-       .command        = command,
+static const struct i2c_device_id tda9840_id[] = {
+       { "tda9840", 0 },
+       { }
 };
+MODULE_DEVICE_TABLE(i2c, tda9840_id);
 
-static struct i2c_client client_template = {
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
        .name = "tda9840",
-       .driver = &driver,
+       .driverid = I2C_DRIVERID_TDA9840,
+       .command = tda9840_command,
+       .probe = tda9840_probe,
+       .legacy_probe = tda9840_legacy_probe,
+       .id_table = tda9840_id,
 };
-
-static int __init this_module_init(void)
-{
-       return i2c_add_driver(&driver);
-}
-
-static void __exit this_module_exit(void)
-{
-       i2c_del_driver(&driver);
-}
-
-module_init(this_module_init);
-module_exit(this_module_exit);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tda9840 driver");
-MODULE_LICENSE("GPL");
index 7da8432cdca7378ea1c4879c0e7db27213753d75..dc12ae7caf6f0b3801e37df82e387db1707c168a 100644 (file)
@@ -3,24 +3,6 @@
 
 #define        I2C_ADDR_TDA9840                0x42
 
-#define TDA9840_DETECT         _IOR('v',1,int)
-/* return values for TDA9840_DETCT */
-#define TDA9840_MONO_DETECT            0x0
-#define        TDA9840_DUAL_DETECT             0x1
-#define        TDA9840_STEREO_DETECT           0x2
-#define        TDA9840_INCORRECT_DETECT        0x3
-
-#define TDA9840_SWITCH         _IOW('v',2,int)
-/* modes than can be set with TDA9840_SWITCH */
-#define        TDA9840_SET_MUTE                0x00
-#define        TDA9840_SET_MONO                0x10
-#define        TDA9840_SET_STEREO              0x2a
-#define        TDA9840_SET_LANG1               0x12
-#define        TDA9840_SET_LANG2               0x1e
-#define        TDA9840_SET_BOTH                0x1a
-#define        TDA9840_SET_BOTH_R              0x16
-#define        TDA9840_SET_EXTERNAL            0x7a
-
 /* values may range between +2.5 and -2.0;
    the value has to be multiplied with 10 */
 #define TDA9840_LEVEL_ADJUST   _IOW('v',3,int)
@@ -29,7 +11,4 @@
    the value has to be multiplied with 10 */
 #define TDA9840_STEREO_ADJUST  _IOW('v',4,int)
 
-/* currently not implemented */
-#define TDA9840_TEST           _IOW('v',5,int)
-
 #endif
index 421c1445e96cd5210ceddb22d2156b474292aa70..cde092adbb5abffdd1aafaf0b21d2b566ff20bcd 100644 (file)
@@ -2,6 +2,7 @@
     tea6415c - i2c-driver for the tea6415c by SGS Thomson
 
     Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
 
     The tea6415c is a bus controlled video-matrix-switch
     with 8 inputs and 6 outputs.
 #include <linux/module.h>
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 #include "tea6415c.h"
 
-static int debug;              /* insmod parameter */
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6415c driver");
+MODULE_LICENSE("GPL");
 
-#define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+static int debug;
+module_param(debug, int, 0644);
 
-#define TEA6415C_NUM_INPUTS    8
-#define TEA6415C_NUM_OUTPUTS   6
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */
 static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END };
@@ -49,60 +50,6 @@ static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIEN
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-/* this function is called by i2c_probe */
-static int detect(struct i2c_adapter *adapter, int address, int kind)
-{
-       struct i2c_client *client = NULL;
-       int err = 0;
-
-       /* let's see whether this adapter can support what we need */
-       if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) {
-               return 0;
-       }
-
-       /* allocate memory for client structure */
-       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (!client) {
-               return -ENOMEM;
-       }
-
-       /* fill client structure */
-       memcpy(client, &client_template, sizeof(struct i2c_client));
-       client->addr = address;
-       client->adapter = adapter;
-
-       /* tell the i2c layer a new client has arrived */
-       if (0 != (err = i2c_attach_client(client))) {
-               kfree(client);
-               return err;
-       }
-
-       printk("tea6415c: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
-
-       return 0;
-}
-
-static int attach(struct i2c_adapter *adapter)
-{
-       /* let's see whether this is a know adapter we can attach to */
-       if (adapter->id != I2C_HW_SAA7146) {
-               dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
-               return -ENODEV;
-       }
-
-       return i2c_probe(adapter, &addr_data, &detect);
-}
-
-static int detach(struct i2c_client *client)
-{
-       int ret = i2c_detach_client(client);
-       kfree(client);
-       return ret;
-}
-
 /* makes a connection between the input-pin 'i' and the output-pin 'o'
    for the tea6415c-client 'client' */
 static int switch_matrix(struct i2c_client *client, int i, int o)
@@ -110,7 +57,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
        u8 byte = 0;
        int ret;
 
-       dprintk("adr:0x%02x, i:%d, o:%d\n", client->addr, i, o);
+       v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o);
 
        /* check if the pins are valid */
        if (0 == ((1 == i ||  3 == i ||  5 == i ||  6 == i ||  8 == i || 10 == i || 20 == i || 11 == i)
@@ -168,14 +115,14 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
 
        ret = i2c_smbus_write_byte(client, byte);
        if (ret) {
-               dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret);
+               v4l_dbg(1, debug, client,
+                       "i2c_smbus_write_byte() failed, ret:%d\n", ret);
                return -EIO;
        }
-
        return ret;
 }
 
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
+static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
        struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg;
        int result = 0;
@@ -187,38 +134,40 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
        default:
                return -ENOIOCTLCMD;
        }
-
        return result;
 }
 
-static struct i2c_driver driver = {
-       .driver = {
-               .name = "tea6415c",
-       },
-       .id     = I2C_DRIVERID_TEA6415C,
-       .attach_adapter = attach,
-       .detach_client  = detach,
-       .command        = command,
-};
-
-static struct i2c_client client_template = {
-       .name = "tea6415c",
-       .driver = &driver,
-};
-
-static int __init this_module_init(void)
+/* this function is called by i2c_probe */
+static int tea6415c_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
-       return i2c_add_driver(&driver);
+       /* let's see whether this adapter can support what we need */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+               return 0;
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
+       return 0;
 }
 
-static void __exit this_module_exit(void)
+static int tea6415c_legacy_probe(struct i2c_adapter *adapter)
 {
-       i2c_del_driver(&driver);
+       /* Let's see whether this is a known adapter we can attach to.
+          Prevents conflicts with tvaudio.c. */
+       return adapter->id == I2C_HW_SAA7146;
 }
 
-module_init(this_module_init);
-module_exit(this_module_exit);
+static const struct i2c_device_id tea6415c_id[] = {
+       { "tea6415c", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tea6415c_id);
 
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tea6415c driver");
-MODULE_LICENSE("GPL");
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "tea6415c",
+       .driverid = I2C_DRIVERID_TEA6415C,
+       .command = tea6415c_command,
+       .probe = tea6415c_probe,
+       .legacy_probe = tea6415c_legacy_probe,
+       .id_table = tea6415c_id,
+};
index b5c8957d130e0115d450c3d0b56ab78b15a9ba03..e50820969e6485f5bde152e43bcc0f741df685ac 100644 (file)
@@ -2,6 +2,7 @@
     tea6420 - i2c-driver for the tea6420 by SGS Thomson
 
     Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
 
     The tea6420 is a bus controlled audio-matrix with 5 stereo inputs,
     4 stereo outputs and gain control for each output.
 #include <linux/module.h>
 #include <linux/ioctl.h>
 #include <linux/i2c.h>
-
+#include <media/v4l2-common.h>
+#include <media/v4l2-i2c-drv-legacy.h>
 #include "tea6420.h"
 
-static int debug;              /* insmod parameter */
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6420 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
 
-#define dprintk(args...) \
-           do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END };
@@ -46,23 +50,20 @@ static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 /* make a connection between the input 'i' and the output 'o'
    with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */
 static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
 {
-       u8 byte = 0;
+       u8 byte;
        int ret;
 
-       dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g);
+       v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g);
 
        /* check if the parameters are valid */
        if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0)
                return -1;
 
-       byte  = ((o - 1) << 5);
+       byte = ((o - 1) << 5);
        byte |= (i - 1);
 
        /* to understand this, have a look at the tea6420-specs (p.5) */
@@ -82,40 +83,41 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
 
        ret = i2c_smbus_write_byte(client, byte);
        if (ret) {
-               dprintk("i2c_smbus_write_byte() failed, ret:%d\n", ret);
+               v4l_dbg(1, debug, client,
+                       "i2c_smbus_write_byte() failed, ret:%d\n", ret);
                return -EIO;
        }
-
        return 0;
 }
 
-/* this function is called by i2c_probe */
-static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
+static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg)
 {
-       struct i2c_client *client;
-       int err = 0, i = 0;
+       struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg;
+       int result = 0;
 
-       /* let's see whether this adapter can support what we need */
-       if (0 == i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE)) {
-               return 0;
+       switch (cmd) {
+       case TEA6420_SWITCH:
+               result = tea6420_switch(client, a->in, a->out, a->gain);
+               break;
+       default:
+               return -ENOIOCTLCMD;
        }
 
-       /* allocate memory for client structure */
-       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (!client) {
-               return -ENOMEM;
-       }
+       return result;
+}
 
-       /* fill client structure */
-       memcpy(client, &client_template, sizeof(struct i2c_client));
-       client->addr = address;
-       client->adapter = adapter;
+/* this function is called by i2c_probe */
+static int tea6420_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       int err, i;
 
-       /* tell the i2c layer a new client has arrived */
-       if (0 != (err = i2c_attach_client(client))) {
-               kfree(client);
-               return err;
-       }
+       /* let's see whether this adapter can support what we need */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+               return -EIO;
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
 
        /* set initial values: set "mute"-input to all outputs at gain 0 */
        err = 0;
@@ -123,78 +125,31 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
                err += tea6420_switch(client, 6, i, 0);
        }
        if (err) {
-               dprintk("could not initialize tea6420\n");
+               v4l_dbg(1, debug, client, "could not initialize tea6420\n");
                kfree(client);
                return -ENODEV;
        }
-
-       printk("tea6420: detected @ 0x%02x on adapter %s\n", address, &client->adapter->name[0]);
-
        return 0;
 }
 
-static int attach(struct i2c_adapter *adapter)
+static int tea6420_legacy_probe(struct i2c_adapter *adapter)
 {
-       /* let's see whether this is a know adapter we can attach to */
-       if (adapter->id != I2C_HW_SAA7146) {
-               dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
-               return -ENODEV;
-       }
-
-       return i2c_probe(adapter, &addr_data, &tea6420_detect);
-}
-
-static int detach(struct i2c_client *client)
-{
-       int ret = i2c_detach_client(client);
-       kfree(client);
-       return ret;
-}
-
-static int command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-       struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg;
-       int result = 0;
-
-       switch (cmd) {
-       case TEA6420_SWITCH:
-               result = tea6420_switch(client, a->in, a->out, a->gain);
-               break;
-       default:
-               return -ENOIOCTLCMD;
-       }
-
-       return result;
+       /* Let's see whether this is a known adapter we can attach to.
+          Prevents conflicts with tvaudio.c. */
+       return adapter->id == I2C_HW_SAA7146;
 }
 
-static struct i2c_driver driver = {
-       .driver = {
-               .name = "tea6420",
-       },
-       .id     = I2C_DRIVERID_TEA6420,
-       .attach_adapter = attach,
-       .detach_client  = detach,
-       .command        = command,
+static const struct i2c_device_id tea6420_id[] = {
+       { "tea6420", 0 },
+       { }
 };
+MODULE_DEVICE_TABLE(i2c, tea6420_id);
 
-static struct i2c_client client_template = {
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
        .name = "tea6420",
-       .driver = &driver,
+       .driverid = I2C_DRIVERID_TEA6420,
+       .command = tea6420_command,
+       .probe = tea6420_probe,
+       .legacy_probe = tea6420_legacy_probe,
+       .id_table = tea6420_id,
 };
-
-static int __init this_module_init(void)
-{
-       return i2c_add_driver(&driver);
-}
-
-static void __exit this_module_exit(void)
-{
-       i2c_del_driver(&driver);
-}
-
-module_init(this_module_init);
-module_exit(this_module_exit);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("tea6420 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
deleted file mode 100644 (file)
index bdf506e..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Driver for Philips SAB3036 "CITAC" tuner control chip.
- *
- * Author: Phil Blundell <philb@gnu.org>
- *
- * The SAB3036 is just about different enough from the chips that
- * tuner.c copes with to make it not worth the effort to crowbar
- * the support into that file.  So instead we have a separate driver.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-
-#include <media/tuner.h>
-
-static int debug;      /* insmod parameter */
-static int this_adap;
-
-static struct i2c_client client_template;
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
-static unsigned short ignore = I2C_CLIENT_END;
-
-static struct i2c_client_address_data addr_data = {
-       .normal_i2c     = normal_i2c,
-       .probe          = &ignore,
-       .ignore         = &ignore,
-};
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned char
-tuner_getstatus (struct i2c_client *c)
-{
-       unsigned char byte;
-       if (i2c_master_recv(c, &byte, 1) != 1)
-               printk(KERN_ERR "tuner-3036: I/O error.\n");
-       return byte;
-}
-
-#define TUNER_FL        0x80
-
-static int
-tuner_islocked (struct i2c_client *c)
-{
-       return (tuner_getstatus(c) & TUNER_FL);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void
-set_tv_freq(struct i2c_client *c, int freq)
-{
-       u16 div = ((freq * 20) / 16);
-       unsigned long give_up = jiffies + HZ;
-       unsigned char buffer[2];
-
-       if (debug)
-               printk(KERN_DEBUG "tuner: setting frequency %dMHz, divisor %x\n", freq / 16, div);
-
-       /* Select high tuning current */
-       buffer[0] = 0x29;
-       buffer[1] = 0x3e;
-
-       if (i2c_master_send(c, buffer, 2) != 2)
-               printk("tuner: i2c i/o error 1\n");
-
-       buffer[0] = 0x80 | ((div>>8) & 0x7f);
-       buffer[1] = div & 0xff;
-
-       if (i2c_master_send(c, buffer, 2) != 2)
-               printk("tuner: i2c i/o error 2\n");
-
-       while (!tuner_islocked(c) && time_before(jiffies, give_up))
-               schedule();
-
-       if (!tuner_islocked(c))
-               printk(KERN_WARNING "tuner: failed to achieve PLL lock\n");
-
-       /* Select low tuning current and engage AFC */
-       buffer[0] = 0x29;
-       buffer[1] = 0xb2;
-
-       if (i2c_master_send(c, buffer, 2) != 2)
-               printk("tuner: i2c i/o error 3\n");
-
-       if (debug)
-               printk(KERN_DEBUG "tuner: status %02x\n", tuner_getstatus(c));
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-tuner_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-       static unsigned char buffer[] = { 0x29, 0x32, 0x2a, 0, 0x2b, 0 };
-
-       struct i2c_client *client;
-
-       if (this_adap > 0)
-               return -1;
-       this_adap++;
-
-       client_template.adapter = adap;
-       client_template.addr = addr;
-
-       client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (client == NULL)
-               return -ENOMEM;
-       memcpy(client, &client_template, sizeof(struct i2c_client));
-
-       printk("tuner: SAB3036 found, status %02x\n", tuner_getstatus(client));
-
-       i2c_attach_client(client);
-
-       if (i2c_master_send(client, buffer, 2) != 2)
-               printk("tuner: i2c i/o error 1\n");
-       if (i2c_master_send(client, buffer+2, 2) != 2)
-               printk("tuner: i2c i/o error 2\n");
-       if (i2c_master_send(client, buffer+4, 2) != 2)
-               printk("tuner: i2c i/o error 3\n");
-       return 0;
-}
-
-static int
-tuner_detach(struct i2c_client *c)
-{
-       return 0;
-}
-
-static int
-tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-       int *iarg = (int*)arg;
-
-       switch (cmd)
-       {
-               case VIDIOCSFREQ:
-                       set_tv_freq(client, *iarg);
-                       break;
-
-               default:
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-static int
-tuner_probe(struct i2c_adapter *adap)
-{
-       this_adap = 0;
-       if (adap->id == I2C_HW_B_LP)
-               return i2c_probe(adap, &addr_data, tuner_attach);
-       return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver
-i2c_driver_tuner =
-{
-       .driver = {
-               .name   =       "sab3036",
-       },
-       .id             =       I2C_DRIVERID_SAB3036,
-       .attach_adapter =       tuner_probe,
-       .detach_client  =       tuner_detach,
-       .command        =       tuner_command
-};
-
-static struct i2c_client client_template =
-{
-       .driver         = &i2c_driver_tuner,
-       .name           = "SAB3036",
-};
-
-static int __init
-tuner3036_init(void)
-{
-       return i2c_add_driver(&i2c_driver_tuner);
-}
-
-static void __exit
-tuner3036_exit(void)
-{
-       i2c_del_driver(&i2c_driver_tuner);
-}
-
-MODULE_DESCRIPTION("SAB3036 tuner driver");
-MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
-MODULE_LICENSE("GPL");
-
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug,"Enable debugging output");
-
-module_init(tuner3036_init);
-module_exit(tuner3036_exit);
index d806a3556eedd9f48b8ba40fc07ef8bf7417bef2..4a7735c6c1a65e022c11689c8b6ef4b1a8f86406 100644 (file)
@@ -92,7 +92,6 @@ struct tuner {
 
        unsigned int        type; /* chip type id */
        unsigned int        config;
-       int (*tuner_callback) (void *dev, int command, int arg);
        const char          *name;
 };
 
@@ -346,7 +345,7 @@ static struct xc5000_config xc5000_cfg;
 
 static void set_type(struct i2c_client *c, unsigned int type,
                     unsigned int new_mode_mask, unsigned int new_config,
-                    int (*tuner_callback) (void *dev, int command,int arg))
+                    int (*tuner_callback) (void *dev, int component, int cmd, int arg))
 {
        struct tuner *t = i2c_get_clientdata(c);
        struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
@@ -362,7 +361,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
        t->config = new_config;
        if (tuner_callback != NULL) {
                tuner_dbg("defining GPIO callback\n");
-               t->tuner_callback = tuner_callback;
+               t->fe.callback = tuner_callback;
        }
 
        if (t->mode == T_UNINITIALIZED) {
@@ -385,7 +384,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
        {
                struct tda829x_config cfg = {
                        .lna_cfg        = t->config,
-                       .tuner_callback = t->tuner_callback,
                };
                if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter,
                                t->i2c->addr, &cfg))
@@ -433,7 +431,6 @@ static void set_type(struct i2c_client *c, unsigned int type,
                struct xc2028_config cfg = {
                        .i2c_adap  = t->i2c->adapter,
                        .i2c_addr  = t->i2c->addr,
-                       .callback  = t->tuner_callback,
                };
                if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
                        goto attach_failed;
@@ -450,10 +447,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
                xc5000_cfg.i2c_address    = t->i2c->addr;
                xc5000_cfg.if_khz         = 5380;
-               xc5000_cfg.tuner_callback = t->tuner_callback;
                if (!dvb_attach(xc5000_attach,
-                               &t->fe, t->i2c->adapter, &xc5000_cfg,
-                               c->adapter->algo_data))
+                               &t->fe, t->i2c->adapter, &xc5000_cfg))
                        goto attach_failed;
 
                xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -1225,7 +1220,7 @@ register_client:
        } else {
                t->mode = V4L2_TUNER_DIGITAL_TV;
        }
-       set_type(client, t->type, t->mode_mask, t->config, t->tuner_callback);
+       set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
        list_add_tail(&t->list, &tuner_list);
        return 0;
 }
index cc27efe121ddb225fd598d426da3ba44e7379ae0..28421d386f1e5b1561763ca4a3da320f7e8a3e5d 100644 (file)
@@ -258,7 +258,9 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h
                            (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
                        {
 #if 0                          /* This code helps to detect new frame markers */
-                               info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3));
+                               dev_info(&uvd->dev->dev,
+                                        "Header sig: 00 FF 00 %02X\n",
+                                        RING_QUEUE_PEEK(&uvd->dp, 3));
 #endif
                                frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
                                if ((frame->header == HDRSIG_MODEL1_128x96) ||
@@ -266,7 +268,8 @@ static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame h
                                    (frame->header == HDRSIG_MODEL1_352x288))
                                {
 #if 0
-                                       info("Header found.");
+                                       dev_info(&uvd->dev->dev,
+                                                "Header found.\n");
 #endif
                                        RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
                                        icam->has_hdr = 1;
@@ -295,7 +298,7 @@ case IBMCAM_MODEL_4:
                            (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
                        {
 #if 0
-                               info("Header found.");
+                               dev_info(&uvd->dev->dev, "Header found.\n");
 #endif
                                RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
                                icam->has_hdr = 1;
@@ -338,7 +341,7 @@ case IBMCAM_MODEL_4:
                                byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
                                frame->header = (byte3 << 8) | byte4;
 #if 0
-                               info("Header found.");
+                               dev_info(&uvd->dev->dev, "Header found.\n");
 #endif
                                RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
                                icam->has_hdr = 1;
@@ -354,7 +357,8 @@ case IBMCAM_MODEL_4:
        }
        if (!icam->has_hdr) {
                if (uvd->debug > 2)
-                       info("Skipping frame, no header");
+                       dev_info(&uvd->dev->dev,
+                                "Skipping frame, no header\n");
                return scan_EndParse;
        }
 
@@ -881,7 +885,9 @@ static enum ParseState ibmcam_model3_parse_lines(
         */
        if ((frame->curline + 1) >= data_h) {
                if (uvd->debug >= 3)
-                       info("Reached line %d. (frame is done)", frame->curline);
+                       dev_info(&uvd->dev->dev,
+                                "Reached line %d. (frame is done)\n",
+                                frame->curline);
                return scan_NextFrame;
        }
 
@@ -954,8 +960,9 @@ static enum ParseState ibmcam_model3_parse_lines(
 
        if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
                if (uvd->debug >= 3) {
-                       info("All requested lines (%ld.) done.",
-                            VIDEOSIZE_Y(frame->request));
+                       dev_info(&uvd->dev->dev,
+                                "All requested lines (%ld.) done.\n",
+                                VIDEOSIZE_Y(frame->request));
                }
                return scan_NextFrame;
        } else
@@ -1000,7 +1007,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
         */
        if ((frame->curline + 1) >= data_h) {
                if (uvd->debug >= 3)
-                       info("Reached line %d. (frame is done)", frame->curline);
+                       dev_info(&uvd->dev->dev,
+                                "Reached line %d. (frame is done)\n",
+                                frame->curline);
                return scan_NextFrame;
        }
 
@@ -1049,8 +1058,9 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
 
        if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
                if (uvd->debug >= 3) {
-                       info("All requested lines (%ld.) done.",
-                            VIDEOSIZE_Y(frame->request));
+                       dev_info(&uvd->dev->dev,
+                                "All requested lines (%ld.) done.\n",
+                                VIDEOSIZE_Y(frame->request));
                }
                return scan_NextFrame;
        } else
@@ -1171,10 +1181,11 @@ static int ibmcam_veio(
                        sizeof(cp),
                        1000);
 #if 0
-               info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-                      "(req=$%02x val=$%04x ind=$%04x)",
-                      cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-                      req, value, index);
+               dev_info(&uvd->dev->dev,
+                        "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+                        "(req=$%02x val=$%04x ind=$%04x)\n",
+                        cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+                        req, value, index);
 #endif
        } else {
                i = usb_control_msg(
@@ -1449,10 +1460,9 @@ static void ibmcam_adjust_contrast(struct uvd *uvd)
  */
 static void ibmcam_change_lighting_conditions(struct uvd *uvd)
 {
-       static const char proc[] = "ibmcam_change_lighting_conditions";
-
        if (debug > 0)
-               info("%s: Set lighting to %hu.", proc, lighting);
+               dev_info(&uvd->dev->dev,
+                        "%s: Set lighting to %hu.\n", __func__, lighting);
 
        switch (IBMCAM_T(uvd)->camera_model) {
        case IBMCAM_MODEL_1:
@@ -1495,8 +1505,6 @@ static void ibmcam_change_lighting_conditions(struct uvd *uvd)
  */
 static void ibmcam_set_sharpness(struct uvd *uvd)
 {
-       static const char proc[] = "ibmcam_set_sharpness";
-
        switch (IBMCAM_T(uvd)->camera_model) {
        case IBMCAM_MODEL_1:
        {
@@ -1505,7 +1513,8 @@ static void ibmcam_set_sharpness(struct uvd *uvd)
 
                RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
                if (debug > 0)
-                       info("%s: Set sharpness to %hu.", proc, sharpness);
+                       dev_info(&uvd->dev->dev, "%s: Set sharpness to %hu.\n",
+                                __func__, sharpness);
 
                sv = sa[sharpness - SHARPNESS_MIN];
                for (i=0; i < 2; i++) {
@@ -1564,11 +1573,11 @@ static void ibmcam_set_sharpness(struct uvd *uvd)
  */
 static void ibmcam_set_brightness(struct uvd *uvd)
 {
-       static const char proc[] = "ibmcam_set_brightness";
        static const unsigned short n = 1;
 
        if (debug > 0)
-               info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
+               dev_info(&uvd->dev->dev, "%s: Set brightness to %hu.\n",
+                        __func__, uvd->vpic.brightness);
 
        switch (IBMCAM_T(uvd)->camera_model) {
        case IBMCAM_MODEL_1:
@@ -2115,7 +2124,8 @@ static void ibmcam_model2_setup_after_video_if(struct uvd *uvd)
                        break;
                }
                if (uvd->debug > 0)
-                       info("Framerate (hardware): %hd.", hw_fps);
+                       dev_info(&uvd->dev->dev, "Framerate (hardware): %hd.\n",
+                                hw_fps);
                RESTRICT_TO_RANGE(hw_fps, 0, 31);
                ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
        }
@@ -3487,7 +3497,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
        /* 01.01.08 - Added for RCA video in support -LO */
        if(init_model3_input) {
                if (debug > 0)
-                       info("Setting input to RCA.");
+                       dev_info(&uvd->dev->dev, "Setting input to RCA.\n");
                for (i=0; i < ARRAY_SIZE(initData); i++) {
                        ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
                }
@@ -3685,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
        unsigned char video_ep = 0;
 
        if (debug >= 1)
-               info("ibmcam_probe(%p,%u.)", intf, ifnum);
+               dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum);
 
        /* We don't handle multi-config cameras */
        if (dev->descriptor.bNumConfigurations != 1)
@@ -3736,14 +3746,16 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
                        brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
                        break;
                }
-               info("%s USB camera found (model %d, rev. 0x%04x)",
-                    brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
+               dev_info(&uvd->dev->dev,
+                        "%s USB camera found (model %d, rev. 0x%04x)\n",
+                        brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
        } while (0);
 
        /* Validate found interface: must have one ISO endpoint */
        nas = intf->num_altsetting;
        if (debug > 0)
-               info("Number of alternate settings=%d.", nas);
+               dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n",
+                        nas);
        if (nas < 2) {
                err("Too few alternate settings for this camera!");
                return -ENODEV;
@@ -3787,7 +3799,9 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
                                actInterface = i;
                                maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
                                if (debug > 0)
-                                       info("Active setting=%d. maxPS=%d.", i, maxPS);
+                                       dev_info(&uvd->dev->dev,
+                                                "Active setting=%d. "
+                                                "maxPS=%d.\n", i, maxPS);
                        } else
                                err("More than one active alt. setting! Ignoring #%d.", i);
                }
@@ -3826,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
                        RESTRICT_TO_RANGE(framerate, 0, 5);
                        break;
                default:
-                       info("IBM camera: using 320x240");
+                       dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n");
                        size = SIZE_320x240;
                        /* No break here */
                case SIZE_320x240:
@@ -3855,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
                        canvasY = 120;
                        break;
                default:
-                       info("IBM NetCamera: using 176x144");
+                       dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n");
                        size = SIZE_176x144;
                        /* No break here */
                case SIZE_176x144:
index 1c180284ec6c2f35aa6fb3bd31e63ee97d562c0d..e986c28b7bb0f73ab289260c12f24a5cc44b5e1c 100644 (file)
@@ -337,7 +337,8 @@ static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct ur
                }
 
                if((sts > 0x01) && (sts < 0x80)) {
-                       info("unknown status %2.2x", sts);
+                       dev_info(&uvd->dev->dev, "unknown status %2.2x\n",
+                                sts);
                        bad++;
                        continue;
                }
@@ -568,8 +569,12 @@ static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
                                        fdrops = (0x80 + curframe - cam->lastframe) & 0x7F;
                                        fdrops--;
                                        if(fdrops) {
-                                               info("Dropped %d frames (%d -> %d)", fdrops,
-                                                    cam->lastframe, curframe);
+                                               dev_info(&uvd->dev->dev,
+                                                        "Dropped %d frames "
+                                                        "(%d -> %d)\n",
+                                                        fdrops,
+                                                        cam->lastframe,
+                                                        curframe);
                                        }
                                }
                                cam->lastframe = curframe;
@@ -784,7 +789,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
        if (dev->descriptor.bNumConfigurations != 1)
                return -ENODEV;
 
-       info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice));
+       dev_info(&intf->dev, "Konica Webcam (rev. 0x%04x)\n",
+                le16_to_cpu(dev->descriptor.bcdDevice));
        RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
 
        /* Validate found interface: must have one ISO endpoint */
@@ -925,7 +931,8 @@ static struct usb_device_id id_table[] = {
 static int __init konicawc_init(void)
 {
        struct usbvideo_cb cbTbl;
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
        memset(&cbTbl, 0, sizeof(cbTbl));
        cbTbl.probe = konicawc_probe;
        cbTbl.setupOnOpen = konicawc_setup_on_open;
index 3d26a30abe1ef99b1c9de8873816efa00f1dc7ee..05c61b52311541dbee042c9d9039f8260ede9d5a 100644 (file)
@@ -1080,7 +1080,8 @@ static struct usbvideo_cb qcm_driver = {
 
 static int __init qcm_init(void)
 {
-       info(DRIVER_DESC " " DRIVER_VERSION);
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+              DRIVER_DESC "\n");
 
        return usbvideo_register(
                &cams,
index 9544e644bf0de4bc6f01b8e22107d20809683657..9714baab7833b61a696ce5120427c42c0a9aa7cd 100644 (file)
@@ -156,10 +156,11 @@ static int ultracam_veio(
                        sizeof(cp),
                        1000);
 #if 1
-               info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-                      "(req=$%02x val=$%04x ind=$%04x)",
-                      cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-                      req, value, index);
+               dev_info(&uvd->dev->dev,
+                        "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+                        "(req=$%02x val=$%04x ind=$%04x)\n",
+                        cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+                        req, value, index);
 #endif
        } else {
                i = usb_control_msg(
@@ -517,19 +518,20 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
        unsigned char video_ep = 0;
 
        if (debug >= 1)
-               info("ultracam_probe(%p)", intf);
+               dev_info(&intf->dev, "ultracam_probe\n");
 
        /* We don't handle multi-config cameras */
        if (dev->descriptor.bNumConfigurations != 1)
                return -ENODEV;
 
-       info("IBM Ultra camera found (rev. 0x%04x)",
-               le16_to_cpu(dev->descriptor.bcdDevice));
+       dev_info(&intf->dev, "IBM Ultra camera found (rev. 0x%04x)\n",
+                le16_to_cpu(dev->descriptor.bcdDevice));
 
        /* Validate found interface: must have one ISO endpoint */
        nas = intf->num_altsetting;
        if (debug > 0)
-               info("Number of alternate settings=%d.", nas);
+               dev_info(&intf->dev, "Number of alternate settings=%d.\n",
+                        nas);
        if (nas < 8) {
                err("Too few alternate settings for this camera!");
                return -ENODEV;
@@ -576,7 +578,9 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
                                actInterface = i;
                                maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
                                if (debug > 0)
-                                       info("Active setting=%d. maxPS=%d.", i, maxPS);
+                                       dev_info(&intf->dev,
+                                                "Active setting=%d. "
+                                                "maxPS=%d.\n", i, maxPS);
                        } else {
                                /* Got another active alt. setting */
                                if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
@@ -584,8 +588,11 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
                                        actInterface = i;
                                        maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
                                        if (debug > 0) {
-                                               info("Even better ctive setting=%d. maxPS=%d.",
-                                                    i, maxPS);
+                                               dev_info(&intf->dev,
+                                                        "Even better ctive "
+                                                        "setting=%d. "
+                                                        "maxPS=%d.\n",
+                                                        i, maxPS);
                                        }
                                }
                        }
index bf1bc2f69b02f727a4cad6ff13cf1f9b46b96a55..07cd87d16f69f602dcbd8bf416347200ce79a8d0 100644 (file)
@@ -468,8 +468,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd)
                        percent = (100 * goodPackets) / allPackets;
                else
                        percent = goodPackets / (allPackets / 100);
-               info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",
-                    allPackets, badPackets, percent);
+               dev_info(&uvd->dev->dev,
+                        "Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%\n",
+                        allPackets, badPackets, percent);
                if (uvd->iso_packet_len > 0) {
                        unsigned long allBytes, xferBytes;
                        char multiplier = ' ';
@@ -497,8 +498,9 @@ static void usbvideo_ReportStatistics(const struct uvd *uvd)
                                        }
                                }
                        }
-                       info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",
-                            xferBytes, multiplier, percent);
+                       dev_info(&uvd->dev->dev,
+                                "Transfer Statistics: Transferred=%lu%cB Usage=%lu%%\n",
+                                xferBytes, multiplier, percent);
                }
        }
 }
@@ -545,7 +547,7 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
        {       /* For debugging purposes only */
                char tmp[20];
                usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
-               info("testpattern: frame=%s", tmp);
+               dev_info(&uvd->dev->dev, "testpattern: frame=%s\n", tmp);
        }
 #endif
        /* Form every scan line */
@@ -854,7 +856,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        usbvideo_ClientIncModCount(uvd);
        if (uvd->debug > 0)
-               info("%s(%p.)", __func__, intf);
+               dev_info(&intf->dev, "%s(%p.)\n", __func__, intf);
 
        mutex_lock(&uvd->lock);
        uvd->remove_pending = 1; /* Now all ISO data will be ignored */
@@ -870,14 +872,15 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 
        video_unregister_device(&uvd->vdev);
        if (uvd->debug > 0)
-               info("%s: Video unregistered.", __func__);
+               dev_info(&intf->dev, "%s: Video unregistered.\n", __func__);
 
        if (uvd->user)
-               info("%s: In use, disconnect pending.", __func__);
+               dev_info(&intf->dev, "%s: In use, disconnect pending.\n",
+                        __func__);
        else
                usbvideo_CameraRelease(uvd);
        mutex_unlock(&uvd->lock);
-       info("USB camera disconnected.");
+       dev_info(&intf->dev, "USB camera disconnected.\n");
 
        usbvideo_ClientDecModCount(uvd);
 }
@@ -1015,14 +1018,17 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
                return -EINVAL;
        }
        if (uvd->video_endp == 0) {
-               info("%s: No video endpoint specified; data pump disabled.", __func__);
+               dev_info(&uvd->dev->dev,
+                        "%s: No video endpoint specified; data pump disabled.\n",
+                        __func__);
        }
        if (uvd->paletteBits == 0) {
                err("%s: No palettes specified!", __func__);
                return -EINVAL;
        }
        if (uvd->defaultPalette == 0) {
-               info("%s: No default palette!", __func__);
+               dev_info(&uvd->dev->dev, "%s: No default palette!\n",
+                        __func__);
        }
 
        uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
@@ -1031,25 +1037,29 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd)
        usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
 
        if (uvd->debug > 0) {
-               info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
-                    __func__, uvd->iface, uvd->video_endp, uvd->paletteBits);
+               dev_info(&uvd->dev->dev,
+                        "%s: iface=%d. endpoint=$%02x paletteBits=$%08lx\n",
+                        __func__, uvd->iface, uvd->video_endp,
+                        uvd->paletteBits);
        }
        if (uvd->dev == NULL) {
                err("%s: uvd->dev == NULL", __func__);
                return -EINVAL;
        }
        uvd->vdev.parent = &uvd->dev->dev;
-       if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+       uvd->vdev.release = video_device_release_empty;
+       if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
                err("%s: video_register_device failed", __func__);
                return -EPIPE;
        }
        if (uvd->debug > 1) {
-               info("%s: video_register_device() successful", __func__);
+               dev_info(&uvd->dev->dev,
+                        "%s: video_register_device() successful\n", __func__);
        }
 
-       info("%s on /dev/video%d: canvas=%s videosize=%s",
-            (uvd->handle != NULL) ? uvd->handle->drvName : "???",
-            uvd->vdev.minor, tmp2, tmp1);
+       dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n",
+                (uvd->handle != NULL) ? uvd->handle->drvName : "???",
+                uvd->vdev.minor, tmp2, tmp1);
 
        usb_get_dev(uvd->dev);
        return 0;
@@ -1111,7 +1121,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        int i, errCode = 0;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __func__, dev);
+               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
 
        if (0 < usbvideo_ClientIncModCount(uvd))
                return -ENODEV;
@@ -1178,19 +1188,25 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
                if (errCode == 0) {
                        if (VALID_CALLBACK(uvd, setupOnOpen)) {
                                if (uvd->debug > 1)
-                                       info("%s: setupOnOpen callback", __func__);
+                                       dev_info(&uvd->dev->dev,
+                                                "%s: setupOnOpen callback\n",
+                                                __func__);
                                errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
                                if (errCode < 0) {
                                        err("%s: setupOnOpen callback failed (%d.).",
                                            __func__, errCode);
                                } else if (uvd->debug > 1) {
-                                       info("%s: setupOnOpen callback successful", __func__);
+                                       dev_info(&uvd->dev->dev,
+                                                "%s: setupOnOpen callback successful\n",
+                                                __func__);
                                }
                        }
                        if (errCode == 0) {
                                uvd->settingsAdjusted = 0;
                                if (uvd->debug > 1)
-                                       info("%s: Open succeeded.", __func__);
+                                       dev_info(&uvd->dev->dev,
+                                                "%s: Open succeeded.\n",
+                                                __func__);
                                uvd->user++;
                                file->private_data = uvd;
                        }
@@ -1200,7 +1216,8 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
        if (errCode != 0)
                usbvideo_ClientDecModCount(uvd);
        if (uvd->debug > 0)
-               info("%s: Returning %d.", __func__, errCode);
+               dev_info(&uvd->dev->dev, "%s: Returning %d.\n", __func__,
+                        errCode);
        return errCode;
 }
 
@@ -1223,7 +1240,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        int i;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __func__, dev);
+               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, dev);
 
        mutex_lock(&uvd->lock);
        GET_CALLBACK(uvd, stopDataPump)(uvd);
@@ -1243,14 +1260,15 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
        uvd->user--;
        if (uvd->remove_pending) {
                if (uvd->debug > 0)
-                       info("usbvideo_v4l_close: Final disconnect.");
+                       dev_info(&uvd->dev->dev, "%s: Final disconnect.\n",
+                                __func__);
                usbvideo_CameraRelease(uvd);
        }
        mutex_unlock(&uvd->lock);
        usbvideo_ClientDecModCount(uvd);
 
        if (uvd->debug > 1)
-               info("%s: Completed.", __func__);
+               dev_info(&uvd->dev->dev, "%s: Completed.\n", __func__);
        file->private_data = NULL;
        return 0;
 }
@@ -1364,8 +1382,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
                        struct video_mmap *vm = arg;
 
                        if (uvd->debug >= 1) {
-                               info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.",
-                                    vm->frame, vm->width, vm->height, vm->format);
+                               dev_info(&uvd->dev->dev,
+                                        "VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.\n",
+                                        vm->frame, vm->width, vm->height, vm->format);
                        }
                        /*
                         * Check if the requested size is supported. If the requestor
@@ -1383,18 +1402,24 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
                        if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
                            (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
                                if (uvd->debug > 0) {
-                                       info("VIDIOCMCAPTURE: Size=%dx%d too large; "
-                                            "allowed only up to %ldx%ld", vm->width, vm->height,
-                                            VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas));
+                                       dev_info(&uvd->dev->dev,
+                                                "VIDIOCMCAPTURE: Size=%dx%d "
+                                                "too large; allowed only up "
+                                                "to %ldx%ld\n", vm->width,
+                                                vm->height,
+                                                VIDEOSIZE_X(uvd->canvas),
+                                                VIDEOSIZE_Y(uvd->canvas));
                                }
                                return -EINVAL;
                        }
                        /* Check if the palette is supported */
                        if (((1L << vm->format) & uvd->paletteBits) == 0) {
                                if (uvd->debug > 0) {
-                                       info("VIDIOCMCAPTURE: format=%d. not supported"
-                                            " (paletteBits=$%08lx)",
-                                            vm->format, uvd->paletteBits);
+                                       dev_info(&uvd->dev->dev,
+                                                "VIDIOCMCAPTURE: format=%d. "
+                                                "not supported "
+                                                "(paletteBits=$%08lx)\n",
+                                                vm->format, uvd->paletteBits);
                                }
                                return -EINVAL;
                        }
@@ -1422,7 +1447,9 @@ static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
 
                        if (uvd->debug >= 1)
-                               info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
+                               dev_info(&uvd->dev->dev,
+                                        "VIDIOCSYNC: syncing to frame %d.\n",
+                                        *frameNum);
                        if (uvd->flags & FLAGS_NO_DECODING)
                                ret = usbvideo_GetFrame(uvd, *frameNum);
                        else if (VALID_CALLBACK(uvd, getFrame)) {
@@ -1504,7 +1531,9 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
                return -EFAULT;
 
        if (uvd->debug >= 1)
-               info("%s: %Zd. bytes, noblock=%d.", __func__, count, noblock);
+               dev_info(&uvd->dev->dev,
+                        "%s: %Zd. bytes, noblock=%d.\n",
+                        __func__, count, noblock);
 
        mutex_lock(&uvd->lock);
 
@@ -1685,18 +1714,21 @@ static void usbvideo_IsocIrq(struct urb *urb)
                return;
 #if 0
        if (urb->actual_length > 0) {
-               info("urb=$%p status=%d. errcount=%d. length=%d.",
-                    urb, urb->status, urb->error_count, urb->actual_length);
+               dev_info(&uvd->dev->dev,
+                        "urb=$%p status=%d. errcount=%d. length=%d.\n",
+                        urb, urb->status, urb->error_count,
+                        urb->actual_length);
        } else {
                static int c = 0;
                if (c++ % 100 == 0)
-                       info("No Isoc data");
+                       dev_info(&uvd->dev->dev, "No Isoc data\n");
        }
 #endif
 
        if (!uvd->streaming) {
                if (uvd->debug >= 1)
-                       info("Not streaming, but interrupt!");
+                       dev_info(&uvd->dev->dev,
+                                "Not streaming, but interrupt!\n");
                return;
        }
 
@@ -1741,7 +1773,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
        int i, errFlag;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __func__, uvd);
+               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
 
        if (!CAMERA_IS_OPERATIONAL(uvd)) {
                err("%s: Camera is not operational", __func__);
@@ -1789,7 +1821,9 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
 
        uvd->streaming = 1;
        if (uvd->debug > 1)
-               info("%s: streaming=1 video_endp=$%02x", __func__, uvd->video_endp);
+               dev_info(&uvd->dev->dev,
+                        "%s: streaming=1 video_endp=$%02x\n", __func__,
+                        uvd->video_endp);
        return 0;
 }
 
@@ -1811,14 +1845,14 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
                return;
 
        if (uvd->debug > 1)
-               info("%s($%p)", __func__, uvd);
+               dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
 
        /* Unschedule all of the iso td's */
        for (i=0; i < USBVIDEO_NUMSBUF; i++) {
                usb_kill_urb(uvd->sbuf[i].urb);
        }
        if (uvd->debug > 1)
-               info("%s: streaming=0", __func__);
+               dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__);
        uvd->streaming = 0;
 
        if (!uvd->remove_pending) {
@@ -1850,7 +1884,8 @@ static int usbvideo_NewFrame(struct uvd *uvd, int framenum)
        int n;
 
        if (uvd->debug > 1)
-               info("usbvideo_NewFrame($%p,%d.)", uvd, framenum);
+               dev_info(&uvd->dev->dev, "usbvideo_NewFrame($%p,%d.)\n", uvd,
+                        framenum);
 
        /* If we're not grabbing a frame right now and the other frame is */
        /*  ready to be grabbed into, then use it instead */
@@ -1955,12 +1990,14 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        struct usbvideo_frame *frame = &uvd->frame[frameNum];
 
        if (uvd->debug >= 2)
-               info("%s($%p,%d.)", __func__, uvd, frameNum);
+               dev_info(&uvd->dev->dev, "%s($%p,%d.)\n", __func__, uvd,
+                        frameNum);
 
        switch (frame->frameState) {
        case FrameState_Unused:
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Unused", __func__);
+                       dev_info(&uvd->dev->dev, "%s: FrameState_Unused\n",
+                                __func__);
                return -EINVAL;
        case FrameState_Ready:
        case FrameState_Grabbing:
@@ -1970,7 +2007,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
        redo:
                if (!CAMERA_IS_OPERATIONAL(uvd)) {
                        if (uvd->debug >= 2)
-                               info("%s: Camera is not operational (1)", __func__);
+                               dev_info(&uvd->dev->dev,
+                                        "%s: Camera is not operational (1)\n",
+                                        __func__);
                        return -EIO;
                }
                ntries = 0;
@@ -1979,24 +2018,33 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                        signalPending = signal_pending(current);
                        if (!CAMERA_IS_OPERATIONAL(uvd)) {
                                if (uvd->debug >= 2)
-                                       info("%s: Camera is not operational (2)", __func__);
+                                       dev_info(&uvd->dev->dev,
+                                                "%s: Camera is not "
+                                                "operational (2)\n", __func__);
                                return -EIO;
                        }
                        assert(uvd->fbuf != NULL);
                        if (signalPending) {
                                if (uvd->debug >= 2)
-                                       info("%s: Signal=$%08x", __func__, signalPending);
+                                       dev_info(&uvd->dev->dev,
+                                       "%s: Signal=$%08x\n", __func__,
+                                       signalPending);
                                if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
                                        usbvideo_TestPattern(uvd, 1, 0);
                                        uvd->curframe = -1;
                                        uvd->stats.frame_num++;
                                        if (uvd->debug >= 2)
-                                               info("%s: Forced test pattern screen", __func__);
+                                               dev_info(&uvd->dev->dev,
+                                                        "%s: Forced test "
+                                                        "pattern screen\n",
+                                                        __func__);
                                        return 0;
                                } else {
                                        /* Standard answer: Interrupted! */
                                        if (uvd->debug >= 2)
-                                               info("%s: Interrupted!", __func__);
+                                               dev_info(&uvd->dev->dev,
+                                                        "%s: Interrupted!\n",
+                                                        __func__);
                                        return -EINTR;
                                }
                        } else {
@@ -2010,8 +2058,10 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                        }
                } while (frame->frameState == FrameState_Grabbing);
                if (uvd->debug >= 2) {
-                       info("%s: Grabbing done; state=%d. (%lu. bytes)",
-                            __func__, frame->frameState, frame->seqRead_Length);
+                       dev_info(&uvd->dev->dev,
+                                "%s: Grabbing done; state=%d. (%lu. bytes)\n",
+                                __func__, frame->frameState,
+                                frame->seqRead_Length);
                }
                if (frame->frameState == FrameState_Error) {
                        int ret = usbvideo_NewFrame(uvd, frameNum);
@@ -2048,7 +2098,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                }
                frame->frameState = FrameState_Done_Hold;
                if (uvd->debug >= 2)
-                       info("%s: Entered FrameState_Done_Hold state.", __func__);
+                       dev_info(&uvd->dev->dev,
+                                "%s: Entered FrameState_Done_Hold state.\n",
+                                __func__);
                return 0;
 
        case FrameState_Done_Hold:
@@ -2059,7 +2111,9 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
                 * it will be released back into the wild to roam freely.
                 */
                if (uvd->debug >= 2)
-                       info("%s: FrameState_Done_Hold state.", __func__);
+                       dev_info(&uvd->dev->dev,
+                                "%s: FrameState_Done_Hold state.\n",
+                                __func__);
                return 0;
        }
 
index 2eb45829791ccf509a04a15599df1381f1c732cd..7a127d6bfdee5432770136980b3899afc6f25825 100644 (file)
@@ -472,9 +472,8 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
 static int
 vicam_open(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vicam_camera *cam =
-           (struct vicam_camera *) dev->priv;
+       struct vicam_camera *cam = video_drvdata(file);
+
        DBG("open\n");
 
        if (!cam) {
@@ -488,20 +487,24 @@ vicam_open(struct inode *inode, struct file *file)
         * rely on this fact forever.
         */
 
+       lock_kernel();
        if (cam->open_count > 0) {
                printk(KERN_INFO
                       "vicam_open called on already opened camera");
+               unlock_kernel();
                return -EBUSY;
        }
 
        cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
        if (!cam->raw_image) {
+               unlock_kernel();
                return -ENOMEM;
        }
 
        cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
        if (!cam->framebuf) {
                kfree(cam->raw_image);
+               unlock_kernel();
                return -ENOMEM;
        }
 
@@ -509,6 +512,7 @@ vicam_open(struct inode *inode, struct file *file)
        if (!cam->cntrlbuf) {
                kfree(cam->raw_image);
                rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
+               unlock_kernel();
                return -ENOMEM;
        }
 
@@ -526,6 +530,7 @@ vicam_open(struct inode *inode, struct file *file)
        cam->open_count++;
 
        file->private_data = cam;
+       unlock_kernel();
 
        return 0;
 }
@@ -795,6 +800,7 @@ static struct video_device vicam_template = {
        .name           = "ViCam-based USB Camera",
        .fops           = &vicam_fops,
        .minor          = -1,
+       .release        = video_device_release_empty,
 };
 
 /* table of devices that work with this driver */
@@ -859,9 +865,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
 
        mutex_init(&cam->cam_lock);
 
-       memcpy(&cam->vdev, &vicam_template,
-              sizeof (vicam_template));
-       cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
+       memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template));
+       video_set_drvdata(&cam->vdev, cam);
 
        cam->udev = dev;
        cam->bulkEndpoint = bulkEndpoint;
index c317ed7a8482fdbcaf47e5f7e635cc634e1cbee9..9e4f50639975308c0ca23ed446f1aa26d8e4f4df 100644 (file)
 
 #include <linux/workqueue.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #include "usbvision.h"
 
 static unsigned int core_debug;
@@ -84,7 +80,8 @@ MODULE_PARM_DESC(adjust_Y_Offset, "adjust Y offset display [core]");
 #ifdef USBVISION_DEBUG
        #define PDEBUG(level, fmt, args...) { \
                if (core_debug & (level)) \
-                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
        }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
index a6d00858b07ecad47da68bf54ccb06280fe55352..92427fdc1459b2b62af94aabe79063a08dc335f3 100644 (file)
@@ -47,7 +47,8 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 
 #define PDEBUG(level, fmt, args...) { \
                if (i2c_debug & (level)) \
-                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
        }
 
 static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
index b977116a0dd99ccfa6475940c01bb860605dea13..77aeb39b2750b1a34e660e3a733209e89da792af 100644 (file)
 
 #include <linux/workqueue.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #include "usbvision.h"
 #include "usbvision-cards.h"
 
@@ -98,7 +94,8 @@ USBVISION_DRIVER_VERSION_PATCHLEVEL)
 #ifdef USBVISION_DEBUG
        #define PDEBUG(level, fmt, args...) { \
                if (video_debug & (level)) \
-                       info("[%s:%d] " fmt, __func__, __LINE__ , ## args); \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
        }
 #else
        #define PDEBUG(level, fmt, args...) do {} while(0)
@@ -360,13 +357,12 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
  */
 static int usbvision_v4l2_open(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
 
        PDEBUG(DBG_IO, "open");
 
+       lock_kernel();
        usbvision_reset_powerOffTimer(usbvision);
 
        if (usbvision->user)
@@ -424,6 +420,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
        usbvision_empty_framequeues(usbvision);
 
        PDEBUG(DBG_IO, "success");
+       unlock_kernel();
        return errCode;
 }
 
@@ -437,9 +434,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
  */
 static int usbvision_v4l2_close(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        PDEBUG(DBG_IO, "close");
        mutex_lock(&usbvision->lock);
@@ -484,9 +479,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
 static int vidioc_g_register (struct file *file, void *priv,
                                struct v4l2_register *reg)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode;
 
        if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
@@ -505,9 +498,7 @@ static int vidioc_g_register (struct file *file, void *priv,
 static int vidioc_s_register (struct file *file, void *priv,
                                struct v4l2_register *reg)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode;
 
        if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
@@ -526,9 +517,7 @@ static int vidioc_s_register (struct file *file, void *priv,
 static int vidioc_querycap (struct file *file, void  *priv,
                                        struct v4l2_capability *vc)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
        strlcpy(vc->card,
@@ -548,9 +537,7 @@ static int vidioc_querycap (struct file *file, void  *priv,
 static int vidioc_enum_input (struct file *file, void *priv,
                                struct v4l2_input *vi)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int chan;
 
        if ((vi->index >= usbvision->video_inputs) || (vi->index < 0) )
@@ -603,9 +590,7 @@ static int vidioc_enum_input (struct file *file, void *priv,
 
 static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        *input = usbvision->ctl_input;
        return 0;
@@ -613,9 +598,7 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *input)
 
 static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        if ((input >= usbvision->video_inputs) || (input < 0) )
                return -EINVAL;
@@ -632,9 +615,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int input)
 
 static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
        usbvision->tvnormId=*id;
 
        mutex_lock(&usbvision->lock);
@@ -650,9 +632,7 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
 static int vidioc_g_tuner (struct file *file, void *priv,
                                struct v4l2_tuner *vt)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        if (!usbvision->have_tuner || vt->index)        // Only tuner 0
                return -EINVAL;
@@ -671,9 +651,7 @@ static int vidioc_g_tuner (struct file *file, void *priv,
 static int vidioc_s_tuner (struct file *file, void *priv,
                                struct v4l2_tuner *vt)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        // Only no or one tuner for now
        if (!usbvision->have_tuner || vt->index)
@@ -687,9 +665,7 @@ static int vidioc_s_tuner (struct file *file, void *priv,
 static int vidioc_g_frequency (struct file *file, void *priv,
                                struct v4l2_frequency *freq)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        freq->tuner = 0; // Only one tuner
        if(usbvision->radio) {
@@ -705,9 +681,7 @@ static int vidioc_g_frequency (struct file *file, void *priv,
 static int vidioc_s_frequency (struct file *file, void *priv,
                                struct v4l2_frequency *freq)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        // Only no or one tuner for now
        if (!usbvision->have_tuner || freq->tuner)
@@ -721,9 +695,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
 
 static int vidioc_g_audio (struct file *file, void *priv, struct v4l2_audio *a)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        memset(a,0,sizeof(*a));
        if(usbvision->radio) {
@@ -748,9 +720,7 @@ static int vidioc_s_audio (struct file *file, void *fh,
 static int vidioc_queryctrl (struct file *file, void *priv,
                            struct v4l2_queryctrl *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int id=ctrl->id;
 
        memset(ctrl,0,sizeof(*ctrl));
@@ -767,9 +737,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
 static int vidioc_g_ctrl (struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        call_i2c_clients(usbvision, VIDIOC_G_CTRL, ctrl);
 
        return 0;
@@ -778,9 +746,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
 static int vidioc_s_ctrl (struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        call_i2c_clients(usbvision, VIDIOC_S_CTRL, ctrl);
 
        return 0;
@@ -789,9 +755,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
 static int vidioc_reqbufs (struct file *file,
                           void *priv, struct v4l2_requestbuffers *vr)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int ret;
 
        RESTRICT_TO_RANGE(vr->count,1,USBVISION_NUMFRAMES);
@@ -819,9 +783,7 @@ static int vidioc_reqbufs (struct file *file,
 static int vidioc_querybuf (struct file *file,
                            void *priv, struct v4l2_buffer *vb)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        struct usbvision_frame *frame;
 
        /* FIXME : must control
@@ -857,9 +819,7 @@ static int vidioc_querybuf (struct file *file,
 
 static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        struct usbvision_frame *frame;
        unsigned long lock_flags;
 
@@ -896,9 +856,7 @@ static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
 
 static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int ret;
        struct usbvision_frame *f;
        unsigned long lock_flags;
@@ -939,9 +897,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *vb)
 
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        usbvision->streaming = Stream_On;
@@ -953,9 +909,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 static int vidioc_streamoff(struct file *file,
                            void *priv, enum v4l2_buf_type type)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int b=V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
        if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -988,9 +942,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
 static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
                                        struct v4l2_format *vf)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        vf->fmt.pix.width = usbvision->curwidth;
        vf->fmt.pix.height = usbvision->curheight;
        vf->fmt.pix.pixelformat = usbvision->palette.format;
@@ -1006,9 +958,7 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
 static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
                               struct v4l2_format *vf)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int formatIdx;
 
        /* Find requested format in available ones */
@@ -1036,9 +986,7 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                               struct v4l2_format *vf)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int ret;
 
        if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) {
@@ -1066,9 +1014,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
                      size_t count, loff_t *ppos)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int noblock = file->f_flags & O_NONBLOCK;
        unsigned long lock_flags;
 
@@ -1177,10 +1123,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
                start = vma->vm_start;
        void *pos;
        u32 i;
-
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
 
        PDEBUG(DBG_MMAP, "mmap");
 
@@ -1237,9 +1180,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
  */
 static int usbvision_radio_open(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
 
        PDEBUG(DBG_IO, "%s:", __func__);
@@ -1289,9 +1230,7 @@ out:
 
 static int usbvision_radio_close(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct usb_usbvision *usbvision =
-               (struct usb_usbvision *) video_get_drvdata(dev);
+       struct usb_usbvision *usbvision = video_drvdata(file);
        int errCode = 0;
 
        PDEBUG(DBG_IO, "");
index feab12aa2c7b5e9c0efb030a7eb1551611dbc766..f16aafe9cf145a6cbbdc44af3451649939573968 100644 (file)
@@ -81,6 +81,22 @@ static struct uvc_control_info uvc_ctrls[] = {
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
                                | UVC_CONTROL_RESTORE,
        },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+               .index          = 6,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .index          = 7,
+               .size           = 4,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
        {
                .entity         = UVC_GUID_UVC_PROCESSING,
                .selector       = PU_BACKLIGHT_COMPENSATION_CONTROL,
@@ -113,6 +129,60 @@ static struct uvc_control_info uvc_ctrls[] = {
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
        },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+               .index          = 12,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .index          = 13,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_DIGITAL_MULTIPLIER_CONTROL,
+               .index          = 14,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
+               .index          = 15,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_ANALOG_VIDEO_STANDARD_CONTROL,
+               .index          = 16,
+               .size           = 1,
+               .flags          = UVC_CONTROL_GET_CUR,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_ANALOG_LOCK_STATUS_CONTROL,
+               .index          = 17,
+               .size           = 1,
+               .flags          = UVC_CONTROL_GET_CUR,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_SCANNING_MODE_CONTROL,
+               .index          = 0,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_RESTORE,
+       },
        {
                .entity         = UVC_GUID_UVC_CAMERA,
                .selector       = CT_AE_MODE_CONTROL,
@@ -138,6 +208,14 @@ static struct uvc_control_info uvc_ctrls[] = {
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
                                | UVC_CONTROL_RESTORE,
        },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_EXPOSURE_TIME_RELATIVE_CONTROL,
+               .index          = 4,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_RESTORE,
+       },
        {
                .entity         = UVC_GUID_UVC_CAMERA,
                .selector       = CT_FOCUS_ABSOLUTE_CONTROL,
@@ -148,42 +226,90 @@ static struct uvc_control_info uvc_ctrls[] = {
        },
        {
                .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = CT_FOCUS_AUTO_CONTROL,
-               .index          = 17,
-               .size           = 1,
-               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
-                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+               .selector       = CT_FOCUS_RELATIVE_CONTROL,
+               .index          = 6,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_AUTO_UPDATE,
        },
        {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
-               .index          = 12,
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_IRIS_ABSOLUTE_CONTROL,
+               .index          = 7,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_IRIS_RELATIVE_CONTROL,
+               .index          = 8,
                .size           = 1,
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
-                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+                               | UVC_CONTROL_AUTO_UPDATE,
        },
        {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
-               .index          = 6,
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ZOOM_ABSOLUTE_CONTROL,
+               .index          = 9,
                .size           = 2,
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
        },
        {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ZOOM_RELATIVE_CONTROL,
+               .index          = 10,
+               .size           = 3,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_PANTILT_ABSOLUTE_CONTROL,
+               .index          = 11,
+               .size           = 8,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_PANTILT_RELATIVE_CONTROL,
+               .index          = 12,
+               .size           = 4,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ROLL_ABSOLUTE_CONTROL,
                .index          = 13,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_ROLL_RELATIVE_CONTROL,
+               .index          = 14,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_FOCUS_AUTO_CONTROL,
+               .index          = 17,
                .size           = 1,
                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
        },
        {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = PU_WHITE_BALANCE_COMPONENT_CONTROL,
-               .index          = 7,
-               .size           = 4,
-               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_PRIVACY_CONTROL,
+               .index          = 18,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
        },
 };
@@ -711,7 +837,17 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
 
        for (i = 0; i < entity->ncontrols; ++i) {
                ctrl = &entity->controls[i];
-               if (ctrl->info == NULL || !ctrl->dirty)
+               if (ctrl->info == NULL)
+                       continue;
+
+               /* Reset the loaded flag for auto-update controls that were
+                * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
+                * uvc_ctrl_get from using the cached value.
+                */
+               if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE)
+                       ctrl->loaded = 0;
+
+               if (!ctrl->dirty)
                        continue;
 
                if (!rollback)
@@ -727,9 +863,6 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
                               ctrl->info->size);
 
-               if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
-                       ctrl->loaded = 0;
-
                ctrl->dirty = 0;
 
                if (ret < 0)
@@ -787,8 +920,7 @@ int uvc_ctrl_get(struct uvc_video_device *video,
                if (ret < 0)
                        return ret;
 
-               if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
-                       ctrl->loaded = 1;
+               ctrl->loaded = 1;
        }
 
        xctrl->value = uvc_get_le_value(
@@ -839,8 +971,7 @@ int uvc_ctrl_set(struct uvc_video_device *video,
                                return ret;
                }
 
-               if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
-                       ctrl->loaded = 1;
+               ctrl->loaded = 1;
        }
 
        if (!ctrl->dirty) {
index 7e102034d38da0726ffca86d58e1bd36fb7ca167..d7ad060640bc5758fd526d7864fc94adcab8a52c 100644 (file)
@@ -1663,7 +1663,7 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
        return uvc_video_suspend(&dev->video);
 }
 
-static int uvc_resume(struct usb_interface *intf)
+static int __uvc_resume(struct usb_interface *intf, int reset)
 {
        struct uvc_device *dev = usb_get_intfdata(intf);
        int ret;
@@ -1672,7 +1672,7 @@ static int uvc_resume(struct usb_interface *intf)
                intf->cur_altsetting->desc.bInterfaceNumber);
 
        if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
-               if ((ret = uvc_ctrl_resume_device(dev)) < 0)
+               if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0)
                        return ret;
 
                return uvc_status_resume(dev);
@@ -1687,6 +1687,16 @@ static int uvc_resume(struct usb_interface *intf)
        return uvc_video_resume(&dev->video);
 }
 
+static int uvc_resume(struct usb_interface *intf)
+{
+       return __uvc_resume(intf, 0);
+}
+
+static int uvc_reset_resume(struct usb_interface *intf)
+{
+       return __uvc_resume(intf, 1);
+}
+
 /* ------------------------------------------------------------------------
  * Driver initialization and cleanup
  */
@@ -1902,6 +1912,24 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Compaq Presario B1200 - Bison Electronics */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0104,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Acer Travelmate 7720 - Bison Electronics */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0105,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
        /* Medion Akoya Mini E1210 - Bison Electronics */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1920,6 +1948,24 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /*  Fujitsu Amilo SI2636 - Bison Electronics */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0202,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /*  Advent 4211 - Bison Electronics */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0203,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
        /* Bison Electronics */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1952,6 +1998,7 @@ struct uvc_driver uvc_driver = {
                .disconnect     = uvc_disconnect,
                .suspend        = uvc_suspend,
                .resume         = uvc_resume,
+               .reset_resume   = uvc_reset_resume,
                .id_table       = uvc_ids,
                .supports_autosuspend = 1,
        },
index 75e678ac54ebbe027aae395133e8a30ad76900b0..5d60b264d59a1d2f7d2a3b41c224023cc5aff40e 100644 (file)
@@ -177,9 +177,15 @@ int uvc_status_init(struct uvc_device *dev)
 
        uvc_input_init(dev);
 
+       dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
+       if (dev->status == NULL)
+               return -ENOMEM;
+
        dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (dev->int_urb == NULL)
+       if (dev->int_urb == NULL) {
+               kfree(dev->status);
                return -ENOMEM;
+       }
 
        pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
 
@@ -192,7 +198,7 @@ int uvc_status_init(struct uvc_device *dev)
                interval = fls(interval) - 1;
 
        usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
-               dev->status, sizeof dev->status, uvc_status_complete,
+               dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
                dev, interval);
 
        return usb_submit_urb(dev->int_urb, GFP_KERNEL);
@@ -202,6 +208,7 @@ void uvc_status_cleanup(struct uvc_device *dev)
 {
        usb_kill_urb(dev->int_urb);
        usb_free_urb(dev->int_urb);
+       kfree(dev->status);
        uvc_input_cleanup(dev);
 }
 
index d7bd71be40a9d8f76afd3a71c12b5025c714867d..78e4c4e09d89cb1c5fae161b7cce07f412712917 100644 (file)
@@ -400,15 +400,13 @@ static int uvc_has_privileges(struct uvc_fh *handle)
 
 static int uvc_v4l2_open(struct inode *inode, struct file *file)
 {
-       struct video_device *vdev;
        struct uvc_video_device *video;
        struct uvc_fh *handle;
        int ret = 0;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
        mutex_lock(&uvc_driver.open_mutex);
-       vdev = video_devdata(file);
-       video = video_get_drvdata(vdev);
+       video = video_drvdata(file);
 
        if (video->dev->state & UVC_DEV_DISCONNECTED) {
                ret = -ENODEV;
@@ -440,8 +438,7 @@ done:
 
 static int uvc_v4l2_release(struct inode *inode, struct file *file)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_video_device *video = video_drvdata(file);
        struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
@@ -845,10 +842,6 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
                if (ret < 0)
                        return ret;
 
-               if (!(video->streaming->cur_format->flags &
-                   UVC_FMT_FLAG_COMPRESSED))
-                       video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
-
                rb->count = ret;
                ret = 0;
                break;
@@ -1031,8 +1024,7 @@ static struct vm_operations_struct uvc_vm_ops = {
 
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_video_device *video = video_drvdata(file);
        struct uvc_buffer *uninitialized_var(buffer);
        struct page *page;
        unsigned long addr, start, size;
@@ -1085,8 +1077,7 @@ done:
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_video_device *video = video_drvdata(file);
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
 
index 6854ac78a1615b07353acfc6ca3d79286cc78e3f..b7bb23820d803013548ef99ce91ccd52039102fb 100644 (file)
@@ -455,7 +455,8 @@ static void uvc_video_decode_isoc(struct urb *urb,
                        urb->iso_frame_desc[i].actual_length - ret);
 
                /* Process the header again. */
-               uvc_video_decode_end(video, buf, mem, ret);
+               uvc_video_decode_end(video, buf, mem,
+                       urb->iso_frame_desc[i].actual_length);
 
                if (buf->state == UVC_BUF_STATE_DONE ||
                    buf->state == UVC_BUF_STATE_ERROR)
@@ -512,7 +513,7 @@ static void uvc_video_decode_bulk(struct urb *urb,
            video->bulk.payload_size >= video->bulk.max_payload_size) {
                if (!video->bulk.skip_payload && buf != NULL) {
                        uvc_video_decode_end(video, buf, video->bulk.header,
-                               video->bulk.header_size);
+                               video->bulk.payload_size);
                        if (buf->state == UVC_BUF_STATE_DONE ||
                            buf->state == UVC_BUF_STATE_ERROR)
                                buf = uvc_queue_next_buffer(&video->queue, buf);
@@ -655,7 +656,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
        if (size > UVC_MAX_FRAME_SIZE)
                return -EINVAL;
 
-       npackets = (size + psize - 1) / psize;
+       npackets = DIV_ROUND_UP(size, psize);
        if (npackets > UVC_MAX_ISO_PACKETS)
                npackets = UVC_MAX_ISO_PACKETS;
 
@@ -970,6 +971,11 @@ int uvc_video_enable(struct uvc_video_device *video, int enable)
                return 0;
        }
 
+       if (video->streaming->cur_format->flags & UVC_FMT_FLAG_COMPRESSED)
+               video->queue.flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
+       else
+               video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
+
        if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
                return ret;
 
index bafe3406e305bd035465851bdd70bd5438b1349a..9a6bc1aafb166bf5533f94494c7a71d68bdae7a1 100644 (file)
@@ -303,6 +303,8 @@ struct uvc_xu_control {
 #define UVC_MAX_FRAME_SIZE     (16*1024*1024)
 /* Maximum number of video buffers. */
 #define UVC_MAX_VIDEO_BUFFERS  32
+/* Maximum status buffer size in bytes of interrupt URB. */
+#define UVC_MAX_STATUS_SIZE    16
 
 #define UVC_CTRL_CONTROL_TIMEOUT       300
 #define UVC_CTRL_STREAMING_TIMEOUT     1000
@@ -634,7 +636,7 @@ struct uvc_device {
        /* Status Interrupt Endpoint */
        struct usb_host_endpoint *int_ep;
        struct urb *int_urb;
-       __u8 status[16];
+       __u8 *status;
        struct input_dev *input;
 
        /* Video Streaming interfaces */
index 79937d1031fc81283baf06abc62c5bc45a4c8409..928cb4037372e963f648c96656a65b9058baf98a 100644 (file)
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 static unsigned int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable debug messages");
index 88ca1310441767ff7314a546a02a8675b69f2cc5..846763d7349e3ca73c3dc56f077da8bf98ca08c6 100644 (file)
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #include <linux/videodev2.h>
 
 MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
@@ -187,9 +183,11 @@ const char **v4l2_ctrl_get_menu(u32 id)
                NULL
        };
        static const char *mpeg_audio_encoding[] = {
-               "Layer I",
-               "Layer II",
-               "Layer III",
+               "MPEG-1/2 Layer I",
+               "MPEG-1/2 Layer II",
+               "MPEG-1/2 Layer III",
+               "MPEG-2/4 AAC",
+               "AC-3",
                NULL
        };
        static const char *mpeg_audio_l1_bitrate[] = {
@@ -243,6 +241,28 @@ const char **v4l2_ctrl_get_menu(u32 id)
                "320 kbps",
                NULL
        };
+       static const char *mpeg_audio_ac3_bitrate[] = {
+               "32 kbps",
+               "40 kbps",
+               "48 kbps",
+               "56 kbps",
+               "64 kbps",
+               "80 kbps",
+               "96 kbps",
+               "112 kbps",
+               "128 kbps",
+               "160 kbps",
+               "192 kbps",
+               "224 kbps",
+               "256 kbps",
+               "320 kbps",
+               "384 kbps",
+               "448 kbps",
+               "512 kbps",
+               "576 kbps",
+               "640 kbps",
+               NULL
+       };
        static const char *mpeg_audio_mode[] = {
                "Stereo",
                "Joint Stereo",
@@ -271,6 +291,7 @@ const char **v4l2_ctrl_get_menu(u32 id)
        static const char *mpeg_video_encoding[] = {
                "MPEG-1",
                "MPEG-2",
+               "MPEG-4 AVC",
                NULL
        };
        static const char *mpeg_video_aspect[] = {
@@ -311,6 +332,8 @@ const char **v4l2_ctrl_get_menu(u32 id)
                        return mpeg_audio_l2_bitrate;
                case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
                        return mpeg_audio_l3_bitrate;
+               case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+                       return mpeg_audio_ac3_bitrate;
                case V4L2_CID_MPEG_AUDIO_MODE:
                        return mpeg_audio_mode;
                case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
@@ -335,62 +358,73 @@ const char **v4l2_ctrl_get_menu(u32 id)
 }
 EXPORT_SYMBOL(v4l2_ctrl_get_menu);
 
-/* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+/* Return the control name. */
+const char *v4l2_ctrl_get_name(u32 id)
 {
-       const char *name;
-
-       qctrl->flags = 0;
-       switch (qctrl->id) {
+       switch (id) {
        /* USER controls */
-       case V4L2_CID_USER_CLASS:       name = "User Controls"; break;
-       case V4L2_CID_AUDIO_VOLUME:     name = "Volume"; break;
-       case V4L2_CID_AUDIO_MUTE:       name = "Mute"; break;
-       case V4L2_CID_AUDIO_BALANCE:    name = "Balance"; break;
-       case V4L2_CID_AUDIO_BASS:       name = "Bass"; break;
-       case V4L2_CID_AUDIO_TREBLE:     name = "Treble"; break;
-       case V4L2_CID_AUDIO_LOUDNESS:   name = "Loudness"; break;
-       case V4L2_CID_BRIGHTNESS:       name = "Brightness"; break;
-       case V4L2_CID_CONTRAST:         name = "Contrast"; break;
-       case V4L2_CID_SATURATION:       name = "Saturation"; break;
-       case V4L2_CID_HUE:              name = "Hue"; break;
+       case V4L2_CID_USER_CLASS:       return "User Controls";
+       case V4L2_CID_AUDIO_VOLUME:     return "Volume";
+       case V4L2_CID_AUDIO_MUTE:       return "Mute";
+       case V4L2_CID_AUDIO_BALANCE:    return "Balance";
+       case V4L2_CID_AUDIO_BASS:       return "Bass";
+       case V4L2_CID_AUDIO_TREBLE:     return "Treble";
+       case V4L2_CID_AUDIO_LOUDNESS:   return "Loudness";
+       case V4L2_CID_BRIGHTNESS:       return "Brightness";
+       case V4L2_CID_CONTRAST:         return "Contrast";
+       case V4L2_CID_SATURATION:       return "Saturation";
+       case V4L2_CID_HUE:              return "Hue";
 
        /* MPEG controls */
-       case V4L2_CID_MPEG_CLASS:               name = "MPEG Encoder Controls"; break;
-       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break;
-       case V4L2_CID_MPEG_AUDIO_ENCODING:      name = "Audio Encoding Layer"; break;
-       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:    name = "Audio Layer I Bitrate"; break;
-       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:    name = "Audio Layer II Bitrate"; break;
-       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:    name = "Audio Layer III Bitrate"; break;
-       case V4L2_CID_MPEG_AUDIO_MODE:          name = "Audio Stereo Mode"; break;
-       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break;
-       case V4L2_CID_MPEG_AUDIO_EMPHASIS:      name = "Audio Emphasis"; break;
-       case V4L2_CID_MPEG_AUDIO_CRC:           name = "Audio CRC"; break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:          name = "Audio Mute"; break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:      name = "Video Encoding"; break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:        name = "Video Aspect"; break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:      name = "Video B Frames"; break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:      name = "Video GOP Size"; break;
-       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:   name = "Video GOP Closure"; break;
-       case V4L2_CID_MPEG_VIDEO_PULLDOWN:      name = "Video Pulldown"; break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:  name = "Video Bitrate Mode"; break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:       name = "Video Bitrate"; break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:  name = "Video Peak Bitrate"; break;
-       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break;
-       case V4L2_CID_MPEG_VIDEO_MUTE:          name = "Video Mute"; break;
-       case V4L2_CID_MPEG_VIDEO_MUTE_YUV:      name = "Video Mute YUV"; break;
-       case V4L2_CID_MPEG_STREAM_TYPE:         name = "Stream Type"; break;
-       case V4L2_CID_MPEG_STREAM_PID_PMT:      name = "Stream PMT Program ID"; break;
-       case V4L2_CID_MPEG_STREAM_PID_AUDIO:    name = "Stream Audio Program ID"; break;
-       case V4L2_CID_MPEG_STREAM_PID_VIDEO:    name = "Stream Video Program ID"; break;
-       case V4L2_CID_MPEG_STREAM_PID_PCR:      name = "Stream PCR Program ID"; break;
-       case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break;
-       case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break;
-       case V4L2_CID_MPEG_STREAM_VBI_FMT:      name = "Stream VBI Format"; break;
+       case V4L2_CID_MPEG_CLASS:               return "MPEG Encoder Controls";
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency";
+       case V4L2_CID_MPEG_AUDIO_ENCODING:      return "Audio Encoding";
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:    return "Audio Layer I Bitrate";
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:    return "Audio Layer II Bitrate";
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:    return "Audio Layer III Bitrate";
+       case V4L2_CID_MPEG_AUDIO_AAC_BITRATE:   return "Audio AAC Bitrate";
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:   return "Audio AC-3 Bitrate";
+       case V4L2_CID_MPEG_AUDIO_MODE:          return "Audio Stereo Mode";
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension";
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:      return "Audio Emphasis";
+       case V4L2_CID_MPEG_AUDIO_CRC:           return "Audio CRC";
+       case V4L2_CID_MPEG_AUDIO_MUTE:          return "Audio Mute";
+       case V4L2_CID_MPEG_VIDEO_ENCODING:      return "Video Encoding";
+       case V4L2_CID_MPEG_VIDEO_ASPECT:        return "Video Aspect";
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:      return "Video B Frames";
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:      return "Video GOP Size";
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:   return "Video GOP Closure";
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:      return "Video Pulldown";
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:  return "Video Bitrate Mode";
+       case V4L2_CID_MPEG_VIDEO_BITRATE:       return "Video Bitrate";
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:  return "Video Peak Bitrate";
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation";
+       case V4L2_CID_MPEG_VIDEO_MUTE:          return "Video Mute";
+       case V4L2_CID_MPEG_VIDEO_MUTE_YUV:      return "Video Mute YUV";
+       case V4L2_CID_MPEG_STREAM_TYPE:         return "Stream Type";
+       case V4L2_CID_MPEG_STREAM_PID_PMT:      return "Stream PMT Program ID";
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:    return "Stream Audio Program ID";
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:    return "Stream Video Program ID";
+       case V4L2_CID_MPEG_STREAM_PID_PCR:      return "Stream PCR Program ID";
+       case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID";
+       case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID";
+       case V4L2_CID_MPEG_STREAM_VBI_FMT:      return "Stream VBI Format";
 
        default:
-               return -EINVAL;
+               return NULL;
        }
+}
+EXPORT_SYMBOL(v4l2_ctrl_get_name);
+
+/* Fill in a struct v4l2_queryctrl */
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+       const char *name = v4l2_ctrl_get_name(qctrl->id);
+
+       qctrl->flags = 0;
+       if (name == NULL)
+               return -EINVAL;
+
        switch (qctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
        case V4L2_CID_AUDIO_LOUDNESS:
@@ -407,6 +441,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
        case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
        case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
        case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
        case V4L2_CID_MPEG_AUDIO_MODE:
        case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
        case V4L2_CID_MPEG_AUDIO_EMPHASIS:
@@ -493,7 +528,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
        case V4L2_CID_MPEG_AUDIO_ENCODING:
                return v4l2_ctrl_query_fill(qctrl,
                                V4L2_MPEG_AUDIO_ENCODING_LAYER_1,
-                               V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1,
+                               V4L2_MPEG_AUDIO_ENCODING_AC3, 1,
                                V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
        case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
                return v4l2_ctrl_query_fill(qctrl,
@@ -510,6 +545,13 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
                                V4L2_MPEG_AUDIO_L3_BITRATE_32K,
                                V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1,
                                V4L2_MPEG_AUDIO_L3_BITRATE_192K);
+       case V4L2_CID_MPEG_AUDIO_AAC_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl, 0, 6400, 1, 3200000);
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_32K,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_640K, 1,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_384K);
        case V4L2_CID_MPEG_AUDIO_MODE:
                return v4l2_ctrl_query_fill(qctrl,
                                V4L2_MPEG_AUDIO_MODE_STEREO,
@@ -535,7 +577,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
        case V4L2_CID_MPEG_VIDEO_ENCODING:
                return v4l2_ctrl_query_fill(qctrl,
                                V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
                                V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
        case V4L2_CID_MPEG_VIDEO_ASPECT:
                return v4l2_ctrl_query_fill(qctrl,
@@ -594,12 +636,17 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
 EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
 
 /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
-   the menu. The qctrl pointer may be NULL, in which case it is ignored. */
+   the menu. The qctrl pointer may be NULL, in which case it is ignored.
+   If menu_items is NULL, then the menu items are retrieved using
+   v4l2_ctrl_get_menu. */
 int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
               const char **menu_items)
 {
        int i;
 
+       qmenu->reserved = 0;
+       if (menu_items == NULL)
+               menu_items = v4l2_ctrl_get_menu(qmenu->id);
        if (menu_items == NULL ||
            (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
                return -EINVAL;
@@ -607,11 +654,31 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc
        if (menu_items[i] == NULL || menu_items[i][0] == '\0')
                return -EINVAL;
        snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]);
-       qmenu->reserved = 0;
        return 0;
 }
 EXPORT_SYMBOL(v4l2_ctrl_query_menu);
 
+/* Fill in a struct v4l2_querymenu based on the specified array of valid
+   menu items (terminated by V4L2_CTRL_MENU_IDS_END).
+   Use this if there are 'holes' in the list of valid menu items. */
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
+{
+       const char **menu_items = v4l2_ctrl_get_menu(qmenu->id);
+
+       qmenu->reserved = 0;
+       if (menu_items == NULL || ids == NULL)
+               return -EINVAL;
+       while (*ids != V4L2_CTRL_MENU_IDS_END) {
+               if (*ids++ == qmenu->index) {
+                       snprintf(qmenu->name, sizeof(qmenu->name),
+                                      menu_items[qmenu->index]);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
+
 /* ctrl_classes points to an array of u32 pointers, the last element is
    a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
    Each array must be sorted low to high and belong to the same control
index 155fdec9ac7d7c4fc0aa773581021fbe59ab3355..ccd6566a515e1c293ec85f8f067f48fb4fea4643 100644 (file)
@@ -42,6 +42,7 @@ static ssize_t show_index(struct device *cd,
                         struct device_attribute *attr, char *buf)
 {
        struct video_device *vfd = container_of(cd, struct video_device, dev);
+
        return sprintf(buf, "%i\n", vfd->index);
 }
 
@@ -49,6 +50,7 @@ static ssize_t show_name(struct device *cd,
                         struct device_attribute *attr, char *buf)
 {
        struct video_device *vfd = container_of(cd, struct video_device, dev);
+
        return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
 }
 
@@ -58,12 +60,16 @@ static struct device_attribute video_device_attrs[] = {
        __ATTR_NULL
 };
 
+/*
+ *     Active devices
+ */
+static struct video_device *video_device[VIDEO_NUM_DEVICES];
+static DEFINE_MUTEX(videodev_lock);
+static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES);
+
 struct video_device *video_device_alloc(void)
 {
-       struct video_device *vfd;
-
-       vfd = kzalloc(sizeof(*vfd), GFP_KERNEL);
-       return vfd;
+       return kzalloc(sizeof(struct video_device), GFP_KERNEL);
 }
 EXPORT_SYMBOL(video_device_alloc);
 
@@ -73,16 +79,52 @@ void video_device_release(struct video_device *vfd)
 }
 EXPORT_SYMBOL(video_device_release);
 
+void video_device_release_empty(struct video_device *vfd)
+{
+       /* Do nothing */
+       /* Only valid when the video_device struct is a static. */
+}
+EXPORT_SYMBOL(video_device_release_empty);
+
+/* Called when the last user of the character device is gone. */
+static void v4l2_chardev_release(struct kobject *kobj)
+{
+       struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj);
+
+       mutex_lock(&videodev_lock);
+       if (video_device[vfd->minor] != vfd) {
+               mutex_unlock(&videodev_lock);
+               BUG();
+               return;
+       }
+
+       /* Free up this device for reuse */
+       video_device[vfd->minor] = NULL;
+       clear_bit(vfd->num, video_nums[vfd->vfl_type]);
+       mutex_unlock(&videodev_lock);
+
+       /* Release the character device */
+       vfd->cdev_release(kobj);
+       /* Release video_device and perform other
+          cleanups as needed. */
+       if (vfd->release)
+               vfd->release(vfd);
+}
+
+/* The new kobj_type for the character device */
+static struct kobj_type v4l2_ktype_cdev_default = {
+       .release = v4l2_chardev_release,
+};
+
 static void video_release(struct device *cd)
 {
        struct video_device *vfd = container_of(cd, struct video_device, dev);
 
-#if 1
-       /* needed until all drivers are fixed */
-       if (!vfd->release)
-               return;
-#endif
-       vfd->release(vfd);
+       /* It's now safe to delete the char device.
+          This will either trigger the v4l2_chardev_release immediately (if
+          the refcount goes to 0) or later when the last user of the
+          character device closes it. */
+       cdev_del(&vfd->cdev);
 }
 
 static struct class video_class = {
@@ -91,87 +133,12 @@ static struct class video_class = {
        .dev_release = video_release,
 };
 
-/*
- *     Active devices
- */
-
-static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DEFINE_MUTEX(videodev_lock);
-
 struct video_device *video_devdata(struct file *file)
 {
        return video_device[iminor(file->f_path.dentry->d_inode)];
 }
 EXPORT_SYMBOL(video_devdata);
 
-/*
- *     Open a video device - FIXME: Obsoleted
- */
-static int video_open(struct inode *inode, struct file *file)
-{
-       unsigned int minor = iminor(inode);
-       int err = 0;
-       struct video_device *vfl;
-       const struct file_operations *old_fops;
-
-       if (minor >= VIDEO_NUM_DEVICES)
-               return -ENODEV;
-       lock_kernel();
-       mutex_lock(&videodev_lock);
-       vfl = video_device[minor];
-       if (vfl == NULL) {
-               mutex_unlock(&videodev_lock);
-               request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
-               mutex_lock(&videodev_lock);
-               vfl = video_device[minor];
-               if (vfl == NULL) {
-                       mutex_unlock(&videodev_lock);
-                       unlock_kernel();
-                       return -ENODEV;
-               }
-       }
-       old_fops = file->f_op;
-       file->f_op = fops_get(vfl->fops);
-       if (file->f_op->open)
-               err = file->f_op->open(inode, file);
-       if (err) {
-               fops_put(file->f_op);
-               file->f_op = fops_get(old_fops);
-       }
-       fops_put(old_fops);
-       mutex_unlock(&videodev_lock);
-       unlock_kernel();
-       return err;
-}
-
-/*
- * open/release helper functions -- handle exclusive opens
- * Should be removed soon
- */
-int video_exclusive_open(struct inode *inode, struct file *file)
-{
-       struct video_device *vfl = video_devdata(file);
-       int retval = 0;
-
-       mutex_lock(&vfl->lock);
-       if (vfl->users)
-               retval = -EBUSY;
-       else
-               vfl->users++;
-       mutex_unlock(&vfl->lock);
-       return retval;
-}
-EXPORT_SYMBOL(video_exclusive_open);
-
-int video_exclusive_release(struct inode *inode, struct file *file)
-{
-       struct video_device *vfl = video_devdata(file);
-
-       vfl->users--;
-       return 0;
-}
-EXPORT_SYMBOL(video_exclusive_release);
-
 /**
  * get_index - assign stream number based on parent device
  * @vdev: video_device to assign index number to, vdev->dev should be assigned
@@ -252,33 +219,29 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
                                        int index)
 {
        int i = 0;
-       int base;
-       int end;
        int ret;
-       char *name_base;
+       int minor_offset = 0;
+       int minor_cnt = VIDEO_NUM_DEVICES;
+       const char *name_base;
+       void *priv = video_get_drvdata(vfd);
+
+       /* the release callback MUST be present */
+       BUG_ON(!vfd->release);
 
        if (vfd == NULL)
                return -EINVAL;
 
        switch (type) {
        case VFL_TYPE_GRABBER:
-               base = MINOR_VFL_TYPE_GRABBER_MIN;
-               end = MINOR_VFL_TYPE_GRABBER_MAX+1;
                name_base = "video";
                break;
        case VFL_TYPE_VTX:
-               base = MINOR_VFL_TYPE_VTX_MIN;
-               end = MINOR_VFL_TYPE_VTX_MAX+1;
                name_base = "vtx";
                break;
        case VFL_TYPE_VBI:
-               base = MINOR_VFL_TYPE_VBI_MIN;
-               end = MINOR_VFL_TYPE_VBI_MAX+1;
                name_base = "vbi";
                break;
        case VFL_TYPE_RADIO:
-               base = MINOR_VFL_TYPE_RADIO_MIN;
-               end = MINOR_VFL_TYPE_RADIO_MAX+1;
                name_base = "radio";
                break;
        default:
@@ -287,28 +250,70 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
                return -EINVAL;
        }
 
+       vfd->vfl_type = type;
+
+#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
+       /* Keep the ranges for the first four types for historical
+        * reasons.
+        * Newer devices (not yet in place) should use the range
+        * of 128-191 and just pick the first free minor there
+        * (new style). */
+       switch (type) {
+       case VFL_TYPE_GRABBER:
+               minor_offset = 0;
+               minor_cnt = 64;
+               break;
+       case VFL_TYPE_RADIO:
+               minor_offset = 64;
+               minor_cnt = 64;
+               break;
+       case VFL_TYPE_VTX:
+               minor_offset = 192;
+               minor_cnt = 32;
+               break;
+       case VFL_TYPE_VBI:
+               minor_offset = 224;
+               minor_cnt = 32;
+               break;
+       default:
+               minor_offset = 128;
+               minor_cnt = 64;
+               break;
+       }
+#endif
+
+       /* Initialize the character device */
+       cdev_init(&vfd->cdev, vfd->fops);
+       vfd->cdev.owner = vfd->fops->owner;
        /* pick a minor number */
        mutex_lock(&videodev_lock);
-       if (nr >= 0  &&  nr < end-base) {
-               /* use the one the driver asked for */
-               i = base + nr;
-               if (NULL != video_device[i]) {
-                       mutex_unlock(&videodev_lock);
-                       return -ENFILE;
-               }
-       } else {
-               /* use first free */
-               for (i = base; i < end; i++)
-                       if (NULL == video_device[i])
-                               break;
-               if (i == end) {
-                       mutex_unlock(&videodev_lock);
-                       return -ENFILE;
-               }
+       nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr);
+       if (nr == minor_cnt)
+               nr = find_first_zero_bit(video_nums[type], minor_cnt);
+       if (nr == minor_cnt) {
+               printk(KERN_ERR "could not get a free kernel number\n");
+               mutex_unlock(&videodev_lock);
+               return -ENFILE;
        }
-       video_device[i] = vfd;
-       vfd->vfl_type = type;
-       vfd->minor = i;
+#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
+       /* 1-on-1 mapping of kernel number to minor number */
+       i = nr;
+#else
+       /* The kernel number and minor numbers are independent */
+       for (i = 0; i < VIDEO_NUM_DEVICES; i++)
+               if (video_device[i] == NULL)
+                       break;
+       if (i == VIDEO_NUM_DEVICES) {
+               mutex_unlock(&videodev_lock);
+               printk(KERN_ERR "could not get a free minor\n");
+               return -ENFILE;
+       }
+#endif
+       vfd->minor = i + minor_offset;
+       vfd->num = nr;
+       set_bit(nr, video_nums[type]);
+       BUG_ON(video_device[vfd->minor]);
+       video_device[vfd->minor] = vfd;
 
        ret = get_index(vfd, index);
        vfd->index = ret;
@@ -320,35 +325,41 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
                goto fail_minor;
        }
 
-       mutex_init(&vfd->lock);
-
+       ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: cdev_add failed\n", __func__);
+               goto fail_minor;
+       }
        /* sysfs class */
-       memset(&vfd->dev, 0x00, sizeof(vfd->dev));
+       memset(&vfd->dev, 0, sizeof(vfd->dev));
+       /* The memset above cleared the device's drvdata, so
+          put back the copy we made earlier. */
+       video_set_drvdata(vfd, priv);
        vfd->dev.class = &video_class;
        vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
        if (vfd->parent)
                vfd->dev.parent = vfd->parent;
-       sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base);
+       sprintf(vfd->dev.bus_id, "%s%d", name_base, nr);
        ret = device_register(&vfd->dev);
        if (ret < 0) {
                printk(KERN_ERR "%s: device_register failed\n", __func__);
-               goto fail_minor;
+               goto del_cdev;
        }
-
-#if 1
-       /* needed until all drivers are fixed */
-       if (!vfd->release)
-               printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
-                      "Please fix your driver for proper sysfs support, see "
-                      "http://lwn.net/Articles/36850/\n", vfd->name);
-#endif
+       /* Remember the cdev's release function */
+       vfd->cdev_release = vfd->cdev.kobj.ktype->release;
+       /* Install our own */
+       vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default;
        return 0;
 
+del_cdev:
+       cdev_del(&vfd->cdev);
+
 fail_minor:
        mutex_lock(&videodev_lock);
        video_device[vfd->minor] = NULL;
-       vfd->minor = -1;
+       clear_bit(vfd->num, video_nums[type]);
        mutex_unlock(&videodev_lock);
+       vfd->minor = -1;
        return ret;
 }
 EXPORT_SYMBOL(video_register_device_index);
@@ -363,42 +374,29 @@ EXPORT_SYMBOL(video_register_device_index);
 
 void video_unregister_device(struct video_device *vfd)
 {
-       mutex_lock(&videodev_lock);
-       if (video_device[vfd->minor] != vfd)
-               panic("videodev: bad unregister");
-
-       video_device[vfd->minor] = NULL;
        device_unregister(&vfd->dev);
-       mutex_unlock(&videodev_lock);
 }
 EXPORT_SYMBOL(video_unregister_device);
 
-/*
- * Video fs operations
- */
-static const struct file_operations video_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .open           = video_open,
-};
-
 /*
  *     Initialise video for linux
  */
-
 static int __init videodev_init(void)
 {
+       dev_t dev = MKDEV(VIDEO_MAJOR, 0);
        int ret;
 
        printk(KERN_INFO "Linux video capture interface: v2.00\n");
-       if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
-               printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
-               return -EIO;
+       ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);
+       if (ret < 0) {
+               printk(KERN_WARNING "videodev: unable to get major %d\n",
+                               VIDEO_MAJOR);
+               return ret;
        }
 
        ret = class_register(&video_class);
        if (ret < 0) {
-               unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+               unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
                printk(KERN_WARNING "video_dev: class_register failed\n");
                return -EIO;
        }
@@ -408,8 +406,10 @@ static int __init videodev_init(void)
 
 static void __exit videodev_exit(void)
 {
+       dev_t dev = MKDEV(VIDEO_MAJOR, 0);
+
        class_unregister(&video_class);
-       unregister_chrdev(VIDEO_MAJOR, VIDEO_NAME);
+       unregister_chrdev_region(dev, VIDEO_NUM_DEVICES);
 }
 
 module_init(videodev_init)
index 140ef92c19c1e5c1333f1e30881a8150c0edbfed..155c9d77a463531d43989b75e2505da632f901b2 100644 (file)
@@ -746,18 +746,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
                                ret = ops->vidioc_enum_fmt_vid_overlay(file,
                                        fh, f);
                        break;
-#if 1
-               /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
-                * according to the spec. The bttv and saa7134 drivers support
-                * it though, so just warn that this is deprecated and will be
-                * removed in the near future. */
-               case V4L2_BUF_TYPE_VBI_CAPTURE:
-                       if (ops->vidioc_enum_fmt_vbi_cap) {
-                               printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
-                               ret = ops->vidioc_enum_fmt_vbi_cap(file, fh, f);
-                       }
-                       break;
-#endif
                case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                        if (ops->vidioc_enum_fmt_vid_out)
                                ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
deleted file mode 100644 (file)
index cf24956..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * VIDEO MOTION CODECs internal API for video devices
- *
- * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
- * bound to a master device.
- *
- * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * ------------------------------------------------------------------------
- */
-
-#define VIDEOCODEC_VERSION "v0.2"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-// kernel config is here (procfs flag)
-
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#endif
-
-#include "videocodec.h"
-
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-struct attached_list {
-       struct videocodec *codec;
-       struct attached_list *next;
-};
-
-struct codec_list {
-       const struct videocodec *codec;
-       int attached;
-       struct attached_list *list;
-       struct codec_list *next;
-};
-
-static struct codec_list *codeclist_top = NULL;
-
-/* ================================================= */
-/* function prototypes of the master/slave interface */
-/* ================================================= */
-
-struct videocodec *
-videocodec_attach (struct videocodec_master *master)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a, *ptr;
-       struct videocodec *codec;
-       int res;
-
-       if (!master) {
-               dprintk(1, KERN_ERR "videocodec_attach: no data\n");
-               return NULL;
-       }
-
-       dprintk(2,
-               "videocodec_attach: '%s', flags %lx, magic %lx\n",
-               master->name, master->flags, master->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR
-                       "videocodec_attach: no device available\n");
-               return NULL;
-       }
-
-       while (h) {
-               // attach only if the slave has at least the flags
-               // expected by the master
-               if ((master->flags & h->codec->flags) == master->flags) {
-                       dprintk(4, "videocodec_attach: try '%s'\n",
-                               h->codec->name);
-
-                       if (!try_module_get(h->codec->owner))
-                               return NULL;
-
-                       codec =
-                           kmalloc(sizeof(struct videocodec), GFP_KERNEL);
-                       if (!codec) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "videocodec_attach: no mem\n");
-                               goto out_module_put;
-                       }
-                       memcpy(codec, h->codec, sizeof(struct videocodec));
-
-                       snprintf(codec->name, sizeof(codec->name),
-                                "%s[%d]", codec->name, h->attached);
-                       codec->master_data = master;
-                       res = codec->setup(codec);
-                       if (res == 0) {
-                               dprintk(3, "videocodec_attach '%s'\n",
-                                       codec->name);
-                               ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
-                               if (!ptr) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "videocodec_attach: no memory\n");
-                                       goto out_kfree;
-                               }
-                               ptr->codec = codec;
-
-                               a = h->list;
-                               if (!a) {
-                                       h->list = ptr;
-                                       dprintk(4,
-                                               "videocodec: first element\n");
-                               } else {
-                                       while (a->next)
-                                               a = a->next;    // find end
-                                       a->next = ptr;
-                                       dprintk(4,
-                                               "videocodec: in after '%s'\n",
-                                               h->codec->name);
-                               }
-
-                               h->attached += 1;
-                               return codec;
-                       } else {
-                               kfree(codec);
-                       }
-               }
-               h = h->next;
-       }
-
-       dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
-       return NULL;
-
- out_module_put:
-       module_put(h->codec->owner);
- out_kfree:
-       kfree(codec);
-       return NULL;
-}
-
-int
-videocodec_detach (struct videocodec *codec)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a, *prev;
-       int res;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_detach: no data\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR "videocodec_detach: no device left...\n");
-               return -ENXIO;
-       }
-
-       while (h) {
-               a = h->list;
-               prev = NULL;
-               while (a) {
-                       if (codec == a->codec) {
-                               res = a->codec->unset(a->codec);
-                               if (res >= 0) {
-                                       dprintk(3,
-                                               "videocodec_detach: '%s'\n",
-                                               a->codec->name);
-                                       a->codec->master_data = NULL;
-                               } else {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "videocodec_detach: '%s'\n",
-                                               a->codec->name);
-                                       a->codec->master_data = NULL;
-                               }
-                               if (prev == NULL) {
-                                       h->list = a->next;
-                                       dprintk(4,
-                                               "videocodec: delete first\n");
-                               } else {
-                                       prev->next = a->next;
-                                       dprintk(4,
-                                               "videocodec: delete middle\n");
-                               }
-                               module_put(a->codec->owner);
-                               kfree(a->codec);
-                               kfree(a);
-                               h->attached -= 1;
-                               return 0;
-                       }
-                       prev = a;
-                       a = a->next;
-               }
-               h = h->next;
-       }
-
-       dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n");
-       return -EINVAL;
-}
-
-int
-videocodec_register (const struct videocodec *codec)
-{
-       struct codec_list *ptr, *h = codeclist_top;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_register: no data!\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
-       if (!ptr) {
-               dprintk(1, KERN_ERR "videocodec_register: no memory\n");
-               return -ENOMEM;
-       }
-       ptr->codec = codec;
-
-       if (!h) {
-               codeclist_top = ptr;
-               dprintk(4, "videocodec: hooked in as first element\n");
-       } else {
-               while (h->next)
-                       h = h->next;    // find the end
-               h->next = ptr;
-               dprintk(4, "videocodec: hooked in after '%s'\n",
-                       h->codec->name);
-       }
-
-       return 0;
-}
-
-int
-videocodec_unregister (const struct videocodec *codec)
-{
-       struct codec_list *prev = NULL, *h = codeclist_top;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_unregister: no data!\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR
-                       "videocodec_unregister: no device left...\n");
-               return -ENXIO;
-       }
-
-       while (h) {
-               if (codec == h->codec) {
-                       if (h->attached) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "videocodec: '%s' is used\n",
-                                       h->codec->name);
-                               return -EBUSY;
-                       }
-                       dprintk(3, "videocodec: unregister '%s' is ok.\n",
-                               h->codec->name);
-                       if (prev == NULL) {
-                               codeclist_top = h->next;
-                               dprintk(4,
-                                       "videocodec: delete first element\n");
-                       } else {
-                               prev->next = h->next;
-                               dprintk(4,
-                                       "videocodec: delete middle element\n");
-                       }
-                       kfree(h);
-                       return 0;
-               }
-               prev = h;
-               h = h->next;
-       }
-
-       dprintk(1,
-               KERN_ERR
-               "videocodec_unregister: given codec not found!\n");
-       return -EINVAL;
-}
-
-#ifdef CONFIG_PROC_FS
-static int proc_videocodecs_show(struct seq_file *m, void *v)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a;
-
-       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
-       seq_printf(m, "(connected as)\n");
-
-       h = codeclist_top;
-       while (h) {
-               seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
-                             h->codec->name, h->codec->type,
-                             h->codec->flags, h->codec->magic);
-               a = h->list;
-               while (a) {
-                       seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
-                                     a->codec->master_data->name,
-                                     a->codec->master_data->type,
-                                     a->codec->master_data->flags,
-                                     a->codec->master_data->magic,
-                                     a->codec->name);
-                       a = a->next;
-               }
-               h = h->next;
-       }
-
-       return 0;
-}
-
-static int proc_videocodecs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_videocodecs_show, NULL);
-}
-
-static const struct file_operations videocodecs_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_videocodecs_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-#endif
-
-/* ===================== */
-/* hook in driver module */
-/* ===================== */
-static int __init
-videocodec_init (void)
-{
-#ifdef CONFIG_PROC_FS
-       static struct proc_dir_entry *videocodec_proc_entry;
-#endif
-
-       printk(KERN_INFO "Linux video codec intermediate layer: %s\n",
-              VIDEOCODEC_VERSION);
-
-#ifdef CONFIG_PROC_FS
-       videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
-       if (!videocodec_proc_entry) {
-               dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
-       }
-#endif
-       return 0;
-}
-
-static void __exit
-videocodec_exit (void)
-{
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("videocodecs", NULL);
-#endif
-}
-
-EXPORT_SYMBOL(videocodec_attach);
-EXPORT_SYMBOL(videocodec_detach);
-EXPORT_SYMBOL(videocodec_register);
-EXPORT_SYMBOL(videocodec_unregister);
-
-module_init(videocodec_init);
-module_exit(videocodec_exit);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Intermediate API module for video codecs "
-                  VIDEOCODEC_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h
deleted file mode 100644 (file)
index 97a3bbe..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * VIDEO MOTION CODECs internal API for video devices
- *
- * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
- * bound to a master device.
- *
- * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: videocodec.h,v 1.1.2.4 2003/01/14 21:15:03 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * ------------------------------------------------------------------------
- */
-
-/* =================== */
-/* general description */
-/* =================== */
-
-/* Should ease the (re-)usage of drivers supporting cards with (different)
-   video codecs. The codecs register to this module their functionality,
-   and the processors (masters) can attach to them if they fit.
-
-   The codecs are typically have a "strong" binding to their master - so I
-   don't think it makes sense to have a full blown interfacing as with e.g.
-   i2c. If you have an other opinion, let's discuss & implement it :-)))
-
-   Usage:
-
-   The slave has just to setup the videocodec structure and use two functions:
-   videocodec_register(codecdata);
-   videocodec_unregister(codecdata);
-   The best is just calling them at module (de-)initialisation.
-
-   The master sets up the structure videocodec_master and calls:
-   codecdata=videocodec_attach(master_codecdata);
-   videocodec_detach(codecdata);
-
-   The slave is called during attach/detach via functions setup previously
-   during register. At that time, the master_data pointer is set up
-   and the slave can access any io registers of the master device (in the case
-   the slave is bound to it). Otherwise it doesn't need this functions and
-   therfor they may not be initialized.
-
-   The other fuctions are just for convenience, as they are for sure used by
-   most/all of the codecs. The last ones may be ommited, too.
-
-   See the structure declaration below for more information and which data has
-   to be set up for the master and the slave.
-
-   ----------------------------------------------------------------------------
-   The master should have "knowledge" of the slave and vice versa.  So the data
-   structures sent to/from slave via set_data/get_data set_image/get_image are
-   device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!)
-   ----------------------------------------------------------------------------
-*/
-\f
-
-/* ========================================== */
-/* description of the videocodec_io structure */
-/* ========================================== */
-
-/*
-   ==== master setup ====
-   name -> name of the device structure for reference and debugging
-   master_data ->  data ref. for the master (e.g. the zr36055,57,67)
-   readreg -> ref. to read-fn from register (setup by master, used by slave)
-   writereg -> ref. to write-fn to register (setup by master, used by slave)
-              this two functions do the lowlevel I/O job
-
-   ==== slave functionality setup ====
-   slave_data -> data ref. for the slave (e.g. the zr36050,60)
-   check -> fn-ref. checks availability of an device, returns -EIO on failure or
-           the type on success
-           this makes espcecially sense if a driver module supports more than
-           one codec which may be quite similar to access, nevertheless it
-           is good for a first functionality check
-
-   -- main functions you always need for compression/decompression --
-
-   set_mode -> this fn-ref. resets the entire codec, and sets up the mode
-              with the last defined norm/size (or device default if not
-              available) - it returns 0 if the mode is possible
-   set_size -> this fn-ref. sets the norm and image size for
-              compression/decompression (returns 0 on success)
-              the norm param is defined in videodev.h (VIDEO_MODE_*)
-
-   additional setup may be available, too - but the codec should work with
-   some default values even without this
-
-   set_data -> sets device-specific data (tables, quality etc.)
-   get_data -> query device-specific data (tables, quality etc.)
-
-   if the device delivers interrupts, they may be setup/handled here
-   setup_interrupt -> codec irq setup (not needed for 36050/60)
-   handle_interrupt -> codec irq handling (not needed for 36050/60)
-
-   if the device delivers pictures, they may be handled here
-   put_image -> puts image data to the codec (not needed for 36050/60)
-   get_image -> gets image data from the codec (not needed for 36050/60)
-               the calls include frame numbers and flags (even/odd/...)
-               if needed and a flag which allows blocking until its ready
-*/
-\f
-/* ============== */
-/* user interface */
-/* ============== */
-
-/*
-   Currently there is only a information display planned, as the layer
-   is not visible for the user space at all.
-
-   Information is available via procfs. The current entry is "/proc/videocodecs"
-   but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--.
-
-A example for such an output is:
-
-<S>lave or attached <M>aster name  type flags    magic    (connected as)
-S                          zr36050 0002 0000d001 00000000 (TEMPLATE)
-M                       zr36055[0] 0001 0000c001 00000000 (zr36050[0])
-M                       zr36055[1] 0001 0000c001 00000000 (zr36050[1])
-
-*/
-\f
-
-/* =============================================== */
-/* special defines for the videocodec_io structure */
-/* =============================================== */
-
-#ifndef __LINUX_VIDEOCODEC_H
-#define __LINUX_VIDEOCODEC_H
-
-#include <linux/videodev.h>
-
-//should be in videodev.h ??? (VID_DO_....)
-#define CODEC_DO_COMPRESSION 0
-#define CODEC_DO_EXPANSION   1
-
-/* this are the current codec flags I think they are needed */
-/*  -> type value in structure */
-#define CODEC_FLAG_JPEG      0x00000001L       // JPEG codec
-#define CODEC_FLAG_MPEG      0x00000002L       // MPEG1/2/4 codec
-#define CODEC_FLAG_DIVX      0x00000004L       // DIVX codec
-#define CODEC_FLAG_WAVELET   0x00000008L       // WAVELET codec
-                                         // room for other types
-
-#define CODEC_FLAG_MAGIC     0x00000800L       // magic key must match
-#define CODEC_FLAG_HARDWARE  0x00001000L       // is a hardware codec
-#define CODEC_FLAG_VFE       0x00002000L       // has direct video frontend
-#define CODEC_FLAG_ENCODER   0x00004000L       // compression capability
-#define CODEC_FLAG_DECODER   0x00008000L       // decompression capability
-#define CODEC_FLAG_NEEDIRQ   0x00010000L       // needs irq handling
-#define CODEC_FLAG_RDWRPIC   0x00020000L       // handles picture I/O
-
-/* a list of modes, some are just examples (is there any HW?) */
-#define CODEC_MODE_BJPG      0x0001    // Baseline JPEG
-#define CODEC_MODE_LJPG      0x0002    // Lossless JPEG
-#define CODEC_MODE_MPEG1     0x0003    // MPEG 1
-#define CODEC_MODE_MPEG2     0x0004    // MPEG 2
-#define CODEC_MODE_MPEG4     0x0005    // MPEG 4
-#define CODEC_MODE_MSDIVX    0x0006    // MS DivX
-#define CODEC_MODE_ODIVX     0x0007    // Open DivX
-#define CODEC_MODE_WAVELET   0x0008    // Wavelet
-
-/* this are the current codec types I want to implement */
-/*  -> type value in structure */
-#define CODEC_TYPE_NONE    0
-#define CODEC_TYPE_L64702  1
-#define CODEC_TYPE_ZR36050 2
-#define CODEC_TYPE_ZR36016 3
-#define CODEC_TYPE_ZR36060 4
-
-/* the type of data may be enhanced by future implementations (data-fn.'s) */
-/*  -> used in command                                                     */
-#define CODEC_G_STATUS         0x0000  /* codec status (query only) */
-#define CODEC_S_CODEC_MODE     0x0001  /* codec mode (baseline JPEG, MPEG1,... */
-#define CODEC_G_CODEC_MODE     0x8001
-#define CODEC_S_VFE            0x0002  /* additional video frontend setup */
-#define CODEC_G_VFE            0x8002
-#define CODEC_S_MMAP           0x0003  /* MMAP setup (if available) */
-
-#define CODEC_S_JPEG_TDS_BYTE  0x0010  /* target data size in bytes */
-#define CODEC_G_JPEG_TDS_BYTE  0x8010
-#define CODEC_S_JPEG_SCALE     0x0011  /* scaling factor for quant. tables */
-#define CODEC_G_JPEG_SCALE     0x8011
-#define CODEC_S_JPEG_HDT_DATA  0x0018  /* huffman-tables */
-#define CODEC_G_JPEG_HDT_DATA  0x8018
-#define CODEC_S_JPEG_QDT_DATA  0x0019  /* quantizing-tables */
-#define CODEC_G_JPEG_QDT_DATA  0x8019
-#define CODEC_S_JPEG_APP_DATA  0x001A  /* APP marker */
-#define CODEC_G_JPEG_APP_DATA  0x801A
-#define CODEC_S_JPEG_COM_DATA  0x001B  /* COM marker */
-#define CODEC_G_JPEG_COM_DATA  0x801B
-
-#define CODEC_S_PRIVATE        0x1000  /* "private" commands start here */
-#define CODEC_G_PRIVATE        0x9000
-
-#define CODEC_G_FLAG           0x8000  /* this is how 'get' is detected */
-
-/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */
-/*  -> used in get_image, put_image                                        */
-#define CODEC_TRANSFER_KERNEL 0        /* use "memcopy" */
-#define CODEC_TRANSFER_USER   1        /* use "to/from_user" */
-\f
-
-/* ========================= */
-/* the structures itself ... */
-/* ========================= */
-
-struct vfe_polarity {
-       unsigned int vsync_pol:1;
-       unsigned int hsync_pol:1;
-       unsigned int field_pol:1;
-       unsigned int blank_pol:1;
-       unsigned int subimg_pol:1;
-       unsigned int poe_pol:1;
-       unsigned int pvalid_pol:1;
-       unsigned int vclk_pol:1;
-};
-
-struct vfe_settings {
-       __u32 x, y;             /* Offsets into image */
-       __u32 width, height;    /* Area to capture */
-       __u16 decimation;       /* Decimation divider */
-       __u16 flags;            /* Flags for capture */
-/* flags are the same as in struct video_capture - see videodev.h:
-#define VIDEO_CAPTURE_ODD              0
-#define VIDEO_CAPTURE_EVEN             1
-*/
-       __u16 quality;          /* quality of the video */
-};
-
-struct tvnorm {
-       u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
-};
-
-struct jpeg_com_marker {
-       int len; /* number of usable bytes in data */
-       char data[60];
-};
-
-struct jpeg_app_marker {
-       int appn; /* number app segment */
-       int len; /* number of usable bytes in data */
-       char data[60];
-};
-
-struct videocodec {
-       struct module *owner;
-       /* -- filled in by slave device during register -- */
-       char name[32];
-       unsigned long magic;    /* may be used for client<->master attaching */
-       unsigned long flags;    /* functionality flags */
-       unsigned int type;      /* codec type */
-
-       /* -- these is filled in later during master device attach -- */
-
-       struct videocodec_master *master_data;
-
-       /* -- these are filled in by the slave device during register -- */
-
-       void *data;             /* private slave data */
-
-       /* attach/detach client functions (indirect call) */
-       int (*setup) (struct videocodec * codec);
-       int (*unset) (struct videocodec * codec);
-
-       /* main functions, every client needs them for sure! */
-       // set compression or decompression (or freeze, stop, standby, etc)
-       int (*set_mode) (struct videocodec * codec,
-                        int mode);
-       // setup picture size and norm (for the codec's video frontend)
-       int (*set_video) (struct videocodec * codec,
-                         struct tvnorm * norm,
-                         struct vfe_settings * cap,
-                         struct vfe_polarity * pol);
-       // other control commands, also mmap setup etc.
-       int (*control) (struct videocodec * codec,
-                       int type,
-                       int size,
-                       void *data);
-
-       /* additional setup/query/processing (may be NULL pointer) */
-       // interrupt setup / handling (for irq's delivered by master)
-       int (*setup_interrupt) (struct videocodec * codec,
-                               long mode);
-       int (*handle_interrupt) (struct videocodec * codec,
-                                int source,
-                                long flag);
-       // picture interface (if any)
-       long (*put_image) (struct videocodec * codec,
-                          int tr_type,
-                          int block,
-                          long *fr_num,
-                          long *flag,
-                          long size,
-                          void *buf);
-       long (*get_image) (struct videocodec * codec,
-                          int tr_type,
-                          int block,
-                          long *fr_num,
-                          long *flag,
-                          long size,
-                          void *buf);
-};
-
-struct videocodec_master {
-       /* -- filled in by master device for registration -- */
-       char name[32];
-       unsigned long magic;    /* may be used for client<->master attaching */
-       unsigned long flags;    /* functionality flags */
-       unsigned int type;      /* master type */
-
-       void *data;             /* private master data */
-
-        __u32(*readreg) (struct videocodec * codec,
-                         __u16 reg);
-       void (*writereg) (struct videocodec * codec,
-                         __u16 reg,
-                         __u32 value);
-};
-\f
-
-/* ================================================= */
-/* function prototypes of the master/slave interface */
-/* ================================================= */
-
-/* attach and detach commands for the master */
-// * master structure needs to be kmalloc'ed before calling attach
-//   and free'd after calling detach
-// * returns pointer on success, NULL on failure
-extern struct videocodec *videocodec_attach(struct videocodec_master *);
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_detach(struct videocodec *);
-
-/* register and unregister commands for the slaves */
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_register(const struct videocodec *);
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_unregister(const struct videocodec *);
-
-/* the other calls are directly done via the videocodec structure! */
-
-#endif                         /*ifndef __LINUX_VIDEOCODEC_H */
index 1edda456fc646c9accaba0b037c46ed44a6a97e2..1efc5f3462c6ce8fa6e8edc45c45c7aceb445499 100644 (file)
 #include <linux/mm.h>
 #include <linux/time.h>
 #include <linux/version.h>
-
-#ifdef CONFIG_KMOD
 #include <linux/kmod.h>
-#endif
 
 #include <linux/i2c.h>
 #include <linux/i2c-algo-sgi.h>
 
 #include <linux/videodev2.h>
-#include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <linux/video_decoder.h>
@@ -810,7 +806,7 @@ static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
        dprintk("vino_free_buffer_with_count(): count = %d\n", count);
 
        for (i = 0; i < count; i++) {
-               ClearPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+               ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
                dma_unmap_single(NULL,
                                 fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
                                 PAGE_SIZE, DMA_FROM_DEVICE);
@@ -888,7 +884,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb,
                                dma_data_addr + VINO_PAGE_SIZE * j;
                }
 
-               SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+               SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
        }
 
        /* page_count needs to be set anyway, because the descriptor table has
@@ -975,7 +971,7 @@ static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
                                dma_data_addr + VINO_PAGE_SIZE * j;
                }
 
-               SetPageReserved(virt_to_page(fb->desc_table.virtual[i]));
+               SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
        }
 
        /* page_count needs to be set anyway, because the descriptor table has
@@ -4025,8 +4021,7 @@ out:
 
 static int vino_open(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
        int ret = 0;
        dprintk("open(): channel = %c\n",
               (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
@@ -4057,8 +4052,7 @@ static int vino_open(struct inode *inode, struct file *file)
 
 static int vino_close(struct inode *inode, struct file *file)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
        dprintk("close():\n");
 
        mutex_lock(&vcs->mutex);
@@ -4101,8 +4095,7 @@ static struct vm_operations_struct vino_vm_ops = {
 
 static int vino_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
 
        unsigned long start = vma->vm_start;
        unsigned long size = vma->vm_end - vma->vm_start;
@@ -4207,8 +4200,7 @@ out:
 
 static unsigned int vino_poll(struct file *file, poll_table *pt)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
        unsigned int outgoing;
        unsigned int ret = 0;
 
@@ -4248,8 +4240,7 @@ error:
 static int vino_do_ioctl(struct inode *inode, struct file *file,
                      unsigned int cmd, void *arg)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
 
 #ifdef VINO_DEBUG
        switch (_IOC_TYPE(cmd)) {
@@ -4356,8 +4347,7 @@ static int vino_do_ioctl(struct inode *inode, struct file *file,
 static int vino_ioctl(struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg)
 {
-       struct video_device *dev = video_devdata(file);
-       struct vino_channel_settings *vcs = video_get_drvdata(dev);
+       struct vino_channel_settings *vcs = video_drvdata(file);
        int ret;
 
        if (mutex_lock_interruptible(&vcs->mutex))
@@ -4641,7 +4631,7 @@ static int __init vino_module_init(void)
        }
        vino_init_stage++;
 
-#if defined(CONFIG_KMOD) && defined(MODULE)
+#ifdef MODULE
        request_module("saa7191");
        request_module("indycam");
 #endif
index 8ba8daafd7ea2a3a2dff574b535a2908128b8d8b..65c8af18e767a7e889ac239517b23823e71c9993 100644 (file)
@@ -898,9 +898,11 @@ static int vivi_open(struct inode *inode, struct file *file)
 
        printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
 
+       lock_kernel();
        list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
                if (dev->vfd->minor == minor)
                        goto found;
+       unlock_kernel();
        return -ENODEV;
 
 found:
@@ -925,8 +927,10 @@ found:
        }
 unlock:
        mutex_unlock(&dev->mutex);
-       if (retval)
+       if (retval) {
+               unlock_kernel();
                return retval;
+       }
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -955,6 +959,7 @@ unlock:
                        sizeof(struct vivi_buffer), fh);
 
        vivi_start_thread(fh);
+       unlock_kernel();
 
        return 0;
 }
index 35293029da02423e1c31cb1aedb136f78c6b090f..45be9ec8edc4a10cba99ad26f5b7b446852506b2 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 
-#include <linux/byteorder/swab.h>
-
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
index 2ff00bc5ad64cf2aa79a2c915296ea03220a4572..b2dbe48a92bbd72360b1fec3dea0e59806dc671f 100644 (file)
@@ -113,6 +113,7 @@ struct w9966_dev {
        signed char contrast;
        signed char color;
        signed char hue;
+       unsigned long in_use;
 };
 
 /*
@@ -184,10 +185,25 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
                              size_t count, loff_t *ppos);
 
+static int w9966_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct w9966_dev *cam = video_drvdata(file);
+
+       return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
+}
+
+static int w9966_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct w9966_dev *cam = video_drvdata(file);
+
+       clear_bit(0, &cam->in_use);
+       return 0;
+}
+
 static const struct file_operations w9966_fops = {
        .owner          = THIS_MODULE,
-       .open           = video_exclusive_open,
-       .release        = video_exclusive_release,
+       .open           = w9966_exclusive_open,
+       .release        = w9966_exclusive_release,
        .ioctl          = w9966_v4l_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = v4l_compat_ioctl32,
@@ -198,6 +214,7 @@ static const struct file_operations w9966_fops = {
 static struct video_device w9966_template = {
        .name           = W9966_DRIVERNAME,
        .fops           = &w9966_fops,
+       .release        = video_device_release_empty,
 };
 
 /*
@@ -332,7 +349,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port)
 
 // Fill in the video_device struct and register us to v4l
        memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device));
-       cam->vdev.priv = cam;
+       video_set_drvdata(&cam->vdev, cam);
 
        if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
                return -1;
@@ -713,8 +730,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
 static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
                              unsigned int cmd, void *arg)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct w9966_dev *cam = vdev->priv;
+       struct w9966_dev *cam = video_drvdata(file);
 
        switch(cmd)
        {
@@ -872,8 +888,7 @@ static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
 static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
                              size_t count, loff_t *ppos)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct w9966_dev *cam = vdev->priv;
+       struct w9966_dev *cam = video_drvdata(file);
        unsigned char addr = 0xa0;      // ECP, read, CCD-transfer, 00000
        unsigned char __user *dest = (unsigned char __user *)buf;
        unsigned long dleft = count;
index 11edf79f57be328a0f6a196f7d849776c3235a39..dcd45dbd82dcfa0424b900f78a495d85f5a3ec9e 100644 (file)
@@ -111,7 +111,7 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG;
 
 static unsigned int param_nv[24]; /* number of values per parameter */
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 module_param(ovmod_load, bool, 0644);
 #endif
 module_param(simcams, ushort, 0644);
@@ -144,7 +144,7 @@ module_param(debug, ushort, 0644);
 module_param(specific_debug, bool, 0644);
 #endif
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 MODULE_PARM_DESC(ovmod_load,
                 "\n<0|1> Automatic 'ovcamchip' module loading."
                 "\n0 disabled, 1 enabled."
index 0c3287734c93f0b77900cb2c9ca6156ee2de592d..6a0902bcba6bee88a250b0511cee48269d9c57bf 100644 (file)
@@ -657,7 +657,7 @@ static int zc0301_open(struct inode* inode, struct file* filp)
        if (!down_read_trylock(&zc0301_dev_lock))
                return -EAGAIN;
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        if (wait_for_completion_interruptible(&cam->probe)) {
                up_read(&zc0301_dev_lock);
@@ -739,7 +739,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
 
        down_write(&zc0301_dev_lock);
 
-       cam = video_get_drvdata(video_devdata(filp));
+       cam = video_drvdata(filp);
 
        zc0301_stop_transfer(cam);
        zc0301_release_buffers(cam);
@@ -759,7 +759,7 @@ static int zc0301_release(struct inode* inode, struct file* filp)
 static ssize_t
 zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
 {
-       struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+       struct zc0301_device *cam = video_drvdata(filp);
        struct zc0301_frame_t* f, * i;
        unsigned long lock_flags;
        long timeout;
@@ -866,7 +866,7 @@ exit:
 
 static unsigned int zc0301_poll(struct file *filp, poll_table *wait)
 {
-       struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+       struct zc0301_device *cam = video_drvdata(filp);
        struct zc0301_frame_t* f;
        unsigned long lock_flags;
        unsigned int mask = 0;
@@ -941,7 +941,7 @@ static struct vm_operations_struct zc0301_vm_ops = {
 
 static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma)
 {
-       struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+       struct zc0301_device *cam = video_drvdata(filp);
        unsigned long size = vma->vm_end - vma->vm_start,
                      start = vma->vm_start;
        void *pos;
@@ -1796,7 +1796,7 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg)
 static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
                             unsigned int cmd, void __user * arg)
 {
-       struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+       struct zc0301_device *cam = video_drvdata(filp);
 
        switch (cmd) {
 
@@ -1891,7 +1891,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
 static int zc0301_ioctl(struct inode* inode, struct file* filp,
                        unsigned int cmd, unsigned long arg)
 {
-       struct zc0301_device* cam = video_get_drvdata(video_devdata(filp));
+       struct zc0301_device *cam = video_drvdata(filp);
        int err = 0;
 
        if (mutex_lock_interruptible(&cam->fileop_mutex))
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
deleted file mode 100644 (file)
index 46b7ad4..0000000
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * zoran - Iomega Buz driver
- *
- * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
- *
- * based on
- *
- * zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * and
- *
- * bttv - Bt848 frame grabber driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
- *                        & Marcus Metzler (mocm@thp.uni-koeln.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _BUZ_H_
-#define _BUZ_H_
-
-struct zoran_requestbuffers {
-       unsigned long count;    /* Number of buffers for MJPEG grabbing */
-       unsigned long size;     /* Size PER BUFFER in bytes */
-};
-
-struct zoran_sync {
-       unsigned long frame;    /* number of buffer that has been free'd */
-       unsigned long length;   /* number of code bytes in buffer (capture only) */
-       unsigned long seq;      /* frame sequence number */
-       struct timeval timestamp;       /* timestamp */
-};
-
-struct zoran_status {
-       int input;              /* Input channel, has to be set prior to BUZIOC_G_STATUS */
-       int signal;             /* Returned: 1 if valid video signal detected */
-       int norm;               /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
-       int color;              /* Returned: 1 if color signal detected */
-};
-
-struct zoran_params {
-
-       /* The following parameters can only be queried */
-
-       int major_version;      /* Major version number of driver */
-       int minor_version;      /* Minor version number of driver */
-
-       /* Main control parameters */
-
-       int input;              /* Input channel: 0 = Composite, 1 = S-VHS */
-       int norm;               /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
-       int decimation;         /* decimation of captured video,
-                                * enlargement of video played back.
-                                * Valid values are 1, 2, 4 or 0.
-                                * 0 is a special value where the user
-                                * has full control over video scaling */
-
-       /* The following parameters only have to be set if decimation==0,
-        * for other values of decimation they provide the data how the image is captured */
-
-       int HorDcm;             /* Horizontal decimation: 1, 2 or 4 */
-       int VerDcm;             /* Vertical decimation: 1 or 2 */
-       int TmpDcm;             /* Temporal decimation: 1 or 2,
-                                * if TmpDcm==2 in capture every second frame is dropped,
-                                * in playback every frame is played twice */
-       int field_per_buff;     /* Number of fields per buffer: 1 or 2 */
-       int img_x;              /* start of image in x direction */
-       int img_y;              /* start of image in y direction */
-       int img_width;          /* image width BEFORE decimation,
-                                * must be a multiple of HorDcm*16 */
-       int img_height;         /* image height BEFORE decimation,
-                                * must be a multiple of VerDcm*8 */
-
-       /* --- End of parameters for decimation==0 only --- */
-
-       /* JPEG control parameters */
-
-       int quality;            /* Measure for quality of compressed images.
-                                * Scales linearly with the size of the compressed images.
-                                * Must be beetween 0 and 100, 100 is a compression
-                                * ratio of 1:4 */
-
-       int odd_even;           /* Which field should come first ??? */
-
-       int APPn;               /* Number of APP segment to be written, must be 0..15 */
-       int APP_len;            /* Length of data in JPEG APPn segment */
-       char APP_data[60];      /* Data in the JPEG APPn segment. */
-
-       int COM_len;            /* Length of data in JPEG COM segment */
-       char COM_data[60];      /* Data in JPEG COM segment */
-
-       unsigned long jpeg_markers;     /* Which markers should go into the JPEG output.
-                                        * Unless you exactly know what you do, leave them untouched.
-                                        * Inluding less markers will make the resulting code
-                                        * smaller, but there will be fewer aplications
-                                        * which can read it.
-                                        * The presence of the APP and COM marker is
-                                        * influenced by APP0_len and COM_len ONLY! */
-#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
-#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
-#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
-#define JPEG_MARKER_COM (1<<6) /* Comment segment */
-#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */
-
-       int VFIFO_FB;           /* Flag for enabling Video Fifo Feedback.
-                                * If this flag is turned on and JPEG decompressing
-                                * is going to the screen, the decompress process
-                                * is stopped every time the Video Fifo is full.
-                                * This enables a smooth decompress to the screen
-                                * but the video output signal will get scrambled */
-
-       /* Misc */
-
-       char reserved[312];     /* Makes 512 bytes for this structure */
-};
-
-/*
-Private IOCTL to set up for displaying MJPEG
-*/
-#define BUZIOC_G_PARAMS       _IOR ('v', BASE_VIDIOCPRIVATE+0,  struct zoran_params)
-#define BUZIOC_S_PARAMS       _IOWR('v', BASE_VIDIOCPRIVATE+1,  struct zoran_params)
-#define BUZIOC_REQBUFS        _IOWR('v', BASE_VIDIOCPRIVATE+2,  struct zoran_requestbuffers)
-#define BUZIOC_QBUF_CAPT      _IOW ('v', BASE_VIDIOCPRIVATE+3,  int)
-#define BUZIOC_QBUF_PLAY      _IOW ('v', BASE_VIDIOCPRIVATE+4,  int)
-#define BUZIOC_SYNC           _IOR ('v', BASE_VIDIOCPRIVATE+5,  struct zoran_sync)
-#define BUZIOC_G_STATUS       _IOWR('v', BASE_VIDIOCPRIVATE+6,  struct zoran_status)
-
-
-#ifdef __KERNEL__
-
-#define MAJOR_VERSION 0                /* driver major version */
-#define MINOR_VERSION 9                /* driver minor version */
-#define RELEASE_VERSION 5      /* release version */
-
-#define ZORAN_NAME    "ZORAN"  /* name of the device */
-
-#define ZR_DEVNAME(zr) ((zr)->name)
-
-#define   BUZ_MAX_WIDTH   (zr->timing->Wa)
-#define   BUZ_MAX_HEIGHT  (zr->timing->Ha)
-#define   BUZ_MIN_WIDTH    32  /* never display less than 32 pixels */
-#define   BUZ_MIN_HEIGHT   24  /* never display less than 24 rows */
-
-#define BUZ_NUM_STAT_COM    4
-#define BUZ_MASK_STAT_COM   3
-
-#define BUZ_MAX_FRAME     256  /* Must be a power of 2 */
-#define BUZ_MASK_FRAME    255  /* Must be BUZ_MAX_FRAME-1 */
-
-#define BUZ_MAX_INPUT       16
-
-#if VIDEO_MAX_FRAME <= 32
-#   define   V4L_MAX_FRAME   32
-#elif VIDEO_MAX_FRAME <= 64
-#   define   V4L_MAX_FRAME   64
-#else
-#   error   "Too many video frame buffers to handle"
-#endif
-#define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
-
-#define MAX_KMALLOC_MEM (128*1024)
-
-#include "zr36057.h"
-
-enum card_type {
-       UNKNOWN = -1,
-
-       /* Pinnacle/Miro */
-       DC10_old,               /* DC30 like */
-       DC10_new,               /* DC10plus like */
-       DC10plus,
-       DC30,
-       DC30plus,
-
-       /* Linux Media Labs */
-       LML33,
-       LML33R10,
-
-       /* Iomega */
-       BUZ,
-
-       /* AverMedia */
-       AVS6EYES,
-
-       /* total number of cards */
-       NUM_CARDS
-};
-
-enum zoran_codec_mode {
-       BUZ_MODE_IDLE,          /* nothing going on */
-       BUZ_MODE_MOTION_COMPRESS,       /* grabbing frames */
-       BUZ_MODE_MOTION_DECOMPRESS,     /* playing frames */
-       BUZ_MODE_STILL_COMPRESS,        /* still frame conversion */
-       BUZ_MODE_STILL_DECOMPRESS       /* still frame conversion */
-};
-
-enum zoran_buffer_state {
-       BUZ_STATE_USER,         /* buffer is owned by application */
-       BUZ_STATE_PEND,         /* buffer is queued in pend[] ready to feed to I/O */
-       BUZ_STATE_DMA,          /* buffer is queued in dma[] for I/O */
-       BUZ_STATE_DONE          /* buffer is ready to return to application */
-};
-
-enum zoran_map_mode {
-       ZORAN_MAP_MODE_RAW,
-       ZORAN_MAP_MODE_JPG_REC,
-#define ZORAN_MAP_MODE_JPG ZORAN_MAP_MODE_JPG_REC
-       ZORAN_MAP_MODE_JPG_PLAY,
-};
-
-enum gpio_type {
-       ZR_GPIO_JPEG_SLEEP = 0,
-       ZR_GPIO_JPEG_RESET,
-       ZR_GPIO_JPEG_FRAME,
-       ZR_GPIO_VID_DIR,
-       ZR_GPIO_VID_EN,
-       ZR_GPIO_VID_RESET,
-       ZR_GPIO_CLK_SEL1,
-       ZR_GPIO_CLK_SEL2,
-       ZR_GPIO_MAX,
-};
-
-enum gpcs_type {
-       GPCS_JPEG_RESET = 0,
-       GPCS_JPEG_START,
-       GPCS_MAX,
-};
-
-struct zoran_format {
-       char *name;
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-       int palette;
-#endif
-       __u32 fourcc;
-       int colorspace;
-       int depth;
-       __u32 flags;
-       __u32 vfespfr;
-};
-/* flags */
-#define ZORAN_FORMAT_COMPRESSED 1<<0
-#define ZORAN_FORMAT_OVERLAY    1<<1
-#define ZORAN_FORMAT_CAPTURE   1<<2
-#define ZORAN_FORMAT_PLAYBACK  1<<3
-
-/* overlay-settings */
-struct zoran_overlay_settings {
-       int is_set;
-       int x, y, width, height;        /* position */
-       int clipcount;          /* position and number of clips */
-       const struct zoran_format *format;      /* overlay format */
-};
-
-/* v4l-capture settings */
-struct zoran_v4l_settings {
-       int width, height, bytesperline;        /* capture size */
-       const struct zoran_format *format;      /* capture format */
-};
-
-/* jpg-capture/-playback settings */
-struct zoran_jpg_settings {
-       int decimation;         /* this bit is used to set everything to default */
-       int HorDcm, VerDcm, TmpDcm;     /* capture decimation settings (TmpDcm=1 means both fields) */
-       int field_per_buff, odd_even;   /* field-settings (odd_even=1 (+TmpDcm=1) means top-field-first) */
-       int img_x, img_y, img_width, img_height;        /* crop settings (subframe capture) */
-       struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
-};
-
-struct zoran_mapping {
-       struct file *file;
-       int count;
-};
-
-struct zoran_jpg_buffer {
-       struct zoran_mapping *map;
-       __le32 *frag_tab;               /* addresses of frag table */
-       u32 frag_tab_bus;       /* same value cached to save time in ISR */
-       enum zoran_buffer_state state;  /* non-zero if corresponding buffer is in use in grab queue */
-       struct zoran_sync bs;   /* DONE: info to return to application */
-};
-
-struct zoran_v4l_buffer {
-       struct zoran_mapping *map;
-       char *fbuffer;          /* virtual  address of frame buffer */
-       unsigned long fbuffer_phys;     /* physical address of frame buffer */
-       unsigned long fbuffer_bus;      /* bus      address of frame buffer */
-       enum zoran_buffer_state state;  /* state: unused/pending/done */
-       struct zoran_sync bs;   /* DONE: info to return to application */
-};
-
-enum zoran_lock_activity {
-       ZORAN_FREE,             /* free for use */
-       ZORAN_ACTIVE,           /* active but unlocked */
-       ZORAN_LOCKED,           /* locked */
-};
-
-/* buffer collections */
-struct zoran_jpg_struct {
-       enum zoran_lock_activity active;        /* feature currently in use? */
-       struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME];  /* buffers */
-       int num_buffers, buffer_size;
-       u8 allocated;           /* Flag if buffers are allocated  */
-       u8 ready_to_be_freed;   /* hack - see zoran_driver.c */
-       u8 need_contiguous;     /* Flag if contiguous buffers are needed */
-};
-
-struct zoran_v4l_struct {
-       enum zoran_lock_activity active;        /* feature currently in use? */
-       struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME];        /* buffers */
-       int num_buffers, buffer_size;
-       u8 allocated;           /* Flag if buffers are allocated  */
-       u8 ready_to_be_freed;   /* hack - see zoran_driver.c */
-};
-
-struct zoran;
-
-/* zoran_fh contains per-open() settings */
-struct zoran_fh {
-       struct zoran *zr;
-
-       enum zoran_map_mode map_mode;   /* Flag which bufferset will map by next mmap() */
-
-       struct zoran_overlay_settings overlay_settings;
-       u32 *overlay_mask;      /* overlay mask */
-       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
-
-       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
-       struct zoran_v4l_struct v4l_buffers;    /* V4L buffers' info */
-
-       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
-       struct zoran_jpg_struct jpg_buffers;    /* MJPEG buffers' info */
-};
-
-struct card_info {
-       enum card_type type;
-       char name[32];
-       u16 i2c_decoder, i2c_encoder;                   /* I2C types */
-       u16 video_vfe, video_codec;                     /* videocodec types */
-       u16 audio_chip;                                 /* audio type */
-       u16 vendor_id, device_id;       /* subsystem vendor/device ID */
-
-       int inputs;             /* number of video inputs */
-       struct input {
-               int muxsel;
-               char name[32];
-       } input[BUZ_MAX_INPUT];
-
-       int norms;
-       struct tvnorm *tvn[3];  /* supported TV norms */
-
-       u32 jpeg_int;           /* JPEG interrupt */
-       u32 vsync_int;          /* VSYNC interrupt */
-       s8 gpio[ZR_GPIO_MAX];
-       u8 gpcs[GPCS_MAX];
-
-       struct vfe_polarity vfe_pol;
-       u8 gpio_pol[ZR_GPIO_MAX];
-
-       /* is the /GWS line conected? */
-       u8 gws_not_connected;
-
-       /* avs6eyes mux setting */
-       u8 input_mux;
-
-       void (*init) (struct zoran * zr);
-};
-
-struct zoran {
-       struct video_device *video_dev;
-
-       struct i2c_adapter i2c_adapter; /* */
-       struct i2c_algo_bit_data i2c_algo;      /* */
-       u32 i2cbr;
-
-       struct i2c_client *decoder;     /* video decoder i2c client */
-       struct i2c_client *encoder;     /* video encoder i2c client */
-
-       struct videocodec *codec;       /* video codec */
-       struct videocodec *vfe; /* video front end */
-
-       struct mutex resource_lock;     /* prevent evil stuff */
-
-       u8 initialized;         /* flag if zoran has been correctly initalized */
-       int user;               /* number of current users */
-       struct card_info card;
-       struct tvnorm *timing;
-
-       unsigned short id;      /* number of this device */
-       char name[32];          /* name of this device */
-       struct pci_dev *pci_dev;        /* PCI device */
-       unsigned char revision; /* revision of zr36057 */
-       unsigned int zr36057_adr;       /* bus address of IO mem returned by PCI BIOS */
-       unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
-
-       spinlock_t spinlock;    /* Spinlock */
-
-       /* Video for Linux parameters */
-       int input, norm;        /* card's norm and input - norm=VIDEO_MODE_* */
-       int hue, saturation, contrast, brightness;      /* Current picture params */
-       struct video_buffer buffer;     /* Current buffer params */
-       struct zoran_overlay_settings overlay_settings;
-       u32 *overlay_mask;      /* overlay mask */
-       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
-
-       wait_queue_head_t v4l_capq;
-
-       int v4l_overlay_active; /* Overlay grab is activated */
-       int v4l_memgrab_active; /* Memory grab is activated */
-
-       int v4l_grab_frame;     /* Frame number being currently grabbed */
-#define NO_GRAB_ACTIVE (-1)
-       unsigned long v4l_grab_seq;     /* Number of frames grabbed */
-       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
-
-       /* V4L grab queue of frames pending */
-       unsigned long v4l_pend_head;
-       unsigned long v4l_pend_tail;
-       unsigned long v4l_sync_tail;
-       int v4l_pend[V4L_MAX_FRAME];
-       struct zoran_v4l_struct v4l_buffers;    /* V4L buffers' info */
-
-       /* Buz MJPEG parameters */
-       enum zoran_codec_mode codec_mode;       /* status of codec */
-       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
-
-       wait_queue_head_t jpg_capq;     /* wait here for grab to finish */
-
-       /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
-       /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
-       /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
-       unsigned long jpg_que_head;     /* Index where to put next buffer which is queued */
-       unsigned long jpg_dma_head;     /* Index of next buffer which goes into stat_com  */
-       unsigned long jpg_dma_tail;     /* Index of last buffer in stat_com               */
-       unsigned long jpg_que_tail;     /* Index of last buffer in queue                  */
-       unsigned long jpg_seq_num;      /* count of frames since grab/play started        */
-       unsigned long jpg_err_seq;      /* last seq_num before error                      */
-       unsigned long jpg_err_shift;
-       unsigned long jpg_queued_num;   /* count of frames queued since grab/play started */
-
-       /* zr36057's code buffer table */
-       __le32 *stat_com;               /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
-
-       /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
-       int jpg_pend[BUZ_MAX_FRAME];
-
-       /* array indexed by frame number */
-       struct zoran_jpg_struct jpg_buffers;    /* MJPEG buffers' info */
-
-       /* Additional stuff for testing */
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *zoran_proc;
-#else
-       void *zoran_proc;
-#endif
-       int testing;
-       int jpeg_error;
-       int intr_counter_GIRQ1;
-       int intr_counter_GIRQ0;
-       int intr_counter_CodRepIRQ;
-       int intr_counter_JPEGRepIRQ;
-       int field_counter;
-       int IRQ1_in;
-       int IRQ1_out;
-       int JPEG_in;
-       int JPEG_out;
-       int JPEG_0;
-       int JPEG_1;
-       int END_event_missed;
-       int JPEG_missed;
-       int JPEG_error;
-       int num_errors;
-       int JPEG_max_missed;
-       int JPEG_min_missed;
-
-       u32 last_isr;
-       unsigned long frame_num;
-
-       wait_queue_head_t test_q;
-};
-
-/*The following should be done in more portable way. It depends on define
-  of _ALPHA_BUZ in the Makefile.*/
-
-#ifdef _ALPHA_BUZ
-#define btwrite(dat,adr)    writel((dat), zr->zr36057_adr+(adr))
-#define btread(adr)         readl(zr->zr36057_adr+(adr))
-#else
-#define btwrite(dat,adr)    writel((dat), zr->zr36057_mem+(adr))
-#define btread(adr)         readl(zr->zr36057_mem+(adr))
-#endif
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-#endif                         /* __kernel__ */
-
-#endif
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig
new file mode 100644 (file)
index 0000000..4ea5fa7
--- /dev/null
@@ -0,0 +1,73 @@
+config VIDEO_ZORAN
+       tristate "Zoran ZR36057/36067 Video For Linux"
+       depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
+       help
+         Say Y for support for MJPEG capture cards based on the Zoran
+         36057/36067 PCI controller chipset. This includes the Iomega
+         Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
+         a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
+         more information, check <file:Documentation/video4linux/Zoran>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called zr36067.
+
+config VIDEO_ZORAN_DC30
+       tristate "Pinnacle/Miro DC30(+) support"
+       depends on VIDEO_ZORAN
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+         card. This also supports really old DC10 cards based on the
+         zr36050 MJPEG codec and zr36016 VFE.
+
+config VIDEO_ZORAN_ZR36060
+       tristate "Zoran ZR36060"
+       depends on VIDEO_ZORAN
+       help
+         Say Y to support Zoran boards based on 36060 chips.
+         This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
+         and 33 R10 and AverMedia 6 boards.
+
+config VIDEO_ZORAN_BUZ
+       tristate "Iomega Buz support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Iomega Buz MJPEG capture/playback card.
+
+config VIDEO_ZORAN_DC10
+       tristate "Pinnacle/Miro DC10(+) support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_LML33
+       tristate "Linux Media Labs LML33 support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Linux Media Labs LML33 MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_LML33R10
+       tristate "Linux Media Labs LML33R10 support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         support for the Linux Media Labs LML33R10 MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_AVS6EYES
+       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
+       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile
new file mode 100644 (file)
index 0000000..44cc133
--- /dev/null
@@ -0,0 +1,6 @@
+zr36067-objs   :=      zoran_procfs.o zoran_device.o \
+                       zoran_driver.o zoran_card.o
+
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
+obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/media/video/zoran/videocodec.c b/drivers/media/video/zoran/videocodec.c
new file mode 100644 (file)
index 0000000..cf24956
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#define VIDEOCODEC_VERSION "v0.2"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+// kernel config is here (procfs flag)
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#endif
+
+#include "videocodec.h"
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+struct attached_list {
+       struct videocodec *codec;
+       struct attached_list *next;
+};
+
+struct codec_list {
+       const struct videocodec *codec;
+       int attached;
+       struct attached_list *list;
+       struct codec_list *next;
+};
+
+static struct codec_list *codeclist_top = NULL;
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+struct videocodec *
+videocodec_attach (struct videocodec_master *master)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a, *ptr;
+       struct videocodec *codec;
+       int res;
+
+       if (!master) {
+               dprintk(1, KERN_ERR "videocodec_attach: no data\n");
+               return NULL;
+       }
+
+       dprintk(2,
+               "videocodec_attach: '%s', flags %lx, magic %lx\n",
+               master->name, master->flags, master->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR
+                       "videocodec_attach: no device available\n");
+               return NULL;
+       }
+
+       while (h) {
+               // attach only if the slave has at least the flags
+               // expected by the master
+               if ((master->flags & h->codec->flags) == master->flags) {
+                       dprintk(4, "videocodec_attach: try '%s'\n",
+                               h->codec->name);
+
+                       if (!try_module_get(h->codec->owner))
+                               return NULL;
+
+                       codec =
+                           kmalloc(sizeof(struct videocodec), GFP_KERNEL);
+                       if (!codec) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "videocodec_attach: no mem\n");
+                               goto out_module_put;
+                       }
+                       memcpy(codec, h->codec, sizeof(struct videocodec));
+
+                       snprintf(codec->name, sizeof(codec->name),
+                                "%s[%d]", codec->name, h->attached);
+                       codec->master_data = master;
+                       res = codec->setup(codec);
+                       if (res == 0) {
+                               dprintk(3, "videocodec_attach '%s'\n",
+                                       codec->name);
+                               ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
+                               if (!ptr) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "videocodec_attach: no memory\n");
+                                       goto out_kfree;
+                               }
+                               ptr->codec = codec;
+
+                               a = h->list;
+                               if (!a) {
+                                       h->list = ptr;
+                                       dprintk(4,
+                                               "videocodec: first element\n");
+                               } else {
+                                       while (a->next)
+                                               a = a->next;    // find end
+                                       a->next = ptr;
+                                       dprintk(4,
+                                               "videocodec: in after '%s'\n",
+                                               h->codec->name);
+                               }
+
+                               h->attached += 1;
+                               return codec;
+                       } else {
+                               kfree(codec);
+                       }
+               }
+               h = h->next;
+       }
+
+       dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
+       return NULL;
+
+ out_module_put:
+       module_put(h->codec->owner);
+ out_kfree:
+       kfree(codec);
+       return NULL;
+}
+
+int
+videocodec_detach (struct videocodec *codec)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a, *prev;
+       int res;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_detach: no data\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR "videocodec_detach: no device left...\n");
+               return -ENXIO;
+       }
+
+       while (h) {
+               a = h->list;
+               prev = NULL;
+               while (a) {
+                       if (codec == a->codec) {
+                               res = a->codec->unset(a->codec);
+                               if (res >= 0) {
+                                       dprintk(3,
+                                               "videocodec_detach: '%s'\n",
+                                               a->codec->name);
+                                       a->codec->master_data = NULL;
+                               } else {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "videocodec_detach: '%s'\n",
+                                               a->codec->name);
+                                       a->codec->master_data = NULL;
+                               }
+                               if (prev == NULL) {
+                                       h->list = a->next;
+                                       dprintk(4,
+                                               "videocodec: delete first\n");
+                               } else {
+                                       prev->next = a->next;
+                                       dprintk(4,
+                                               "videocodec: delete middle\n");
+                               }
+                               module_put(a->codec->owner);
+                               kfree(a->codec);
+                               kfree(a);
+                               h->attached -= 1;
+                               return 0;
+                       }
+                       prev = a;
+                       a = a->next;
+               }
+               h = h->next;
+       }
+
+       dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n");
+       return -EINVAL;
+}
+
+int
+videocodec_register (const struct videocodec *codec)
+{
+       struct codec_list *ptr, *h = codeclist_top;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_register: no data!\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
+       if (!ptr) {
+               dprintk(1, KERN_ERR "videocodec_register: no memory\n");
+               return -ENOMEM;
+       }
+       ptr->codec = codec;
+
+       if (!h) {
+               codeclist_top = ptr;
+               dprintk(4, "videocodec: hooked in as first element\n");
+       } else {
+               while (h->next)
+                       h = h->next;    // find the end
+               h->next = ptr;
+               dprintk(4, "videocodec: hooked in after '%s'\n",
+                       h->codec->name);
+       }
+
+       return 0;
+}
+
+int
+videocodec_unregister (const struct videocodec *codec)
+{
+       struct codec_list *prev = NULL, *h = codeclist_top;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_unregister: no data!\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR
+                       "videocodec_unregister: no device left...\n");
+               return -ENXIO;
+       }
+
+       while (h) {
+               if (codec == h->codec) {
+                       if (h->attached) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "videocodec: '%s' is used\n",
+                                       h->codec->name);
+                               return -EBUSY;
+                       }
+                       dprintk(3, "videocodec: unregister '%s' is ok.\n",
+                               h->codec->name);
+                       if (prev == NULL) {
+                               codeclist_top = h->next;
+                               dprintk(4,
+                                       "videocodec: delete first element\n");
+                       } else {
+                               prev->next = h->next;
+                               dprintk(4,
+                                       "videocodec: delete middle element\n");
+                       }
+                       kfree(h);
+                       return 0;
+               }
+               prev = h;
+               h = h->next;
+       }
+
+       dprintk(1,
+               KERN_ERR
+               "videocodec_unregister: given codec not found!\n");
+       return -EINVAL;
+}
+
+#ifdef CONFIG_PROC_FS
+static int proc_videocodecs_show(struct seq_file *m, void *v)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a;
+
+       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
+       seq_printf(m, "(connected as)\n");
+
+       h = codeclist_top;
+       while (h) {
+               seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
+                             h->codec->name, h->codec->type,
+                             h->codec->flags, h->codec->magic);
+               a = h->list;
+               while (a) {
+                       seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
+                                     a->codec->master_data->name,
+                                     a->codec->master_data->type,
+                                     a->codec->master_data->flags,
+                                     a->codec->master_data->magic,
+                                     a->codec->name);
+                       a = a->next;
+               }
+               h = h->next;
+       }
+
+       return 0;
+}
+
+static int proc_videocodecs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_videocodecs_show, NULL);
+}
+
+static const struct file_operations videocodecs_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_videocodecs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
+/* ===================== */
+/* hook in driver module */
+/* ===================== */
+static int __init
+videocodec_init (void)
+{
+#ifdef CONFIG_PROC_FS
+       static struct proc_dir_entry *videocodec_proc_entry;
+#endif
+
+       printk(KERN_INFO "Linux video codec intermediate layer: %s\n",
+              VIDEOCODEC_VERSION);
+
+#ifdef CONFIG_PROC_FS
+       videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
+       if (!videocodec_proc_entry) {
+               dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
+       }
+#endif
+       return 0;
+}
+
+static void __exit
+videocodec_exit (void)
+{
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("videocodecs", NULL);
+#endif
+}
+
+EXPORT_SYMBOL(videocodec_attach);
+EXPORT_SYMBOL(videocodec_detach);
+EXPORT_SYMBOL(videocodec_register);
+EXPORT_SYMBOL(videocodec_unregister);
+
+module_init(videocodec_init);
+module_exit(videocodec_exit);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Intermediate API module for video codecs "
+                  VIDEOCODEC_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h
new file mode 100644 (file)
index 0000000..97a3bbe
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: videocodec.h,v 1.1.2.4 2003/01/14 21:15:03 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+/* =================== */
+/* general description */
+/* =================== */
+
+/* Should ease the (re-)usage of drivers supporting cards with (different)
+   video codecs. The codecs register to this module their functionality,
+   and the processors (masters) can attach to them if they fit.
+
+   The codecs are typically have a "strong" binding to their master - so I
+   don't think it makes sense to have a full blown interfacing as with e.g.
+   i2c. If you have an other opinion, let's discuss & implement it :-)))
+
+   Usage:
+
+   The slave has just to setup the videocodec structure and use two functions:
+   videocodec_register(codecdata);
+   videocodec_unregister(codecdata);
+   The best is just calling them at module (de-)initialisation.
+
+   The master sets up the structure videocodec_master and calls:
+   codecdata=videocodec_attach(master_codecdata);
+   videocodec_detach(codecdata);
+
+   The slave is called during attach/detach via functions setup previously
+   during register. At that time, the master_data pointer is set up
+   and the slave can access any io registers of the master device (in the case
+   the slave is bound to it). Otherwise it doesn't need this functions and
+   therfor they may not be initialized.
+
+   The other fuctions are just for convenience, as they are for sure used by
+   most/all of the codecs. The last ones may be ommited, too.
+
+   See the structure declaration below for more information and which data has
+   to be set up for the master and the slave.
+
+   ----------------------------------------------------------------------------
+   The master should have "knowledge" of the slave and vice versa.  So the data
+   structures sent to/from slave via set_data/get_data set_image/get_image are
+   device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!)
+   ----------------------------------------------------------------------------
+*/
+\f
+
+/* ========================================== */
+/* description of the videocodec_io structure */
+/* ========================================== */
+
+/*
+   ==== master setup ====
+   name -> name of the device structure for reference and debugging
+   master_data ->  data ref. for the master (e.g. the zr36055,57,67)
+   readreg -> ref. to read-fn from register (setup by master, used by slave)
+   writereg -> ref. to write-fn to register (setup by master, used by slave)
+              this two functions do the lowlevel I/O job
+
+   ==== slave functionality setup ====
+   slave_data -> data ref. for the slave (e.g. the zr36050,60)
+   check -> fn-ref. checks availability of an device, returns -EIO on failure or
+           the type on success
+           this makes espcecially sense if a driver module supports more than
+           one codec which may be quite similar to access, nevertheless it
+           is good for a first functionality check
+
+   -- main functions you always need for compression/decompression --
+
+   set_mode -> this fn-ref. resets the entire codec, and sets up the mode
+              with the last defined norm/size (or device default if not
+              available) - it returns 0 if the mode is possible
+   set_size -> this fn-ref. sets the norm and image size for
+              compression/decompression (returns 0 on success)
+              the norm param is defined in videodev.h (VIDEO_MODE_*)
+
+   additional setup may be available, too - but the codec should work with
+   some default values even without this
+
+   set_data -> sets device-specific data (tables, quality etc.)
+   get_data -> query device-specific data (tables, quality etc.)
+
+   if the device delivers interrupts, they may be setup/handled here
+   setup_interrupt -> codec irq setup (not needed for 36050/60)
+   handle_interrupt -> codec irq handling (not needed for 36050/60)
+
+   if the device delivers pictures, they may be handled here
+   put_image -> puts image data to the codec (not needed for 36050/60)
+   get_image -> gets image data from the codec (not needed for 36050/60)
+               the calls include frame numbers and flags (even/odd/...)
+               if needed and a flag which allows blocking until its ready
+*/
+\f
+/* ============== */
+/* user interface */
+/* ============== */
+
+/*
+   Currently there is only a information display planned, as the layer
+   is not visible for the user space at all.
+
+   Information is available via procfs. The current entry is "/proc/videocodecs"
+   but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--.
+
+A example for such an output is:
+
+<S>lave or attached <M>aster name  type flags    magic    (connected as)
+S                          zr36050 0002 0000d001 00000000 (TEMPLATE)
+M                       zr36055[0] 0001 0000c001 00000000 (zr36050[0])
+M                       zr36055[1] 0001 0000c001 00000000 (zr36050[1])
+
+*/
+\f
+
+/* =============================================== */
+/* special defines for the videocodec_io structure */
+/* =============================================== */
+
+#ifndef __LINUX_VIDEOCODEC_H
+#define __LINUX_VIDEOCODEC_H
+
+#include <linux/videodev.h>
+
+//should be in videodev.h ??? (VID_DO_....)
+#define CODEC_DO_COMPRESSION 0
+#define CODEC_DO_EXPANSION   1
+
+/* this are the current codec flags I think they are needed */
+/*  -> type value in structure */
+#define CODEC_FLAG_JPEG      0x00000001L       // JPEG codec
+#define CODEC_FLAG_MPEG      0x00000002L       // MPEG1/2/4 codec
+#define CODEC_FLAG_DIVX      0x00000004L       // DIVX codec
+#define CODEC_FLAG_WAVELET   0x00000008L       // WAVELET codec
+                                         // room for other types
+
+#define CODEC_FLAG_MAGIC     0x00000800L       // magic key must match
+#define CODEC_FLAG_HARDWARE  0x00001000L       // is a hardware codec
+#define CODEC_FLAG_VFE       0x00002000L       // has direct video frontend
+#define CODEC_FLAG_ENCODER   0x00004000L       // compression capability
+#define CODEC_FLAG_DECODER   0x00008000L       // decompression capability
+#define CODEC_FLAG_NEEDIRQ   0x00010000L       // needs irq handling
+#define CODEC_FLAG_RDWRPIC   0x00020000L       // handles picture I/O
+
+/* a list of modes, some are just examples (is there any HW?) */
+#define CODEC_MODE_BJPG      0x0001    // Baseline JPEG
+#define CODEC_MODE_LJPG      0x0002    // Lossless JPEG
+#define CODEC_MODE_MPEG1     0x0003    // MPEG 1
+#define CODEC_MODE_MPEG2     0x0004    // MPEG 2
+#define CODEC_MODE_MPEG4     0x0005    // MPEG 4
+#define CODEC_MODE_MSDIVX    0x0006    // MS DivX
+#define CODEC_MODE_ODIVX     0x0007    // Open DivX
+#define CODEC_MODE_WAVELET   0x0008    // Wavelet
+
+/* this are the current codec types I want to implement */
+/*  -> type value in structure */
+#define CODEC_TYPE_NONE    0
+#define CODEC_TYPE_L64702  1
+#define CODEC_TYPE_ZR36050 2
+#define CODEC_TYPE_ZR36016 3
+#define CODEC_TYPE_ZR36060 4
+
+/* the type of data may be enhanced by future implementations (data-fn.'s) */
+/*  -> used in command                                                     */
+#define CODEC_G_STATUS         0x0000  /* codec status (query only) */
+#define CODEC_S_CODEC_MODE     0x0001  /* codec mode (baseline JPEG, MPEG1,... */
+#define CODEC_G_CODEC_MODE     0x8001
+#define CODEC_S_VFE            0x0002  /* additional video frontend setup */
+#define CODEC_G_VFE            0x8002
+#define CODEC_S_MMAP           0x0003  /* MMAP setup (if available) */
+
+#define CODEC_S_JPEG_TDS_BYTE  0x0010  /* target data size in bytes */
+#define CODEC_G_JPEG_TDS_BYTE  0x8010
+#define CODEC_S_JPEG_SCALE     0x0011  /* scaling factor for quant. tables */
+#define CODEC_G_JPEG_SCALE     0x8011
+#define CODEC_S_JPEG_HDT_DATA  0x0018  /* huffman-tables */
+#define CODEC_G_JPEG_HDT_DATA  0x8018
+#define CODEC_S_JPEG_QDT_DATA  0x0019  /* quantizing-tables */
+#define CODEC_G_JPEG_QDT_DATA  0x8019
+#define CODEC_S_JPEG_APP_DATA  0x001A  /* APP marker */
+#define CODEC_G_JPEG_APP_DATA  0x801A
+#define CODEC_S_JPEG_COM_DATA  0x001B  /* COM marker */
+#define CODEC_G_JPEG_COM_DATA  0x801B
+
+#define CODEC_S_PRIVATE        0x1000  /* "private" commands start here */
+#define CODEC_G_PRIVATE        0x9000
+
+#define CODEC_G_FLAG           0x8000  /* this is how 'get' is detected */
+
+/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */
+/*  -> used in get_image, put_image                                        */
+#define CODEC_TRANSFER_KERNEL 0        /* use "memcopy" */
+#define CODEC_TRANSFER_USER   1        /* use "to/from_user" */
+\f
+
+/* ========================= */
+/* the structures itself ... */
+/* ========================= */
+
+struct vfe_polarity {
+       unsigned int vsync_pol:1;
+       unsigned int hsync_pol:1;
+       unsigned int field_pol:1;
+       unsigned int blank_pol:1;
+       unsigned int subimg_pol:1;
+       unsigned int poe_pol:1;
+       unsigned int pvalid_pol:1;
+       unsigned int vclk_pol:1;
+};
+
+struct vfe_settings {
+       __u32 x, y;             /* Offsets into image */
+       __u32 width, height;    /* Area to capture */
+       __u16 decimation;       /* Decimation divider */
+       __u16 flags;            /* Flags for capture */
+/* flags are the same as in struct video_capture - see videodev.h:
+#define VIDEO_CAPTURE_ODD              0
+#define VIDEO_CAPTURE_EVEN             1
+*/
+       __u16 quality;          /* quality of the video */
+};
+
+struct tvnorm {
+       u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
+};
+
+struct jpeg_com_marker {
+       int len; /* number of usable bytes in data */
+       char data[60];
+};
+
+struct jpeg_app_marker {
+       int appn; /* number app segment */
+       int len; /* number of usable bytes in data */
+       char data[60];
+};
+
+struct videocodec {
+       struct module *owner;
+       /* -- filled in by slave device during register -- */
+       char name[32];
+       unsigned long magic;    /* may be used for client<->master attaching */
+       unsigned long flags;    /* functionality flags */
+       unsigned int type;      /* codec type */
+
+       /* -- these is filled in later during master device attach -- */
+
+       struct videocodec_master *master_data;
+
+       /* -- these are filled in by the slave device during register -- */
+
+       void *data;             /* private slave data */
+
+       /* attach/detach client functions (indirect call) */
+       int (*setup) (struct videocodec * codec);
+       int (*unset) (struct videocodec * codec);
+
+       /* main functions, every client needs them for sure! */
+       // set compression or decompression (or freeze, stop, standby, etc)
+       int (*set_mode) (struct videocodec * codec,
+                        int mode);
+       // setup picture size and norm (for the codec's video frontend)
+       int (*set_video) (struct videocodec * codec,
+                         struct tvnorm * norm,
+                         struct vfe_settings * cap,
+                         struct vfe_polarity * pol);
+       // other control commands, also mmap setup etc.
+       int (*control) (struct videocodec * codec,
+                       int type,
+                       int size,
+                       void *data);
+
+       /* additional setup/query/processing (may be NULL pointer) */
+       // interrupt setup / handling (for irq's delivered by master)
+       int (*setup_interrupt) (struct videocodec * codec,
+                               long mode);
+       int (*handle_interrupt) (struct videocodec * codec,
+                                int source,
+                                long flag);
+       // picture interface (if any)
+       long (*put_image) (struct videocodec * codec,
+                          int tr_type,
+                          int block,
+                          long *fr_num,
+                          long *flag,
+                          long size,
+                          void *buf);
+       long (*get_image) (struct videocodec * codec,
+                          int tr_type,
+                          int block,
+                          long *fr_num,
+                          long *flag,
+                          long size,
+                          void *buf);
+};
+
+struct videocodec_master {
+       /* -- filled in by master device for registration -- */
+       char name[32];
+       unsigned long magic;    /* may be used for client<->master attaching */
+       unsigned long flags;    /* functionality flags */
+       unsigned int type;      /* master type */
+
+       void *data;             /* private master data */
+
+        __u32(*readreg) (struct videocodec * codec,
+                         __u16 reg);
+       void (*writereg) (struct videocodec * codec,
+                         __u16 reg,
+                         __u32 value);
+};
+\f
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+/* attach and detach commands for the master */
+// * master structure needs to be kmalloc'ed before calling attach
+//   and free'd after calling detach
+// * returns pointer on success, NULL on failure
+extern struct videocodec *videocodec_attach(struct videocodec_master *);
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_detach(struct videocodec *);
+
+/* register and unregister commands for the slaves */
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_register(const struct videocodec *);
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_unregister(const struct videocodec *);
+
+/* the other calls are directly done via the videocodec structure! */
+
+#endif                         /*ifndef __LINUX_VIDEOCODEC_H */
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
new file mode 100644 (file)
index 0000000..46b7ad4
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+ * zoran - Iomega Buz driver
+ *
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * based on
+ *
+ * zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * and
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *                        & Marcus Metzler (mocm@thp.uni-koeln.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BUZ_H_
+#define _BUZ_H_
+
+struct zoran_requestbuffers {
+       unsigned long count;    /* Number of buffers for MJPEG grabbing */
+       unsigned long size;     /* Size PER BUFFER in bytes */
+};
+
+struct zoran_sync {
+       unsigned long frame;    /* number of buffer that has been free'd */
+       unsigned long length;   /* number of code bytes in buffer (capture only) */
+       unsigned long seq;      /* frame sequence number */
+       struct timeval timestamp;       /* timestamp */
+};
+
+struct zoran_status {
+       int input;              /* Input channel, has to be set prior to BUZIOC_G_STATUS */
+       int signal;             /* Returned: 1 if valid video signal detected */
+       int norm;               /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
+       int color;              /* Returned: 1 if color signal detected */
+};
+
+struct zoran_params {
+
+       /* The following parameters can only be queried */
+
+       int major_version;      /* Major version number of driver */
+       int minor_version;      /* Minor version number of driver */
+
+       /* Main control parameters */
+
+       int input;              /* Input channel: 0 = Composite, 1 = S-VHS */
+       int norm;               /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
+       int decimation;         /* decimation of captured video,
+                                * enlargement of video played back.
+                                * Valid values are 1, 2, 4 or 0.
+                                * 0 is a special value where the user
+                                * has full control over video scaling */
+
+       /* The following parameters only have to be set if decimation==0,
+        * for other values of decimation they provide the data how the image is captured */
+
+       int HorDcm;             /* Horizontal decimation: 1, 2 or 4 */
+       int VerDcm;             /* Vertical decimation: 1 or 2 */
+       int TmpDcm;             /* Temporal decimation: 1 or 2,
+                                * if TmpDcm==2 in capture every second frame is dropped,
+                                * in playback every frame is played twice */
+       int field_per_buff;     /* Number of fields per buffer: 1 or 2 */
+       int img_x;              /* start of image in x direction */
+       int img_y;              /* start of image in y direction */
+       int img_width;          /* image width BEFORE decimation,
+                                * must be a multiple of HorDcm*16 */
+       int img_height;         /* image height BEFORE decimation,
+                                * must be a multiple of VerDcm*8 */
+
+       /* --- End of parameters for decimation==0 only --- */
+
+       /* JPEG control parameters */
+
+       int quality;            /* Measure for quality of compressed images.
+                                * Scales linearly with the size of the compressed images.
+                                * Must be beetween 0 and 100, 100 is a compression
+                                * ratio of 1:4 */
+
+       int odd_even;           /* Which field should come first ??? */
+
+       int APPn;               /* Number of APP segment to be written, must be 0..15 */
+       int APP_len;            /* Length of data in JPEG APPn segment */
+       char APP_data[60];      /* Data in the JPEG APPn segment. */
+
+       int COM_len;            /* Length of data in JPEG COM segment */
+       char COM_data[60];      /* Data in JPEG COM segment */
+
+       unsigned long jpeg_markers;     /* Which markers should go into the JPEG output.
+                                        * Unless you exactly know what you do, leave them untouched.
+                                        * Inluding less markers will make the resulting code
+                                        * smaller, but there will be fewer aplications
+                                        * which can read it.
+                                        * The presence of the APP and COM marker is
+                                        * influenced by APP0_len and COM_len ONLY! */
+#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
+#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
+#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
+#define JPEG_MARKER_COM (1<<6) /* Comment segment */
+#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */
+
+       int VFIFO_FB;           /* Flag for enabling Video Fifo Feedback.
+                                * If this flag is turned on and JPEG decompressing
+                                * is going to the screen, the decompress process
+                                * is stopped every time the Video Fifo is full.
+                                * This enables a smooth decompress to the screen
+                                * but the video output signal will get scrambled */
+
+       /* Misc */
+
+       char reserved[312];     /* Makes 512 bytes for this structure */
+};
+
+/*
+Private IOCTL to set up for displaying MJPEG
+*/
+#define BUZIOC_G_PARAMS       _IOR ('v', BASE_VIDIOCPRIVATE+0,  struct zoran_params)
+#define BUZIOC_S_PARAMS       _IOWR('v', BASE_VIDIOCPRIVATE+1,  struct zoran_params)
+#define BUZIOC_REQBUFS        _IOWR('v', BASE_VIDIOCPRIVATE+2,  struct zoran_requestbuffers)
+#define BUZIOC_QBUF_CAPT      _IOW ('v', BASE_VIDIOCPRIVATE+3,  int)
+#define BUZIOC_QBUF_PLAY      _IOW ('v', BASE_VIDIOCPRIVATE+4,  int)
+#define BUZIOC_SYNC           _IOR ('v', BASE_VIDIOCPRIVATE+5,  struct zoran_sync)
+#define BUZIOC_G_STATUS       _IOWR('v', BASE_VIDIOCPRIVATE+6,  struct zoran_status)
+
+
+#ifdef __KERNEL__
+
+#define MAJOR_VERSION 0                /* driver major version */
+#define MINOR_VERSION 9                /* driver minor version */
+#define RELEASE_VERSION 5      /* release version */
+
+#define ZORAN_NAME    "ZORAN"  /* name of the device */
+
+#define ZR_DEVNAME(zr) ((zr)->name)
+
+#define   BUZ_MAX_WIDTH   (zr->timing->Wa)
+#define   BUZ_MAX_HEIGHT  (zr->timing->Ha)
+#define   BUZ_MIN_WIDTH    32  /* never display less than 32 pixels */
+#define   BUZ_MIN_HEIGHT   24  /* never display less than 24 rows */
+
+#define BUZ_NUM_STAT_COM    4
+#define BUZ_MASK_STAT_COM   3
+
+#define BUZ_MAX_FRAME     256  /* Must be a power of 2 */
+#define BUZ_MASK_FRAME    255  /* Must be BUZ_MAX_FRAME-1 */
+
+#define BUZ_MAX_INPUT       16
+
+#if VIDEO_MAX_FRAME <= 32
+#   define   V4L_MAX_FRAME   32
+#elif VIDEO_MAX_FRAME <= 64
+#   define   V4L_MAX_FRAME   64
+#else
+#   error   "Too many video frame buffers to handle"
+#endif
+#define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
+
+#define MAX_KMALLOC_MEM (128*1024)
+
+#include "zr36057.h"
+
+enum card_type {
+       UNKNOWN = -1,
+
+       /* Pinnacle/Miro */
+       DC10_old,               /* DC30 like */
+       DC10_new,               /* DC10plus like */
+       DC10plus,
+       DC30,
+       DC30plus,
+
+       /* Linux Media Labs */
+       LML33,
+       LML33R10,
+
+       /* Iomega */
+       BUZ,
+
+       /* AverMedia */
+       AVS6EYES,
+
+       /* total number of cards */
+       NUM_CARDS
+};
+
+enum zoran_codec_mode {
+       BUZ_MODE_IDLE,          /* nothing going on */
+       BUZ_MODE_MOTION_COMPRESS,       /* grabbing frames */
+       BUZ_MODE_MOTION_DECOMPRESS,     /* playing frames */
+       BUZ_MODE_STILL_COMPRESS,        /* still frame conversion */
+       BUZ_MODE_STILL_DECOMPRESS       /* still frame conversion */
+};
+
+enum zoran_buffer_state {
+       BUZ_STATE_USER,         /* buffer is owned by application */
+       BUZ_STATE_PEND,         /* buffer is queued in pend[] ready to feed to I/O */
+       BUZ_STATE_DMA,          /* buffer is queued in dma[] for I/O */
+       BUZ_STATE_DONE          /* buffer is ready to return to application */
+};
+
+enum zoran_map_mode {
+       ZORAN_MAP_MODE_RAW,
+       ZORAN_MAP_MODE_JPG_REC,
+#define ZORAN_MAP_MODE_JPG ZORAN_MAP_MODE_JPG_REC
+       ZORAN_MAP_MODE_JPG_PLAY,
+};
+
+enum gpio_type {
+       ZR_GPIO_JPEG_SLEEP = 0,
+       ZR_GPIO_JPEG_RESET,
+       ZR_GPIO_JPEG_FRAME,
+       ZR_GPIO_VID_DIR,
+       ZR_GPIO_VID_EN,
+       ZR_GPIO_VID_RESET,
+       ZR_GPIO_CLK_SEL1,
+       ZR_GPIO_CLK_SEL2,
+       ZR_GPIO_MAX,
+};
+
+enum gpcs_type {
+       GPCS_JPEG_RESET = 0,
+       GPCS_JPEG_START,
+       GPCS_MAX,
+};
+
+struct zoran_format {
+       char *name;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+       int palette;
+#endif
+       __u32 fourcc;
+       int colorspace;
+       int depth;
+       __u32 flags;
+       __u32 vfespfr;
+};
+/* flags */
+#define ZORAN_FORMAT_COMPRESSED 1<<0
+#define ZORAN_FORMAT_OVERLAY    1<<1
+#define ZORAN_FORMAT_CAPTURE   1<<2
+#define ZORAN_FORMAT_PLAYBACK  1<<3
+
+/* overlay-settings */
+struct zoran_overlay_settings {
+       int is_set;
+       int x, y, width, height;        /* position */
+       int clipcount;          /* position and number of clips */
+       const struct zoran_format *format;      /* overlay format */
+};
+
+/* v4l-capture settings */
+struct zoran_v4l_settings {
+       int width, height, bytesperline;        /* capture size */
+       const struct zoran_format *format;      /* capture format */
+};
+
+/* jpg-capture/-playback settings */
+struct zoran_jpg_settings {
+       int decimation;         /* this bit is used to set everything to default */
+       int HorDcm, VerDcm, TmpDcm;     /* capture decimation settings (TmpDcm=1 means both fields) */
+       int field_per_buff, odd_even;   /* field-settings (odd_even=1 (+TmpDcm=1) means top-field-first) */
+       int img_x, img_y, img_width, img_height;        /* crop settings (subframe capture) */
+       struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
+};
+
+struct zoran_mapping {
+       struct file *file;
+       int count;
+};
+
+struct zoran_jpg_buffer {
+       struct zoran_mapping *map;
+       __le32 *frag_tab;               /* addresses of frag table */
+       u32 frag_tab_bus;       /* same value cached to save time in ISR */
+       enum zoran_buffer_state state;  /* non-zero if corresponding buffer is in use in grab queue */
+       struct zoran_sync bs;   /* DONE: info to return to application */
+};
+
+struct zoran_v4l_buffer {
+       struct zoran_mapping *map;
+       char *fbuffer;          /* virtual  address of frame buffer */
+       unsigned long fbuffer_phys;     /* physical address of frame buffer */
+       unsigned long fbuffer_bus;      /* bus      address of frame buffer */
+       enum zoran_buffer_state state;  /* state: unused/pending/done */
+       struct zoran_sync bs;   /* DONE: info to return to application */
+};
+
+enum zoran_lock_activity {
+       ZORAN_FREE,             /* free for use */
+       ZORAN_ACTIVE,           /* active but unlocked */
+       ZORAN_LOCKED,           /* locked */
+};
+
+/* buffer collections */
+struct zoran_jpg_struct {
+       enum zoran_lock_activity active;        /* feature currently in use? */
+       struct zoran_jpg_buffer buffer[BUZ_MAX_FRAME];  /* buffers */
+       int num_buffers, buffer_size;
+       u8 allocated;           /* Flag if buffers are allocated  */
+       u8 ready_to_be_freed;   /* hack - see zoran_driver.c */
+       u8 need_contiguous;     /* Flag if contiguous buffers are needed */
+};
+
+struct zoran_v4l_struct {
+       enum zoran_lock_activity active;        /* feature currently in use? */
+       struct zoran_v4l_buffer buffer[VIDEO_MAX_FRAME];        /* buffers */
+       int num_buffers, buffer_size;
+       u8 allocated;           /* Flag if buffers are allocated  */
+       u8 ready_to_be_freed;   /* hack - see zoran_driver.c */
+};
+
+struct zoran;
+
+/* zoran_fh contains per-open() settings */
+struct zoran_fh {
+       struct zoran *zr;
+
+       enum zoran_map_mode map_mode;   /* Flag which bufferset will map by next mmap() */
+
+       struct zoran_overlay_settings overlay_settings;
+       u32 *overlay_mask;      /* overlay mask */
+       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
+
+       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
+       struct zoran_v4l_struct v4l_buffers;    /* V4L buffers' info */
+
+       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
+       struct zoran_jpg_struct jpg_buffers;    /* MJPEG buffers' info */
+};
+
+struct card_info {
+       enum card_type type;
+       char name[32];
+       u16 i2c_decoder, i2c_encoder;                   /* I2C types */
+       u16 video_vfe, video_codec;                     /* videocodec types */
+       u16 audio_chip;                                 /* audio type */
+       u16 vendor_id, device_id;       /* subsystem vendor/device ID */
+
+       int inputs;             /* number of video inputs */
+       struct input {
+               int muxsel;
+               char name[32];
+       } input[BUZ_MAX_INPUT];
+
+       int norms;
+       struct tvnorm *tvn[3];  /* supported TV norms */
+
+       u32 jpeg_int;           /* JPEG interrupt */
+       u32 vsync_int;          /* VSYNC interrupt */
+       s8 gpio[ZR_GPIO_MAX];
+       u8 gpcs[GPCS_MAX];
+
+       struct vfe_polarity vfe_pol;
+       u8 gpio_pol[ZR_GPIO_MAX];
+
+       /* is the /GWS line conected? */
+       u8 gws_not_connected;
+
+       /* avs6eyes mux setting */
+       u8 input_mux;
+
+       void (*init) (struct zoran * zr);
+};
+
+struct zoran {
+       struct video_device *video_dev;
+
+       struct i2c_adapter i2c_adapter; /* */
+       struct i2c_algo_bit_data i2c_algo;      /* */
+       u32 i2cbr;
+
+       struct i2c_client *decoder;     /* video decoder i2c client */
+       struct i2c_client *encoder;     /* video encoder i2c client */
+
+       struct videocodec *codec;       /* video codec */
+       struct videocodec *vfe; /* video front end */
+
+       struct mutex resource_lock;     /* prevent evil stuff */
+
+       u8 initialized;         /* flag if zoran has been correctly initalized */
+       int user;               /* number of current users */
+       struct card_info card;
+       struct tvnorm *timing;
+
+       unsigned short id;      /* number of this device */
+       char name[32];          /* name of this device */
+       struct pci_dev *pci_dev;        /* PCI device */
+       unsigned char revision; /* revision of zr36057 */
+       unsigned int zr36057_adr;       /* bus address of IO mem returned by PCI BIOS */
+       unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
+
+       spinlock_t spinlock;    /* Spinlock */
+
+       /* Video for Linux parameters */
+       int input, norm;        /* card's norm and input - norm=VIDEO_MODE_* */
+       int hue, saturation, contrast, brightness;      /* Current picture params */
+       struct video_buffer buffer;     /* Current buffer params */
+       struct zoran_overlay_settings overlay_settings;
+       u32 *overlay_mask;      /* overlay mask */
+       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
+
+       wait_queue_head_t v4l_capq;
+
+       int v4l_overlay_active; /* Overlay grab is activated */
+       int v4l_memgrab_active; /* Memory grab is activated */
+
+       int v4l_grab_frame;     /* Frame number being currently grabbed */
+#define NO_GRAB_ACTIVE (-1)
+       unsigned long v4l_grab_seq;     /* Number of frames grabbed */
+       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
+
+       /* V4L grab queue of frames pending */
+       unsigned long v4l_pend_head;
+       unsigned long v4l_pend_tail;
+       unsigned long v4l_sync_tail;
+       int v4l_pend[V4L_MAX_FRAME];
+       struct zoran_v4l_struct v4l_buffers;    /* V4L buffers' info */
+
+       /* Buz MJPEG parameters */
+       enum zoran_codec_mode codec_mode;       /* status of codec */
+       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
+
+       wait_queue_head_t jpg_capq;     /* wait here for grab to finish */
+
+       /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
+       /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
+       /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
+       unsigned long jpg_que_head;     /* Index where to put next buffer which is queued */
+       unsigned long jpg_dma_head;     /* Index of next buffer which goes into stat_com  */
+       unsigned long jpg_dma_tail;     /* Index of last buffer in stat_com               */
+       unsigned long jpg_que_tail;     /* Index of last buffer in queue                  */
+       unsigned long jpg_seq_num;      /* count of frames since grab/play started        */
+       unsigned long jpg_err_seq;      /* last seq_num before error                      */
+       unsigned long jpg_err_shift;
+       unsigned long jpg_queued_num;   /* count of frames queued since grab/play started */
+
+       /* zr36057's code buffer table */
+       __le32 *stat_com;               /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+
+       /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
+       int jpg_pend[BUZ_MAX_FRAME];
+
+       /* array indexed by frame number */
+       struct zoran_jpg_struct jpg_buffers;    /* MJPEG buffers' info */
+
+       /* Additional stuff for testing */
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *zoran_proc;
+#else
+       void *zoran_proc;
+#endif
+       int testing;
+       int jpeg_error;
+       int intr_counter_GIRQ1;
+       int intr_counter_GIRQ0;
+       int intr_counter_CodRepIRQ;
+       int intr_counter_JPEGRepIRQ;
+       int field_counter;
+       int IRQ1_in;
+       int IRQ1_out;
+       int JPEG_in;
+       int JPEG_out;
+       int JPEG_0;
+       int JPEG_1;
+       int END_event_missed;
+       int JPEG_missed;
+       int JPEG_error;
+       int num_errors;
+       int JPEG_max_missed;
+       int JPEG_min_missed;
+
+       u32 last_isr;
+       unsigned long frame_num;
+
+       wait_queue_head_t test_q;
+};
+
+/*The following should be done in more portable way. It depends on define
+  of _ALPHA_BUZ in the Makefile.*/
+
+#ifdef _ALPHA_BUZ
+#define btwrite(dat,adr)    writel((dat), zr->zr36057_adr+(adr))
+#define btread(adr)         readl(zr->zr36057_adr+(adr))
+#else
+#define btwrite(dat,adr)    writel((dat), zr->zr36057_mem+(adr))
+#define btread(adr)         readl(zr->zr36057_mem+(adr))
+#endif
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#endif                         /* __kernel__ */
+
+#endif
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
new file mode 100644 (file)
index 0000000..3282be7
--- /dev/null
@@ -0,0 +1,1670 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+
+#include <linux/proc_fs.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/kmod.h>
+#include <linux/wait.h>
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/video_decoder.h>
+#include <linux/video_encoder.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_card.h"
+#include "zoran_device.h"
+#include "zoran_procfs.h"
+
+extern const struct zoran_format zoran_formats[];
+
+static int card[BUZ_MAX] = { -1, -1, -1, -1 };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "The type of card");
+
+static int encoder[BUZ_MAX] = { -1, -1, -1, -1 };
+module_param_array(encoder, int, NULL, 0444);
+MODULE_PARM_DESC(encoder, "i2c TV encoder");
+
+static int decoder[BUZ_MAX] = { -1, -1, -1, -1 };
+module_param_array(decoder, int, NULL, 0444);
+MODULE_PARM_DESC(decoder, "i2c TV decoder");
+
+/*
+   The video mem address of the video card.
+   The driver has a little database for some videocards
+   to determine it from there. If your video card is not in there
+   you have either to give it to the driver as a parameter
+   or set in in a VIDIOCSFBUF ioctl
+ */
+
+static unsigned long vidmem;   /* default = 0 - Video memory base address */
+module_param(vidmem, ulong, 0444);
+MODULE_PARM_DESC(vidmem, "Default video memory base address");
+
+/*
+   Default input and video norm at startup of the driver.
+*/
+
+static unsigned int default_input;     /* default 0 = Composite, 1 = S-Video */
+module_param(default_input, uint, 0444);
+MODULE_PARM_DESC(default_input,
+                "Default input (0=Composite, 1=S-Video, 2=Internal)");
+
+static int default_mux = 1;    /* 6 Eyes input selection */
+module_param(default_mux, int, 0644);
+MODULE_PARM_DESC(default_mux,
+                "Default 6 Eyes mux setting (Input selection)");
+
+static int default_norm;       /* default 0 = PAL, 1 = NTSC 2 = SECAM */
+module_param(default_norm, int, 0444);
+MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
+
+/* /dev/videoN, -1 for autodetect */
+static int video_nr[BUZ_MAX] = {-1, -1, -1, -1};
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
+
+/*
+   Number and size of grab buffers for Video 4 Linux
+   The vast majority of applications should not need more than 2,
+   the very popular BTTV driver actually does ONLY have 2.
+   Time sensitive applications might need more, the maximum
+   is VIDEO_MAX_FRAME (defined in <linux/videodev.h>).
+
+   The size is set so that the maximum possible request
+   can be satisfied. Decrease  it, if bigphys_area alloc'd
+   memory is low. If you don't have the bigphys_area patch,
+   set it to 128 KB. Will you allow only to grab small
+   images with V4L, but that's better than nothing.
+
+   v4l_bufsize has to be given in KB !
+
+*/
+
+int v4l_nbufs = 2;
+int v4l_bufsize = 128;         /* Everybody should be able to work with this setting */
+module_param(v4l_nbufs, int, 0644);
+MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
+module_param(v4l_bufsize, int, 0644);
+MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
+
+int jpg_nbufs = 32;
+int jpg_bufsize = 512;         /* max size for 100% quality full-PAL frame */
+module_param(jpg_nbufs, int, 0644);
+MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
+module_param(jpg_bufsize, int, 0644);
+MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
+
+int pass_through = 0;          /* 1=Pass through TV signal when device is not used */
+                               /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
+module_param(pass_through, int, 0644);
+MODULE_PARM_DESC(pass_through,
+                "Pass TV signal through to TV-out when idling");
+
+int zr36067_debug = 1;
+module_param_named(debug, zr36067_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-5)");
+
+MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
+MODULE_AUTHOR("Serguei Miridonov");
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id zr36067_pci_tbl[] = {
+       {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
+
+int zoran_num;                 /* number of Buzs in use */
+struct zoran *zoran[BUZ_MAX];
+
+/* videocodec bus functions ZR36060 */
+static u32
+zr36060_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 0, 1, reg >> 8)
+           || post_office_write(zr, 0, 2, reg & 0xff)) {
+               return -1;
+       }
+
+       data = post_office_read(zr, 0, 3) & 0xff;
+       return data;
+}
+
+static void
+zr36060_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 0, 1, reg >> 8)
+           || post_office_write(zr, 0, 2, reg & 0xff)) {
+               return;
+       }
+
+       post_office_write(zr, 0, 3, val & 0xff);
+}
+
+/* videocodec bus functions ZR36050 */
+static u32
+zr36050_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
+               return -1;
+       }
+
+       data = post_office_read(zr, 0, reg & 0x03) & 0xff;      // reg. LOWBYTES + read
+       return data;
+}
+
+static void
+zr36050_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
+               return;
+       }
+
+       post_office_write(zr, 0, reg & 0x03, val & 0xff);       // reg. LOWBYTES + wr. data
+}
+
+/* videocodec bus functions ZR36016 */
+static u32
+zr36016_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)) {
+               return -1;
+       }
+
+       data = post_office_read(zr, 2, reg & 0x03) & 0xff;      // read
+       return data;
+}
+
+/* hack for in zoran_device.c */
+void
+zr36016_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)) {
+               return;
+       }
+
+       post_office_write(zr, 2, reg & 0x03, val & 0x0ff);      // wr. data
+}
+
+/*
+ * Board specific information
+ */
+
+static void
+dc10_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: dc10_init()\n", ZR_DEVNAME(zr));
+
+       /* Pixel clock selection */
+       GPIO(zr, 4, 0);
+       GPIO(zr, 5, 1);
+       /* Enable the video bus sync signals */
+       GPIO(zr, 7, 0);
+}
+
+static void
+dc10plus_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: dc10plus_init()\n", ZR_DEVNAME(zr));
+}
+
+static void
+buz_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: buz_init()\n", ZR_DEVNAME(zr));
+
+       /* some stuff from Iomega */
+       pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
+       pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020);
+       pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000);
+}
+
+static void
+lml33_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: lml33_init()\n", ZR_DEVNAME(zr));
+
+       GPIO(zr, 2, 1);         // Set Composite input/output
+}
+
+static void
+avs6eyes_init (struct zoran *zr)
+{
+       // AverMedia 6-Eyes original driver by Christer Weinigel
+
+       // Lifted straight from Christer's old driver and
+       // modified slightly by Martin Samuelsson.
+
+       int mux = default_mux; /* 1 = BT866, 7 = VID1 */
+
+       GPIO(zr, 4, 1); /* Bt866 SLEEP on */
+       udelay(2);
+
+       GPIO(zr, 0, 1); /* ZR36060 /RESET on */
+       GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
+       GPIO(zr, 2, mux & 1);   /* MUX S0 */
+       GPIO(zr, 3, 0); /* /FRAME on */
+       GPIO(zr, 4, 0); /* Bt866 SLEEP off */
+       GPIO(zr, 5, mux & 2);   /* MUX S1 */
+       GPIO(zr, 6, 0); /* ? */
+       GPIO(zr, 7, mux & 4);   /* MUX S2 */
+
+}
+
+static char *
+i2cid_to_modulename (u16 i2c_id)
+{
+       char *name = NULL;
+
+       switch (i2c_id) {
+       case I2C_DRIVERID_SAA7110:
+               name = "saa7110";
+               break;
+       case I2C_DRIVERID_SAA7111A:
+               name = "saa7111";
+               break;
+       case I2C_DRIVERID_SAA7114:
+               name = "saa7114";
+               break;
+       case I2C_DRIVERID_SAA7185B:
+               name = "saa7185";
+               break;
+       case I2C_DRIVERID_ADV7170:
+               name = "adv7170";
+               break;
+       case I2C_DRIVERID_ADV7175:
+               name = "adv7175";
+               break;
+       case I2C_DRIVERID_BT819:
+               name = "bt819";
+               break;
+       case I2C_DRIVERID_BT856:
+               name = "bt856";
+               break;
+       case I2C_DRIVERID_BT866:
+               name = "bt866";
+               break;
+       case I2C_DRIVERID_VPX3220:
+               name = "vpx3220";
+               break;
+       case I2C_DRIVERID_KS0127:
+               name = "ks0127";
+               break;
+       }
+
+       return name;
+}
+
+static char *
+codecid_to_modulename (u16 codecid)
+{
+       char *name = NULL;
+
+       switch (codecid) {
+       case CODEC_TYPE_ZR36060:
+               name = "zr36060";
+               break;
+       case CODEC_TYPE_ZR36050:
+               name = "zr36050";
+               break;
+       case CODEC_TYPE_ZR36016:
+               name = "zr36016";
+               break;
+       }
+
+       return name;
+}
+
+// struct tvnorm {
+//      u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
+// };
+
+static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
+static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
+static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
+
+static struct tvnorm f50ccir601_lml33 = { 864, 720, 75+34, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_lml33 = { 858, 720, 57+34, 788, 525, 480, 16 };
+
+/* The DC10 (57/16/50) uses VActive as HSync, so HStart must be 0 */
+static struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 };
+static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
+
+/* FIXME: I cannot swap U and V in saa7114, so i do one
+ * pixel left shift in zoran (75 -> 74)
+ * (Maxim Yevtyushkin <max@linuxmedialabs.com>) */
+static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
+
+/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
+ * copy Maxim's left shift hack for the 6 Eyes.
+ *
+ * Christer's driver used the unshifted norms, though...
+ * /Sam  */
+static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
+
+static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
+       {
+               .type = DC10_old,
+               .name = "DC10(old)",
+               .i2c_decoder = I2C_DRIVERID_VPX3220,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = 3,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = DC10_new,
+               .name = "DC10(new)",
+               .i2c_decoder = I2C_DRIVERID_SAA7110,
+               .i2c_encoder = I2C_DRIVERID_ADV7175,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 3,
+               .input = {
+                               { 0, "Composite" },
+                               { 7, "S-Video" },
+                               { 5, "Internal/comp" }
+                       },
+               .norms = 3,
+               .tvn = {
+                               &f50sqpixel,
+                               &f60sqpixel,
+                               &f50sqpixel},
+               .jpeg_int = ZR36057_ISR_GIRQ0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { -1, 1},
+               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10plus_init,
+       }, {
+               .type = DC10plus,
+               .name = "DC10plus",
+               .vendor_id = PCI_VENDOR_ID_MIRO,
+               .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS,
+               .i2c_decoder = I2C_DRIVERID_SAA7110,
+               .i2c_encoder = I2C_DRIVERID_ADV7175,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 3,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" },
+                       { 5, "Internal/comp" }
+               },
+               .norms = 3,
+               .tvn = {
+                       &f50sqpixel,
+                       &f60sqpixel,
+                       &f50sqpixel
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { -1, 1 },
+               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10plus_init,
+       }, {
+               .type = DC30,
+               .name = "DC30",
+               .i2c_decoder = I2C_DRIVERID_VPX3220,
+               .i2c_encoder = I2C_DRIVERID_ADV7175,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = 3,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = DC30plus,
+               .name = "DC30plus",
+               .vendor_id = PCI_VENDOR_ID_MIRO,
+               .device_id = PCI_DEVICE_ID_MIRO_DC30PLUS,
+               .i2c_decoder = I2C_DRIVERID_VPX3220,
+               .i2c_encoder = I2C_DRIVERID_ADV7175,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = 3,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = LML33,
+               .name = "LML33",
+               .i2c_decoder = I2C_DRIVERID_BT819,
+               .i2c_encoder = I2C_DRIVERID_BT856,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = 2,
+               .tvn = {
+                       &f50ccir601_lml33,
+                       &f60ccir601_lml33,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &lml33_init,
+       }, {
+               .type = LML33R10,
+               .name = "LML33R10",
+               .vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH,
+               .device_id = PCI_DEVICE_ID_LML_33R10,
+               .i2c_decoder = I2C_DRIVERID_SAA7114,
+               .i2c_encoder = I2C_DRIVERID_ADV7170,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = 2,
+               .tvn = {
+                       &f50ccir601_lm33r10,
+                       &f60ccir601_lm33r10,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &lml33_init,
+       }, {
+               .type = BUZ,
+               .name = "Buz",
+               .vendor_id = PCI_VENDOR_ID_IOMEGA,
+               .device_id = PCI_DEVICE_ID_IOMEGA_BUZ,
+               .i2c_decoder = I2C_DRIVERID_SAA7111A,
+               .i2c_encoder = I2C_DRIVERID_SAA7185B,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 3, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = 3,
+               .tvn = {
+                       &f50ccir601,
+                       &f60ccir601,
+                       &f50ccir601
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &buz_init,
+       }, {
+               .type = AVS6EYES,
+               .name = "6-Eyes",
+               /* AverMedia chose not to brand the 6-Eyes. Thus it
+                  can't be autodetected, and requires card=x. */
+               .vendor_id = -1,
+               .device_id = -1,
+               .i2c_decoder = I2C_DRIVERID_KS0127,
+               .i2c_encoder = I2C_DRIVERID_BT866,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 10,
+               .input = {
+                       { 0, "Composite 1" },
+                       { 1, "Composite 2" },
+                       { 2, "Composite 3" },
+                       { 4, "Composite 4" },
+                       { 5, "Composite 5" },
+                       { 6, "Composite 6" },
+                       { 8, "S-Video 1" },
+                       { 9, "S-Video 2" },
+                       {10, "S-Video 3" },
+                       {15, "YCbCr" }
+               },
+               .norms = 2,
+               .tvn = {
+                       &f50ccir601_avs6eyes,
+                       &f60ccir601_avs6eyes,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
+               .gpcs = { 3, 1 },                       // Validity unknown /Sam
+               .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
+               .gws_not_connected = 1,
+               .input_mux = 1,
+               .init = &avs6eyes_init,
+       }
+
+};
+
+/*
+ * I2C functions
+ */
+/* software I2C functions */
+static int
+zoran_i2c_getsda (void *data)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       return (btread(ZR36057_I2CBR) >> 1) & 1;
+}
+
+static int
+zoran_i2c_getscl (void *data)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       return btread(ZR36057_I2CBR) & 1;
+}
+
+static void
+zoran_i2c_setsda (void *data,
+                 int   state)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       if (state)
+               zr->i2cbr |= 2;
+       else
+               zr->i2cbr &= ~2;
+       btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static void
+zoran_i2c_setscl (void *data,
+                 int   state)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       if (state)
+               zr->i2cbr |= 1;
+       else
+               zr->i2cbr &= ~1;
+       btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static int
+zoran_i2c_client_register (struct i2c_client *client)
+{
+       struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
+       int res = 0;
+
+       dprintk(2,
+               KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n",
+               ZR_DEVNAME(zr), client->driver->id);
+
+       mutex_lock(&zr->resource_lock);
+
+       if (zr->user > 0) {
+               /* we're already busy, so we keep a reference to
+                * them... Could do a lot of stuff here, but this
+                * is easiest. (Did I ever mention I'm a lazy ass?)
+                */
+               res = -EBUSY;
+               goto clientreg_unlock_and_return;
+       }
+
+       if (client->driver->id == zr->card.i2c_decoder)
+               zr->decoder = client;
+       else if (client->driver->id == zr->card.i2c_encoder)
+               zr->encoder = client;
+       else {
+               res = -ENODEV;
+               goto clientreg_unlock_and_return;
+       }
+
+clientreg_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int
+zoran_i2c_client_unregister (struct i2c_client *client)
+{
+       struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
+       int res = 0;
+
+       dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr));
+
+       mutex_lock(&zr->resource_lock);
+
+       if (zr->user > 0) {
+               res = -EBUSY;
+               goto clientunreg_unlock_and_return;
+       }
+
+       /* try to locate it */
+       if (client == zr->encoder) {
+               zr->encoder = NULL;
+       } else if (client == zr->decoder) {
+               zr->decoder = NULL;
+               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id);
+       }
+clientunreg_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
+       .setsda = zoran_i2c_setsda,
+       .setscl = zoran_i2c_setscl,
+       .getsda = zoran_i2c_getsda,
+       .getscl = zoran_i2c_getscl,
+       .udelay = 10,
+       .timeout = 100,
+};
+
+static int
+zoran_register_i2c (struct zoran *zr)
+{
+       memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
+              sizeof(struct i2c_algo_bit_data));
+       zr->i2c_algo.data = zr;
+       zr->i2c_adapter.id = I2C_HW_B_ZR36067;
+       zr->i2c_adapter.client_register = zoran_i2c_client_register;
+       zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
+       strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
+               sizeof(zr->i2c_adapter.name));
+       i2c_set_adapdata(&zr->i2c_adapter, zr);
+       zr->i2c_adapter.algo_data = &zr->i2c_algo;
+       zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
+       return i2c_bit_add_bus(&zr->i2c_adapter);
+}
+
+static void
+zoran_unregister_i2c (struct zoran *zr)
+{
+       i2c_del_adapter(&zr->i2c_adapter);
+}
+
+/* Check a zoran_params struct for correctness, insert default params */
+
+int
+zoran_check_jpg_settings (struct zoran              *zr,
+                         struct zoran_jpg_settings *settings)
+{
+       int err = 0, err0 = 0;
+
+       dprintk(4,
+               KERN_DEBUG
+               "%s: check_jpg_settings() - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
+               ZR_DEVNAME(zr), settings->decimation, settings->HorDcm,
+               settings->VerDcm, settings->TmpDcm);
+       dprintk(4,
+               KERN_DEBUG
+               "%s: check_jpg_settings() - x: %d, y: %d, w: %d, y: %d\n",
+               ZR_DEVNAME(zr), settings->img_x, settings->img_y,
+               settings->img_width, settings->img_height);
+       /* Check decimation, set default values for decimation = 1, 2, 4 */
+       switch (settings->decimation) {
+       case 1:
+
+               settings->HorDcm = 1;
+               settings->VerDcm = 1;
+               settings->TmpDcm = 1;
+               settings->field_per_buff = 2;
+               settings->img_x = 0;
+               settings->img_y = 0;
+               settings->img_width = BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 2:
+
+               settings->HorDcm = 2;
+               settings->VerDcm = 1;
+               settings->TmpDcm = 2;
+               settings->field_per_buff = 1;
+               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings->img_y = 0;
+               settings->img_width =
+                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 4:
+
+               if (zr->card.type == DC10_new) {
+                       dprintk(1,
+                               KERN_DEBUG
+                               "%s: check_jpg_settings() - HDec by 4 is not supported on the DC10\n",
+                               ZR_DEVNAME(zr));
+                       err0++;
+                       break;
+               }
+
+               settings->HorDcm = 4;
+               settings->VerDcm = 2;
+               settings->TmpDcm = 2;
+               settings->field_per_buff = 1;
+               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings->img_y = 0;
+               settings->img_width =
+                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 0:
+
+               /* We have to check the data the user has set */
+
+               if (settings->HorDcm != 1 && settings->HorDcm != 2 &&
+                   (zr->card.type == DC10_new || settings->HorDcm != 4))
+                       err0++;
+               if (settings->VerDcm != 1 && settings->VerDcm != 2)
+                       err0++;
+               if (settings->TmpDcm != 1 && settings->TmpDcm != 2)
+                       err0++;
+               if (settings->field_per_buff != 1 &&
+                   settings->field_per_buff != 2)
+                       err0++;
+               if (settings->img_x < 0)
+                       err0++;
+               if (settings->img_y < 0)
+                       err0++;
+               if (settings->img_width < 0)
+                       err0++;
+               if (settings->img_height < 0)
+                       err0++;
+               if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH)
+                       err0++;
+               if (settings->img_y + settings->img_height >
+                   BUZ_MAX_HEIGHT / 2)
+                       err0++;
+               if (settings->HorDcm && settings->VerDcm) {
+                       if (settings->img_width %
+                           (16 * settings->HorDcm) != 0)
+                               err0++;
+                       if (settings->img_height %
+                           (8 * settings->VerDcm) != 0)
+                               err0++;
+               }
+
+               if (err0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: check_jpg_settings() - error in params for decimation = 0\n",
+                               ZR_DEVNAME(zr));
+                       err++;
+               }
+               break;
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: check_jpg_settings() - decimation = %d, must be 0, 1, 2 or 4\n",
+                       ZR_DEVNAME(zr), settings->decimation);
+               err++;
+               break;
+       }
+
+       if (settings->jpg_comp.quality > 100)
+               settings->jpg_comp.quality = 100;
+       if (settings->jpg_comp.quality < 5)
+               settings->jpg_comp.quality = 5;
+       if (settings->jpg_comp.APPn < 0)
+               settings->jpg_comp.APPn = 0;
+       if (settings->jpg_comp.APPn > 15)
+               settings->jpg_comp.APPn = 15;
+       if (settings->jpg_comp.APP_len < 0)
+               settings->jpg_comp.APP_len = 0;
+       if (settings->jpg_comp.APP_len > 60)
+               settings->jpg_comp.APP_len = 60;
+       if (settings->jpg_comp.COM_len < 0)
+               settings->jpg_comp.COM_len = 0;
+       if (settings->jpg_comp.COM_len > 60)
+               settings->jpg_comp.COM_len = 60;
+       if (err)
+               return -EINVAL;
+       return 0;
+}
+
+void
+zoran_open_init_params (struct zoran *zr)
+{
+       int i;
+
+       /* User must explicitly set a window */
+       zr->overlay_settings.is_set = 0;
+       zr->overlay_mask = NULL;
+       zr->overlay_active = ZORAN_FREE;
+
+       zr->v4l_memgrab_active = 0;
+       zr->v4l_overlay_active = 0;
+       zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+       zr->v4l_grab_seq = 0;
+       zr->v4l_settings.width = 192;
+       zr->v4l_settings.height = 144;
+       zr->v4l_settings.format = &zoran_formats[7];    /* YUY2 - YUV-4:2:2 packed */
+       zr->v4l_settings.bytesperline =
+           zr->v4l_settings.width *
+           ((zr->v4l_settings.format->depth + 7) / 8);
+
+       /* DMA ring stuff for V4L */
+       zr->v4l_pend_tail = 0;
+       zr->v4l_pend_head = 0;
+       zr->v4l_sync_tail = 0;
+       zr->v4l_buffers.active = ZORAN_FREE;
+       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+               zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       zr->v4l_buffers.allocated = 0;
+
+       for (i = 0; i < BUZ_MAX_FRAME; i++) {
+               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       zr->jpg_buffers.active = ZORAN_FREE;
+       zr->jpg_buffers.allocated = 0;
+       /* Set necessary params and call zoran_check_jpg_settings to set the defaults */
+       zr->jpg_settings.decimation = 1;
+       zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */
+       if (zr->card.type != BUZ)
+               zr->jpg_settings.odd_even = 1;
+       else
+               zr->jpg_settings.odd_even = 0;
+       zr->jpg_settings.jpg_comp.APPn = 0;
+       zr->jpg_settings.jpg_comp.APP_len = 0;  /* No APPn marker */
+       memset(zr->jpg_settings.jpg_comp.APP_data, 0,
+              sizeof(zr->jpg_settings.jpg_comp.APP_data));
+       zr->jpg_settings.jpg_comp.COM_len = 0;  /* No COM marker */
+       memset(zr->jpg_settings.jpg_comp.COM_data, 0,
+              sizeof(zr->jpg_settings.jpg_comp.COM_data));
+       zr->jpg_settings.jpg_comp.jpeg_markers =
+           JPEG_MARKER_DHT | JPEG_MARKER_DQT;
+       i = zoran_check_jpg_settings(zr, &zr->jpg_settings);
+       if (i)
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_open_init_params() internal error\n",
+                       ZR_DEVNAME(zr));
+
+       clear_interrupt_counters(zr);
+       zr->testing = 0;
+}
+
+static void __devinit
+test_interrupts (struct zoran *zr)
+{
+       DEFINE_WAIT(wait);
+       int timeout, icr;
+
+       clear_interrupt_counters(zr);
+
+       zr->testing = 1;
+       icr = btread(ZR36057_ICR);
+       btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
+       prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE);
+       timeout = schedule_timeout(HZ);
+       finish_wait(&zr->test_q, &wait);
+       btwrite(0, ZR36057_ICR);
+       btwrite(0x78000000, ZR36057_ISR);
+       zr->testing = 0;
+       dprintk(5, KERN_INFO "%s: Testing interrupts...\n", ZR_DEVNAME(zr));
+       if (timeout) {
+               dprintk(1, ": time spent: %d\n", 1 * HZ - timeout);
+       }
+       if (zr36067_debug > 1)
+               print_interrupts(zr);
+       btwrite(icr, ZR36057_ICR);
+}
+
+static int __devinit
+zr36057_init (struct zoran *zr)
+{
+       int j, err;
+       int two = 2;
+       int zero = 0;
+
+       dprintk(1,
+               KERN_INFO
+               "%s: zr36057_init() - initializing card[%d], zr=%p\n",
+               ZR_DEVNAME(zr), zr->id, zr);
+
+       /* default setup of all parameters which will persist between opens */
+       zr->user = 0;
+
+       init_waitqueue_head(&zr->v4l_capq);
+       init_waitqueue_head(&zr->jpg_capq);
+       init_waitqueue_head(&zr->test_q);
+       zr->jpg_buffers.allocated = 0;
+       zr->v4l_buffers.allocated = 0;
+
+       zr->buffer.base = (void *) vidmem;
+       zr->buffer.width = 0;
+       zr->buffer.height = 0;
+       zr->buffer.depth = 0;
+       zr->buffer.bytesperline = 0;
+
+       /* Avoid nonsense settings from user for default input/norm */
+       if (default_norm < VIDEO_MODE_PAL &&
+           default_norm > VIDEO_MODE_SECAM)
+               default_norm = VIDEO_MODE_PAL;
+       zr->norm = default_norm;
+       if (!(zr->timing = zr->card.tvn[zr->norm])) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n",
+                       ZR_DEVNAME(zr));
+               zr->norm = VIDEO_MODE_PAL;
+               zr->timing = zr->card.tvn[zr->norm];
+       }
+
+       if (default_input > zr->card.inputs-1) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: default_input value %d out of range (0-%d)\n",
+                       ZR_DEVNAME(zr), default_input, zr->card.inputs-1);
+               default_input = 0;
+       }
+       zr->input = default_input;
+
+       /* Should the following be reset at every open ? */
+       zr->hue = 32768;
+       zr->contrast = 32768;
+       zr->saturation = 32768;
+       zr->brightness = 32768;
+
+       /* default setup (will be repeated at every open) */
+       zoran_open_init_params(zr);
+
+       /* allocate memory *before* doing anything to the hardware
+        * in case allocation fails */
+       zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
+       zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+       if (!zr->stat_com || !zr->video_dev) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
+                       ZR_DEVNAME(zr));
+               err = -ENOMEM;
+               goto exit_free;
+       }
+       for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+               zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
+       }
+
+       /*
+        *   Now add the template and register the device unit.
+        */
+       memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
+       strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
+       err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
+       if (err < 0)
+               goto exit_unregister;
+
+       zoran_init_hardware(zr);
+       if (zr36067_debug > 2)
+               detect_guest_activity(zr);
+       test_interrupts(zr);
+       if (!pass_through) {
+               decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
+               encoder_command(zr, ENCODER_SET_INPUT, &two);
+       }
+
+       zr->zoran_proc = NULL;
+       zr->initialized = 1;
+       return 0;
+
+exit_unregister:
+       zoran_unregister_i2c(zr);
+exit_free:
+       kfree(zr->stat_com);
+       kfree(zr->video_dev);
+       return err;
+}
+
+static void
+zoran_release (struct zoran *zr)
+{
+       if (!zr->initialized)
+               goto exit_free;
+       /* unregister videocodec bus */
+       if (zr->codec) {
+               struct videocodec_master *master = zr->codec->master_data;
+
+               videocodec_detach(zr->codec);
+               kfree(master);
+       }
+       if (zr->vfe) {
+               struct videocodec_master *master = zr->vfe->master_data;
+
+               videocodec_detach(zr->vfe);
+               kfree(master);
+       }
+
+       /* unregister i2c bus */
+       zoran_unregister_i2c(zr);
+       /* disable PCI bus-mastering */
+       zoran_set_pci_master(zr, 0);
+       /* put chip into reset */
+       btwrite(0, ZR36057_SPGPPCR);
+       free_irq(zr->pci_dev->irq, zr);
+       /* unmap and free memory */
+       kfree(zr->stat_com);
+       zoran_proc_cleanup(zr);
+       iounmap(zr->zr36057_mem);
+       pci_disable_device(zr->pci_dev);
+       video_unregister_device(zr->video_dev);
+exit_free:
+       kfree(zr);
+}
+
+void
+zoran_vdev_release (struct video_device *vdev)
+{
+       kfree(vdev);
+}
+
+static struct videocodec_master * __devinit
+zoran_setup_videocodec (struct zoran *zr,
+                       int           type)
+{
+       struct videocodec_master *m = NULL;
+
+       m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL);
+       if (!m) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_setup_videocodec() - no memory\n",
+                       ZR_DEVNAME(zr));
+               return m;
+       }
+
+       /* magic and type are unused for master struct. Makes sense only at
+          codec structs.
+          In the past, .type were initialized to the old V4L1 .hardware
+          value, as VID_HARDWARE_ZR36067
+        */
+       m->magic = 0L;
+       m->type = 0;
+
+       m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
+       strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
+       m->data = zr;
+
+       switch (type)
+       {
+       case CODEC_TYPE_ZR36060:
+               m->readreg = zr36060_read;
+               m->writereg = zr36060_write;
+               m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE;
+               break;
+       case CODEC_TYPE_ZR36050:
+               m->readreg = zr36050_read;
+               m->writereg = zr36050_write;
+               m->flags |= CODEC_FLAG_JPEG;
+               break;
+       case CODEC_TYPE_ZR36016:
+               m->readreg = zr36016_read;
+               m->writereg = zr36016_write;
+               m->flags |= CODEC_FLAG_VFE;
+               break;
+       }
+
+       return m;
+}
+
+/*
+ *   Scan for a Buz card (actually for the PCI controller ZR36057),
+ *   request the irq and map the io memory
+ */
+static int __devinit
+find_zr36057 (void)
+{
+       unsigned char latency, need_latency;
+       struct zoran *zr;
+       struct pci_dev *dev = NULL;
+       int result;
+       struct videocodec_master *master_vfe = NULL;
+       struct videocodec_master *master_codec = NULL;
+       int card_num;
+       char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name;
+
+       zoran_num = 0;
+       while (zoran_num < BUZ_MAX &&
+              (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) {
+               card_num = card[zoran_num];
+               zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
+               if (!zr) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: find_zr36057() - kzalloc failed\n",
+                               ZORAN_NAME);
+                       continue;
+               }
+               zr->pci_dev = dev;
+               //zr->zr36057_mem = NULL;
+               zr->id = zoran_num;
+               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
+               spin_lock_init(&zr->spinlock);
+               mutex_init(&zr->resource_lock);
+               if (pci_enable_device(dev))
+                       goto zr_free_mem;
+               zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
+               pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
+                                    &zr->revision);
+               if (zr->revision < 2) {
+                       dprintk(1,
+                               KERN_INFO
+                               "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n",
+                               ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
+                               zr->zr36057_adr);
+
+                       if (card_num == -1) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - no card specified, please use the card=X insmod option\n",
+                                       ZR_DEVNAME(zr));
+                               goto zr_free_mem;
+                       }
+               } else {
+                       int i;
+                       unsigned short ss_vendor, ss_device;
+
+                       ss_vendor = zr->pci_dev->subsystem_vendor;
+                       ss_device = zr->pci_dev->subsystem_device;
+                       dprintk(1,
+                               KERN_INFO
+                               "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n",
+                               ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
+                               zr->zr36057_adr);
+                       dprintk(1,
+                               KERN_INFO
+                               "%s: subsystem vendor=0x%04x id=0x%04x\n",
+                               ZR_DEVNAME(zr), ss_vendor, ss_device);
+                       if (card_num == -1) {
+                               dprintk(3,
+                                       KERN_DEBUG
+                                       "%s: find_zr36057() - trying to autodetect card type\n",
+                                       ZR_DEVNAME(zr));
+                               for (i=0;i<NUM_CARDS;i++) {
+                                       if (ss_vendor == zoran_cards[i].vendor_id &&
+                                           ss_device == zoran_cards[i].device_id) {
+                                               dprintk(3,
+                                                       KERN_DEBUG
+                                                       "%s: find_zr36057() - card %s detected\n",
+                                                       ZR_DEVNAME(zr),
+                                                       zoran_cards[i].name);
+                                               card_num = i;
+                                               break;
+                                       }
+                               }
+                               if (i == NUM_CARDS) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: find_zr36057() - unknown card\n",
+                                               ZR_DEVNAME(zr));
+                                       goto zr_free_mem;
+                               }
+                       }
+               }
+
+               if (card_num < 0 || card_num >= NUM_CARDS) {
+                       dprintk(2,
+                               KERN_ERR
+                               "%s: find_zr36057() - invalid cardnum %d\n",
+                               ZR_DEVNAME(zr), card_num);
+                       goto zr_free_mem;
+               }
+
+               /* even though we make this a non pointer and thus
+                * theoretically allow for making changes to this struct
+                * on a per-individual card basis at runtime, this is
+                * strongly discouraged. This structure is intended to
+                * keep general card information, no settings or anything */
+               zr->card = zoran_cards[card_num];
+               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
+                        "%s[%u]", zr->card.name, zr->id);
+
+               zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000);
+               if (!zr->zr36057_mem) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: find_zr36057() - ioremap failed\n",
+                               ZR_DEVNAME(zr));
+                       goto zr_free_mem;
+               }
+
+               result = request_irq(zr->pci_dev->irq,
+                                    zoran_irq,
+                                    IRQF_SHARED | IRQF_DISABLED,
+                                    ZR_DEVNAME(zr),
+                                    (void *) zr);
+               if (result < 0) {
+                       if (result == -EINVAL) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - bad irq number or handler\n",
+                                       ZR_DEVNAME(zr));
+                       } else if (result == -EBUSY) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
+                                       ZR_DEVNAME(zr), zr->pci_dev->irq);
+                       } else {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - can't assign irq, error code %d\n",
+                                       ZR_DEVNAME(zr), result);
+                       }
+                       goto zr_unmap;
+               }
+
+               /* set PCI latency timer */
+               pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+                                    &latency);
+               need_latency = zr->revision > 1 ? 32 : 48;
+               if (latency != need_latency) {
+                       dprintk(2,
+                               KERN_INFO
+                               "%s: Changing PCI latency from %d to %d.\n",
+                               ZR_DEVNAME(zr), latency, need_latency);
+                       pci_write_config_byte(zr->pci_dev,
+                                             PCI_LATENCY_TIMER,
+                                             need_latency);
+               }
+
+               zr36057_restart(zr);
+               /* i2c */
+               dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
+                       ZR_DEVNAME(zr));
+
+               /* i2c decoder */
+               if (decoder[zr->id] != -1) {
+                       i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
+                       zr->card.i2c_decoder = decoder[zr->id];
+               } else if (zr->card.i2c_decoder != 0) {
+                       i2c_dec_name =
+                               i2cid_to_modulename(zr->card.i2c_decoder);
+               } else {
+                       i2c_dec_name = NULL;
+               }
+
+               if (i2c_dec_name) {
+                       if ((result = request_module(i2c_dec_name)) < 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load module %s: %d\n",
+                                       ZR_DEVNAME(zr), i2c_dec_name, result);
+                       }
+               }
+
+               /* i2c encoder */
+               if (encoder[zr->id] != -1) {
+                       i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
+                       zr->card.i2c_encoder = encoder[zr->id];
+               } else if (zr->card.i2c_encoder != 0) {
+                       i2c_enc_name =
+                               i2cid_to_modulename(zr->card.i2c_encoder);
+               } else {
+                       i2c_enc_name = NULL;
+               }
+
+               if (i2c_enc_name) {
+                       if ((result = request_module(i2c_enc_name)) < 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load module %s: %d\n",
+                                       ZR_DEVNAME(zr), i2c_enc_name, result);
+                       }
+               }
+
+               if (zoran_register_i2c(zr) < 0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: find_zr36057() - can't initialize i2c bus\n",
+                               ZR_DEVNAME(zr));
+                       goto zr_free_irq;
+               }
+
+               dprintk(2,
+                       KERN_INFO "%s: Initializing videocodec bus...\n",
+                       ZR_DEVNAME(zr));
+
+               if (zr->card.video_codec != 0 &&
+                   (codec_name =
+                    codecid_to_modulename(zr->card.video_codec)) != NULL) {
+                       if ((result = request_module(codec_name)) < 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load modules %s: %d\n",
+                                       ZR_DEVNAME(zr), codec_name, result);
+                       }
+               }
+               if (zr->card.video_vfe != 0 &&
+                   (vfe_name =
+                    codecid_to_modulename(zr->card.video_vfe)) != NULL) {
+                       if ((result = request_module(vfe_name)) < 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load modules %s: %d\n",
+                                       ZR_DEVNAME(zr), vfe_name, result);
+                       }
+               }
+
+               /* reset JPEG codec */
+               jpeg_codec_sleep(zr, 1);
+               jpeg_codec_reset(zr);
+               /* video bus enabled */
+               /* display codec revision */
+               if (zr->card.video_codec != 0) {
+                       master_codec = zoran_setup_videocodec(zr,
+                                                             zr->card.video_codec);
+                       if (!master_codec)
+                               goto zr_unreg_i2c;
+                       zr->codec = videocodec_attach(master_codec);
+                       if (!zr->codec) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - no codec found\n",
+                                       ZR_DEVNAME(zr));
+                               goto zr_free_codec;
+                       }
+                       if (zr->codec->type != zr->card.video_codec) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - wrong codec\n",
+                                       ZR_DEVNAME(zr));
+                               goto zr_detach_codec;
+                       }
+               }
+               if (zr->card.video_vfe != 0) {
+                       master_vfe = zoran_setup_videocodec(zr,
+                                                           zr->card.video_vfe);
+                       if (!master_vfe)
+                               goto zr_detach_codec;
+                       zr->vfe = videocodec_attach(master_vfe);
+                       if (!zr->vfe) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() - no VFE found\n",
+                                       ZR_DEVNAME(zr));
+                               goto zr_free_vfe;
+                       }
+                       if (zr->vfe->type != zr->card.video_vfe) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: find_zr36057() = wrong VFE\n",
+                                       ZR_DEVNAME(zr));
+                               goto zr_detach_vfe;
+                       }
+               }
+               /* Success so keep the pci_dev referenced */
+               pci_dev_get(zr->pci_dev);
+               zoran[zoran_num++] = zr;
+               continue;
+
+               // Init errors
+             zr_detach_vfe:
+               videocodec_detach(zr->vfe);
+             zr_free_vfe:
+               kfree(master_vfe);
+             zr_detach_codec:
+               videocodec_detach(zr->codec);
+             zr_free_codec:
+               kfree(master_codec);
+             zr_unreg_i2c:
+               zoran_unregister_i2c(zr);
+             zr_free_irq:
+               btwrite(0, ZR36057_SPGPPCR);
+               free_irq(zr->pci_dev->irq, zr);
+             zr_unmap:
+               iounmap(zr->zr36057_mem);
+             zr_free_mem:
+               kfree(zr);
+               continue;
+       }
+       if (dev)        /* Clean up ref count on early exit */
+               pci_dev_put(dev);
+
+       if (zoran_num == 0) {
+               dprintk(1, KERN_INFO "No known MJPEG cards found.\n");
+       }
+       return zoran_num;
+}
+
+static int __init
+init_dc10_cards (void)
+{
+       int i;
+
+       memset(zoran, 0, sizeof(zoran));
+       printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
+              MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
+
+       /* Look for cards */
+       if (find_zr36057() < 0) {
+               return -EIO;
+       }
+       if (zoran_num == 0)
+               return -ENODEV;
+       dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME,
+               zoran_num);
+       /* check the parameters we have been given, adjust if necessary */
+       if (v4l_nbufs < 2)
+               v4l_nbufs = 2;
+       if (v4l_nbufs > VIDEO_MAX_FRAME)
+               v4l_nbufs = VIDEO_MAX_FRAME;
+       /* The user specfies the in KB, we want them in byte
+        * (and page aligned) */
+       v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
+       if (v4l_bufsize < 32768)
+               v4l_bufsize = 32768;
+       /* 2 MB is arbitrary but sufficient for the maximum possible images */
+       if (v4l_bufsize > 2048 * 1024)
+               v4l_bufsize = 2048 * 1024;
+       if (jpg_nbufs < 4)
+               jpg_nbufs = 4;
+       if (jpg_nbufs > BUZ_MAX_FRAME)
+               jpg_nbufs = BUZ_MAX_FRAME;
+       jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
+       if (jpg_bufsize < 8192)
+               jpg_bufsize = 8192;
+       if (jpg_bufsize > (512 * 1024))
+               jpg_bufsize = 512 * 1024;
+       /* Use parameter for vidmem or try to find a video card */
+       if (vidmem) {
+               dprintk(1,
+                       KERN_INFO
+                       "%s: Using supplied video memory base address @ 0x%lx\n",
+                       ZORAN_NAME, vidmem);
+       }
+
+       /* random nonsense */
+       dprintk(6, KERN_DEBUG "Jotti is een held!\n");
+
+       /* some mainboards might not do PCI-PCI data transfer well */
+       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: chipset does not support reliable PCI-PCI DMA\n",
+                       ZORAN_NAME);
+       }
+
+       /* take care of Natoma chipset and a revision 1 zr36057 */
+       for (i = 0; i < zoran_num; i++) {
+               struct zoran *zr = zoran[i];
+
+               if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
+                       zr->jpg_buffers.need_contiguous = 1;
+                       dprintk(1,
+                               KERN_INFO
+                               "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
+                               ZR_DEVNAME(zr));
+               }
+
+               if (zr36057_init(zr) < 0) {
+                       for (i = 0; i < zoran_num; i++)
+                               zoran_release(zoran[i]);
+                       return -EIO;
+               }
+               zoran_proc_init(zr);
+       }
+
+       return 0;
+}
+
+static void __exit
+unload_dc10_cards (void)
+{
+       int i;
+
+       for (i = 0; i < zoran_num; i++)
+               zoran_release(zoran[i]);
+}
+
+module_init(init_dc10_cards);
+module_exit(unload_dc10_cards);
diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h
new file mode 100644 (file)
index 0000000..e4dc9d2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ZORAN_CARD_H__
+#define __ZORAN_CARD_H__
+
+extern int zr36067_debug;
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (zr36067_debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* Anybody who uses more than four? */
+#define BUZ_MAX 4
+extern int zoran_num;
+extern struct zoran *zoran[BUZ_MAX];
+
+extern struct video_device zoran_template;
+
+extern int zoran_check_jpg_settings(struct zoran *zr,
+                                   struct zoran_jpg_settings *settings);
+extern void zoran_open_init_params(struct zoran *zr);
+extern void zoran_vdev_release(struct video_device *vdev);
+
+void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
+
+#endif                         /* __ZORAN_CARD_H__ */
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
new file mode 100644 (file)
index 0000000..5d948ff
--- /dev/null
@@ -0,0 +1,1747 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles device access (PCI/I2C/codec/...)
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+
+#include <linux/pci.h>
+#include <linux/video_decoder.h>
+#include <linux/video_encoder.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \
+                  ZR36057_ISR_GIRQ1 | \
+                  ZR36057_ISR_JPEGRepIRQ )
+
+static int lml33dpath;         /* default = 0
+                                * 1 will use digital path in capture
+                                * mode instead of analog. It can be
+                                * used for picture adjustments using
+                                * tool like xawtv while watching image
+                                * on TV monitor connected to the output.
+                                * However, due to absence of 75 Ohm
+                                * load on Bt819 input, there will be
+                                * some image imperfections */
+
+module_param(lml33dpath, bool, 0644);
+MODULE_PARM_DESC(lml33dpath,
+                "Use digital path capture mode (on LML33 cards)");
+
+static void
+zr36057_init_vfe (struct zoran *zr);
+
+/*
+ * General Purpose I/O and Guest bus access
+ */
+
+/*
+ * This is a bit tricky. When a board lacks a GPIO function, the corresponding
+ * GPIO bit number in the card_info structure is set to 0.
+ */
+
+void
+GPIO (struct zoran *zr,
+      int           bit,
+      unsigned int  value)
+{
+       u32 reg;
+       u32 mask;
+
+       /* Make sure the bit number is legal
+        * A bit number of -1 (lacking) gives a mask of 0,
+        * making it harmless */
+       mask = (1 << (24 + bit)) & 0xff000000;
+       reg = btread(ZR36057_GPPGCR1) & ~mask;
+       if (value) {
+               reg |= mask;
+       }
+       btwrite(reg, ZR36057_GPPGCR1);
+       udelay(1);
+}
+
+/*
+ * Wait til post office is no longer busy
+ */
+
+int
+post_office_wait (struct zoran *zr)
+{
+       u32 por;
+
+//      while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {
+       while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) {
+               /* wait for something to happen */
+       }
+       if ((por & ZR36057_POR_POTime) && !zr->card.gws_not_connected) {
+               /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */
+               dprintk(1, KERN_INFO "%s: pop timeout %08x\n", ZR_DEVNAME(zr),
+                       por);
+               return -1;
+       }
+
+       return 0;
+}
+
+int
+post_office_write (struct zoran *zr,
+                  unsigned int  guest,
+                  unsigned int  reg,
+                  unsigned int  value)
+{
+       u32 por;
+
+       por =
+           ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) |
+           ((reg & 7) << 16) | (value & 0xFF);
+       btwrite(por, ZR36057_POR);
+
+       return post_office_wait(zr);
+}
+
+int
+post_office_read (struct zoran *zr,
+                 unsigned int  guest,
+                 unsigned int  reg)
+{
+       u32 por;
+
+       por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);
+       btwrite(por, ZR36057_POR);
+       if (post_office_wait(zr) < 0) {
+               return -1;
+       }
+
+       return btread(ZR36057_POR) & 0xFF;
+}
+
+/*
+ * detect guests
+ */
+
+static void
+dump_guests (struct zoran *zr)
+{
+       if (zr36067_debug > 2) {
+               int i, guest[8];
+
+               for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
+                       guest[i] = post_office_read(zr, i, 0);
+               }
+
+               printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
+
+               for (i = 1; i < 8; i++) {
+                       printk(" 0x%02x", guest[i]);
+               }
+               printk("\n");
+       }
+}
+
+static inline unsigned long
+get_time (void)
+{
+       struct timeval tv;
+
+       do_gettimeofday(&tv);
+       return (1000000 * tv.tv_sec + tv.tv_usec);
+}
+
+void
+detect_guest_activity (struct zoran *zr)
+{
+       int timeout, i, j, res, guest[8], guest0[8], change[8][3];
+       unsigned long t0, t1;
+
+       dump_guests(zr);
+       printk(KERN_INFO "%s: Detecting guests activity, please wait...\n",
+              ZR_DEVNAME(zr));
+       for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
+               guest0[i] = guest[i] = post_office_read(zr, i, 0);
+       }
+
+       timeout = 0;
+       j = 0;
+       t0 = get_time();
+       while (timeout < 10000) {
+               udelay(10);
+               timeout++;
+               for (i = 1; (i < 8) && (j < 8); i++) {
+                       res = post_office_read(zr, i, 0);
+                       if (res != guest[i]) {
+                               t1 = get_time();
+                               change[j][0] = (t1 - t0);
+                               t0 = t1;
+                               change[j][1] = i;
+                               change[j][2] = res;
+                               j++;
+                               guest[i] = res;
+                       }
+               }
+               if (j >= 8)
+                       break;
+       }
+       printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
+
+       for (i = 1; i < 8; i++) {
+               printk(" 0x%02x", guest0[i]);
+       }
+       printk("\n");
+       if (j == 0) {
+               printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr));
+               return;
+       }
+       for (i = 0; i < j; i++) {
+               printk(KERN_INFO "%s: %6d: %d => 0x%02x\n", ZR_DEVNAME(zr),
+                      change[i][0], change[i][1], change[i][2]);
+       }
+}
+
+/*
+ * JPEG Codec access
+ */
+
+void
+jpeg_codec_sleep (struct zoran *zr,
+                 int           sleep)
+{
+       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
+       if (!sleep) {
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: jpeg_codec_sleep() - wake GPIO=0x%08x\n",
+                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
+               udelay(500);
+       } else {
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: jpeg_codec_sleep() - sleep GPIO=0x%08x\n",
+                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
+               udelay(2);
+       }
+}
+
+int
+jpeg_codec_reset (struct zoran *zr)
+{
+       /* Take the codec out of sleep */
+       jpeg_codec_sleep(zr, 0);
+
+       if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) {
+               post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0,
+                                 0);
+               udelay(2);
+       } else {
+               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
+               udelay(2);
+               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
+               udelay(2);
+       }
+
+       return 0;
+}
+
+/*
+ *   Set the registers for the size we have specified. Don't bother
+ *   trying to understand this without the ZR36057 manual in front of
+ *   you [AC].
+ *
+ *   PS: The manual is free for download in .pdf format from
+ *   www.zoran.com - nicely done those folks.
+ */
+
+static void
+zr36057_adjust_vfe (struct zoran          *zr,
+                   enum zoran_codec_mode  mode)
+{
+       u32 reg;
+
+       switch (mode) {
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               reg = btread(ZR36057_VFEHCR);
+               if ((reg & (1 << 10)) && zr->card.type != LML33R10) {
+                       reg += ((1 << 10) | 1);
+               }
+               btwrite(reg, ZR36057_VFEHCR);
+               break;
+       case BUZ_MODE_MOTION_COMPRESS:
+       case BUZ_MODE_IDLE:
+       default:
+               if (zr->norm == VIDEO_MODE_NTSC ||
+                   (zr->card.type == LML33R10 &&
+                    zr->norm == VIDEO_MODE_PAL))
+                       btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               else
+                       btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               reg = btread(ZR36057_VFEHCR);
+               if (!(reg & (1 << 10)) && zr->card.type != LML33R10) {
+                       reg -= ((1 << 10) | 1);
+               }
+               btwrite(reg, ZR36057_VFEHCR);
+               break;
+       }
+}
+
+/*
+ * set geometry
+ */
+
+static void
+zr36057_set_vfe (struct zoran              *zr,
+                int                        video_width,
+                int                        video_height,
+                const struct zoran_format *format)
+{
+       struct tvnorm *tvn;
+       unsigned HStart, HEnd, VStart, VEnd;
+       unsigned DispMode;
+       unsigned VidWinWid, VidWinHt;
+       unsigned hcrop1, hcrop2, vcrop1, vcrop2;
+       unsigned Wa, We, Ha, He;
+       unsigned X, Y, HorDcm, VerDcm;
+       u32 reg;
+       unsigned mask_line_size;
+
+       tvn = zr->timing;
+
+       Wa = tvn->Wa;
+       Ha = tvn->Ha;
+
+       dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
+               ZR_DEVNAME(zr), video_width, video_height);
+
+       if (zr->norm != VIDEO_MODE_PAL &&
+           zr->norm != VIDEO_MODE_NTSC &&
+           zr->norm != VIDEO_MODE_SECAM) {
+               dprintk(1,
+                       KERN_ERR "%s: set_vfe() - norm = %d not valid\n",
+                       ZR_DEVNAME(zr), zr->norm);
+               return;
+       }
+       if (video_width < BUZ_MIN_WIDTH ||
+           video_height < BUZ_MIN_HEIGHT ||
+           video_width > Wa || video_height > Ha) {
+               dprintk(1, KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n",
+                       ZR_DEVNAME(zr), video_width, video_height);
+               return;
+       }
+
+       /**** zr36057 ****/
+
+       /* horizontal */
+       VidWinWid = video_width;
+       X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa);
+       We = (VidWinWid * 64) / X;
+       HorDcm = 64 - X;
+       hcrop1 = 2 * ((tvn->Wa - We) / 4);
+       hcrop2 = tvn->Wa - We - hcrop1;
+       HStart = tvn->HStart ? tvn->HStart : 1;
+       /* (Ronald) Original comment:
+        * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+"
+        * this is false. It inverses chroma values on the LML33R10 (so Cr
+        * suddenly is shown as Cb and reverse, really cool effect if you
+        * want to see blue faces, not useful otherwise). So don't use |1.
+        * However, the DC10 has '0' as HStart, but does need |1, so we
+        * use a dirty check...
+        */
+       HEnd = HStart + tvn->Wa - 1;
+       HStart += hcrop1;
+       HEnd -= hcrop2;
+       reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)
+           | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);
+       if (zr->card.vfe_pol.hsync_pol)
+               reg |= ZR36057_VFEHCR_HSPol;
+       btwrite(reg, ZR36057_VFEHCR);
+
+       /* Vertical */
+       DispMode = !(video_height > BUZ_MAX_HEIGHT / 2);
+       VidWinHt = DispMode ? video_height : video_height / 2;
+       Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha);
+       He = (VidWinHt * 64) / Y;
+       VerDcm = 64 - Y;
+       vcrop1 = (tvn->Ha / 2 - He) / 2;
+       vcrop2 = tvn->Ha / 2 - He - vcrop1;
+       VStart = tvn->VStart;
+       VEnd = VStart + tvn->Ha / 2;    // - 1; FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP
+       VStart += vcrop1;
+       VEnd -= vcrop2;
+       reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)
+           | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);
+       if (zr->card.vfe_pol.vsync_pol)
+               reg |= ZR36057_VFEVCR_VSPol;
+       btwrite(reg, ZR36057_VFEVCR);
+
+       /* scaler and pixel format */
+       reg = 0;
+       reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
+       reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
+       reg |= (DispMode << ZR36057_VFESPFR_DispMode);
+       /* RJ: I don't know, why the following has to be the opposite
+        * of the corresponding ZR36060 setting, but only this way
+        * we get the correct colors when uncompressing to the screen  */
+       //reg |= ZR36057_VFESPFR_VCLKPol; /**/
+       /* RJ: Don't know if that is needed for NTSC also */
+       if (zr->norm != VIDEO_MODE_NTSC)
+               reg |= ZR36057_VFESPFR_ExtFl;   // NEEDED!!!!!!! Wolfgang
+       reg |= ZR36057_VFESPFR_TopField;
+       if (HorDcm >= 48) {
+               reg |= 3 << ZR36057_VFESPFR_HFilter;    /* 5 tap filter */
+       } else if (HorDcm >= 32) {
+               reg |= 2 << ZR36057_VFESPFR_HFilter;    /* 4 tap filter */
+       } else if (HorDcm >= 16) {
+               reg |= 1 << ZR36057_VFESPFR_HFilter;    /* 3 tap filter */
+       }
+       reg |= format->vfespfr;
+       btwrite(reg, ZR36057_VFESPFR);
+
+       /* display configuration */
+       reg = (16 << ZR36057_VDCR_MinPix)
+           | (VidWinHt << ZR36057_VDCR_VidWinHt)
+           | (VidWinWid << ZR36057_VDCR_VidWinWid);
+       if (pci_pci_problems & PCIPCI_TRITON)
+               // || zr->revision < 1) // Revision 1 has also Triton support
+               reg &= ~ZR36057_VDCR_Triton;
+       else
+               reg |= ZR36057_VDCR_Triton;
+       btwrite(reg, ZR36057_VDCR);
+
+       /* (Ronald) don't write this if overlay_mask = NULL */
+       if (zr->overlay_mask) {
+               /* Write overlay clipping mask data, but don't enable overlay clipping */
+               /* RJ: since this makes only sense on the screen, we use
+                * zr->overlay_settings.width instead of video_width */
+
+               mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
+               reg = virt_to_bus(zr->overlay_mask);
+               btwrite(reg, ZR36057_MMTR);
+               reg = virt_to_bus(zr->overlay_mask + mask_line_size);
+               btwrite(reg, ZR36057_MMBR);
+               reg =
+                   mask_line_size - (zr->overlay_settings.width +
+                                     31) / 32;
+               if (DispMode == 0)
+                       reg += mask_line_size;
+               reg <<= ZR36057_OCR_MaskStride;
+               btwrite(reg, ZR36057_OCR);
+       }
+
+       zr36057_adjust_vfe(zr, zr->codec_mode);
+}
+
+/*
+ * Switch overlay on or off
+ */
+
+void
+zr36057_overlay (struct zoran *zr,
+                int           on)
+{
+       u32 reg;
+
+       if (on) {
+               /* do the necessary settings ... */
+               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);       /* switch it off first */
+
+               zr36057_set_vfe(zr,
+                               zr->overlay_settings.width,
+                               zr->overlay_settings.height,
+                               zr->overlay_settings.format);
+
+               /* Start and length of each line MUST be 4-byte aligned.
+                * This should be allready checked before the call to this routine.
+                * All error messages are internal driver checking only! */
+
+               /* video display top and bottom registers */
+               reg = (long) zr->buffer.base +
+                   zr->overlay_settings.x *
+                   ((zr->overlay_settings.format->depth + 7) / 8) +
+                   zr->overlay_settings.y *
+                   zr->buffer.bytesperline;
+               btwrite(reg, ZR36057_VDTR);
+               if (reg & 3)
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zr36057_overlay() - video_address not aligned\n",
+                               ZR_DEVNAME(zr));
+               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
+                       reg += zr->buffer.bytesperline;
+               btwrite(reg, ZR36057_VDBR);
+
+               /* video stride, status, and frame grab register */
+               reg = zr->buffer.bytesperline -
+                   zr->overlay_settings.width *
+                   ((zr->overlay_settings.format->depth + 7) / 8);
+               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
+                       reg += zr->buffer.bytesperline;
+               if (reg & 3)
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zr36057_overlay() - video_stride not aligned\n",
+                               ZR_DEVNAME(zr));
+               reg = (reg << ZR36057_VSSFGR_DispStride);
+               reg |= ZR36057_VSSFGR_VidOvf;   /* clear overflow status */
+               btwrite(reg, ZR36057_VSSFGR);
+
+               /* Set overlay clipping */
+               if (zr->overlay_settings.clipcount > 0)
+                       btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);
+
+               /* ... and switch it on */
+               btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);
+       } else {
+               /* Switch it off */
+               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
+       }
+}
+
+/*
+ * The overlay mask has one bit for each pixel on a scan line,
+ *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
+ */
+
+void
+write_overlay_mask (struct file       *file,
+                   struct video_clip *vp,
+                   int                count)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
+       u32 *mask;
+       int x, y, width, height;
+       unsigned i, j, k;
+       u32 reg;
+
+       /* fill mask with one bits */
+       memset(fh->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);
+       reg = 0;
+
+       for (i = 0; i < count; ++i) {
+               /* pick up local copy of clip */
+               x = vp[i].x;
+               y = vp[i].y;
+               width = vp[i].width;
+               height = vp[i].height;
+
+               /* trim clips that extend beyond the window */
+               if (x < 0) {
+                       width += x;
+                       x = 0;
+               }
+               if (y < 0) {
+                       height += y;
+                       y = 0;
+               }
+               if (x + width > fh->overlay_settings.width) {
+                       width = fh->overlay_settings.width - x;
+               }
+               if (y + height > fh->overlay_settings.height) {
+                       height = fh->overlay_settings.height - y;
+               }
+
+               /* ignore degenerate clips */
+               if (height <= 0) {
+                       continue;
+               }
+               if (width <= 0) {
+                       continue;
+               }
+
+               /* apply clip for each scan line */
+               for (j = 0; j < height; ++j) {
+                       /* reset bit for each pixel */
+                       /* this can be optimized later if need be */
+                       mask = fh->overlay_mask + (y + j) * mask_line_size;
+                       for (k = 0; k < width; ++k) {
+                               mask[(x + k) / 32] &=
+                                   ~((u32) 1 << (x + k) % 32);
+                       }
+               }
+       }
+}
+
+/* Enable/Disable uncompressed memory grabbing of the 36057 */
+
+void
+zr36057_set_memgrab (struct zoran *zr,
+                    int           mode)
+{
+       if (mode) {
+               /* We only check SnapShot and not FrameGrab here.  SnapShot==1
+                * means a capture is already in progress, but FrameGrab==1
+                * doesn't necessary mean that.  It's more correct to say a 1
+                * to 0 transition indicates a capture completed.  If a
+                * capture is pending when capturing is tuned off, FrameGrab
+                * will be stuck at 1 until capturing is turned back on.
+                */
+               if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot)
+                       dprintk(1,
+                               KERN_WARNING
+                               "%s: zr36057_set_memgrab(1) with SnapShot on!?\n",
+                               ZR_DEVNAME(zr));
+
+               /* switch on VSync interrupts */
+               btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
+               btor(zr->card.vsync_int, ZR36057_ICR);  // SW
+
+               /* enable SnapShot */
+               btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
+
+               /* Set zr36057 video front end  and enable video */
+               zr36057_set_vfe(zr, zr->v4l_settings.width,
+                               zr->v4l_settings.height,
+                               zr->v4l_settings.format);
+
+               zr->v4l_memgrab_active = 1;
+       } else {
+               /* switch off VSync interrupts */
+               btand(~zr->card.vsync_int, ZR36057_ICR);        // SW
+
+               zr->v4l_memgrab_active = 0;
+               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+
+               /* reenable grabbing to screen if it was running */
+               if (zr->v4l_overlay_active) {
+                       zr36057_overlay(zr, 1);
+               } else {
+                       btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
+                       btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
+               }
+       }
+}
+
+int
+wait_grab_pending (struct zoran *zr)
+{
+       unsigned long flags;
+
+       /* wait until all pending grabs are finished */
+
+       if (!zr->v4l_memgrab_active)
+               return 0;
+
+       wait_event_interruptible(zr->v4l_capq,
+                       (zr->v4l_pend_tail == zr->v4l_pend_head));
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+       zr36057_set_memgrab(zr, 0);
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *  Set up the Buz-specific MJPEG part                                       *
+ *                                                                           *
+ *****************************************************************************/
+
+static inline void
+set_frame (struct zoran *zr,
+          int           val)
+{
+       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
+}
+
+static void
+set_videobus_dir (struct zoran *zr,
+                 int           val)
+{
+       switch (zr->card.type) {
+       case LML33:
+       case LML33R10:
+               if (lml33dpath == 0)
+                       GPIO(zr, 5, val);
+               else
+                       GPIO(zr, 5, 1);
+               break;
+       default:
+               GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
+                    zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
+               break;
+       }
+}
+
+static void
+init_jpeg_queue (struct zoran *zr)
+{
+       int i;
+
+       /* re-initialize DMA ring stuff */
+       zr->jpg_que_head = 0;
+       zr->jpg_dma_head = 0;
+       zr->jpg_dma_tail = 0;
+       zr->jpg_que_tail = 0;
+       zr->jpg_seq_num = 0;
+       zr->JPEG_error = 0;
+       zr->num_errors = 0;
+       zr->jpg_err_seq = 0;
+       zr->jpg_err_shift = 0;
+       zr->jpg_queued_num = 0;
+       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
+               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       for (i = 0; i < BUZ_NUM_STAT_COM; i++) {
+               zr->stat_com[i] = cpu_to_le32(1);       /* mark as unavailable to zr36057 */
+       }
+}
+
+static void
+zr36057_set_jpg (struct zoran          *zr,
+                enum zoran_codec_mode  mode)
+{
+       struct tvnorm *tvn;
+       u32 reg;
+
+       tvn = zr->timing;
+
+       /* assert P_Reset, disable code transfer, deassert Active */
+       btwrite(0, ZR36057_JPC);
+
+       /* MJPEG compression mode */
+       switch (mode) {
+
+       case BUZ_MODE_MOTION_COMPRESS:
+       default:
+               reg = ZR36057_JMC_MJPGCmpMode;
+               break;
+
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               reg = ZR36057_JMC_MJPGExpMode;
+               reg |= ZR36057_JMC_SyncMstr;
+               /* RJ: The following is experimental - improves the output to screen */
+               //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
+               break;
+
+       case BUZ_MODE_STILL_COMPRESS:
+               reg = ZR36057_JMC_JPGCmpMode;
+               break;
+
+       case BUZ_MODE_STILL_DECOMPRESS:
+               reg = ZR36057_JMC_JPGExpMode;
+               break;
+
+       }
+       reg |= ZR36057_JMC_JPG;
+       if (zr->jpg_settings.field_per_buff == 1)
+               reg |= ZR36057_JMC_Fld_per_buff;
+       btwrite(reg, ZR36057_JMC);
+
+       /* vertical */
+       btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR);
+       reg = (6 << ZR36057_VSP_VsyncSize) |
+             (tvn->Ht << ZR36057_VSP_FrmTot);
+       btwrite(reg, ZR36057_VSP);
+       reg = ((zr->jpg_settings.img_y + tvn->VStart) << ZR36057_FVAP_NAY) |
+             (zr->jpg_settings.img_height << ZR36057_FVAP_PAY);
+       btwrite(reg, ZR36057_FVAP);
+
+       /* horizontal */
+       if (zr->card.vfe_pol.hsync_pol)
+               btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
+       else
+               btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
+       reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) |
+             (tvn->Wt << ZR36057_HSP_LineTot);
+       btwrite(reg, ZR36057_HSP);
+       reg = ((zr->jpg_settings.img_x +
+               tvn->HStart + 4) << ZR36057_FHAP_NAX) |
+             (zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
+       btwrite(reg, ZR36057_FHAP);
+
+       /* field process parameters */
+       if (zr->jpg_settings.odd_even)
+               reg = ZR36057_FPP_Odd_Even;
+       else
+               reg = 0;
+
+       btwrite(reg, ZR36057_FPP);
+
+       /* Set proper VCLK Polarity, else colors will be wrong during playback */
+       //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
+
+       /* code base address */
+       reg = virt_to_bus(zr->stat_com);
+       btwrite(reg, ZR36057_JCBA);
+
+       /* FIFO threshold (FIFO is 160. double words) */
+       /* NOTE: decimal values here */
+       switch (mode) {
+
+       case BUZ_MODE_STILL_COMPRESS:
+       case BUZ_MODE_MOTION_COMPRESS:
+               if (zr->card.type != BUZ)
+                       reg = 140;
+               else
+                       reg = 60;
+               break;
+
+       case BUZ_MODE_STILL_DECOMPRESS:
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               reg = 20;
+               break;
+
+       default:
+               reg = 80;
+               break;
+
+       }
+       btwrite(reg, ZR36057_JCFT);
+       zr36057_adjust_vfe(zr, mode);
+
+}
+
+void
+print_interrupts (struct zoran *zr)
+{
+       int res, noerr = 0;
+
+       printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr));
+       if ((res = zr->field_counter) < -1 || res > 1) {
+               printk(" FD:%d", res);
+       }
+       if ((res = zr->intr_counter_GIRQ1) != 0) {
+               printk(" GIRQ1:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_GIRQ0) != 0) {
+               printk(" GIRQ0:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_CodRepIRQ) != 0) {
+               printk(" CodRepIRQ:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
+               printk(" JPEGRepIRQ:%d", res);
+               noerr++;
+       }
+       if (zr->JPEG_max_missed) {
+               printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
+                      zr->JPEG_min_missed);
+       }
+       if (zr->END_event_missed) {
+               printk(" ENDs missed: %d", zr->END_event_missed);
+       }
+       //if (zr->jpg_queued_num) {
+       printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
+              zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
+       //}
+       if (!noerr) {
+               printk(": no interrupts detected.");
+       }
+       printk("\n");
+}
+
+void
+clear_interrupt_counters (struct zoran *zr)
+{
+       zr->intr_counter_GIRQ1 = 0;
+       zr->intr_counter_GIRQ0 = 0;
+       zr->intr_counter_CodRepIRQ = 0;
+       zr->intr_counter_JPEGRepIRQ = 0;
+       zr->field_counter = 0;
+       zr->IRQ1_in = 0;
+       zr->IRQ1_out = 0;
+       zr->JPEG_in = 0;
+       zr->JPEG_out = 0;
+       zr->JPEG_0 = 0;
+       zr->JPEG_1 = 0;
+       zr->END_event_missed = 0;
+       zr->JPEG_missed = 0;
+       zr->JPEG_max_missed = 0;
+       zr->JPEG_min_missed = 0x7fffffff;
+}
+
+static u32
+count_reset_interrupt (struct zoran *zr)
+{
+       u32 isr;
+
+       if ((isr = btread(ZR36057_ISR) & 0x78000000)) {
+               if (isr & ZR36057_ISR_GIRQ1) {
+                       btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
+                       zr->intr_counter_GIRQ1++;
+               }
+               if (isr & ZR36057_ISR_GIRQ0) {
+                       btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
+                       zr->intr_counter_GIRQ0++;
+               }
+               if (isr & ZR36057_ISR_CodRepIRQ) {
+                       btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR);
+                       zr->intr_counter_CodRepIRQ++;
+               }
+               if (isr & ZR36057_ISR_JPEGRepIRQ) {
+                       btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR);
+                       zr->intr_counter_JPEGRepIRQ++;
+               }
+       }
+       return isr;
+}
+
+void
+jpeg_start (struct zoran *zr)
+{
+       int reg;
+
+       zr->frame_num = 0;
+
+       /* deassert P_reset, disable code transfer, deassert Active */
+       btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC);
+       /* stop flushing the internal code buffer */
+       btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
+       /* enable code transfer */
+       btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC);
+
+       /* clear IRQs */
+       btwrite(IRQ_MASK, ZR36057_ISR);
+       /* enable the JPEG IRQs */
+       btwrite(zr->card.jpeg_int |
+                       ZR36057_ICR_JPEGRepIRQ |
+                       ZR36057_ICR_IntPinEn,
+               ZR36057_ICR);
+
+       set_frame(zr, 0);       // \FRAME
+
+       /* set the JPEG codec guest ID */
+       reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPEGuestID) |
+              (0 << ZR36057_JCGI_JPEGuestReg);
+       btwrite(reg, ZR36057_JCGI);
+
+       if (zr->card.video_vfe == CODEC_TYPE_ZR36016 &&
+           zr->card.video_codec == CODEC_TYPE_ZR36050) {
+               /* Enable processing on the ZR36016 */
+               if (zr->vfe)
+                       zr36016_write(zr->vfe, 0, 1);
+
+               /* load the address of the GO register in the ZR36050 latch */
+               post_office_write(zr, 0, 0, 0);
+       }
+
+       /* assert Active */
+       btor(ZR36057_JPC_Active, ZR36057_JPC);
+
+       /* enable the Go generation */
+       btor(ZR36057_JMC_Go_en, ZR36057_JMC);
+       udelay(30);
+
+       set_frame(zr, 1);       // /FRAME
+
+       dprintk(3, KERN_DEBUG "%s: jpeg_start\n", ZR_DEVNAME(zr));
+}
+
+void
+zr36057_enable_jpg (struct zoran          *zr,
+                   enum zoran_codec_mode  mode)
+{
+       static int zero;
+       static int one = 1;
+       struct vfe_settings cap;
+       int field_size =
+           zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
+
+       zr->codec_mode = mode;
+
+       cap.x = zr->jpg_settings.img_x;
+       cap.y = zr->jpg_settings.img_y;
+       cap.width = zr->jpg_settings.img_width;
+       cap.height = zr->jpg_settings.img_height;
+       cap.decimation =
+           zr->jpg_settings.HorDcm | (zr->jpg_settings.VerDcm << 8);
+       cap.quality = zr->jpg_settings.jpg_comp.quality;
+
+       switch (mode) {
+
+       case BUZ_MODE_MOTION_COMPRESS: {
+               struct jpeg_app_marker app;
+               struct jpeg_com_marker com;
+
+               /* In motion compress mode, the decoder output must be enabled, and
+                * the video bus direction set to input.
+                */
+               set_videobus_dir(zr, 0);
+               decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
+               encoder_command(zr, ENCODER_SET_INPUT, &zero);
+
+               /* Take the JPEG codec and the VFE out of sleep */
+               jpeg_codec_sleep(zr, 0);
+
+               /* set JPEG app/com marker */
+               app.appn = zr->jpg_settings.jpg_comp.APPn;
+               app.len = zr->jpg_settings.jpg_comp.APP_len;
+               memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60);
+               zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA,
+                                  sizeof(struct jpeg_app_marker), &app);
+
+               com.len = zr->jpg_settings.jpg_comp.COM_len;
+               memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60);
+               zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA,
+                                  sizeof(struct jpeg_com_marker), &com);
+
+               /* Setup the JPEG codec */
+               zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE,
+                                  sizeof(int), &field_size);
+               zr->codec->set_video(zr->codec, zr->timing, &cap,
+                                    &zr->card.vfe_pol);
+               zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION);
+
+               /* Setup the VFE */
+               if (zr->vfe) {
+                       zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE,
+                                        sizeof(int), &field_size);
+                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+                                          &zr->card.vfe_pol);
+                       zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION);
+               }
+
+               init_jpeg_queue(zr);
+               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
+
+               clear_interrupt_counters(zr);
+               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_COMPRESS)\n",
+                       ZR_DEVNAME(zr));
+               break;
+       }
+
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               /* In motion decompression mode, the decoder output must be disabled, and
+                * the video bus direction set to output.
+                */
+               decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
+               set_videobus_dir(zr, 1);
+               encoder_command(zr, ENCODER_SET_INPUT, &one);
+
+               /* Take the JPEG codec and the VFE out of sleep */
+               jpeg_codec_sleep(zr, 0);
+               /* Setup the VFE */
+               if (zr->vfe) {
+                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+                                          &zr->card.vfe_pol);
+                       zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION);
+               }
+               /* Setup the JPEG codec */
+               zr->codec->set_video(zr->codec, zr->timing, &cap,
+                                    &zr->card.vfe_pol);
+               zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION);
+
+               init_jpeg_queue(zr);
+               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
+
+               clear_interrupt_counters(zr);
+               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_DECOMPRESS)\n",
+                       ZR_DEVNAME(zr));
+               break;
+
+       case BUZ_MODE_IDLE:
+       default:
+               /* shut down processing */
+               btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ),
+                     ZR36057_ICR);
+               btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ,
+                       ZR36057_ISR);
+               btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en
+
+               msleep(50);
+
+               set_videobus_dir(zr, 0);
+               set_frame(zr, 1);       // /FRAME
+               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);      // /CFlush
+               btwrite(0, ZR36057_JPC);        // \P_Reset,\CodTrnsEn,\Active
+               btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
+               btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC);
+               jpeg_codec_reset(zr);
+               jpeg_codec_sleep(zr, 1);
+               zr36057_adjust_vfe(zr, mode);
+
+               decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
+               encoder_command(zr, ENCODER_SET_INPUT, &zero);
+
+               dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
+               break;
+
+       }
+}
+
+/* when this is called the spinlock must be held */
+void
+zoran_feed_stat_com (struct zoran *zr)
+{
+       /* move frames from pending queue to DMA */
+
+       int frame, i, max_stat_com;
+
+       max_stat_com =
+           (zr->jpg_settings.TmpDcm ==
+            1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
+
+       while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com &&
+              zr->jpg_dma_head < zr->jpg_que_head) {
+
+               frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME];
+               if (zr->jpg_settings.TmpDcm == 1) {
+                       /* fill 1 stat_com entry */
+                       i = (zr->jpg_dma_head -
+                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
+                               break;
+                       zr->stat_com[i] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+               } else {
+                       /* fill 2 stat_com entries */
+                       i = ((zr->jpg_dma_head -
+                             zr->jpg_err_shift) & 1) * 2;
+                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
+                               break;
+                       zr->stat_com[i] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+                       zr->stat_com[i + 1] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
+               }
+               zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
+               zr->jpg_dma_head++;
+
+       }
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
+               zr->jpg_queued_num++;
+}
+
+/* when this is called the spinlock must be held */
+static void
+zoran_reap_stat_com (struct zoran *zr)
+{
+       /* move frames from DMA queue to done queue */
+
+       int i;
+       u32 stat_com;
+       unsigned int seq;
+       unsigned int dif;
+       struct zoran_jpg_buffer *buffer;
+       int frame;
+
+       /* In motion decompress we don't have a hardware frame counter,
+        * we just count the interrupts here */
+
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+               zr->jpg_seq_num++;
+       }
+       while (zr->jpg_dma_tail < zr->jpg_dma_head) {
+               if (zr->jpg_settings.TmpDcm == 1)
+                       i = (zr->jpg_dma_tail -
+                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+               else
+                       i = ((zr->jpg_dma_tail -
+                             zr->jpg_err_shift) & 1) * 2 + 1;
+
+               stat_com = le32_to_cpu(zr->stat_com[i]);
+
+               if ((stat_com & 1) == 0) {
+                       return;
+               }
+               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
+               buffer = &zr->jpg_buffers.buffer[frame];
+               do_gettimeofday(&buffer->bs.timestamp);
+
+               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                       buffer->bs.length = (stat_com & 0x7fffff) >> 1;
+
+                       /* update sequence number with the help of the counter in stat_com */
+
+                       seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff;
+                       dif = (seq - zr->jpg_seq_num) & 0xff;
+                       zr->jpg_seq_num += dif;
+               } else {
+                       buffer->bs.length = 0;
+               }
+               buffer->bs.seq =
+                   zr->jpg_settings.TmpDcm ==
+                   2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
+               buffer->state = BUZ_STATE_DONE;
+
+               zr->jpg_dma_tail++;
+       }
+}
+
+static void
+error_handler (struct zoran *zr,
+              u32           astat,
+              u32           stat)
+{
+       /* This is JPEG error handling part */
+       if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) &&
+           (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) {
+               //dprintk(1, KERN_ERR "%s: Internal error: error handling request in mode %d\n", ZR_DEVNAME(zr), zr->codec_mode);
+               return;
+       }
+
+       if ((stat & 1) == 0 &&
+           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS &&
+           zr->jpg_dma_tail - zr->jpg_que_tail >=
+            zr->jpg_buffers.num_buffers) {
+               /* No free buffers... */
+               zoran_reap_stat_com(zr);
+               zoran_feed_stat_com(zr);
+               wake_up_interruptible(&zr->jpg_capq);
+               zr->JPEG_missed = 0;
+               return;
+       }
+
+       if (zr->JPEG_error != 1) {
+               /*
+                * First entry: error just happened during normal operation
+                *
+                * In BUZ_MODE_MOTION_COMPRESS:
+                *
+                * Possible glitch in TV signal. In this case we should
+                * stop the codec and wait for good quality signal before
+                * restarting it to avoid further problems
+                *
+                * In BUZ_MODE_MOTION_DECOMPRESS:
+                *
+                * Bad JPEG frame: we have to mark it as processed (codec crashed
+                * and was not able to do it itself), and to remove it from queue.
+                */
+               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+               udelay(1);
+               stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
+               btwrite(0, ZR36057_JPC);
+               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
+               jpeg_codec_reset(zr);
+               jpeg_codec_sleep(zr, 1);
+               zr->JPEG_error = 1;
+               zr->num_errors++;
+
+               /* Report error */
+               if (zr36067_debug > 1 && zr->num_errors <= 8) {
+                       long frame;
+                       frame =
+                           zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
+                       printk(KERN_ERR
+                              "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
+                              ZR_DEVNAME(zr), stat, zr->last_isr,
+                              zr->jpg_que_tail, zr->jpg_dma_tail,
+                              zr->jpg_dma_head, zr->jpg_que_head,
+                              zr->jpg_seq_num, frame);
+                       printk("stat_com frames:");
+                       {
+                               int i, j;
+                               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+                                       for (i = 0;
+                                            i < zr->jpg_buffers.num_buffers;
+                                            i++) {
+                                               if (le32_to_cpu(zr->stat_com[j]) ==
+                                                   zr->jpg_buffers.
+                                                   buffer[i].
+                                                   frag_tab_bus) {
+                                                       printk("% d->%d",
+                                                              j, i);
+                                               }
+                                       }
+                               }
+                               printk("\n");
+                       }
+               }
+               /* Find an entry in stat_com and rotate contents */
+               {
+                       int i;
+
+                       if (zr->jpg_settings.TmpDcm == 1)
+                               i = (zr->jpg_dma_tail -
+                                    zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+                       else
+                               i = ((zr->jpg_dma_tail -
+                                     zr->jpg_err_shift) & 1) * 2;
+                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+                               /* Mimic zr36067 operation */
+                               zr->stat_com[i] |= cpu_to_le32(1);
+                               if (zr->jpg_settings.TmpDcm != 1)
+                                       zr->stat_com[i + 1] |= cpu_to_le32(1);
+                               /* Refill */
+                               zoran_reap_stat_com(zr);
+                               zoran_feed_stat_com(zr);
+                               wake_up_interruptible(&zr->jpg_capq);
+                               /* Find an entry in stat_com again after refill */
+                               if (zr->jpg_settings.TmpDcm == 1)
+                                       i = (zr->jpg_dma_tail -
+                                            zr->jpg_err_shift) &
+                                           BUZ_MASK_STAT_COM;
+                               else
+                                       i = ((zr->jpg_dma_tail -
+                                             zr->jpg_err_shift) & 1) * 2;
+                       }
+                       if (i) {
+                               /* Rotate stat_comm entries to make current entry first */
+                               int j;
+                               __le32 bus_addr[BUZ_NUM_STAT_COM];
+
+                               /* Here we are copying the stat_com array, which
+                                * is already in little endian format, so
+                                * no endian conversions here
+                                */
+                               memcpy(bus_addr, zr->stat_com,
+                                      sizeof(bus_addr));
+                               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+                                       zr->stat_com[j] =
+                                           bus_addr[(i + j) &
+                                                    BUZ_MASK_STAT_COM];
+
+                               }
+                               zr->jpg_err_shift += i;
+                               zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
+                       }
+                       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
+                               zr->jpg_err_seq = zr->jpg_seq_num;      /* + 1; */
+               }
+       }
+
+       /* Now the stat_comm buffer is ready for restart */
+       do {
+               int status, mode;
+
+               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                       decoder_command(zr, DECODER_GET_STATUS, &status);
+                       mode = CODEC_DO_COMPRESSION;
+               } else {
+                       status = 0;
+                       mode = CODEC_DO_EXPANSION;
+               }
+               if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+                   (status & DECODER_STATUS_GOOD)) {
+                       /********** RESTART code *************/
+                       jpeg_codec_reset(zr);
+                       zr->codec->set_mode(zr->codec, mode);
+                       zr36057_set_jpg(zr, zr->codec_mode);
+                       jpeg_start(zr);
+
+                       if (zr->num_errors <= 8)
+                               dprintk(2, KERN_INFO "%s: Restart\n",
+                                       ZR_DEVNAME(zr));
+
+                       zr->JPEG_missed = 0;
+                       zr->JPEG_error = 2;
+                       /********** End RESTART code ***********/
+               }
+       } while (0);
+}
+
+irqreturn_t
+zoran_irq (int             irq,
+          void           *dev_id)
+{
+       u32 stat, astat;
+       int count;
+       struct zoran *zr;
+       unsigned long flags;
+
+       zr = dev_id;
+       count = 0;
+
+       if (zr->testing) {
+               /* Testing interrupts */
+               spin_lock_irqsave(&zr->spinlock, flags);
+               while ((stat = count_reset_interrupt(zr))) {
+                       if (count++ > 100) {
+                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: IRQ lockup while testing, isr=0x%08x, cleared int mask\n",
+                                       ZR_DEVNAME(zr), stat);
+                               wake_up_interruptible(&zr->test_q);
+                       }
+               }
+               zr->last_isr = stat;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+               return IRQ_HANDLED;
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+       while (1) {
+               /* get/clear interrupt status bits */
+               stat = count_reset_interrupt(zr);
+               astat = stat & IRQ_MASK;
+               if (!astat) {
+                       break;
+               }
+               dprintk(4,
+                       KERN_DEBUG
+                       "zoran_irq: astat: 0x%08x, mask: 0x%08x\n",
+                       astat, btread(ZR36057_ICR));
+               if (astat & zr->card.vsync_int) {       // SW
+
+                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                               /* count missed interrupts */
+                               zr->JPEG_missed++;
+                       }
+                       //post_office_read(zr,1,0);
+                       /* Interrupts may still happen when
+                        * zr->v4l_memgrab_active is switched off.
+                        * We simply ignore them */
+
+                       if (zr->v4l_memgrab_active) {
+
+                               /* A lot more checks should be here ... */
+                               if ((btread(ZR36057_VSSFGR) &
+                                    ZR36057_VSSFGR_SnapShot) == 0)
+                                       dprintk(1,
+                                               KERN_WARNING
+                                               "%s: BuzIRQ with SnapShot off ???\n",
+                                               ZR_DEVNAME(zr));
+
+                               if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
+                                       /* There is a grab on a frame going on, check if it has finished */
+
+                                       if ((btread(ZR36057_VSSFGR) &
+                                            ZR36057_VSSFGR_FrameGrab) ==
+                                           0) {
+                                               /* it is finished, notify the user */
+
+                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
+                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq;
+                                               do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
+                                               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+                                               zr->v4l_pend_tail++;
+                                       }
+                               }
+
+                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE)
+                                       wake_up_interruptible(&zr->v4l_capq);
+
+                               /* Check if there is another grab queued */
+
+                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE &&
+                                   zr->v4l_pend_tail != zr->v4l_pend_head) {
+
+                                       int frame = zr->v4l_pend[zr->v4l_pend_tail &
+                                                        V4L_MASK_FRAME];
+                                       u32 reg;
+
+                                       zr->v4l_grab_frame = frame;
+
+                                       /* Set zr36057 video front end and enable video */
+
+                                       /* Buffer address */
+
+                                       reg =
+                                           zr->v4l_buffers.buffer[frame].
+                                           fbuffer_bus;
+                                       btwrite(reg, ZR36057_VDTR);
+                                       if (zr->v4l_settings.height >
+                                           BUZ_MAX_HEIGHT / 2)
+                                               reg +=
+                                                   zr->v4l_settings.
+                                                   bytesperline;
+                                       btwrite(reg, ZR36057_VDBR);
+
+                                       /* video stride, status, and frame grab register */
+                                       reg = 0;
+                                       if (zr->v4l_settings.height >
+                                           BUZ_MAX_HEIGHT / 2)
+                                               reg +=
+                                                   zr->v4l_settings.
+                                                   bytesperline;
+                                       reg =
+                                           (reg <<
+                                            ZR36057_VSSFGR_DispStride);
+                                       reg |= ZR36057_VSSFGR_VidOvf;
+                                       reg |= ZR36057_VSSFGR_SnapShot;
+                                       reg |= ZR36057_VSSFGR_FrameGrab;
+                                       btwrite(reg, ZR36057_VSSFGR);
+
+                                       btor(ZR36057_VDCR_VidEn,
+                                            ZR36057_VDCR);
+                               }
+                       }
+
+                       /* even if we don't grab, we do want to increment
+                        * the sequence counter to see lost frames */
+                       zr->v4l_grab_seq++;
+               }
+#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
+               if (astat & ZR36057_ISR_CodRepIRQ) {
+                       zr->intr_counter_CodRepIRQ++;
+                       IDEBUG(printk
+                              (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
+                               ZR_DEVNAME(zr)));
+                       btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
+               }
+#endif                         /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
+
+#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
+               if (astat & ZR36057_ISR_JPEGRepIRQ) {
+
+                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                               if (zr36067_debug > 1 &&
+                                   (!zr->frame_num || zr->JPEG_error)) {
+                                       printk(KERN_INFO
+                                              "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
+                                              ZR_DEVNAME(zr), stat,
+                                              zr->jpg_settings.odd_even,
+                                              zr->jpg_settings.
+                                              field_per_buff,
+                                              zr->JPEG_missed);
+                                       {
+                                               char sc[] = "0000";
+                                               char sv[5];
+                                               int i;
+                                               strcpy(sv, sc);
+                                               for (i = 0; i < 4; i++) {
+                                                       if (le32_to_cpu(zr->stat_com[i]) & 1)
+                                                               sv[i] = '1';
+                                               }
+                                               sv[4] = 0;
+                                               printk(KERN_INFO
+                                                      "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
+                                                      ZR_DEVNAME(zr), sv,
+                                                      zr->jpg_que_tail,
+                                                      zr->jpg_dma_tail,
+                                                      zr->jpg_dma_head,
+                                                      zr->jpg_que_head);
+                                       }
+                               } else {
+                                       if (zr->JPEG_missed > zr->JPEG_max_missed)      // Get statistics
+                                               zr->JPEG_max_missed =
+                                                   zr->JPEG_missed;
+                                       if (zr->JPEG_missed <
+                                           zr->JPEG_min_missed)
+                                               zr->JPEG_min_missed =
+                                                   zr->JPEG_missed;
+                               }
+
+                               if (zr36067_debug > 2 && zr->frame_num < 6) {
+                                       int i;
+                                       printk("%s: seq=%ld stat_com:",
+                                              ZR_DEVNAME(zr), zr->jpg_seq_num);
+                                       for (i = 0; i < 4; i++) {
+                                               printk(" %08x",
+                                                      le32_to_cpu(zr->stat_com[i]));
+                                       }
+                                       printk("\n");
+                               }
+                               zr->frame_num++;
+                               zr->JPEG_missed = 0;
+                               zr->JPEG_error = 0;
+                               zoran_reap_stat_com(zr);
+                               zoran_feed_stat_com(zr);
+                               wake_up_interruptible(&zr->jpg_capq);
+                       } /*else {
+                             dprintk(1,
+                                       KERN_ERR
+                                       "%s: JPEG interrupt while not in motion (de)compress mode!\n",
+                                       ZR_DEVNAME(zr));
+                       }*/
+               }
+#endif                         /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
+
+               /* DATERR, too many fields missed, error processing */
+               if ((astat & zr->card.jpeg_int) ||
+                   zr->JPEG_missed > 25 ||
+                   zr->JPEG_error == 1 ||
+                   ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
+                    (zr->frame_num & (zr->JPEG_missed >
+                                      zr->jpg_settings.field_per_buff)))) {
+                       error_handler(zr, astat, stat);
+               }
+
+               count++;
+               if (count > 10) {
+                       dprintk(2, KERN_WARNING "%s: irq loop %d\n",
+                               ZR_DEVNAME(zr), count);
+                       if (count > 20) {
+                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+                               dprintk(2,
+                                       KERN_ERR
+                                       "%s: IRQ lockup, cleared int mask\n",
+                                       ZR_DEVNAME(zr));
+                               break;
+                       }
+               }
+               zr->last_isr = stat;
+       }
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return IRQ_HANDLED;
+}
+
+void
+zoran_set_pci_master (struct zoran *zr,
+                     int           set_master)
+{
+       if (set_master) {
+               pci_set_master(zr->pci_dev);
+       } else {
+               u16 command;
+
+               pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command);
+               command &= ~PCI_COMMAND_MASTER;
+               pci_write_config_word(zr->pci_dev, PCI_COMMAND, command);
+       }
+}
+
+void
+zoran_init_hardware (struct zoran *zr)
+{
+       int j, zero = 0;
+
+       /* Enable bus-mastering */
+       zoran_set_pci_master(zr, 1);
+
+       /* Initialize the board */
+       if (zr->card.init) {
+               zr->card.init(zr);
+       }
+
+       j = zr->card.input[zr->input].muxsel;
+
+       decoder_command(zr, 0, NULL);
+       decoder_command(zr, DECODER_SET_NORM, &zr->norm);
+       decoder_command(zr, DECODER_SET_INPUT, &j);
+
+       encoder_command(zr, 0, NULL);
+       encoder_command(zr, ENCODER_SET_NORM, &zr->norm);
+       encoder_command(zr, ENCODER_SET_INPUT, &zero);
+
+       /* toggle JPEG codec sleep to sync PLL */
+       jpeg_codec_sleep(zr, 1);
+       jpeg_codec_sleep(zr, 0);
+
+       /* set individual interrupt enables (without GIRQ1)
+        * but don't global enable until zoran_open() */
+
+       //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR);  // SW
+       // It looks like using only JPEGRepIRQEn is not always reliable,
+       // may be when JPEG codec crashes it won't generate IRQ? So,
+        /*CP*/                 //        btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM    WHY ? LP
+           zr36057_init_vfe(zr);
+
+       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+
+       btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
+}
+
+void
+zr36057_restart (struct zoran *zr)
+{
+       btwrite(0, ZR36057_SPGPPCR);
+       mdelay(1);
+       btor(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR);
+       mdelay(1);
+
+       /* assert P_Reset */
+       btwrite(0, ZR36057_JPC);
+       /* set up GPIO direction - all output */
+       btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR);
+
+       /* set up GPIO pins and guest bus timing */
+       btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
+}
+
+/*
+ * initialize video front end
+ */
+
+static void
+zr36057_init_vfe (struct zoran *zr)
+{
+       u32 reg;
+
+       reg = btread(ZR36057_VFESPFR);
+       reg |= ZR36057_VFESPFR_LittleEndian;
+       reg &= ~ZR36057_VFESPFR_VCLKPol;
+       reg |= ZR36057_VFESPFR_ExtFl;
+       reg |= ZR36057_VFESPFR_TopField;
+       btwrite(reg, ZR36057_VFESPFR);
+       reg = btread(ZR36057_VDCR);
+       if (pci_pci_problems & PCIPCI_TRITON)
+               // || zr->revision < 1) // Revision 1 has also Triton support
+               reg &= ~ZR36057_VDCR_Triton;
+       else
+               reg |= ZR36057_VDCR_Triton;
+       btwrite(reg, ZR36057_VDCR);
+}
+
+/*
+ * Interface to decoder and encoder chips using i2c bus
+ */
+
+int
+decoder_command (struct zoran *zr,
+                int           cmd,
+                void         *data)
+{
+       if (zr->decoder == NULL)
+               return -EIO;
+
+       if (zr->card.type == LML33 &&
+           (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
+               int res;
+
+               // Bt819 needs to reset its FIFO buffer using #FRST pin and
+               // LML33 card uses GPIO(7) for that.
+               GPIO(zr, 7, 0);
+               res = zr->decoder->driver->command(zr->decoder, cmd, data);
+               // Pull #FRST high.
+               GPIO(zr, 7, 1);
+               return res;
+       } else
+               return zr->decoder->driver->command(zr->decoder, cmd,
+                                                   data);
+}
+
+int
+encoder_command (struct zoran *zr,
+                int           cmd,
+                void         *data)
+{
+       if (zr->encoder == NULL)
+               return -1;
+
+       return zr->encoder->driver->command(zr->encoder, cmd, data);
+}
diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h
new file mode 100644 (file)
index 0000000..74c6c8e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ZORAN_DEVICE_H__
+#define __ZORAN_DEVICE_H__
+
+/* general purpose I/O */
+extern void GPIO(struct zoran *zr,
+                int bit,
+                unsigned int value);
+
+/* codec (or actually: guest bus) access */
+extern int post_office_wait(struct zoran *zr);
+extern int post_office_write(struct zoran *zr,
+                            unsigned guest,
+                            unsigned reg,
+                            unsigned value);
+extern int post_office_read(struct zoran *zr,
+                           unsigned guest,
+                           unsigned reg);
+
+extern void detect_guest_activity(struct zoran *zr);
+
+extern void jpeg_codec_sleep(struct zoran *zr,
+                            int sleep);
+extern int jpeg_codec_reset(struct zoran *zr);
+
+/* zr360x7 access to raw capture */
+extern void zr36057_overlay(struct zoran *zr,
+                           int on);
+extern void write_overlay_mask(struct file *file,
+                              struct video_clip *vp,
+                              int count);
+extern void zr36057_set_memgrab(struct zoran *zr,
+                               int mode);
+extern int wait_grab_pending(struct zoran *zr);
+
+/* interrupts */
+extern void print_interrupts(struct zoran *zr);
+extern void clear_interrupt_counters(struct zoran *zr);
+extern irqreturn_t zoran_irq(int irq, void *dev_id);
+
+/* JPEG codec access */
+extern void jpeg_start(struct zoran *zr);
+extern void zr36057_enable_jpg(struct zoran *zr,
+                              enum zoran_codec_mode mode);
+extern void zoran_feed_stat_com(struct zoran *zr);
+
+/* general */
+extern void zoran_set_pci_master(struct zoran *zr,
+                                int set_master);
+extern void zoran_init_hardware(struct zoran *zr);
+extern void zr36057_restart(struct zoran *zr);
+
+extern const struct zoran_format zoran_formats[];
+
+extern int v4l_nbufs;
+extern int v4l_bufsize;
+extern int jpg_nbufs;
+extern int jpg_bufsize;
+extern int pass_through;
+
+/* i2c */
+extern int decoder_command(struct zoran *zr,
+                          int cmd,
+                          void *data);
+extern int encoder_command(struct zoran *zr,
+                          int cmd,
+                          void *data);
+
+#endif                         /* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
new file mode 100644 (file)
index 0000000..25de763
--- /dev/null
@@ -0,0 +1,4649 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
+ *
+ * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Based on
+ *
+ * Miro DC10 driver
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Iomega Buz driver version 1.0
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * buz.0.0.3
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *                        & Marcus Metzler (mocm@thp.uni-koeln.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <linux/spinlock.h>
+#define     MAP_NR(x)       virt_to_page(x)
+#define     ZORAN_VID_TYPE  ( \
+                               VID_TYPE_CAPTURE | \
+                               VID_TYPE_OVERLAY | \
+                               VID_TYPE_CLIPPING | \
+                               VID_TYPE_FRAMERAM | \
+                               VID_TYPE_SCALES | \
+                               VID_TYPE_MJPEG_DECODER | \
+                               VID_TYPE_MJPEG_ENCODER \
+                            )
+
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "videocodec.h"
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+
+#include <linux/video_decoder.h>
+#include <linux/video_encoder.h>
+#include <linux/mutex.h>
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+       /* we declare some card type definitions here, they mean
+        * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
+#define ZORAN_V4L2_VID_FLAGS ( \
+                               V4L2_CAP_STREAMING |\
+                               V4L2_CAP_VIDEO_CAPTURE |\
+                               V4L2_CAP_VIDEO_OUTPUT |\
+                               V4L2_CAP_VIDEO_OVERLAY \
+                             )
+
+
+#if defined(CONFIG_VIDEO_V4L1_COMPAT)
+#define ZFMT(pal, fcc, cs) \
+       .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
+#else
+#define ZFMT(pal, fcc, cs) \
+       .fourcc = (fcc), .colorspace = (cs)
+#endif
+
+const struct zoran_format zoran_formats[] = {
+       {
+               .name = "15-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB555,
+                    V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB),
+               .depth = 15,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "15-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB),
+               .depth = 15,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
+       }, {
+               .name = "16-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB565,
+                    V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "16-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
+       }, {
+               .name = "24-bit RGB",
+               ZFMT(VIDEO_PALETTE_RGB24,
+                    V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB),
+               .depth = 24,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
+       }, {
+               .name = "32-bit RGB LE",
+               ZFMT(VIDEO_PALETTE_RGB32,
+                    V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB),
+               .depth = 32,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "32-bit RGB BE",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB),
+               .depth = 32,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888,
+       }, {
+               .name = "4:2:2, packed, YUYV",
+               ZFMT(VIDEO_PALETTE_YUV422,
+                    V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422,
+       }, {
+               .name = "4:2:2, packed, UYVY",
+               ZFMT(VIDEO_PALETTE_UYVY,
+                    V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M),
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "Hardware-encoded Motion-JPEG",
+               ZFMT(-1,
+                    V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M),
+               .depth = 0,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_PLAYBACK |
+                        ZORAN_FORMAT_COMPRESSED,
+       }
+};
+#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
+
+// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
+
+
+static int lock_norm;  /* 0 = default 1 = Don't change TV standard (norm) */
+module_param(lock_norm, int, 0644);
+MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
+
+       /* small helper function for calculating buffersizes for v4l2
+        * we calculate the nearest higher power-of-two, which
+        * will be the recommended buffersize */
+static __u32
+zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
+{
+       __u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm;
+       __u32 num = (1024 * 512) / (div);
+       __u32 result = 2;
+
+       num--;
+       while (num) {
+               num >>= 1;
+               result <<= 1;
+       }
+
+       if (result > jpg_bufsize)
+               return jpg_bufsize;
+       if (result < 8192)
+               return 8192;
+       return result;
+}
+
+/* forward references */
+static void v4l_fbuffer_free(struct file *file);
+static void jpg_fbuffer_free(struct file *file);
+
+/*
+ *   Allocate the V4L grab buffers
+ *
+ *   These have to be pysically contiguous.
+ *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc
+ *   else we try to allocate them with bigphysarea_alloc_pages
+ *   if the bigphysarea patch is present in the kernel,
+ *   else we try to use high memory (if the user has bootet
+ *   Linux with the necessary memory left over).
+ */
+
+static unsigned long
+get_high_mem (unsigned long size)
+{
+/*
+ * Check if there is usable memory at the end of Linux memory
+ * of at least size. Return the physical address of this memory,
+ * return 0 on failure.
+ *
+ * The idea is from Alexandro Rubini's book "Linux device drivers".
+ * The driver from him which is downloadable from O'Reilly's
+ * web site misses the "virt_to_phys(high_memory)" part
+ * (and therefore doesn't work at all - at least with 2.2.x kernels).
+ *
+ * It should be unnecessary to mention that THIS IS DANGEROUS,
+ * if more than one driver at a time has the idea to use this memory!!!!
+ */
+
+       volatile unsigned char __iomem *mem;
+       unsigned char c;
+       unsigned long hi_mem_ph;
+       unsigned long i;
+
+       /* Map the high memory to user space */
+
+       hi_mem_ph = virt_to_phys(high_memory);
+
+       mem = ioremap(hi_mem_ph, size);
+       if (!mem) {
+               dprintk(1,
+                       KERN_ERR "%s: get_high_mem() - ioremap failed\n",
+                       ZORAN_NAME);
+               return 0;
+       }
+
+       for (i = 0; i < size; i++) {
+               /* Check if it is memory */
+               c = i & 0xff;
+               writeb(c, mem + i);
+               if (readb(mem + i) != c)
+                       break;
+               c = 255 - c;
+               writeb(c, mem + i);
+               if (readb(mem + i) != c)
+                       break;
+               writeb(0, mem + i);     /* zero out memory */
+
+               /* give the kernel air to breath */
+               if ((i & 0x3ffff) == 0x3ffff)
+                       schedule();
+       }
+
+       iounmap(mem);
+
+       if (i != size) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: get_high_mem() - requested %lu, avail %lu\n",
+                       ZORAN_NAME, size, i);
+               return 0;
+       }
+
+       return hi_mem_ph;
+}
+
+static int
+v4l_fbuffer_alloc (struct file *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int i, off;
+       unsigned char *mem;
+       unsigned long pmem = 0;
+
+       /* we might have old buffers lying around... */
+       if (fh->v4l_buffers.ready_to_be_freed) {
+               v4l_fbuffer_free(file);
+       }
+
+       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
+               if (fh->v4l_buffers.buffer[i].fbuffer)
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n",
+                               ZR_DEVNAME(zr), i);
+
+               //udelay(20);
+               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
+                       /* Use kmalloc */
+
+                       mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
+                       if (!mem) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",
+                                       ZR_DEVNAME(zr), i);
+                               v4l_fbuffer_free(file);
+                               return -ENOBUFS;
+                       }
+                       fh->v4l_buffers.buffer[i].fbuffer = mem;
+                       fh->v4l_buffers.buffer[i].fbuffer_phys =
+                           virt_to_phys(mem);
+                       fh->v4l_buffers.buffer[i].fbuffer_bus =
+                           virt_to_bus(mem);
+                       for (off = 0; off < fh->v4l_buffers.buffer_size;
+                            off += PAGE_SIZE)
+                               SetPageReserved(MAP_NR(mem + off));
+                       dprintk(4,
+                               KERN_INFO
+                               "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n",
+                               ZR_DEVNAME(zr), i, (unsigned long) mem,
+                               virt_to_bus(mem));
+               } else {
+
+                       /* Use high memory which has been left at boot time */
+
+                       /* Ok., Ok. this is an evil hack - we make
+                        * the assumption that physical addresses are
+                        * the same as bus addresses (true at least
+                        * for Intel processors). The whole method of
+                        * obtaining and using this memory is not very
+                        * nice - but I hope it saves some poor users
+                        * from kernel hacking, which might have even
+                        * more evil results */
+
+                       if (i == 0) {
+                               int size =
+                                   fh->v4l_buffers.num_buffers *
+                                   fh->v4l_buffers.buffer_size;
+
+                               pmem = get_high_mem(size);
+                               if (pmem == 0) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n",
+                                               ZR_DEVNAME(zr), size >> 10);
+                                       return -ENOBUFS;
+                               }
+                               fh->v4l_buffers.buffer[0].fbuffer = NULL;
+                               fh->v4l_buffers.buffer[0].fbuffer_phys = pmem;
+                               fh->v4l_buffers.buffer[0].fbuffer_bus = pmem;
+                               dprintk(4,
+                                       KERN_INFO
+                                       "%s: v4l_fbuffer_alloc() - using %d KB high memory\n",
+                                       ZR_DEVNAME(zr), size >> 10);
+                       } else {
+                               fh->v4l_buffers.buffer[i].fbuffer = NULL;
+                               fh->v4l_buffers.buffer[i].fbuffer_phys =
+                                   pmem + i * fh->v4l_buffers.buffer_size;
+                               fh->v4l_buffers.buffer[i].fbuffer_bus =
+                                   pmem + i * fh->v4l_buffers.buffer_size;
+                       }
+               }
+       }
+
+       fh->v4l_buffers.allocated = 1;
+
+       return 0;
+}
+
+/* free the V4L grab buffers */
+static void
+v4l_fbuffer_free (struct file *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int i, off;
+       unsigned char *mem;
+
+       dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr));
+
+       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
+               if (!fh->v4l_buffers.buffer[i].fbuffer)
+                       continue;
+
+               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
+                       mem = fh->v4l_buffers.buffer[i].fbuffer;
+                       for (off = 0; off < fh->v4l_buffers.buffer_size;
+                            off += PAGE_SIZE)
+                               ClearPageReserved(MAP_NR(mem + off));
+                       kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
+               }
+               fh->v4l_buffers.buffer[i].fbuffer = NULL;
+       }
+
+       fh->v4l_buffers.allocated = 0;
+       fh->v4l_buffers.ready_to_be_freed = 0;
+}
+
+/*
+ *   Allocate the MJPEG grab buffers.
+ *
+ *   If the requested buffer size is smaller than MAX_KMALLOC_MEM,
+ *   kmalloc is used to request a physically contiguous area,
+ *   else we allocate the memory in framgents with get_zeroed_page.
+ *
+ *   If a Natoma chipset is present and this is a revision 1 zr36057,
+ *   each MJPEG buffer needs to be physically contiguous.
+ *   (RJ: This statement is from Dave Perks' original driver,
+ *   I could never check it because I have a zr36067)
+ *   The driver cares about this because it reduces the buffer
+ *   size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation).
+ *
+ *   RJ: The contents grab buffers needs never be accessed in the driver.
+ *       Therefore there is no need to allocate them with vmalloc in order
+ *       to get a contiguous virtual memory space.
+ *       I don't understand why many other drivers first allocate them with
+ *       vmalloc (which uses internally also get_zeroed_page, but delivers you
+ *       virtual addresses) and then again have to make a lot of efforts
+ *       to get the physical address.
+ *
+ *   Ben Capper:
+ *       On big-endian architectures (such as ppc) some extra steps
+ *       are needed. When reading and writing to the stat_com array
+ *       and fragment buffers, the device expects to see little-
+ *       endian values. The use of cpu_to_le32() and le32_to_cpu()
+ *       in this function (and one or two others in zoran_device.c)
+ *       ensure that these values are always stored in little-endian
+ *       form, regardless of architecture. The zr36057 does Very Bad
+ *       Things on big endian architectures if the stat_com array
+ *       and fragment buffers are not little-endian.
+ */
+
+static int
+jpg_fbuffer_alloc (struct file *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int i, j, off;
+       unsigned long mem;
+
+       /* we might have old buffers lying around */
+       if (fh->jpg_buffers.ready_to_be_freed) {
+               jpg_fbuffer_free(file);
+       }
+
+       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
+               if (fh->jpg_buffers.buffer[i].frag_tab)
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n",
+                               ZR_DEVNAME(zr), i);
+
+               /* Allocate fragment table for this buffer */
+
+               mem = get_zeroed_page(GFP_KERNEL);
+               if (mem == 0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n",
+                               ZR_DEVNAME(zr), i);
+                       jpg_fbuffer_free(file);
+                       return -ENOBUFS;
+               }
+               fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
+               fh->jpg_buffers.buffer[i].frag_tab_bus =
+                   virt_to_bus((void *) mem);
+
+               //if (alloc_contig) {
+               if (fh->jpg_buffers.need_contiguous) {
+                       mem =
+                           (unsigned long) kmalloc(fh->jpg_buffers.
+                                                   buffer_size,
+                                                   GFP_KERNEL);
+                       if (mem == 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n",
+                                       ZR_DEVNAME(zr), i);
+                               jpg_fbuffer_free(file);
+                               return -ENOBUFS;
+                       }
+                       fh->jpg_buffers.buffer[i].frag_tab[0] =
+                           cpu_to_le32(virt_to_bus((void *) mem));
+                       fh->jpg_buffers.buffer[i].frag_tab[1] =
+                           cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);
+                       for (off = 0; off < fh->jpg_buffers.buffer_size;
+                            off += PAGE_SIZE)
+                               SetPageReserved(MAP_NR(mem + off));
+               } else {
+                       /* jpg_bufsize is allreay page aligned */
+                       for (j = 0;
+                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+                            j++) {
+                               mem = get_zeroed_page(GFP_KERNEL);
+                               if (mem == 0) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n",
+                                               ZR_DEVNAME(zr), i);
+                                       jpg_fbuffer_free(file);
+                                       return -ENOBUFS;
+                               }
+
+                               fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
+                                   cpu_to_le32(virt_to_bus((void *) mem));
+                               fh->jpg_buffers.buffer[i].frag_tab[2 * j +
+                                                                  1] =
+                                   cpu_to_le32((PAGE_SIZE / 4) << 1);
+                               SetPageReserved(MAP_NR(mem));
+                       }
+
+                       fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);
+               }
+       }
+
+       dprintk(4,
+               KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n",
+               ZR_DEVNAME(zr),
+               (fh->jpg_buffers.num_buffers *
+                fh->jpg_buffers.buffer_size) >> 10);
+
+       fh->jpg_buffers.allocated = 1;
+
+       return 0;
+}
+
+/* free the MJPEG grab buffers */
+static void
+jpg_fbuffer_free (struct file *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int i, j, off;
+       unsigned char *mem;
+
+       dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));
+
+       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
+               if (!fh->jpg_buffers.buffer[i].frag_tab)
+                       continue;
+
+               //if (alloc_contig) {
+               if (fh->jpg_buffers.need_contiguous) {
+                       if (fh->jpg_buffers.buffer[i].frag_tab[0]) {
+                               mem = (unsigned char *) bus_to_virt(le32_to_cpu(
+                                       fh->jpg_buffers.buffer[i].frag_tab[0]));
+                               for (off = 0;
+                                    off < fh->jpg_buffers.buffer_size;
+                                    off += PAGE_SIZE)
+                                       ClearPageReserved(MAP_NR
+                                                         (mem + off));
+                               kfree(mem);
+                               fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
+                               fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
+                       }
+               } else {
+                       for (j = 0;
+                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+                            j++) {
+                               if (!fh->jpg_buffers.buffer[i].
+                                   frag_tab[2 * j])
+                                       break;
+                               ClearPageReserved(MAP_NR
+                                                 (bus_to_virt
+                                                  (le32_to_cpu
+                                                   (fh->jpg_buffers.
+                                                    buffer[i].frag_tab[2 *
+                                                                      j]))));
+                               free_page((unsigned long)
+                                         bus_to_virt
+                                                 (le32_to_cpu
+                                                  (fh->jpg_buffers.
+                                                     buffer[i].
+                                                     frag_tab[2 * j])));
+                               fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
+                                   0;
+                               fh->jpg_buffers.buffer[i].frag_tab[2 * j +
+                                                                  1] = 0;
+                       }
+               }
+
+               free_page((unsigned long) fh->jpg_buffers.buffer[i].
+                         frag_tab);
+               fh->jpg_buffers.buffer[i].frag_tab = NULL;
+       }
+
+       fh->jpg_buffers.allocated = 0;
+       fh->jpg_buffers.ready_to_be_freed = 0;
+}
+
+/*
+ *   V4L Buffer grabbing
+ */
+
+static int
+zoran_v4l_set_format (struct file               *file,
+                     int                        width,
+                     int                        height,
+                     const struct zoran_format *format)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int bpp;
+
+       /* Check size and format of the grab wanted */
+
+       if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
+           height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_set_format() - wrong frame size (%dx%d)\n",
+                       ZR_DEVNAME(zr), width, height);
+               return -EINVAL;
+       }
+
+       bpp = (format->depth + 7) / 8;
+
+       /* Check against available buffer size */
+       if (height * width * bpp > fh->v4l_buffers.buffer_size) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_set_format() - video buffer size (%d kB) is too small\n",
+                       ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10);
+               return -EINVAL;
+       }
+
+       /* The video front end needs 4-byte alinged line sizes */
+
+       if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_set_format() - wrong frame alingment\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       fh->v4l_settings.width = width;
+       fh->v4l_settings.height = height;
+       fh->v4l_settings.format = format;
+       fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width;
+
+       return 0;
+}
+
+static int
+zoran_v4l_queue_frame (struct file *file,
+                      int          num)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int res = 0;
+
+       if (!fh->v4l_buffers.allocated) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_queue_frame() - buffers not yet allocated\n",
+                       ZR_DEVNAME(zr));
+               res = -ENOMEM;
+       }
+
+       /* No grabbing outside the buffer range! */
+       if (num >= fh->v4l_buffers.num_buffers || num < 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_queue_frame() - buffer %d is out of range\n",
+                       ZR_DEVNAME(zr), num);
+               res = -EINVAL;
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (fh->v4l_buffers.active == ZORAN_FREE) {
+               if (zr->v4l_buffers.active == ZORAN_FREE) {
+                       zr->v4l_buffers = fh->v4l_buffers;
+                       fh->v4l_buffers.active = ZORAN_ACTIVE;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: v4l_queue_frame() - another session is already capturing\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+               }
+       }
+
+       /* make sure a grab isn't going on currently with this buffer */
+       if (!res) {
+               switch (zr->v4l_buffers.buffer[num].state) {
+               default:
+               case BUZ_STATE_PEND:
+                       if (zr->v4l_buffers.active == ZORAN_FREE) {
+                               fh->v4l_buffers.active = ZORAN_FREE;
+                               zr->v4l_buffers.allocated = 0;
+                       }
+                       res = -EBUSY;   /* what are you doing? */
+                       break;
+               case BUZ_STATE_DONE:
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n",
+                               ZR_DEVNAME(zr), num);
+               case BUZ_STATE_USER:
+                       /* since there is at least one unused buffer there's room for at least
+                        * one more pend[] entry */
+                       zr->v4l_pend[zr->v4l_pend_head++ &
+                                       V4L_MASK_FRAME] = num;
+                       zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
+                       zr->v4l_buffers.buffer[num].bs.length =
+                           fh->v4l_settings.bytesperline *
+                           zr->v4l_settings.height;
+                       fh->v4l_buffers.buffer[num] =
+                           zr->v4l_buffers.buffer[num];
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       if (!res && zr->v4l_buffers.active == ZORAN_FREE)
+               zr->v4l_buffers.active = fh->v4l_buffers.active;
+
+       return res;
+}
+
+static int
+v4l_grab (struct file       *file,
+         struct video_mmap *mp)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int res = 0, i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (zoran_formats[i].palette == mp->format &&
+                   zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&
+                   !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))
+                       break;
+       }
+       if (i == NUM_FORMATS || zoran_formats[i].depth == 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_grab() - wrong bytes-per-pixel format\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       /*
+        * To minimize the time spent in the IRQ routine, we avoid setting up
+        * the video front end there.
+        * If this grab has different parameters from a running streaming capture
+        * we stop the streaming capture and start it over again.
+        */
+       if (zr->v4l_memgrab_active &&
+           (zr->v4l_settings.width != mp->width ||
+            zr->v4l_settings.height != mp->height ||
+            zr->v4l_settings.format->palette != mp->format)) {
+               res = wait_grab_pending(zr);
+               if (res)
+                       return res;
+       }
+       if ((res = zoran_v4l_set_format(file,
+                                       mp->width,
+                                       mp->height,
+                                       &zoran_formats[i])))
+               return res;
+       zr->v4l_settings = fh->v4l_settings;
+
+       /* queue the frame in the pending queue */
+       if ((res = zoran_v4l_queue_frame(file, mp->frame))) {
+               fh->v4l_buffers.active = ZORAN_FREE;
+               return res;
+       }
+
+       /* put the 36057 into frame grabbing mode */
+       if (!res && !zr->v4l_memgrab_active)
+               zr36057_set_memgrab(zr, 1);
+
+       //dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr));
+
+       return res;
+}
+
+/*
+ * Sync on a V4L buffer
+ */
+
+static int
+v4l_sync (struct file *file,
+         int          frame)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+
+       if (fh->v4l_buffers.active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_sync() - no grab active for this session\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       /* check passed-in frame number */
+       if (frame >= fh->v4l_buffers.num_buffers || frame < 0) {
+               dprintk(1,
+                       KERN_ERR "%s: v4l_sync() - frame %d is invalid\n",
+                       ZR_DEVNAME(zr), frame);
+               return -EINVAL;
+       }
+
+       /* Check if is buffer was queued at all */
+       if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n",
+                       ZR_DEVNAME(zr));
+               return -EPROTO;
+       }
+
+       /* wait on this buffer to get ready */
+       if (!wait_event_interruptible_timeout(zr->v4l_capq,
+                               (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),
+                               10*HZ))
+               return -ETIME;
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       /* buffer should now be in BUZ_STATE_DONE */
+       if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
+               dprintk(2,
+                       KERN_ERR "%s: v4l_sync() - internal state error\n",
+                       ZR_DEVNAME(zr));
+
+       zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
+       fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       /* Check if streaming capture has finished */
+       if (zr->v4l_pend_tail == zr->v4l_pend_head) {
+               zr36057_set_memgrab(zr, 0);
+               if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
+                       fh->v4l_buffers.active = zr->v4l_buffers.active =
+                           ZORAN_FREE;
+                       zr->v4l_buffers.allocated = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+/*
+ *   Queue a MJPEG buffer for capture/playback
+ */
+
+static int
+zoran_jpg_queue_frame (struct file          *file,
+                      int                   num,
+                      enum zoran_codec_mode mode)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int res = 0;
+
+       /* Check if buffers are allocated */
+       if (!fh->jpg_buffers.allocated) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_queue_frame() - buffers not yet allocated\n",
+                       ZR_DEVNAME(zr));
+               return -ENOMEM;
+       }
+
+       /* No grabbing outside the buffer range! */
+       if (num >= fh->jpg_buffers.num_buffers || num < 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_queue_frame() - buffer %d out of range\n",
+                       ZR_DEVNAME(zr), num);
+               return -EINVAL;
+       }
+
+       /* what is the codec mode right now? */
+       if (zr->codec_mode == BUZ_MODE_IDLE) {
+               zr->jpg_settings = fh->jpg_settings;
+       } else if (zr->codec_mode != mode) {
+               /* wrong codec mode active - invalid */
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_queue_frame() - codec in wrong mode\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       if (fh->jpg_buffers.active == ZORAN_FREE) {
+               if (zr->jpg_buffers.active == ZORAN_FREE) {
+                       zr->jpg_buffers = fh->jpg_buffers;
+                       fh->jpg_buffers.active = ZORAN_ACTIVE;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: jpg_queue_frame() - another session is already capturing\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+               }
+       }
+
+       if (!res && zr->codec_mode == BUZ_MODE_IDLE) {
+               /* Ok load up the jpeg codec */
+               zr36057_enable_jpg(zr, mode);
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (!res) {
+               switch (zr->jpg_buffers.buffer[num].state) {
+               case BUZ_STATE_DONE:
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n",
+                               ZR_DEVNAME(zr));
+               case BUZ_STATE_USER:
+                       /* since there is at least one unused buffer there's room for at
+                        *least one more pend[] entry */
+                       zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] =
+                           num;
+                       zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
+                       fh->jpg_buffers.buffer[num] =
+                           zr->jpg_buffers.buffer[num];
+                       zoran_feed_stat_com(zr);
+                       break;
+               default:
+               case BUZ_STATE_DMA:
+               case BUZ_STATE_PEND:
+                       if (zr->jpg_buffers.active == ZORAN_FREE) {
+                               fh->jpg_buffers.active = ZORAN_FREE;
+                               zr->jpg_buffers.allocated = 0;
+                       }
+                       res = -EBUSY;   /* what are you doing? */
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       if (!res && zr->jpg_buffers.active == ZORAN_FREE) {
+               zr->jpg_buffers.active = fh->jpg_buffers.active;
+       }
+
+       return res;
+}
+
+static int
+jpg_qbuf (struct file          *file,
+         int                   frame,
+         enum zoran_codec_mode mode)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+
+       /* Does the user want to stop streaming? */
+       if (frame < 0) {
+               if (zr->codec_mode == mode) {
+                       if (fh->jpg_buffers.active == ZORAN_FREE) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: jpg_qbuf(-1) - session not active\n",
+                                       ZR_DEVNAME(zr));
+                               return -EINVAL;
+                       }
+                       fh->jpg_buffers.active = zr->jpg_buffers.active =
+                           ZORAN_FREE;
+                       zr->jpg_buffers.allocated = 0;
+                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+                       return 0;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: jpg_qbuf() - stop streaming but not in streaming mode\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+       }
+
+       if ((res = zoran_jpg_queue_frame(file, frame, mode)))
+               return res;
+
+       /* Start the jpeg codec when the first frame is queued  */
+       if (!res && zr->jpg_que_head == 1)
+               jpeg_start(zr);
+
+       return res;
+}
+
+/*
+ *   Sync on a MJPEG buffer
+ */
+
+static int
+jpg_sync (struct file       *file,
+         struct zoran_sync *bs)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int frame;
+
+       if (fh->jpg_buffers.active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_sync() - capture is not currently active\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+       if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
+           zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_sync() - codec not in streaming mode\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+       if (!wait_event_interruptible_timeout(zr->jpg_capq,
+                       (zr->jpg_que_tail != zr->jpg_dma_tail ||
+                        zr->jpg_dma_tail == zr->jpg_dma_head),
+                       10*HZ)) {
+               int isr;
+
+               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+               udelay(1);
+               zr->codec->control(zr->codec, CODEC_G_STATUS,
+                                          sizeof(isr), &isr);
+               dprintk(1,
+                       KERN_ERR
+                       "%s: jpg_sync() - timeout: codec isr=0x%02x\n",
+                       ZR_DEVNAME(zr), isr);
+
+               return -ETIME;
+
+       }
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (zr->jpg_dma_tail != zr->jpg_dma_head)
+               frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
+       else
+               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+       /* buffer should now be in BUZ_STATE_DONE */
+       if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
+               dprintk(2,
+                       KERN_ERR "%s: jpg_sync() - internal state error\n",
+                       ZR_DEVNAME(zr));
+
+       *bs = zr->jpg_buffers.buffer[frame].bs;
+       bs->frame = frame;
+       zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
+       fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+static void
+zoran_open_init_session (struct file *file)
+{
+       int i;
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       /* Per default, map the V4L Buffers */
+       fh->map_mode = ZORAN_MAP_MODE_RAW;
+
+       /* take over the card's current settings */
+       fh->overlay_settings = zr->overlay_settings;
+       fh->overlay_settings.is_set = 0;
+       fh->overlay_settings.format = zr->overlay_settings.format;
+       fh->overlay_active = ZORAN_FREE;
+
+       /* v4l settings */
+       fh->v4l_settings = zr->v4l_settings;
+
+       /* v4l_buffers */
+       memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct));
+       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+               fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+               fh->v4l_buffers.buffer[i].bs.frame = i;
+       }
+       fh->v4l_buffers.allocated = 0;
+       fh->v4l_buffers.ready_to_be_freed = 0;
+       fh->v4l_buffers.active = ZORAN_FREE;
+       fh->v4l_buffers.buffer_size = v4l_bufsize;
+       fh->v4l_buffers.num_buffers = v4l_nbufs;
+
+       /* jpg settings */
+       fh->jpg_settings = zr->jpg_settings;
+
+       /* jpg_buffers */
+       memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct));
+       for (i = 0; i < BUZ_MAX_FRAME; i++) {
+               fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+               fh->jpg_buffers.buffer[i].bs.frame = i;
+       }
+       fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous;
+       fh->jpg_buffers.allocated = 0;
+       fh->jpg_buffers.ready_to_be_freed = 0;
+       fh->jpg_buffers.active = ZORAN_FREE;
+       fh->jpg_buffers.buffer_size = jpg_bufsize;
+       fh->jpg_buffers.num_buffers = jpg_nbufs;
+}
+
+static void
+zoran_close_end_session (struct file *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       /* overlay */
+       if (fh->overlay_active != ZORAN_FREE) {
+               fh->overlay_active = zr->overlay_active = ZORAN_FREE;
+               zr->v4l_overlay_active = 0;
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+       }
+
+       /* v4l capture */
+       if (fh->v4l_buffers.active != ZORAN_FREE) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               zr36057_set_memgrab(zr, 0);
+               zr->v4l_buffers.allocated = 0;
+               zr->v4l_buffers.active = fh->v4l_buffers.active =
+                   ZORAN_FREE;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+       }
+
+       /* v4l buffers */
+       if (fh->v4l_buffers.allocated ||
+           fh->v4l_buffers.ready_to_be_freed) {
+               v4l_fbuffer_free(file);
+       }
+
+       /* jpg capture */
+       if (fh->jpg_buffers.active != ZORAN_FREE) {
+               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+               zr->jpg_buffers.allocated = 0;
+               zr->jpg_buffers.active = fh->jpg_buffers.active =
+                   ZORAN_FREE;
+       }
+
+       /* jpg buffers */
+       if (fh->jpg_buffers.allocated ||
+           fh->jpg_buffers.ready_to_be_freed) {
+               jpg_fbuffer_free(file);
+       }
+}
+
+/*
+ *   Open a zoran card. Right now the flags stuff is just playing
+ */
+
+static int
+zoran_open (struct inode *inode,
+           struct file  *file)
+{
+       unsigned int minor = iminor(inode);
+       struct zoran *zr = NULL;
+       struct zoran_fh *fh;
+       int i, res, first_open = 0, have_module_locks = 0;
+
+       lock_kernel();
+       /* find the device */
+       for (i = 0; i < zoran_num; i++) {
+               if (zoran[i]->video_dev->minor == minor) {
+                       zr = zoran[i];
+                       break;
+               }
+       }
+
+       if (!zr) {
+               dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME);
+               res = -ENODEV;
+               goto open_unlock_and_return;
+       }
+
+       /* see fs/device.c - the kernel already locks during open(),
+        * so locking ourselves only causes deadlocks */
+       /*mutex_lock(&zr->resource_lock);*/
+
+       if (!zr->decoder) {
+               dprintk(1,
+                       KERN_ERR "%s: no TV decoder loaded for device!\n",
+                       ZR_DEVNAME(zr));
+               res = -EIO;
+               goto open_unlock_and_return;
+       }
+
+       /* try to grab a module lock */
+       if (!try_module_get(THIS_MODULE)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: failed to acquire my own lock! PANIC!\n",
+                       ZR_DEVNAME(zr));
+               res = -ENODEV;
+               goto open_unlock_and_return;
+       }
+       if (!try_module_get(zr->decoder->driver->driver.owner)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: failed to grab ownership of i2c decoder\n",
+                       ZR_DEVNAME(zr));
+               res = -EIO;
+               module_put(THIS_MODULE);
+               goto open_unlock_and_return;
+       }
+       if (zr->encoder &&
+           !try_module_get(zr->encoder->driver->driver.owner)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: failed to grab ownership of i2c encoder\n",
+                       ZR_DEVNAME(zr));
+               res = -EIO;
+               module_put(zr->decoder->driver->driver.owner);
+               module_put(THIS_MODULE);
+               goto open_unlock_and_return;
+       }
+
+       have_module_locks = 1;
+
+       if (zr->user >= 2048) {
+               dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
+                       ZR_DEVNAME(zr), zr->user);
+               res = -EBUSY;
+               goto open_unlock_and_return;
+       }
+
+       dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
+               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
+
+       /* now, create the open()-specific file_ops struct */
+       fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
+       if (!fh) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_open() - allocation of zoran_fh failed\n",
+                       ZR_DEVNAME(zr));
+               res = -ENOMEM;
+               goto open_unlock_and_return;
+       }
+       /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
+        * on norm-change! */
+       fh->overlay_mask =
+           kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+       if (!fh->overlay_mask) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_open() - allocation of overlay_mask failed\n",
+                       ZR_DEVNAME(zr));
+               kfree(fh);
+               res = -ENOMEM;
+               goto open_unlock_and_return;
+       }
+
+       if (zr->user++ == 0)
+               first_open = 1;
+
+       /*mutex_unlock(&zr->resource_lock);*/
+
+       /* default setup - TODO: look at flags */
+       if (first_open) {       /* First device open */
+               zr36057_restart(zr);
+               zoran_open_init_params(zr);
+               zoran_init_hardware(zr);
+
+               btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
+       }
+
+       /* set file_ops stuff */
+       file->private_data = fh;
+       fh->zr = zr;
+       zoran_open_init_session(file);
+       unlock_kernel();
+
+       return 0;
+
+open_unlock_and_return:
+       /* if we grabbed locks, release them accordingly */
+       if (have_module_locks) {
+               module_put(zr->decoder->driver->driver.owner);
+               if (zr->encoder) {
+                       module_put(zr->encoder->driver->driver.owner);
+               }
+               module_put(THIS_MODULE);
+       }
+
+       /* if there's no device found, we didn't obtain the lock either */
+       if (zr) {
+               /*mutex_unlock(&zr->resource_lock);*/
+       }
+       unlock_kernel();
+
+       return res;
+}
+
+static int
+zoran_close (struct inode *inode,
+            struct file  *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
+               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
+
+       /* kernel locks (fs/device.c), so don't do that ourselves
+        * (prevents deadlocks) */
+       /*mutex_lock(&zr->resource_lock);*/
+
+       zoran_close_end_session(file);
+
+       if (zr->user-- == 1) {  /* Last process */
+               /* Clean up JPEG process */
+               wake_up_interruptible(&zr->jpg_capq);
+               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+               zr->jpg_buffers.allocated = 0;
+               zr->jpg_buffers.active = ZORAN_FREE;
+
+               /* disable interrupts */
+               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+
+               if (zr36067_debug > 1)
+                       print_interrupts(zr);
+
+               /* Overlay off */
+               zr->v4l_overlay_active = 0;
+               zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+
+               /* capture off */
+               wake_up_interruptible(&zr->v4l_capq);
+               zr36057_set_memgrab(zr, 0);
+               zr->v4l_buffers.allocated = 0;
+               zr->v4l_buffers.active = ZORAN_FREE;
+               zoran_set_pci_master(zr, 0);
+
+               if (!pass_through) {    /* Switch to color bar */
+                       int zero = 0, two = 2;
+                       decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
+                       encoder_command(zr, ENCODER_SET_INPUT, &two);
+               }
+       }
+
+       file->private_data = NULL;
+       kfree(fh->overlay_mask);
+       kfree(fh);
+
+       /* release locks on the i2c modules */
+       module_put(zr->decoder->driver->driver.owner);
+       if (zr->encoder) {
+                module_put(zr->encoder->driver->driver.owner);
+       }
+       module_put(THIS_MODULE);
+
+       /*mutex_unlock(&zr->resource_lock);*/
+
+       dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr));
+
+       return 0;
+}
+
+
+static ssize_t
+zoran_read (struct file *file,
+           char        __user *data,
+           size_t       count,
+           loff_t      *ppos)
+{
+       /* we simply don't support read() (yet)... */
+
+       return -EINVAL;
+}
+
+static ssize_t
+zoran_write (struct file *file,
+            const char  __user *data,
+            size_t       count,
+            loff_t      *ppos)
+{
+       /* ...and the same goes for write() */
+
+       return -EINVAL;
+}
+
+static int
+setup_fbuffer (struct file               *file,
+              void                      *base,
+              const struct zoran_format *fmt,
+              int                        width,
+              int                        height,
+              int                        bytesperline)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       /* (Ronald) v4l/v4l2 guidelines */
+       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
+          ALi Magik (that needs very low latency while the card needs a
+          higher value always) */
+
+       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+               return -ENXIO;
+
+       /* we need a bytesperline value, even if not given */
+       if (!bytesperline)
+               bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
+
+#if 0
+       if (zr->overlay_active) {
+               /* dzjee... stupid users... don't even bother to turn off
+                * overlay before changing the memory location...
+                * normally, we would return errors here. However, one of
+                * the tools that does this is... xawtv! and since xawtv
+                * is used by +/- 99% of the users, we'd rather be user-
+                * friendly and silently do as if nothing went wrong */
+               dprintk(3,
+                       KERN_ERR
+                       "%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n",
+                       ZR_DEVNAME(zr));
+               zr36057_overlay(zr, 0);
+       }
+#endif
+
+       if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_fbuffer() - no valid overlay format given\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+       if (height <= 0 || width <= 0 || bytesperline <= 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n",
+                       ZR_DEVNAME(zr), width, height, bytesperline);
+               return -EINVAL;
+       }
+       if (bytesperline & 3) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n",
+                       ZR_DEVNAME(zr), bytesperline);
+               return -EINVAL;
+       }
+
+       zr->buffer.base = (void *) ((unsigned long) base & ~3);
+       zr->buffer.height = height;
+       zr->buffer.width = width;
+       zr->buffer.depth = fmt->depth;
+       zr->overlay_settings.format = fmt;
+       zr->buffer.bytesperline = bytesperline;
+
+       /* The user should set new window parameters */
+       zr->overlay_settings.is_set = 0;
+
+       return 0;
+}
+
+
+static int
+setup_window (struct file       *file,
+             int                x,
+             int                y,
+             int                width,
+             int                height,
+             struct video_clip __user *clips,
+             int                clipcount,
+             void              __user *bitmap)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       struct video_clip *vcp = NULL;
+       int on, end;
+
+
+       if (!zr->buffer.base) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_window() - frame buffer has to be set first\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       if (!fh->overlay_settings.format) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_window() - no overlay format set\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       /*
+        * The video front end needs 4-byte alinged line sizes, we correct that
+        * silently here if necessary
+        */
+       if (zr->buffer.depth == 15 || zr->buffer.depth == 16) {
+               end = (x + width) & ~1; /* round down */
+               x = (x + 1) & ~1;       /* round up */
+               width = end - x;
+       }
+
+       if (zr->buffer.depth == 24) {
+               end = (x + width) & ~3; /* round down */
+               x = (x + 3) & ~3;       /* round up */
+               width = end - x;
+       }
+
+       if (width > BUZ_MAX_WIDTH)
+               width = BUZ_MAX_WIDTH;
+       if (height > BUZ_MAX_HEIGHT)
+               height = BUZ_MAX_HEIGHT;
+
+       /* Check for vaild parameters */
+       if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
+           width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_window() - width = %d or height = %d invalid\n",
+                       ZR_DEVNAME(zr), width, height);
+               return -EINVAL;
+       }
+
+       fh->overlay_settings.x = x;
+       fh->overlay_settings.y = y;
+       fh->overlay_settings.width = width;
+       fh->overlay_settings.height = height;
+       fh->overlay_settings.clipcount = clipcount;
+
+       /*
+        * If an overlay is running, we have to switch it off
+        * and switch it on again in order to get the new settings in effect.
+        *
+        * We also want to avoid that the overlay mask is written
+        * when an overlay is running.
+        */
+
+       on = zr->v4l_overlay_active && !zr->v4l_memgrab_active &&
+           zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active != ZORAN_FREE;
+       if (on)
+               zr36057_overlay(zr, 0);
+
+       /*
+        *   Write the overlay mask if clips are wanted.
+        *   We prefer a bitmap.
+        */
+       if (bitmap) {
+               /* fake value - it just means we want clips */
+               fh->overlay_settings.clipcount = 1;
+
+               if (copy_from_user(fh->overlay_mask, bitmap,
+                                  (width * height + 7) / 8)) {
+                       return -EFAULT;
+               }
+       } else if (clipcount > 0) {
+               /* write our own bitmap from the clips */
+               vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4));
+               if (vcp == NULL) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: setup_window() - Alloc of clip mask failed\n",
+                               ZR_DEVNAME(zr));
+                       return -ENOMEM;
+               }
+               if (copy_from_user
+                   (vcp, clips, sizeof(struct video_clip) * clipcount)) {
+                       vfree(vcp);
+                       return -EFAULT;
+               }
+               write_overlay_mask(file, vcp, clipcount);
+               vfree(vcp);
+       }
+
+       fh->overlay_settings.is_set = 1;
+       if (fh->overlay_active != ZORAN_FREE &&
+           zr->overlay_active != ZORAN_FREE)
+               zr->overlay_settings = fh->overlay_settings;
+
+       if (on)
+               zr36057_overlay(zr, 1);
+
+       /* Make sure the changes come into effect */
+       return wait_grab_pending(zr);
+}
+
+static int
+setup_overlay (struct file *file,
+              int          on)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       /* If there is nothing to do, return immediatly */
+       if ((on && fh->overlay_active != ZORAN_FREE) ||
+           (!on && fh->overlay_active == ZORAN_FREE))
+               return 0;
+
+       /* check whether we're touching someone else's overlay */
+       if (on && zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_overlay() - overlay is already active for another session\n",
+                       ZR_DEVNAME(zr));
+               return -EBUSY;
+       }
+       if (!on && zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: setup_overlay() - you cannot cancel someone else's session\n",
+                       ZR_DEVNAME(zr));
+               return -EPERM;
+       }
+
+       if (on == 0) {
+               zr->overlay_active = fh->overlay_active = ZORAN_FREE;
+               zr->v4l_overlay_active = 0;
+               /* When a grab is running, the video simply
+                * won't be switched on any more */
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+       } else {
+               if (!zr->buffer.base || !fh->overlay_settings.is_set) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: setup_overlay() - buffer or window not set\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+               if (!fh->overlay_settings.format) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: setup_overlay() - no overlay format set\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+               zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
+               zr->v4l_overlay_active = 1;
+               zr->overlay_mask = fh->overlay_mask;
+               zr->overlay_settings = fh->overlay_settings;
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 1);
+               /* When a grab is running, the video will be
+                * switched on when grab is finished */
+       }
+
+       /* Make sure the changes come into effect */
+       return wait_grab_pending(zr);
+}
+
+       /* get the status of a buffer in the clients buffer queue */
+static int
+zoran_v4l2_buffer_status (struct file        *file,
+                         struct v4l2_buffer *buf,
+                         int                 num)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+
+               /* check range */
+               if (num < 0 || num >= fh->v4l_buffers.num_buffers ||
+                   !fh->v4l_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+
+               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               buf->length = fh->v4l_buffers.buffer_size;
+
+               /* get buffer */
+               buf->bytesused = fh->v4l_buffers.buffer[num].bs.length;
+               if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE ||
+                   fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) {
+                       buf->sequence = fh->v4l_buffers.buffer[num].bs.seq;
+                       buf->flags |= V4L2_BUF_FLAG_DONE;
+                       buf->timestamp =
+                           fh->v4l_buffers.buffer[num].bs.timestamp;
+               } else {
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               }
+
+               if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)
+                       buf->field = V4L2_FIELD_TOP;
+               else
+                       buf->field = V4L2_FIELD_INTERLACED;
+
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+
+               /* check range */
+               if (num < 0 || num >= fh->jpg_buffers.num_buffers ||
+                   !fh->jpg_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+
+               buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
+                             V4L2_BUF_TYPE_VIDEO_CAPTURE :
+                             V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               buf->length = fh->jpg_buffers.buffer_size;
+
+               /* these variables are only written after frame has been captured */
+               if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE ||
+                   fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) {
+                       buf->sequence = fh->jpg_buffers.buffer[num].bs.seq;
+                       buf->timestamp =
+                           fh->jpg_buffers.buffer[num].bs.timestamp;
+                       buf->bytesused =
+                           fh->jpg_buffers.buffer[num].bs.length;
+                       buf->flags |= V4L2_BUF_FLAG_DONE;
+               } else {
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               }
+
+               /* which fields are these? */
+               if (fh->jpg_settings.TmpDcm != 1)
+                       buf->field =
+                           fh->jpg_settings.
+                           odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+               else
+                       buf->field =
+                           fh->jpg_settings.
+                           odd_even ? V4L2_FIELD_SEQ_TB :
+                           V4L2_FIELD_SEQ_BT;
+
+               break;
+
+       default:
+
+               dprintk(5,
+                       KERN_ERR
+                       "%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n",
+                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
+               return -EINVAL;
+       }
+
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->index = num;
+       buf->m.offset = buf->length * num;
+
+       return 0;
+}
+
+static int
+zoran_set_norm (struct zoran *zr,
+               int           norm) /* VIDEO_MODE_* */
+{
+       int norm_encoder, on;
+
+       if (zr->v4l_buffers.active != ZORAN_FREE ||
+           zr->jpg_buffers.active != ZORAN_FREE) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: set_norm() called while in playback/capture mode\n",
+                       ZR_DEVNAME(zr));
+               return -EBUSY;
+       }
+
+       if (lock_norm && norm != zr->norm) {
+               if (lock_norm > 1) {
+                       dprintk(1,
+                               KERN_WARNING
+                               "%s: set_norm() - TV standard is locked, can not switch norm\n",
+                               ZR_DEVNAME(zr));
+                       return -EPERM;
+               } else {
+                       dprintk(1,
+                               KERN_WARNING
+                               "%s: set_norm() - TV standard is locked, norm was not changed\n",
+                               ZR_DEVNAME(zr));
+                       norm = zr->norm;
+               }
+       }
+
+       if (norm != VIDEO_MODE_AUTO &&
+           (norm < 0 || norm >= zr->card.norms ||
+            !zr->card.tvn[norm])) {
+               dprintk(1,
+                       KERN_ERR "%s: set_norm() - unsupported norm %d\n",
+                       ZR_DEVNAME(zr), norm);
+               return -EINVAL;
+       }
+
+       if (norm == VIDEO_MODE_AUTO) {
+               int status;
+
+               /* if we have autodetect, ... */
+               struct video_decoder_capability caps;
+               decoder_command(zr, DECODER_GET_CAPABILITIES, &caps);
+               if (!(caps.flags & VIDEO_DECODER_AUTO)) {
+                       dprintk(1, KERN_ERR "%s: norm=auto unsupported\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+
+               decoder_command(zr, DECODER_SET_NORM, &norm);
+
+               /* let changes come into effect */
+               ssleep(2);
+
+               decoder_command(zr, DECODER_GET_STATUS, &status);
+               if (!(status & DECODER_STATUS_GOOD)) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: set_norm() - no norm detected\n",
+                               ZR_DEVNAME(zr));
+                       /* reset norm */
+                       decoder_command(zr, DECODER_SET_NORM, &zr->norm);
+                       return -EIO;
+               }
+
+               if (status & DECODER_STATUS_NTSC)
+                       norm = VIDEO_MODE_NTSC;
+               else if (status & DECODER_STATUS_SECAM)
+                       norm = VIDEO_MODE_SECAM;
+               else
+                       norm = VIDEO_MODE_PAL;
+       }
+       zr->timing = zr->card.tvn[norm];
+       norm_encoder = norm;
+
+       /* We switch overlay off and on since a change in the
+        * norm needs different VFE settings */
+       on = zr->overlay_active && !zr->v4l_memgrab_active;
+       if (on)
+               zr36057_overlay(zr, 0);
+
+       decoder_command(zr, DECODER_SET_NORM, &norm);
+       encoder_command(zr, ENCODER_SET_NORM, &norm_encoder);
+
+       if (on)
+               zr36057_overlay(zr, 1);
+
+       /* Make sure the changes come into effect */
+       zr->norm = norm;
+
+       return 0;
+}
+
+static int
+zoran_set_input (struct zoran *zr,
+                int           input)
+{
+       int realinput;
+
+       if (input == zr->input) {
+               return 0;
+       }
+
+       if (zr->v4l_buffers.active != ZORAN_FREE ||
+           zr->jpg_buffers.active != ZORAN_FREE) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: set_input() called while in playback/capture mode\n",
+                       ZR_DEVNAME(zr));
+               return -EBUSY;
+       }
+
+       if (input < 0 || input >= zr->card.inputs) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: set_input() - unnsupported input %d\n",
+                       ZR_DEVNAME(zr), input);
+               return -EINVAL;
+       }
+
+       realinput = zr->card.input[input].muxsel;
+       zr->input = input;
+
+       decoder_command(zr, DECODER_SET_INPUT, &realinput);
+
+       return 0;
+}
+
+/*
+ *   ioctl routine
+ */
+
+static int
+zoran_do_ioctl (struct inode *inode,
+               struct file  *file,
+               unsigned int  cmd,
+               void         *arg)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       /* CAREFUL: used in multiple places here */
+       struct zoran_jpg_settings settings;
+
+       /* we might have older buffers lying around... We don't want
+        * to wait, but we do want to try cleaning them up ASAP. So
+        * we try to obtain the lock and free them. If that fails, we
+        * don't do anything and wait for the next turn. In the end,
+        * zoran_close() or a new allocation will still free them...
+        * This is just a 'the sooner the better' extra 'feature'
+        *
+        * We don't free the buffers right on munmap() because that
+        * causes oopses (kfree() inside munmap() oopses for no
+        * apparent reason - it's also not reproduceable in any way,
+        * but moving the free code outside the munmap() handler fixes
+        * all this... If someone knows why, please explain me (Ronald)
+        */
+       if (mutex_trylock(&zr->resource_lock)) {
+               /* we obtained it! Let's try to free some things */
+               if (fh->jpg_buffers.ready_to_be_freed)
+                       jpg_fbuffer_free(file);
+               if (fh->v4l_buffers.ready_to_be_freed)
+                       v4l_fbuffer_free(file);
+
+               mutex_unlock(&zr->resource_lock);
+       }
+
+       switch (cmd) {
+
+       case VIDIOCGCAP:
+       {
+               struct video_capability *vcap = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
+
+               memset(vcap, 0, sizeof(struct video_capability));
+               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
+               vcap->type = ZORAN_VID_TYPE;
+
+               vcap->channels = zr->card.inputs;
+               vcap->audios = 0;
+               mutex_lock(&zr->resource_lock);
+               vcap->maxwidth = BUZ_MAX_WIDTH;
+               vcap->maxheight = BUZ_MAX_HEIGHT;
+               vcap->minwidth = BUZ_MIN_WIDTH;
+               vcap->minheight = BUZ_MIN_HEIGHT;
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOCGCHAN:
+       {
+               struct video_channel *vchan = arg;
+               int channel = vchan->channel;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n",
+                       ZR_DEVNAME(zr), vchan->channel);
+
+               memset(vchan, 0, sizeof(struct video_channel));
+               if (channel > zr->card.inputs || channel < 0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOCGCHAN on not existing channel %d\n",
+                               ZR_DEVNAME(zr), channel);
+                       return -EINVAL;
+               }
+
+               strcpy(vchan->name, zr->card.input[channel].name);
+
+               vchan->tuners = 0;
+               vchan->flags = 0;
+               vchan->type = VIDEO_TYPE_CAMERA;
+               mutex_lock(&zr->resource_lock);
+               vchan->norm = zr->norm;
+               mutex_unlock(&zr->resource_lock);
+               vchan->channel = channel;
+
+               return 0;
+       }
+               break;
+
+               /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
+                *
+                * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
+                * *                                 ^^^^^^^
+                * * The famos BTTV driver has it implemented with a struct video_channel argument
+                * * and we follow it for compatibility reasons
+                * *
+                * * BTW: this is the only way the user can set the norm!
+                */
+
+       case VIDIOCSCHAN:
+       {
+               struct video_channel *vchan = arg;
+               int res;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOCSCHAN - channel=%d, norm=%d\n",
+                       ZR_DEVNAME(zr), vchan->channel, vchan->norm);
+
+               mutex_lock(&zr->resource_lock);
+               if ((res = zoran_set_input(zr, vchan->channel)))
+                       goto schan_unlock_and_return;
+               if ((res = zoran_set_norm(zr, vchan->norm)))
+                       goto schan_unlock_and_return;
+
+               /* Make sure the changes come into effect */
+               res = wait_grab_pending(zr);
+       schan_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOCGPICT:
+       {
+               struct video_picture *vpict = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr));
+
+               memset(vpict, 0, sizeof(struct video_picture));
+               mutex_lock(&zr->resource_lock);
+               vpict->hue = zr->hue;
+               vpict->brightness = zr->brightness;
+               vpict->contrast = zr->contrast;
+               vpict->colour = zr->saturation;
+               if (fh->overlay_settings.format) {
+                       vpict->depth = fh->overlay_settings.format->depth;
+                       vpict->palette = fh->overlay_settings.format->palette;
+               } else {
+                       vpict->depth = 0;
+               }
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOCSPICT:
+       {
+               struct video_picture *vpict = arg;
+               int i;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n",
+                       ZR_DEVNAME(zr), vpict->brightness, vpict->hue,
+                       vpict->colour, vpict->contrast, vpict->depth,
+                       vpict->palette);
+
+               for (i = 0; i < NUM_FORMATS; i++) {
+                       const struct zoran_format *fmt = &zoran_formats[i];
+
+                       if (fmt->palette != -1 &&
+                           fmt->flags & ZORAN_FORMAT_OVERLAY &&
+                           fmt->palette == vpict->palette &&
+                           fmt->depth == vpict->depth)
+                               break;
+               }
+               if (i == NUM_FORMATS) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOCSPICT - Invalid palette %d\n",
+                               ZR_DEVNAME(zr), vpict->palette);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+
+               decoder_command(zr, DECODER_SET_PICTURE, vpict);
+
+               zr->hue = vpict->hue;
+               zr->contrast = vpict->contrast;
+               zr->saturation = vpict->colour;
+               zr->brightness = vpict->brightness;
+
+               fh->overlay_settings.format = &zoran_formats[i];
+
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOCCAPTURE:
+       {
+               int *on = arg, res;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n",
+                       ZR_DEVNAME(zr), *on);
+
+               mutex_lock(&zr->resource_lock);
+               res = setup_overlay(file, *on);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOCGWIN:
+       {
+               struct video_window *vwin = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr));
+
+               memset(vwin, 0, sizeof(struct video_window));
+               mutex_lock(&zr->resource_lock);
+               vwin->x = fh->overlay_settings.x;
+               vwin->y = fh->overlay_settings.y;
+               vwin->width = fh->overlay_settings.width;
+               vwin->height = fh->overlay_settings.height;
+               mutex_unlock(&zr->resource_lock);
+               vwin->clipcount = 0;
+               return 0;
+       }
+               break;
+
+       case VIDIOCSWIN:
+       {
+               struct video_window *vwin = arg;
+               int res;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n",
+                       ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width,
+                       vwin->height, vwin->clipcount);
+
+               mutex_lock(&zr->resource_lock);
+               res =
+                   setup_window(file, vwin->x, vwin->y, vwin->width,
+                                vwin->height, vwin->clips,
+                                vwin->clipcount, NULL);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOCGFBUF:
+       {
+               struct video_buffer *vbuf = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+               *vbuf = zr->buffer;
+               mutex_unlock(&zr->resource_lock);
+               return 0;
+       }
+               break;
+
+       case VIDIOCSFBUF:
+       {
+               struct video_buffer *vbuf = arg;
+               int i, res = 0;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n",
+                       ZR_DEVNAME(zr), vbuf->base, vbuf->width,
+                       vbuf->height, vbuf->depth, vbuf->bytesperline);
+
+               for (i = 0; i < NUM_FORMATS; i++)
+                       if (zoran_formats[i].depth == vbuf->depth)
+                               break;
+               if (i == NUM_FORMATS) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOCSFBUF - invalid fbuf depth %d\n",
+                               ZR_DEVNAME(zr), vbuf->depth);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+               res =
+                   setup_fbuffer(file, vbuf->base, &zoran_formats[i],
+                                 vbuf->width, vbuf->height,
+                                 vbuf->bytesperline);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOCSYNC:
+       {
+               int *frame = arg, res;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n",
+                       ZR_DEVNAME(zr), *frame);
+
+               mutex_lock(&zr->resource_lock);
+               res = v4l_sync(file, *frame);
+               mutex_unlock(&zr->resource_lock);
+               if (!res)
+                       zr->v4l_sync_tail++;
+               return res;
+       }
+               break;
+
+       case VIDIOCMCAPTURE:
+       {
+               struct video_mmap *vmap = arg;
+               int res;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n",
+                       ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height,
+                       vmap->format);
+
+               mutex_lock(&zr->resource_lock);
+               res = v4l_grab(file, vmap);
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOCGMBUF:
+       {
+               struct video_mbuf *vmbuf = arg;
+               int i, res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr));
+
+               vmbuf->size =
+                   fh->v4l_buffers.num_buffers *
+                   fh->v4l_buffers.buffer_size;
+               vmbuf->frames = fh->v4l_buffers.num_buffers;
+               for (i = 0; i < vmbuf->frames; i++) {
+                       vmbuf->offsets[i] =
+                           i * fh->v4l_buffers.buffer_size;
+               }
+
+               mutex_lock(&zr->resource_lock);
+
+               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOCGMBUF - buffers already allocated\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto v4l1reqbuf_unlock_and_return;
+               }
+
+               if (v4l_fbuffer_alloc(file)) {
+                       res = -ENOMEM;
+                       goto v4l1reqbuf_unlock_and_return;
+               }
+
+               /* The next mmap will map the V4L buffers */
+               fh->map_mode = ZORAN_MAP_MODE_RAW;
+       v4l1reqbuf_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOCGUNIT:
+       {
+               struct video_unit *vunit = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr));
+
+               vunit->video = zr->video_dev->minor;
+               vunit->vbi = VIDEO_NO_UNIT;
+               vunit->radio = VIDEO_NO_UNIT;
+               vunit->audio = VIDEO_NO_UNIT;
+               vunit->teletext = VIDEO_NO_UNIT;
+
+               return 0;
+       }
+               break;
+
+               /*
+                * RJ: In principal we could support subcaptures for V4L grabbing.
+                *     Not even the famous BTTV driver has them, however.
+                *     If there should be a strong demand, one could consider
+                *     to implement them.
+                */
+       case VIDIOCGCAPTURE:
+       {
+               dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+               break;
+
+       case VIDIOCSCAPTURE:
+       {
+               dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+               break;
+
+       case BUZIOC_G_PARAMS:
+       {
+               struct zoran_params *bparams = arg;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr));
+
+               memset(bparams, 0, sizeof(struct zoran_params));
+               bparams->major_version = MAJOR_VERSION;
+               bparams->minor_version = MINOR_VERSION;
+
+               mutex_lock(&zr->resource_lock);
+
+               bparams->norm = zr->norm;
+               bparams->input = zr->input;
+
+               bparams->decimation = fh->jpg_settings.decimation;
+               bparams->HorDcm = fh->jpg_settings.HorDcm;
+               bparams->VerDcm = fh->jpg_settings.VerDcm;
+               bparams->TmpDcm = fh->jpg_settings.TmpDcm;
+               bparams->field_per_buff = fh->jpg_settings.field_per_buff;
+               bparams->img_x = fh->jpg_settings.img_x;
+               bparams->img_y = fh->jpg_settings.img_y;
+               bparams->img_width = fh->jpg_settings.img_width;
+               bparams->img_height = fh->jpg_settings.img_height;
+               bparams->odd_even = fh->jpg_settings.odd_even;
+
+               bparams->quality = fh->jpg_settings.jpg_comp.quality;
+               bparams->APPn = fh->jpg_settings.jpg_comp.APPn;
+               bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len;
+               memcpy(bparams->APP_data,
+                      fh->jpg_settings.jpg_comp.APP_data,
+                      sizeof(bparams->APP_data));
+               bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len;
+               memcpy(bparams->COM_data,
+                      fh->jpg_settings.jpg_comp.COM_data,
+                      sizeof(bparams->COM_data));
+               bparams->jpeg_markers =
+                   fh->jpg_settings.jpg_comp.jpeg_markers;
+
+               mutex_unlock(&zr->resource_lock);
+
+               bparams->VFIFO_FB = 0;
+
+               return 0;
+       }
+               break;
+
+       case BUZIOC_S_PARAMS:
+       {
+               struct zoran_params *bparams = arg;
+               int res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr));
+
+               settings.decimation = bparams->decimation;
+               settings.HorDcm = bparams->HorDcm;
+               settings.VerDcm = bparams->VerDcm;
+               settings.TmpDcm = bparams->TmpDcm;
+               settings.field_per_buff = bparams->field_per_buff;
+               settings.img_x = bparams->img_x;
+               settings.img_y = bparams->img_y;
+               settings.img_width = bparams->img_width;
+               settings.img_height = bparams->img_height;
+               settings.odd_even = bparams->odd_even;
+
+               settings.jpg_comp.quality = bparams->quality;
+               settings.jpg_comp.APPn = bparams->APPn;
+               settings.jpg_comp.APP_len = bparams->APP_len;
+               memcpy(settings.jpg_comp.APP_data, bparams->APP_data,
+                      sizeof(bparams->APP_data));
+               settings.jpg_comp.COM_len = bparams->COM_len;
+               memcpy(settings.jpg_comp.COM_data, bparams->COM_data,
+                      sizeof(bparams->COM_data));
+               settings.jpg_comp.jpeg_markers = bparams->jpeg_markers;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (zr->codec_mode != BUZ_MODE_IDLE) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto sparams_unlock_and_return;
+               }
+
+               /* Check the params first before overwriting our
+                * nternal values */
+               if (zoran_check_jpg_settings(zr, &settings)) {
+                       res = -EINVAL;
+                       goto sparams_unlock_and_return;
+               }
+
+               fh->jpg_settings = settings;
+       sparams_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case BUZIOC_REQBUFS:
+       {
+               struct zoran_requestbuffers *breq = arg;
+               int res = 0;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n",
+                       ZR_DEVNAME(zr), breq->count, breq->size);
+
+               /* Enforce reasonable lower and upper limits */
+               if (breq->count < 4)
+                       breq->count = 4;        /* Could be choosen smaller */
+               if (breq->count > jpg_nbufs)
+                       breq->count = jpg_nbufs;
+               breq->size = PAGE_ALIGN(breq->size);
+               if (breq->size < 8192)
+                       breq->size = 8192;      /* Arbitrary */
+               /* breq->size is limited by 1 page for the stat_com
+                * tables to a Maximum of 2 MB */
+               if (breq->size > jpg_bufsize)
+                       breq->size = jpg_bufsize;
+               if (fh->jpg_buffers.need_contiguous &&
+                   breq->size > MAX_KMALLOC_MEM)
+                       breq->size = MAX_KMALLOC_MEM;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: BUZIOC_REQBUFS - buffers allready allocated\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+                       goto jpgreqbuf_unlock_and_return;
+               }
+
+               fh->jpg_buffers.num_buffers = breq->count;
+               fh->jpg_buffers.buffer_size = breq->size;
+
+               if (jpg_fbuffer_alloc(file)) {
+                       res = -ENOMEM;
+                       goto jpgreqbuf_unlock_and_return;
+               }
+
+               /* The next mmap will map the MJPEG buffers - could
+                * also be *_PLAY, but it doesn't matter here */
+               fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
+       jpgreqbuf_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case BUZIOC_QBUF_CAPT:
+       {
+               int *frame = arg, res;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n",
+                       ZR_DEVNAME(zr), *frame);
+
+               mutex_lock(&zr->resource_lock);
+               res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case BUZIOC_QBUF_PLAY:
+       {
+               int *frame = arg, res;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n",
+                       ZR_DEVNAME(zr), *frame);
+
+               mutex_lock(&zr->resource_lock);
+               res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case BUZIOC_SYNC:
+       {
+               struct zoran_sync *bsync = arg;
+               int res;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+               res = jpg_sync(file, bsync);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case BUZIOC_G_STATUS:
+       {
+               struct zoran_status *bstat = arg;
+               int norm, input, status, res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr));
+
+               if (zr->codec_mode != BUZ_MODE_IDLE) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: BUZIOC_G_STATUS called but Buz in capture/playback mode\n",
+                               ZR_DEVNAME(zr));
+                       return -EINVAL;
+               }
+
+               input = zr->card.input[bstat->input].muxsel;
+               norm = VIDEO_MODE_AUTO;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (zr->codec_mode != BUZ_MODE_IDLE) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: BUZIOC_G_STATUS called, but Buz in capture/playback mode\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto gstat_unlock_and_return;
+               }
+
+               decoder_command(zr, DECODER_SET_INPUT, &input);
+               decoder_command(zr, DECODER_SET_NORM, &norm);
+
+               /* sleep 1 second */
+               ssleep(1);
+
+               /* Get status of video decoder */
+               decoder_command(zr, DECODER_GET_STATUS, &status);
+
+               /* restore previous input and norm */
+               input = zr->card.input[zr->input].muxsel;
+               decoder_command(zr, DECODER_SET_INPUT, &input);
+               decoder_command(zr, DECODER_SET_NORM, &zr->norm);
+       gstat_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               if (!res) {
+                       bstat->signal =
+                           (status & DECODER_STATUS_GOOD) ? 1 : 0;
+                       if (status & DECODER_STATUS_NTSC)
+                               bstat->norm = VIDEO_MODE_NTSC;
+                       else if (status & DECODER_STATUS_SECAM)
+                               bstat->norm = VIDEO_MODE_SECAM;
+                       else
+                               bstat->norm = VIDEO_MODE_PAL;
+
+                       bstat->color =
+                           (status & DECODER_STATUS_COLOR) ? 1 : 0;
+               }
+
+               return res;
+       }
+               break;
+
+               /* The new video4linux2 capture interface - much nicer than video4linux1, since
+                * it allows for integrating the JPEG capturing calls inside standard v4l2
+                */
+
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
+
+               memset(cap, 0, sizeof(*cap));
+               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+               strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
+               snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+                        pci_name(zr->pci_dev));
+               cap->version =
+                   KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
+                                  RELEASE_VERSION);
+               cap->capabilities = ZORAN_V4L2_VID_FLAGS;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *fmt = arg;
+               int index = fmt->index, num = -1, i, flag = 0, type =
+                   fmt->type;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUM_FMT - index=%d\n",
+                       ZR_DEVNAME(zr), fmt->index);
+
+               switch (fmt->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       flag = ZORAN_FORMAT_CAPTURE;
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       flag = ZORAN_FORMAT_PLAYBACK;
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       flag = ZORAN_FORMAT_OVERLAY;
+                       break;
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_ENUM_FMT - unknown type %d\n",
+                               ZR_DEVNAME(zr), fmt->type);
+                       return -EINVAL;
+               }
+
+               for (i = 0; i < NUM_FORMATS; i++) {
+                       if (zoran_formats[i].flags & flag)
+                               num++;
+                       if (num == fmt->index)
+                               break;
+               }
+               if (fmt->index < 0 /* late, but not too late */  ||
+                   i == NUM_FORMATS)
+                       return -EINVAL;
+
+               memset(fmt, 0, sizeof(*fmt));
+               fmt->index = index;
+               fmt->type = type;
+               strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
+               fmt->pixelformat = zoran_formats[i].fourcc;
+               if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
+                       fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *fmt = arg;
+               int type = fmt->type;
+
+               dprintk(5, KERN_DEBUG "%s: VIDIOC_G_FMT\n", ZR_DEVNAME(zr));
+
+               memset(fmt, 0, sizeof(*fmt));
+               fmt->type = type;
+
+               switch (fmt->type) {
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+
+                       mutex_lock(&zr->resource_lock);
+
+                       fmt->fmt.win.w.left = fh->overlay_settings.x;
+                       fmt->fmt.win.w.top = fh->overlay_settings.y;
+                       fmt->fmt.win.w.width = fh->overlay_settings.width;
+                       fmt->fmt.win.w.height =
+                           fh->overlay_settings.height;
+                       if (fh->overlay_settings.width * 2 >
+                           BUZ_MAX_HEIGHT)
+                               fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
+                       else
+                               fmt->fmt.win.field = V4L2_FIELD_TOP;
+
+                       mutex_unlock(&zr->resource_lock);
+
+                       break;
+
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+
+                       mutex_lock(&zr->resource_lock);
+
+                       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+                           fh->map_mode == ZORAN_MAP_MODE_RAW) {
+
+                               fmt->fmt.pix.width =
+                                   fh->v4l_settings.width;
+                               fmt->fmt.pix.height =
+                                   fh->v4l_settings.height;
+                               fmt->fmt.pix.sizeimage =
+                                   fh->v4l_settings.bytesperline *
+                                   fh->v4l_settings.height;
+                               fmt->fmt.pix.pixelformat =
+                                   fh->v4l_settings.format->fourcc;
+                               fmt->fmt.pix.colorspace =
+                                   fh->v4l_settings.format->colorspace;
+                               fmt->fmt.pix.bytesperline =
+                                   fh->v4l_settings.bytesperline;
+                               if (BUZ_MAX_HEIGHT <
+                                   (fh->v4l_settings.height * 2))
+                                       fmt->fmt.pix.field =
+                                           V4L2_FIELD_INTERLACED;
+                               else
+                                       fmt->fmt.pix.field =
+                                           V4L2_FIELD_TOP;
+
+                       } else {
+
+                               fmt->fmt.pix.width =
+                                   fh->jpg_settings.img_width /
+                                   fh->jpg_settings.HorDcm;
+                               fmt->fmt.pix.height =
+                                   fh->jpg_settings.img_height /
+                                   (fh->jpg_settings.VerDcm *
+                                    fh->jpg_settings.TmpDcm);
+                               fmt->fmt.pix.sizeimage =
+                                   zoran_v4l2_calc_bufsize(&fh->
+                                                           jpg_settings);
+                               fmt->fmt.pix.pixelformat =
+                                   V4L2_PIX_FMT_MJPEG;
+                               if (fh->jpg_settings.TmpDcm == 1)
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_SEQ_BT :
+                                            V4L2_FIELD_SEQ_BT);
+                               else
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_TOP :
+                                            V4L2_FIELD_BOTTOM);
+
+                               fmt->fmt.pix.bytesperline = 0;
+                               fmt->fmt.pix.colorspace =
+                                   V4L2_COLORSPACE_SMPTE170M;
+                       }
+
+                       mutex_unlock(&zr->resource_lock);
+
+                       break;
+
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_G_FMT - unsupported type %d\n",
+                               ZR_DEVNAME(zr), fmt->type);
+                       return -EINVAL;
+               }
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *fmt = arg;
+               int i, res = 0;
+               __le32 printformat;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ",
+                       ZR_DEVNAME(zr), fmt->type);
+
+               switch (fmt->type) {
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+
+                       dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
+                               fmt->fmt.win.w.left, fmt->fmt.win.w.top,
+                               fmt->fmt.win.w.width,
+                               fmt->fmt.win.w.height,
+                               fmt->fmt.win.clipcount,
+                               fmt->fmt.win.bitmap);
+                       mutex_lock(&zr->resource_lock);
+                       res =
+                           setup_window(file, fmt->fmt.win.w.left,
+                                        fmt->fmt.win.w.top,
+                                        fmt->fmt.win.w.width,
+                                        fmt->fmt.win.w.height,
+                                        (struct video_clip __user *)
+                                          fmt->fmt.win.clips,
+                                        fmt->fmt.win.clipcount,
+                                        fmt->fmt.win.bitmap);
+                       mutex_unlock(&zr->resource_lock);
+                       return res;
+                       break;
+
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+
+                       printformat =
+                           __cpu_to_le32(fmt->fmt.pix.pixelformat);
+                       dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
+                               fmt->fmt.pix.width, fmt->fmt.pix.height,
+                               fmt->fmt.pix.pixelformat,
+                               (char *) &printformat);
+
+                       /* we can be requested to do JPEG/raw playback/capture */
+                       if (!
+                           (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                            (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                             fmt->fmt.pix.pixelformat ==
+                             V4L2_PIX_FMT_MJPEG))) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: VIDIOC_S_FMT - unknown type %d/0x%x(%4.4s) combination\n",
+                                       ZR_DEVNAME(zr), fmt->type,
+                                       fmt->fmt.pix.pixelformat,
+                                       (char *) &printformat);
+                               return -EINVAL;
+                       }
+
+                       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
+                               mutex_lock(&zr->resource_lock);
+
+                               settings = fh->jpg_settings;
+
+                               if (fh->v4l_buffers.allocated ||
+                                   fh->jpg_buffers.allocated) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+                                               ZR_DEVNAME(zr));
+                                       res = -EBUSY;
+                                       goto sfmtjpg_unlock_and_return;
+                               }
+
+                               /* we actually need to set 'real' parameters now */
+                               if ((fmt->fmt.pix.height * 2) >
+                                   BUZ_MAX_HEIGHT)
+                                       settings.TmpDcm = 1;
+                               else
+                                       settings.TmpDcm = 2;
+                               settings.decimation = 0;
+                               if (fmt->fmt.pix.height <=
+                                   fh->jpg_settings.img_height / 2)
+                                       settings.VerDcm = 2;
+                               else
+                                       settings.VerDcm = 1;
+                               if (fmt->fmt.pix.width <=
+                                   fh->jpg_settings.img_width / 4)
+                                       settings.HorDcm = 4;
+                               else if (fmt->fmt.pix.width <=
+                                        fh->jpg_settings.img_width / 2)
+                                       settings.HorDcm = 2;
+                               else
+                                       settings.HorDcm = 1;
+                               if (settings.TmpDcm == 1)
+                                       settings.field_per_buff = 2;
+                               else
+                                       settings.field_per_buff = 1;
+
+                               /* check */
+                               if ((res =
+                                    zoran_check_jpg_settings(zr,
+                                                             &settings)))
+                                       goto sfmtjpg_unlock_and_return;
+
+                               /* it's ok, so set them */
+                               fh->jpg_settings = settings;
+
+                               /* tell the user what we actually did */
+                               fmt->fmt.pix.width =
+                                   settings.img_width / settings.HorDcm;
+                               fmt->fmt.pix.height =
+                                   settings.img_height * 2 /
+                                   (settings.TmpDcm * settings.VerDcm);
+                               if (settings.TmpDcm == 1)
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_SEQ_TB :
+                                            V4L2_FIELD_SEQ_BT);
+                               else
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_TOP :
+                                            V4L2_FIELD_BOTTOM);
+                               fh->jpg_buffers.buffer_size =
+                                   zoran_v4l2_calc_bufsize(&fh->
+                                                           jpg_settings);
+                               fmt->fmt.pix.bytesperline = 0;
+                               fmt->fmt.pix.sizeimage =
+                                   fh->jpg_buffers.buffer_size;
+                               fmt->fmt.pix.colorspace =
+                                   V4L2_COLORSPACE_SMPTE170M;
+
+                               /* we hereby abuse this variable to show that
+                                * we're gonna do mjpeg capture */
+                               fh->map_mode =
+                                   (fmt->type ==
+                                    V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
+                                   ZORAN_MAP_MODE_JPG_REC :
+                                   ZORAN_MAP_MODE_JPG_PLAY;
+                       sfmtjpg_unlock_and_return:
+                               mutex_unlock(&zr->resource_lock);
+                       } else {
+                               for (i = 0; i < NUM_FORMATS; i++)
+                                       if (fmt->fmt.pix.pixelformat ==
+                                           zoran_formats[i].fourcc)
+                                               break;
+                               if (i == NUM_FORMATS) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n",
+                                               ZR_DEVNAME(zr),
+                                               fmt->fmt.pix.pixelformat,
+                                               (char *) &printformat);
+                                       return -EINVAL;
+                               }
+                               mutex_lock(&zr->resource_lock);
+                               if (fh->jpg_buffers.allocated ||
+                                   (fh->v4l_buffers.allocated &&
+                                    fh->v4l_buffers.active !=
+                                    ZORAN_FREE)) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+                                               ZR_DEVNAME(zr));
+                                       res = -EBUSY;
+                                       goto sfmtv4l_unlock_and_return;
+                               }
+                               if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+                                       fmt->fmt.pix.height =
+                                           BUZ_MAX_HEIGHT;
+                               if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+                                       fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+
+                               if ((res =
+                                    zoran_v4l_set_format(file,
+                                                         fmt->fmt.pix.
+                                                         width,
+                                                         fmt->fmt.pix.
+                                                         height,
+                                                         &zoran_formats
+                                                         [i])))
+                                       goto sfmtv4l_unlock_and_return;
+
+                               /* tell the user the
+                                * results/missing stuff */
+                               fmt->fmt.pix.bytesperline =
+                                       fh->v4l_settings.bytesperline;
+                               fmt->fmt.pix.sizeimage =
+                                       fh->v4l_settings.height *
+                                       fh->v4l_settings.bytesperline;
+                               fmt->fmt.pix.colorspace =
+                                       fh->v4l_settings.format->colorspace;
+                               if (BUZ_MAX_HEIGHT <
+                                   (fh->v4l_settings.height * 2))
+                                       fmt->fmt.pix.field =
+                                           V4L2_FIELD_INTERLACED;
+                               else
+                                       fmt->fmt.pix.field =
+                                           V4L2_FIELD_TOP;
+
+                               fh->map_mode = ZORAN_MAP_MODE_RAW;
+                       sfmtv4l_unlock_and_return:
+                               mutex_unlock(&zr->resource_lock);
+                       }
+
+                       break;
+
+               default:
+                       dprintk(3, "unsupported\n");
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_S_FMT - unsupported type %d\n",
+                               ZR_DEVNAME(zr), fmt->type);
+                       return -EINVAL;
+               }
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_G_FBUF:
+       {
+               struct v4l2_framebuffer *fb = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr));
+
+               memset(fb, 0, sizeof(*fb));
+               mutex_lock(&zr->resource_lock);
+               fb->base = zr->buffer.base;
+               fb->fmt.width = zr->buffer.width;
+               fb->fmt.height = zr->buffer.height;
+               if (zr->overlay_settings.format) {
+                       fb->fmt.pixelformat =
+                               fh->overlay_settings.format->fourcc;
+               }
+               fb->fmt.bytesperline = zr->buffer.bytesperline;
+               mutex_unlock(&zr->resource_lock);
+               fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
+               fb->fmt.field = V4L2_FIELD_INTERLACED;
+               fb->flags = V4L2_FBUF_FLAG_OVERLAY;
+               fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_FBUF:
+       {
+               int i, res = 0;
+               struct v4l2_framebuffer *fb = arg;
+               __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOC_S_FBUF - base=0x%p, size=%dx%d, bpl=%d, fmt=0x%x (%4.4s)\n",
+                       ZR_DEVNAME(zr), fb->base, fb->fmt.width, fb->fmt.height,
+                       fb->fmt.bytesperline, fb->fmt.pixelformat,
+                       (char *) &printformat);
+
+               for (i = 0; i < NUM_FORMATS; i++)
+                       if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
+                               break;
+               if (i == NUM_FORMATS) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
+                               ZR_DEVNAME(zr), fb->fmt.pixelformat,
+                               (char *) &printformat);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+               res =
+                   setup_fbuffer(file, fb->base, &zoran_formats[i],
+                                 fb->fmt.width, fb->fmt.height,
+                                 fb->fmt.bytesperline);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_OVERLAY:
+       {
+               int *on = arg, res;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n",
+                       ZR_DEVNAME(zr), *on);
+
+               mutex_lock(&zr->resource_lock);
+               res = setup_overlay(file, *on);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_REQBUFS:
+       {
+               struct v4l2_requestbuffers *req = arg;
+               int res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_REQBUFS - type=%d\n",
+                       ZR_DEVNAME(zr), req->type);
+
+               if (req->memory != V4L2_MEMORY_MMAP) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: only MEMORY_MMAP capture is supported, not %d\n",
+                               ZR_DEVNAME(zr), req->memory);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+
+               if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_REQBUFS - buffers allready allocated\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+                       goto v4l2reqbuf_unlock_and_return;
+               }
+
+               if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
+                   req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+
+                       /* control user input */
+                       if (req->count < 2)
+                               req->count = 2;
+                       if (req->count > v4l_nbufs)
+                               req->count = v4l_nbufs;
+                       fh->v4l_buffers.num_buffers = req->count;
+
+                       if (v4l_fbuffer_alloc(file)) {
+                               res = -ENOMEM;
+                               goto v4l2reqbuf_unlock_and_return;
+                       }
+
+                       /* The next mmap will map the V4L buffers */
+                       fh->map_mode = ZORAN_MAP_MODE_RAW;
+
+               } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
+                          fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+
+                       /* we need to calculate size ourselves now */
+                       if (req->count < 4)
+                               req->count = 4;
+                       if (req->count > jpg_nbufs)
+                               req->count = jpg_nbufs;
+                       fh->jpg_buffers.num_buffers = req->count;
+                       fh->jpg_buffers.buffer_size =
+                           zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+                       if (jpg_fbuffer_alloc(file)) {
+                               res = -ENOMEM;
+                               goto v4l2reqbuf_unlock_and_return;
+                       }
+
+                       /* The next mmap will map the MJPEG buffers */
+                       if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
+                       else
+                               fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
+
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_REQBUFS - unknown type %d\n",
+                               ZR_DEVNAME(zr), req->type);
+                       res = -EINVAL;
+                       goto v4l2reqbuf_unlock_and_return;
+               }
+       v4l2reqbuf_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_QUERYBUF:
+       {
+               struct v4l2_buffer *buf = arg;
+               __u32 type = buf->type;
+               int index = buf->index, res;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n",
+                       ZR_DEVNAME(zr), buf->index, buf->type);
+
+               memset(buf, 0, sizeof(*buf));
+               buf->type = type;
+               buf->index = index;
+
+               mutex_lock(&zr->resource_lock);
+               res = zoran_v4l2_buffer_status(file, buf, buf->index);
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_QBUF:
+       {
+               struct v4l2_buffer *buf = arg;
+               int res = 0, codec_mode, buf_type;
+
+               dprintk(3,
+                       KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n",
+                       ZR_DEVNAME(zr), buf->type, buf->index);
+
+               mutex_lock(&zr->resource_lock);
+
+               switch (fh->map_mode) {
+               case ZORAN_MAP_MODE_RAW:
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                               res = -EINVAL;
+                               goto qbuf_unlock_and_return;
+                       }
+
+                       res = zoran_v4l_queue_frame(file, buf->index);
+                       if (res)
+                               goto qbuf_unlock_and_return;
+                       if (!zr->v4l_memgrab_active &&
+                           fh->v4l_buffers.active == ZORAN_LOCKED)
+                               zr36057_set_memgrab(zr, 1);
+                       break;
+
+               case ZORAN_MAP_MODE_JPG_REC:
+               case ZORAN_MAP_MODE_JPG_PLAY:
+                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+                               buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+                               codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
+                       } else {
+                               buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                               codec_mode = BUZ_MODE_MOTION_COMPRESS;
+                       }
+
+                       if (buf->type != buf_type) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                               res = -EINVAL;
+                               goto qbuf_unlock_and_return;
+                       }
+
+                       res =
+                           zoran_jpg_queue_frame(file, buf->index,
+                                                 codec_mode);
+                       if (res != 0)
+                               goto qbuf_unlock_and_return;
+                       if (zr->codec_mode == BUZ_MODE_IDLE &&
+                           fh->jpg_buffers.active == ZORAN_LOCKED) {
+                               zr36057_enable_jpg(zr, codec_mode);
+                       }
+                       break;
+
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_QBUF - unsupported type %d\n",
+                               ZR_DEVNAME(zr), buf->type);
+                       res = -EINVAL;
+                       goto qbuf_unlock_and_return;
+               }
+       qbuf_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_DQBUF:
+       {
+               struct v4l2_buffer *buf = arg;
+               int res = 0, buf_type, num = -1;        /* compiler borks here (?) */
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n",
+                       ZR_DEVNAME(zr), buf->type);
+
+               mutex_lock(&zr->resource_lock);
+
+               switch (fh->map_mode) {
+               case ZORAN_MAP_MODE_RAW:
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                               res = -EINVAL;
+                               goto dqbuf_unlock_and_return;
+                       }
+
+                       num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+                       if (file->f_flags & O_NONBLOCK &&
+                           zr->v4l_buffers.buffer[num].state !=
+                           BUZ_STATE_DONE) {
+                               res = -EAGAIN;
+                               goto dqbuf_unlock_and_return;
+                       }
+                       res = v4l_sync(file, num);
+                       if (res)
+                               goto dqbuf_unlock_and_return;
+                       else
+                               zr->v4l_sync_tail++;
+                       res = zoran_v4l2_buffer_status(file, buf, num);
+                       break;
+
+               case ZORAN_MAP_MODE_JPG_REC:
+               case ZORAN_MAP_MODE_JPG_PLAY:
+               {
+                       struct zoran_sync bs;
+
+                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
+                               buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+                       else
+                               buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+                       if (buf->type != buf_type) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                               res = -EINVAL;
+                               goto dqbuf_unlock_and_return;
+                       }
+
+                       num =
+                           zr->jpg_pend[zr->
+                                        jpg_que_tail & BUZ_MASK_FRAME];
+
+                       if (file->f_flags & O_NONBLOCK &&
+                           zr->jpg_buffers.buffer[num].state !=
+                           BUZ_STATE_DONE) {
+                               res = -EAGAIN;
+                               goto dqbuf_unlock_and_return;
+                       }
+                       res = jpg_sync(file, &bs);
+                       if (res)
+                               goto dqbuf_unlock_and_return;
+                       res =
+                           zoran_v4l2_buffer_status(file, buf, bs.frame);
+                       break;
+               }
+
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_DQBUF - unsupported type %d\n",
+                               ZR_DEVNAME(zr), buf->type);
+                       res = -EINVAL;
+                       goto dqbuf_unlock_and_return;
+               }
+       dqbuf_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_STREAMON:
+       {
+               int res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+
+               switch (fh->map_mode) {
+               case ZORAN_MAP_MODE_RAW:        /* raw capture */
+                       if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
+                           fh->v4l_buffers.active != ZORAN_ACTIVE) {
+                               res = -EBUSY;
+                               goto strmon_unlock_and_return;
+                       }
+
+                       zr->v4l_buffers.active = fh->v4l_buffers.active =
+                           ZORAN_LOCKED;
+                       zr->v4l_settings = fh->v4l_settings;
+
+                       zr->v4l_sync_tail = zr->v4l_pend_tail;
+                       if (!zr->v4l_memgrab_active &&
+                           zr->v4l_pend_head != zr->v4l_pend_tail) {
+                               zr36057_set_memgrab(zr, 1);
+                       }
+                       break;
+
+               case ZORAN_MAP_MODE_JPG_REC:
+               case ZORAN_MAP_MODE_JPG_PLAY:
+                       /* what is the codec mode right now? */
+                       if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
+                           fh->jpg_buffers.active != ZORAN_ACTIVE) {
+                               res = -EBUSY;
+                               goto strmon_unlock_and_return;
+                       }
+
+                       zr->jpg_buffers.active = fh->jpg_buffers.active =
+                           ZORAN_LOCKED;
+
+                       if (zr->jpg_que_head != zr->jpg_que_tail) {
+                               /* Start the jpeg codec when the first frame is queued  */
+                               jpeg_start(zr);
+                       }
+
+                       break;
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_STREAMON - invalid map mode %d\n",
+                               ZR_DEVNAME(zr), fh->map_mode);
+                       res = -EINVAL;
+                       goto strmon_unlock_and_return;
+               }
+       strmon_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_STREAMOFF:
+       {
+               int i, res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+
+               switch (fh->map_mode) {
+               case ZORAN_MAP_MODE_RAW:        /* raw capture */
+                       if (fh->v4l_buffers.active == ZORAN_FREE &&
+                           zr->v4l_buffers.active != ZORAN_FREE) {
+                               res = -EPERM;   /* stay off other's settings! */
+                               goto strmoff_unlock_and_return;
+                       }
+                       if (zr->v4l_buffers.active == ZORAN_FREE)
+                               goto strmoff_unlock_and_return;
+
+                       /* unload capture */
+                       if (zr->v4l_memgrab_active) {
+                               unsigned long flags;
+
+                               spin_lock_irqsave(&zr->spinlock, flags);
+                               zr36057_set_memgrab(zr, 0);
+                               spin_unlock_irqrestore(&zr->spinlock, flags);
+                       }
+
+                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
+                               zr->v4l_buffers.buffer[i].state =
+                                   BUZ_STATE_USER;
+                       fh->v4l_buffers = zr->v4l_buffers;
+
+                       zr->v4l_buffers.active = fh->v4l_buffers.active =
+                           ZORAN_FREE;
+
+                       zr->v4l_grab_seq = 0;
+                       zr->v4l_pend_head = zr->v4l_pend_tail = 0;
+                       zr->v4l_sync_tail = 0;
+
+                       break;
+
+               case ZORAN_MAP_MODE_JPG_REC:
+               case ZORAN_MAP_MODE_JPG_PLAY:
+                       if (fh->jpg_buffers.active == ZORAN_FREE &&
+                           zr->jpg_buffers.active != ZORAN_FREE) {
+                               res = -EPERM;   /* stay off other's settings! */
+                               goto strmoff_unlock_and_return;
+                       }
+                       if (zr->jpg_buffers.active == ZORAN_FREE)
+                               goto strmoff_unlock_and_return;
+
+                       res =
+                           jpg_qbuf(file, -1,
+                                    (fh->map_mode ==
+                                     ZORAN_MAP_MODE_JPG_REC) ?
+                                    BUZ_MODE_MOTION_COMPRESS :
+                                    BUZ_MODE_MOTION_DECOMPRESS);
+                       if (res)
+                               goto strmoff_unlock_and_return;
+                       break;
+               default:
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
+                               ZR_DEVNAME(zr), fh->map_mode);
+                       res = -EINVAL;
+                       goto strmoff_unlock_and_return;
+               }
+       strmoff_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *ctrl = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCTRL - id=%d\n",
+                       ZR_DEVNAME(zr), ctrl->id);
+
+               /* we only support hue/saturation/contrast/brightness */
+               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+                   ctrl->id > V4L2_CID_HUE)
+                       return -EINVAL;
+               else {
+                       int id = ctrl->id;
+                       memset(ctrl, 0, sizeof(*ctrl));
+                       ctrl->id = id;
+               }
+
+               switch (ctrl->id) {
+               case V4L2_CID_BRIGHTNESS:
+                       strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
+                       break;
+               case V4L2_CID_CONTRAST:
+                       strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
+                       break;
+               case V4L2_CID_SATURATION:
+                       strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
+                       break;
+               case V4L2_CID_HUE:
+                       strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
+                       break;
+               }
+
+               ctrl->minimum = 0;
+               ctrl->maximum = 65535;
+               ctrl->step = 1;
+               ctrl->default_value = 32768;
+               ctrl->type = V4L2_CTRL_TYPE_INTEGER;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_CTRL - id=%d\n",
+                       ZR_DEVNAME(zr), ctrl->id);
+
+               /* we only support hue/saturation/contrast/brightness */
+               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+                   ctrl->id > V4L2_CID_HUE)
+                       return -EINVAL;
+
+               mutex_lock(&zr->resource_lock);
+               switch (ctrl->id) {
+               case V4L2_CID_BRIGHTNESS:
+                       ctrl->value = zr->brightness;
+                       break;
+               case V4L2_CID_CONTRAST:
+                       ctrl->value = zr->contrast;
+                       break;
+               case V4L2_CID_SATURATION:
+                       ctrl->value = zr->saturation;
+                       break;
+               case V4L2_CID_HUE:
+                       ctrl->value = zr->hue;
+                       break;
+               }
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+               struct video_picture pict;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_CTRL - id=%d\n",
+                       ZR_DEVNAME(zr), ctrl->id);
+
+               /* we only support hue/saturation/contrast/brightness */
+               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+                   ctrl->id > V4L2_CID_HUE)
+                       return -EINVAL;
+
+               if (ctrl->value < 0 || ctrl->value > 65535) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n",
+                               ZR_DEVNAME(zr), ctrl->value, ctrl->id);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+               switch (ctrl->id) {
+               case V4L2_CID_BRIGHTNESS:
+                       zr->brightness = ctrl->value;
+                       break;
+               case V4L2_CID_CONTRAST:
+                       zr->contrast = ctrl->value;
+                       break;
+               case V4L2_CID_SATURATION:
+                       zr->saturation = ctrl->value;
+                       break;
+               case V4L2_CID_HUE:
+                       zr->hue = ctrl->value;
+                       break;
+               }
+               pict.brightness = zr->brightness;
+               pict.contrast = zr->contrast;
+               pict.colour = zr->saturation;
+               pict.hue = zr->hue;
+
+               decoder_command(zr, DECODER_SET_PICTURE, &pict);
+
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *std = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMSTD - index=%d\n",
+                       ZR_DEVNAME(zr), std->index);
+
+               if (std->index < 0 || std->index >= (zr->card.norms + 1))
+                       return -EINVAL;
+               else {
+                       int id = std->index;
+                       memset(std, 0, sizeof(*std));
+                       std->index = id;
+               }
+
+               if (std->index == zr->card.norms) {
+                       /* if we have autodetect, ... */
+                       struct video_decoder_capability caps;
+                       decoder_command(zr, DECODER_GET_CAPABILITIES,
+                                       &caps);
+                       if (caps.flags & VIDEO_DECODER_AUTO) {
+                               std->id = V4L2_STD_ALL;
+                               strncpy(std->name, "Autodetect", sizeof(std->name)-1);
+                               return 0;
+                       } else
+                               return -EINVAL;
+               }
+               switch (std->index) {
+               case 0:
+                       std->id = V4L2_STD_PAL;
+                       strncpy(std->name, "PAL", sizeof(std->name)-1);
+                       std->frameperiod.numerator = 1;
+                       std->frameperiod.denominator = 25;
+                       std->framelines = zr->card.tvn[0]->Ht;
+                       break;
+               case 1:
+                       std->id = V4L2_STD_NTSC;
+                       strncpy(std->name, "NTSC", sizeof(std->name)-1);
+                       std->frameperiod.numerator = 1001;
+                       std->frameperiod.denominator = 30000;
+                       std->framelines = zr->card.tvn[1]->Ht;
+                       break;
+               case 2:
+                       std->id = V4L2_STD_SECAM;
+                       strncpy(std->name, "SECAM", sizeof(std->name)-1);
+                       std->frameperiod.numerator = 1;
+                       std->frameperiod.denominator = 25;
+                       std->framelines = zr->card.tvn[2]->Ht;
+                       break;
+               }
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_G_STD:
+       {
+               v4l2_std_id *std = arg;
+               int norm;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+               norm = zr->norm;
+               mutex_unlock(&zr->resource_lock);
+
+               switch (norm) {
+               case VIDEO_MODE_PAL:
+                       *std = V4L2_STD_PAL;
+                       break;
+               case VIDEO_MODE_NTSC:
+                       *std = V4L2_STD_NTSC;
+                       break;
+               case VIDEO_MODE_SECAM:
+                       *std = V4L2_STD_SECAM;
+                       break;
+               }
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_STD:
+       {
+               int norm = -1, res = 0;
+               v4l2_std_id *std = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
+                       ZR_DEVNAME(zr), (unsigned long long)*std);
+
+               if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
+                       norm = VIDEO_MODE_PAL;
+               else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
+                       norm = VIDEO_MODE_NTSC;
+               else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
+                       norm = VIDEO_MODE_SECAM;
+               else if (*std == V4L2_STD_ALL)
+                       norm = VIDEO_MODE_AUTO;
+               else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_S_STD - invalid norm 0x%llx\n",
+                               ZR_DEVNAME(zr), (unsigned long long)*std);
+                       return -EINVAL;
+               }
+
+               mutex_lock(&zr->resource_lock);
+               if ((res = zoran_set_norm(zr, norm)))
+                       goto sstd_unlock_and_return;
+
+               res = wait_grab_pending(zr);
+       sstd_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOC_ENUMINPUT:
+       {
+               struct v4l2_input *inp = arg;
+               int status;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMINPUT - index=%d\n",
+                       ZR_DEVNAME(zr), inp->index);
+
+               if (inp->index < 0 || inp->index >= zr->card.inputs)
+                       return -EINVAL;
+               else {
+                       int id = inp->index;
+                       memset(inp, 0, sizeof(*inp));
+                       inp->index = id;
+               }
+
+               strncpy(inp->name, zr->card.input[inp->index].name,
+                       sizeof(inp->name) - 1);
+               inp->type = V4L2_INPUT_TYPE_CAMERA;
+               inp->std = V4L2_STD_ALL;
+
+               /* Get status of video decoder */
+               mutex_lock(&zr->resource_lock);
+               decoder_command(zr, DECODER_GET_STATUS, &status);
+               mutex_unlock(&zr->resource_lock);
+
+               if (!(status & DECODER_STATUS_GOOD)) {
+                       inp->status |= V4L2_IN_ST_NO_POWER;
+                       inp->status |= V4L2_IN_ST_NO_SIGNAL;
+               }
+               if (!(status & DECODER_STATUS_COLOR))
+                       inp->status |= V4L2_IN_ST_NO_COLOR;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_G_INPUT:
+       {
+               int *input = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr));
+
+               mutex_lock(&zr->resource_lock);
+               *input = zr->input;
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_INPUT:
+       {
+               int *input = arg, res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n",
+                       ZR_DEVNAME(zr), *input);
+
+               mutex_lock(&zr->resource_lock);
+               if ((res = zoran_set_input(zr, *input)))
+                       goto sinput_unlock_and_return;
+
+               /* Make sure the changes come into effect */
+               res = wait_grab_pending(zr);
+       sinput_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOC_ENUMOUTPUT:
+       {
+               struct v4l2_output *outp = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMOUTPUT - index=%d\n",
+                       ZR_DEVNAME(zr), outp->index);
+
+               if (outp->index != 0)
+                       return -EINVAL;
+
+               memset(outp, 0, sizeof(*outp));
+               outp->index = 0;
+               outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
+               strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_G_OUTPUT:
+       {
+               int *output = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_OUTPUT\n", ZR_DEVNAME(zr));
+
+               *output = 0;
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_OUTPUT:
+       {
+               int *output = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_OUTPUT - output=%d\n",
+                       ZR_DEVNAME(zr), *output);
+
+               if (*output != 0)
+                       return -EINVAL;
+
+               return 0;
+       }
+               break;
+
+               /* cropping (sub-frame capture) */
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *cropcap = arg;
+               int type = cropcap->type, res = 0;
+
+               dprintk(3, KERN_ERR "%s: VIDIOC_CROPCAP - type=%d\n",
+                       ZR_DEVNAME(zr), cropcap->type);
+
+               memset(cropcap, 0, sizeof(*cropcap));
+               cropcap->type = type;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                   (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto cropcap_unlock_and_return;
+               }
+
+               cropcap->bounds.top = cropcap->bounds.left = 0;
+               cropcap->bounds.width = BUZ_MAX_WIDTH;
+               cropcap->bounds.height = BUZ_MAX_HEIGHT;
+               cropcap->defrect.top = cropcap->defrect.left = 0;
+               cropcap->defrect.width = BUZ_MIN_WIDTH;
+               cropcap->defrect.height = BUZ_MIN_HEIGHT;
+       cropcap_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOC_G_CROP:
+       {
+               struct v4l2_crop *crop = arg;
+               int type = crop->type, res = 0;
+
+               dprintk(3, KERN_ERR "%s: VIDIOC_G_CROP - type=%d\n",
+                       ZR_DEVNAME(zr), crop->type);
+
+               memset(crop, 0, sizeof(*crop));
+               crop->type = type;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                   (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto gcrop_unlock_and_return;
+               }
+
+               crop->c.top = fh->jpg_settings.img_y;
+               crop->c.left = fh->jpg_settings.img_x;
+               crop->c.width = fh->jpg_settings.img_width;
+               crop->c.height = fh->jpg_settings.img_height;
+
+       gcrop_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return res;
+       }
+               break;
+
+       case VIDIOC_S_CROP:
+       {
+               struct v4l2_crop *crop = arg;
+               int res = 0;
+
+               settings = fh->jpg_settings;
+
+               dprintk(3,
+                       KERN_ERR
+                       "%s: VIDIOC_S_CROP - type=%d, x=%d,y=%d,w=%d,h=%d\n",
+                       ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top,
+                       crop->c.width, crop->c.height);
+
+               mutex_lock(&zr->resource_lock);
+
+               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_S_CROP - cannot change settings while active\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+                       goto scrop_unlock_and_return;
+               }
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                   (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+                               ZR_DEVNAME(zr));
+                       res = -EINVAL;
+                       goto scrop_unlock_and_return;
+               }
+
+               /* move into a form that we understand */
+               settings.img_x = crop->c.left;
+               settings.img_y = crop->c.top;
+               settings.img_width = crop->c.width;
+               settings.img_height = crop->c.height;
+
+               /* check validity */
+               if ((res = zoran_check_jpg_settings(zr, &settings)))
+                       goto scrop_unlock_and_return;
+
+               /* accept */
+               fh->jpg_settings = settings;
+
+       scrop_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+               return res;
+       }
+               break;
+
+       case VIDIOC_G_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *params = arg;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_JPEGCOMP\n",
+                       ZR_DEVNAME(zr));
+
+               memset(params, 0, sizeof(*params));
+
+               mutex_lock(&zr->resource_lock);
+
+               params->quality = fh->jpg_settings.jpg_comp.quality;
+               params->APPn = fh->jpg_settings.jpg_comp.APPn;
+               memcpy(params->APP_data,
+                      fh->jpg_settings.jpg_comp.APP_data,
+                      fh->jpg_settings.jpg_comp.APP_len);
+               params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
+               memcpy(params->COM_data,
+                      fh->jpg_settings.jpg_comp.COM_data,
+                      fh->jpg_settings.jpg_comp.COM_len);
+               params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
+               params->jpeg_markers =
+                   fh->jpg_settings.jpg_comp.jpeg_markers;
+
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_S_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *params = arg;
+               int res = 0;
+
+               settings = fh->jpg_settings;
+
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: VIDIOC_S_JPEGCOMP - quality=%d, APPN=%d, APP_len=%d, COM_len=%d\n",
+                       ZR_DEVNAME(zr), params->quality, params->APPn,
+                       params->APP_len, params->COM_len);
+
+               settings.jpg_comp = *params;
+
+               mutex_lock(&zr->resource_lock);
+
+               if (fh->v4l_buffers.active != ZORAN_FREE ||
+                   fh->jpg_buffers.active != ZORAN_FREE) {
+                       dprintk(1,
+                               KERN_WARNING
+                               "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
+                               ZR_DEVNAME(zr));
+                       res = -EBUSY;
+                       goto sjpegc_unlock_and_return;
+               }
+
+               if ((res = zoran_check_jpg_settings(zr, &settings)))
+                       goto sjpegc_unlock_and_return;
+               if (!fh->jpg_buffers.allocated)
+                       fh->jpg_buffers.buffer_size =
+                           zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+               fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
+       sjpegc_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               return 0;
+       }
+               break;
+
+       case VIDIOC_QUERYSTD:   /* why is this useful? */
+       {
+               v4l2_std_id *std = arg;
+
+               dprintk(3,
+                       KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n",
+                       ZR_DEVNAME(zr), (unsigned long long)*std);
+
+               if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC ||
+                   *std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM &&
+                                            zr->card.norms == 3)) {
+                       return 0;
+               }
+
+               return -EINVAL;
+       }
+               break;
+
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *fmt = arg;
+               int res = 0;
+
+               dprintk(3, KERN_DEBUG "%s: VIDIOC_TRY_FMT - type=%d\n",
+                       ZR_DEVNAME(zr), fmt->type);
+
+               switch (fmt->type) {
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       mutex_lock(&zr->resource_lock);
+
+                       if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
+                               fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
+                       if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
+                               fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
+                       if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
+                               fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
+                       if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
+                               fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
+
+                       mutex_unlock(&zr->resource_lock);
+                       break;
+
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (fmt->fmt.pix.bytesperline > 0)
+                               return -EINVAL;
+
+                       mutex_lock(&zr->resource_lock);
+
+                       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
+                               settings = fh->jpg_settings;
+
+                               /* we actually need to set 'real' parameters now */
+                               if ((fmt->fmt.pix.height * 2) >
+                                   BUZ_MAX_HEIGHT)
+                                       settings.TmpDcm = 1;
+                               else
+                                       settings.TmpDcm = 2;
+                               settings.decimation = 0;
+                               if (fmt->fmt.pix.height <=
+                                   fh->jpg_settings.img_height / 2)
+                                       settings.VerDcm = 2;
+                               else
+                                       settings.VerDcm = 1;
+                               if (fmt->fmt.pix.width <=
+                                   fh->jpg_settings.img_width / 4)
+                                       settings.HorDcm = 4;
+                               else if (fmt->fmt.pix.width <=
+                                        fh->jpg_settings.img_width / 2)
+                                       settings.HorDcm = 2;
+                               else
+                                       settings.HorDcm = 1;
+                               if (settings.TmpDcm == 1)
+                                       settings.field_per_buff = 2;
+                               else
+                                       settings.field_per_buff = 1;
+
+                               /* check */
+                               if ((res =
+                                    zoran_check_jpg_settings(zr,
+                                                             &settings)))
+                                       goto tryfmt_unlock_and_return;
+
+                               /* tell the user what we actually did */
+                               fmt->fmt.pix.width =
+                                   settings.img_width / settings.HorDcm;
+                               fmt->fmt.pix.height =
+                                   settings.img_height * 2 /
+                                   (settings.TmpDcm * settings.VerDcm);
+                               if (settings.TmpDcm == 1)
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_SEQ_TB :
+                                            V4L2_FIELD_SEQ_BT);
+                               else
+                                       fmt->fmt.pix.field =
+                                           (fh->jpg_settings.
+                                            odd_even ? V4L2_FIELD_TOP :
+                                            V4L2_FIELD_BOTTOM);
+
+                               fmt->fmt.pix.sizeimage =
+                                   zoran_v4l2_calc_bufsize(&settings);
+                       } else if (fmt->type ==
+                                  V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                               int i;
+
+                               for (i = 0; i < NUM_FORMATS; i++)
+                                       if (zoran_formats[i].fourcc ==
+                                           fmt->fmt.pix.pixelformat)
+                                               break;
+                               if (i == NUM_FORMATS) {
+                                       res = -EINVAL;
+                                       goto tryfmt_unlock_and_return;
+                               }
+
+                               if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+                                       fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+                               if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
+                                       fmt->fmt.pix.width = BUZ_MIN_WIDTH;
+                               if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+                                       fmt->fmt.pix.height =
+                                           BUZ_MAX_HEIGHT;
+                               if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
+                                       fmt->fmt.pix.height =
+                                           BUZ_MIN_HEIGHT;
+                       } else {
+                               res = -EINVAL;
+                               goto tryfmt_unlock_and_return;
+                       }
+               tryfmt_unlock_and_return:
+                       mutex_unlock(&zr->resource_lock);
+
+                       return res;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+
+               return 0;
+       }
+               break;
+
+       default:
+               dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
+                       ZR_DEVNAME(zr), cmd);
+               return -ENOIOCTLCMD;
+               break;
+
+       }
+       return 0;
+}
+
+
+static int
+zoran_ioctl (struct inode *inode,
+            struct file  *file,
+            unsigned int  cmd,
+            unsigned long arg)
+{
+       return video_usercopy(inode, file, cmd, arg, zoran_do_ioctl);
+}
+
+static unsigned int
+zoran_poll (struct file *file,
+           poll_table  *wait)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int res = 0, frame;
+       unsigned long flags;
+
+       /* we should check whether buffers are ready to be synced on
+        * (w/o waits - O_NONBLOCK) here
+        * if ready for read (sync), return POLLIN|POLLRDNORM,
+        * if ready for write (sync), return POLLOUT|POLLWRNORM,
+        * if error, return POLLERR,
+        * if no buffers queued or so, return POLLNVAL
+        */
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+               poll_wait(file, &zr->v4l_capq, wait);
+               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
+                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
+                       zr->v4l_pend_tail, zr->v4l_pend_head);
+               /* Process is the one capturing? */
+               if (fh->v4l_buffers.active != ZORAN_FREE &&
+                   /* Buffer ready to DQBUF? */
+                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
+                       res = POLLIN | POLLRDNORM;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+               poll_wait(file, &zr->jpg_capq, wait);
+               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
+                       "UPMD"[zr->jpg_buffers.buffer[frame].state],
+                       zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
+               if (fh->jpg_buffers.active != ZORAN_FREE &&
+                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
+                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
+                               res = POLLIN | POLLRDNORM;
+                       else
+                               res = POLLOUT | POLLWRNORM;
+               }
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               break;
+
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_poll() - internal error, unknown map_mode=%d\n",
+                       ZR_DEVNAME(zr), fh->map_mode);
+               res = POLLNVAL;
+       }
+
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+
+/*
+ * This maps the buffers to user space.
+ *
+ * Depending on the state of fh->map_mode
+ * the V4L or the MJPEG buffers are mapped
+ * per buffer or all together
+ *
+ * Note that we need to connect to some
+ * unmap signal event to unmap the de-allocate
+ * the buffer accordingly (zoran_vm_close())
+ */
+
+static void
+zoran_vm_open (struct vm_area_struct *vma)
+{
+       struct zoran_mapping *map = vma->vm_private_data;
+
+       map->count++;
+}
+
+static void
+zoran_vm_close (struct vm_area_struct *vma)
+{
+       struct zoran_mapping *map = vma->vm_private_data;
+       struct file *file = map->file;
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int i;
+
+       map->count--;
+       if (map->count == 0) {
+               switch (fh->map_mode) {
+               case ZORAN_MAP_MODE_JPG_REC:
+               case ZORAN_MAP_MODE_JPG_PLAY:
+
+                       dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n",
+                               ZR_DEVNAME(zr));
+
+                       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
+                               if (fh->jpg_buffers.buffer[i].map == map) {
+                                       fh->jpg_buffers.buffer[i].map =
+                                           NULL;
+                               }
+                       }
+                       kfree(map);
+
+                       for (i = 0; i < fh->jpg_buffers.num_buffers; i++)
+                               if (fh->jpg_buffers.buffer[i].map)
+                                       break;
+                       if (i == fh->jpg_buffers.num_buffers) {
+                               mutex_lock(&zr->resource_lock);
+
+                               if (fh->jpg_buffers.active != ZORAN_FREE) {
+                                       jpg_qbuf(file, -1, zr->codec_mode);
+                                       zr->jpg_buffers.allocated = 0;
+                                       zr->jpg_buffers.active =
+                                           fh->jpg_buffers.active =
+                                           ZORAN_FREE;
+                               }
+                               //jpg_fbuffer_free(file);
+                               fh->jpg_buffers.allocated = 0;
+                               fh->jpg_buffers.ready_to_be_freed = 1;
+
+                               mutex_unlock(&zr->resource_lock);
+                       }
+
+                       break;
+
+               case ZORAN_MAP_MODE_RAW:
+
+                       dprintk(3, KERN_INFO "%s: munmap(V4L)\n",
+                               ZR_DEVNAME(zr));
+
+                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
+                               if (fh->v4l_buffers.buffer[i].map == map) {
+                                       /* unqueue/unmap */
+                                       fh->v4l_buffers.buffer[i].map =
+                                           NULL;
+                               }
+                       }
+                       kfree(map);
+
+                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
+                               if (fh->v4l_buffers.buffer[i].map)
+                                       break;
+                       if (i == fh->v4l_buffers.num_buffers) {
+                               mutex_lock(&zr->resource_lock);
+
+                               if (fh->v4l_buffers.active != ZORAN_FREE) {
+                                       unsigned long flags;
+
+                                       spin_lock_irqsave(&zr->spinlock, flags);
+                                       zr36057_set_memgrab(zr, 0);
+                                       zr->v4l_buffers.allocated = 0;
+                                       zr->v4l_buffers.active =
+                                           fh->v4l_buffers.active =
+                                           ZORAN_FREE;
+                                       spin_unlock_irqrestore(&zr->spinlock, flags);
+                               }
+                               //v4l_fbuffer_free(file);
+                               fh->v4l_buffers.allocated = 0;
+                               fh->v4l_buffers.ready_to_be_freed = 1;
+
+                               mutex_unlock(&zr->resource_lock);
+                       }
+
+                       break;
+
+               default:
+                       printk(KERN_ERR
+                              "%s: munmap() - internal error - unknown map mode %d\n",
+                              ZR_DEVNAME(zr), fh->map_mode);
+                       break;
+
+               }
+       }
+}
+
+static struct vm_operations_struct zoran_vm_ops = {
+       .open = zoran_vm_open,
+       .close = zoran_vm_close,
+};
+
+static int
+zoran_mmap (struct file           *file,
+           struct vm_area_struct *vma)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long size = (vma->vm_end - vma->vm_start);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int i, j;
+       unsigned long page, start = vma->vm_start, todo, pos, fraglen;
+       int first, last;
+       struct zoran_mapping *map;
+       int res = 0;
+
+       dprintk(3,
+               KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
+               ZR_DEVNAME(zr),
+               fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG",
+               vma->vm_start, vma->vm_end, size);
+
+       if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
+           !(vma->vm_flags & VM_WRITE)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: mmap() - no MAP_SHARED/PROT_{READ,WRITE} given\n",
+                       ZR_DEVNAME(zr));
+               return -EINVAL;
+       }
+
+       switch (fh->map_mode) {
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+
+               /* lock */
+               mutex_lock(&zr->resource_lock);
+
+               /* Map the MJPEG buffers */
+               if (!fh->jpg_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zoran_mmap(MJPEG) - buffers not yet allocated\n",
+                               ZR_DEVNAME(zr));
+                       res = -ENOMEM;
+                       goto jpg_mmap_unlock_and_return;
+               }
+
+               first = offset / fh->jpg_buffers.buffer_size;
+               last = first - 1 + size / fh->jpg_buffers.buffer_size;
+               if (offset % fh->jpg_buffers.buffer_size != 0 ||
+                   size % fh->jpg_buffers.buffer_size != 0 || first < 0 ||
+                   last < 0 || first >= fh->jpg_buffers.num_buffers ||
+                   last >= fh->jpg_buffers.num_buffers) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
+                               ZR_DEVNAME(zr), offset, size,
+                               fh->jpg_buffers.buffer_size,
+                               fh->jpg_buffers.num_buffers);
+                       res = -EINVAL;
+                       goto jpg_mmap_unlock_and_return;
+               }
+               for (i = first; i <= last; i++) {
+                       if (fh->jpg_buffers.buffer[i].map) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: mmap(MJPEG) - buffer %d already mapped\n",
+                                       ZR_DEVNAME(zr), i);
+                               res = -EBUSY;
+                               goto jpg_mmap_unlock_and_return;
+                       }
+               }
+
+               /* map these buffers (v4l_buffers[i]) */
+               map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
+               if (!map) {
+                       res = -ENOMEM;
+                       goto jpg_mmap_unlock_and_return;
+               }
+               map->file = file;
+               map->count = 1;
+
+               vma->vm_ops = &zoran_vm_ops;
+               vma->vm_flags |= VM_DONTEXPAND;
+               vma->vm_private_data = map;
+
+               for (i = first; i <= last; i++) {
+                       for (j = 0;
+                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+                            j++) {
+                               fraglen =
+                                   (le32_to_cpu(fh->jpg_buffers.buffer[i].
+                                    frag_tab[2 * j + 1]) & ~1) << 1;
+                               todo = size;
+                               if (todo > fraglen)
+                                       todo = fraglen;
+                               pos =
+                                   le32_to_cpu(fh->jpg_buffers.
+                                   buffer[i].frag_tab[2 * j]);
+                               /* should just be pos on i386 */
+                               page = virt_to_phys(bus_to_virt(pos))
+                                                               >> PAGE_SHIFT;
+                               if (remap_pfn_range(vma, start, page,
+                                                       todo, PAGE_SHARED)) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
+                                               ZR_DEVNAME(zr));
+                                       res = -EAGAIN;
+                                       goto jpg_mmap_unlock_and_return;
+                               }
+                               size -= todo;
+                               start += todo;
+                               if (size == 0)
+                                       break;
+                               if (le32_to_cpu(fh->jpg_buffers.buffer[i].
+                                   frag_tab[2 * j + 1]) & 1)
+                                       break;  /* was last fragment */
+                       }
+                       fh->jpg_buffers.buffer[i].map = map;
+                       if (size == 0)
+                               break;
+
+               }
+       jpg_mmap_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               break;
+
+       case ZORAN_MAP_MODE_RAW:
+
+               mutex_lock(&zr->resource_lock);
+
+               /* Map the V4L buffers */
+               if (!fh->v4l_buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zoran_mmap(V4L) - buffers not yet allocated\n",
+                               ZR_DEVNAME(zr));
+                       res = -ENOMEM;
+                       goto v4l_mmap_unlock_and_return;
+               }
+
+               first = offset / fh->v4l_buffers.buffer_size;
+               last = first - 1 + size / fh->v4l_buffers.buffer_size;
+               if (offset % fh->v4l_buffers.buffer_size != 0 ||
+                   size % fh->v4l_buffers.buffer_size != 0 || first < 0 ||
+                   last < 0 || first >= fh->v4l_buffers.num_buffers ||
+                   last >= fh->v4l_buffers.buffer_size) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
+                               ZR_DEVNAME(zr), offset, size,
+                               fh->v4l_buffers.buffer_size,
+                               fh->v4l_buffers.num_buffers);
+                       res = -EINVAL;
+                       goto v4l_mmap_unlock_and_return;
+               }
+               for (i = first; i <= last; i++) {
+                       if (fh->v4l_buffers.buffer[i].map) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: mmap(V4L) - buffer %d already mapped\n",
+                                       ZR_DEVNAME(zr), i);
+                               res = -EBUSY;
+                               goto v4l_mmap_unlock_and_return;
+                       }
+               }
+
+               /* map these buffers (v4l_buffers[i]) */
+               map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
+               if (!map) {
+                       res = -ENOMEM;
+                       goto v4l_mmap_unlock_and_return;
+               }
+               map->file = file;
+               map->count = 1;
+
+               vma->vm_ops = &zoran_vm_ops;
+               vma->vm_flags |= VM_DONTEXPAND;
+               vma->vm_private_data = map;
+
+               for (i = first; i <= last; i++) {
+                       todo = size;
+                       if (todo > fh->v4l_buffers.buffer_size)
+                               todo = fh->v4l_buffers.buffer_size;
+                       page = fh->v4l_buffers.buffer[i].fbuffer_phys;
+                       if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
+                                                       todo, PAGE_SHARED)) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: zoran_mmap(V4L)i - remap_pfn_range failed\n",
+                                       ZR_DEVNAME(zr));
+                               res = -EAGAIN;
+                               goto v4l_mmap_unlock_and_return;
+                       }
+                       size -= todo;
+                       start += todo;
+                       fh->v4l_buffers.buffer[i].map = map;
+                       if (size == 0)
+                               break;
+               }
+       v4l_mmap_unlock_and_return:
+               mutex_unlock(&zr->resource_lock);
+
+               break;
+
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: zoran_mmap() - internal error - unknown map mode %d\n",
+                       ZR_DEVNAME(zr), fh->map_mode);
+               break;
+       }
+
+       return 0;
+}
+
+static const struct file_operations zoran_fops = {
+       .owner = THIS_MODULE,
+       .open = zoran_open,
+       .release = zoran_close,
+       .ioctl = zoran_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = v4l_compat_ioctl32,
+#endif
+       .llseek = no_llseek,
+       .read = zoran_read,
+       .write = zoran_write,
+       .mmap = zoran_mmap,
+       .poll = zoran_poll,
+};
+
+struct video_device zoran_template __devinitdata = {
+       .name = ZORAN_NAME,
+       .fops = &zoran_fops,
+       .release = &zoran_vdev_release,
+       .minor = -1
+};
+
diff --git a/drivers/media/video/zoran/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c
new file mode 100644 (file)
index 0000000..870bc5a
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles the procFS entries (/proc/ZORAN[%d])
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/seq_file.h>
+
+#include <linux/ctype.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_procfs.h"
+#include "zoran_card.h"
+
+#ifdef CONFIG_PROC_FS
+struct procfs_params_zr36067 {
+       char *name;
+       short reg;
+       u32 mask;
+       short bit;
+};
+
+static const struct procfs_params_zr36067 zr67[] = {
+       {"HSPol", 0x000, 1, 30},
+       {"HStart", 0x000, 0x3ff, 10},
+       {"HEnd", 0x000, 0x3ff, 0},
+
+       {"VSPol", 0x004, 1, 30},
+       {"VStart", 0x004, 0x3ff, 10},
+       {"VEnd", 0x004, 0x3ff, 0},
+
+       {"ExtFl", 0x008, 1, 26},
+       {"TopField", 0x008, 1, 25},
+       {"VCLKPol", 0x008, 1, 24},
+       {"DupFld", 0x008, 1, 20},
+       {"LittleEndian", 0x008, 1, 0},
+
+       {"HsyncStart", 0x10c, 0xffff, 16},
+       {"LineTot", 0x10c, 0xffff, 0},
+
+       {"NAX", 0x110, 0xffff, 16},
+       {"PAX", 0x110, 0xffff, 0},
+
+       {"NAY", 0x114, 0xffff, 16},
+       {"PAY", 0x114, 0xffff, 0},
+
+       /* {"",,,}, */
+
+       {NULL, 0, 0, 0},
+};
+
+static void
+setparam (struct zoran *zr,
+         char         *name,
+         char         *sval)
+{
+       int i = 0, reg0, reg, val;
+
+       while (zr67[i].name != NULL) {
+               if (!strncmp(name, zr67[i].name, strlen(zr67[i].name))) {
+                       reg = reg0 = btread(zr67[i].reg);
+                       reg &= ~(zr67[i].mask << zr67[i].bit);
+                       if (!isdigit(sval[0]))
+                               break;
+                       val = simple_strtoul(sval, NULL, 0);
+                       if ((val & ~zr67[i].mask))
+                               break;
+                       reg |= (val & zr67[i].mask) << zr67[i].bit;
+                       dprintk(4,
+                               KERN_INFO
+                               "%s: setparam: setting ZR36067 register 0x%03x: 0x%08x=>0x%08x %s=%d\n",
+                               ZR_DEVNAME(zr), zr67[i].reg, reg0, reg,
+                               zr67[i].name, val);
+                       btwrite(reg, zr67[i].reg);
+                       break;
+               }
+               i++;
+       }
+}
+
+static int zoran_show(struct seq_file *p, void *v)
+{
+       struct zoran *zr = p->private;
+       int i;
+
+       seq_printf(p, "ZR36067 registers:\n");
+       for (i = 0; i < 0x130; i += 16)
+               seq_printf(p, "%03X %08X  %08X  %08X  %08X \n", i,
+                          btread(i), btread(i+4), btread(i+8), btread(i+12));
+       return 0;
+}
+
+static int zoran_open(struct inode *inode, struct file *file)
+{
+       struct zoran *data = PDE(inode)->data;
+       return single_open(file, zoran_show, data);
+}
+
+static ssize_t zoran_write(struct file *file, const char __user *buffer,
+                       size_t count, loff_t *ppos)
+{
+       struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
+       char *string, *sp;
+       char *line, *ldelim, *varname, *svar, *tdelim;
+
+       if (count > 32768)      /* Stupidity filter */
+               return -EINVAL;
+
+       string = sp = vmalloc(count + 1);
+       if (!string) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: write_proc: can not allocate memory\n",
+                       ZR_DEVNAME(zr));
+               return -ENOMEM;
+       }
+       if (copy_from_user(string, buffer, count)) {
+               vfree (string);
+               return -EFAULT;
+       }
+       string[count] = 0;
+       dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
+               ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
+       ldelim = " \t\n";
+       tdelim = "=";
+       line = strpbrk(sp, ldelim);
+       while (line) {
+               *line = 0;
+               svar = strpbrk(sp, tdelim);
+               if (svar) {
+                       *svar = 0;
+                       varname = sp;
+                       svar++;
+                       setparam(zr, varname, svar);
+               }
+               sp = line + 1;
+               line = strpbrk(sp, ldelim);
+       }
+       vfree(string);
+
+       return count;
+}
+
+static const struct file_operations zoran_operations = {
+       .owner          = THIS_MODULE,
+       .open           = zoran_open,
+       .read           = seq_read,
+       .write          = zoran_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
+int
+zoran_proc_init (struct zoran *zr)
+{
+#ifdef CONFIG_PROC_FS
+       char name[8];
+
+       snprintf(name, 7, "zoran%d", zr->id);
+       zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
+       if (zr->zoran_proc != NULL) {
+               dprintk(2,
+                       KERN_INFO
+                       "%s: procfs entry /proc/%s allocated. data=%p\n",
+                       ZR_DEVNAME(zr), name, zr->zoran_proc->data);
+       } else {
+               dprintk(1, KERN_ERR "%s: Unable to initialise /proc/%s\n",
+                       ZR_DEVNAME(zr), name);
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+void
+zoran_proc_cleanup (struct zoran *zr)
+{
+#ifdef CONFIG_PROC_FS
+       char name[8];
+
+       snprintf(name, 7, "zoran%d", zr->id);
+       if (zr->zoran_proc)
+               remove_proc_entry(name, NULL);
+       zr->zoran_proc = NULL;
+#endif
+}
diff --git a/drivers/media/video/zoran/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h
new file mode 100644 (file)
index 0000000..f2d5b1b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ZORAN_PROCFS_H__
+#define __ZORAN_PROCFS_H__
+
+extern int zoran_proc_init(struct zoran *zr);
+extern void zoran_proc_cleanup(struct zoran *zr);
+
+#endif                         /* __ZORAN_PROCFS_H__ */
diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/video/zoran/zr36016.c
new file mode 100644 (file)
index 0000000..00d132b
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Zoran ZR36016 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#define ZR016_VERSION "v0.7"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* includes for structures and defines regarding video
+   #include<linux/videodev.h> */
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+//#include<errno.h>
+
+/* v4l  API */
+#include <linux/videodev.h>
+
+/* headerfile of this module */
+#include"zr36016.h"
+
+/* codec io API */
+#include"videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36016_codecs;
+
+/* debugging is available via module parameter */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36016_read (struct zr36016 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value =
+                   (ptr->codec->master_data->
+                    readreg(ptr->codec, reg)) & 0xFF;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
+               value);
+
+       return value;
+}
+
+static void
+zr36016_write (struct zr36016 *ptr,
+              u16             reg,
+              u8              value)
+{
+       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
+               reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg) {
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* indirect read and write functions */
+/* the 016 supports auto-addr-increment, but
+ * writing it all time cost not much and is safer... */
+static u8
+zr36016_readi (struct zr36016 *ptr,
+              u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if ((ptr->codec->master_data->writereg) &&
+           (ptr->codec->master_data->readreg)) {
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
+               value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;     // DATA
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing read (i)!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
+               reg, value);
+       return value;
+}
+
+static void
+zr36016_writei (struct zr36016 *ptr,
+               u16             reg,
+               u8              value)
+{
+       dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
+               value, reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg) {
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);      // DATA
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written (i)!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   version read
+   ========================================================================= */
+
+/* version kept in datastructure */
+static u8
+zr36016_read_version (struct zr36016 *ptr)
+{
+       ptr->version = zr36016_read(ptr, 0) >> 4;
+       return ptr->version;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from PAX-Lo register
+   ========================================================================= */
+
+static int
+zr36016_basic_test (struct zr36016 *ptr)
+{
+       if (debug) {
+               int i;
+               zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
+               dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
+               for (i = 0; i <= 0x0b; i++)
+                       dprintk(1, "%02x ", zr36016_readi(ptr, i));
+               dprintk(1, "\n");
+       }
+       // for testing just write 0, then the default value to a register and read
+       // it back in both cases
+       zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
+       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to vfe processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
+       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to vfe processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       // we allow version numbers from 0-3, should be enough, though
+       zr36016_read_version(ptr);
+       if (ptr->version & 0x0c) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, suspicious version %d found...\n",
+                       ptr->name, ptr->version);
+               return -ENXIO;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets - NO USE --
+   ========================================================================= */
+
+#if 0
+static int zr36016_pushit (struct zr36016 *ptr,
+                          u16             startreg,
+                          u16             len,
+                          const char     *data)
+{
+       int i=0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
+               ptr->name, startreg,len);
+       while (i<len) {
+               zr36016_writei(ptr, startreg++,  data[i++]);
+       }
+
+       return i;
+}
+#endif
+
+/* =========================================================================
+   Basic datasets & init:
+
+   //TODO//
+   ========================================================================= */
+
+// needed offset values          PAL NTSC SECAM
+static const int zr016_xoff[] = { 20, 20, 20 };
+static const int zr016_yoff[] = { 8, 9, 7 };
+
+static void
+zr36016_init (struct zr36016 *ptr)
+{
+       // stop any processing
+       zr36016_write(ptr, ZR016_GOSTOP, 0);
+
+       // mode setup (yuv422 in and out, compression/expansuon due to mode)
+       zr36016_write(ptr, ZR016_MODE,
+                     ZR016_YUV422 | ZR016_YUV422_YUV422 |
+                     (ptr->mode == CODEC_DO_COMPRESSION ?
+                      ZR016_COMPRESSION : ZR016_EXPANSION));
+
+       // misc setup
+       zr36016_writei(ptr, ZR016I_SETUP1,
+                      (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
+                      (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
+       zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
+
+       // Window setup
+       // (no extra offset for now, norm defines offset, default width height)
+       zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
+       zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
+       zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
+       zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
+       zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
+       zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
+       zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
+       zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
+
+       /* shall we continue now, please? */
+       zr36016_write(ptr, ZR016_GOSTOP, 1);
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36016_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36016_init(ptr);
+
+       return 0;
+}
+
+/* set picture size */
+static int
+zr36016_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+
+       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
+               ptr->name, norm->HStart, norm->VStart,
+               cap->x, cap->y, cap->width, cap->height,
+               cap->decimation);
+
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y for now ... */
+       ptr->width = cap->width;
+       ptr->height = cap->height;
+       /* (Ronald) This is ugly. zoran_device.c, line 387
+        * already mentions what happens if HStart is even
+        * (blue faces, etc., cr/cb inversed). There's probably
+        * some good reason why HStart is 0 instead of 1, so I'm
+        * leaving it to this for now, but really... This can be
+        * done a lot simpler */
+       ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
+       /* Something to note here (I don't understand it), setting
+        * VStart too high will cause the codec to 'not work'. I
+        * really don't get it. values of 16 (VStart) already break
+        * it here. Just '0' seems to work. More testing needed! */
+       ptr->yoff = norm->VStart + cap->y;
+       /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
+       ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
+       ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36016_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status - we don't know it ... */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = 0;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = 0;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != 0)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36016_unset (struct videocodec *codec)
+{
+       struct zr36016 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36016_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36016_setup (struct videocodec *codec)
+{
+       struct zr36016 *ptr;
+       int res;
+
+       dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
+               zr36016_codecs);
+
+       if (zr36016_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36016: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
+                zr36016_codecs);
+       ptr->num = zr36016_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36016_basic_test(ptr);
+       if (res < 0) {
+               zr36016_unset(codec);
+               return res;
+       }
+       //final setup
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 768;
+       ptr->height = 288;
+       ptr->xdec = 1;
+       ptr->ydec = 0;
+       zr36016_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
+               ptr->name, ptr->version);
+
+       return 0;
+}
+
+static const struct videocodec zr36016_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36016",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER,
+       .type = CODEC_TYPE_ZR36016,
+       .setup = zr36016_setup, // functionality
+       .unset = zr36016_unset,
+       .set_mode = zr36016_set_mode,
+       .set_video = zr36016_set_video,
+       .control = zr36016_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36016_init_module (void)
+{
+       //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
+       zr36016_codecs = 0;
+       return videocodec_register(&zr36016_codec);
+}
+
+static void __exit
+zr36016_cleanup_module (void)
+{
+       if (zr36016_codecs) {
+               dprintk(1,
+                       "zr36016: something's wrong - %d codecs left somehow.\n",
+                       zr36016_codecs);
+       }
+       videocodec_unregister(&zr36016_codec);
+}
+
+module_init(zr36016_init_module);
+module_exit(zr36016_cleanup_module);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
+                  ZR016_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36016.h b/drivers/media/video/zoran/zr36016.h
new file mode 100644 (file)
index 0000000..8c79229
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Zoran ZR36016 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36016.h,v 1.1.2.3 2003/01/14 21:18:07 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 ZR36016_H
+#define ZR36016_H
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36016 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // coder status
+       __u8 version;
+       // actual coder setup
+       int mode;
+
+       __u16 xoff;
+       __u16 yoff;
+       __u16 width;
+       __u16 height;
+       __u16 xdec;
+       __u16 ydec;
+};
+
+/* direct  register addresses */
+#define ZR016_GOSTOP      0x00
+#define ZR016_MODE        0x01
+#define ZR016_IADDR       0x02
+#define ZR016_IDATA       0x03
+
+/* indirect  register addresses */
+#define ZR016I_SETUP1     0x00
+#define ZR016I_SETUP2     0x01
+#define ZR016I_NAX_LO     0x02
+#define ZR016I_NAX_HI     0x03
+#define ZR016I_PAX_LO     0x04
+#define ZR016I_PAX_HI     0x05
+#define ZR016I_NAY_LO     0x06
+#define ZR016I_NAY_HI     0x07
+#define ZR016I_PAY_LO     0x08
+#define ZR016I_PAY_HI     0x09
+#define ZR016I_NOL_LO     0x0a
+#define ZR016I_NOL_HI     0x0b
+
+/* possible values for mode register */
+#define ZR016_RGB444_YUV444  0x00
+#define ZR016_RGB444_YUV422  0x01
+#define ZR016_RGB444_YUV411  0x02
+#define ZR016_RGB444_Y400    0x03
+#define ZR016_RGB444_RGB444  0x04
+#define ZR016_YUV444_YUV444  0x08
+#define ZR016_YUV444_YUV422  0x09
+#define ZR016_YUV444_YUV411  0x0a
+#define ZR016_YUV444_Y400    0x0b
+#define ZR016_YUV444_RGB444  0x0c
+#define ZR016_YUV422_YUV422  0x11
+#define ZR016_YUV422_YUV411  0x12
+#define ZR016_YUV422_Y400    0x13
+#define ZR016_YUV411_YUV411  0x16
+#define ZR016_YUV411_Y400    0x17
+#define ZR016_4444_4444      0x19
+#define ZR016_100_100        0x1b
+
+#define ZR016_RGB444         0x00
+#define ZR016_YUV444         0x20
+#define ZR016_YUV422         0x40
+
+#define ZR016_COMPRESSION    0x80
+#define ZR016_EXPANSION      0x80
+
+/* possible values for setup 1 register */
+#define ZR016_CKRT           0x80
+#define ZR016_VERT           0x40
+#define ZR016_HORZ           0x20
+#define ZR016_HRFL           0x10
+#define ZR016_DSFL           0x08
+#define ZR016_SBFL           0x04
+#define ZR016_RSTR           0x02
+#define ZR016_CNTI           0x01
+
+/* possible values for setup 2 register */
+#define ZR016_SYEN           0x40
+#define ZR016_CCIR           0x04
+#define ZR016_SIGN           0x02
+#define ZR016_YMCS           0x01
+
+#endif                         /*fndef ZR36016_H */
diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/video/zoran/zr36050.c
new file mode 100644 (file)
index 0000000..cf8b271
--- /dev/null
@@ -0,0 +1,904 @@
+/*
+ * Zoran ZR36050 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#define ZR050_VERSION "v0.7.1"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* includes for structures and defines regarding video
+   #include<linux/videodev.h> */
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+//#include<errno.h>
+
+/* headerfile of this module */
+#include "zr36050.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36050_codecs;
+
+/* debugging is available via module parameter */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36050_read (struct zr36050 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value = (ptr->codec->master_data->readreg(ptr->codec,
+                                                         reg)) & 0xFF;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
+               value);
+
+       return value;
+}
+
+static void
+zr36050_write (struct zr36050 *ptr,
+              u16             reg,
+              u8              value)
+{
+       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
+               reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg)
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   status read
+   ========================================================================= */
+
+/* status is kept in datastructure */
+static u8
+zr36050_read_status1 (struct zr36050 *ptr)
+{
+       ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
+
+       zr36050_read(ptr, 0);
+       return ptr->status1;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   scale factor read
+   ========================================================================= */
+
+/* scale factor is kept in datastructure */
+static u16
+zr36050_read_scalefactor (struct zr36050 *ptr)
+{
+       ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
+                        (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
+
+       /* leave 0 selected for an eventually GO from master */
+       zr36050_read(ptr, 0);
+       return ptr->scalefact;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   wait if codec is ready to proceed (end of processing) or time is over
+   ========================================================================= */
+
+static void
+zr36050_wait_end (struct zr36050 *ptr)
+{
+       int i = 0;
+
+       while (!(zr36050_read_status1(ptr) & 0x4)) {
+               udelay(1);
+               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
+                       dprintk(1,
+                               "%s: timeout at wait_end (last status: 0x%02x)\n",
+                               ptr->name, ptr->status1);
+                       break;
+               }
+       }
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from memory the SOF marker
+   ========================================================================= */
+
+static int
+zr36050_basic_test (struct zr36050 *ptr)
+{
+       zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
+       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
+       if ((zr36050_read(ptr, ZR050_SOF_IDX) |
+            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
+       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
+       if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
+            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+
+       zr36050_wait_end(ptr);
+       if ((ptr->status1 & 0x4) == 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, jpeg processor failed (end flag)!\n",
+                       ptr->name);
+               return -EBUSY;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets
+   ========================================================================= */
+
+static int
+zr36050_pushit (struct zr36050 *ptr,
+               u16             startreg,
+               u16             len,
+               const char     *data)
+{
+       int i = 0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+               startreg, len);
+       while (i < len) {
+               zr36050_write(ptr, startreg++, data[i++]);
+       }
+
+       return i;
+}
+
+/* =========================================================================
+   Basic datasets:
+
+   jpeg baseline setup data (you find it on lots places in internet, or just
+   extract it from any regular .jpg image...)
+
+   Could be variable, but until it's not needed it they are just fixed to save
+   memory. Otherwise expand zr36050 structure with arrays, push the values to
+   it and initalize from there, as e.g. the linux zr36057/60 driver does it.
+   ========================================================================= */
+
+static const char zr36050_dqt[0x86] = {
+       0xff, 0xdb,             //Marker: DQT
+       0x00, 0x84,             //Length: 2*65+2
+       0x00,                   //Pq,Tq first table
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+       0x01,                   //Pq,Tq second table
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36050_dht[0x1a4] = {
+       0xff, 0xc4,             //Marker: DHT
+       0x01, 0xa2,             //Length: 2*AC, 2*DC
+       0x00,                   //DC first table
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x01,                   //DC second table
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x10,                   //AC first table
+       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+       0xF8, 0xF9, 0xFA,
+       0x11,                   //AC second table
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+       0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS          0x3  //Y,U,V
+#define BASELINE_PRECISION        0x8  //MCU size (?)
+static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
+static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
+static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/* =========================================================================
+   Local helper functions:
+
+   calculation and setup of parameter-dependent JPEG baseline segments
+   (needed for compression only)
+   ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+
+/* SOF (start of frame) segment depends on width, height and sampling ratio
+                        of each color component */
+
+static int
+zr36050_set_sof (struct zr36050 *ptr)
+{
+       char sof_data[34];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+               ptr->width, ptr->height, NO_OF_COMPONENTS);
+       sof_data[0] = 0xff;
+       sof_data[1] = 0xc0;
+       sof_data[2] = 0x00;
+       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36050
+       sof_data[5] = (ptr->height) >> 8;
+       sof_data[6] = (ptr->height) & 0xff;
+       sof_data[7] = (ptr->width) >> 8;
+       sof_data[8] = (ptr->width) & 0xff;
+       sof_data[9] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sof_data[10 + (i * 3)] = i;     // index identifier
+               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]);  // sampling ratios
+               sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
+       }
+       return zr36050_pushit(ptr, ZR050_SOF_IDX,
+                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* SOS (start of scan) segment depends on the used scan components
+                       of each color component */
+
+static int
+zr36050_set_sos (struct zr36050 *ptr)
+{
+       char sos_data[16];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOS\n", ptr->name);
+       sos_data[0] = 0xff;
+       sos_data[1] = 0xda;
+       sos_data[2] = 0x00;
+       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+       sos_data[4] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sos_data[5 + (i * 2)] = i;      // index
+               sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i];   // AC/DC tbl.sel.
+       }
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+       return zr36050_pushit(ptr, ZR050_SOS1_IDX,
+                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+                             sos_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* DRI (define restart interval) */
+
+static int
+zr36050_set_dri (struct zr36050 *ptr)
+{
+       char dri_data[6];       // max. size of register set
+
+       dprintk(3, "%s: write DRI\n", ptr->name);
+       dri_data[0] = 0xff;
+       dri_data[1] = 0xdd;
+       dri_data[2] = 0x00;
+       dri_data[3] = 0x04;
+       dri_data[4] = ptr->dri >> 8;
+       dri_data[5] = ptr->dri & 0xff;
+       return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
+}
+
+/* =========================================================================
+   Setup function:
+
+   Setup compression/decompression of Zoran's JPEG processor
+   ( see also zoran 36050 manual )
+
+   ... sorry for the spaghetti code ...
+   ========================================================================= */
+static void
+zr36050_init (struct zr36050 *ptr)
+{
+       int sum = 0;
+       long bitcnt, tmp;
+
+       if (ptr->mode == CODEC_DO_COMPRESSION) {
+               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
+
+               /* 050 communicates with 057 in master mode */
+               zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
+
+               /* encoding table preload for compression */
+               zr36050_write(ptr, ZR050_MODE,
+                             ZR050_MO_COMP | ZR050_MO_TLM);
+               zr36050_write(ptr, ZR050_OPTIONS, 0);
+
+               /* disable all IRQs */
+               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+               /* volume control settings */
+               /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
+               zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
+               zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
+
+               zr36050_write(ptr, ZR050_AF_HI, 0xff);
+               zr36050_write(ptr, ZR050_AF_M, 0xff);
+               zr36050_write(ptr, ZR050_AF_LO, 0xff);
+
+               /* setup the variable jpeg tables */
+               sum += zr36050_set_sof(ptr);
+               sum += zr36050_set_sos(ptr);
+               sum += zr36050_set_dri(ptr);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name);
+               sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
+                                     sizeof(zr36050_dqt), zr36050_dqt);
+               sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
+                                     sizeof(zr36050_dht), zr36050_dht);
+               zr36050_write(ptr, ZR050_APP_IDX, 0xff);
+               zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
+               zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
+               zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
+               sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
+                                     ptr->app.data) + 4;
+               zr36050_write(ptr, ZR050_COM_IDX, 0xff);
+               zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
+               zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
+               zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
+               sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
+                                     ptr->com.data) + 4;
+
+               /* do the internal huffman table preload */
+               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
+               zr36050_wait_end(ptr);
+               dprintk(2, "%s: Status after table preload: 0x%02x\n",
+                       ptr->name, ptr->status1);
+
+               if ((ptr->status1 & 0x4) == 0) {
+                       dprintk(1, KERN_ERR "%s: init aborted!\n",
+                               ptr->name);
+                       return; // something is wrong, its timed out!!!!
+               }
+
+               /* setup misc. data for compression (target code sizes) */
+
+               /* size of compressed code to reach without header data */
+               sum = ptr->real_code_vol - sum;
+               bitcnt = sum << 3;      /* need the size in bits */
+
+               tmp = bitcnt >> 16;
+               dprintk(3,
+                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+               zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
+
+               bitcnt -= bitcnt >> 7;  // bits without stuffing
+               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
+
+               tmp = bitcnt >> 16;
+               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+                       ptr->name, bitcnt, tmp);
+               zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
+
+               /* compression setup with or without bitrate control */
+               zr36050_write(ptr, ZR050_MODE,
+                             ZR050_MO_COMP | ZR050_MO_PASS2 |
+                             (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
+
+               /* this headers seem to deliver "valid AVI" jpeg frames */
+               zr36050_write(ptr, ZR050_MARKERS_EN,
+                             ZR050_ME_DQT | ZR050_ME_DHT |
+                             ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
+                             ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
+       } else {
+               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
+
+               /* 050 communicates with 055 in master mode */
+               zr36050_write(ptr, ZR050_HARDWARE,
+                             ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
+
+               /* encoding table preload */
+               zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
+
+               /* disable all IRQs */
+               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+               dprintk(3, "%s: write DHT\n", ptr->name);
+               zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
+                              zr36050_dht);
+
+               /* do the internal huffman table preload */
+               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
+               zr36050_wait_end(ptr);
+               dprintk(2, "%s: Status after table preload: 0x%02x\n",
+                       ptr->name, ptr->status1);
+
+               if ((ptr->status1 & 0x4) == 0) {
+                       dprintk(1, KERN_ERR "%s: init aborted!\n",
+                               ptr->name);
+                       return; // something is wrong, its timed out!!!!
+               }
+
+               /* setup misc. data for expansion */
+               zr36050_write(ptr, ZR050_MODE, 0);
+               zr36050_write(ptr, ZR050_MARKERS_EN, 0);
+       }
+
+       /* adr on selected, to allow GO from master */
+       zr36050_read(ptr, 0);
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36050_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36050_init(ptr);
+
+       return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int
+zr36050_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+       int size;
+
+       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
+               ptr->name, norm->HStart, norm->VStart,
+               cap->x, cap->y, cap->width, cap->height,
+               cap->decimation, cap->quality);
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y and norm for now ... */
+       ptr->width = cap->width / (cap->decimation & 0xff);
+       ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
+
+       /* (KM) JPEG quality */
+       size = ptr->width * ptr->height;
+       size *= 16; /* size in bits */
+       /* apply quality setting */
+       size = size * cap->quality / 200;
+
+       /* Minimum: 1kb */
+       if (size < 8192)
+               size = 8192;
+       /* Maximum: 7/8 of code buffer */
+       if (size > ptr->total_code_vol * 7)
+               size = ptr->total_code_vol * 7;
+
+       ptr->real_code_vol = size >> 3; /* in bytes */
+
+       /* Set max_block_vol here (previously in zr36050_init, moved
+        * here for consistency with zr36060 code */
+       zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36050_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               zr36050_read_status1(ptr);
+               *ival = ptr->status1;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = CODEC_MODE_BJPG;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != CODEC_MODE_BJPG)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = ptr->total_code_vol;
+               break;
+
+       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->total_code_vol = *ival;
+               /* (Kieran Morrissey)
+                * code copied from zr36060.c to ensure proper bitrate */
+               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+               break;
+
+       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = zr36050_read_scalefactor(ptr);
+               break;
+
+       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->scalefact = *ival;
+               break;
+
+       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               *app = ptr->app;
+               break;
+       }
+
+       case CODEC_S_JPEG_APP_DATA: {    /* set appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               ptr->app = *app;
+               break;
+       }
+
+       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               *com = ptr->com;
+               break;
+       }
+
+       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               ptr->com = *com;
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36050_unset (struct videocodec *codec)
+{
+       struct zr36050 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36050_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36050_setup (struct videocodec *codec)
+{
+       struct zr36050 *ptr;
+       int res;
+
+       dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n",
+               zr36050_codecs);
+
+       if (zr36050_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36050: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
+                zr36050_codecs);
+       ptr->num = zr36050_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36050_basic_test(ptr);
+       if (res < 0) {
+               zr36050_unset(codec);
+               return res;
+       }
+       //final setup
+       memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
+       memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
+
+       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
+                                * (what is the difference?) */
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 384;
+       ptr->height = 288;
+       ptr->total_code_vol = 16000;
+       ptr->max_block_vol = 240;
+       ptr->scalefact = 0x100;
+       ptr->dri = 1;
+
+       /* no app/com marker by default */
+       ptr->app.appn = 0;
+       ptr->app.len = 0;
+       ptr->com.len = 0;
+
+       zr36050_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec attached and running\n",
+               ptr->name);
+
+       return 0;
+}
+
+static const struct videocodec zr36050_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36050",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER,
+       .type = CODEC_TYPE_ZR36050,
+       .setup = zr36050_setup, // functionality
+       .unset = zr36050_unset,
+       .set_mode = zr36050_set_mode,
+       .set_video = zr36050_set_video,
+       .control = zr36050_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36050_init_module (void)
+{
+       //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
+       zr36050_codecs = 0;
+       return videocodec_register(&zr36050_codec);
+}
+
+static void __exit
+zr36050_cleanup_module (void)
+{
+       if (zr36050_codecs) {
+               dprintk(1,
+                       "zr36050: something's wrong - %d codecs left somehow.\n",
+                       zr36050_codecs);
+       }
+       videocodec_unregister(&zr36050_codec);
+}
+
+module_init(zr36050_init_module);
+module_exit(zr36050_cleanup_module);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
+                  ZR050_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36050.h b/drivers/media/video/zoran/zr36050.h
new file mode 100644 (file)
index 0000000..9f52f0c
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Zoran ZR36050 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36050.h,v 1.1.2.2 2003/01/14 21:18:22 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 ZR36050_H
+#define ZR36050_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36050 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // last coder status
+       __u8 status1;
+       // actual coder setup
+       int mode;
+
+       __u16 width;
+       __u16 height;
+
+       __u16 bitrate_ctrl;
+
+       __u32 total_code_vol;
+       __u32 real_code_vol;
+       __u16 max_block_vol;
+
+       __u8 h_samp_ratio[8];
+       __u8 v_samp_ratio[8];
+       __u16 scalefact;
+       __u16 dri;
+
+       /* com/app marker */
+       struct jpeg_com_marker com;
+       struct jpeg_app_marker app;
+};
+
+/* zr36050 register addresses */
+#define ZR050_GO                  0x000
+#define ZR050_HARDWARE            0x002
+#define ZR050_MODE                0x003
+#define ZR050_OPTIONS             0x004
+#define ZR050_MBCV                0x005
+#define ZR050_MARKERS_EN          0x006
+#define ZR050_INT_REQ_0           0x007
+#define ZR050_INT_REQ_1           0x008
+#define ZR050_TCV_NET_HI          0x009
+#define ZR050_TCV_NET_MH          0x00a
+#define ZR050_TCV_NET_ML          0x00b
+#define ZR050_TCV_NET_LO          0x00c
+#define ZR050_TCV_DATA_HI         0x00d
+#define ZR050_TCV_DATA_MH         0x00e
+#define ZR050_TCV_DATA_ML         0x00f
+#define ZR050_TCV_DATA_LO         0x010
+#define ZR050_SF_HI               0x011
+#define ZR050_SF_LO               0x012
+#define ZR050_AF_HI               0x013
+#define ZR050_AF_M                0x014
+#define ZR050_AF_LO               0x015
+#define ZR050_ACV_HI              0x016
+#define ZR050_ACV_MH              0x017
+#define ZR050_ACV_ML              0x018
+#define ZR050_ACV_LO              0x019
+#define ZR050_ACT_HI              0x01a
+#define ZR050_ACT_MH              0x01b
+#define ZR050_ACT_ML              0x01c
+#define ZR050_ACT_LO              0x01d
+#define ZR050_ACV_TRUN_HI         0x01e
+#define ZR050_ACV_TRUN_MH         0x01f
+#define ZR050_ACV_TRUN_ML         0x020
+#define ZR050_ACV_TRUN_LO         0x021
+#define ZR050_STATUS_0            0x02e
+#define ZR050_STATUS_1            0x02f
+
+#define ZR050_SOF_IDX             0x040
+#define ZR050_SOS1_IDX            0x07a
+#define ZR050_SOS2_IDX            0x08a
+#define ZR050_SOS3_IDX            0x09a
+#define ZR050_SOS4_IDX            0x0aa
+#define ZR050_DRI_IDX             0x0c0
+#define ZR050_DNL_IDX             0x0c6
+#define ZR050_DQT_IDX             0x0cc
+#define ZR050_DHT_IDX             0x1d4
+#define ZR050_APP_IDX             0x380
+#define ZR050_COM_IDX             0x3c0
+
+/* zr36050 hardware register bits */
+
+#define ZR050_HW_BSWD                0x80
+#define ZR050_HW_MSTR                0x40
+#define ZR050_HW_DMA                 0x20
+#define ZR050_HW_CFIS_1_CLK          0x00
+#define ZR050_HW_CFIS_2_CLK          0x04
+#define ZR050_HW_CFIS_3_CLK          0x08
+#define ZR050_HW_CFIS_4_CLK          0x0C
+#define ZR050_HW_CFIS_5_CLK          0x10
+#define ZR050_HW_CFIS_6_CLK          0x14
+#define ZR050_HW_CFIS_7_CLK          0x18
+#define ZR050_HW_CFIS_8_CLK          0x1C
+#define ZR050_HW_BELE                0x01
+
+/* zr36050 mode register bits */
+
+#define ZR050_MO_COMP                0x80
+#define ZR050_MO_COMP                0x80
+#define ZR050_MO_ATP                 0x40
+#define ZR050_MO_PASS2               0x20
+#define ZR050_MO_TLM                 0x10
+#define ZR050_MO_DCONLY              0x08
+#define ZR050_MO_BRC                 0x04
+
+#define ZR050_MO_ATP                 0x40
+#define ZR050_MO_PASS2               0x20
+#define ZR050_MO_TLM                 0x10
+#define ZR050_MO_DCONLY              0x08
+
+/* zr36050 option register bits */
+
+#define ZR050_OP_NSCN_1              0x00
+#define ZR050_OP_NSCN_2              0x20
+#define ZR050_OP_NSCN_3              0x40
+#define ZR050_OP_NSCN_4              0x60
+#define ZR050_OP_NSCN_5              0x80
+#define ZR050_OP_NSCN_6              0xA0
+#define ZR050_OP_NSCN_7              0xC0
+#define ZR050_OP_NSCN_8              0xE0
+#define ZR050_OP_OVF                 0x10
+
+
+/* zr36050 markers-enable register bits */
+
+#define ZR050_ME_APP                 0x80
+#define ZR050_ME_COM                 0x40
+#define ZR050_ME_DRI                 0x20
+#define ZR050_ME_DQT                 0x10
+#define ZR050_ME_DHT                 0x08
+#define ZR050_ME_DNL                 0x04
+#define ZR050_ME_DQTI                0x02
+#define ZR050_ME_DHTI                0x01
+
+/* zr36050 status0/1 register bit masks */
+
+#define ZR050_ST_RST_MASK            0x20
+#define ZR050_ST_SOF_MASK            0x02
+#define ZR050_ST_SOS_MASK            0x02
+#define ZR050_ST_DATRDY_MASK         0x80
+#define ZR050_ST_MRKDET_MASK         0x40
+#define ZR050_ST_RFM_MASK            0x10
+#define ZR050_ST_RFD_MASK            0x08
+#define ZR050_ST_END_MASK            0x04
+#define ZR050_ST_TCVOVF_MASK         0x02
+#define ZR050_ST_DATOVF_MASK         0x01
+
+/* pixel component idx */
+
+#define ZR050_Y_COMPONENT         0
+#define ZR050_U_COMPONENT         1
+#define ZR050_V_COMPONENT         2
+
+#endif                         /*fndef ZR36050_H */
diff --git a/drivers/media/video/zoran/zr36057.h b/drivers/media/video/zoran/zr36057.h
new file mode 100644 (file)
index 0000000..54c9362
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * zr36057.h - zr36057 register offsets
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 _ZR36057_H_
+#define _ZR36057_H_
+
+
+/* Zoran ZR36057 registers */
+
+#define ZR36057_VFEHCR          0x000  /* Video Front End, Horizontal Configuration Register */
+#define ZR36057_VFEHCR_HSPol            (1<<30)
+#define ZR36057_VFEHCR_HStart           10
+#define ZR36057_VFEHCR_HEnd            0
+#define ZR36057_VFEHCR_Hmask           0x3ff
+
+#define ZR36057_VFEVCR          0x004  /* Video Front End, Vertical Configuration Register */
+#define ZR36057_VFEVCR_VSPol            (1<<30)
+#define ZR36057_VFEVCR_VStart           10
+#define ZR36057_VFEVCR_VEnd            0
+#define ZR36057_VFEVCR_Vmask           0x3ff
+
+#define ZR36057_VFESPFR         0x008  /* Video Front End, Scaler and Pixel Format Register */
+#define ZR36057_VFESPFR_ExtFl           (1<<26)
+#define ZR36057_VFESPFR_TopField        (1<<25)
+#define ZR36057_VFESPFR_VCLKPol         (1<<24)
+#define ZR36057_VFESPFR_HFilter         21
+#define ZR36057_VFESPFR_HorDcm          14
+#define ZR36057_VFESPFR_VerDcm          8
+#define ZR36057_VFESPFR_DispMode        6
+#define ZR36057_VFESPFR_YUV422          (0<<3)
+#define ZR36057_VFESPFR_RGB888          (1<<3)
+#define ZR36057_VFESPFR_RGB565          (2<<3)
+#define ZR36057_VFESPFR_RGB555          (3<<3)
+#define ZR36057_VFESPFR_ErrDif          (1<<2)
+#define ZR36057_VFESPFR_Pack24          (1<<1)
+#define ZR36057_VFESPFR_LittleEndian    (1<<0)
+
+#define ZR36057_VDTR            0x00c  /* Video Display "Top" Register */
+
+#define ZR36057_VDBR            0x010  /* Video Display "Bottom" Register */
+
+#define ZR36057_VSSFGR          0x014  /* Video Stride, Status, and Frame Grab Register */
+#define ZR36057_VSSFGR_DispStride       16
+#define ZR36057_VSSFGR_VidOvf           (1<<8)
+#define ZR36057_VSSFGR_SnapShot         (1<<1)
+#define ZR36057_VSSFGR_FrameGrab        (1<<0)
+
+#define ZR36057_VDCR            0x018  /* Video Display Configuration Register */
+#define ZR36057_VDCR_VidEn              (1<<31)
+#define ZR36057_VDCR_MinPix             24
+#define ZR36057_VDCR_Triton             (1<<24)
+#define ZR36057_VDCR_VidWinHt           12
+#define ZR36057_VDCR_VidWinWid          0
+
+#define ZR36057_MMTR            0x01c  /* Masking Map "Top" Register */
+
+#define ZR36057_MMBR            0x020  /* Masking Map "Bottom" Register */
+
+#define ZR36057_OCR             0x024  /* Overlay Control Register */
+#define ZR36057_OCR_OvlEnable           (1 << 15)
+#define ZR36057_OCR_MaskStride          0
+
+#define ZR36057_SPGPPCR         0x028  /* System, PCI, and General Purpose Pins Control Register */
+#define ZR36057_SPGPPCR_SoftReset      (1<<24)
+
+#define ZR36057_GPPGCR1         0x02c  /* General Purpose Pins and GuestBus Control Register (1) */
+
+#define ZR36057_MCSAR           0x030  /* MPEG Code Source Address Register */
+
+#define ZR36057_MCTCR           0x034  /* MPEG Code Transfer Control Register */
+#define ZR36057_MCTCR_CodTime           (1 << 30)
+#define ZR36057_MCTCR_CEmpty            (1 << 29)
+#define ZR36057_MCTCR_CFlush            (1 << 28)
+#define ZR36057_MCTCR_CodGuestID       20
+#define ZR36057_MCTCR_CodGuestReg      16
+
+#define ZR36057_MCMPR           0x038  /* MPEG Code Memory Pointer Register */
+
+#define ZR36057_ISR             0x03c  /* Interrupt Status Register */
+#define ZR36057_ISR_GIRQ1               (1<<30)
+#define ZR36057_ISR_GIRQ0               (1<<29)
+#define ZR36057_ISR_CodRepIRQ           (1<<28)
+#define ZR36057_ISR_JPEGRepIRQ          (1<<27)
+
+#define ZR36057_ICR             0x040  /* Interrupt Control Register */
+#define ZR36057_ICR_GIRQ1               (1<<30)
+#define ZR36057_ICR_GIRQ0               (1<<29)
+#define ZR36057_ICR_CodRepIRQ           (1<<28)
+#define ZR36057_ICR_JPEGRepIRQ          (1<<27)
+#define ZR36057_ICR_IntPinEn            (1<<24)
+
+#define ZR36057_I2CBR           0x044  /* I2C Bus Register */
+#define ZR36057_I2CBR_SDA              (1<<1)
+#define ZR36057_I2CBR_SCL              (1<<0)
+
+#define ZR36057_JMC             0x100  /* JPEG Mode and Control */
+#define ZR36057_JMC_JPG                 (1 << 31)
+#define ZR36057_JMC_JPGExpMode          (0 << 29)
+#define ZR36057_JMC_JPGCmpMode          (1 << 29)
+#define ZR36057_JMC_MJPGExpMode         (2 << 29)
+#define ZR36057_JMC_MJPGCmpMode         (3 << 29)
+#define ZR36057_JMC_RTBUSY_FB           (1 << 6)
+#define ZR36057_JMC_Go_en               (1 << 5)
+#define ZR36057_JMC_SyncMstr            (1 << 4)
+#define ZR36057_JMC_Fld_per_buff        (1 << 3)
+#define ZR36057_JMC_VFIFO_FB            (1 << 2)
+#define ZR36057_JMC_CFIFO_FB            (1 << 1)
+#define ZR36057_JMC_Stll_LitEndian      (1 << 0)
+
+#define ZR36057_JPC             0x104  /* JPEG Process Control */
+#define ZR36057_JPC_P_Reset             (1 << 7)
+#define ZR36057_JPC_CodTrnsEn           (1 << 5)
+#define ZR36057_JPC_Active              (1 << 0)
+
+#define ZR36057_VSP             0x108  /* Vertical Sync Parameters */
+#define ZR36057_VSP_VsyncSize           16
+#define ZR36057_VSP_FrmTot              0
+
+#define ZR36057_HSP             0x10c  /* Horizontal Sync Parameters */
+#define ZR36057_HSP_HsyncStart          16
+#define ZR36057_HSP_LineTot             0
+
+#define ZR36057_FHAP            0x110  /* Field Horizontal Active Portion */
+#define ZR36057_FHAP_NAX                16
+#define ZR36057_FHAP_PAX                0
+
+#define ZR36057_FVAP            0x114  /* Field Vertical Active Portion */
+#define ZR36057_FVAP_NAY                16
+#define ZR36057_FVAP_PAY                0
+
+#define ZR36057_FPP             0x118  /* Field Process Parameters */
+#define ZR36057_FPP_Odd_Even            (1 << 0)
+
+#define ZR36057_JCBA            0x11c  /* JPEG Code Base Address */
+
+#define ZR36057_JCFT            0x120  /* JPEG Code FIFO Threshold */
+
+#define ZR36057_JCGI            0x124  /* JPEG Codec Guest ID */
+#define ZR36057_JCGI_JPEGuestID         4
+#define ZR36057_JCGI_JPEGuestReg        0
+
+#define ZR36057_GCR2            0x12c  /* GuestBus Control Register (2) */
+
+#define ZR36057_POR             0x200  /* Post Office Register */
+#define ZR36057_POR_POPen               (1<<25)
+#define ZR36057_POR_POTime              (1<<24)
+#define ZR36057_POR_PODir               (1<<23)
+
+#define ZR36057_STR             0x300  /* "Still" Transfer Register */
+
+#endif
diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c
new file mode 100644 (file)
index 0000000..8e74054
--- /dev/null
@@ -0,0 +1,1014 @@
+/*
+ * Zoran ZR36060 basic configuration functions
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#define ZR060_VERSION "v0.7"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* includes for structures and defines regarding video
+   #include<linux/videodev.h> */
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+//#include<errno.h>
+
+/* headerfile of this module */
+#include "zr36060.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36060_codecs;
+
+static int low_bitrate;
+module_param(low_bitrate, bool, 0);
+MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
+
+/* debugging is available via module parameter */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36060_read (struct zr36060 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value = (ptr->codec->master_data->readreg(ptr->codec,
+                                                         reg)) & 0xff;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value);
+
+       return value;
+}
+
+static void
+zr36060_write(struct zr36060 *ptr,
+             u16             reg,
+             u8              value)
+{
+       //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg);
+       dprintk(4, "0x%02x @0x%04x\n", value, reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg)
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   status read
+   ========================================================================= */
+
+/* status is kept in datastructure */
+static u8
+zr36060_read_status (struct zr36060 *ptr)
+{
+       ptr->status = zr36060_read(ptr, ZR060_CFSR);
+
+       zr36060_read(ptr, 0);
+       return ptr->status;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   scale factor read
+   ========================================================================= */
+
+/* scale factor is kept in datastructure */
+static u16
+zr36060_read_scalefactor (struct zr36060 *ptr)
+{
+       ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
+                        (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
+
+       /* leave 0 selected for an eventually GO from master */
+       zr36060_read(ptr, 0);
+       return ptr->scalefact;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   wait if codec is ready to proceed (end of processing) or time is over
+   ========================================================================= */
+
+static void
+zr36060_wait_end (struct zr36060 *ptr)
+{
+       int i = 0;
+
+       while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
+               udelay(1);
+               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
+                       dprintk(1,
+                               "%s: timeout at wait_end (last status: 0x%02x)\n",
+                               ptr->name, ptr->status);
+                       break;
+               }
+       }
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from memory the SOF marker
+   ========================================================================= */
+
+static int
+zr36060_basic_test (struct zr36060 *ptr)
+{
+       if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
+           (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+
+       zr36060_wait_end(ptr);
+       if (ptr->status & ZR060_CFSR_Busy) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, jpeg processor failed (end flag)!\n",
+                       ptr->name);
+               return -EBUSY;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets
+   ========================================================================= */
+
+static int
+zr36060_pushit (struct zr36060 *ptr,
+               u16             startreg,
+               u16             len,
+               const char     *data)
+{
+       int i = 0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+               startreg, len);
+       while (i < len) {
+               zr36060_write(ptr, startreg++, data[i++]);
+       }
+
+       return i;
+}
+
+/* =========================================================================
+   Basic datasets:
+
+   jpeg baseline setup data (you find it on lots places in internet, or just
+   extract it from any regular .jpg image...)
+
+   Could be variable, but until it's not needed it they are just fixed to save
+   memory. Otherwise expand zr36060 structure with arrays, push the values to
+   it and initalize from there, as e.g. the linux zr36057/60 driver does it.
+   ========================================================================= */
+
+static const char zr36060_dqt[0x86] = {
+       0xff, 0xdb,             //Marker: DQT
+       0x00, 0x84,             //Length: 2*65+2
+       0x00,                   //Pq,Tq first table
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+       0x01,                   //Pq,Tq second table
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36060_dht[0x1a4] = {
+       0xff, 0xc4,             //Marker: DHT
+       0x01, 0xa2,             //Length: 2*AC, 2*DC
+       0x00,                   //DC first table
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x01,                   //DC second table
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x10,                   //AC first table
+       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+       0xF8, 0xF9, 0xFA,
+       0x11,                   //AC second table
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+       0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS          0x3  //Y,U,V
+#define BASELINE_PRECISION        0x8  //MCU size (?)
+static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
+static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
+static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/* =========================================================================
+   Local helper functions:
+
+   calculation and setup of parameter-dependent JPEG baseline segments
+   (needed for compression only)
+   ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+
+/* SOF (start of frame) segment depends on width, height and sampling ratio
+                        of each color component */
+
+static int
+zr36060_set_sof (struct zr36060 *ptr)
+{
+       char sof_data[34];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+               ptr->width, ptr->height, NO_OF_COMPONENTS);
+       sof_data[0] = 0xff;
+       sof_data[1] = 0xc0;
+       sof_data[2] = 0x00;
+       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36060
+       sof_data[5] = (ptr->height) >> 8;
+       sof_data[6] = (ptr->height) & 0xff;
+       sof_data[7] = (ptr->width) >> 8;
+       sof_data[8] = (ptr->width) & 0xff;
+       sof_data[9] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sof_data[10 + (i * 3)] = i;     // index identifier
+               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
+                                        (ptr->v_samp_ratio[i]); // sampling ratios
+               sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
+       }
+       return zr36060_pushit(ptr, ZR060_SOF_IDX,
+                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* SOS (start of scan) segment depends on the used scan components
+                       of each color component */
+
+static int
+zr36060_set_sos (struct zr36060 *ptr)
+{
+       char sos_data[16];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOS\n", ptr->name);
+       sos_data[0] = 0xff;
+       sos_data[1] = 0xda;
+       sos_data[2] = 0x00;
+       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+       sos_data[4] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sos_data[5 + (i * 2)] = i;      // index
+               sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
+                                       zr36060_ta[i]; // AC/DC tbl.sel.
+       }
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+       return zr36060_pushit(ptr, ZR060_SOS_IDX,
+                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+                             sos_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* DRI (define restart interval) */
+
+static int
+zr36060_set_dri (struct zr36060 *ptr)
+{
+       char dri_data[6];       // max. size of register set
+
+       dprintk(3, "%s: write DRI\n", ptr->name);
+       dri_data[0] = 0xff;
+       dri_data[1] = 0xdd;
+       dri_data[2] = 0x00;
+       dri_data[3] = 0x04;
+       dri_data[4] = (ptr->dri) >> 8;
+       dri_data[5] = (ptr->dri) & 0xff;
+       return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
+}
+
+/* =========================================================================
+   Setup function:
+
+   Setup compression/decompression of Zoran's JPEG processor
+   ( see also zoran 36060 manual )
+
+   ... sorry for the spaghetti code ...
+   ========================================================================= */
+static void
+zr36060_init (struct zr36060 *ptr)
+{
+       int sum = 0;
+       long bitcnt, tmp;
+
+       if (ptr->mode == CODEC_DO_COMPRESSION) {
+               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
+
+               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+               /* 060 communicates with 067 in master mode */
+               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
+
+               /* Compression with or without variable scale factor */
+               /*FIXME: What about ptr->bitrate_ctrl? */
+               zr36060_write(ptr, ZR060_CMR,
+                             ZR060_CMR_Comp | ZR060_CMR_Pass2 |
+                             ZR060_CMR_BRB);
+
+               /* Must be zero */
+               zr36060_write(ptr, ZR060_MBZ, 0x00);
+               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+               /* Disable all IRQs - no DataErr means autoreset */
+               zr36060_write(ptr, ZR060_IMR, 0);
+
+               /* volume control settings */
+               zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
+               zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
+
+               zr36060_write(ptr, ZR060_AF_HI, 0xff);
+               zr36060_write(ptr, ZR060_AF_M, 0xff);
+               zr36060_write(ptr, ZR060_AF_LO, 0xff);
+
+               /* setup the variable jpeg tables */
+               sum += zr36060_set_sof(ptr);
+               sum += zr36060_set_sos(ptr);
+               sum += zr36060_set_dri(ptr);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               sum +=
+                   zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
+                                  zr36060_dqt);
+               sum +=
+                   zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
+                                  zr36060_dht);
+               zr36060_write(ptr, ZR060_APP_IDX, 0xff);
+               zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
+               zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
+               zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
+               sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
+                                     ptr->app.data) + 4;
+               zr36060_write(ptr, ZR060_COM_IDX, 0xff);
+               zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
+               zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
+               zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
+               sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
+                                     ptr->com.data) + 4;
+
+               /* setup misc. data for compression (target code sizes) */
+
+               /* size of compressed code to reach without header data */
+               sum = ptr->real_code_vol - sum;
+               bitcnt = sum << 3;      /* need the size in bits */
+
+               tmp = bitcnt >> 16;
+               dprintk(3,
+                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+               zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
+
+               bitcnt -= bitcnt >> 7;  // bits without stuffing
+               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
+
+               tmp = bitcnt >> 16;
+               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+                       ptr->name, bitcnt, tmp);
+               zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
+
+               /* JPEG markers to be included in the compressed stream */
+               zr36060_write(ptr, ZR060_MER,
+                             ZR060_MER_DQT | ZR060_MER_DHT |
+                             ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
+                             ((ptr->app.len > 0) ? ZR060_MER_App : 0));
+
+               /* Setup the Video Frontend */
+               /* Limit pixel range to 16..235 as per CCIR-601 */
+               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
+
+       } else {
+               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
+
+               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+               /* 060 communicates with 067 in master mode */
+               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
+
+               /* Decompression */
+               zr36060_write(ptr, ZR060_CMR, 0);
+
+               /* Must be zero */
+               zr36060_write(ptr, ZR060_MBZ, 0x00);
+               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+               /* Disable all IRQs - no DataErr means autoreset */
+               zr36060_write(ptr, ZR060_IMR, 0);
+
+               /* setup misc. data for expansion */
+               zr36060_write(ptr, ZR060_MER, 0);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
+                              zr36060_dht);
+
+               /* Setup the Video Frontend */
+               //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt);
+               //this doesn't seem right and doesn't work...
+               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
+       }
+
+       /* Load the tables */
+       zr36060_write(ptr, ZR060_LOAD,
+                     ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
+       zr36060_wait_end(ptr);
+       dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
+               ptr->status);
+
+       if (ptr->status & ZR060_CFSR_Busy) {
+               dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
+               return;         // something is wrong, its timed out!!!!
+       }
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36060_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36060_init(ptr);
+
+       return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int
+zr36060_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+       u32 reg;
+       int size;
+
+       dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
+               cap->x, cap->y, cap->width, cap->height, cap->decimation);
+
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y and norm for now ... */
+       ptr->width = cap->width / (cap->decimation & 0xff);
+       ptr->height = cap->height / (cap->decimation >> 8);
+
+       zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+       /* Note that VSPol/HSPol bits in zr36060 have the opposite
+        * meaning of their zr360x7 counterparts with the same names
+        * N.b. for VSPol this is only true if FIVEdge = 0 (default,
+        * left unchanged here - in accordance with datasheet).
+       */
+       reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
+           | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
+           | (pol->field_pol ? ZR060_VPR_FIPol : 0)
+           | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
+           | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
+           | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
+           | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
+           | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
+       zr36060_write(ptr, ZR060_VPR, reg);
+
+       reg = 0;
+       switch (cap->decimation & 0xff) {
+       default:
+       case 1:
+               break;
+
+       case 2:
+               reg |= ZR060_SR_HScale2;
+               break;
+
+       case 4:
+               reg |= ZR060_SR_HScale4;
+               break;
+       }
+
+       switch (cap->decimation >> 8) {
+       default:
+       case 1:
+               break;
+
+       case 2:
+               reg |= ZR060_SR_VScale;
+               break;
+       }
+       zr36060_write(ptr, ZR060_SR, reg);
+
+       zr36060_write(ptr, ZR060_BCR_Y, 0x00);
+       zr36060_write(ptr, ZR060_BCR_U, 0x80);
+       zr36060_write(ptr, ZR060_BCR_V, 0x80);
+
+       /* sync generator */
+
+       reg = norm->Ht - 1;     /* Vtotal */
+       zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
+
+       reg = norm->Wt - 1;     /* Htotal */
+       zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
+
+       reg = 6 - 1;            /* VsyncSize */
+       zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
+
+       //reg   = 30 - 1;               /* HsyncSize */
+///*CP*/        reg = (zr->params.norm == 1 ? 57 : 68);
+       reg = 68;
+       zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
+
+       reg = norm->VStart - 1; /* BVstart */
+       zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
+
+       reg += norm->Ha / 2;    /* BVend */
+       zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
+
+       reg = norm->HStart - 1; /* BHstart */
+       zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
+
+       reg += norm->Wa;        /* BHend */
+       zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
+
+       /* active area */
+       reg = cap->y + norm->VStart;    /* Vstart */
+       zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
+
+       reg += cap->height;     /* Vend */
+       zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
+
+       reg = cap->x + norm->HStart;    /* Hstart */
+       zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
+
+       reg += cap->width;      /* Hend */
+       zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
+
+       /* subimage area */
+       reg = norm->VStart - 4; /* SVstart */
+       zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
+
+       reg += norm->Ha / 2 + 8;        /* SVend */
+       zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
+
+       reg = norm->HStart /*+ 64 */  - 4;      /* SHstart */
+       zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
+
+       reg += norm->Wa + 8;    /* SHend */
+       zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
+
+       size = ptr->width * ptr->height;
+       /* Target compressed field size in bits: */
+       size = size * 16;       /* uncompressed size in bits */
+       /* (Ronald) by default, quality = 100 is a compression
+        * ratio 1:2. Setting low_bitrate (insmod option) sets
+        * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
+        * buz can't handle more at decimation=1... Use low_bitrate if
+        * you have a Buz, unless you know what you're doing */
+       size = size * cap->quality / (low_bitrate ? 400 : 200);
+       /* Lower limit (arbitrary, 1 KB) */
+       if (size < 8192)
+               size = 8192;
+       /* Upper limit: 7/8 of the code buffers */
+       if (size > ptr->total_code_vol * 7)
+               size = ptr->total_code_vol * 7;
+
+       ptr->real_code_vol = size >> 3; /* in bytes */
+
+       /* the MBCVR is the *maximum* block volume, according to the
+        * JPEG ISO specs, this shouldn't be used, since that allows
+        * for the best encoding quality. So set it to it's max value */
+       reg = ptr->max_block_vol;
+       zr36060_write(ptr, ZR060_MBCVR, reg);
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36060_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               zr36060_read_status(ptr);
+               *ival = ptr->status;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = CODEC_MODE_BJPG;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != CODEC_MODE_BJPG)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = ptr->total_code_vol;
+               break;
+
+       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->total_code_vol = *ival;
+               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+               break;
+
+       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = zr36060_read_scalefactor(ptr);
+               break;
+
+       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->scalefact = *ival;
+               break;
+
+       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               *app = ptr->app;
+               break;
+       }
+
+       case CODEC_S_JPEG_APP_DATA: {   /* set appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               ptr->app = *app;
+               break;
+       }
+
+       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               *com = ptr->com;
+               break;
+       }
+
+       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               ptr->com = *com;
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36060_unset (struct videocodec *codec)
+{
+       struct zr36060 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36060_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36060_setup (struct videocodec *codec)
+{
+       struct zr36060 *ptr;
+       int res;
+
+       dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
+               zr36060_codecs);
+
+       if (zr36060_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36060: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
+                zr36060_codecs);
+       ptr->num = zr36060_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36060_basic_test(ptr);
+       if (res < 0) {
+               zr36060_unset(codec);
+               return res;
+       }
+       //final setup
+       memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
+       memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
+
+       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
+                                * (what is the difference?) */
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 384;
+       ptr->height = 288;
+       ptr->total_code_vol = 16000;    /* CHECKME */
+       ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+       ptr->max_block_vol = 240;       /* CHECKME, was 120 is 240 */
+       ptr->scalefact = 0x100;
+       ptr->dri = 1;           /* CHECKME, was 8 is 1 */
+
+       /* by default, no COM or APP markers - app should set those */
+       ptr->com.len = 0;
+       ptr->app.appn = 0;
+       ptr->app.len = 0;
+
+       zr36060_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec attached and running\n",
+               ptr->name);
+
+       return 0;
+}
+
+static const struct videocodec zr36060_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36060",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
+       .type = CODEC_TYPE_ZR36060,
+       .setup = zr36060_setup, // functionality
+       .unset = zr36060_unset,
+       .set_mode = zr36060_set_mode,
+       .set_video = zr36060_set_video,
+       .control = zr36060_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36060_init_module (void)
+{
+       //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION);
+       zr36060_codecs = 0;
+       return videocodec_register(&zr36060_codec);
+}
+
+static void __exit
+zr36060_cleanup_module (void)
+{
+       if (zr36060_codecs) {
+               dprintk(1,
+                       "zr36060: something's wrong - %d codecs left somehow.\n",
+                       zr36060_codecs);
+       }
+
+       /* however, we can't just stay alive */
+       videocodec_unregister(&zr36060_codec);
+}
+
+module_init(zr36060_init_module);
+module_exit(zr36060_cleanup_module);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
+MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
+                  ZR060_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36060.h b/drivers/media/video/zoran/zr36060.h
new file mode 100644 (file)
index 0000000..914ffa4
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Zoran ZR36060 basic configuration functions - header file
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * $Id: zr36060.h,v 1.1.1.1.2.3 2003/01/14 21:18:47 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 ZR36060_H
+#define ZR36060_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36060 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // last coder status
+       __u8 status;
+       // actual coder setup
+       int mode;
+
+       __u16 width;
+       __u16 height;
+
+       __u16 bitrate_ctrl;
+
+       __u32 total_code_vol;
+       __u32 real_code_vol;
+       __u16 max_block_vol;
+
+       __u8 h_samp_ratio[8];
+       __u8 v_samp_ratio[8];
+       __u16 scalefact;
+       __u16 dri;
+
+       /* app/com marker data */
+       struct jpeg_app_marker app;
+       struct jpeg_com_marker com;
+};
+
+/* ZR36060 register addresses */
+#define ZR060_LOAD                     0x000
+#define ZR060_CFSR                     0x001
+#define ZR060_CIR                      0x002
+#define ZR060_CMR                      0x003
+#define ZR060_MBZ                      0x004
+#define ZR060_MBCVR                    0x005
+#define ZR060_MER                      0x006
+#define ZR060_IMR                      0x007
+#define ZR060_ISR                      0x008
+#define ZR060_TCV_NET_HI               0x009
+#define ZR060_TCV_NET_MH               0x00a
+#define ZR060_TCV_NET_ML               0x00b
+#define ZR060_TCV_NET_LO               0x00c
+#define ZR060_TCV_DATA_HI              0x00d
+#define ZR060_TCV_DATA_MH              0x00e
+#define ZR060_TCV_DATA_ML              0x00f
+#define ZR060_TCV_DATA_LO              0x010
+#define ZR060_SF_HI                    0x011
+#define ZR060_SF_LO                    0x012
+#define ZR060_AF_HI                    0x013
+#define ZR060_AF_M                     0x014
+#define ZR060_AF_LO                    0x015
+#define ZR060_ACV_HI                   0x016
+#define ZR060_ACV_MH                   0x017
+#define ZR060_ACV_ML                   0x018
+#define ZR060_ACV_LO                   0x019
+#define ZR060_ACT_HI                   0x01a
+#define ZR060_ACT_MH                   0x01b
+#define ZR060_ACT_ML                   0x01c
+#define ZR060_ACT_LO                   0x01d
+#define ZR060_ACV_TRUN_HI              0x01e
+#define ZR060_ACV_TRUN_MH              0x01f
+#define ZR060_ACV_TRUN_ML              0x020
+#define ZR060_ACV_TRUN_LO              0x021
+#define ZR060_IDR_DEV                  0x022
+#define ZR060_IDR_REV                  0x023
+#define ZR060_TCR_HI                   0x024
+#define ZR060_TCR_LO                   0x025
+#define ZR060_VCR                      0x030
+#define ZR060_VPR                      0x031
+#define ZR060_SR                       0x032
+#define ZR060_BCR_Y                    0x033
+#define ZR060_BCR_U                    0x034
+#define ZR060_BCR_V                    0x035
+#define ZR060_SGR_VTOTAL_HI            0x036
+#define ZR060_SGR_VTOTAL_LO            0x037
+#define ZR060_SGR_HTOTAL_HI            0x038
+#define ZR060_SGR_HTOTAL_LO            0x039
+#define ZR060_SGR_VSYNC                        0x03a
+#define ZR060_SGR_HSYNC                        0x03b
+#define ZR060_SGR_BVSTART              0x03c
+#define ZR060_SGR_BHSTART              0x03d
+#define ZR060_SGR_BVEND_HI             0x03e
+#define ZR060_SGR_BVEND_LO             0x03f
+#define ZR060_SGR_BHEND_HI             0x040
+#define ZR060_SGR_BHEND_LO             0x041
+#define ZR060_AAR_VSTART_HI            0x042
+#define ZR060_AAR_VSTART_LO            0x043
+#define ZR060_AAR_VEND_HI              0x044
+#define ZR060_AAR_VEND_LO              0x045
+#define ZR060_AAR_HSTART_HI            0x046
+#define ZR060_AAR_HSTART_LO            0x047
+#define ZR060_AAR_HEND_HI              0x048
+#define ZR060_AAR_HEND_LO              0x049
+#define ZR060_SWR_VSTART_HI            0x04a
+#define ZR060_SWR_VSTART_LO            0x04b
+#define ZR060_SWR_VEND_HI              0x04c
+#define ZR060_SWR_VEND_LO              0x04d
+#define ZR060_SWR_HSTART_HI            0x04e
+#define ZR060_SWR_HSTART_LO            0x04f
+#define ZR060_SWR_HEND_HI              0x050
+#define ZR060_SWR_HEND_LO              0x051
+
+#define ZR060_SOF_IDX                  0x060
+#define ZR060_SOS_IDX                  0x07a
+#define ZR060_DRI_IDX                  0x0c0
+#define ZR060_DQT_IDX                  0x0cc
+#define ZR060_DHT_IDX                  0x1d4
+#define ZR060_APP_IDX                  0x380
+#define ZR060_COM_IDX                  0x3c0
+
+/* ZR36060 LOAD register bits */
+
+#define ZR060_LOAD_Load                        (1 << 7)
+#define ZR060_LOAD_SyncRst             (1 << 0)
+
+/* ZR36060 Code FIFO Status register bits */
+
+#define ZR060_CFSR_Busy                        (1 << 7)
+#define ZR060_CFSR_CBusy               (1 << 2)
+#define ZR060_CFSR_CFIFO               (3 << 0)
+
+/* ZR36060 Code Interface register */
+
+#define ZR060_CIR_Code16               (1 << 7)
+#define ZR060_CIR_Endian               (1 << 6)
+#define ZR060_CIR_CFIS                 (1 << 2)
+#define ZR060_CIR_CodeMstr             (1 << 0)
+
+/* ZR36060 Codec Mode register */
+
+#define ZR060_CMR_Comp                 (1 << 7)
+#define ZR060_CMR_ATP                  (1 << 6)
+#define ZR060_CMR_Pass2                        (1 << 5)
+#define ZR060_CMR_TLM                  (1 << 4)
+#define ZR060_CMR_BRB                  (1 << 2)
+#define ZR060_CMR_FSF                  (1 << 1)
+
+/* ZR36060 Markers Enable register */
+
+#define ZR060_MER_App                  (1 << 7)
+#define ZR060_MER_Com                  (1 << 6)
+#define ZR060_MER_DRI                  (1 << 5)
+#define ZR060_MER_DQT                  (1 << 4)
+#define ZR060_MER_DHT                  (1 << 3)
+
+/* ZR36060 Interrupt Mask register */
+
+#define ZR060_IMR_EOAV                 (1 << 3)
+#define ZR060_IMR_EOI                  (1 << 2)
+#define ZR060_IMR_End                  (1 << 1)
+#define ZR060_IMR_DataErr              (1 << 0)
+
+/* ZR36060 Interrupt Status register */
+
+#define ZR060_ISR_ProCnt               (3 << 6)
+#define ZR060_ISR_EOAV                 (1 << 3)
+#define ZR060_ISR_EOI                  (1 << 2)
+#define ZR060_ISR_End                  (1 << 1)
+#define ZR060_ISR_DataErr              (1 << 0)
+
+/* ZR36060 Video Control register */
+
+#define ZR060_VCR_Video8               (1 << 7)
+#define ZR060_VCR_Range                        (1 << 6)
+#define ZR060_VCR_FIDet                        (1 << 3)
+#define ZR060_VCR_FIVedge              (1 << 2)
+#define ZR060_VCR_FIExt                        (1 << 1)
+#define ZR060_VCR_SyncMstr             (1 << 0)
+
+/* ZR36060 Video Polarity register */
+
+#define ZR060_VPR_VCLKPol              (1 << 7)
+#define ZR060_VPR_PValPol              (1 << 6)
+#define ZR060_VPR_PoePol               (1 << 5)
+#define ZR060_VPR_SImgPol              (1 << 4)
+#define ZR060_VPR_BLPol                        (1 << 3)
+#define ZR060_VPR_FIPol                        (1 << 2)
+#define ZR060_VPR_HSPol                        (1 << 1)
+#define ZR060_VPR_VSPol                        (1 << 0)
+
+/* ZR36060 Scaling register */
+
+#define ZR060_SR_VScale                        (1 << 2)
+#define ZR060_SR_HScale2               (1 << 0)
+#define ZR060_SR_HScale4               (2 << 0)
+
+#endif                         /*fndef ZR36060_H */
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
deleted file mode 100644 (file)
index 3282be7..0000000
+++ /dev/null
@@ -1,1670 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-
-#include <linux/proc_fs.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-#include <linux/kmod.h>
-#include <linux/wait.h>
-
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_card.h"
-#include "zoran_device.h"
-#include "zoran_procfs.h"
-
-extern const struct zoran_format zoran_formats[];
-
-static int card[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card, "The type of card");
-
-static int encoder[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(encoder, int, NULL, 0444);
-MODULE_PARM_DESC(encoder, "i2c TV encoder");
-
-static int decoder[BUZ_MAX] = { -1, -1, -1, -1 };
-module_param_array(decoder, int, NULL, 0444);
-MODULE_PARM_DESC(decoder, "i2c TV decoder");
-
-/*
-   The video mem address of the video card.
-   The driver has a little database for some videocards
-   to determine it from there. If your video card is not in there
-   you have either to give it to the driver as a parameter
-   or set in in a VIDIOCSFBUF ioctl
- */
-
-static unsigned long vidmem;   /* default = 0 - Video memory base address */
-module_param(vidmem, ulong, 0444);
-MODULE_PARM_DESC(vidmem, "Default video memory base address");
-
-/*
-   Default input and video norm at startup of the driver.
-*/
-
-static unsigned int default_input;     /* default 0 = Composite, 1 = S-Video */
-module_param(default_input, uint, 0444);
-MODULE_PARM_DESC(default_input,
-                "Default input (0=Composite, 1=S-Video, 2=Internal)");
-
-static int default_mux = 1;    /* 6 Eyes input selection */
-module_param(default_mux, int, 0644);
-MODULE_PARM_DESC(default_mux,
-                "Default 6 Eyes mux setting (Input selection)");
-
-static int default_norm;       /* default 0 = PAL, 1 = NTSC 2 = SECAM */
-module_param(default_norm, int, 0444);
-MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
-
-/* /dev/videoN, -1 for autodetect */
-static int video_nr[BUZ_MAX] = {-1, -1, -1, -1};
-module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
-
-/*
-   Number and size of grab buffers for Video 4 Linux
-   The vast majority of applications should not need more than 2,
-   the very popular BTTV driver actually does ONLY have 2.
-   Time sensitive applications might need more, the maximum
-   is VIDEO_MAX_FRAME (defined in <linux/videodev.h>).
-
-   The size is set so that the maximum possible request
-   can be satisfied. Decrease  it, if bigphys_area alloc'd
-   memory is low. If you don't have the bigphys_area patch,
-   set it to 128 KB. Will you allow only to grab small
-   images with V4L, but that's better than nothing.
-
-   v4l_bufsize has to be given in KB !
-
-*/
-
-int v4l_nbufs = 2;
-int v4l_bufsize = 128;         /* Everybody should be able to work with this setting */
-module_param(v4l_nbufs, int, 0644);
-MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
-module_param(v4l_bufsize, int, 0644);
-MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
-
-int jpg_nbufs = 32;
-int jpg_bufsize = 512;         /* max size for 100% quality full-PAL frame */
-module_param(jpg_nbufs, int, 0644);
-MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
-module_param(jpg_bufsize, int, 0644);
-MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
-
-int pass_through = 0;          /* 1=Pass through TV signal when device is not used */
-                               /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
-module_param(pass_through, int, 0644);
-MODULE_PARM_DESC(pass_through,
-                "Pass TV signal through to TV-out when idling");
-
-int zr36067_debug = 1;
-module_param_named(debug, zr36067_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-5)");
-
-MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
-MODULE_AUTHOR("Serguei Miridonov");
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id zr36067_pci_tbl[] = {
-       {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0}
-};
-MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
-
-int zoran_num;                 /* number of Buzs in use */
-struct zoran *zoran[BUZ_MAX];
-
-/* videocodec bus functions ZR36060 */
-static u32
-zr36060_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 0, 1, reg >> 8)
-           || post_office_write(zr, 0, 2, reg & 0xff)) {
-               return -1;
-       }
-
-       data = post_office_read(zr, 0, 3) & 0xff;
-       return data;
-}
-
-static void
-zr36060_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 0, 1, reg >> 8)
-           || post_office_write(zr, 0, 2, reg & 0xff)) {
-               return;
-       }
-
-       post_office_write(zr, 0, 3, val & 0xff);
-}
-
-/* videocodec bus functions ZR36050 */
-static u32
-zr36050_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
-               return -1;
-       }
-
-       data = post_office_read(zr, 0, reg & 0x03) & 0xff;      // reg. LOWBYTES + read
-       return data;
-}
-
-static void
-zr36050_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
-               return;
-       }
-
-       post_office_write(zr, 0, reg & 0x03, val & 0xff);       // reg. LOWBYTES + wr. data
-}
-
-/* videocodec bus functions ZR36016 */
-static u32
-zr36016_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)) {
-               return -1;
-       }
-
-       data = post_office_read(zr, 2, reg & 0x03) & 0xff;      // read
-       return data;
-}
-
-/* hack for in zoran_device.c */
-void
-zr36016_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)) {
-               return;
-       }
-
-       post_office_write(zr, 2, reg & 0x03, val & 0x0ff);      // wr. data
-}
-
-/*
- * Board specific information
- */
-
-static void
-dc10_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: dc10_init()\n", ZR_DEVNAME(zr));
-
-       /* Pixel clock selection */
-       GPIO(zr, 4, 0);
-       GPIO(zr, 5, 1);
-       /* Enable the video bus sync signals */
-       GPIO(zr, 7, 0);
-}
-
-static void
-dc10plus_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: dc10plus_init()\n", ZR_DEVNAME(zr));
-}
-
-static void
-buz_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: buz_init()\n", ZR_DEVNAME(zr));
-
-       /* some stuff from Iomega */
-       pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
-       pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020);
-       pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000);
-}
-
-static void
-lml33_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: lml33_init()\n", ZR_DEVNAME(zr));
-
-       GPIO(zr, 2, 1);         // Set Composite input/output
-}
-
-static void
-avs6eyes_init (struct zoran *zr)
-{
-       // AverMedia 6-Eyes original driver by Christer Weinigel
-
-       // Lifted straight from Christer's old driver and
-       // modified slightly by Martin Samuelsson.
-
-       int mux = default_mux; /* 1 = BT866, 7 = VID1 */
-
-       GPIO(zr, 4, 1); /* Bt866 SLEEP on */
-       udelay(2);
-
-       GPIO(zr, 0, 1); /* ZR36060 /RESET on */
-       GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
-       GPIO(zr, 2, mux & 1);   /* MUX S0 */
-       GPIO(zr, 3, 0); /* /FRAME on */
-       GPIO(zr, 4, 0); /* Bt866 SLEEP off */
-       GPIO(zr, 5, mux & 2);   /* MUX S1 */
-       GPIO(zr, 6, 0); /* ? */
-       GPIO(zr, 7, mux & 4);   /* MUX S2 */
-
-}
-
-static char *
-i2cid_to_modulename (u16 i2c_id)
-{
-       char *name = NULL;
-
-       switch (i2c_id) {
-       case I2C_DRIVERID_SAA7110:
-               name = "saa7110";
-               break;
-       case I2C_DRIVERID_SAA7111A:
-               name = "saa7111";
-               break;
-       case I2C_DRIVERID_SAA7114:
-               name = "saa7114";
-               break;
-       case I2C_DRIVERID_SAA7185B:
-               name = "saa7185";
-               break;
-       case I2C_DRIVERID_ADV7170:
-               name = "adv7170";
-               break;
-       case I2C_DRIVERID_ADV7175:
-               name = "adv7175";
-               break;
-       case I2C_DRIVERID_BT819:
-               name = "bt819";
-               break;
-       case I2C_DRIVERID_BT856:
-               name = "bt856";
-               break;
-       case I2C_DRIVERID_BT866:
-               name = "bt866";
-               break;
-       case I2C_DRIVERID_VPX3220:
-               name = "vpx3220";
-               break;
-       case I2C_DRIVERID_KS0127:
-               name = "ks0127";
-               break;
-       }
-
-       return name;
-}
-
-static char *
-codecid_to_modulename (u16 codecid)
-{
-       char *name = NULL;
-
-       switch (codecid) {
-       case CODEC_TYPE_ZR36060:
-               name = "zr36060";
-               break;
-       case CODEC_TYPE_ZR36050:
-               name = "zr36050";
-               break;
-       case CODEC_TYPE_ZR36016:
-               name = "zr36016";
-               break;
-       }
-
-       return name;
-}
-
-// struct tvnorm {
-//      u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
-// };
-
-static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
-static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
-static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
-
-static struct tvnorm f50ccir601_lml33 = { 864, 720, 75+34, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_lml33 = { 858, 720, 57+34, 788, 525, 480, 16 };
-
-/* The DC10 (57/16/50) uses VActive as HSync, so HStart must be 0 */
-static struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 };
-static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
-
-/* FIXME: I cannot swap U and V in saa7114, so i do one
- * pixel left shift in zoran (75 -> 74)
- * (Maxim Yevtyushkin <max@linuxmedialabs.com>) */
-static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
-
-/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
- * copy Maxim's left shift hack for the 6 Eyes.
- *
- * Christer's driver used the unshifted norms, though...
- * /Sam  */
-static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
-
-static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
-       {
-               .type = DC10_old,
-               .name = "DC10(old)",
-               .i2c_decoder = I2C_DRIVERID_VPX3220,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = 3,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = DC10_new,
-               .name = "DC10(new)",
-               .i2c_decoder = I2C_DRIVERID_SAA7110,
-               .i2c_encoder = I2C_DRIVERID_ADV7175,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 3,
-               .input = {
-                               { 0, "Composite" },
-                               { 7, "S-Video" },
-                               { 5, "Internal/comp" }
-                       },
-               .norms = 3,
-               .tvn = {
-                               &f50sqpixel,
-                               &f60sqpixel,
-                               &f50sqpixel},
-               .jpeg_int = ZR36057_ISR_GIRQ0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { -1, 1},
-               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10plus_init,
-       }, {
-               .type = DC10plus,
-               .name = "DC10plus",
-               .vendor_id = PCI_VENDOR_ID_MIRO,
-               .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS,
-               .i2c_decoder = I2C_DRIVERID_SAA7110,
-               .i2c_encoder = I2C_DRIVERID_ADV7175,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 3,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" },
-                       { 5, "Internal/comp" }
-               },
-               .norms = 3,
-               .tvn = {
-                       &f50sqpixel,
-                       &f60sqpixel,
-                       &f50sqpixel
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { -1, 1 },
-               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10plus_init,
-       }, {
-               .type = DC30,
-               .name = "DC30",
-               .i2c_decoder = I2C_DRIVERID_VPX3220,
-               .i2c_encoder = I2C_DRIVERID_ADV7175,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = 3,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = DC30plus,
-               .name = "DC30plus",
-               .vendor_id = PCI_VENDOR_ID_MIRO,
-               .device_id = PCI_DEVICE_ID_MIRO_DC30PLUS,
-               .i2c_decoder = I2C_DRIVERID_VPX3220,
-               .i2c_encoder = I2C_DRIVERID_ADV7175,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = 3,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = LML33,
-               .name = "LML33",
-               .i2c_decoder = I2C_DRIVERID_BT819,
-               .i2c_encoder = I2C_DRIVERID_BT856,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = 2,
-               .tvn = {
-                       &f50ccir601_lml33,
-                       &f60ccir601_lml33,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &lml33_init,
-       }, {
-               .type = LML33R10,
-               .name = "LML33R10",
-               .vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH,
-               .device_id = PCI_DEVICE_ID_LML_33R10,
-               .i2c_decoder = I2C_DRIVERID_SAA7114,
-               .i2c_encoder = I2C_DRIVERID_ADV7170,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = 2,
-               .tvn = {
-                       &f50ccir601_lm33r10,
-                       &f60ccir601_lm33r10,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &lml33_init,
-       }, {
-               .type = BUZ,
-               .name = "Buz",
-               .vendor_id = PCI_VENDOR_ID_IOMEGA,
-               .device_id = PCI_DEVICE_ID_IOMEGA_BUZ,
-               .i2c_decoder = I2C_DRIVERID_SAA7111A,
-               .i2c_encoder = I2C_DRIVERID_SAA7185B,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 3, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = 3,
-               .tvn = {
-                       &f50ccir601,
-                       &f60ccir601,
-                       &f50ccir601
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &buz_init,
-       }, {
-               .type = AVS6EYES,
-               .name = "6-Eyes",
-               /* AverMedia chose not to brand the 6-Eyes. Thus it
-                  can't be autodetected, and requires card=x. */
-               .vendor_id = -1,
-               .device_id = -1,
-               .i2c_decoder = I2C_DRIVERID_KS0127,
-               .i2c_encoder = I2C_DRIVERID_BT866,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 10,
-               .input = {
-                       { 0, "Composite 1" },
-                       { 1, "Composite 2" },
-                       { 2, "Composite 3" },
-                       { 4, "Composite 4" },
-                       { 5, "Composite 5" },
-                       { 6, "Composite 6" },
-                       { 8, "S-Video 1" },
-                       { 9, "S-Video 2" },
-                       {10, "S-Video 3" },
-                       {15, "YCbCr" }
-               },
-               .norms = 2,
-               .tvn = {
-                       &f50ccir601_avs6eyes,
-                       &f60ccir601_avs6eyes,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
-               .gpcs = { 3, 1 },                       // Validity unknown /Sam
-               .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
-               .gws_not_connected = 1,
-               .input_mux = 1,
-               .init = &avs6eyes_init,
-       }
-
-};
-
-/*
- * I2C functions
- */
-/* software I2C functions */
-static int
-zoran_i2c_getsda (void *data)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       return (btread(ZR36057_I2CBR) >> 1) & 1;
-}
-
-static int
-zoran_i2c_getscl (void *data)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       return btread(ZR36057_I2CBR) & 1;
-}
-
-static void
-zoran_i2c_setsda (void *data,
-                 int   state)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       if (state)
-               zr->i2cbr |= 2;
-       else
-               zr->i2cbr &= ~2;
-       btwrite(zr->i2cbr, ZR36057_I2CBR);
-}
-
-static void
-zoran_i2c_setscl (void *data,
-                 int   state)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       if (state)
-               zr->i2cbr |= 1;
-       else
-               zr->i2cbr &= ~1;
-       btwrite(zr->i2cbr, ZR36057_I2CBR);
-}
-
-static int
-zoran_i2c_client_register (struct i2c_client *client)
-{
-       struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
-       int res = 0;
-
-       dprintk(2,
-               KERN_DEBUG "%s: i2c_client_register() - driver id = %d\n",
-               ZR_DEVNAME(zr), client->driver->id);
-
-       mutex_lock(&zr->resource_lock);
-
-       if (zr->user > 0) {
-               /* we're already busy, so we keep a reference to
-                * them... Could do a lot of stuff here, but this
-                * is easiest. (Did I ever mention I'm a lazy ass?)
-                */
-               res = -EBUSY;
-               goto clientreg_unlock_and_return;
-       }
-
-       if (client->driver->id == zr->card.i2c_decoder)
-               zr->decoder = client;
-       else if (client->driver->id == zr->card.i2c_encoder)
-               zr->encoder = client;
-       else {
-               res = -ENODEV;
-               goto clientreg_unlock_and_return;
-       }
-
-clientreg_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int
-zoran_i2c_client_unregister (struct i2c_client *client)
-{
-       struct zoran *zr = (struct zoran *) i2c_get_adapdata(client->adapter);
-       int res = 0;
-
-       dprintk(2, KERN_DEBUG "%s: i2c_client_unregister()\n", ZR_DEVNAME(zr));
-
-       mutex_lock(&zr->resource_lock);
-
-       if (zr->user > 0) {
-               res = -EBUSY;
-               goto clientunreg_unlock_and_return;
-       }
-
-       /* try to locate it */
-       if (client == zr->encoder) {
-               zr->encoder = NULL;
-       } else if (client == zr->decoder) {
-               zr->decoder = NULL;
-               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%d]", zr->id);
-       }
-clientunreg_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
-       .setsda = zoran_i2c_setsda,
-       .setscl = zoran_i2c_setscl,
-       .getsda = zoran_i2c_getsda,
-       .getscl = zoran_i2c_getscl,
-       .udelay = 10,
-       .timeout = 100,
-};
-
-static int
-zoran_register_i2c (struct zoran *zr)
-{
-       memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
-              sizeof(struct i2c_algo_bit_data));
-       zr->i2c_algo.data = zr;
-       zr->i2c_adapter.id = I2C_HW_B_ZR36067;
-       zr->i2c_adapter.client_register = zoran_i2c_client_register;
-       zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
-       strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
-               sizeof(zr->i2c_adapter.name));
-       i2c_set_adapdata(&zr->i2c_adapter, zr);
-       zr->i2c_adapter.algo_data = &zr->i2c_algo;
-       zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
-       return i2c_bit_add_bus(&zr->i2c_adapter);
-}
-
-static void
-zoran_unregister_i2c (struct zoran *zr)
-{
-       i2c_del_adapter(&zr->i2c_adapter);
-}
-
-/* Check a zoran_params struct for correctness, insert default params */
-
-int
-zoran_check_jpg_settings (struct zoran              *zr,
-                         struct zoran_jpg_settings *settings)
-{
-       int err = 0, err0 = 0;
-
-       dprintk(4,
-               KERN_DEBUG
-               "%s: check_jpg_settings() - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
-               ZR_DEVNAME(zr), settings->decimation, settings->HorDcm,
-               settings->VerDcm, settings->TmpDcm);
-       dprintk(4,
-               KERN_DEBUG
-               "%s: check_jpg_settings() - x: %d, y: %d, w: %d, y: %d\n",
-               ZR_DEVNAME(zr), settings->img_x, settings->img_y,
-               settings->img_width, settings->img_height);
-       /* Check decimation, set default values for decimation = 1, 2, 4 */
-       switch (settings->decimation) {
-       case 1:
-
-               settings->HorDcm = 1;
-               settings->VerDcm = 1;
-               settings->TmpDcm = 1;
-               settings->field_per_buff = 2;
-               settings->img_x = 0;
-               settings->img_y = 0;
-               settings->img_width = BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 2:
-
-               settings->HorDcm = 2;
-               settings->VerDcm = 1;
-               settings->TmpDcm = 2;
-               settings->field_per_buff = 1;
-               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings->img_y = 0;
-               settings->img_width =
-                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 4:
-
-               if (zr->card.type == DC10_new) {
-                       dprintk(1,
-                               KERN_DEBUG
-                               "%s: check_jpg_settings() - HDec by 4 is not supported on the DC10\n",
-                               ZR_DEVNAME(zr));
-                       err0++;
-                       break;
-               }
-
-               settings->HorDcm = 4;
-               settings->VerDcm = 2;
-               settings->TmpDcm = 2;
-               settings->field_per_buff = 1;
-               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings->img_y = 0;
-               settings->img_width =
-                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 0:
-
-               /* We have to check the data the user has set */
-
-               if (settings->HorDcm != 1 && settings->HorDcm != 2 &&
-                   (zr->card.type == DC10_new || settings->HorDcm != 4))
-                       err0++;
-               if (settings->VerDcm != 1 && settings->VerDcm != 2)
-                       err0++;
-               if (settings->TmpDcm != 1 && settings->TmpDcm != 2)
-                       err0++;
-               if (settings->field_per_buff != 1 &&
-                   settings->field_per_buff != 2)
-                       err0++;
-               if (settings->img_x < 0)
-                       err0++;
-               if (settings->img_y < 0)
-                       err0++;
-               if (settings->img_width < 0)
-                       err0++;
-               if (settings->img_height < 0)
-                       err0++;
-               if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH)
-                       err0++;
-               if (settings->img_y + settings->img_height >
-                   BUZ_MAX_HEIGHT / 2)
-                       err0++;
-               if (settings->HorDcm && settings->VerDcm) {
-                       if (settings->img_width %
-                           (16 * settings->HorDcm) != 0)
-                               err0++;
-                       if (settings->img_height %
-                           (8 * settings->VerDcm) != 0)
-                               err0++;
-               }
-
-               if (err0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: check_jpg_settings() - error in params for decimation = 0\n",
-                               ZR_DEVNAME(zr));
-                       err++;
-               }
-               break;
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: check_jpg_settings() - decimation = %d, must be 0, 1, 2 or 4\n",
-                       ZR_DEVNAME(zr), settings->decimation);
-               err++;
-               break;
-       }
-
-       if (settings->jpg_comp.quality > 100)
-               settings->jpg_comp.quality = 100;
-       if (settings->jpg_comp.quality < 5)
-               settings->jpg_comp.quality = 5;
-       if (settings->jpg_comp.APPn < 0)
-               settings->jpg_comp.APPn = 0;
-       if (settings->jpg_comp.APPn > 15)
-               settings->jpg_comp.APPn = 15;
-       if (settings->jpg_comp.APP_len < 0)
-               settings->jpg_comp.APP_len = 0;
-       if (settings->jpg_comp.APP_len > 60)
-               settings->jpg_comp.APP_len = 60;
-       if (settings->jpg_comp.COM_len < 0)
-               settings->jpg_comp.COM_len = 0;
-       if (settings->jpg_comp.COM_len > 60)
-               settings->jpg_comp.COM_len = 60;
-       if (err)
-               return -EINVAL;
-       return 0;
-}
-
-void
-zoran_open_init_params (struct zoran *zr)
-{
-       int i;
-
-       /* User must explicitly set a window */
-       zr->overlay_settings.is_set = 0;
-       zr->overlay_mask = NULL;
-       zr->overlay_active = ZORAN_FREE;
-
-       zr->v4l_memgrab_active = 0;
-       zr->v4l_overlay_active = 0;
-       zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-       zr->v4l_grab_seq = 0;
-       zr->v4l_settings.width = 192;
-       zr->v4l_settings.height = 144;
-       zr->v4l_settings.format = &zoran_formats[7];    /* YUY2 - YUV-4:2:2 packed */
-       zr->v4l_settings.bytesperline =
-           zr->v4l_settings.width *
-           ((zr->v4l_settings.format->depth + 7) / 8);
-
-       /* DMA ring stuff for V4L */
-       zr->v4l_pend_tail = 0;
-       zr->v4l_pend_head = 0;
-       zr->v4l_sync_tail = 0;
-       zr->v4l_buffers.active = ZORAN_FREE;
-       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-               zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       zr->v4l_buffers.allocated = 0;
-
-       for (i = 0; i < BUZ_MAX_FRAME; i++) {
-               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       zr->jpg_buffers.active = ZORAN_FREE;
-       zr->jpg_buffers.allocated = 0;
-       /* Set necessary params and call zoran_check_jpg_settings to set the defaults */
-       zr->jpg_settings.decimation = 1;
-       zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */
-       if (zr->card.type != BUZ)
-               zr->jpg_settings.odd_even = 1;
-       else
-               zr->jpg_settings.odd_even = 0;
-       zr->jpg_settings.jpg_comp.APPn = 0;
-       zr->jpg_settings.jpg_comp.APP_len = 0;  /* No APPn marker */
-       memset(zr->jpg_settings.jpg_comp.APP_data, 0,
-              sizeof(zr->jpg_settings.jpg_comp.APP_data));
-       zr->jpg_settings.jpg_comp.COM_len = 0;  /* No COM marker */
-       memset(zr->jpg_settings.jpg_comp.COM_data, 0,
-              sizeof(zr->jpg_settings.jpg_comp.COM_data));
-       zr->jpg_settings.jpg_comp.jpeg_markers =
-           JPEG_MARKER_DHT | JPEG_MARKER_DQT;
-       i = zoran_check_jpg_settings(zr, &zr->jpg_settings);
-       if (i)
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_open_init_params() internal error\n",
-                       ZR_DEVNAME(zr));
-
-       clear_interrupt_counters(zr);
-       zr->testing = 0;
-}
-
-static void __devinit
-test_interrupts (struct zoran *zr)
-{
-       DEFINE_WAIT(wait);
-       int timeout, icr;
-
-       clear_interrupt_counters(zr);
-
-       zr->testing = 1;
-       icr = btread(ZR36057_ICR);
-       btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
-       prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE);
-       timeout = schedule_timeout(HZ);
-       finish_wait(&zr->test_q, &wait);
-       btwrite(0, ZR36057_ICR);
-       btwrite(0x78000000, ZR36057_ISR);
-       zr->testing = 0;
-       dprintk(5, KERN_INFO "%s: Testing interrupts...\n", ZR_DEVNAME(zr));
-       if (timeout) {
-               dprintk(1, ": time spent: %d\n", 1 * HZ - timeout);
-       }
-       if (zr36067_debug > 1)
-               print_interrupts(zr);
-       btwrite(icr, ZR36057_ICR);
-}
-
-static int __devinit
-zr36057_init (struct zoran *zr)
-{
-       int j, err;
-       int two = 2;
-       int zero = 0;
-
-       dprintk(1,
-               KERN_INFO
-               "%s: zr36057_init() - initializing card[%d], zr=%p\n",
-               ZR_DEVNAME(zr), zr->id, zr);
-
-       /* default setup of all parameters which will persist between opens */
-       zr->user = 0;
-
-       init_waitqueue_head(&zr->v4l_capq);
-       init_waitqueue_head(&zr->jpg_capq);
-       init_waitqueue_head(&zr->test_q);
-       zr->jpg_buffers.allocated = 0;
-       zr->v4l_buffers.allocated = 0;
-
-       zr->buffer.base = (void *) vidmem;
-       zr->buffer.width = 0;
-       zr->buffer.height = 0;
-       zr->buffer.depth = 0;
-       zr->buffer.bytesperline = 0;
-
-       /* Avoid nonsense settings from user for default input/norm */
-       if (default_norm < VIDEO_MODE_PAL &&
-           default_norm > VIDEO_MODE_SECAM)
-               default_norm = VIDEO_MODE_PAL;
-       zr->norm = default_norm;
-       if (!(zr->timing = zr->card.tvn[zr->norm])) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n",
-                       ZR_DEVNAME(zr));
-               zr->norm = VIDEO_MODE_PAL;
-               zr->timing = zr->card.tvn[zr->norm];
-       }
-
-       if (default_input > zr->card.inputs-1) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: default_input value %d out of range (0-%d)\n",
-                       ZR_DEVNAME(zr), default_input, zr->card.inputs-1);
-               default_input = 0;
-       }
-       zr->input = default_input;
-
-       /* Should the following be reset at every open ? */
-       zr->hue = 32768;
-       zr->contrast = 32768;
-       zr->saturation = 32768;
-       zr->brightness = 32768;
-
-       /* default setup (will be repeated at every open) */
-       zoran_open_init_params(zr);
-
-       /* allocate memory *before* doing anything to the hardware
-        * in case allocation fails */
-       zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
-       zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
-       if (!zr->stat_com || !zr->video_dev) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
-                       ZR_DEVNAME(zr));
-               err = -ENOMEM;
-               goto exit_free;
-       }
-       for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-               zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
-       }
-
-       /*
-        *   Now add the template and register the device unit.
-        */
-       memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
-       strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
-       err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
-       if (err < 0)
-               goto exit_unregister;
-
-       zoran_init_hardware(zr);
-       if (zr36067_debug > 2)
-               detect_guest_activity(zr);
-       test_interrupts(zr);
-       if (!pass_through) {
-               decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
-               encoder_command(zr, ENCODER_SET_INPUT, &two);
-       }
-
-       zr->zoran_proc = NULL;
-       zr->initialized = 1;
-       return 0;
-
-exit_unregister:
-       zoran_unregister_i2c(zr);
-exit_free:
-       kfree(zr->stat_com);
-       kfree(zr->video_dev);
-       return err;
-}
-
-static void
-zoran_release (struct zoran *zr)
-{
-       if (!zr->initialized)
-               goto exit_free;
-       /* unregister videocodec bus */
-       if (zr->codec) {
-               struct videocodec_master *master = zr->codec->master_data;
-
-               videocodec_detach(zr->codec);
-               kfree(master);
-       }
-       if (zr->vfe) {
-               struct videocodec_master *master = zr->vfe->master_data;
-
-               videocodec_detach(zr->vfe);
-               kfree(master);
-       }
-
-       /* unregister i2c bus */
-       zoran_unregister_i2c(zr);
-       /* disable PCI bus-mastering */
-       zoran_set_pci_master(zr, 0);
-       /* put chip into reset */
-       btwrite(0, ZR36057_SPGPPCR);
-       free_irq(zr->pci_dev->irq, zr);
-       /* unmap and free memory */
-       kfree(zr->stat_com);
-       zoran_proc_cleanup(zr);
-       iounmap(zr->zr36057_mem);
-       pci_disable_device(zr->pci_dev);
-       video_unregister_device(zr->video_dev);
-exit_free:
-       kfree(zr);
-}
-
-void
-zoran_vdev_release (struct video_device *vdev)
-{
-       kfree(vdev);
-}
-
-static struct videocodec_master * __devinit
-zoran_setup_videocodec (struct zoran *zr,
-                       int           type)
-{
-       struct videocodec_master *m = NULL;
-
-       m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL);
-       if (!m) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_setup_videocodec() - no memory\n",
-                       ZR_DEVNAME(zr));
-               return m;
-       }
-
-       /* magic and type are unused for master struct. Makes sense only at
-          codec structs.
-          In the past, .type were initialized to the old V4L1 .hardware
-          value, as VID_HARDWARE_ZR36067
-        */
-       m->magic = 0L;
-       m->type = 0;
-
-       m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
-       strncpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
-       m->data = zr;
-
-       switch (type)
-       {
-       case CODEC_TYPE_ZR36060:
-               m->readreg = zr36060_read;
-               m->writereg = zr36060_write;
-               m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE;
-               break;
-       case CODEC_TYPE_ZR36050:
-               m->readreg = zr36050_read;
-               m->writereg = zr36050_write;
-               m->flags |= CODEC_FLAG_JPEG;
-               break;
-       case CODEC_TYPE_ZR36016:
-               m->readreg = zr36016_read;
-               m->writereg = zr36016_write;
-               m->flags |= CODEC_FLAG_VFE;
-               break;
-       }
-
-       return m;
-}
-
-/*
- *   Scan for a Buz card (actually for the PCI controller ZR36057),
- *   request the irq and map the io memory
- */
-static int __devinit
-find_zr36057 (void)
-{
-       unsigned char latency, need_latency;
-       struct zoran *zr;
-       struct pci_dev *dev = NULL;
-       int result;
-       struct videocodec_master *master_vfe = NULL;
-       struct videocodec_master *master_codec = NULL;
-       int card_num;
-       char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name;
-
-       zoran_num = 0;
-       while (zoran_num < BUZ_MAX &&
-              (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) {
-               card_num = card[zoran_num];
-               zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
-               if (!zr) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: find_zr36057() - kzalloc failed\n",
-                               ZORAN_NAME);
-                       continue;
-               }
-               zr->pci_dev = dev;
-               //zr->zr36057_mem = NULL;
-               zr->id = zoran_num;
-               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
-               spin_lock_init(&zr->spinlock);
-               mutex_init(&zr->resource_lock);
-               if (pci_enable_device(dev))
-                       goto zr_free_mem;
-               zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
-               pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
-                                    &zr->revision);
-               if (zr->revision < 2) {
-                       dprintk(1,
-                               KERN_INFO
-                               "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n",
-                               ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
-                               zr->zr36057_adr);
-
-                       if (card_num == -1) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - no card specified, please use the card=X insmod option\n",
-                                       ZR_DEVNAME(zr));
-                               goto zr_free_mem;
-                       }
-               } else {
-                       int i;
-                       unsigned short ss_vendor, ss_device;
-
-                       ss_vendor = zr->pci_dev->subsystem_vendor;
-                       ss_device = zr->pci_dev->subsystem_device;
-                       dprintk(1,
-                               KERN_INFO
-                               "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n",
-                               ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
-                               zr->zr36057_adr);
-                       dprintk(1,
-                               KERN_INFO
-                               "%s: subsystem vendor=0x%04x id=0x%04x\n",
-                               ZR_DEVNAME(zr), ss_vendor, ss_device);
-                       if (card_num == -1) {
-                               dprintk(3,
-                                       KERN_DEBUG
-                                       "%s: find_zr36057() - trying to autodetect card type\n",
-                                       ZR_DEVNAME(zr));
-                               for (i=0;i<NUM_CARDS;i++) {
-                                       if (ss_vendor == zoran_cards[i].vendor_id &&
-                                           ss_device == zoran_cards[i].device_id) {
-                                               dprintk(3,
-                                                       KERN_DEBUG
-                                                       "%s: find_zr36057() - card %s detected\n",
-                                                       ZR_DEVNAME(zr),
-                                                       zoran_cards[i].name);
-                                               card_num = i;
-                                               break;
-                                       }
-                               }
-                               if (i == NUM_CARDS) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: find_zr36057() - unknown card\n",
-                                               ZR_DEVNAME(zr));
-                                       goto zr_free_mem;
-                               }
-                       }
-               }
-
-               if (card_num < 0 || card_num >= NUM_CARDS) {
-                       dprintk(2,
-                               KERN_ERR
-                               "%s: find_zr36057() - invalid cardnum %d\n",
-                               ZR_DEVNAME(zr), card_num);
-                       goto zr_free_mem;
-               }
-
-               /* even though we make this a non pointer and thus
-                * theoretically allow for making changes to this struct
-                * on a per-individual card basis at runtime, this is
-                * strongly discouraged. This structure is intended to
-                * keep general card information, no settings or anything */
-               zr->card = zoran_cards[card_num];
-               snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
-                        "%s[%u]", zr->card.name, zr->id);
-
-               zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000);
-               if (!zr->zr36057_mem) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: find_zr36057() - ioremap failed\n",
-                               ZR_DEVNAME(zr));
-                       goto zr_free_mem;
-               }
-
-               result = request_irq(zr->pci_dev->irq,
-                                    zoran_irq,
-                                    IRQF_SHARED | IRQF_DISABLED,
-                                    ZR_DEVNAME(zr),
-                                    (void *) zr);
-               if (result < 0) {
-                       if (result == -EINVAL) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - bad irq number or handler\n",
-                                       ZR_DEVNAME(zr));
-                       } else if (result == -EBUSY) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
-                                       ZR_DEVNAME(zr), zr->pci_dev->irq);
-                       } else {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - can't assign irq, error code %d\n",
-                                       ZR_DEVNAME(zr), result);
-                       }
-                       goto zr_unmap;
-               }
-
-               /* set PCI latency timer */
-               pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
-                                    &latency);
-               need_latency = zr->revision > 1 ? 32 : 48;
-               if (latency != need_latency) {
-                       dprintk(2,
-                               KERN_INFO
-                               "%s: Changing PCI latency from %d to %d.\n",
-                               ZR_DEVNAME(zr), latency, need_latency);
-                       pci_write_config_byte(zr->pci_dev,
-                                             PCI_LATENCY_TIMER,
-                                             need_latency);
-               }
-
-               zr36057_restart(zr);
-               /* i2c */
-               dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
-                       ZR_DEVNAME(zr));
-
-               /* i2c decoder */
-               if (decoder[zr->id] != -1) {
-                       i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
-                       zr->card.i2c_decoder = decoder[zr->id];
-               } else if (zr->card.i2c_decoder != 0) {
-                       i2c_dec_name =
-                               i2cid_to_modulename(zr->card.i2c_decoder);
-               } else {
-                       i2c_dec_name = NULL;
-               }
-
-               if (i2c_dec_name) {
-                       if ((result = request_module(i2c_dec_name)) < 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load module %s: %d\n",
-                                       ZR_DEVNAME(zr), i2c_dec_name, result);
-                       }
-               }
-
-               /* i2c encoder */
-               if (encoder[zr->id] != -1) {
-                       i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
-                       zr->card.i2c_encoder = encoder[zr->id];
-               } else if (zr->card.i2c_encoder != 0) {
-                       i2c_enc_name =
-                               i2cid_to_modulename(zr->card.i2c_encoder);
-               } else {
-                       i2c_enc_name = NULL;
-               }
-
-               if (i2c_enc_name) {
-                       if ((result = request_module(i2c_enc_name)) < 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load module %s: %d\n",
-                                       ZR_DEVNAME(zr), i2c_enc_name, result);
-                       }
-               }
-
-               if (zoran_register_i2c(zr) < 0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: find_zr36057() - can't initialize i2c bus\n",
-                               ZR_DEVNAME(zr));
-                       goto zr_free_irq;
-               }
-
-               dprintk(2,
-                       KERN_INFO "%s: Initializing videocodec bus...\n",
-                       ZR_DEVNAME(zr));
-
-               if (zr->card.video_codec != 0 &&
-                   (codec_name =
-                    codecid_to_modulename(zr->card.video_codec)) != NULL) {
-                       if ((result = request_module(codec_name)) < 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load modules %s: %d\n",
-                                       ZR_DEVNAME(zr), codec_name, result);
-                       }
-               }
-               if (zr->card.video_vfe != 0 &&
-                   (vfe_name =
-                    codecid_to_modulename(zr->card.video_vfe)) != NULL) {
-                       if ((result = request_module(vfe_name)) < 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load modules %s: %d\n",
-                                       ZR_DEVNAME(zr), vfe_name, result);
-                       }
-               }
-
-               /* reset JPEG codec */
-               jpeg_codec_sleep(zr, 1);
-               jpeg_codec_reset(zr);
-               /* video bus enabled */
-               /* display codec revision */
-               if (zr->card.video_codec != 0) {
-                       master_codec = zoran_setup_videocodec(zr,
-                                                             zr->card.video_codec);
-                       if (!master_codec)
-                               goto zr_unreg_i2c;
-                       zr->codec = videocodec_attach(master_codec);
-                       if (!zr->codec) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - no codec found\n",
-                                       ZR_DEVNAME(zr));
-                               goto zr_free_codec;
-                       }
-                       if (zr->codec->type != zr->card.video_codec) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - wrong codec\n",
-                                       ZR_DEVNAME(zr));
-                               goto zr_detach_codec;
-                       }
-               }
-               if (zr->card.video_vfe != 0) {
-                       master_vfe = zoran_setup_videocodec(zr,
-                                                           zr->card.video_vfe);
-                       if (!master_vfe)
-                               goto zr_detach_codec;
-                       zr->vfe = videocodec_attach(master_vfe);
-                       if (!zr->vfe) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() - no VFE found\n",
-                                       ZR_DEVNAME(zr));
-                               goto zr_free_vfe;
-                       }
-                       if (zr->vfe->type != zr->card.video_vfe) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: find_zr36057() = wrong VFE\n",
-                                       ZR_DEVNAME(zr));
-                               goto zr_detach_vfe;
-                       }
-               }
-               /* Success so keep the pci_dev referenced */
-               pci_dev_get(zr->pci_dev);
-               zoran[zoran_num++] = zr;
-               continue;
-
-               // Init errors
-             zr_detach_vfe:
-               videocodec_detach(zr->vfe);
-             zr_free_vfe:
-               kfree(master_vfe);
-             zr_detach_codec:
-               videocodec_detach(zr->codec);
-             zr_free_codec:
-               kfree(master_codec);
-             zr_unreg_i2c:
-               zoran_unregister_i2c(zr);
-             zr_free_irq:
-               btwrite(0, ZR36057_SPGPPCR);
-               free_irq(zr->pci_dev->irq, zr);
-             zr_unmap:
-               iounmap(zr->zr36057_mem);
-             zr_free_mem:
-               kfree(zr);
-               continue;
-       }
-       if (dev)        /* Clean up ref count on early exit */
-               pci_dev_put(dev);
-
-       if (zoran_num == 0) {
-               dprintk(1, KERN_INFO "No known MJPEG cards found.\n");
-       }
-       return zoran_num;
-}
-
-static int __init
-init_dc10_cards (void)
-{
-       int i;
-
-       memset(zoran, 0, sizeof(zoran));
-       printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
-              MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
-
-       /* Look for cards */
-       if (find_zr36057() < 0) {
-               return -EIO;
-       }
-       if (zoran_num == 0)
-               return -ENODEV;
-       dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME,
-               zoran_num);
-       /* check the parameters we have been given, adjust if necessary */
-       if (v4l_nbufs < 2)
-               v4l_nbufs = 2;
-       if (v4l_nbufs > VIDEO_MAX_FRAME)
-               v4l_nbufs = VIDEO_MAX_FRAME;
-       /* The user specfies the in KB, we want them in byte
-        * (and page aligned) */
-       v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
-       if (v4l_bufsize < 32768)
-               v4l_bufsize = 32768;
-       /* 2 MB is arbitrary but sufficient for the maximum possible images */
-       if (v4l_bufsize > 2048 * 1024)
-               v4l_bufsize = 2048 * 1024;
-       if (jpg_nbufs < 4)
-               jpg_nbufs = 4;
-       if (jpg_nbufs > BUZ_MAX_FRAME)
-               jpg_nbufs = BUZ_MAX_FRAME;
-       jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
-       if (jpg_bufsize < 8192)
-               jpg_bufsize = 8192;
-       if (jpg_bufsize > (512 * 1024))
-               jpg_bufsize = 512 * 1024;
-       /* Use parameter for vidmem or try to find a video card */
-       if (vidmem) {
-               dprintk(1,
-                       KERN_INFO
-                       "%s: Using supplied video memory base address @ 0x%lx\n",
-                       ZORAN_NAME, vidmem);
-       }
-
-       /* random nonsense */
-       dprintk(6, KERN_DEBUG "Jotti is een held!\n");
-
-       /* some mainboards might not do PCI-PCI data transfer well */
-       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: chipset does not support reliable PCI-PCI DMA\n",
-                       ZORAN_NAME);
-       }
-
-       /* take care of Natoma chipset and a revision 1 zr36057 */
-       for (i = 0; i < zoran_num; i++) {
-               struct zoran *zr = zoran[i];
-
-               if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
-                       zr->jpg_buffers.need_contiguous = 1;
-                       dprintk(1,
-                               KERN_INFO
-                               "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
-                               ZR_DEVNAME(zr));
-               }
-
-               if (zr36057_init(zr) < 0) {
-                       for (i = 0; i < zoran_num; i++)
-                               zoran_release(zoran[i]);
-                       return -EIO;
-               }
-               zoran_proc_init(zr);
-       }
-
-       return 0;
-}
-
-static void __exit
-unload_dc10_cards (void)
-{
-       int i;
-
-       for (i = 0; i < zoran_num; i++)
-               zoran_release(zoran[i]);
-}
-
-module_init(init_dc10_cards);
-module_exit(unload_dc10_cards);
diff --git a/drivers/media/video/zoran_card.h b/drivers/media/video/zoran_card.h
deleted file mode 100644 (file)
index e4dc9d2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ZORAN_CARD_H__
-#define __ZORAN_CARD_H__
-
-extern int zr36067_debug;
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (zr36067_debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* Anybody who uses more than four? */
-#define BUZ_MAX 4
-extern int zoran_num;
-extern struct zoran *zoran[BUZ_MAX];
-
-extern struct video_device zoran_template;
-
-extern int zoran_check_jpg_settings(struct zoran *zr,
-                                   struct zoran_jpg_settings *settings);
-extern void zoran_open_init_params(struct zoran *zr);
-extern void zoran_vdev_release(struct video_device *vdev);
-
-void zr36016_write(struct videocodec *codec, u16 reg, u32 val);
-
-#endif                         /* __ZORAN_CARD_H__ */
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
deleted file mode 100644 (file)
index 88d3697..0000000
+++ /dev/null
@@ -1,1749 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles device access (PCI/I2C/codec/...)
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-
-#include <linux/pci.h>
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_device.h"
-#include "zoran_card.h"
-
-#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \
-                  ZR36057_ISR_GIRQ1 | \
-                  ZR36057_ISR_JPEGRepIRQ )
-
-extern const struct zoran_format zoran_formats[];
-
-static int lml33dpath;         /* default = 0
-                                * 1 will use digital path in capture
-                                * mode instead of analog. It can be
-                                * used for picture adjustments using
-                                * tool like xawtv while watching image
-                                * on TV monitor connected to the output.
-                                * However, due to absence of 75 Ohm
-                                * load on Bt819 input, there will be
-                                * some image imperfections */
-
-module_param(lml33dpath, bool, 0644);
-MODULE_PARM_DESC(lml33dpath,
-                "Use digital path capture mode (on LML33 cards)");
-
-static void
-zr36057_init_vfe (struct zoran *zr);
-
-/*
- * General Purpose I/O and Guest bus access
- */
-
-/*
- * This is a bit tricky. When a board lacks a GPIO function, the corresponding
- * GPIO bit number in the card_info structure is set to 0.
- */
-
-void
-GPIO (struct zoran *zr,
-      int           bit,
-      unsigned int  value)
-{
-       u32 reg;
-       u32 mask;
-
-       /* Make sure the bit number is legal
-        * A bit number of -1 (lacking) gives a mask of 0,
-        * making it harmless */
-       mask = (1 << (24 + bit)) & 0xff000000;
-       reg = btread(ZR36057_GPPGCR1) & ~mask;
-       if (value) {
-               reg |= mask;
-       }
-       btwrite(reg, ZR36057_GPPGCR1);
-       udelay(1);
-}
-
-/*
- * Wait til post office is no longer busy
- */
-
-int
-post_office_wait (struct zoran *zr)
-{
-       u32 por;
-
-//      while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {
-       while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) {
-               /* wait for something to happen */
-       }
-       if ((por & ZR36057_POR_POTime) && !zr->card.gws_not_connected) {
-               /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */
-               dprintk(1, KERN_INFO "%s: pop timeout %08x\n", ZR_DEVNAME(zr),
-                       por);
-               return -1;
-       }
-
-       return 0;
-}
-
-int
-post_office_write (struct zoran *zr,
-                  unsigned int  guest,
-                  unsigned int  reg,
-                  unsigned int  value)
-{
-       u32 por;
-
-       por =
-           ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) |
-           ((reg & 7) << 16) | (value & 0xFF);
-       btwrite(por, ZR36057_POR);
-
-       return post_office_wait(zr);
-}
-
-int
-post_office_read (struct zoran *zr,
-                 unsigned int  guest,
-                 unsigned int  reg)
-{
-       u32 por;
-
-       por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);
-       btwrite(por, ZR36057_POR);
-       if (post_office_wait(zr) < 0) {
-               return -1;
-       }
-
-       return btread(ZR36057_POR) & 0xFF;
-}
-
-/*
- * detect guests
- */
-
-static void
-dump_guests (struct zoran *zr)
-{
-       if (zr36067_debug > 2) {
-               int i, guest[8];
-
-               for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
-                       guest[i] = post_office_read(zr, i, 0);
-               }
-
-               printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
-
-               for (i = 1; i < 8; i++) {
-                       printk(" 0x%02x", guest[i]);
-               }
-               printk("\n");
-       }
-}
-
-static inline unsigned long
-get_time (void)
-{
-       struct timeval tv;
-
-       do_gettimeofday(&tv);
-       return (1000000 * tv.tv_sec + tv.tv_usec);
-}
-
-void
-detect_guest_activity (struct zoran *zr)
-{
-       int timeout, i, j, res, guest[8], guest0[8], change[8][3];
-       unsigned long t0, t1;
-
-       dump_guests(zr);
-       printk(KERN_INFO "%s: Detecting guests activity, please wait...\n",
-              ZR_DEVNAME(zr));
-       for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
-               guest0[i] = guest[i] = post_office_read(zr, i, 0);
-       }
-
-       timeout = 0;
-       j = 0;
-       t0 = get_time();
-       while (timeout < 10000) {
-               udelay(10);
-               timeout++;
-               for (i = 1; (i < 8) && (j < 8); i++) {
-                       res = post_office_read(zr, i, 0);
-                       if (res != guest[i]) {
-                               t1 = get_time();
-                               change[j][0] = (t1 - t0);
-                               t0 = t1;
-                               change[j][1] = i;
-                               change[j][2] = res;
-                               j++;
-                               guest[i] = res;
-                       }
-               }
-               if (j >= 8)
-                       break;
-       }
-       printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
-
-       for (i = 1; i < 8; i++) {
-               printk(" 0x%02x", guest0[i]);
-       }
-       printk("\n");
-       if (j == 0) {
-               printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr));
-               return;
-       }
-       for (i = 0; i < j; i++) {
-               printk(KERN_INFO "%s: %6d: %d => 0x%02x\n", ZR_DEVNAME(zr),
-                      change[i][0], change[i][1], change[i][2]);
-       }
-}
-
-/*
- * JPEG Codec access
- */
-
-void
-jpeg_codec_sleep (struct zoran *zr,
-                 int           sleep)
-{
-       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
-       if (!sleep) {
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: jpeg_codec_sleep() - wake GPIO=0x%08x\n",
-                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
-               udelay(500);
-       } else {
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: jpeg_codec_sleep() - sleep GPIO=0x%08x\n",
-                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
-               udelay(2);
-       }
-}
-
-int
-jpeg_codec_reset (struct zoran *zr)
-{
-       /* Take the codec out of sleep */
-       jpeg_codec_sleep(zr, 0);
-
-       if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) {
-               post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0,
-                                 0);
-               udelay(2);
-       } else {
-               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
-               udelay(2);
-               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
-               udelay(2);
-       }
-
-       return 0;
-}
-
-/*
- *   Set the registers for the size we have specified. Don't bother
- *   trying to understand this without the ZR36057 manual in front of
- *   you [AC].
- *
- *   PS: The manual is free for download in .pdf format from
- *   www.zoran.com - nicely done those folks.
- */
-
-static void
-zr36057_adjust_vfe (struct zoran          *zr,
-                   enum zoran_codec_mode  mode)
-{
-       u32 reg;
-
-       switch (mode) {
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               reg = btread(ZR36057_VFEHCR);
-               if ((reg & (1 << 10)) && zr->card.type != LML33R10) {
-                       reg += ((1 << 10) | 1);
-               }
-               btwrite(reg, ZR36057_VFEHCR);
-               break;
-       case BUZ_MODE_MOTION_COMPRESS:
-       case BUZ_MODE_IDLE:
-       default:
-               if (zr->norm == VIDEO_MODE_NTSC ||
-                   (zr->card.type == LML33R10 &&
-                    zr->norm == VIDEO_MODE_PAL))
-                       btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               else
-                       btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               reg = btread(ZR36057_VFEHCR);
-               if (!(reg & (1 << 10)) && zr->card.type != LML33R10) {
-                       reg -= ((1 << 10) | 1);
-               }
-               btwrite(reg, ZR36057_VFEHCR);
-               break;
-       }
-}
-
-/*
- * set geometry
- */
-
-static void
-zr36057_set_vfe (struct zoran              *zr,
-                int                        video_width,
-                int                        video_height,
-                const struct zoran_format *format)
-{
-       struct tvnorm *tvn;
-       unsigned HStart, HEnd, VStart, VEnd;
-       unsigned DispMode;
-       unsigned VidWinWid, VidWinHt;
-       unsigned hcrop1, hcrop2, vcrop1, vcrop2;
-       unsigned Wa, We, Ha, He;
-       unsigned X, Y, HorDcm, VerDcm;
-       u32 reg;
-       unsigned mask_line_size;
-
-       tvn = zr->timing;
-
-       Wa = tvn->Wa;
-       Ha = tvn->Ha;
-
-       dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
-               ZR_DEVNAME(zr), video_width, video_height);
-
-       if (zr->norm != VIDEO_MODE_PAL &&
-           zr->norm != VIDEO_MODE_NTSC &&
-           zr->norm != VIDEO_MODE_SECAM) {
-               dprintk(1,
-                       KERN_ERR "%s: set_vfe() - norm = %d not valid\n",
-                       ZR_DEVNAME(zr), zr->norm);
-               return;
-       }
-       if (video_width < BUZ_MIN_WIDTH ||
-           video_height < BUZ_MIN_HEIGHT ||
-           video_width > Wa || video_height > Ha) {
-               dprintk(1, KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n",
-                       ZR_DEVNAME(zr), video_width, video_height);
-               return;
-       }
-
-       /**** zr36057 ****/
-
-       /* horizontal */
-       VidWinWid = video_width;
-       X = (VidWinWid * 64 + tvn->Wa - 1) / tvn->Wa;
-       We = (VidWinWid * 64) / X;
-       HorDcm = 64 - X;
-       hcrop1 = 2 * ((tvn->Wa - We) / 4);
-       hcrop2 = tvn->Wa - We - hcrop1;
-       HStart = tvn->HStart ? tvn->HStart : 1;
-       /* (Ronald) Original comment:
-        * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+"
-        * this is false. It inverses chroma values on the LML33R10 (so Cr
-        * suddenly is shown as Cb and reverse, really cool effect if you
-        * want to see blue faces, not useful otherwise). So don't use |1.
-        * However, the DC10 has '0' as HStart, but does need |1, so we
-        * use a dirty check...
-        */
-       HEnd = HStart + tvn->Wa - 1;
-       HStart += hcrop1;
-       HEnd -= hcrop2;
-       reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)
-           | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);
-       if (zr->card.vfe_pol.hsync_pol)
-               reg |= ZR36057_VFEHCR_HSPol;
-       btwrite(reg, ZR36057_VFEHCR);
-
-       /* Vertical */
-       DispMode = !(video_height > BUZ_MAX_HEIGHT / 2);
-       VidWinHt = DispMode ? video_height : video_height / 2;
-       Y = (VidWinHt * 64 * 2 + tvn->Ha - 1) / tvn->Ha;
-       He = (VidWinHt * 64) / Y;
-       VerDcm = 64 - Y;
-       vcrop1 = (tvn->Ha / 2 - He) / 2;
-       vcrop2 = tvn->Ha / 2 - He - vcrop1;
-       VStart = tvn->VStart;
-       VEnd = VStart + tvn->Ha / 2;    // - 1; FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP
-       VStart += vcrop1;
-       VEnd -= vcrop2;
-       reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)
-           | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);
-       if (zr->card.vfe_pol.vsync_pol)
-               reg |= ZR36057_VFEVCR_VSPol;
-       btwrite(reg, ZR36057_VFEVCR);
-
-       /* scaler and pixel format */
-       reg = 0;
-       reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
-       reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
-       reg |= (DispMode << ZR36057_VFESPFR_DispMode);
-       /* RJ: I don't know, why the following has to be the opposite
-        * of the corresponding ZR36060 setting, but only this way
-        * we get the correct colors when uncompressing to the screen  */
-       //reg |= ZR36057_VFESPFR_VCLKPol; /**/
-       /* RJ: Don't know if that is needed for NTSC also */
-       if (zr->norm != VIDEO_MODE_NTSC)
-               reg |= ZR36057_VFESPFR_ExtFl;   // NEEDED!!!!!!! Wolfgang
-       reg |= ZR36057_VFESPFR_TopField;
-       if (HorDcm >= 48) {
-               reg |= 3 << ZR36057_VFESPFR_HFilter;    /* 5 tap filter */
-       } else if (HorDcm >= 32) {
-               reg |= 2 << ZR36057_VFESPFR_HFilter;    /* 4 tap filter */
-       } else if (HorDcm >= 16) {
-               reg |= 1 << ZR36057_VFESPFR_HFilter;    /* 3 tap filter */
-       }
-       reg |= format->vfespfr;
-       btwrite(reg, ZR36057_VFESPFR);
-
-       /* display configuration */
-       reg = (16 << ZR36057_VDCR_MinPix)
-           | (VidWinHt << ZR36057_VDCR_VidWinHt)
-           | (VidWinWid << ZR36057_VDCR_VidWinWid);
-       if (pci_pci_problems & PCIPCI_TRITON)
-               // || zr->revision < 1) // Revision 1 has also Triton support
-               reg &= ~ZR36057_VDCR_Triton;
-       else
-               reg |= ZR36057_VDCR_Triton;
-       btwrite(reg, ZR36057_VDCR);
-
-       /* (Ronald) don't write this if overlay_mask = NULL */
-       if (zr->overlay_mask) {
-               /* Write overlay clipping mask data, but don't enable overlay clipping */
-               /* RJ: since this makes only sense on the screen, we use
-                * zr->overlay_settings.width instead of video_width */
-
-               mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-               reg = virt_to_bus(zr->overlay_mask);
-               btwrite(reg, ZR36057_MMTR);
-               reg = virt_to_bus(zr->overlay_mask + mask_line_size);
-               btwrite(reg, ZR36057_MMBR);
-               reg =
-                   mask_line_size - (zr->overlay_settings.width +
-                                     31) / 32;
-               if (DispMode == 0)
-                       reg += mask_line_size;
-               reg <<= ZR36057_OCR_MaskStride;
-               btwrite(reg, ZR36057_OCR);
-       }
-
-       zr36057_adjust_vfe(zr, zr->codec_mode);
-}
-
-/*
- * Switch overlay on or off
- */
-
-void
-zr36057_overlay (struct zoran *zr,
-                int           on)
-{
-       u32 reg;
-
-       if (on) {
-               /* do the necessary settings ... */
-               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);       /* switch it off first */
-
-               zr36057_set_vfe(zr,
-                               zr->overlay_settings.width,
-                               zr->overlay_settings.height,
-                               zr->overlay_settings.format);
-
-               /* Start and length of each line MUST be 4-byte aligned.
-                * This should be allready checked before the call to this routine.
-                * All error messages are internal driver checking only! */
-
-               /* video display top and bottom registers */
-               reg = (long) zr->buffer.base +
-                   zr->overlay_settings.x *
-                   ((zr->overlay_settings.format->depth + 7) / 8) +
-                   zr->overlay_settings.y *
-                   zr->buffer.bytesperline;
-               btwrite(reg, ZR36057_VDTR);
-               if (reg & 3)
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zr36057_overlay() - video_address not aligned\n",
-                               ZR_DEVNAME(zr));
-               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-                       reg += zr->buffer.bytesperline;
-               btwrite(reg, ZR36057_VDBR);
-
-               /* video stride, status, and frame grab register */
-               reg = zr->buffer.bytesperline -
-                   zr->overlay_settings.width *
-                   ((zr->overlay_settings.format->depth + 7) / 8);
-               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-                       reg += zr->buffer.bytesperline;
-               if (reg & 3)
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zr36057_overlay() - video_stride not aligned\n",
-                               ZR_DEVNAME(zr));
-               reg = (reg << ZR36057_VSSFGR_DispStride);
-               reg |= ZR36057_VSSFGR_VidOvf;   /* clear overflow status */
-               btwrite(reg, ZR36057_VSSFGR);
-
-               /* Set overlay clipping */
-               if (zr->overlay_settings.clipcount > 0)
-                       btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);
-
-               /* ... and switch it on */
-               btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);
-       } else {
-               /* Switch it off */
-               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
-       }
-}
-
-/*
- * The overlay mask has one bit for each pixel on a scan line,
- *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
- */
-
-void
-write_overlay_mask (struct file       *file,
-                   struct video_clip *vp,
-                   int                count)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-       u32 *mask;
-       int x, y, width, height;
-       unsigned i, j, k;
-       u32 reg;
-
-       /* fill mask with one bits */
-       memset(fh->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);
-       reg = 0;
-
-       for (i = 0; i < count; ++i) {
-               /* pick up local copy of clip */
-               x = vp[i].x;
-               y = vp[i].y;
-               width = vp[i].width;
-               height = vp[i].height;
-
-               /* trim clips that extend beyond the window */
-               if (x < 0) {
-                       width += x;
-                       x = 0;
-               }
-               if (y < 0) {
-                       height += y;
-                       y = 0;
-               }
-               if (x + width > fh->overlay_settings.width) {
-                       width = fh->overlay_settings.width - x;
-               }
-               if (y + height > fh->overlay_settings.height) {
-                       height = fh->overlay_settings.height - y;
-               }
-
-               /* ignore degenerate clips */
-               if (height <= 0) {
-                       continue;
-               }
-               if (width <= 0) {
-                       continue;
-               }
-
-               /* apply clip for each scan line */
-               for (j = 0; j < height; ++j) {
-                       /* reset bit for each pixel */
-                       /* this can be optimized later if need be */
-                       mask = fh->overlay_mask + (y + j) * mask_line_size;
-                       for (k = 0; k < width; ++k) {
-                               mask[(x + k) / 32] &=
-                                   ~((u32) 1 << (x + k) % 32);
-                       }
-               }
-       }
-}
-
-/* Enable/Disable uncompressed memory grabbing of the 36057 */
-
-void
-zr36057_set_memgrab (struct zoran *zr,
-                    int           mode)
-{
-       if (mode) {
-               /* We only check SnapShot and not FrameGrab here.  SnapShot==1
-                * means a capture is already in progress, but FrameGrab==1
-                * doesn't necessary mean that.  It's more correct to say a 1
-                * to 0 transition indicates a capture completed.  If a
-                * capture is pending when capturing is tuned off, FrameGrab
-                * will be stuck at 1 until capturing is turned back on.
-                */
-               if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot)
-                       dprintk(1,
-                               KERN_WARNING
-                               "%s: zr36057_set_memgrab(1) with SnapShot on!?\n",
-                               ZR_DEVNAME(zr));
-
-               /* switch on VSync interrupts */
-               btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
-               btor(zr->card.vsync_int, ZR36057_ICR);  // SW
-
-               /* enable SnapShot */
-               btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
-
-               /* Set zr36057 video front end  and enable video */
-               zr36057_set_vfe(zr, zr->v4l_settings.width,
-                               zr->v4l_settings.height,
-                               zr->v4l_settings.format);
-
-               zr->v4l_memgrab_active = 1;
-       } else {
-               /* switch off VSync interrupts */
-               btand(~zr->card.vsync_int, ZR36057_ICR);        // SW
-
-               zr->v4l_memgrab_active = 0;
-               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-
-               /* reenable grabbing to screen if it was running */
-               if (zr->v4l_overlay_active) {
-                       zr36057_overlay(zr, 1);
-               } else {
-                       btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
-                       btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
-               }
-       }
-}
-
-int
-wait_grab_pending (struct zoran *zr)
-{
-       unsigned long flags;
-
-       /* wait until all pending grabs are finished */
-
-       if (!zr->v4l_memgrab_active)
-               return 0;
-
-       wait_event_interruptible(zr->v4l_capq,
-                       (zr->v4l_pend_tail == zr->v4l_pend_head));
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-       zr36057_set_memgrab(zr, 0);
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-/*****************************************************************************
- *                                                                           *
- *  Set up the Buz-specific MJPEG part                                       *
- *                                                                           *
- *****************************************************************************/
-
-static inline void
-set_frame (struct zoran *zr,
-          int           val)
-{
-       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
-}
-
-static void
-set_videobus_dir (struct zoran *zr,
-                 int           val)
-{
-       switch (zr->card.type) {
-       case LML33:
-       case LML33R10:
-               if (lml33dpath == 0)
-                       GPIO(zr, 5, val);
-               else
-                       GPIO(zr, 5, 1);
-               break;
-       default:
-               GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
-                    zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
-               break;
-       }
-}
-
-static void
-init_jpeg_queue (struct zoran *zr)
-{
-       int i;
-
-       /* re-initialize DMA ring stuff */
-       zr->jpg_que_head = 0;
-       zr->jpg_dma_head = 0;
-       zr->jpg_dma_tail = 0;
-       zr->jpg_que_tail = 0;
-       zr->jpg_seq_num = 0;
-       zr->JPEG_error = 0;
-       zr->num_errors = 0;
-       zr->jpg_err_seq = 0;
-       zr->jpg_err_shift = 0;
-       zr->jpg_queued_num = 0;
-       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
-               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       for (i = 0; i < BUZ_NUM_STAT_COM; i++) {
-               zr->stat_com[i] = cpu_to_le32(1);       /* mark as unavailable to zr36057 */
-       }
-}
-
-static void
-zr36057_set_jpg (struct zoran          *zr,
-                enum zoran_codec_mode  mode)
-{
-       struct tvnorm *tvn;
-       u32 reg;
-
-       tvn = zr->timing;
-
-       /* assert P_Reset, disable code transfer, deassert Active */
-       btwrite(0, ZR36057_JPC);
-
-       /* MJPEG compression mode */
-       switch (mode) {
-
-       case BUZ_MODE_MOTION_COMPRESS:
-       default:
-               reg = ZR36057_JMC_MJPGCmpMode;
-               break;
-
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               reg = ZR36057_JMC_MJPGExpMode;
-               reg |= ZR36057_JMC_SyncMstr;
-               /* RJ: The following is experimental - improves the output to screen */
-               //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
-               break;
-
-       case BUZ_MODE_STILL_COMPRESS:
-               reg = ZR36057_JMC_JPGCmpMode;
-               break;
-
-       case BUZ_MODE_STILL_DECOMPRESS:
-               reg = ZR36057_JMC_JPGExpMode;
-               break;
-
-       }
-       reg |= ZR36057_JMC_JPG;
-       if (zr->jpg_settings.field_per_buff == 1)
-               reg |= ZR36057_JMC_Fld_per_buff;
-       btwrite(reg, ZR36057_JMC);
-
-       /* vertical */
-       btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR);
-       reg = (6 << ZR36057_VSP_VsyncSize) |
-             (tvn->Ht << ZR36057_VSP_FrmTot);
-       btwrite(reg, ZR36057_VSP);
-       reg = ((zr->jpg_settings.img_y + tvn->VStart) << ZR36057_FVAP_NAY) |
-             (zr->jpg_settings.img_height << ZR36057_FVAP_PAY);
-       btwrite(reg, ZR36057_FVAP);
-
-       /* horizontal */
-       if (zr->card.vfe_pol.hsync_pol)
-               btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
-       else
-               btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
-       reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) |
-             (tvn->Wt << ZR36057_HSP_LineTot);
-       btwrite(reg, ZR36057_HSP);
-       reg = ((zr->jpg_settings.img_x +
-               tvn->HStart + 4) << ZR36057_FHAP_NAX) |
-             (zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
-       btwrite(reg, ZR36057_FHAP);
-
-       /* field process parameters */
-       if (zr->jpg_settings.odd_even)
-               reg = ZR36057_FPP_Odd_Even;
-       else
-               reg = 0;
-
-       btwrite(reg, ZR36057_FPP);
-
-       /* Set proper VCLK Polarity, else colors will be wrong during playback */
-       //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
-
-       /* code base address */
-       reg = virt_to_bus(zr->stat_com);
-       btwrite(reg, ZR36057_JCBA);
-
-       /* FIFO threshold (FIFO is 160. double words) */
-       /* NOTE: decimal values here */
-       switch (mode) {
-
-       case BUZ_MODE_STILL_COMPRESS:
-       case BUZ_MODE_MOTION_COMPRESS:
-               if (zr->card.type != BUZ)
-                       reg = 140;
-               else
-                       reg = 60;
-               break;
-
-       case BUZ_MODE_STILL_DECOMPRESS:
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               reg = 20;
-               break;
-
-       default:
-               reg = 80;
-               break;
-
-       }
-       btwrite(reg, ZR36057_JCFT);
-       zr36057_adjust_vfe(zr, mode);
-
-}
-
-void
-print_interrupts (struct zoran *zr)
-{
-       int res, noerr = 0;
-
-       printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr));
-       if ((res = zr->field_counter) < -1 || res > 1) {
-               printk(" FD:%d", res);
-       }
-       if ((res = zr->intr_counter_GIRQ1) != 0) {
-               printk(" GIRQ1:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_GIRQ0) != 0) {
-               printk(" GIRQ0:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_CodRepIRQ) != 0) {
-               printk(" CodRepIRQ:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
-               printk(" JPEGRepIRQ:%d", res);
-               noerr++;
-       }
-       if (zr->JPEG_max_missed) {
-               printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
-                      zr->JPEG_min_missed);
-       }
-       if (zr->END_event_missed) {
-               printk(" ENDs missed: %d", zr->END_event_missed);
-       }
-       //if (zr->jpg_queued_num) {
-       printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
-              zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
-       //}
-       if (!noerr) {
-               printk(": no interrupts detected.");
-       }
-       printk("\n");
-}
-
-void
-clear_interrupt_counters (struct zoran *zr)
-{
-       zr->intr_counter_GIRQ1 = 0;
-       zr->intr_counter_GIRQ0 = 0;
-       zr->intr_counter_CodRepIRQ = 0;
-       zr->intr_counter_JPEGRepIRQ = 0;
-       zr->field_counter = 0;
-       zr->IRQ1_in = 0;
-       zr->IRQ1_out = 0;
-       zr->JPEG_in = 0;
-       zr->JPEG_out = 0;
-       zr->JPEG_0 = 0;
-       zr->JPEG_1 = 0;
-       zr->END_event_missed = 0;
-       zr->JPEG_missed = 0;
-       zr->JPEG_max_missed = 0;
-       zr->JPEG_min_missed = 0x7fffffff;
-}
-
-static u32
-count_reset_interrupt (struct zoran *zr)
-{
-       u32 isr;
-
-       if ((isr = btread(ZR36057_ISR) & 0x78000000)) {
-               if (isr & ZR36057_ISR_GIRQ1) {
-                       btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
-                       zr->intr_counter_GIRQ1++;
-               }
-               if (isr & ZR36057_ISR_GIRQ0) {
-                       btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
-                       zr->intr_counter_GIRQ0++;
-               }
-               if (isr & ZR36057_ISR_CodRepIRQ) {
-                       btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR);
-                       zr->intr_counter_CodRepIRQ++;
-               }
-               if (isr & ZR36057_ISR_JPEGRepIRQ) {
-                       btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR);
-                       zr->intr_counter_JPEGRepIRQ++;
-               }
-       }
-       return isr;
-}
-
-void
-jpeg_start (struct zoran *zr)
-{
-       int reg;
-
-       zr->frame_num = 0;
-
-       /* deassert P_reset, disable code transfer, deassert Active */
-       btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC);
-       /* stop flushing the internal code buffer */
-       btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
-       /* enable code transfer */
-       btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC);
-
-       /* clear IRQs */
-       btwrite(IRQ_MASK, ZR36057_ISR);
-       /* enable the JPEG IRQs */
-       btwrite(zr->card.jpeg_int |
-                       ZR36057_ICR_JPEGRepIRQ |
-                       ZR36057_ICR_IntPinEn,
-               ZR36057_ICR);
-
-       set_frame(zr, 0);       // \FRAME
-
-       /* set the JPEG codec guest ID */
-       reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPEGuestID) |
-              (0 << ZR36057_JCGI_JPEGuestReg);
-       btwrite(reg, ZR36057_JCGI);
-
-       if (zr->card.video_vfe == CODEC_TYPE_ZR36016 &&
-           zr->card.video_codec == CODEC_TYPE_ZR36050) {
-               /* Enable processing on the ZR36016 */
-               if (zr->vfe)
-                       zr36016_write(zr->vfe, 0, 1);
-
-               /* load the address of the GO register in the ZR36050 latch */
-               post_office_write(zr, 0, 0, 0);
-       }
-
-       /* assert Active */
-       btor(ZR36057_JPC_Active, ZR36057_JPC);
-
-       /* enable the Go generation */
-       btor(ZR36057_JMC_Go_en, ZR36057_JMC);
-       udelay(30);
-
-       set_frame(zr, 1);       // /FRAME
-
-       dprintk(3, KERN_DEBUG "%s: jpeg_start\n", ZR_DEVNAME(zr));
-}
-
-void
-zr36057_enable_jpg (struct zoran          *zr,
-                   enum zoran_codec_mode  mode)
-{
-       static int zero;
-       static int one = 1;
-       struct vfe_settings cap;
-       int field_size =
-           zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
-
-       zr->codec_mode = mode;
-
-       cap.x = zr->jpg_settings.img_x;
-       cap.y = zr->jpg_settings.img_y;
-       cap.width = zr->jpg_settings.img_width;
-       cap.height = zr->jpg_settings.img_height;
-       cap.decimation =
-           zr->jpg_settings.HorDcm | (zr->jpg_settings.VerDcm << 8);
-       cap.quality = zr->jpg_settings.jpg_comp.quality;
-
-       switch (mode) {
-
-       case BUZ_MODE_MOTION_COMPRESS: {
-               struct jpeg_app_marker app;
-               struct jpeg_com_marker com;
-
-               /* In motion compress mode, the decoder output must be enabled, and
-                * the video bus direction set to input.
-                */
-               set_videobus_dir(zr, 0);
-               decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
-               encoder_command(zr, ENCODER_SET_INPUT, &zero);
-
-               /* Take the JPEG codec and the VFE out of sleep */
-               jpeg_codec_sleep(zr, 0);
-
-               /* set JPEG app/com marker */
-               app.appn = zr->jpg_settings.jpg_comp.APPn;
-               app.len = zr->jpg_settings.jpg_comp.APP_len;
-               memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60);
-               zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA,
-                                  sizeof(struct jpeg_app_marker), &app);
-
-               com.len = zr->jpg_settings.jpg_comp.COM_len;
-               memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60);
-               zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA,
-                                  sizeof(struct jpeg_com_marker), &com);
-
-               /* Setup the JPEG codec */
-               zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE,
-                                  sizeof(int), &field_size);
-               zr->codec->set_video(zr->codec, zr->timing, &cap,
-                                    &zr->card.vfe_pol);
-               zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION);
-
-               /* Setup the VFE */
-               if (zr->vfe) {
-                       zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE,
-                                        sizeof(int), &field_size);
-                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
-                                          &zr->card.vfe_pol);
-                       zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION);
-               }
-
-               init_jpeg_queue(zr);
-               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
-
-               clear_interrupt_counters(zr);
-               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_COMPRESS)\n",
-                       ZR_DEVNAME(zr));
-               break;
-       }
-
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               /* In motion decompression mode, the decoder output must be disabled, and
-                * the video bus direction set to output.
-                */
-               decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
-               set_videobus_dir(zr, 1);
-               encoder_command(zr, ENCODER_SET_INPUT, &one);
-
-               /* Take the JPEG codec and the VFE out of sleep */
-               jpeg_codec_sleep(zr, 0);
-               /* Setup the VFE */
-               if (zr->vfe) {
-                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
-                                          &zr->card.vfe_pol);
-                       zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION);
-               }
-               /* Setup the JPEG codec */
-               zr->codec->set_video(zr->codec, zr->timing, &cap,
-                                    &zr->card.vfe_pol);
-               zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION);
-
-               init_jpeg_queue(zr);
-               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
-
-               clear_interrupt_counters(zr);
-               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_DECOMPRESS)\n",
-                       ZR_DEVNAME(zr));
-               break;
-
-       case BUZ_MODE_IDLE:
-       default:
-               /* shut down processing */
-               btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ),
-                     ZR36057_ICR);
-               btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ,
-                       ZR36057_ISR);
-               btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en
-
-               msleep(50);
-
-               set_videobus_dir(zr, 0);
-               set_frame(zr, 1);       // /FRAME
-               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);      // /CFlush
-               btwrite(0, ZR36057_JPC);        // \P_Reset,\CodTrnsEn,\Active
-               btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
-               btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC);
-               jpeg_codec_reset(zr);
-               jpeg_codec_sleep(zr, 1);
-               zr36057_adjust_vfe(zr, mode);
-
-               decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
-               encoder_command(zr, ENCODER_SET_INPUT, &zero);
-
-               dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
-               break;
-
-       }
-}
-
-/* when this is called the spinlock must be held */
-void
-zoran_feed_stat_com (struct zoran *zr)
-{
-       /* move frames from pending queue to DMA */
-
-       int frame, i, max_stat_com;
-
-       max_stat_com =
-           (zr->jpg_settings.TmpDcm ==
-            1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
-
-       while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com &&
-              zr->jpg_dma_head < zr->jpg_que_head) {
-
-               frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME];
-               if (zr->jpg_settings.TmpDcm == 1) {
-                       /* fill 1 stat_com entry */
-                       i = (zr->jpg_dma_head -
-                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
-                               break;
-                       zr->stat_com[i] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
-               } else {
-                       /* fill 2 stat_com entries */
-                       i = ((zr->jpg_dma_head -
-                             zr->jpg_err_shift) & 1) * 2;
-                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
-                               break;
-                       zr->stat_com[i] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
-                       zr->stat_com[i + 1] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
-               }
-               zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
-               zr->jpg_dma_head++;
-
-       }
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
-               zr->jpg_queued_num++;
-}
-
-/* when this is called the spinlock must be held */
-static void
-zoran_reap_stat_com (struct zoran *zr)
-{
-       /* move frames from DMA queue to done queue */
-
-       int i;
-       u32 stat_com;
-       unsigned int seq;
-       unsigned int dif;
-       struct zoran_jpg_buffer *buffer;
-       int frame;
-
-       /* In motion decompress we don't have a hardware frame counter,
-        * we just count the interrupts here */
-
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
-               zr->jpg_seq_num++;
-       }
-       while (zr->jpg_dma_tail < zr->jpg_dma_head) {
-               if (zr->jpg_settings.TmpDcm == 1)
-                       i = (zr->jpg_dma_tail -
-                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-               else
-                       i = ((zr->jpg_dma_tail -
-                             zr->jpg_err_shift) & 1) * 2 + 1;
-
-               stat_com = le32_to_cpu(zr->stat_com[i]);
-
-               if ((stat_com & 1) == 0) {
-                       return;
-               }
-               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
-               buffer = &zr->jpg_buffers.buffer[frame];
-               do_gettimeofday(&buffer->bs.timestamp);
-
-               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                       buffer->bs.length = (stat_com & 0x7fffff) >> 1;
-
-                       /* update sequence number with the help of the counter in stat_com */
-
-                       seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff;
-                       dif = (seq - zr->jpg_seq_num) & 0xff;
-                       zr->jpg_seq_num += dif;
-               } else {
-                       buffer->bs.length = 0;
-               }
-               buffer->bs.seq =
-                   zr->jpg_settings.TmpDcm ==
-                   2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
-               buffer->state = BUZ_STATE_DONE;
-
-               zr->jpg_dma_tail++;
-       }
-}
-
-static void
-error_handler (struct zoran *zr,
-              u32           astat,
-              u32           stat)
-{
-       /* This is JPEG error handling part */
-       if ((zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) &&
-           (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS)) {
-               //dprintk(1, KERN_ERR "%s: Internal error: error handling request in mode %d\n", ZR_DEVNAME(zr), zr->codec_mode);
-               return;
-       }
-
-       if ((stat & 1) == 0 &&
-           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS &&
-           zr->jpg_dma_tail - zr->jpg_que_tail >=
-            zr->jpg_buffers.num_buffers) {
-               /* No free buffers... */
-               zoran_reap_stat_com(zr);
-               zoran_feed_stat_com(zr);
-               wake_up_interruptible(&zr->jpg_capq);
-               zr->JPEG_missed = 0;
-               return;
-       }
-
-       if (zr->JPEG_error != 1) {
-               /*
-                * First entry: error just happened during normal operation
-                *
-                * In BUZ_MODE_MOTION_COMPRESS:
-                *
-                * Possible glitch in TV signal. In this case we should
-                * stop the codec and wait for good quality signal before
-                * restarting it to avoid further problems
-                *
-                * In BUZ_MODE_MOTION_DECOMPRESS:
-                *
-                * Bad JPEG frame: we have to mark it as processed (codec crashed
-                * and was not able to do it itself), and to remove it from queue.
-                */
-               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
-               udelay(1);
-               stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
-               btwrite(0, ZR36057_JPC);
-               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
-               jpeg_codec_reset(zr);
-               jpeg_codec_sleep(zr, 1);
-               zr->JPEG_error = 1;
-               zr->num_errors++;
-
-               /* Report error */
-               if (zr36067_debug > 1 && zr->num_errors <= 8) {
-                       long frame;
-                       frame =
-                           zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
-                       printk(KERN_ERR
-                              "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
-                              ZR_DEVNAME(zr), stat, zr->last_isr,
-                              zr->jpg_que_tail, zr->jpg_dma_tail,
-                              zr->jpg_dma_head, zr->jpg_que_head,
-                              zr->jpg_seq_num, frame);
-                       printk("stat_com frames:");
-                       {
-                               int i, j;
-                               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-                                       for (i = 0;
-                                            i < zr->jpg_buffers.num_buffers;
-                                            i++) {
-                                               if (le32_to_cpu(zr->stat_com[j]) ==
-                                                   zr->jpg_buffers.
-                                                   buffer[i].
-                                                   frag_tab_bus) {
-                                                       printk("% d->%d",
-                                                              j, i);
-                                               }
-                                       }
-                               }
-                               printk("\n");
-                       }
-               }
-               /* Find an entry in stat_com and rotate contents */
-               {
-                       int i;
-
-                       if (zr->jpg_settings.TmpDcm == 1)
-                               i = (zr->jpg_dma_tail -
-                                    zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-                       else
-                               i = ((zr->jpg_dma_tail -
-                                     zr->jpg_err_shift) & 1) * 2;
-                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
-                               /* Mimic zr36067 operation */
-                               zr->stat_com[i] |= cpu_to_le32(1);
-                               if (zr->jpg_settings.TmpDcm != 1)
-                                       zr->stat_com[i + 1] |= cpu_to_le32(1);
-                               /* Refill */
-                               zoran_reap_stat_com(zr);
-                               zoran_feed_stat_com(zr);
-                               wake_up_interruptible(&zr->jpg_capq);
-                               /* Find an entry in stat_com again after refill */
-                               if (zr->jpg_settings.TmpDcm == 1)
-                                       i = (zr->jpg_dma_tail -
-                                            zr->jpg_err_shift) &
-                                           BUZ_MASK_STAT_COM;
-                               else
-                                       i = ((zr->jpg_dma_tail -
-                                             zr->jpg_err_shift) & 1) * 2;
-                       }
-                       if (i) {
-                               /* Rotate stat_comm entries to make current entry first */
-                               int j;
-                               __le32 bus_addr[BUZ_NUM_STAT_COM];
-
-                               /* Here we are copying the stat_com array, which
-                                * is already in little endian format, so
-                                * no endian conversions here
-                                */
-                               memcpy(bus_addr, zr->stat_com,
-                                      sizeof(bus_addr));
-                               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-                                       zr->stat_com[j] =
-                                           bus_addr[(i + j) &
-                                                    BUZ_MASK_STAT_COM];
-
-                               }
-                               zr->jpg_err_shift += i;
-                               zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
-                       }
-                       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
-                               zr->jpg_err_seq = zr->jpg_seq_num;      /* + 1; */
-               }
-       }
-
-       /* Now the stat_comm buffer is ready for restart */
-       do {
-               int status, mode;
-
-               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                       decoder_command(zr, DECODER_GET_STATUS, &status);
-                       mode = CODEC_DO_COMPRESSION;
-               } else {
-                       status = 0;
-                       mode = CODEC_DO_EXPANSION;
-               }
-               if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-                   (status & DECODER_STATUS_GOOD)) {
-                       /********** RESTART code *************/
-                       jpeg_codec_reset(zr);
-                       zr->codec->set_mode(zr->codec, mode);
-                       zr36057_set_jpg(zr, zr->codec_mode);
-                       jpeg_start(zr);
-
-                       if (zr->num_errors <= 8)
-                               dprintk(2, KERN_INFO "%s: Restart\n",
-                                       ZR_DEVNAME(zr));
-
-                       zr->JPEG_missed = 0;
-                       zr->JPEG_error = 2;
-                       /********** End RESTART code ***********/
-               }
-       } while (0);
-}
-
-irqreturn_t
-zoran_irq (int             irq,
-          void           *dev_id)
-{
-       u32 stat, astat;
-       int count;
-       struct zoran *zr;
-       unsigned long flags;
-
-       zr = dev_id;
-       count = 0;
-
-       if (zr->testing) {
-               /* Testing interrupts */
-               spin_lock_irqsave(&zr->spinlock, flags);
-               while ((stat = count_reset_interrupt(zr))) {
-                       if (count++ > 100) {
-                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: IRQ lockup while testing, isr=0x%08x, cleared int mask\n",
-                                       ZR_DEVNAME(zr), stat);
-                               wake_up_interruptible(&zr->test_q);
-                       }
-               }
-               zr->last_isr = stat;
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-               return IRQ_HANDLED;
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-       while (1) {
-               /* get/clear interrupt status bits */
-               stat = count_reset_interrupt(zr);
-               astat = stat & IRQ_MASK;
-               if (!astat) {
-                       break;
-               }
-               dprintk(4,
-                       KERN_DEBUG
-                       "zoran_irq: astat: 0x%08x, mask: 0x%08x\n",
-                       astat, btread(ZR36057_ICR));
-               if (astat & zr->card.vsync_int) {       // SW
-
-                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                               /* count missed interrupts */
-                               zr->JPEG_missed++;
-                       }
-                       //post_office_read(zr,1,0);
-                       /* Interrupts may still happen when
-                        * zr->v4l_memgrab_active is switched off.
-                        * We simply ignore them */
-
-                       if (zr->v4l_memgrab_active) {
-
-                               /* A lot more checks should be here ... */
-                               if ((btread(ZR36057_VSSFGR) &
-                                    ZR36057_VSSFGR_SnapShot) == 0)
-                                       dprintk(1,
-                                               KERN_WARNING
-                                               "%s: BuzIRQ with SnapShot off ???\n",
-                                               ZR_DEVNAME(zr));
-
-                               if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
-                                       /* There is a grab on a frame going on, check if it has finished */
-
-                                       if ((btread(ZR36057_VSSFGR) &
-                                            ZR36057_VSSFGR_FrameGrab) ==
-                                           0) {
-                                               /* it is finished, notify the user */
-
-                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
-                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq;
-                                               do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
-                                               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-                                               zr->v4l_pend_tail++;
-                                       }
-                               }
-
-                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE)
-                                       wake_up_interruptible(&zr->v4l_capq);
-
-                               /* Check if there is another grab queued */
-
-                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE &&
-                                   zr->v4l_pend_tail != zr->v4l_pend_head) {
-
-                                       int frame = zr->v4l_pend[zr->v4l_pend_tail &
-                                                        V4L_MASK_FRAME];
-                                       u32 reg;
-
-                                       zr->v4l_grab_frame = frame;
-
-                                       /* Set zr36057 video front end and enable video */
-
-                                       /* Buffer address */
-
-                                       reg =
-                                           zr->v4l_buffers.buffer[frame].
-                                           fbuffer_bus;
-                                       btwrite(reg, ZR36057_VDTR);
-                                       if (zr->v4l_settings.height >
-                                           BUZ_MAX_HEIGHT / 2)
-                                               reg +=
-                                                   zr->v4l_settings.
-                                                   bytesperline;
-                                       btwrite(reg, ZR36057_VDBR);
-
-                                       /* video stride, status, and frame grab register */
-                                       reg = 0;
-                                       if (zr->v4l_settings.height >
-                                           BUZ_MAX_HEIGHT / 2)
-                                               reg +=
-                                                   zr->v4l_settings.
-                                                   bytesperline;
-                                       reg =
-                                           (reg <<
-                                            ZR36057_VSSFGR_DispStride);
-                                       reg |= ZR36057_VSSFGR_VidOvf;
-                                       reg |= ZR36057_VSSFGR_SnapShot;
-                                       reg |= ZR36057_VSSFGR_FrameGrab;
-                                       btwrite(reg, ZR36057_VSSFGR);
-
-                                       btor(ZR36057_VDCR_VidEn,
-                                            ZR36057_VDCR);
-                               }
-                       }
-
-                       /* even if we don't grab, we do want to increment
-                        * the sequence counter to see lost frames */
-                       zr->v4l_grab_seq++;
-               }
-#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
-               if (astat & ZR36057_ISR_CodRepIRQ) {
-                       zr->intr_counter_CodRepIRQ++;
-                       IDEBUG(printk
-                              (KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
-                               ZR_DEVNAME(zr)));
-                       btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
-               }
-#endif                         /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
-
-#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
-               if (astat & ZR36057_ISR_JPEGRepIRQ) {
-
-                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                               if (zr36067_debug > 1 &&
-                                   (!zr->frame_num || zr->JPEG_error)) {
-                                       printk(KERN_INFO
-                                              "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
-                                              ZR_DEVNAME(zr), stat,
-                                              zr->jpg_settings.odd_even,
-                                              zr->jpg_settings.
-                                              field_per_buff,
-                                              zr->JPEG_missed);
-                                       {
-                                               char sc[] = "0000";
-                                               char sv[5];
-                                               int i;
-                                               strcpy(sv, sc);
-                                               for (i = 0; i < 4; i++) {
-                                                       if (le32_to_cpu(zr->stat_com[i]) & 1)
-                                                               sv[i] = '1';
-                                               }
-                                               sv[4] = 0;
-                                               printk(KERN_INFO
-                                                      "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
-                                                      ZR_DEVNAME(zr), sv,
-                                                      zr->jpg_que_tail,
-                                                      zr->jpg_dma_tail,
-                                                      zr->jpg_dma_head,
-                                                      zr->jpg_que_head);
-                                       }
-                               } else {
-                                       if (zr->JPEG_missed > zr->JPEG_max_missed)      // Get statistics
-                                               zr->JPEG_max_missed =
-                                                   zr->JPEG_missed;
-                                       if (zr->JPEG_missed <
-                                           zr->JPEG_min_missed)
-                                               zr->JPEG_min_missed =
-                                                   zr->JPEG_missed;
-                               }
-
-                               if (zr36067_debug > 2 && zr->frame_num < 6) {
-                                       int i;
-                                       printk("%s: seq=%ld stat_com:",
-                                              ZR_DEVNAME(zr), zr->jpg_seq_num);
-                                       for (i = 0; i < 4; i++) {
-                                               printk(" %08x",
-                                                      le32_to_cpu(zr->stat_com[i]));
-                                       }
-                                       printk("\n");
-                               }
-                               zr->frame_num++;
-                               zr->JPEG_missed = 0;
-                               zr->JPEG_error = 0;
-                               zoran_reap_stat_com(zr);
-                               zoran_feed_stat_com(zr);
-                               wake_up_interruptible(&zr->jpg_capq);
-                       } /*else {
-                             dprintk(1,
-                                       KERN_ERR
-                                       "%s: JPEG interrupt while not in motion (de)compress mode!\n",
-                                       ZR_DEVNAME(zr));
-                       }*/
-               }
-#endif                         /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
-
-               /* DATERR, too many fields missed, error processing */
-               if ((astat & zr->card.jpeg_int) ||
-                   zr->JPEG_missed > 25 ||
-                   zr->JPEG_error == 1 ||
-                   ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
-                    (zr->frame_num & (zr->JPEG_missed >
-                                      zr->jpg_settings.field_per_buff)))) {
-                       error_handler(zr, astat, stat);
-               }
-
-               count++;
-               if (count > 10) {
-                       dprintk(2, KERN_WARNING "%s: irq loop %d\n",
-                               ZR_DEVNAME(zr), count);
-                       if (count > 20) {
-                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-                               dprintk(2,
-                                       KERN_ERR
-                                       "%s: IRQ lockup, cleared int mask\n",
-                                       ZR_DEVNAME(zr));
-                               break;
-                       }
-               }
-               zr->last_isr = stat;
-       }
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return IRQ_HANDLED;
-}
-
-void
-zoran_set_pci_master (struct zoran *zr,
-                     int           set_master)
-{
-       if (set_master) {
-               pci_set_master(zr->pci_dev);
-       } else {
-               u16 command;
-
-               pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command);
-               command &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(zr->pci_dev, PCI_COMMAND, command);
-       }
-}
-
-void
-zoran_init_hardware (struct zoran *zr)
-{
-       int j, zero = 0;
-
-       /* Enable bus-mastering */
-       zoran_set_pci_master(zr, 1);
-
-       /* Initialize the board */
-       if (zr->card.init) {
-               zr->card.init(zr);
-       }
-
-       j = zr->card.input[zr->input].muxsel;
-
-       decoder_command(zr, 0, NULL);
-       decoder_command(zr, DECODER_SET_NORM, &zr->norm);
-       decoder_command(zr, DECODER_SET_INPUT, &j);
-
-       encoder_command(zr, 0, NULL);
-       encoder_command(zr, ENCODER_SET_NORM, &zr->norm);
-       encoder_command(zr, ENCODER_SET_INPUT, &zero);
-
-       /* toggle JPEG codec sleep to sync PLL */
-       jpeg_codec_sleep(zr, 1);
-       jpeg_codec_sleep(zr, 0);
-
-       /* set individual interrupt enables (without GIRQ1)
-        * but don't global enable until zoran_open() */
-
-       //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR);  // SW
-       // It looks like using only JPEGRepIRQEn is not always reliable,
-       // may be when JPEG codec crashes it won't generate IRQ? So,
-        /*CP*/                 //        btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM    WHY ? LP
-           zr36057_init_vfe(zr);
-
-       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-
-       btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
-}
-
-void
-zr36057_restart (struct zoran *zr)
-{
-       btwrite(0, ZR36057_SPGPPCR);
-       mdelay(1);
-       btor(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR);
-       mdelay(1);
-
-       /* assert P_Reset */
-       btwrite(0, ZR36057_JPC);
-       /* set up GPIO direction - all output */
-       btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR);
-
-       /* set up GPIO pins and guest bus timing */
-       btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
-}
-
-/*
- * initialize video front end
- */
-
-static void
-zr36057_init_vfe (struct zoran *zr)
-{
-       u32 reg;
-
-       reg = btread(ZR36057_VFESPFR);
-       reg |= ZR36057_VFESPFR_LittleEndian;
-       reg &= ~ZR36057_VFESPFR_VCLKPol;
-       reg |= ZR36057_VFESPFR_ExtFl;
-       reg |= ZR36057_VFESPFR_TopField;
-       btwrite(reg, ZR36057_VFESPFR);
-       reg = btread(ZR36057_VDCR);
-       if (pci_pci_problems & PCIPCI_TRITON)
-               // || zr->revision < 1) // Revision 1 has also Triton support
-               reg &= ~ZR36057_VDCR_Triton;
-       else
-               reg |= ZR36057_VDCR_Triton;
-       btwrite(reg, ZR36057_VDCR);
-}
-
-/*
- * Interface to decoder and encoder chips using i2c bus
- */
-
-int
-decoder_command (struct zoran *zr,
-                int           cmd,
-                void         *data)
-{
-       if (zr->decoder == NULL)
-               return -EIO;
-
-       if (zr->card.type == LML33 &&
-           (cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
-               int res;
-
-               // Bt819 needs to reset its FIFO buffer using #FRST pin and
-               // LML33 card uses GPIO(7) for that.
-               GPIO(zr, 7, 0);
-               res = zr->decoder->driver->command(zr->decoder, cmd, data);
-               // Pull #FRST high.
-               GPIO(zr, 7, 1);
-               return res;
-       } else
-               return zr->decoder->driver->command(zr->decoder, cmd,
-                                                   data);
-}
-
-int
-encoder_command (struct zoran *zr,
-                int           cmd,
-                void         *data)
-{
-       if (zr->encoder == NULL)
-               return -1;
-
-       return zr->encoder->driver->command(zr->encoder, cmd, data);
-}
diff --git a/drivers/media/video/zoran_device.h b/drivers/media/video/zoran_device.h
deleted file mode 100644 (file)
index 37fa86a..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ZORAN_DEVICE_H__
-#define __ZORAN_DEVICE_H__
-
-/* general purpose I/O */
-extern void GPIO(struct zoran *zr,
-                int bit,
-                unsigned int value);
-
-/* codec (or actually: guest bus) access */
-extern int post_office_wait(struct zoran *zr);
-extern int post_office_write(struct zoran *zr,
-                            unsigned guest,
-                            unsigned reg,
-                            unsigned value);
-extern int post_office_read(struct zoran *zr,
-                           unsigned guest,
-                           unsigned reg);
-
-extern void detect_guest_activity(struct zoran *zr);
-
-extern void jpeg_codec_sleep(struct zoran *zr,
-                            int sleep);
-extern int jpeg_codec_reset(struct zoran *zr);
-
-/* zr360x7 access to raw capture */
-extern void zr36057_overlay(struct zoran *zr,
-                           int on);
-extern void write_overlay_mask(struct file *file,
-                              struct video_clip *vp,
-                              int count);
-extern void zr36057_set_memgrab(struct zoran *zr,
-                               int mode);
-extern int wait_grab_pending(struct zoran *zr);
-
-/* interrupts */
-extern void print_interrupts(struct zoran *zr);
-extern void clear_interrupt_counters(struct zoran *zr);
-extern irqreturn_t zoran_irq(int irq, void *dev_id);
-
-/* JPEG codec access */
-extern void jpeg_start(struct zoran *zr);
-extern void zr36057_enable_jpg(struct zoran *zr,
-                              enum zoran_codec_mode mode);
-extern void zoran_feed_stat_com(struct zoran *zr);
-
-/* general */
-extern void zoran_set_pci_master(struct zoran *zr,
-                                int set_master);
-extern void zoran_init_hardware(struct zoran *zr);
-extern void zr36057_restart(struct zoran *zr);
-
-/* i2c */
-extern int decoder_command(struct zoran *zr,
-                          int cmd,
-                          void *data);
-extern int encoder_command(struct zoran *zr,
-                          int cmd,
-                          void *data);
-
-#endif                         /* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
deleted file mode 100644 (file)
index 2dab9ee..0000000
+++ /dev/null
@@ -1,4648 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
- *
- * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
- *
- * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * Based on
- *
- * Miro DC10 driver
- * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
- *
- * Iomega Buz driver version 1.0
- * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
- *
- * buz.0.0.3
- * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * bttv - Bt848 frame grabber driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
- *                        & Marcus Metzler (mocm@thp.uni-koeln.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <linux/spinlock.h>
-#define     MAP_NR(x)       virt_to_page(x)
-#define     ZORAN_VID_TYPE  ( \
-                               VID_TYPE_CAPTURE | \
-                               VID_TYPE_OVERLAY | \
-                               VID_TYPE_CLIPPING | \
-                               VID_TYPE_FRAMERAM | \
-                               VID_TYPE_SCALES | \
-                               VID_TYPE_MJPEG_DECODER | \
-                               VID_TYPE_MJPEG_ENCODER \
-                            )
-
-#include <linux/videodev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "videocodec.h"
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
-
-#include <linux/video_decoder.h>
-#include <linux/video_encoder.h>
-#include <linux/mutex.h>
-#include "zoran.h"
-#include "zoran_device.h"
-#include "zoran_card.h"
-
-       /* we declare some card type definitions here, they mean
-        * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */
-#define ZORAN_V4L2_VID_FLAGS ( \
-                               V4L2_CAP_STREAMING |\
-                               V4L2_CAP_VIDEO_CAPTURE |\
-                               V4L2_CAP_VIDEO_OUTPUT |\
-                               V4L2_CAP_VIDEO_OVERLAY \
-                             )
-
-
-#if defined(CONFIG_VIDEO_V4L1_COMPAT)
-#define ZFMT(pal, fcc, cs) \
-       .palette = (pal), .fourcc = (fcc), .colorspace = (cs)
-#else
-#define ZFMT(pal, fcc, cs) \
-       .fourcc = (fcc), .colorspace = (cs)
-#endif
-
-const struct zoran_format zoran_formats[] = {
-       {
-               .name = "15-bit RGB LE",
-               ZFMT(VIDEO_PALETTE_RGB555,
-                    V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB),
-               .depth = 15,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
-                          ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "15-bit RGB BE",
-               ZFMT(-1,
-                    V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB),
-               .depth = 15,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
-       }, {
-               .name = "16-bit RGB LE",
-               ZFMT(VIDEO_PALETTE_RGB565,
-                    V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB),
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif|
-                          ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "16-bit RGB BE",
-               ZFMT(-1,
-                    V4L2_PIX_FMT_RGB565X, V4L2_COLORSPACE_SRGB),
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
-       }, {
-               .name = "24-bit RGB",
-               ZFMT(VIDEO_PALETTE_RGB24,
-                    V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB),
-               .depth = 24,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
-       }, {
-               .name = "32-bit RGB LE",
-               ZFMT(VIDEO_PALETTE_RGB32,
-                    V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB),
-               .depth = 32,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "32-bit RGB BE",
-               ZFMT(-1,
-                    V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB),
-               .depth = 32,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888,
-       }, {
-               .name = "4:2:2, packed, YUYV",
-               ZFMT(VIDEO_PALETTE_YUV422,
-                    V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M),
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_YUV422,
-       }, {
-               .name = "4:2:2, packed, UYVY",
-               ZFMT(VIDEO_PALETTE_UYVY,
-                    V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M),
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "Hardware-encoded Motion-JPEG",
-               ZFMT(-1,
-                    V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M),
-               .depth = 0,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_PLAYBACK |
-                        ZORAN_FORMAT_COMPRESSED,
-       }
-};
-#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
-
-// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined
-
-
-extern int v4l_nbufs;
-extern int v4l_bufsize;
-extern int jpg_nbufs;
-extern int jpg_bufsize;
-extern int pass_through;
-
-static int lock_norm;  /* 0 = default 1 = Don't change TV standard (norm) */
-module_param(lock_norm, int, 0644);
-MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)");
-
-       /* small helper function for calculating buffersizes for v4l2
-        * we calculate the nearest higher power-of-two, which
-        * will be the recommended buffersize */
-static __u32
-zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
-{
-       __u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm;
-       __u32 num = (1024 * 512) / (div);
-       __u32 result = 2;
-
-       num--;
-       while (num) {
-               num >>= 1;
-               result <<= 1;
-       }
-
-       if (result > jpg_bufsize)
-               return jpg_bufsize;
-       if (result < 8192)
-               return 8192;
-       return result;
-}
-
-/* forward references */
-static void v4l_fbuffer_free(struct file *file);
-static void jpg_fbuffer_free(struct file *file);
-
-/*
- *   Allocate the V4L grab buffers
- *
- *   These have to be pysically contiguous.
- *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc
- *   else we try to allocate them with bigphysarea_alloc_pages
- *   if the bigphysarea patch is present in the kernel,
- *   else we try to use high memory (if the user has bootet
- *   Linux with the necessary memory left over).
- */
-
-static unsigned long
-get_high_mem (unsigned long size)
-{
-/*
- * Check if there is usable memory at the end of Linux memory
- * of at least size. Return the physical address of this memory,
- * return 0 on failure.
- *
- * The idea is from Alexandro Rubini's book "Linux device drivers".
- * The driver from him which is downloadable from O'Reilly's
- * web site misses the "virt_to_phys(high_memory)" part
- * (and therefore doesn't work at all - at least with 2.2.x kernels).
- *
- * It should be unnecessary to mention that THIS IS DANGEROUS,
- * if more than one driver at a time has the idea to use this memory!!!!
- */
-
-       volatile unsigned char __iomem *mem;
-       unsigned char c;
-       unsigned long hi_mem_ph;
-       unsigned long i;
-
-       /* Map the high memory to user space */
-
-       hi_mem_ph = virt_to_phys(high_memory);
-
-       mem = ioremap(hi_mem_ph, size);
-       if (!mem) {
-               dprintk(1,
-                       KERN_ERR "%s: get_high_mem() - ioremap failed\n",
-                       ZORAN_NAME);
-               return 0;
-       }
-
-       for (i = 0; i < size; i++) {
-               /* Check if it is memory */
-               c = i & 0xff;
-               writeb(c, mem + i);
-               if (readb(mem + i) != c)
-                       break;
-               c = 255 - c;
-               writeb(c, mem + i);
-               if (readb(mem + i) != c)
-                       break;
-               writeb(0, mem + i);     /* zero out memory */
-
-               /* give the kernel air to breath */
-               if ((i & 0x3ffff) == 0x3ffff)
-                       schedule();
-       }
-
-       iounmap(mem);
-
-       if (i != size) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: get_high_mem() - requested %lu, avail %lu\n",
-                       ZORAN_NAME, size, i);
-               return 0;
-       }
-
-       return hi_mem_ph;
-}
-
-static int
-v4l_fbuffer_alloc (struct file *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int i, off;
-       unsigned char *mem;
-       unsigned long pmem = 0;
-
-       /* we might have old buffers lying around... */
-       if (fh->v4l_buffers.ready_to_be_freed) {
-               v4l_fbuffer_free(file);
-       }
-
-       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-               if (fh->v4l_buffers.buffer[i].fbuffer)
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n",
-                               ZR_DEVNAME(zr), i);
-
-               //udelay(20);
-               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-                       /* Use kmalloc */
-
-                       mem = kmalloc(fh->v4l_buffers.buffer_size, GFP_KERNEL);
-                       if (!mem) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",
-                                       ZR_DEVNAME(zr), i);
-                               v4l_fbuffer_free(file);
-                               return -ENOBUFS;
-                       }
-                       fh->v4l_buffers.buffer[i].fbuffer = mem;
-                       fh->v4l_buffers.buffer[i].fbuffer_phys =
-                           virt_to_phys(mem);
-                       fh->v4l_buffers.buffer[i].fbuffer_bus =
-                           virt_to_bus(mem);
-                       for (off = 0; off < fh->v4l_buffers.buffer_size;
-                            off += PAGE_SIZE)
-                               SetPageReserved(MAP_NR(mem + off));
-                       dprintk(4,
-                               KERN_INFO
-                               "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n",
-                               ZR_DEVNAME(zr), i, (unsigned long) mem,
-                               virt_to_bus(mem));
-               } else {
-
-                       /* Use high memory which has been left at boot time */
-
-                       /* Ok., Ok. this is an evil hack - we make
-                        * the assumption that physical addresses are
-                        * the same as bus addresses (true at least
-                        * for Intel processors). The whole method of
-                        * obtaining and using this memory is not very
-                        * nice - but I hope it saves some poor users
-                        * from kernel hacking, which might have even
-                        * more evil results */
-
-                       if (i == 0) {
-                               int size =
-                                   fh->v4l_buffers.num_buffers *
-                                   fh->v4l_buffers.buffer_size;
-
-                               pmem = get_high_mem(size);
-                               if (pmem == 0) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n",
-                                               ZR_DEVNAME(zr), size >> 10);
-                                       return -ENOBUFS;
-                               }
-                               fh->v4l_buffers.buffer[0].fbuffer = NULL;
-                               fh->v4l_buffers.buffer[0].fbuffer_phys = pmem;
-                               fh->v4l_buffers.buffer[0].fbuffer_bus = pmem;
-                               dprintk(4,
-                                       KERN_INFO
-                                       "%s: v4l_fbuffer_alloc() - using %d KB high memory\n",
-                                       ZR_DEVNAME(zr), size >> 10);
-                       } else {
-                               fh->v4l_buffers.buffer[i].fbuffer = NULL;
-                               fh->v4l_buffers.buffer[i].fbuffer_phys =
-                                   pmem + i * fh->v4l_buffers.buffer_size;
-                               fh->v4l_buffers.buffer[i].fbuffer_bus =
-                                   pmem + i * fh->v4l_buffers.buffer_size;
-                       }
-               }
-       }
-
-       fh->v4l_buffers.allocated = 1;
-
-       return 0;
-}
-
-/* free the V4L grab buffers */
-static void
-v4l_fbuffer_free (struct file *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int i, off;
-       unsigned char *mem;
-
-       dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr));
-
-       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-               if (!fh->v4l_buffers.buffer[i].fbuffer)
-                       continue;
-
-               if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-                       mem = fh->v4l_buffers.buffer[i].fbuffer;
-                       for (off = 0; off < fh->v4l_buffers.buffer_size;
-                            off += PAGE_SIZE)
-                               ClearPageReserved(MAP_NR(mem + off));
-                       kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
-               }
-               fh->v4l_buffers.buffer[i].fbuffer = NULL;
-       }
-
-       fh->v4l_buffers.allocated = 0;
-       fh->v4l_buffers.ready_to_be_freed = 0;
-}
-
-/*
- *   Allocate the MJPEG grab buffers.
- *
- *   If the requested buffer size is smaller than MAX_KMALLOC_MEM,
- *   kmalloc is used to request a physically contiguous area,
- *   else we allocate the memory in framgents with get_zeroed_page.
- *
- *   If a Natoma chipset is present and this is a revision 1 zr36057,
- *   each MJPEG buffer needs to be physically contiguous.
- *   (RJ: This statement is from Dave Perks' original driver,
- *   I could never check it because I have a zr36067)
- *   The driver cares about this because it reduces the buffer
- *   size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation).
- *
- *   RJ: The contents grab buffers needs never be accessed in the driver.
- *       Therefore there is no need to allocate them with vmalloc in order
- *       to get a contiguous virtual memory space.
- *       I don't understand why many other drivers first allocate them with
- *       vmalloc (which uses internally also get_zeroed_page, but delivers you
- *       virtual addresses) and then again have to make a lot of efforts
- *       to get the physical address.
- *
- *   Ben Capper:
- *       On big-endian architectures (such as ppc) some extra steps
- *       are needed. When reading and writing to the stat_com array
- *       and fragment buffers, the device expects to see little-
- *       endian values. The use of cpu_to_le32() and le32_to_cpu()
- *       in this function (and one or two others in zoran_device.c)
- *       ensure that these values are always stored in little-endian
- *       form, regardless of architecture. The zr36057 does Very Bad
- *       Things on big endian architectures if the stat_com array
- *       and fragment buffers are not little-endian.
- */
-
-static int
-jpg_fbuffer_alloc (struct file *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int i, j, off;
-       unsigned long mem;
-
-       /* we might have old buffers lying around */
-       if (fh->jpg_buffers.ready_to_be_freed) {
-               jpg_fbuffer_free(file);
-       }
-
-       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-               if (fh->jpg_buffers.buffer[i].frag_tab)
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n",
-                               ZR_DEVNAME(zr), i);
-
-               /* Allocate fragment table for this buffer */
-
-               mem = get_zeroed_page(GFP_KERNEL);
-               if (mem == 0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n",
-                               ZR_DEVNAME(zr), i);
-                       jpg_fbuffer_free(file);
-                       return -ENOBUFS;
-               }
-               fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem;
-               fh->jpg_buffers.buffer[i].frag_tab_bus =
-                   virt_to_bus((void *) mem);
-
-               //if (alloc_contig) {
-               if (fh->jpg_buffers.need_contiguous) {
-                       mem =
-                           (unsigned long) kmalloc(fh->jpg_buffers.
-                                                   buffer_size,
-                                                   GFP_KERNEL);
-                       if (mem == 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n",
-                                       ZR_DEVNAME(zr), i);
-                               jpg_fbuffer_free(file);
-                               return -ENOBUFS;
-                       }
-                       fh->jpg_buffers.buffer[i].frag_tab[0] =
-                           cpu_to_le32(virt_to_bus((void *) mem));
-                       fh->jpg_buffers.buffer[i].frag_tab[1] =
-                           cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);
-                       for (off = 0; off < fh->jpg_buffers.buffer_size;
-                            off += PAGE_SIZE)
-                               SetPageReserved(MAP_NR(mem + off));
-               } else {
-                       /* jpg_bufsize is allreay page aligned */
-                       for (j = 0;
-                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-                            j++) {
-                               mem = get_zeroed_page(GFP_KERNEL);
-                               if (mem == 0) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n",
-                                               ZR_DEVNAME(zr), i);
-                                       jpg_fbuffer_free(file);
-                                       return -ENOBUFS;
-                               }
-
-                               fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-                                   cpu_to_le32(virt_to_bus((void *) mem));
-                               fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-                                                                  1] =
-                                   cpu_to_le32((PAGE_SIZE / 4) << 1);
-                               SetPageReserved(MAP_NR(mem));
-                       }
-
-                       fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);
-               }
-       }
-
-       dprintk(4,
-               KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n",
-               ZR_DEVNAME(zr),
-               (fh->jpg_buffers.num_buffers *
-                fh->jpg_buffers.buffer_size) >> 10);
-
-       fh->jpg_buffers.allocated = 1;
-
-       return 0;
-}
-
-/* free the MJPEG grab buffers */
-static void
-jpg_fbuffer_free (struct file *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int i, j, off;
-       unsigned char *mem;
-
-       dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));
-
-       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-               if (!fh->jpg_buffers.buffer[i].frag_tab)
-                       continue;
-
-               //if (alloc_contig) {
-               if (fh->jpg_buffers.need_contiguous) {
-                       if (fh->jpg_buffers.buffer[i].frag_tab[0]) {
-                               mem = (unsigned char *) bus_to_virt(le32_to_cpu(
-                                       fh->jpg_buffers.buffer[i].frag_tab[0]));
-                               for (off = 0;
-                                    off < fh->jpg_buffers.buffer_size;
-                                    off += PAGE_SIZE)
-                                       ClearPageReserved(MAP_NR
-                                                         (mem + off));
-                               kfree(mem);
-                               fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
-                               fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
-                       }
-               } else {
-                       for (j = 0;
-                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-                            j++) {
-                               if (!fh->jpg_buffers.buffer[i].
-                                   frag_tab[2 * j])
-                                       break;
-                               ClearPageReserved(MAP_NR
-                                                 (bus_to_virt
-                                                  (le32_to_cpu
-                                                   (fh->jpg_buffers.
-                                                    buffer[i].frag_tab[2 *
-                                                                      j]))));
-                               free_page((unsigned long)
-                                         bus_to_virt
-                                                 (le32_to_cpu
-                                                  (fh->jpg_buffers.
-                                                     buffer[i].
-                                                     frag_tab[2 * j])));
-                               fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-                                   0;
-                               fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-                                                                  1] = 0;
-                       }
-               }
-
-               free_page((unsigned long) fh->jpg_buffers.buffer[i].
-                         frag_tab);
-               fh->jpg_buffers.buffer[i].frag_tab = NULL;
-       }
-
-       fh->jpg_buffers.allocated = 0;
-       fh->jpg_buffers.ready_to_be_freed = 0;
-}
-
-/*
- *   V4L Buffer grabbing
- */
-
-static int
-zoran_v4l_set_format (struct file               *file,
-                     int                        width,
-                     int                        height,
-                     const struct zoran_format *format)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int bpp;
-
-       /* Check size and format of the grab wanted */
-
-       if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
-           height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_set_format() - wrong frame size (%dx%d)\n",
-                       ZR_DEVNAME(zr), width, height);
-               return -EINVAL;
-       }
-
-       bpp = (format->depth + 7) / 8;
-
-       /* Check against available buffer size */
-       if (height * width * bpp > fh->v4l_buffers.buffer_size) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_set_format() - video buffer size (%d kB) is too small\n",
-                       ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10);
-               return -EINVAL;
-       }
-
-       /* The video front end needs 4-byte alinged line sizes */
-
-       if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_set_format() - wrong frame alingment\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       fh->v4l_settings.width = width;
-       fh->v4l_settings.height = height;
-       fh->v4l_settings.format = format;
-       fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width;
-
-       return 0;
-}
-
-static int
-zoran_v4l_queue_frame (struct file *file,
-                      int          num)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int res = 0;
-
-       if (!fh->v4l_buffers.allocated) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_queue_frame() - buffers not yet allocated\n",
-                       ZR_DEVNAME(zr));
-               res = -ENOMEM;
-       }
-
-       /* No grabbing outside the buffer range! */
-       if (num >= fh->v4l_buffers.num_buffers || num < 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_queue_frame() - buffer %d is out of range\n",
-                       ZR_DEVNAME(zr), num);
-               res = -EINVAL;
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (fh->v4l_buffers.active == ZORAN_FREE) {
-               if (zr->v4l_buffers.active == ZORAN_FREE) {
-                       zr->v4l_buffers = fh->v4l_buffers;
-                       fh->v4l_buffers.active = ZORAN_ACTIVE;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: v4l_queue_frame() - another session is already capturing\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-               }
-       }
-
-       /* make sure a grab isn't going on currently with this buffer */
-       if (!res) {
-               switch (zr->v4l_buffers.buffer[num].state) {
-               default:
-               case BUZ_STATE_PEND:
-                       if (zr->v4l_buffers.active == ZORAN_FREE) {
-                               fh->v4l_buffers.active = ZORAN_FREE;
-                               zr->v4l_buffers.allocated = 0;
-                       }
-                       res = -EBUSY;   /* what are you doing? */
-                       break;
-               case BUZ_STATE_DONE:
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n",
-                               ZR_DEVNAME(zr), num);
-               case BUZ_STATE_USER:
-                       /* since there is at least one unused buffer there's room for at least
-                        * one more pend[] entry */
-                       zr->v4l_pend[zr->v4l_pend_head++ &
-                                       V4L_MASK_FRAME] = num;
-                       zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
-                       zr->v4l_buffers.buffer[num].bs.length =
-                           fh->v4l_settings.bytesperline *
-                           zr->v4l_settings.height;
-                       fh->v4l_buffers.buffer[num] =
-                           zr->v4l_buffers.buffer[num];
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       if (!res && zr->v4l_buffers.active == ZORAN_FREE)
-               zr->v4l_buffers.active = fh->v4l_buffers.active;
-
-       return res;
-}
-
-static int
-v4l_grab (struct file       *file,
-         struct video_mmap *mp)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int res = 0, i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (zoran_formats[i].palette == mp->format &&
-                   zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&
-                   !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))
-                       break;
-       }
-       if (i == NUM_FORMATS || zoran_formats[i].depth == 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_grab() - wrong bytes-per-pixel format\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       /*
-        * To minimize the time spent in the IRQ routine, we avoid setting up
-        * the video front end there.
-        * If this grab has different parameters from a running streaming capture
-        * we stop the streaming capture and start it over again.
-        */
-       if (zr->v4l_memgrab_active &&
-           (zr->v4l_settings.width != mp->width ||
-            zr->v4l_settings.height != mp->height ||
-            zr->v4l_settings.format->palette != mp->format)) {
-               res = wait_grab_pending(zr);
-               if (res)
-                       return res;
-       }
-       if ((res = zoran_v4l_set_format(file,
-                                       mp->width,
-                                       mp->height,
-                                       &zoran_formats[i])))
-               return res;
-       zr->v4l_settings = fh->v4l_settings;
-
-       /* queue the frame in the pending queue */
-       if ((res = zoran_v4l_queue_frame(file, mp->frame))) {
-               fh->v4l_buffers.active = ZORAN_FREE;
-               return res;
-       }
-
-       /* put the 36057 into frame grabbing mode */
-       if (!res && !zr->v4l_memgrab_active)
-               zr36057_set_memgrab(zr, 1);
-
-       //dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr));
-
-       return res;
-}
-
-/*
- * Sync on a V4L buffer
- */
-
-static int
-v4l_sync (struct file *file,
-         int          frame)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-
-       if (fh->v4l_buffers.active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_sync() - no grab active for this session\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       /* check passed-in frame number */
-       if (frame >= fh->v4l_buffers.num_buffers || frame < 0) {
-               dprintk(1,
-                       KERN_ERR "%s: v4l_sync() - frame %d is invalid\n",
-                       ZR_DEVNAME(zr), frame);
-               return -EINVAL;
-       }
-
-       /* Check if is buffer was queued at all */
-       if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n",
-                       ZR_DEVNAME(zr));
-               return -EPROTO;
-       }
-
-       /* wait on this buffer to get ready */
-       if (!wait_event_interruptible_timeout(zr->v4l_capq,
-                               (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),
-                               10*HZ))
-               return -ETIME;
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       /* buffer should now be in BUZ_STATE_DONE */
-       if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
-               dprintk(2,
-                       KERN_ERR "%s: v4l_sync() - internal state error\n",
-                       ZR_DEVNAME(zr));
-
-       zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
-       fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       /* Check if streaming capture has finished */
-       if (zr->v4l_pend_tail == zr->v4l_pend_head) {
-               zr36057_set_memgrab(zr, 0);
-               if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
-                       fh->v4l_buffers.active = zr->v4l_buffers.active =
-                           ZORAN_FREE;
-                       zr->v4l_buffers.allocated = 0;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-/*
- *   Queue a MJPEG buffer for capture/playback
- */
-
-static int
-zoran_jpg_queue_frame (struct file          *file,
-                      int                   num,
-                      enum zoran_codec_mode mode)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int res = 0;
-
-       /* Check if buffers are allocated */
-       if (!fh->jpg_buffers.allocated) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_queue_frame() - buffers not yet allocated\n",
-                       ZR_DEVNAME(zr));
-               return -ENOMEM;
-       }
-
-       /* No grabbing outside the buffer range! */
-       if (num >= fh->jpg_buffers.num_buffers || num < 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_queue_frame() - buffer %d out of range\n",
-                       ZR_DEVNAME(zr), num);
-               return -EINVAL;
-       }
-
-       /* what is the codec mode right now? */
-       if (zr->codec_mode == BUZ_MODE_IDLE) {
-               zr->jpg_settings = fh->jpg_settings;
-       } else if (zr->codec_mode != mode) {
-               /* wrong codec mode active - invalid */
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_queue_frame() - codec in wrong mode\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       if (fh->jpg_buffers.active == ZORAN_FREE) {
-               if (zr->jpg_buffers.active == ZORAN_FREE) {
-                       zr->jpg_buffers = fh->jpg_buffers;
-                       fh->jpg_buffers.active = ZORAN_ACTIVE;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: jpg_queue_frame() - another session is already capturing\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-               }
-       }
-
-       if (!res && zr->codec_mode == BUZ_MODE_IDLE) {
-               /* Ok load up the jpeg codec */
-               zr36057_enable_jpg(zr, mode);
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (!res) {
-               switch (zr->jpg_buffers.buffer[num].state) {
-               case BUZ_STATE_DONE:
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n",
-                               ZR_DEVNAME(zr));
-               case BUZ_STATE_USER:
-                       /* since there is at least one unused buffer there's room for at
-                        *least one more pend[] entry */
-                       zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] =
-                           num;
-                       zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
-                       fh->jpg_buffers.buffer[num] =
-                           zr->jpg_buffers.buffer[num];
-                       zoran_feed_stat_com(zr);
-                       break;
-               default:
-               case BUZ_STATE_DMA:
-               case BUZ_STATE_PEND:
-                       if (zr->jpg_buffers.active == ZORAN_FREE) {
-                               fh->jpg_buffers.active = ZORAN_FREE;
-                               zr->jpg_buffers.allocated = 0;
-                       }
-                       res = -EBUSY;   /* what are you doing? */
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       if (!res && zr->jpg_buffers.active == ZORAN_FREE) {
-               zr->jpg_buffers.active = fh->jpg_buffers.active;
-       }
-
-       return res;
-}
-
-static int
-jpg_qbuf (struct file          *file,
-         int                   frame,
-         enum zoran_codec_mode mode)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-
-       /* Does the user want to stop streaming? */
-       if (frame < 0) {
-               if (zr->codec_mode == mode) {
-                       if (fh->jpg_buffers.active == ZORAN_FREE) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: jpg_qbuf(-1) - session not active\n",
-                                       ZR_DEVNAME(zr));
-                               return -EINVAL;
-                       }
-                       fh->jpg_buffers.active = zr->jpg_buffers.active =
-                           ZORAN_FREE;
-                       zr->jpg_buffers.allocated = 0;
-                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-                       return 0;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: jpg_qbuf() - stop streaming but not in streaming mode\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-       }
-
-       if ((res = zoran_jpg_queue_frame(file, frame, mode)))
-               return res;
-
-       /* Start the jpeg codec when the first frame is queued  */
-       if (!res && zr->jpg_que_head == 1)
-               jpeg_start(zr);
-
-       return res;
-}
-
-/*
- *   Sync on a MJPEG buffer
- */
-
-static int
-jpg_sync (struct file       *file,
-         struct zoran_sync *bs)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int frame;
-
-       if (fh->jpg_buffers.active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_sync() - capture is not currently active\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-       if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
-           zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_sync() - codec not in streaming mode\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-       if (!wait_event_interruptible_timeout(zr->jpg_capq,
-                       (zr->jpg_que_tail != zr->jpg_dma_tail ||
-                        zr->jpg_dma_tail == zr->jpg_dma_head),
-                       10*HZ)) {
-               int isr;
-
-               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
-               udelay(1);
-               zr->codec->control(zr->codec, CODEC_G_STATUS,
-                                          sizeof(isr), &isr);
-               dprintk(1,
-                       KERN_ERR
-                       "%s: jpg_sync() - timeout: codec isr=0x%02x\n",
-                       ZR_DEVNAME(zr), isr);
-
-               return -ETIME;
-
-       }
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (zr->jpg_dma_tail != zr->jpg_dma_head)
-               frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
-       else
-               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
-       /* buffer should now be in BUZ_STATE_DONE */
-       if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
-               dprintk(2,
-                       KERN_ERR "%s: jpg_sync() - internal state error\n",
-                       ZR_DEVNAME(zr));
-
-       *bs = zr->jpg_buffers.buffer[frame].bs;
-       bs->frame = frame;
-       zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
-       fh->jpg_buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-static void
-zoran_open_init_session (struct file *file)
-{
-       int i;
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       /* Per default, map the V4L Buffers */
-       fh->map_mode = ZORAN_MAP_MODE_RAW;
-
-       /* take over the card's current settings */
-       fh->overlay_settings = zr->overlay_settings;
-       fh->overlay_settings.is_set = 0;
-       fh->overlay_settings.format = zr->overlay_settings.format;
-       fh->overlay_active = ZORAN_FREE;
-
-       /* v4l settings */
-       fh->v4l_settings = zr->v4l_settings;
-
-       /* v4l_buffers */
-       memset(&fh->v4l_buffers, 0, sizeof(struct zoran_v4l_struct));
-       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-               fh->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-               fh->v4l_buffers.buffer[i].bs.frame = i;
-       }
-       fh->v4l_buffers.allocated = 0;
-       fh->v4l_buffers.ready_to_be_freed = 0;
-       fh->v4l_buffers.active = ZORAN_FREE;
-       fh->v4l_buffers.buffer_size = v4l_bufsize;
-       fh->v4l_buffers.num_buffers = v4l_nbufs;
-
-       /* jpg settings */
-       fh->jpg_settings = zr->jpg_settings;
-
-       /* jpg_buffers */
-       memset(&fh->jpg_buffers, 0, sizeof(struct zoran_jpg_struct));
-       for (i = 0; i < BUZ_MAX_FRAME; i++) {
-               fh->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-               fh->jpg_buffers.buffer[i].bs.frame = i;
-       }
-       fh->jpg_buffers.need_contiguous = zr->jpg_buffers.need_contiguous;
-       fh->jpg_buffers.allocated = 0;
-       fh->jpg_buffers.ready_to_be_freed = 0;
-       fh->jpg_buffers.active = ZORAN_FREE;
-       fh->jpg_buffers.buffer_size = jpg_bufsize;
-       fh->jpg_buffers.num_buffers = jpg_nbufs;
-}
-
-static void
-zoran_close_end_session (struct file *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       /* overlay */
-       if (fh->overlay_active != ZORAN_FREE) {
-               fh->overlay_active = zr->overlay_active = ZORAN_FREE;
-               zr->v4l_overlay_active = 0;
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-       }
-
-       /* v4l capture */
-       if (fh->v4l_buffers.active != ZORAN_FREE) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               zr36057_set_memgrab(zr, 0);
-               zr->v4l_buffers.allocated = 0;
-               zr->v4l_buffers.active = fh->v4l_buffers.active =
-                   ZORAN_FREE;
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-       }
-
-       /* v4l buffers */
-       if (fh->v4l_buffers.allocated ||
-           fh->v4l_buffers.ready_to_be_freed) {
-               v4l_fbuffer_free(file);
-       }
-
-       /* jpg capture */
-       if (fh->jpg_buffers.active != ZORAN_FREE) {
-               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-               zr->jpg_buffers.allocated = 0;
-               zr->jpg_buffers.active = fh->jpg_buffers.active =
-                   ZORAN_FREE;
-       }
-
-       /* jpg buffers */
-       if (fh->jpg_buffers.allocated ||
-           fh->jpg_buffers.ready_to_be_freed) {
-               jpg_fbuffer_free(file);
-       }
-}
-
-/*
- *   Open a zoran card. Right now the flags stuff is just playing
- */
-
-static int
-zoran_open (struct inode *inode,
-           struct file  *file)
-{
-       unsigned int minor = iminor(inode);
-       struct zoran *zr = NULL;
-       struct zoran_fh *fh;
-       int i, res, first_open = 0, have_module_locks = 0;
-
-       /* find the device */
-       for (i = 0; i < zoran_num; i++) {
-               if (zoran[i]->video_dev->minor == minor) {
-                       zr = zoran[i];
-                       break;
-               }
-       }
-
-       if (!zr) {
-               dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME);
-               res = -ENODEV;
-               goto open_unlock_and_return;
-       }
-
-       /* see fs/device.c - the kernel already locks during open(),
-        * so locking ourselves only causes deadlocks */
-       /*mutex_lock(&zr->resource_lock);*/
-
-       if (!zr->decoder) {
-               dprintk(1,
-                       KERN_ERR "%s: no TV decoder loaded for device!\n",
-                       ZR_DEVNAME(zr));
-               res = -EIO;
-               goto open_unlock_and_return;
-       }
-
-       /* try to grab a module lock */
-       if (!try_module_get(THIS_MODULE)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: failed to acquire my own lock! PANIC!\n",
-                       ZR_DEVNAME(zr));
-               res = -ENODEV;
-               goto open_unlock_and_return;
-       }
-       if (!try_module_get(zr->decoder->driver->driver.owner)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: failed to grab ownership of i2c decoder\n",
-                       ZR_DEVNAME(zr));
-               res = -EIO;
-               module_put(THIS_MODULE);
-               goto open_unlock_and_return;
-       }
-       if (zr->encoder &&
-           !try_module_get(zr->encoder->driver->driver.owner)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: failed to grab ownership of i2c encoder\n",
-                       ZR_DEVNAME(zr));
-               res = -EIO;
-               module_put(zr->decoder->driver->driver.owner);
-               module_put(THIS_MODULE);
-               goto open_unlock_and_return;
-       }
-
-       have_module_locks = 1;
-
-       if (zr->user >= 2048) {
-               dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
-                       ZR_DEVNAME(zr), zr->user);
-               res = -EBUSY;
-               goto open_unlock_and_return;
-       }
-
-       dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
-               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
-
-       /* now, create the open()-specific file_ops struct */
-       fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
-       if (!fh) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_open() - allocation of zoran_fh failed\n",
-                       ZR_DEVNAME(zr));
-               res = -ENOMEM;
-               goto open_unlock_and_return;
-       }
-       /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
-        * on norm-change! */
-       fh->overlay_mask =
-           kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
-       if (!fh->overlay_mask) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_open() - allocation of overlay_mask failed\n",
-                       ZR_DEVNAME(zr));
-               kfree(fh);
-               res = -ENOMEM;
-               goto open_unlock_and_return;
-       }
-
-       if (zr->user++ == 0)
-               first_open = 1;
-
-       /*mutex_unlock(&zr->resource_lock);*/
-
-       /* default setup - TODO: look at flags */
-       if (first_open) {       /* First device open */
-               zr36057_restart(zr);
-               zoran_open_init_params(zr);
-               zoran_init_hardware(zr);
-
-               btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
-       }
-
-       /* set file_ops stuff */
-       file->private_data = fh;
-       fh->zr = zr;
-       zoran_open_init_session(file);
-
-       return 0;
-
-open_unlock_and_return:
-       /* if we grabbed locks, release them accordingly */
-       if (have_module_locks) {
-               module_put(zr->decoder->driver->driver.owner);
-               if (zr->encoder) {
-                       module_put(zr->encoder->driver->driver.owner);
-               }
-               module_put(THIS_MODULE);
-       }
-
-       /* if there's no device found, we didn't obtain the lock either */
-       if (zr) {
-               /*mutex_unlock(&zr->resource_lock);*/
-       }
-
-       return res;
-}
-
-static int
-zoran_close (struct inode *inode,
-            struct file  *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
-               ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
-
-       /* kernel locks (fs/device.c), so don't do that ourselves
-        * (prevents deadlocks) */
-       /*mutex_lock(&zr->resource_lock);*/
-
-       zoran_close_end_session(file);
-
-       if (zr->user-- == 1) {  /* Last process */
-               /* Clean up JPEG process */
-               wake_up_interruptible(&zr->jpg_capq);
-               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-               zr->jpg_buffers.allocated = 0;
-               zr->jpg_buffers.active = ZORAN_FREE;
-
-               /* disable interrupts */
-               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-
-               if (zr36067_debug > 1)
-                       print_interrupts(zr);
-
-               /* Overlay off */
-               zr->v4l_overlay_active = 0;
-               zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-
-               /* capture off */
-               wake_up_interruptible(&zr->v4l_capq);
-               zr36057_set_memgrab(zr, 0);
-               zr->v4l_buffers.allocated = 0;
-               zr->v4l_buffers.active = ZORAN_FREE;
-               zoran_set_pci_master(zr, 0);
-
-               if (!pass_through) {    /* Switch to color bar */
-                       int zero = 0, two = 2;
-                       decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
-                       encoder_command(zr, ENCODER_SET_INPUT, &two);
-               }
-       }
-
-       file->private_data = NULL;
-       kfree(fh->overlay_mask);
-       kfree(fh);
-
-       /* release locks on the i2c modules */
-       module_put(zr->decoder->driver->driver.owner);
-       if (zr->encoder) {
-                module_put(zr->encoder->driver->driver.owner);
-       }
-       module_put(THIS_MODULE);
-
-       /*mutex_unlock(&zr->resource_lock);*/
-
-       dprintk(4, KERN_INFO "%s: zoran_close() done\n", ZR_DEVNAME(zr));
-
-       return 0;
-}
-
-
-static ssize_t
-zoran_read (struct file *file,
-           char        __user *data,
-           size_t       count,
-           loff_t      *ppos)
-{
-       /* we simply don't support read() (yet)... */
-
-       return -EINVAL;
-}
-
-static ssize_t
-zoran_write (struct file *file,
-            const char  __user *data,
-            size_t       count,
-            loff_t      *ppos)
-{
-       /* ...and the same goes for write() */
-
-       return -EINVAL;
-}
-
-static int
-setup_fbuffer (struct file               *file,
-              void                      *base,
-              const struct zoran_format *fmt,
-              int                        width,
-              int                        height,
-              int                        bytesperline)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       /* (Ronald) v4l/v4l2 guidelines */
-       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
-          ALi Magik (that needs very low latency while the card needs a
-          higher value always) */
-
-       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
-               return -ENXIO;
-
-       /* we need a bytesperline value, even if not given */
-       if (!bytesperline)
-               bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
-
-#if 0
-       if (zr->overlay_active) {
-               /* dzjee... stupid users... don't even bother to turn off
-                * overlay before changing the memory location...
-                * normally, we would return errors here. However, one of
-                * the tools that does this is... xawtv! and since xawtv
-                * is used by +/- 99% of the users, we'd rather be user-
-                * friendly and silently do as if nothing went wrong */
-               dprintk(3,
-                       KERN_ERR
-                       "%s: setup_fbuffer() - forced overlay turnoff because framebuffer changed\n",
-                       ZR_DEVNAME(zr));
-               zr36057_overlay(zr, 0);
-       }
-#endif
-
-       if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_fbuffer() - no valid overlay format given\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-       if (height <= 0 || width <= 0 || bytesperline <= 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n",
-                       ZR_DEVNAME(zr), width, height, bytesperline);
-               return -EINVAL;
-       }
-       if (bytesperline & 3) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n",
-                       ZR_DEVNAME(zr), bytesperline);
-               return -EINVAL;
-       }
-
-       zr->buffer.base = (void *) ((unsigned long) base & ~3);
-       zr->buffer.height = height;
-       zr->buffer.width = width;
-       zr->buffer.depth = fmt->depth;
-       zr->overlay_settings.format = fmt;
-       zr->buffer.bytesperline = bytesperline;
-
-       /* The user should set new window parameters */
-       zr->overlay_settings.is_set = 0;
-
-       return 0;
-}
-
-
-static int
-setup_window (struct file       *file,
-             int                x,
-             int                y,
-             int                width,
-             int                height,
-             struct video_clip __user *clips,
-             int                clipcount,
-             void              __user *bitmap)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       struct video_clip *vcp = NULL;
-       int on, end;
-
-
-       if (!zr->buffer.base) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_window() - frame buffer has to be set first\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       if (!fh->overlay_settings.format) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_window() - no overlay format set\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       /*
-        * The video front end needs 4-byte alinged line sizes, we correct that
-        * silently here if necessary
-        */
-       if (zr->buffer.depth == 15 || zr->buffer.depth == 16) {
-               end = (x + width) & ~1; /* round down */
-               x = (x + 1) & ~1;       /* round up */
-               width = end - x;
-       }
-
-       if (zr->buffer.depth == 24) {
-               end = (x + width) & ~3; /* round down */
-               x = (x + 3) & ~3;       /* round up */
-               width = end - x;
-       }
-
-       if (width > BUZ_MAX_WIDTH)
-               width = BUZ_MAX_WIDTH;
-       if (height > BUZ_MAX_HEIGHT)
-               height = BUZ_MAX_HEIGHT;
-
-       /* Check for vaild parameters */
-       if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
-           width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_window() - width = %d or height = %d invalid\n",
-                       ZR_DEVNAME(zr), width, height);
-               return -EINVAL;
-       }
-
-       fh->overlay_settings.x = x;
-       fh->overlay_settings.y = y;
-       fh->overlay_settings.width = width;
-       fh->overlay_settings.height = height;
-       fh->overlay_settings.clipcount = clipcount;
-
-       /*
-        * If an overlay is running, we have to switch it off
-        * and switch it on again in order to get the new settings in effect.
-        *
-        * We also want to avoid that the overlay mask is written
-        * when an overlay is running.
-        */
-
-       on = zr->v4l_overlay_active && !zr->v4l_memgrab_active &&
-           zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active != ZORAN_FREE;
-       if (on)
-               zr36057_overlay(zr, 0);
-
-       /*
-        *   Write the overlay mask if clips are wanted.
-        *   We prefer a bitmap.
-        */
-       if (bitmap) {
-               /* fake value - it just means we want clips */
-               fh->overlay_settings.clipcount = 1;
-
-               if (copy_from_user(fh->overlay_mask, bitmap,
-                                  (width * height + 7) / 8)) {
-                       return -EFAULT;
-               }
-       } else if (clipcount > 0) {
-               /* write our own bitmap from the clips */
-               vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4));
-               if (vcp == NULL) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: setup_window() - Alloc of clip mask failed\n",
-                               ZR_DEVNAME(zr));
-                       return -ENOMEM;
-               }
-               if (copy_from_user
-                   (vcp, clips, sizeof(struct video_clip) * clipcount)) {
-                       vfree(vcp);
-                       return -EFAULT;
-               }
-               write_overlay_mask(file, vcp, clipcount);
-               vfree(vcp);
-       }
-
-       fh->overlay_settings.is_set = 1;
-       if (fh->overlay_active != ZORAN_FREE &&
-           zr->overlay_active != ZORAN_FREE)
-               zr->overlay_settings = fh->overlay_settings;
-
-       if (on)
-               zr36057_overlay(zr, 1);
-
-       /* Make sure the changes come into effect */
-       return wait_grab_pending(zr);
-}
-
-static int
-setup_overlay (struct file *file,
-              int          on)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       /* If there is nothing to do, return immediatly */
-       if ((on && fh->overlay_active != ZORAN_FREE) ||
-           (!on && fh->overlay_active == ZORAN_FREE))
-               return 0;
-
-       /* check whether we're touching someone else's overlay */
-       if (on && zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_overlay() - overlay is already active for another session\n",
-                       ZR_DEVNAME(zr));
-               return -EBUSY;
-       }
-       if (!on && zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: setup_overlay() - you cannot cancel someone else's session\n",
-                       ZR_DEVNAME(zr));
-               return -EPERM;
-       }
-
-       if (on == 0) {
-               zr->overlay_active = fh->overlay_active = ZORAN_FREE;
-               zr->v4l_overlay_active = 0;
-               /* When a grab is running, the video simply
-                * won't be switched on any more */
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-       } else {
-               if (!zr->buffer.base || !fh->overlay_settings.is_set) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: setup_overlay() - buffer or window not set\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-               if (!fh->overlay_settings.format) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: setup_overlay() - no overlay format set\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-               zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
-               zr->v4l_overlay_active = 1;
-               zr->overlay_mask = fh->overlay_mask;
-               zr->overlay_settings = fh->overlay_settings;
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 1);
-               /* When a grab is running, the video will be
-                * switched on when grab is finished */
-       }
-
-       /* Make sure the changes come into effect */
-       return wait_grab_pending(zr);
-}
-
-       /* get the status of a buffer in the clients buffer queue */
-static int
-zoran_v4l2_buffer_status (struct file        *file,
-                         struct v4l2_buffer *buf,
-                         int                 num)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-
-               /* check range */
-               if (num < 0 || num >= fh->v4l_buffers.num_buffers ||
-                   !fh->v4l_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-
-               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               buf->length = fh->v4l_buffers.buffer_size;
-
-               /* get buffer */
-               buf->bytesused = fh->v4l_buffers.buffer[num].bs.length;
-               if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE ||
-                   fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) {
-                       buf->sequence = fh->v4l_buffers.buffer[num].bs.seq;
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-                       buf->timestamp =
-                           fh->v4l_buffers.buffer[num].bs.timestamp;
-               } else {
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               }
-
-               if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)
-                       buf->field = V4L2_FIELD_TOP;
-               else
-                       buf->field = V4L2_FIELD_INTERLACED;
-
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-
-               /* check range */
-               if (num < 0 || num >= fh->jpg_buffers.num_buffers ||
-                   !fh->jpg_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-
-               buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
-                             V4L2_BUF_TYPE_VIDEO_CAPTURE :
-                             V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               buf->length = fh->jpg_buffers.buffer_size;
-
-               /* these variables are only written after frame has been captured */
-               if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE ||
-                   fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) {
-                       buf->sequence = fh->jpg_buffers.buffer[num].bs.seq;
-                       buf->timestamp =
-                           fh->jpg_buffers.buffer[num].bs.timestamp;
-                       buf->bytesused =
-                           fh->jpg_buffers.buffer[num].bs.length;
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-               } else {
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               }
-
-               /* which fields are these? */
-               if (fh->jpg_settings.TmpDcm != 1)
-                       buf->field =
-                           fh->jpg_settings.
-                           odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
-               else
-                       buf->field =
-                           fh->jpg_settings.
-                           odd_even ? V4L2_FIELD_SEQ_TB :
-                           V4L2_FIELD_SEQ_BT;
-
-               break;
-
-       default:
-
-               dprintk(5,
-                       KERN_ERR
-                       "%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n",
-                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
-               return -EINVAL;
-       }
-
-       buf->memory = V4L2_MEMORY_MMAP;
-       buf->index = num;
-       buf->m.offset = buf->length * num;
-
-       return 0;
-}
-
-static int
-zoran_set_norm (struct zoran *zr,
-               int           norm) /* VIDEO_MODE_* */
-{
-       int norm_encoder, on;
-
-       if (zr->v4l_buffers.active != ZORAN_FREE ||
-           zr->jpg_buffers.active != ZORAN_FREE) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: set_norm() called while in playback/capture mode\n",
-                       ZR_DEVNAME(zr));
-               return -EBUSY;
-       }
-
-       if (lock_norm && norm != zr->norm) {
-               if (lock_norm > 1) {
-                       dprintk(1,
-                               KERN_WARNING
-                               "%s: set_norm() - TV standard is locked, can not switch norm\n",
-                               ZR_DEVNAME(zr));
-                       return -EPERM;
-               } else {
-                       dprintk(1,
-                               KERN_WARNING
-                               "%s: set_norm() - TV standard is locked, norm was not changed\n",
-                               ZR_DEVNAME(zr));
-                       norm = zr->norm;
-               }
-       }
-
-       if (norm != VIDEO_MODE_AUTO &&
-           (norm < 0 || norm >= zr->card.norms ||
-            !zr->card.tvn[norm])) {
-               dprintk(1,
-                       KERN_ERR "%s: set_norm() - unsupported norm %d\n",
-                       ZR_DEVNAME(zr), norm);
-               return -EINVAL;
-       }
-
-       if (norm == VIDEO_MODE_AUTO) {
-               int status;
-
-               /* if we have autodetect, ... */
-               struct video_decoder_capability caps;
-               decoder_command(zr, DECODER_GET_CAPABILITIES, &caps);
-               if (!(caps.flags & VIDEO_DECODER_AUTO)) {
-                       dprintk(1, KERN_ERR "%s: norm=auto unsupported\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-
-               decoder_command(zr, DECODER_SET_NORM, &norm);
-
-               /* let changes come into effect */
-               ssleep(2);
-
-               decoder_command(zr, DECODER_GET_STATUS, &status);
-               if (!(status & DECODER_STATUS_GOOD)) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: set_norm() - no norm detected\n",
-                               ZR_DEVNAME(zr));
-                       /* reset norm */
-                       decoder_command(zr, DECODER_SET_NORM, &zr->norm);
-                       return -EIO;
-               }
-
-               if (status & DECODER_STATUS_NTSC)
-                       norm = VIDEO_MODE_NTSC;
-               else if (status & DECODER_STATUS_SECAM)
-                       norm = VIDEO_MODE_SECAM;
-               else
-                       norm = VIDEO_MODE_PAL;
-       }
-       zr->timing = zr->card.tvn[norm];
-       norm_encoder = norm;
-
-       /* We switch overlay off and on since a change in the
-        * norm needs different VFE settings */
-       on = zr->overlay_active && !zr->v4l_memgrab_active;
-       if (on)
-               zr36057_overlay(zr, 0);
-
-       decoder_command(zr, DECODER_SET_NORM, &norm);
-       encoder_command(zr, ENCODER_SET_NORM, &norm_encoder);
-
-       if (on)
-               zr36057_overlay(zr, 1);
-
-       /* Make sure the changes come into effect */
-       zr->norm = norm;
-
-       return 0;
-}
-
-static int
-zoran_set_input (struct zoran *zr,
-                int           input)
-{
-       int realinput;
-
-       if (input == zr->input) {
-               return 0;
-       }
-
-       if (zr->v4l_buffers.active != ZORAN_FREE ||
-           zr->jpg_buffers.active != ZORAN_FREE) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: set_input() called while in playback/capture mode\n",
-                       ZR_DEVNAME(zr));
-               return -EBUSY;
-       }
-
-       if (input < 0 || input >= zr->card.inputs) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: set_input() - unnsupported input %d\n",
-                       ZR_DEVNAME(zr), input);
-               return -EINVAL;
-       }
-
-       realinput = zr->card.input[input].muxsel;
-       zr->input = input;
-
-       decoder_command(zr, DECODER_SET_INPUT, &realinput);
-
-       return 0;
-}
-
-/*
- *   ioctl routine
- */
-
-static int
-zoran_do_ioctl (struct inode *inode,
-               struct file  *file,
-               unsigned int  cmd,
-               void         *arg)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       /* CAREFUL: used in multiple places here */
-       struct zoran_jpg_settings settings;
-
-       /* we might have older buffers lying around... We don't want
-        * to wait, but we do want to try cleaning them up ASAP. So
-        * we try to obtain the lock and free them. If that fails, we
-        * don't do anything and wait for the next turn. In the end,
-        * zoran_close() or a new allocation will still free them...
-        * This is just a 'the sooner the better' extra 'feature'
-        *
-        * We don't free the buffers right on munmap() because that
-        * causes oopses (kfree() inside munmap() oopses for no
-        * apparent reason - it's also not reproduceable in any way,
-        * but moving the free code outside the munmap() handler fixes
-        * all this... If someone knows why, please explain me (Ronald)
-        */
-       if (mutex_trylock(&zr->resource_lock)) {
-               /* we obtained it! Let's try to free some things */
-               if (fh->jpg_buffers.ready_to_be_freed)
-                       jpg_fbuffer_free(file);
-               if (fh->v4l_buffers.ready_to_be_freed)
-                       v4l_fbuffer_free(file);
-
-               mutex_unlock(&zr->resource_lock);
-       }
-
-       switch (cmd) {
-
-       case VIDIOCGCAP:
-       {
-               struct video_capability *vcap = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
-
-               memset(vcap, 0, sizeof(struct video_capability));
-               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
-               vcap->type = ZORAN_VID_TYPE;
-
-               vcap->channels = zr->card.inputs;
-               vcap->audios = 0;
-               mutex_lock(&zr->resource_lock);
-               vcap->maxwidth = BUZ_MAX_WIDTH;
-               vcap->maxheight = BUZ_MAX_HEIGHT;
-               vcap->minwidth = BUZ_MIN_WIDTH;
-               vcap->minheight = BUZ_MIN_HEIGHT;
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOCGCHAN:
-       {
-               struct video_channel *vchan = arg;
-               int channel = vchan->channel;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGCHAN - channel=%d\n",
-                       ZR_DEVNAME(zr), vchan->channel);
-
-               memset(vchan, 0, sizeof(struct video_channel));
-               if (channel > zr->card.inputs || channel < 0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOCGCHAN on not existing channel %d\n",
-                               ZR_DEVNAME(zr), channel);
-                       return -EINVAL;
-               }
-
-               strcpy(vchan->name, zr->card.input[channel].name);
-
-               vchan->tuners = 0;
-               vchan->flags = 0;
-               vchan->type = VIDEO_TYPE_CAMERA;
-               mutex_lock(&zr->resource_lock);
-               vchan->norm = zr->norm;
-               mutex_unlock(&zr->resource_lock);
-               vchan->channel = channel;
-
-               return 0;
-       }
-               break;
-
-               /* RJ: the documentation at http://roadrunner.swansea.linux.org.uk/v4lapi.shtml says:
-                *
-                * * "The VIDIOCSCHAN ioctl takes an integer argument and switches the capture to this input."
-                * *                                 ^^^^^^^
-                * * The famos BTTV driver has it implemented with a struct video_channel argument
-                * * and we follow it for compatibility reasons
-                * *
-                * * BTW: this is the only way the user can set the norm!
-                */
-
-       case VIDIOCSCHAN:
-       {
-               struct video_channel *vchan = arg;
-               int res;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOCSCHAN - channel=%d, norm=%d\n",
-                       ZR_DEVNAME(zr), vchan->channel, vchan->norm);
-
-               mutex_lock(&zr->resource_lock);
-               if ((res = zoran_set_input(zr, vchan->channel)))
-                       goto schan_unlock_and_return;
-               if ((res = zoran_set_norm(zr, vchan->norm)))
-                       goto schan_unlock_and_return;
-
-               /* Make sure the changes come into effect */
-               res = wait_grab_pending(zr);
-       schan_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOCGPICT:
-       {
-               struct video_picture *vpict = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGPICT\n", ZR_DEVNAME(zr));
-
-               memset(vpict, 0, sizeof(struct video_picture));
-               mutex_lock(&zr->resource_lock);
-               vpict->hue = zr->hue;
-               vpict->brightness = zr->brightness;
-               vpict->contrast = zr->contrast;
-               vpict->colour = zr->saturation;
-               if (fh->overlay_settings.format) {
-                       vpict->depth = fh->overlay_settings.format->depth;
-                       vpict->palette = fh->overlay_settings.format->palette;
-               } else {
-                       vpict->depth = 0;
-               }
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOCSPICT:
-       {
-               struct video_picture *vpict = arg;
-               int i;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOCSPICT - bri=%d, hue=%d, col=%d, con=%d, dep=%d, pal=%d\n",
-                       ZR_DEVNAME(zr), vpict->brightness, vpict->hue,
-                       vpict->colour, vpict->contrast, vpict->depth,
-                       vpict->palette);
-
-               for (i = 0; i < NUM_FORMATS; i++) {
-                       const struct zoran_format *fmt = &zoran_formats[i];
-
-                       if (fmt->palette != -1 &&
-                           fmt->flags & ZORAN_FORMAT_OVERLAY &&
-                           fmt->palette == vpict->palette &&
-                           fmt->depth == vpict->depth)
-                               break;
-               }
-               if (i == NUM_FORMATS) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOCSPICT - Invalid palette %d\n",
-                               ZR_DEVNAME(zr), vpict->palette);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-
-               decoder_command(zr, DECODER_SET_PICTURE, vpict);
-
-               zr->hue = vpict->hue;
-               zr->contrast = vpict->contrast;
-               zr->saturation = vpict->colour;
-               zr->brightness = vpict->brightness;
-
-               fh->overlay_settings.format = &zoran_formats[i];
-
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOCCAPTURE:
-       {
-               int *on = arg, res;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCCAPTURE - on=%d\n",
-                       ZR_DEVNAME(zr), *on);
-
-               mutex_lock(&zr->resource_lock);
-               res = setup_overlay(file, *on);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOCGWIN:
-       {
-               struct video_window *vwin = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGWIN\n", ZR_DEVNAME(zr));
-
-               memset(vwin, 0, sizeof(struct video_window));
-               mutex_lock(&zr->resource_lock);
-               vwin->x = fh->overlay_settings.x;
-               vwin->y = fh->overlay_settings.y;
-               vwin->width = fh->overlay_settings.width;
-               vwin->height = fh->overlay_settings.height;
-               mutex_unlock(&zr->resource_lock);
-               vwin->clipcount = 0;
-               return 0;
-       }
-               break;
-
-       case VIDIOCSWIN:
-       {
-               struct video_window *vwin = arg;
-               int res;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOCSWIN - x=%d, y=%d, w=%d, h=%d, clipcount=%d\n",
-                       ZR_DEVNAME(zr), vwin->x, vwin->y, vwin->width,
-                       vwin->height, vwin->clipcount);
-
-               mutex_lock(&zr->resource_lock);
-               res =
-                   setup_window(file, vwin->x, vwin->y, vwin->width,
-                                vwin->height, vwin->clips,
-                                vwin->clipcount, NULL);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOCGFBUF:
-       {
-               struct video_buffer *vbuf = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGFBUF\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-               *vbuf = zr->buffer;
-               mutex_unlock(&zr->resource_lock);
-               return 0;
-       }
-               break;
-
-       case VIDIOCSFBUF:
-       {
-               struct video_buffer *vbuf = arg;
-               int i, res = 0;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n",
-                       ZR_DEVNAME(zr), vbuf->base, vbuf->width,
-                       vbuf->height, vbuf->depth, vbuf->bytesperline);
-
-               for (i = 0; i < NUM_FORMATS; i++)
-                       if (zoran_formats[i].depth == vbuf->depth)
-                               break;
-               if (i == NUM_FORMATS) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOCSFBUF - invalid fbuf depth %d\n",
-                               ZR_DEVNAME(zr), vbuf->depth);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-               res =
-                   setup_fbuffer(file, vbuf->base, &zoran_formats[i],
-                                 vbuf->width, vbuf->height,
-                                 vbuf->bytesperline);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOCSYNC:
-       {
-               int *frame = arg, res;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCSYNC - frame=%d\n",
-                       ZR_DEVNAME(zr), *frame);
-
-               mutex_lock(&zr->resource_lock);
-               res = v4l_sync(file, *frame);
-               mutex_unlock(&zr->resource_lock);
-               if (!res)
-                       zr->v4l_sync_tail++;
-               return res;
-       }
-               break;
-
-       case VIDIOCMCAPTURE:
-       {
-               struct video_mmap *vmap = arg;
-               int res;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOCMCAPTURE - frame=%d, geom=%dx%d, fmt=%d\n",
-                       ZR_DEVNAME(zr), vmap->frame, vmap->width, vmap->height,
-                       vmap->format);
-
-               mutex_lock(&zr->resource_lock);
-               res = v4l_grab(file, vmap);
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOCGMBUF:
-       {
-               struct video_mbuf *vmbuf = arg;
-               int i, res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGMBUF\n", ZR_DEVNAME(zr));
-
-               vmbuf->size =
-                   fh->v4l_buffers.num_buffers *
-                   fh->v4l_buffers.buffer_size;
-               vmbuf->frames = fh->v4l_buffers.num_buffers;
-               for (i = 0; i < vmbuf->frames; i++) {
-                       vmbuf->offsets[i] =
-                           i * fh->v4l_buffers.buffer_size;
-               }
-
-               mutex_lock(&zr->resource_lock);
-
-               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOCGMBUF - buffers already allocated\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto v4l1reqbuf_unlock_and_return;
-               }
-
-               if (v4l_fbuffer_alloc(file)) {
-                       res = -ENOMEM;
-                       goto v4l1reqbuf_unlock_and_return;
-               }
-
-               /* The next mmap will map the V4L buffers */
-               fh->map_mode = ZORAN_MAP_MODE_RAW;
-       v4l1reqbuf_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOCGUNIT:
-       {
-               struct video_unit *vunit = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr));
-
-               vunit->video = zr->video_dev->minor;
-               vunit->vbi = VIDEO_NO_UNIT;
-               vunit->radio = VIDEO_NO_UNIT;
-               vunit->audio = VIDEO_NO_UNIT;
-               vunit->teletext = VIDEO_NO_UNIT;
-
-               return 0;
-       }
-               break;
-
-               /*
-                * RJ: In principal we could support subcaptures for V4L grabbing.
-                *     Not even the famous BTTV driver has them, however.
-                *     If there should be a strong demand, one could consider
-                *     to implement them.
-                */
-       case VIDIOCGCAPTURE:
-       {
-               dprintk(3, KERN_ERR "%s: VIDIOCGCAPTURE not supported\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-               break;
-
-       case VIDIOCSCAPTURE:
-       {
-               dprintk(3, KERN_ERR "%s: VIDIOCSCAPTURE not supported\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-               break;
-
-       case BUZIOC_G_PARAMS:
-       {
-               struct zoran_params *bparams = arg;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_G_PARAMS\n", ZR_DEVNAME(zr));
-
-               memset(bparams, 0, sizeof(struct zoran_params));
-               bparams->major_version = MAJOR_VERSION;
-               bparams->minor_version = MINOR_VERSION;
-
-               mutex_lock(&zr->resource_lock);
-
-               bparams->norm = zr->norm;
-               bparams->input = zr->input;
-
-               bparams->decimation = fh->jpg_settings.decimation;
-               bparams->HorDcm = fh->jpg_settings.HorDcm;
-               bparams->VerDcm = fh->jpg_settings.VerDcm;
-               bparams->TmpDcm = fh->jpg_settings.TmpDcm;
-               bparams->field_per_buff = fh->jpg_settings.field_per_buff;
-               bparams->img_x = fh->jpg_settings.img_x;
-               bparams->img_y = fh->jpg_settings.img_y;
-               bparams->img_width = fh->jpg_settings.img_width;
-               bparams->img_height = fh->jpg_settings.img_height;
-               bparams->odd_even = fh->jpg_settings.odd_even;
-
-               bparams->quality = fh->jpg_settings.jpg_comp.quality;
-               bparams->APPn = fh->jpg_settings.jpg_comp.APPn;
-               bparams->APP_len = fh->jpg_settings.jpg_comp.APP_len;
-               memcpy(bparams->APP_data,
-                      fh->jpg_settings.jpg_comp.APP_data,
-                      sizeof(bparams->APP_data));
-               bparams->COM_len = zr->jpg_settings.jpg_comp.COM_len;
-               memcpy(bparams->COM_data,
-                      fh->jpg_settings.jpg_comp.COM_data,
-                      sizeof(bparams->COM_data));
-               bparams->jpeg_markers =
-                   fh->jpg_settings.jpg_comp.jpeg_markers;
-
-               mutex_unlock(&zr->resource_lock);
-
-               bparams->VFIFO_FB = 0;
-
-               return 0;
-       }
-               break;
-
-       case BUZIOC_S_PARAMS:
-       {
-               struct zoran_params *bparams = arg;
-               int res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_S_PARAMS\n", ZR_DEVNAME(zr));
-
-               settings.decimation = bparams->decimation;
-               settings.HorDcm = bparams->HorDcm;
-               settings.VerDcm = bparams->VerDcm;
-               settings.TmpDcm = bparams->TmpDcm;
-               settings.field_per_buff = bparams->field_per_buff;
-               settings.img_x = bparams->img_x;
-               settings.img_y = bparams->img_y;
-               settings.img_width = bparams->img_width;
-               settings.img_height = bparams->img_height;
-               settings.odd_even = bparams->odd_even;
-
-               settings.jpg_comp.quality = bparams->quality;
-               settings.jpg_comp.APPn = bparams->APPn;
-               settings.jpg_comp.APP_len = bparams->APP_len;
-               memcpy(settings.jpg_comp.APP_data, bparams->APP_data,
-                      sizeof(bparams->APP_data));
-               settings.jpg_comp.COM_len = bparams->COM_len;
-               memcpy(settings.jpg_comp.COM_data, bparams->COM_data,
-                      sizeof(bparams->COM_data));
-               settings.jpg_comp.jpeg_markers = bparams->jpeg_markers;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (zr->codec_mode != BUZ_MODE_IDLE) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: BUZIOC_S_PARAMS called, but Buz in capture/playback mode\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto sparams_unlock_and_return;
-               }
-
-               /* Check the params first before overwriting our
-                * nternal values */
-               if (zoran_check_jpg_settings(zr, &settings)) {
-                       res = -EINVAL;
-                       goto sparams_unlock_and_return;
-               }
-
-               fh->jpg_settings = settings;
-       sparams_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case BUZIOC_REQBUFS:
-       {
-               struct zoran_requestbuffers *breq = arg;
-               int res = 0;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: BUZIOC_REQBUFS - count=%lu, size=%lu\n",
-                       ZR_DEVNAME(zr), breq->count, breq->size);
-
-               /* Enforce reasonable lower and upper limits */
-               if (breq->count < 4)
-                       breq->count = 4;        /* Could be choosen smaller */
-               if (breq->count > jpg_nbufs)
-                       breq->count = jpg_nbufs;
-               breq->size = PAGE_ALIGN(breq->size);
-               if (breq->size < 8192)
-                       breq->size = 8192;      /* Arbitrary */
-               /* breq->size is limited by 1 page for the stat_com
-                * tables to a Maximum of 2 MB */
-               if (breq->size > jpg_bufsize)
-                       breq->size = jpg_bufsize;
-               if (fh->jpg_buffers.need_contiguous &&
-                   breq->size > MAX_KMALLOC_MEM)
-                       breq->size = MAX_KMALLOC_MEM;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: BUZIOC_REQBUFS - buffers allready allocated\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-                       goto jpgreqbuf_unlock_and_return;
-               }
-
-               fh->jpg_buffers.num_buffers = breq->count;
-               fh->jpg_buffers.buffer_size = breq->size;
-
-               if (jpg_fbuffer_alloc(file)) {
-                       res = -ENOMEM;
-                       goto jpgreqbuf_unlock_and_return;
-               }
-
-               /* The next mmap will map the MJPEG buffers - could
-                * also be *_PLAY, but it doesn't matter here */
-               fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
-       jpgreqbuf_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case BUZIOC_QBUF_CAPT:
-       {
-               int *frame = arg, res;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_CAPT - frame=%d\n",
-                       ZR_DEVNAME(zr), *frame);
-
-               mutex_lock(&zr->resource_lock);
-               res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_COMPRESS);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case BUZIOC_QBUF_PLAY:
-       {
-               int *frame = arg, res;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_QBUF_PLAY - frame=%d\n",
-                       ZR_DEVNAME(zr), *frame);
-
-               mutex_lock(&zr->resource_lock);
-               res = jpg_qbuf(file, *frame, BUZ_MODE_MOTION_DECOMPRESS);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case BUZIOC_SYNC:
-       {
-               struct zoran_sync *bsync = arg;
-               int res;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_SYNC\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-               res = jpg_sync(file, bsync);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case BUZIOC_G_STATUS:
-       {
-               struct zoran_status *bstat = arg;
-               int norm, input, status, res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr));
-
-               if (zr->codec_mode != BUZ_MODE_IDLE) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: BUZIOC_G_STATUS called but Buz in capture/playback mode\n",
-                               ZR_DEVNAME(zr));
-                       return -EINVAL;
-               }
-
-               input = zr->card.input[bstat->input].muxsel;
-               norm = VIDEO_MODE_AUTO;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (zr->codec_mode != BUZ_MODE_IDLE) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: BUZIOC_G_STATUS called, but Buz in capture/playback mode\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto gstat_unlock_and_return;
-               }
-
-               decoder_command(zr, DECODER_SET_INPUT, &input);
-               decoder_command(zr, DECODER_SET_NORM, &norm);
-
-               /* sleep 1 second */
-               ssleep(1);
-
-               /* Get status of video decoder */
-               decoder_command(zr, DECODER_GET_STATUS, &status);
-
-               /* restore previous input and norm */
-               input = zr->card.input[zr->input].muxsel;
-               decoder_command(zr, DECODER_SET_INPUT, &input);
-               decoder_command(zr, DECODER_SET_NORM, &zr->norm);
-       gstat_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               if (!res) {
-                       bstat->signal =
-                           (status & DECODER_STATUS_GOOD) ? 1 : 0;
-                       if (status & DECODER_STATUS_NTSC)
-                               bstat->norm = VIDEO_MODE_NTSC;
-                       else if (status & DECODER_STATUS_SECAM)
-                               bstat->norm = VIDEO_MODE_SECAM;
-                       else
-                               bstat->norm = VIDEO_MODE_PAL;
-
-                       bstat->color =
-                           (status & DECODER_STATUS_COLOR) ? 1 : 0;
-               }
-
-               return res;
-       }
-               break;
-
-               /* The new video4linux2 capture interface - much nicer than video4linux1, since
-                * it allows for integrating the JPEG capturing calls inside standard v4l2
-                */
-
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
-
-               memset(cap, 0, sizeof(*cap));
-               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
-               strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
-               snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-                        pci_name(zr->pci_dev));
-               cap->version =
-                   KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
-                                  RELEASE_VERSION);
-               cap->capabilities = ZORAN_V4L2_VID_FLAGS;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *fmt = arg;
-               int index = fmt->index, num = -1, i, flag = 0, type =
-                   fmt->type;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUM_FMT - index=%d\n",
-                       ZR_DEVNAME(zr), fmt->index);
-
-               switch (fmt->type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       flag = ZORAN_FORMAT_CAPTURE;
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       flag = ZORAN_FORMAT_PLAYBACK;
-                       break;
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       flag = ZORAN_FORMAT_OVERLAY;
-                       break;
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_ENUM_FMT - unknown type %d\n",
-                               ZR_DEVNAME(zr), fmt->type);
-                       return -EINVAL;
-               }
-
-               for (i = 0; i < NUM_FORMATS; i++) {
-                       if (zoran_formats[i].flags & flag)
-                               num++;
-                       if (num == fmt->index)
-                               break;
-               }
-               if (fmt->index < 0 /* late, but not too late */  ||
-                   i == NUM_FORMATS)
-                       return -EINVAL;
-
-               memset(fmt, 0, sizeof(*fmt));
-               fmt->index = index;
-               fmt->type = type;
-               strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
-               fmt->pixelformat = zoran_formats[i].fourcc;
-               if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
-                       fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *fmt = arg;
-               int type = fmt->type;
-
-               dprintk(5, KERN_DEBUG "%s: VIDIOC_G_FMT\n", ZR_DEVNAME(zr));
-
-               memset(fmt, 0, sizeof(*fmt));
-               fmt->type = type;
-
-               switch (fmt->type) {
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-
-                       mutex_lock(&zr->resource_lock);
-
-                       fmt->fmt.win.w.left = fh->overlay_settings.x;
-                       fmt->fmt.win.w.top = fh->overlay_settings.y;
-                       fmt->fmt.win.w.width = fh->overlay_settings.width;
-                       fmt->fmt.win.w.height =
-                           fh->overlay_settings.height;
-                       if (fh->overlay_settings.width * 2 >
-                           BUZ_MAX_HEIGHT)
-                               fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
-                       else
-                               fmt->fmt.win.field = V4L2_FIELD_TOP;
-
-                       mutex_unlock(&zr->resource_lock);
-
-                       break;
-
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-
-                       mutex_lock(&zr->resource_lock);
-
-                       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-                           fh->map_mode == ZORAN_MAP_MODE_RAW) {
-
-                               fmt->fmt.pix.width =
-                                   fh->v4l_settings.width;
-                               fmt->fmt.pix.height =
-                                   fh->v4l_settings.height;
-                               fmt->fmt.pix.sizeimage =
-                                   fh->v4l_settings.bytesperline *
-                                   fh->v4l_settings.height;
-                               fmt->fmt.pix.pixelformat =
-                                   fh->v4l_settings.format->fourcc;
-                               fmt->fmt.pix.colorspace =
-                                   fh->v4l_settings.format->colorspace;
-                               fmt->fmt.pix.bytesperline =
-                                   fh->v4l_settings.bytesperline;
-                               if (BUZ_MAX_HEIGHT <
-                                   (fh->v4l_settings.height * 2))
-                                       fmt->fmt.pix.field =
-                                           V4L2_FIELD_INTERLACED;
-                               else
-                                       fmt->fmt.pix.field =
-                                           V4L2_FIELD_TOP;
-
-                       } else {
-
-                               fmt->fmt.pix.width =
-                                   fh->jpg_settings.img_width /
-                                   fh->jpg_settings.HorDcm;
-                               fmt->fmt.pix.height =
-                                   fh->jpg_settings.img_height /
-                                   (fh->jpg_settings.VerDcm *
-                                    fh->jpg_settings.TmpDcm);
-                               fmt->fmt.pix.sizeimage =
-                                   zoran_v4l2_calc_bufsize(&fh->
-                                                           jpg_settings);
-                               fmt->fmt.pix.pixelformat =
-                                   V4L2_PIX_FMT_MJPEG;
-                               if (fh->jpg_settings.TmpDcm == 1)
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_SEQ_BT :
-                                            V4L2_FIELD_SEQ_BT);
-                               else
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_TOP :
-                                            V4L2_FIELD_BOTTOM);
-
-                               fmt->fmt.pix.bytesperline = 0;
-                               fmt->fmt.pix.colorspace =
-                                   V4L2_COLORSPACE_SMPTE170M;
-                       }
-
-                       mutex_unlock(&zr->resource_lock);
-
-                       break;
-
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_G_FMT - unsupported type %d\n",
-                               ZR_DEVNAME(zr), fmt->type);
-                       return -EINVAL;
-               }
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *fmt = arg;
-               int i, res = 0;
-               __le32 printformat;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ",
-                       ZR_DEVNAME(zr), fmt->type);
-
-               switch (fmt->type) {
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-
-                       dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
-                               fmt->fmt.win.w.left, fmt->fmt.win.w.top,
-                               fmt->fmt.win.w.width,
-                               fmt->fmt.win.w.height,
-                               fmt->fmt.win.clipcount,
-                               fmt->fmt.win.bitmap);
-                       mutex_lock(&zr->resource_lock);
-                       res =
-                           setup_window(file, fmt->fmt.win.w.left,
-                                        fmt->fmt.win.w.top,
-                                        fmt->fmt.win.w.width,
-                                        fmt->fmt.win.w.height,
-                                        (struct video_clip __user *)
-                                          fmt->fmt.win.clips,
-                                        fmt->fmt.win.clipcount,
-                                        fmt->fmt.win.bitmap);
-                       mutex_unlock(&zr->resource_lock);
-                       return res;
-                       break;
-
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-
-                       printformat =
-                           __cpu_to_le32(fmt->fmt.pix.pixelformat);
-                       dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
-                               fmt->fmt.pix.width, fmt->fmt.pix.height,
-                               fmt->fmt.pix.pixelformat,
-                               (char *) &printformat);
-
-                       /* we can be requested to do JPEG/raw playback/capture */
-                       if (!
-                           (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                            (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-                             fmt->fmt.pix.pixelformat ==
-                             V4L2_PIX_FMT_MJPEG))) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: VIDIOC_S_FMT - unknown type %d/0x%x(%4.4s) combination\n",
-                                       ZR_DEVNAME(zr), fmt->type,
-                                       fmt->fmt.pix.pixelformat,
-                                       (char *) &printformat);
-                               return -EINVAL;
-                       }
-
-                       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
-                               mutex_lock(&zr->resource_lock);
-
-                               settings = fh->jpg_settings;
-
-                               if (fh->v4l_buffers.allocated ||
-                                   fh->jpg_buffers.allocated) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: VIDIOC_S_FMT - cannot change capture mode\n",
-                                               ZR_DEVNAME(zr));
-                                       res = -EBUSY;
-                                       goto sfmtjpg_unlock_and_return;
-                               }
-
-                               /* we actually need to set 'real' parameters now */
-                               if ((fmt->fmt.pix.height * 2) >
-                                   BUZ_MAX_HEIGHT)
-                                       settings.TmpDcm = 1;
-                               else
-                                       settings.TmpDcm = 2;
-                               settings.decimation = 0;
-                               if (fmt->fmt.pix.height <=
-                                   fh->jpg_settings.img_height / 2)
-                                       settings.VerDcm = 2;
-                               else
-                                       settings.VerDcm = 1;
-                               if (fmt->fmt.pix.width <=
-                                   fh->jpg_settings.img_width / 4)
-                                       settings.HorDcm = 4;
-                               else if (fmt->fmt.pix.width <=
-                                        fh->jpg_settings.img_width / 2)
-                                       settings.HorDcm = 2;
-                               else
-                                       settings.HorDcm = 1;
-                               if (settings.TmpDcm == 1)
-                                       settings.field_per_buff = 2;
-                               else
-                                       settings.field_per_buff = 1;
-
-                               /* check */
-                               if ((res =
-                                    zoran_check_jpg_settings(zr,
-                                                             &settings)))
-                                       goto sfmtjpg_unlock_and_return;
-
-                               /* it's ok, so set them */
-                               fh->jpg_settings = settings;
-
-                               /* tell the user what we actually did */
-                               fmt->fmt.pix.width =
-                                   settings.img_width / settings.HorDcm;
-                               fmt->fmt.pix.height =
-                                   settings.img_height * 2 /
-                                   (settings.TmpDcm * settings.VerDcm);
-                               if (settings.TmpDcm == 1)
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_SEQ_TB :
-                                            V4L2_FIELD_SEQ_BT);
-                               else
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_TOP :
-                                            V4L2_FIELD_BOTTOM);
-                               fh->jpg_buffers.buffer_size =
-                                   zoran_v4l2_calc_bufsize(&fh->
-                                                           jpg_settings);
-                               fmt->fmt.pix.bytesperline = 0;
-                               fmt->fmt.pix.sizeimage =
-                                   fh->jpg_buffers.buffer_size;
-
-                               /* we hereby abuse this variable to show that
-                                * we're gonna do mjpeg capture */
-                               fh->map_mode =
-                                   (fmt->type ==
-                                    V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
-                                   ZORAN_MAP_MODE_JPG_REC :
-                                   ZORAN_MAP_MODE_JPG_PLAY;
-                       sfmtjpg_unlock_and_return:
-                               mutex_unlock(&zr->resource_lock);
-                       } else {
-                               for (i = 0; i < NUM_FORMATS; i++)
-                                       if (fmt->fmt.pix.pixelformat ==
-                                           zoran_formats[i].fourcc)
-                                               break;
-                               if (i == NUM_FORMATS) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n",
-                                               ZR_DEVNAME(zr),
-                                               fmt->fmt.pix.pixelformat,
-                                               (char *) &printformat);
-                                       return -EINVAL;
-                               }
-                               mutex_lock(&zr->resource_lock);
-                               if (fh->jpg_buffers.allocated ||
-                                   (fh->v4l_buffers.allocated &&
-                                    fh->v4l_buffers.active !=
-                                    ZORAN_FREE)) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: VIDIOC_S_FMT - cannot change capture mode\n",
-                                               ZR_DEVNAME(zr));
-                                       res = -EBUSY;
-                                       goto sfmtv4l_unlock_and_return;
-                               }
-                               if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-                                       fmt->fmt.pix.height =
-                                           BUZ_MAX_HEIGHT;
-                               if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-                                       fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-
-                               if ((res =
-                                    zoran_v4l_set_format(file,
-                                                         fmt->fmt.pix.
-                                                         width,
-                                                         fmt->fmt.pix.
-                                                         height,
-                                                         &zoran_formats
-                                                         [i])))
-                                       goto sfmtv4l_unlock_and_return;
-
-                               /* tell the user the
-                                * results/missing stuff */
-                               fmt->fmt.pix.bytesperline =
-                                       fh->v4l_settings.bytesperline;
-                               fmt->fmt.pix.sizeimage =
-                                       fh->v4l_settings.height *
-                                       fh->v4l_settings.bytesperline;
-                               if (BUZ_MAX_HEIGHT <
-                                   (fh->v4l_settings.height * 2))
-                                       fmt->fmt.pix.field =
-                                           V4L2_FIELD_INTERLACED;
-                               else
-                                       fmt->fmt.pix.field =
-                                           V4L2_FIELD_TOP;
-
-                               fh->map_mode = ZORAN_MAP_MODE_RAW;
-                       sfmtv4l_unlock_and_return:
-                               mutex_unlock(&zr->resource_lock);
-                       }
-
-                       break;
-
-               default:
-                       dprintk(3, "unsupported\n");
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_S_FMT - unsupported type %d\n",
-                               ZR_DEVNAME(zr), fmt->type);
-                       return -EINVAL;
-               }
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_G_FBUF:
-       {
-               struct v4l2_framebuffer *fb = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_FBUF\n", ZR_DEVNAME(zr));
-
-               memset(fb, 0, sizeof(*fb));
-               mutex_lock(&zr->resource_lock);
-               fb->base = zr->buffer.base;
-               fb->fmt.width = zr->buffer.width;
-               fb->fmt.height = zr->buffer.height;
-               if (zr->overlay_settings.format) {
-                       fb->fmt.pixelformat =
-                               fh->overlay_settings.format->fourcc;
-               }
-               fb->fmt.bytesperline = zr->buffer.bytesperline;
-               mutex_unlock(&zr->resource_lock);
-               fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
-               fb->fmt.field = V4L2_FIELD_INTERLACED;
-               fb->flags = V4L2_FBUF_FLAG_OVERLAY;
-               fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_FBUF:
-       {
-               int i, res = 0;
-               struct v4l2_framebuffer *fb = arg;
-               __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOC_S_FBUF - base=0x%p, size=%dx%d, bpl=%d, fmt=0x%x (%4.4s)\n",
-                       ZR_DEVNAME(zr), fb->base, fb->fmt.width, fb->fmt.height,
-                       fb->fmt.bytesperline, fb->fmt.pixelformat,
-                       (char *) &printformat);
-
-               for (i = 0; i < NUM_FORMATS; i++)
-                       if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
-                               break;
-               if (i == NUM_FORMATS) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
-                               ZR_DEVNAME(zr), fb->fmt.pixelformat,
-                               (char *) &printformat);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-               res =
-                   setup_fbuffer(file, fb->base, &zoran_formats[i],
-                                 fb->fmt.width, fb->fmt.height,
-                                 fb->fmt.bytesperline);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_OVERLAY:
-       {
-               int *on = arg, res;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_PREVIEW - on=%d\n",
-                       ZR_DEVNAME(zr), *on);
-
-               mutex_lock(&zr->resource_lock);
-               res = setup_overlay(file, *on);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_REQBUFS:
-       {
-               struct v4l2_requestbuffers *req = arg;
-               int res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_REQBUFS - type=%d\n",
-                       ZR_DEVNAME(zr), req->type);
-
-               if (req->memory != V4L2_MEMORY_MMAP) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: only MEMORY_MMAP capture is supported, not %d\n",
-                               ZR_DEVNAME(zr), req->memory);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-
-               if (fh->v4l_buffers.allocated || fh->jpg_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_REQBUFS - buffers allready allocated\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-                       goto v4l2reqbuf_unlock_and_return;
-               }
-
-               if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
-                   req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-
-                       /* control user input */
-                       if (req->count < 2)
-                               req->count = 2;
-                       if (req->count > v4l_nbufs)
-                               req->count = v4l_nbufs;
-                       fh->v4l_buffers.num_buffers = req->count;
-
-                       if (v4l_fbuffer_alloc(file)) {
-                               res = -ENOMEM;
-                               goto v4l2reqbuf_unlock_and_return;
-                       }
-
-                       /* The next mmap will map the V4L buffers */
-                       fh->map_mode = ZORAN_MAP_MODE_RAW;
-
-               } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
-                          fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-
-                       /* we need to calculate size ourselves now */
-                       if (req->count < 4)
-                               req->count = 4;
-                       if (req->count > jpg_nbufs)
-                               req->count = jpg_nbufs;
-                       fh->jpg_buffers.num_buffers = req->count;
-                       fh->jpg_buffers.buffer_size =
-                           zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-
-                       if (jpg_fbuffer_alloc(file)) {
-                               res = -ENOMEM;
-                               goto v4l2reqbuf_unlock_and_return;
-                       }
-
-                       /* The next mmap will map the MJPEG buffers */
-                       if (req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                               fh->map_mode = ZORAN_MAP_MODE_JPG_REC;
-                       else
-                               fh->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
-
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_REQBUFS - unknown type %d\n",
-                               ZR_DEVNAME(zr), req->type);
-                       res = -EINVAL;
-                       goto v4l2reqbuf_unlock_and_return;
-               }
-       v4l2reqbuf_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_QUERYBUF:
-       {
-               struct v4l2_buffer *buf = arg;
-               __u32 type = buf->type;
-               int index = buf->index, res;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOC_QUERYBUF - index=%d, type=%d\n",
-                       ZR_DEVNAME(zr), buf->index, buf->type);
-
-               memset(buf, 0, sizeof(*buf));
-               buf->type = type;
-               buf->index = index;
-
-               mutex_lock(&zr->resource_lock);
-               res = zoran_v4l2_buffer_status(file, buf, buf->index);
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_QBUF:
-       {
-               struct v4l2_buffer *buf = arg;
-               int res = 0, codec_mode, buf_type;
-
-               dprintk(3,
-                       KERN_DEBUG "%s: VIDIOC_QBUF - type=%d, index=%d\n",
-                       ZR_DEVNAME(zr), buf->type, buf->index);
-
-               mutex_lock(&zr->resource_lock);
-
-               switch (fh->map_mode) {
-               case ZORAN_MAP_MODE_RAW:
-                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                               res = -EINVAL;
-                               goto qbuf_unlock_and_return;
-                       }
-
-                       res = zoran_v4l_queue_frame(file, buf->index);
-                       if (res)
-                               goto qbuf_unlock_and_return;
-                       if (!zr->v4l_memgrab_active &&
-                           fh->v4l_buffers.active == ZORAN_LOCKED)
-                               zr36057_set_memgrab(zr, 1);
-                       break;
-
-               case ZORAN_MAP_MODE_JPG_REC:
-               case ZORAN_MAP_MODE_JPG_PLAY:
-                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-                               buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-                               codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
-                       } else {
-                               buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                               codec_mode = BUZ_MODE_MOTION_COMPRESS;
-                       }
-
-                       if (buf->type != buf_type) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                               res = -EINVAL;
-                               goto qbuf_unlock_and_return;
-                       }
-
-                       res =
-                           zoran_jpg_queue_frame(file, buf->index,
-                                                 codec_mode);
-                       if (res != 0)
-                               goto qbuf_unlock_and_return;
-                       if (zr->codec_mode == BUZ_MODE_IDLE &&
-                           fh->jpg_buffers.active == ZORAN_LOCKED) {
-                               zr36057_enable_jpg(zr, codec_mode);
-                       }
-                       break;
-
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_QBUF - unsupported type %d\n",
-                               ZR_DEVNAME(zr), buf->type);
-                       res = -EINVAL;
-                       goto qbuf_unlock_and_return;
-               }
-       qbuf_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_DQBUF:
-       {
-               struct v4l2_buffer *buf = arg;
-               int res = 0, buf_type, num = -1;        /* compiler borks here (?) */
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_DQBUF - type=%d\n",
-                       ZR_DEVNAME(zr), buf->type);
-
-               mutex_lock(&zr->resource_lock);
-
-               switch (fh->map_mode) {
-               case ZORAN_MAP_MODE_RAW:
-                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                               res = -EINVAL;
-                               goto dqbuf_unlock_and_return;
-                       }
-
-                       num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
-                       if (file->f_flags & O_NONBLOCK &&
-                           zr->v4l_buffers.buffer[num].state !=
-                           BUZ_STATE_DONE) {
-                               res = -EAGAIN;
-                               goto dqbuf_unlock_and_return;
-                       }
-                       res = v4l_sync(file, num);
-                       if (res)
-                               goto dqbuf_unlock_and_return;
-                       else
-                               zr->v4l_sync_tail++;
-                       res = zoran_v4l2_buffer_status(file, buf, num);
-                       break;
-
-               case ZORAN_MAP_MODE_JPG_REC:
-               case ZORAN_MAP_MODE_JPG_PLAY:
-               {
-                       struct zoran_sync bs;
-
-                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
-                               buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-                       else
-                               buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-                       if (buf->type != buf_type) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                                       ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                               res = -EINVAL;
-                               goto dqbuf_unlock_and_return;
-                       }
-
-                       num =
-                           zr->jpg_pend[zr->
-                                        jpg_que_tail & BUZ_MASK_FRAME];
-
-                       if (file->f_flags & O_NONBLOCK &&
-                           zr->jpg_buffers.buffer[num].state !=
-                           BUZ_STATE_DONE) {
-                               res = -EAGAIN;
-                               goto dqbuf_unlock_and_return;
-                       }
-                       res = jpg_sync(file, &bs);
-                       if (res)
-                               goto dqbuf_unlock_and_return;
-                       res =
-                           zoran_v4l2_buffer_status(file, buf, bs.frame);
-                       break;
-               }
-
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_DQBUF - unsupported type %d\n",
-                               ZR_DEVNAME(zr), buf->type);
-                       res = -EINVAL;
-                       goto dqbuf_unlock_and_return;
-               }
-       dqbuf_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_STREAMON:
-       {
-               int res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMON\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-
-               switch (fh->map_mode) {
-               case ZORAN_MAP_MODE_RAW:        /* raw capture */
-                       if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
-                           fh->v4l_buffers.active != ZORAN_ACTIVE) {
-                               res = -EBUSY;
-                               goto strmon_unlock_and_return;
-                       }
-
-                       zr->v4l_buffers.active = fh->v4l_buffers.active =
-                           ZORAN_LOCKED;
-                       zr->v4l_settings = fh->v4l_settings;
-
-                       zr->v4l_sync_tail = zr->v4l_pend_tail;
-                       if (!zr->v4l_memgrab_active &&
-                           zr->v4l_pend_head != zr->v4l_pend_tail) {
-                               zr36057_set_memgrab(zr, 1);
-                       }
-                       break;
-
-               case ZORAN_MAP_MODE_JPG_REC:
-               case ZORAN_MAP_MODE_JPG_PLAY:
-                       /* what is the codec mode right now? */
-                       if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
-                           fh->jpg_buffers.active != ZORAN_ACTIVE) {
-                               res = -EBUSY;
-                               goto strmon_unlock_and_return;
-                       }
-
-                       zr->jpg_buffers.active = fh->jpg_buffers.active =
-                           ZORAN_LOCKED;
-
-                       if (zr->jpg_que_head != zr->jpg_que_tail) {
-                               /* Start the jpeg codec when the first frame is queued  */
-                               jpeg_start(zr);
-                       }
-
-                       break;
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_STREAMON - invalid map mode %d\n",
-                               ZR_DEVNAME(zr), fh->map_mode);
-                       res = -EINVAL;
-                       goto strmon_unlock_and_return;
-               }
-       strmon_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_STREAMOFF:
-       {
-               int i, res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_STREAMOFF\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-
-               switch (fh->map_mode) {
-               case ZORAN_MAP_MODE_RAW:        /* raw capture */
-                       if (fh->v4l_buffers.active == ZORAN_FREE &&
-                           zr->v4l_buffers.active != ZORAN_FREE) {
-                               res = -EPERM;   /* stay off other's settings! */
-                               goto strmoff_unlock_and_return;
-                       }
-                       if (zr->v4l_buffers.active == ZORAN_FREE)
-                               goto strmoff_unlock_and_return;
-
-                       /* unload capture */
-                       if (zr->v4l_memgrab_active) {
-                               unsigned long flags;
-
-                               spin_lock_irqsave(&zr->spinlock, flags);
-                               zr36057_set_memgrab(zr, 0);
-                               spin_unlock_irqrestore(&zr->spinlock, flags);
-                       }
-
-                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
-                               zr->v4l_buffers.buffer[i].state =
-                                   BUZ_STATE_USER;
-                       fh->v4l_buffers = zr->v4l_buffers;
-
-                       zr->v4l_buffers.active = fh->v4l_buffers.active =
-                           ZORAN_FREE;
-
-                       zr->v4l_grab_seq = 0;
-                       zr->v4l_pend_head = zr->v4l_pend_tail = 0;
-                       zr->v4l_sync_tail = 0;
-
-                       break;
-
-               case ZORAN_MAP_MODE_JPG_REC:
-               case ZORAN_MAP_MODE_JPG_PLAY:
-                       if (fh->jpg_buffers.active == ZORAN_FREE &&
-                           zr->jpg_buffers.active != ZORAN_FREE) {
-                               res = -EPERM;   /* stay off other's settings! */
-                               goto strmoff_unlock_and_return;
-                       }
-                       if (zr->jpg_buffers.active == ZORAN_FREE)
-                               goto strmoff_unlock_and_return;
-
-                       res =
-                           jpg_qbuf(file, -1,
-                                    (fh->map_mode ==
-                                     ZORAN_MAP_MODE_JPG_REC) ?
-                                    BUZ_MODE_MOTION_COMPRESS :
-                                    BUZ_MODE_MOTION_DECOMPRESS);
-                       if (res)
-                               goto strmoff_unlock_and_return;
-                       break;
-               default:
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
-                               ZR_DEVNAME(zr), fh->map_mode);
-                       res = -EINVAL;
-                       goto strmoff_unlock_and_return;
-               }
-       strmoff_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *ctrl = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCTRL - id=%d\n",
-                       ZR_DEVNAME(zr), ctrl->id);
-
-               /* we only support hue/saturation/contrast/brightness */
-               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-                   ctrl->id > V4L2_CID_HUE)
-                       return -EINVAL;
-               else {
-                       int id = ctrl->id;
-                       memset(ctrl, 0, sizeof(*ctrl));
-                       ctrl->id = id;
-               }
-
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
-                       break;
-               case V4L2_CID_CONTRAST:
-                       strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
-                       break;
-               case V4L2_CID_SATURATION:
-                       strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
-                       break;
-               case V4L2_CID_HUE:
-                       strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
-                       break;
-               }
-
-               ctrl->minimum = 0;
-               ctrl->maximum = 65535;
-               ctrl->step = 1;
-               ctrl->default_value = 32768;
-               ctrl->type = V4L2_CTRL_TYPE_INTEGER;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_G_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_CTRL - id=%d\n",
-                       ZR_DEVNAME(zr), ctrl->id);
-
-               /* we only support hue/saturation/contrast/brightness */
-               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-                   ctrl->id > V4L2_CID_HUE)
-                       return -EINVAL;
-
-               mutex_lock(&zr->resource_lock);
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       ctrl->value = zr->brightness;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       ctrl->value = zr->contrast;
-                       break;
-               case V4L2_CID_SATURATION:
-                       ctrl->value = zr->saturation;
-                       break;
-               case V4L2_CID_HUE:
-                       ctrl->value = zr->hue;
-                       break;
-               }
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-               struct video_picture pict;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_CTRL - id=%d\n",
-                       ZR_DEVNAME(zr), ctrl->id);
-
-               /* we only support hue/saturation/contrast/brightness */
-               if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-                   ctrl->id > V4L2_CID_HUE)
-                       return -EINVAL;
-
-               if (ctrl->value < 0 || ctrl->value > 65535) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n",
-                               ZR_DEVNAME(zr), ctrl->value, ctrl->id);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-               switch (ctrl->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       zr->brightness = ctrl->value;
-                       break;
-               case V4L2_CID_CONTRAST:
-                       zr->contrast = ctrl->value;
-                       break;
-               case V4L2_CID_SATURATION:
-                       zr->saturation = ctrl->value;
-                       break;
-               case V4L2_CID_HUE:
-                       zr->hue = ctrl->value;
-                       break;
-               }
-               pict.brightness = zr->brightness;
-               pict.contrast = zr->contrast;
-               pict.colour = zr->saturation;
-               pict.hue = zr->hue;
-
-               decoder_command(zr, DECODER_SET_PICTURE, &pict);
-
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *std = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMSTD - index=%d\n",
-                       ZR_DEVNAME(zr), std->index);
-
-               if (std->index < 0 || std->index >= (zr->card.norms + 1))
-                       return -EINVAL;
-               else {
-                       int id = std->index;
-                       memset(std, 0, sizeof(*std));
-                       std->index = id;
-               }
-
-               if (std->index == zr->card.norms) {
-                       /* if we have autodetect, ... */
-                       struct video_decoder_capability caps;
-                       decoder_command(zr, DECODER_GET_CAPABILITIES,
-                                       &caps);
-                       if (caps.flags & VIDEO_DECODER_AUTO) {
-                               std->id = V4L2_STD_ALL;
-                               strncpy(std->name, "Autodetect", sizeof(std->name)-1);
-                               return 0;
-                       } else
-                               return -EINVAL;
-               }
-               switch (std->index) {
-               case 0:
-                       std->id = V4L2_STD_PAL;
-                       strncpy(std->name, "PAL", sizeof(std->name)-1);
-                       std->frameperiod.numerator = 1;
-                       std->frameperiod.denominator = 25;
-                       std->framelines = zr->card.tvn[0]->Ht;
-                       break;
-               case 1:
-                       std->id = V4L2_STD_NTSC;
-                       strncpy(std->name, "NTSC", sizeof(std->name)-1);
-                       std->frameperiod.numerator = 1001;
-                       std->frameperiod.denominator = 30000;
-                       std->framelines = zr->card.tvn[1]->Ht;
-                       break;
-               case 2:
-                       std->id = V4L2_STD_SECAM;
-                       strncpy(std->name, "SECAM", sizeof(std->name)-1);
-                       std->frameperiod.numerator = 1;
-                       std->frameperiod.denominator = 25;
-                       std->framelines = zr->card.tvn[2]->Ht;
-                       break;
-               }
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_G_STD:
-       {
-               v4l2_std_id *std = arg;
-               int norm;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_STD\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-               norm = zr->norm;
-               mutex_unlock(&zr->resource_lock);
-
-               switch (norm) {
-               case VIDEO_MODE_PAL:
-                       *std = V4L2_STD_PAL;
-                       break;
-               case VIDEO_MODE_NTSC:
-                       *std = V4L2_STD_NTSC;
-                       break;
-               case VIDEO_MODE_SECAM:
-                       *std = V4L2_STD_SECAM;
-                       break;
-               }
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_STD:
-       {
-               int norm = -1, res = 0;
-               v4l2_std_id *std = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
-                       ZR_DEVNAME(zr), (unsigned long long)*std);
-
-               if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
-                       norm = VIDEO_MODE_PAL;
-               else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
-                       norm = VIDEO_MODE_NTSC;
-               else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
-                       norm = VIDEO_MODE_SECAM;
-               else if (*std == V4L2_STD_ALL)
-                       norm = VIDEO_MODE_AUTO;
-               else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_S_STD - invalid norm 0x%llx\n",
-                               ZR_DEVNAME(zr), (unsigned long long)*std);
-                       return -EINVAL;
-               }
-
-               mutex_lock(&zr->resource_lock);
-               if ((res = zoran_set_norm(zr, norm)))
-                       goto sstd_unlock_and_return;
-
-               res = wait_grab_pending(zr);
-       sstd_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOC_ENUMINPUT:
-       {
-               struct v4l2_input *inp = arg;
-               int status;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMINPUT - index=%d\n",
-                       ZR_DEVNAME(zr), inp->index);
-
-               if (inp->index < 0 || inp->index >= zr->card.inputs)
-                       return -EINVAL;
-               else {
-                       int id = inp->index;
-                       memset(inp, 0, sizeof(*inp));
-                       inp->index = id;
-               }
-
-               strncpy(inp->name, zr->card.input[inp->index].name,
-                       sizeof(inp->name) - 1);
-               inp->type = V4L2_INPUT_TYPE_CAMERA;
-               inp->std = V4L2_STD_ALL;
-
-               /* Get status of video decoder */
-               mutex_lock(&zr->resource_lock);
-               decoder_command(zr, DECODER_GET_STATUS, &status);
-               mutex_unlock(&zr->resource_lock);
-
-               if (!(status & DECODER_STATUS_GOOD)) {
-                       inp->status |= V4L2_IN_ST_NO_POWER;
-                       inp->status |= V4L2_IN_ST_NO_SIGNAL;
-               }
-               if (!(status & DECODER_STATUS_COLOR))
-                       inp->status |= V4L2_IN_ST_NO_COLOR;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_G_INPUT:
-       {
-               int *input = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_INPUT\n", ZR_DEVNAME(zr));
-
-               mutex_lock(&zr->resource_lock);
-               *input = zr->input;
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_INPUT:
-       {
-               int *input = arg, res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_INPUT - input=%d\n",
-                       ZR_DEVNAME(zr), *input);
-
-               mutex_lock(&zr->resource_lock);
-               if ((res = zoran_set_input(zr, *input)))
-                       goto sinput_unlock_and_return;
-
-               /* Make sure the changes come into effect */
-               res = wait_grab_pending(zr);
-       sinput_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOC_ENUMOUTPUT:
-       {
-               struct v4l2_output *outp = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_ENUMOUTPUT - index=%d\n",
-                       ZR_DEVNAME(zr), outp->index);
-
-               if (outp->index != 0)
-                       return -EINVAL;
-
-               memset(outp, 0, sizeof(*outp));
-               outp->index = 0;
-               outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-               strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_G_OUTPUT:
-       {
-               int *output = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_OUTPUT\n", ZR_DEVNAME(zr));
-
-               *output = 0;
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_OUTPUT:
-       {
-               int *output = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_S_OUTPUT - output=%d\n",
-                       ZR_DEVNAME(zr), *output);
-
-               if (*output != 0)
-                       return -EINVAL;
-
-               return 0;
-       }
-               break;
-
-               /* cropping (sub-frame capture) */
-       case VIDIOC_CROPCAP:
-       {
-               struct v4l2_cropcap *cropcap = arg;
-               int type = cropcap->type, res = 0;
-
-               dprintk(3, KERN_ERR "%s: VIDIOC_CROPCAP - type=%d\n",
-                       ZR_DEVNAME(zr), cropcap->type);
-
-               memset(cropcap, 0, sizeof(*cropcap));
-               cropcap->type = type;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-                   (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto cropcap_unlock_and_return;
-               }
-
-               cropcap->bounds.top = cropcap->bounds.left = 0;
-               cropcap->bounds.width = BUZ_MAX_WIDTH;
-               cropcap->bounds.height = BUZ_MAX_HEIGHT;
-               cropcap->defrect.top = cropcap->defrect.left = 0;
-               cropcap->defrect.width = BUZ_MIN_WIDTH;
-               cropcap->defrect.height = BUZ_MIN_HEIGHT;
-       cropcap_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOC_G_CROP:
-       {
-               struct v4l2_crop *crop = arg;
-               int type = crop->type, res = 0;
-
-               dprintk(3, KERN_ERR "%s: VIDIOC_G_CROP - type=%d\n",
-                       ZR_DEVNAME(zr), crop->type);
-
-               memset(crop, 0, sizeof(*crop));
-               crop->type = type;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-                   (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto gcrop_unlock_and_return;
-               }
-
-               crop->c.top = fh->jpg_settings.img_y;
-               crop->c.left = fh->jpg_settings.img_x;
-               crop->c.width = fh->jpg_settings.img_width;
-               crop->c.height = fh->jpg_settings.img_height;
-
-       gcrop_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return res;
-       }
-               break;
-
-       case VIDIOC_S_CROP:
-       {
-               struct v4l2_crop *crop = arg;
-               int res = 0;
-
-               settings = fh->jpg_settings;
-
-               dprintk(3,
-                       KERN_ERR
-                       "%s: VIDIOC_S_CROP - type=%d, x=%d,y=%d,w=%d,h=%d\n",
-                       ZR_DEVNAME(zr), crop->type, crop->c.left, crop->c.top,
-                       crop->c.width, crop->c.height);
-
-               mutex_lock(&zr->resource_lock);
-
-               if (fh->jpg_buffers.allocated || fh->v4l_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_S_CROP - cannot change settings while active\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-                       goto scrop_unlock_and_return;
-               }
-
-               if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-                   (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-                    fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-                               ZR_DEVNAME(zr));
-                       res = -EINVAL;
-                       goto scrop_unlock_and_return;
-               }
-
-               /* move into a form that we understand */
-               settings.img_x = crop->c.left;
-               settings.img_y = crop->c.top;
-               settings.img_width = crop->c.width;
-               settings.img_height = crop->c.height;
-
-               /* check validity */
-               if ((res = zoran_check_jpg_settings(zr, &settings)))
-                       goto scrop_unlock_and_return;
-
-               /* accept */
-               fh->jpg_settings = settings;
-
-       scrop_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-               return res;
-       }
-               break;
-
-       case VIDIOC_G_JPEGCOMP:
-       {
-               struct v4l2_jpegcompression *params = arg;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_G_JPEGCOMP\n",
-                       ZR_DEVNAME(zr));
-
-               memset(params, 0, sizeof(*params));
-
-               mutex_lock(&zr->resource_lock);
-
-               params->quality = fh->jpg_settings.jpg_comp.quality;
-               params->APPn = fh->jpg_settings.jpg_comp.APPn;
-               memcpy(params->APP_data,
-                      fh->jpg_settings.jpg_comp.APP_data,
-                      fh->jpg_settings.jpg_comp.APP_len);
-               params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
-               memcpy(params->COM_data,
-                      fh->jpg_settings.jpg_comp.COM_data,
-                      fh->jpg_settings.jpg_comp.COM_len);
-               params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
-               params->jpeg_markers =
-                   fh->jpg_settings.jpg_comp.jpeg_markers;
-
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_S_JPEGCOMP:
-       {
-               struct v4l2_jpegcompression *params = arg;
-               int res = 0;
-
-               settings = fh->jpg_settings;
-
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: VIDIOC_S_JPEGCOMP - quality=%d, APPN=%d, APP_len=%d, COM_len=%d\n",
-                       ZR_DEVNAME(zr), params->quality, params->APPn,
-                       params->APP_len, params->COM_len);
-
-               settings.jpg_comp = *params;
-
-               mutex_lock(&zr->resource_lock);
-
-               if (fh->v4l_buffers.active != ZORAN_FREE ||
-                   fh->jpg_buffers.active != ZORAN_FREE) {
-                       dprintk(1,
-                               KERN_WARNING
-                               "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
-                               ZR_DEVNAME(zr));
-                       res = -EBUSY;
-                       goto sjpegc_unlock_and_return;
-               }
-
-               if ((res = zoran_check_jpg_settings(zr, &settings)))
-                       goto sjpegc_unlock_and_return;
-               if (!fh->jpg_buffers.allocated)
-                       fh->jpg_buffers.buffer_size =
-                           zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-               fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
-       sjpegc_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               return 0;
-       }
-               break;
-
-       case VIDIOC_QUERYSTD:   /* why is this useful? */
-       {
-               v4l2_std_id *std = arg;
-
-               dprintk(3,
-                       KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n",
-                       ZR_DEVNAME(zr), (unsigned long long)*std);
-
-               if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC ||
-                   *std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM &&
-                                            zr->card.norms == 3)) {
-                       return 0;
-               }
-
-               return -EINVAL;
-       }
-               break;
-
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *fmt = arg;
-               int res = 0;
-
-               dprintk(3, KERN_DEBUG "%s: VIDIOC_TRY_FMT - type=%d\n",
-                       ZR_DEVNAME(zr), fmt->type);
-
-               switch (fmt->type) {
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-                       mutex_lock(&zr->resource_lock);
-
-                       if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
-                               fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
-                       if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
-                               fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
-                       if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
-                               fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
-                       if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
-                               fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
-
-                       mutex_unlock(&zr->resource_lock);
-                       break;
-
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-                       if (fmt->fmt.pix.bytesperline > 0)
-                               return -EINVAL;
-
-                       mutex_lock(&zr->resource_lock);
-
-                       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) {
-                               settings = fh->jpg_settings;
-
-                               /* we actually need to set 'real' parameters now */
-                               if ((fmt->fmt.pix.height * 2) >
-                                   BUZ_MAX_HEIGHT)
-                                       settings.TmpDcm = 1;
-                               else
-                                       settings.TmpDcm = 2;
-                               settings.decimation = 0;
-                               if (fmt->fmt.pix.height <=
-                                   fh->jpg_settings.img_height / 2)
-                                       settings.VerDcm = 2;
-                               else
-                                       settings.VerDcm = 1;
-                               if (fmt->fmt.pix.width <=
-                                   fh->jpg_settings.img_width / 4)
-                                       settings.HorDcm = 4;
-                               else if (fmt->fmt.pix.width <=
-                                        fh->jpg_settings.img_width / 2)
-                                       settings.HorDcm = 2;
-                               else
-                                       settings.HorDcm = 1;
-                               if (settings.TmpDcm == 1)
-                                       settings.field_per_buff = 2;
-                               else
-                                       settings.field_per_buff = 1;
-
-                               /* check */
-                               if ((res =
-                                    zoran_check_jpg_settings(zr,
-                                                             &settings)))
-                                       goto tryfmt_unlock_and_return;
-
-                               /* tell the user what we actually did */
-                               fmt->fmt.pix.width =
-                                   settings.img_width / settings.HorDcm;
-                               fmt->fmt.pix.height =
-                                   settings.img_height * 2 /
-                                   (settings.TmpDcm * settings.VerDcm);
-                               if (settings.TmpDcm == 1)
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_SEQ_TB :
-                                            V4L2_FIELD_SEQ_BT);
-                               else
-                                       fmt->fmt.pix.field =
-                                           (fh->jpg_settings.
-                                            odd_even ? V4L2_FIELD_TOP :
-                                            V4L2_FIELD_BOTTOM);
-
-                               fmt->fmt.pix.sizeimage =
-                                   zoran_v4l2_calc_bufsize(&settings);
-                       } else if (fmt->type ==
-                                  V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                               int i;
-
-                               for (i = 0; i < NUM_FORMATS; i++)
-                                       if (zoran_formats[i].fourcc ==
-                                           fmt->fmt.pix.pixelformat)
-                                               break;
-                               if (i == NUM_FORMATS) {
-                                       res = -EINVAL;
-                                       goto tryfmt_unlock_and_return;
-                               }
-
-                               if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-                                       fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-                               if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
-                                       fmt->fmt.pix.width = BUZ_MIN_WIDTH;
-                               if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-                                       fmt->fmt.pix.height =
-                                           BUZ_MAX_HEIGHT;
-                               if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT)
-                                       fmt->fmt.pix.height =
-                                           BUZ_MIN_HEIGHT;
-                       } else {
-                               res = -EINVAL;
-                               goto tryfmt_unlock_and_return;
-                       }
-               tryfmt_unlock_and_return:
-                       mutex_unlock(&zr->resource_lock);
-
-                       return res;
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-
-               return 0;
-       }
-               break;
-
-       default:
-               dprintk(1, KERN_DEBUG "%s: UNKNOWN ioctl cmd: 0x%x\n",
-                       ZR_DEVNAME(zr), cmd);
-               return -ENOIOCTLCMD;
-               break;
-
-       }
-       return 0;
-}
-
-
-static int
-zoran_ioctl (struct inode *inode,
-            struct file  *file,
-            unsigned int  cmd,
-            unsigned long arg)
-{
-       return video_usercopy(inode, file, cmd, arg, zoran_do_ioctl);
-}
-
-static unsigned int
-zoran_poll (struct file *file,
-           poll_table  *wait)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int res = 0, frame;
-       unsigned long flags;
-
-       /* we should check whether buffers are ready to be synced on
-        * (w/o waits - O_NONBLOCK) here
-        * if ready for read (sync), return POLLIN|POLLRDNORM,
-        * if ready for write (sync), return POLLOUT|POLLWRNORM,
-        * if error, return POLLERR,
-        * if no buffers queued or so, return POLLNVAL
-        */
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-               poll_wait(file, &zr->v4l_capq, wait);
-               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
-                       ZR_DEVNAME(zr), __func__,
-                       "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail,
-                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
-                       zr->v4l_pend_tail, zr->v4l_pend_head);
-               /* Process is the one capturing? */
-               if (fh->v4l_buffers.active != ZORAN_FREE &&
-                   /* Buffer ready to DQBUF? */
-                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
-                       res = POLLIN | POLLRDNORM;
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-               poll_wait(file, &zr->jpg_capq, wait);
-               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
-                       ZR_DEVNAME(zr), __func__,
-                       "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail,
-                       "UPMD"[zr->jpg_buffers.buffer[frame].state],
-                       zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head);
-               if (fh->jpg_buffers.active != ZORAN_FREE &&
-                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
-                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
-                               res = POLLIN | POLLRDNORM;
-                       else
-                               res = POLLOUT | POLLWRNORM;
-               }
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               break;
-
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_poll() - internal error, unknown map_mode=%d\n",
-                       ZR_DEVNAME(zr), fh->map_mode);
-               res = POLLNVAL;
-       }
-
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-
-/*
- * This maps the buffers to user space.
- *
- * Depending on the state of fh->map_mode
- * the V4L or the MJPEG buffers are mapped
- * per buffer or all together
- *
- * Note that we need to connect to some
- * unmap signal event to unmap the de-allocate
- * the buffer accordingly (zoran_vm_close())
- */
-
-static void
-zoran_vm_open (struct vm_area_struct *vma)
-{
-       struct zoran_mapping *map = vma->vm_private_data;
-
-       map->count++;
-}
-
-static void
-zoran_vm_close (struct vm_area_struct *vma)
-{
-       struct zoran_mapping *map = vma->vm_private_data;
-       struct file *file = map->file;
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int i;
-
-       map->count--;
-       if (map->count == 0) {
-               switch (fh->map_mode) {
-               case ZORAN_MAP_MODE_JPG_REC:
-               case ZORAN_MAP_MODE_JPG_PLAY:
-
-                       dprintk(3, KERN_INFO "%s: munmap(MJPEG)\n",
-                               ZR_DEVNAME(zr));
-
-                       for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-                               if (fh->jpg_buffers.buffer[i].map == map) {
-                                       fh->jpg_buffers.buffer[i].map =
-                                           NULL;
-                               }
-                       }
-                       kfree(map);
-
-                       for (i = 0; i < fh->jpg_buffers.num_buffers; i++)
-                               if (fh->jpg_buffers.buffer[i].map)
-                                       break;
-                       if (i == fh->jpg_buffers.num_buffers) {
-                               mutex_lock(&zr->resource_lock);
-
-                               if (fh->jpg_buffers.active != ZORAN_FREE) {
-                                       jpg_qbuf(file, -1, zr->codec_mode);
-                                       zr->jpg_buffers.allocated = 0;
-                                       zr->jpg_buffers.active =
-                                           fh->jpg_buffers.active =
-                                           ZORAN_FREE;
-                               }
-                               //jpg_fbuffer_free(file);
-                               fh->jpg_buffers.allocated = 0;
-                               fh->jpg_buffers.ready_to_be_freed = 1;
-
-                               mutex_unlock(&zr->resource_lock);
-                       }
-
-                       break;
-
-               case ZORAN_MAP_MODE_RAW:
-
-                       dprintk(3, KERN_INFO "%s: munmap(V4L)\n",
-                               ZR_DEVNAME(zr));
-
-                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {
-                               if (fh->v4l_buffers.buffer[i].map == map) {
-                                       /* unqueue/unmap */
-                                       fh->v4l_buffers.buffer[i].map =
-                                           NULL;
-                               }
-                       }
-                       kfree(map);
-
-                       for (i = 0; i < fh->v4l_buffers.num_buffers; i++)
-                               if (fh->v4l_buffers.buffer[i].map)
-                                       break;
-                       if (i == fh->v4l_buffers.num_buffers) {
-                               mutex_lock(&zr->resource_lock);
-
-                               if (fh->v4l_buffers.active != ZORAN_FREE) {
-                                       unsigned long flags;
-
-                                       spin_lock_irqsave(&zr->spinlock, flags);
-                                       zr36057_set_memgrab(zr, 0);
-                                       zr->v4l_buffers.allocated = 0;
-                                       zr->v4l_buffers.active =
-                                           fh->v4l_buffers.active =
-                                           ZORAN_FREE;
-                                       spin_unlock_irqrestore(&zr->spinlock, flags);
-                               }
-                               //v4l_fbuffer_free(file);
-                               fh->v4l_buffers.allocated = 0;
-                               fh->v4l_buffers.ready_to_be_freed = 1;
-
-                               mutex_unlock(&zr->resource_lock);
-                       }
-
-                       break;
-
-               default:
-                       printk(KERN_ERR
-                              "%s: munmap() - internal error - unknown map mode %d\n",
-                              ZR_DEVNAME(zr), fh->map_mode);
-                       break;
-
-               }
-       }
-}
-
-static struct vm_operations_struct zoran_vm_ops = {
-       .open = zoran_vm_open,
-       .close = zoran_vm_close,
-};
-
-static int
-zoran_mmap (struct file           *file,
-           struct vm_area_struct *vma)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long size = (vma->vm_end - vma->vm_start);
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       int i, j;
-       unsigned long page, start = vma->vm_start, todo, pos, fraglen;
-       int first, last;
-       struct zoran_mapping *map;
-       int res = 0;
-
-       dprintk(3,
-               KERN_INFO "%s: mmap(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
-               ZR_DEVNAME(zr),
-               fh->map_mode == ZORAN_MAP_MODE_RAW ? "V4L" : "MJPEG",
-               vma->vm_start, vma->vm_end, size);
-
-       if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
-           !(vma->vm_flags & VM_WRITE)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: mmap() - no MAP_SHARED/PROT_{READ,WRITE} given\n",
-                       ZR_DEVNAME(zr));
-               return -EINVAL;
-       }
-
-       switch (fh->map_mode) {
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-
-               /* lock */
-               mutex_lock(&zr->resource_lock);
-
-               /* Map the MJPEG buffers */
-               if (!fh->jpg_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zoran_mmap(MJPEG) - buffers not yet allocated\n",
-                               ZR_DEVNAME(zr));
-                       res = -ENOMEM;
-                       goto jpg_mmap_unlock_and_return;
-               }
-
-               first = offset / fh->jpg_buffers.buffer_size;
-               last = first - 1 + size / fh->jpg_buffers.buffer_size;
-               if (offset % fh->jpg_buffers.buffer_size != 0 ||
-                   size % fh->jpg_buffers.buffer_size != 0 || first < 0 ||
-                   last < 0 || first >= fh->jpg_buffers.num_buffers ||
-                   last >= fh->jpg_buffers.num_buffers) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: mmap(MJPEG) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-                               ZR_DEVNAME(zr), offset, size,
-                               fh->jpg_buffers.buffer_size,
-                               fh->jpg_buffers.num_buffers);
-                       res = -EINVAL;
-                       goto jpg_mmap_unlock_and_return;
-               }
-               for (i = first; i <= last; i++) {
-                       if (fh->jpg_buffers.buffer[i].map) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: mmap(MJPEG) - buffer %d already mapped\n",
-                                       ZR_DEVNAME(zr), i);
-                               res = -EBUSY;
-                               goto jpg_mmap_unlock_and_return;
-                       }
-               }
-
-               /* map these buffers (v4l_buffers[i]) */
-               map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-               if (!map) {
-                       res = -ENOMEM;
-                       goto jpg_mmap_unlock_and_return;
-               }
-               map->file = file;
-               map->count = 1;
-
-               vma->vm_ops = &zoran_vm_ops;
-               vma->vm_flags |= VM_DONTEXPAND;
-               vma->vm_private_data = map;
-
-               for (i = first; i <= last; i++) {
-                       for (j = 0;
-                            j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-                            j++) {
-                               fraglen =
-                                   (le32_to_cpu(fh->jpg_buffers.buffer[i].
-                                    frag_tab[2 * j + 1]) & ~1) << 1;
-                               todo = size;
-                               if (todo > fraglen)
-                                       todo = fraglen;
-                               pos =
-                                   le32_to_cpu(fh->jpg_buffers.
-                                   buffer[i].frag_tab[2 * j]);
-                               /* should just be pos on i386 */
-                               page = virt_to_phys(bus_to_virt(pos))
-                                                               >> PAGE_SHIFT;
-                               if (remap_pfn_range(vma, start, page,
-                                                       todo, PAGE_SHARED)) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
-                                               ZR_DEVNAME(zr));
-                                       res = -EAGAIN;
-                                       goto jpg_mmap_unlock_and_return;
-                               }
-                               size -= todo;
-                               start += todo;
-                               if (size == 0)
-                                       break;
-                               if (le32_to_cpu(fh->jpg_buffers.buffer[i].
-                                   frag_tab[2 * j + 1]) & 1)
-                                       break;  /* was last fragment */
-                       }
-                       fh->jpg_buffers.buffer[i].map = map;
-                       if (size == 0)
-                               break;
-
-               }
-       jpg_mmap_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               break;
-
-       case ZORAN_MAP_MODE_RAW:
-
-               mutex_lock(&zr->resource_lock);
-
-               /* Map the V4L buffers */
-               if (!fh->v4l_buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zoran_mmap(V4L) - buffers not yet allocated\n",
-                               ZR_DEVNAME(zr));
-                       res = -ENOMEM;
-                       goto v4l_mmap_unlock_and_return;
-               }
-
-               first = offset / fh->v4l_buffers.buffer_size;
-               last = first - 1 + size / fh->v4l_buffers.buffer_size;
-               if (offset % fh->v4l_buffers.buffer_size != 0 ||
-                   size % fh->v4l_buffers.buffer_size != 0 || first < 0 ||
-                   last < 0 || first >= fh->v4l_buffers.num_buffers ||
-                   last >= fh->v4l_buffers.buffer_size) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: mmap(V4L) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-                               ZR_DEVNAME(zr), offset, size,
-                               fh->v4l_buffers.buffer_size,
-                               fh->v4l_buffers.num_buffers);
-                       res = -EINVAL;
-                       goto v4l_mmap_unlock_and_return;
-               }
-               for (i = first; i <= last; i++) {
-                       if (fh->v4l_buffers.buffer[i].map) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: mmap(V4L) - buffer %d already mapped\n",
-                                       ZR_DEVNAME(zr), i);
-                               res = -EBUSY;
-                               goto v4l_mmap_unlock_and_return;
-                       }
-               }
-
-               /* map these buffers (v4l_buffers[i]) */
-               map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-               if (!map) {
-                       res = -ENOMEM;
-                       goto v4l_mmap_unlock_and_return;
-               }
-               map->file = file;
-               map->count = 1;
-
-               vma->vm_ops = &zoran_vm_ops;
-               vma->vm_flags |= VM_DONTEXPAND;
-               vma->vm_private_data = map;
-
-               for (i = first; i <= last; i++) {
-                       todo = size;
-                       if (todo > fh->v4l_buffers.buffer_size)
-                               todo = fh->v4l_buffers.buffer_size;
-                       page = fh->v4l_buffers.buffer[i].fbuffer_phys;
-                       if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
-                                                       todo, PAGE_SHARED)) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: zoran_mmap(V4L)i - remap_pfn_range failed\n",
-                                       ZR_DEVNAME(zr));
-                               res = -EAGAIN;
-                               goto v4l_mmap_unlock_and_return;
-                       }
-                       size -= todo;
-                       start += todo;
-                       fh->v4l_buffers.buffer[i].map = map;
-                       if (size == 0)
-                               break;
-               }
-       v4l_mmap_unlock_and_return:
-               mutex_unlock(&zr->resource_lock);
-
-               break;
-
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: zoran_mmap() - internal error - unknown map mode %d\n",
-                       ZR_DEVNAME(zr), fh->map_mode);
-               break;
-       }
-
-       return 0;
-}
-
-static const struct file_operations zoran_fops = {
-       .owner = THIS_MODULE,
-       .open = zoran_open,
-       .release = zoran_close,
-       .ioctl = zoran_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = v4l_compat_ioctl32,
-#endif
-       .llseek = no_llseek,
-       .read = zoran_read,
-       .write = zoran_write,
-       .mmap = zoran_mmap,
-       .poll = zoran_poll,
-};
-
-struct video_device zoran_template __devinitdata = {
-       .name = ZORAN_NAME,
-       .fops = &zoran_fops,
-       .release = &zoran_vdev_release,
-       .minor = -1
-};
-
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
deleted file mode 100644 (file)
index 870bc5a..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles the procFS entries (/proc/ZORAN[%d])
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-#include <linux/seq_file.h>
-
-#include <linux/ctype.h>
-#include <linux/poll.h>
-#include <asm/io.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_procfs.h"
-#include "zoran_card.h"
-
-#ifdef CONFIG_PROC_FS
-struct procfs_params_zr36067 {
-       char *name;
-       short reg;
-       u32 mask;
-       short bit;
-};
-
-static const struct procfs_params_zr36067 zr67[] = {
-       {"HSPol", 0x000, 1, 30},
-       {"HStart", 0x000, 0x3ff, 10},
-       {"HEnd", 0x000, 0x3ff, 0},
-
-       {"VSPol", 0x004, 1, 30},
-       {"VStart", 0x004, 0x3ff, 10},
-       {"VEnd", 0x004, 0x3ff, 0},
-
-       {"ExtFl", 0x008, 1, 26},
-       {"TopField", 0x008, 1, 25},
-       {"VCLKPol", 0x008, 1, 24},
-       {"DupFld", 0x008, 1, 20},
-       {"LittleEndian", 0x008, 1, 0},
-
-       {"HsyncStart", 0x10c, 0xffff, 16},
-       {"LineTot", 0x10c, 0xffff, 0},
-
-       {"NAX", 0x110, 0xffff, 16},
-       {"PAX", 0x110, 0xffff, 0},
-
-       {"NAY", 0x114, 0xffff, 16},
-       {"PAY", 0x114, 0xffff, 0},
-
-       /* {"",,,}, */
-
-       {NULL, 0, 0, 0},
-};
-
-static void
-setparam (struct zoran *zr,
-         char         *name,
-         char         *sval)
-{
-       int i = 0, reg0, reg, val;
-
-       while (zr67[i].name != NULL) {
-               if (!strncmp(name, zr67[i].name, strlen(zr67[i].name))) {
-                       reg = reg0 = btread(zr67[i].reg);
-                       reg &= ~(zr67[i].mask << zr67[i].bit);
-                       if (!isdigit(sval[0]))
-                               break;
-                       val = simple_strtoul(sval, NULL, 0);
-                       if ((val & ~zr67[i].mask))
-                               break;
-                       reg |= (val & zr67[i].mask) << zr67[i].bit;
-                       dprintk(4,
-                               KERN_INFO
-                               "%s: setparam: setting ZR36067 register 0x%03x: 0x%08x=>0x%08x %s=%d\n",
-                               ZR_DEVNAME(zr), zr67[i].reg, reg0, reg,
-                               zr67[i].name, val);
-                       btwrite(reg, zr67[i].reg);
-                       break;
-               }
-               i++;
-       }
-}
-
-static int zoran_show(struct seq_file *p, void *v)
-{
-       struct zoran *zr = p->private;
-       int i;
-
-       seq_printf(p, "ZR36067 registers:\n");
-       for (i = 0; i < 0x130; i += 16)
-               seq_printf(p, "%03X %08X  %08X  %08X  %08X \n", i,
-                          btread(i), btread(i+4), btread(i+8), btread(i+12));
-       return 0;
-}
-
-static int zoran_open(struct inode *inode, struct file *file)
-{
-       struct zoran *data = PDE(inode)->data;
-       return single_open(file, zoran_show, data);
-}
-
-static ssize_t zoran_write(struct file *file, const char __user *buffer,
-                       size_t count, loff_t *ppos)
-{
-       struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
-       char *string, *sp;
-       char *line, *ldelim, *varname, *svar, *tdelim;
-
-       if (count > 32768)      /* Stupidity filter */
-               return -EINVAL;
-
-       string = sp = vmalloc(count + 1);
-       if (!string) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: write_proc: can not allocate memory\n",
-                       ZR_DEVNAME(zr));
-               return -ENOMEM;
-       }
-       if (copy_from_user(string, buffer, count)) {
-               vfree (string);
-               return -EFAULT;
-       }
-       string[count] = 0;
-       dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
-               ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
-       ldelim = " \t\n";
-       tdelim = "=";
-       line = strpbrk(sp, ldelim);
-       while (line) {
-               *line = 0;
-               svar = strpbrk(sp, tdelim);
-               if (svar) {
-                       *svar = 0;
-                       varname = sp;
-                       svar++;
-                       setparam(zr, varname, svar);
-               }
-               sp = line + 1;
-               line = strpbrk(sp, ldelim);
-       }
-       vfree(string);
-
-       return count;
-}
-
-static const struct file_operations zoran_operations = {
-       .owner          = THIS_MODULE,
-       .open           = zoran_open,
-       .read           = seq_read,
-       .write          = zoran_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-#endif
-
-int
-zoran_proc_init (struct zoran *zr)
-{
-#ifdef CONFIG_PROC_FS
-       char name[8];
-
-       snprintf(name, 7, "zoran%d", zr->id);
-       zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
-       if (zr->zoran_proc != NULL) {
-               dprintk(2,
-                       KERN_INFO
-                       "%s: procfs entry /proc/%s allocated. data=%p\n",
-                       ZR_DEVNAME(zr), name, zr->zoran_proc->data);
-       } else {
-               dprintk(1, KERN_ERR "%s: Unable to initialise /proc/%s\n",
-                       ZR_DEVNAME(zr), name);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-void
-zoran_proc_cleanup (struct zoran *zr)
-{
-#ifdef CONFIG_PROC_FS
-       char name[8];
-
-       snprintf(name, 7, "zoran%d", zr->id);
-       if (zr->zoran_proc)
-               remove_proc_entry(name, NULL);
-       zr->zoran_proc = NULL;
-#endif
-}
diff --git a/drivers/media/video/zoran_procfs.h b/drivers/media/video/zoran_procfs.h
deleted file mode 100644 (file)
index f2d5b1b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ZORAN_PROCFS_H__
-#define __ZORAN_PROCFS_H__
-
-extern int zoran_proc_init(struct zoran *zr);
-extern void zoran_proc_cleanup(struct zoran *zr);
-
-#endif                         /* __ZORAN_PROCFS_H__ */
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
deleted file mode 100644 (file)
index 00d132b..0000000
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Zoran ZR36016 basic configuration functions
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * ------------------------------------------------------------------------
- */
-
-#define ZR016_VERSION "v0.7"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-//#include<errno.h>
-
-/* v4l  API */
-#include <linux/videodev.h>
-
-/* headerfile of this module */
-#include"zr36016.h"
-
-/* codec io API */
-#include"videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36016_codecs;
-
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36016_read (struct zr36016 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value =
-                   (ptr->codec->master_data->
-                    readreg(ptr->codec, reg)) & 0xFF;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
-               value);
-
-       return value;
-}
-
-static void
-zr36016_write (struct zr36016 *ptr,
-              u16             reg,
-              u8              value)
-{
-       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
-               reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg) {
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* indirect read and write functions */
-/* the 016 supports auto-addr-increment, but
- * writing it all time cost not much and is safer... */
-static u8
-zr36016_readi (struct zr36016 *ptr,
-              u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if ((ptr->codec->master_data->writereg) &&
-           (ptr->codec->master_data->readreg)) {
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
-               value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;     // DATA
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing read (i)!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
-               reg, value);
-       return value;
-}
-
-static void
-zr36016_writei (struct zr36016 *ptr,
-               u16             reg,
-               u8              value)
-{
-       dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
-               value, reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg) {
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);      // DATA
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written (i)!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   version read
-   ========================================================================= */
-
-/* version kept in datastructure */
-static u8
-zr36016_read_version (struct zr36016 *ptr)
-{
-       ptr->version = zr36016_read(ptr, 0) >> 4;
-       return ptr->version;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from PAX-Lo register
-   ========================================================================= */
-
-static int
-zr36016_basic_test (struct zr36016 *ptr)
-{
-       if (debug) {
-               int i;
-               zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
-               dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
-               for (i = 0; i <= 0x0b; i++)
-                       dprintk(1, "%02x ", zr36016_readi(ptr, i));
-               dprintk(1, "\n");
-       }
-       // for testing just write 0, then the default value to a register and read
-       // it back in both cases
-       zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
-       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to vfe processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
-       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to vfe processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       // we allow version numbers from 0-3, should be enough, though
-       zr36016_read_version(ptr);
-       if (ptr->version & 0x0c) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, suspicious version %d found...\n",
-                       ptr->name, ptr->version);
-               return -ENXIO;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets - NO USE --
-   ========================================================================= */
-
-#if 0
-static int zr36016_pushit (struct zr36016 *ptr,
-                          u16             startreg,
-                          u16             len,
-                          const char     *data)
-{
-       int i=0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
-               ptr->name, startreg,len);
-       while (i<len) {
-               zr36016_writei(ptr, startreg++,  data[i++]);
-       }
-
-       return i;
-}
-#endif
-
-/* =========================================================================
-   Basic datasets & init:
-
-   //TODO//
-   ========================================================================= */
-
-// needed offset values          PAL NTSC SECAM
-static const int zr016_xoff[] = { 20, 20, 20 };
-static const int zr016_yoff[] = { 8, 9, 7 };
-
-static void
-zr36016_init (struct zr36016 *ptr)
-{
-       // stop any processing
-       zr36016_write(ptr, ZR016_GOSTOP, 0);
-
-       // mode setup (yuv422 in and out, compression/expansuon due to mode)
-       zr36016_write(ptr, ZR016_MODE,
-                     ZR016_YUV422 | ZR016_YUV422_YUV422 |
-                     (ptr->mode == CODEC_DO_COMPRESSION ?
-                      ZR016_COMPRESSION : ZR016_EXPANSION));
-
-       // misc setup
-       zr36016_writei(ptr, ZR016I_SETUP1,
-                      (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
-                      (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
-       zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
-
-       // Window setup
-       // (no extra offset for now, norm defines offset, default width height)
-       zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
-       zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
-       zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
-       zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
-       zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
-       zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
-       zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
-       zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
-
-       /* shall we continue now, please? */
-       zr36016_write(ptr, ZR016_GOSTOP, 1);
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36016_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36016_init(ptr);
-
-       return 0;
-}
-
-/* set picture size */
-static int
-zr36016_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-
-       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
-               ptr->name, norm->HStart, norm->VStart,
-               cap->x, cap->y, cap->width, cap->height,
-               cap->decimation);
-
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y for now ... */
-       ptr->width = cap->width;
-       ptr->height = cap->height;
-       /* (Ronald) This is ugly. zoran_device.c, line 387
-        * already mentions what happens if HStart is even
-        * (blue faces, etc., cr/cb inversed). There's probably
-        * some good reason why HStart is 0 instead of 1, so I'm
-        * leaving it to this for now, but really... This can be
-        * done a lot simpler */
-       ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
-       /* Something to note here (I don't understand it), setting
-        * VStart too high will cause the codec to 'not work'. I
-        * really don't get it. values of 16 (VStart) already break
-        * it here. Just '0' seems to work. More testing needed! */
-       ptr->yoff = norm->VStart + cap->y;
-       /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
-       ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
-       ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36016_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status - we don't know it ... */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = 0;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = 0;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != 0)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36016_unset (struct videocodec *codec)
-{
-       struct zr36016 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36016_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36016_setup (struct videocodec *codec)
-{
-       struct zr36016 *ptr;
-       int res;
-
-       dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
-               zr36016_codecs);
-
-       if (zr36016_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36016: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
-                zr36016_codecs);
-       ptr->num = zr36016_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36016_basic_test(ptr);
-       if (res < 0) {
-               zr36016_unset(codec);
-               return res;
-       }
-       //final setup
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 768;
-       ptr->height = 288;
-       ptr->xdec = 1;
-       ptr->ydec = 0;
-       zr36016_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
-               ptr->name, ptr->version);
-
-       return 0;
-}
-
-static const struct videocodec zr36016_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36016",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER,
-       .type = CODEC_TYPE_ZR36016,
-       .setup = zr36016_setup, // functionality
-       .unset = zr36016_unset,
-       .set_mode = zr36016_set_mode,
-       .set_video = zr36016_set_video,
-       .control = zr36016_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36016_init_module (void)
-{
-       //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
-       zr36016_codecs = 0;
-       return videocodec_register(&zr36016_codec);
-}
-
-static void __exit
-zr36016_cleanup_module (void)
-{
-       if (zr36016_codecs) {
-               dprintk(1,
-                       "zr36016: something's wrong - %d codecs left somehow.\n",
-                       zr36016_codecs);
-       }
-       videocodec_unregister(&zr36016_codec);
-}
-
-module_init(zr36016_init_module);
-module_exit(zr36016_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
-                  ZR016_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zr36016.h b/drivers/media/video/zr36016.h
deleted file mode 100644 (file)
index 8c79229..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Zoran ZR36016 basic configuration functions - header file
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36016.h,v 1.1.2.3 2003/01/14 21:18:07 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 ZR36016_H
-#define ZR36016_H
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36016 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // coder status
-       __u8 version;
-       // actual coder setup
-       int mode;
-
-       __u16 xoff;
-       __u16 yoff;
-       __u16 width;
-       __u16 height;
-       __u16 xdec;
-       __u16 ydec;
-};
-
-/* direct  register addresses */
-#define ZR016_GOSTOP      0x00
-#define ZR016_MODE        0x01
-#define ZR016_IADDR       0x02
-#define ZR016_IDATA       0x03
-
-/* indirect  register addresses */
-#define ZR016I_SETUP1     0x00
-#define ZR016I_SETUP2     0x01
-#define ZR016I_NAX_LO     0x02
-#define ZR016I_NAX_HI     0x03
-#define ZR016I_PAX_LO     0x04
-#define ZR016I_PAX_HI     0x05
-#define ZR016I_NAY_LO     0x06
-#define ZR016I_NAY_HI     0x07
-#define ZR016I_PAY_LO     0x08
-#define ZR016I_PAY_HI     0x09
-#define ZR016I_NOL_LO     0x0a
-#define ZR016I_NOL_HI     0x0b
-
-/* possible values for mode register */
-#define ZR016_RGB444_YUV444  0x00
-#define ZR016_RGB444_YUV422  0x01
-#define ZR016_RGB444_YUV411  0x02
-#define ZR016_RGB444_Y400    0x03
-#define ZR016_RGB444_RGB444  0x04
-#define ZR016_YUV444_YUV444  0x08
-#define ZR016_YUV444_YUV422  0x09
-#define ZR016_YUV444_YUV411  0x0a
-#define ZR016_YUV444_Y400    0x0b
-#define ZR016_YUV444_RGB444  0x0c
-#define ZR016_YUV422_YUV422  0x11
-#define ZR016_YUV422_YUV411  0x12
-#define ZR016_YUV422_Y400    0x13
-#define ZR016_YUV411_YUV411  0x16
-#define ZR016_YUV411_Y400    0x17
-#define ZR016_4444_4444      0x19
-#define ZR016_100_100        0x1b
-
-#define ZR016_RGB444         0x00
-#define ZR016_YUV444         0x20
-#define ZR016_YUV422         0x40
-
-#define ZR016_COMPRESSION    0x80
-#define ZR016_EXPANSION      0x80
-
-/* possible values for setup 1 register */
-#define ZR016_CKRT           0x80
-#define ZR016_VERT           0x40
-#define ZR016_HORZ           0x20
-#define ZR016_HRFL           0x10
-#define ZR016_DSFL           0x08
-#define ZR016_SBFL           0x04
-#define ZR016_RSTR           0x02
-#define ZR016_CNTI           0x01
-
-/* possible values for setup 2 register */
-#define ZR016_SYEN           0x40
-#define ZR016_CCIR           0x04
-#define ZR016_SIGN           0x02
-#define ZR016_YMCS           0x01
-
-#endif                         /*fndef ZR36016_H */
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
deleted file mode 100644 (file)
index cf8b271..0000000
+++ /dev/null
@@ -1,904 +0,0 @@
-/*
- * Zoran ZR36050 basic configuration functions
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * ------------------------------------------------------------------------
- */
-
-#define ZR050_VERSION "v0.7.1"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-//#include<errno.h>
-
-/* headerfile of this module */
-#include "zr36050.h"
-
-/* codec io API */
-#include "videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36050_codecs;
-
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36050_read (struct zr36050 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value = (ptr->codec->master_data->readreg(ptr->codec,
-                                                         reg)) & 0xFF;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
-               value);
-
-       return value;
-}
-
-static void
-zr36050_write (struct zr36050 *ptr,
-              u16             reg,
-              u8              value)
-{
-       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
-               reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg)
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   status read
-   ========================================================================= */
-
-/* status is kept in datastructure */
-static u8
-zr36050_read_status1 (struct zr36050 *ptr)
-{
-       ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
-
-       zr36050_read(ptr, 0);
-       return ptr->status1;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   scale factor read
-   ========================================================================= */
-
-/* scale factor is kept in datastructure */
-static u16
-zr36050_read_scalefactor (struct zr36050 *ptr)
-{
-       ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
-                        (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
-
-       /* leave 0 selected for an eventually GO from master */
-       zr36050_read(ptr, 0);
-       return ptr->scalefact;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   wait if codec is ready to proceed (end of processing) or time is over
-   ========================================================================= */
-
-static void
-zr36050_wait_end (struct zr36050 *ptr)
-{
-       int i = 0;
-
-       while (!(zr36050_read_status1(ptr) & 0x4)) {
-               udelay(1);
-               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
-                       dprintk(1,
-                               "%s: timeout at wait_end (last status: 0x%02x)\n",
-                               ptr->name, ptr->status1);
-                       break;
-               }
-       }
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from memory the SOF marker
-   ========================================================================= */
-
-static int
-zr36050_basic_test (struct zr36050 *ptr)
-{
-       zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
-       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
-       if ((zr36050_read(ptr, ZR050_SOF_IDX) |
-            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
-       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
-       if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
-            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-
-       zr36050_wait_end(ptr);
-       if ((ptr->status1 & 0x4) == 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, jpeg processor failed (end flag)!\n",
-                       ptr->name);
-               return -EBUSY;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets
-   ========================================================================= */
-
-static int
-zr36050_pushit (struct zr36050 *ptr,
-               u16             startreg,
-               u16             len,
-               const char     *data)
-{
-       int i = 0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
-               startreg, len);
-       while (i < len) {
-               zr36050_write(ptr, startreg++, data[i++]);
-       }
-
-       return i;
-}
-
-/* =========================================================================
-   Basic datasets:
-
-   jpeg baseline setup data (you find it on lots places in internet, or just
-   extract it from any regular .jpg image...)
-
-   Could be variable, but until it's not needed it they are just fixed to save
-   memory. Otherwise expand zr36050 structure with arrays, push the values to
-   it and initalize from there, as e.g. the linux zr36057/60 driver does it.
-   ========================================================================= */
-
-static const char zr36050_dqt[0x86] = {
-       0xff, 0xdb,             //Marker: DQT
-       0x00, 0x84,             //Length: 2*65+2
-       0x00,                   //Pq,Tq first table
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-       0x01,                   //Pq,Tq second table
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-};
-
-static const char zr36050_dht[0x1a4] = {
-       0xff, 0xc4,             //Marker: DHT
-       0x01, 0xa2,             //Length: 2*AC, 2*DC
-       0x00,                   //DC first table
-       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x01,                   //DC second table
-       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x10,                   //AC first table
-       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
-       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
-       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
-       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
-       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
-       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
-       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
-       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-       0xF8, 0xF9, 0xFA,
-       0x11,                   //AC second table
-       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
-       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
-       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
-       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
-       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
-       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
-       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
-       0xF9, 0xFA
-};
-
-/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
-#define NO_OF_COMPONENTS          0x3  //Y,U,V
-#define BASELINE_PRECISION        0x8  //MCU size (?)
-static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
-static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
-static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
-
-/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
-static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
-static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
-
-/* =========================================================================
-   Local helper functions:
-
-   calculation and setup of parameter-dependent JPEG baseline segments
-   (needed for compression only)
-   ========================================================================= */
-
-/* ------------------------------------------------------------------------- */
-
-/* SOF (start of frame) segment depends on width, height and sampling ratio
-                        of each color component */
-
-static int
-zr36050_set_sof (struct zr36050 *ptr)
-{
-       char sof_data[34];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
-               ptr->width, ptr->height, NO_OF_COMPONENTS);
-       sof_data[0] = 0xff;
-       sof_data[1] = 0xc0;
-       sof_data[2] = 0x00;
-       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
-       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36050
-       sof_data[5] = (ptr->height) >> 8;
-       sof_data[6] = (ptr->height) & 0xff;
-       sof_data[7] = (ptr->width) >> 8;
-       sof_data[8] = (ptr->width) & 0xff;
-       sof_data[9] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sof_data[10 + (i * 3)] = i;     // index identifier
-               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]);  // sampling ratios
-               sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
-       }
-       return zr36050_pushit(ptr, ZR050_SOF_IDX,
-                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* SOS (start of scan) segment depends on the used scan components
-                       of each color component */
-
-static int
-zr36050_set_sos (struct zr36050 *ptr)
-{
-       char sos_data[16];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOS\n", ptr->name);
-       sos_data[0] = 0xff;
-       sos_data[1] = 0xda;
-       sos_data[2] = 0x00;
-       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
-       sos_data[4] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sos_data[5 + (i * 2)] = i;      // index
-               sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i];   // AC/DC tbl.sel.
-       }
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
-       return zr36050_pushit(ptr, ZR050_SOS1_IDX,
-                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
-                             sos_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* DRI (define restart interval) */
-
-static int
-zr36050_set_dri (struct zr36050 *ptr)
-{
-       char dri_data[6];       // max. size of register set
-
-       dprintk(3, "%s: write DRI\n", ptr->name);
-       dri_data[0] = 0xff;
-       dri_data[1] = 0xdd;
-       dri_data[2] = 0x00;
-       dri_data[3] = 0x04;
-       dri_data[4] = ptr->dri >> 8;
-       dri_data[5] = ptr->dri & 0xff;
-       return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
-}
-
-/* =========================================================================
-   Setup function:
-
-   Setup compression/decompression of Zoran's JPEG processor
-   ( see also zoran 36050 manual )
-
-   ... sorry for the spaghetti code ...
-   ========================================================================= */
-static void
-zr36050_init (struct zr36050 *ptr)
-{
-       int sum = 0;
-       long bitcnt, tmp;
-
-       if (ptr->mode == CODEC_DO_COMPRESSION) {
-               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
-
-               /* 050 communicates with 057 in master mode */
-               zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
-
-               /* encoding table preload for compression */
-               zr36050_write(ptr, ZR050_MODE,
-                             ZR050_MO_COMP | ZR050_MO_TLM);
-               zr36050_write(ptr, ZR050_OPTIONS, 0);
-
-               /* disable all IRQs */
-               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
-               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
-
-               /* volume control settings */
-               /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
-               zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
-               zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
-
-               zr36050_write(ptr, ZR050_AF_HI, 0xff);
-               zr36050_write(ptr, ZR050_AF_M, 0xff);
-               zr36050_write(ptr, ZR050_AF_LO, 0xff);
-
-               /* setup the variable jpeg tables */
-               sum += zr36050_set_sof(ptr);
-               sum += zr36050_set_sos(ptr);
-               sum += zr36050_set_dri(ptr);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name);
-               sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
-                                     sizeof(zr36050_dqt), zr36050_dqt);
-               sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
-                                     sizeof(zr36050_dht), zr36050_dht);
-               zr36050_write(ptr, ZR050_APP_IDX, 0xff);
-               zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
-               zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
-               zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
-               sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
-                                     ptr->app.data) + 4;
-               zr36050_write(ptr, ZR050_COM_IDX, 0xff);
-               zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
-               zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
-               zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
-               sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
-                                     ptr->com.data) + 4;
-
-               /* do the internal huffman table preload */
-               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
-
-               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
-               zr36050_wait_end(ptr);
-               dprintk(2, "%s: Status after table preload: 0x%02x\n",
-                       ptr->name, ptr->status1);
-
-               if ((ptr->status1 & 0x4) == 0) {
-                       dprintk(1, KERN_ERR "%s: init aborted!\n",
-                               ptr->name);
-                       return; // something is wrong, its timed out!!!!
-               }
-
-               /* setup misc. data for compression (target code sizes) */
-
-               /* size of compressed code to reach without header data */
-               sum = ptr->real_code_vol - sum;
-               bitcnt = sum << 3;      /* need the size in bits */
-
-               tmp = bitcnt >> 16;
-               dprintk(3,
-                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
-                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
-               zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
-
-               bitcnt -= bitcnt >> 7;  // bits without stuffing
-               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
-
-               tmp = bitcnt >> 16;
-               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
-                       ptr->name, bitcnt, tmp);
-               zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
-
-               /* compression setup with or without bitrate control */
-               zr36050_write(ptr, ZR050_MODE,
-                             ZR050_MO_COMP | ZR050_MO_PASS2 |
-                             (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
-
-               /* this headers seem to deliver "valid AVI" jpeg frames */
-               zr36050_write(ptr, ZR050_MARKERS_EN,
-                             ZR050_ME_DQT | ZR050_ME_DHT |
-                             ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
-                             ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
-       } else {
-               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
-
-               /* 050 communicates with 055 in master mode */
-               zr36050_write(ptr, ZR050_HARDWARE,
-                             ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
-
-               /* encoding table preload */
-               zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
-
-               /* disable all IRQs */
-               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
-               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
-
-               dprintk(3, "%s: write DHT\n", ptr->name);
-               zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
-                              zr36050_dht);
-
-               /* do the internal huffman table preload */
-               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
-
-               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
-               zr36050_wait_end(ptr);
-               dprintk(2, "%s: Status after table preload: 0x%02x\n",
-                       ptr->name, ptr->status1);
-
-               if ((ptr->status1 & 0x4) == 0) {
-                       dprintk(1, KERN_ERR "%s: init aborted!\n",
-                               ptr->name);
-                       return; // something is wrong, its timed out!!!!
-               }
-
-               /* setup misc. data for expansion */
-               zr36050_write(ptr, ZR050_MODE, 0);
-               zr36050_write(ptr, ZR050_MARKERS_EN, 0);
-       }
-
-       /* adr on selected, to allow GO from master */
-       zr36050_read(ptr, 0);
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36050_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36050_init(ptr);
-
-       return 0;
-}
-
-/* set picture size (norm is ignored as the codec doesn't know about it) */
-static int
-zr36050_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-       int size;
-
-       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
-               ptr->name, norm->HStart, norm->VStart,
-               cap->x, cap->y, cap->width, cap->height,
-               cap->decimation, cap->quality);
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y and norm for now ... */
-       ptr->width = cap->width / (cap->decimation & 0xff);
-       ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
-
-       /* (KM) JPEG quality */
-       size = ptr->width * ptr->height;
-       size *= 16; /* size in bits */
-       /* apply quality setting */
-       size = size * cap->quality / 200;
-
-       /* Minimum: 1kb */
-       if (size < 8192)
-               size = 8192;
-       /* Maximum: 7/8 of code buffer */
-       if (size > ptr->total_code_vol * 7)
-               size = ptr->total_code_vol * 7;
-
-       ptr->real_code_vol = size >> 3; /* in bytes */
-
-       /* Set max_block_vol here (previously in zr36050_init, moved
-        * here for consistency with zr36060 code */
-       zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36050_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               zr36050_read_status1(ptr);
-               *ival = ptr->status1;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = CODEC_MODE_BJPG;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != CODEC_MODE_BJPG)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = ptr->total_code_vol;
-               break;
-
-       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->total_code_vol = *ival;
-               /* (Kieran Morrissey)
-                * code copied from zr36060.c to ensure proper bitrate */
-               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-               break;
-
-       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = zr36050_read_scalefactor(ptr);
-               break;
-
-       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->scalefact = *ival;
-               break;
-
-       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               *app = ptr->app;
-               break;
-       }
-
-       case CODEC_S_JPEG_APP_DATA: {    /* set appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               ptr->app = *app;
-               break;
-       }
-
-       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               *com = ptr->com;
-               break;
-       }
-
-       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               ptr->com = *com;
-               break;
-       }
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36050_unset (struct videocodec *codec)
-{
-       struct zr36050 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36050_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36050_setup (struct videocodec *codec)
-{
-       struct zr36050 *ptr;
-       int res;
-
-       dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n",
-               zr36050_codecs);
-
-       if (zr36050_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36050: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
-                zr36050_codecs);
-       ptr->num = zr36050_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36050_basic_test(ptr);
-       if (res < 0) {
-               zr36050_unset(codec);
-               return res;
-       }
-       //final setup
-       memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
-       memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
-
-       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
-                                * (what is the difference?) */
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 384;
-       ptr->height = 288;
-       ptr->total_code_vol = 16000;
-       ptr->max_block_vol = 240;
-       ptr->scalefact = 0x100;
-       ptr->dri = 1;
-
-       /* no app/com marker by default */
-       ptr->app.appn = 0;
-       ptr->app.len = 0;
-       ptr->com.len = 0;
-
-       zr36050_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec attached and running\n",
-               ptr->name);
-
-       return 0;
-}
-
-static const struct videocodec zr36050_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36050",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER,
-       .type = CODEC_TYPE_ZR36050,
-       .setup = zr36050_setup, // functionality
-       .unset = zr36050_unset,
-       .set_mode = zr36050_set_mode,
-       .set_video = zr36050_set_video,
-       .control = zr36050_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36050_init_module (void)
-{
-       //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
-       zr36050_codecs = 0;
-       return videocodec_register(&zr36050_codec);
-}
-
-static void __exit
-zr36050_cleanup_module (void)
-{
-       if (zr36050_codecs) {
-               dprintk(1,
-                       "zr36050: something's wrong - %d codecs left somehow.\n",
-                       zr36050_codecs);
-       }
-       videocodec_unregister(&zr36050_codec);
-}
-
-module_init(zr36050_init_module);
-module_exit(zr36050_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
-                  ZR050_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zr36050.h b/drivers/media/video/zr36050.h
deleted file mode 100644 (file)
index 9f52f0c..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Zoran ZR36050 basic configuration functions - header file
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36050.h,v 1.1.2.2 2003/01/14 21:18:22 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 ZR36050_H
-#define ZR36050_H
-
-#include "videocodec.h"
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36050 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // last coder status
-       __u8 status1;
-       // actual coder setup
-       int mode;
-
-       __u16 width;
-       __u16 height;
-
-       __u16 bitrate_ctrl;
-
-       __u32 total_code_vol;
-       __u32 real_code_vol;
-       __u16 max_block_vol;
-
-       __u8 h_samp_ratio[8];
-       __u8 v_samp_ratio[8];
-       __u16 scalefact;
-       __u16 dri;
-
-       /* com/app marker */
-       struct jpeg_com_marker com;
-       struct jpeg_app_marker app;
-};
-
-/* zr36050 register addresses */
-#define ZR050_GO                  0x000
-#define ZR050_HARDWARE            0x002
-#define ZR050_MODE                0x003
-#define ZR050_OPTIONS             0x004
-#define ZR050_MBCV                0x005
-#define ZR050_MARKERS_EN          0x006
-#define ZR050_INT_REQ_0           0x007
-#define ZR050_INT_REQ_1           0x008
-#define ZR050_TCV_NET_HI          0x009
-#define ZR050_TCV_NET_MH          0x00a
-#define ZR050_TCV_NET_ML          0x00b
-#define ZR050_TCV_NET_LO          0x00c
-#define ZR050_TCV_DATA_HI         0x00d
-#define ZR050_TCV_DATA_MH         0x00e
-#define ZR050_TCV_DATA_ML         0x00f
-#define ZR050_TCV_DATA_LO         0x010
-#define ZR050_SF_HI               0x011
-#define ZR050_SF_LO               0x012
-#define ZR050_AF_HI               0x013
-#define ZR050_AF_M                0x014
-#define ZR050_AF_LO               0x015
-#define ZR050_ACV_HI              0x016
-#define ZR050_ACV_MH              0x017
-#define ZR050_ACV_ML              0x018
-#define ZR050_ACV_LO              0x019
-#define ZR050_ACT_HI              0x01a
-#define ZR050_ACT_MH              0x01b
-#define ZR050_ACT_ML              0x01c
-#define ZR050_ACT_LO              0x01d
-#define ZR050_ACV_TRUN_HI         0x01e
-#define ZR050_ACV_TRUN_MH         0x01f
-#define ZR050_ACV_TRUN_ML         0x020
-#define ZR050_ACV_TRUN_LO         0x021
-#define ZR050_STATUS_0            0x02e
-#define ZR050_STATUS_1            0x02f
-
-#define ZR050_SOF_IDX             0x040
-#define ZR050_SOS1_IDX            0x07a
-#define ZR050_SOS2_IDX            0x08a
-#define ZR050_SOS3_IDX            0x09a
-#define ZR050_SOS4_IDX            0x0aa
-#define ZR050_DRI_IDX             0x0c0
-#define ZR050_DNL_IDX             0x0c6
-#define ZR050_DQT_IDX             0x0cc
-#define ZR050_DHT_IDX             0x1d4
-#define ZR050_APP_IDX             0x380
-#define ZR050_COM_IDX             0x3c0
-
-/* zr36050 hardware register bits */
-
-#define ZR050_HW_BSWD                0x80
-#define ZR050_HW_MSTR                0x40
-#define ZR050_HW_DMA                 0x20
-#define ZR050_HW_CFIS_1_CLK          0x00
-#define ZR050_HW_CFIS_2_CLK          0x04
-#define ZR050_HW_CFIS_3_CLK          0x08
-#define ZR050_HW_CFIS_4_CLK          0x0C
-#define ZR050_HW_CFIS_5_CLK          0x10
-#define ZR050_HW_CFIS_6_CLK          0x14
-#define ZR050_HW_CFIS_7_CLK          0x18
-#define ZR050_HW_CFIS_8_CLK          0x1C
-#define ZR050_HW_BELE                0x01
-
-/* zr36050 mode register bits */
-
-#define ZR050_MO_COMP                0x80
-#define ZR050_MO_COMP                0x80
-#define ZR050_MO_ATP                 0x40
-#define ZR050_MO_PASS2               0x20
-#define ZR050_MO_TLM                 0x10
-#define ZR050_MO_DCONLY              0x08
-#define ZR050_MO_BRC                 0x04
-
-#define ZR050_MO_ATP                 0x40
-#define ZR050_MO_PASS2               0x20
-#define ZR050_MO_TLM                 0x10
-#define ZR050_MO_DCONLY              0x08
-
-/* zr36050 option register bits */
-
-#define ZR050_OP_NSCN_1              0x00
-#define ZR050_OP_NSCN_2              0x20
-#define ZR050_OP_NSCN_3              0x40
-#define ZR050_OP_NSCN_4              0x60
-#define ZR050_OP_NSCN_5              0x80
-#define ZR050_OP_NSCN_6              0xA0
-#define ZR050_OP_NSCN_7              0xC0
-#define ZR050_OP_NSCN_8              0xE0
-#define ZR050_OP_OVF                 0x10
-
-
-/* zr36050 markers-enable register bits */
-
-#define ZR050_ME_APP                 0x80
-#define ZR050_ME_COM                 0x40
-#define ZR050_ME_DRI                 0x20
-#define ZR050_ME_DQT                 0x10
-#define ZR050_ME_DHT                 0x08
-#define ZR050_ME_DNL                 0x04
-#define ZR050_ME_DQTI                0x02
-#define ZR050_ME_DHTI                0x01
-
-/* zr36050 status0/1 register bit masks */
-
-#define ZR050_ST_RST_MASK            0x20
-#define ZR050_ST_SOF_MASK            0x02
-#define ZR050_ST_SOS_MASK            0x02
-#define ZR050_ST_DATRDY_MASK         0x80
-#define ZR050_ST_MRKDET_MASK         0x40
-#define ZR050_ST_RFM_MASK            0x10
-#define ZR050_ST_RFD_MASK            0x08
-#define ZR050_ST_END_MASK            0x04
-#define ZR050_ST_TCVOVF_MASK         0x02
-#define ZR050_ST_DATOVF_MASK         0x01
-
-/* pixel component idx */
-
-#define ZR050_Y_COMPONENT         0
-#define ZR050_U_COMPONENT         1
-#define ZR050_V_COMPONENT         2
-
-#endif                         /*fndef ZR36050_H */
diff --git a/drivers/media/video/zr36057.h b/drivers/media/video/zr36057.h
deleted file mode 100644 (file)
index 54c9362..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * zr36057.h - zr36057 register offsets
- *
- * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 _ZR36057_H_
-#define _ZR36057_H_
-
-
-/* Zoran ZR36057 registers */
-
-#define ZR36057_VFEHCR          0x000  /* Video Front End, Horizontal Configuration Register */
-#define ZR36057_VFEHCR_HSPol            (1<<30)
-#define ZR36057_VFEHCR_HStart           10
-#define ZR36057_VFEHCR_HEnd            0
-#define ZR36057_VFEHCR_Hmask           0x3ff
-
-#define ZR36057_VFEVCR          0x004  /* Video Front End, Vertical Configuration Register */
-#define ZR36057_VFEVCR_VSPol            (1<<30)
-#define ZR36057_VFEVCR_VStart           10
-#define ZR36057_VFEVCR_VEnd            0
-#define ZR36057_VFEVCR_Vmask           0x3ff
-
-#define ZR36057_VFESPFR         0x008  /* Video Front End, Scaler and Pixel Format Register */
-#define ZR36057_VFESPFR_ExtFl           (1<<26)
-#define ZR36057_VFESPFR_TopField        (1<<25)
-#define ZR36057_VFESPFR_VCLKPol         (1<<24)
-#define ZR36057_VFESPFR_HFilter         21
-#define ZR36057_VFESPFR_HorDcm          14
-#define ZR36057_VFESPFR_VerDcm          8
-#define ZR36057_VFESPFR_DispMode        6
-#define ZR36057_VFESPFR_YUV422          (0<<3)
-#define ZR36057_VFESPFR_RGB888          (1<<3)
-#define ZR36057_VFESPFR_RGB565          (2<<3)
-#define ZR36057_VFESPFR_RGB555          (3<<3)
-#define ZR36057_VFESPFR_ErrDif          (1<<2)
-#define ZR36057_VFESPFR_Pack24          (1<<1)
-#define ZR36057_VFESPFR_LittleEndian    (1<<0)
-
-#define ZR36057_VDTR            0x00c  /* Video Display "Top" Register */
-
-#define ZR36057_VDBR            0x010  /* Video Display "Bottom" Register */
-
-#define ZR36057_VSSFGR          0x014  /* Video Stride, Status, and Frame Grab Register */
-#define ZR36057_VSSFGR_DispStride       16
-#define ZR36057_VSSFGR_VidOvf           (1<<8)
-#define ZR36057_VSSFGR_SnapShot         (1<<1)
-#define ZR36057_VSSFGR_FrameGrab        (1<<0)
-
-#define ZR36057_VDCR            0x018  /* Video Display Configuration Register */
-#define ZR36057_VDCR_VidEn              (1<<31)
-#define ZR36057_VDCR_MinPix             24
-#define ZR36057_VDCR_Triton             (1<<24)
-#define ZR36057_VDCR_VidWinHt           12
-#define ZR36057_VDCR_VidWinWid          0
-
-#define ZR36057_MMTR            0x01c  /* Masking Map "Top" Register */
-
-#define ZR36057_MMBR            0x020  /* Masking Map "Bottom" Register */
-
-#define ZR36057_OCR             0x024  /* Overlay Control Register */
-#define ZR36057_OCR_OvlEnable           (1 << 15)
-#define ZR36057_OCR_MaskStride          0
-
-#define ZR36057_SPGPPCR         0x028  /* System, PCI, and General Purpose Pins Control Register */
-#define ZR36057_SPGPPCR_SoftReset      (1<<24)
-
-#define ZR36057_GPPGCR1         0x02c  /* General Purpose Pins and GuestBus Control Register (1) */
-
-#define ZR36057_MCSAR           0x030  /* MPEG Code Source Address Register */
-
-#define ZR36057_MCTCR           0x034  /* MPEG Code Transfer Control Register */
-#define ZR36057_MCTCR_CodTime           (1 << 30)
-#define ZR36057_MCTCR_CEmpty            (1 << 29)
-#define ZR36057_MCTCR_CFlush            (1 << 28)
-#define ZR36057_MCTCR_CodGuestID       20
-#define ZR36057_MCTCR_CodGuestReg      16
-
-#define ZR36057_MCMPR           0x038  /* MPEG Code Memory Pointer Register */
-
-#define ZR36057_ISR             0x03c  /* Interrupt Status Register */
-#define ZR36057_ISR_GIRQ1               (1<<30)
-#define ZR36057_ISR_GIRQ0               (1<<29)
-#define ZR36057_ISR_CodRepIRQ           (1<<28)
-#define ZR36057_ISR_JPEGRepIRQ          (1<<27)
-
-#define ZR36057_ICR             0x040  /* Interrupt Control Register */
-#define ZR36057_ICR_GIRQ1               (1<<30)
-#define ZR36057_ICR_GIRQ0               (1<<29)
-#define ZR36057_ICR_CodRepIRQ           (1<<28)
-#define ZR36057_ICR_JPEGRepIRQ          (1<<27)
-#define ZR36057_ICR_IntPinEn            (1<<24)
-
-#define ZR36057_I2CBR           0x044  /* I2C Bus Register */
-#define ZR36057_I2CBR_SDA              (1<<1)
-#define ZR36057_I2CBR_SCL              (1<<0)
-
-#define ZR36057_JMC             0x100  /* JPEG Mode and Control */
-#define ZR36057_JMC_JPG                 (1 << 31)
-#define ZR36057_JMC_JPGExpMode          (0 << 29)
-#define ZR36057_JMC_JPGCmpMode          (1 << 29)
-#define ZR36057_JMC_MJPGExpMode         (2 << 29)
-#define ZR36057_JMC_MJPGCmpMode         (3 << 29)
-#define ZR36057_JMC_RTBUSY_FB           (1 << 6)
-#define ZR36057_JMC_Go_en               (1 << 5)
-#define ZR36057_JMC_SyncMstr            (1 << 4)
-#define ZR36057_JMC_Fld_per_buff        (1 << 3)
-#define ZR36057_JMC_VFIFO_FB            (1 << 2)
-#define ZR36057_JMC_CFIFO_FB            (1 << 1)
-#define ZR36057_JMC_Stll_LitEndian      (1 << 0)
-
-#define ZR36057_JPC             0x104  /* JPEG Process Control */
-#define ZR36057_JPC_P_Reset             (1 << 7)
-#define ZR36057_JPC_CodTrnsEn           (1 << 5)
-#define ZR36057_JPC_Active              (1 << 0)
-
-#define ZR36057_VSP             0x108  /* Vertical Sync Parameters */
-#define ZR36057_VSP_VsyncSize           16
-#define ZR36057_VSP_FrmTot              0
-
-#define ZR36057_HSP             0x10c  /* Horizontal Sync Parameters */
-#define ZR36057_HSP_HsyncStart          16
-#define ZR36057_HSP_LineTot             0
-
-#define ZR36057_FHAP            0x110  /* Field Horizontal Active Portion */
-#define ZR36057_FHAP_NAX                16
-#define ZR36057_FHAP_PAX                0
-
-#define ZR36057_FVAP            0x114  /* Field Vertical Active Portion */
-#define ZR36057_FVAP_NAY                16
-#define ZR36057_FVAP_PAY                0
-
-#define ZR36057_FPP             0x118  /* Field Process Parameters */
-#define ZR36057_FPP_Odd_Even            (1 << 0)
-
-#define ZR36057_JCBA            0x11c  /* JPEG Code Base Address */
-
-#define ZR36057_JCFT            0x120  /* JPEG Code FIFO Threshold */
-
-#define ZR36057_JCGI            0x124  /* JPEG Codec Guest ID */
-#define ZR36057_JCGI_JPEGuestID         4
-#define ZR36057_JCGI_JPEGuestReg        0
-
-#define ZR36057_GCR2            0x12c  /* GuestBus Control Register (2) */
-
-#define ZR36057_POR             0x200  /* Post Office Register */
-#define ZR36057_POR_POPen               (1<<25)
-#define ZR36057_POR_POTime              (1<<24)
-#define ZR36057_POR_PODir               (1<<23)
-
-#define ZR36057_STR             0x300  /* "Still" Transfer Register */
-
-#endif
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
deleted file mode 100644 (file)
index 8e74054..0000000
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * Zoran ZR36060 basic configuration functions
- *
- * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * ------------------------------------------------------------------------
- */
-
-#define ZR060_VERSION "v0.7"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* includes for structures and defines regarding video
-   #include<linux/videodev.h> */
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-//#include<errno.h>
-
-/* headerfile of this module */
-#include "zr36060.h"
-
-/* codec io API */
-#include "videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36060_codecs;
-
-static int low_bitrate;
-module_param(low_bitrate, bool, 0);
-MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate");
-
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36060_read (struct zr36060 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value = (ptr->codec->master_data->readreg(ptr->codec,
-                                                         reg)) & 0xff;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value);
-
-       return value;
-}
-
-static void
-zr36060_write(struct zr36060 *ptr,
-             u16             reg,
-             u8              value)
-{
-       //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg);
-       dprintk(4, "0x%02x @0x%04x\n", value, reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg)
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   status read
-   ========================================================================= */
-
-/* status is kept in datastructure */
-static u8
-zr36060_read_status (struct zr36060 *ptr)
-{
-       ptr->status = zr36060_read(ptr, ZR060_CFSR);
-
-       zr36060_read(ptr, 0);
-       return ptr->status;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   scale factor read
-   ========================================================================= */
-
-/* scale factor is kept in datastructure */
-static u16
-zr36060_read_scalefactor (struct zr36060 *ptr)
-{
-       ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
-                        (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
-
-       /* leave 0 selected for an eventually GO from master */
-       zr36060_read(ptr, 0);
-       return ptr->scalefact;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   wait if codec is ready to proceed (end of processing) or time is over
-   ========================================================================= */
-
-static void
-zr36060_wait_end (struct zr36060 *ptr)
-{
-       int i = 0;
-
-       while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
-               udelay(1);
-               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
-                       dprintk(1,
-                               "%s: timeout at wait_end (last status: 0x%02x)\n",
-                               ptr->name, ptr->status);
-                       break;
-               }
-       }
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from memory the SOF marker
-   ========================================================================= */
-
-static int
-zr36060_basic_test (struct zr36060 *ptr)
-{
-       if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
-           (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-
-       zr36060_wait_end(ptr);
-       if (ptr->status & ZR060_CFSR_Busy) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, jpeg processor failed (end flag)!\n",
-                       ptr->name);
-               return -EBUSY;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets
-   ========================================================================= */
-
-static int
-zr36060_pushit (struct zr36060 *ptr,
-               u16             startreg,
-               u16             len,
-               const char     *data)
-{
-       int i = 0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
-               startreg, len);
-       while (i < len) {
-               zr36060_write(ptr, startreg++, data[i++]);
-       }
-
-       return i;
-}
-
-/* =========================================================================
-   Basic datasets:
-
-   jpeg baseline setup data (you find it on lots places in internet, or just
-   extract it from any regular .jpg image...)
-
-   Could be variable, but until it's not needed it they are just fixed to save
-   memory. Otherwise expand zr36060 structure with arrays, push the values to
-   it and initalize from there, as e.g. the linux zr36057/60 driver does it.
-   ========================================================================= */
-
-static const char zr36060_dqt[0x86] = {
-       0xff, 0xdb,             //Marker: DQT
-       0x00, 0x84,             //Length: 2*65+2
-       0x00,                   //Pq,Tq first table
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-       0x01,                   //Pq,Tq second table
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-};
-
-static const char zr36060_dht[0x1a4] = {
-       0xff, 0xc4,             //Marker: DHT
-       0x01, 0xa2,             //Length: 2*AC, 2*DC
-       0x00,                   //DC first table
-       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x01,                   //DC second table
-       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x10,                   //AC first table
-       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
-       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
-       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
-       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
-       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
-       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
-       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
-       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-       0xF8, 0xF9, 0xFA,
-       0x11,                   //AC second table
-       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
-       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
-       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
-       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
-       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
-       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
-       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
-       0xF9, 0xFA
-};
-
-/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
-#define NO_OF_COMPONENTS          0x3  //Y,U,V
-#define BASELINE_PRECISION        0x8  //MCU size (?)
-static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
-static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
-static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
-
-/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
-static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
-static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
-
-/* =========================================================================
-   Local helper functions:
-
-   calculation and setup of parameter-dependent JPEG baseline segments
-   (needed for compression only)
-   ========================================================================= */
-
-/* ------------------------------------------------------------------------- */
-
-/* SOF (start of frame) segment depends on width, height and sampling ratio
-                        of each color component */
-
-static int
-zr36060_set_sof (struct zr36060 *ptr)
-{
-       char sof_data[34];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
-               ptr->width, ptr->height, NO_OF_COMPONENTS);
-       sof_data[0] = 0xff;
-       sof_data[1] = 0xc0;
-       sof_data[2] = 0x00;
-       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
-       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36060
-       sof_data[5] = (ptr->height) >> 8;
-       sof_data[6] = (ptr->height) & 0xff;
-       sof_data[7] = (ptr->width) >> 8;
-       sof_data[8] = (ptr->width) & 0xff;
-       sof_data[9] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sof_data[10 + (i * 3)] = i;     // index identifier
-               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
-                                        (ptr->v_samp_ratio[i]); // sampling ratios
-               sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
-       }
-       return zr36060_pushit(ptr, ZR060_SOF_IDX,
-                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* SOS (start of scan) segment depends on the used scan components
-                       of each color component */
-
-static int
-zr36060_set_sos (struct zr36060 *ptr)
-{
-       char sos_data[16];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOS\n", ptr->name);
-       sos_data[0] = 0xff;
-       sos_data[1] = 0xda;
-       sos_data[2] = 0x00;
-       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
-       sos_data[4] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sos_data[5 + (i * 2)] = i;      // index
-               sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
-                                       zr36060_ta[i]; // AC/DC tbl.sel.
-       }
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
-       return zr36060_pushit(ptr, ZR060_SOS_IDX,
-                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
-                             sos_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* DRI (define restart interval) */
-
-static int
-zr36060_set_dri (struct zr36060 *ptr)
-{
-       char dri_data[6];       // max. size of register set
-
-       dprintk(3, "%s: write DRI\n", ptr->name);
-       dri_data[0] = 0xff;
-       dri_data[1] = 0xdd;
-       dri_data[2] = 0x00;
-       dri_data[3] = 0x04;
-       dri_data[4] = (ptr->dri) >> 8;
-       dri_data[5] = (ptr->dri) & 0xff;
-       return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
-}
-
-/* =========================================================================
-   Setup function:
-
-   Setup compression/decompression of Zoran's JPEG processor
-   ( see also zoran 36060 manual )
-
-   ... sorry for the spaghetti code ...
-   ========================================================================= */
-static void
-zr36060_init (struct zr36060 *ptr)
-{
-       int sum = 0;
-       long bitcnt, tmp;
-
-       if (ptr->mode == CODEC_DO_COMPRESSION) {
-               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
-
-               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-               /* 060 communicates with 067 in master mode */
-               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
-
-               /* Compression with or without variable scale factor */
-               /*FIXME: What about ptr->bitrate_ctrl? */
-               zr36060_write(ptr, ZR060_CMR,
-                             ZR060_CMR_Comp | ZR060_CMR_Pass2 |
-                             ZR060_CMR_BRB);
-
-               /* Must be zero */
-               zr36060_write(ptr, ZR060_MBZ, 0x00);
-               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
-               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
-
-               /* Disable all IRQs - no DataErr means autoreset */
-               zr36060_write(ptr, ZR060_IMR, 0);
-
-               /* volume control settings */
-               zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
-               zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
-
-               zr36060_write(ptr, ZR060_AF_HI, 0xff);
-               zr36060_write(ptr, ZR060_AF_M, 0xff);
-               zr36060_write(ptr, ZR060_AF_LO, 0xff);
-
-               /* setup the variable jpeg tables */
-               sum += zr36060_set_sof(ptr);
-               sum += zr36060_set_sos(ptr);
-               sum += zr36060_set_dri(ptr);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               sum +=
-                   zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
-                                  zr36060_dqt);
-               sum +=
-                   zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
-                                  zr36060_dht);
-               zr36060_write(ptr, ZR060_APP_IDX, 0xff);
-               zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
-               zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
-               zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
-               sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
-                                     ptr->app.data) + 4;
-               zr36060_write(ptr, ZR060_COM_IDX, 0xff);
-               zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
-               zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
-               zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
-               sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
-                                     ptr->com.data) + 4;
-
-               /* setup misc. data for compression (target code sizes) */
-
-               /* size of compressed code to reach without header data */
-               sum = ptr->real_code_vol - sum;
-               bitcnt = sum << 3;      /* need the size in bits */
-
-               tmp = bitcnt >> 16;
-               dprintk(3,
-                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
-                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
-               zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
-
-               bitcnt -= bitcnt >> 7;  // bits without stuffing
-               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
-
-               tmp = bitcnt >> 16;
-               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
-                       ptr->name, bitcnt, tmp);
-               zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
-
-               /* JPEG markers to be included in the compressed stream */
-               zr36060_write(ptr, ZR060_MER,
-                             ZR060_MER_DQT | ZR060_MER_DHT |
-                             ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
-                             ((ptr->app.len > 0) ? ZR060_MER_App : 0));
-
-               /* Setup the Video Frontend */
-               /* Limit pixel range to 16..235 as per CCIR-601 */
-               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
-
-       } else {
-               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
-
-               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-               /* 060 communicates with 067 in master mode */
-               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
-
-               /* Decompression */
-               zr36060_write(ptr, ZR060_CMR, 0);
-
-               /* Must be zero */
-               zr36060_write(ptr, ZR060_MBZ, 0x00);
-               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
-               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
-
-               /* Disable all IRQs - no DataErr means autoreset */
-               zr36060_write(ptr, ZR060_IMR, 0);
-
-               /* setup misc. data for expansion */
-               zr36060_write(ptr, ZR060_MER, 0);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
-                              zr36060_dht);
-
-               /* Setup the Video Frontend */
-               //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt);
-               //this doesn't seem right and doesn't work...
-               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
-       }
-
-       /* Load the tables */
-       zr36060_write(ptr, ZR060_LOAD,
-                     ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
-       zr36060_wait_end(ptr);
-       dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
-               ptr->status);
-
-       if (ptr->status & ZR060_CFSR_Busy) {
-               dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
-               return;         // something is wrong, its timed out!!!!
-       }
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36060_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36060_init(ptr);
-
-       return 0;
-}
-
-/* set picture size (norm is ignored as the codec doesn't know about it) */
-static int
-zr36060_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-       u32 reg;
-       int size;
-
-       dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
-               cap->x, cap->y, cap->width, cap->height, cap->decimation);
-
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y and norm for now ... */
-       ptr->width = cap->width / (cap->decimation & 0xff);
-       ptr->height = cap->height / (cap->decimation >> 8);
-
-       zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-       /* Note that VSPol/HSPol bits in zr36060 have the opposite
-        * meaning of their zr360x7 counterparts with the same names
-        * N.b. for VSPol this is only true if FIVEdge = 0 (default,
-        * left unchanged here - in accordance with datasheet).
-       */
-       reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
-           | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
-           | (pol->field_pol ? ZR060_VPR_FIPol : 0)
-           | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
-           | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
-           | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
-           | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
-           | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
-       zr36060_write(ptr, ZR060_VPR, reg);
-
-       reg = 0;
-       switch (cap->decimation & 0xff) {
-       default:
-       case 1:
-               break;
-
-       case 2:
-               reg |= ZR060_SR_HScale2;
-               break;
-
-       case 4:
-               reg |= ZR060_SR_HScale4;
-               break;
-       }
-
-       switch (cap->decimation >> 8) {
-       default:
-       case 1:
-               break;
-
-       case 2:
-               reg |= ZR060_SR_VScale;
-               break;
-       }
-       zr36060_write(ptr, ZR060_SR, reg);
-
-       zr36060_write(ptr, ZR060_BCR_Y, 0x00);
-       zr36060_write(ptr, ZR060_BCR_U, 0x80);
-       zr36060_write(ptr, ZR060_BCR_V, 0x80);
-
-       /* sync generator */
-
-       reg = norm->Ht - 1;     /* Vtotal */
-       zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
-
-       reg = norm->Wt - 1;     /* Htotal */
-       zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
-
-       reg = 6 - 1;            /* VsyncSize */
-       zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
-
-       //reg   = 30 - 1;               /* HsyncSize */
-///*CP*/        reg = (zr->params.norm == 1 ? 57 : 68);
-       reg = 68;
-       zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
-
-       reg = norm->VStart - 1; /* BVstart */
-       zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
-
-       reg += norm->Ha / 2;    /* BVend */
-       zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
-
-       reg = norm->HStart - 1; /* BHstart */
-       zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
-
-       reg += norm->Wa;        /* BHend */
-       zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
-
-       /* active area */
-       reg = cap->y + norm->VStart;    /* Vstart */
-       zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
-
-       reg += cap->height;     /* Vend */
-       zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
-
-       reg = cap->x + norm->HStart;    /* Hstart */
-       zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
-
-       reg += cap->width;      /* Hend */
-       zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
-
-       /* subimage area */
-       reg = norm->VStart - 4; /* SVstart */
-       zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
-
-       reg += norm->Ha / 2 + 8;        /* SVend */
-       zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
-
-       reg = norm->HStart /*+ 64 */  - 4;      /* SHstart */
-       zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
-
-       reg += norm->Wa + 8;    /* SHend */
-       zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
-
-       size = ptr->width * ptr->height;
-       /* Target compressed field size in bits: */
-       size = size * 16;       /* uncompressed size in bits */
-       /* (Ronald) by default, quality = 100 is a compression
-        * ratio 1:2. Setting low_bitrate (insmod option) sets
-        * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
-        * buz can't handle more at decimation=1... Use low_bitrate if
-        * you have a Buz, unless you know what you're doing */
-       size = size * cap->quality / (low_bitrate ? 400 : 200);
-       /* Lower limit (arbitrary, 1 KB) */
-       if (size < 8192)
-               size = 8192;
-       /* Upper limit: 7/8 of the code buffers */
-       if (size > ptr->total_code_vol * 7)
-               size = ptr->total_code_vol * 7;
-
-       ptr->real_code_vol = size >> 3; /* in bytes */
-
-       /* the MBCVR is the *maximum* block volume, according to the
-        * JPEG ISO specs, this shouldn't be used, since that allows
-        * for the best encoding quality. So set it to it's max value */
-       reg = ptr->max_block_vol;
-       zr36060_write(ptr, ZR060_MBCVR, reg);
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36060_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               zr36060_read_status(ptr);
-               *ival = ptr->status;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = CODEC_MODE_BJPG;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != CODEC_MODE_BJPG)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = ptr->total_code_vol;
-               break;
-
-       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->total_code_vol = *ival;
-               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-               break;
-
-       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = zr36060_read_scalefactor(ptr);
-               break;
-
-       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->scalefact = *ival;
-               break;
-
-       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               *app = ptr->app;
-               break;
-       }
-
-       case CODEC_S_JPEG_APP_DATA: {   /* set appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               ptr->app = *app;
-               break;
-       }
-
-       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               *com = ptr->com;
-               break;
-       }
-
-       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               ptr->com = *com;
-               break;
-       }
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36060_unset (struct videocodec *codec)
-{
-       struct zr36060 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36060_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36060_setup (struct videocodec *codec)
-{
-       struct zr36060 *ptr;
-       int res;
-
-       dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
-               zr36060_codecs);
-
-       if (zr36060_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36060: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
-                zr36060_codecs);
-       ptr->num = zr36060_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36060_basic_test(ptr);
-       if (res < 0) {
-               zr36060_unset(codec);
-               return res;
-       }
-       //final setup
-       memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
-       memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
-
-       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
-                                * (what is the difference?) */
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 384;
-       ptr->height = 288;
-       ptr->total_code_vol = 16000;    /* CHECKME */
-       ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-       ptr->max_block_vol = 240;       /* CHECKME, was 120 is 240 */
-       ptr->scalefact = 0x100;
-       ptr->dri = 1;           /* CHECKME, was 8 is 1 */
-
-       /* by default, no COM or APP markers - app should set those */
-       ptr->com.len = 0;
-       ptr->app.appn = 0;
-       ptr->app.len = 0;
-
-       zr36060_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec attached and running\n",
-               ptr->name);
-
-       return 0;
-}
-
-static const struct videocodec zr36060_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36060",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
-       .type = CODEC_TYPE_ZR36060,
-       .setup = zr36060_setup, // functionality
-       .unset = zr36060_unset,
-       .set_mode = zr36060_set_mode,
-       .set_video = zr36060_set_video,
-       .control = zr36060_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36060_init_module (void)
-{
-       //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION);
-       zr36060_codecs = 0;
-       return videocodec_register(&zr36060_codec);
-}
-
-static void __exit
-zr36060_cleanup_module (void)
-{
-       if (zr36060_codecs) {
-               dprintk(1,
-                       "zr36060: something's wrong - %d codecs left somehow.\n",
-                       zr36060_codecs);
-       }
-
-       /* however, we can't just stay alive */
-       videocodec_unregister(&zr36060_codec);
-}
-
-module_init(zr36060_init_module);
-module_exit(zr36060_cleanup_module);
-
-MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
-MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
-                  ZR060_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zr36060.h b/drivers/media/video/zr36060.h
deleted file mode 100644 (file)
index 914ffa4..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Zoran ZR36060 basic configuration functions - header file
- *
- * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * $Id: zr36060.h,v 1.1.1.1.2.3 2003/01/14 21:18:47 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 ZR36060_H
-#define ZR36060_H
-
-#include "videocodec.h"
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36060 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // last coder status
-       __u8 status;
-       // actual coder setup
-       int mode;
-
-       __u16 width;
-       __u16 height;
-
-       __u16 bitrate_ctrl;
-
-       __u32 total_code_vol;
-       __u32 real_code_vol;
-       __u16 max_block_vol;
-
-       __u8 h_samp_ratio[8];
-       __u8 v_samp_ratio[8];
-       __u16 scalefact;
-       __u16 dri;
-
-       /* app/com marker data */
-       struct jpeg_app_marker app;
-       struct jpeg_com_marker com;
-};
-
-/* ZR36060 register addresses */
-#define ZR060_LOAD                     0x000
-#define ZR060_CFSR                     0x001
-#define ZR060_CIR                      0x002
-#define ZR060_CMR                      0x003
-#define ZR060_MBZ                      0x004
-#define ZR060_MBCVR                    0x005
-#define ZR060_MER                      0x006
-#define ZR060_IMR                      0x007
-#define ZR060_ISR                      0x008
-#define ZR060_TCV_NET_HI               0x009
-#define ZR060_TCV_NET_MH               0x00a
-#define ZR060_TCV_NET_ML               0x00b
-#define ZR060_TCV_NET_LO               0x00c
-#define ZR060_TCV_DATA_HI              0x00d
-#define ZR060_TCV_DATA_MH              0x00e
-#define ZR060_TCV_DATA_ML              0x00f
-#define ZR060_TCV_DATA_LO              0x010
-#define ZR060_SF_HI                    0x011
-#define ZR060_SF_LO                    0x012
-#define ZR060_AF_HI                    0x013
-#define ZR060_AF_M                     0x014
-#define ZR060_AF_LO                    0x015
-#define ZR060_ACV_HI                   0x016
-#define ZR060_ACV_MH                   0x017
-#define ZR060_ACV_ML                   0x018
-#define ZR060_ACV_LO                   0x019
-#define ZR060_ACT_HI                   0x01a
-#define ZR060_ACT_MH                   0x01b
-#define ZR060_ACT_ML                   0x01c
-#define ZR060_ACT_LO                   0x01d
-#define ZR060_ACV_TRUN_HI              0x01e
-#define ZR060_ACV_TRUN_MH              0x01f
-#define ZR060_ACV_TRUN_ML              0x020
-#define ZR060_ACV_TRUN_LO              0x021
-#define ZR060_IDR_DEV                  0x022
-#define ZR060_IDR_REV                  0x023
-#define ZR060_TCR_HI                   0x024
-#define ZR060_TCR_LO                   0x025
-#define ZR060_VCR                      0x030
-#define ZR060_VPR                      0x031
-#define ZR060_SR                       0x032
-#define ZR060_BCR_Y                    0x033
-#define ZR060_BCR_U                    0x034
-#define ZR060_BCR_V                    0x035
-#define ZR060_SGR_VTOTAL_HI            0x036
-#define ZR060_SGR_VTOTAL_LO            0x037
-#define ZR060_SGR_HTOTAL_HI            0x038
-#define ZR060_SGR_HTOTAL_LO            0x039
-#define ZR060_SGR_VSYNC                        0x03a
-#define ZR060_SGR_HSYNC                        0x03b
-#define ZR060_SGR_BVSTART              0x03c
-#define ZR060_SGR_BHSTART              0x03d
-#define ZR060_SGR_BVEND_HI             0x03e
-#define ZR060_SGR_BVEND_LO             0x03f
-#define ZR060_SGR_BHEND_HI             0x040
-#define ZR060_SGR_BHEND_LO             0x041
-#define ZR060_AAR_VSTART_HI            0x042
-#define ZR060_AAR_VSTART_LO            0x043
-#define ZR060_AAR_VEND_HI              0x044
-#define ZR060_AAR_VEND_LO              0x045
-#define ZR060_AAR_HSTART_HI            0x046
-#define ZR060_AAR_HSTART_LO            0x047
-#define ZR060_AAR_HEND_HI              0x048
-#define ZR060_AAR_HEND_LO              0x049
-#define ZR060_SWR_VSTART_HI            0x04a
-#define ZR060_SWR_VSTART_LO            0x04b
-#define ZR060_SWR_VEND_HI              0x04c
-#define ZR060_SWR_VEND_LO              0x04d
-#define ZR060_SWR_HSTART_HI            0x04e
-#define ZR060_SWR_HSTART_LO            0x04f
-#define ZR060_SWR_HEND_HI              0x050
-#define ZR060_SWR_HEND_LO              0x051
-
-#define ZR060_SOF_IDX                  0x060
-#define ZR060_SOS_IDX                  0x07a
-#define ZR060_DRI_IDX                  0x0c0
-#define ZR060_DQT_IDX                  0x0cc
-#define ZR060_DHT_IDX                  0x1d4
-#define ZR060_APP_IDX                  0x380
-#define ZR060_COM_IDX                  0x3c0
-
-/* ZR36060 LOAD register bits */
-
-#define ZR060_LOAD_Load                        (1 << 7)
-#define ZR060_LOAD_SyncRst             (1 << 0)
-
-/* ZR36060 Code FIFO Status register bits */
-
-#define ZR060_CFSR_Busy                        (1 << 7)
-#define ZR060_CFSR_CBusy               (1 << 2)
-#define ZR060_CFSR_CFIFO               (3 << 0)
-
-/* ZR36060 Code Interface register */
-
-#define ZR060_CIR_Code16               (1 << 7)
-#define ZR060_CIR_Endian               (1 << 6)
-#define ZR060_CIR_CFIS                 (1 << 2)
-#define ZR060_CIR_CodeMstr             (1 << 0)
-
-/* ZR36060 Codec Mode register */
-
-#define ZR060_CMR_Comp                 (1 << 7)
-#define ZR060_CMR_ATP                  (1 << 6)
-#define ZR060_CMR_Pass2                        (1 << 5)
-#define ZR060_CMR_TLM                  (1 << 4)
-#define ZR060_CMR_BRB                  (1 << 2)
-#define ZR060_CMR_FSF                  (1 << 1)
-
-/* ZR36060 Markers Enable register */
-
-#define ZR060_MER_App                  (1 << 7)
-#define ZR060_MER_Com                  (1 << 6)
-#define ZR060_MER_DRI                  (1 << 5)
-#define ZR060_MER_DQT                  (1 << 4)
-#define ZR060_MER_DHT                  (1 << 3)
-
-/* ZR36060 Interrupt Mask register */
-
-#define ZR060_IMR_EOAV                 (1 << 3)
-#define ZR060_IMR_EOI                  (1 << 2)
-#define ZR060_IMR_End                  (1 << 1)
-#define ZR060_IMR_DataErr              (1 << 0)
-
-/* ZR36060 Interrupt Status register */
-
-#define ZR060_ISR_ProCnt               (3 << 6)
-#define ZR060_ISR_EOAV                 (1 << 3)
-#define ZR060_ISR_EOI                  (1 << 2)
-#define ZR060_ISR_End                  (1 << 1)
-#define ZR060_ISR_DataErr              (1 << 0)
-
-/* ZR36060 Video Control register */
-
-#define ZR060_VCR_Video8               (1 << 7)
-#define ZR060_VCR_Range                        (1 << 6)
-#define ZR060_VCR_FIDet                        (1 << 3)
-#define ZR060_VCR_FIVedge              (1 << 2)
-#define ZR060_VCR_FIExt                        (1 << 1)
-#define ZR060_VCR_SyncMstr             (1 << 0)
-
-/* ZR36060 Video Polarity register */
-
-#define ZR060_VPR_VCLKPol              (1 << 7)
-#define ZR060_VPR_PValPol              (1 << 6)
-#define ZR060_VPR_PoePol               (1 << 5)
-#define ZR060_VPR_SImgPol              (1 << 4)
-#define ZR060_VPR_BLPol                        (1 << 3)
-#define ZR060_VPR_FIPol                        (1 << 2)
-#define ZR060_VPR_HSPol                        (1 << 1)
-#define ZR060_VPR_VSPol                        (1 << 0)
-
-/* ZR36060 Scaling register */
-
-#define ZR060_SR_VScale                        (1 << 2)
-#define ZR060_SR_HScale2               (1 << 0)
-#define ZR060_SR_HScale4               (2 << 0)
-
-#endif                         /*fndef ZR36060_H */
index 18d1c4ba79fbf7c8384ba8497320d180ad226b44..7cdac99deea69fe909b0a03e5be6e25459e54b12 100644 (file)
@@ -52,7 +52,7 @@
 
 
 /* Debug macro */
-#define DBG(x...) if (debug) info(x)
+#define DBG(x...) if (debug) printk(KERN_INFO KBUILD_MODNAME x)
 
 
 /* Init methods, need to find nicer names for these
@@ -116,6 +116,7 @@ struct zr364xx_camera {
        int height;
        int method;
        struct mutex lock;
+       int users;
 };
 
 
@@ -127,7 +128,7 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
 
        unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
        if (!transfer_buffer) {
-               info("kmalloc(%d) failed", size);
+               dev_err(&udev->dev, "kmalloc(%d) failed\n", size);
                return -ENOMEM;
        }
 
@@ -143,7 +144,8 @@ static int send_control_msg(struct usb_device *udev, u8 request, u16 value,
        kfree(transfer_buffer);
 
        if (status < 0)
-               info("Failed sending control message, error %d.", status);
+               dev_err(&udev->dev,
+                       "Failed sending control message, error %d.\n", status);
 
        return status;
 }
@@ -303,11 +305,11 @@ static int read_frame(struct zr364xx_camera *cam, int framenum)
                DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]);
                DBG("bulk : n=%d size=%d", n, actual_length);
                if (n < 0) {
-                       info("error reading bulk msg");
+                       dev_err(&cam->udev->dev, "error reading bulk msg\n");
                        return 0;
                }
                if (actual_length < 0 || actual_length > BUFFER_SIZE) {
-                       info("wrong number of bytes");
+                       dev_err(&cam->udev->dev, "wrong number of bytes\n");
                        return 0;
                }
 
@@ -641,42 +643,47 @@ static int zr364xx_open(struct inode *inode, struct file *file)
 
        DBG("zr364xx_open");
 
-       cam->skip = 2;
+       mutex_lock(&cam->lock);
 
-       err = video_exclusive_open(inode, file);
-       if (err < 0)
-               return err;
+       if (cam->users) {
+               err = -EBUSY;
+               goto out;
+       }
 
        if (!cam->framebuf) {
                cam->framebuf = vmalloc_32(MAX_FRAME_SIZE * FRAMES);
                if (!cam->framebuf) {
-                       info("vmalloc_32 failed!");
-                       return -ENOMEM;
+                       dev_err(&cam->udev->dev, "vmalloc_32 failed!\n");
+                       err = -ENOMEM;
+                       goto out;
                }
        }
 
-       mutex_lock(&cam->lock);
        for (i = 0; init[cam->method][i].size != -1; i++) {
                err =
                    send_control_msg(udev, 1, init[cam->method][i].value,
                                     0, init[cam->method][i].bytes,
                                     init[cam->method][i].size);
                if (err < 0) {
-                       info("error during open sequence: %d", i);
-                       mutex_unlock(&cam->lock);
-                       return err;
+                       dev_err(&cam->udev->dev,
+                               "error during open sequence: %d\n", i);
+                       goto out;
                }
        }
 
+       cam->skip = 2;
+       cam->users++;
        file->private_data = vdev;
 
        /* Added some delay here, since opening/closing the camera quickly,
         * like Ekiga does during its startup, can crash the webcam
         */
        mdelay(100);
+       err = 0;
 
+out:
        mutex_unlock(&cam->lock);
-       return 0;
+       return err;
 }
 
 
@@ -697,28 +704,30 @@ static int zr364xx_release(struct inode *inode, struct file *file)
        udev = cam->udev;
 
        mutex_lock(&cam->lock);
+
+       cam->users--;
+       file->private_data = NULL;
+
        for (i = 0; i < 2; i++) {
                err =
                    send_control_msg(udev, 1, init[cam->method][i].value,
                                     0, init[i][cam->method].bytes,
                                     init[cam->method][i].size);
                if (err < 0) {
-                       info("error during release sequence");
-                       mutex_unlock(&cam->lock);
-                       return err;
+                       dev_err(&udev->dev, "error during release sequence\n");
+                       goto out;
                }
        }
 
-       file->private_data = NULL;
-       video_exclusive_release(inode, file);
-
        /* Added some delay here, since opening/closing the camera quickly,
         * like Ekiga does during its startup, can crash the webcam
         */
        mdelay(100);
+       err = 0;
 
+out:
        mutex_unlock(&cam->lock);
-       return 0;
+       return err;
 }
 
 
@@ -801,13 +810,14 @@ static int zr364xx_probe(struct usb_interface *intf,
 
        DBG("probing...");
 
-       info(DRIVER_DESC " compatible webcam plugged");
-       info("model %04x:%04x detected", udev->descriptor.idVendor,
-            udev->descriptor.idProduct);
+       dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
+       dev_info(&intf->dev, "model %04x:%04x detected\n",
+                le16_to_cpu(udev->descriptor.idVendor),
+                le16_to_cpu(udev->descriptor.idProduct));
 
        cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
        if (cam == NULL) {
-               info("cam: out of memory !");
+               dev_err(&udev->dev, "cam: out of memory !\n");
                return -ENOMEM;
        }
        /* save the init method used by this camera */
@@ -815,7 +825,7 @@ static int zr364xx_probe(struct usb_interface *intf,
 
        cam->vdev = video_device_alloc();
        if (cam->vdev == NULL) {
-               info("cam->vdev: out of memory !");
+               dev_err(&udev->dev, "cam->vdev: out of memory !\n");
                kfree(cam);
                return -ENOMEM;
        }
@@ -827,7 +837,7 @@ static int zr364xx_probe(struct usb_interface *intf,
        cam->udev = udev;
 
        if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) {
-               info("cam->buffer: out of memory !");
+               dev_info(&udev->dev, "cam->buffer: out of memory !\n");
                video_device_release(cam->vdev);
                kfree(cam);
                return -ENODEV;
@@ -835,17 +845,17 @@ static int zr364xx_probe(struct usb_interface *intf,
 
        switch (mode) {
        case 1:
-               info("160x120 mode selected");
+               dev_info(&udev->dev, "160x120 mode selected\n");
                cam->width = 160;
                cam->height = 120;
                break;
        case 2:
-               info("640x480 mode selected");
+               dev_info(&udev->dev, "640x480 mode selected\n");
                cam->width = 640;
                cam->height = 480;
                break;
        default:
-               info("320x240 mode selected");
+               dev_info(&udev->dev, "320x240 mode selected\n");
                cam->width = 320;
                cam->height = 240;
                break;
@@ -865,7 +875,7 @@ static int zr364xx_probe(struct usb_interface *intf,
 
        err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
        if (err) {
-               info("video_register_device failed");
+               dev_err(&udev->dev, "video_register_device failed\n");
                video_device_release(cam->vdev);
                kfree(cam->buffer);
                kfree(cam);
@@ -874,7 +884,8 @@ static int zr364xx_probe(struct usb_interface *intf,
 
        usb_set_intfdata(intf, cam);
 
-       info(DRIVER_DESC " controlling video device %d", cam->vdev->minor);
+       dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
+                cam->vdev->minor);
        return 0;
 }
 
@@ -884,7 +895,7 @@ static void zr364xx_disconnect(struct usb_interface *intf)
        struct zr364xx_camera *cam = usb_get_intfdata(intf);
        usb_set_intfdata(intf, NULL);
        dev_set_drvdata(&intf->dev, NULL);
-       info(DRIVER_DESC " webcam unplugged");
+       dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
        if (cam->vdev)
                video_unregister_device(cam->vdev);
        cam->vdev = NULL;
@@ -913,16 +924,16 @@ static int __init zr364xx_init(void)
        int retval;
        retval = usb_register(&zr364xx_driver);
        if (retval)
-               info("usb_register failed!");
+               printk(KERN_ERR KBUILD_MODNAME ": usb_register failed!\n");
        else
-               info(DRIVER_DESC " module loaded");
+               printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
        return retval;
 }
 
 
 static void __exit zr364xx_exit(void)
 {
-       info(DRIVER_DESC " module unloaded");
+       printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC " module unloaded\n");
        usb_deregister(&zr364xx_driver);
 }
 
index 2c2e39aa1efaf04d8747018369089bc44a0c3b8a..b0982dacfd0ac03fe71ac57e2740cc3599b55fd3 100644 (file)
@@ -5,7 +5,7 @@
 # In the future, some of these should be built conditionally.
 #
 
-i2o_core-y             += iop.o driver.o device.o debug.o pci.o exec-osm.o
+i2o_core-y             += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o
 i2o_bus-y              += bus-osm.o
 i2o_config-y           += config-osm.o
 obj-$(CONFIG_I2O)      += i2o_core.o
index 8774c670e668c55a4fe54bff02b014d0fcde89bc..54c2e9ae23e5e98c9b10849bab02364a338e3185 100644 (file)
@@ -467,7 +467,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
 
        res.virt = NULL;
 
-       if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
+       if (i2o_dma_alloc(dev, &res, reslen))
                return -ENOMEM;
 
        msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
index 6cbcc21de5182b2ce3e4087e3a022654eb7cb606..56faef1a1d55a3412d852ab9b56a805d0651627a 100644 (file)
@@ -388,8 +388,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
 
        dev = &c->pdev->dev;
 
-       if (i2o_dma_realloc
-           (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
+       if (i2o_dma_realloc(dev, &c->dlct,
+                                       le32_to_cpu(sb->expected_lct_size)))
                return -ENOMEM;
 
        msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
index 4238de98d4a68e9c9ab45b62d6d9fc0c6c73963b..a3fabdbe6ca6eb01efc616aee7df91cc4ae312c1 100644 (file)
@@ -260,7 +260,7 @@ static int i2o_cfg_swdl(unsigned long arg)
        if (IS_ERR(msg))
                return PTR_ERR(msg);
 
-       if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+       if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
                i2o_msg_nop(c, msg);
                return -ENOMEM;
        }
@@ -339,7 +339,7 @@ static int i2o_cfg_swul(unsigned long arg)
        if (IS_ERR(msg))
                return PTR_ERR(msg);
 
-       if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+       if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
                i2o_msg_nop(c, msg);
                return -ENOMEM;
        }
@@ -634,9 +634,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
                        sg_size = sg[i].flag_count & 0xffffff;
                        p = &(sg_list[sg_index]);
                        /* Allocate memory for the transfer */
-                       if (i2o_dma_alloc
-                           (&c->pdev->dev, p, sg_size,
-                            PCI_DMA_BIDIRECTIONAL)) {
+                       if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
                                printk(KERN_DEBUG
                                       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
                                       c->name, sg_size, i, sg_count);
@@ -780,12 +778,11 @@ static int i2o_cfg_passthru(unsigned long arg)
        u32 size = 0;
        u32 reply_size = 0;
        u32 rcode = 0;
-       void *sg_list[SG_TABLESIZE];
+       struct i2o_dma sg_list[SG_TABLESIZE];
        u32 sg_offset = 0;
        u32 sg_count = 0;
        int sg_index = 0;
        u32 i = 0;
-       void *p = NULL;
        i2o_status_block *sb;
        struct i2o_message *msg;
        unsigned int iop;
@@ -842,6 +839,7 @@ static int i2o_cfg_passthru(unsigned long arg)
        memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
        if (sg_offset) {
                struct sg_simple_element *sg;
+               struct i2o_dma *p;
 
                if (sg_offset * 4 >= size) {
                        rcode = -EFAULT;
@@ -871,22 +869,22 @@ static int i2o_cfg_passthru(unsigned long arg)
                                goto sg_list_cleanup;
                        }
                        sg_size = sg[i].flag_count & 0xffffff;
+                       p = &(sg_list[sg_index]);
+                       if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
                        /* Allocate memory for the transfer */
-                       p = kmalloc(sg_size, GFP_KERNEL);
-                       if (!p) {
                                printk(KERN_DEBUG
                                       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
                                       c->name, sg_size, i, sg_count);
                                rcode = -ENOMEM;
                                goto sg_list_cleanup;
                        }
-                       sg_list[sg_index++] = p;        // sglist indexed with input frame, not our internal frame.
+                       sg_index++;
                        /* Copy in the user's SG buffer if necessary */
                        if (sg[i].
                            flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
                                // TODO 64bit fix
                                if (copy_from_user
-                                   (p, (void __user *)sg[i].addr_bus,
+                                   (p->virt, (void __user *)sg[i].addr_bus,
                                     sg_size)) {
                                        printk(KERN_DEBUG
                                               "%s: Could not copy SG buf %d FROM user\n",
@@ -895,8 +893,7 @@ static int i2o_cfg_passthru(unsigned long arg)
                                        goto sg_list_cleanup;
                                }
                        }
-                       //TODO 64bit fix
-                       sg[i].addr_bus = virt_to_bus(p);
+                       sg[i].addr_bus = p->phys;
                }
        }
 
@@ -908,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg)
        }
 
        if (sg_offset) {
-               u32 rmsg[128];
+               u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
                /* Copy back the Scatter Gather buffers back to user space */
                u32 j;
                // TODO 64bit fix
@@ -942,11 +939,11 @@ static int i2o_cfg_passthru(unsigned long arg)
                                sg_size = sg[j].flag_count & 0xffffff;
                                // TODO 64bit fix
                                if (copy_to_user
-                                   ((void __user *)sg[j].addr_bus, sg_list[j],
+                                   ((void __user *)sg[j].addr_bus, sg_list[j].virt,
                                     sg_size)) {
                                        printk(KERN_WARNING
                                               "%s: Could not copy %p TO user %x\n",
-                                              c->name, sg_list[j],
+                                              c->name, sg_list[j].virt,
                                               sg[j].addr_bus);
                                        rcode = -EFAULT;
                                        goto sg_list_cleanup;
@@ -973,7 +970,7 @@ sg_list_cleanup:
        }
 
        for (i = 0; i < sg_index; i++)
-               kfree(sg_list[i]);
+               i2o_dma_free(&c->pdev->dev, &sg_list[i]);
 
 cleanup:
        kfree(reply);
index da715e11c1b28cc493de7047e1772074c804e981..be2b5926d26c14b34bcbb40fd4db664f50618495 100644 (file)
@@ -1004,7 +1004,7 @@ static int i2o_hrt_get(struct i2o_controller *c)
 
                size = hrt->num_entries * hrt->entry_len << 2;
                if (size > c->hrt.len) {
-                       if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL))
+                       if (i2o_dma_realloc(dev, &c->hrt, size))
                                return -ENOMEM;
                        else
                                hrt = c->hrt.virt;
diff --git a/drivers/message/i2o/memory.c b/drivers/message/i2o/memory.c
new file mode 100644 (file)
index 0000000..f5cc95c
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ *     Functions to handle I2O memory
+ *
+ *     Pulled from the inlines in i2o headers and uninlined
+ *
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the 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/i2o.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "core.h"
+
+/* Protects our 32/64bit mask switching */
+static DEFINE_MUTEX(mem_lock);
+
+/**
+ *     i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
+ *     @c: I2O controller for which the calculation should be done
+ *     @body_size: maximum body size used for message in 32-bit words.
+ *
+ *     Return the maximum number of SG elements in a SG list.
+ */
+u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
+{
+       i2o_status_block *sb = c->status_block.virt;
+       u16 sg_count =
+           (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
+           body_size;
+
+       if (c->pae_support) {
+               /*
+                * for 64-bit a SG attribute element must be added and each
+                * SG element needs 12 bytes instead of 8.
+                */
+               sg_count -= 2;
+               sg_count /= 3;
+       } else
+               sg_count /= 2;
+
+       if (c->short_req && (sg_count > 8))
+               sg_count = 8;
+
+       return sg_count;
+}
+EXPORT_SYMBOL_GPL(i2o_sg_tablesize);
+
+
+/**
+ *     i2o_dma_map_single - Map pointer to controller and fill in I2O message.
+ *     @c: I2O controller
+ *     @ptr: pointer to the data which should be mapped
+ *     @size: size of data in bytes
+ *     @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ *     @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ *     This function does all necessary DMA handling and also writes the I2O
+ *     SGL elements into the I2O message. For details on DMA handling see also
+ *     dma_map_single(). The pointer sg_ptr will only be set to the end of the
+ *     SG list if the allocation was successful.
+ *
+ *     Returns DMA address which must be checked for failures using
+ *     dma_mapping_error().
+ */
+dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
+                                           size_t size,
+                                           enum dma_data_direction direction,
+                                           u32 ** sg_ptr)
+{
+       u32 sg_flags;
+       u32 *mptr = *sg_ptr;
+       dma_addr_t dma_addr;
+
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               sg_flags = 0xd4000000;
+               break;
+       case DMA_FROM_DEVICE:
+               sg_flags = 0xd0000000;
+               break;
+       default:
+               return 0;
+       }
+
+       dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
+       if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+               if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+                       *mptr++ = cpu_to_le32(0x7C020002);
+                       *mptr++ = cpu_to_le32(PAGE_SIZE);
+               }
+#endif
+
+               *mptr++ = cpu_to_le32(sg_flags | size);
+               *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+               if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+                       *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));
+#endif
+               *sg_ptr = mptr;
+       }
+       return dma_addr;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_map_single);
+
+/**
+ *     i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
+ *     @c: I2O controller
+ *     @sg: SG list to be mapped
+ *     @sg_count: number of elements in the SG list
+ *     @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ *     @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ *     This function does all necessary DMA handling and also writes the I2O
+ *     SGL elements into the I2O message. For details on DMA handling see also
+ *     dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
+ *     list if the allocation was successful.
+ *
+ *     Returns 0 on failure or 1 on success.
+ */
+int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg,
+           int sg_count, enum dma_data_direction direction, u32 ** sg_ptr)
+{
+       u32 sg_flags;
+       u32 *mptr = *sg_ptr;
+
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               sg_flags = 0x14000000;
+               break;
+       case DMA_FROM_DEVICE:
+               sg_flags = 0x10000000;
+               break;
+       default:
+               return 0;
+       }
+
+       sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
+       if (!sg_count)
+               return 0;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+       if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+               *mptr++ = cpu_to_le32(0x7C020002);
+               *mptr++ = cpu_to_le32(PAGE_SIZE);
+       }
+#endif
+
+       while (sg_count-- > 0) {
+               if (!sg_count)
+                       sg_flags |= 0xC0000000;
+               *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));
+               *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+               if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+                       *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
+#endif
+               sg = sg_next(sg);
+       }
+       *sg_ptr = mptr;
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_map_sg);
+
+/**
+ *     i2o_dma_alloc - Allocate DMA memory
+ *     @dev: struct device pointer to the PCI device of the I2O controller
+ *     @addr: i2o_dma struct which should get the DMA buffer
+ *     @len: length of the new DMA memory
+ *
+ *     Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ *     Returns 0 on success or -ENOMEM on failure.
+ */
+int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       int dma_64 = 0;
+
+       mutex_lock(&mem_lock);
+       if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
+               dma_64 = 1;
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+                       mutex_unlock(&mem_lock);
+                       return -ENOMEM;
+               }
+       }
+
+       addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL);
+
+       if ((sizeof(dma_addr_t) > 4) && dma_64)
+               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+                       printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
+       mutex_unlock(&mem_lock);
+
+       if (!addr->virt)
+               return -ENOMEM;
+
+       memset(addr->virt, 0, len);
+       addr->len = len;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_alloc);
+
+
+/**
+ *     i2o_dma_free - Free DMA memory
+ *     @dev: struct device pointer to the PCI device of the I2O controller
+ *     @addr: i2o_dma struct which contains the DMA buffer
+ *
+ *     Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+       if (addr->virt) {
+               if (addr->phys)
+                       dma_free_coherent(dev, addr->len, addr->virt,
+                                         addr->phys);
+               else
+                       kfree(addr->virt);
+               addr->virt = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(i2o_dma_free);
+
+
+/**
+ *     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
+ *
+ *     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)
+{
+       i2o_dma_free(dev, addr);
+
+       if (len)
+               return i2o_dma_alloc(dev, addr, len);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(i2o_dma_realloc);
+
+/*
+ *     i2o_pool_alloc - Allocate an slab cache and mempool
+ *     @mempool: pointer to struct i2o_pool to write data into.
+ *     @name: name which is used to identify cache
+ *     @size: size of each object
+ *     @min_nr: minimum number of objects
+ *
+ *     First allocates a slab cache with name and size. Then allocates a
+ *     mempool which uses the slab cache for allocation and freeing.
+ *
+ *     Returns 0 on success or negative error code on failure.
+ */
+int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
+                                size_t size, int min_nr)
+{
+       pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+       if (!pool->name)
+               goto exit;
+       strcpy(pool->name, name);
+
+       pool->slab =
+           kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);
+       if (!pool->slab)
+               goto free_name;
+
+       pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);
+       if (!pool->mempool)
+               goto free_slab;
+
+       return 0;
+
+free_slab:
+       kmem_cache_destroy(pool->slab);
+
+free_name:
+       kfree(pool->name);
+
+exit:
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(i2o_pool_alloc);
+
+/*
+ *     i2o_pool_free - Free slab cache and mempool again
+ *     @mempool: pointer to struct i2o_pool which should be freed
+ *
+ *     Note that you have to return all objects to the mempool again before
+ *     calling i2o_pool_free().
+ */
+void i2o_pool_free(struct i2o_pool *pool)
+{
+       mempool_destroy(pool->mempool);
+       kmem_cache_destroy(pool->slab);
+       kfree(pool->name);
+};
+EXPORT_SYMBOL_GPL(i2o_pool_free);
index 685a89547a51fdc26929c5df2202b1f353188d7a..610ef1204e68f83ccfb2cd35f98ab5d3472c2229 100644 (file)
@@ -186,31 +186,29 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
                }
        }
 
-       if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->status, 8)) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
 
-       if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
 
-       if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->dlct, 8192)) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
 
-       if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block),
-                         GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
 
-       if (i2o_dma_alloc
-           (dev, &c->out_queue,
-            I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
-            sizeof(u32), GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->out_queue,
+               I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
+                               sizeof(u32))) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
index 0dae245c625953fa2194f643d580db06f00a3aac..5eff8ad834d6f6bae7da3e97a89a3a6c87a336fa 100644 (file)
@@ -87,6 +87,44 @@ config MFD_TC6393XB
        help
          Support for Toshiba Mobile IO Controller TC6393XB
 
+config MFD_WM8400
+       tristate "Support Wolfson Microelectronics WM8400"
+       help
+         Support for the Wolfson Microelecronics WM8400 PMIC and audio
+         CODEC.  This driver adds provides common support for accessing
+         the device, additional drivers must be enabled in order to use
+         the functionality of the device.
+
+config MFD_WM8350
+       tristate
+
+config MFD_WM8350_CONFIG_MODE_0
+       bool
+       depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_1
+       bool
+       depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_2
+       bool
+       depends on MFD_WM8350
+
+config MFD_WM8350_CONFIG_MODE_3
+       bool
+       depends on MFD_WM8350
+
+config MFD_WM8350_I2C
+       tristate "Support Wolfson Microelectronics WM8350 with I2C"
+       select MFD_WM8350
+       depends on I2C
+       help
+         The WM8350 is an integrated audio and power management
+         subsystem with watchdog and RTC functionality for embedded
+         systems.  This option enables core support for the WM8350 with
+         I2C as the control interface.  Additional options must be
+         selected to enable support for the functionality of the chip.
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
index 6abebe364419ed9668f0e08ea68abf0c362a7733..759b1fe1c891a44bac2c5486ea51da90d1de0985 100644 (file)
@@ -12,6 +12,11 @@ obj-$(CONFIG_MFD_T7L66XB)    += t7l66xb.o
 obj-$(CONFIG_MFD_TC6387XB)     += tc6387xb.o
 obj-$(CONFIG_MFD_TC6393XB)     += tc6393xb.o
 
+obj-$(CONFIG_MFD_WM8400)       += wm8400-core.o
+wm8350-objs                    := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
+obj-$(CONFIG_MFD_WM8350)       += wm8350.o
+obj-$(CONFIG_MFD_WM8350_I2C)   += wm8350-i2c.o
+
 obj-$(CONFIG_MFD_CORE)         += mfd-core.o
 
 obj-$(CONFIG_MCP)              += mcp-core.o
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
new file mode 100644 (file)
index 0000000..25a7a5d
--- /dev/null
@@ -0,0 +1,1273 @@
+/*
+ * wm8350-core.c  --  Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood, Mark Brown
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/module.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/comparator.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/wdt.h>
+
+#define WM8350_UNLOCK_KEY              0x0013
+#define WM8350_LOCK_KEY                        0x0000
+
+#define WM8350_CLOCK_CONTROL_1         0x28
+#define WM8350_AIF_TEST                        0x74
+
+/* debug */
+#define WM8350_BUS_DEBUG 0
+#if WM8350_BUS_DEBUG
+#define dump(regs, src) do { \
+       int i_; \
+       u16 *src_ = src; \
+       printk(KERN_DEBUG); \
+       for (i_ = 0; i_ < regs; i_++) \
+               printk(" 0x%4.4x", *src_++); \
+       printk("\n"); \
+} while (0);
+#else
+#define dump(bytes, src)
+#endif
+
+#define WM8350_LOCK_DEBUG 0
+#if WM8350_LOCK_DEBUG
+#define ldbg(format, arg...) printk(format, ## arg)
+#else
+#define ldbg(format, arg...)
+#endif
+
+/*
+ * WM8350 Device IO
+ */
+static DEFINE_MUTEX(io_mutex);
+static DEFINE_MUTEX(reg_lock_mutex);
+static DEFINE_MUTEX(auxadc_mutex);
+
+/* Perform a physical read from the device.
+ */
+static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
+                           u16 *dest)
+{
+       int i, ret;
+       int bytes = num_regs * 2;
+
+       dev_dbg(wm8350->dev, "volatile read\n");
+       ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
+
+       for (i = reg; i < reg + num_regs; i++) {
+               /* Cache is CPU endian */
+               dest[i - reg] = be16_to_cpu(dest[i - reg]);
+
+               /* Satisfy non-volatile bits from cache */
+               dest[i - reg] &= wm8350_reg_io_map[i].vol;
+               dest[i - reg] |= wm8350->reg_cache[i];
+
+               /* Mask out non-readable bits */
+               dest[i - reg] &= wm8350_reg_io_map[i].readable;
+       }
+
+       dump(num_regs, dest);
+
+       return ret;
+}
+
+static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
+{
+       int i;
+       int end = reg + num_regs;
+       int ret = 0;
+       int bytes = num_regs * 2;
+
+       if (wm8350->read_dev == NULL)
+               return -ENODEV;
+
+       if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+               dev_err(wm8350->dev, "invalid reg %x\n",
+                       reg + num_regs - 1);
+               return -EINVAL;
+       }
+
+       dev_dbg(wm8350->dev,
+               "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs);
+
+#if WM8350_BUS_DEBUG
+       /* we can _safely_ read any register, but warn if read not supported */
+       for (i = reg; i < end; i++) {
+               if (!wm8350_reg_io_map[i].readable)
+                       dev_warn(wm8350->dev,
+                               "reg R%d is not readable\n", i);
+       }
+#endif
+
+       /* if any volatile registers are required, then read back all */
+       for (i = reg; i < end; i++)
+               if (wm8350_reg_io_map[i].vol)
+                       return wm8350_phys_read(wm8350, reg, num_regs, dest);
+
+       /* no volatiles, then cache is good */
+       dev_dbg(wm8350->dev, "cache read\n");
+       memcpy(dest, &wm8350->reg_cache[reg], bytes);
+       dump(num_regs, dest);
+       return ret;
+}
+
+static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
+{
+       if (reg == WM8350_SECURITY ||
+           wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
+               return 0;
+
+       if ((reg == WM8350_GPIO_CONFIGURATION_I_O) ||
+           (reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
+            reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
+           (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
+            reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
+               return 1;
+       return 0;
+}
+
+static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src)
+{
+       int i;
+       int end = reg + num_regs;
+       int bytes = num_regs * 2;
+
+       if (wm8350->write_dev == NULL)
+               return -ENODEV;
+
+       if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
+               dev_err(wm8350->dev, "invalid reg %x\n",
+                       reg + num_regs - 1);
+               return -EINVAL;
+       }
+
+       /* it's generally not a good idea to write to RO or locked registers */
+       for (i = reg; i < end; i++) {
+               if (!wm8350_reg_io_map[i].writable) {
+                       dev_err(wm8350->dev,
+                               "attempted write to read only reg R%d\n", i);
+                       return -EINVAL;
+               }
+
+               if (is_reg_locked(wm8350, i)) {
+                       dev_err(wm8350->dev,
+                              "attempted write to locked reg R%d\n", i);
+                       return -EINVAL;
+               }
+
+               src[i - reg] &= wm8350_reg_io_map[i].writable;
+
+               wm8350->reg_cache[i] =
+                       (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable)
+                       | src[i - reg];
+
+               src[i - reg] = cpu_to_be16(src[i - reg]);
+       }
+
+       /* Actually write it out */
+       return wm8350->write_dev(wm8350, reg, bytes, (char *)src);
+}
+
+/*
+ * Safe read, modify, write methods
+ */
+int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+       u16 data;
+       int err;
+
+       mutex_lock(&io_mutex);
+       err = wm8350_read(wm8350, reg, 1, &data);
+       if (err) {
+               dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+               goto out;
+       }
+
+       data &= ~mask;
+       err = wm8350_write(wm8350, reg, 1, &data);
+       if (err)
+               dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+       mutex_unlock(&io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_clear_bits);
+
+int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask)
+{
+       u16 data;
+       int err;
+
+       mutex_lock(&io_mutex);
+       err = wm8350_read(wm8350, reg, 1, &data);
+       if (err) {
+               dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+               goto out;
+       }
+
+       data |= mask;
+       err = wm8350_write(wm8350, reg, 1, &data);
+       if (err)
+               dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+out:
+       mutex_unlock(&io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_set_bits);
+
+u16 wm8350_reg_read(struct wm8350 *wm8350, int reg)
+{
+       u16 data;
+       int err;
+
+       mutex_lock(&io_mutex);
+       err = wm8350_read(wm8350, reg, 1, &data);
+       if (err)
+               dev_err(wm8350->dev, "read from reg R%d failed\n", reg);
+
+       mutex_unlock(&io_mutex);
+       return data;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_read);
+
+int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val)
+{
+       int ret;
+       u16 data = val;
+
+       mutex_lock(&io_mutex);
+       ret = wm8350_write(wm8350, reg, 1, &data);
+       if (ret)
+               dev_err(wm8350->dev, "write to reg R%d failed\n", reg);
+       mutex_unlock(&io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_write);
+
+int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs,
+                     u16 *dest)
+{
+       int err = 0;
+
+       mutex_lock(&io_mutex);
+       err = wm8350_read(wm8350, start_reg, regs, dest);
+       if (err)
+               dev_err(wm8350->dev, "block read starting from R%d failed\n",
+                       start_reg);
+       mutex_unlock(&io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_read);
+
+int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
+                      u16 *src)
+{
+       int ret = 0;
+
+       mutex_lock(&io_mutex);
+       ret = wm8350_write(wm8350, start_reg, regs, src);
+       if (ret)
+               dev_err(wm8350->dev, "block write starting at R%d failed\n",
+                       start_reg);
+       mutex_unlock(&io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_block_write);
+
+int wm8350_reg_lock(struct wm8350 *wm8350)
+{
+       u16 key = WM8350_LOCK_KEY;
+       int ret;
+
+       ldbg(__func__);
+       mutex_lock(&io_mutex);
+       ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+       if (ret)
+               dev_err(wm8350->dev, "lock failed\n");
+       mutex_unlock(&io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_lock);
+
+int wm8350_reg_unlock(struct wm8350 *wm8350)
+{
+       u16 key = WM8350_UNLOCK_KEY;
+       int ret;
+
+       ldbg(__func__);
+       mutex_lock(&io_mutex);
+       ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+       if (ret)
+               dev_err(wm8350->dev, "unlock failed\n");
+       mutex_unlock(&io_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
+
+static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
+{
+       mutex_lock(&wm8350->irq_mutex);
+
+       if (wm8350->irq[irq].handler)
+               wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data);
+       else {
+               dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
+                       irq);
+               wm8350_mask_irq(wm8350, irq);
+       }
+
+       mutex_unlock(&wm8350->irq_mutex);
+}
+
+/*
+ * wm8350_irq_worker actually handles the interrupts.  Since all
+ * interrupts are clear on read the IRQ line will be reasserted and
+ * the physical IRQ will be handled again if another interrupt is
+ * asserted while we run - in the normal course of events this is a
+ * rare occurrence so we save I2C/SPI reads.
+ */
+static void wm8350_irq_worker(struct work_struct *work)
+{
+       struct wm8350 *wm8350 = container_of(work, struct wm8350, irq_work);
+       u16 level_one, status1, status2, comp;
+
+       /* TODO: Use block reads to improve performance? */
+       level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
+               & ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
+       status1 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_1)
+               & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_1_MASK);
+       status2 = wm8350_reg_read(wm8350, WM8350_INT_STATUS_2)
+               & ~wm8350_reg_read(wm8350, WM8350_INT_STATUS_2_MASK);
+       comp = wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS)
+               & ~wm8350_reg_read(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK);
+
+       /* over current */
+       if (level_one & WM8350_OC_INT) {
+               u16 oc;
+
+               oc = wm8350_reg_read(wm8350, WM8350_OVER_CURRENT_INT_STATUS);
+               oc &= ~wm8350_reg_read(wm8350,
+                                      WM8350_OVER_CURRENT_INT_STATUS_MASK);
+
+               if (oc & WM8350_OC_LS_EINT)     /* limit switch */
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_OC_LS);
+       }
+
+       /* under voltage */
+       if (level_one & WM8350_UV_INT) {
+               u16 uv;
+
+               uv = wm8350_reg_read(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS);
+               uv &= ~wm8350_reg_read(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK);
+
+               if (uv & WM8350_UV_DC1_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC1);
+               if (uv & WM8350_UV_DC2_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC2);
+               if (uv & WM8350_UV_DC3_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC3);
+               if (uv & WM8350_UV_DC4_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC4);
+               if (uv & WM8350_UV_DC5_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC5);
+               if (uv & WM8350_UV_DC6_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_DC6);
+               if (uv & WM8350_UV_LDO1_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO1);
+               if (uv & WM8350_UV_LDO2_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO2);
+               if (uv & WM8350_UV_LDO3_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO3);
+               if (uv & WM8350_UV_LDO4_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_UV_LDO4);
+       }
+
+       /* charger, RTC */
+       if (status1) {
+               if (status1 & WM8350_CHG_BAT_HOT_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_BAT_HOT);
+               if (status1 & WM8350_CHG_BAT_COLD_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_BAT_COLD);
+               if (status1 & WM8350_CHG_BAT_FAIL_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_BAT_FAIL);
+               if (status1 & WM8350_CHG_TO_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_TO);
+               if (status1 & WM8350_CHG_END_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_END);
+               if (status1 & WM8350_CHG_START_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CHG_START);
+               if (status1 & WM8350_CHG_FAST_RDY_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_FAST_RDY);
+               if (status1 & WM8350_CHG_VBATT_LT_3P9_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_VBATT_LT_3P9);
+               if (status1 & WM8350_CHG_VBATT_LT_3P1_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_VBATT_LT_3P1);
+               if (status1 & WM8350_CHG_VBATT_LT_2P85_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CHG_VBATT_LT_2P85);
+               if (status1 & WM8350_RTC_ALM_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_ALM);
+               if (status1 & WM8350_RTC_SEC_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_SEC);
+               if (status1 & WM8350_RTC_PER_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_RTC_PER);
+       }
+
+       /* current sink, system, aux adc */
+       if (status2) {
+               if (status2 & WM8350_CS1_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS1);
+               if (status2 & WM8350_CS2_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CS2);
+
+               if (status2 & WM8350_SYS_HYST_COMP_FAIL_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_SYS_HYST_COMP_FAIL);
+               if (status2 & WM8350_SYS_CHIP_GT115_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_SYS_CHIP_GT115);
+               if (status2 & WM8350_SYS_CHIP_GT140_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_SYS_CHIP_GT140);
+               if (status2 & WM8350_SYS_WDOG_TO_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_SYS_WDOG_TO);
+
+               if (status2 & WM8350_AUXADC_DATARDY_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_AUXADC_DATARDY);
+               if (status2 & WM8350_AUXADC_DCOMP4_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_AUXADC_DCOMP4);
+               if (status2 & WM8350_AUXADC_DCOMP3_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_AUXADC_DCOMP3);
+               if (status2 & WM8350_AUXADC_DCOMP2_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_AUXADC_DCOMP2);
+               if (status2 & WM8350_AUXADC_DCOMP1_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_AUXADC_DCOMP1);
+
+               if (status2 & WM8350_USB_LIMIT_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_USB_LIMIT);
+       }
+
+       /* wake, codec, ext */
+       if (comp) {
+               if (comp & WM8350_WKUP_OFF_STATE_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_OFF_STATE);
+               if (comp & WM8350_WKUP_HIB_STATE_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_HIB_STATE);
+               if (comp & WM8350_WKUP_CONV_FAULT_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_CONV_FAULT);
+               if (comp & WM8350_WKUP_WDOG_RST_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_WDOG_RST);
+               if (comp & WM8350_WKUP_GP_PWR_ON_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_GP_PWR_ON);
+               if (comp & WM8350_WKUP_ONKEY_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_WKUP_ONKEY);
+               if (comp & WM8350_WKUP_GP_WAKEUP_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_WKUP_GP_WAKEUP);
+
+               if (comp & WM8350_CODEC_JCK_DET_L_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CODEC_JCK_DET_L);
+               if (comp & WM8350_CODEC_JCK_DET_R_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CODEC_JCK_DET_R);
+               if (comp & WM8350_CODEC_MICSCD_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_CODEC_MICSCD);
+               if (comp & WM8350_CODEC_MICD_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_CODEC_MICD);
+
+               if (comp & WM8350_EXT_USB_FB_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_USB_FB);
+               if (comp & WM8350_EXT_WALL_FB_EINT)
+                       wm8350_irq_call_handler(wm8350,
+                                               WM8350_IRQ_EXT_WALL_FB);
+               if (comp & WM8350_EXT_BAT_FB_EINT)
+                       wm8350_irq_call_handler(wm8350, WM8350_IRQ_EXT_BAT_FB);
+       }
+
+       if (level_one & WM8350_GP_INT) {
+               int i;
+               u16 gpio;
+
+               gpio = wm8350_reg_read(wm8350, WM8350_GPIO_INT_STATUS);
+               gpio &= ~wm8350_reg_read(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK);
+
+               for (i = 0; i < 12; i++) {
+                       if (gpio & (1 << i))
+                               wm8350_irq_call_handler(wm8350,
+                                                       WM8350_IRQ_GPIO(i));
+               }
+       }
+
+       enable_irq(wm8350->chip_irq);
+}
+
+static irqreturn_t wm8350_irq(int irq, void *data)
+{
+       struct wm8350 *wm8350 = data;
+
+       disable_irq_nosync(irq);
+       schedule_work(&wm8350->irq_work);
+
+       return IRQ_HANDLED;
+}
+
+int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+                       void (*handler) (struct wm8350 *, int, void *),
+                       void *data)
+{
+       if (irq < 0 || irq > WM8350_NUM_IRQ || !handler)
+               return -EINVAL;
+
+       if (wm8350->irq[irq].handler)
+               return -EBUSY;
+
+       mutex_lock(&wm8350->irq_mutex);
+       wm8350->irq[irq].handler = handler;
+       wm8350->irq[irq].data = data;
+       mutex_unlock(&wm8350->irq_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_irq);
+
+int wm8350_free_irq(struct wm8350 *wm8350, int irq)
+{
+       if (irq < 0 || irq > WM8350_NUM_IRQ)
+               return -EINVAL;
+
+       mutex_lock(&wm8350->irq_mutex);
+       wm8350->irq[irq].handler = NULL;
+       mutex_unlock(&wm8350->irq_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_free_irq);
+
+int wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+{
+       switch (irq) {
+       case WM8350_IRQ_CHG_BAT_HOT:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_BAT_HOT_EINT);
+       case WM8350_IRQ_CHG_BAT_COLD:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_BAT_COLD_EINT);
+       case WM8350_IRQ_CHG_BAT_FAIL:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_BAT_FAIL_EINT);
+       case WM8350_IRQ_CHG_TO:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_TO_EINT);
+       case WM8350_IRQ_CHG_END:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_END_EINT);
+       case WM8350_IRQ_CHG_START:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_START_EINT);
+       case WM8350_IRQ_CHG_FAST_RDY:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_FAST_RDY_EINT);
+       case WM8350_IRQ_RTC_PER:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_RTC_PER_EINT);
+       case WM8350_IRQ_RTC_SEC:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_RTC_SEC_EINT);
+       case WM8350_IRQ_RTC_ALM:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_RTC_ALM_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_3P9:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_3P1:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_2P85:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                      WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+       case WM8350_IRQ_CS1:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_CS1_EINT);
+       case WM8350_IRQ_CS2:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_CS2_EINT);
+       case WM8350_IRQ_USB_LIMIT:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_USB_LIMIT_EINT);
+       case WM8350_IRQ_AUXADC_DATARDY:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_AUXADC_DATARDY_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP4:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_AUXADC_DCOMP4_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP3:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_AUXADC_DCOMP3_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP2:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_AUXADC_DCOMP2_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP1:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_AUXADC_DCOMP1_EINT);
+       case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+       case WM8350_IRQ_SYS_CHIP_GT115:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_SYS_CHIP_GT115_EINT);
+       case WM8350_IRQ_SYS_CHIP_GT140:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_SYS_CHIP_GT140_EINT);
+       case WM8350_IRQ_SYS_WDOG_TO:
+               return wm8350_set_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                      WM8350_IM_SYS_WDOG_TO_EINT);
+       case WM8350_IRQ_UV_LDO4:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_LDO4_EINT);
+       case WM8350_IRQ_UV_LDO3:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_LDO3_EINT);
+       case WM8350_IRQ_UV_LDO2:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_LDO2_EINT);
+       case WM8350_IRQ_UV_LDO1:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_LDO1_EINT);
+       case WM8350_IRQ_UV_DC6:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC6_EINT);
+       case WM8350_IRQ_UV_DC5:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC5_EINT);
+       case WM8350_IRQ_UV_DC4:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC4_EINT);
+       case WM8350_IRQ_UV_DC3:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC3_EINT);
+       case WM8350_IRQ_UV_DC2:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC2_EINT);
+       case WM8350_IRQ_UV_DC1:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                      WM8350_IM_UV_DC1_EINT);
+       case WM8350_IRQ_OC_LS:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_OVER_CURRENT_INT_STATUS_MASK,
+                                      WM8350_IM_OC_LS_EINT);
+       case WM8350_IRQ_EXT_USB_FB:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_EXT_USB_FB_EINT);
+       case WM8350_IRQ_EXT_WALL_FB:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_EXT_WALL_FB_EINT);
+       case WM8350_IRQ_EXT_BAT_FB:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_EXT_BAT_FB_EINT);
+       case WM8350_IRQ_CODEC_JCK_DET_L:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_CODEC_JCK_DET_L_EINT);
+       case WM8350_IRQ_CODEC_JCK_DET_R:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_CODEC_JCK_DET_R_EINT);
+       case WM8350_IRQ_CODEC_MICSCD:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_CODEC_MICSCD_EINT);
+       case WM8350_IRQ_CODEC_MICD:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_CODEC_MICD_EINT);
+       case WM8350_IRQ_WKUP_OFF_STATE:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_OFF_STATE_EINT);
+       case WM8350_IRQ_WKUP_HIB_STATE:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_HIB_STATE_EINT);
+       case WM8350_IRQ_WKUP_CONV_FAULT:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_CONV_FAULT_EINT);
+       case WM8350_IRQ_WKUP_WDOG_RST:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_OFF_STATE_EINT);
+       case WM8350_IRQ_WKUP_GP_PWR_ON:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_GP_PWR_ON_EINT);
+       case WM8350_IRQ_WKUP_ONKEY:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_ONKEY_EINT);
+       case WM8350_IRQ_WKUP_GP_WAKEUP:
+               return wm8350_set_bits(wm8350,
+                                      WM8350_COMPARATOR_INT_STATUS_MASK,
+                                      WM8350_IM_WKUP_GP_WAKEUP_EINT);
+       case WM8350_IRQ_GPIO(0):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP0_EINT);
+       case WM8350_IRQ_GPIO(1):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP1_EINT);
+       case WM8350_IRQ_GPIO(2):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP2_EINT);
+       case WM8350_IRQ_GPIO(3):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP3_EINT);
+       case WM8350_IRQ_GPIO(4):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP4_EINT);
+       case WM8350_IRQ_GPIO(5):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP5_EINT);
+       case WM8350_IRQ_GPIO(6):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP6_EINT);
+       case WM8350_IRQ_GPIO(7):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP7_EINT);
+       case WM8350_IRQ_GPIO(8):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP8_EINT);
+       case WM8350_IRQ_GPIO(9):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP9_EINT);
+       case WM8350_IRQ_GPIO(10):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP10_EINT);
+       case WM8350_IRQ_GPIO(11):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP11_EINT);
+       case WM8350_IRQ_GPIO(12):
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_INT_STATUS_MASK,
+                                      WM8350_IM_GP12_EINT);
+       default:
+               dev_warn(wm8350->dev, "Attempting to mask unknown IRQ %d\n",
+                        irq);
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_mask_irq);
+
+int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+{
+       switch (irq) {
+       case WM8350_IRQ_CHG_BAT_HOT:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_BAT_HOT_EINT);
+       case WM8350_IRQ_CHG_BAT_COLD:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_BAT_COLD_EINT);
+       case WM8350_IRQ_CHG_BAT_FAIL:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_BAT_FAIL_EINT);
+       case WM8350_IRQ_CHG_TO:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_TO_EINT);
+       case WM8350_IRQ_CHG_END:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_END_EINT);
+       case WM8350_IRQ_CHG_START:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_START_EINT);
+       case WM8350_IRQ_CHG_FAST_RDY:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_FAST_RDY_EINT);
+       case WM8350_IRQ_RTC_PER:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_RTC_PER_EINT);
+       case WM8350_IRQ_RTC_SEC:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_RTC_SEC_EINT);
+       case WM8350_IRQ_RTC_ALM:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_RTC_ALM_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_3P9:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_VBATT_LT_3P9_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_3P1:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_VBATT_LT_3P1_EINT);
+       case WM8350_IRQ_CHG_VBATT_LT_2P85:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK,
+                                        WM8350_IM_CHG_VBATT_LT_2P85_EINT);
+       case WM8350_IRQ_CS1:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_CS1_EINT);
+       case WM8350_IRQ_CS2:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_CS2_EINT);
+       case WM8350_IRQ_USB_LIMIT:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_USB_LIMIT_EINT);
+       case WM8350_IRQ_AUXADC_DATARDY:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_AUXADC_DATARDY_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP4:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_AUXADC_DCOMP4_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP3:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_AUXADC_DCOMP3_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP2:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_AUXADC_DCOMP2_EINT);
+       case WM8350_IRQ_AUXADC_DCOMP1:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_AUXADC_DCOMP1_EINT);
+       case WM8350_IRQ_SYS_HYST_COMP_FAIL:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_SYS_HYST_COMP_FAIL_EINT);
+       case WM8350_IRQ_SYS_CHIP_GT115:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_SYS_CHIP_GT115_EINT);
+       case WM8350_IRQ_SYS_CHIP_GT140:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_SYS_CHIP_GT140_EINT);
+       case WM8350_IRQ_SYS_WDOG_TO:
+               return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_2_MASK,
+                                        WM8350_IM_SYS_WDOG_TO_EINT);
+       case WM8350_IRQ_UV_LDO4:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_LDO4_EINT);
+       case WM8350_IRQ_UV_LDO3:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_LDO3_EINT);
+       case WM8350_IRQ_UV_LDO2:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_LDO2_EINT);
+       case WM8350_IRQ_UV_LDO1:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_LDO1_EINT);
+       case WM8350_IRQ_UV_DC6:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC6_EINT);
+       case WM8350_IRQ_UV_DC5:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC5_EINT);
+       case WM8350_IRQ_UV_DC4:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC4_EINT);
+       case WM8350_IRQ_UV_DC3:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC3_EINT);
+       case WM8350_IRQ_UV_DC2:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC2_EINT);
+       case WM8350_IRQ_UV_DC1:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_UNDER_VOLTAGE_INT_STATUS_MASK,
+                                        WM8350_IM_UV_DC1_EINT);
+       case WM8350_IRQ_OC_LS:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_OVER_CURRENT_INT_STATUS_MASK,
+                                        WM8350_IM_OC_LS_EINT);
+       case WM8350_IRQ_EXT_USB_FB:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_EXT_USB_FB_EINT);
+       case WM8350_IRQ_EXT_WALL_FB:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_EXT_WALL_FB_EINT);
+       case WM8350_IRQ_EXT_BAT_FB:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_EXT_BAT_FB_EINT);
+       case WM8350_IRQ_CODEC_JCK_DET_L:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_CODEC_JCK_DET_L_EINT);
+       case WM8350_IRQ_CODEC_JCK_DET_R:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_CODEC_JCK_DET_R_EINT);
+       case WM8350_IRQ_CODEC_MICSCD:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_CODEC_MICSCD_EINT);
+       case WM8350_IRQ_CODEC_MICD:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_CODEC_MICD_EINT);
+       case WM8350_IRQ_WKUP_OFF_STATE:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_OFF_STATE_EINT);
+       case WM8350_IRQ_WKUP_HIB_STATE:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_HIB_STATE_EINT);
+       case WM8350_IRQ_WKUP_CONV_FAULT:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_CONV_FAULT_EINT);
+       case WM8350_IRQ_WKUP_WDOG_RST:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_OFF_STATE_EINT);
+       case WM8350_IRQ_WKUP_GP_PWR_ON:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_GP_PWR_ON_EINT);
+       case WM8350_IRQ_WKUP_ONKEY:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_ONKEY_EINT);
+       case WM8350_IRQ_WKUP_GP_WAKEUP:
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_COMPARATOR_INT_STATUS_MASK,
+                                        WM8350_IM_WKUP_GP_WAKEUP_EINT);
+       case WM8350_IRQ_GPIO(0):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP0_EINT);
+       case WM8350_IRQ_GPIO(1):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP1_EINT);
+       case WM8350_IRQ_GPIO(2):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP2_EINT);
+       case WM8350_IRQ_GPIO(3):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP3_EINT);
+       case WM8350_IRQ_GPIO(4):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP4_EINT);
+       case WM8350_IRQ_GPIO(5):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP5_EINT);
+       case WM8350_IRQ_GPIO(6):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP6_EINT);
+       case WM8350_IRQ_GPIO(7):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP7_EINT);
+       case WM8350_IRQ_GPIO(8):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP8_EINT);
+       case WM8350_IRQ_GPIO(9):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP9_EINT);
+       case WM8350_IRQ_GPIO(10):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP10_EINT);
+       case WM8350_IRQ_GPIO(11):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP11_EINT);
+       case WM8350_IRQ_GPIO(12):
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_STATUS_MASK,
+                                        WM8350_IM_GP12_EINT);
+       default:
+               dev_warn(wm8350->dev, "Attempting to unmask unknown IRQ %d\n",
+                        irq);
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+
+/*
+ * Cache is always host endian.
+ */
+static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
+{
+       int i, ret = 0;
+       u16 value;
+       const u16 *reg_map;
+
+       switch (mode) {
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+       case 0:
+               reg_map = wm8350_mode0_defaults;
+               break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+       case 1:
+               reg_map = wm8350_mode1_defaults;
+               break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+       case 2:
+               reg_map = wm8350_mode2_defaults;
+               break;
+#endif
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+       case 3:
+               reg_map = wm8350_mode3_defaults;
+               break;
+#endif
+       default:
+               dev_err(wm8350->dev, "Configuration mode %d not supported\n",
+                       mode);
+               return -EINVAL;
+       }
+
+       wm8350->reg_cache =
+           kzalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL);
+       if (wm8350->reg_cache == NULL)
+               return -ENOMEM;
+
+       /* Read the initial cache state back from the device - this is
+        * a PMIC so the device many not be in a virgin state and we
+        * can't rely on the silicon values.
+        */
+       for (i = 0; i < WM8350_MAX_REGISTER; i++) {
+               /* audio register range */
+               if (wm8350_reg_io_map[i].readable &&
+                   (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) {
+                       ret = wm8350->read_dev(wm8350, i, 2, (char *)&value);
+                       if (ret < 0) {
+                               dev_err(wm8350->dev,
+                                      "failed to read initial cache value\n");
+                               goto out;
+                       }
+                       value = be16_to_cpu(value);
+                       value &= wm8350_reg_io_map[i].readable;
+                       wm8350->reg_cache[i] = value;
+               } else
+                       wm8350->reg_cache[i] = reg_map[i];
+       }
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_create_cache);
+
+/*
+ * Register a client device.  This is non-fatal since there is no need to
+ * fail the entire device init due to a single platform device failing.
+ */
+static void wm8350_client_dev_register(struct wm8350 *wm8350,
+                                      const char *name,
+                                      struct platform_device **pdev)
+{
+       int ret;
+
+       *pdev = platform_device_alloc(name, -1);
+       if (pdev == NULL) {
+               dev_err(wm8350->dev, "Failed to allocate %s\n", name);
+               return;
+       }
+
+       (*pdev)->dev.parent = wm8350->dev;
+       platform_set_drvdata(*pdev, wm8350);
+       ret = platform_device_add(*pdev);
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to register %s: %d\n", name, ret);
+               platform_device_put(*pdev);
+               *pdev = NULL;
+       }
+}
+
+int wm8350_device_init(struct wm8350 *wm8350, int irq,
+                      struct wm8350_platform_data *pdata)
+{
+       int ret = -EINVAL;
+       u16 id1, id2, mask, mode;
+
+       /* get WM8350 revision and config mode */
+       wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
+       wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+
+       id1 = be16_to_cpu(id1);
+       id2 = be16_to_cpu(id2);
+
+       if (id1 == 0x6143) {
+               switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
+               case WM8350_REV_E:
+                       dev_info(wm8350->dev, "Found Rev E device\n");
+                       wm8350->rev = WM8350_REV_E;
+                       break;
+               case WM8350_REV_F:
+                       dev_info(wm8350->dev, "Found Rev F device\n");
+                       wm8350->rev = WM8350_REV_F;
+                       break;
+               case WM8350_REV_G:
+                       dev_info(wm8350->dev, "Found Rev G device\n");
+                       wm8350->rev = WM8350_REV_G;
+                       break;
+               default:
+                       /* For safety we refuse to run on unknown hardware */
+                       dev_info(wm8350->dev, "Found unknown rev\n");
+                       ret = -ENODEV;
+                       goto err;
+               }
+       } else {
+               dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
+                        id1);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       mode = id2 & WM8350_CONF_STS_MASK >> 10;
+       mask = id2 & WM8350_CUST_ID_MASK;
+       dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
+
+       ret = wm8350_create_cache(wm8350, mode);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8350: failed to create register cache\n");
+               return ret;
+       }
+
+       if (pdata->init) {
+               ret = pdata->init(wm8350);
+               if (ret != 0) {
+                       dev_err(wm8350->dev, "Platform init() failed: %d\n",
+                               ret);
+                       goto err;
+               }
+       }
+
+       mutex_init(&wm8350->irq_mutex);
+       INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
+       if (irq != NO_IRQ) {
+               ret = request_irq(irq, wm8350_irq, 0,
+                                 "wm8350", wm8350);
+               if (ret != 0) {
+                       dev_err(wm8350->dev, "Failed to request IRQ: %d\n",
+                               ret);
+                       goto err;
+               }
+       } else {
+               dev_err(wm8350->dev, "No IRQ configured\n");
+               goto err;
+       }
+       wm8350->chip_irq = irq;
+
+       wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
+
+       wm8350_client_dev_register(wm8350, "wm8350-codec",
+                                  &(wm8350->codec.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-gpio",
+                                  &(wm8350->gpio.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-power",
+                                  &(wm8350->power.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-rtc", &(wm8350->rtc.pdev));
+       wm8350_client_dev_register(wm8350, "wm8350-wdt", &(wm8350->wdt.pdev));
+
+       return 0;
+
+err:
+       kfree(wm8350->reg_cache);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_device_init);
+
+void wm8350_device_exit(struct wm8350 *wm8350)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
+               platform_device_unregister(wm8350->pmic.pdev[i]);
+
+       platform_device_unregister(wm8350->wdt.pdev);
+       platform_device_unregister(wm8350->rtc.pdev);
+       platform_device_unregister(wm8350->power.pdev);
+       platform_device_unregister(wm8350->gpio.pdev);
+       platform_device_unregister(wm8350->codec.pdev);
+
+       free_irq(wm8350->chip_irq, wm8350);
+       flush_work(&wm8350->irq_work);
+       kfree(wm8350->reg_cache);
+}
+EXPORT_SYMBOL_GPL(wm8350_device_exit);
+
+MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-gpio.c b/drivers/mfd/wm8350-gpio.c
new file mode 100644 (file)
index 0000000..ebf99be
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * wm8350-core.c  --  Device access for Wolfson WM8350
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/module.h>
+#include <linux/errno.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+
+static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
+{
+       int ret;
+
+       wm8350_reg_unlock(wm8350);
+       if (dir == WM8350_GPIO_DIR_OUT)
+               ret = wm8350_clear_bits(wm8350,
+                                       WM8350_GPIO_CONFIGURATION_I_O,
+                                       1 << gpio);
+       else
+               ret = wm8350_set_bits(wm8350,
+                                     WM8350_GPIO_CONFIGURATION_I_O,
+                                     1 << gpio);
+       wm8350_reg_lock(wm8350);
+       return ret;
+}
+
+static int gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
+{
+       if (db == WM8350_GPIO_DEBOUNCE_ON)
+               return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
+                                      1 << gpio);
+       else
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_DEBOUNCE, 1 << gpio);
+}
+
+static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
+{
+       u16 reg;
+
+       wm8350_reg_unlock(wm8350);
+       switch (gpio) {
+       case 0:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+                   & ~WM8350_GP0_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+                                reg | ((func & 0xf) << 0));
+               break;
+       case 1:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+                   & ~WM8350_GP1_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+                                reg | ((func & 0xf) << 4));
+               break;
+       case 2:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+                   & ~WM8350_GP2_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+                                reg | ((func & 0xf) << 8));
+               break;
+       case 3:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
+                   & ~WM8350_GP3_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
+                                reg | ((func & 0xf) << 12));
+               break;
+       case 4:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+                   & ~WM8350_GP4_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+                                reg | ((func & 0xf) << 0));
+               break;
+       case 5:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+                   & ~WM8350_GP5_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+                                reg | ((func & 0xf) << 4));
+               break;
+       case 6:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+                   & ~WM8350_GP6_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+                                reg | ((func & 0xf) << 8));
+               break;
+       case 7:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
+                   & ~WM8350_GP7_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
+                                reg | ((func & 0xf) << 12));
+               break;
+       case 8:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+                   & ~WM8350_GP8_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+                                reg | ((func & 0xf) << 0));
+               break;
+       case 9:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+                   & ~WM8350_GP9_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+                                reg | ((func & 0xf) << 4));
+               break;
+       case 10:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+                   & ~WM8350_GP10_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+                                reg | ((func & 0xf) << 8));
+               break;
+       case 11:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
+                   & ~WM8350_GP11_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
+                                reg | ((func & 0xf) << 12));
+               break;
+       case 12:
+               reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
+                   & ~WM8350_GP12_FN_MASK;
+               wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
+                                reg | ((func & 0xf) << 0));
+               break;
+       default:
+               wm8350_reg_lock(wm8350);
+               return -EINVAL;
+       }
+
+       wm8350_reg_lock(wm8350);
+       return 0;
+}
+
+static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
+{
+       if (up)
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_PIN_PULL_UP_CONTROL,
+                                      1 << gpio);
+       else
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_PIN_PULL_UP_CONTROL,
+                                        1 << gpio);
+}
+
+static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
+{
+       if (down)
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_PULL_DOWN_CONTROL,
+                                      1 << gpio);
+       else
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_PULL_DOWN_CONTROL,
+                                        1 << gpio);
+}
+
+static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
+{
+       if (pol == WM8350_GPIO_ACTIVE_HIGH)
+               return wm8350_set_bits(wm8350,
+                                      WM8350_GPIO_PIN_POLARITY_TYPE,
+                                      1 << gpio);
+       else
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_PIN_POLARITY_TYPE,
+                                        1 << gpio);
+}
+
+static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
+{
+       if (invert == WM8350_GPIO_INVERT_ON)
+               return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
+       else
+               return wm8350_clear_bits(wm8350,
+                                        WM8350_GPIO_INT_MODE, 1 << gpio);
+}
+
+int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
+                      int pol, int pull, int invert, int debounce)
+{
+       /* make sure we never pull up and down at the same time */
+       if (pull == WM8350_GPIO_PULL_NONE) {
+               if (gpio_set_pull_up(wm8350, gpio, 0))
+                       goto err;
+               if (gpio_set_pull_down(wm8350, gpio, 0))
+                       goto err;
+       } else if (pull == WM8350_GPIO_PULL_UP) {
+               if (gpio_set_pull_down(wm8350, gpio, 0))
+                       goto err;
+               if (gpio_set_pull_up(wm8350, gpio, 1))
+                       goto err;
+       } else if (pull == WM8350_GPIO_PULL_DOWN) {
+               if (gpio_set_pull_up(wm8350, gpio, 0))
+                       goto err;
+               if (gpio_set_pull_down(wm8350, gpio, 1))
+                       goto err;
+       }
+
+       if (gpio_set_invert(wm8350, gpio, invert))
+               goto err;
+       if (gpio_set_polarity(wm8350, gpio, pol))
+               goto err;
+       if (gpio_set_debounce(wm8350, gpio, debounce))
+               goto err;
+       if (gpio_set_dir(wm8350, gpio, dir))
+               goto err;
+       return gpio_set_func(wm8350, gpio, func);
+
+err:
+       return -EIO;
+}
+EXPORT_SYMBOL_GPL(wm8350_gpio_config);
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
new file mode 100644 (file)
index 0000000..8dfe21b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * wm8350-i2c.c  --  Generic I2C driver for Wolfson WM8350 PMIC
+ *
+ * This driver defines and configures the WM8350 for the Freescale i.MX32ADS.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *         linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm8350/core.h>
+
+static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg,
+                                 int bytes, void *dest)
+{
+       int ret;
+
+       ret = i2c_master_send(wm8350->i2c_client, &reg, 1);
+       if (ret < 0)
+               return ret;
+       return i2c_master_recv(wm8350->i2c_client, dest, bytes);
+}
+
+static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg,
+                                  int bytes, void *src)
+{
+       /* we add 1 byte for device register */
+       u8 msg[(WM8350_MAX_REGISTER << 1) + 1];
+
+       if (bytes > ((WM8350_MAX_REGISTER << 1) + 1))
+               return -EINVAL;
+
+       msg[0] = reg;
+       memcpy(&msg[1], src, bytes);
+       return i2c_master_send(wm8350->i2c_client, msg, bytes + 1);
+}
+
+static int wm8350_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct wm8350 *wm8350;
+       int ret = 0;
+
+       wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL);
+       if (wm8350 == NULL) {
+               kfree(i2c);
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(i2c, wm8350);
+       wm8350->dev = &i2c->dev;
+       wm8350->i2c_client = i2c;
+       wm8350->read_dev = wm8350_i2c_read_device;
+       wm8350->write_dev = wm8350_i2c_write_device;
+
+       ret = wm8350_device_init(wm8350, i2c->irq, i2c->dev.platform_data);
+       if (ret < 0)
+               goto err;
+
+       return ret;
+
+err:
+       kfree(wm8350);
+       return ret;
+}
+
+static int wm8350_i2c_remove(struct i2c_client *i2c)
+{
+       struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
+
+       wm8350_device_exit(wm8350);
+       kfree(wm8350);
+
+       return 0;
+}
+
+static const struct i2c_device_id wm8350_i2c_id[] = {
+       { "wm8350", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
+
+
+static struct i2c_driver wm8350_i2c_driver = {
+       .driver = {
+                  .name = "wm8350",
+                  .owner = THIS_MODULE,
+       },
+       .probe = wm8350_i2c_probe,
+       .remove = wm8350_i2c_remove,
+       .id_table = wm8350_i2c_id,
+};
+
+static int __init wm8350_i2c_init(void)
+{
+       return i2c_add_driver(&wm8350_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(wm8350_i2c_init);
+
+static void __exit wm8350_i2c_exit(void)
+{
+       i2c_del_driver(&wm8350_i2c_driver);
+}
+module_exit(wm8350_i2c_exit);
+
+MODULE_DESCRIPTION("I2C support for the WM8350 AudioPlus PMIC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
new file mode 100644 (file)
index 0000000..974678d
--- /dev/null
@@ -0,0 +1,1347 @@
+/*
+ * wm8350-regmap.c  --  Wolfson Microelectronics WM8350 register map
+ *
+ * This file splits out the tables describing the defaults and access
+ * status of the WM8350 registers since they are rather large.
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/mfd/wm8350/core.h>
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode0_defaults[] = {
+       0x17FF,     /* R0   - Reset/ID */
+       0x1000,     /* R1   - ID */
+       0x0000,     /* R2 */
+       0x1002,     /* R3   - System Control 1 */
+       0x0004,     /* R4   - System Control 2 */
+       0x0000,     /* R5   - System Hibernate */
+       0x8A00,     /* R6   - Interface Control */
+       0x0000,     /* R7 */
+       0x8000,     /* R8   - Power mgmt (1) */
+       0x0000,     /* R9   - Power mgmt (2) */
+       0x0000,     /* R10  - Power mgmt (3) */
+       0x2000,     /* R11  - Power mgmt (4) */
+       0x0E00,     /* R12  - Power mgmt (5) */
+       0x0000,     /* R13  - Power mgmt (6) */
+       0x0000,     /* R14  - Power mgmt (7) */
+       0x0000,     /* R15 */
+       0x0000,     /* R16  - RTC Seconds/Minutes */
+       0x0100,     /* R17  - RTC Hours/Day */
+       0x0101,     /* R18  - RTC Date/Month */
+       0x1400,     /* R19  - RTC Year */
+       0x0000,     /* R20  - Alarm Seconds/Minutes */
+       0x0000,     /* R21  - Alarm Hours/Day */
+       0x0000,     /* R22  - Alarm Date/Month */
+       0x0320,     /* R23  - RTC Time Control */
+       0x0000,     /* R24  - System Interrupts */
+       0x0000,     /* R25  - Interrupt Status 1 */
+       0x0000,     /* R26  - Interrupt Status 2 */
+       0x0000,     /* R27  - Power Up Interrupt Status */
+       0x0000,     /* R28  - Under Voltage Interrupt status */
+       0x0000,     /* R29  - Over Current Interrupt status */
+       0x0000,     /* R30  - GPIO Interrupt Status */
+       0x0000,     /* R31  - Comparator Interrupt Status */
+       0x3FFF,     /* R32  - System Interrupts Mask */
+       0x0000,     /* R33  - Interrupt Status 1 Mask */
+       0x0000,     /* R34  - Interrupt Status 2 Mask */
+       0x0000,     /* R35  - Power Up Interrupt Status Mask */
+       0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+       0x0000,     /* R37  - Over Current Interrupt status Mask */
+       0x0000,     /* R38  - GPIO Interrupt Status Mask */
+       0x0000,     /* R39  - Comparator Interrupt Status Mask */
+       0x0040,     /* R40  - Clock Control 1 */
+       0x0000,     /* R41  - Clock Control 2 */
+       0x3B00,     /* R42  - FLL Control 1 */
+       0x7086,     /* R43  - FLL Control 2 */
+       0xC226,     /* R44  - FLL Control 3 */
+       0x0000,     /* R45  - FLL Control 4 */
+       0x0000,     /* R46 */
+       0x0000,     /* R47 */
+       0x0000,     /* R48  - DAC Control */
+       0x0000,     /* R49 */
+       0x00C0,     /* R50  - DAC Digital Volume L */
+       0x00C0,     /* R51  - DAC Digital Volume R */
+       0x0000,     /* R52 */
+       0x0040,     /* R53  - DAC LR Rate */
+       0x0000,     /* R54  - DAC Clock Control */
+       0x0000,     /* R55 */
+       0x0000,     /* R56 */
+       0x0000,     /* R57 */
+       0x4000,     /* R58  - DAC Mute */
+       0x0000,     /* R59  - DAC Mute Volume */
+       0x0000,     /* R60  - DAC Side */
+       0x0000,     /* R61 */
+       0x0000,     /* R62 */
+       0x0000,     /* R63 */
+       0x8000,     /* R64  - ADC Control */
+       0x0000,     /* R65 */
+       0x00C0,     /* R66  - ADC Digital Volume L */
+       0x00C0,     /* R67  - ADC Digital Volume R */
+       0x0000,     /* R68  - ADC Divider */
+       0x0000,     /* R69 */
+       0x0040,     /* R70  - ADC LR Rate */
+       0x0000,     /* R71 */
+       0x0303,     /* R72  - Input Control */
+       0x0000,     /* R73  - IN3 Input Control */
+       0x0000,     /* R74  - Mic Bias Control */
+       0x0000,     /* R75 */
+       0x0000,     /* R76  - Output Control */
+       0x0000,     /* R77  - Jack Detect */
+       0x0000,     /* R78  - Anti Pop Control */
+       0x0000,     /* R79 */
+       0x0040,     /* R80  - Left Input Volume */
+       0x0040,     /* R81  - Right Input Volume */
+       0x0000,     /* R82 */
+       0x0000,     /* R83 */
+       0x0000,     /* R84 */
+       0x0000,     /* R85 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87 */
+       0x0800,     /* R88  - Left Mixer Control */
+       0x1000,     /* R89  - Right Mixer Control */
+       0x0000,     /* R90 */
+       0x0000,     /* R91 */
+       0x0000,     /* R92  - OUT3 Mixer Control */
+       0x0000,     /* R93  - OUT4 Mixer Control */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0000,     /* R96  - Output Left Mixer Volume */
+       0x0000,     /* R97  - Output Right Mixer Volume */
+       0x0000,     /* R98  - Input Mixer Volume L */
+       0x0000,     /* R99  - Input Mixer Volume R */
+       0x0000,     /* R100 - Input Mixer Volume */
+       0x0000,     /* R101 */
+       0x0000,     /* R102 */
+       0x0000,     /* R103 */
+       0x00E4,     /* R104 - LOUT1 Volume */
+       0x00E4,     /* R105 - ROUT1 Volume */
+       0x00E4,     /* R106 - LOUT2 Volume */
+       0x02E4,     /* R107 - ROUT2 Volume */
+       0x0000,     /* R108 */
+       0x0000,     /* R109 */
+       0x0000,     /* R110 */
+       0x0000,     /* R111 - BEEP Volume */
+       0x0A00,     /* R112 - AI Formating */
+       0x0000,     /* R113 - ADC DAC COMP */
+       0x0020,     /* R114 - AI ADC Control */
+       0x0020,     /* R115 - AI DAC Control */
+       0x0000,     /* R116 - AIF Test */
+       0x0000,     /* R117 */
+       0x0000,     /* R118 */
+       0x0000,     /* R119 */
+       0x0000,     /* R120 */
+       0x0000,     /* R121 */
+       0x0000,     /* R122 */
+       0x0000,     /* R123 */
+       0x0000,     /* R124 */
+       0x0000,     /* R125 */
+       0x0000,     /* R126 */
+       0x0000,     /* R127 */
+       0x1FFF,     /* R128 - GPIO Debounce */
+       0x0000,     /* R129 - GPIO Pin pull up Control */
+       0x03FC,     /* R130 - GPIO Pull down Control */
+       0x0000,     /* R131 - GPIO Interrupt Mode */
+       0x0000,     /* R132 */
+       0x0000,     /* R133 - GPIO Control */
+       0x0FFC,     /* R134 - GPIO Configuration (i/o) */
+       0x0FFC,     /* R135 - GPIO Pin Polarity / Type */
+       0x0000,     /* R136 */
+       0x0000,     /* R137 */
+       0x0000,     /* R138 */
+       0x0000,     /* R139 */
+       0x0013,     /* R140 - GPIO Function Select 1 */
+       0x0000,     /* R141 - GPIO Function Select 2 */
+       0x0000,     /* R142 - GPIO Function Select 3 */
+       0x0003,     /* R143 - GPIO Function Select 4 */
+       0x0000,     /* R144 - Digitiser Control (1) */
+       0x0002,     /* R145 - Digitiser Control (2) */
+       0x0000,     /* R146 */
+       0x0000,     /* R147 */
+       0x0000,     /* R148 */
+       0x0000,     /* R149 */
+       0x0000,     /* R150 */
+       0x0000,     /* R151 */
+       0x7000,     /* R152 - AUX1 Readback */
+       0x7000,     /* R153 - AUX2 Readback */
+       0x7000,     /* R154 - AUX3 Readback */
+       0x7000,     /* R155 - AUX4 Readback */
+       0x0000,     /* R156 - USB Voltage Readback */
+       0x0000,     /* R157 - LINE Voltage Readback */
+       0x0000,     /* R158 - BATT Voltage Readback */
+       0x0000,     /* R159 - Chip Temp Readback */
+       0x0000,     /* R160 */
+       0x0000,     /* R161 */
+       0x0000,     /* R162 */
+       0x0000,     /* R163 - Generic Comparator Control */
+       0x0000,     /* R164 - Generic comparator 1 */
+       0x0000,     /* R165 - Generic comparator 2 */
+       0x0000,     /* R166 - Generic comparator 3 */
+       0x0000,     /* R167 - Generic comparator 4 */
+       0xA00F,     /* R168 - Battery Charger Control 1 */
+       0x0B06,     /* R169 - Battery Charger Control 2 */
+       0x0000,     /* R170 - Battery Charger Control 3 */
+       0x0000,     /* R171 */
+       0x0000,     /* R172 - Current Sink Driver A */
+       0x0000,     /* R173 - CSA Flash control */
+       0x0000,     /* R174 - Current Sink Driver B */
+       0x0000,     /* R175 - CSB Flash control */
+       0x0000,     /* R176 - DCDC/LDO requested */
+       0x002D,     /* R177 - DCDC Active options */
+       0x0000,     /* R178 - DCDC Sleep options */
+       0x0025,     /* R179 - Power-check comparator */
+       0x000E,     /* R180 - DCDC1 Control */
+       0x0000,     /* R181 - DCDC1 Timeouts */
+       0x1006,     /* R182 - DCDC1 Low Power */
+       0x0018,     /* R183 - DCDC2 Control */
+       0x0000,     /* R184 - DCDC2 Timeouts */
+       0x0000,     /* R185 */
+       0x0000,     /* R186 - DCDC3 Control */
+       0x0000,     /* R187 - DCDC3 Timeouts */
+       0x0006,     /* R188 - DCDC3 Low Power */
+       0x0000,     /* R189 - DCDC4 Control */
+       0x0000,     /* R190 - DCDC4 Timeouts */
+       0x0006,     /* R191 - DCDC4 Low Power */
+       0x0008,     /* R192 - DCDC5 Control */
+       0x0000,     /* R193 - DCDC5 Timeouts */
+       0x0000,     /* R194 */
+       0x0000,     /* R195 - DCDC6 Control */
+       0x0000,     /* R196 - DCDC6 Timeouts */
+       0x0006,     /* R197 - DCDC6 Low Power */
+       0x0000,     /* R198 */
+       0x0003,     /* R199 - Limit Switch Control */
+       0x001C,     /* R200 - LDO1 Control */
+       0x0000,     /* R201 - LDO1 Timeouts */
+       0x001C,     /* R202 - LDO1 Low Power */
+       0x001B,     /* R203 - LDO2 Control */
+       0x0000,     /* R204 - LDO2 Timeouts */
+       0x001C,     /* R205 - LDO2 Low Power */
+       0x001B,     /* R206 - LDO3 Control */
+       0x0000,     /* R207 - LDO3 Timeouts */
+       0x001C,     /* R208 - LDO3 Low Power */
+       0x001B,     /* R209 - LDO4 Control */
+       0x0000,     /* R210 - LDO4 Timeouts */
+       0x001C,     /* R211 - LDO4 Low Power */
+       0x0000,     /* R212 */
+       0x0000,     /* R213 */
+       0x0000,     /* R214 */
+       0x0000,     /* R215 - VCC_FAULT Masks */
+       0x001F,     /* R216 - Main Bandgap Control */
+       0x0000,     /* R217 - OSC Control */
+       0x9000,     /* R218 - RTC Tick Control */
+       0x0000,     /* R219 */
+       0x4000,     /* R220 - RAM BIST 1 */
+       0x0000,     /* R221 */
+       0x0000,     /* R222 */
+       0x0000,     /* R223 */
+       0x0000,     /* R224 */
+       0x0000,     /* R225 - DCDC/LDO status */
+       0x0000,     /* R226 */
+       0x0000,     /* R227 */
+       0x0000,     /* R228 */
+       0x0000,     /* R229 */
+       0xE000,     /* R230 - GPIO Pin Status */
+       0x0000,     /* R231 */
+       0x0000,     /* R232 */
+       0x0000,     /* R233 */
+       0x0000,     /* R234 */
+       0x0000,     /* R235 */
+       0x0000,     /* R236 */
+       0x0000,     /* R237 */
+       0x0000,     /* R238 */
+       0x0000,     /* R239 */
+       0x0000,     /* R240 */
+       0x0000,     /* R241 */
+       0x0000,     /* R242 */
+       0x0000,     /* R243 */
+       0x0000,     /* R244 */
+       0x0000,     /* R245 */
+       0x0000,     /* R246 */
+       0x0000,     /* R247 */
+       0x0000,     /* R248 */
+       0x0000,     /* R249 */
+       0x0000,     /* R250 */
+       0x0000,     /* R251 */
+       0x0000,     /* R252 */
+       0x0000,     /* R253 */
+       0x0000,     /* R254 */
+       0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode1_defaults[] = {
+       0x17FF,     /* R0   - Reset/ID */
+       0x1000,     /* R1   - ID */
+       0x0000,     /* R2 */
+       0x1002,     /* R3   - System Control 1 */
+       0x0014,     /* R4   - System Control 2 */
+       0x0000,     /* R5   - System Hibernate */
+       0x8A00,     /* R6   - Interface Control */
+       0x0000,     /* R7 */
+       0x8000,     /* R8   - Power mgmt (1) */
+       0x0000,     /* R9   - Power mgmt (2) */
+       0x0000,     /* R10  - Power mgmt (3) */
+       0x2000,     /* R11  - Power mgmt (4) */
+       0x0E00,     /* R12  - Power mgmt (5) */
+       0x0000,     /* R13  - Power mgmt (6) */
+       0x0000,     /* R14  - Power mgmt (7) */
+       0x0000,     /* R15 */
+       0x0000,     /* R16  - RTC Seconds/Minutes */
+       0x0100,     /* R17  - RTC Hours/Day */
+       0x0101,     /* R18  - RTC Date/Month */
+       0x1400,     /* R19  - RTC Year */
+       0x0000,     /* R20  - Alarm Seconds/Minutes */
+       0x0000,     /* R21  - Alarm Hours/Day */
+       0x0000,     /* R22  - Alarm Date/Month */
+       0x0320,     /* R23  - RTC Time Control */
+       0x0000,     /* R24  - System Interrupts */
+       0x0000,     /* R25  - Interrupt Status 1 */
+       0x0000,     /* R26  - Interrupt Status 2 */
+       0x0000,     /* R27  - Power Up Interrupt Status */
+       0x0000,     /* R28  - Under Voltage Interrupt status */
+       0x0000,     /* R29  - Over Current Interrupt status */
+       0x0000,     /* R30  - GPIO Interrupt Status */
+       0x0000,     /* R31  - Comparator Interrupt Status */
+       0x3FFF,     /* R32  - System Interrupts Mask */
+       0x0000,     /* R33  - Interrupt Status 1 Mask */
+       0x0000,     /* R34  - Interrupt Status 2 Mask */
+       0x0000,     /* R35  - Power Up Interrupt Status Mask */
+       0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+       0x0000,     /* R37  - Over Current Interrupt status Mask */
+       0x0000,     /* R38  - GPIO Interrupt Status Mask */
+       0x0000,     /* R39  - Comparator Interrupt Status Mask */
+       0x0040,     /* R40  - Clock Control 1 */
+       0x0000,     /* R41  - Clock Control 2 */
+       0x3B00,     /* R42  - FLL Control 1 */
+       0x7086,     /* R43  - FLL Control 2 */
+       0xC226,     /* R44  - FLL Control 3 */
+       0x0000,     /* R45  - FLL Control 4 */
+       0x0000,     /* R46 */
+       0x0000,     /* R47 */
+       0x0000,     /* R48  - DAC Control */
+       0x0000,     /* R49 */
+       0x00C0,     /* R50  - DAC Digital Volume L */
+       0x00C0,     /* R51  - DAC Digital Volume R */
+       0x0000,     /* R52 */
+       0x0040,     /* R53  - DAC LR Rate */
+       0x0000,     /* R54  - DAC Clock Control */
+       0x0000,     /* R55 */
+       0x0000,     /* R56 */
+       0x0000,     /* R57 */
+       0x4000,     /* R58  - DAC Mute */
+       0x0000,     /* R59  - DAC Mute Volume */
+       0x0000,     /* R60  - DAC Side */
+       0x0000,     /* R61 */
+       0x0000,     /* R62 */
+       0x0000,     /* R63 */
+       0x8000,     /* R64  - ADC Control */
+       0x0000,     /* R65 */
+       0x00C0,     /* R66  - ADC Digital Volume L */
+       0x00C0,     /* R67  - ADC Digital Volume R */
+       0x0000,     /* R68  - ADC Divider */
+       0x0000,     /* R69 */
+       0x0040,     /* R70  - ADC LR Rate */
+       0x0000,     /* R71 */
+       0x0303,     /* R72  - Input Control */
+       0x0000,     /* R73  - IN3 Input Control */
+       0x0000,     /* R74  - Mic Bias Control */
+       0x0000,     /* R75 */
+       0x0000,     /* R76  - Output Control */
+       0x0000,     /* R77  - Jack Detect */
+       0x0000,     /* R78  - Anti Pop Control */
+       0x0000,     /* R79 */
+       0x0040,     /* R80  - Left Input Volume */
+       0x0040,     /* R81  - Right Input Volume */
+       0x0000,     /* R82 */
+       0x0000,     /* R83 */
+       0x0000,     /* R84 */
+       0x0000,     /* R85 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87 */
+       0x0800,     /* R88  - Left Mixer Control */
+       0x1000,     /* R89  - Right Mixer Control */
+       0x0000,     /* R90 */
+       0x0000,     /* R91 */
+       0x0000,     /* R92  - OUT3 Mixer Control */
+       0x0000,     /* R93  - OUT4 Mixer Control */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0000,     /* R96  - Output Left Mixer Volume */
+       0x0000,     /* R97  - Output Right Mixer Volume */
+       0x0000,     /* R98  - Input Mixer Volume L */
+       0x0000,     /* R99  - Input Mixer Volume R */
+       0x0000,     /* R100 - Input Mixer Volume */
+       0x0000,     /* R101 */
+       0x0000,     /* R102 */
+       0x0000,     /* R103 */
+       0x00E4,     /* R104 - LOUT1 Volume */
+       0x00E4,     /* R105 - ROUT1 Volume */
+       0x00E4,     /* R106 - LOUT2 Volume */
+       0x02E4,     /* R107 - ROUT2 Volume */
+       0x0000,     /* R108 */
+       0x0000,     /* R109 */
+       0x0000,     /* R110 */
+       0x0000,     /* R111 - BEEP Volume */
+       0x0A00,     /* R112 - AI Formating */
+       0x0000,     /* R113 - ADC DAC COMP */
+       0x0020,     /* R114 - AI ADC Control */
+       0x0020,     /* R115 - AI DAC Control */
+       0x0000,     /* R116 - AIF Test */
+       0x0000,     /* R117 */
+       0x0000,     /* R118 */
+       0x0000,     /* R119 */
+       0x0000,     /* R120 */
+       0x0000,     /* R121 */
+       0x0000,     /* R122 */
+       0x0000,     /* R123 */
+       0x0000,     /* R124 */
+       0x0000,     /* R125 */
+       0x0000,     /* R126 */
+       0x0000,     /* R127 */
+       0x1FFF,     /* R128 - GPIO Debounce */
+       0x0000,     /* R129 - GPIO Pin pull up Control */
+       0x03FC,     /* R130 - GPIO Pull down Control */
+       0x0000,     /* R131 - GPIO Interrupt Mode */
+       0x0000,     /* R132 */
+       0x0000,     /* R133 - GPIO Control */
+       0x00FB,     /* R134 - GPIO Configuration (i/o) */
+       0x04FE,     /* R135 - GPIO Pin Polarity / Type */
+       0x0000,     /* R136 */
+       0x0000,     /* R137 */
+       0x0000,     /* R138 */
+       0x0000,     /* R139 */
+       0x0312,     /* R140 - GPIO Function Select 1 */
+       0x1003,     /* R141 - GPIO Function Select 2 */
+       0x1331,     /* R142 - GPIO Function Select 3 */
+       0x0003,     /* R143 - GPIO Function Select 4 */
+       0x0000,     /* R144 - Digitiser Control (1) */
+       0x0002,     /* R145 - Digitiser Control (2) */
+       0x0000,     /* R146 */
+       0x0000,     /* R147 */
+       0x0000,     /* R148 */
+       0x0000,     /* R149 */
+       0x0000,     /* R150 */
+       0x0000,     /* R151 */
+       0x7000,     /* R152 - AUX1 Readback */
+       0x7000,     /* R153 - AUX2 Readback */
+       0x7000,     /* R154 - AUX3 Readback */
+       0x7000,     /* R155 - AUX4 Readback */
+       0x0000,     /* R156 - USB Voltage Readback */
+       0x0000,     /* R157 - LINE Voltage Readback */
+       0x0000,     /* R158 - BATT Voltage Readback */
+       0x0000,     /* R159 - Chip Temp Readback */
+       0x0000,     /* R160 */
+       0x0000,     /* R161 */
+       0x0000,     /* R162 */
+       0x0000,     /* R163 - Generic Comparator Control */
+       0x0000,     /* R164 - Generic comparator 1 */
+       0x0000,     /* R165 - Generic comparator 2 */
+       0x0000,     /* R166 - Generic comparator 3 */
+       0x0000,     /* R167 - Generic comparator 4 */
+       0xA00F,     /* R168 - Battery Charger Control 1 */
+       0x0B06,     /* R169 - Battery Charger Control 2 */
+       0x0000,     /* R170 - Battery Charger Control 3 */
+       0x0000,     /* R171 */
+       0x0000,     /* R172 - Current Sink Driver A */
+       0x0000,     /* R173 - CSA Flash control */
+       0x0000,     /* R174 - Current Sink Driver B */
+       0x0000,     /* R175 - CSB Flash control */
+       0x0000,     /* R176 - DCDC/LDO requested */
+       0x002D,     /* R177 - DCDC Active options */
+       0x0000,     /* R178 - DCDC Sleep options */
+       0x0025,     /* R179 - Power-check comparator */
+       0x0062,     /* R180 - DCDC1 Control */
+       0x0400,     /* R181 - DCDC1 Timeouts */
+       0x1006,     /* R182 - DCDC1 Low Power */
+       0x0018,     /* R183 - DCDC2 Control */
+       0x0000,     /* R184 - DCDC2 Timeouts */
+       0x0000,     /* R185 */
+       0x0026,     /* R186 - DCDC3 Control */
+       0x0400,     /* R187 - DCDC3 Timeouts */
+       0x0006,     /* R188 - DCDC3 Low Power */
+       0x0062,     /* R189 - DCDC4 Control */
+       0x0400,     /* R190 - DCDC4 Timeouts */
+       0x0006,     /* R191 - DCDC4 Low Power */
+       0x0008,     /* R192 - DCDC5 Control */
+       0x0000,     /* R193 - DCDC5 Timeouts */
+       0x0000,     /* R194 */
+       0x0026,     /* R195 - DCDC6 Control */
+       0x0800,     /* R196 - DCDC6 Timeouts */
+       0x0006,     /* R197 - DCDC6 Low Power */
+       0x0000,     /* R198 */
+       0x0003,     /* R199 - Limit Switch Control */
+       0x0006,     /* R200 - LDO1 Control */
+       0x0400,     /* R201 - LDO1 Timeouts */
+       0x001C,     /* R202 - LDO1 Low Power */
+       0x0006,     /* R203 - LDO2 Control */
+       0x0400,     /* R204 - LDO2 Timeouts */
+       0x001C,     /* R205 - LDO2 Low Power */
+       0x001B,     /* R206 - LDO3 Control */
+       0x0000,     /* R207 - LDO3 Timeouts */
+       0x001C,     /* R208 - LDO3 Low Power */
+       0x001B,     /* R209 - LDO4 Control */
+       0x0000,     /* R210 - LDO4 Timeouts */
+       0x001C,     /* R211 - LDO4 Low Power */
+       0x0000,     /* R212 */
+       0x0000,     /* R213 */
+       0x0000,     /* R214 */
+       0x0000,     /* R215 - VCC_FAULT Masks */
+       0x001F,     /* R216 - Main Bandgap Control */
+       0x0000,     /* R217 - OSC Control */
+       0x9000,     /* R218 - RTC Tick Control */
+       0x0000,     /* R219 */
+       0x4000,     /* R220 - RAM BIST 1 */
+       0x0000,     /* R221 */
+       0x0000,     /* R222 */
+       0x0000,     /* R223 */
+       0x0000,     /* R224 */
+       0x0000,     /* R225 - DCDC/LDO status */
+       0x0000,     /* R226 */
+       0x0000,     /* R227 */
+       0x0000,     /* R228 */
+       0x0000,     /* R229 */
+       0xE000,     /* R230 - GPIO Pin Status */
+       0x0000,     /* R231 */
+       0x0000,     /* R232 */
+       0x0000,     /* R233 */
+       0x0000,     /* R234 */
+       0x0000,     /* R235 */
+       0x0000,     /* R236 */
+       0x0000,     /* R237 */
+       0x0000,     /* R238 */
+       0x0000,     /* R239 */
+       0x0000,     /* R240 */
+       0x0000,     /* R241 */
+       0x0000,     /* R242 */
+       0x0000,     /* R243 */
+       0x0000,     /* R244 */
+       0x0000,     /* R245 */
+       0x0000,     /* R246 */
+       0x0000,     /* R247 */
+       0x0000,     /* R248 */
+       0x0000,     /* R249 */
+       0x0000,     /* R250 */
+       0x0000,     /* R251 */
+       0x0000,     /* R252 */
+       0x0000,     /* R253 */
+       0x0000,     /* R254 */
+       0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode2_defaults[] = {
+       0x17FF,     /* R0   - Reset/ID */
+       0x1000,     /* R1   - ID */
+       0x0000,     /* R2 */
+       0x1002,     /* R3   - System Control 1 */
+       0x0014,     /* R4   - System Control 2 */
+       0x0000,     /* R5   - System Hibernate */
+       0x8A00,     /* R6   - Interface Control */
+       0x0000,     /* R7 */
+       0x8000,     /* R8   - Power mgmt (1) */
+       0x0000,     /* R9   - Power mgmt (2) */
+       0x0000,     /* R10  - Power mgmt (3) */
+       0x2000,     /* R11  - Power mgmt (4) */
+       0x0E00,     /* R12  - Power mgmt (5) */
+       0x0000,     /* R13  - Power mgmt (6) */
+       0x0000,     /* R14  - Power mgmt (7) */
+       0x0000,     /* R15 */
+       0x0000,     /* R16  - RTC Seconds/Minutes */
+       0x0100,     /* R17  - RTC Hours/Day */
+       0x0101,     /* R18  - RTC Date/Month */
+       0x1400,     /* R19  - RTC Year */
+       0x0000,     /* R20  - Alarm Seconds/Minutes */
+       0x0000,     /* R21  - Alarm Hours/Day */
+       0x0000,     /* R22  - Alarm Date/Month */
+       0x0320,     /* R23  - RTC Time Control */
+       0x0000,     /* R24  - System Interrupts */
+       0x0000,     /* R25  - Interrupt Status 1 */
+       0x0000,     /* R26  - Interrupt Status 2 */
+       0x0000,     /* R27  - Power Up Interrupt Status */
+       0x0000,     /* R28  - Under Voltage Interrupt status */
+       0x0000,     /* R29  - Over Current Interrupt status */
+       0x0000,     /* R30  - GPIO Interrupt Status */
+       0x0000,     /* R31  - Comparator Interrupt Status */
+       0x3FFF,     /* R32  - System Interrupts Mask */
+       0x0000,     /* R33  - Interrupt Status 1 Mask */
+       0x0000,     /* R34  - Interrupt Status 2 Mask */
+       0x0000,     /* R35  - Power Up Interrupt Status Mask */
+       0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+       0x0000,     /* R37  - Over Current Interrupt status Mask */
+       0x0000,     /* R38  - GPIO Interrupt Status Mask */
+       0x0000,     /* R39  - Comparator Interrupt Status Mask */
+       0x0040,     /* R40  - Clock Control 1 */
+       0x0000,     /* R41  - Clock Control 2 */
+       0x3B00,     /* R42  - FLL Control 1 */
+       0x7086,     /* R43  - FLL Control 2 */
+       0xC226,     /* R44  - FLL Control 3 */
+       0x0000,     /* R45  - FLL Control 4 */
+       0x0000,     /* R46 */
+       0x0000,     /* R47 */
+       0x0000,     /* R48  - DAC Control */
+       0x0000,     /* R49 */
+       0x00C0,     /* R50  - DAC Digital Volume L */
+       0x00C0,     /* R51  - DAC Digital Volume R */
+       0x0000,     /* R52 */
+       0x0040,     /* R53  - DAC LR Rate */
+       0x0000,     /* R54  - DAC Clock Control */
+       0x0000,     /* R55 */
+       0x0000,     /* R56 */
+       0x0000,     /* R57 */
+       0x4000,     /* R58  - DAC Mute */
+       0x0000,     /* R59  - DAC Mute Volume */
+       0x0000,     /* R60  - DAC Side */
+       0x0000,     /* R61 */
+       0x0000,     /* R62 */
+       0x0000,     /* R63 */
+       0x8000,     /* R64  - ADC Control */
+       0x0000,     /* R65 */
+       0x00C0,     /* R66  - ADC Digital Volume L */
+       0x00C0,     /* R67  - ADC Digital Volume R */
+       0x0000,     /* R68  - ADC Divider */
+       0x0000,     /* R69 */
+       0x0040,     /* R70  - ADC LR Rate */
+       0x0000,     /* R71 */
+       0x0303,     /* R72  - Input Control */
+       0x0000,     /* R73  - IN3 Input Control */
+       0x0000,     /* R74  - Mic Bias Control */
+       0x0000,     /* R75 */
+       0x0000,     /* R76  - Output Control */
+       0x0000,     /* R77  - Jack Detect */
+       0x0000,     /* R78  - Anti Pop Control */
+       0x0000,     /* R79 */
+       0x0040,     /* R80  - Left Input Volume */
+       0x0040,     /* R81  - Right Input Volume */
+       0x0000,     /* R82 */
+       0x0000,     /* R83 */
+       0x0000,     /* R84 */
+       0x0000,     /* R85 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87 */
+       0x0800,     /* R88  - Left Mixer Control */
+       0x1000,     /* R89  - Right Mixer Control */
+       0x0000,     /* R90 */
+       0x0000,     /* R91 */
+       0x0000,     /* R92  - OUT3 Mixer Control */
+       0x0000,     /* R93  - OUT4 Mixer Control */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0000,     /* R96  - Output Left Mixer Volume */
+       0x0000,     /* R97  - Output Right Mixer Volume */
+       0x0000,     /* R98  - Input Mixer Volume L */
+       0x0000,     /* R99  - Input Mixer Volume R */
+       0x0000,     /* R100 - Input Mixer Volume */
+       0x0000,     /* R101 */
+       0x0000,     /* R102 */
+       0x0000,     /* R103 */
+       0x00E4,     /* R104 - LOUT1 Volume */
+       0x00E4,     /* R105 - ROUT1 Volume */
+       0x00E4,     /* R106 - LOUT2 Volume */
+       0x02E4,     /* R107 - ROUT2 Volume */
+       0x0000,     /* R108 */
+       0x0000,     /* R109 */
+       0x0000,     /* R110 */
+       0x0000,     /* R111 - BEEP Volume */
+       0x0A00,     /* R112 - AI Formating */
+       0x0000,     /* R113 - ADC DAC COMP */
+       0x0020,     /* R114 - AI ADC Control */
+       0x0020,     /* R115 - AI DAC Control */
+       0x0000,     /* R116 - AIF Test */
+       0x0000,     /* R117 */
+       0x0000,     /* R118 */
+       0x0000,     /* R119 */
+       0x0000,     /* R120 */
+       0x0000,     /* R121 */
+       0x0000,     /* R122 */
+       0x0000,     /* R123 */
+       0x0000,     /* R124 */
+       0x0000,     /* R125 */
+       0x0000,     /* R126 */
+       0x0000,     /* R127 */
+       0x1FFF,     /* R128 - GPIO Debounce */
+       0x0000,     /* R129 - GPIO Pin pull up Control */
+       0x03FC,     /* R130 - GPIO Pull down Control */
+       0x0000,     /* R131 - GPIO Interrupt Mode */
+       0x0000,     /* R132 */
+       0x0000,     /* R133 - GPIO Control */
+       0x08FB,     /* R134 - GPIO Configuration (i/o) */
+       0x0CFE,     /* R135 - GPIO Pin Polarity / Type */
+       0x0000,     /* R136 */
+       0x0000,     /* R137 */
+       0x0000,     /* R138 */
+       0x0000,     /* R139 */
+       0x0312,     /* R140 - GPIO Function Select 1 */
+       0x0003,     /* R141 - GPIO Function Select 2 */
+       0x2331,     /* R142 - GPIO Function Select 3 */
+       0x0003,     /* R143 - GPIO Function Select 4 */
+       0x0000,     /* R144 - Digitiser Control (1) */
+       0x0002,     /* R145 - Digitiser Control (2) */
+       0x0000,     /* R146 */
+       0x0000,     /* R147 */
+       0x0000,     /* R148 */
+       0x0000,     /* R149 */
+       0x0000,     /* R150 */
+       0x0000,     /* R151 */
+       0x7000,     /* R152 - AUX1 Readback */
+       0x7000,     /* R153 - AUX2 Readback */
+       0x7000,     /* R154 - AUX3 Readback */
+       0x7000,     /* R155 - AUX4 Readback */
+       0x0000,     /* R156 - USB Voltage Readback */
+       0x0000,     /* R157 - LINE Voltage Readback */
+       0x0000,     /* R158 - BATT Voltage Readback */
+       0x0000,     /* R159 - Chip Temp Readback */
+       0x0000,     /* R160 */
+       0x0000,     /* R161 */
+       0x0000,     /* R162 */
+       0x0000,     /* R163 - Generic Comparator Control */
+       0x0000,     /* R164 - Generic comparator 1 */
+       0x0000,     /* R165 - Generic comparator 2 */
+       0x0000,     /* R166 - Generic comparator 3 */
+       0x0000,     /* R167 - Generic comparator 4 */
+       0xA00F,     /* R168 - Battery Charger Control 1 */
+       0x0B06,     /* R169 - Battery Charger Control 2 */
+       0x0000,     /* R170 - Battery Charger Control 3 */
+       0x0000,     /* R171 */
+       0x0000,     /* R172 - Current Sink Driver A */
+       0x0000,     /* R173 - CSA Flash control */
+       0x0000,     /* R174 - Current Sink Driver B */
+       0x0000,     /* R175 - CSB Flash control */
+       0x0000,     /* R176 - DCDC/LDO requested */
+       0x002D,     /* R177 - DCDC Active options */
+       0x0000,     /* R178 - DCDC Sleep options */
+       0x0025,     /* R179 - Power-check comparator */
+       0x000E,     /* R180 - DCDC1 Control */
+       0x0400,     /* R181 - DCDC1 Timeouts */
+       0x1006,     /* R182 - DCDC1 Low Power */
+       0x0018,     /* R183 - DCDC2 Control */
+       0x0000,     /* R184 - DCDC2 Timeouts */
+       0x0000,     /* R185 */
+       0x002E,     /* R186 - DCDC3 Control */
+       0x0800,     /* R187 - DCDC3 Timeouts */
+       0x0006,     /* R188 - DCDC3 Low Power */
+       0x000E,     /* R189 - DCDC4 Control */
+       0x0800,     /* R190 - DCDC4 Timeouts */
+       0x0006,     /* R191 - DCDC4 Low Power */
+       0x0008,     /* R192 - DCDC5 Control */
+       0x0000,     /* R193 - DCDC5 Timeouts */
+       0x0000,     /* R194 */
+       0x0026,     /* R195 - DCDC6 Control */
+       0x0C00,     /* R196 - DCDC6 Timeouts */
+       0x0006,     /* R197 - DCDC6 Low Power */
+       0x0000,     /* R198 */
+       0x0003,     /* R199 - Limit Switch Control */
+       0x001A,     /* R200 - LDO1 Control */
+       0x0800,     /* R201 - LDO1 Timeouts */
+       0x001C,     /* R202 - LDO1 Low Power */
+       0x0010,     /* R203 - LDO2 Control */
+       0x0800,     /* R204 - LDO2 Timeouts */
+       0x001C,     /* R205 - LDO2 Low Power */
+       0x000A,     /* R206 - LDO3 Control */
+       0x0C00,     /* R207 - LDO3 Timeouts */
+       0x001C,     /* R208 - LDO3 Low Power */
+       0x001A,     /* R209 - LDO4 Control */
+       0x0800,     /* R210 - LDO4 Timeouts */
+       0x001C,     /* R211 - LDO4 Low Power */
+       0x0000,     /* R212 */
+       0x0000,     /* R213 */
+       0x0000,     /* R214 */
+       0x0000,     /* R215 - VCC_FAULT Masks */
+       0x001F,     /* R216 - Main Bandgap Control */
+       0x0000,     /* R217 - OSC Control */
+       0x9000,     /* R218 - RTC Tick Control */
+       0x0000,     /* R219 */
+       0x4000,     /* R220 - RAM BIST 1 */
+       0x0000,     /* R221 */
+       0x0000,     /* R222 */
+       0x0000,     /* R223 */
+       0x0000,     /* R224 */
+       0x0000,     /* R225 - DCDC/LDO status */
+       0x0000,     /* R226 */
+       0x0000,     /* R227 */
+       0x0000,     /* R228 */
+       0x0000,     /* R229 */
+       0xE000,     /* R230 - GPIO Pin Status */
+       0x0000,     /* R231 */
+       0x0000,     /* R232 */
+       0x0000,     /* R233 */
+       0x0000,     /* R234 */
+       0x0000,     /* R235 */
+       0x0000,     /* R236 */
+       0x0000,     /* R237 */
+       0x0000,     /* R238 */
+       0x0000,     /* R239 */
+       0x0000,     /* R240 */
+       0x0000,     /* R241 */
+       0x0000,     /* R242 */
+       0x0000,     /* R243 */
+       0x0000,     /* R244 */
+       0x0000,     /* R245 */
+       0x0000,     /* R246 */
+       0x0000,     /* R247 */
+       0x0000,     /* R248 */
+       0x0000,     /* R249 */
+       0x0000,     /* R250 */
+       0x0000,     /* R251 */
+       0x0000,     /* R252 */
+       0x0000,     /* R253 */
+       0x0000,     /* R254 */
+       0x0000,     /* R255 */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8350_mode3_defaults[] = {
+       0x17FF,     /* R0   - Reset/ID */
+       0x1000,     /* R1   - ID */
+       0x0000,     /* R2 */
+       0x1000,     /* R3   - System Control 1 */
+       0x0004,     /* R4   - System Control 2 */
+       0x0000,     /* R5   - System Hibernate */
+       0x8A00,     /* R6   - Interface Control */
+       0x0000,     /* R7 */
+       0x8000,     /* R8   - Power mgmt (1) */
+       0x0000,     /* R9   - Power mgmt (2) */
+       0x0000,     /* R10  - Power mgmt (3) */
+       0x2000,     /* R11  - Power mgmt (4) */
+       0x0E00,     /* R12  - Power mgmt (5) */
+       0x0000,     /* R13  - Power mgmt (6) */
+       0x0000,     /* R14  - Power mgmt (7) */
+       0x0000,     /* R15 */
+       0x0000,     /* R16  - RTC Seconds/Minutes */
+       0x0100,     /* R17  - RTC Hours/Day */
+       0x0101,     /* R18  - RTC Date/Month */
+       0x1400,     /* R19  - RTC Year */
+       0x0000,     /* R20  - Alarm Seconds/Minutes */
+       0x0000,     /* R21  - Alarm Hours/Day */
+       0x0000,     /* R22  - Alarm Date/Month */
+       0x0320,     /* R23  - RTC Time Control */
+       0x0000,     /* R24  - System Interrupts */
+       0x0000,     /* R25  - Interrupt Status 1 */
+       0x0000,     /* R26  - Interrupt Status 2 */
+       0x0000,     /* R27  - Power Up Interrupt Status */
+       0x0000,     /* R28  - Under Voltage Interrupt status */
+       0x0000,     /* R29  - Over Current Interrupt status */
+       0x0000,     /* R30  - GPIO Interrupt Status */
+       0x0000,     /* R31  - Comparator Interrupt Status */
+       0x3FFF,     /* R32  - System Interrupts Mask */
+       0x0000,     /* R33  - Interrupt Status 1 Mask */
+       0x0000,     /* R34  - Interrupt Status 2 Mask */
+       0x0000,     /* R35  - Power Up Interrupt Status Mask */
+       0x0000,     /* R36  - Under Voltage Interrupt status Mask */
+       0x0000,     /* R37  - Over Current Interrupt status Mask */
+       0x0000,     /* R38  - GPIO Interrupt Status Mask */
+       0x0000,     /* R39  - Comparator Interrupt Status Mask */
+       0x0040,     /* R40  - Clock Control 1 */
+       0x0000,     /* R41  - Clock Control 2 */
+       0x3B00,     /* R42  - FLL Control 1 */
+       0x7086,     /* R43  - FLL Control 2 */
+       0xC226,     /* R44  - FLL Control 3 */
+       0x0000,     /* R45  - FLL Control 4 */
+       0x0000,     /* R46 */
+       0x0000,     /* R47 */
+       0x0000,     /* R48  - DAC Control */
+       0x0000,     /* R49 */
+       0x00C0,     /* R50  - DAC Digital Volume L */
+       0x00C0,     /* R51  - DAC Digital Volume R */
+       0x0000,     /* R52 */
+       0x0040,     /* R53  - DAC LR Rate */
+       0x0000,     /* R54  - DAC Clock Control */
+       0x0000,     /* R55 */
+       0x0000,     /* R56 */
+       0x0000,     /* R57 */
+       0x4000,     /* R58  - DAC Mute */
+       0x0000,     /* R59  - DAC Mute Volume */
+       0x0000,     /* R60  - DAC Side */
+       0x0000,     /* R61 */
+       0x0000,     /* R62 */
+       0x0000,     /* R63 */
+       0x8000,     /* R64  - ADC Control */
+       0x0000,     /* R65 */
+       0x00C0,     /* R66  - ADC Digital Volume L */
+       0x00C0,     /* R67  - ADC Digital Volume R */
+       0x0000,     /* R68  - ADC Divider */
+       0x0000,     /* R69 */
+       0x0040,     /* R70  - ADC LR Rate */
+       0x0000,     /* R71 */
+       0x0303,     /* R72  - Input Control */
+       0x0000,     /* R73  - IN3 Input Control */
+       0x0000,     /* R74  - Mic Bias Control */
+       0x0000,     /* R75 */
+       0x0000,     /* R76  - Output Control */
+       0x0000,     /* R77  - Jack Detect */
+       0x0000,     /* R78  - Anti Pop Control */
+       0x0000,     /* R79 */
+       0x0040,     /* R80  - Left Input Volume */
+       0x0040,     /* R81  - Right Input Volume */
+       0x0000,     /* R82 */
+       0x0000,     /* R83 */
+       0x0000,     /* R84 */
+       0x0000,     /* R85 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87 */
+       0x0800,     /* R88  - Left Mixer Control */
+       0x1000,     /* R89  - Right Mixer Control */
+       0x0000,     /* R90 */
+       0x0000,     /* R91 */
+       0x0000,     /* R92  - OUT3 Mixer Control */
+       0x0000,     /* R93  - OUT4 Mixer Control */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0000,     /* R96  - Output Left Mixer Volume */
+       0x0000,     /* R97  - Output Right Mixer Volume */
+       0x0000,     /* R98  - Input Mixer Volume L */
+       0x0000,     /* R99  - Input Mixer Volume R */
+       0x0000,     /* R100 - Input Mixer Volume */
+       0x0000,     /* R101 */
+       0x0000,     /* R102 */
+       0x0000,     /* R103 */
+       0x00E4,     /* R104 - LOUT1 Volume */
+       0x00E4,     /* R105 - ROUT1 Volume */
+       0x00E4,     /* R106 - LOUT2 Volume */
+       0x02E4,     /* R107 - ROUT2 Volume */
+       0x0000,     /* R108 */
+       0x0000,     /* R109 */
+       0x0000,     /* R110 */
+       0x0000,     /* R111 - BEEP Volume */
+       0x0A00,     /* R112 - AI Formating */
+       0x0000,     /* R113 - ADC DAC COMP */
+       0x0020,     /* R114 - AI ADC Control */
+       0x0020,     /* R115 - AI DAC Control */
+       0x0000,     /* R116 - AIF Test */
+       0x0000,     /* R117 */
+       0x0000,     /* R118 */
+       0x0000,     /* R119 */
+       0x0000,     /* R120 */
+       0x0000,     /* R121 */
+       0x0000,     /* R122 */
+       0x0000,     /* R123 */
+       0x0000,     /* R124 */
+       0x0000,     /* R125 */
+       0x0000,     /* R126 */
+       0x0000,     /* R127 */
+       0x1FFF,     /* R128 - GPIO Debounce */
+       0x0000,     /* R129 - GPIO Pin pull up Control */
+       0x03FC,     /* R130 - GPIO Pull down Control */
+       0x0000,     /* R131 - GPIO Interrupt Mode */
+       0x0000,     /* R132 */
+       0x0000,     /* R133 - GPIO Control */
+       0x0A7B,     /* R134 - GPIO Configuration (i/o) */
+       0x06FE,     /* R135 - GPIO Pin Polarity / Type */
+       0x0000,     /* R136 */
+       0x0000,     /* R137 */
+       0x0000,     /* R138 */
+       0x0000,     /* R139 */
+       0x1312,     /* R140 - GPIO Function Select 1 */
+       0x1030,     /* R141 - GPIO Function Select 2 */
+       0x2231,     /* R142 - GPIO Function Select 3 */
+       0x0003,     /* R143 - GPIO Function Select 4 */
+       0x0000,     /* R144 - Digitiser Control (1) */
+       0x0002,     /* R145 - Digitiser Control (2) */
+       0x0000,     /* R146 */
+       0x0000,     /* R147 */
+       0x0000,     /* R148 */
+       0x0000,     /* R149 */
+       0x0000,     /* R150 */
+       0x0000,     /* R151 */
+       0x7000,     /* R152 - AUX1 Readback */
+       0x7000,     /* R153 - AUX2 Readback */
+       0x7000,     /* R154 - AUX3 Readback */
+       0x7000,     /* R155 - AUX4 Readback */
+       0x0000,     /* R156 - USB Voltage Readback */
+       0x0000,     /* R157 - LINE Voltage Readback */
+       0x0000,     /* R158 - BATT Voltage Readback */
+       0x0000,     /* R159 - Chip Temp Readback */
+       0x0000,     /* R160 */
+       0x0000,     /* R161 */
+       0x0000,     /* R162 */
+       0x0000,     /* R163 - Generic Comparator Control */
+       0x0000,     /* R164 - Generic comparator 1 */
+       0x0000,     /* R165 - Generic comparator 2 */
+       0x0000,     /* R166 - Generic comparator 3 */
+       0x0000,     /* R167 - Generic comparator 4 */
+       0xA00F,     /* R168 - Battery Charger Control 1 */
+       0x0B06,     /* R169 - Battery Charger Control 2 */
+       0x0000,     /* R170 - Battery Charger Control 3 */
+       0x0000,     /* R171 */
+       0x0000,     /* R172 - Current Sink Driver A */
+       0x0000,     /* R173 - CSA Flash control */
+       0x0000,     /* R174 - Current Sink Driver B */
+       0x0000,     /* R175 - CSB Flash control */
+       0x0000,     /* R176 - DCDC/LDO requested */
+       0x002D,     /* R177 - DCDC Active options */
+       0x0000,     /* R178 - DCDC Sleep options */
+       0x0025,     /* R179 - Power-check comparator */
+       0x000E,     /* R180 - DCDC1 Control */
+       0x0400,     /* R181 - DCDC1 Timeouts */
+       0x1006,     /* R182 - DCDC1 Low Power */
+       0x0018,     /* R183 - DCDC2 Control */
+       0x0000,     /* R184 - DCDC2 Timeouts */
+       0x0000,     /* R185 */
+       0x000E,     /* R186 - DCDC3 Control */
+       0x0400,     /* R187 - DCDC3 Timeouts */
+       0x0006,     /* R188 - DCDC3 Low Power */
+       0x0026,     /* R189 - DCDC4 Control */
+       0x0400,     /* R190 - DCDC4 Timeouts */
+       0x0006,     /* R191 - DCDC4 Low Power */
+       0x0008,     /* R192 - DCDC5 Control */
+       0x0000,     /* R193 - DCDC5 Timeouts */
+       0x0000,     /* R194 */
+       0x0026,     /* R195 - DCDC6 Control */
+       0x0400,     /* R196 - DCDC6 Timeouts */
+       0x0006,     /* R197 - DCDC6 Low Power */
+       0x0000,     /* R198 */
+       0x0003,     /* R199 - Limit Switch Control */
+       0x001C,     /* R200 - LDO1 Control */
+       0x0000,     /* R201 - LDO1 Timeouts */
+       0x001C,     /* R202 - LDO1 Low Power */
+       0x001C,     /* R203 - LDO2 Control */
+       0x0400,     /* R204 - LDO2 Timeouts */
+       0x001C,     /* R205 - LDO2 Low Power */
+       0x001C,     /* R206 - LDO3 Control */
+       0x0400,     /* R207 - LDO3 Timeouts */
+       0x001C,     /* R208 - LDO3 Low Power */
+       0x001F,     /* R209 - LDO4 Control */
+       0x0400,     /* R210 - LDO4 Timeouts */
+       0x001C,     /* R211 - LDO4 Low Power */
+       0x0000,     /* R212 */
+       0x0000,     /* R213 */
+       0x0000,     /* R214 */
+       0x0000,     /* R215 - VCC_FAULT Masks */
+       0x001F,     /* R216 - Main Bandgap Control */
+       0x0000,     /* R217 - OSC Control */
+       0x9000,     /* R218 - RTC Tick Control */
+       0x0000,     /* R219 */
+       0x4000,     /* R220 - RAM BIST 1 */
+       0x0000,     /* R221 */
+       0x0000,     /* R222 */
+       0x0000,     /* R223 */
+       0x0000,     /* R224 */
+       0x0000,     /* R225 - DCDC/LDO status */
+       0x0000,     /* R226 */
+       0x0000,     /* R227 */
+       0x0000,     /* R228 */
+       0x0000,     /* R229 */
+       0xE000,     /* R230 - GPIO Pin Status */
+       0x0000,     /* R231 */
+       0x0000,     /* R232 */
+       0x0000,     /* R233 */
+       0x0000,     /* R234 */
+       0x0000,     /* R235 */
+       0x0000,     /* R236 */
+       0x0000,     /* R237 */
+       0x0000,     /* R238 */
+       0x0000,     /* R239 */
+       0x0000,     /* R240 */
+       0x0000,     /* R241 */
+       0x0000,     /* R242 */
+       0x0000,     /* R243 */
+       0x0000,     /* R244 */
+       0x0000,     /* R245 */
+       0x0000,     /* R246 */
+       0x0000,     /* R247 */
+       0x0000,     /* R248 */
+       0x0000,     /* R249 */
+       0x0000,     /* R250 */
+       0x0000,     /* R251 */
+       0x0000,     /* R252 */
+       0x0000,     /* R253 */
+       0x0000,     /* R254 */
+       0x0000,     /* R255 */
+};
+#endif
+
+/* The register defaults for the config mode used must be compiled in but
+ * due to the impact on kernel size it is possible to disable
+ */
+#ifndef WM8350_HAVE_CONFIG_MODE
+#warning No WM8350 config modes supported - select at least one of the
+#warning MFD_WM8350_CONFIG_MODE_n options from the board driver.
+#endif
+
+/*
+ * Access masks.
+ */
+
+const struct wm8350_reg_access wm8350_reg_io_map[] = {
+       /*  read    write volatile */
+       { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0   - Reset/ID */
+       { 0x7CFF, 0x0C00, 0x7FFF }, /* R1   - ID */
+       { 0x0000, 0x0000, 0x0000 }, /* R2 */
+       { 0xBE3B, 0xBE3B, 0x8000 }, /* R3   - System Control 1 */
+       { 0xFCF7, 0xFCF7, 0xF800 }, /* R4   - System Control 2 */
+       { 0x80FF, 0x80FF, 0x8000 }, /* R5   - System Hibernate */
+       { 0xFB0E, 0xFB0E, 0x0000 }, /* R6   - Interface Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R7 */
+       { 0xE537, 0xE537, 0xFFFF }, /* R8   - Power mgmt (1) */
+       { 0x0FF3, 0x0FF3, 0xFFFF }, /* R9   - Power mgmt (2) */
+       { 0x008F, 0x008F, 0xFFFF }, /* R10  - Power mgmt (3) */
+       { 0x6D3C, 0x6D3C, 0xFFFF }, /* R11  - Power mgmt (4) */
+       { 0x1F8F, 0x1F8F, 0xFFFF }, /* R12  - Power mgmt (5) */
+       { 0x8F3F, 0x8F3F, 0xFFFF }, /* R13  - Power mgmt (6) */
+       { 0x0003, 0x0003, 0xFFFF }, /* R14  - Power mgmt (7) */
+       { 0x0000, 0x0000, 0x0000 }, /* R15 */
+       { 0x7F7F, 0x7F7F, 0xFFFF }, /* R16  - RTC Seconds/Minutes */
+       { 0x073F, 0x073F, 0xFFFF }, /* R17  - RTC Hours/Day */
+       { 0x1F3F, 0x1F3F, 0xFFFF }, /* R18  - RTC Date/Month */
+       { 0x3FFF, 0x00FF, 0xFFFF }, /* R19  - RTC Year */
+       { 0x7F7F, 0x7F7F, 0x0000 }, /* R20  - Alarm Seconds/Minutes */
+       { 0x0F3F, 0x0F3F, 0x0000 }, /* R21  - Alarm Hours/Day */
+       { 0x1F3F, 0x1F3F, 0x0000 }, /* R22  - Alarm Date/Month */
+       { 0xEF7F, 0xEA7F, 0xFFFF }, /* R23  - RTC Time Control */
+       { 0x3BFF, 0x0000, 0xFFFF }, /* R24  - System Interrupts */
+       { 0xFEE7, 0x0000, 0xFFFF }, /* R25  - Interrupt Status 1 */
+       { 0x35FF, 0x0000, 0xFFFF }, /* R26  - Interrupt Status 2 */
+       { 0x0F3F, 0x0000, 0xFFFF }, /* R27  - Power Up Interrupt Status */
+       { 0x0F3F, 0x0000, 0xFFFF }, /* R28  - Under Voltage Interrupt status */
+       { 0x8000, 0x0000, 0xFFFF }, /* R29  - Over Current Interrupt status */
+       { 0x1FFF, 0x0000, 0xFFFF }, /* R30  - GPIO Interrupt Status */
+       { 0xEF7F, 0x0000, 0xFFFF }, /* R31  - Comparator Interrupt Status */
+       { 0x3FFF, 0x3FFF, 0x0000 }, /* R32  - System Interrupts Mask */
+       { 0xFEE7, 0xFEE7, 0x0000 }, /* R33  - Interrupt Status 1 Mask */
+       { 0xF5FF, 0xF5FF, 0x0000 }, /* R34  - Interrupt Status 2 Mask */
+       { 0x0F3F, 0x0F3F, 0x0000 }, /* R35  - Power Up Interrupt Status Mask */
+       { 0x0F3F, 0x0F3F, 0x0000 }, /* R36  - Under Voltage Int status Mask */
+       { 0x8000, 0x8000, 0x0000 }, /* R37  - Over Current Int status Mask */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R38  - GPIO Interrupt Status Mask */
+       { 0xEF7F, 0xEF7F, 0x0000 }, /* R39  - Comparator IntStatus Mask */
+       { 0xC9F7, 0xC9F7, 0xFFFF }, /* R40  - Clock Control 1 */
+       { 0x8001, 0x8001, 0x0000 }, /* R41  - Clock Control 2 */
+       { 0xFFF7, 0xFFF7, 0xFFFF }, /* R42  - FLL Control 1 */
+       { 0xFBFF, 0xFBFF, 0x0000 }, /* R43  - FLL Control 2 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R44  - FLL Control 3 */
+       { 0x0033, 0x0033, 0x0000 }, /* R45  - FLL Control 4 */
+       { 0x0000, 0x0000, 0x0000 }, /* R46 */
+       { 0x0000, 0x0000, 0x0000 }, /* R47 */
+       { 0x3033, 0x3033, 0x0000 }, /* R48  - DAC Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R49 */
+       { 0x81FF, 0x81FF, 0xFFFF }, /* R50  - DAC Digital Volume L */
+       { 0x81FF, 0x81FF, 0xFFFF }, /* R51  - DAC Digital Volume R */
+       { 0x0000, 0x0000, 0x0000 }, /* R52 */
+       { 0x0FFF, 0x0FFF, 0xFFFF }, /* R53  - DAC LR Rate */
+       { 0x0017, 0x0017, 0x0000 }, /* R54  - DAC Clock Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R55 */
+       { 0x0000, 0x0000, 0x0000 }, /* R56 */
+       { 0x0000, 0x0000, 0x0000 }, /* R57 */
+       { 0x4000, 0x4000, 0x0000 }, /* R58  - DAC Mute */
+       { 0x7000, 0x7000, 0x0000 }, /* R59  - DAC Mute Volume */
+       { 0x3C00, 0x3C00, 0x0000 }, /* R60  - DAC Side */
+       { 0x0000, 0x0000, 0x0000 }, /* R61 */
+       { 0x0000, 0x0000, 0x0000 }, /* R62 */
+       { 0x0000, 0x0000, 0x0000 }, /* R63 */
+       { 0x8303, 0x8303, 0xFFFF }, /* R64  - ADC Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R65 */
+       { 0x81FF, 0x81FF, 0xFFFF }, /* R66  - ADC Digital Volume L */
+       { 0x81FF, 0x81FF, 0xFFFF }, /* R67  - ADC Digital Volume R */
+       { 0x0FFF, 0x0FFF, 0x0000 }, /* R68  - ADC Divider */
+       { 0x0000, 0x0000, 0x0000 }, /* R69 */
+       { 0x0FFF, 0x0FFF, 0xFFFF }, /* R70  - ADC LR Rate */
+       { 0x0000, 0x0000, 0x0000 }, /* R71 */
+       { 0x0707, 0x0707, 0xFFFF }, /* R72  - Input Control */
+       { 0xC0C0, 0xC0C0, 0xFFFF }, /* R73  - IN3 Input Control */
+       { 0xC09F, 0xC09F, 0xFFFF }, /* R74  - Mic Bias Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R75 */
+       { 0x0F15, 0x0F15, 0xFFFF }, /* R76  - Output Control */
+       { 0xC000, 0xC000, 0xFFFF }, /* R77  - Jack Detect */
+       { 0x03FF, 0x03FF, 0x0000 }, /* R78  - Anti Pop Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R79 */
+       { 0xE1FC, 0xE1FC, 0x8000 }, /* R80  - Left Input Volume */
+       { 0xE1FC, 0xE1FC, 0x8000 }, /* R81  - Right Input Volume */
+       { 0x0000, 0x0000, 0x0000 }, /* R82 */
+       { 0x0000, 0x0000, 0x0000 }, /* R83 */
+       { 0x0000, 0x0000, 0x0000 }, /* R84 */
+       { 0x0000, 0x0000, 0x0000 }, /* R85 */
+       { 0x0000, 0x0000, 0x0000 }, /* R86 */
+       { 0x0000, 0x0000, 0x0000 }, /* R87 */
+       { 0x9807, 0x9807, 0xFFFF }, /* R88  - Left Mixer Control */
+       { 0x980B, 0x980B, 0xFFFF }, /* R89  - Right Mixer Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R90 */
+       { 0x0000, 0x0000, 0x0000 }, /* R91 */
+       { 0x8909, 0x8909, 0xFFFF }, /* R92  - OUT3 Mixer Control */
+       { 0x9E07, 0x9E07, 0xFFFF }, /* R93  - OUT4 Mixer Control */
+       { 0x0000, 0x0000, 0x0000 }, /* R94 */
+       { 0x0000, 0x0000, 0x0000 }, /* R95 */
+       { 0x0EEE, 0x0EEE, 0x0000 }, /* R96  - Output Left Mixer Volume */
+       { 0xE0EE, 0xE0EE, 0x0000 }, /* R97  - Output Right Mixer Volume */
+       { 0x0E0F, 0x0E0F, 0x0000 }, /* R98  - Input Mixer Volume L */
+       { 0xE0E1, 0xE0E1, 0x0000 }, /* R99  - Input Mixer Volume R */
+       { 0x800E, 0x800E, 0x0000 }, /* R100 - Input Mixer Volume */
+       { 0x0000, 0x0000, 0x0000 }, /* R101 */
+       { 0x0000, 0x0000, 0x0000 }, /* R102 */
+       { 0x0000, 0x0000, 0x0000 }, /* R103 */
+       { 0xE1FC, 0xE1FC, 0xFFFF }, /* R104 - LOUT1 Volume */
+       { 0xE1FC, 0xE1FC, 0xFFFF }, /* R105 - ROUT1 Volume */
+       { 0xE1FC, 0xE1FC, 0xFFFF }, /* R106 - LOUT2 Volume */
+       { 0xE7FC, 0xE7FC, 0xFFFF }, /* R107 - ROUT2 Volume */
+       { 0x0000, 0x0000, 0x0000 }, /* R108 */
+       { 0x0000, 0x0000, 0x0000 }, /* R109 */
+       { 0x0000, 0x0000, 0x0000 }, /* R110 */
+       { 0x80E0, 0x80E0, 0xFFFF }, /* R111 - BEEP Volume */
+       { 0xBF00, 0xBF00, 0x0000 }, /* R112 - AI Formating */
+       { 0x00F1, 0x00F1, 0x0000 }, /* R113 - ADC DAC COMP */
+       { 0x00F8, 0x00F8, 0x0000 }, /* R114 - AI ADC Control */
+       { 0x40FB, 0x40FB, 0x0000 }, /* R115 - AI DAC Control */
+       { 0x7C30, 0x7C30, 0x0000 }, /* R116 - AIF Test */
+       { 0x0000, 0x0000, 0x0000 }, /* R117 */
+       { 0x0000, 0x0000, 0x0000 }, /* R118 */
+       { 0x0000, 0x0000, 0x0000 }, /* R119 */
+       { 0x0000, 0x0000, 0x0000 }, /* R120 */
+       { 0x0000, 0x0000, 0x0000 }, /* R121 */
+       { 0x0000, 0x0000, 0x0000 }, /* R122 */
+       { 0x0000, 0x0000, 0x0000 }, /* R123 */
+       { 0x0000, 0x0000, 0x0000 }, /* R124 */
+       { 0x0000, 0x0000, 0x0000 }, /* R125 */
+       { 0x0000, 0x0000, 0x0000 }, /* R126 */
+       { 0x0000, 0x0000, 0x0000 }, /* R127 */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R128 - GPIO Debounce */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R129 - GPIO Pin pull up Control */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R130 - GPIO Pull down Control */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R131 - GPIO Interrupt Mode */
+       { 0x0000, 0x0000, 0x0000 }, /* R132 */
+       { 0x00C0, 0x00C0, 0x0000 }, /* R133 - GPIO Control */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R134 - GPIO Configuration (i/o) */
+       { 0x1FFF, 0x1FFF, 0x0000 }, /* R135 - GPIO Pin Polarity / Type */
+       { 0x0000, 0x0000, 0x0000 }, /* R136 */
+       { 0x0000, 0x0000, 0x0000 }, /* R137 */
+       { 0x0000, 0x0000, 0x0000 }, /* R138 */
+       { 0x0000, 0x0000, 0x0000 }, /* R139 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R140 - GPIO Function Select 1 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R141 - GPIO Function Select 2 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R142 - GPIO Function Select 3 */
+       { 0x000F, 0x000F, 0x0000 }, /* R143 - GPIO Function Select 4 */
+       { 0xF0FF, 0xF0FF, 0xA000 }, /* R144 - Digitiser Control (1) */
+       { 0x3707, 0x3707, 0x0000 }, /* R145 - Digitiser Control (2) */
+       { 0x0000, 0x0000, 0x0000 }, /* R146 */
+       { 0x0000, 0x0000, 0x0000 }, /* R147 */
+       { 0x0000, 0x0000, 0x0000 }, /* R148 */
+       { 0x0000, 0x0000, 0x0000 }, /* R149 */
+       { 0x0000, 0x0000, 0x0000 }, /* R150 */
+       { 0x0000, 0x0000, 0x0000 }, /* R151 */
+       { 0x7FFF, 0x7000, 0xFFFF }, /* R152 - AUX1 Readback */
+       { 0x7FFF, 0x7000, 0xFFFF }, /* R153 - AUX2 Readback */
+       { 0x7FFF, 0x7000, 0xFFFF }, /* R154 - AUX3 Readback */
+       { 0x7FFF, 0x7000, 0xFFFF }, /* R155 - AUX4 Readback */
+       { 0x0FFF, 0x0000, 0xFFFF }, /* R156 - USB Voltage Readback */
+       { 0x0FFF, 0x0000, 0xFFFF }, /* R157 - LINE Voltage Readback */
+       { 0x0FFF, 0x0000, 0xFFFF }, /* R158 - BATT Voltage Readback */
+       { 0x0FFF, 0x0000, 0xFFFF }, /* R159 - Chip Temp Readback */
+       { 0x0000, 0x0000, 0x0000 }, /* R160 */
+       { 0x0000, 0x0000, 0x0000 }, /* R161 */
+       { 0x0000, 0x0000, 0x0000 }, /* R162 */
+       { 0x000F, 0x000F, 0x0000 }, /* R163 - Generic Comparator Control */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R164 - Generic comparator 1 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R165 - Generic comparator 2 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R166 - Generic comparator 3 */
+       { 0xFFFF, 0xFFFF, 0x0000 }, /* R167 - Generic comparator 4 */
+       { 0xBFFF, 0xBFFF, 0x8000 }, /* R168 - Battery Charger Control 1 */
+       { 0xFFFF, 0x4FFF, 0xB000 }, /* R169 - Battery Charger Control 2 */
+       { 0x007F, 0x007F, 0x0000 }, /* R170 - Battery Charger Control 3 */
+       { 0x0000, 0x0000, 0x0000 }, /* R171 */
+       { 0x903F, 0x903F, 0xFFFF }, /* R172 - Current Sink Driver A */
+       { 0xE333, 0xE333, 0xFFFF }, /* R173 - CSA Flash control */
+       { 0x903F, 0x903F, 0xFFFF }, /* R174 - Current Sink Driver B */
+       { 0xE333, 0xE333, 0xFFFF }, /* R175 - CSB Flash control */
+       { 0x8F3F, 0x8F3F, 0xFFFF }, /* R176 - DCDC/LDO requested */
+       { 0x332D, 0x332D, 0x0000 }, /* R177 - DCDC Active options */
+       { 0x002D, 0x002D, 0x0000 }, /* R178 - DCDC Sleep options */
+       { 0x5177, 0x5177, 0x8000 }, /* R179 - Power-check comparator */
+       { 0x047F, 0x047F, 0x0000 }, /* R180 - DCDC1 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R181 - DCDC1 Timeouts */
+       { 0x737F, 0x737F, 0x0000 }, /* R182 - DCDC1 Low Power */
+       { 0x535B, 0x535B, 0x0000 }, /* R183 - DCDC2 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R184 - DCDC2 Timeouts */
+       { 0x0000, 0x0000, 0x0000 }, /* R185 */
+       { 0x047F, 0x047F, 0x0000 }, /* R186 - DCDC3 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R187 - DCDC3 Timeouts */
+       { 0x737F, 0x737F, 0x0000 }, /* R188 - DCDC3 Low Power */
+       { 0x047F, 0x047F, 0x0000 }, /* R189 - DCDC4 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R190 - DCDC4 Timeouts */
+       { 0x737F, 0x737F, 0x0000 }, /* R191 - DCDC4 Low Power */
+       { 0x535B, 0x535B, 0x0000 }, /* R192 - DCDC5 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R193 - DCDC5 Timeouts */
+       { 0x0000, 0x0000, 0x0000 }, /* R194 */
+       { 0x047F, 0x047F, 0x0000 }, /* R195 - DCDC6 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R196 - DCDC6 Timeouts */
+       { 0x737F, 0x737F, 0x0000 }, /* R197 - DCDC6 Low Power */
+       { 0x0000, 0x0000, 0x0000 }, /* R198 */
+       { 0xFFD3, 0xFFD3, 0x0000 }, /* R199 - Limit Switch Control */
+       { 0x441F, 0x441F, 0x0000 }, /* R200 - LDO1 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R201 - LDO1 Timeouts */
+       { 0x331F, 0x331F, 0x0000 }, /* R202 - LDO1 Low Power */
+       { 0x441F, 0x441F, 0x0000 }, /* R203 - LDO2 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R204 - LDO2 Timeouts */
+       { 0x331F, 0x331F, 0x0000 }, /* R205 - LDO2 Low Power */
+       { 0x441F, 0x441F, 0x0000 }, /* R206 - LDO3 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R207 - LDO3 Timeouts */
+       { 0x331F, 0x331F, 0x0000 }, /* R208 - LDO3 Low Power */
+       { 0x441F, 0x441F, 0x0000 }, /* R209 - LDO4 Control */
+       { 0xFFC0, 0xFFC0, 0x0000 }, /* R210 - LDO4 Timeouts */
+       { 0x331F, 0x331F, 0x0000 }, /* R211 - LDO4 Low Power */
+       { 0x0000, 0x0000, 0x0000 }, /* R212 */
+       { 0x0000, 0x0000, 0x0000 }, /* R213 */
+       { 0x0000, 0x0000, 0x0000 }, /* R214 */
+       { 0x8F3F, 0x8F3F, 0x0000 }, /* R215 - VCC_FAULT Masks */
+       { 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */
+       { 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */
+       { 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */
+       { 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */
+       { 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */
+       { 0x0000, 0x0000, 0x0000 }, /* R221 */
+       { 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */
+       { 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */
+       { 0x0000, 0x0000, 0x0000 }, /* R224 */
+       { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
+       { 0x0000, 0x0000, 0x0000 }, /* R226 */
+       { 0x0000, 0x0000, 0xFFFF }, /* R227 */
+       { 0x0000, 0x0000, 0x0000 }, /* R228 */
+       { 0x0000, 0x0000, 0x0000 }, /* R229 */
+       { 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */
+       { 0xFFFF, 0x1FFF, 0xFFFF }, /* R231 */
+       { 0xFFFF, 0x1FFF, 0xFFFF }, /* R232 */
+       { 0xFFFF, 0x1FFF, 0xFFFF }, /* R233 */
+       { 0x0000, 0x0000, 0x0000 }, /* R234 */
+       { 0x0000, 0x0000, 0x0000 }, /* R235 */
+       { 0x0000, 0x0000, 0x0000 }, /* R236 */
+       { 0x0000, 0x0000, 0x0000 }, /* R237 */
+       { 0x0000, 0x0000, 0x0000 }, /* R238 */
+       { 0x0000, 0x0000, 0x0000 }, /* R239 */
+       { 0x0000, 0x0000, 0x0000 }, /* R240 */
+       { 0x0000, 0x0000, 0x0000 }, /* R241 */
+       { 0x0000, 0x0000, 0x0000 }, /* R242 */
+       { 0x0000, 0x0000, 0x0000 }, /* R243 */
+       { 0x0000, 0x0000, 0x0000 }, /* R244 */
+       { 0x0000, 0x0000, 0x0000 }, /* R245 */
+       { 0x0000, 0x0000, 0x0000 }, /* R246 */
+       { 0x0000, 0x0000, 0x0000 }, /* R247 */
+       { 0xFFFF, 0x0010, 0xFFFF }, /* R248 */
+       { 0x0000, 0x0000, 0x0000 }, /* R249 */
+       { 0xFFFF, 0x0010, 0xFFFF }, /* R250 */
+       { 0xFFFF, 0x0010, 0xFFFF }, /* R251 */
+       { 0x0000, 0x0000, 0x0000 }, /* R252 */
+       { 0xFFFF, 0x0010, 0xFFFF }, /* R253 */
+       { 0x0000, 0x0000, 0x0000 }, /* R254 */
+       { 0x0000, 0x0000, 0x0000 }, /* R255 */
+};
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
new file mode 100644 (file)
index 0000000..6a0cedb
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * Core driver for WM8400.
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/mfd/wm8400-private.h>
+#include <linux/mfd/wm8400-audio.h>
+
+static struct {
+       u16  readable;    /* Mask of readable bits */
+       u16  writable;    /* Mask of writable bits */
+       u16  vol;         /* Mask of volatile bits */
+       int  is_codec;    /* Register controlled by codec reset */
+       u16  default_val; /* Value on reset */
+} reg_data[] = {
+       { 0xFFFF, 0xFFFF, 0x0000, 0, 0x6172 }, /* R0 */
+       { 0x7000, 0x0000, 0x8000, 0, 0x0000 }, /* R1 */
+       { 0xFF17, 0xFF17, 0x0000, 0, 0x0000 }, /* R2 */
+       { 0xEBF3, 0xEBF3, 0x0000, 1, 0x6000 }, /* R3 */
+       { 0x3CF3, 0x3CF3, 0x0000, 1, 0x0000 }, /* R4  */
+       { 0xF1F8, 0xF1F8, 0x0000, 1, 0x4050 }, /* R5  */
+       { 0xFC1F, 0xFC1F, 0x0000, 1, 0x4000 }, /* R6  */
+       { 0xDFDE, 0xDFDE, 0x0000, 1, 0x01C8 }, /* R7  */
+       { 0xFCFC, 0xFCFC, 0x0000, 1, 0x0000 }, /* R8  */
+       { 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R9  */
+       { 0xEFFF, 0xEFFF, 0x0000, 1, 0x0040 }, /* R10 */
+       { 0x27F7, 0x27F7, 0x0000, 1, 0x0004 }, /* R11 */
+       { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R12 */
+       { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R13 */
+       { 0x1FEF, 0x1FEF, 0x0000, 1, 0x0000 }, /* R14 */
+       { 0x0163, 0x0163, 0x0000, 1, 0x0100 }, /* R15 */
+       { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R16 */
+       { 0x01FF, 0x01FF, 0x0000, 1, 0x00C0 }, /* R17 */
+       { 0x1FFF, 0x0FFF, 0x0000, 1, 0x0000 }, /* R18 */
+       { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1000 }, /* R19 */
+       { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R20 */
+       { 0xFFFF, 0xFFFF, 0x0000, 1, 0x1010 }, /* R21 */
+       { 0x0FDD, 0x0FDD, 0x0000, 1, 0x8000 }, /* R22 */
+       { 0x1FFF, 0x1FFF, 0x0000, 1, 0x0800 }, /* R23 */
+       { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R24 */
+       { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R25 */
+       { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R26 */
+       { 0x0000, 0x01DF, 0x0000, 1, 0x008B }, /* R27 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R28 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R29 */
+       { 0x0000, 0x0077, 0x0000, 1, 0x0066 }, /* R30 */
+       { 0x0000, 0x0033, 0x0000, 1, 0x0022 }, /* R31 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R32 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0079 }, /* R33 */
+       { 0x0000, 0x0003, 0x0000, 1, 0x0003 }, /* R34 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0003 }, /* R35 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R36 */
+       { 0x0000, 0x003F, 0x0000, 1, 0x0100 }, /* R37 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R38 */
+       { 0x0000, 0x000F, 0x0000, 0, 0x0000 }, /* R39 */
+       { 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R40 */
+       { 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R41 */
+       { 0x0000, 0x01B7, 0x0000, 1, 0x0000 }, /* R42 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R43 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R44 */
+       { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R45 */
+       { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R46 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R47 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R48 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R49 */
+       { 0x0000, 0x01FF, 0x0000, 1, 0x0000 }, /* R50 */
+       { 0x0000, 0x01B3, 0x0000, 1, 0x0180 }, /* R51 */
+       { 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R52 */
+       { 0x0000, 0x0077, 0x0000, 1, 0x0000 }, /* R53 */
+       { 0x0000, 0x00FF, 0x0000, 1, 0x0000 }, /* R54 */
+       { 0x0000, 0x0001, 0x0000, 1, 0x0000 }, /* R55 */
+       { 0x0000, 0x003F, 0x0000, 1, 0x0000 }, /* R56 */
+       { 0x0000, 0x004F, 0x0000, 1, 0x0000 }, /* R57 */
+       { 0x0000, 0x00FD, 0x0000, 1, 0x0000 }, /* R58 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R59 */
+       { 0x1FFF, 0x1FFF, 0x0000, 1, 0x0000 }, /* R60 */
+       { 0xFFFF, 0xFFFF, 0x0000, 1, 0x0000 }, /* R61 */
+       { 0x03FF, 0x03FF, 0x0000, 1, 0x0000 }, /* R62 */
+       { 0x007F, 0x007F, 0x0000, 1, 0x0000 }, /* R63 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R64 */
+       { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R65 */
+       { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R66 */
+       { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R67 */
+       { 0xDFFF, 0xDFFF, 0x0000, 0, 0x0000 }, /* R68 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R69 */
+       { 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R70 */
+       { 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R71 */
+       { 0xFFFF, 0xFFFF, 0x0000, 0, 0x4400 }, /* R72 */
+       { 0x23FF, 0x23FF, 0x0000, 0, 0x0000 }, /* R73 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R74 */
+       { 0x000E, 0x000E, 0x0000, 0, 0x0008 }, /* R75 */
+       { 0xE00F, 0xE00F, 0x0000, 0, 0x0000 }, /* R76 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R77 */
+       { 0x03C0, 0x03C0, 0x0000, 0, 0x02C0 }, /* R78 */
+       { 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R79 */
+       { 0xFFFF, 0xFFFF, 0x0000, 0, 0x0000 }, /* R80 */
+       { 0xFFFF, 0x0000, 0xffff, 0, 0x0000 }, /* R81 */
+       { 0x2BFF, 0x0000, 0xffff, 0, 0x0000 }, /* R82 */
+       { 0x0000, 0x0000, 0x0000, 0, 0x0000 }, /* R83 */
+       { 0x80FF, 0x80FF, 0x0000, 0, 0x00ff }, /* R84 */
+};
+
+static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest)
+{
+       int i, ret = 0;
+
+       BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+       /* If there are any volatile reads then read back the entire block */
+       for (i = reg; i < reg + num_regs; i++)
+               if (reg_data[i].vol) {
+                       ret = wm8400->read_dev(wm8400->io_data, reg,
+                                              num_regs, dest);
+                       if (ret != 0)
+                               return ret;
+                       for (i = 0; i < num_regs; i++)
+                               dest[i] = be16_to_cpu(dest[i]);
+
+                       return 0;
+               }
+
+       /* Otherwise use the cache */
+       memcpy(dest, &wm8400->reg_cache[reg], num_regs * sizeof(u16));
+
+       return 0;
+}
+
+static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs,
+                       u16 *src)
+{
+       int ret, i;
+
+       BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache));
+
+       for (i = 0; i < num_regs; i++) {
+               BUG_ON(!reg_data[reg + i].writable);
+               wm8400->reg_cache[reg + i] = src[i];
+               src[i] = cpu_to_be16(src[i]);
+       }
+
+       /* Do the actual I/O */
+       ret = wm8400->write_dev(wm8400->io_data, reg, num_regs, src);
+       if (ret != 0)
+               return -EIO;
+
+       return 0;
+}
+
+/**
+ * wm8400_reg_read - Single register read
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg:    Register to read
+ *
+ * @return  Read value
+ */
+u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg)
+{
+       u16 val;
+
+       mutex_lock(&wm8400->io_lock);
+
+       wm8400_read(wm8400, reg, 1, &val);
+
+       mutex_unlock(&wm8400->io_lock);
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(wm8400_reg_read);
+
+int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data)
+{
+       int ret;
+
+       mutex_lock(&wm8400->io_lock);
+
+       ret = wm8400_read(wm8400, reg, count, data);
+
+       mutex_unlock(&wm8400->io_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_block_read);
+
+/**
+ * wm8400_set_bits - Bitmask write
+ *
+ * @wm8400: Pointer to wm8400 control structure
+ * @reg:    Register to access
+ * @mask:   Mask of bits to change
+ * @val:    Value to set for masked bits
+ */
+int wm8400_set_bits(struct wm8400 *wm8400, u8 reg, u16 mask, u16 val)
+{
+       u16 tmp;
+       int ret;
+
+       mutex_lock(&wm8400->io_lock);
+
+       ret = wm8400_read(wm8400, reg, 1, &tmp);
+       tmp = (tmp & ~mask) | val;
+       if (ret == 0)
+               ret = wm8400_write(wm8400, reg, 1, &tmp);
+
+       mutex_unlock(&wm8400->io_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8400_set_bits);
+
+/**
+ * wm8400_reset_codec_reg_cache - Reset cached codec registers to
+ * their default values.
+ */
+void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
+{
+       int i;
+
+       mutex_lock(&wm8400->io_lock);
+
+       /* Reset all codec registers to their initial value */
+       for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+               if (reg_data[i].is_codec)
+                       wm8400->reg_cache[i] = reg_data[i].default_val;
+
+       mutex_unlock(&wm8400->io_lock);
+}
+EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
+
+/*
+ * wm8400_init - Generic initialisation
+ *
+ * The WM8400 can be configured as either an I2C or SPI device.  Probe
+ * functions for each bus set up the accessors then call into this to
+ * set up the device itself.
+ */
+static int wm8400_init(struct wm8400 *wm8400,
+                      struct wm8400_platform_data *pdata)
+{
+       u16 reg;
+       int ret, i;
+
+       mutex_init(&wm8400->io_lock);
+
+       wm8400->dev->driver_data = wm8400;
+
+       /* Check that this is actually a WM8400 */
+       ret = wm8400->read_dev(wm8400->io_data, WM8400_RESET_ID, 1, &reg);
+       if (ret != 0) {
+               dev_err(wm8400->dev, "Chip ID register read failed\n");
+               return -EIO;
+       }
+       if (be16_to_cpu(reg) != reg_data[WM8400_RESET_ID].default_val) {
+               dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
+                       be16_to_cpu(reg));
+               return -ENODEV;
+       }
+
+       /* We don't know what state the hardware is in and since this
+        * is a PMIC we can't reset it safely so initialise the register
+        * cache from the hardware.
+        */
+       ret = wm8400->read_dev(wm8400->io_data, 0,
+                              ARRAY_SIZE(wm8400->reg_cache),
+                              wm8400->reg_cache);
+       if (ret != 0) {
+               dev_err(wm8400->dev, "Register cache read failed\n");
+               return -EIO;
+       }
+       for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+               wm8400->reg_cache[i] = be16_to_cpu(wm8400->reg_cache[i]);
+
+       /* If the codec is in reset use hard coded values */
+       if (!(wm8400->reg_cache[WM8400_POWER_MANAGEMENT_1] & WM8400_CODEC_ENA))
+               for (i = 0; i < ARRAY_SIZE(wm8400->reg_cache); i++)
+                       if (reg_data[i].is_codec)
+                               wm8400->reg_cache[i] = reg_data[i].default_val;
+
+       ret = wm8400_read(wm8400, WM8400_ID, 1, &reg);
+       if (ret != 0) {
+               dev_err(wm8400->dev, "ID register read failed: %d\n", ret);
+               return ret;
+       }
+       reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
+       dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
+
+       if (pdata && pdata->platform_init) {
+               ret = pdata->platform_init(wm8400->dev);
+               if (ret != 0)
+                       dev_err(wm8400->dev, "Platform init failed: %d\n",
+                               ret);
+       } else
+               dev_warn(wm8400->dev, "No platform initialisation supplied\n");
+
+       return ret;
+}
+
+static void wm8400_release(struct wm8400 *wm8400)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++)
+               if (wm8400->regulators[i].name)
+                       platform_device_unregister(&wm8400->regulators[i]);
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8400_i2c_read(void *io_data, char reg, int count, u16 *dest)
+{
+       struct i2c_client *i2c = io_data;
+       struct i2c_msg xfer[2];
+       int ret;
+
+       /* Write register */
+       xfer[0].addr = i2c->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = &reg;
+
+       /* Read data */
+       xfer[1].addr = i2c->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = count * sizeof(u16);
+       xfer[1].buf = (u8 *)dest;
+
+       ret = i2c_transfer(i2c->adapter, xfer, 2);
+       if (ret == 2)
+               ret = 0;
+       else if (ret >= 0)
+               ret = -EIO;
+
+       return ret;
+}
+
+static int wm8400_i2c_write(void *io_data, char reg, int count, const u16 *src)
+{
+       struct i2c_client *i2c = io_data;
+       u8 *msg;
+       int ret;
+
+       /* We add 1 byte for device register - ideally I2C would gather. */
+       msg = kmalloc((count * sizeof(u16)) + 1, GFP_KERNEL);
+       if (msg == NULL)
+               return -ENOMEM;
+
+       msg[0] = reg;
+       memcpy(&msg[1], src, count * sizeof(u16));
+
+       ret = i2c_master_send(i2c, msg, (count * sizeof(u16)) + 1);
+
+       if (ret == (count * 2) + 1)
+               ret = 0;
+       else if (ret >= 0)
+               ret = -EIO;
+
+       kfree(msg);
+
+       return ret;
+}
+
+static int wm8400_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct wm8400 *wm8400;
+       int ret;
+
+       wm8400 = kzalloc(sizeof(struct wm8400), GFP_KERNEL);
+       if (wm8400 == NULL) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       wm8400->io_data = i2c;
+       wm8400->read_dev = wm8400_i2c_read;
+       wm8400->write_dev = wm8400_i2c_write;
+       wm8400->dev = &i2c->dev;
+       i2c_set_clientdata(i2c, wm8400);
+
+       ret = wm8400_init(wm8400, i2c->dev.platform_data);
+       if (ret != 0)
+               goto struct_err;
+
+       return 0;
+
+struct_err:
+       i2c_set_clientdata(i2c, NULL);
+       kfree(wm8400);
+err:
+       return ret;
+}
+
+static int wm8400_i2c_remove(struct i2c_client *i2c)
+{
+       struct wm8400 *wm8400 = i2c_get_clientdata(i2c);
+
+       wm8400_release(wm8400);
+       i2c_set_clientdata(i2c, NULL);
+       kfree(wm8400);
+
+       return 0;
+}
+
+static const struct i2c_device_id wm8400_i2c_id[] = {
+       { "wm8400", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8400_i2c_id);
+
+static struct i2c_driver wm8400_i2c_driver = {
+       .driver = {
+               .name = "WM8400",
+               .owner = THIS_MODULE,
+       },
+       .probe    = wm8400_i2c_probe,
+       .remove   = wm8400_i2c_remove,
+       .id_table = wm8400_i2c_id,
+};
+#endif
+
+static int __init wm8400_module_init(void)
+{
+       int ret = -ENODEV;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8400_i2c_driver);
+       if (ret != 0)
+               pr_err("Failed to register I2C driver: %d\n", ret);
+#endif
+
+       return ret;
+}
+module_init(wm8400_module_init);
+
+static void __exit wm8400_module_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8400_i2c_driver);
+#endif
+}
+module_exit(wm8400_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index a726f3b01a6b36debf060b647c4384a4aab8f1b3..efd3aa08b88bb85c3ca8855084a8bd1314c2c30f 100644 (file)
@@ -15,7 +15,7 @@ if MISC_DEVICES
 
 config ATMEL_PWM
        tristate "Atmel AT32/AT91 PWM support"
-       depends on AVR32 || ARCH_AT91
+       depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
        help
          This option enables device driver support for the PWM channels
          on certain Atmel prcoessors.  Pulse Width Modulation is used for
@@ -409,6 +409,7 @@ config EEEPC_LAPTOP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on HWMON
        depends on EXPERIMENTAL
+       depends on RFKILL
        ---help---
          This driver supports the Fn-Fx keys on Eee PC laptops.
          It also adds the ability to switch camera/wlan on/off.
index 6d407c2a4f91d80e54d5885e741ce436fb21aa31..5dabfb69ee537f25a1bc93814c0e894ebf3ba494 100644 (file)
@@ -309,7 +309,7 @@ static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
        return -EINVAL;
 }
 
-void hp_wmi_notify(u32 value, void *context)
+static void hp_wmi_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
        static struct key_entry *key;
index daf585689ce33a0e77a07bd3991e2165f8c04acb..abdebe347383903d93f43e59365a76ef2b6db48f 100644 (file)
@@ -399,9 +399,9 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
                goto err_irq;
        }
 
-       if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
-                                        MKDEV(phantom_major, minor),
-                                        NULL, "phantom%u", minor)))
+       if (IS_ERR(device_create(phantom_class, &pdev->dev,
+                                MKDEV(phantom_major, minor), NULL,
+                                "phantom%u", minor)))
                dev_err(&pdev->dev, "can't create device\n");
 
        pci_set_drvdata(pdev, pht);
index 40df7cb3f0a571fc6ed4645a13e1c9dae83c036b..f93f03a9e6e9e3c0cb1d034b7f746386df76bfe2 100644 (file)
@@ -30,9 +30,9 @@
 /*
  * Size used to map GRU GSeg
  */
-#if defined CONFIG_IA64
+#if defined(CONFIG_IA64)
 #define GRU_GSEG_PAGESIZE      (256 * 1024UL)
-#elif defined CONFIG_X86_64
+#elif defined(CONFIG_X86_64)
 #define GRU_GSEG_PAGESIZE      (256 * 1024UL)          /* ZZZ 2MB ??? */
 #else
 #error "Unsupported architecture"
index 0dc36225c7c6c2f76b909cec45342d4ede4b9a80..48762e7b98be65a5b3758489657a5d1675cf5de0 100644 (file)
@@ -26,7 +26,7 @@
  * Architecture dependent functions
  */
 
-#if defined CONFIG_IA64
+#if defined(CONFIG_IA64)
 #include <linux/compiler.h>
 #include <asm/intrinsics.h>
 #define __flush_cache(p)               ia64_fc(p)
@@ -36,7 +36,7 @@
                        barrier();                                      \
                        *((volatile int *)(p)) = v; /* force st.rel */  \
                } while (0)
-#elif defined CONFIG_X86_64
+#elif defined(CONFIG_X86_64)
 #define __flush_cache(p)               clflush(p)
 #define gru_ordered_store_int(p,v)                                     \
                do {                                                    \
@@ -299,6 +299,7 @@ static inline void gru_flush_cache(void *p)
 static inline void gru_start_instruction(struct gru_instruction *ins, int op32)
 {
        gru_ordered_store_int(ins, op32);
+       gru_flush_cache(ins);
 }
 
 
@@ -604,8 +605,9 @@ static inline int gru_get_cb_substatus(void *cb)
 static inline int gru_check_status(void *cb)
 {
        struct gru_control_block_status *cbs = (void *)cb;
-       int ret = cbs->istatus;
+       int ret;
 
+       ret = cbs->istatus;
        if (ret == CBS_CALL_OS)
                ret = gru_check_status_proc(cb);
        return ret;
@@ -617,7 +619,7 @@ static inline int gru_check_status(void *cb)
 static inline int gru_wait(void *cb)
 {
        struct gru_control_block_status *cbs = (void *)cb;
-       int ret = cbs->istatus;;
+       int ret = cbs->istatus;
 
        if (ret != CBS_IDLE)
                ret = gru_wait_proc(cb);
index 3d33015bbf31a18d2a6aca7c0a662788abc34b97..8c389d606c304c8b9b34022c8d2e71ceba4bb6e8 100644 (file)
@@ -214,12 +214,14 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
 }
 
 /*
- *
  * atomic_pte_lookup
  *
  * Convert a user virtual address to a physical address
  * Only supports Intel large pages (2MB only) on x86_64.
  *     ZZZ - hugepage support is incomplete
+ *
+ * NOTE: mmap_sem is already held on entry to this function. This
+ * guarantees existence of the page tables.
  */
 static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
        int write, unsigned long *paddr, int *pageshift)
@@ -229,9 +231,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
        pud_t *pudp;
        pte_t pte;
 
-       WARN_ON(irqs_disabled());               /* ZZZ debug */
-
-       local_irq_disable();
        pgdp = pgd_offset(vma->vm_mm, vaddr);
        if (unlikely(pgd_none(*pgdp)))
                goto err;
@@ -250,8 +249,6 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr,
 #endif
                pte = *pte_offset_kernel(pmdp, vaddr);
 
-       local_irq_enable();
-
        if (unlikely(!pte_present(pte) ||
                     (write && (!pte_write(pte) || !pte_dirty(pte)))))
                return 1;
@@ -324,6 +321,7 @@ static int gru_try_dropin(struct gru_thread_state *gts,
         * Atomic lookup is faster & usually works even if called in non-atomic
         * context.
         */
+       rmb();  /* Must/check ms_range_active before loading PTEs */
        ret = atomic_pte_lookup(vma, vaddr, write, &paddr, &pageshift);
        if (ret) {
                if (!cb)
@@ -543,6 +541,7 @@ int gru_get_exception_detail(unsigned long arg)
                ucbnum = get_cb_number((void *)excdet.cb);
                cbrnum = thread_cbr_number(gts, ucbnum);
                cbe = get_cbe_by_index(gts->ts_gru, cbrnum);
+               prefetchw(cbe);         /* Harmless on hardware, required for emulator */
                excdet.opc = cbe->opccpy;
                excdet.exopc = cbe->exopccpy;
                excdet.ecause = cbe->ecause;
index d61cee796efdc234aba44fdcb5969283f24780d7..5c027b6b4e5a7438815b290e09a99a0290bf55f5 100644 (file)
@@ -113,7 +113,7 @@ static int gru_file_mmap(struct file *file, struct vm_area_struct *vma)
                return -EPERM;
 
        if (vma->vm_start & (GRU_GSEG_PAGESIZE - 1) ||
-                       vma->vm_end & (GRU_GSEG_PAGESIZE - 1))
+                               vma->vm_end & (GRU_GSEG_PAGESIZE - 1))
                return -EINVAL;
 
        vma->vm_flags |=
@@ -398,6 +398,12 @@ static int __init gru_init(void)
        irq = get_base_irq();
        for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) {
                ret = request_irq(irq + chip, gru_intr, 0, id, NULL);
+               /* TODO: fix irq handling on x86. For now ignore failures because
+                * interrupts are not required & not yet fully supported */
+               if (ret) {
+                       printk("!!!WARNING: GRU ignoring request failure!!!\n");
+                       ret = 0;
+               }
                if (ret) {
                        printk(KERN_ERR "%s: request_irq failed\n",
                               GRU_DRIVER_ID_STR);
index d16031d626730b2dd36e0fac1d27264f4c8c9857..b63018d60fe1a56b22e0cc2c02cc43b650dba7f6 100644 (file)
 #define GSEGPOFF(h)            ((h) & (GRU_SIZE - 1))
 
 /* Convert an arbitrary handle address to the beginning of the GRU segment */
-#ifndef __PLUGIN__
 #define GRUBASE(h)             ((void *)((unsigned long)(h) & ~(GRU_SIZE - 1)))
-#else
-extern void *gmu_grubase(void *h);
-#define GRUBASE(h)             gmu_grubase(h)
-#endif
 
 /* General addressing macros. */
 static inline void *get_gseg_base_address(void *base, int ctxnum)
index dfd49af0fe18220d41a4afc438fc0b74c3439a6f..880c55dfb66266dfd53cae3dea2492b986ff5744 100644 (file)
@@ -122,6 +122,7 @@ int gru_get_cb_exception_detail(void *cb,
        struct gru_control_block_extended *cbe;
 
        cbe = get_cbe(GRUBASE(cb), get_cb_number(cb));
+       prefetchw(cbe);         /* Harmless on hardware, required for emulator */
        excdet->opc = cbe->opccpy;
        excdet->exopc = cbe->exopccpy;
        excdet->ecause = cbe->ecause;
@@ -466,7 +467,7 @@ int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes)
        STAT(mesq_send);
        BUG_ON(bytes < sizeof(int) || bytes > 2 * GRU_CACHE_LINE_BYTES);
 
-       clines = (bytes + GRU_CACHE_LINE_BYTES - 1) / GRU_CACHE_LINE_BYTES;
+       clines = DIV_ROUND_UP(bytes, GRU_CACHE_LINE_BYTES);
        if (gru_get_cpu_resources(bytes, &cb, &dsr))
                return MQE_BUG_NO_RESOURCES;
        memcpy(dsr, mesg, bytes);
index 0eeb8dddd2f51396a85d726a8286f09b68348580..e11e1ac509002c862553744d606e4582b2bf3238 100644 (file)
@@ -432,29 +432,35 @@ static inline long gru_copy_handle(void *d, void *s)
        return GRU_HANDLE_BYTES;
 }
 
-/* rewrite in assembly & use lots of prefetch */
-static void gru_load_context_data(void *save, void *grubase, int ctxnum,
-                                 unsigned long cbrmap, unsigned long dsrmap)
+static void gru_prefetch_context(void *gseg, void *cb, void *cbe, unsigned long cbrmap,
+                               unsigned long length)
 {
-       void *gseg, *cb, *cbe;
-       unsigned long length;
        int i, scr;
 
-       gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
-       length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
        prefetch_data(gseg + GRU_DS_BASE, length / GRU_CACHE_LINE_BYTES,
                      GRU_CACHE_LINE_BYTES);
 
-       cb = gseg + GRU_CB_BASE;
-       cbe = grubase + GRU_CBE_BASE;
        for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
                prefetch_data(cb, 1, GRU_CACHE_LINE_BYTES);
                prefetch_data(cbe + i * GRU_HANDLE_STRIDE, 1,
                              GRU_CACHE_LINE_BYTES);
                cb += GRU_HANDLE_STRIDE;
        }
+}
+
+static void gru_load_context_data(void *save, void *grubase, int ctxnum,
+                                 unsigned long cbrmap, unsigned long dsrmap)
+{
+       void *gseg, *cb, *cbe;
+       unsigned long length;
+       int i, scr;
 
+       gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
        cb = gseg + GRU_CB_BASE;
+       cbe = grubase + GRU_CBE_BASE;
+       length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
+       gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
+
        for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
                save += gru_copy_handle(cb, save);
                save += gru_copy_handle(cbe + i * GRU_HANDLE_STRIDE, save);
@@ -472,15 +478,16 @@ static void gru_unload_context_data(void *save, void *grubase, int ctxnum,
        int i, scr;
 
        gseg = grubase + ctxnum * GRU_GSEG_STRIDE;
-
        cb = gseg + GRU_CB_BASE;
        cbe = grubase + GRU_CBE_BASE;
+       length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
+       gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
+
        for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
                save += gru_copy_handle(save, cb);
                save += gru_copy_handle(save, cbe + i * GRU_HANDLE_STRIDE);
                cb += GRU_HANDLE_STRIDE;
        }
-       length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
        memcpy(save, gseg + GRU_DS_BASE, length);
 }
 
index c16028872bbbc0b19c23c8cdb895ad91a22fa3a4..1b9fc3c6b8752240c591aa23ed6a7d0f13bbea44 100644 (file)
@@ -172,7 +172,7 @@ struct mmc_omap_host {
        struct omap_mmc_platform_data *pdata;
 };
 
-void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
+static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
 {
        unsigned long tick_ns;
 
@@ -182,7 +182,7 @@ void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
        }
 }
 
-void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
+static void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable)
 {
        unsigned long flags;
 
@@ -1455,7 +1455,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 
        host->irq = irq;
        host->phys_base = host->mem_res->start;
-       host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
+       host->virt_base = ioremap(res->start, res->end - res->start + 1);
+       if (!host->virt_base)
+               goto err_ioremap;
 
        if (cpu_is_omap24xx()) {
                host->iclk = clk_get(&pdev->dev, "mmc_ick");
@@ -1510,6 +1512,8 @@ err_free_iclk:
                clk_put(host->iclk);
        }
 err_free_mmc_host:
+       iounmap(host->virt_base);
+err_ioremap:
        kfree(host);
 err_free_mem_region:
        release_mem_region(res->start, res->end - res->start + 1);
@@ -1536,6 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
        if (host->fclk && !IS_ERR(host->fclk))
                clk_put(host->fclk);
 
+       iounmap(host->virt_base);
        release_mem_region(pdev->resource[0].start,
                           pdev->resource[0].end - pdev->resource[0].start + 1);
 
index 0a84f10d719c2e2a8f4c37b4696bc3f1dc1e7d2b..9bd7026b0021bbc0aa15fadedd79ae0471844767 100644 (file)
@@ -327,7 +327,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 
        {
                .vendor         = PCI_VENDOR_ID_MARVELL,
-               .device         = PCI_DEVICE_ID_MARVELL_CAFE_SD,
+               .device         = PCI_DEVICE_ID_MARVELL_88ALP01_SD,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .driver_data    = (kernel_ulong_t)&sdhci_cafe,
index 90924fb00481eda9289716337883155326bd8130..d600c2deff73824a70edb5e36f29157f4a36e16a 100644 (file)
@@ -118,7 +118,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
                DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
                      dev->offset, mrq.CardOffset);
                mrq.Page = 0;
-               if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
+               ret = pcmcia_map_mem_page(win, &mrq);
+               if (ret != 0) {
                        cs_error(dev->p_dev, MapMemPage, ret);
                        return NULL;
                }
@@ -326,9 +327,8 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
 
        DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
        ret = pcmcia_modify_configuration(link, &mod);
-       if(ret != CS_SUCCESS) {
+       if (ret != 0)
                cs_error(link, ModifyConfiguration, ret);
-       }
 }
 
 
@@ -368,14 +368,14 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link,
        tuple.DesiredTuple = RETURN_FIRST_TUPLE;
 
        rc = pcmcia_get_first_tuple(link, &tuple);
-       while(rc == CS_SUCCESS) {
+       while (rc == 0) {
                rc = pcmcia_get_tuple_data(link, &tuple);
-               if(rc != CS_SUCCESS) {
+               if (rc != 0) {
                        cs_error(link, GetTupleData, rc);
                        break;
                }
-               rc = pcmcia_parse_tuple(link, &tuple, &parse);
-               if(rc != CS_SUCCESS) {
+               rc = pcmcia_parse_tuple(&tuple, &parse);
+               if (rc != 0) {
                        cs_error(link, ParseTuple, rc);
                        break;
                }
@@ -493,18 +493,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        int last_ret = 0, last_fn = 0;
        int ret;
        int i;
-       config_info_t t;
        static char *probes[] = { "jedec_probe", "cfi_probe" };
        int new_name = 0;
 
        DEBUG(3, "link=0x%p", link);
 
-       DEBUG(2, "Validating CIS");
-       ret = pcmcia_validate_cis(link, NULL);
-       if(ret != CS_SUCCESS) {
-               cs_error(link, GetTupleData, ret);
-       }
-
        card_settings(dev, link, &new_name);
 
        dev->pcmcia_map.phys = NO_XIP;
@@ -571,10 +564,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
        dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
 
-       DEBUG(2, "Getting configuration");
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t));
-       DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
-       dev->vpp = (vpp) ? vpp : t.Vpp1;
+       dev->vpp = (vpp) ? vpp : link->socket.socket.Vpp;
        link->conf.Attributes = 0;
        if(setvpp == 2) {
                link->conf.Vpp = dev->vpp;
@@ -583,16 +573,10 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        }
 
        link->conf.IntType = INT_MEMORY;
-       link->conf.ConfigBase = t.ConfigBase;
-       link->conf.Status = t.Status;
-       link->conf.Pin = t.Pin;
-       link->conf.Copy = t.Copy;
-       link->conf.ExtStatus = t.ExtStatus;
        link->conf.ConfigIndex = 0;
-       link->conf.Present = t.Present;
        DEBUG(2, "Setting Configuration");
        ret = pcmcia_request_configuration(link, &link->conf);
-       if(ret != CS_SUCCESS) {
+       if (ret != 0) {
                cs_error(link, RequestConfiguration, ret);
                if (dev->win_base) {
                        iounmap(dev->win_base);
index e00d424e6575da02ed20246b44c6545c1cbe8b34..1c74762dec89c25f73c3d7ab7fa4fbdaf2e08688 100644 (file)
@@ -26,13 +26,11 @@ static void mtd_notify_add(struct mtd_info* mtd)
        if (!mtd)
                return;
 
-       device_create_drvdata(mtd_class, NULL,
-                             MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
-                             NULL, "mtd%d", mtd->index);
+       device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+                     NULL, "mtd%d", mtd->index);
 
-       device_create_drvdata(mtd_class, NULL,
-                             MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
-                             NULL, "mtd%dro", mtd->index);
+       device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+                     NULL, "mtd%dro", mtd->index);
 }
 
 static void mtd_notify_remove(struct mtd_info* mtd)
index edb90b58a9b16980bd42066f6026bbd1ca7c0667..9a06dc93ee0d36a14428b618d810fb2ece02140d 100644 (file)
@@ -564,10 +564,8 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 
        for ( ; ret <= 0 && *types; types++) {
                parser = get_partition_parser(*types);
-#ifdef CONFIG_KMOD
                if (!parser && !request_module("%s", *types))
                                parser = get_partition_parser(*types);
-#endif
                if (!parser) {
                        printk(KERN_NOTICE "%s partition parsing not available\n",
                               *types);
index 26d42987971fc9480520454fd2944e23c5f47641..782994ead0e83e1a123d011ac867ee3c9ea08c17 100644 (file)
@@ -145,7 +145,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
 
 static int ams_delta_nand_ready(struct mtd_info *mtd)
 {
-       return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
+       return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
 }
 
 /*
@@ -185,7 +185,7 @@ static int __init ams_delta_init(void)
        this->read_buf = ams_delta_read_buf;
        this->verify_buf = ams_delta_verify_buf;
        this->cmd_ctrl = ams_delta_hwcontrol;
-       if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
+       if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
                this->dev_ready = ams_delta_nand_ready;
        } else {
                this->dev_ready = NULL;
index 95345d05157922fdfedf21b6a7d9527215f40be3..b8064bf3aee43d45f086ddbf3675fae71a696c25 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01
  *
+ * The data sheet for this device can be found at:
+ *    http://www.marvell.com/products/pcconn/88ALP01.jsp
+ *
  * Copyright © 2006 Red Hat, Inc.
  * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
  */
@@ -842,7 +845,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
 }
 
 static struct pci_device_id cafe_nand_tbl[] = {
-       { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_88ALP01_NAND,
+         PCI_ANY_ID, PCI_ANY_ID },
        { }
 };
 
index 5ba4bab6d43e75342e9932cd93b6207e6d0dd517..7d15e7c6bcad51f65860ff6b42e09881e8e2064a 100644 (file)
@@ -17,7 +17,7 @@
        Annapolis MD 21403
 
     Fixed (again!) the missing interrupt locking on TX/RX shifting.
-       Alan Cox <Alan.Cox@linux.org>
+       Alan Cox <alan@lxorguk.ukuu.org.uk>
 
     Removed calls to init_etherdev since they are no longer needed, and
     cleaned up modularization just a bit. The driver still allows only
     the board. Now getting 150K/second FTP with a 3c501 card. Still playing
     with a TX-TX optimisation to see if we can touch 180-200K/second as seems
     theoretically maximum.
-               19950402 Alan Cox <Alan.Cox@linux.org>
+               19950402 Alan Cox <alan@lxorguk.ukuu.org.uk>
 
     Cleaned up for 2.3.x because we broke SMP now.
-               20000208 Alan Cox <alan@redhat.com>
+               20000208 Alan Cox <alan@lxorguk.ukuu.org.uk>
 
     Check up pass for 2.5. Nothing significant changed
-               20021009 Alan Cox <alan@redhat.com>
+               20021009 Alan Cox <alan@lxorguk.ukuu.org.uk>
 
     Fixed zero fill corner case
-               20030104 Alan Cox <alan@redhat.com>
+               20030104 Alan Cox <alan@lxorguk.ukuu.org.uk>
 
 
    For the avoidance of doubt the "preferred form" of this code is one which
 
 
 static const char version[] =
-       DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@redhat.com).\n";
+       DRV_NAME ".c: " DRV_VERSION " Alan Cox (alan@lxorguk.ukuu.org.uk).\n";
 
 /*
  *     Braindamage remaining:
index b9d097c9f6bbb88613e71ce53a42d9388a51fbf2..3a7bc524af33cebb0ca332f81440442099b86e27 100644 (file)
@@ -40,7 +40,7 @@
                v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
                v1.15 1/31/98 Faster recovery for Tx errors. -djb
                v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
-               v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
+               v1.18 12Mar2001 Andrew Morton
                        - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
                        - Reviewed against 1.18 from scyld.com
                v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
index e4e3241628d615bb752d99c3cfc18c2ab4e0124e..a0f8b6e2d0af80af13b5774fe40ec9c5ee132db7 100644 (file)
@@ -18,7 +18,7 @@
 
        2001/11/17 - Added ethtool support (jgarzik)
 
-       2002/10/28 - Locking updates for 2.5 (alan@redhat.com)
+       2002/10/28 - Locking updates for 2.5 (alan@lxorguk.ukuu.org.uk)
 
 */
 
index e9d529442b067e5c016195be99cfb0d5c4927dc2..ad301ace608532521c448c8723edb94f45dc5776 100644 (file)
@@ -2400,7 +2400,7 @@ config EHEA
          will be called ehea.
 
 config ENIC
-       tristate "E, the Cisco 10G Ethernet NIC"
+       tristate "Cisco 10G Ethernet NIC support"
        depends on PCI && INET
        select INET_LRO
        help
@@ -2410,7 +2410,6 @@ config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
        depends on PCI && INET
        select INET_LRO
-       select INTEL_IOATDMA
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
          adapters.  For more information on how to identify your adapter, go
@@ -2426,6 +2425,11 @@ config IXGBE
          To compile this driver as a module, choose M here. The module
          will be called ixgbe.
 
+config IXGBE_DCA
+       bool
+       default y
+       depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
+
 config IXGB
        tristate "Intel(R) PRO/10GbE support"
        depends on PCI
@@ -2462,7 +2466,6 @@ config MYRI10GE
        select FW_LOADER
        select CRC32
        select INET_LRO
-       select INTEL_IOATDMA
        ---help---
          This driver supports Myricom Myri-10G Dual Protocol interface in
          Ethernet mode. If the eeprom on your board is not recent enough,
@@ -2474,6 +2477,11 @@ config MYRI10GE
          To compile this driver as a module, choose M here. The module
          will be called myri10ge.
 
+config MYRI10GE_DCA
+       bool
+       default y
+       depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
+
 config NETXEN_NIC
        tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
        depends on PCI
index a0b4c8516073d7384c4baeb2fd1064ec7dc31234..735fc9476403c4df27229298af32021ddd9f1762 100644 (file)
@@ -4,7 +4,7 @@
  *      - Jay Schulist <jschlst@samba.org>
  *
  *     With more than a little help from;
- *     - Alan Cox <Alan.Cox@linux.org> 
+ *     - Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  *      Derived from:
  *      - skeleton.c: A network driver outline for linux.
index 7b92201a7b50b8f0c2984ce17601074daf8bfe23..019b13c08ae6ead71f5a0b976b1e087a3df87df7 100644 (file)
@@ -94,8 +94,8 @@ static irqreturn_t au1000_interrupt(int, void *);
 static void au1000_tx_timeout(struct net_device *);
 static void set_rx_mode(struct net_device *);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
-static int mdio_read(struct net_device *, int, int);
-static void mdio_write(struct net_device *, int, int, u16);
+static int au1000_mdio_read(struct net_device *, int, int);
+static void au1000_mdio_write(struct net_device *, int, int, u16);
 static void au1000_adjust_link(struct net_device *);
 static void enable_mac(struct net_device *, int);
 
@@ -191,7 +191,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 /*
  * MII operations
  */
-static int mdio_read(struct net_device *dev, int phy_addr, int reg)
+static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
 {
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
        volatile u32 *const mii_control_reg = &aup->mac->mii_control;
@@ -225,7 +225,8 @@ static int mdio_read(struct net_device *dev, int phy_addr, int reg)
        return (int)*mii_data_reg;
 }
 
-static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
+static void au1000_mdio_write(struct net_device *dev, int phy_addr,
+                             int reg, u16 value)
 {
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
        volatile u32 *const mii_control_reg = &aup->mac->mii_control;
@@ -249,7 +250,7 @@ static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
        *mii_control_reg = mii_control;
 }
 
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int au1000_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 {
        /* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
         * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
@@ -257,21 +258,21 @@ static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 
        enable_mac(dev, 0); /* make sure the MAC associated with this
                             * mii_bus is enabled */
-       return mdio_read(dev, phy_addr, regnum);
+       return au1000_mdio_read(dev, phy_addr, regnum);
 }
 
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
-                        u16 value)
+static int au1000_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+                               u16 value)
 {
        struct net_device *const dev = bus->priv;
 
        enable_mac(dev, 0); /* make sure the MAC associated with this
                             * mii_bus is enabled */
-       mdio_write(dev, phy_addr, regnum, value);
+       au1000_mdio_write(dev, phy_addr, regnum, value);
        return 0;
 }
 
-static int mdiobus_reset(struct mii_bus *bus)
+static int au1000_mdiobus_reset(struct mii_bus *bus)
 {
        struct net_device *const dev = bus->priv;
 
@@ -703,9 +704,9 @@ static struct net_device * au1000_probe(int port_num)
                goto err_out;
 
        aup->mii_bus->priv = dev;
-       aup->mii_bus->read = mdiobus_read;
-       aup->mii_bus->write = mdiobus_write;
-       aup->mii_bus->reset = mdiobus_reset;
+       aup->mii_bus->read = au1000_mdiobus_read;
+       aup->mii_bus->write = au1000_mdiobus_write;
+       aup->mii_bus->reset = au1000_mdiobus_reset;
        aup->mii_bus->name = "au1000_eth_mii";
        snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
        aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
index a0d41c5d97d8565334f247adb1e39187665af4e8..b458d607a9c669215b48ffa831fe0c86cd4fde88 100644 (file)
@@ -253,7 +253,7 @@ init_error:
  * MII operations
  */
 /* Wait until the previous MDC/MDIO transaction has completed */
-static void mdio_poll(void)
+static void bfin_mdio_poll(void)
 {
        int timeout_cnt = MAX_TIMEOUT_CNT;
 
@@ -269,25 +269,25 @@ static void mdio_poll(void)
 }
 
 /* Read an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 {
-       mdio_poll();
+       bfin_mdio_poll();
 
        /* read mode */
        bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
                                SET_REGAD((u16) regnum) |
                                STABUSY);
 
-       mdio_poll();
+       bfin_mdio_poll();
 
        return (int) bfin_read_EMAC_STADAT();
 }
 
 /* Write an off-chip register in a PHY through the MDC/MDIO port */
-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
-                        u16 value)
+static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+                             u16 value)
 {
-       mdio_poll();
+       bfin_mdio_poll();
 
        bfin_write_EMAC_STADAT((u32) value);
 
@@ -297,12 +297,12 @@ static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
                                STAOP |
                                STABUSY);
 
-       mdio_poll();
+       bfin_mdio_poll();
 
        return 0;
 }
 
-static int mdiobus_reset(struct mii_bus *bus)
+static int bfin_mdiobus_reset(struct mii_bus *bus)
 {
        return 0;
 }
@@ -818,7 +818,7 @@ static void bfin_mac_enable(void)
        bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
 
        /* Wait MII done */
-       mdio_poll();
+       bfin_mdio_poll();
 
        /* We enable only RX here */
        /* ASTP   : Enable Automatic Pad Stripping
@@ -1063,9 +1063,9 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
                goto out_err_mdiobus_alloc;
 
        lp->mii_bus->priv = ndev;
-       lp->mii_bus->read = mdiobus_read;
-       lp->mii_bus->write = mdiobus_write;
-       lp->mii_bus->reset = mdiobus_reset;
+       lp->mii_bus->read = bfin_mdiobus_read;
+       lp->mii_bus->write = bfin_mdiobus_write;
+       lp->mii_bus->reset = bfin_mdiobus_reset;
        lp->mii_bus->name = "bfin_mac_mdio";
        snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0");
        lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
index a28de8182802c68698f86f966acb20a2032d74c4..7107620f615dfd0d17bef1b06fce245ef12411f0 100644 (file)
@@ -36,8 +36,7 @@
 
   Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
 
-  Andrew Morton     : andrewm@uow.edu.au
-                    : Kernel 2.3.48
+  Andrew Morton     : Kernel 2.3.48
                     : Handle kmalloc() failures
                     : Other resource allocation fixes
                     : Add SMP locks
@@ -49,7 +48,7 @@
                     : Fixed an out-of-mem bug in dma_rx()
                     : Updated Documentation/networking/cs89x0.txt
 
-  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre1
+  Andrew Morton     : Kernel 2.3.99-pre1
                     : Use skb_reserve to longword align IP header (two places)
                     : Remove a delay loop from dma_rx()
                     : Replace '100' with HZ
                     : Added 'cs89x0_dma=N' kernel boot option
                     : Correctly initialise lp->lock in non-module compile
 
-  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1
+  Andrew Morton     : Kernel 2.3.99-pre4-1
                     : MOD_INC/DEC race fix (see
                     : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
 
-  Andrew Morton     : andrewm@uow.edu.au / Kernel 2.4.0-test7-pre2
+  Andrew Morton     : Kernel 2.4.0-test7-pre2
                     : Enhanced EEPROM support to cover more devices,
                     :   abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch
                     :   (Jason Gunthorpe <jgg@ualberta.ca>)
 #include "cs89x0.h"
 
 static char version[] __initdata =
-"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
+"cs89x0.c: v2.4.3-pre1 Russell Nelson <nelson@crynwr.com>, Andrew Morton\n";
 
 #define DRV_NAME "cs89x0"
 
@@ -1877,7 +1876,7 @@ MODULE_PARM_DESC(dmasize , "(ignored)");
 MODULE_PARM_DESC(use_dma , "(ignored)");
 #endif
 
-MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>");
+MODULE_AUTHOR("Mike Cruse, Russwll Nelson <nelson@crynwr.com>, Andrew Morton");
 MODULE_LICENSE("GPL");
 
 
index 455ef529cd626ca167626161cc6cc3a35d981fb6..bc8e2413abd25d6c5106bcc83d10098fde44489d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 744fac0b1617643294122f6cd9027a9671e9a9d0..5c3c05da4d96338e3f80e659c3c6e09d0017121b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 593fb643a615086ff6a16cb8ed88844bf0705804..e312d315a42d4e5ded041e3c1d8c717ae6ae02a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 6ad92405d9a034268796aafb7ece1540aa37c6bc..1d8d46eb3c960e0efd3725d731f947abb02b438f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 45e92164c26047765ed0aacb6cdb76025042c9b2..47e53769af5b7f074e45e07505be797263261458 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 3e8d5faec3a4a9b6dd7ab9aeebf7e6f62ef74431..b19e4376ba76ec1584b948507783f8a566c7575b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index f31985df0bb9a2646adefd39746b8f05ab89072d..1ace41a13ac360363b2857475920a014daad4e94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 0f6fd63b28475cdf5bc0be26ebb5cf07cd88035d..265aa8a15afaed2eb5a61177917d07cd6649b476 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 7a379138b5a6ebe757da3ce5c86abfd37174fc46..d514e5019dfc36b0935bace2be32056b0ee4f272 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index b75ddd8777fe8dbd0c900e775351e9ebe753fe13..0d9b0e6dccff41f58544345b0570cd762241b0c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index b2c5314582aa0cb954872d29127388f8edc5645c..4407ac9bb5559e87e427c445982cfa188a975ccf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 42ce65f76a87517904bd89b4378cace767c53580..fd3eb07e3f40a5bb093307a1dab7c21f3bef338e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 4c4d6e877ea698baf6ed92bbfc606f1b389dc476..3b5517b8fbde74a1131d932c890d0d5e3f39ab97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 87919419b707faf3107877181dd96ec0b8cd5938..c6480be0bc1f7ed033b9a9ed0d856d12b4490255 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 917970ed24a1cbd1369d1160889ce8a61b0f0307..852c399a8b0ae838a0c963c2b3788918626e1e02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 4da5b09b9bc29221ec7a2eae370bb9b8832a398a..968f64be3743acb165dbe40013e5d2a4dd60ee42 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 0a21cfbd2b2135fd47aedad1803fcc5d6c446d8f..be55e9ae74d18caeadfc8f6d2e6ca663ef773692 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2007 Chelsio Communications.  All rights reserved.
+ * Copyright (C) 2006-2008 Chelsio Communications.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 29db711303b9040070aa6c2bc54f7295ed520a24..bb8698a867545384842032a10d330c3ee785cc0b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -35,7 +35,7 @@
 #define DRV_DESC "Chelsio T3 Network Driver"
 #define DRV_NAME "cxgb3"
 /* Driver version */
-#define DRV_VERSION "1.0-ko"
+#define DRV_VERSION "1.1.0-ko"
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 7
index 306c2dc4ab34884d2687fdae9c302d80b01b2426..33f956bd6b59b8f96134c9e09cc23149f4556b77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index ffdc0a1892bd2334ed770647ea5c82a8ba498645..9d7786937aadf4c7e806d3bec7c6c58e8dd46d04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
index 795c594a4b7c550e1d4200206205961aff4820a5..b751c1b96cfa77e2d445e3c182a4d2003cb8de73 100644 (file)
@@ -8,7 +8,7 @@
  *
  * Many modifications, and currently maintained, by
  *  Philip Blundell <philb@gnu.org>
- * Added the Compaq LTE  Alan Cox <alan@redhat.com>
+ * Added the Compaq LTE  Alan Cox <alan@lxorguk.ukuu.org.uk>
  * Added MCA support Adam Fritzler
  *
  * Note - this driver is experimental still - it has problems on faster
index f3a47a87dbbe3206304d2827187e2561780d165a..180e968dc54d87401eaa174c30a724223425d4bf 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/tcp.h>
+#include <net/ip6_checksum.h>
 
 #include "cq_enet_desc.h"
 #include "vnic_dev.h"
index bcec7320895c889e96afaf7c067fa80438a4447a..78a1628c9892f71514cd781eed6a62b56fa0de48 100644 (file)
@@ -62,3 +62,15 @@ config IBM_NEW_EMAC_TAH
 config IBM_NEW_EMAC_EMAC4
        bool
        default n
+
+config IBM_NEW_EMAC_NO_FLOW_CTRL
+       bool
+       default n
+
+config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+       bool
+       default n
+
+config IBM_NEW_EMAC_MAL_COMMON_ERR
+       bool
+       default n
index 58dfd32ccca8c1a82c2d7569bfad8a4812d11d28..efcf21c9f5c7a825ee66ca0671e689c90c13f5ff 100644 (file)
@@ -202,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
 {
        return  phy_mode == PHY_MODE_GMII ||
                phy_mode == PHY_MODE_RGMII ||
+               phy_mode == PHY_MODE_SGMII ||
                phy_mode == PHY_MODE_TBI ||
                phy_mode == PHY_MODE_RTBI;
 }
 
 static inline int emac_phy_gpcs(int phy_mode)
 {
-       return  phy_mode == PHY_MODE_TBI ||
+       return  phy_mode == PHY_MODE_SGMII ||
+               phy_mode == PHY_MODE_TBI ||
                phy_mode == PHY_MODE_RTBI;
 }
 
@@ -562,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
        switch (dev->phy.speed) {
        case SPEED_1000:
                if (emac_phy_gpcs(dev->phy.mode)) {
-                       mr1 |= EMAC_MR1_MF_1000GPCS |
-                               EMAC_MR1_MF_IPPA(dev->phy.address);
+                       mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
+                               (dev->phy.gpcs_address != 0xffffffff) ?
+                                dev->phy.gpcs_address : dev->phy.address);
 
                        /* Put some arbitrary OUI, Manuf & Rev IDs so we can
                         * identify this GPCS PHY later.
@@ -675,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
        out_be32(&p->iser,  r);
 
        /* We need to take GPCS PHY out of isolate mode after EMAC reset */
-       if (emac_phy_gpcs(dev->phy.mode))
-               emac_mii_reset_phy(&dev->phy);
+       if (emac_phy_gpcs(dev->phy.mode)) {
+               if (dev->phy.gpcs_address != 0xffffffff)
+                       emac_mii_reset_gpcs(&dev->phy);
+               else
+                       emac_mii_reset_phy(&dev->phy);
+       }
 
        return 0;
 }
@@ -881,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
        struct emac_instance *dev = netdev_priv(ndev);
        int res;
 
-       res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev,
+       res = __emac_mdio_read((dev->mdio_instance &&
+                               dev->phy.gpcs_address != id) ?
+                               dev->mdio_instance : dev,
                               (u8) id, (u8) reg);
        return res;
 }
@@ -890,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
 {
        struct emac_instance *dev = netdev_priv(ndev);
 
-       __emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev,
+       __emac_mdio_write((dev->mdio_instance &&
+                          dev->phy.gpcs_address != id) ?
+                          dev->mdio_instance : dev,
                          (u8) id, (u8) reg, (u16) val);
 }
 
@@ -2382,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
                 * XXX I probably should move these settings to the dev tree
                 */
                dev->phy.address = -1;
-               dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
+               dev->phy.features = SUPPORTED_MII;
+               if (emac_phy_supports_gige(dev->phy_mode))
+                       dev->phy.features |= SUPPORTED_1000baseT_Full;
+               else
+                       dev->phy.features |= SUPPORTED_100baseT_Full;
                dev->phy.pause = 1;
 
                return 0;
@@ -2421,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
                 * Note that the busy_phy_map is currently global
                 * while it should probably be per-ASIC...
                 */
-               dev->phy.address = dev->cell_index;
+               dev->phy.gpcs_address = dev->gpcs_address;
+               if (dev->phy.gpcs_address == 0xffffffff)
+                       dev->phy.address = dev->cell_index;
        }
 
        emac_configure(dev);
@@ -2531,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
                dev->phy_address = 0xffffffff;
        if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
                dev->phy_map = 0xffffffff;
+       if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
+               dev->gpcs_address = 0xffffffff;
        if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
                return -ENXIO;
        if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
@@ -2585,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
                if (of_device_is_compatible(np, "ibm,emac-440ep") ||
                    of_device_is_compatible(np, "ibm,emac-440gr"))
                        dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+               if (of_device_is_compatible(np, "ibm,emac-405ez"))
+                       dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
        }
 
        /* Fixup some feature bits based on the device tree */
@@ -2842,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
               ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
               ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
 
+       if (dev->phy_mode == PHY_MODE_SGMII)
+               printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
+
        if (dev->phy.address >= 0)
                printk("%s: found %s PHY (0x%02x)\n", ndev->name,
                       dev->phy.def->name, dev->phy.address);
index 5ca70e55b6c51a49509953985e24f92928f02e7e..18d56c6c4238e75673e34c3bdd7c0ec2a55563bb 100644 (file)
@@ -190,6 +190,9 @@ struct emac_instance {
        struct delayed_work             link_work;
        int                             link_polling;
 
+       /* GPCS PHY infos */
+       u32                             gpcs_address;
+
        /* Shared MDIO if any */
        u32                             mdio_ph;
        struct of_device                *mdio_dev;
@@ -344,6 +347,9 @@ enum {
 #endif
 #ifdef CONFIG_IBM_NEW_EMAC_RGMII
            EMAC_FTR_HAS_RGMII  |
+#endif
+#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+           EMAC_FTR_NO_FLOW_CONTROL_40x |
 #endif
        EMAC_FTR_460EX_PHY_CLK_FIX |
        EMAC_FTR_440EP_PHY_CLK_FIX,
index 10c267b2b9610b1e446a4fe32e4deba9c5700976..1839d3f154a3f3256f15b9d842f86fbd407a8fe5 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 
 #include "core.h"
+#include <asm/dcr-regs.h>
 
 static int mal_count;
 
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
        mal_schedule_poll(mal);
        set_mal_dcrn(mal, MAL_TXEOBISR, r);
 
+       if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+               mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+                               (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+
        return IRQ_HANDLED;
 }
 
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
        mal_schedule_poll(mal);
        set_mal_dcrn(mal, MAL_RXEOBISR, r);
 
+       if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+               mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+                               (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+
        return IRQ_HANDLED;
 }
 
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t mal_int(int irq, void *dev_instance)
+{
+       struct mal_instance *mal = dev_instance;
+       u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+       if (esr & MAL_ESR_EVB) {
+               /* descriptor error */
+               if (esr & MAL_ESR_DE) {
+                       if (esr & MAL_ESR_CIDT)
+                               return mal_rxde(irq, dev_instance);
+                       else
+                               return mal_txde(irq, dev_instance);
+               } else { /* SERR */
+                       return mal_serr(irq, dev_instance);
+               }
+       }
+       return IRQ_HANDLED;
+}
+
 void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
 {
        /* Spinlock-type semantics: only one caller disable poll at a time */
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
        unsigned int dcr_base;
        const u32 *prop;
        u32 cfg;
+       unsigned long irqflags;
+       irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
 
        mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
        if (!mal) {
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
                goto fail;
        }
 
+       if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
+               mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
+                               MAL_FTR_COMMON_ERR_INT);
+
        mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
        mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
        mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
-       mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
-       mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+
+       if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+               mal->txde_irq = mal->rxde_irq = mal->serr_irq;
+       } else {
+               mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
+               mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+       }
+
        if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
            mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
            mal->rxde_irq == NO_IRQ) {
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
                             sizeof(struct mal_descriptor) *
                             mal_rx_bd_offset(mal, i));
 
-       err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal);
+       if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+               irqflags = IRQF_SHARED;
+               hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
+       } else {
+               irqflags = 0;
+               hdlr_serr = mal_serr;
+               hdlr_txde = mal_txde;
+               hdlr_rxde = mal_rxde;
+       }
+
+       err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
        if (err)
                goto fail2;
-       err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal);
+       err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
        if (err)
                goto fail3;
        err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
        if (err)
                goto fail4;
-       err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
+       err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
        if (err)
                goto fail5;
        err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
index 717dc38b685885d0b0bd6fc8dac0610bc3042808..2f0a87360844afc3d1dd7eaaf3f3b0ebd6f6510c 100644 (file)
@@ -213,6 +213,8 @@ struct mal_instance {
        struct of_device        *ofdev;
        int                     index;
        spinlock_t              lock;
+
+       unsigned int features;
 };
 
 static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
@@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
        dcr_write(mal->dcr_host, reg, val);
 }
 
+/* Features of various MAL implementations */
+
+/* Set if you have interrupt coalescing and you have to clear the SDR
+ * register for TXEOB and RXEOB interrupts to work
+ */
+#define MAL_FTR_CLEAR_ICINTSTAT        0x00000001
+
+/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
+ * interrupt
+ */
+#define MAL_FTR_COMMON_ERR_INT 0x00000002
+
+enum {
+       MAL_FTRS_ALWAYS = 0,
+
+       MAL_FTRS_POSSIBLE =
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+               MAL_FTR_CLEAR_ICINTSTAT |
+#endif
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
+               MAL_FTR_COMMON_ERR_INT |
+#endif
+               0,
+};
+
+static inline int mal_has_feature(struct mal_instance *dev,
+               unsigned long feature)
+{
+       return (MAL_FTRS_ALWAYS & feature) ||
+               (MAL_FTRS_POSSIBLE & dev->features & feature);
+}
+
 /* Register MAL devices */
 int mal_init(void);
 void mal_exit(void);
index 9164abb72d9bc908bac64e89a7ed5ddf6db1174e..c40cd8df2212089e2f810bd1f25e0f6354dc42f3 100644 (file)
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
        phy->mdio_write(phy->dev, phy->address, reg, val);
 }
 
+static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
+{
+       return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
+}
+
+static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
+{
+       phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
+}
+
 int emac_mii_reset_phy(struct mii_phy *phy)
 {
        int val;
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
        return limit <= 0;
 }
 
+int emac_mii_reset_gpcs(struct mii_phy *phy)
+{
+       int val;
+       int limit = 10000;
+
+       val = gpcs_phy_read(phy, MII_BMCR);
+       val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
+       val |= BMCR_RESET;
+       gpcs_phy_write(phy, MII_BMCR, val);
+
+       udelay(300);
+
+       while (limit--) {
+               val = gpcs_phy_read(phy, MII_BMCR);
+               if (val >= 0 && (val & BMCR_RESET) == 0)
+                       break;
+               udelay(10);
+       }
+       if ((val & BMCR_ISOLATE) && limit > 0)
+               gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
+
+       if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
+               /* Configure GPCS interface to recommended setting for SGMII */
+               gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
+               gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
+               gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX     */
+       }
+
+       return limit <= 0;
+}
+
 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
        int ctl, adv;
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
        return  0;
 }
 
+static int m88e1112_init(struct mii_phy *phy)
+{
+       /*
+        * Marvell 88E1112 PHY needs to have the SGMII MAC
+        * interace (page 2) properly configured to
+        * communicate with the 460EX/GT GPCS interface.
+        */
+
+       u16 reg_short;
+
+       pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
+
+       /* Set access to Page 2 */
+       phy_write(phy, 0x16, 0x0002);
+
+       phy_write(phy, 0x00, 0x0040); /* 1Gbps */
+       reg_short = (u16)(phy_read(phy, 0x1a));
+       reg_short |= 0x8000; /* bypass Auto-Negotiation */
+       phy_write(phy, 0x1a, reg_short);
+       emac_mii_reset_phy(phy); /* reset MAC interface */
+
+       /* Reset access to Page 0 */
+       phy_write(phy, 0x16, 0x0000);
+
+       return  0;
+}
+
 static int et1011c_init(struct mii_phy *phy)
 {
        u16 reg_short;
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
        .ops            = &m88e1111_phy_ops,
 };
 
+static struct mii_phy_ops m88e1112_phy_ops = {
+       .init           = m88e1112_init,
+       .setup_aneg     = genmii_setup_aneg,
+       .setup_forced   = genmii_setup_forced,
+       .poll_link      = genmii_poll_link,
+       .read_link      = genmii_read_link
+};
+
+static struct mii_phy_def m88e1112_phy_def = {
+       .phy_id         = 0x01410C90,
+       .phy_id_mask    = 0x0ffffff0,
+       .name           = "Marvell 88E1112 Ethernet",
+       .ops            = &m88e1112_phy_ops,
+};
+
 static struct mii_phy_def *mii_phy_table[] = {
        &et1011c_phy_def,
        &cis8201_phy_def,
        &bcm5248_phy_def,
        &m88e1111_phy_def,
+       &m88e1112_phy_def,
        &genmii_phy_def,
        NULL
 };
index 1b65c81f65577513af7ab34a52b7205fee10bab5..5d2bf4cbe50b9fb2ee365d1f30f7b0dee7d064fb 100644 (file)
@@ -57,6 +57,7 @@ struct mii_phy {
                                   or determined automaticaly */
        int address;            /* PHY address */
        int mode;               /* PHY mode */
+       int gpcs_address;       /* GPCS PHY address */
 
        /* 1: autoneg enabled, 0: disabled */
        int autoneg;
@@ -81,5 +82,6 @@ struct mii_phy {
  */
 int emac_mii_phy_probe(struct mii_phy *phy, int address);
 int emac_mii_reset_phy(struct mii_phy *phy);
+int emac_mii_reset_gpcs(struct mii_phy *phy);
 
 #endif /* __IBM_NEWEMAC_PHY_H */
index 95e3464068db540c1d2a3f530960586ee2d0cfe0..f02764725a221fdde54b43ea9be1e7d65c8e8b75 100644 (file)
@@ -71,7 +71,7 @@ History:
   June 1st, 2000
        corrected version codes, added support for the latest 2.3 changes
   Oct 28th, 2002
-       cleaned up for the 2.5 tree <alan@redhat.com>
+       cleaned up for the 2.5 tree <alan@lxorguk.ukuu.org.uk>
 
  *************************************************************************/
 
index 36030241f7a9cf72102f09a019cae9ca54f0e169..2a9930e6e2afef50c5e3e711d5232bc8f9aead96 100644 (file)
@@ -67,9 +67,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
        const struct dongle_driver *drv = NULL;
        int err = -EINVAL;
 
-#ifdef CONFIG_KMOD
        request_module("irda-dongle-%d", type);
-#endif
 
        if (dev->dongle_drv != NULL)
                return -EBUSY;
index 2198b77c53ed07f8f089a3bdbed3ba1542c52aba..e116d340dcc6e158b35160f43ccd76d92feaa796 100644 (file)
@@ -36,7 +36,7 @@
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
 #include <linux/dca.h>
 #endif
 
@@ -136,7 +136,7 @@ struct ixgbe_ring {
                      * offset associated with this ring, which is different
                      * for DCE and RSS modes */
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        /* cpu for tx queue */
        int cpu;
 #endif
index ca17af4349d03ee6283f2f3340c1107d7ad1ed8b..7548fb7360d9a611827bd602262223d687dc3702 100644 (file)
@@ -80,7 +80,7 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
 static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
                             void *p);
 static struct notifier_block dca_notifier = {
@@ -296,7 +296,7 @@ done_cleaning:
        return (total_packets ? true : false);
 }
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
 static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
                                 struct ixgbe_ring *rx_ring)
 {
@@ -383,7 +383,7 @@ static int __ixgbe_notify_dca(struct device *dev, void *data)
        return 0;
 }
 
-#endif /* CONFIG_DCA or CONFIG_DCA_MODULE */
+#endif /* CONFIG_IXGBE_DCA */
 /**
  * ixgbe_receive_skb - Send a completed packet up the stack
  * @adapter: board private structure
@@ -947,7 +947,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
        r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
        for (i = 0; i < q_vector->txr_count; i++) {
                tx_ring = &(adapter->tx_ring[r_idx]);
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
                if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                        ixgbe_update_tx_dca(adapter, tx_ring);
 #endif
@@ -1022,7 +1022,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 
        r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
        rx_ring = &(adapter->rx_ring[r_idx]);
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                ixgbe_update_rx_dca(adapter, rx_ring);
 #endif
@@ -1066,7 +1066,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
        r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
        for (i = 0; i < q_vector->rxr_count; i++) {
                rx_ring = &(adapter->rx_ring[r_idx]);
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
                if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
                        ixgbe_update_rx_dca(adapter, rx_ring);
 #endif
@@ -2155,7 +2155,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 
        netif_carrier_off(netdev);
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
                adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
                dca_remove_requester(&adapter->pdev->dev);
@@ -2167,7 +2167,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        ixgbe_clean_all_tx_rings(adapter);
        ixgbe_clean_all_rx_rings(adapter);
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        /* since we reset the hardware DCA settings were cleared */
        if (dca_add_requester(&adapter->pdev->dev) == 0) {
                adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
@@ -2193,7 +2193,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
        struct ixgbe_adapter *adapter = q_vector->adapter;
        int tx_cleaned, work_done = 0;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
                ixgbe_update_tx_dca(adapter, adapter->tx_ring);
                ixgbe_update_rx_dca(adapter, adapter->rx_ring);
@@ -3922,7 +3922,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        if (err)
                goto err_register;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        if (dca_add_requester(&pdev->dev) == 0) {
                adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
                /* always use CB2 mode, difference is masked
@@ -3972,7 +3972,7 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
 
        flush_scheduled_work();
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
                adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
                dca_remove_requester(&pdev->dev);
@@ -4105,10 +4105,10 @@ static int __init ixgbe_init_module(void)
 
        printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        dca_register_notify(&dca_notifier);
-
 #endif
+
        ret = pci_register_driver(&ixgbe_driver);
        return ret;
 }
@@ -4123,13 +4123,13 @@ module_init(ixgbe_init_module);
  **/
 static void __exit ixgbe_exit_module(void)
 {
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
        dca_unregister_notify(&dca_notifier);
 #endif
        pci_unregister_driver(&ixgbe_driver);
 }
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
+#ifdef CONFIG_IXGBE_DCA
 static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
                             void *p)
 {
@@ -4140,7 +4140,7 @@ static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
 
        return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
 }
-#endif /* CONFIG_DCA or CONFIG_DCA_MODULE */
+#endif /* CONFIG_IXGBE_DCA */
 
 module_exit(ixgbe_exit_module);
 
index 5f9a1313fa3e3cd13b64f37c21373ce0cb3e6a5a..81c6cdc3851f8afd54d3319df5e6e9b99d516a25 100644 (file)
@@ -21,7 +21,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -38,6 +37,7 @@
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/if_vlan.h>
+#include <net/ip6_checksum.h>
 #include "jme.h"
 
 static int force_pseudohp = -1;
index 51ad3765e0750c2857555c437ed259631a5394b7..85587a6667b9f170d3b55686a6474c20754a4c15 100644 (file)
@@ -9,7 +9,7 @@
  *     2 of the License, or (at your option) any later version.
  *
  *     Copyright (C) 1996 Paul Mackerras.
- *     Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ *     Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  *     Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
  *
index 6dce901c7f450b1611186568f78083536b37886b..a9aebad526528d369798dd88b051aa90a26ec6ec 100644 (file)
@@ -188,7 +188,7 @@ struct myri10ge_slice_state {
        dma_addr_t fw_stats_bus;
        int watchdog_tx_done;
        int watchdog_tx_req;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        int cached_dca_tag;
        int cpu;
        __be32 __iomem *dca_tag;
@@ -220,7 +220,7 @@ struct myri10ge_priv {
        int msi_enabled;
        int msix_enabled;
        struct msix_entry *msix_vectors;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        int dca_enabled;
 #endif
        u32 link_state;
@@ -902,7 +902,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        struct myri10ge_slice_state *ss;
        int i, status;
        size_t bytes;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        unsigned long dca_tag_off;
 #endif
 
@@ -1012,7 +1012,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        }
        put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
 
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_DCA_OFFSET, &cmd, 0);
        dca_tag_off = cmd.data0;
        for (i = 0; i < mgp->num_slices; i++) {
@@ -1051,7 +1051,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
        return status;
 }
 
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
 static void
 myri10ge_write_dca(struct myri10ge_slice_state *ss, int cpu, int tag)
 {
@@ -1505,7 +1505,7 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
        struct net_device *netdev = ss->mgp->dev;
        int work_done;
 
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        if (ss->mgp->dca_enabled)
                myri10ge_update_dca(ss);
 #endif
@@ -1736,7 +1736,7 @@ static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = {
        "tx_boundary", "WC", "irq", "MSI", "MSIX",
        "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
        "serial_number", "watchdog_resets",
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        "dca_capable_firmware", "dca_device_present",
 #endif
        "link_changes", "link_up", "dropped_link_overflow",
@@ -1815,7 +1815,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
        data[i++] = (unsigned int)mgp->read_write_dma;
        data[i++] = (unsigned int)mgp->serial_number;
        data[i++] = (unsigned int)mgp->watchdog_resets;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        data[i++] = (unsigned int)(mgp->ss[0].dca_tag != NULL);
        data[i++] = (unsigned int)(mgp->dca_enabled);
 #endif
@@ -3844,7 +3844,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_err(&pdev->dev, "failed reset\n");
                goto abort_with_slices;
        }
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        myri10ge_setup_dca(mgp);
 #endif
        pci_set_drvdata(pdev, mgp);
@@ -3948,7 +3948,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
        netdev = mgp->dev;
        unregister_netdev(netdev);
 
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        myri10ge_teardown_dca(mgp);
 #endif
        myri10ge_dummy_rdma(mgp, 0);
@@ -3993,7 +3993,7 @@ static struct pci_driver myri10ge_driver = {
 #endif
 };
 
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
 static int
 myri10ge_notify_dca(struct notifier_block *nb, unsigned long event, void *p)
 {
@@ -4024,7 +4024,7 @@ static __init int myri10ge_init_module(void)
                       myri10ge_driver.name, myri10ge_rss_hash);
                myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT;
        }
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        dca_register_notify(&myri10ge_dca_notifier);
 #endif
        if (myri10ge_max_slices > MYRI10GE_MAX_SLICES)
@@ -4037,7 +4037,7 @@ module_init(myri10ge_init_module);
 
 static __exit void myri10ge_cleanup_module(void)
 {
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+#ifdef CONFIG_MYRI10GE_DCA
        dca_unregister_notify(&myri10ge_dca_notifier);
 #endif
        pci_unregister_driver(&myri10ge_driver);
index 7112fd5e0e1ba8f76f9f0995695aed0f7749c212..08c4dd896077b7199762821264c522cc721b065a 100644 (file)
@@ -355,9 +355,10 @@ static int tc574_config(struct pcmcia_device *link)
        for (i = j = 0; j < 0x400; j += 0x20) {
                link->io.BasePort1 = j ^ 0x300;
                i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS) break;
+               if (i == 0)
+                       break;
        }
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIO, i);
                goto failed;
        }
@@ -377,7 +378,7 @@ static int tc574_config(struct pcmcia_device *link)
        tuple.TupleDataMax = 64;
        tuple.TupleOffset = 0;
        tuple.DesiredTuple = 0x88;
-       if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+       if (pcmcia_get_first_tuple(link, &tuple) == 0) {
                pcmcia_get_tuple_data(link, &tuple);
                for (i = 0; i < 3; i++)
                        phys_addr[i] = htons(le16_to_cpu(buf[i]));
index 549a64558420dba22d81afc96f426bfe794e9b27..c235cdba69c6384d11b83ace2b2a1aac2f4a1905 100644 (file)
@@ -15,7 +15,7 @@
     incorporated herein by reference.
     Donald Becker may be reached at becker@scyld.com
     
-    Updated for 2.5.x by Alan Cox <alan@redhat.com>
+    Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk>
 
 ======================================================================*/
 
@@ -278,9 +278,10 @@ static int tc589_config(struct pcmcia_device *link)
        if (multi && (j & 0x80)) continue;
        link->io.BasePort1 = j ^ 0x300;
        i = pcmcia_request_io(link, &link->io);
-       if (i == CS_SUCCESS) break;
+       if (i == 0)
+               break;
     }
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        cs_error(link, RequestIO, i);
        goto failed;
     }
@@ -295,7 +296,7 @@ static int tc589_config(struct pcmcia_device *link)
     /* The 3c589 has an extra EEPROM for configuration info, including
        the hardware address.  The 3c562 puts the address in the CIS. */
     tuple.DesiredTuple = 0x88;
-    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, &tuple) == 0) {
        pcmcia_get_tuple_data(link, &tuple);
        for (i = 0; i < 3; i++)
            phys_addr[i] = htons(le16_to_cpu(buf[i]));
index e8f55d8ed7a900f86329e72e682c1f0f3023b02c..9b8f793b1cc81c08ac586ae99082ce72658fcb9a 100644 (file)
@@ -111,7 +111,7 @@ config ARCNET_COM20020_CS
 
 config PCMCIA_IBMTR
        tristate "IBM PCMCIA tokenring adapter support"
-       depends on IBMTR!=y && TR && !64BIT
+       depends on IBMTR!=y && TR
        help
          Say Y here if you intend to attach this type of Token Ring PCMCIA
          card to your computer. You then also need to say Y to "Token Ring
index 52bf11b73c6e950e0829bed0dcee087f98c52b38..b37a498939ae7d1a16f6e1a5c0ad8545f6d32380 100644 (file)
@@ -262,7 +262,7 @@ static int try_io_port(struct pcmcia_device *link)
        if (link->io.NumPorts2 > 0) {
            /* for master/slave multifunction cards */
            link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-           link->irq.Attributes = 
+           link->irq.Attributes =
                IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
        }
     } else {
@@ -276,7 +276,8 @@ static int try_io_port(struct pcmcia_device *link)
            link->io.BasePort1 = j ^ 0x300;
            link->io.BasePort2 = (j ^ 0x300) + 0x10;
            ret = pcmcia_request_io(link, &link->io);
-           if (ret == CS_SUCCESS) return ret;
+           if (ret == 0)
+                   return ret;
        }
        return ret;
     } else {
@@ -284,59 +285,50 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
+static int axnet_configcheck(struct pcmcia_device *p_dev,
+                            cistpl_cftable_entry_t *cfg,
+                            cistpl_cftable_entry_t *dflt,
+                            unsigned int vcc,
+                            void *priv_data)
+{
+       int i;
+       cistpl_io_t *io = &cfg->io;
+
+       if (cfg->index == 0 || cfg->io.nwin == 0)
+               return -ENODEV;
+
+       p_dev->conf.ConfigIndex = 0x05;
+       /* For multifunction cards, by convention, we configure the
+          network function with window 0, and serial with window 1 */
+       if (io->nwin > 1) {
+               i = (io->win[1].len > io->win[0].len);
+               p_dev->io.BasePort2 = io->win[1-i].base;
+               p_dev->io.NumPorts2 = io->win[1-i].len;
+       } else {
+               i = p_dev->io.NumPorts2 = 0;
+       }
+       p_dev->io.BasePort1 = io->win[i].base;
+       p_dev->io.NumPorts1 = io->win[i].len;
+       p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+       if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+               return try_io_port(p_dev);
+
+       return -ENODEV;
+}
+
 static int axnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     axnet_dev_t *info = PRIV(dev);
-    tuple_t tuple;
-    cisparse_t parse;
     int i, j, last_ret, last_fn;
-    u_short buf[64];
     DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "axnet_config(0x%p)\n", link);
 
-    tuple.Attributes = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-
     /* don't trust the CIS on this; Linksys got it wrong */
     link->conf.Present = 0x63;
-
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (last_ret == CS_SUCCESS) {
-       cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-       cistpl_io_t *io = &(parse.cftable_entry.io);
-       
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-               pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
-               cfg->index == 0 || cfg->io.nwin == 0)
-           goto next_entry;
-       
-       link->conf.ConfigIndex = 0x05;
-       /* For multifunction cards, by convention, we configure the
-          network function with window 0, and serial with window 1 */
-       if (io->nwin > 1) {
-           i = (io->win[1].len > io->win[0].len);
-           link->io.BasePort2 = io->win[1-i].base;
-           link->io.NumPorts2 = io->win[1-i].len;
-       } else {
-           i = link->io.NumPorts2 = 0;
-       }
-       link->io.BasePort1 = io->win[i].base;
-       link->io.NumPorts1 = io->win[i].len;
-       link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-       if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
-           last_ret = try_io_port(link);
-           if (last_ret == CS_SUCCESS) break;
-       }
-    next_entry:
-       last_ret = pcmcia_get_next_tuple(link, &tuple);
-    }
-    if (last_ret != CS_SUCCESS) {
+    last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
+    if (last_ret != 0) {
        cs_error(link, RequestIO, last_ret);
        goto failed;
     }
index ea9414c4d90000fa23ff7171b18cb84462bf6706..831090c756220fcc86743067d62eb36683517b57 100644 (file)
@@ -260,21 +260,21 @@ static int com20020_config(struct pcmcia_device *link)
     DEBUG(0, "com20020_config(0x%p)\n", link);
 
     DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
-    i = !CS_SUCCESS;
+    i = -ENODEV;
     if (!link->io.BasePort1)
     {
        for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
        {
            link->io.BasePort1 = ioaddr;
            i = pcmcia_request_io(link, &link->io);
-           if (i == CS_SUCCESS)
+           if (i == 0)
                break;
        }
     }
     else
        i = pcmcia_request_io(link, &link->io);
     
-    if (i != CS_SUCCESS)
+    if (i != 0)
     {
        DEBUG(1,"arcnet: requestIO failed totally!\n");
        goto failed;
@@ -287,7 +287,7 @@ static int com20020_config(struct pcmcia_device *link)
           link->irq.AssignedIRQ,
           link->irq.IRQInfo1, link->irq.IRQInfo2);
     i = pcmcia_request_irq(link, &link->irq);
-    if (i != CS_SUCCESS)
+    if (i != 0)
     {
        DEBUG(1,"arcnet: requestIRQ failed totally!\n");
        goto failed;
index a550c9bd126f595312e5649fec71af7599ae3b6f..69d916daa7bbb313440dbd4c2827a6779a715376 100644 (file)
@@ -309,7 +309,8 @@ static int mfc_try_io_port(struct pcmcia_device *link)
            printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
        }
        ret = pcmcia_request_io(link, &link->io);
-       if (ret == CS_SUCCESS) return ret;
+       if (ret == 0)
+               return ret;
     }
     return ret;
 }
@@ -325,7 +326,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
        link->io.BasePort1 = ioaddr;
        ret = pcmcia_request_io(link, &link->io);
-       if (ret == CS_SUCCESS) {
+       if (ret == 0) {
            /* calculate ConfigIndex value */
            link->conf.ConfigIndex = 
                ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
@@ -356,12 +357,12 @@ static int fmvj18x_config(struct pcmcia_device *link)
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_FUNCE;
     tuple.TupleOffset = 0;
-    if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, &tuple) == 0) {
        /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
        CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-       CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
+       CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
        link->conf.ConfigIndex = parse.cftable_entry.index;
        switch (link->manf_id) {
        case MANFID_TDK:
@@ -430,10 +431,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
        link->irq.Attributes =
                IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
        ret = mfc_try_io_port(link);
-       if (ret != CS_SUCCESS) goto cs_failed;
+       if (ret != 0) goto cs_failed;
     } else if (cardtype == UNGERMANN) {
        ret = ungermann_try_io_port(link);
-       if (ret != CS_SUCCESS) goto cs_failed;
+       if (ret != 0) goto cs_failed;
     } else { 
        CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
     }
@@ -565,7 +566,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link, &req, &link->win);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        cs_error(link, RequestWindow, i);
        return -1;
     }
@@ -599,7 +600,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 
     iounmap(base);
     j = pcmcia_release_window(link->win);
-    if (j != CS_SUCCESS)
+    if (j != 0)
        cs_error(link, ReleaseWindow, j);
     return (i != 0x200) ? 0 : -1;
 
@@ -620,7 +621,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link, &req, &link->win);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        cs_error(link, RequestWindow, i);
        return -1;
     }
@@ -642,7 +643,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 
     iounmap(base);
     j = pcmcia_release_window(link->win);
-    if (j != CS_SUCCESS)
+    if (j != 0)
        cs_error(link, ReleaseWindow, j);
     return 0;
 
index 4eafa4f42cff5e5a01c4f8c16ea27757dbf43650..cf3cca4642f225320d9b076a9d82510c23aae493 100644 (file)
@@ -238,7 +238,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     /* Try PRIMARY card at 0xA20-0xA23 */
     link->io.BasePort1 = 0xA20;
     i = pcmcia_request_io(link, &link->io);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
        link->io.BasePort1 = 0xA24;
        CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
index cfcbea9b7e2e374e36e45e986aac3d5d69af4681..448cd40aeba5ab37c2c913db34745ac87b2857fd 100644 (file)
@@ -69,7 +69,7 @@ Driver Notes and Issues
 History
 -------------------------------------------------------------------------------
 Log: nmclan_cs.c,v
- * 2.5.75-ac1 2003/07/11 Alan Cox <alan@redhat.com>
+ * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk>
  * Fixed hang on card eject as we probe it
  * Cleaned up to use new style locking.
  *
@@ -925,7 +925,7 @@ static void mace_tx_timeout(struct net_device *dev)
   printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
 #if RESET_ON_TIMEOUT
   printk("resetting card\n");
-  pcmcia_reset_card(link, NULL);
+  pcmcia_reset_card(link->socket);
 #else /* #if RESET_ON_TIMEOUT */
   printk("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
index ebc1ae6bcbe5fc27f7152add5064a8dde48b9f70..e40d6301aa7aaf1084b9e0cef1bfbf7588d692c3 100644 (file)
@@ -310,7 +310,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
     req.Base = 0; req.Size = 0;
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link, &req, &link->win);
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        cs_error(link, RequestWindow, i);
        return NULL;
     }
@@ -333,7 +333,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 
     iounmap(virt);
     j = pcmcia_release_window(link->win);
-    if (j != CS_SUCCESS)
+    if (j != 0)
        cs_error(link, ReleaseWindow, j);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
@@ -504,7 +504,8 @@ static int try_io_port(struct pcmcia_device *link)
            link->io.BasePort1 = j ^ 0x300;
            link->io.BasePort2 = (j ^ 0x300) + 0x10;
            ret = pcmcia_request_io(link, &link->io);
-           if (ret == CS_SUCCESS) return ret;
+           if (ret == 0)
+                   return ret;
        }
        return ret;
     } else {
@@ -512,58 +513,53 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
+static int pcnet_confcheck(struct pcmcia_device *p_dev,
+                          cistpl_cftable_entry_t *cfg,
+                          cistpl_cftable_entry_t *dflt,
+                          unsigned int vcc,
+                          void *priv_data)
+{
+       int *has_shmem = priv_data;
+       int i;
+       cistpl_io_t *io = &cfg->io;
+
+       if (cfg->index == 0 || cfg->io.nwin == 0)
+               return -EINVAL;
+
+       /* For multifunction cards, by convention, we configure the
+          network function with window 0, and serial with window 1 */
+       if (io->nwin > 1) {
+               i = (io->win[1].len > io->win[0].len);
+               p_dev->io.BasePort2 = io->win[1-i].base;
+               p_dev->io.NumPorts2 = io->win[1-i].len;
+       } else {
+               i = p_dev->io.NumPorts2 = 0;
+       }
+
+       *has_shmem = ((cfg->mem.nwin == 1) &&
+                     (cfg->mem.win[0].len >= 0x4000));
+       p_dev->io.BasePort1 = io->win[i].base;
+       p_dev->io.NumPorts1 = io->win[i].len;
+       p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+       if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+               return try_io_port(p_dev);
+
+       return 0;
+}
+
 static int pcnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    tuple_t tuple;
-    cisparse_t parse;
-    int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+    int last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
-    u_short buf[64];
     hw_info_t *local_hw_info;
     DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "pcnet_config(0x%p)\n", link);
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (last_ret == CS_SUCCESS) {
-       cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-       cistpl_io_t *io = &(parse.cftable_entry.io);
-
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                       pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
-                       cfg->index == 0 || cfg->io.nwin == 0)
-               goto next_entry;
-
-       link->conf.ConfigIndex = cfg->index;
-       /* For multifunction cards, by convention, we configure the
-          network function with window 0, and serial with window 1 */
-       if (io->nwin > 1) {
-           i = (io->win[1].len > io->win[0].len);
-           link->io.BasePort2 = io->win[1-i].base;
-           link->io.NumPorts2 = io->win[1-i].len;
-       } else {
-           i = link->io.NumPorts2 = 0;
-       }
-       has_shmem = ((cfg->mem.nwin == 1) &&
-                    (cfg->mem.win[0].len >= 0x4000));
-       link->io.BasePort1 = io->win[i].base;
-       link->io.NumPorts1 = io->win[i].len;
-       link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-       if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
-           last_ret = try_io_port(link);
-           if (last_ret == CS_SUCCESS) break;
-       }
-    next_entry:
-       last_ret = pcmcia_get_next_tuple(link, &tuple);
-    }
-    if (last_ret != CS_SUCCESS) {
+    last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
+    if (last_ret) {
        cs_error(link, RequestIO, last_ret);
        goto failed;
     }
index 250eb1954c342d7ecf3c77e7ef62978c18d6a5b8..c74d6656d2662bcf5b2d91dcea374c062404b4b1 100644 (file)
@@ -409,10 +409,13 @@ static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 {
        int i;
 
-       if ((i = pcmcia_get_first_tuple(handle, tuple)) != CS_SUCCESS ||
-                       (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS)
+       i = pcmcia_get_first_tuple(handle, tuple);
+       if (i != 0)
                return i;
-       return pcmcia_parse_tuple(handle, tuple, parse);
+       i = pcmcia_get_tuple_data(handle, tuple);
+       if (i != 0)
+               return i;
+       return pcmcia_parse_tuple(tuple, parse);
 }
 
 static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
@@ -420,10 +423,10 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
 {
        int i;
 
-       if ((i = pcmcia_get_next_tuple(handle, tuple)) != CS_SUCCESS ||
-                       (i = pcmcia_get_tuple_data(handle, tuple)) != CS_SUCCESS)
+       if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 ||
+                       (i = pcmcia_get_tuple_data(handle, tuple)) != 0)
                return i;
-       return pcmcia_parse_tuple(handle, tuple, parse);
+       return pcmcia_parse_tuple(tuple, parse);
 }
 
 /*======================================================================
@@ -459,27 +462,36 @@ static int mhz_3288_power(struct pcmcia_device *link)
     return 0;
 }
 
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cf,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
+{
+       int k;
+       p_dev->io.BasePort2 = cf->io.win[0].base;
+       for (k = 0; k < 0x400; k += 0x10) {
+               if (k & 0x80)
+                       continue;
+               p_dev->io.BasePort1 = k ^ 0x300;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
+}
+
 static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    cisparse_t *parse;
-    cistpl_cftable_entry_t *cf;
-    u_char *buf;
     win_req_t req;
     memreq_t mem;
-    int i, k;
+    int i;
 
     cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
     if (!cfg_mem)
-        return CS_OUT_OF_RESOURCE;
-
-    tuple = &cfg_mem->tuple;
-    parse = &cfg_mem->parse;
-    cf = &parse->cftable_entry;
-    buf = cfg_mem->buf;
+           return -ENOMEM;
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
@@ -489,27 +501,9 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->io.NumPorts2 = 8;
 
-    tuple->Attributes = tuple->TupleOffset = 0;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
-    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
-    i = first_tuple(link, tuple, parse);
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
-    while (i == CS_SUCCESS) {
-       link->conf.ConfigIndex = cf->index;
-       link->io.BasePort2 = cf->io.win[0].base;
-       for (k = 0; k < 0x400; k += 0x10) {
-           if (k & 0x80) continue;
-           link->io.BasePort1 = k ^ 0x300;
-           i = pcmcia_request_io(link, &link->io);
-           if (i == CS_SUCCESS) break;
-       }
-       if (i == CS_SUCCESS) break;
-       i = next_tuple(link, tuple, parse);
-    }
-    if (i != CS_SUCCESS)
+    if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
        goto free_cfg_mem;
     dev->base_addr = link->io.BasePort1;
 
@@ -518,7 +512,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     req.Base = req.Size = 0;
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link, &req, &link->win);
-    if (i != CS_SUCCESS)
+    if (i != 0)
        goto free_cfg_mem;
     smc->base = ioremap(req.Base, req.Size);
     mem.CardOffset = mem.Page = 0;
@@ -526,14 +520,14 @@ static int mhz_mfc_config(struct pcmcia_device *link)
        mem.CardOffset = link->conf.ConfigBase;
     i = pcmcia_map_mem_page(link->win, &mem);
 
-    if ((i == CS_SUCCESS)
+    if ((i == 0)
        && (smc->manfid == MANFID_MEGAHERTZ)
        && (smc->cardid == PRODID_MEGAHERTZ_EM3288))
        mhz_3288_power(link);
 
 free_cfg_mem:
     kfree(cfg_mem);
-    return i;
+    return -ENODEV;
 }
 
 static int mhz_setup(struct pcmcia_device *link)
@@ -560,12 +554,12 @@ static int mhz_setup(struct pcmcia_device *link)
     /* Read the station address from the CIS.  It is stored as the last
        (fourth) string in the Version 1 Version/ID tuple. */
     tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
+    if (first_tuple(link, tuple, parse) != 0) {
        rc = -1;
        goto free_cfg_mem;
     }
     /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    if (next_tuple(link, tuple, parse) != CS_SUCCESS)
+    if (next_tuple(link, tuple, parse) != 0)
        first_tuple(link, tuple, parse);
     if (parse->version_1.ns > 3) {
        station_addr = parse->version_1.str + parse->version_1.ofs[3];
@@ -577,11 +571,11 @@ static int mhz_setup(struct pcmcia_device *link)
 
     /* Another possibility: for the EM3288, in a special tuple */
     tuple->DesiredTuple = 0x81;
-    if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_first_tuple(link, tuple) != 0) {
        rc = -1;
        goto free_cfg_mem;
     }
-    if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) {
+    if (pcmcia_get_tuple_data(link, tuple) != 0) {
        rc = -1;
        goto free_cfg_mem;
     }
@@ -660,46 +654,27 @@ static int mot_setup(struct pcmcia_device *link)
 
 /*====================================================================*/
 
+static int smc_configcheck(struct pcmcia_device *p_dev,
+                          cistpl_cftable_entry_t *cf,
+                          cistpl_cftable_entry_t *dflt,
+                          unsigned int vcc,
+                          void *priv_data)
+{
+       p_dev->io.BasePort1 = cf->io.win[0].base;
+       p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int smc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    cisparse_t *parse;
-    cistpl_cftable_entry_t *cf;
-    u_char *buf;
     int i;
 
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-       return CS_OUT_OF_RESOURCE;
-
-    tuple = &cfg_mem->tuple;
-    parse = &cfg_mem->parse;
-    cf = &parse->cftable_entry;
-    buf = cfg_mem->buf;
-
-    tuple->Attributes = tuple->TupleOffset = 0;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
-    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
     link->io.NumPorts1 = 16;
-    i = first_tuple(link, tuple, parse);
-    while (i != CS_NO_MORE_ITEMS) {
-       if (i == CS_SUCCESS) {
-           link->conf.ConfigIndex = cf->index;
-           link->io.BasePort1 = cf->io.win[0].base;
-           link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-           i = pcmcia_request_io(link, &link->io);
-           if (i == CS_SUCCESS) break;
-       }
-       i = next_tuple(link, tuple, parse);
-    }
-    if (i == CS_SUCCESS)
-       dev->base_addr = link->io.BasePort1;
+    i = pcmcia_loop_config(link, smc_configcheck, NULL);
+    if (!i)
+           dev->base_addr = link->io.BasePort1;
 
-    kfree(cfg_mem);
     return i;
 }
 
@@ -715,7 +690,7 @@ static int smc_setup(struct pcmcia_device *link)
 
     cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
     if (!cfg_mem)
-       return CS_OUT_OF_RESOURCE;
+           return -ENOMEM;
 
     tuple = &cfg_mem->tuple;
     parse = &cfg_mem->parse;
@@ -728,12 +703,12 @@ static int smc_setup(struct pcmcia_device *link)
     /* Check for a LAN function extension tuple */
     tuple->DesiredTuple = CISTPL_FUNCE;
     i = first_tuple(link, tuple, parse);
-    while (i == CS_SUCCESS) {
+    while (i == 0) {
        if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
            break;
        i = next_tuple(link, tuple, parse);
     }
-    if (i == CS_SUCCESS) {
+    if (i == 0) {
        node_id = (cistpl_lan_node_id_t *)parse->funce.data;
        if (node_id->nb == 6) {
            for (i = 0; i < 6; i++)
@@ -780,9 +755,10 @@ static int osi_config(struct pcmcia_device *link)
     for (i = j = 0; j < 4; j++) {
        link->io.BasePort2 = com[j];
        i = pcmcia_request_io(link, &link->io);
-       if (i == CS_SUCCESS) break;
+       if (i == 0)
+               break;
     }
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        /* Fallback: turn off hard decode */
        link->conf.ConfigIndex = 0x03;
        link->io.NumPorts2 = 0;
@@ -815,13 +791,13 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
     /* Read the station address from tuple 0x90, subtuple 0x04 */
     tuple->DesiredTuple = 0x90;
     i = pcmcia_get_first_tuple(link, tuple);
-    while (i == CS_SUCCESS) {
+    while (i == 0) {
        i = pcmcia_get_tuple_data(link, tuple);
-       if ((i != CS_SUCCESS) || (buf[0] == 0x04))
+       if ((i != 0) || (buf[0] == 0x04))
            break;
        i = pcmcia_get_next_tuple(link, tuple);
     }
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        rc = -1;
        goto free_cfg_mem;
     }
@@ -959,8 +935,11 @@ static int check_sig(struct pcmcia_device *link)
 
 ======================================================================*/
 
-#define CS_EXIT_TEST(ret, svc, label) \
-if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; }
+#define CS_EXIT_TEST(ret, svc, label)  \
+if (ret != 0) {                                \
+       cs_error(link, svc, ret);       \
+       goto label;                     \
+}
 
 static int smc91c92_config(struct pcmcia_device *link)
 {
index c33a3d523566194a24dfba5289a823bd87217e1a..e1fd585e71315ea15ec07a6ed9b2e675db1df4d2 100644 (file)
@@ -377,7 +377,7 @@ first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 
        if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 &&
                        (err = pcmcia_get_tuple_data(handle, tuple)) == 0)
-               err = pcmcia_parse_tuple(handle, tuple, parse);
+               err = pcmcia_parse_tuple(tuple, parse);
        return err;
 }
 
@@ -388,7 +388,7 @@ next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
 
        if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 &&
                        (err = pcmcia_get_tuple_data(handle, tuple)) == 0)
-               err = pcmcia_parse_tuple(handle, tuple, parse);
+               err = pcmcia_parse_tuple(tuple, parse);
        return err;
 }
 
@@ -715,6 +715,47 @@ has_ce2_string(struct pcmcia_device * p_dev)
        return 0;
 }
 
+static int
+xirc2ps_config_modem(struct pcmcia_device *p_dev,
+                    cistpl_cftable_entry_t *cf,
+                    cistpl_cftable_entry_t *dflt,
+                    unsigned int vcc,
+                    void *priv_data)
+{
+       unsigned int ioaddr;
+
+       if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
+               for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+                       p_dev->io.BasePort2 = cf->io.win[0].base;
+                       p_dev->io.BasePort1 = ioaddr;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
+}
+
+static int
+xirc2ps_config_check(struct pcmcia_device *p_dev,
+                    cistpl_cftable_entry_t *cf,
+                    cistpl_cftable_entry_t *dflt,
+                    unsigned int vcc,
+                    void *priv_data)
+{
+       int *pass = priv_data;
+
+       if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
+               p_dev->io.BasePort2 = cf->io.win[0].base;
+               p_dev->io.BasePort1 = p_dev->io.BasePort2
+                       + (*pass ? (cf->index & 0x20 ? -24:8)
+                          : (cf->index & 0x20 ?   8:-24));
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
+
+}
+
 /****************
  * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
  * is received, to configure the PCMCIA socket, and to make the
@@ -725,13 +766,12 @@ xirc2ps_config(struct pcmcia_device * link)
 {
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
+    unsigned int ioaddr;
     tuple_t tuple;
     cisparse_t parse;
-    unsigned int ioaddr;
     int err, i;
     u_char buf[64];
     cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     DECLARE_MAC_BUF(mac);
 
     local->dingo_ccr = NULL;
@@ -846,19 +886,8 @@ xirc2ps_config(struct pcmcia_device * link)
            /* Take the Modem IO port from the CIS and scan for a free
             * Ethernet port */
            link->io.NumPorts1 = 16; /* no Mako stuff anymore */
-           tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-           for (err = first_tuple(link, &tuple, &parse); !err;
-                                err = next_tuple(link, &tuple, &parse)) {
-               if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
-                   for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-                       link->conf.ConfigIndex = cf->index ;
-                       link->io.BasePort2 = cf->io.win[0].base;
-                       link->io.BasePort1 = ioaddr;
-                       if (!(err=pcmcia_request_io(link, &link->io)))
-                           goto port_found;
-                   }
-               }
-           }
+           if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
+                   goto port_found;
        } else {
            link->io.NumPorts1 = 18;
            /* We do 2 passes here: The first one uses the regular mapping and
@@ -866,21 +895,9 @@ xirc2ps_config(struct pcmcia_device * link)
             * mirrored every 32 bytes. Actually we use a mirrored port for
             * the Mako if (on the first pass) the COR bit 5 is set.
             */
-           for (pass=0; pass < 2; pass++) {
-               tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-               for (err = first_tuple(link, &tuple, &parse); !err;
-                                    err = next_tuple(link, &tuple, &parse)){
-                   if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8){
-                       link->conf.ConfigIndex = cf->index ;
-                       link->io.BasePort2 = cf->io.win[0].base;
-                       link->io.BasePort1 = link->io.BasePort2
-                                   + (pass ? (cf->index & 0x20 ? -24:8)
-                                           : (cf->index & 0x20 ?   8:-24));
-                       if (!(err=pcmcia_request_io(link, &link->io)))
+           for (pass=0; pass < 2; pass++)
+                   if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
                            goto port_found;
-                   }
-               }
-           }
            /* if special option:
             * try to configure as Ethernet only.
             * .... */
index 6671e2da0d572c07e09bdaffaf12f3d5da9af48b..d0ed1ef284a80404510e8f169537f40e4cb678a3 100644 (file)
@@ -55,6 +55,7 @@ EXPORT_SYMBOL(mdiobus_alloc);
 
 /**
  * mdiobus_release - mii_bus device release callback
+ * @d: the target struct device that contains the mii_bus
  *
  * Description: called when the last reference to an mii_bus is
  * dropped, to free the underlying memory.
index 17162748005893a86ca206faf95c5ec194be5eb5..e11b03b2b25a776c2494951953feeb44777d2f84 100644 (file)
@@ -309,11 +309,6 @@ void phy_disconnect(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_disconnect);
 
-static int phy_compare_id(struct device *dev, void *data)
-{
-       return strcmp((char *)data, dev->bus_id) ? 0 : 1;
-}
-
 /**
  * phy_attach - attach a network device to a particular PHY device
  * @dev: network device to attach
@@ -337,8 +332,7 @@ struct phy_device *phy_attach(struct net_device *dev,
 
        /* Search the list of PHY devices on the mdio bus for the
         * PHY with the requested name */
-       d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
-
+       d = bus_find_device_by_name(bus, NULL, bus_id);
        if (d) {
                phydev = to_phy_device(d);
        } else {
@@ -557,6 +551,7 @@ int genphy_restart_aneg(struct phy_device *phydev)
 
        return ctl;
 }
+EXPORT_SYMBOL(genphy_restart_aneg);
 
 
 /**
index 0ca0fcbb7c01f5dcb1f840dd31ca24d1696a83e6..7e857e938adb582ae432b26d35114e8099d51eb2 100644 (file)
@@ -866,8 +866,8 @@ static int __init ppp_init(void)
                        err = PTR_ERR(ppp_class);
                        goto out_chrdev;
                }
-               device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
-                                     NULL, "ppp");
+               device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
+                             "ppp");
        }
 
 out:
@@ -2127,13 +2127,9 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg)
            || ccp_option[1] < 2 || ccp_option[1] > data.length)
                goto out;
 
-       cp = find_compressor(ccp_option[0]);
-#ifdef CONFIG_KMOD
-       if (!cp) {
-               request_module("ppp-compress-%d", ccp_option[0]);
-               cp = find_compressor(ccp_option[0]);
-       }
-#endif /* CONFIG_KMOD */
+       cp = try_then_request_module(
+               find_compressor(ccp_option[0]),
+               "ppp-compress-%d", ccp_option[0]);
        if (!cp)
                goto out;
 
index c6898c1fc54d95de595fa990fc7b0977149c796a..03aecc97fb453d32eefb596dddba3f6286d909df 100644 (file)
@@ -115,13 +115,8 @@ static int pppox_create(struct net *net, struct socket *sock, int protocol)
                goto out;
 
        rc = -EPROTONOSUPPORT;
-#ifdef CONFIG_KMOD
-       if (!pppox_protos[protocol]) {
-               char buffer[32];
-               sprintf(buffer, "pppox-proto-%d", protocol);
-               request_module(buffer);
-       }
-#endif
+       if (!pppox_protos[protocol])
+               request_module("pppox-proto-%d", protocol);
        if (!pppox_protos[protocol] ||
            !try_module_get(pppox_protos[protocol]->owner))
                goto out;
index c37ea436c9189adebf24bb579ba68e0659eae184..38116f9d41635c7cc23ad13a4e6b618b59cf5b06 100644 (file)
@@ -58,7 +58,7 @@
  */
 #if (PAGE_SHIFT == 12) || (PAGE_SHIFT == 13)   /* 4k & 8k pages */
 #define TX_DESC_PER_OAL ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2)
-#elif (PAGE_SHIFT == 16)       /* 64k pages */
+#else /* all other page sizes */
 #define TX_DESC_PER_OAL 0
 #endif
 
index 6457f8c4fdaaff10e3e5e0781331cd961fbd77d6..b62fbd4bf00f5821fd2e2c81b9e2b5b76eb792b4 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
index 3af822b6226ec822dc385b7956c25c100170170a..4b2caa6b7ac5eba5a01d2cc9c3ddbe0611e3a573 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_vlan.h>
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <net/ip6_checksum.h>
 
 #include "qlge.h"
 
index bdae2c59a7509020e7759e097935c420b762b324..c821da21d8ebe95cb48eedf70a466de2953ec7ec 100644 (file)
@@ -2154,6 +2154,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        spin_lock_init(&tp->lock);
 
+       tp->mmio_addr = ioaddr;
+
        rtl_init_mac_address(tp, ioaddr);
 
        /* Get MAC address */
@@ -2186,7 +2188,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif
 
        tp->intr_mask = 0xffff;
-       tp->mmio_addr = ioaddr;
        tp->align = cfg->align;
        tp->hw_start = cfg->hw_start;
        tp->intr_event = cfg->intr_event;
index 3805b9318be725c8292bd86bc962a15ffe1b8486..3813d15e2df75d613392bf20f5e134f358cd26ed 100644 (file)
@@ -3034,7 +3034,8 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
 
-       if (wol->wolopts & ~sky2_wol_supported(sky2->hw))
+       if ((wol->wolopts & ~sky2_wol_supported(sky2->hw))
+           || !device_can_wakeup(&hw->pdev->dev))
                return -EOPNOTSUPP;
 
        sky2->wol = wol->wolopts;
@@ -3045,6 +3046,8 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
                sky2_write32(hw, B0_CTST, sky2->wol
                             ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
 
+       device_set_wakeup_enable(&hw->pdev->dev, sky2->wol);
+
        if (!netif_running(dev))
                sky2_wol_init(sky2);
        return 0;
@@ -4179,18 +4182,6 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
        return err;
 }
 
-static int __devinit pci_wake_enabled(struct pci_dev *dev)
-{
-       int pm  = pci_find_capability(dev, PCI_CAP_ID_PM);
-       u16 value;
-
-       if (!pm)
-               return 0;
-       if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value))
-               return 0;
-       return value & PCI_PM_CTRL_PME_ENABLE;
-}
-
 /*
  * Read and parse the first part of Vital Product Data
  */
@@ -4314,7 +4305,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                }
        }
 
-       wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0;
+       wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0;
 
        err = -ENOMEM;
        hw = kzalloc(sizeof(*hw), GFP_KERNEL);
index 3d19d00e8eecf1c1af4110b3fd1e1bf6e8327d8b..8aa7460ef0e305733ff83cb1d655108861afd4be 100644 (file)
@@ -685,8 +685,10 @@ static void smc911x_phy_detect(struct net_device *dev)
         * PHY#1 to PHY#31, and then PHY#0 last.
         */
        switch(lp->version) {
-               case 0x115:
-               case 0x117:
+               case CHIP_9115:
+               case CHIP_9117:
+               case CHIP_9215:
+               case CHIP_9217:
                        cfg = SMC_GET_HW_CFG(lp);
                        if (cfg & HW_CFG_EXT_PHY_DET_) {
                                cfg &= ~HW_CFG_PHY_CLK_SEL_;
index 2abfc284519829ee05856b26b80c0ce45f2e27b5..bf6240f23f5d77109919057cb213c06167963267 100644 (file)
@@ -666,10 +666,13 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr,
 #define LAN911X_INTERNAL_PHY_ID                (0x0007C000)
 
 /* Chip ID values */
-#define CHIP_9115      0x115
-#define CHIP_9116      0x116
-#define CHIP_9117      0x117
-#define CHIP_9118      0x118
+#define CHIP_9115      0x0115
+#define CHIP_9116      0x0116
+#define CHIP_9117      0x0117
+#define CHIP_9118      0x0118
+#define CHIP_9215      0x115A
+#define CHIP_9217      0x117A
+#define CHIP_9218      0x118A
 
 struct chip_id {
        u16 id;
@@ -681,6 +684,9 @@ static const struct chip_id chip_ids[] =  {
        { CHIP_9116, "LAN9116" },
        { CHIP_9117, "LAN9117" },
        { CHIP_9118, "LAN9118" },
+       { CHIP_9215, "LAN9215" },
+       { CHIP_9217, "LAN9217" },
+       { CHIP_9218, "LAN9218" },
        { 0, NULL },
 };
 
index 4980b12b62198e80911ca16c52153870be1c4a1a..df20cafff7dd3a5da1926740e5cb14193f5b81f9 100644 (file)
@@ -796,7 +796,7 @@ err_out_unregister_bus:
        mdiobus_unregister(lp->mii_bus);
 err_out_free_mdio_irq:
        kfree(lp->mii_bus->irq);
-err_out_free_mii_bus;
+err_out_free_mii_bus:
        mdiobus_free(lp->mii_bus);
 err_out:
        return err;
index ec871f646766dc7294101fe5ad7f789b66d3f0bb..c41d68761364550ebe2d2d8376f2a8c293b5d799 100644 (file)
@@ -29,7 +29,8 @@
  *
  *     Tigran Aivazian <tigran@sco.com>:       TLan_PciProbe() now uses
  *                                             new PCI BIOS interface.
- *     Alan Cox        <alan@redhat.com>:      Fixed the out of memory
+ *     Alan Cox        <alan@lxorguk.ukuu.org.uk>:
+ *                                             Fixed the out of memory
  *                                             handling.
  *
  *     Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
index fa73e6eed6be52ed1c9f7972f70e26a05112ad59..ed50d288e4940a79bdefca127a6c92d5713ab45d 100644 (file)
@@ -25,7 +25,7 @@
  *  To do:
  *    1. Multicast support.
  *
- *  Initial 2.5 cleanup Alan Cox <alan@redhat.com>  2002/10/28
+ *  Initial 2.5 cleanup Alan Cox <alan@lxorguk.ukuu.org.uk>  2002/10/28
  */
 
 #include <linux/module.h>
index f54c45049d50d86c700e3f18a5c2525321a662c9..124d5d690dde2508a29b8d5ae7bd907bcd259c38 100644 (file)
@@ -1688,6 +1688,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
        unsigned i;
 
        dw32 (ROMCmd, 0);       /* Reset the pointer with a dummy write. */
+       udelay(5);
 
        for (i = 0; i < 6; i++) {
                int value, boguscnt = 100000;
index 656200472fa17aa3e5e8e5d592c4fc2fa1ff2077..8e46a513a252a8fecf48629e064a6f220bc7c100 100644 (file)
@@ -23,7 +23,7 @@
     Marcelo Tosatti <marcelo@conectiva.com.br> :
     Made it compile in 2.3 (device to net_device)
 
-    Alan Cox <alan@redhat.com> :
+    Alan Cox <alan@lxorguk.ukuu.org.uk> :
     Cleaned up for kernel merge.
     Removed the back compatibility support
     Reformatted, fixing spelling etc as I went
@@ -49,7 +49,7 @@
     support.  Updated PCI resource allocation.  Do not
     forget to unmap PCI mapped skbs.
 
-    Alan Cox <alan@redhat.com>
+    Alan Cox <alan@lxorguk.ukuu.org.uk>
     Added new PCI identifiers provided by Clear Zhang at ALi
     for their 1563 ethernet device.
 
index ad20f96edfa11e5d597881b49795c7967ee7e2a4..2dced383bcfb8a3f93ef4cfc69569f40105cdba5 100644 (file)
@@ -12,7 +12,7 @@
  *     Scatter gather
  *     More testing
  *
- * The changes are (c) Copyright 2004, Red Hat Inc. <alan@redhat.com>
+ * The changes are (c) Copyright 2004, Red Hat Inc. <alan@lxorguk.ukuu.org.uk>
  * Additional fixes and clean up: Francois Romieu
  *
  * This source has not been verified for use in safety critical systems.
index 2ae2ec40015d9cb33faa34defcbe220698196729..21efd99b9294bac7a17ce21763f4074e65596ef1 100644 (file)
@@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE
 
 config PC300
        tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
-       depends on HDLC && PCI
+       depends on HDLC && PCI && BROKEN
        ---help---
          Driver for the Cyclades-PC300 synchronous communication boards.
 
index f14051556c87d08098108f2f695a5bc2c6d35f5a..7f97f8d08c39eeba79eaa4da5cdfc5368d59487d 100644 (file)
@@ -388,8 +388,8 @@ static int __init cosa_init(void)
                goto out_chrdev;
        }
        for (i = 0; i < nr_cards; i++)
-               device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
-                                     NULL, "cosa%d", i);
+               device_create(cosa_class, NULL, MKDEV(cosa_major, i), NULL,
+                             "cosa%d", i);
        err = 0;
        goto out;
 
index f80640f5a744f382ff14355caa60011199c74f93..d7bb63e616b5e41f9ca72f2c52fa583dddcff113 100644 (file)
@@ -122,7 +122,6 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
      * Most functions mess with the structure
      * Disable interrupts while we do the polling
      */
-    spin_lock_irqsave(&sc->lmc_lock, flags);
 
     switch (cmd) {
         /*
@@ -152,6 +151,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                break;
        }
 
+       spin_lock_irqsave(&sc->lmc_lock, flags);
         sc->lmc_media->set_status (sc, &ctl);
 
         if(ctl.crc_length != sc->ictl.crc_length) {
@@ -161,6 +161,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
            else
                sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE;
         }
+       spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
         ret = 0;
         break;
@@ -187,15 +188,18 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                break;                          /* no change */
             }
             
+           spin_lock_irqsave(&sc->lmc_lock, flags);
             lmc_proto_close(sc);
 
             sc->if_type = new_type;
             lmc_proto_attach(sc);
            ret = lmc_proto_open(sc);
+           spin_unlock_irqrestore(&sc->lmc_lock, flags);
            break;
        }
 
     case LMCIOCGETXINFO: /*fold01*/
+       spin_lock_irqsave(&sc->lmc_lock, flags);
         sc->lmc_xinfo.Magic0 = 0xBEEFCAFE;
 
         sc->lmc_xinfo.PciCardType = sc->lmc_cardtype;
@@ -208,6 +212,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
         sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ;
         sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc);
         sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16);
+       spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
         sc->lmc_xinfo.Magic1 = 0xDEADBEEF;
 
@@ -220,6 +225,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
         break;
 
     case LMCIOCGETLMCSTATS:
+           spin_lock_irqsave(&sc->lmc_lock, flags);
            if (sc->lmc_cardtype == LMC_CARDTYPE_T1) {
                    lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_LSB);
                    sc->extra_stats.framingBitErrorCount +=
@@ -243,6 +249,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                    sc->extra_stats.severelyErroredFrameCount +=
                            regVal & T1FRAMER_SEF_MASK;
            }
+           spin_unlock_irqrestore(&sc->lmc_lock, flags);
            if (copy_to_user(ifr->ifr_data, &sc->lmc_device->stats,
                             sizeof(sc->lmc_device->stats)) ||
                copy_to_user(ifr->ifr_data + sizeof(sc->lmc_device->stats),
@@ -258,12 +265,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                    break;
            }
 
+           spin_lock_irqsave(&sc->lmc_lock, flags);
            memset(&sc->lmc_device->stats, 0, sizeof(sc->lmc_device->stats));
            memset(&sc->extra_stats, 0, sizeof(sc->extra_stats));
            sc->extra_stats.check = STATCHECK;
            sc->extra_stats.version_size = (DRIVER_VERSION << 16) +
                    sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats);
            sc->extra_stats.lmc_cardtype = sc->lmc_cardtype;
+           spin_unlock_irqrestore(&sc->lmc_lock, flags);
            ret = 0;
            break;
 
@@ -282,8 +291,10 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                ret = -EFAULT;
                break;
        }
+       spin_lock_irqsave(&sc->lmc_lock, flags);
         sc->lmc_media->set_circuit_type(sc, ctl.circuit_type);
         sc->ictl.circuit_type = ctl.circuit_type;
+       spin_unlock_irqrestore(&sc->lmc_lock, flags);
         ret = 0;
 
         break;
@@ -294,12 +305,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
             break;
         }
 
+       spin_lock_irqsave(&sc->lmc_lock, flags);
         /* Reset driver and bring back to current state */
         printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
         lmc_running_reset (dev);
         printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16));
 
         LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16));
+       spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
         ret = 0;
         break;
@@ -338,14 +351,15 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
              */
             netif_stop_queue(dev);
 
-       if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) {
+           if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) {
                ret = -EFAULT;
                break;
-       }
+           }
             switch(xc.command){
             case lmc_xilinx_reset: /*fold02*/
                 {
                     u16 mii;
+                   spin_lock_irqsave(&sc->lmc_lock, flags);
                     mii = lmc_mii_readreg (sc, 0, 16);
 
                     /*
@@ -404,6 +418,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                             lmc_led_off(sc, LMC_DS3_LED2);
                         }
                     }
+                   spin_unlock_irqrestore(&sc->lmc_lock, flags);
                     
                     
 
@@ -416,6 +431,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                 {
                     u16 mii;
                     int timeout = 500000;
+                   spin_lock_irqsave(&sc->lmc_lock, flags);
                     mii = lmc_mii_readreg (sc, 0, 16);
 
                     /*
@@ -451,13 +467,14 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                      */
                     while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
                            (timeout-- > 0))
-                        ;
+                        cpu_relax();
 
 
                     /*
                      * stop driving Xilinx-related signals
                      */
                     lmc_gpio_mkinput(sc, 0xff);
+                   spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
                     ret = 0x0;
                     
@@ -493,6 +510,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
 
                     printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data);
 
+                   spin_lock_irqsave(&sc->lmc_lock, flags);
                     lmc_gpio_mkinput(sc, 0xff);
 
                     /*
@@ -545,7 +563,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
                      */
                     while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 &&
                            (timeout-- > 0))
-                        ;
+                        cpu_relax();
 
                     printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout);
 
@@ -588,6 +606,7 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
 
                     sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET;
                     lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16);
+                   spin_unlock_irqrestore(&sc->lmc_lock, flags);
 
                     kfree(data);
                     
@@ -611,8 +630,6 @@ int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
         break;
     }
 
-    spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/
-
     lmc_trace(dev, "lmc_ioctl out");
 
     return ret;
index 243bd8d918fedfdf350fce7e0a1a3c0be8451b7d..ccd9cd35ecbe9e7f82ca370739415add9e4026b3 100644 (file)
@@ -18,7 +18,8 @@
  *     DMA now uses get_free_page as kmalloc buffers may span a 64K 
  *     boundary.
  *
- *     Modified for SMP safety and SMP locking by Alan Cox <alan@redhat.com>
+ *     Modified for SMP safety and SMP locking by Alan Cox
+ *                                     <alan@lxorguk.ukuu.org.uk>
  *
  *     Performance
  *
index 4f372396c5121a29a06b970d8ac865f2ed996556..85b3e785d484f31e942d5d5a47a349f02a3a0b22 100644 (file)
@@ -2,7 +2,7 @@
  *     Description of Z8530 Z85C30 and Z85230 communications chips
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ * Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
  */
 
 #ifndef _Z8530_H
index fd72e427cb2830183b729fbae965ee88b5003da2..27696c20f4c2cf4d8fd10a8abaa41d843fd0974e 100644 (file)
@@ -206,126 +206,123 @@ static void airo_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int airo_cs_config_check(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cfg,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
+{
+       win_req_t *req = priv_data;
+
+       if (cfg->index == 0)
+               return -ENODEV;
+
+       /* Does this card need audio output? */
+       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+               p_dev->conf.Status = CCSR_AUDIO_ENA;
+       }
+
+       /* Use power settings for Vcc and Vpp if present */
+       /*  Note that the CIS values need to be rescaled */
+       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+       /* Do we need to allocate an interrupt? */
+       if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+       /* IO window settings */
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+       }
+
+       /* This reserves IO space but doesn't actually enable it */
+       if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+               return -ENODEV;
+
+       /*
+         Now set up a common memory window, if needed.  There is room
+         in the struct pcmcia_device structure for one memory window handle,
+         but if the base addresses need to be saved, or if multiple
+         windows are needed, the info should go in the private data
+         structure for this device.
+
+         Note that the memory window base is a physical address, and
+         needs to be mapped to virtual space with ioremap() before it
+         is used.
+       */
+       if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+               cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+               memreq_t map;
+               req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+               req->Base = mem->win[0].host_addr;
+               req->Size = mem->win[0].len;
+               req->AccessSpeed = 0;
+               if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0)
+                       return -ENODEV;
+               map.Page = 0;
+               map.CardOffset = mem->win[0].card_addr;
+               if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+                       return -ENODEV;
+       }
+       /* If we got this far, we're cool! */
+       return 0;
+}
+
+
 static int airo_config(struct pcmcia_device *link)
 {
-       tuple_t tuple;
-       cisparse_t parse;
        local_info_t *dev;
+       win_req_t *req;
        int last_fn, last_ret;
-       u_char buf[64];
-       win_req_t req;
-       memreq_t map;
 
        dev = link->priv;
 
        DEBUG(0, "airo_config(0x%p)\n", link);
 
+       req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       /*
+        * In this loop, we scan the CIS for configuration table
+        * entries, each of which describes a valid card
+        * configuration, including voltage, IO window, memory window,
+        * and interrupt settings.
+        *
+        * We make no assumptions about the card to be configured: we
+        * use just the information available in the CIS.  In an ideal
+        * world, this would work for any PCMCIA card, but it requires
+        * a complete and accurate CIS.  In practice, a driver usually
+        * "knows" most of these things without consulting the CIS,
+        * and most client drivers will only use the CIS to fill in
+        * implementation-defined details.
+        */
+       last_ret = pcmcia_loop_config(link, airo_cs_config_check, req);
+       if (last_ret)
+               goto failed;
+
        /*
-         In this loop, we scan the CIS for configuration table entries,
-         each of which describes a valid card configuration, including
-         voltage, IO window, memory window, and interrupt settings.
-         
-         We make no assumptions about the card to be configured: we use
-         just the information available in the CIS.  In an ideal world,
-         this would work for any PCMCIA card, but it requires a complete
-         and accurate CIS.  In practice, a driver usually "knows" most of
-         these things without consulting the CIS, and most client drivers
-         will only use the CIS to fill in implementation-defined details.
+         Allocate an interrupt line.  Note that this does not assign a
+         handler to the interrupt, unless the 'Handler' member of the
+         irq structure is initialized.
        */
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t dflt = { 0 };
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
-               
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-               if (cfg->index == 0) goto next_entry;
-               link->conf.ConfigIndex = cfg->index;
-               
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
-               
-               /* Use power settings for Vcc and Vpp if present */
-               /*  Note that the CIS values need to be rescaled */
-               if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-               else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-               
-               /* Do we need to allocate an interrupt? */
-               if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-               
-               /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-                       if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin > 1) {
-                               link->io.Attributes2 = link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-               }
-               
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(link, &link->io) != 0)
-                       goto next_entry;
-               
-               /*
-                 Now set up a common memory window, if needed.  There is room
-                 in the struct pcmcia_device structure for one memory window handle,
-                 but if the base addresses need to be saved, or if multiple
-                 windows are needed, the info should go in the private data
-                 structure for this device.
-                 
-                 Note that the memory window base is a physical address, and
-                 needs to be mapped to virtual space with ioremap() before it
-                 is used.
-               */
-               if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
-                       cistpl_mem_t *mem =
-                               (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
-                       req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-                       req.Base = mem->win[0].host_addr;
-                       req.Size = mem->win[0].len;
-                       req.AccessSpeed = 0;
-                       if (pcmcia_request_window(&link, &req, &link->win) != 0)
-                               goto next_entry;
-                       map.Page = 0; map.CardOffset = mem->win[0].card_addr;
-                       if (pcmcia_map_mem_page(link->win, &map) != 0)
-                               goto next_entry;
-               }
-               /* If we got this far, we're cool! */
-               break;
-               
-       next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-       }
-       
-    /*
-      Allocate an interrupt line.  Note that this does not assign a
-      handler to the interrupt, unless the 'Handler' member of the
-      irq structure is initialized.
-    */
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
        
@@ -362,14 +359,17 @@ static int airo_config(struct pcmcia_device *link)
                printk(" & 0x%04x-0x%04x", link->io.BasePort2,
                       link->io.BasePort2+link->io.NumPorts2-1);
        if (link->win)
-               printk(", mem 0x%06lx-0x%06lx", req.Base,
-                      req.Base+req.Size-1);
+               printk(", mem 0x%06lx-0x%06lx", req->Base,
+                      req->Base+req->Size-1);
        printk("\n");
+       kfree(req);
        return 0;
 
  cs_failed:
        cs_error(link, last_fn, last_ret);
+ failed:
        airo_release(link);
+       kfree(req);
        return -ENODEV;
 } /* airo_config */
 
index 74726990d59e0ae1851fe0d587032f355dabecbf..f05f584ab7bc960f9e8ba5ea29207ec63582bd2c 100644 (file)
@@ -1640,6 +1640,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
        return ret;
 }
 
+static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value)
+{
+       return -EOPNOTSUPP;
+}
+
 static struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -1664,7 +1669,8 @@ static struct ieee80211_ops ath9k_ops = {
        .get_tsf            = ath9k_get_tsf,
        .reset_tsf          = ath9k_reset_tsf,
        .tx_last_beacon     = NULL,
-       .ampdu_action       = ath9k_ampdu_action
+       .ampdu_action       = ath9k_ampdu_action,
+       .set_frag_threshold = ath9k_no_fragmentation,
 };
 
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
index d2388e8d179a440dce544ec598d857cc3e8b5b5f..77406245dc7b8fb171f82802bd8d4e494747f20e 100644 (file)
@@ -224,13 +224,58 @@ static int card_present(void *arg)
        return 0;
 }
 
+static int atmel_config_check(struct pcmcia_device *p_dev,
+                             cistpl_cftable_entry_t *cfg,
+                             cistpl_cftable_entry_t *dflt,
+                             unsigned int vcc,
+                             void *priv_data)
+{
+       if (cfg->index == 0)
+               return -ENODEV;
+
+       /* Does this card need audio output? */
+       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+               p_dev->conf.Status = CCSR_AUDIO_ENA;
+       }
+
+       /* Use power settings for Vcc and Vpp if present */
+       /*  Note that the CIS values need to be rescaled */
+       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+       /* Do we need to allocate an interrupt? */
+       if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+       /* IO window settings */
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+       }
+
+       /* This reserves IO space but doesn't actually enable it */
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int atmel_config(struct pcmcia_device *link)
 {
-       tuple_t tuple;
-       cisparse_t parse;
        local_info_t *dev;
        int last_fn, last_ret;
-       u_char buf[64];
        struct pcmcia_device_id *did;
 
        dev = link->priv;
@@ -238,11 +283,6 @@ static int atmel_config(struct pcmcia_device *link)
 
        DEBUG(0, "atmel_config(0x%p)\n", link);
 
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-
        /*
          In this loop, we scan the CIS for configuration table entries,
          each of which describes a valid card configuration, including
@@ -255,66 +295,8 @@ static int atmel_config(struct pcmcia_device *link)
          these things without consulting the CIS, and most client drivers
          will only use the CIS to fill in implementation-defined details.
        */
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t dflt = { 0 };
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
-
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-               if (cfg->index == 0) goto next_entry;
-               link->conf.ConfigIndex = cfg->index;
-
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
-
-               /* Use power settings for Vcc and Vpp if present */
-               /*  Note that the CIS values need to be rescaled */
-               if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-               else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-               /* Do we need to allocate an interrupt? */
-               if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-               /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-                       if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin > 1) {
-                               link->io.Attributes2 = link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-               }
-
-               /* This reserves IO space but doesn't actually enable it */
-               if (pcmcia_request_io(link, &link->io) != 0)
-                       goto next_entry;
-
-               /* If we got this far, we're cool! */
-               break;
-
-       next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-       }
+       if (pcmcia_loop_config(link, atmel_config_check, NULL))
+               goto failed;
 
        /*
          Allocate an interrupt line.  Note that this does not assign a
@@ -360,6 +342,7 @@ static int atmel_config(struct pcmcia_device *link)
 
  cs_failed:
        cs_error(link, last_fn, last_ret);
+ failed:
        atmel_release(link);
        return -ENODEV;
 }
index b8aa16307f79135c89d23268926b64c3468355cc..3cfc30307a27d33f48ed8bbffc3e2da13a2cc686 100644 (file)
@@ -82,13 +82,13 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
        tuple.TupleOffset = 0;
 
        res = pcmcia_get_first_tuple(dev, &tuple);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_kfree_ssb;
        res = pcmcia_get_tuple_data(dev, &tuple);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_kfree_ssb;
-       res = pcmcia_parse_tuple(dev, &tuple, &parse);
-       if (res != CS_SUCCESS)
+       res = pcmcia_parse_tuple(&tuple, &parse);
+       if (res != 0)
                goto err_kfree_ssb;
 
        dev->conf.ConfigBase = parse.config.base;
@@ -107,13 +107,13 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
        win.Size = SSB_CORE_SIZE;
        win.AccessSpeed = 250;
        res = pcmcia_request_window(&dev, &win, &dev->win);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_kfree_ssb;
 
        mem.CardOffset = 0;
        mem.Page = 0;
        res = pcmcia_map_mem_page(dev->win, &mem);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_disable;
 
        dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
@@ -121,11 +121,11 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
        dev->irq.Handler = NULL; /* The handler is registered later. */
        dev->irq.Instance = NULL;
        res = pcmcia_request_irq(dev, &dev->irq);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_disable;
 
        res = pcmcia_request_configuration(dev, &dev->conf);
-       if (res != CS_SUCCESS)
+       if (res != 0)
                goto err_disable;
 
        err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
index 3b4e55cf33cd4a071b57a35144b4a3aa3b6883af..633740277352314f16ff1b995747be09d072bdb4 100644 (file)
@@ -234,7 +234,7 @@ static void sandisk_set_iobase(local_info_t *local)
        reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
                       " res=%d\n", res);
        }
@@ -246,7 +246,7 @@ static void sandisk_set_iobase(local_info_t *local)
        reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
                       " res=%d\n", res);
        }
@@ -305,7 +305,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
        tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
        if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
            pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
-           pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
+           pcmcia_parse_tuple(&tuple, parse) ||
                parse->longlink_mfc.nfn < 2) {
                /* No multi-function links found */
                ret = -ENODEV;
@@ -322,7 +322,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
        reg.Value = COR_SOFT_RESET;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
                       dev->name, res);
                goto done;
@@ -339,7 +339,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
        reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
                       dev->name, res);
                goto done;
@@ -374,7 +374,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
        reg.Value = 0;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
                       res);
                return;
@@ -386,7 +386,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
        reg.Value |= COR_SOFT_RESET;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
                       res);
                return;
@@ -399,7 +399,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
                reg.Value |= COR_IREQ_ENA;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
                       res);
                return;
@@ -433,7 +433,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Value = 0;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
                       "(%d)\n", res);
                return;
@@ -446,7 +446,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Value |= COR_SOFT_RESET;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
                       "(%d)\n", res);
                return;
@@ -460,7 +460,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Offset = CISREG_CCSR;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
                       "(%d)\n", res);
                return;
@@ -472,7 +472,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
        reg.Value = old_cor & ~COR_SOFT_RESET;
        res = pcmcia_access_configuration_register(hw_priv->link,
                                                   &reg);
-       if (res != CS_SUCCESS) {
+       if (res != 0) {
                printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
                       "(%d)\n", res);
                return;
@@ -532,145 +532,118 @@ static void prism2_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-#define CFG_CHECK2(fn, retf) \
-do { int _ret = (retf); \
-if (_ret != 0) { \
-       PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \
-       cs_error(link, fn, _ret); \
-       goto next_entry; \
-} \
-} while (0)
-
 
 /* run after a CARD_INSERTION event is received to configure the PCMCIA
  * socket and make the device available to the system */
+
+static int prism2_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cfg,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
+{
+       if (cfg->index == 0)
+               return -ENODEV;
+
+       PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
+              "(default 0x%02X)\n", cfg->index, dflt->index);
+
+       /* Does this card need audio output? */
+       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+               p_dev->conf.Status = CCSR_AUDIO_ENA;
+       }
+
+       /* Use power settings for Vcc and Vpp if present */
+       /*  Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
+                   10000 && !ignore_cis_vcc) {
+                       PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping"
+                              " this entry\n");
+                       return -ENODEV;
+               }
+       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
+                   10000 && !ignore_cis_vcc) {
+                       PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch "
+                              "- skipping this entry\n");
+                       return -ENODEV;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       /* Do we need to allocate an interrupt? */
+       if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+       else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) {
+               /* At least Compaq WL200 does not have IRQInfo1 set,
+                * but it does not work without interrupts.. */
+               printk(KERN_WARNING "Config has no IRQ info, but trying to "
+                      "enable IRQ anyway..\n");
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+       }
+
+       /* IO window settings */
+       PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
+              "dflt->io.nwin=%d\n",
+              cfg->io.nwin, dflt->io.nwin);
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
+                      "io.base=0x%04x, len=%d\n", io->flags,
+                      io->win[0].base, io->win[0].len);
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.IOAddrLines = io->flags &
+                       CISTPL_IO_LINES_MASK;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+       }
+
+       /* This reserves IO space but doesn't actually enable it */
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int prism2_config(struct pcmcia_device *link)
 {
        struct net_device *dev;
        struct hostap_interface *iface;
        local_info_t *local;
        int ret = 1;
-       tuple_t tuple;
-       cisparse_t *parse;
        int last_fn, last_ret;
-       u_char buf[64];
-       config_info_t conf;
-       cistpl_cftable_entry_t dflt = { 0 };
        struct hostap_cs_priv *hw_priv;
 
        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
-       parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
        hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
-       if (parse == NULL || hw_priv == NULL) {
+       if (hw_priv == NULL) {
                ret = -ENOMEM;
                goto failed;
        }
 
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-
-       CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(link, &conf));
-
        /* Look for an appropriate configuration table entry in the CIS */
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       for (;;) {
-               cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
-               CFG_CHECK2(GetTupleData,
-                          pcmcia_get_tuple_data(link, &tuple));
-               CFG_CHECK2(ParseTuple,
-                          pcmcia_parse_tuple(link, &tuple, parse));
-
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-                       dflt = *cfg;
-               if (cfg->index == 0)
-                       goto next_entry;
-               link->conf.ConfigIndex = cfg->index;
-               PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
-                      "(default 0x%02X)\n", cfg->index, dflt.index);
-
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
-
-               /* Use power settings for Vcc and Vpp if present */
-               /*  Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
-                           10000 && !ignore_cis_vcc) {
-                               PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping"
-                                      " this entry\n");
-                               goto next_entry;
-                       }
-               } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
-                           10000 && !ignore_cis_vcc) {
-                               PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch "
-                                      "- skipping this entry\n");
-                               goto next_entry;
-                       }
-               }
-
-               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-               /* Do we need to allocate an interrupt? */
-               if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-               else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) {
-                       /* At least Compaq WL200 does not have IRQInfo1 set,
-                        * but it does not work without interrupts.. */
-                       printk("Config has no IRQ info, but trying to enable "
-                              "IRQ anyway..\n");
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-               }
-
-               /* IO window settings */
-               PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
-                      "dflt.io.nwin=%d\n",
-                      cfg->io.nwin, dflt.io.nwin);
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-                       PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
-                              "io.base=0x%04x, len=%d\n", io->flags,
-                              io->win[0].base, io->win[0].len);
-                       if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       link->io.IOAddrLines = io->flags &
-                               CISTPL_IO_LINES_MASK;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin > 1) {
-                               link->io.Attributes2 = link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-               }
-
-               /* This reserves IO space but doesn't actually enable it */
-               CFG_CHECK2(RequestIO,
-                          pcmcia_request_io(link, &link->io));
-
-               /* This configuration table entry is OK */
-               break;
-
-       next_entry:
-               CS_CHECK(GetNextTuple,
-                        pcmcia_get_next_tuple(link, &tuple));
+       last_ret = pcmcia_loop_config(link, prism2_config_check, NULL);
+       if (last_ret) {
+               if (!ignore_cis_vcc)
+                       printk(KERN_ERR "GetNextTuple(): No matching "
+                              "CIS configuration.  Maybe you need the "
+                              "ignore_cis_vcc=1 parameter.\n");
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        /* Need to allocate net_device before requesting IRQ handler */
@@ -738,14 +711,12 @@ static int prism2_config(struct pcmcia_device *link)
                if (ret == 0 && local->ddev)
                        strcpy(hw_priv->node.dev_name, local->ddev->name);
        }
-       kfree(parse);
        return ret;
 
  cs_failed:
        cs_error(link, last_fn, last_ret);
 
  failed:
-       kfree(parse);
        kfree(hw_priv);
        prism2_release((u_long)link);
        return ret;
index f6003e7996afcd01aec848c726fa21d2080761c4..5155b8a760a7299cd5b01ae139821ec3c5dd0fe1 100644 (file)
@@ -833,12 +833,12 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
        switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
        case CSR_HW_REV_TYPE_5100:
        case CSR_HW_REV_TYPE_5300:
-               /* 5X00 wants in Celsius */
+       case CSR_HW_REV_TYPE_5350:
+               /* 5X00 and 5350 wants in Celsius */
                priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
                break;
        case CSR_HW_REV_TYPE_5150:
-       case CSR_HW_REV_TYPE_5350:
-               /* 5X50 wants in Kelvin */
+               /* 5150 wants in Kelvin */
                priv->hw_params.ct_kill_threshold =
                                CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
                break;
index 93944de923cafd0913979e1f45bf8a36023d2285..e2a58e477036e611da5ffc78abeda5748f7392ce 100644 (file)
@@ -2422,7 +2422,7 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
                        void *priv_sta)
 {
        struct iwl_lq_sta *lq_sta = priv_sta;
-       struct iwl_priv *priv = priv_r;
+       struct iwl_priv *priv __maybe_unused = priv_r;
 
        IWL_DEBUG_RATE("enter\n");
        kfree(lq_sta);
index a912fb68c09990fd12bfc18360e3d9c674b79e7f..297696de2da0554543f86cf1a50be458cba82b2b 100644 (file)
@@ -823,7 +823,9 @@ int lbs_update_channel(struct lbs_private *priv)
 int lbs_set_channel(struct lbs_private *priv, u8 channel)
 {
        struct cmd_ds_802_11_rf_channel cmd;
+#ifdef DEBUG
        u8 old_channel = priv->curbssparams.channel;
+#endif
        int ret = 0;
 
        lbs_deb_enter(LBS_DEB_CMD);
index e3505c110af696f2bd81ae32983c7f9e52b03762..842a08d1f1063427a1550062c436b62e2fde8701 100644 (file)
@@ -791,7 +791,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 ||
            (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 ||
-           (ret = pcmcia_parse_tuple(p_dev, &tuple, &parse)) != 0)
+           (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
        {
                lbs_pr_err("error in pcmcia_get_first_tuple etc\n");
                goto out1;
index c9e4a435b2fc04d916ae61e6db150345027a568c..1a019e98dac3ee8ef0b7be504a6cee8af6a36369 100644 (file)
@@ -533,11 +533,11 @@ static int __init init_mac80211_hwsim(void)
                data = hw->priv;
                data->hw = hw;
 
-               data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw,
-                                               "hwsim%d", i);
+               data->dev = device_create(hwsim_class, NULL, 0, hw,
+                                         "hwsim%d", i);
                if (IS_ERR(data->dev)) {
                        printk(KERN_DEBUG
-                              "mac80211_hwsim: device_create_drvdata "
+                              "mac80211_hwsim: device_create "
                               "failed (%ld)\n", PTR_ERR(data->dev));
                        err = -ENOMEM;
                        goto failed_drvdata;
index 25bae7933aa587fa22ba5b4b402c80011f3f49bf..a670f36b5f3f3c1e3222d0e45c27491132caed7d 100644 (file)
@@ -749,9 +749,10 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {
     for (i = j = 0x0; j < 0x400; j += 0x20) {
        link->io.BasePort1 = j ^ 0x300;
        i = pcmcia_request_io(link, &link->io);
-       if (i == CS_SUCCESS) break;
+       if (i == 0)
+               break;
     }
-    if (i != CS_SUCCESS) {
+    if (i != 0) {
        cs_error(link, RequestIO, i);
        goto failed;
     }
index 9eaa252c2430b441bf6671a9a9a354ad9bbe4c0d..6fcf2bda7cdfbe5e0e356ab5adfee8982a2f6b27 100644 (file)
@@ -80,7 +80,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
        /* We need atomic ops here, because we're not holding the lock */
        set_bit(0, &card->hard_reset_in_progress);
 
-       err = pcmcia_reset_card(link, NULL);
+       err = pcmcia_reset_card(link->socket);
        if (err)
                return err;
 
@@ -165,6 +165,70 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
                last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
        } while (0)
 
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
+                                  cistpl_cftable_entry_t *cfg,
+                                  cistpl_cftable_entry_t *dflt,
+                                  unsigned int vcc,
+                                  void *priv_data)
+{
+       if (cfg->index == 0)
+               goto next_entry;
+
+       /* Use power settings for Vcc and Vpp if present */
+       /* Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       /* Do we need to allocate an interrupt? */
+       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+       /* IO window settings */
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+
+               /* This reserves IO space but doesn't actually enable it */
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       goto next_entry;
+       }
+       return 0;
+
+next_entry:
+       pcmcia_disable_device(p_dev);
+       return -ENODEV;
+};
+
 static int
 orinoco_cs_config(struct pcmcia_device *link)
 {
@@ -173,16 +237,8 @@ orinoco_cs_config(struct pcmcia_device *link)
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int last_fn, last_ret;
-       u_char buf[64];
-       config_info_t conf;
-       tuple_t tuple;
-       cisparse_t parse;
        void __iomem *mem;
 
-       /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(link, &conf));
-
        /*
         * In this loop, we scan the CIS for configuration table
         * entries, each of which describes a valid card
@@ -197,94 +253,14 @@ orinoco_cs_config(struct pcmcia_device *link)
         * and most client drivers will only use the CIS to fill in
         * implementation-defined details.
         */
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               cistpl_cftable_entry_t dflt = { .index = 0 };
-
-               if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
-                   || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
-                       goto next_entry;
-
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-                       dflt = *cfg;
-               if (cfg->index == 0)
-                       goto next_entry;
-               link->conf.ConfigIndex = cfg->index;
-
-               /* Use power settings for Vcc and Vpp if present */
-               /* Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if (!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if(!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               }
-
-               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                           cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                           dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               
-               /* Do we need to allocate an interrupt? */
-               link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-               /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io =
-                           (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-                       if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 =
-                                   IO_DATA_PATH_WIDTH_16;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 =
-                                   IO_DATA_PATH_WIDTH_8;
-                       link->io.IOAddrLines =
-                           io->flags & CISTPL_IO_LINES_MASK;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin > 1) {
-                               link->io.Attributes2 =
-                                   link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-
-                       /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link, &link->io) != 0)
-                               goto next_entry;
-               }
-
-
-               /* If we got this far, we're cool! */
-
-               break;
-               
-       next_entry:
-               pcmcia_disable_device(link);
-               last_ret = pcmcia_get_next_tuple(link, &tuple);
-               if (last_ret  == CS_NO_MORE_ITEMS) {
+       last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
+       if (last_ret) {
+               if (!ignore_cis_vcc)
                        printk(KERN_ERR PFX "GetNextTuple(): No matching "
                               "CIS configuration.  Maybe you need the "
                               "ignore_cis_vcc=1 parameter.\n");
-                       goto cs_failed;
-               }
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        /*
@@ -335,7 +311,6 @@ orinoco_cs_config(struct pcmcia_device *link)
               "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
               link->irq.AssignedIRQ, link->io.BasePort1,
               link->io.BasePort1 + link->io.NumPorts1 - 1);
-
        return 0;
 
  cs_failed:
@@ -403,6 +378,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
+       unsigned long flags;
 
        if (! test_bit(0, &card->hard_reset_in_progress)) {
                err = orinoco_reinit_firmware(dev);
@@ -412,7 +388,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                        return -EIO;
                }
 
-               spin_lock(&priv->lock);
+               spin_lock_irqsave(&priv->lock, flags);
 
                netif_device_attach(dev);
                priv->hw_unavailable--;
@@ -424,7 +400,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                                       dev->name, err);
                }
 
-               spin_unlock(&priv->lock);
+               spin_unlock_irqrestore(&priv->lock, flags);
        }
 
        return err;
index 1994aa199d3726375c9b19346cea7e1babaab0d0..117c7d3a52b0ca4beb7e78f41da62d7a08797cae 100644 (file)
@@ -479,7 +479,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
        printk(KERN_ERR "p54: eeprom parse failed!\n");
        return err;
 }
-EXPORT_SYMBOL_GPL(p54_parse_eeprom);
 
 static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
 {
index 1912f5e9a0a98aff4d67e84180307060356ab349..75d749bccb0d13e17104b67e348c3723bbb1032b 100644 (file)
@@ -39,6 +39,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x0846, 0x4200)},   /* Netgear WG121 */
        {USB_DEVICE(0x0846, 0x4210)},   /* Netgear WG121 the second ? */
        {USB_DEVICE(0x0846, 0x4220)},   /* Netgear WG111 */
+       {USB_DEVICE(0x09aa, 0x1000)},   /* Spinnaker Proto board */
        {USB_DEVICE(0x0cde, 0x0006)},   /* Medion 40900, Roper Europe */
        {USB_DEVICE(0x124a, 0x4023)},   /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
        {USB_DEVICE(0x1915, 0x2234)},   /* Linksys WUSB54G OEM */
@@ -63,8 +64,8 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */
        {USB_DEVICE(0x0cde, 0x0008)},   /* Sagem XG703A */
        {USB_DEVICE(0x0d8e, 0x3762)},   /* DLink DWL-G120 Cohiba */
-       {USB_DEVICE(0x09aa, 0x1000)},   /* Spinnaker Proto board */
        {USB_DEVICE(0x124a, 0x4025)},   /* IOGear GWU513 (GW3887IK chip) */
+       {USB_DEVICE(0x1260, 0xee22)},   /* SMC 2862W-G version 2 */
        {USB_DEVICE(0x13b1, 0x000a)},   /* Linksys WUSB54G ver 2 */
        {USB_DEVICE(0x13B1, 0x000C)},   /* Linksys WUSB54AG */
        {USB_DEVICE(0x1435, 0x0427)},   /* Inventel UR054G */
index 44da0d19b5c8d9c0ed8a96d5996e88c5d2b452fe..1404a57175207f71d39ac28b12ad78651610d0c1 100644 (file)
@@ -798,9 +798,9 @@ static void ray_release(struct pcmcia_device *link)
     iounmap(local->amem);
     /* Do bother checking to see if these succeed or not */
     i = pcmcia_release_window(local->amem_handle);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
+    if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
     i = pcmcia_release_window(local->rmem_handle);
-    if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
+    if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
     pcmcia_disable_device(link);
 
     DEBUG(2,"ray_release ending\n");
index 1676ac484790bfcc692b72a06f3e3feb3e0f2669..451d410ecdae4fae126ab835bdadd5647a4f13b8 100644 (file)
@@ -374,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
        struct txentry_desc txdesc;
        struct skb_frame_desc *skbdesc;
-       unsigned int iv_len;
+       unsigned int iv_len = 0;
 
        if (unlikely(rt2x00queue_full(queue)))
                return -EINVAL;
@@ -395,6 +395,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        entry->skb = skb;
        rt2x00queue_create_tx_descriptor(entry, &txdesc);
 
+       if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)
+               iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
+
        /*
         * All information is retreived from the skb->cb array,
         * now we should claim ownership of the driver part of that
@@ -410,9 +413,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
         * the frame so we can provide it to the driver seperately.
         */
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
-           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) &&
-               (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) {
-               iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
+           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
                rt2x00crypto_tx_remove_iv(skb, iv_len);
        }
 
index e9902613e2eeb70695ca52a408e5d558eb515e52..431e3c78bf27668b00d87fc06120a7f909ae5090 100644 (file)
@@ -33,10 +33,13 @@ MODULE_LICENSE("GPL");
 static struct usb_device_id rtl8187_table[] __devinitdata = {
        /* Asus */
        {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},
+       /* Belkin */
+       {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B},
        /* Realtek */
        {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
        {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B},
+       {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B},
        /* Netgear */
        {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187},
        {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187},
index 67b26d3c3cd50548a1b4639ffb949b4345a98906..852789ad34b3e33e0094bbc2bce4496096e00209 100644 (file)
@@ -235,6 +235,70 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
  * device available to the system.
  */
 
+static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
+                                   cistpl_cftable_entry_t *cfg,
+                                   cistpl_cftable_entry_t *dflt,
+                                   unsigned int vcc,
+                                   void *priv_data)
+{
+       if (cfg->index == 0)
+               goto next_entry;
+
+       /* Use power settings for Vcc and Vpp if present */
+       /* Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       }
+
+       if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+       else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       /* Do we need to allocate an interrupt? */
+       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+       /* IO window settings */
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               if (!(io->flags & CISTPL_IO_8BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+               if (!(io->flags & CISTPL_IO_16BIT))
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin > 1) {
+                       p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+
+               /* This reserves IO space but doesn't actually enable it */
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       goto next_entry;
+       }
+       return 0;
+
+next_entry:
+       pcmcia_disable_device(p_dev);
+       return -ENODEV;
+};
+
 static int
 spectrum_cs_config(struct pcmcia_device *link)
 {
@@ -243,16 +307,8 @@ spectrum_cs_config(struct pcmcia_device *link)
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int last_fn, last_ret;
-       u_char buf[64];
-       config_info_t conf;
-       tuple_t tuple;
-       cisparse_t parse;
        void __iomem *mem;
 
-       /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(link, &conf));
-
        /*
         * In this loop, we scan the CIS for configuration table
         * entries, each of which describes a valid card
@@ -267,94 +323,14 @@ spectrum_cs_config(struct pcmcia_device *link)
         * and most client drivers will only use the CIS to fill in
         * implementation-defined details.
         */
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               cistpl_cftable_entry_t dflt = { .index = 0 };
-
-               if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
-                   || (pcmcia_parse_tuple(link, &tuple, &parse) != 0))
-                       goto next_entry;
-
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-                       dflt = *cfg;
-               if (cfg->index == 0)
-                       goto next_entry;
-               link->conf.ConfigIndex = cfg->index;
-
-               /* Use power settings for Vcc and Vpp if present */
-               /* Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if (!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if(!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               }
-
-               if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                           cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                           dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               
-               /* Do we need to allocate an interrupt? */
-               link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-               /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io =
-                           (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-                       if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 =
-                                   IO_DATA_PATH_WIDTH_16;
-                       if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 =
-                                   IO_DATA_PATH_WIDTH_8;
-                       link->io.IOAddrLines =
-                           io->flags & CISTPL_IO_LINES_MASK;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin > 1) {
-                               link->io.Attributes2 =
-                                   link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-
-                       /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link, &link->io) != 0)
-                               goto next_entry;
-               }
-
-
-               /* If we got this far, we're cool! */
-
-               break;
-               
-       next_entry:
-               pcmcia_disable_device(link);
-               last_ret = pcmcia_get_next_tuple(link, &tuple);
-               if (last_ret  == CS_NO_MORE_ITEMS) {
+       last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
+       if (last_ret) {
+               if (!ignore_cis_vcc)
                        printk(KERN_ERR PFX "GetNextTuple(): No matching "
                               "CIS configuration.  Maybe you need the "
                               "ignore_cis_vcc=1 parameter.\n");
-                       goto cs_failed;
-               }
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        /*
@@ -450,10 +426,11 @@ spectrum_cs_suspend(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
+       unsigned long flags;
        int err = 0;
 
        /* Mark the device as stopped, to block IO until later */
-       spin_lock(&priv->lock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        err = __orinoco_down(dev);
        if (err)
@@ -463,7 +440,7 @@ spectrum_cs_suspend(struct pcmcia_device *link)
        netif_device_detach(dev);
        priv->hw_unavailable++;
 
-       spin_unlock(&priv->lock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        return err;
 }
index 136220b5ca81a389fee29bf0a28d622723c0d927..e939a73ff794a731583292d5e41e7e8a23f64d8e 100644 (file)
@@ -4387,7 +4387,7 @@ MODULE_LICENSE("GPL");
  *
  * Thanks go also to:
  *     James Ashton (jaa101@syseng.anu.edu.au),
- *     Alan Cox (alan@redhat.com),
+ *     Alan Cox (alan@lxorguk.ukuu.org.uk),
  *     Allan Creighton (allanc@cs.usyd.edu.au),
  *     Matthew Geier (matthew@cs.usyd.edu.au),
  *     Remo di Giovanni (remo@cs.usyd.edu.au),
index b33ac47dd8df710956340f9cd258e6b6e1c4cd23..44d31bbf39e49d57409b5f41a3e487040974d1e6 100644 (file)
  *
  * Thanks go also to:
  *     James Ashton <jaa101@syseng.anu.edu.au>,
- *     Alan Cox <alan@redhat.com>,
+ *     Alan Cox <alan@lxorguk.ukuu.org.uk>,
  *     Allan Creighton <allanc@cs.usyd.edu.au>,
  *     Matthew Geier <matthew@cs.usyd.edu.au>,
  *     Remo di Giovanni <remo@cs.usyd.edu.au>,
index b5de38a9b791bd3611678051e8d26d1d252e627b..e124b1d6267afa03cc5e3c149d8ab77080159b2c 100644 (file)
@@ -3702,7 +3702,7 @@ wv_pcmcia_reset(struct net_device *       dev)
 #endif
 
   i = pcmcia_access_configuration_register(link, &reg);
-  if(i != CS_SUCCESS)
+  if (i != 0)
     {
       cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
@@ -3716,7 +3716,7 @@ wv_pcmcia_reset(struct net_device *       dev)
   reg.Action = CS_WRITE;
   reg.Value = reg.Value | COR_SW_RESET;
   i = pcmcia_access_configuration_register(link, &reg);
-  if(i != CS_SUCCESS)
+  if (i != 0)
     {
       cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
@@ -3725,7 +3725,7 @@ wv_pcmcia_reset(struct net_device *       dev)
   reg.Action = CS_WRITE;
   reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
   i = pcmcia_access_configuration_register(link, &reg);
-  if(i != CS_SUCCESS)
+  if (i != 0)
     {
       cs_error(link, AccessConfigurationRegister, i);
       return FALSE;
@@ -3903,7 +3903,7 @@ wv_pcmcia_config(struct pcmcia_device *   link)
   do
     {
       i = pcmcia_request_io(link, &link->io);
-      if(i != CS_SUCCESS)
+      if (i != 0)
        {
          cs_error(link, RequestIO, i);
          break;
@@ -3914,7 +3914,7 @@ wv_pcmcia_config(struct pcmcia_device *   link)
        * actually assign a handler to the interrupt.
        */
       i = pcmcia_request_irq(link, &link->irq);
-      if(i != CS_SUCCESS)
+      if (i != 0)
        {
          cs_error(link, RequestIRQ, i);
          break;
@@ -3926,7 +3926,7 @@ wv_pcmcia_config(struct pcmcia_device *   link)
        */
       link->conf.ConfigIndex = 1;
       i = pcmcia_request_configuration(link, &link->conf);
-      if(i != CS_SUCCESS)
+      if (i != 0)
        {
          cs_error(link, RequestConfiguration, i);
          break;
@@ -3942,7 +3942,7 @@ wv_pcmcia_config(struct pcmcia_device *   link)
       req.Base = req.Size = 0;
       req.AccessSpeed = mem_speed;
       i = pcmcia_request_window(&link, &req, &link->win);
-      if(i != CS_SUCCESS)
+      if (i != 0)
        {
          cs_error(link, RequestWindow, i);
          break;
@@ -3954,7 +3954,7 @@ wv_pcmcia_config(struct pcmcia_device *   link)
 
       mem.CardOffset = 0; mem.Page = 0;
       i = pcmcia_map_mem_page(link->win, &mem);
-      if(i != CS_SUCCESS)
+      if (i != 0)
        {
          cs_error(link, MapMemPage, i);
          break;
index 74a5ad2f1223cc23c21c7e593a3f42b8ebd3e41f..68789c6e1ce9ac96cb180b7c8a6d798719764294 100644 (file)
@@ -1977,10 +1977,10 @@ static int wl3501_config(struct pcmcia_device *link)
                link->io.BasePort1 = j;
                link->io.BasePort2 = link->io.BasePort1 + 0x10;
                i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS)
+               if (i == 0)
                        break;
        }
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIO, i);
                goto failed;
        }
index 3c3dd403f5ddd9f58bed9f632baad6b72409e0ee..c6948d8f53f62fbf4f6b06cf3292ebe80828132a 100644 (file)
@@ -239,11 +239,14 @@ static void xennet_alloc_rx_buffers(struct net_device *dev)
         */
        batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
        for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
-               skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD,
+               skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD + NET_IP_ALIGN,
                                         GFP_ATOMIC | __GFP_NOWARN);
                if (unlikely(!skb))
                        goto no_skb;
 
+               /* Align ip header to a 16 bytes boundary */
+               skb_reserve(skb, NET_IP_ALIGN);
+
                page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
                if (!page) {
                        kfree_skb(skb);
@@ -471,7 +474,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
 
-       frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
+       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
        if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
                printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
                       frags);
index 2f047e573d86cda7210d2346582324b5f126518e..f5f75844954cf829641774ec940307fd8e71b635 100644 (file)
@@ -126,7 +126,7 @@ static void nubus_advance(unsigned char **ptr, int len, int map)
        {
                while(not_useful(p,map))
                        p++;
-                       p++;
+               p++;
                len--;
        }
        *ptr = p;
index ad8ac1a8af28689acc7198b22fe95a888d62e6a6..7c79e94a35eac932a165367a11439a8af1d35cc0 100644 (file)
@@ -410,7 +410,7 @@ struct of_modalias_table {
        char *modalias;
 };
 static struct of_modalias_table of_modalias_table[] = {
-       /* Empty for now; add entries as needed */
+       { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
 };
 
 /**
@@ -420,13 +420,12 @@ static struct of_modalias_table of_modalias_table[] = {
  * @len:       Length of modalias value
  *
  * Based on the value of the compatible property, this routine will determine
- * an appropriate modalias value for a particular device tree node.  Three
- * separate methods are used to derive a modalias value.
+ * an appropriate modalias value for a particular device tree node.  Two
+ * separate methods are attempted to derive a modalias value.
  *
  * First method is to lookup the compatible value in of_modalias_table.
- * Second is to look for a "linux,<modalias>" entry in the compatible list
- * and used that for modalias.  Third is to strip off the manufacturer
- * prefix from the first compatible entry and use the remainder as modalias
+ * Second is to strip off the manufacturer prefix from the first
+ * compatible entry and use the remainder as modalias
  *
  * This routine returns 0 on success
  */
@@ -449,21 +448,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
        if (!compatible)
                return -ENODEV;
 
-       /* 2. search for linux,<modalias> entry */
-       p = compatible;
-       while (cplen > 0) {
-               if (!strncmp(p, "linux,", 6)) {
-                       p += 6;
-                       strlcpy(modalias, p, len);
-                       return 0;
-               }
-
-               i = strlen(p) + 1;
-               p += i;
-               cplen -= i;
-       }
-
-       /* 3. take first compatible entry and strip manufacturer */
+       /* 2. take first compatible entry and strip manufacturer */
        p = strchr(compatible, ',');
        if (!p)
                return -ENODEV;
@@ -473,3 +458,112 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
 }
 EXPORT_SYMBOL_GPL(of_modalias_node);
 
+/**
+ * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * @np:                pointer to a device tree node containing a list
+ * @list_name: property name that contains a list
+ * @cells_name:        property name that specifies phandles' arguments count
+ * @index:     index of a phandle to parse out
+ * @out_node:  pointer to device_node struct pointer (will be filled)
+ * @out_args:  pointer to arguments pointer (will be filled)
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_node and out_args, on error returns
+ * appropriate errno value.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ *     #list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ *     #list-cells = <1>;
+ * }
+ *
+ * node3 {
+ *     list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ */
+int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
+                               const char *cells_name, int index,
+                               struct device_node **out_node,
+                               const void **out_args)
+{
+       int ret = -EINVAL;
+       const u32 *list;
+       const u32 *list_end;
+       int size;
+       int cur_index = 0;
+       struct device_node *node = NULL;
+       const void *args;
+
+       list = of_get_property(np, list_name, &size);
+       if (!list) {
+               ret = -ENOENT;
+               goto err0;
+       }
+       list_end = list + size / sizeof(*list);
+
+       while (list < list_end) {
+               const u32 *cells;
+               const phandle *phandle;
+
+               phandle = list;
+               args = list + 1;
+
+               /* one cell hole in the list = <>; */
+               if (!*phandle) {
+                       list++;
+                       goto next;
+               }
+
+               node = of_find_node_by_phandle(*phandle);
+               if (!node) {
+                       pr_debug("%s: could not find phandle\n",
+                                np->full_name);
+                       goto err0;
+               }
+
+               cells = of_get_property(node, cells_name, &size);
+               if (!cells || size != sizeof(*cells)) {
+                       pr_debug("%s: could not get %s for %s\n",
+                                np->full_name, cells_name, node->full_name);
+                       goto err1;
+               }
+
+               /* Next phandle is at offset of one phandle cell + #cells */
+               list += 1 + *cells;
+               if (list > list_end) {
+                       pr_debug("%s: insufficient arguments length\n",
+                                np->full_name);
+                       goto err1;
+               }
+next:
+               if (cur_index == index)
+                       break;
+
+               of_node_put(node);
+               node = NULL;
+               cur_index++;
+       }
+
+       if (!node) {
+               ret = -ENOENT;
+               goto err0;
+       }
+
+       *out_node = node;
+       *out_args = args;
+
+       return 0;
+err1:
+       of_node_put(node);
+err0:
+       pr_debug("%s failed with status %d\n", __func__, ret);
+       return ret;
+}
+EXPORT_SYMBOL(of_parse_phandles_with_args);
index 1c9cab844f10aaa60cf80d9996b4782d0c1256e6..7cd7301b583992683391215816bd6bd277785691 100644 (file)
  */
 int of_get_gpio(struct device_node *np, int index)
 {
-       int ret = -EINVAL;
+       int ret;
        struct device_node *gc;
        struct of_gpio_chip *of_gc = NULL;
        int size;
-       const u32 *gpios;
-       u32 nr_cells;
-       int i;
        const void *gpio_spec;
        const u32 *gpio_cells;
-       int gpio_index = 0;
 
-       gpios = of_get_property(np, "gpios", &size);
-       if (!gpios) {
-               ret = -ENOENT;
+       ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+                                         &gc, &gpio_spec);
+       if (ret) {
+               pr_debug("%s: can't parse gpios property\n", __func__);
                goto err0;
        }
-       nr_cells = size / sizeof(u32);
-
-       for (i = 0; i < nr_cells; gpio_index++) {
-               const phandle *gpio_phandle;
-
-               gpio_phandle = gpios + i;
-               gpio_spec = gpio_phandle + 1;
-
-               /* one cell hole in the gpios = <>; */
-               if (!*gpio_phandle) {
-                       if (gpio_index == index)
-                               return -ENOENT;
-                       i++;
-                       continue;
-               }
-
-               gc = of_find_node_by_phandle(*gpio_phandle);
-               if (!gc) {
-                       pr_debug("%s: could not find phandle for gpios\n",
-                                np->full_name);
-                       goto err0;
-               }
-
-               of_gc = gc->data;
-               if (!of_gc) {
-                       pr_debug("%s: gpio controller %s isn't registered\n",
-                                np->full_name, gc->full_name);
-                       goto err1;
-               }
-
-               gpio_cells = of_get_property(gc, "#gpio-cells", &size);
-               if (!gpio_cells || size != sizeof(*gpio_cells) ||
-                               *gpio_cells != of_gc->gpio_cells) {
-                       pr_debug("%s: wrong #gpio-cells for %s\n",
-                                np->full_name, gc->full_name);
-                       goto err1;
-               }
-
-               /* Next phandle is at phandle cells + #gpio-cells */
-               i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
-               if (i >= nr_cells + 1) {
-                       pr_debug("%s: insufficient gpio-spec length\n",
-                                np->full_name);
-                       goto err1;
-               }
-
-               if (gpio_index == index)
-                       break;
-
-               of_gc = NULL;
-               of_node_put(gc);
-       }
 
+       of_gc = gc->data;
        if (!of_gc) {
-               ret = -ENOENT;
-               goto err0;
+               pr_debug("%s: gpio controller %s isn't registered\n",
+                        np->full_name, gc->full_name);
+               ret = -ENODEV;
+               goto err1;
+       }
+
+       gpio_cells = of_get_property(gc, "#gpio-cells", &size);
+       if (!gpio_cells || size != sizeof(*gpio_cells) ||
+                       *gpio_cells != of_gc->gpio_cells) {
+               pr_debug("%s: wrong #gpio-cells for %s\n",
+                        np->full_name, gc->full_name);
+               ret = -EINVAL;
+               goto err1;
        }
 
        ret = of_gc->xlate(of_gc, np, gpio_spec);
index 9304c45550790c7e2f1f53833d4370ac051b3f4f..ed982273fb8b1d9311aba68a3b2a42de5d174e78 100644 (file)
@@ -5,6 +5,7 @@
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ * @author Barry Kasindorf
  *
  * This is the core of the buffer management. Each
  * CPU buffer is processed and entered into the
@@ -33,7 +34,7 @@
 #include "event_buffer.h"
 #include "cpu_buffer.h"
 #include "buffer_sync.h"
+
 static LIST_HEAD(dying_tasks);
 static LIST_HEAD(dead_tasks);
 static cpumask_t marked_cpus = CPU_MASK_NONE;
@@ -48,10 +49,11 @@ static void process_task_mortuary(void);
  * Can be invoked from softirq via RCU callback due to
  * call_rcu() of the task struct, hence the _irqsave.
  */
-static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+task_free_notify(struct notifier_block *self, unsigned long val, void *data)
 {
        unsigned long flags;
-       struct task_struct * task = data;
+       struct task_struct *task = data;
        spin_lock_irqsave(&task_mortuary, flags);
        list_add(&task->tasks, &dying_tasks);
        spin_unlock_irqrestore(&task_mortuary, flags);
@@ -62,13 +64,14 @@ static int task_free_notify(struct notifier_block * self, unsigned long val, voi
 /* The task is on its way out. A sync of the buffer means we can catch
  * any remaining samples for this task.
  */
-static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+task_exit_notify(struct notifier_block *self, unsigned long val, void *data)
 {
        /* To avoid latency problems, we only process the current CPU,
         * hoping that most samples for the task are on this CPU
         */
        sync_buffer(raw_smp_processor_id());
-       return 0;
+       return 0;
 }
 
 
@@ -77,11 +80,12 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi
  * we don't lose any. This does not have to be exact, it's a QoI issue
  * only.
  */
-static int munmap_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+munmap_notify(struct notifier_block *self, unsigned long val, void *data)
 {
        unsigned long addr = (unsigned long)data;
-       struct mm_struct * mm = current->mm;
-       struct vm_area_struct * mpnt;
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *mpnt;
 
        down_read(&mm->mmap_sem);
 
@@ -99,11 +103,12 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void *
        return 0;
 }
 
+
 /* We need to be told about new modules so we don't attribute to a previously
  * loaded module, or drop the samples on the floor.
  */
-static int module_load_notify(struct notifier_block * self, unsigned long val, void * data)
+static int
+module_load_notify(struct notifier_block *self, unsigned long val, void *data)
 {
 #ifdef CONFIG_MODULES
        if (val != MODULE_STATE_COMING)
@@ -118,7 +123,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
        return 0;
 }
 
+
 static struct notifier_block task_free_nb = {
        .notifier_call  = task_free_notify,
 };
@@ -135,7 +140,7 @@ static struct notifier_block module_load_nb = {
        .notifier_call = module_load_notify,
 };
 
+
 static void end_sync(void)
 {
        end_cpu_work();
@@ -208,14 +213,14 @@ static inline unsigned long fast_get_dcookie(struct path *path)
  * not strictly necessary but allows oprofile to associate
  * shared-library samples with particular applications
  */
-static unsigned long get_exec_dcookie(struct mm_struct * mm)
+static unsigned long get_exec_dcookie(struct mm_struct *mm)
 {
        unsigned long cookie = NO_COOKIE;
-       struct vm_area_struct * vma;
+       struct vm_area_struct *vma;
+
        if (!mm)
                goto out;
+
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                if (!vma->vm_file)
                        continue;
@@ -235,13 +240,14 @@ out:
  * sure to do this lookup before a mm->mmap modification happens so
  * we don't lose track.
  */
-static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
+static unsigned long
+lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
 {
        unsigned long cookie = NO_COOKIE;
-       struct vm_area_struct * vma;
+       struct vm_area_struct *vma;
 
        for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
+
                if (addr < vma->vm_start || addr >= vma->vm_end)
                        continue;
 
@@ -263,9 +269,20 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
        return cookie;
 }
 
+static void increment_tail(struct oprofile_cpu_buffer *b)
+{
+       unsigned long new_tail = b->tail_pos + 1;
+
+       rmb();  /* be sure fifo pointers are synchromized */
+
+       if (new_tail < b->buffer_size)
+               b->tail_pos = new_tail;
+       else
+               b->tail_pos = 0;
+}
 
 static unsigned long last_cookie = INVALID_COOKIE;
+
 static void add_cpu_switch(int i)
 {
        add_event_entry(ESCAPE_CODE);
@@ -278,16 +295,16 @@ static void add_kernel_ctx_switch(unsigned int in_kernel)
 {
        add_event_entry(ESCAPE_CODE);
        if (in_kernel)
-               add_event_entry(KERNEL_ENTER_SWITCH_CODE); 
+               add_event_entry(KERNEL_ENTER_SWITCH_CODE);
        else
-               add_event_entry(KERNEL_EXIT_SWITCH_CODE); 
+               add_event_entry(KERNEL_EXIT_SWITCH_CODE);
 }
+
 static void
-add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
+add_user_ctx_switch(struct task_struct const *task, unsigned long cookie)
 {
        add_event_entry(ESCAPE_CODE);
-       add_event_entry(CTX_SWITCH_CODE); 
+       add_event_entry(CTX_SWITCH_CODE);
        add_event_entry(task->pid);
        add_event_entry(cookie);
        /* Another code for daemon back-compat */
@@ -296,7 +313,7 @@ add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
        add_event_entry(task->tgid);
 }
 
+
 static void add_cookie_switch(unsigned long cookie)
 {
        add_event_entry(ESCAPE_CODE);
@@ -304,13 +321,78 @@ static void add_cookie_switch(unsigned long cookie)
        add_event_entry(cookie);
 }
 
+
 static void add_trace_begin(void)
 {
        add_event_entry(ESCAPE_CODE);
        add_event_entry(TRACE_BEGIN_CODE);
 }
 
+#ifdef CONFIG_OPROFILE_IBS
+
+#define IBS_FETCH_CODE_SIZE    2
+#define IBS_OP_CODE_SIZE       5
+#define IBS_EIP(offset)                                \
+       (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip)
+#define IBS_EVENT(offset)                              \
+       (((struct op_sample *)&cpu_buf->buffer[(offset)])->event)
+
+/*
+ * Add IBS fetch and op entries to event buffer
+ */
+static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
+       int in_kernel, struct mm_struct *mm)
+{
+       unsigned long rip;
+       int i, count;
+       unsigned long ibs_cookie = 0;
+       off_t offset;
+
+       increment_tail(cpu_buf);        /* move to RIP entry */
+
+       rip = IBS_EIP(cpu_buf->tail_pos);
+
+#ifdef __LP64__
+       rip += IBS_EVENT(cpu_buf->tail_pos) << 32;
+#endif
+
+       if (mm) {
+               ibs_cookie = lookup_dcookie(mm, rip, &offset);
+
+               if (ibs_cookie == NO_COOKIE)
+                       offset = rip;
+               if (ibs_cookie == INVALID_COOKIE) {
+                       atomic_inc(&oprofile_stats.sample_lost_no_mapping);
+                       offset = rip;
+               }
+               if (ibs_cookie != last_cookie) {
+                       add_cookie_switch(ibs_cookie);
+                       last_cookie = ibs_cookie;
+               }
+       } else
+               offset = rip;
+
+       add_event_entry(ESCAPE_CODE);
+       add_event_entry(code);
+       add_event_entry(offset);        /* Offset from Dcookie */
+
+       /* we send the Dcookie offset, but send the raw Linear Add also*/
+       add_event_entry(IBS_EIP(cpu_buf->tail_pos));
+       add_event_entry(IBS_EVENT(cpu_buf->tail_pos));
+
+       if (code == IBS_FETCH_CODE)
+               count = IBS_FETCH_CODE_SIZE;    /*IBS FETCH is 2 int64s*/
+       else
+               count = IBS_OP_CODE_SIZE;       /*IBS OP is 5 int64s*/
+
+       for (i = 0; i < count; i++) {
+               increment_tail(cpu_buf);
+               add_event_entry(IBS_EIP(cpu_buf->tail_pos));
+               add_event_entry(IBS_EVENT(cpu_buf->tail_pos));
+       }
+}
+
+#endif
 
 static void add_sample_entry(unsigned long offset, unsigned long event)
 {
@@ -319,13 +401,13 @@ static void add_sample_entry(unsigned long offset, unsigned long event)
 }
 
 
-static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
+static int add_us_sample(struct mm_struct *mm, struct op_sample *s)
 {
        unsigned long cookie;
        off_t offset;
-       cookie = lookup_dcookie(mm, s->eip, &offset);
+
+       cookie = lookup_dcookie(mm, s->eip, &offset);
+
        if (cookie == INVALID_COOKIE) {
                atomic_inc(&oprofile_stats.sample_lost_no_mapping);
                return 0;
@@ -341,13 +423,13 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
        return 1;
 }
 
+
 /* Add a sample to the global event buffer. If possible the
  * sample is converted into a persistent dentry/offset pair
  * for later lookup from userspace.
  */
 static int
-add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
+add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
 {
        if (in_kernel) {
                add_sample_entry(s->eip, s->event);
@@ -359,9 +441,9 @@ add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
        }
        return 0;
 }
 
-static void release_mm(struct mm_struct * mm)
+
+static void release_mm(struct mm_struct *mm)
 {
        if (!mm)
                return;
@@ -370,9 +452,9 @@ static void release_mm(struct mm_struct * mm)
 }
 
 
-static struct mm_struct * take_tasks_mm(struct task_struct * task)
+static struct mm_struct *take_tasks_mm(struct task_struct *task)
 {
-       struct mm_struct * mm = get_task_mm(task);
+       struct mm_struct *mm = get_task_mm(task);
        if (mm)
                down_read(&mm->mmap_sem);
        return mm;
@@ -383,10 +465,10 @@ static inline int is_code(unsigned long val)
 {
        return val == ESCAPE_CODE;
 }
+
 
 /* "acquire" as many cpu buffer slots as we can */
-static unsigned long get_slots(struct oprofile_cpu_buffer * b)
+static unsigned long get_slots(struct oprofile_cpu_buffer *b)
 {
        unsigned long head = b->head_pos;
        unsigned long tail = b->tail_pos;
@@ -412,19 +494,6 @@ static unsigned long get_slots(struct oprofile_cpu_buffer * b)
 }
 
 
-static void increment_tail(struct oprofile_cpu_buffer * b)
-{
-       unsigned long new_tail = b->tail_pos + 1;
-
-       rmb();
-
-       if (new_tail < b->buffer_size)
-               b->tail_pos = new_tail;
-       else
-               b->tail_pos = 0;
-}
-
-
 /* Move tasks along towards death. Any tasks on dead_tasks
  * will definitely have no remaining references in any
  * CPU buffers at this point, because we use two lists,
@@ -435,8 +504,8 @@ static void process_task_mortuary(void)
 {
        unsigned long flags;
        LIST_HEAD(local_dead_tasks);
-       struct task_struct * task;
-       struct task_struct * ttask;
+       struct task_struct *task;
+       struct task_struct *ttask;
 
        spin_lock_irqsave(&task_mortuary, flags);
 
@@ -493,7 +562,7 @@ void sync_buffer(int cpu)
 {
        struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
        struct mm_struct *mm = NULL;
-       struct task_struct * new;
+       struct task_struct *new;
        unsigned long cookie = 0;
        int in_kernel = 1;
        unsigned int i;
@@ -501,7 +570,7 @@ void sync_buffer(int cpu)
        unsigned long available;
 
        mutex_lock(&buffer_mutex);
+
        add_cpu_switch(cpu);
 
        /* Remember, only we can modify tail_pos */
@@ -509,8 +578,8 @@ void sync_buffer(int cpu)
        available = get_slots(cpu_buf);
 
        for (i = 0; i < available; ++i) {
-               struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
+               struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos];
+
                if (is_code(s->eip)) {
                        if (s->event <= CPU_IS_KERNEL) {
                                /* kernel/userspace switch */
@@ -521,8 +590,18 @@ void sync_buffer(int cpu)
                        } else if (s->event == CPU_TRACE_BEGIN) {
                                state = sb_bt_start;
                                add_trace_begin();
+#ifdef CONFIG_OPROFILE_IBS
+                       } else if (s->event == IBS_FETCH_BEGIN) {
+                               state = sb_bt_start;
+                               add_ibs_begin(cpu_buf,
+                                       IBS_FETCH_CODE, in_kernel, mm);
+                       } else if (s->event == IBS_OP_BEGIN) {
+                               state = sb_bt_start;
+                               add_ibs_begin(cpu_buf,
+                                       IBS_OP_CODE, in_kernel, mm);
+#endif
                        } else {
-                               struct mm_struct * oldmm = mm;
+                               struct mm_struct *oldmm = mm;
 
                                /* userspace context switch */
                                new = (struct task_struct *)s->event;
@@ -533,13 +612,11 @@ void sync_buffer(int cpu)
                                        cookie = get_exec_dcookie(mm);
                                add_user_ctx_switch(new, cookie);
                        }
-               } else {
-                       if (state >= sb_bt_start &&
-                           !add_sample(mm, s, in_kernel)) {
-                               if (state == sb_bt_start) {
-                                       state = sb_bt_ignore;
-                                       atomic_inc(&oprofile_stats.bt_lost_no_mapping);
-                               }
+               } else if (state >= sb_bt_start &&
+                          !add_sample(mm, s, in_kernel)) {
+                       if (state == sb_bt_start) {
+                               state = sb_bt_ignore;
+                               atomic_inc(&oprofile_stats.bt_lost_no_mapping);
                        }
                }
 
index 7ba78e6d210e72ac9b41395ccc25fb6b4bfcd658..e1bd5a937f6c77d33ac1f92a16966e556c8bfff8 100644 (file)
@@ -5,6 +5,7 @@
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ * @author Barry Kasindorf <barry.kasindorf@amd.com>
  *
  * Each CPU has a local buffer that stores PC value/event
  * pairs. We also log context switches when we notice them.
@@ -209,7 +210,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
        return 1;
 }
 
-static int oprofile_begin_trace(struct oprofile_cpu_buffer * cpu_buf)
+static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)
 {
        if (nr_available_slots(cpu_buf) < 4) {
                cpu_buf->sample_lost_overflow++;
@@ -254,6 +255,75 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
        oprofile_add_ext_sample(pc, regs, event, is_kernel);
 }
 
+#ifdef CONFIG_OPROFILE_IBS
+
+#define MAX_IBS_SAMPLE_SIZE    14
+static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf,
+       unsigned long pc, int is_kernel, unsigned  int *ibs, int ibs_code)
+{
+       struct task_struct *task;
+
+       cpu_buf->sample_received++;
+
+       if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) {
+               cpu_buf->sample_lost_overflow++;
+               return 0;
+       }
+
+       is_kernel = !!is_kernel;
+
+       /* notice a switch from user->kernel or vice versa */
+       if (cpu_buf->last_is_kernel != is_kernel) {
+               cpu_buf->last_is_kernel = is_kernel;
+               add_code(cpu_buf, is_kernel);
+       }
+
+       /* notice a task switch */
+       if (!is_kernel) {
+               task = current;
+
+               if (cpu_buf->last_task != task) {
+                       cpu_buf->last_task = task;
+                       add_code(cpu_buf, (unsigned long)task);
+               }
+       }
+
+       add_code(cpu_buf, ibs_code);
+       add_sample(cpu_buf, ibs[0], ibs[1]);
+       add_sample(cpu_buf, ibs[2], ibs[3]);
+       add_sample(cpu_buf, ibs[4], ibs[5]);
+
+       if (ibs_code == IBS_OP_BEGIN) {
+       add_sample(cpu_buf, ibs[6], ibs[7]);
+       add_sample(cpu_buf, ibs[8], ibs[9]);
+       add_sample(cpu_buf, ibs[10], ibs[11]);
+       }
+
+       return 1;
+}
+
+void oprofile_add_ibs_sample(struct pt_regs *const regs,
+                               unsigned int * const ibs_sample, u8 code)
+{
+       int is_kernel = !user_mode(regs);
+       unsigned long pc = profile_pc(regs);
+
+       struct oprofile_cpu_buffer *cpu_buf =
+                        &per_cpu(cpu_buffer, smp_processor_id());
+
+       if (!backtrace_depth) {
+               log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code);
+               return;
+       }
+
+       /* if log_sample() fails we can't backtrace since we lost the source
+       * of this event */
+       if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code))
+               oprofile_ops.backtrace(regs, backtrace_depth);
+}
+
+#endif
+
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
 {
        struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
@@ -296,7 +366,7 @@ static void wq_sync_buffer(struct work_struct *work)
        struct oprofile_cpu_buffer * b =
                container_of(work, struct oprofile_cpu_buffer, work.work);
        if (b->cpu != smp_processor_id()) {
-               printk("WQ on CPU%d, prefer CPU%d\n",
+               printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n",
                       smp_processor_id(), b->cpu);
        }
        sync_buffer(b->cpu);
index c3e366b522619bd135964a17022638f4adfdec82..9c44d004da69c6a3747d5b9a4976be7f63c0d099 100644 (file)
@@ -55,5 +55,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
 /* transient events for the CPU buffer -> event buffer */
 #define CPU_IS_KERNEL 1
 #define CPU_TRACE_BEGIN 2
+#define IBS_FETCH_BEGIN 3
+#define IBS_OP_BEGIN    4
 
 #endif /* OPROFILE_CPU_BUFFER_H */
index db717c1d62a5bd4f38952e2f9f441dde26ed6313..8565bbbeb6ecdf42f924366af7d96c7eeda24983 100644 (file)
        * ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd
        on timeout.  Matches 2.2.x behaviour.
 
-2001-03-02  Andrew Morton <andrewm@uow.edu.au>
+2001-03-02  Andrew Morton
 
        * parport_pc.c (registered_parport): New static variable.
        (parport_pc_find_ports): Set it when we register PCI driver.
index e97059415ab423387eb0dfd0f4c210cd38766c68..ac2a805ac7ea642e6bea96fc14bdcbe7a832b3c0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
+/*
  * IEEE-1284 implementation for parport.
  *
  * Authors: Phil Blundell <philb@gnu.org>
index 00e1d9620f7cbca16e94f12bd932bba8f2b1b1e0..b1899e9c1f6573091309b71b68ec017e9ab53599 100644 (file)
@@ -149,52 +149,44 @@ static void parport_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int parport_config_check(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cfg,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
+{
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               if (epp_mode)
+                       p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               if (io->nwin == 2) {
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       return -ENODEV;
+               return 0;
+       }
+       return -ENODEV;
+}
+
 static int parport_config(struct pcmcia_device *link)
 {
     parport_info_t *info = link->priv;
-    tuple_t tuple;
-    u_short buf[128];
-    cisparse_t parse;
-    cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
-    cistpl_cftable_entry_t dflt = { 0 };
     struct parport *p;
     int last_ret, last_fn;
-    
+
     DEBUG(0, "parport_config(0x%p)\n", link);
-    
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (1) {
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-           goto next_entry;
-
-       if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-           cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-           link->conf.ConfigIndex = cfg->index;
-           if (epp_mode)
-               link->conf.ConfigIndex |= FORCE_EPP_MODE;
-           link->io.BasePort1 = io->win[0].base;
-           link->io.NumPorts1 = io->win[0].len;
-           link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-           if (io->nwin == 2) {
-               link->io.BasePort2 = io->win[1].base;
-               link->io.NumPorts2 = io->win[1].len;
-           }
-           if (pcmcia_request_io(link, &link->io) != 0)
-               goto next_entry;
-           /* If we've got this far, we're done */
-           break;
-       }
-       
-    next_entry:
-       if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+
+    last_ret = pcmcia_loop_config(link, parport_config_check, NULL);
+    if (last_ret) {
+           cs_error(link, RequestIO, last_ret);
+           goto failed;
     }
-    
+
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
 
index cd565bb4e1a990ba303aa308a6094c7466b3e331..0f6550719bcf179d9fc493407b5d2a3dc38f447a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $
+/*
  * Parallel port device probing code
  *
  * Authors:    Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
index a8a62bbbb5769c61446386205c64266887793d5d..0ebca450ed298f6a79a4be0cc24fd71f8273532a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
+/*
  * Parallel-port resource manager code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
diff --git a/drivers/pci/dma_remapping.h b/drivers/pci/dma_remapping.h
deleted file mode 100644 (file)
index bff5c65..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-#ifndef _DMA_REMAPPING_H
-#define _DMA_REMAPPING_H
-
-/*
- * We need a fixed PAGE_SIZE of 4K irrespective of
- * arch PAGE_SIZE for IOMMU page tables.
- */
-#define PAGE_SHIFT_4K          (12)
-#define PAGE_SIZE_4K           (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K           (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr)    (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
-#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT_4K)
-#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
-
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
-       u64     val;
-       u64     rsvd1;
-};
-#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
-       return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
-       root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
-       root->val |= value & PAGE_MASK_4K;
-}
-
-struct context_entry;
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
-       return (struct context_entry *)
-               (root_present(root)?phys_to_virt(
-               root->val & PAGE_MASK_4K):
-               NULL);
-}
-
-/*
- * low 64 bits:
- * 0: present
- * 1: fault processing disable
- * 2-3: translation type
- * 12-63: address space root
- * high 64 bits:
- * 0-2: address width
- * 3-6: aval
- * 8-23: domain id
- */
-struct context_entry {
-       u64 lo;
-       u64 hi;
-};
-#define context_present(c) ((c).lo & 1)
-#define context_fault_disable(c) (((c).lo >> 1) & 1)
-#define context_translation_type(c) (((c).lo >> 2) & 3)
-#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
-#define context_address_width(c) ((c).hi &  7)
-#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
-
-#define context_set_present(c) do {(c).lo |= 1;} while (0)
-#define context_set_fault_enable(c) \
-       do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
-#define context_set_translation_type(c, val) \
-       do { \
-               (c).lo &= (((u64)-1) << 4) | 3; \
-               (c).lo |= ((val) & 3) << 2; \
-       } while (0)
-#define CONTEXT_TT_MULTI_LEVEL 0
-#define context_set_address_root(c, val) \
-       do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
-#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
-#define context_set_domain_id(c, val) \
-       do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
-#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-11: available
- * 12-63: Host physcial address
- */
-struct dma_pte {
-       u64 val;
-};
-#define dma_clear_pte(p)       do {(p).val = 0;} while (0)
-
-#define DMA_PTE_READ (1)
-#define DMA_PTE_WRITE (2)
-
-#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
-#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
-#define dma_set_pte_prot(p, prot) \
-               do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
-#define dma_set_pte_addr(p, addr) do {\
-               (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
-#define dma_pte_present(p) (((p).val & 3) != 0)
-
-struct intel_iommu;
-
-struct dmar_domain {
-       int     id;                     /* domain id */
-       struct intel_iommu *iommu;      /* back pointer to owning iommu */
-
-       struct list_head devices;       /* all devices' list */
-       struct iova_domain iovad;       /* iova's that belong to this domain */
-
-       struct dma_pte  *pgd;           /* virtual address */
-       spinlock_t      mapping_lock;   /* page table lock */
-       int             gaw;            /* max guest address width */
-
-       /* adjusted guest address width, 0 is level 2 30-bit */
-       int             agaw;
-
-#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
-       int             flags;
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
-       struct list_head link;  /* link to domain siblings */
-       struct list_head global; /* link to global list */
-       u8 bus;                 /* PCI bus numer */
-       u8 devfn;               /* PCI devfn number */
-       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
-       struct dmar_domain *domain; /* pointer to domain */
-};
-
-extern int init_dmars(void);
-extern void free_dmar_iommu(struct intel_iommu *iommu);
-
-extern int dmar_disabled;
-
-#ifndef CONFIG_DMAR_GFX_WA
-static inline void iommu_prepare_gfx_mapping(void)
-{
-       return;
-}
-#endif /* !CONFIG_DMAR_GFX_WA */
-
-#endif
index bd2c01674f5ec1cd07063ce499e38e5faf805995..e842e756308a71c470e658164ec6c2163d5e8955 100644 (file)
@@ -28,9 +28,9 @@
 
 #include <linux/pci.h>
 #include <linux/dmar.h>
+#include <linux/iova.h>
+#include <linux/intel-iommu.h>
 #include <linux/timer.h>
-#include "iova.h"
-#include "intel-iommu.h"
 
 #undef PREFIX
 #define PREFIX "DMAR:"
index 8467d028732514277a098815f3597ebfed1591ae..7d27631e6e627bba3202633d68ff5578dd84e663 100644 (file)
@@ -276,7 +276,7 @@ int __init ibmphp_access_ebda (void)
        iounmap (io_mem);
        debug ("returned ebda segment: %x\n", ebda_seg);
        
-       io_mem = ioremap (ebda_seg<<4, 65000);
+       io_mem = ioremap(ebda_seg<<4, 1024);
        if (!io_mem )
                return -ENOMEM;
        next_offset = 0x180;
index 9b714ea93d207036fe9b51d6f3c2bbe0233c1c25..50884507b8be5005cd4767c65407edb7b4599db8 100644 (file)
@@ -147,9 +147,5 @@ int rpaphp_register_slot(struct slot *slot)
        list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
        info("Slot [%s] registered\n", slot->name);
        return 0;
-
-sysfs_fail:
-       pci_hp_deregister(php_slot);
-       return retval;
 }
 
index 389fdd6f4a9f6afcdd0877150887dc1f1571a914..fc5f2dbf532383b637258a3aec52024654d6693e 100644 (file)
@@ -33,8 +33,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/mempool.h>
 #include <linux/timer.h>
-#include "iova.h"
-#include "intel-iommu.h"
+#include <linux/iova.h>
+#include <linux/intel-iommu.h>
 #include <asm/proto.h> /* force_iommu in this header in x86-64*/
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
@@ -156,7 +156,7 @@ static inline void *alloc_domain_mem(void)
        return iommu_kmem_cache_alloc(iommu_domain_cache);
 }
 
-static inline void free_domain_mem(void *vaddr)
+static void free_domain_mem(void *vaddr)
 {
        kmem_cache_free(iommu_domain_cache, vaddr);
 }
@@ -1341,7 +1341,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
  * find_domain
  * Note: we use struct pci_dev->dev.archdata.iommu stores the info
  */
-struct dmar_domain *
+static struct dmar_domain *
 find_domain(struct pci_dev *pdev)
 {
        struct device_domain_info *info;
@@ -2318,3 +2318,111 @@ int __init intel_iommu_init(void)
        return 0;
 }
 
+void intel_iommu_domain_exit(struct dmar_domain *domain)
+{
+       u64 end;
+
+       /* Domain 0 is reserved, so dont process it */
+       if (!domain)
+               return;
+
+       end = DOMAIN_MAX_ADDR(domain->gaw);
+       end = end & (~PAGE_MASK_4K);
+
+       /* clear ptes */
+       dma_pte_clear_range(domain, 0, end);
+
+       /* free page tables */
+       dma_pte_free_pagetable(domain, 0, end);
+
+       iommu_free_domain(domain);
+       free_domain_mem(domain);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_domain_exit);
+
+struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev)
+{
+       struct dmar_drhd_unit *drhd;
+       struct dmar_domain *domain;
+       struct intel_iommu *iommu;
+
+       drhd = dmar_find_matched_drhd_unit(pdev);
+       if (!drhd) {
+               printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n");
+               return NULL;
+       }
+
+       iommu = drhd->iommu;
+       if (!iommu) {
+               printk(KERN_ERR
+                       "intel_iommu_domain_alloc: iommu == NULL\n");
+               return NULL;
+       }
+       domain = iommu_alloc_domain(iommu);
+       if (!domain) {
+               printk(KERN_ERR
+                       "intel_iommu_domain_alloc: domain == NULL\n");
+               return NULL;
+       }
+       if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+               printk(KERN_ERR
+                       "intel_iommu_domain_alloc: domain_init() failed\n");
+               intel_iommu_domain_exit(domain);
+               return NULL;
+       }
+       return domain;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc);
+
+int intel_iommu_context_mapping(
+       struct dmar_domain *domain, struct pci_dev *pdev)
+{
+       int rc;
+       rc = domain_context_mapping(domain, pdev);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_context_mapping);
+
+int intel_iommu_page_mapping(
+       struct dmar_domain *domain, dma_addr_t iova,
+       u64 hpa, size_t size, int prot)
+{
+       int rc;
+       rc = domain_page_mapping(domain, iova, hpa, size, prot);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_page_mapping);
+
+void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+{
+       detach_domain_for_dev(domain, bus, devfn);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_detach_dev);
+
+struct dmar_domain *
+intel_iommu_find_domain(struct pci_dev *pdev)
+{
+       return find_domain(pdev);
+}
+EXPORT_SYMBOL_GPL(intel_iommu_find_domain);
+
+int intel_iommu_found(void)
+{
+       return g_num_of_iommus;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_found);
+
+u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
+{
+       struct dma_pte *pte;
+       u64 pfn;
+
+       pfn = 0;
+       pte = addr_to_dma_pte(domain, iova);
+
+       if (pte)
+               pfn = dma_pte_addr(*pte);
+
+       return pfn >> PAGE_SHIFT_4K;
+}
+EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
deleted file mode 100644 (file)
index 2142c01..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Ashok Raj <ashok.raj@intel.com>
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- */
-
-#ifndef _INTEL_IOMMU_H_
-#define _INTEL_IOMMU_H_
-
-#include <linux/types.h>
-#include <linux/msi.h>
-#include <linux/sysdev.h>
-#include "iova.h"
-#include <linux/io.h>
-#include <asm/cacheflush.h>
-#include "dma_remapping.h"
-
-/*
- * Intel IOMMU register specification per version 1.0 public spec.
- */
-
-#define        DMAR_VER_REG    0x0     /* Arch version supported by this IOMMU */
-#define        DMAR_CAP_REG    0x8     /* Hardware supported capabilities */
-#define        DMAR_ECAP_REG   0x10    /* Extended capabilities supported */
-#define        DMAR_GCMD_REG   0x18    /* Global command register */
-#define        DMAR_GSTS_REG   0x1c    /* Global status register */
-#define        DMAR_RTADDR_REG 0x20    /* Root entry table */
-#define        DMAR_CCMD_REG   0x28    /* Context command reg */
-#define        DMAR_FSTS_REG   0x34    /* Fault Status register */
-#define        DMAR_FECTL_REG  0x38    /* Fault control register */
-#define        DMAR_FEDATA_REG 0x3c    /* Fault event interrupt data register */
-#define        DMAR_FEADDR_REG 0x40    /* Fault event interrupt addr register */
-#define        DMAR_FEUADDR_REG 0x44   /* Upper address register */
-#define        DMAR_AFLOG_REG  0x58    /* Advanced Fault control */
-#define        DMAR_PMEN_REG   0x64    /* Enable Protected Memory Region */
-#define        DMAR_PLMBASE_REG 0x68   /* PMRR Low addr */
-#define        DMAR_PLMLIMIT_REG 0x6c  /* PMRR low limit */
-#define        DMAR_PHMBASE_REG 0x70   /* pmrr high base addr */
-#define        DMAR_PHMLIMIT_REG 0x78  /* pmrr high limit */
-#define DMAR_IQH_REG   0x80    /* Invalidation queue head register */
-#define DMAR_IQT_REG   0x88    /* Invalidation queue tail register */
-#define DMAR_IQA_REG   0x90    /* Invalidation queue addr register */
-#define DMAR_ICS_REG   0x98    /* Invalidation complete status register */
-#define DMAR_IRTA_REG  0xb8    /* Interrupt remapping table addr register */
-
-#define OFFSET_STRIDE          (9)
-/*
-#define dmar_readl(dmar, reg) readl(dmar + reg)
-#define dmar_readq(dmar, reg) ({ \
-               u32 lo, hi; \
-               lo = readl(dmar + reg); \
-               hi = readl(dmar + reg + 4); \
-               (((u64) hi) << 32) + lo; })
-*/
-static inline u64 dmar_readq(void __iomem *addr)
-{
-       u32 lo, hi;
-       lo = readl(addr);
-       hi = readl(addr + 4);
-       return (((u64) hi) << 32) + lo;
-}
-
-static inline void dmar_writeq(void __iomem *addr, u64 val)
-{
-       writel((u32)val, addr);
-       writel((u32)(val >> 32), addr + 4);
-}
-
-#define DMAR_VER_MAJOR(v)              (((v) & 0xf0) >> 4)
-#define DMAR_VER_MINOR(v)              ((v) & 0x0f)
-
-/*
- * Decoding Capability Register
- */
-#define cap_read_drain(c)      (((c) >> 55) & 1)
-#define cap_write_drain(c)     (((c) >> 54) & 1)
-#define cap_max_amask_val(c)   (((c) >> 48) & 0x3f)
-#define cap_num_fault_regs(c)  ((((c) >> 40) & 0xff) + 1)
-#define cap_pgsel_inv(c)       (((c) >> 39) & 1)
-
-#define cap_super_page_val(c)  (((c) >> 34) & 0xf)
-#define cap_super_offset(c)    (((find_first_bit(&cap_super_page_val(c), 4)) \
-                                       * OFFSET_STRIDE) + 21)
-
-#define cap_fault_reg_offset(c)        ((((c) >> 24) & 0x3ff) * 16)
-#define cap_max_fault_reg_offset(c) \
-       (cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16)
-
-#define cap_zlr(c)             (((c) >> 22) & 1)
-#define cap_isoch(c)           (((c) >> 23) & 1)
-#define cap_mgaw(c)            ((((c) >> 16) & 0x3f) + 1)
-#define cap_sagaw(c)           (((c) >> 8) & 0x1f)
-#define cap_caching_mode(c)    (((c) >> 7) & 1)
-#define cap_phmr(c)            (((c) >> 6) & 1)
-#define cap_plmr(c)            (((c) >> 5) & 1)
-#define cap_rwbf(c)            (((c) >> 4) & 1)
-#define cap_afl(c)             (((c) >> 3) & 1)
-#define cap_ndoms(c)           (((unsigned long)1) << (4 + 2 * ((c) & 0x7)))
-/*
- * Extended Capability Register
- */
-
-#define ecap_niotlb_iunits(e)  ((((e) >> 24) & 0xff) + 1)
-#define ecap_iotlb_offset(e)   ((((e) >> 8) & 0x3ff) * 16)
-#define ecap_max_iotlb_offset(e) \
-       (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
-#define ecap_coherent(e)       ((e) & 0x1)
-#define ecap_qis(e)            ((e) & 0x2)
-#define ecap_eim_support(e)    ((e >> 4) & 0x1)
-#define ecap_ir_support(e)     ((e >> 3) & 0x1)
-#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)
-
-
-/* IOTLB_REG */
-#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
-#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
-#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
-#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
-#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
-#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
-#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
-#define DMA_TLB_DID(id)        (((u64)((id) & 0xffff)) << 32)
-#define DMA_TLB_IVT (((u64)1) << 63)
-#define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
-#define DMA_TLB_MAX_SIZE (0x3f)
-
-/* INVALID_DESC */
-#define DMA_ID_TLB_GLOBAL_FLUSH        (((u64)1) << 3)
-#define DMA_ID_TLB_DSI_FLUSH   (((u64)2) << 3)
-#define DMA_ID_TLB_PSI_FLUSH   (((u64)3) << 3)
-#define DMA_ID_TLB_READ_DRAIN  (((u64)1) << 7)
-#define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6)
-#define DMA_ID_TLB_DID(id)     (((u64)((id & 0xffff) << 16)))
-#define DMA_ID_TLB_IH_NONLEAF  (((u64)1) << 6)
-#define DMA_ID_TLB_ADDR(addr)  (addr)
-#define DMA_ID_TLB_ADDR_MASK(mask)     (mask)
-
-/* PMEN_REG */
-#define DMA_PMEN_EPM (((u32)1)<<31)
-#define DMA_PMEN_PRS (((u32)1)<<0)
-
-/* GCMD_REG */
-#define DMA_GCMD_TE (((u32)1) << 31)
-#define DMA_GCMD_SRTP (((u32)1) << 30)
-#define DMA_GCMD_SFL (((u32)1) << 29)
-#define DMA_GCMD_EAFL (((u32)1) << 28)
-#define DMA_GCMD_WBF (((u32)1) << 27)
-#define DMA_GCMD_QIE (((u32)1) << 26)
-#define DMA_GCMD_SIRTP (((u32)1) << 24)
-#define DMA_GCMD_IRE (((u32) 1) << 25)
-
-/* GSTS_REG */
-#define DMA_GSTS_TES (((u32)1) << 31)
-#define DMA_GSTS_RTPS (((u32)1) << 30)
-#define DMA_GSTS_FLS (((u32)1) << 29)
-#define DMA_GSTS_AFLS (((u32)1) << 28)
-#define DMA_GSTS_WBFS (((u32)1) << 27)
-#define DMA_GSTS_QIES (((u32)1) << 26)
-#define DMA_GSTS_IRTPS (((u32)1) << 24)
-#define DMA_GSTS_IRES (((u32)1) << 25)
-
-/* CCMD_REG */
-#define DMA_CCMD_ICC (((u64)1) << 63)
-#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
-#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
-#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
-#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
-#define DMA_CCMD_MASK_NOBIT 0
-#define DMA_CCMD_MASK_1BIT 1
-#define DMA_CCMD_MASK_2BIT 2
-#define DMA_CCMD_MASK_3BIT 3
-#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
-#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
-
-/* FECTL_REG */
-#define DMA_FECTL_IM (((u32)1) << 31)
-
-/* FSTS_REG */
-#define DMA_FSTS_PPF ((u32)2)
-#define DMA_FSTS_PFO ((u32)1)
-#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
-
-/* FRCD_REG, 32 bits access */
-#define DMA_FRCD_F (((u32)1) << 31)
-#define dma_frcd_type(d) ((d >> 30) & 1)
-#define dma_frcd_fault_reason(c) (c & 0xff)
-#define dma_frcd_source_id(c) (c & 0xffff)
-#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
-
-#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */
-
-#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
-{\
-       cycles_t start_time = get_cycles();\
-       while (1) {\
-               sts = op (iommu->reg + offset);\
-               if (cond)\
-                       break;\
-               if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
-                       panic("DMAR hardware is malfunctioning\n");\
-               cpu_relax();\
-       }\
-}
-
-#define QI_LENGTH      256     /* queue length */
-
-enum {
-       QI_FREE,
-       QI_IN_USE,
-       QI_DONE
-};
-
-#define QI_CC_TYPE             0x1
-#define QI_IOTLB_TYPE          0x2
-#define QI_DIOTLB_TYPE         0x3
-#define QI_IEC_TYPE            0x4
-#define QI_IWD_TYPE            0x5
-
-#define QI_IEC_SELECTIVE       (((u64)1) << 4)
-#define QI_IEC_IIDEX(idx)      (((u64)(idx & 0xffff) << 32))
-#define QI_IEC_IM(m)           (((u64)(m & 0x1f) << 27))
-
-#define QI_IWD_STATUS_DATA(d)  (((u64)d) << 32)
-#define QI_IWD_STATUS_WRITE    (((u64)1) << 5)
-
-struct qi_desc {
-       u64 low, high;
-};
-
-struct q_inval {
-       spinlock_t      q_lock;
-       struct qi_desc  *desc;          /* invalidation queue */
-       int             *desc_status;   /* desc status */
-       int             free_head;      /* first free entry */
-       int             free_tail;      /* last free entry */
-       int             free_cnt;
-};
-
-#ifdef CONFIG_INTR_REMAP
-/* 1MB - maximum possible interrupt remapping table size */
-#define INTR_REMAP_PAGE_ORDER  8
-#define INTR_REMAP_TABLE_REG_SIZE      0xf
-
-#define INTR_REMAP_TABLE_ENTRIES       65536
-
-struct ir_table {
-       struct irte *base;
-};
-#endif
-
-struct intel_iommu {
-       void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
-       u64             cap;
-       u64             ecap;
-       int             seg;
-       u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
-       spinlock_t      register_lock; /* protect register handling */
-       int             seq_id; /* sequence id of the iommu */
-
-#ifdef CONFIG_DMAR
-       unsigned long   *domain_ids; /* bitmap of domains */
-       struct dmar_domain **domains; /* ptr to domains */
-       spinlock_t      lock; /* protect context, domain ids */
-       struct root_entry *root_entry; /* virtual address */
-
-       unsigned int irq;
-       unsigned char name[7];    /* Device Name */
-       struct msi_msg saved_msg;
-       struct sys_device sysdev;
-#endif
-       struct q_inval  *qi;            /* Queued invalidation info */
-#ifdef CONFIG_INTR_REMAP
-       struct ir_table *ir_table;      /* Interrupt remapping info */
-#endif
-};
-
-static inline void __iommu_flush_cache(
-       struct intel_iommu *iommu, void *addr, int size)
-{
-       if (!ecap_coherent(iommu->ecap))
-               clflush_cache_range(addr, size);
-}
-
-extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
-
-extern int alloc_iommu(struct dmar_drhd_unit *drhd);
-extern void free_iommu(struct intel_iommu *iommu);
-extern int dmar_enable_qi(struct intel_iommu *iommu);
-extern void qi_global_iec(struct intel_iommu *iommu);
-
-extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
-#endif
index bb642cc5e18c9a410c28b1bb60490550b049f105..738d4c89581cc7a41f5c2746add5dca767ad81be 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/pci.h>
 #include <linux/irq.h>
 #include <asm/io_apic.h>
-#include "intel-iommu.h"
+#include <linux/intel-iommu.h>
 #include "intr_remapping.h"
 
 static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
index 05f2635bbe4e501caa8f59953003ba2f6b9e4610..ca48f0df8ac989bb41889e1efd87db7d5ee5fe10 100644 (file)
@@ -1,4 +1,4 @@
-#include "intel-iommu.h"
+#include <linux/intel-iommu.h>
 
 struct ioapic_scope {
        struct intel_iommu *iommu;
index 3ef4ac064315dd6bd0df4cc86559a34c66cbeb23..2287116e9822472a1ef879bd6facfbd30920b087 100644 (file)
@@ -7,7 +7,7 @@
  * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
  */
 
-#include "iova.h"
+#include <linux/iova.h>
 
 void
 init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h
deleted file mode 100644 (file)
index 228f6c9..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006, Intel Corporation.
- *
- * This file is released under the GPLv2.
- *
- * Copyright (C) 2006-2008 Intel Corporation
- * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
- *
- */
-
-#ifndef _IOVA_H_
-#define _IOVA_H_
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/rbtree.h>
-#include <linux/dma-mapping.h>
-
-/* IO virtual address start page frame number */
-#define IOVA_START_PFN         (1)
-
-/* iova structure */
-struct iova {
-       struct rb_node  node;
-       unsigned long   pfn_hi; /* IOMMU dish out addr hi */
-       unsigned long   pfn_lo; /* IOMMU dish out addr lo */
-};
-
-/* holds all the iova translations for a domain */
-struct iova_domain {
-       spinlock_t      iova_alloc_lock;/* Lock to protect iova  allocation */
-       spinlock_t      iova_rbtree_lock; /* Lock to protect update of rbtree */
-       struct rb_root  rbroot;         /* iova domain rbtree root */
-       struct rb_node  *cached32_node; /* Save last alloced node */
-       unsigned long   dma_32bit_pfn;
-};
-
-struct iova *alloc_iova_mem(void);
-void free_iova_mem(struct iova *iova);
-void free_iova(struct iova_domain *iovad, unsigned long pfn);
-void __free_iova(struct iova_domain *iovad, struct iova *iova);
-struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
-       unsigned long limit_pfn,
-       bool size_aligned);
-struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
-       unsigned long pfn_hi);
-void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
-void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
-struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
-void put_iova_domain(struct iova_domain *iovad);
-
-#endif
index 36698e57b97f659dbc20f03f4f6df6fe0e718694..dd9161a054e1c1264891a918a634d5a60fa0d062 100644 (file)
@@ -1237,8 +1237,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 #endif
 
-static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
 {
+       const struct pci_dev *a = to_pci_dev(d_a);
+       const struct pci_dev *b = to_pci_dev(d_b);
+
        if      (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
        else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return  1;
 
@@ -1251,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
        return 0;
 }
 
-/*
- * Yes, this forcably breaks the klist abstraction temporarily.  It
- * just wants to sort the klist, not change reference counts and
- * take/drop locks rapidly in the process.  It does all this while
- * holding the lock for the list, so objects can't otherwise be
- * added/removed while we're swizzling.
- */
-static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
-{
-       struct list_head *pos;
-       struct klist_node *n;
-       struct device *dev;
-       struct pci_dev *b;
-
-       list_for_each(pos, list) {
-               n = container_of(pos, struct klist_node, n_node);
-               dev = container_of(n, struct device, knode_bus);
-               b = to_pci_dev(dev);
-               if (pci_sort_bf_cmp(a, b) <= 0) {
-                       list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
-                       return;
-               }
-       }
-       list_move_tail(&a->dev.knode_bus.n_node, list);
-}
-
 void __init pci_sort_breadthfirst(void)
 {
-       LIST_HEAD(sorted_devices);
-       struct list_head *pos, *tmp;
-       struct klist_node *n;
-       struct device *dev;
-       struct pci_dev *pdev;
-       struct klist *device_klist;
-
-       device_klist = bus_get_device_klist(&pci_bus_type);
-
-       spin_lock(&device_klist->k_lock);
-       list_for_each_safe(pos, tmp, &device_klist->k_list) {
-               n = container_of(pos, struct klist_node, n_node);
-               dev = container_of(n, struct device, knode_bus);
-               pdev = to_pci_dev(dev);
-               pci_insertion_sort_klist(pdev, &sorted_devices);
-       }
-       list_splice(&sorted_devices, &device_klist->k_list);
-       spin_unlock(&device_klist->k_lock);
+       bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
 }
index 9236e7f869c81779f7fccecb2cdf49f601186543..e872ac925b4b3479cc06e5699973edbf65128881 100644 (file)
@@ -1561,8 +1561,7 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
                if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
                    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
 #ifdef DEBUG
-                       dev_dbg(&dev->dev, "calling ");
-                       print_fn_descriptor_symbol("%s\n", f->hook);
+                       dev_dbg(&dev->dev, "calling %pF\n", f->hook);
 #endif
                        f->hook(dev);
                }
index 3abbfad9ddab592f592001e31e3911efe002566c..d5e2106760f81743267dd85169553c4158c1373b 100644 (file)
@@ -378,11 +378,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
        align = 0;
        min_align = 0;
        for (order = 0; order <= max_order; order++) {
-#ifdef CONFIG_RESOURCES_64BIT
-               resource_size_t align1 = 1ULL << (order + 20);
-#else
-               resource_size_t align1 = 1U << (order + 20);
-#endif
+               resource_size_t align1 = 1;
+
+               align1 <<= (order + 20);
+
                if (!align)
                        min_align = align1;
                else if (ALIGN(align + min_align, min_align) < align1)
index a87902de8d3b9ec187b66a69c9ea97931577c504..b46c60b7270842fcbaef50f7bd9eb8136e0d50f0 100644 (file)
@@ -2,10 +2,6 @@
 # Makefile for the kernel pcmcia subsystem (c/o David Hinds)
 #
 
-ifeq ($(CONFIG_PCMCIA_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
-
 pcmcia_core-y                                  += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
 pcmcia_core-$(CONFIG_CARDBUS)                  += cardbus.o
 obj-$(CONFIG_PCCARD)                           += pcmcia_core.o
@@ -68,10 +64,11 @@ sa1100_cs-$(CONFIG_SA1100_SHANNON)          += sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)              += sa1100_simpad.o
 
 pxa2xx_lubbock_cs-y                            += pxa2xx_lubbock.o sa1111_generic.o
+pxa2xx_cm_x2xx_cs-y                            += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o
 pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK)              += pxa2xx_lubbock_cs.o
 pxa2xx-obj-$(CONFIG_MACH_MAINSTONE)            += pxa2xx_mainstone.o
 pxa2xx-obj-$(CONFIG_PXA_SHARPSL)               += pxa2xx_sharpsl.o
-pxa2xx-obj-$(CONFIG_MACH_ARMCORE)              += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o
+pxa2xx-obj-$(CONFIG_MACH_ARMCORE)              += pxa2xx_cm_x2xx_cs.o
 pxa2xx-obj-$(CONFIG_ARCH_VIPER)                        += pxa2xx_viper.o
 pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA)            += pxa2xx_trizeps.o
 pxa2xx-obj-$(CONFIG_MACH_PALMTX)               += pxa2xx_palmtx.o
index 75e8f8505e47230156103ccb784a606ed43b8698..fc1de46fd20a0f5317389861380c0903858fee5a 100644 (file)
@@ -292,7 +292,7 @@ au1x00_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
                skt->spd_io[map->map] = speed;
        }
 
-       map->start=(ioaddr_t)(u32)skt->virt_io;
+       map->start=(unsigned int)(u32)skt->virt_io;
        map->stop=map->start+MAP_SIZE;
        return 0;
 
index a53ef5902518d88e7434b456a4d5b54eb0f90663..13a4fbc587116e076e34ccd981deaa36d9ac4e3f 100644 (file)
@@ -116,7 +116,7 @@ struct au1000_pcmcia_socket {
        struct resource         res_attr;
 
        void *                  virt_io;
-       ioaddr_t                phys_io;
+       unsigned int            phys_io;
        unsigned int            phys_attr;
        unsigned int            phys_mem;
        unsigned short          speed_io, speed_attr, speed_mem;
index aa1cd4d3aa292c4e840a4b09471b6068a81f9385..d6b4bd1db7d7e6b9edbb5a3117070cc0f718df58 100644 (file)
@@ -37,7 +37,6 @@
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/bus_ops.h>
-#include "cs_internal.h"
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 8a9b18cee847e980881c1f0536925fca0bbcc52f..9627390835caa2cd28b97090ec90d76cf37bf5e2 100644 (file)
@@ -41,7 +41,6 @@
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/bus_ops.h>
-#include "cs_internal.h"
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 911ca0e8dfc29b94498fec85b10c73cb33be7aef..db77e1f3309a087a6c93c06d251284981df80311 100644 (file)
@@ -238,7 +238,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
        pci_bus_add_devices(bus);
 
        s->irq.AssignedIRQ = s->pci_irq;
-       return CS_SUCCESS;
+       return 0;
 }
 
 void cb_free(struct pcmcia_socket * s)
index 65129b54eb09c309ef87e9ebf94a3c60869efdd9..dcce9f5d84654a0612f99ed9bbe85813d53966f5 100644 (file)
@@ -92,7 +92,8 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
        if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
                mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
                if (mem->res == NULL) {
-                       printk(KERN_NOTICE "cs: unable to map card memory!\n");
+                       dev_printk(KERN_NOTICE, &s->dev,
+                                  "cs: unable to map card memory!\n");
                        return NULL;
                }
                s->cis_virt = NULL;
@@ -265,13 +266,13 @@ EXPORT_SYMBOL(pcmcia_write_cis_mem);
 ======================================================================*/
 
 static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
-                          u_int len, void *ptr)
+                          size_t len, void *ptr)
 {
     struct cis_cache_entry *cis;
     int ret;
 
     if (s->fake_cis) {
-       if (s->fake_cis_len > addr+len)
+       if (s->fake_cis_len >= addr+len)
            memcpy(ptr, s->fake_cis+addr, len);
        else
            memset(ptr, 0xff, len);
@@ -351,7 +352,9 @@ int verify_cis_cache(struct pcmcia_socket *s)
 
        buf = kmalloc(256, GFP_KERNEL);
        if (buf == NULL)
-               return -1;
+               dev_printk(KERN_WARNING, &s->dev,
+                          "no memory for verifying CIS\n");
+               return -ENOMEM;
        list_for_each_entry(cis, &s->cis_cache, node) {
                int len = cis->len;
 
@@ -380,18 +383,22 @@ int verify_cis_cache(struct pcmcia_socket *s)
     
 ======================================================================*/
 
-int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis)
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+                      const u8 *data, const size_t len)
 {
-    kfree(s->fake_cis);
-    s->fake_cis = NULL;
-    if (cis->Length > CISTPL_MAX_CIS_SIZE)
-       return CS_BAD_SIZE;
-    s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
-    if (s->fake_cis == NULL)
-       return CS_OUT_OF_RESOURCE;
-    s->fake_cis_len = cis->Length;
-    memcpy(s->fake_cis, cis->Data, cis->Length);
-    return CS_SUCCESS;
+       if (len > CISTPL_MAX_CIS_SIZE) {
+               dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n");
+               return -EINVAL;
+       }
+       kfree(s->fake_cis);
+       s->fake_cis = kmalloc(len, GFP_KERNEL);
+       if (s->fake_cis == NULL) {
+               dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n");
+               return -ENOMEM;
+       }
+       s->fake_cis_len = len;
+       memcpy(s->fake_cis, data, len);
+       return 0;
 }
 EXPORT_SYMBOL(pcmcia_replace_cis);
 
@@ -418,9 +425,9 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *t
 int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
 {
     if (!s)
-       return CS_BAD_HANDLE;
+       return -EINVAL;
     if (!(s->state & SOCKET_PRESENT))
-       return CS_NO_CARD;
+       return -ENODEV;
     tuple->TupleLink = tuple->Flags = 0;
 #ifdef CONFIG_CARDBUS
     if (s->state & SOCKET_CARDBUS) {
@@ -440,10 +447,10 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
        !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
        cisdata_t req = tuple->DesiredTuple;
        tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
-       if (pccard_get_next_tuple(s, function, tuple) == CS_SUCCESS) {
+       if (pccard_get_next_tuple(s, function, tuple) == 0) {
            tuple->DesiredTuple = CISTPL_LINKTARGET;
-           if (pccard_get_next_tuple(s, function, tuple) != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
+           if (pccard_get_next_tuple(s, function, tuple) != 0)
+               return -ENOSPC;
        } else
            tuple->CISOffset = tuple->TupleLink = 0;
        tuple->DesiredTuple = req;
@@ -498,9 +505,9 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
     int ofs, i, attr;
 
     if (!s)
-       return CS_BAD_HANDLE;
+       return -EINVAL;
     if (!(s->state & SOCKET_PRESENT))
-       return CS_NO_CARD;
+       return -ENODEV;
 
     link[1] = tuple->TupleLink;
     ofs = tuple->CISOffset + tuple->TupleLink;
@@ -519,7 +526,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
        /* End of chain?  Follow long link if possible */
        if (link[0] == CISTPL_END) {
            if ((ofs = follow_link(s, tuple)) < 0)
-               return CS_NO_MORE_ITEMS;
+               return -ENOSPC;
            attr = SPACE(tuple->Flags);
            read_cis_cache(s, attr, ofs, 2, link);
        }
@@ -577,13 +584,13 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_
     }
     if (i == MAX_TUPLES) {
        cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n");
-       return CS_NO_MORE_ITEMS;
+       return -ENOSPC;
     }
     
     tuple->TupleCode = link[0];
     tuple->TupleLink = link[1];
     tuple->CISOffset = ofs + 2;
-    return CS_SUCCESS;
+    return 0;
 }
 EXPORT_SYMBOL(pccard_get_next_tuple);
 
@@ -596,18 +603,18 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
     u_int len;
 
     if (!s)
-       return CS_BAD_HANDLE;
+       return -EINVAL;
 
     if (tuple->TupleLink < tuple->TupleOffset)
-       return CS_NO_MORE_ITEMS;
+       return -ENOSPC;
     len = tuple->TupleLink - tuple->TupleOffset;
     tuple->TupleDataLen = tuple->TupleLink;
     if (len == 0)
-       return CS_SUCCESS;
+       return 0;
     read_cis_cache(s, SPACE(tuple->Flags),
                   tuple->CISOffset + tuple->TupleOffset,
                   _MIN(len, tuple->TupleDataMax), tuple->TupleData);
-    return CS_SUCCESS;
+    return 0;
 }
 EXPORT_SYMBOL(pccard_get_tuple_data);
 
@@ -640,25 +647,31 @@ static int parse_device(tuple_t *tuple, cistpl_device_t *device)
        case 3: device->dev[i].speed = 150; break;
        case 4: device->dev[i].speed = 100; break;
        case 7:
-           if (++p == q) return CS_BAD_TUPLE;
+           if (++p == q)
+                   return -EINVAL;
            device->dev[i].speed = SPEED_CVT(*p);
            while (*p & 0x80)
-               if (++p == q) return CS_BAD_TUPLE;
+               if (++p == q)
+                       return -EINVAL;
            break;
        default:
-           return CS_BAD_TUPLE;
+           return -EINVAL;
        }
 
-       if (++p == q) return CS_BAD_TUPLE;
-       if (*p == 0xff) break;
+       if (++p == q)
+               return -EINVAL;
+       if (*p == 0xff)
+               break;
        scale = *p & 7;
-       if (scale == 7) return CS_BAD_TUPLE;
+       if (scale == 7)
+               return -EINVAL;
        device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
        device->ndev++;
-       if (++p == q) break;
+       if (++p == q)
+               break;
     }
     
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -667,12 +680,12 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
 {
     u_char *p;
     if (tuple->TupleDataLen < 5)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     p = (u_char *) tuple->TupleData;
     csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
     csum->len = get_unaligned_le16(p + 2);
     csum->sum = *(p + 4);
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -680,9 +693,9 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
 static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
 {
     if (tuple->TupleDataLen < 4)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     link->addr = get_unaligned_le32(tuple->TupleData);
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -697,13 +710,13 @@ static int parse_longlink_mfc(tuple_t *tuple,
     
     link->nfn = *p; p++;
     if (tuple->TupleDataLen <= link->nfn*5)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     for (i = 0; i < link->nfn; i++) {
        link->fn[i].space = *p; p++;
        link->fn[i].addr = get_unaligned_le32(p);
        p += 4;
     }
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -713,24 +726,27 @@ static int parse_strings(u_char *p, u_char *q, int max,
 {
     int i, j, ns;
 
-    if (p == q) return CS_BAD_TUPLE;
+    if (p == q)
+           return -EINVAL;
     ns = 0; j = 0;
     for (i = 0; i < max; i++) {
-       if (*p == 0xff) break;
+       if (*p == 0xff)
+               break;
        ofs[i] = j;
        ns++;
        for (;;) {
            s[j++] = (*p == 0xff) ? '\0' : *p;
            if ((*p == '\0') || (*p == 0xff)) break;
-           if (++p == q) return CS_BAD_TUPLE;
+           if (++p == q)
+                   return -EINVAL;
        }
        if ((*p == 0xff) || (++p == q)) break;
     }
     if (found) {
        *found = ns;
-       return CS_SUCCESS;
+       return 0;
     } else {
-       return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
+       return (ns == max) ? 0 : -EINVAL;
     }
 }
 
@@ -745,7 +761,8 @@ static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
     
     vers_1->major = *p; p++;
     vers_1->minor = *p; p++;
-    if (p >= q) return CS_BAD_TUPLE;
+    if (p >= q)
+           return -EINVAL;
 
     return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
                         vers_1->str, vers_1->ofs, &vers_1->ns);
@@ -781,7 +798,7 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
        p += 2;
     }
     jedec->nid = nid;
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -789,10 +806,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
 {
     if (tuple->TupleDataLen < 4)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     m->manf = get_unaligned_le16(tuple->TupleData);
     m->card = get_unaligned_le16(tuple->TupleData + 2);
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -801,11 +818,11 @@ static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
 {
     u_char *p;
     if (tuple->TupleDataLen < 2)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     p = (u_char *)tuple->TupleData;
     f->func = p[0];
     f->sysinit = p[1];
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -815,12 +832,12 @@ static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
     u_char *p;
     int i;
     if (tuple->TupleDataLen < 1)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     p = (u_char *)tuple->TupleData;
     f->type = p[0];
     for (i = 1; i < tuple->TupleDataLen; i++)
        f->data[i-1] = p[i];
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -834,7 +851,7 @@ static int parse_config(tuple_t *tuple, cistpl_config_t *config)
     rasz = *p & 0x03;
     rmsz = (*p & 0x3c) >> 2;
     if (tuple->TupleDataLen < rasz+rmsz+4)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     config->last_idx = *(++p);
     p++;
     config->base = 0;
@@ -846,7 +863,7 @@ static int parse_config(tuple_t *tuple, cistpl_config_t *config)
     for (i = 0; i <= rmsz; i++)
        config->rmask[i>>2] += p[i] << (8*(i%4));
     config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*======================================================================
@@ -1002,10 +1019,12 @@ static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
 
 static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
 {
-    if (p == q) return NULL;
+    if (p == q)
+           return NULL;
     irq->IRQInfo1 = *p; p++;
     if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
-       if (p+2 > q) return NULL;
+       if (p+2 > q)
+               return NULL;
        irq->IRQInfo2 = (p[1]<<8) + p[0];
        p += 2;
     }
@@ -1026,7 +1045,8 @@ static int parse_cftable_entry(tuple_t *tuple,
     if (*p & 0x40)
        entry->flags |= CISTPL_CFTABLE_DEFAULT;
     if (*p & 0x80) {
-       if (++p == q) return CS_BAD_TUPLE;
+       if (++p == q)
+               return -EINVAL;
        if (*p & 0x10)
            entry->flags |= CISTPL_CFTABLE_BVDS;
        if (*p & 0x20)
@@ -1040,30 +1060,35 @@ static int parse_cftable_entry(tuple_t *tuple,
        entry->interface = 0;
 
     /* Process optional features */
-    if (++p == q) return CS_BAD_TUPLE;
+    if (++p == q)
+           return -EINVAL;
     features = *p; p++;
 
     /* Power options */
     if ((features & 3) > 0) {
        p = parse_power(p, q, &entry->vcc);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vcc.present = 0;
     if ((features & 3) > 1) {
        p = parse_power(p, q, &entry->vpp1);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vpp1.present = 0;
     if ((features & 3) > 2) {
        p = parse_power(p, q, &entry->vpp2);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vpp2.present = 0;
 
     /* Timing options */
     if (features & 0x04) {
        p = parse_timing(p, q, &entry->timing);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else {
        entry->timing.wait = 0;
        entry->timing.ready = 0;
@@ -1073,14 +1098,16 @@ static int parse_cftable_entry(tuple_t *tuple,
     /* I/O window options */
     if (features & 0x08) {
        p = parse_io(p, q, &entry->io);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->io.nwin = 0;
     
     /* Interrupt options */
     if (features & 0x10) {
        p = parse_irq(p, q, &entry->irq);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->irq.IRQInfo1 = 0;
 
@@ -1094,7 +1121,8 @@ static int parse_cftable_entry(tuple_t *tuple,
        entry->mem.win[0].card_addr = 0;
        entry->mem.win[0].host_addr = 0;
        p += 2;
-       if (p > q) return CS_BAD_TUPLE;
+       if (p > q)
+               return -EINVAL;
        break;
     case 0x40:
        entry->mem.nwin = 1;
@@ -1102,26 +1130,30 @@ static int parse_cftable_entry(tuple_t *tuple,
        entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
        entry->mem.win[0].host_addr = 0;
        p += 4;
-       if (p > q) return CS_BAD_TUPLE;
+       if (p > q)
+               return -EINVAL;
        break;
     case 0x60:
        p = parse_mem(p, q, &entry->mem);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
        break;
     }
 
     /* Misc features */
     if (features & 0x80) {
-       if (p == q) return CS_BAD_TUPLE;
+       if (p == q)
+               return -EINVAL;
        entry->flags |= (*p << 8);
        while (*p & 0x80)
-           if (++p == q) return CS_BAD_TUPLE;
+           if (++p == q)
+                   return -EINVAL;
        p++;
     }
 
     entry->subtuples = q-p;
     
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -1132,12 +1164,12 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
 {
     u_char *p;
     if (tuple->TupleDataLen < 6)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     p = (u_char *)tuple->TupleData;
     bar->attr = *p;
     p += 2;
     bar->size = get_unaligned_le32(p);
-    return CS_SUCCESS;
+    return 0;
 }
 
 static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
@@ -1146,12 +1178,12 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
     
     p = (u_char *)tuple->TupleData;
     if ((*p != 3) || (tuple->TupleDataLen < 6))
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     config->last_idx = *(++p);
     p++;
     config->base = get_unaligned_le32(p);
     config->subtuples = tuple->TupleDataLen - 6;
-    return CS_SUCCESS;
+    return 0;
 }
 
 static int parse_cftable_entry_cb(tuple_t *tuple,
@@ -1167,29 +1199,34 @@ static int parse_cftable_entry_cb(tuple_t *tuple,
        entry->flags |= CISTPL_CFTABLE_DEFAULT;
 
     /* Process optional features */
-    if (++p == q) return CS_BAD_TUPLE;
+    if (++p == q)
+           return -EINVAL;
     features = *p; p++;
 
     /* Power options */
     if ((features & 3) > 0) {
        p = parse_power(p, q, &entry->vcc);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vcc.present = 0;
     if ((features & 3) > 1) {
        p = parse_power(p, q, &entry->vpp1);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vpp1.present = 0;
     if ((features & 3) > 2) {
        p = parse_power(p, q, &entry->vpp2);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->vpp2.present = 0;
 
     /* I/O window options */
     if (features & 0x08) {
-       if (p == q) return CS_BAD_TUPLE;
+       if (p == q)
+               return -EINVAL;
        entry->io = *p; p++;
     } else
        entry->io = 0;
@@ -1197,32 +1234,37 @@ static int parse_cftable_entry_cb(tuple_t *tuple,
     /* Interrupt options */
     if (features & 0x10) {
        p = parse_irq(p, q, &entry->irq);
-       if (p == NULL) return CS_BAD_TUPLE;
+       if (p == NULL)
+               return -EINVAL;
     } else
        entry->irq.IRQInfo1 = 0;
 
     if (features & 0x20) {
-       if (p == q) return CS_BAD_TUPLE;
+       if (p == q)
+               return -EINVAL;
        entry->mem = *p; p++;
     } else
        entry->mem = 0;
 
     /* Misc features */
     if (features & 0x80) {
-       if (p == q) return CS_BAD_TUPLE;
+       if (p == q)
+               return -EINVAL;
        entry->flags |= (*p << 8);
        if (*p & 0x80) {
-           if (++p == q) return CS_BAD_TUPLE;
+           if (++p == q)
+                   return -EINVAL;
            entry->flags |= (*p << 16);
        }
        while (*p & 0x80)
-           if (++p == q) return CS_BAD_TUPLE;
+           if (++p == q)
+                   return -EINVAL;
        p++;
     }
 
     entry->subtuples = q-p;
     
-    return CS_SUCCESS;
+    return 0;
 }
 
 #endif
@@ -1248,7 +1290,7 @@ static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
        p += 6;
     }
     geo->ngeo = n;
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -1258,7 +1300,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
     u_char *p, *q;
 
     if (tuple->TupleDataLen < 10)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     
     p = tuple->TupleData;
     q = p + tuple->TupleDataLen;
@@ -1282,15 +1324,18 @@ static int parse_org(tuple_t *tuple, cistpl_org_t *org)
     
     p = tuple->TupleData;
     q = p + tuple->TupleDataLen;
-    if (p == q) return CS_BAD_TUPLE;
+    if (p == q)
+           return -EINVAL;
     org->data_org = *p;
-    if (++p == q) return CS_BAD_TUPLE;
+    if (++p == q)
+           return -EINVAL;
     for (i = 0; i < 30; i++) {
        org->desc[i] = *p;
        if (*p == '\0') break;
-       if (++p == q) return CS_BAD_TUPLE;
+       if (++p == q)
+               return -EINVAL;
     }
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
@@ -1300,7 +1345,7 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
     u_char *p;
 
     if (tuple->TupleDataLen < 10)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
 
     p = tuple->TupleData;
 
@@ -1309,17 +1354,17 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
     fmt->offset = get_unaligned_le32(p + 2);
     fmt->length = get_unaligned_le32(p + 6);
 
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*====================================================================*/
 
-int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse)
+int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
 {
-    int ret = CS_SUCCESS;
+    int ret = 0;
     
     if (tuple->TupleDataLen > tuple->TupleDataMax)
-       return CS_BAD_TUPLE;
+       return -EINVAL;
     switch (tuple->TupleCode) {
     case CISTPL_DEVICE:
     case CISTPL_DEVICE_A:
@@ -1387,15 +1432,17 @@ int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse)
        break;
     case CISTPL_NO_LINK:
     case CISTPL_LINKTARGET:
-       ret = CS_SUCCESS;
+       ret = 0;
        break;
     default:
-       ret = CS_UNSUPPORTED_FUNCTION;
+       ret = -EINVAL;
        break;
     }
+    if (ret)
+           __cs_dbg(0, "parse_tuple failed %d\n", ret);
     return ret;
 }
-EXPORT_SYMBOL(pccard_parse_tuple);
+EXPORT_SYMBOL(pcmcia_parse_tuple);
 
 /*======================================================================
 
@@ -1410,18 +1457,22 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
     int ret;
 
     buf = kmalloc(256, GFP_KERNEL);
-    if (buf == NULL)
-       return CS_OUT_OF_RESOURCE;
+    if (buf == NULL) {
+           dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
+           return -ENOMEM;
+    }
     tuple.DesiredTuple = code;
     tuple.Attributes = TUPLE_RETURN_COMMON;
     ret = pccard_get_first_tuple(s, function, &tuple);
-    if (ret != CS_SUCCESS) goto done;
+    if (ret != 0)
+           goto done;
     tuple.TupleData = buf;
     tuple.TupleOffset = 0;
     tuple.TupleDataMax = 255;
     ret = pccard_get_tuple_data(s, &tuple);
-    if (ret != CS_SUCCESS) goto done;
-    ret = pccard_parse_tuple(&tuple, parse);
+    if (ret != 0)
+           goto done;
+    ret = pcmcia_parse_tuple(&tuple, parse);
 done:
     kfree(buf);
     return ret;
@@ -1446,37 +1497,40 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
     int ret, reserved, dev_ok = 0, ident_ok = 0;
 
     if (!s)
-       return CS_BAD_HANDLE;
+       return -EINVAL;
 
     tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
-    if (tuple == NULL)
-       return CS_OUT_OF_RESOURCE;
+    if (tuple == NULL) {
+           dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
+           return -ENOMEM;
+    }
     p = kmalloc(sizeof(*p), GFP_KERNEL);
     if (p == NULL) {
-       kfree(tuple);
-       return CS_OUT_OF_RESOURCE;
+           kfree(tuple);
+           dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
+           return -ENOMEM;
     }
 
     count = reserved = 0;
     tuple->DesiredTuple = RETURN_FIRST_TUPLE;
     tuple->Attributes = TUPLE_RETURN_COMMON;
     ret = pccard_get_first_tuple(s, function, tuple);
-    if (ret != CS_SUCCESS)
+    if (ret != 0)
        goto done;
 
     /* First tuple should be DEVICE; we should really have either that
        or a CFTABLE_ENTRY of some sort */
     if ((tuple->TupleCode == CISTPL_DEVICE) ||
-       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) ||
-       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS))
+       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == 0) ||
+       (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
        dev_ok++;
 
     /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
        tuple, for card identification.  Certain old D-Link and Linksys
        cards have only a broken VERS_2 tuple; hence the bogus test. */
-    if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == CS_SUCCESS) ||
-       (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == CS_SUCCESS) ||
-       (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS))
+    if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == 0) ||
+       (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == 0) ||
+       (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != -ENOSPC))
        ident_ok++;
 
     if (!dev_ok && !ident_ok)
@@ -1484,7 +1538,8 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
 
     for (count = 1; count < MAX_TUPLES; count++) {
        ret = pccard_get_next_tuple(s, function, tuple);
-       if (ret != CS_SUCCESS) break;
+       if (ret != 0)
+               break;
        if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
            ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
            ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
@@ -1499,6 +1554,6 @@ done:
            *info = count;
     kfree(tuple);
     kfree(p);
-    return CS_SUCCESS;
+    return 0;
 }
 EXPORT_SYMBOL(pccard_validate_cis);
index d1207393fc3e4029a8b5f6402f82c185d517ff39..c68c5d3382859eb4af84f8d9e0278ee3ce00b8ea 100644 (file)
@@ -61,7 +61,7 @@ INT_MODULE_PARM(unreset_limit,        30);            /* unreset_check's */
 /* Access speed for attribute memory windows */
 INT_MODULE_PARM(cis_speed,     300);           /* ns */
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static int pc_debug;
 
 module_param(pc_debug, int, 0644);
@@ -247,7 +247,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 
        wait_for_completion(&socket->thread_done);
        if (!socket->thread) {
-               printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
+               dev_printk(KERN_WARNING, &socket->dev,
+                          "PCMCIA: warning: socket thread did not start\n");
                return -EIO;
        }
 
@@ -366,16 +367,16 @@ static int socket_reset(struct pcmcia_socket *skt)
                skt->ops->get_status(skt, &status);
 
                if (!(status & SS_DETECT))
-                       return CS_NO_CARD;
+                       return -ENODEV;
 
                if (status & SS_READY)
-                       return CS_SUCCESS;
+                       return 0;
 
                msleep(unreset_check * 10);
        }
 
        cs_err(skt, "time out after reset.\n");
-       return CS_GENERAL_FAILURE;
+       return -ETIMEDOUT;
 }
 
 /*
@@ -412,7 +413,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
 
        s->ops->get_status(s, &status);
        if (status & SS_POWERON) {
-               printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
+               dev_printk(KERN_ERR, &s->dev,
+                          "*** DANGER *** unable to remove socket power\n");
        }
 
        cs_socket_put(s);
@@ -426,14 +428,14 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 
        skt->ops->get_status(skt, &status);
        if (!(status & SS_DETECT))
-               return CS_NO_CARD;
+               return -ENODEV;
 
        msleep(initial_delay * 10);
 
        for (i = 0; i < 100; i++) {
                skt->ops->get_status(skt, &status);
                if (!(status & SS_DETECT))
-                       return CS_NO_CARD;
+                       return -ENODEV;
 
                if (!(status & SS_PENDING))
                        break;
@@ -443,13 +445,13 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 
        if (status & SS_PENDING) {
                cs_err(skt, "voltage interrogation timed out.\n");
-               return CS_GENERAL_FAILURE;
+               return -ETIMEDOUT;
        }
 
        if (status & SS_CARDBUS) {
                if (!(skt->features & SS_CAP_CARDBUS)) {
                        cs_err(skt, "cardbus cards are not supported.\n");
-                       return CS_BAD_TYPE;
+                       return -EINVAL;
                }
                skt->state |= SOCKET_CARDBUS;
        }
@@ -463,7 +465,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
                skt->socket.Vcc = skt->socket.Vpp = 50;
        else {
                cs_err(skt, "unsupported voltage key.\n");
-               return CS_BAD_TYPE;
+               return -EIO;
        }
 
        if (skt->power_hook)
@@ -480,7 +482,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        skt->ops->get_status(skt, &status);
        if (!(status & SS_POWERON)) {
                cs_err(skt, "unable to apply power.\n");
-               return CS_BAD_TYPE;
+               return -EIO;
        }
 
        status = socket_reset(skt);
@@ -502,15 +504,16 @@ static int socket_insert(struct pcmcia_socket *skt)
        cs_dbg(skt, 4, "insert\n");
 
        if (!cs_socket_get(skt))
-               return CS_NO_CARD;
+               return -ENODEV;
 
        ret = socket_setup(skt, setup_delay);
-       if (ret == CS_SUCCESS) {
+       if (ret == 0) {
                skt->state |= SOCKET_PRESENT;
 
-               printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n",
-                      (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA",
-                      skt->sock);
+               dev_printk(KERN_NOTICE, &skt->dev,
+                          "pccard: %s card inserted into slot %d\n",
+                          (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA",
+                          skt->sock);
 
 #ifdef CONFIG_CARDBUS
                if (skt->state & SOCKET_CARDBUS) {
@@ -531,7 +534,7 @@ static int socket_insert(struct pcmcia_socket *skt)
 static int socket_suspend(struct pcmcia_socket *skt)
 {
        if (skt->state & SOCKET_SUSPEND)
-               return CS_IN_USE;
+               return -EBUSY;
 
        send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
        skt->socket = dead_socket;
@@ -540,7 +543,7 @@ static int socket_suspend(struct pcmcia_socket *skt)
                skt->ops->suspend(skt);
        skt->state |= SOCKET_SUSPEND;
 
-       return CS_SUCCESS;
+       return 0;
 }
 
 /*
@@ -553,7 +556,7 @@ static int socket_resume(struct pcmcia_socket *skt)
        int ret;
 
        if (!(skt->state & SOCKET_SUSPEND))
-               return CS_IN_USE;
+               return -EBUSY;
 
        skt->socket = dead_socket;
        skt->ops->init(skt);
@@ -565,7 +568,7 @@ static int socket_resume(struct pcmcia_socket *skt)
        }
 
        ret = socket_setup(skt, resume_delay);
-       if (ret == CS_SUCCESS) {
+       if (ret == 0) {
                /*
                 * FIXME: need a better check here for cardbus cards.
                 */
@@ -590,12 +593,13 @@ static int socket_resume(struct pcmcia_socket *skt)
 
        skt->state &= ~SOCKET_SUSPEND;
 
-       return CS_SUCCESS;
+       return 0;
 }
 
 static void socket_remove(struct pcmcia_socket *skt)
 {
-       printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
+       dev_printk(KERN_NOTICE, &skt->dev,
+                  "pccard: card ejected from slot %d\n", skt->sock);
        socket_shutdown(skt);
 }
 
@@ -641,8 +645,8 @@ static int pccardd(void *__skt)
        /* register with the device core */
        ret = device_register(&skt->dev);
        if (ret) {
-               printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
-                       skt);
+               dev_printk(KERN_WARNING, &skt->dev,
+                          "PCMCIA: unable to register socket\n");
                skt->thread = NULL;
                complete(&skt->thread_done);
                return 0;
@@ -748,7 +752,7 @@ EXPORT_SYMBOL(pccard_register_pcmcia);
  * CIS register.
  */
 
-int pccard_reset_card(struct pcmcia_socket *skt)
+int pcmcia_reset_card(struct pcmcia_socket *skt)
 {
        int ret;
 
@@ -757,15 +761,15 @@ int pccard_reset_card(struct pcmcia_socket *skt)
        mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
-                       ret = CS_NO_CARD;
+                       ret = -ENODEV;
                        break;
                }
                if (skt->state & SOCKET_SUSPEND) {
-                       ret = CS_IN_USE;
+                       ret = -EBUSY;
                        break;
                }
                if (skt->state & SOCKET_CARDBUS) {
-                       ret = CS_UNSUPPORTED_FUNCTION;
+                       ret = -EPERM;
                        break;
                }
 
@@ -774,20 +778,20 @@ int pccard_reset_card(struct pcmcia_socket *skt)
                        send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
                        if (skt->callback)
                                skt->callback->suspend(skt);
-                       if (socket_reset(skt) == CS_SUCCESS) {
+                       if (socket_reset(skt) == 0) {
                                send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
                                if (skt->callback)
                                        skt->callback->resume(skt);
                        }
                }
 
-               ret = CS_SUCCESS;
+               ret = 0;
        } while (0);
        mutex_unlock(&skt->skt_mutex);
 
        return ret;
 } /* reset_card */
-EXPORT_SYMBOL(pccard_reset_card);
+EXPORT_SYMBOL(pcmcia_reset_card);
 
 
 /* These shut down or wake up a socket.  They are sort of user
@@ -802,11 +806,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
        mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
-                       ret = CS_NO_CARD;
+                       ret = -ENODEV;
                        break;
                }
                if (skt->state & SOCKET_CARDBUS) {
-                       ret = CS_UNSUPPORTED_FUNCTION;
+                       ret = -EPERM;
                        break;
                }
                if (skt->callback) {
@@ -832,11 +836,11 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
        mutex_lock(&skt->skt_mutex);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
-                       ret = CS_NO_CARD;
+                       ret = -ENODEV;
                        break;
                }
                if (skt->state & SOCKET_CARDBUS) {
-                       ret = CS_UNSUPPORTED_FUNCTION;
+                       ret = -EPERM;
                        break;
                }
                ret = socket_resume(skt);
@@ -892,7 +896,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
                        ret = -EBUSY;
                        break;
                }
-               if (socket_insert(skt) == CS_NO_CARD) {
+               if (socket_insert(skt) == -ENODEV) {
                        ret = -ENODEV;
                        break;
                }
index 63dc1a28bda2772d6f2f213656ce07223cd8dd6c..79615e6d540ba69a01573d3999340e46d001f9b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * cs_internal.h
+ * cs_internal.h -- definitions internal to the PCMCIA core modules
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * (C) 1999            David A. Hinds
+ * (C) 2003 - 2008     Dominik Brodowski
+ *
+ *
+ * This file contains definitions _only_ needed by the PCMCIA core modules.
+ * It must not be included by PCMCIA socket drivers or by PCMCIA device
+ * drivers.
  */
 
 #ifndef _LINUX_CS_INTERNAL_H
 #include <linux/kref.h>
 
 /* Flags in client state */
-#define CLIENT_CONFIG_LOCKED   0x0001
-#define CLIENT_IRQ_REQ         0x0002
-#define CLIENT_IO_REQ          0x0004
-#define CLIENT_UNBOUND         0x0008
-#define CLIENT_STALE           0x0010
 #define CLIENT_WIN_REQ(i)      (0x1<<(i))
-#define CLIENT_CARDBUS         0x8000
 
 /* Each card function gets one of these guys */
 typedef struct config_t {
        struct kref     ref;
-    u_int              state;
-    u_int              Attributes;
-    u_int              IntType;
-    u_int              ConfigBase;
-    u_char             Status, Pin, Copy, Option, ExtStatus;
-    u_int              CardValues;
-    io_req_t           io;
-    struct {
-       u_int           Attributes;
-    } irq;
+       unsigned int    state;
+       unsigned int    Attributes;
+       unsigned int    IntType;
+       unsigned int    ConfigBase;
+       unsigned char   Status, Pin, Copy, Option, ExtStatus;
+       unsigned int    CardValues;
+       io_req_t        io;
+       struct {
+               u_int   Attributes;
+       } irq;
 } config_t;
 
+
 struct cis_cache_entry {
        struct list_head        node;
        unsigned int            addr;
@@ -49,6 +50,30 @@ struct cis_cache_entry {
        unsigned char           cache[0];
 };
 
+struct pccard_resource_ops {
+       int     (*validate_mem)         (struct pcmcia_socket *s);
+       int     (*adjust_io_region)     (struct resource *res,
+                                        unsigned long r_start,
+                                        unsigned long r_end,
+                                        struct pcmcia_socket *s);
+       struct resource* (*find_io)     (unsigned long base, int num,
+                                        unsigned long align,
+                                        struct pcmcia_socket *s);
+       struct resource* (*find_mem)    (unsigned long base, unsigned long num,
+                                        unsigned long align, int low,
+                                        struct pcmcia_socket *s);
+       int     (*add_io)               (struct pcmcia_socket *s,
+                                        unsigned int action,
+                                        unsigned long r_start,
+                                        unsigned long r_end);
+       int     (*add_mem)              (struct pcmcia_socket *s,
+                                        unsigned int action,
+                                        unsigned long r_start,
+                                        unsigned long r_end);
+       int     (*init)                 (struct pcmcia_socket *s);
+       void    (*exit)                 (struct pcmcia_socket *s);
+};
+
 /* Flags in config state */
 #define CONFIG_LOCKED          0x01
 #define CONFIG_IRQ_REQ         0x02
@@ -59,7 +84,6 @@ struct cis_cache_entry {
 #define SOCKET_INUSE           0x0010
 #define SOCKET_SUSPEND         0x0080
 #define SOCKET_WIN_REQ(i)      (0x0100<<(i))
-#define SOCKET_REGION_INFO     0x4000
 #define SOCKET_CARDBUS         0x8000
 #define SOCKET_CARDBUS_CONFIG  0x10000
 
@@ -83,69 +107,153 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
        }
 }
 
-/* In cardbus.c */
-int cb_alloc(struct pcmcia_socket *s);
-void cb_free(struct pcmcia_socket *s);
-int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr);
+#ifdef CONFIG_PCMCIA_DEBUG
+extern int cs_debug_level(int);
 
-/* In cistpl.c */
-int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
-                u_int addr, u_int len, void *ptr);
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
-                  u_int addr, u_int len, void *ptr);
-void release_cis_mem(struct pcmcia_socket *s);
-void destroy_cis_cache(struct pcmcia_socket *s);
+#define cs_dbg(skt, lvl, fmt, arg...) do {             \
+       if (cs_debug_level(lvl))                        \
+               dev_printk(KERN_DEBUG, &skt->dev,       \
+                "cs: " fmt, ## arg);                   \
+} while (0)
+#define __cs_dbg(lvl, fmt, arg...) do {                        \
+       if (cs_debug_level(lvl))                        \
+               printk(KERN_DEBUG                       \
+                "cs: " fmt, ## arg);                   \
+} while (0)
+
+#else
+#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0)
+#define __cs_dbg(lvl, fmt, arg...) do { } while (0)
+#endif
+
+#define cs_err(skt, fmt, arg...) \
+       dev_printk(KERN_ERR, &skt->dev, "cs: " fmt, ## arg)
+
+
+/*
+ * Stuff internal to module "pcmcia_core":
+ */
+
+/* cistpl.c */
 int verify_cis_cache(struct pcmcia_socket *s);
-int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
 
-/* In rsrc_mgr */
-int pcmcia_validate_mem(struct pcmcia_socket *s);
-struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
-                  struct pcmcia_socket *s);
-int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
-                    unsigned long r_end, struct pcmcia_socket *s);
-struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
-                   int low, struct pcmcia_socket *s);
+/* rsrc_mgr.c */
 void release_resource_db(struct pcmcia_socket *s);
 
-/* In socket_sysfs.c */
+/* socket_sysfs.c */
 extern int pccard_sysfs_add_socket(struct device *dev);
 extern void pccard_sysfs_remove_socket(struct device *dev);
 
-/* In cs.c */
-extern struct rw_semaphore pcmcia_socket_list_rwsem;
-extern struct list_head pcmcia_socket_list;
-int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
-int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
-int pccard_reset_card(struct pcmcia_socket *skt);
+/* cardbus.c */
+int cb_alloc(struct pcmcia_socket *s);
+void cb_free(struct pcmcia_socket *s);
+int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
+               void *ptr);
+
 
 
+/*
+ * Stuff exported by module "pcmcia_core" to module "pcmcia"
+ */
+
 struct pcmcia_callback{
        struct module   *owner;
-       int             (*event) (struct pcmcia_socket *s, event_t event, int priority);
+       int             (*event) (struct pcmcia_socket *s,
+                                 event_t event, int priority);
        void            (*requery) (struct pcmcia_socket *s, int new_cis);
        int             (*suspend) (struct pcmcia_socket *s);
        int             (*resume) (struct pcmcia_socket *s);
 };
 
+/* cs.c */
+extern struct rw_semaphore pcmcia_socket_list_rwsem;
+extern struct list_head pcmcia_socket_list;
+extern struct class pcmcia_socket_class;
+
+int pcmcia_get_window(struct pcmcia_socket *s,
+                     window_handle_t *handle,
+                     int idx,
+                     win_req_t *req);
 int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr);
 
-#define cs_socket_name(skt)    ((skt)->dev.bus_id)
+int pcmcia_suspend_card(struct pcmcia_socket *skt);
+int pcmcia_resume_card(struct pcmcia_socket *skt);
 
-#ifdef DEBUG
-extern int cs_debug_level(int);
+int pcmcia_eject_card(struct pcmcia_socket *skt);
+int pcmcia_insert_card(struct pcmcia_socket *skt);
 
-#define cs_dbg(skt, lvl, fmt, arg...) do {             \
-       if (cs_debug_level(lvl))                        \
-               printk(KERN_DEBUG "cs: %s: " fmt,       \
-                      cs_socket_name(skt) , ## arg);   \
-} while (0)
+struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
+void pcmcia_put_socket(struct pcmcia_socket *skt);
 
-#else
-#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0)
-#endif
+/* cistpl.c */
+int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
+                       u_int addr, u_int len, void *ptr);
+void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
+                         u_int addr, u_int len, void *ptr);
+void release_cis_mem(struct pcmcia_socket *s);
+void destroy_cis_cache(struct pcmcia_socket *s);
+int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
+                     cisdata_t code, void *parse);
+int pcmcia_replace_cis(struct pcmcia_socket *s,
+                      const u8 *data, const size_t len);
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function,
+                       unsigned int *count);
 
-#define cs_err(skt, fmt, arg...) \
-       printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.bus_id , ## arg)
+/* rsrc_mgr.c */
+int pcmcia_validate_mem(struct pcmcia_socket *s);
+struct resource *pcmcia_find_io_region(unsigned long base,
+                                      int num,
+                                      unsigned long align,
+                                      struct pcmcia_socket *s);
+int pcmcia_adjust_io_region(struct resource *res,
+                           unsigned long r_start,
+                           unsigned long r_end,
+                           struct pcmcia_socket *s);
+struct resource *pcmcia_find_mem_region(u_long base,
+                                       u_long num,
+                                       u_long align,
+                                       int low,
+                                       struct pcmcia_socket *s);
+
+/*
+ * Stuff internal to module "pcmcia".
+ */
+/* ds.c */
+extern struct bus_type pcmcia_bus_type;
+
+/* pcmcia_resource.c */
+extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+
+#ifdef CONFIG_PCMCIA_IOCTL
+/* ds.c */
+extern spinlock_t pcmcia_dev_list_lock;
+
+extern struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev);
+extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
+
+struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+                                       unsigned int function);
+
+/* pcmcia_ioctl.c */
+extern void __init pcmcia_setup_ioctl(void);
+extern void __exit pcmcia_cleanup_ioctl(void);
+extern void handle_event(struct pcmcia_socket *s, event_t event);
+extern int handle_request(struct pcmcia_socket *s, event_t event);
+
+#else /* CONFIG_PCMCIA_IOCTL */
+
+static inline void __init pcmcia_setup_ioctl(void) { return; }
+static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
+static inline void handle_event(struct pcmcia_socket *s, event_t event)
+{
+       return;
+}
+static inline int handle_request(struct pcmcia_socket *s, event_t event)
+{
+       return 0;
+}
+
+#endif /* CONFIG_PCMCIA_IOCTL */
 
 #endif /* _LINUX_CS_INTERNAL_H */
index 34c83d3ca0fac69df37ece4e352a99697ae515cd..7956602554901297f86055cea142707f7eead769 100644 (file)
@@ -32,7 +32,6 @@
 #include <pcmcia/ss.h>
 
 #include "cs_internal.h"
-#include "ds_internal.h"
 
 /*====================================================================*/
 
@@ -42,17 +41,22 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
 MODULE_DESCRIPTION("PCMCIA Driver Services");
 MODULE_LICENSE("GPL");
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 int ds_pc_debug;
 
 module_param_named(pc_debug, ds_pc_debug, int, 0644);
 
 #define ds_dbg(lvl, fmt, arg...) do {                          \
-       if (ds_pc_debug > (lvl))                                        \
+       if (ds_pc_debug > (lvl))                                \
                printk(KERN_DEBUG "ds: " fmt , ## arg);         \
 } while (0)
+#define ds_dev_dbg(lvl, dev, fmt, arg...) do {                         \
+       if (ds_pc_debug > (lvl))                                        \
+               dev_printk(KERN_DEBUG, dev, "ds: " fmt , ## arg);       \
+} while (0)
 #else
 #define ds_dbg(lvl, fmt, arg...) do { } while (0)
+#define ds_dev_dbg(lvl, dev, fmt, arg...) do { } while (0)
 #endif
 
 spinlock_t pcmcia_dev_list_lock;
@@ -64,42 +68,19 @@ spinlock_t pcmcia_dev_list_lock;
 /* String tables for error messages */
 
 typedef struct lookup_t {
-    int key;
-    char *msg;
+    const int key;
+    const char *msg;
 } lookup_t;
 
 static const lookup_t error_table[] = {
-    { CS_SUCCESS,              "Operation succeeded" },
-    { CS_BAD_ADAPTER,          "Bad adapter" },
-    { CS_BAD_ATTRIBUTE,        "Bad attribute", },
-    { CS_BAD_BASE,             "Bad base address" },
-    { CS_BAD_EDC,              "Bad EDC" },
-    { CS_BAD_IRQ,              "Bad IRQ" },
-    { CS_BAD_OFFSET,           "Bad offset" },
-    { CS_BAD_PAGE,             "Bad page number" },
-    { CS_READ_FAILURE,         "Read failure" },
-    { CS_BAD_SIZE,             "Bad size" },
-    { CS_BAD_SOCKET,           "Bad socket" },
-    { CS_BAD_TYPE,             "Bad type" },
-    { CS_BAD_VCC,              "Bad Vcc" },
-    { CS_BAD_VPP,              "Bad Vpp" },
-    { CS_BAD_WINDOW,           "Bad window" },
-    { CS_WRITE_FAILURE,                "Write failure" },
-    { CS_NO_CARD,              "No card present" },
-    { CS_UNSUPPORTED_FUNCTION, "Usupported function" },
-    { CS_UNSUPPORTED_MODE,     "Unsupported mode" },
-    { CS_BAD_SPEED,            "Bad speed" },
-    { CS_BUSY,                 "Resource busy" },
-    { CS_GENERAL_FAILURE,      "General failure" },
-    { CS_WRITE_PROTECTED,      "Write protected" },
-    { CS_BAD_ARG_LENGTH,       "Bad argument length" },
-    { CS_BAD_ARGS,             "Bad arguments" },
-    { CS_CONFIGURATION_LOCKED, "Configuration locked" },
-    { CS_IN_USE,               "Resource in use" },
-    { CS_NO_MORE_ITEMS,                "No more items" },
-    { CS_OUT_OF_RESOURCE,      "Out of resource" },
-    { CS_BAD_HANDLE,           "Bad handle" },
-    { CS_BAD_TUPLE,            "Bad CIS tuple" }
+    { 0,                       "Operation succeeded" },
+    { -EIO,                    "Input/Output error" },
+    { -ENODEV,                 "No card present" },
+    { -EINVAL,                 "Bad parameter" },
+    { -EACCES,                 "Configuration locked" },
+    { -EBUSY,                  "Resource in use" },
+    { -ENOSPC,                 "No more items" },
+    { -ENOMEM,                 "Out of resource" },
 };
 
 
@@ -155,46 +136,32 @@ static const lookup_t service_table[] = {
     { ReplaceCIS,                      "ReplaceCIS" }
 };
 
-
-static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
+const char *pcmcia_error_func(int func)
 {
        int i;
-       char *serv;
-
-       if (!p_dev)
-               printk(KERN_NOTICE);
-       else
-               printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
 
        for (i = 0; i < ARRAY_SIZE(service_table); i++)
-               if (service_table[i].key == err->func)
-                       break;
-       if (i < ARRAY_SIZE(service_table))
-               serv = service_table[i].msg;
-       else
-               serv = "Unknown service number";
+               if (service_table[i].key == func)
+                       return service_table[i].msg;
 
-       for (i = 0; i < ARRAY_SIZE(error_table); i++)
-               if (error_table[i].key == err->retcode)
-                       break;
-       if (i < ARRAY_SIZE(error_table))
-               printk("%s: %s\n", serv, error_table[i].msg);
-       else
-               printk("%s: Unknown error code %#x\n", serv, err->retcode);
+       return "Unknown service number";
+}
+EXPORT_SYMBOL(pcmcia_error_func);
 
-       return CS_SUCCESS;
-} /* report_error */
+const char *pcmcia_error_ret(int ret)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(error_table); i++)
+               if (error_table[i].key == ret)
+                       return error_table[i].msg;
 
-/* end of code which was in cs.c before */
+       return "unknown";
+}
+EXPORT_SYMBOL(pcmcia_error_ret);
 
 /*======================================================================*/
 
-void cs_error(struct pcmcia_device *p_dev, int func, int ret)
-{
-       error_info_t err = { func, ret };
-       pcmcia_report_error(p_dev, &err);
-}
-EXPORT_SYMBOL(cs_error);
 
 
 static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
@@ -391,7 +358,7 @@ static void pcmcia_release_function(struct kref *ref)
 static void pcmcia_release_dev(struct device *dev)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
-       ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id);
+       ds_dev_dbg(1, dev, "releasing device\n");
        pcmcia_put_socket(p_dev->socket);
        kfree(p_dev->devname);
        kref_put(&p_dev->function_config->ref, pcmcia_release_function);
@@ -401,7 +368,7 @@ static void pcmcia_release_dev(struct device *dev)
 static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)
 {
        if (!s->pcmcia_state.device_add_pending) {
-               ds_dbg(1, "scheduling to add %s secondary"
+               ds_dev_dbg(1, &s->dev, "scheduling to add %s secondary"
                       " device to %d\n", mfc ? "mfc" : "pfc", s->sock);
                s->pcmcia_state.device_add_pending = 1;
                s->pcmcia_state.mfc_pfc = mfc;
@@ -439,8 +406,7 @@ static int pcmcia_device_probe(struct device * dev)
         */
        did = p_dev->dev.driver_data;
 
-       ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id,
-              p_drv->drv.name);
+       ds_dev_dbg(1, dev, "trying to bind to %s\n", p_drv->drv.name);
 
        if ((!p_drv->probe) || (!p_dev->function_config) ||
            (!try_module_get(p_drv->owner))) {
@@ -455,15 +421,16 @@ static int pcmcia_device_probe(struct device * dev)
                p_dev->conf.ConfigBase = cis_config.base;
                p_dev->conf.Present = cis_config.rmask[0];
        } else {
-               printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n");
+               dev_printk(KERN_INFO, dev,
+                          "pcmcia: could not parse base and rmask0 of CIS\n");
                p_dev->conf.ConfigBase = 0;
                p_dev->conf.Present = 0;
        }
 
        ret = p_drv->probe(p_dev);
        if (ret) {
-               ds_dbg(1, "binding %s to %s failed with %d\n",
-                      p_dev->dev.bus_id, p_drv->drv.name, ret);
+               ds_dev_dbg(1, dev, "binding to %s failed with %d\n",
+                          p_drv->drv.name, ret);
                goto put_module;
        }
 
@@ -490,8 +457,9 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
        struct pcmcia_device    *tmp;
        unsigned long           flags;
 
-       ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock,
-              leftover ? leftover->devname : "");
+       ds_dev_dbg(2, leftover ? &leftover->dev : &s->dev,
+                  "pcmcia_card_remove(%d) %s\n", s->sock,
+                  leftover ? leftover->devname : "");
 
        if (!leftover)
                s->device_count = 0;
@@ -508,7 +476,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
                p_dev->_removed=1;
                spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
-               ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id);
+               ds_dev_dbg(2, &p_dev->dev, "unregistering device\n");
                device_unregister(&p_dev->dev);
        }
 
@@ -525,7 +493,7 @@ static int pcmcia_device_remove(struct device * dev)
        p_dev = to_pcmcia_dev(dev);
        p_drv = to_pcmcia_drv(dev->driver);
 
-       ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id);
+       ds_dev_dbg(1, dev, "removing device\n");
 
        /* If we're removing the primary module driving a
         * pseudo multi-function card, we need to unbind
@@ -548,13 +516,15 @@ static int pcmcia_device_remove(struct device * dev)
 
        /* check for proper unloading */
        if (p_dev->_irq || p_dev->_io || p_dev->_locked)
-               printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
-                      p_drv->drv.name);
+               dev_printk(KERN_INFO, dev,
+                       "pcmcia: driver %s did not release config properly\n",
+                       p_drv->drv.name);
 
        for (i = 0; i < MAX_WIN; i++)
                if (p_dev->_win & CLIENT_WIN_REQ(i))
-                       printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
-                              p_drv->drv.name);
+                       dev_printk(KERN_INFO, dev,
+                         "pcmcia: driver %s did not release window properly\n",
+                          p_drv->drv.name);
 
        /* references from pcmcia_probe_device */
        pcmcia_put_dev(p_dev);
@@ -603,8 +573,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                }
                if (!pccard_read_tuple(p_dev->socket, p_dev->func,
                                      CISTPL_DEVICE_GEO, devgeo)) {
-                       ds_dbg(0, "mem device geometry probably means "
-                              "FUNCID_MEMORY\n");
+                       ds_dev_dbg(0, &p_dev->dev,
+                                  "mem device geometry probably means "
+                                  "FUNCID_MEMORY\n");
                        p_dev->func_id = CISTPL_FUNCID_MEMORY;
                        p_dev->has_func_id = 1;
                }
@@ -685,7 +656,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        if (!p_dev->devname)
                goto err_free;
        sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
-       ds_dbg(3, "devname is %s\n", p_dev->devname);
+       ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
 
        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
 
@@ -706,7 +677,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
        if (!p_dev->function_config) {
-               ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id);
+               ds_dev_dbg(3, &p_dev->dev, "creating config_t\n");
                p_dev->function_config = kzalloc(sizeof(struct config_t),
                                                 GFP_KERNEL);
                if (!p_dev->function_config)
@@ -714,8 +685,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
                kref_init(&p_dev->function_config->ref);
        }
 
-       printk(KERN_NOTICE "pcmcia: registering new device %s\n",
-              p_dev->devname);
+       dev_printk(KERN_NOTICE, &p_dev->dev,
+                  "pcmcia: registering new device %s\n",
+                  p_dev->devname);
 
        pcmcia_device_query(p_dev);
 
@@ -750,19 +722,20 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
        int ret = 0;
 
        if (!(s->resource_setup_done)) {
-               ds_dbg(3, "no resources available, delaying card_add\n");
+               ds_dev_dbg(3, &s->dev,
+                          "no resources available, delaying card_add\n");
                return -EAGAIN; /* try again, but later... */
        }
 
        if (pcmcia_validate_mem(s)) {
-               ds_dbg(3, "validating mem resources failed, "
+               ds_dev_dbg(3, &s->dev, "validating mem resources failed, "
                       "delaying card_add\n");
                return -EAGAIN; /* try again, but later... */
        }
 
        ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
        if (ret || !no_chains) {
-               ds_dbg(0, "invalid CIS or invalid resources\n");
+               ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
                return -ENODEV;
        }
 
@@ -783,7 +756,7 @@ static void pcmcia_delayed_add_device(struct work_struct *work)
 {
        struct pcmcia_socket *s =
                container_of(work, struct pcmcia_socket, device_add);
-       ds_dbg(1, "adding additional device to %d\n", s->sock);
+       ds_dev_dbg(1, &s->dev, "adding additional device to %d\n", s->sock);
        pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
        s->pcmcia_state.device_add_pending = 0;
        s->pcmcia_state.mfc_pfc = 0;
@@ -793,8 +766,7 @@ static int pcmcia_requery(struct device *dev, void * _data)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
        if (!p_dev->dev.driver) {
-               ds_dbg(1, "update device information for %s\n",
-                      p_dev->dev.bus_id);
+               ds_dev_dbg(1, dev, "update device information\n");
                pcmcia_device_query(p_dev);
        }
 
@@ -808,7 +780,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis)
        unsigned long flags;
 
        /* must be called with skt_mutex held */
-       ds_dbg(0, "re-scanning socket %d\n", skt->sock);
+       ds_dev_dbg(0, &skt->dev, "re-scanning socket %d\n", skt->sock);
 
        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
        if (list_empty(&skt->devices_list))
@@ -859,17 +831,17 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
        int ret = -ENOMEM;
        int no_funcs;
        int old_funcs;
-       cisdump_t *cis;
        cistpl_longlink_mfc_t mfc;
 
        if (!filename)
                return -EINVAL;
 
-       ds_dbg(1, "trying to load CIS file %s\n", filename);
+       ds_dev_dbg(1, &dev->dev, "trying to load CIS file %s\n", filename);
 
        if (strlen(filename) > (FIRMWARE_NAME_MAX - 1)) {
-               printk(KERN_WARNING "pcmcia: CIS filename is too long [%s]\n",
-                       filename);
+               dev_printk(KERN_WARNING, &dev->dev,
+                          "pcmcia: CIS filename is too long [%s]\n",
+                          filename);
                return -EINVAL;
        }
 
@@ -878,23 +850,16 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
        if (request_firmware(&fw, path, &dev->dev) == 0) {
                if (fw->size >= CISTPL_MAX_CIS_SIZE) {
                        ret = -EINVAL;
-                       printk(KERN_ERR "pcmcia: CIS override is too big\n");
+                       dev_printk(KERN_ERR, &dev->dev,
+                                  "pcmcia: CIS override is too big\n");
                        goto release;
                }
 
-               cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
-               if (!cis) {
-                       ret = -ENOMEM;
-                       goto release;
-               }
-
-               cis->Length = fw->size + 1;
-               memcpy(cis->Data, fw->data, fw->size);
-
-               if (!pcmcia_replace_cis(s, cis))
+               if (!pcmcia_replace_cis(s, fw->data, fw->size))
                        ret = 0;
                else {
-                       printk(KERN_ERR "pcmcia: CIS override failed\n");
+                       dev_printk(KERN_ERR, &dev->dev,
+                                  "pcmcia: CIS override failed\n");
                        goto release;
                }
 
@@ -998,14 +963,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
                 * after it has re-checked that there is no possible module
                 * with a prod_id/manf_id/card_id match.
                 */
-               ds_dbg(0, "skipping FUNC_ID match for %s until userspace "
-                      "interaction\n", dev->dev.bus_id);
+               ds_dev_dbg(0, &dev->dev,
+                       "skipping FUNC_ID match until userspace interaction\n");
                if (!dev->allow_func_id_match)
                        return 0;
        }
 
        if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
-               ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id);
+               ds_dev_dbg(0, &dev->dev, "device needs a fake CIS\n");
                if (!dev->socket->fake_cis)
                        pcmcia_load_firmware(dev, did->cisfile);
 
@@ -1037,11 +1002,9 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
        /* match dynamic devices first */
        spin_lock(&p_drv->dynids.lock);
        list_for_each_entry(dynid, &p_drv->dynids.list, node) {
-               ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
-                      drv->name);
+               ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
                if (pcmcia_devmatch(p_dev, &dynid->id)) {
-                       ds_dbg(0, "matched %s to %s\n", dev->bus_id,
-                              drv->name);
+                       ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
                        spin_unlock(&p_drv->dynids.lock);
                        return 1;
                }
@@ -1051,18 +1014,15 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
 #ifdef CONFIG_PCMCIA_IOCTL
        /* matching by cardmgr */
        if (p_dev->cardmgr == p_drv) {
-               ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id,
-                      drv->name);
+               ds_dev_dbg(0, dev, "cardmgr matched to %s\n", drv->name);
                return 1;
        }
 #endif
 
        while (did && did->match_flags) {
-               ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
-                      drv->name);
+               ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
                if (pcmcia_devmatch(p_dev, did)) {
-                       ds_dbg(0, "matched %s to %s\n", dev->bus_id,
-                              drv->name);
+                       ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
                        return 1;
                }
                did++;
@@ -1268,7 +1228,7 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
        if (p_dev->suspended)
                return 0;
 
-       ds_dbg(2, "suspending %s\n", dev->bus_id);
+       ds_dev_dbg(2, dev, "suspending\n");
 
        if (dev->driver)
                p_drv = to_pcmcia_drv(dev->driver);
@@ -1279,15 +1239,16 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
        if (p_drv->suspend) {
                ret = p_drv->suspend(p_dev);
                if (ret) {
-                       printk(KERN_ERR "pcmcia: device %s (driver %s) did "
-                              "not want to go to sleep (%d)\n",
-                              p_dev->devname, p_drv->drv.name, ret);
+                       dev_printk(KERN_ERR, dev,
+                                  "pcmcia: device %s (driver %s) did "
+                                  "not want to go to sleep (%d)\n",
+                                  p_dev->devname, p_drv->drv.name, ret);
                        goto out;
                }
        }
 
        if (p_dev->device_no == p_dev->func) {
-               ds_dbg(2, "releasing configuration for %s\n", dev->bus_id);
+               ds_dev_dbg(2, dev, "releasing configuration\n");
                pcmcia_release_configuration(p_dev);
        }
 
@@ -1307,7 +1268,7 @@ static int pcmcia_dev_resume(struct device * dev)
        if (!p_dev->suspended)
                return 0;
 
-       ds_dbg(2, "resuming %s\n", dev->bus_id);
+       ds_dev_dbg(2, dev, "resuming\n");
 
        if (dev->driver)
                p_drv = to_pcmcia_drv(dev->driver);
@@ -1316,7 +1277,7 @@ static int pcmcia_dev_resume(struct device * dev)
                goto out;
 
        if (p_dev->device_no == p_dev->func) {
-               ds_dbg(2, "requesting configuration for %s\n", dev->bus_id);
+               ds_dev_dbg(2, dev, "requesting configuration\n");
                ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
                if (ret)
                        goto out;
@@ -1358,14 +1319,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
 
 static int pcmcia_bus_resume(struct pcmcia_socket *skt)
 {
-       ds_dbg(2, "resuming socket %d\n", skt->sock);
+       ds_dev_dbg(2, &skt->dev, "resuming socket %d\n", skt->sock);
        bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
        return 0;
 }
 
 static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
 {
-       ds_dbg(2, "suspending socket %d\n", skt->sock);
+       ds_dev_dbg(2, &skt->dev, "suspending socket %d\n", skt->sock);
        if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
                             pcmcia_bus_suspend_callback)) {
                pcmcia_bus_resume(skt);
@@ -1391,13 +1352,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
        struct pcmcia_socket *s = pcmcia_get_socket(skt);
 
        if (!s) {
-               printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
-                       "failed, event 0x%x lost!\n", skt, event);
+               dev_printk(KERN_ERR, &skt->dev,
+                          "PCMCIA obtaining reference to socket "      \
+                          "failed, event 0x%x lost!\n", event);
                return -ENODEV;
        }
 
-       ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
-              event, priority, skt);
+       ds_dev_dbg(1, &skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
+                  event, priority, skt);
 
        switch (event) {
        case CS_EVENT_CARD_REMOVAL:
@@ -1472,7 +1434,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
 
        socket = pcmcia_get_socket(socket);
        if (!socket) {
-               printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
+               dev_printk(KERN_ERR, dev,
+                          "PCMCIA obtaining reference to socket failed\n");
                return -ENODEV;
        }
 
@@ -1492,7 +1455,7 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
 
        ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
        if (ret) {
-               printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+               dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n");
                pcmcia_put_socket(socket);
                return (ret);
        }
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h
deleted file mode 100644 (file)
index 3a2b25e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* ds_internal.h - internal header for 16-bit PCMCIA devices management */
-
-extern spinlock_t pcmcia_dev_list_lock;
-extern struct bus_type pcmcia_bus_type;
-
-extern struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev);
-extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
-
-struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function);
-
-extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
-
-#ifdef CONFIG_PCMCIA_IOCTL
-extern void __init pcmcia_setup_ioctl(void);
-extern void __exit pcmcia_cleanup_ioctl(void);
-extern void handle_event(struct pcmcia_socket *s, event_t event);
-extern int handle_request(struct pcmcia_socket *s, event_t event);
-#else
-static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
-static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; }
-static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; }
-#endif
index fb2bc1fb015d417c19d879378a4538bee57ee372..117dc12ab4380060889814b4ca0b1d8fffb317d0 100644 (file)
@@ -46,7 +46,6 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
-#include "cs_internal.h"
 
 #define MODNAME "hd64465_ss"
 
index 68f6b2702bc42c66f27758c3fbbd25dcb80f83bc..71653ab8489015f768459866a4ea1ff3d23e84d2 100644 (file)
@@ -63,7 +63,7 @@
 #include "vg468.h"
 #include "ricoh.h"
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static const char version[] =
 "i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
 
index 3616da22715239ca658d0bd5816e01eb170d94f5..2ab4f22c21de423a7fccb64cc6562b444e6c1b59 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "m32r_cfc.h"
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static int m32r_cfc_debug;
 module_param(m32r_cfc_debug, int, 0644);
 #define debug(lvl, fmt, arg...) do {                           \
@@ -505,7 +505,7 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)
                pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);
        }
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
        if(state->flags & SS_IOCARD){
                debug(3, ":IOCARD");
        }
index 2b42b7155e34a9571b89df20dd990bfb76b5ba46..2f108c23dbd98872dc474bf4e19f901fbab63378 100644 (file)
@@ -45,7 +45,7 @@
 
 #define PCC_DEBUG_DBEX
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static int m32r_pcc_debug;
 module_param(m32r_pcc_debug, int, 0644);
 #define debug(lvl, fmt, arg...) do {                           \
@@ -460,7 +460,7 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)
 
        pcc_set(sock,PCCSIGCR,reg);
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
        if(state->flags & SS_IOCARD){
                debug(3, ":IOCARD");
        }
index ff66604e90d4d7620fe58af4c28dec12ae874be2..d1ad0966392dc5bc4fcf31b136ff8757525a2c50 100644 (file)
@@ -64,8 +64,8 @@
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
-#ifdef PCMCIA_DEBUG
-static int pc_debug = PCMCIA_DEBUG;
+#ifdef CONFIG_PCMCIA_DEBUG
+static int pc_debug;
 module_param(pc_debug, int, 0);
 #define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);
 #else
index a234ce1967a3d7b4186a6a9993b7492a75d87c14..5554015a7813c74f7c84352aacc190345dde6da6 100644 (file)
@@ -140,7 +140,8 @@ static int o2micro_override(struct yenta_socket *socket)
                a = config_readb(socket, O2_RESERVED1);
                b = config_readb(socket, O2_RESERVED2);
 
-               printk(KERN_INFO "Yenta O2: res at 0x94/0xD4: %02x/%02x\n", a, b);
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "O2: res at 0x94/0xD4: %02x/%02x\n", a, b);
 
                switch (socket->dev->device) {
                /*
@@ -153,7 +154,9 @@ static int o2micro_override(struct yenta_socket *socket)
                case PCI_DEVICE_ID_O2_6812:
                case PCI_DEVICE_ID_O2_6832:
                case PCI_DEVICE_ID_O2_6836:
-                       printk(KERN_INFO "Yenta O2: old bridge, disabling read prefetch/write burst\n");
+                       dev_printk(KERN_INFO, &socket->dev->dev,
+                                  "Yenta O2: old bridge, disabling read "
+                                  "prefetch/write burst\n");
                        config_writeb(socket, O2_RESERVED1,
                                      a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
                        config_writeb(socket, O2_RESERVED2,
@@ -161,7 +164,8 @@ static int o2micro_override(struct yenta_socket *socket)
                        break;
 
                default:
-                       printk(KERN_INFO "Yenta O2: enabling read prefetch/write burst\n");
+                       dev_printk(KERN_INFO , &socket->dev->dev,
+                                  "O2: enabling read prefetch/write burst\n");
                        config_writeb(socket, O2_RESERVED1,
                                      a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
                        config_writeb(socket, O2_RESERVED2,
index 419f97fc9a625befbd2805ec1b0693a4bb1af6b1..1703b20cad5d215ae1a2295329d87a2b253380f1 100644 (file)
@@ -38,7 +38,6 @@
 #include <pcmcia/ss.h>
 
 #include "cs_internal.h"
-#include "ds_internal.h"
 
 static int major_dev = -1;
 
@@ -58,7 +57,7 @@ typedef struct user_info_t {
 } user_info_t;
 
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 extern int ds_pc_debug;
 
 #define ds_dbg(lvl, fmt, arg...) do {          \
@@ -149,7 +148,7 @@ static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
 
        irq = adj->resource.irq.IRQ;
        if ((irq < 0) || (irq > 15))
-               return CS_BAD_IRQ;
+               return -EINVAL;
 
        if (adj->Action != REMOVE_MANAGED_RESOURCE)
                return 0;
@@ -167,7 +166,7 @@ static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
 #else
 
 static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
-       return CS_SUCCESS;
+       return 0;
 }
 
 #endif
@@ -175,7 +174,7 @@ static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
 static int pcmcia_adjust_resource_info(adjust_t *adj)
 {
        struct pcmcia_socket *s;
-       int ret = CS_UNSUPPORTED_FUNCTION;
+       int ret = -ENOSYS;
        unsigned long flags;
 
        down_read(&pcmcia_socket_list_rwsem);
@@ -248,7 +247,7 @@ static int pccard_get_status(struct pcmcia_socket *s,
        if (s->state & SOCKET_SUSPEND)
                status->CardState |= CS_EVENT_PM_SUSPEND;
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
 
        c = (p_dev) ? p_dev->function_config : NULL;
 
@@ -274,7 +273,7 @@ static int pccard_get_status(struct pcmcia_socket *s,
                        status->CardState |=
                                (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
                }
-               return CS_SUCCESS;
+               return 0;
        }
        status->CardState |=
                (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
@@ -284,9 +283,81 @@ static int pccard_get_status(struct pcmcia_socket *s,
                (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
        status->CardState |=
                (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
-       return CS_SUCCESS;
+       return 0;
 } /* pccard_get_status */
 
+int pccard_get_configuration_info(struct pcmcia_socket *s,
+                                 struct pcmcia_device *p_dev,
+                                 config_info_t *config)
+{
+       config_t *c;
+
+       if (!(s->state & SOCKET_PRESENT))
+               return -ENODEV;
+
+
+#ifdef CONFIG_CARDBUS
+       if (s->state & SOCKET_CARDBUS) {
+               memset(config, 0, sizeof(config_info_t));
+               config->Vcc = s->socket.Vcc;
+               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+               config->Option = s->cb_dev->subordinate->number;
+               if (s->state & SOCKET_CARDBUS_CONFIG) {
+                       config->Attributes = CONF_VALID_CLIENT;
+                       config->IntType = INT_CARDBUS;
+                       config->AssignedIRQ = s->irq.AssignedIRQ;
+                       if (config->AssignedIRQ)
+                               config->Attributes |= CONF_ENABLE_IRQ;
+                       if (s->io[0].res) {
+                               config->BasePort1 = s->io[0].res->start;
+                               config->NumPorts1 = s->io[0].res->end -
+                                       config->BasePort1 + 1;
+                       }
+               }
+               return 0;
+       }
+#endif
+
+       if (p_dev) {
+               c = p_dev->function_config;
+               config->Function = p_dev->func;
+       } else {
+               c = NULL;
+               config->Function = 0;
+       }
+
+       if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
+               config->Attributes = 0;
+               config->Vcc = s->socket.Vcc;
+               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+               return 0;
+       }
+
+       config->Attributes = c->Attributes | CONF_VALID_CLIENT;
+       config->Vcc = s->socket.Vcc;
+       config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+       config->IntType = c->IntType;
+       config->ConfigBase = c->ConfigBase;
+       config->Status = c->Status;
+       config->Pin = c->Pin;
+       config->Copy = c->Copy;
+       config->Option = c->Option;
+       config->ExtStatus = c->ExtStatus;
+       config->Present = config->CardValues = c->CardValues;
+       config->IRQAttributes = c->irq.Attributes;
+       config->AssignedIRQ = s->irq.AssignedIRQ;
+       config->BasePort1 = c->io.BasePort1;
+       config->NumPorts1 = c->io.NumPorts1;
+       config->Attributes1 = c->io.Attributes1;
+       config->BasePort2 = c->io.BasePort2;
+       config->NumPorts2 = c->io.NumPorts2;
+       config->Attributes2 = c->io.Attributes2;
+       config->IOAddrLines = c->io.IOAddrLines;
+
+       return 0;
+} /* pccard_get_configuration_info */
+
+
 /*======================================================================
 
     These manage a ring buffer of events pending for one user process
@@ -764,7 +835,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
     case DS_GET_CONFIGURATION_INFO:
        if (buf->config.Function &&
           (buf->config.Function >= s->functions))
-           ret = CS_BAD_ARGS;
+           ret = -EINVAL;
        else {
            struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
            ret = pccard_get_configuration_info(s, p_dev, &buf->config);
@@ -787,15 +858,15 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        break;
     case DS_PARSE_TUPLE:
        buf->tuple.TupleData = buf->tuple_parse.data;
-       ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
+       ret = pcmcia_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
        break;
     case DS_RESET_CARD:
-       ret = pccard_reset_card(s);
+       ret = pcmcia_reset_card(s);
        break;
     case DS_GET_STATUS:
            if (buf->status.Function &&
                (buf->status.Function >= s->functions))
-                   ret = CS_BAD_ARGS;
+                   ret = -EINVAL;
            else {
                    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
                    ret = pccard_get_status(s, p_dev, &buf->status);
@@ -826,7 +897,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
            goto free_out;
        }
 
-       ret = CS_BAD_ARGS;
+       ret = -EINVAL;
 
        if (!(buf->conf_reg.Function &&
             (buf->conf_reg.Function >= s->functions))) {
@@ -867,7 +938,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
                           &buf->win_info.map);
        break;
     case DS_REPLACE_CIS:
-       ret = pcmcia_replace_cis(s, &buf->cisdump);
+       ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
        break;
     case DS_BIND_REQUEST:
        if (!capable(CAP_SYS_ADMIN)) {
@@ -889,22 +960,19 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        err = -EINVAL;
     }
 
-    if ((err == 0) && (ret != CS_SUCCESS)) {
+    if ((err == 0) && (ret != 0)) {
        ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
        switch (ret) {
-       case CS_BAD_SOCKET: case CS_NO_CARD:
-           err = -ENODEV; break;
-       case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
-       case CS_BAD_TUPLE:
-           err = -EINVAL; break;
-       case CS_IN_USE:
-           err = -EBUSY; break;
-       case CS_OUT_OF_RESOURCE:
+       case -ENODEV:
+       case -EINVAL:
+       case -EBUSY:
+       case -ENOSYS:
+           err = ret;
+           break;
+       case -ENOMEM:
            err = -ENOSPC; break;
-       case CS_NO_MORE_ITEMS:
+       case -ENOSPC:
            err = -ENODATA; break;
-       case CS_UNSUPPORTED_FUNCTION:
-           err = -ENOSYS; break;
        default:
            err = -EIO; break;
        }
index 4884a18cf9e69918c0e3371cebb5a89b944921bb..afea2b2558b5d63d3af6fe04f230011a66fdd415 100644 (file)
@@ -29,7 +29,6 @@
 #include <pcmcia/ds.h>
 
 #include "cs_internal.h"
-#include "ds_internal.h"
 
 
 /* Access speed for IO windows */
@@ -44,16 +43,17 @@ static u8 pcmcia_used_irq[NR_IRQS];
 #endif
 
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 extern int ds_pc_debug;
 
 #define ds_dbg(skt, lvl, fmt, arg...) do {                     \
        if (ds_pc_debug >= lvl)                                 \
-               printk(KERN_DEBUG "pcmcia_resource: %s: " fmt,  \
-                       cs_socket_name(skt) , ## arg);          \
+               dev_printk(KERN_DEBUG, &skt->dev,               \
+                          "pcmcia_resource: " fmt,             \
+                          ## arg);                             \
 } while (0)
 #else
-#define ds_dbg(lvl, fmt, arg...) do { } while (0)
+#define ds_dbg(skt, lvl, fmt, arg...) do { } while (0)
 #endif
 
 
@@ -168,13 +168,13 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
        u_char val;
 
        if (!p_dev || !p_dev->function_config)
-               return CS_NO_CARD;
+               return -EINVAL;
 
        s = p_dev->socket;
        c = p_dev->function_config;
 
        if (!(c->state & CONFIG_LOCKED))
-               return CS_CONFIGURATION_LOCKED;
+               return -EACCES;
 
        addr = (c->ConfigBase + reg->Offset) >> 1;
 
@@ -188,93 +188,14 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
                pcmcia_write_cis_mem(s, 1, addr, 1, &val);
                break;
        default:
-               return CS_BAD_ARGS;
+               return -EINVAL;
                break;
        }
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_access_configuration_register */
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 
 
-int pccard_get_configuration_info(struct pcmcia_socket *s,
-                                 struct pcmcia_device *p_dev,
-                                 config_info_t *config)
-{
-       config_t *c;
-
-       if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
-
-
-#ifdef CONFIG_CARDBUS
-       if (s->state & SOCKET_CARDBUS) {
-               memset(config, 0, sizeof(config_info_t));
-               config->Vcc = s->socket.Vcc;
-               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-               config->Option = s->cb_dev->subordinate->number;
-               if (s->state & SOCKET_CARDBUS_CONFIG) {
-                       config->Attributes = CONF_VALID_CLIENT;
-                       config->IntType = INT_CARDBUS;
-                       config->AssignedIRQ = s->irq.AssignedIRQ;
-                       if (config->AssignedIRQ)
-                               config->Attributes |= CONF_ENABLE_IRQ;
-                       if (s->io[0].res) {
-                               config->BasePort1 = s->io[0].res->start;
-                               config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
-                       }
-               }
-               return CS_SUCCESS;
-       }
-#endif
-
-       if (p_dev) {
-               c = p_dev->function_config;
-               config->Function = p_dev->func;
-       } else {
-               c = NULL;
-               config->Function = 0;
-       }
-
-       if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
-               config->Attributes = 0;
-               config->Vcc = s->socket.Vcc;
-               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-               return CS_SUCCESS;
-       }
-
-       config->Attributes = c->Attributes | CONF_VALID_CLIENT;
-       config->Vcc = s->socket.Vcc;
-       config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-       config->IntType = c->IntType;
-       config->ConfigBase = c->ConfigBase;
-       config->Status = c->Status;
-       config->Pin = c->Pin;
-       config->Copy = c->Copy;
-       config->Option = c->Option;
-       config->ExtStatus = c->ExtStatus;
-       config->Present = config->CardValues = c->CardValues;
-       config->IRQAttributes = c->irq.Attributes;
-       config->AssignedIRQ = s->irq.AssignedIRQ;
-       config->BasePort1 = c->io.BasePort1;
-       config->NumPorts1 = c->io.NumPorts1;
-       config->Attributes1 = c->io.Attributes1;
-       config->BasePort2 = c->io.BasePort2;
-       config->NumPorts2 = c->io.NumPorts2;
-       config->Attributes2 = c->io.Attributes2;
-       config->IOAddrLines = c->io.IOAddrLines;
-
-       return CS_SUCCESS;
-} /* pccard_get_configuration_info */
-
-int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
-                                 config_info_t *config)
-{
-       return pccard_get_configuration_info(p_dev->socket, p_dev,
-                                            config);
-}
-EXPORT_SYMBOL(pcmcia_get_configuration_info);
-
-
 /** pcmcia_get_window
  */
 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
@@ -284,12 +205,12 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
        int w;
 
        if (!s || !(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        for (w = idx; w < MAX_WIN; w++)
                if (s->state & SOCKET_WIN_REQ(w))
                        break;
        if (w == MAX_WIN)
-               return CS_NO_MORE_ITEMS;
+               return -EINVAL;
        win = &s->win[w];
        req->Base = win->ctl.res->start;
        req->Size = win->ctl.res->end - win->ctl.res->start + 1;
@@ -304,7 +225,7 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
        if (win->ctl.flags & MAP_USE_WAIT)
                req->Attributes |= WIN_USE_WAIT;
        *handle = win;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_get_window */
 EXPORT_SYMBOL(pcmcia_get_window);
 
@@ -316,10 +237,10 @@ EXPORT_SYMBOL(pcmcia_get_window);
 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
 {
        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
-               return CS_BAD_HANDLE;
+               return -EINVAL;
        req->Page = 0;
        req->CardOffset = win->ctl.card_start;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_get_mem_page */
 EXPORT_SYMBOL(pcmcia_get_mem_page);
 
@@ -328,14 +249,18 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
 {
        struct pcmcia_socket *s;
        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
-               return CS_BAD_HANDLE;
-       if (req->Page != 0)
-               return CS_BAD_PAGE;
+               return -EINVAL;
        s = win->sock;
+       if (req->Page != 0) {
+               ds_dbg(s, 0, "failure: requested page is zero\n");
+               return -EINVAL;
+       }
        win->ctl.card_start = req->CardOffset;
-       if (s->ops->set_mem_map(s, &win->ctl) != 0)
-               return CS_BAD_OFFSET;
-       return CS_SUCCESS;
+       if (s->ops->set_mem_map(s, &win->ctl) != 0) {
+               ds_dbg(s, 0, "failed to set_mem_map\n");
+               return -EIO;
+       }
+       return 0;
 } /* pcmcia_map_mem_page */
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
@@ -354,9 +279,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
        c = p_dev->function_config;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        if (!(c->state & CONFIG_LOCKED))
-               return CS_CONFIGURATION_LOCKED;
+               return -EACCES;
 
        if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
                if (mod->Attributes & CONF_ENABLE_IRQ) {
@@ -369,20 +294,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                s->ops->set_socket(s, &s->socket);
        }
 
-       if (mod->Attributes & CONF_VCC_CHANGE_VALID)
-               return CS_BAD_VCC;
+       if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
+               ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+               return -EINVAL;
+       }
 
        /* We only allow changing Vpp1 and Vpp2 to the same value */
        if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
            (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
                if (mod->Vpp1 != mod->Vpp2)
-                       return CS_BAD_VPP;
+                       ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
+                       return -EINVAL;
                s->socket.Vpp = mod->Vpp1;
-               if (s->ops->set_socket(s, &s->socket))
-                       return CS_BAD_VPP;
+               if (s->ops->set_socket(s, &s->socket)) {
+                       dev_printk(KERN_WARNING, &s->dev,
+                                  "Unable to set VPP\n");
+                       return -EIO;
+               }
        } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
-                  (mod->Attributes & CONF_VPP2_CHANGE_VALID))
-               return CS_BAD_VPP;
+                  (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
+               ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+               return -EINVAL;
+       }
 
        if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
                pccard_io_map io_off = { 0, 0, 0, 0, 1 };
@@ -406,7 +339,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 
@@ -441,7 +374,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
                        }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_configuration */
 
 
@@ -459,7 +392,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
        config_t *c = p_dev->function_config;
 
        if (!p_dev->_io )
-               return CS_BAD_HANDLE;
+               return -EINVAL;
 
        p_dev->_io = 0;
 
@@ -467,7 +400,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
            (c->io.NumPorts1 != req->NumPorts1) ||
            (c->io.BasePort2 != req->BasePort2) ||
            (c->io.NumPorts2 != req->NumPorts2))
-               return CS_BAD_ARGS;
+               return -EINVAL;
 
        c->state &= ~CONFIG_IO_REQ;
 
@@ -475,7 +408,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
        if (req->NumPorts2)
                release_io_space(s, req->BasePort2, req->NumPorts2);
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_io */
 
 
@@ -485,15 +418,19 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        config_t *c= p_dev->function_config;
 
        if (!p_dev->_irq)
-               return CS_BAD_HANDLE;
+               return -EINVAL;
        p_dev->_irq = 0;
 
        if (c->state & CONFIG_LOCKED)
-               return CS_CONFIGURATION_LOCKED;
-       if (c->irq.Attributes != req->Attributes)
-               return CS_BAD_ATTRIBUTE;
-       if (s->irq.AssignedIRQ != req->AssignedIRQ)
-               return CS_BAD_IRQ;
+               return -EACCES;
+       if (c->irq.Attributes != req->Attributes) {
+               ds_dbg(s, 0, "IRQ attributes must match assigned ones\n");
+               return -EINVAL;
+       }
+       if (s->irq.AssignedIRQ != req->AssignedIRQ) {
+               ds_dbg(s, 0, "IRQ must match assigned one\n");
+               return -EINVAL;
+       }
        if (--s->irq.Config == 0) {
                c->state &= ~CONFIG_IRQ_REQ;
                s->irq.AssignedIRQ = 0;
@@ -507,7 +444,7 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        pcmcia_used_irq[req->AssignedIRQ]--;
 #endif
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_irq */
 
 
@@ -516,10 +453,10 @@ int pcmcia_release_window(window_handle_t win)
        struct pcmcia_socket *s;
 
        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
-               return CS_BAD_HANDLE;
+               return -EINVAL;
        s = win->sock;
        if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
-               return CS_BAD_HANDLE;
+               return -EINVAL;
 
        /* Shut down memory window */
        win->ctl.flags &= ~MAP_ACTIVE;
@@ -536,7 +473,7 @@ int pcmcia_release_window(window_handle_t win)
 
        win->magic = 0;
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_window */
 EXPORT_SYMBOL(pcmcia_release_window);
 
@@ -551,18 +488,23 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        pccard_io_map iomap;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;;
 
-       if (req->IntType & INT_CARDBUS)
-               return CS_UNSUPPORTED_MODE;
+       if (req->IntType & INT_CARDBUS) {
+               ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n");
+               return -EINVAL;
+       }
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
-               return CS_CONFIGURATION_LOCKED;
+               return -EACCES;
 
        /* Do power control.  We don't allow changes in Vcc. */
        s->socket.Vpp = req->Vpp;
-       if (s->ops->set_socket(s, &s->socket))
-               return CS_BAD_VPP;
+       if (s->ops->set_socket(s, &s->socket)) {
+               dev_printk(KERN_WARNING, &s->dev,
+                          "Unable to set socket state\n");
+               return -EINVAL;
+       }
 
        /* Pick memory or I/O card, DMA mode, interrupt */
        c->IntType = req->IntType;
@@ -651,7 +593,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 
        c->state |= CONFIG_LOCKED;
        p_dev->_locked = 1;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
 
@@ -667,37 +609,48 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
        config_t *c;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
 
        if (!req)
-               return CS_UNSUPPORTED_MODE;
+               return -EINVAL;
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
-               return CS_CONFIGURATION_LOCKED;
-       if (c->state & CONFIG_IO_REQ)
-               return CS_IN_USE;
-       if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
-               return CS_BAD_ATTRIBUTE;
+               return -EACCES;
+       if (c->state & CONFIG_IO_REQ) {
+               ds_dbg(s, 0, "IO already configured\n");
+               return -EBUSY;
+       }
+       if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
+               ds_dbg(s, 0, "bad attribute setting for IO region 1\n");
+               return -EINVAL;
+       }
        if ((req->NumPorts2 > 0) &&
-           (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
-               return CS_BAD_ATTRIBUTE;
+           (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
+               ds_dbg(s, 0, "bad attribute setting for IO region 2\n");
+               return -EINVAL;
+       }
 
+       ds_dbg(s, 1, "trying to allocate resource 1\n");
        if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
-                          req->NumPorts1, req->IOAddrLines))
-               return CS_IN_USE;
+                          req->NumPorts1, req->IOAddrLines)) {
+               ds_dbg(s, 0, "allocation of resource 1 failed\n");
+               return -EBUSY;
+       }
 
        if (req->NumPorts2) {
+               ds_dbg(s, 1, "trying to allocate resource 2\n");
                if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
                                   req->NumPorts2, req->IOAddrLines)) {
+                       ds_dbg(s, 0, "allocation of resource 2 failed\n");
                        release_io_space(s, req->BasePort1, req->NumPorts1);
-                       return CS_IN_USE;
+                       return -EBUSY;
                }
        }
 
        c->io = *req;
        c->state |= CONFIG_IO_REQ;
        p_dev->_io = 1;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
 
@@ -723,16 +676,18 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 {
        struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
-       int ret = CS_IN_USE, irq = 0;
+       int ret = -EINVAL, irq = 0;
        int type;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
-               return CS_CONFIGURATION_LOCKED;
-       if (c->state & CONFIG_IRQ_REQ)
-               return CS_IN_USE;
+               return -EACCES;
+       if (c->state & CONFIG_IRQ_REQ) {
+               ds_dbg(s, 0, "IRQ already configured\n");
+               return -EBUSY;
+       }
 
        /* Decide what type of interrupt we are registering */
        type = 0;
@@ -795,15 +750,19 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        }
 
        if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
-               if (request_irq(irq, req->Handler, type,  p_dev->devname, req->Instance))
-                       return CS_IN_USE;
+               ret = request_irq(irq, req->Handler, type,
+                                 p_dev->devname, req->Instance);
+               if (ret)
+                       return ret;
        }
 
        /* Make sure the fact the request type was overridden is passed back */
        if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
                req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
-               printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n");
-               printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n");
+               dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
+                       "request for exclusive IRQ could not be fulfilled.\n");
+               dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
+                       "needs updating to supported shared IRQ lines.\n");
        }
        c->irq.Attributes = req->Attributes;
        s->irq.AssignedIRQ = req->AssignedIRQ = irq;
@@ -816,7 +775,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        pcmcia_used_irq[irq]++;
 #endif
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_irq */
 EXPORT_SYMBOL(pcmcia_request_irq);
 
@@ -834,9 +793,11 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        int w;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
-       if (req->Attributes & (WIN_PAGED | WIN_SHARED))
-               return CS_BAD_ATTRIBUTE;
+               return -ENODEV;
+       if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
+               ds_dbg(s, 0, "bad attribute setting for iomem region\n");
+               return -EINVAL;
+       }
 
        /* Window size defaults to smallest available */
        if (req->Size == 0)
@@ -844,19 +805,25 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        align = (((s->features & SS_CAP_MEM_ALIGN) ||
                  (req->Attributes & WIN_STRICT_ALIGN)) ?
                 req->Size : s->map_size);
-       if (req->Size & (s->map_size-1))
-               return CS_BAD_SIZE;
+       if (req->Size & (s->map_size-1)) {
+               ds_dbg(s, 0, "invalid map size\n");
+               return -EINVAL;
+       }
        if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
-           (req->Base & (align-1)))
-               return CS_BAD_BASE;
+           (req->Base & (align-1))) {
+               ds_dbg(s, 0, "invalid base address\n");
+               return -EINVAL;
+       }
        if (req->Base)
                align = 0;
 
        /* Allocate system memory window */
        for (w = 0; w < MAX_WIN; w++)
                if (!(s->state & SOCKET_WIN_REQ(w))) break;
-       if (w == MAX_WIN)
-               return CS_OUT_OF_RESOURCE;
+       if (w == MAX_WIN) {
+               ds_dbg(s, 0, "all windows are used already\n");
+               return -EINVAL;
+       }
 
        win = &s->win[w];
        win->magic = WINDOW_MAGIC;
@@ -867,8 +834,10 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        if (!(s->features & SS_CAP_STATIC_MAP)) {
                win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align,
                                                      (req->Attributes & WIN_MAP_BELOW_1MB), s);
-               if (!win->ctl.res)
-                       return CS_IN_USE;
+               if (!win->ctl.res) {
+                       ds_dbg(s, 0, "allocating mem region failed\n");
+                       return -EINVAL;
+               }
        }
        (*p_dev)->_win |= CLIENT_WIN_REQ(w);
 
@@ -885,8 +854,10 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        if (req->Attributes & WIN_USE_WAIT)
                win->ctl.flags |= MAP_USE_WAIT;
        win->ctl.card_start = 0;
-       if (s->ops->set_mem_map(s, &win->ctl) != 0)
-               return CS_BAD_ARGS;
+       if (s->ops->set_mem_map(s, &win->ctl) != 0) {
+               ds_dbg(s, 0, "failed to set memory mapping\n");
+               return -EIO;
+       }
        s->state |= SOCKET_WIN_REQ(w);
 
        /* Return window handle */
@@ -897,7 +868,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        }
        *wh = win;
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
 
@@ -909,3 +880,79 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
                pcmcia_release_window(p_dev->win);
 }
 EXPORT_SYMBOL(pcmcia_disable_device);
+
+
+struct pcmcia_cfg_mem {
+       tuple_t tuple;
+       cisparse_t parse;
+       u8 buf[256];
+       cistpl_cftable_entry_t dflt;
+};
+
+/**
+ * pcmcia_loop_config() - loop over configuration options
+ * @p_dev:     the struct pcmcia_device which we need to loop for.
+ * @conf_check:        function to call for each configuration option.
+ *             It gets passed the struct pcmcia_device, the CIS data
+ *             describing the configuration option, and private data
+ *             being passed to pcmcia_loop_config()
+ * @priv_data: private data to be passed to the conf_check function.
+ *
+ * pcmcia_loop_config() loops over all configuration options, and calls
+ * the driver-specific conf_check() for each one, checking whether
+ * it is a valid one.
+ */
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+                      int      (*conf_check)   (struct pcmcia_device *p_dev,
+                                                cistpl_cftable_entry_t *cfg,
+                                                cistpl_cftable_entry_t *dflt,
+                                                unsigned int vcc,
+                                                void *priv_data),
+                      void *priv_data)
+{
+       struct pcmcia_cfg_mem *cfg_mem;
+
+       tuple_t *tuple;
+       int ret = -ENODEV;
+       unsigned int vcc;
+
+       cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
+       if (cfg_mem == NULL)
+               return -ENOMEM;
+
+       /* get the current Vcc setting */
+       vcc = p_dev->socket->socket.Vcc;
+
+       tuple = &cfg_mem->tuple;
+       tuple->TupleData = cfg_mem->buf;
+       tuple->TupleDataMax = 255;
+       tuple->TupleOffset = 0;
+       tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+       tuple->Attributes = 0;
+
+       ret = pcmcia_get_first_tuple(p_dev, tuple);
+       while (!ret) {
+               cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
+
+               if (pcmcia_get_tuple_data(p_dev, tuple))
+                       goto next_entry;
+
+               if (pcmcia_parse_tuple(tuple, &cfg_mem->parse))
+                       goto next_entry;
+
+               /* default values */
+               p_dev->conf.ConfigIndex = cfg->index;
+               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+                       cfg_mem->dflt = *cfg;
+
+               ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
+               if (!ret)
+                       break;
+
+next_entry:
+               ret = pcmcia_get_next_tuple(p_dev, tuple);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(pcmcia_loop_config);
index 13f1e0fd3f31cf096b5c07cf10392278e0308bdc..bb9ddb9532e35a6790aa6f50dcaa1a5a7aba7b75 100644 (file)
@@ -36,7 +36,6 @@
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
-#include "cs_internal.h"
 #include "soc_common.h"
 #include "pxa2xx_base.h"
 
index 203e579ebbd22e77e5413f86995bce689cc87508..17f4ecf1c0c5b214af03b7188ecedca3e516d8b5 100644 (file)
@@ -122,19 +122,22 @@ static void free_region(struct resource *res)
 
 static int add_interval(struct resource_map *map, u_long base, u_long num)
 {
-    struct resource_map *p, *q;
+       struct resource_map *p, *q;
 
-    for (p = map; ; p = p->next) {
-       if ((p != map) && (p->base+p->num-1 >= base))
-           return -1;
-       if ((p->next == map) || (p->next->base > base+num-1))
-           break;
-    }
-    q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
-    if (!q) return CS_OUT_OF_RESOURCE;
-    q->base = base; q->num = num;
-    q->next = p->next; p->next = q;
-    return CS_SUCCESS;
+       for (p = map; ; p = p->next) {
+               if ((p != map) && (p->base+p->num-1 >= base))
+                       return -1;
+               if ((p->next == map) || (p->next->base > base+num-1))
+                       break;
+       }
+       q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+       if (!q) {
+               printk(KERN_WARNING "out of memory to update resources\n");
+               return -ENOMEM;
+       }
+       q->base = base; q->num = num;
+       q->next = p->next; p->next = q;
+       return 0;
 }
 
 /*====================================================================*/
@@ -166,7 +169,10 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
            } else {
                /* Split the block into two pieces */
                p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
-               if (!p) return CS_OUT_OF_RESOURCE;
+               if (!p) {
+                   printk(KERN_WARNING "out of memory to update resources\n");
+                   return -ENOMEM;
+               }
                p->base = base+num;
                p->num = q->base+q->num - p->base;
                q->num = base - q->base;
@@ -174,7 +180,7 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
            }
        }
     }
-    return CS_SUCCESS;
+    return 0;
 }
 
 /*======================================================================
@@ -194,13 +200,14 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
     int any;
     u_char *b, hole, most;
 
-    printk(KERN_INFO "cs: IO port probe %#x-%#x:",
-          base, base+num-1);
+    dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
+              base, base+num-1);
 
     /* First, what does a floating port look like? */
     b = kzalloc(256, GFP_KERNEL);
     if (!b) {
-            printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+           dev_printk(KERN_ERR, &s->dev,
+                  "do_io_probe: unable to kmalloc 256 bytes");
             return;
     }
     for (i = base, most = 0; i < base+num; i += 8) {
@@ -366,8 +373,8 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
     struct socket_data *s_data = s->resource_data;
     u_long i, j, bad, fail, step;
 
-    printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
-          base, base+num-1);
+    dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
+              base, base+num-1);
     bad = fail = 0;
     step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
     /* don't allow too large steps */
@@ -431,8 +438,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
        if (probe_mask & MEM_PROBE_HIGH) {
                if (inv_probe(s_data->mem_db.next, s) > 0)
                        return 0;
-               printk(KERN_NOTICE "cs: warning: no high memory space "
-                      "available!\n");
+               dev_printk(KERN_NOTICE, &s->dev,
+                          "cs: warning: no high memory space available!\n");
                return -ENODEV;
        }
 
@@ -794,10 +801,11 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
                if (res->flags & IORESOURCE_IO) {
                        if (res == &ioport_resource)
                                continue;
-                       printk(KERN_INFO "pcmcia: parent PCI bridge I/O "
-                               "window: 0x%llx - 0x%llx\n",
-                               (unsigned long long)res->start,
-                               (unsigned long long)res->end);
+                       dev_printk(KERN_INFO, &s->cb_dev->dev,
+                                  "pcmcia: parent PCI bridge I/O "
+                                  "window: 0x%llx - 0x%llx\n",
+                                  (unsigned long long)res->start,
+                                  (unsigned long long)res->end);
                        if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
                                done |= IORESOURCE_IO;
 
@@ -806,10 +814,11 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
                if (res->flags & IORESOURCE_MEM) {
                        if (res == &iomem_resource)
                                continue;
-                       printk(KERN_INFO "pcmcia: parent PCI bridge Memory "
-                               "window: 0x%llx - 0x%llx\n",
-                               (unsigned long long)res->start,
-                               (unsigned long long)res->end);
+                       dev_printk(KERN_INFO, &s->cb_dev->dev,
+                                  "pcmcia: parent PCI bridge Memory "
+                                  "window: 0x%llx - 0x%llx\n",
+                                  (unsigned long long)res->start,
+                                  (unsigned long long)res->end);
                        if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
                                done |= IORESOURCE_MEM;
                }
index da3972153226a019c424ae98972ae8796e274f89..f49ac6666153bca4718a4813878bb5fba5f7b429 100644 (file)
@@ -54,7 +54,7 @@
 #include <mach/pxa-regs.h>
 #endif
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 
 static int pc_debug;
 module_param(pc_debug, int, 0644);
index 91ef6a0da3ab14d84893ee47129de75876d7cf4d..38c67375f363aeb9483a5656170a453e61c4101a 100644 (file)
@@ -15,7 +15,6 @@
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
-#include "cs_internal.h"
 
 
 struct device;
@@ -137,7 +136,7 @@ extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_lev
 extern int soc_common_drv_pcmcia_remove(struct device *dev);
 
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 
 extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
                             int lvl, const char *fmt, ...);
index 006a29e91d83d58118ee8ff5a40234a45efcc85e..ff9a3bb3c88d5c26e4f619c23f444352817167d2 100644 (file)
@@ -316,27 +316,18 @@ static ssize_t pccard_store_cis(struct kobject *kobj,
                                char *buf, loff_t off, size_t count)
 {
        struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
-       cisdump_t *cis;
        int error;
 
        if (off)
                return -EINVAL;
 
-       if (count >= 0x200)
+       if (count >= CISTPL_MAX_CIS_SIZE)
                return -EINVAL;
 
        if (!(s->state & SOCKET_PRESENT))
                return -ENODEV;
 
-       cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
-       if (!cis)
-               return -ENOMEM;
-
-       cis->Length = count + 1;
-       memcpy(cis->Data, buf, count);
-
-       error = pcmcia_replace_cis(s, cis);
-       kfree(cis);
+       error = pcmcia_replace_cis(s, buf, count);
        if (error)
                return -EIO;
 
index 5792bd5c54f93a4a3a3394d665145209b2f5c5e8..2a613e920fd4d19c4b9b802ec0ce291916c85fd8 100644 (file)
@@ -55,7 +55,7 @@
 #include <pcmcia/ss.h>
 #include "tcic.h"
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 static int pc_debug;
 
 module_param(pc_debug, int, 0644);
index 129db7bd06c3661e291204f893bb4c6dedbcccd6..aaa70227bfb05ee4df811a00fc11df5670d8d50c 100644 (file)
@@ -339,8 +339,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
 
        mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
        devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
-       printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
-              pci_name(socket->dev), mfunc, devctl);
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "TI: mfunc 0x%08x, devctl 0x%02x\n", mfunc, devctl);
 
        /* make sure PCI interrupts are enabled before probing */
        ti_init(socket);
@@ -354,8 +354,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
         * We're here which means PCI interrupts are _not_ delivered. try to
         * find the right setting (all serial or parallel)
         */
-       printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n",
-              pci_name(socket->dev));
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "TI: probing PCI interrupt failed, trying to fix\n");
 
        /* for serial PCI make sure MFUNC3 is set to IRQSER */
        if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) {
@@ -379,8 +379,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
 
                                pci_irq_status = yenta_probe_cb_irq(socket);
                                if (pci_irq_status == 1) {
-                                       printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts ok\n",
-                                              pci_name(socket->dev));
+                                       dev_printk(KERN_INFO, &socket->dev->dev,
+                                           "TI: all-serial interrupts ok\n");
                                        mfunc_old = mfunc;
                                        goto out;
                                }
@@ -395,8 +395,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
                }
 
                /* serial PCI interrupts not working fall back to parallel */
-               printk(KERN_INFO "Yenta TI: socket %s falling back to parallel PCI interrupts\n",
-                      pci_name(socket->dev));
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "TI: falling back to parallel PCI interrupts\n");
                devctl &= ~TI113X_DCR_IMODE_MASK;
                devctl |= TI113X_DCR_IMODE_SERIAL; /* serial ISA could be right */
                config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
@@ -427,8 +427,8 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
        pci_irq_status = yenta_probe_cb_irq(socket);
        if (pci_irq_status == 1) {
                mfunc_old = mfunc;
-               printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n",
-                      pci_name(socket->dev));
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "TI: parallel PCI interrupts ok\n");
        } else {
                /* not working, back to old value */
                mfunc = mfunc_old;
@@ -440,8 +440,9 @@ static void ti12xx_irqroute_func0(struct yenta_socket *socket)
 out:
        if (pci_irq_status < 1) {
                socket->cb_irq = 0;
-               printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n",
-                      pci_name(socket->dev));
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "Yenta TI: no PCI interrupts. Fish. "
+                          "Please report.\n");
        }
 }
 
@@ -513,8 +514,9 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
 
        mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC);
        devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
-       printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n",
-              pci_name(socket->dev), mfunc, devctl);
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "TI: mfunc 0x%08x, devctl 0x%02x\n",
+                  mfunc, devctl);
 
        /* if IRQs are configured as tied, align irq of func1 with func0 */
        sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
@@ -533,9 +535,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
         * We're here which means PCI interrupts are _not_ delivered. try to
         * find the right setting
         */
-       printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n",
-              pci_name(socket->dev));
-
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "TI: probing PCI interrupt failed, trying to fix\n");
 
        /* if all serial: set INTRTIE, probe again */
        if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) {
@@ -544,8 +545,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
                if (ti12xx_tie_interrupts(socket, &old_irq)) {
                        pci_irq_status = yenta_probe_cb_irq(socket);
                        if (pci_irq_status == 1) {
-                               printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts, tied ok\n",
-                                      pci_name(socket->dev));
+                               dev_printk(KERN_INFO, &socket->dev->dev,
+                                       "TI: all-serial interrupts, tied ok\n");
                                goto out;
                        }
 
@@ -582,8 +583,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
 
                        pci_irq_status = yenta_probe_cb_irq(socket);
                        if (pci_irq_status == 1) {
-                               printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n",
-                                      pci_name(socket->dev));
+                               dev_printk(KERN_INFO, &socket->dev->dev,
+                                          "TI: parallel PCI interrupts ok\n");
                                goto out;
                        }
 
@@ -593,13 +594,13 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
                        if (pci_irq_status == -1)
                                goto out;
                }
-               
+
                /* still nothing: set INTRTIE */
                if (ti12xx_tie_interrupts(socket, &old_irq)) {
                        pci_irq_status = yenta_probe_cb_irq(socket);
                        if (pci_irq_status == 1) {
-                               printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts, tied ok\n",
-                                      pci_name(socket->dev));
+                               dev_printk(KERN_INFO, &socket->dev->dev,
+                                   "TI: parallel PCI interrupts, tied ok\n");
                                goto out;
                        }
 
@@ -610,8 +611,8 @@ static void ti12xx_irqroute_func1(struct yenta_socket *socket)
 out:
        if (pci_irq_status < 1) {
                socket->cb_irq = 0;
-               printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n",
-                      pci_name(socket->dev));
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "TI: no PCI interrupts. Fish. Please report.\n");
        }
 }
 
@@ -815,11 +816,13 @@ static int ti12xx_override(struct yenta_socket *socket)
        /* make sure that memory burst is active */
        val_orig = val = config_readl(socket, TI113X_SYSTEM_CONTROL);
        if (disable_clkrun && PCI_FUNC(socket->dev->devfn) == 0) {
-               printk(KERN_INFO "Yenta: Disabling CLKRUN feature\n");
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "Disabling CLKRUN feature\n");
                val |= TI113X_SCR_KEEPCLK;
        }
        if (!(val & TI122X_SCR_MRBURSTUP)) {
-               printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n");
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "Enabling burst memory read transactions\n");
                val |= TI122X_SCR_MRBURSTUP;
        }
        if (val_orig != val)
@@ -830,10 +833,12 @@ static int ti12xx_override(struct yenta_socket *socket)
         * CSC interrupts to PCI rather than INTVAL.
         */
        val = config_readb(socket, TI1250_DIAGNOSTIC);
-       printk(KERN_INFO "Yenta: Using %s to route CSC interrupts to PCI\n",
-               (val & TI1250_DIAG_PCI_CSC) ? "CSCINT" : "INTVAL");
-       printk(KERN_INFO "Yenta: Routing CardBus interrupts to %s\n",
-               (val & TI1250_DIAG_PCI_IREQ) ? "PCI" : "ISA");
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "Using %s to route CSC interrupts to PCI\n",
+                  (val & TI1250_DIAG_PCI_CSC) ? "CSCINT" : "INTVAL");
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "Routing CardBus interrupts to %s\n",
+                  (val & TI1250_DIAG_PCI_IREQ) ? "PCI" : "ISA");
 
        /* do irqrouting, depending on function */
        if (PCI_FUNC(socket->dev->devfn) == 0)
@@ -858,8 +863,9 @@ static int ti1250_override(struct yenta_socket *socket)
                diag |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
 
        if (diag != old) {
-               printk(KERN_INFO "Yenta: adjusting diagnostic: %02x -> %02x\n",
-                       old, diag);
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "adjusting diagnostic: %02x -> %02x\n",
+                          old, diag);
                config_writeb(socket, TI1250_DIAGNOSTIC, diag);
        }
 
@@ -924,7 +930,9 @@ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
                /* default to clear TLTEnable bit, old behaviour */
                test_c9 &= ~ENE_TEST_C9_TLTENABLE;
 
-       printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "EnE: chaning testregister 0xC9, %02x -> %02x\n",
+                  old_c9, test_c9);
        config_writeb(socket, ENE_TEST_C9, test_c9);
 }
 
index 0ab1fb65cdc335541ae9bb0da1668686badef607..3ecd7c99d8eb69bba960e4127037fd84886b6171 100644 (file)
@@ -38,11 +38,7 @@ static int pwr_irqs_off;
 module_param(pwr_irqs_off, bool, 0644);
 MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
 
-#if 0
-#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
-#else
-#define debug(x,args...)
-#endif
+#define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args)
 
 /* Don't ask.. */
 #define to_cycles(ns)  ((ns)/120)
@@ -69,13 +65,13 @@ MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation");
 static inline u32 cb_readl(struct yenta_socket *socket, unsigned reg)
 {
        u32 val = readl(socket->base + reg);
-       debug("%p %04x %08x\n", socket, reg, val);
+       debug("%04x %08x\n", socket, reg, val);
        return val;
 }
 
 static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
-       debug("%p %04x %08x\n", socket, reg, val);
+       debug("%04x %08x\n", socket, reg, val);
        writel(val, socket->base + reg);
        readl(socket->base + reg); /* avoid problems with PCI write posting */
 }
@@ -84,7 +80,7 @@ static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
 {
        u8 val;
        pci_read_config_byte(socket->dev, offset, &val);
-       debug("%p %04x %02x\n", socket, offset, val);
+       debug("%04x %02x\n", socket, offset, val);
        return val;
 }
 
@@ -92,7 +88,7 @@ static inline u16 config_readw(struct yenta_socket *socket, unsigned offset)
 {
        u16 val;
        pci_read_config_word(socket->dev, offset, &val);
-       debug("%p %04x %04x\n", socket, offset, val);
+       debug("%04x %04x\n", socket, offset, val);
        return val;
 }
 
@@ -100,32 +96,32 @@ static inline u32 config_readl(struct yenta_socket *socket, unsigned offset)
 {
        u32 val;
        pci_read_config_dword(socket->dev, offset, &val);
-       debug("%p %04x %08x\n", socket, offset, val);
+       debug("%04x %08x\n", socket, offset, val);
        return val;
 }
 
 static inline void config_writeb(struct yenta_socket *socket, unsigned offset, u8 val)
 {
-       debug("%p %04x %02x\n", socket, offset, val);
+       debug("%04x %02x\n", socket, offset, val);
        pci_write_config_byte(socket->dev, offset, val);
 }
 
 static inline void config_writew(struct yenta_socket *socket, unsigned offset, u16 val)
 {
-       debug("%p %04x %04x\n", socket, offset, val);
+       debug("%04x %04x\n", socket, offset, val);
        pci_write_config_word(socket->dev, offset, val);
 }
 
 static inline void config_writel(struct yenta_socket *socket, unsigned offset, u32 val)
 {
-       debug("%p %04x %08x\n", socket, offset, val);
+       debug("%04x %08x\n", socket, offset, val);
        pci_write_config_dword(socket->dev, offset, val);
 }
 
 static inline u8 exca_readb(struct yenta_socket *socket, unsigned reg)
 {
        u8 val = readb(socket->base + 0x800 + reg);
-       debug("%p %04x %02x\n", socket, reg, val);
+       debug("%04x %02x\n", socket, reg, val);
        return val;
 }
 
@@ -134,20 +130,20 @@ static inline u8 exca_readw(struct yenta_socket *socket, unsigned reg)
        u16 val;
        val = readb(socket->base + 0x800 + reg);
        val |= readb(socket->base + 0x800 + reg + 1) << 8;
-       debug("%p %04x %04x\n", socket, reg, val);
+       debug("%04x %04x\n", socket, reg, val);
        return val;
 }
 
 static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val)
 {
-       debug("%p %04x %02x\n", socket, reg, val);
+       debug("%04x %02x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
        readb(socket->base + 0x800 + reg); /* PCI write posting... */
 }
 
 static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
 {
-       debug("%p %04x %04x\n", socket, reg, val);
+       debug("%04x %04x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
        writeb(val >> 8, socket->base + 0x800 + reg + 1);
 
@@ -207,7 +203,7 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
 
 
        if (state & CB_CBCARD) {
-               val |= SS_CARDBUS;      
+               val |= SS_CARDBUS;
                val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
                val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
                val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
@@ -650,8 +646,10 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
                root = pci_find_parent_resource(socket->dev, res);
                if (root && (request_resource(root, res) == 0))
                        return 0;
-               printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
-                               pci_name(socket->dev), nr);
+               dev_printk(KERN_INFO, &socket->dev->dev,
+                          "Preassigned resource %d busy or not available, "
+                          "reconfiguring...\n",
+                          nr);
        }
 
        if (type & IORESOURCE_IO) {
@@ -674,8 +672,9 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
                        return 1;
        }
 
-       printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
-              pci_name(socket->dev), type);
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "no resource of type %x available, trying to continue...\n",
+                  type);
        res->start = res->end = res->flags = 0;
        return 0;
 }
@@ -923,7 +922,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
        socket->probe_status = 0;
 
        if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) {
-               printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
+               dev_printk(KERN_WARNING, &socket->dev->dev,
+                          "request_irq() in yenta_probe_cb_irq() failed!\n");
                return -1;
        }
 
@@ -960,8 +960,9 @@ static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_i
        else
                socket->socket.irq_mask = 0;
 
-       printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
-              socket->socket.irq_mask, socket->cb_irq);
+       dev_printk(KERN_INFO, &socket->dev->dev,
+                  "ISA IRQ mask 0x%04x, PCI irq %d\n",
+                  socket->socket.irq_mask, socket->cb_irq);
 }
 
 /*
@@ -1051,8 +1052,9 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
 
        /* Show that the wanted subordinate number is not possible: */
        if (cardbus_bridge->subordinate > upper_limit)
-               printk(KERN_WARNING "Yenta: Upper limit for fixing this "
-                       "bridge's parent bridge: #%02x\n", upper_limit);
+               dev_printk(KERN_WARNING, &cardbus_bridge->dev,
+                          "Upper limit for fixing this "
+                          "bridge's parent bridge: #%02x\n", upper_limit);
 
        /* If we have room to increase the bridge's subordinate number, */
        if (bridge_to_fix->subordinate < upper_limit) {
@@ -1061,10 +1063,11 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
                unsigned char subordinate_to_assign =
                        min(cardbus_bridge->subordinate, upper_limit);
 
-               printk(KERN_INFO "Yenta: Raising subordinate bus# of parent "
-                       "bus (#%02x) from #%02x to #%02x\n",
-                       bridge_to_fix->number,
-                       bridge_to_fix->subordinate, subordinate_to_assign);
+               dev_printk(KERN_INFO, &bridge_to_fix->dev,
+                          "Raising subordinate bus# of parent "
+                          "bus (#%02x) from #%02x to #%02x\n",
+                          bridge_to_fix->number,
+                          bridge_to_fix->subordinate, subordinate_to_assign);
 
                /* Save the new subordinate in the bus struct of the bridge */
                bridge_to_fix->subordinate = subordinate_to_assign;
@@ -1091,8 +1094,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
         * Bail out if so.
         */
        if (!dev->subordinate) {
-               printk(KERN_ERR "Yenta: no bus associated with %s! "
-                       "(try 'pci=assign-busses')\n", pci_name(dev));
+               dev_printk(KERN_ERR, &dev->dev, "no bus associated! "
+                          "(try 'pci=assign-busses')\n");
                return -ENODEV;
        }
 
@@ -1127,7 +1130,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
                goto disable;
 
        if (!pci_resource_start(dev, 0)) {
-               printk(KERN_ERR "No cardbus resource!\n");
+               dev_printk(KERN_ERR, &dev->dev, "No cardbus resource!\n");
                ret = -ENODEV;
                goto release;
        }
@@ -1146,8 +1149,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
         * report the subsystem vendor and device for help debugging
         * the irq stuff...
         */
-       printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n",
-               pci_name(dev), dev->subsystem_vendor, dev->subsystem_device);
+       dev_printk(KERN_INFO, &dev->dev, "CardBus bridge found [%04x:%04x]\n",
+                  dev->subsystem_vendor, dev->subsystem_device);
 
        yenta_config_init(socket);
 
@@ -1179,8 +1182,12 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
                socket->poll_timer.data = (unsigned long)socket;
                socket->poll_timer.expires = jiffies + HZ;
                add_timer(&socket->poll_timer);
-               printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n"
-                      KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n");
+               dev_printk(KERN_INFO, &dev->dev,
+                          "no PCI IRQ, CardBus support disabled for this "
+                          "socket.\n");
+               dev_printk(KERN_INFO, &dev->dev,
+                          "check your BIOS CardBus, BIOS IRQ or ACPI "
+                          "settings.\n");
        } else {
                socket->socket.features |= SS_CAP_CARDBUS;
        }
@@ -1188,7 +1195,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
        /* Figure out what the dang thing can do for the PCMCIA layer... */
        yenta_interrogate(socket);
        yenta_get_socket_capabilities(socket, isa_interrupts);
-       printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
+       dev_printk(KERN_INFO, &dev->dev,
+                  "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 
        yenta_fixup_parent_bridge(dev->subordinate);
 
index 9fd7bb9b7dce2579d1955a055ad5bf362f0e14b2..3b8b9d3cb03d6cc2f8738e67abd145ff09a4285f 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 extern spinlock_t pnp_lock;
+extern struct device_attribute pnp_interface_attrs[];
 void *pnp_alloc(long size);
 
 int pnp_register_protocol(struct pnp_protocol *protocol);
@@ -16,7 +17,6 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 
 int pnp_add_device(struct pnp_dev *dev);
 struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
-int pnp_interface_attach_device(struct pnp_dev *dev);
 
 int pnp_add_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);
@@ -147,7 +147,7 @@ char *pnp_resource_type_name(struct resource *res);
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
 
 void pnp_free_resources(struct pnp_dev *dev);
-int pnp_resource_type(struct resource *res);
+unsigned long pnp_resource_type(struct resource *res);
 
 struct pnp_resource {
        struct list_head list;
index a411582bcd72d3caf7638fc1ede2a0747498af6e..817fe626e15b2d78a5cfa32ab7f26e761ee37009 100644 (file)
@@ -159,21 +159,13 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
 
 int __pnp_add_device(struct pnp_dev *dev)
 {
-       int ret;
-
        pnp_fixup_device(dev);
        dev->status = PNP_READY;
        spin_lock(&pnp_lock);
        list_add_tail(&dev->global_list, &pnp_global);
        list_add_tail(&dev->protocol_list, &dev->protocol->devices);
        spin_unlock(&pnp_lock);
-
-       ret = device_register(&dev->dev);
-       if (ret)
-               return ret;
-
-       pnp_interface_attach_device(dev);
-       return 0;
+       return device_register(&dev->dev);
 }
 
 /*
@@ -218,7 +210,6 @@ void __pnp_remove_device(struct pnp_dev *dev)
 
 static int __init pnp_init(void)
 {
-       printk(KERN_INFO "Linux Plug and Play Support v0.97 (c) Adam Belay\n");
        return bus_register(&pnp_bus_type);
 }
 
index d3f869ee1d92a5b8e90919b6df880efb7ec73ee8..e3f7e89c4dfb29a794a86a40a8bcf088550c032f 100644 (file)
@@ -206,6 +206,7 @@ struct bus_type pnp_bus_type = {
        .remove  = pnp_device_remove,
        .suspend = pnp_bus_suspend,
        .resume  = pnp_bus_resume,
+       .dev_attrs = pnp_interface_attrs,
 };
 
 int pnp_register_driver(struct pnp_driver *drv)
index a876ecf7028c06c003d5fc1aed974bb9f5f97f98..478a4a739c00dabdc3ccf3a4689b2e84c32d5ce6 100644 (file)
@@ -243,8 +243,6 @@ static ssize_t pnp_show_options(struct device *dmdev,
        return ret;
 }
 
-static DEVICE_ATTR(options, S_IRUGO, pnp_show_options, NULL);
-
 static ssize_t pnp_show_current_resources(struct device *dmdev,
                                          struct device_attribute *attr,
                                          char *buf)
@@ -420,9 +418,6 @@ done:
        return count;
 }
 
-static DEVICE_ATTR(resources, S_IRUGO | S_IWUSR,
-                  pnp_show_current_resources, pnp_set_current_resources);
-
 static ssize_t pnp_show_current_ids(struct device *dmdev,
                                    struct device_attribute *attr, char *buf)
 {
@@ -437,27 +432,11 @@ static ssize_t pnp_show_current_ids(struct device *dmdev,
        return (str - buf);
 }
 
-static DEVICE_ATTR(id, S_IRUGO, pnp_show_current_ids, NULL);
-
-int pnp_interface_attach_device(struct pnp_dev *dev)
-{
-       int rc = device_create_file(&dev->dev, &dev_attr_options);
-
-       if (rc)
-               goto err;
-       rc = device_create_file(&dev->dev, &dev_attr_resources);
-       if (rc)
-               goto err_opt;
-       rc = device_create_file(&dev->dev, &dev_attr_id);
-       if (rc)
-               goto err_res;
-
-       return 0;
-
-err_res:
-       device_remove_file(&dev->dev, &dev_attr_resources);
-err_opt:
-       device_remove_file(&dev->dev, &dev_attr_options);
-err:
-       return rc;
-}
+struct device_attribute pnp_interface_attrs[] = {
+       __ATTR(resources, S_IRUGO | S_IWUSR,
+                  pnp_show_current_resources,
+                  pnp_set_current_resources),
+       __ATTR(options, S_IRUGO, pnp_show_options, NULL),
+       __ATTR(id, S_IRUGO, pnp_show_current_ids, NULL),
+       __ATTR_NULL,
+};
index 101a835e8759fb3f757d72426cfc05c2d678865c..46455fbab6d51f6dae89b6b68da5a4b2f34f4851 100644 (file)
@@ -1012,7 +1012,7 @@ static int __init isapnp_init(void)
                printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
                return 0;
        }
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
        if (check_legacy_ioport(_PIDXR) || check_legacy_ioport(_PNPWRP))
                return -EINVAL;
 #endif
index 662dfcddedc62fce03362f72cd79c421f6542a37..2bfe13369df5e75d36d58bb1674646bc424bcfac 100644 (file)
@@ -519,7 +519,7 @@ static int __init pnpbios_init(void)
 {
        int ret;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
        if (check_legacy_ioport(PNPBIOS_BASE))
                return -ENODEV;
 #endif
@@ -577,7 +577,7 @@ static int __init pnpbios_thread_init(void)
 {
        struct task_struct *task;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
        if (check_legacy_ioport(PNPBIOS_BASE))
                return 0;
 #endif
index 0bdf9b8a5e58593d308ecc95f25fb7d2209e2998..c144bd575611f300249923264f065741957e9bb3 100644 (file)
@@ -245,7 +245,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
         */
        for_each_pci_dev(pdev) {
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-                       unsigned int type;
+                       unsigned long type;
 
                        type = pci_resource_flags(pdev, i) &
                                        (IORESOURCE_IO | IORESOURCE_MEM);
@@ -338,8 +338,7 @@ void pnp_fixup_device(struct pnp_dev *dev)
                if (!compare_pnp_id(dev->id, f->id))
                        continue;
 #ifdef DEBUG
-               dev_dbg(&dev->dev, "%s: calling ", f->id);
-               print_fn_descriptor_symbol("%s\n", f->quirk_function);
+               dev_dbg(&dev->dev, "%s: calling %pF\n", f->id, f->quirk_function);
 #endif
                f->quirk_function(dev);
        }
index 4cfe3a1efdfbc24a213abc838dab1631abf9f5d4..dbae23acdd5b12e1df4a83164dbec01a4c6d7a54 100644 (file)
@@ -467,14 +467,14 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 #endif
 }
 
-int pnp_resource_type(struct resource *res)
+unsigned long pnp_resource_type(struct resource *res)
 {
        return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
                             IORESOURCE_IRQ | IORESOURCE_DMA);
 }
 
 struct resource *pnp_get_resource(struct pnp_dev *dev,
-                                 unsigned int type, unsigned int num)
+                                 unsigned long type, unsigned int num)
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
index 32570af3c5c904fa86cffe26efbcc7650757d474..5fbca2681baaeb112ef0ae789ddd6aabb2a63156 100644 (file)
@@ -205,9 +205,9 @@ static int olpc_bat_get_property(struct power_supply *psy,
                                 union power_supply_propval *val)
 {
        int ret = 0;
-       int16_t ec_word;
+       __be16 ec_word;
        uint8_t ec_byte;
-       uint64_t ser_buf;
+       __be64 ser_buf;
 
        ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
        if (ret)
@@ -257,16 +257,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               ec_word = be16_to_cpu(ec_word);
-               val->intval = ec_word * 9760L / 32;
+               val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32;
                break;
        case POWER_SUPPLY_PROP_CURRENT_AVG:
                ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               ec_word = be16_to_cpu(ec_word);
-               val->intval = ec_word * 15625L / 120;
+               val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -278,24 +276,22 @@ static int olpc_bat_get_property(struct power_supply *psy,
                ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
-               ec_word = be16_to_cpu(ec_word);
-               val->intval = ec_word * 100 / 256;
+
+               val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
                break;
        case POWER_SUPPLY_PROP_TEMP_AMBIENT:
                ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               ec_word = be16_to_cpu(ec_word);
-               val->intval = ec_word * 100 / 256;
+               val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
                break;
        case POWER_SUPPLY_PROP_CHARGE_COUNTER:
                ret = olpc_ec_cmd(EC_BAT_ACR, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               ec_word = be16_to_cpu(ec_word);
-               val->intval = ec_word * 6250 / 15;
+               val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15;
                break;
        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
                ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
index cb1ccb4729210c1a3cfd8901bf7dea5c56117146..3007695f90c822e067a31e3c44da67d4598ff2e7 100644 (file)
@@ -91,8 +91,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
 {
        int rc = 0;
 
-       psy->dev = device_create_drvdata(power_supply_class, parent, 0,
-                                        psy, "%s", psy->name);
+       psy->dev = device_create(power_supply_class, parent, 0, psy,
+                                "%s", psy->name);
        if (IS_ERR(psy->dev)) {
                rc = PTR_ERR(psy->dev);
                goto dev_create_failed;
index a656128f1fdd80c70f01f1ec4f128b6b2aacb954..4dada6ee1119464a7d3136bfb47d3805c605d0c4 100644 (file)
@@ -56,4 +56,28 @@ config REGULATOR_BQ24022
          charging select between 100 mA and 500 mA charging current
          limit.
 
+config REGULATOR_WM8350
+       tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
+       depends on MFD_WM8350
+       select REGULATOR
+       help
+         This driver provides support for the voltage and current regulators
+          of the WM8350 AudioPlus PMIC.
+
+config REGULATOR_WM8400
+       tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
+       depends on MFD_WM8400
+       select REGULATOR
+       help
+         This driver provides support for the voltage regulators of the
+         WM8400 AudioPlus PMIC.
+
+config REGULATOR_DA903X
+       tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
+       depends on PMIC_DA903X
+       select REGULATOR
+       help
+         Say y here to support the BUCKs and LDOs regulators found on
+         Dialog Semiconductor DA9030/DA9034 PMIC.
+
 endmenu
index ac2c64efe65c6478a851aecb11cb9eb4f793466e..254d40c02ee8cefd29e4f332f12b6c99603d705d 100644 (file)
@@ -8,5 +8,8 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
+obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
+obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
index 263699d6152d2b662e1889df0cd37235c51c664c..366565aba865380672a3ed0e2e04e07b98d40238 100644 (file)
 #include <linux/regulator/bq24022.h>
 #include <linux/regulator/driver.h>
 
+
 static int bq24022_set_current_limit(struct regulator_dev *rdev,
                                        int min_uA, int max_uA)
 {
-       struct platform_device *pdev = rdev_get_drvdata(rdev);
-       struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+       struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-       dev_dbg(&pdev->dev, "setting current limit to %s mA\n",
+       dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n",
                max_uA >= 500000 ? "500" : "100");
 
        /* REVISIT: maybe return error if min_uA != 0 ? */
@@ -34,18 +34,16 @@ static int bq24022_set_current_limit(struct regulator_dev *rdev,
 
 static int bq24022_get_current_limit(struct regulator_dev *rdev)
 {
-       struct platform_device *pdev = rdev_get_drvdata(rdev);
-       struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+       struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
        return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000;
 }
 
 static int bq24022_enable(struct regulator_dev *rdev)
 {
-       struct platform_device *pdev = rdev_get_drvdata(rdev);
-       struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+       struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-       dev_dbg(&pdev->dev, "enabling charger\n");
+       dev_dbg(rdev_get_dev(rdev), "enabling charger\n");
 
        gpio_set_value(pdata->gpio_nce, 0);
        return 0;
@@ -53,10 +51,9 @@ static int bq24022_enable(struct regulator_dev *rdev)
 
 static int bq24022_disable(struct regulator_dev *rdev)
 {
-       struct platform_device *pdev = rdev_get_drvdata(rdev);
-       struct bq24022_mach_info *pdata = pdev->dev.platform_data;
+       struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev);
 
-       dev_dbg(&pdev->dev, "disabling charger\n");
+       dev_dbg(rdev_get_dev(rdev), "disabling charger\n");
 
        gpio_set_value(pdata->gpio_nce, 1);
        return 0;
@@ -108,7 +105,7 @@ static int __init bq24022_probe(struct platform_device *pdev)
        ret = gpio_direction_output(pdata->gpio_iset2, 0);
        ret = gpio_direction_output(pdata->gpio_nce, 1);
 
-       bq24022 = regulator_register(&bq24022_desc, pdev);
+       bq24022 = regulator_register(&bq24022_desc, &pdev->dev, pdata);
        if (IS_ERR(bq24022)) {
                dev_dbg(&pdev->dev, "couldn't register regulator\n");
                ret = PTR_ERR(bq24022);
index 9c79862615685d39d92f7e2b73cd2a8638bf21d7..02a774424e8de2bbade4eafeaadf6b8160fc05ef 100644 (file)
@@ -2,8 +2,9 @@
  * core.c  --  Voltage/Current Regulator framework.
  *
  * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
  *
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
@@ -64,14 +65,9 @@ struct regulator_map {
        struct list_head list;
        struct device *dev;
        const char *supply;
-       const char *regulator;
+       struct regulator_dev *regulator;
 };
 
-static inline struct regulator_dev *to_rdev(struct device *d)
-{
-       return container_of(d, struct regulator_dev, dev);
-}
-
 /*
  * struct regulator
  *
@@ -227,7 +223,7 @@ static ssize_t device_requested_uA_show(struct device *dev,
 static ssize_t regulator_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        ssize_t ret;
 
        mutex_lock(&rdev->mutex);
@@ -240,15 +236,31 @@ static ssize_t regulator_uV_show(struct device *dev,
 static ssize_t regulator_uA_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
 }
 
+static ssize_t regulator_name_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
+       const char *name;
+
+       if (rdev->constraints->name)
+               name = rdev->constraints->name;
+       else if (rdev->desc->name)
+               name = rdev->desc->name;
+       else
+               name = "";
+
+       return sprintf(buf, "%s\n", name);
+}
+
 static ssize_t regulator_opmode_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        int mode = _regulator_get_mode(rdev);
 
        switch (mode) {
@@ -267,7 +279,7 @@ static ssize_t regulator_opmode_show(struct device *dev,
 static ssize_t regulator_state_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        int state = _regulator_is_enabled(rdev);
 
        if (state > 0)
@@ -281,7 +293,7 @@ static ssize_t regulator_state_show(struct device *dev,
 static ssize_t regulator_min_uA_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "constraint not defined\n");
@@ -292,7 +304,7 @@ static ssize_t regulator_min_uA_show(struct device *dev,
 static ssize_t regulator_max_uA_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "constraint not defined\n");
@@ -303,7 +315,7 @@ static ssize_t regulator_max_uA_show(struct device *dev,
 static ssize_t regulator_min_uV_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "constraint not defined\n");
@@ -314,7 +326,7 @@ static ssize_t regulator_min_uV_show(struct device *dev,
 static ssize_t regulator_max_uV_show(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "constraint not defined\n");
@@ -325,7 +337,7 @@ static ssize_t regulator_max_uV_show(struct device *dev,
 static ssize_t regulator_total_uA_show(struct device *dev,
                                      struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        struct regulator *regulator;
        int uA = 0;
 
@@ -339,14 +351,14 @@ static ssize_t regulator_total_uA_show(struct device *dev,
 static ssize_t regulator_num_users_show(struct device *dev,
                                      struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        return sprintf(buf, "%d\n", rdev->use_count);
 }
 
 static ssize_t regulator_type_show(struct device *dev,
                                  struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        switch (rdev->desc->type) {
        case REGULATOR_VOLTAGE:
@@ -360,7 +372,7 @@ static ssize_t regulator_type_show(struct device *dev,
 static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -370,7 +382,7 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
 static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -380,7 +392,7 @@ static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
 static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -406,7 +418,7 @@ static ssize_t suspend_opmode_show(struct regulator_dev *rdev,
 static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -417,7 +429,7 @@ static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
 static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -428,7 +440,7 @@ static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
 static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -439,7 +451,7 @@ static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
 static ssize_t regulator_suspend_mem_state_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -453,7 +465,7 @@ static ssize_t regulator_suspend_mem_state_show(struct device *dev,
 static ssize_t regulator_suspend_disk_state_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -467,7 +479,7 @@ static ssize_t regulator_suspend_disk_state_show(struct device *dev,
 static ssize_t regulator_suspend_standby_state_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
 
        if (!rdev->constraints)
                return sprintf(buf, "not defined\n");
@@ -477,7 +489,9 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev,
        else
                return sprintf(buf, "disabled\n");
 }
+
 static struct device_attribute regulator_dev_attrs[] = {
+       __ATTR(name, 0444, regulator_name_show, NULL),
        __ATTR(microvolts, 0444, regulator_uV_show, NULL),
        __ATTR(microamps, 0444, regulator_uA_show, NULL),
        __ATTR(opmode, 0444, regulator_opmode_show, NULL),
@@ -512,7 +526,7 @@ static struct device_attribute regulator_dev_attrs[] = {
 
 static void regulator_dev_release(struct device *dev)
 {
-       struct regulator_dev *rdev = to_rdev(dev);
+       struct regulator_dev *rdev = dev_get_drvdata(dev);
        kfree(rdev);
 }
 
@@ -569,8 +583,11 @@ static int suspend_set_state(struct regulator_dev *rdev,
 
        /* enable & disable are mandatory for suspend control */
        if (!rdev->desc->ops->set_suspend_enable ||
-               !rdev->desc->ops->set_suspend_disable)
+               !rdev->desc->ops->set_suspend_disable) {
+               printk(KERN_ERR "%s: no way to set suspend state\n",
+                       __func__);
                return -EINVAL;
+       }
 
        if (rstate->enabled)
                ret = rdev->desc->ops->set_suspend_enable(rdev);
@@ -656,6 +673,155 @@ static void print_constraints(struct regulator_dev *rdev)
        printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
 }
 
+/**
+ * set_machine_constraints - sets regulator constraints
+ * @regulator: regulator source
+ *
+ * Allows platform initialisation code to define and constrain
+ * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
+ * Constraints *must* be set by platform code in order for some
+ * regulator operations to proceed i.e. set_voltage, set_current_limit,
+ * set_mode.
+ */
+static int set_machine_constraints(struct regulator_dev *rdev,
+       struct regulation_constraints *constraints)
+{
+       int ret = 0;
+       const char *name;
+       struct regulator_ops *ops = rdev->desc->ops;
+
+       if (constraints->name)
+               name = constraints->name;
+       else if (rdev->desc->name)
+               name = rdev->desc->name;
+       else
+               name = "regulator";
+
+       rdev->constraints = constraints;
+
+       /* do we need to apply the constraint voltage */
+       if (rdev->constraints->apply_uV &&
+               rdev->constraints->min_uV == rdev->constraints->max_uV &&
+               ops->set_voltage) {
+               ret = ops->set_voltage(rdev,
+                       rdev->constraints->min_uV, rdev->constraints->max_uV);
+                       if (ret < 0) {
+                               printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
+                                      __func__,
+                                      rdev->constraints->min_uV, name);
+                               rdev->constraints = NULL;
+                               goto out;
+                       }
+       }
+
+       /* are we enabled at boot time by firmware / bootloader */
+       if (rdev->constraints->boot_on)
+               rdev->use_count = 1;
+
+       /* do we need to setup our suspend state */
+       if (constraints->initial_state) {
+               ret = suspend_prepare(rdev, constraints->initial_state);
+               if (ret < 0) {
+                       printk(KERN_ERR "%s: failed to set suspend state for %s\n",
+                              __func__, name);
+                       rdev->constraints = NULL;
+                       goto out;
+               }
+       }
+
+       /* if always_on is set then turn the regulator on if it's not
+        * already on. */
+       if (constraints->always_on && ops->enable &&
+           ((ops->is_enabled && !ops->is_enabled(rdev)) ||
+            (!ops->is_enabled && !constraints->boot_on))) {
+               ret = ops->enable(rdev);
+               if (ret < 0) {
+                       printk(KERN_ERR "%s: failed to enable %s\n",
+                              __func__, name);
+                       rdev->constraints = NULL;
+                       goto out;
+               }
+       }
+
+       print_constraints(rdev);
+out:
+       return ret;
+}
+
+/**
+ * set_supply - set regulator supply regulator
+ * @regulator: regulator name
+ * @supply: supply regulator name
+ *
+ * Called by platform initialisation code to set the supply regulator for this
+ * regulator. This ensures that a regulators supply will also be enabled by the
+ * core if it's child is enabled.
+ */
+static int set_supply(struct regulator_dev *rdev,
+       struct regulator_dev *supply_rdev)
+{
+       int err;
+
+       err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
+                               "supply");
+       if (err) {
+               printk(KERN_ERR
+                      "%s: could not add device link %s err %d\n",
+                      __func__, supply_rdev->dev.kobj.name, err);
+                      goto out;
+       }
+       rdev->supply = supply_rdev;
+       list_add(&rdev->slist, &supply_rdev->supply_list);
+out:
+       return err;
+}
+
+/**
+ * set_consumer_device_supply: Bind a regulator to a symbolic supply
+ * @regulator: regulator source
+ * @dev:       device the supply applies to
+ * @supply:    symbolic name for supply
+ *
+ * Allows platform initialisation code to map physical regulator
+ * sources to symbolic names for supplies for use by devices.  Devices
+ * should use these symbolic names to request regulators, avoiding the
+ * need to provide board-specific regulator names as platform data.
+ */
+static int set_consumer_device_supply(struct regulator_dev *rdev,
+       struct device *consumer_dev, const char *supply)
+{
+       struct regulator_map *node;
+
+       if (supply == NULL)
+               return -EINVAL;
+
+       node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
+       if (node == NULL)
+               return -ENOMEM;
+
+       node->regulator = rdev;
+       node->dev = consumer_dev;
+       node->supply = supply;
+
+       list_add(&node->list, &regulator_map_list);
+       return 0;
+}
+
+static void unset_consumer_device_supply(struct regulator_dev *rdev,
+       struct device *consumer_dev)
+{
+       struct regulator_map *node, *n;
+
+       list_for_each_entry_safe(node, n, &regulator_map_list, list) {
+               if (rdev == node->regulator &&
+                       consumer_dev == node->dev) {
+                       list_del(&node->list);
+                       kfree(node);
+                       return;
+               }
+       }
+}
+
 #define REG_STR_SIZE   32
 
 static struct regulator *create_regulator(struct regulator_dev *rdev,
@@ -746,7 +912,6 @@ struct regulator *regulator_get(struct device *dev, const char *id)
        struct regulator_dev *rdev;
        struct regulator_map *map;
        struct regulator *regulator = ERR_PTR(-ENODEV);
-       const char *supply = id;
 
        if (id == NULL) {
                printk(KERN_ERR "regulator: get() with no identifier\n");
@@ -758,15 +923,9 @@ struct regulator *regulator_get(struct device *dev, const char *id)
        list_for_each_entry(map, &regulator_map_list, list) {
                if (dev == map->dev &&
                    strcmp(map->supply, id) == 0) {
-                       supply = map->regulator;
-                       break;
-               }
-       }
-
-       list_for_each_entry(rdev, &regulator_list, list) {
-               if (strcmp(supply, rdev->desc->name) == 0 &&
-                   try_module_get(rdev->owner))
+                       rdev = map->regulator;
                        goto found;
+               }
        }
        printk(KERN_ERR "regulator: Unable to get requested regulator: %s\n",
               id);
@@ -774,12 +933,16 @@ struct regulator *regulator_get(struct device *dev, const char *id)
        return regulator;
 
 found:
+       if (!try_module_get(rdev->owner))
+               goto out;
+
        regulator = create_regulator(rdev, dev, id);
        if (regulator == NULL) {
                regulator = ERR_PTR(-ENOMEM);
                module_put(rdev->owner);
        }
 
+out:
        mutex_unlock(&regulator_list_mutex);
        return regulator;
 }
@@ -1559,11 +1722,12 @@ EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
  * Returns 0 on success.
  */
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-                                         void *reg_data)
+       struct device *dev, void *driver_data)
 {
        static atomic_t regulator_no = ATOMIC_INIT(0);
        struct regulator_dev *rdev;
-       int ret;
+       struct regulator_init_data *init_data = dev->platform_data;
+       int ret, i;
 
        if (regulator_desc == NULL)
                return ERR_PTR(-EINVAL);
@@ -1575,6 +1739,9 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
            !regulator_desc->type == REGULATOR_CURRENT)
                return ERR_PTR(-EINVAL);
 
+       if (!init_data)
+               return ERR_PTR(-EINVAL);
+
        rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
        if (rdev == NULL)
                return ERR_PTR(-ENOMEM);
@@ -1582,7 +1749,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        mutex_lock(&regulator_list_mutex);
 
        mutex_init(&rdev->mutex);
-       rdev->reg_data = reg_data;
+       rdev->reg_data = driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
        INIT_LIST_HEAD(&rdev->consumer_list);
@@ -1591,20 +1758,68 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        INIT_LIST_HEAD(&rdev->slist);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
 
+       /* preform any regulator specific init */
+       if (init_data->regulator_init) {
+               ret = init_data->regulator_init(rdev->reg_data);
+               if (ret < 0) {
+                       kfree(rdev);
+                       rdev = ERR_PTR(ret);
+                       goto out;
+               }
+       }
+
+       /* set regulator constraints */
+       ret = set_machine_constraints(rdev, &init_data->constraints);
+       if (ret < 0) {
+               kfree(rdev);
+               rdev = ERR_PTR(ret);
+               goto out;
+       }
+
+       /* register with sysfs */
        rdev->dev.class = &regulator_class;
-       device_initialize(&rdev->dev);
+       rdev->dev.parent = dev;
        snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
-                "regulator_%ld_%s",
-                (unsigned long)atomic_inc_return(&regulator_no) - 1,
-                regulator_desc->name);
-
-       ret = device_add(&rdev->dev);
-       if (ret == 0)
-               list_add(&rdev->list, &regulator_list);
-       else {
+                "regulator.%d", atomic_inc_return(&regulator_no) - 1);
+       ret = device_register(&rdev->dev);
+       if (ret != 0) {
                kfree(rdev);
                rdev = ERR_PTR(ret);
+               goto out;
+       }
+
+       dev_set_drvdata(&rdev->dev, rdev);
+
+       /* set supply regulator if it exists */
+       if (init_data->supply_regulator_dev) {
+               ret = set_supply(rdev,
+                       dev_get_drvdata(init_data->supply_regulator_dev));
+               if (ret < 0) {
+                       device_unregister(&rdev->dev);
+                       kfree(rdev);
+                       rdev = ERR_PTR(ret);
+                       goto out;
+               }
        }
+
+       /* add consumers devices */
+       for (i = 0; i < init_data->num_consumer_supplies; i++) {
+               ret = set_consumer_device_supply(rdev,
+                       init_data->consumer_supplies[i].dev,
+                       init_data->consumer_supplies[i].supply);
+               if (ret < 0) {
+                       for (--i; i >= 0; i--)
+                               unset_consumer_device_supply(rdev,
+                                       init_data->consumer_supplies[i].dev);
+                       device_unregister(&rdev->dev);
+                       kfree(rdev);
+                       rdev = ERR_PTR(ret);
+                       goto out;
+               }
+       }
+
+       list_add(&rdev->list, &regulator_list);
+out:
        mutex_unlock(&regulator_list_mutex);
        return rdev;
 }
@@ -1630,187 +1845,6 @@ void regulator_unregister(struct regulator_dev *rdev)
 }
 EXPORT_SYMBOL_GPL(regulator_unregister);
 
-/**
- * regulator_set_supply - set regulator supply regulator
- * @regulator: regulator name
- * @supply: supply regulator name
- *
- * Called by platform initialisation code to set the supply regulator for this
- * regulator. This ensures that a regulators supply will also be enabled by the
- * core if it's child is enabled.
- */
-int regulator_set_supply(const char *regulator, const char *supply)
-{
-       struct regulator_dev *rdev, *supply_rdev;
-       int err;
-
-       if (regulator == NULL || supply == NULL)
-               return -EINVAL;
-
-       mutex_lock(&regulator_list_mutex);
-
-       list_for_each_entry(rdev, &regulator_list, list) {
-               if (!strcmp(rdev->desc->name, regulator))
-                       goto found_regulator;
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return -ENODEV;
-
-found_regulator:
-       list_for_each_entry(supply_rdev, &regulator_list, list) {
-               if (!strcmp(supply_rdev->desc->name, supply))
-                       goto found_supply;
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return -ENODEV;
-
-found_supply:
-       err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
-                               "supply");
-       if (err) {
-               printk(KERN_ERR
-                      "%s: could not add device link %s err %d\n",
-                      __func__, supply_rdev->dev.kobj.name, err);
-                      goto out;
-       }
-       rdev->supply = supply_rdev;
-       list_add(&rdev->slist, &supply_rdev->supply_list);
-out:
-       mutex_unlock(&regulator_list_mutex);
-       return err;
-}
-EXPORT_SYMBOL_GPL(regulator_set_supply);
-
-/**
- * regulator_get_supply - get regulator supply regulator
- * @regulator: regulator name
- *
- * Returns the supply supply regulator name or NULL if no supply regulator
- * exists (i.e the regulator is supplied directly from USB, Line, Battery, etc)
- */
-const char *regulator_get_supply(const char *regulator)
-{
-       struct regulator_dev *rdev;
-
-       if (regulator == NULL)
-               return NULL;
-
-       mutex_lock(&regulator_list_mutex);
-       list_for_each_entry(rdev, &regulator_list, list) {
-               if (!strcmp(rdev->desc->name, regulator))
-                       goto found;
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return NULL;
-
-found:
-       mutex_unlock(&regulator_list_mutex);
-       if (rdev->supply)
-               return rdev->supply->desc->name;
-       else
-               return NULL;
-}
-EXPORT_SYMBOL_GPL(regulator_get_supply);
-
-/**
- * regulator_set_machine_constraints - sets regulator constraints
- * @regulator: regulator source
- *
- * Allows platform initialisation code to define and constrain
- * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
- * Constraints *must* be set by platform code in order for some
- * regulator operations to proceed i.e. set_voltage, set_current_limit,
- * set_mode.
- */
-int regulator_set_machine_constraints(const char *regulator_name,
-       struct regulation_constraints *constraints)
-{
-       struct regulator_dev *rdev;
-       int ret = 0;
-
-       if (regulator_name == NULL)
-               return -EINVAL;
-
-       mutex_lock(&regulator_list_mutex);
-
-       list_for_each_entry(rdev, &regulator_list, list) {
-               if (!strcmp(regulator_name, rdev->desc->name))
-                       goto found;
-       }
-       ret = -ENODEV;
-       goto out;
-
-found:
-       mutex_lock(&rdev->mutex);
-       rdev->constraints = constraints;
-
-       /* do we need to apply the constraint voltage */
-       if (rdev->constraints->apply_uV &&
-               rdev->constraints->min_uV == rdev->constraints->max_uV &&
-               rdev->desc->ops->set_voltage) {
-               ret = rdev->desc->ops->set_voltage(rdev,
-                       rdev->constraints->min_uV, rdev->constraints->max_uV);
-                       if (ret < 0) {
-                               printk(KERN_ERR "%s: failed to apply %duV"
-                                       " constraint\n", __func__,
-                                       rdev->constraints->min_uV);
-                               rdev->constraints = NULL;
-                               goto out;
-                       }
-       }
-
-       /* are we enabled at boot time by firmware / bootloader */
-       if (rdev->constraints->boot_on)
-               rdev->use_count = 1;
-
-       /* do we need to setup our suspend state */
-       if (constraints->initial_state)
-               ret = suspend_prepare(rdev, constraints->initial_state);
-
-       print_constraints(rdev);
-       mutex_unlock(&rdev->mutex);
-
-out:
-       mutex_unlock(&regulator_list_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(regulator_set_machine_constraints);
-
-
-/**
- * regulator_set_device_supply: Bind a regulator to a symbolic supply
- * @regulator: regulator source
- * @dev:       device the supply applies to
- * @supply:    symbolic name for supply
- *
- * Allows platform initialisation code to map physical regulator
- * sources to symbolic names for supplies for use by devices.  Devices
- * should use these symbolic names to request regulators, avoiding the
- * need to provide board-specific regulator names as platform data.
- */
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-                               const char *supply)
-{
-       struct regulator_map *node;
-
-       if (regulator == NULL || supply == NULL)
-               return -EINVAL;
-
-       node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
-       if (node == NULL)
-               return -ENOMEM;
-
-       node->regulator = regulator;
-       node->dev = dev;
-       node->supply = supply;
-
-       mutex_lock(&regulator_list_mutex);
-       list_add(&node->list, &regulator_map_list);
-       mutex_unlock(&regulator_list_mutex);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(regulator_set_device_supply);
-
 /**
  * regulator_suspend_prepare: prepare regulators for system wide suspend
  * @state: system suspend state
@@ -1893,6 +1927,18 @@ int rdev_get_id(struct regulator_dev *rdev)
 }
 EXPORT_SYMBOL_GPL(rdev_get_id);
 
+struct device *rdev_get_dev(struct regulator_dev *rdev)
+{
+       return &rdev->dev;
+}
+EXPORT_SYMBOL_GPL(rdev_get_dev);
+
+void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
+{
+       return reg_init_data->driver_data;
+}
+EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
+
 static int __init regulator_init(void)
 {
        printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
new file mode 100644 (file)
index 0000000..3688e33
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * Regulators driver for Dialog Semiconductor DA903x
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Copyright (C) 2008 Compulab Ltd.
+ *
+ * This program is free software; you can 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/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/da903x.h>
+
+/* DA9030 Registers */
+#define DA9030_INVAL           (-1)
+#define DA9030_LDO1011         (0x10)
+#define DA9030_LDO15           (0x11)
+#define DA9030_LDO1416         (0x12)
+#define DA9030_LDO1819         (0x13)
+#define DA9030_LDO17           (0x14)
+#define DA9030_BUCK2DVM1       (0x15)
+#define DA9030_BUCK2DVM2       (0x16)
+#define DA9030_RCTL11          (0x17)
+#define DA9030_RCTL21          (0x18)
+#define DA9030_LDO1            (0x90)
+#define DA9030_LDO23           (0x91)
+#define DA9030_LDO45           (0x92)
+#define DA9030_LDO6            (0x93)
+#define DA9030_LDO78           (0x94)
+#define DA9030_LDO912          (0x95)
+#define DA9030_BUCK            (0x96)
+#define DA9030_RCTL12          (0x97)
+#define DA9030_RCTL22          (0x98)
+#define DA9030_LDO_UNLOCK      (0xa0)
+#define DA9030_LDO_UNLOCK_MASK (0xe0)
+#define DA9034_OVER1           (0x10)
+
+/* DA9034 Registers */
+#define DA9034_INVAL           (-1)
+#define DA9034_OVER2           (0x11)
+#define DA9034_OVER3           (0x12)
+#define DA9034_LDO643          (0x13)
+#define DA9034_LDO987          (0x14)
+#define DA9034_LDO1110         (0x15)
+#define DA9034_LDO1312         (0x16)
+#define DA9034_LDO1514         (0x17)
+#define DA9034_VCC1            (0x20)
+#define DA9034_ADTV1           (0x23)
+#define DA9034_ADTV2           (0x24)
+#define DA9034_AVRC            (0x25)
+#define DA9034_CDTV1           (0x26)
+#define DA9034_CDTV2           (0x27)
+#define DA9034_CVRC            (0x28)
+#define DA9034_SDTV1           (0x29)
+#define DA9034_SDTV2           (0x2a)
+#define DA9034_SVRC            (0x2b)
+#define DA9034_MDTV1           (0x32)
+#define DA9034_MDTV2           (0x33)
+#define DA9034_MVRC            (0x34)
+
+struct da903x_regulator_info {
+       struct regulator_desc desc;
+
+       int     min_uV;
+       int     max_uV;
+       int     step_uV;
+       int     vol_reg;
+       int     vol_shift;
+       int     vol_nbits;
+       int     update_reg;
+       int     update_bit;
+       int     enable_reg;
+       int     enable_bit;
+};
+
+static inline int check_range(struct da903x_regulator_info *info,
+                               int min_uV, int max_uV)
+{
+       if (min_uV < info->min_uV || min_uV > info->max_uV)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* DA9030/DA9034 common operations */
+static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+       val <<= info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da903x_get_voltage(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int ret;
+
+       ret = da903x_read(da9034_dev, info->vol_reg, &val);
+       if (ret)
+               return ret;
+
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val = (val & mask) >> info->vol_shift;
+
+       return info->min_uV + info->step_uV * val;
+}
+
+static int da903x_enable(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+       return da903x_set_bits(da9034_dev, info->enable_reg,
+                                       1 << info->enable_bit);
+}
+
+static int da903x_disable(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+
+       return da903x_clr_bits(da9034_dev, info->enable_reg,
+                                       1 << info->enable_bit);
+}
+
+static int da903x_is_enabled(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t reg_val;
+       int ret;
+
+       ret = da903x_read(da9034_dev, info->enable_reg, &reg_val);
+       if (ret)
+               return ret;
+
+       return reg_val & (1 << info->enable_bit);
+}
+
+/* DA9030 specific operations */
+static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int ret;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+       val <<= info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */
+       mask |= DA9030_LDO_UNLOCK_MASK;
+
+       /* write twice */
+       ret = da903x_update(da903x_dev, info->vol_reg, val, mask);
+       if (ret)
+               return ret;
+
+       return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int thresh;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       thresh = (info->max_uV + info->min_uV) / 2;
+       if (min_uV < thresh) {
+               val = (thresh - min_uV + info->step_uV - 1) / info->step_uV;
+               val |= 0x4;
+       } else {
+               val = (min_uV - thresh + info->step_uV - 1) / info->step_uV;
+       }
+
+       val <<= info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       return da903x_update(da903x_dev, info->vol_reg, val, mask);
+}
+
+static int da9030_get_ldo14_voltage(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da903x_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int ret;
+
+       ret = da903x_read(da903x_dev, info->vol_reg, &val);
+       if (ret)
+               return ret;
+
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val = (val & mask) >> info->vol_shift;
+
+       if (val & 0x4)
+               return info->min_uV + info->step_uV * (3 - (val & ~0x4));
+       else
+               return (info->max_uV + info->min_uV) / 2 +
+                       info->step_uV * (val & ~0x4);
+}
+
+/* DA9034 specific operations */
+static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int ret;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+       val <<= info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       ret = da903x_update(da9034_dev, info->vol_reg, val, mask);
+       if (ret)
+               return ret;
+
+       ret = da903x_set_bits(da9034_dev, info->update_reg,
+                                       1 << info->update_bit);
+       return ret;
+}
+
+static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
+                                   int min_uV, int max_uV)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+
+       if (check_range(info, min_uV, max_uV)) {
+               pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+               return -EINVAL;
+       }
+
+       val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+       val = (val > 7 || val < 20) ? 8 : val - 12;
+       val <<= info->vol_shift;
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+       return da903x_update(da9034_dev, info->vol_reg, val, mask);
+}
+
+static int da9034_get_ldo12_voltage(struct regulator_dev *rdev)
+{
+       struct da903x_regulator_info *info = rdev_get_drvdata(rdev);
+       struct device *da9034_dev = rdev_get_dev(rdev)->parent;
+       uint8_t val, mask;
+       int ret;
+
+       ret = da903x_read(da9034_dev, info->vol_reg, &val);
+       if (ret)
+               return ret;
+
+       mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+       val = (val & mask) >> info->vol_shift;
+
+       if (val >= 8)
+               return 2700000 + info->step_uV * (val - 8);
+
+       return info->min_uV + info->step_uV * val;
+}
+
+static struct regulator_ops da903x_regulator_ldo_ops = {
+       .set_voltage    = da903x_set_ldo_voltage,
+       .get_voltage    = da903x_get_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane DA9030 LDO14 */
+static struct regulator_ops da9030_regulator_ldo14_ops = {
+       .set_voltage    = da9030_set_ldo14_voltage,
+       .get_voltage    = da9030_get_ldo14_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the DA9030 LDO1 and LDO15 that have locks  */
+static struct regulator_ops da9030_regulator_ldo1_15_ops = {
+       .set_voltage    = da9030_set_ldo1_15_voltage,
+       .get_voltage    = da903x_get_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+static struct regulator_ops da9034_regulator_dvc_ops = {
+       .set_voltage    = da9034_set_dvc_voltage,
+       .get_voltage    = da903x_get_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+/* NOTE: this is dedicated for the insane LDO12 */
+static struct regulator_ops da9034_regulator_ldo12_ops = {
+       .set_voltage    = da9034_set_ldo12_voltage,
+       .get_voltage    = da9034_get_ldo12_voltage,
+       .enable         = da903x_enable,
+       .disable        = da903x_disable,
+       .is_enabled     = da903x_is_enabled,
+};
+
+#define DA903x_LDO(_pmic, _id, min, max, step, vreg, shift, nbits, ereg, ebit) \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = "LDO" #_id,                                   \
+               .ops    = &da903x_regulator_ldo_ops,                    \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = _pmic##_ID_LDO##_id,                          \
+               .owner  = THIS_MODULE,                                  \
+       },                                                              \
+       .min_uV         = (min) * 1000,                                 \
+       .max_uV         = (max) * 1000,                                 \
+       .step_uV        = (step) * 1000,                                \
+       .vol_reg        = _pmic##_##vreg,                               \
+       .vol_shift      = (shift),                                      \
+       .vol_nbits      = (nbits),                                      \
+       .enable_reg     = _pmic##_##ereg,                               \
+       .enable_bit     = (ebit),                                       \
+}
+
+#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{                                                                      \
+       .desc   = {                                                     \
+               .name   = #_id,                                         \
+               .ops    = &da9034_regulator_dvc_ops,                    \
+               .type   = REGULATOR_VOLTAGE,                            \
+               .id     = DA9034_ID_##_id,                              \
+               .owner  = THIS_MODULE,                                  \
+       },                                                              \
+       .min_uV         = (min) * 1000,                                 \
+       .max_uV         = (max) * 1000,                                 \
+       .step_uV        = (step) * 1000,                                \
+       .vol_reg        = DA9034_##vreg,                                \
+       .vol_shift      = (0),                                          \
+       .vol_nbits      = (nbits),                                      \
+       .update_reg     = DA9034_##ureg,                                \
+       .update_bit     = (ubit),                                       \
+       .enable_reg     = DA9034_##ereg,                                \
+       .enable_bit     = (ebit),                                       \
+}
+
+#define DA9034_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
+       DA903x_LDO(DA9034, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+#define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)        \
+       DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit)
+
+static struct da903x_regulator_info da903x_regulator_info[] = {
+       /* DA9030 */
+       DA9030_LDO( 1, 1200, 3200, 100,    LDO1, 0, 5, RCTL12, 1),
+       DA9030_LDO( 2, 1800, 3200, 100,   LDO23, 0, 4, RCTL12, 2),
+       DA9030_LDO( 3, 1800, 3200, 100,   LDO23, 4, 4, RCTL12, 3),
+       DA9030_LDO( 4, 1800, 3200, 100,   LDO45, 0, 4, RCTL12, 4),
+       DA9030_LDO( 5, 1800, 3200, 100,   LDO45, 4, 4, RCTL12, 5),
+       DA9030_LDO( 6, 1800, 3200, 100,    LDO6, 0, 4, RCTL12, 6),
+       DA9030_LDO( 7, 1800, 3200, 100,   LDO78, 0, 4, RCTL12, 7),
+       DA9030_LDO( 8, 1800, 3200, 100,   LDO78, 4, 4, RCTL22, 0),
+       DA9030_LDO( 9, 1800, 3200, 100,  LDO912, 0, 4, RCTL22, 1),
+       DA9030_LDO(10, 1800, 3200, 100, LDO1011, 0, 4, RCTL22, 2),
+       DA9030_LDO(11, 1800, 3200, 100, LDO1011, 4, 4, RCTL22, 3),
+       DA9030_LDO(12, 1800, 3200, 100,  LDO912, 4, 4, RCTL22, 4),
+       DA9030_LDO(14, 2760, 2940,  30, LDO1416, 0, 3, RCTL11, 4),
+       DA9030_LDO(15, 1100, 2650,  50,   LDO15, 0, 5, RCTL11, 5),
+       DA9030_LDO(16, 1100, 2650,  50, LDO1416, 3, 5, RCTL11, 6),
+       DA9030_LDO(17, 1800, 3200, 100,   LDO17, 0, 4, RCTL11, 7),
+       DA9030_LDO(18, 1800, 3200, 100, LDO1819, 0, 4, RCTL21, 2),
+       DA9030_LDO(19, 1800, 3200, 100, LDO1819, 4, 4, RCTL21, 1),
+       DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */
+
+       /* DA9034 */
+       DA9034_DVC(BUCK1, 725, 1500, 25, ADTV1, 5, VCC1, 0, OVER1, 0),
+       DA9034_DVC(BUCK2, 725, 1500, 25, CDTV1, 5, VCC1, 2, OVER1, 1),
+       DA9034_DVC(LDO2,  725, 1500, 25, SDTV1, 5, VCC1, 4, OVER1, 2),
+       DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4),
+
+       DA9034_LDO( 3, 1800, 3300, 100,  LDO643, 0, 4, OVER3, 5),
+       DA9034_LDO( 4, 1800, 2900,1100,  LDO643, 4, 1, OVER3, 6),
+       DA9034_LDO( 6, 2500, 2850,  50,  LDO643, 5, 3, OVER2, 0),
+       DA9034_LDO( 7, 2700, 3050,  50,  LDO987, 0, 3, OVER2, 1),
+       DA9034_LDO( 8, 2700, 2850,  50,  LDO987, 3, 2, OVER2, 2),
+       DA9034_LDO( 9, 2700, 3050,  50,  LDO987, 5, 3, OVER2, 3),
+       DA9034_LDO(10, 2700, 3050,  50, LDO1110, 0, 3, OVER2, 4),
+       DA9034_LDO(11, 1800, 3300, 100, LDO1110, 4, 4, OVER2, 5),
+       DA9034_LDO(12, 1700, 3050,  50, LDO1312, 0, 4, OVER3, 6),
+       DA9034_LDO(13, 1800, 3300, 100, LDO1312, 4, 4, OVER2, 7),
+       DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0),
+       DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1),
+       DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */
+};
+
+static inline struct da903x_regulator_info *find_regulator_info(int id)
+{
+       struct da903x_regulator_info *ri;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da903x_regulator_info); i++) {
+               ri = &da903x_regulator_info[i];
+               if (ri->desc.id == id)
+                       return ri;
+       }
+       return NULL;
+}
+
+static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+{
+       struct da903x_regulator_info *ri = NULL;
+       struct regulator_dev *rdev;
+
+       ri = find_regulator_info(pdev->id);
+       if (ri == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       /* Workaround for the weird LDO12 voltage setting */
+       if (ri->desc.id == DA9034_ID_LDO12)
+               ri->desc.ops = &da9034_regulator_ldo12_ops;
+
+       if (ri->desc.id == DA9030_ID_LDO14)
+               ri->desc.ops = &da9030_regulator_ldo14_ops;
+
+       if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15)
+               ri->desc.ops = &da9030_regulator_ldo1_15_ops;
+
+       rdev = regulator_register(&ri->desc, pdev->dev.parent, ri);
+       if (IS_ERR(rdev)) {
+               dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               ri->desc.name);
+               return PTR_ERR(rdev);
+       }
+
+       platform_set_drvdata(pdev, rdev);
+       return 0;
+}
+
+static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+       regulator_unregister(rdev);
+       return 0;
+}
+
+static struct platform_driver da903x_regulator_driver = {
+       .driver = {
+               .name   = "da903x-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = da903x_regulator_probe,
+       .remove         = da903x_regulator_remove,
+};
+
+static int __init da903x_regulator_init(void)
+{
+       return platform_driver_register(&da903x_regulator_driver);
+}
+module_init(da903x_regulator_init);
+
+static void __exit da903x_regulator_exit(void)
+{
+       platform_driver_unregister(&da903x_regulator_driver);
+}
+module_exit(da903x_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
+             "Mike Rapoport <mike@compulab.co.il>");
+MODULE_DESCRIPTION("Regulator Driver for Dialog Semiconductor DA903X PMIC");
+MODULE_ALIAS("platform:da903x-regulator");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
new file mode 100644 (file)
index 0000000..1f44b17
--- /dev/null
@@ -0,0 +1,1431 @@
+/*
+ * wm8350.c  --  Voltage and current regulation for the Wolfson WM8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood
+ *         linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/* Microamps */
+static const int isink_cur[] = {
+       4,
+       5,
+       6,
+       7,
+       8,
+       10,
+       11,
+       14,
+       16,
+       19,
+       23,
+       27,
+       32,
+       39,
+       46,
+       54,
+       65,
+       77,
+       92,
+       109,
+       130,
+       154,
+       183,
+       218,
+       259,
+       308,
+       367,
+       436,
+       518,
+       616,
+       733,
+       872,
+       1037,
+       1233,
+       1466,
+       1744,
+       2073,
+       2466,
+       2933,
+       3487,
+       4147,
+       4932,
+       5865,
+       6975,
+       8294,
+       9864,
+       11730,
+       13949,
+       16589,
+       19728,
+       23460,
+       27899,
+       33178,
+       39455,
+       46920,
+       55798,
+       66355,
+       78910,
+       93840,
+       111596,
+       132710,
+       157820,
+       187681,
+       223191
+};
+
+static int get_isink_val(int min_uA, int max_uA, u16 *setting)
+{
+       int i;
+
+       for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
+               if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
+                       *setting = i;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
+{
+       if (val < 16)
+               return (val * 50) + 900;
+       else
+               return ((val - 16) * 100) + 1800;
+
+}
+
+static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
+{
+       if (mV < 1800)
+               return (mV - 900) / 50;
+       else
+               return ((mV - 1800) / 100) + 16;
+}
+
+static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
+{
+       return (val * 25) + 850;
+}
+
+static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
+{
+       return (mV - 850) / 25;
+}
+
+static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
+       int max_uA)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int isink = rdev_get_id(rdev);
+       u16 val, setting;
+       int ret;
+
+       ret = get_isink_val(min_uA, max_uA, &setting);
+       if (ret != 0)
+               return ret;
+
+       switch (isink) {
+       case WM8350_ISINK_A:
+               val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+                   ~WM8350_CS1_ISEL_MASK;
+               wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_A,
+                                val | setting);
+               break;
+       case WM8350_ISINK_B:
+               val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+                   ~WM8350_CS1_ISEL_MASK;
+               wm8350_reg_write(wm8350, WM8350_CURRENT_SINK_DRIVER_B,
+                                val | setting);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8350_isink_get_current(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int isink = rdev_get_id(rdev);
+       u16 val;
+
+       switch (isink) {
+       case WM8350_ISINK_A:
+               val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+                   WM8350_CS1_ISEL_MASK;
+               break;
+       case WM8350_ISINK_B:
+               val = wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+                   WM8350_CS1_ISEL_MASK;
+               break;
+       default:
+               return 0;
+       }
+
+       return (isink_cur[val] + 50) / 100;
+}
+
+/* turn on ISINK followed by DCDC */
+static int wm8350_isink_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int isink = rdev_get_id(rdev);
+
+       switch (isink) {
+       case WM8350_ISINK_A:
+               switch (wm8350->pmic.isink_A_dcdc) {
+               case WM8350_DCDC_2:
+               case WM8350_DCDC_5:
+                       wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+                                       WM8350_CS1_ENA);
+                       wm8350_set_bits(wm8350, WM8350_CSA_FLASH_CONTROL,
+                                       WM8350_CS1_DRIVE);
+                       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+                                       1 << (wm8350->pmic.isink_A_dcdc -
+                                             WM8350_DCDC_1));
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case WM8350_ISINK_B:
+               switch (wm8350->pmic.isink_B_dcdc) {
+               case WM8350_DCDC_2:
+               case WM8350_DCDC_5:
+                       wm8350_set_bits(wm8350, WM8350_POWER_MGMT_7,
+                                       WM8350_CS2_ENA);
+                       wm8350_set_bits(wm8350, WM8350_CSB_FLASH_CONTROL,
+                                       WM8350_CS2_DRIVE);
+                       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+                                       1 << (wm8350->pmic.isink_B_dcdc -
+                                             WM8350_DCDC_1));
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int wm8350_isink_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int isink = rdev_get_id(rdev);
+
+       switch (isink) {
+       case WM8350_ISINK_A:
+               switch (wm8350->pmic.isink_A_dcdc) {
+               case WM8350_DCDC_2:
+               case WM8350_DCDC_5:
+                       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+                                         1 << (wm8350->pmic.isink_A_dcdc -
+                                               WM8350_DCDC_1));
+                       wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+                                         WM8350_CS1_ENA);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case WM8350_ISINK_B:
+               switch (wm8350->pmic.isink_B_dcdc) {
+               case WM8350_DCDC_2:
+               case WM8350_DCDC_5:
+                       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED,
+                                         1 << (wm8350->pmic.isink_B_dcdc -
+                                               WM8350_DCDC_1));
+                       wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_7,
+                                         WM8350_CS2_ENA);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int wm8350_isink_is_enabled(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int isink = rdev_get_id(rdev);
+
+       switch (isink) {
+       case WM8350_ISINK_A:
+               return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_A) &
+                   0x8000;
+       case WM8350_ISINK_B:
+               return wm8350_reg_read(wm8350, WM8350_CURRENT_SINK_DRIVER_B) &
+                   0x8000;
+       }
+       return -EINVAL;
+}
+
+int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
+                          u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
+                          u16 drive)
+{
+       switch (isink) {
+       case WM8350_ISINK_A:
+               wm8350_reg_write(wm8350, WM8350_CSA_FLASH_CONTROL,
+                                (mode ? WM8350_CS1_FLASH_MODE : 0) |
+                                (trigger ? WM8350_CS1_TRIGSRC : 0) |
+                                duration | on_ramp | off_ramp | drive);
+               break;
+       case WM8350_ISINK_B:
+               wm8350_reg_write(wm8350, WM8350_CSB_FLASH_CONTROL,
+                                (mode ? WM8350_CS2_FLASH_MODE : 0) |
+                                (trigger ? WM8350_CS2_TRIGSRC : 0) |
+                                duration | on_ramp | off_ramp | drive);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
+
+static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
+       int max_uV)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, dcdc = rdev_get_id(rdev), mV,
+               min_mV = min_uV / 1000, max_mV = max_uV / 1000;
+       u16 val;
+
+       if (min_mV < 850 || min_mV > 4025)
+               return -EINVAL;
+       if (max_mV < 850 || max_mV > 4025)
+               return -EINVAL;
+
+       /* step size is 25mV */
+       mV = (min_mV - 826) / 25;
+       if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
+               return -EINVAL;
+       BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               volt_reg = WM8350_DCDC1_CONTROL;
+               break;
+       case WM8350_DCDC_3:
+               volt_reg = WM8350_DCDC3_CONTROL;
+               break;
+       case WM8350_DCDC_4:
+               volt_reg = WM8350_DCDC4_CONTROL;
+               break;
+       case WM8350_DCDC_6:
+               volt_reg = WM8350_DCDC6_CONTROL;
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       /* all DCDCs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+       wm8350_reg_write(wm8350, volt_reg, val | mV);
+       return 0;
+}
+
+static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               volt_reg = WM8350_DCDC1_CONTROL;
+               break;
+       case WM8350_DCDC_3:
+               volt_reg = WM8350_DCDC3_CONTROL;
+               break;
+       case WM8350_DCDC_4:
+               volt_reg = WM8350_DCDC4_CONTROL;
+               break;
+       case WM8350_DCDC_6:
+               volt_reg = WM8350_DCDC6_CONTROL;
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       /* all DCDCs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
+       return wm8350_dcdc_val_to_mvolts(val) * 1000;
+}
+
+static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
+
+       if (mV && (mV < 850 || mV > 4025)) {
+               dev_err(wm8350->dev,
+                       "DCDC%d suspend voltage %d mV out of range\n",
+                       dcdc, mV);
+               return -EINVAL;
+       }
+       if (mV == 0)
+               mV = 850;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               volt_reg = WM8350_DCDC1_LOW_POWER;
+               break;
+       case WM8350_DCDC_3:
+               volt_reg = WM8350_DCDC3_LOW_POWER;
+               break;
+       case WM8350_DCDC_4:
+               volt_reg = WM8350_DCDC4_LOW_POWER;
+               break;
+       case WM8350_DCDC_6:
+               volt_reg = WM8350_DCDC6_LOW_POWER;
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       /* all DCDCs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
+       wm8350_reg_write(wm8350, volt_reg,
+                        val | wm8350_dcdc_mvolts_to_val(mV));
+       return 0;
+}
+
+static int wm8350_dcdc_set_suspend_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
+                       & ~WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+                       wm8350->pmic.dcdc1_hib_mode);
+               break;
+       case WM8350_DCDC_3:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
+                       & ~WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+                       wm8350->pmic.dcdc3_hib_mode);
+               break;
+       case WM8350_DCDC_4:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
+                       & ~WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+                       wm8350->pmic.dcdc4_hib_mode);
+               break;
+       case WM8350_DCDC_6:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
+                       & ~WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+                       wm8350->pmic.dcdc6_hib_mode);
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8350_dcdc_set_suspend_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+               wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
+                       WM8350_DCDC_HIB_MODE_DIS);
+               break;
+       case WM8350_DCDC_3:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+               wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
+                       WM8350_DCDC_HIB_MODE_DIS);
+               break;
+       case WM8350_DCDC_4:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+               wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
+                       WM8350_DCDC_HIB_MODE_DIS);
+               break;
+       case WM8350_DCDC_6:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+               wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
+                       WM8350_DCDC_HIB_MODE_DIS);
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       switch (dcdc) {
+       case WM8350_DCDC_2:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+                   & ~WM8350_DC2_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+                                WM8350_DC2_HIB_MODE_ACTIVE);
+               break;
+       case WM8350_DCDC_5:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+                   & ~WM8350_DC2_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+                                WM8350_DC5_HIB_MODE_ACTIVE);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int wm8350_dcdc25_set_suspend_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       switch (dcdc) {
+       case WM8350_DCDC_2:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+                   & ~WM8350_DC2_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+                                WM8350_DC2_HIB_MODE_DISABLE);
+               break;
+       case WM8350_DCDC_5:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+                   & ~WM8350_DC2_HIB_MODE_MASK;
+               wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+                                WM8350_DC2_HIB_MODE_DISABLE);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
+       unsigned int mode)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 *hib_mode;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               hib_mode = &wm8350->pmic.dcdc1_hib_mode;
+               break;
+       case WM8350_DCDC_3:
+               hib_mode = &wm8350->pmic.dcdc3_hib_mode;
+               break;
+       case WM8350_DCDC_4:
+               hib_mode = &wm8350->pmic.dcdc4_hib_mode;
+               break;
+       case WM8350_DCDC_6:
+               hib_mode = &wm8350->pmic.dcdc6_hib_mode;
+               break;
+       case WM8350_DCDC_2:
+       case WM8350_DCDC_5:
+       default:
+               return -EINVAL;
+       }
+
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+               *hib_mode = WM8350_DCDC_HIB_MODE_IMAGE;
+               break;
+       case REGULATOR_MODE_IDLE:
+               *hib_mode = WM8350_DCDC_HIB_MODE_STANDBY;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               *hib_mode = WM8350_DCDC_HIB_MODE_LDO_IM;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
+       u16 val;
+
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
+
+       if (mV < 900 || mV > 3300) {
+               dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
+                       ldo, mV);
+               return -EINVAL;
+       }
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               volt_reg = WM8350_LDO1_LOW_POWER;
+               break;
+       case WM8350_LDO_2:
+               volt_reg = WM8350_LDO2_LOW_POWER;
+               break;
+       case WM8350_LDO_3:
+               volt_reg = WM8350_LDO3_LOW_POWER;
+               break;
+       case WM8350_LDO_4:
+               volt_reg = WM8350_LDO4_LOW_POWER;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* all LDOs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+       wm8350_reg_write(wm8350, volt_reg,
+                        val | wm8350_ldo_mvolts_to_val(mV));
+       return 0;
+}
+
+static int wm8350_ldo_set_suspend_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, ldo = rdev_get_id(rdev);
+       u16 val;
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               volt_reg = WM8350_LDO1_LOW_POWER;
+               break;
+       case WM8350_LDO_2:
+               volt_reg = WM8350_LDO2_LOW_POWER;
+               break;
+       case WM8350_LDO_3:
+               volt_reg = WM8350_LDO3_LOW_POWER;
+               break;
+       case WM8350_LDO_4:
+               volt_reg = WM8350_LDO4_LOW_POWER;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* all LDOs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+       wm8350_reg_write(wm8350, volt_reg, val);
+       return 0;
+}
+
+static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, ldo = rdev_get_id(rdev);
+       u16 val;
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               volt_reg = WM8350_LDO1_LOW_POWER;
+               break;
+       case WM8350_LDO_2:
+               volt_reg = WM8350_LDO2_LOW_POWER;
+               break;
+       case WM8350_LDO_3:
+               volt_reg = WM8350_LDO3_LOW_POWER;
+               break;
+       case WM8350_LDO_4:
+               volt_reg = WM8350_LDO4_LOW_POWER;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* all LDOs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
+       wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
+       return 0;
+}
+
+static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
+       int max_uV)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
+               max_mV = max_uV / 1000;
+       u16 val;
+
+       if (min_mV < 900 || min_mV > 3300)
+               return -EINVAL;
+       if (max_mV < 900 || max_mV > 3300)
+               return -EINVAL;
+
+       if (min_mV < 1800) {
+               /* step size is 50mV < 1800mV */
+               mV = (min_mV - 851) / 50;
+               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+                       return -EINVAL;
+               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+       } else {
+               /* step size is 100mV > 1800mV */
+               mV = ((min_mV - 1701) / 100) + 16;
+               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
+                       return -EINVAL;
+               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
+       }
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               volt_reg = WM8350_LDO1_CONTROL;
+               break;
+       case WM8350_LDO_2:
+               volt_reg = WM8350_LDO2_CONTROL;
+               break;
+       case WM8350_LDO_3:
+               volt_reg = WM8350_LDO3_CONTROL;
+               break;
+       case WM8350_LDO_4:
+               volt_reg = WM8350_LDO4_CONTROL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* all LDOs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
+       wm8350_reg_write(wm8350, volt_reg, val | mV);
+       return 0;
+}
+
+static int wm8350_ldo_get_voltage(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int volt_reg, ldo = rdev_get_id(rdev);
+       u16 val;
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               volt_reg = WM8350_LDO1_CONTROL;
+               break;
+       case WM8350_LDO_2:
+               volt_reg = WM8350_LDO2_CONTROL;
+               break;
+       case WM8350_LDO_3:
+               volt_reg = WM8350_LDO3_CONTROL;
+               break;
+       case WM8350_LDO_4:
+               volt_reg = WM8350_LDO4_CONTROL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* all LDOs have same mV bits */
+       val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
+       return wm8350_ldo_val_to_mvolts(val) * 1000;
+}
+
+int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
+                        u16 stop, u16 fault)
+{
+       int slot_reg;
+       u16 val;
+
+       dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+               __func__, dcdc, start, stop);
+
+       /* slot valid ? */
+       if (start > 15 || stop > 15)
+               return -EINVAL;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               slot_reg = WM8350_DCDC1_TIMEOUTS;
+               break;
+       case WM8350_DCDC_2:
+               slot_reg = WM8350_DCDC2_TIMEOUTS;
+               break;
+       case WM8350_DCDC_3:
+               slot_reg = WM8350_DCDC3_TIMEOUTS;
+               break;
+       case WM8350_DCDC_4:
+               slot_reg = WM8350_DCDC4_TIMEOUTS;
+               break;
+       case WM8350_DCDC_5:
+               slot_reg = WM8350_DCDC5_TIMEOUTS;
+               break;
+       case WM8350_DCDC_6:
+               slot_reg = WM8350_DCDC6_TIMEOUTS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       val = wm8350_reg_read(wm8350, slot_reg) &
+           ~(WM8350_DC1_ENSLOT_MASK | WM8350_DC1_SDSLOT_MASK |
+             WM8350_DC1_ERRACT_MASK);
+       wm8350_reg_write(wm8350, slot_reg,
+                        val | (start << WM8350_DC1_ENSLOT_SHIFT) |
+                        (stop << WM8350_DC1_SDSLOT_SHIFT) |
+                        (fault << WM8350_DC1_ERRACT_SHIFT));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc_set_slot);
+
+int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop)
+{
+       int slot_reg;
+       u16 val;
+
+       dev_dbg(wm8350->dev, "%s %d start %d stop %d\n",
+               __func__, ldo, start, stop);
+
+       /* slot valid ? */
+       if (start > 15 || stop > 15)
+               return -EINVAL;
+
+       switch (ldo) {
+       case WM8350_LDO_1:
+               slot_reg = WM8350_LDO1_TIMEOUTS;
+               break;
+       case WM8350_LDO_2:
+               slot_reg = WM8350_LDO2_TIMEOUTS;
+               break;
+       case WM8350_LDO_3:
+               slot_reg = WM8350_LDO3_TIMEOUTS;
+               break;
+       case WM8350_LDO_4:
+               slot_reg = WM8350_LDO4_TIMEOUTS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       val = wm8350_reg_read(wm8350, slot_reg) & ~WM8350_LDO1_SDSLOT_MASK;
+       wm8350_reg_write(wm8350, slot_reg, val | ((start << 10) | (stop << 6)));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_ldo_set_slot);
+
+int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
+                          u16 ilim, u16 ramp, u16 feedback)
+{
+       u16 val;
+
+       dev_dbg(wm8350->dev, "%s %d mode: %s %s\n", __func__, dcdc,
+               mode ? "normal" : "boost", ilim ? "low" : "normal");
+
+       switch (dcdc) {
+       case WM8350_DCDC_2:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
+                   & ~(WM8350_DC2_MODE_MASK | WM8350_DC2_ILIM_MASK |
+                       WM8350_DC2_RMP_MASK | WM8350_DC2_FBSRC_MASK);
+               wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
+                                (mode << WM8350_DC2_MODE_SHIFT) |
+                                (ilim << WM8350_DC2_ILIM_SHIFT) |
+                                (ramp << WM8350_DC2_RMP_SHIFT) |
+                                (feedback << WM8350_DC2_FBSRC_SHIFT));
+               break;
+       case WM8350_DCDC_5:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
+                   & ~(WM8350_DC5_MODE_MASK | WM8350_DC5_ILIM_MASK |
+                       WM8350_DC5_RMP_MASK | WM8350_DC5_FBSRC_MASK);
+               wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
+                                (mode << WM8350_DC5_MODE_SHIFT) |
+                                (ilim << WM8350_DC5_ILIM_SHIFT) |
+                                (ramp << WM8350_DC5_RMP_SHIFT) |
+                                (feedback << WM8350_DC5_FBSRC_SHIFT));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
+
+static int wm8350_dcdc_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 shift;
+
+       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+               return -EINVAL;
+
+       shift = dcdc - WM8350_DCDC_1;
+       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+       return 0;
+}
+
+static int wm8350_dcdc_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 shift;
+
+       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+               return -EINVAL;
+
+       shift = dcdc - WM8350_DCDC_1;
+       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+
+       return 0;
+}
+
+static int wm8350_ldo_enable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int ldo = rdev_get_id(rdev);
+       u16 shift;
+
+       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+               return -EINVAL;
+
+       shift = (ldo - WM8350_LDO_1) + 8;
+       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+       return 0;
+}
+
+static int wm8350_ldo_disable(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int ldo = rdev_get_id(rdev);
+       u16 shift;
+
+       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+               return -EINVAL;
+
+       shift = (ldo - WM8350_LDO_1) + 8;
+       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
+       return 0;
+}
+
+static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
+{
+       int reg = 0, ret;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+               reg = WM8350_DCDC1_FORCE_PWM;
+               break;
+       case WM8350_DCDC_3:
+               reg = WM8350_DCDC3_FORCE_PWM;
+               break;
+       case WM8350_DCDC_4:
+               reg = WM8350_DCDC4_FORCE_PWM;
+               break;
+       case WM8350_DCDC_6:
+               reg = WM8350_DCDC6_FORCE_PWM;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (enable)
+               ret = wm8350_set_bits(wm8350, reg,
+                       WM8350_DCDC1_FORCE_PWM_ENA);
+       else
+               ret = wm8350_clear_bits(wm8350, reg,
+                       WM8350_DCDC1_FORCE_PWM_ENA);
+       return ret;
+}
+
+static int wm8350_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 val;
+
+       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+               return -EINVAL;
+
+       if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+               return -EINVAL;
+
+       val = 1 << (dcdc - WM8350_DCDC_1);
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               /* force continuous mode */
+               wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+               wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+               force_continuous_enable(wm8350, dcdc, 1);
+               break;
+       case REGULATOR_MODE_NORMAL:
+               /* active / pulse skipping */
+               wm8350_set_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+               wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+               force_continuous_enable(wm8350, dcdc, 0);
+               break;
+       case REGULATOR_MODE_IDLE:
+               /* standby mode */
+               force_continuous_enable(wm8350, dcdc, 0);
+               wm8350_clear_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+               wm8350_clear_bits(wm8350, WM8350_DCDC_ACTIVE_OPTIONS, val);
+               break;
+       case REGULATOR_MODE_STANDBY:
+               /* LDO mode */
+               force_continuous_enable(wm8350, dcdc, 0);
+               wm8350_set_bits(wm8350, WM8350_DCDC_SLEEP_OPTIONS, val);
+               break;
+       }
+
+       return 0;
+}
+
+static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev);
+       u16 mask, sleep, active, force;
+       int mode = REGULATOR_MODE_NORMAL;
+
+       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+               return -EINVAL;
+
+       if (dcdc == WM8350_DCDC_2 || dcdc == WM8350_DCDC_5)
+               return -EINVAL;
+
+       mask = 1 << (dcdc - WM8350_DCDC_1);
+       active = wm8350_reg_read(wm8350, WM8350_DCDC_ACTIVE_OPTIONS) & mask;
+       sleep = wm8350_reg_read(wm8350, WM8350_DCDC_SLEEP_OPTIONS) & mask;
+       force = wm8350_reg_read(wm8350, WM8350_DCDC1_FORCE_PWM)
+           & WM8350_DCDC1_FORCE_PWM_ENA;
+       dev_dbg(wm8350->dev, "mask %x active %x sleep %x force %x",
+               mask, active, sleep, force);
+
+       if (active && !sleep) {
+               if (force)
+                       mode = REGULATOR_MODE_FAST;
+               else
+                       mode = REGULATOR_MODE_NORMAL;
+       } else if (!active && !sleep)
+               mode = REGULATOR_MODE_IDLE;
+       else if (!sleep)
+               mode = REGULATOR_MODE_STANDBY;
+
+       return mode;
+}
+
+static unsigned int wm8350_ldo_get_mode(struct regulator_dev *rdev)
+{
+       return REGULATOR_MODE_NORMAL;
+}
+
+struct wm8350_dcdc_efficiency {
+       int uA_load_min;
+       int uA_load_max;
+       unsigned int mode;
+};
+
+static const struct wm8350_dcdc_efficiency dcdc1_6_efficiency[] = {
+       {0, 10000, REGULATOR_MODE_STANDBY},       /* 0 - 10mA - LDO */
+       {10000, 100000, REGULATOR_MODE_IDLE},     /* 10mA - 100mA - Standby */
+       {100000, 1000000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+       {-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static const struct wm8350_dcdc_efficiency dcdc3_4_efficiency[] = {
+       {0, 10000, REGULATOR_MODE_STANDBY},      /* 0 - 10mA - LDO */
+       {10000, 100000, REGULATOR_MODE_IDLE},    /* 10mA - 100mA - Standby */
+       {100000, 800000, REGULATOR_MODE_NORMAL}, /* > 100mA - Active */
+       {-1, -1, REGULATOR_MODE_NORMAL},
+};
+
+static unsigned int get_mode(int uA, const struct wm8350_dcdc_efficiency *eff)
+{
+       int i = 0;
+
+       while (eff[i].uA_load_min != -1) {
+               if (uA >= eff[i].uA_load_min && uA <= eff[i].uA_load_max)
+                       return eff[i].mode;
+       }
+       return REGULATOR_MODE_NORMAL;
+}
+
+/* Query the regulator for it's most efficient mode @ uV,uA
+ * WM8350 regulator efficiency is pretty similar over
+ * different input and output uV.
+ */
+static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
+                                                int input_uV, int output_uV,
+                                                int output_uA)
+{
+       int dcdc = rdev_get_id(rdev), mode;
+
+       switch (dcdc) {
+       case WM8350_DCDC_1:
+       case WM8350_DCDC_6:
+               mode = get_mode(output_uA, dcdc1_6_efficiency);
+               break;
+       case WM8350_DCDC_3:
+       case WM8350_DCDC_4:
+               mode = get_mode(output_uA, dcdc3_4_efficiency);
+               break;
+       default:
+               mode = REGULATOR_MODE_NORMAL;
+               break;
+       }
+       return mode;
+}
+
+static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int dcdc = rdev_get_id(rdev), shift;
+
+       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
+               return -EINVAL;
+
+       shift = dcdc - WM8350_DCDC_1;
+       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+           & (1 << shift);
+}
+
+static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
+{
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+       int ldo = rdev_get_id(rdev), shift;
+
+       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
+               return -EINVAL;
+
+       shift = (ldo - WM8350_LDO_1) + 8;
+       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
+           & (1 << shift);
+}
+
+static struct regulator_ops wm8350_dcdc_ops = {
+       .set_voltage = wm8350_dcdc_set_voltage,
+       .get_voltage = wm8350_dcdc_get_voltage,
+       .enable = wm8350_dcdc_enable,
+       .disable = wm8350_dcdc_disable,
+       .get_mode = wm8350_dcdc_get_mode,
+       .set_mode = wm8350_dcdc_set_mode,
+       .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
+       .is_enabled = wm8350_dcdc_is_enabled,
+       .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
+       .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
+       .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
+       .set_suspend_mode = wm8350_dcdc_set_suspend_mode,
+};
+
+static struct regulator_ops wm8350_dcdc2_5_ops = {
+       .enable = wm8350_dcdc_enable,
+       .disable = wm8350_dcdc_disable,
+       .is_enabled = wm8350_dcdc_is_enabled,
+       .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
+       .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_ldo_ops = {
+       .set_voltage = wm8350_ldo_set_voltage,
+       .get_voltage = wm8350_ldo_get_voltage,
+       .enable = wm8350_ldo_enable,
+       .disable = wm8350_ldo_disable,
+       .is_enabled = wm8350_ldo_is_enabled,
+       .get_mode = wm8350_ldo_get_mode,
+       .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
+       .set_suspend_enable = wm8350_ldo_set_suspend_enable,
+       .set_suspend_disable = wm8350_ldo_set_suspend_disable,
+};
+
+static struct regulator_ops wm8350_isink_ops = {
+       .set_current_limit = wm8350_isink_set_current,
+       .get_current_limit = wm8350_isink_get_current,
+       .enable = wm8350_isink_enable,
+       .disable = wm8350_isink_disable,
+       .is_enabled = wm8350_isink_is_enabled,
+};
+
+static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
+       {
+               .name = "DCDC1",
+               .id = WM8350_DCDC_1,
+               .ops = &wm8350_dcdc_ops,
+               .irq = WM8350_IRQ_UV_DC1,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC2",
+               .id = WM8350_DCDC_2,
+               .ops = &wm8350_dcdc2_5_ops,
+               .irq = WM8350_IRQ_UV_DC2,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC3",
+               .id = WM8350_DCDC_3,
+               .ops = &wm8350_dcdc_ops,
+               .irq = WM8350_IRQ_UV_DC3,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC4",
+               .id = WM8350_DCDC_4,
+               .ops = &wm8350_dcdc_ops,
+               .irq = WM8350_IRQ_UV_DC4,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC5",
+               .id = WM8350_DCDC_5,
+               .ops = &wm8350_dcdc2_5_ops,
+               .irq = WM8350_IRQ_UV_DC5,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+        },
+       {
+               .name = "DCDC6",
+               .id = WM8350_DCDC_6,
+               .ops = &wm8350_dcdc_ops,
+               .irq = WM8350_IRQ_UV_DC6,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO1",
+               .id = WM8350_LDO_1,
+               .ops = &wm8350_ldo_ops,
+               .irq = WM8350_IRQ_UV_LDO1,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO2",
+               .id = WM8350_LDO_2,
+               .ops = &wm8350_ldo_ops,
+               .irq = WM8350_IRQ_UV_LDO2,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO3",
+               .id = WM8350_LDO_3,
+               .ops = &wm8350_ldo_ops,
+               .irq = WM8350_IRQ_UV_LDO3,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO4",
+               .id = WM8350_LDO_4,
+               .ops = &wm8350_ldo_ops,
+               .irq = WM8350_IRQ_UV_LDO4,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "ISINKA",
+               .id = WM8350_ISINK_A,
+               .ops = &wm8350_isink_ops,
+               .irq = WM8350_IRQ_CS1,
+               .type = REGULATOR_CURRENT,
+               .owner = THIS_MODULE,
+        },
+       {
+               .name = "ISINKB",
+               .id = WM8350_ISINK_B,
+               .ops = &wm8350_isink_ops,
+               .irq = WM8350_IRQ_CS2,
+               .type = REGULATOR_CURRENT,
+               .owner = THIS_MODULE,
+        },
+};
+
+static void pmic_uv_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+       struct regulator_dev *rdev = (struct regulator_dev *)data;
+
+       if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
+               regulator_notifier_call_chain(rdev,
+                                             REGULATOR_EVENT_REGULATION_OUT,
+                                             wm8350);
+       else
+               regulator_notifier_call_chain(rdev,
+                                             REGULATOR_EVENT_UNDER_VOLTAGE,
+                                             wm8350);
+}
+
+static int wm8350_regulator_probe(struct platform_device *pdev)
+{
+       struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
+       struct regulator_dev *rdev;
+       int ret;
+       u16 val;
+
+       if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
+               return -ENODEV;
+
+       /* do any regulatior specific init */
+       switch (pdev->id) {
+       case WM8350_DCDC_1:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
+               wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               break;
+       case WM8350_DCDC_3:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
+               wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               break;
+       case WM8350_DCDC_4:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
+               wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               break;
+       case WM8350_DCDC_6:
+               val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
+               wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
+               break;
+       }
+
+
+       /* register regulator */
+       rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
+                                 dev_get_drvdata(&pdev->dev));
+       if (IS_ERR(rdev)) {
+               dev_err(&pdev->dev, "failed to register %s\n",
+                       wm8350_reg[pdev->id].name);
+               return PTR_ERR(rdev);
+       }
+
+       /* register regulator IRQ */
+       ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
+                                 pmic_uv_handler, rdev);
+       if (ret < 0) {
+               regulator_unregister(rdev);
+               dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
+                       wm8350_reg[pdev->id].name);
+               return ret;
+       }
+
+       wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+       return 0;
+}
+
+static int wm8350_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+
+       wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq);
+       wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
+
+       regulator_unregister(rdev);
+
+       return 0;
+}
+
+int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
+                             struct regulator_init_data *initdata)
+{
+       struct platform_device *pdev;
+       int ret;
+
+       if (wm8350->pmic.pdev[reg])
+               return -EBUSY;
+
+       pdev = platform_device_alloc("wm8350-regulator", reg);
+       if (!pdev)
+               return -ENOMEM;
+
+       wm8350->pmic.pdev[reg] = pdev;
+
+       initdata->driver_data = wm8350;
+
+       pdev->dev.platform_data = initdata;
+       pdev->dev.parent = wm8350->dev;
+       platform_set_drvdata(pdev, wm8350);
+
+       ret = platform_device_add(pdev);
+
+       if (ret != 0) {
+               dev_err(wm8350->dev, "Failed to register regulator %d: %d\n",
+                       reg, ret);
+               platform_device_del(pdev);
+               wm8350->pmic.pdev[reg] = NULL;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_regulator);
+
+static struct platform_driver wm8350_regulator_driver = {
+       .probe = wm8350_regulator_probe,
+       .remove = wm8350_regulator_remove,
+       .driver         = {
+               .name   = "wm8350-regulator",
+       },
+};
+
+static int __init wm8350_regulator_init(void)
+{
+       return platform_driver_register(&wm8350_regulator_driver);
+}
+subsys_initcall(wm8350_regulator_init);
+
+static void __exit wm8350_regulator_exit(void)
+{
+       platform_driver_unregister(&wm8350_regulator_driver);
+}
+module_exit(wm8350_regulator_exit);
+
+/* Module information */
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_DESCRIPTION("WM8350 voltage and current regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
new file mode 100644 (file)
index 0000000..48b372e
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Regulator support for WM8400
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/wm8400-private.h>
+
+static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       u16 val;
+
+       val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+       return (val & WM8400_LDO1_ENA) != 0;
+}
+
+static int wm8400_ldo_enable(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+       return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+                              WM8400_LDO1_ENA, WM8400_LDO1_ENA);
+}
+
+static int wm8400_ldo_disable(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+
+       return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+                              WM8400_LDO1_ENA, 0);
+}
+
+static int wm8400_ldo_get_voltage(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       u16 val;
+
+       val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
+       val &= WM8400_LDO1_VSEL_MASK;
+
+       if (val < 15)
+               return 900000 + (val * 50000);
+       else
+               return 1600000 + ((val - 14) * 100000);
+}
+
+static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
+                                 int min_uV, int max_uV)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       u16 val;
+
+       if (min_uV < 900000 || min_uV > 3300000)
+               return -EINVAL;
+
+       if (min_uV < 1700000) {
+               /* Steps of 50mV from 900mV;  */
+               val = (min_uV - 850001) / 50000;
+
+               if ((val * 50000) + 900000 > max_uV)
+                       return -EINVAL;
+               BUG_ON((val * 50000) + 900000 < min_uV);
+       } else {
+               /* Steps of 100mV from 1700mV */
+               val = ((min_uV - 1600001) / 100000);
+
+               if ((val * 100000) + 1700000 > max_uV)
+                       return -EINVAL;
+               BUG_ON((val * 100000) + 1700000 < min_uV);
+
+               val += 0xf;
+       }
+
+       return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
+                              WM8400_LDO1_VSEL_MASK, val);
+}
+
+static struct regulator_ops wm8400_ldo_ops = {
+       .is_enabled = wm8400_ldo_is_enabled,
+       .enable = wm8400_ldo_enable,
+       .disable = wm8400_ldo_disable,
+       .get_voltage = wm8400_ldo_get_voltage,
+       .set_voltage = wm8400_ldo_set_voltage,
+};
+
+static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+       u16 val;
+
+       val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+       return (val & WM8400_DC1_ENA) != 0;
+}
+
+static int wm8400_dcdc_enable(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+       return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                              WM8400_DC1_ENA, WM8400_DC1_ENA);
+}
+
+static int wm8400_dcdc_disable(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+       return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                              WM8400_DC1_ENA, 0);
+}
+
+static int wm8400_dcdc_get_voltage(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       u16 val;
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+       val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
+       val &= WM8400_DC1_VSEL_MASK;
+
+       return 850000 + (25000 * val);
+}
+
+static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
+                                 int min_uV, int max_uV)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       u16 val;
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+
+       if (min_uV < 850000)
+               return -EINVAL;
+
+       val = (min_uV - 825001) / 25000;
+
+       if (850000 + (25000 * val) > max_uV)
+               return -EINVAL;
+       BUG_ON(850000 + (25000 * val) < min_uV);
+
+       return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                              WM8400_DC1_VSEL_MASK, val);
+}
+
+static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+       u16 data[2];
+       int ret;
+
+       ret = wm8400_block_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset, 2,
+                               data);
+       if (ret != 0)
+               return 0;
+
+       /* Datasheet: hibernate */
+       if (data[0] & WM8400_DC1_SLEEP)
+               return REGULATOR_MODE_STANDBY;
+
+       /* Datasheet: standby */
+       if (!(data[0] & WM8400_DC1_ACTIVE))
+               return REGULATOR_MODE_IDLE;
+
+       /* Datasheet: active with or without force PWM */
+       if (data[1] & WM8400_DC1_FRC_PWM)
+               return REGULATOR_MODE_FAST;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
+{
+       struct wm8400 *wm8400 = rdev_get_drvdata(dev);
+       int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
+       int ret;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               /* Datasheet: active with force PWM */
+               ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+                                     WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
+               if (ret != 0)
+                       return ret;
+
+               return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                                      WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+                                      WM8400_DC1_ACTIVE);
+
+       case REGULATOR_MODE_NORMAL:
+               /* Datasheet: active */
+               ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_2 + offset,
+                                     WM8400_DC1_FRC_PWM, 0);
+               if (ret != 0)
+                       return ret;
+
+               return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                                      WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
+                                      WM8400_DC1_ACTIVE);
+
+       case REGULATOR_MODE_IDLE:
+               /* Datasheet: standby */
+               ret = wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                                     WM8400_DC1_ACTIVE, 0);
+               if (ret != 0)
+                       return ret;
+               return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
+                                      WM8400_DC1_SLEEP, 0);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
+                                                int input_uV, int output_uV,
+                                                int load_uA)
+{
+       return REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops wm8400_dcdc_ops = {
+       .is_enabled = wm8400_dcdc_is_enabled,
+       .enable = wm8400_dcdc_enable,
+       .disable = wm8400_dcdc_disable,
+       .get_voltage = wm8400_dcdc_get_voltage,
+       .set_voltage = wm8400_dcdc_set_voltage,
+       .get_mode = wm8400_dcdc_get_mode,
+       .set_mode = wm8400_dcdc_set_mode,
+       .get_optimum_mode = wm8400_dcdc_get_optimum_mode,
+};
+
+static struct regulator_desc regulators[] = {
+       {
+               .name = "LDO1",
+               .id = WM8400_LDO1,
+               .ops = &wm8400_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO2",
+               .id = WM8400_LDO2,
+               .ops = &wm8400_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO3",
+               .id = WM8400_LDO3,
+               .ops = &wm8400_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "LDO4",
+               .id = WM8400_LDO4,
+               .ops = &wm8400_ldo_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC1",
+               .id = WM8400_DCDC1,
+               .ops = &wm8400_dcdc_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+       {
+               .name = "DCDC2",
+               .id = WM8400_DCDC2,
+               .ops = &wm8400_dcdc_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init wm8400_regulator_probe(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev;
+
+       rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
+               pdev->dev.driver_data);
+
+       if (IS_ERR(rdev))
+               return PTR_ERR(rdev);
+
+       return 0;
+}
+
+static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+{
+       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+       regulator_unregister(rdev);
+
+       return 0;
+}
+
+static struct platform_driver wm8400_regulator_driver = {
+       .driver = {
+               .name = "wm8400-regulator",
+       },
+       .probe = wm8400_regulator_probe,
+       .remove = __devexit_p(wm8400_regulator_remove),
+};
+
+/**
+ * wm8400_register_regulator - enable software control of a WM8400 regulator
+ *
+ * This function enables software control of a WM8400 regulator via
+ * the regulator API.  It is intended to be called from the
+ * platform_init() callback of the WM8400 MFD driver.
+ *
+ * @param dev      The WM8400 device to operate on.
+ * @param reg      The regulator to control.
+ * @param initdata Regulator initdata for the regulator.
+ */
+int wm8400_register_regulator(struct device *dev, int reg,
+                             struct regulator_init_data *initdata)
+{
+       struct wm8400 *wm8400 = dev->driver_data;
+
+       if (wm8400->regulators[reg].name)
+               return -EBUSY;
+
+       initdata->driver_data = wm8400;
+
+       wm8400->regulators[reg].name = "wm8400-regulator";
+       wm8400->regulators[reg].id = reg;
+       wm8400->regulators[reg].dev.parent = dev;
+       wm8400->regulators[reg].dev.driver_data = wm8400;
+       wm8400->regulators[reg].dev.platform_data = initdata;
+
+       return platform_device_register(&wm8400->regulators[reg]);
+}
+EXPORT_SYMBOL_GPL(wm8400_register_regulator);
+
+static int __init wm8400_regulator_init(void)
+{
+       return platform_driver_register(&wm8400_regulator_driver);
+}
+module_init(wm8400_regulator_init);
+
+static void __exit wm8400_regulator_exit(void)
+{
+       platform_driver_unregister(&wm8400_regulator_driver);
+}
+module_exit(wm8400_regulator_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM8400 regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8400-regulator");
index b57fba5c6d027d645573ae070649d745bab26950..f660ef3e5b29e801f205eb06358cf54f26490e25 100644 (file)
@@ -220,22 +220,22 @@ config RTC_DRV_PCF8583
          will be called rtc-pcf8583.
 
 config RTC_DRV_M41T80
-       tristate "ST M41T80/81/82/83/84/85/87"
+       tristate "ST M41T65/M41T80/81/82/83/84/85/87"
        help
-         If you say Y here you will get support for the
-         ST M41T80 RTC chips series. Currently following chips are
-         supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85
-         and M41ST87.
+         If you say Y here you will get support for the ST M41T60
+         and M41T80 RTC chips series. Currently, the following chips are
+         supported: M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84,
+         M41ST85, and M41ST87.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-m41t80.
 
 config RTC_DRV_M41T80_WDT
-       bool "ST M41T80 series RTC watchdog timer"
+       bool "ST M41T65/M41T80 series RTC watchdog timer"
        depends on RTC_DRV_M41T80
        help
          If you say Y here you will get support for the
-         watchdog timer in ST M41T80 RTC chips series.
+         watchdog timer in the ST M41T60 and M41T80 RTC chips series.
 
 config RTC_DRV_TWL92330
        boolean "TI TWL92330/Menelaus"
@@ -319,6 +319,15 @@ config RTC_DRV_RS5C348
          This driver can also be built as a module. If so, the module
          will be called rtc-rs5c348.
 
+config RTC_DRV_DS3234
+       tristate "Maxim/Dallas DS3234"
+       help
+         If you say yes here you get support for the
+         Maxim/Dallas DS3234 SPI RTC chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-ds3234.
+
 endif # SPI_MASTER
 
 comment "Platform RTC drivers"
@@ -352,6 +361,11 @@ config RTC_DRV_DS1216
        help
          If you say yes here you get support for the Dallas DS1216 RTC chips.
 
+config RTC_DRV_DS1286
+       tristate "Dallas DS1286"
+       help
+         If you say yes here you get support for the Dallas DS1286 RTC chips.
+
 config RTC_DRV_DS1302
        tristate "Dallas DS1302"
        depends on SH_SECUREEDGE5410
@@ -405,6 +419,15 @@ config RTC_DRV_M48T86
          This driver can also be built as a module. If so, the module
          will be called rtc-m48t86.
 
+config RTC_DRV_M48T35
+       tristate "ST M48T35"
+       help
+         If you say Y here you will get support for the
+         ST M48T35 RTC chip.
+
+         This driver can also be built as a module, if so, the module
+         will be called "rtc-m48t35".
+
 config RTC_DRV_M48T59
        tristate "ST M48T59/M48T08/M48T02"
        help
@@ -589,7 +612,7 @@ config RTC_DRV_RS5C313
 
 config RTC_DRV_PPC
        tristate "PowerPC machine dependent RTC support"
-       depends on PPC_MERGE
+       depends on PPC
        help
         The PowerPC kernel has machine-specific functions for accessing
         the RTC. This exposes that functionality through the generic RTC
index 10f41f85c38a0fbbea375e7d38b5ef1ea3a805a1..d05928b3ca9466b7402a2392f555e32f3051ad31 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9)        += rtc-at91sam9.o
 obj-$(CONFIG_RTC_DRV_BFIN)     += rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_DS1216)   += rtc-ds1216.o
+obj-$(CONFIG_RTC_DRV_DS1286)   += rtc-ds1286.o
 obj-$(CONFIG_RTC_DRV_DS1302)   += rtc-ds1302.o
 obj-$(CONFIG_RTC_DRV_DS1305)   += rtc-ds1305.o
 obj-$(CONFIG_RTC_DRV_DS1307)   += rtc-ds1307.o
@@ -31,11 +32,13 @@ obj-$(CONFIG_RTC_DRV_DS1511)        += rtc-ds1511.o
 obj-$(CONFIG_RTC_DRV_DS1553)   += rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)   += rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)   += rtc-ds1742.o
+obj-$(CONFIG_RTC_DRV_DS3234)   += rtc-ds3234.o
 obj-$(CONFIG_RTC_DRV_EP93XX)   += rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)   += rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_ISL1208)  += rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)   += rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)   += rtc-m41t94.o
+obj-$(CONFIG_RTC_DRV_M48T35)   += rtc-m48t35.o
 obj-$(CONFIG_RTC_DRV_M48T59)   += rtc-m48t59.o
 obj-$(CONFIG_RTC_DRV_M48T86)   += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_BQ4802)   += rtc-bq4802.o
index 4e888cc8be5b1cacbeac68bd054ab3f6f65d295a..37082616482bd7a79ad3162ba00ca82bd260894e 100644 (file)
 #include <linux/completion.h>
 
 #include <asm/uaccess.h>
+
 #include <mach/at91_rtc.h>
 
 
-#define AT91_RTC_FREQ          1
 #define AT91_RTC_EPOCH         1900UL  /* just like arch/arm/common/rtctime.c */
 
 static DECLARE_COMPLETION(at91_rtc_updated);
@@ -228,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
                        (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
        seq_printf(seq, "periodic_IRQ\t: %s\n",
                        (imr & AT91_RTC_SECEV) ? "yes" : "no");
-       seq_printf(seq, "periodic_freq\t: %ld\n",
-                       (unsigned long) AT91_RTC_FREQ);
 
        return 0;
 }
index b23af0c2a869181e5b4fb5480546b93103d93d40..963ad0b6a4e9da64ff911cba52508e5c39b8085a 100644 (file)
@@ -913,6 +913,92 @@ static inline int cmos_poweroff(struct device *dev)
  * predate even PNPBIOS should set up platform_bus devices.
  */
 
+#ifdef CONFIG_ACPI
+
+#include <linux/acpi.h>
+
+#ifdef CONFIG_PM
+static u32 rtc_handler(void *context)
+{
+       acpi_clear_event(ACPI_EVENT_RTC);
+       acpi_disable_event(ACPI_EVENT_RTC, 0);
+       return ACPI_INTERRUPT_HANDLED;
+}
+
+static inline void rtc_wake_setup(void)
+{
+       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+       /*
+        * After the RTC handler is installed, the Fixed_RTC event should
+        * be disabled. Only when the RTC alarm is set will it be enabled.
+        */
+       acpi_clear_event(ACPI_EVENT_RTC);
+       acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_on(struct device *dev)
+{
+       acpi_clear_event(ACPI_EVENT_RTC);
+       acpi_enable_event(ACPI_EVENT_RTC, 0);
+}
+
+static void rtc_wake_off(struct device *dev)
+{
+       acpi_disable_event(ACPI_EVENT_RTC, 0);
+}
+#else
+#define rtc_wake_setup()       do{}while(0)
+#define rtc_wake_on            NULL
+#define rtc_wake_off           NULL
+#endif
+
+/* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
+ * its device node and pass extra config data.  This helps its driver use
+ * capabilities that the now-obsolete mc146818 didn't have, and informs it
+ * that this board's RTC is wakeup-capable (per ACPI spec).
+ */
+static struct cmos_rtc_board_info acpi_rtc_info;
+
+static void __devinit
+cmos_wake_setup(struct device *dev)
+{
+       if (acpi_disabled)
+               return;
+
+       rtc_wake_setup();
+       acpi_rtc_info.wake_on = rtc_wake_on;
+       acpi_rtc_info.wake_off = rtc_wake_off;
+
+       /* workaround bug in some ACPI tables */
+       if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
+               dev_dbg(dev, "bogus FADT month_alarm (%d)\n",
+                       acpi_gbl_FADT.month_alarm);
+               acpi_gbl_FADT.month_alarm = 0;
+       }
+
+       acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
+       acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
+       acpi_rtc_info.rtc_century = acpi_gbl_FADT.century;
+
+       /* NOTE:  S4_RTC_WAKE is NOT currently useful to Linux */
+       if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
+               dev_info(dev, "RTC can wake from S4\n");
+
+       dev->platform_data = &acpi_rtc_info;
+
+       /* RTC always wakes from S1/S2/S3, and often S4/STD */
+       device_init_wakeup(dev, 1);
+}
+
+#else
+
+static void __devinit
+cmos_wake_setup(struct device *dev)
+{
+}
+
+#endif
+
 #ifdef CONFIG_PNP
 
 #include <linux/pnp.h>
@@ -920,6 +1006,8 @@ static inline int cmos_poweroff(struct device *dev)
 static int __devinit
 cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
+       cmos_wake_setup(&pnp->dev);
+
        if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
                /* Some machines contain a PNP entry for the RTC, but
                 * don't define the IRQ. It should always be safe to
@@ -997,6 +1085,7 @@ static struct pnp_driver cmos_pnp_driver = {
 
 static int __init cmos_platform_probe(struct platform_device *pdev)
 {
+       cmos_wake_setup(&pdev->dev);
        return cmos_do_probe(&pdev->dev,
                        platform_get_resource(pdev, IORESOURCE_IO, 0),
                        platform_get_irq(pdev, 0));
@@ -1031,29 +1120,32 @@ static struct platform_driver cmos_platform_driver = {
 
 static int __init cmos_init(void)
 {
+       int retval = 0;
+
 #ifdef CONFIG_PNP
-       if (pnp_platform_devices)
-               return pnp_register_driver(&cmos_pnp_driver);
-       else
-               return platform_driver_probe(&cmos_platform_driver,
-                       cmos_platform_probe);
-#else
-       return platform_driver_probe(&cmos_platform_driver,
-                       cmos_platform_probe);
-#endif /* CONFIG_PNP */
+       pnp_register_driver(&cmos_pnp_driver);
+#endif
+
+       if (!cmos_rtc.dev)
+               retval = platform_driver_probe(&cmos_platform_driver,
+                                              cmos_platform_probe);
+
+       if (retval == 0)
+               return 0;
+
+#ifdef CONFIG_PNP
+       pnp_unregister_driver(&cmos_pnp_driver);
+#endif
+       return retval;
 }
 module_init(cmos_init);
 
 static void __exit cmos_exit(void)
 {
 #ifdef CONFIG_PNP
-       if (pnp_platform_devices)
-               pnp_unregister_driver(&cmos_pnp_driver);
-       else
-               platform_driver_unregister(&cmos_platform_driver);
-#else
+       pnp_unregister_driver(&cmos_pnp_driver);
+#endif
        platform_driver_unregister(&cmos_platform_driver);
-#endif /* CONFIG_PNP */
 }
 module_exit(cmos_exit);
 
index 52e2743b04ecf77bb6a975d6c8609fa042025dea..079e9ed907e06caa6d5a453c56c31e413f0cf6c5 100644 (file)
@@ -432,9 +432,15 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
 {
        struct rtc_device *rtc = file->private_data;
 
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
-       clear_uie(rtc);
-#endif
+       /* We shut down the repeating IRQs that userspace enabled,
+        * since nothing is listening to them.
+        *  - Update (UIE) ... currently only managed through ioctls
+        *  - Periodic (PIE) ... also used through rtc_*() interface calls
+        *
+        * Leave the alarm alone; it may be set to trigger a system wakeup
+        * later, or be used by kernel code, and is a one-shot event anyway.
+        */
+       rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
        rtc_irq_set_state(rtc, NULL, 0);
 
        if (rtc->ops->release)
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
new file mode 100644 (file)
index 0000000..4fcb16b
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * DS1286 Real Time Clock interface for Linux
+ *
+ * Copyright (C) 1998, 1999, 2000 Ralf Baechle
+ * Copyright (C) 2008 Thomas Bogendoerfer
+ *
+ * Based on code written by Paul Gortmaker.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+#include <linux/ds1286.h>
+#include <linux/io.h>
+
+#define DRV_VERSION            "1.0"
+
+struct ds1286_priv {
+       struct rtc_device *rtc;
+       u32 __iomem *rtcregs;
+       size_t size;
+       unsigned long baseaddr;
+       spinlock_t lock;
+};
+
+static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg)
+{
+       return __raw_readl(&priv->rtcregs[reg]) & 0xff;
+}
+
+static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg)
+{
+       __raw_writel(data, &priv->rtcregs[reg]);
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned long flags;
+       unsigned char val;
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               /* Mask alarm int. enab. bit    */
+               spin_lock_irqsave(&priv->lock, flags);
+               val = ds1286_rtc_read(priv, RTC_CMD);
+               val |=  RTC_TDM;
+               ds1286_rtc_write(priv, val, RTC_CMD);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               break;
+       case RTC_AIE_ON:
+               /* Allow alarm interrupts.      */
+               spin_lock_irqsave(&priv->lock, flags);
+               val = ds1286_rtc_read(priv, RTC_CMD);
+               val &=  ~RTC_TDM;
+               ds1286_rtc_write(priv, val, RTC_CMD);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               break;
+       case RTC_WIE_OFF:
+               /* Mask watchdog int. enab. bit */
+               spin_lock_irqsave(&priv->lock, flags);
+               val = ds1286_rtc_read(priv, RTC_CMD);
+               val |= RTC_WAM;
+               ds1286_rtc_write(priv, val, RTC_CMD);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               break;
+       case RTC_WIE_ON:
+               /* Allow watchdog interrupts.   */
+               spin_lock_irqsave(&priv->lock, flags);
+               val = ds1286_rtc_read(priv, RTC_CMD);
+               val &= ~RTC_WAM;
+               ds1286_rtc_write(priv, val, RTC_CMD);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+#else
+#define ds1286_ioctl    NULL
+#endif
+
+#ifdef CONFIG_PROC_FS
+
+static int ds1286_proc(struct device *dev, struct seq_file *seq)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned char month, cmd, amode;
+       const char *s;
+
+       month = ds1286_rtc_read(priv, RTC_MONTH);
+       seq_printf(seq,
+                  "oscillator\t: %s\n"
+                  "square_wave\t: %s\n",
+                  (month & RTC_EOSC) ? "disabled" : "enabled",
+                  (month & RTC_ESQW) ? "disabled" : "enabled");
+
+       amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) |
+               ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) |
+               ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7);
+       switch (amode) {
+       case 7:
+               s = "each minute";
+               break;
+       case 3:
+               s = "minutes match";
+               break;
+       case 1:
+               s = "hours and minutes match";
+               break;
+       case 0:
+               s = "days, hours and minutes match";
+               break;
+       default:
+               s = "invalid";
+               break;
+       }
+       seq_printf(seq, "alarm_mode\t: %s\n", s);
+
+       cmd = ds1286_rtc_read(priv, RTC_CMD);
+       seq_printf(seq,
+                  "alarm_enable\t: %s\n"
+                  "wdog_alarm\t: %s\n"
+                  "alarm_mask\t: %s\n"
+                  "wdog_alarm_mask\t: %s\n"
+                  "interrupt_mode\t: %s\n"
+                  "INTB_mode\t: %s_active\n"
+                  "interrupt_pins\t: %s\n",
+                  (cmd & RTC_TDF) ? "yes" : "no",
+                  (cmd & RTC_WAF) ? "yes" : "no",
+                  (cmd & RTC_TDM) ? "disabled" : "enabled",
+                  (cmd & RTC_WAM) ? "disabled" : "enabled",
+                  (cmd & RTC_PU_LVL) ? "pulse" : "level",
+                  (cmd & RTC_IBH_LO) ? "low" : "high",
+                  (cmd & RTC_IPSW) ? "unswapped" : "swapped");
+       return 0;
+}
+
+#else
+#define ds1286_proc     NULL
+#endif
+
+static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned char save_control;
+       unsigned long flags;
+       unsigned long uip_watchdog = jiffies;
+
+       /*
+        * read RTC once any update in progress is done. The update
+        * can take just over 2ms. We wait 10 to 20ms. There is no need to
+        * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+        * If you need to know *exactly* when a second has started, enable
+        * periodic update complete interrupts, (via ioctl) and then
+        * immediately read /dev/rtc which will block until you get the IRQ.
+        * Once the read clears, read the RTC time (again via ioctl). Easy.
+        */
+
+       if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE)
+               while (time_before(jiffies, uip_watchdog + 2*HZ/100))
+                       barrier();
+
+       /*
+        * Only the values that we read from the RTC are set. We leave
+        * tm_wday, tm_yday and tm_isdst untouched. Even though the
+        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+        * by the RTC when initially set to a non-zero value.
+        */
+       spin_lock_irqsave(&priv->lock, flags);
+       save_control = ds1286_rtc_read(priv, RTC_CMD);
+       ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
+
+       tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS);
+       tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES);
+       tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f;
+       tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE);
+       tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f;
+       tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR);
+
+       ds1286_rtc_write(priv, save_control, RTC_CMD);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon);
+       tm->tm_year = bcd2bin(tm->tm_year);
+
+       /*
+        * Account for differences between how the RTC uses the values
+        * and how they are defined in a struct rtc_time;
+        */
+       if (tm->tm_year < 45)
+               tm->tm_year += 30;
+       tm->tm_year += 40;
+       if (tm->tm_year < 70)
+               tm->tm_year += 100;
+
+       tm->tm_mon--;
+
+       return rtc_valid_tm(tm);
+}
+
+static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned char mon, day, hrs, min, sec;
+       unsigned char save_control;
+       unsigned int yrs;
+       unsigned long flags;
+
+       yrs = tm->tm_year + 1900;
+       mon = tm->tm_mon + 1;   /* tm_mon starts at zero */
+       day = tm->tm_mday;
+       hrs = tm->tm_hour;
+       min = tm->tm_min;
+       sec = tm->tm_sec;
+
+       if (yrs < 1970)
+               return -EINVAL;
+
+       yrs -= 1940;
+       if (yrs > 255)    /* They are unsigned */
+               return -EINVAL;
+
+       if (yrs >= 100)
+               yrs -= 100;
+
+       sec = bin2bcd(sec);
+       min = bin2bcd(min);
+       hrs = bin2bcd(hrs);
+       day = bin2bcd(day);
+       mon = bin2bcd(mon);
+       yrs = bin2bcd(yrs);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       save_control = ds1286_rtc_read(priv, RTC_CMD);
+       ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
+
+       ds1286_rtc_write(priv, yrs, RTC_YEAR);
+       ds1286_rtc_write(priv, mon, RTC_MONTH);
+       ds1286_rtc_write(priv, day, RTC_DATE);
+       ds1286_rtc_write(priv, hrs, RTC_HOURS);
+       ds1286_rtc_write(priv, min, RTC_MINUTES);
+       ds1286_rtc_write(priv, sec, RTC_SECONDS);
+       ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND);
+
+       ds1286_rtc_write(priv, save_control, RTC_CMD);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       return 0;
+}
+
+static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned char cmd;
+       unsigned long flags;
+
+       /*
+        * Only the values that we read from the RTC are set. That
+        * means only tm_wday, tm_hour, tm_min.
+        */
+       spin_lock_irqsave(&priv->lock, flags);
+       alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;
+       alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM)  & 0x1f;
+       alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM)    & 0x07;
+       cmd = ds1286_rtc_read(priv, RTC_CMD);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       alm->time.tm_min = bcd2bin(alm->time.tm_min);
+       alm->time.tm_hour = bcd2bin(alm->time.tm_hour);
+       alm->time.tm_sec = 0;
+       return 0;
+}
+
+static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct ds1286_priv *priv = dev_get_drvdata(dev);
+       unsigned char hrs, min, sec;
+
+       hrs = alm->time.tm_hour;
+       min = alm->time.tm_min;
+       sec = alm->time.tm_sec;
+
+       if (hrs >= 24)
+               hrs = 0xff;
+
+       if (min >= 60)
+               min = 0xff;
+
+       if (sec != 0)
+               return -EINVAL;
+
+       min = bin2bcd(min);
+       hrs = bin2bcd(hrs);
+
+       spin_lock(&priv->lock);
+       ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM);
+       ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM);
+       spin_unlock(&priv->lock);
+
+       return 0;
+}
+
+static const struct rtc_class_ops ds1286_ops = {
+       .ioctl          = ds1286_ioctl,
+       .proc           = ds1286_proc,
+       .read_time      = ds1286_read_time,
+       .set_time       = ds1286_set_time,
+       .read_alarm     = ds1286_read_alarm,
+       .set_alarm      = ds1286_set_alarm,
+};
+
+static int __devinit ds1286_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       struct ds1286_priv *priv;
+       int ret = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->size = res->end - res->start + 1;
+       if (!request_mem_region(res->start, priv->size, pdev->name)) {
+               ret = -EBUSY;
+               goto out;
+       }
+       priv->baseaddr = res->start;
+       priv->rtcregs = ioremap(priv->baseaddr, priv->size);
+       if (!priv->rtcregs) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       spin_lock_init(&priv->lock);
+       rtc = rtc_device_register("ds1286", &pdev->dev,
+                                 &ds1286_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto out;
+       }
+       priv->rtc = rtc;
+       platform_set_drvdata(pdev, priv);
+       return 0;
+
+out:
+       if (priv->rtc)
+               rtc_device_unregister(priv->rtc);
+       if (priv->rtcregs)
+               iounmap(priv->rtcregs);
+       if (priv->baseaddr)
+               release_mem_region(priv->baseaddr, priv->size);
+       kfree(priv);
+       return ret;
+}
+
+static int __devexit ds1286_remove(struct platform_device *pdev)
+{
+       struct ds1286_priv *priv = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(priv->rtc);
+       iounmap(priv->rtcregs);
+       release_mem_region(priv->baseaddr, priv->size);
+       kfree(priv);
+       return 0;
+}
+
+static struct platform_driver ds1286_platform_driver = {
+       .driver         = {
+               .name   = "rtc-ds1286",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ds1286_probe,
+       .remove         = __devexit_p(ds1286_remove),
+};
+
+static int __init ds1286_init(void)
+{
+       return platform_driver_register(&ds1286_platform_driver);
+}
+
+static void __exit ds1286_exit(void)
+{
+       platform_driver_unregister(&ds1286_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("DS1286 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:rtc-ds1286");
+
+module_init(ds1286_init);
+module_exit(ds1286_exit);
index bbf97e65202a24327b57beafbba98d6daca738a2..4fcf0734a6ef088f5bf162de0f09341bac979349 100644 (file)
  * to have set the chip up as a clock (turning on the oscillator and
  * setting the date and time), Linux can ignore the non-clock features.
  * That's a natural job for a factory or repair bench.
- *
- * This is currently a simple no-alarms driver.  If your board has the
- * alarm irq wired up on a ds1337 or ds1339, and you want to use that,
- * then look at the rtc-rs5c372 driver for code to steal...
  */
 enum ds_type {
        ds_1307,
@@ -67,6 +63,7 @@ enum ds_type {
 #      define DS1307_BIT_RS0           0x01
 #define DS1337_REG_CONTROL     0x0e
 #      define DS1337_BIT_nEOSC         0x80
+#      define DS1339_BIT_BBSQI         0x20
 #      define DS1337_BIT_RS2           0x10
 #      define DS1337_BIT_RS1           0x08
 #      define DS1337_BIT_INTCN         0x04
@@ -83,19 +80,22 @@ enum ds_type {
 #      define DS1337_BIT_OSF           0x80
 #      define DS1337_BIT_A2I           0x02
 #      define DS1337_BIT_A1I           0x01
+#define DS1339_REG_ALARM1_SECS 0x07
 #define DS1339_REG_TRICKLE     0x10
 
 
 
 struct ds1307 {
        u8                      reg_addr;
-       bool                    has_nvram;
-       u8                      regs[8];
+       u8                      regs[11];
        enum ds_type            type;
+       unsigned long           flags;
+#define HAS_NVRAM      0               /* bit 0 == sysfs file active */
+#define HAS_ALARM      1               /* bit 1 == irq claimed */
        struct i2c_msg          msg[2];
        struct i2c_client       *client;
-       struct i2c_client       dev;
        struct rtc_device       *rtc;
+       struct work_struct      work;
 };
 
 struct chip_desc {
@@ -132,12 +132,79 @@ static const struct i2c_device_id ds1307_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ds1307_id);
 
+/*----------------------------------------------------------------------*/
+
+/*
+ * The IRQ logic includes a "real" handler running in IRQ context just
+ * long enough to schedule this workqueue entry.   We need a task context
+ * to talk to the RTC, since I2C I/O calls require that; and disable the
+ * IRQ until we clear its status on the chip, so that this handler can
+ * work with any type of triggering (not just falling edge).
+ *
+ * The ds1337 and ds1339 both have two alarms, but we only use the first
+ * one (with a "seconds" field).  For ds1337 we expect nINTA is our alarm
+ * signal; ds1339 chips have only one alarm signal.
+ */
+static void ds1307_work(struct work_struct *work)
+{
+       struct ds1307           *ds1307;
+       struct i2c_client       *client;
+       struct mutex            *lock;
+       int                     stat, control;
+
+       ds1307 = container_of(work, struct ds1307, work);
+       client = ds1307->client;
+       lock = &ds1307->rtc->ops_lock;
+
+       mutex_lock(lock);
+       stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+       if (stat < 0)
+               goto out;
+
+       if (stat & DS1337_BIT_A1I) {
+               stat &= ~DS1337_BIT_A1I;
+               i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat);
+
+               control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+               if (control < 0)
+                       goto out;
+
+               control &= ~DS1337_BIT_A1IE;
+               i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+
+               /* rtc_update_irq() assumes that it is called
+                * from IRQ-disabled context.
+                */
+               local_irq_disable();
+               rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
+               local_irq_enable();
+       }
+
+out:
+       if (test_bit(HAS_ALARM, &ds1307->flags))
+               enable_irq(client->irq);
+       mutex_unlock(lock);
+}
+
+static irqreturn_t ds1307_irq(int irq, void *dev_id)
+{
+       struct i2c_client       *client = dev_id;
+       struct ds1307           *ds1307 = i2c_get_clientdata(client);
+
+       disable_irq_nosync(irq);
+       schedule_work(&ds1307->work);
+       return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
        struct ds1307   *ds1307 = dev_get_drvdata(dev);
        int             tmp;
 
        /* read the RTC date and time registers all at once */
+       ds1307->reg_addr = 0;
        ds1307->msg[1].flags = I2C_M_RD;
        ds1307->msg[1].len = 7;
 
@@ -231,9 +298,186 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
        return 0;
 }
 
+static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct ds1307           *ds1307 = i2c_get_clientdata(client);
+       int                     ret;
+
+       if (!test_bit(HAS_ALARM, &ds1307->flags))
+               return -EINVAL;
+
+       /* read all ALARM1, ALARM2, and status registers at once */
+       ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
+       ds1307->msg[1].flags = I2C_M_RD;
+       ds1307->msg[1].len = 9;
+
+       ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+                       ds1307->msg, 2);
+       if (ret != 2) {
+               dev_err(dev, "%s error %d\n", "alarm read", ret);
+               return -EIO;
+       }
+
+       dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
+                       "alarm read",
+                       ds1307->regs[0], ds1307->regs[1],
+                       ds1307->regs[2], ds1307->regs[3],
+                       ds1307->regs[4], ds1307->regs[5],
+                       ds1307->regs[6], ds1307->regs[7],
+                       ds1307->regs[8]);
+
+       /* report alarm time (ALARM1); assume 24 hour and day-of-month modes,
+        * and that all four fields are checked matches
+        */
+       t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f);
+       t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
+       t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
+       t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
+       t->time.tm_mon = -1;
+       t->time.tm_year = -1;
+       t->time.tm_wday = -1;
+       t->time.tm_yday = -1;
+       t->time.tm_isdst = -1;
+
+       /* ... and status */
+       t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
+       t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I);
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, enabled=%d, pending=%d\n",
+               "alarm read", t->time.tm_sec, t->time.tm_min,
+               t->time.tm_hour, t->time.tm_mday,
+               t->enabled, t->pending);
+
+       return 0;
+}
+
+static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+{
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct ds1307           *ds1307 = i2c_get_clientdata(client);
+       unsigned char           *buf = ds1307->regs;
+       u8                      control, status;
+       int                     ret;
+
+       if (!test_bit(HAS_ALARM, &ds1307->flags))
+               return -EINVAL;
+
+       dev_dbg(dev, "%s secs=%d, mins=%d, "
+               "hours=%d, mday=%d, enabled=%d, pending=%d\n",
+               "alarm set", t->time.tm_sec, t->time.tm_min,
+               t->time.tm_hour, t->time.tm_mday,
+               t->enabled, t->pending);
+
+       /* read current status of both alarms and the chip */
+       ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
+       ds1307->msg[1].flags = I2C_M_RD;
+       ds1307->msg[1].len = 9;
+
+       ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+                       ds1307->msg, 2);
+       if (ret != 2) {
+               dev_err(dev, "%s error %d\n", "alarm write", ret);
+               return -EIO;
+       }
+       control = ds1307->regs[7];
+       status = ds1307->regs[8];
+
+       dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n",
+                       "alarm set (old status)",
+                       ds1307->regs[0], ds1307->regs[1],
+                       ds1307->regs[2], ds1307->regs[3],
+                       ds1307->regs[4], ds1307->regs[5],
+                       ds1307->regs[6], control, status);
+
+       /* set ALARM1, using 24 hour and day-of-month modes */
+       *buf++ = DS1339_REG_ALARM1_SECS;        /* first register addr */
+       buf[0] = bin2bcd(t->time.tm_sec);
+       buf[1] = bin2bcd(t->time.tm_min);
+       buf[2] = bin2bcd(t->time.tm_hour);
+       buf[3] = bin2bcd(t->time.tm_mday);
+
+       /* set ALARM2 to non-garbage */
+       buf[4] = 0;
+       buf[5] = 0;
+       buf[6] = 0;
+
+       /* optionally enable ALARM1 */
+       buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
+       if (t->enabled) {
+               dev_dbg(dev, "alarm IRQ armed\n");
+               buf[7] |= DS1337_BIT_A1IE;      /* only ALARM1 is used */
+       }
+       buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
+
+       ds1307->msg[1].flags = 0;
+       ds1307->msg[1].len = 10;
+
+       ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
+                       &ds1307->msg[1], 1);
+       if (ret != 1) {
+               dev_err(dev, "can't set alarm time\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct ds1307           *ds1307 = i2c_get_clientdata(client);
+       int                     ret;
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               if (!test_bit(HAS_ALARM, &ds1307->flags))
+                       return -ENOTTY;
+
+               ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+               if (ret < 0)
+                       return ret;
+
+               ret &= ~DS1337_BIT_A1IE;
+
+               ret = i2c_smbus_write_byte_data(client,
+                                               DS1337_REG_CONTROL, ret);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       case RTC_AIE_ON:
+               if (!test_bit(HAS_ALARM, &ds1307->flags))
+                       return -ENOTTY;
+
+               ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+               if (ret < 0)
+                       return ret;
+
+               ret |= DS1337_BIT_A1IE;
+
+               ret = i2c_smbus_write_byte_data(client,
+                                               DS1337_REG_CONTROL, ret);
+               if (ret < 0)
+                       return ret;
+
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return 0;
+}
+
 static const struct rtc_class_ops ds13xx_rtc_ops = {
        .read_time      = ds1307_get_time,
        .set_time       = ds1307_set_time,
+       .read_alarm     = ds1307_read_alarm,
+       .set_alarm      = ds1307_set_alarm,
+       .ioctl          = ds1307_ioctl,
 };
 
 /*----------------------------------------------------------------------*/
@@ -327,6 +571,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
        int                     tmp;
        const struct chip_desc  *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
+       int                     want_irq = false;
 
        if (!i2c_check_functionality(adapter,
                        I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
@@ -353,6 +598,12 @@ static int __devinit ds1307_probe(struct i2c_client *client,
        switch (ds1307->type) {
        case ds_1337:
        case ds_1339:
+               /* has IRQ? */
+               if (ds1307->client->irq > 0 && chip->alarm) {
+                       INIT_WORK(&ds1307->work, ds1307_work);
+                       want_irq = true;
+               }
+
                ds1307->reg_addr = DS1337_REG_CONTROL;
                ds1307->msg[1].len = 2;
 
@@ -369,8 +620,20 @@ static int __devinit ds1307_probe(struct i2c_client *client,
 
                /* oscillator off?  turn it on, so clock can tick. */
                if (ds1307->regs[0] & DS1337_BIT_nEOSC)
-                       i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
-                               ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+                       ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
+
+               /* Using IRQ?  Disable the square wave and both alarms.
+                * For ds1339, be sure alarms can trigger when we're
+                * running on Vbackup (BBSQI); we assume ds1337 will
+                * ignore that bit
+                */
+               if (want_irq) {
+                       ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI;
+                       ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
+               }
+
+               i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+                                                       ds1307->regs[0]);
 
                /* oscillator fault?  clear flag, and warn */
                if (ds1307->regs[1] & DS1337_BIT_OSF) {
@@ -495,10 +758,22 @@ read_rtc:
                goto exit_free;
        }
 
+       if (want_irq) {
+               err = request_irq(client->irq, ds1307_irq, 0,
+                         ds1307->rtc->name, client);
+               if (err) {
+                       dev_err(&client->dev,
+                               "unable to request IRQ!\n");
+                       goto exit_irq;
+               }
+               set_bit(HAS_ALARM, &ds1307->flags);
+               dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+       }
+
        if (chip->nvram56) {
                err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
                if (err == 0) {
-                       ds1307->has_nvram = true;
+                       set_bit(HAS_NVRAM, &ds1307->flags);
                        dev_info(&client->dev, "56 bytes nvram\n");
                }
        }
@@ -512,7 +787,9 @@ exit_bad:
                        ds1307->regs[2], ds1307->regs[3],
                        ds1307->regs[4], ds1307->regs[5],
                        ds1307->regs[6]);
-
+exit_irq:
+       if (ds1307->rtc)
+               rtc_device_unregister(ds1307->rtc);
 exit_free:
        kfree(ds1307);
        return err;
@@ -520,9 +797,14 @@ exit_free:
 
 static int __devexit ds1307_remove(struct i2c_client *client)
 {
-       struct ds1307   *ds1307 = i2c_get_clientdata(client);
+       struct ds1307           *ds1307 = i2c_get_clientdata(client);
+
+       if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) {
+               free_irq(client->irq, client);
+               cancel_work_sync(&ds1307->work);
+       }
 
-       if (ds1307->has_nvram)
+       if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
                sysfs_remove_bin_file(&client->dev.kobj, &nvram);
 
        rtc_device_unregister(ds1307->rtc);
index a150418fba765d5db942db7bd2ffdb525716367e..a5b0fc09f0c673976720b10eca2cc3ecf8ff03bb 100644 (file)
@@ -429,12 +429,33 @@ static int __devexit ds1374_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
+{
+       if (client->irq >= 0 && device_may_wakeup(&client->dev))
+               enable_irq_wake(client->irq);
+       return 0;
+}
+
+static int ds1374_resume(struct i2c_client *client)
+{
+       if (client->irq >= 0 && device_may_wakeup(&client->dev))
+               disable_irq_wake(client->irq);
+       return 0;
+}
+#else
+#define ds1374_suspend NULL
+#define ds1374_resume  NULL
+#endif
+
 static struct i2c_driver ds1374_driver = {
        .driver = {
                .name = "rtc-ds1374",
                .owner = THIS_MODULE,
        },
        .probe = ds1374_probe,
+       .suspend = ds1374_suspend,
+       .resume = ds1374_resume,
        .remove = __devexit_p(ds1374_remove),
        .id_table = ds1374_id,
 };
index 0f0d27d1c4ca366916b7958798ac44570681f679..86981d34fbb6717a66d47a11db1287b4e3a4c7f5 100644 (file)
@@ -379,18 +379,6 @@ ds1511_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
- static void
-ds1511_rtc_release(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-       if (pdata->irq >= 0) {
-               pdata->irqen = 0;
-               ds1511_rtc_update_alarm(pdata);
-       }
-}
-
  static int
 ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
@@ -428,7 +416,6 @@ static const struct rtc_class_ops ds1511_rtc_ops = {
        .set_time       = ds1511_rtc_set_time,
        .read_alarm     = ds1511_rtc_read_alarm,
        .set_alarm      = ds1511_rtc_set_alarm,
-       .release        = ds1511_rtc_release,
        .ioctl          = ds1511_rtc_ioctl,
 };
 
index a19f1141554083058d5be71ac4064e81c97ac281..4ef59285b489ec28d05b9c038ae35d28e49a0b40 100644 (file)
@@ -207,17 +207,6 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void ds1553_rtc_release(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-       if (pdata->irq >= 0) {
-               pdata->irqen = 0;
-               ds1553_rtc_update_alarm(pdata);
-       }
-}
-
 static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
                            unsigned long arg)
 {
@@ -254,7 +243,6 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
        .set_time       = ds1553_rtc_set_time,
        .read_alarm     = ds1553_rtc_read_alarm,
        .set_alarm      = ds1553_rtc_set_alarm,
-       .release        = ds1553_rtc_release,
        .ioctl          = ds1553_rtc_ioctl,
 };
 
index 6fa4556f5f5c06b4d469e4a8c553d0d47357ebe0..341d7a5b45a28c3ecab9de39f9c0e515e5ac4331 100644 (file)
@@ -9,17 +9,10 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/rtc.h>
 
-#define DRV_VERSION "0.3"
-
-/* Addresses to scan: none. This chip cannot be detected. */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.4"
 
 /* Registers */
 
@@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD;
 
 #define DS1672_REG_CONTROL_EOSC        0x80
 
-/* Prototypes */
-static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
+static struct i2c_driver ds1672_driver;
 
 /*
  * In the routines that deal directly with the ds1672 hardware, we use
@@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        unsigned char buf[4];
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 1, &addr },          /* setup read ptr */
-               { client->addr, I2C_M_RD, 4, buf },     /* read date */
+               {client->addr, 0, 1, &addr},    /* setup read ptr */
+               {client->addr, I2C_M_RD, 4, buf},       /* read date */
        };
 
        /* read date registers */
@@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
        buf[2] = (secs & 0x0000FF00) >> 8;
        buf[3] = (secs & 0x00FF0000) >> 16;
        buf[4] = (secs & 0xFF000000) >> 24;
-       buf[5] = 0;     /* set control reg to enable counting */
+       buf[5] = 0;             /* set control reg to enable counting */
 
        xfer = i2c_master_send(client, buf, 6);
        if (xfer != 6) {
@@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
        unsigned char addr = DS1672_REG_CONTROL;
 
        struct i2c_msg msgs[] = {
-               { client->addr, 0, 1, &addr },          /* setup read ptr */
-               { client->addr, I2C_M_RD, 1, status },  /* read control */
+               {client->addr, 0, 1, &addr},    /* setup read ptr */
+               {client->addr, I2C_M_RD, 1, status},    /* read control */
        };
 
        /* read control register */
@@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status)
 }
 
 /* following are the sysfs callback functions */
-static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_control(struct device *dev, struct device_attribute *attr,
+                           char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
        u8 control;
@@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c
                return err;
 
        return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
-                                       ? "disabled" : "enabled");
+                      ? "disabled" : "enabled");
 }
+
 static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
 
 static const struct rtc_class_ops ds1672_rtc_ops = {
-       .read_time      = ds1672_rtc_read_time,
-       .set_time       = ds1672_rtc_set_time,
-       .set_mmss       = ds1672_rtc_set_mmss,
+       .read_time = ds1672_rtc_read_time,
+       .set_time = ds1672_rtc_set_time,
+       .set_mmss = ds1672_rtc_set_mmss,
 };
 
-static int ds1672_attach(struct i2c_adapter *adapter)
+static int ds1672_remove(struct i2c_client *client)
 {
-       return i2c_probe(adapter, &addr_data, ds1672_probe);
-}
-
-static int ds1672_detach(struct i2c_client *client)
-{
-       int err;
        struct rtc_device *rtc = i2c_get_clientdata(client);
 
-       if (rtc)
+       if (rtc)
                rtc_device_unregister(rtc);
 
-       if ((err = i2c_detach_client(client)))
-               return err;
-
-       kfree(client);
-
        return 0;
 }
 
-static struct i2c_driver ds1672_driver = {
-       .driver         = {
-               .name   = "ds1672",
-       },
-       .id             = I2C_DRIVERID_DS1672,
-       .attach_adapter = &ds1672_attach,
-       .detach_client  = &ds1672_detach,
-};
-
-static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
+static int ds1672_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        int err = 0;
        u8 control;
-       struct i2c_client *client;
        struct rtc_device *rtc;
 
-       dev_dbg(&adapter->dev, "%s\n", __func__);
+       dev_dbg(&client->dev, "%s\n", __func__);
 
-       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
-               err = -ENODEV;
-               goto exit;
-       }
-
-       if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
-               err = -ENOMEM;
-               goto exit;
-       }
-
-       /* I2C client */
-       client->addr = address;
-       client->driver = &ds1672_driver;
-       client->adapter = adapter;
-
-       strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE);
-
-       /* Inform the i2c layer */
-       if ((err = i2c_attach_client(client)))
-               goto exit_kfree;
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
 
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
        rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev,
-                               &ds1672_rtc_ops, THIS_MODULE);
+                                 &ds1672_rtc_ops, THIS_MODULE);
 
-       if (IS_ERR(rtc)) {
-               err = PTR_ERR(rtc);
-               goto exit_detach;
-       }
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
 
        i2c_set_clientdata(client, rtc);
 
@@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
 
        if (control & DS1672_REG_CONTROL_EOSC)
                dev_warn(&client->dev, "Oscillator not enabled. "
-                                       "Set time to enable.\n");
+                        "Set time to enable.\n");
 
        /* Register sysfs hooks */
        err = device_create_file(&client->dev, &dev_attr_control);
@@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
-exit_devreg:
+ exit_devreg:
        rtc_device_unregister(rtc);
-
-exit_detach:
-       i2c_detach_client(client);
-
-exit_kfree:
-       kfree(client);
-
-exit:
        return err;
 }
 
+static struct i2c_driver ds1672_driver = {
+       .driver = {
+                  .name = "rtc-ds1672",
+                  },
+       .probe = &ds1672_probe,
+       .remove = &ds1672_remove,
+};
+
 static int __init ds1672_init(void)
 {
        return i2c_add_driver(&ds1672_driver);
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
new file mode 100644 (file)
index 0000000..37d131d
--- /dev/null
@@ -0,0 +1,290 @@
+/* drivers/rtc/rtc-ds3234.c
+ *
+ * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
+ * and SRAM.
+ *
+ * Copyright (C) 2008 MIMOMax Wireless Ltd.
+ *
+ * This program is free software; you can 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:
+ *
+ * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com>
+ *             - Created based on the max6902 code. Only implements the
+ *               date/time keeping functions; no SRAM yet.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+#define DS3234_REG_SECONDS     0x00
+#define DS3234_REG_MINUTES     0x01
+#define DS3234_REG_HOURS       0x02
+#define DS3234_REG_DAY         0x03
+#define DS3234_REG_DATE                0x04
+#define DS3234_REG_MONTH       0x05
+#define DS3234_REG_YEAR                0x06
+#define DS3234_REG_CENTURY     (1 << 7) /* Bit 7 of the Month register */
+
+#define DS3234_REG_CONTROL     0x0E
+#define DS3234_REG_CONT_STAT   0x0F
+
+#undef DS3234_DEBUG
+
+struct ds3234 {
+       struct rtc_device *rtc;
+       u8 buf[8]; /* Burst read: addr + 7 regs */
+       u8 tx_buf[2];
+       u8 rx_buf[2];
+};
+
+static void ds3234_set_reg(struct device *dev, unsigned char address,
+                               unsigned char data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       unsigned char buf[2];
+
+       /* MSB must be '1' to indicate write */
+       buf[0] = address | 0x80;
+       buf[1] = data;
+
+       spi_write(spi, buf, 2);
+}
+
+static int ds3234_get_reg(struct device *dev, unsigned char address,
+                               unsigned char *data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct ds3234 *chip = dev_get_drvdata(dev);
+       struct spi_message message;
+       struct spi_transfer xfer;
+       int status;
+
+       if (!data)
+               return -EINVAL;
+
+       /* Build our spi message */
+       spi_message_init(&message);
+       memset(&xfer, 0, sizeof(xfer));
+
+       /* Address + dummy tx byte */
+       xfer.len = 2;
+       xfer.tx_buf = chip->tx_buf;
+       xfer.rx_buf = chip->rx_buf;
+
+       chip->tx_buf[0] = address;
+       chip->tx_buf[1] = 0xff;
+
+       spi_message_add_tail(&xfer, &message);
+
+       /* do the i/o */
+       status = spi_sync(spi, &message);
+       if (status == 0)
+               status = message.status;
+       else
+               return status;
+
+       *data = chip->rx_buf[1];
+
+       return status;
+}
+
+static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct ds3234 *chip = dev_get_drvdata(dev);
+       struct spi_message message;
+       struct spi_transfer xfer;
+       int status;
+
+       /* build the message */
+       spi_message_init(&message);
+       memset(&xfer, 0, sizeof(xfer));
+       xfer.len = 1 + 7;       /* Addr + 7 registers */
+       xfer.tx_buf = chip->buf;
+       xfer.rx_buf = chip->buf;
+       chip->buf[0] = 0x00;    /* Start address */
+       spi_message_add_tail(&xfer, &message);
+
+       /* do the i/o */
+       status = spi_sync(spi, &message);
+       if (status == 0)
+               status = message.status;
+       else
+               return status;
+
+       /* Seconds, Minutes, Hours, Day, Date, Month, Year */
+       dt->tm_sec      = bcd2bin(chip->buf[1]);
+       dt->tm_min      = bcd2bin(chip->buf[2]);
+       dt->tm_hour     = bcd2bin(chip->buf[3] & 0x3f);
+       dt->tm_wday     = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */
+       dt->tm_mday     = bcd2bin(chip->buf[5]);
+       dt->tm_mon      = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */
+       dt->tm_year     = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */
+
+#ifdef DS3234_DEBUG
+       dev_dbg(dev, "\n%s : Read RTC values\n", __func__);
+       dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
+       dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
+       dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
+       dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
+       dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
+       dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
+       dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
+#endif
+
+       return 0;
+}
+
+static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+#ifdef DS3234_DEBUG
+       dev_dbg(dev, "\n%s : Setting RTC values\n", __func__);
+       dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
+       dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
+       dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
+       dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
+       dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
+       dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
+       dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
+#endif
+
+       ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
+       ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
+       ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
+
+       /* 0 = Sun */
+       ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1));
+       ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday));
+
+       /* 0 = Jan */
+       ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1));
+
+       /* Assume 20YY although we just want to make sure not to go negative. */
+       if (dt->tm_year > 100)
+               dt->tm_year -= 100;
+
+       ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year));
+
+       return 0;
+}
+
+static int ds3234_read_time(struct device *dev, struct rtc_time *tm)
+{
+       return ds3234_get_datetime(dev, tm);
+}
+
+static int ds3234_set_time(struct device *dev, struct rtc_time *tm)
+{
+       return ds3234_set_datetime(dev, tm);
+}
+
+static const struct rtc_class_ops ds3234_rtc_ops = {
+       .read_time      = ds3234_read_time,
+       .set_time       = ds3234_set_time,
+};
+
+static int ds3234_probe(struct spi_device *spi)
+{
+       struct rtc_device *rtc;
+       unsigned char tmp;
+       struct ds3234 *chip;
+       int res;
+
+       rtc = rtc_device_register("ds3234",
+                               &spi->dev, &ds3234_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       spi->mode = SPI_MODE_3;
+       spi->bits_per_word = 8;
+       spi_setup(spi);
+
+       chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL);
+       if (!chip) {
+               rtc_device_unregister(rtc);
+               return -ENOMEM;
+       }
+       chip->rtc = rtc;
+       dev_set_drvdata(&spi->dev, chip);
+
+       res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
+       if (res) {
+               rtc_device_unregister(rtc);
+               return res;
+       }
+
+       /* Control settings
+        *
+        * CONTROL_REG
+        * BIT 7        6       5       4       3       2       1       0
+        *     EOSC     BBSQW   CONV    RS2     RS1     INTCN   A2IE    A1IE
+        *
+        *     0        0       0       1       1       1       0       0
+        *
+        * CONTROL_STAT_REG
+        * BIT 7        6       5       4       3       2       1       0
+        *     OSF      BB32kHz CRATE1  CRATE0  EN32kHz BSY     A2F     A1F
+        *
+        *     1        0       0       0       1       0       0       0
+        */
+       ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
+       ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c);
+
+       ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
+       ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88);
+
+       /* Print our settings */
+       ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
+       dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
+
+       ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
+       dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
+
+       return 0;
+}
+
+static int __exit ds3234_remove(struct spi_device *spi)
+{
+       struct ds3234 *chip = platform_get_drvdata(spi);
+       struct rtc_device *rtc = chip->rtc;
+
+       if (rtc)
+               rtc_device_unregister(rtc);
+
+       kfree(chip);
+
+       return 0;
+}
+
+static struct spi_driver ds3234_driver = {
+       .driver = {
+               .name    = "ds3234",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe   = ds3234_probe,
+       .remove = __devexit_p(ds3234_remove),
+};
+
+static __init int ds3234_init(void)
+{
+       printk(KERN_INFO "DS3234 SPI RTC Driver\n");
+       return spi_register_driver(&ds3234_driver);
+}
+module_init(ds3234_init);
+
+static __exit void ds3234_exit(void)
+{
+       spi_unregister_driver(&ds3234_driver);
+}
+module_exit(ds3234_exit);
+
+MODULE_DESCRIPTION("DS3234 SPI RTC driver");
+MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
+MODULE_LICENSE("GPL");
index 24bc1689fc74c095d88641cb7c78755e5ee0b9f8..470fb2d295452a7be54f92747076107c0c025436 100644 (file)
 #define M41T80_ALHOUR_HT       (1 << 6)        /* HT: Halt Update Bit */
 #define M41T80_FLAGS_AF                (1 << 6)        /* AF: Alarm Flag Bit */
 #define M41T80_FLAGS_BATT_LOW  (1 << 4)        /* BL: Battery Low Bit */
+#define M41T80_WATCHDOG_RB2    (1 << 7)        /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB1    (1 << 1)        /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB0    (1 << 0)        /* RB: Watchdog resolution */
 
-#define M41T80_FEATURE_HT      (1 << 0)
-#define M41T80_FEATURE_BL      (1 << 1)
+#define M41T80_FEATURE_HT      (1 << 0)        /* Halt feature */
+#define M41T80_FEATURE_BL      (1 << 1)        /* Battery low indicator */
+#define M41T80_FEATURE_SQ      (1 << 2)        /* Squarewave feature */
+#define M41T80_FEATURE_WD      (1 << 3)        /* Extra watchdog resolution */
 
 #define DRV_VERSION "0.05"
 
 static const struct i2c_device_id m41t80_id[] = {
-       { "m41t80", 0 },
-       { "m41t81", M41T80_FEATURE_HT },
-       { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
-       { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
-       { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
-       { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
-       { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
-       { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
+       { "m41t80", M41T80_FEATURE_SQ },
+       { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ},
+       { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+       { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+       { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+       { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+       { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
+       { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, m41t80_id);
@@ -386,8 +392,12 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
+       struct m41t80_data *clientdata = i2c_get_clientdata(client);
        int val;
 
+       if (!(clientdata->features & M41T80_FEATURE_SQ))
+               return -EINVAL;
+
        val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW);
        if (val < 0)
                return -EIO;
@@ -408,9 +418,13 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
                                const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
+       struct m41t80_data *clientdata = i2c_get_clientdata(client);
        int almon, sqw;
        int val = simple_strtoul(buf, NULL, 0);
 
+       if (!(clientdata->features & M41T80_FEATURE_SQ))
+               return -EINVAL;
+
        if (val) {
                if (!is_power_of_2(val))
                        return -EINVAL;
@@ -499,6 +513,8 @@ static void wdt_ping(void)
                        .buf    = i2c_data,
                },
        };
+       struct m41t80_data *clientdata = i2c_get_clientdata(save_client);
+
        i2c_data[0] = 0x09;             /* watchdog register */
 
        if (wdt_margin > 31)
@@ -509,6 +525,13 @@ static void wdt_ping(void)
                 */
                i2c_data[1] = wdt_margin<<2 | 0x82;
 
+       /*
+        * M41T65 has three bits for watchdog resolution.  Don't set bit 7, as
+        * that would be an invalid resolution.
+        */
+       if (clientdata->features & M41T80_FEATURE_WD)
+               i2c_data[1] &= ~M41T80_WATCHDOG_RB2;
+
        i2c_transfer(save_client->adapter, msgs1, 1);
 }
 
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
new file mode 100644 (file)
index 0000000..0b21975
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ *
+ * Copyright (C) 2008 Thomas Bogendoerfer
+ *
+ * Based on code written by Paul Gortmaker.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/bcd.h>
+#include <linux/io.h>
+
+#define DRV_VERSION            "1.0"
+
+struct m48t35_rtc {
+       u8      pad[0x7ff8];    /* starts at 0x7ff8 */
+       u8      control;
+       u8      sec;
+       u8      min;
+       u8      hour;
+       u8      day;
+       u8      date;
+       u8      month;
+       u8      year;
+};
+
+#define M48T35_RTC_SET         0x80
+#define M48T35_RTC_READ                0x40
+
+struct m48t35_priv {
+       struct rtc_device *rtc;
+       struct m48t35_rtc __iomem *reg;
+       size_t size;
+       unsigned long baseaddr;
+       spinlock_t lock;
+};
+
+static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct m48t35_priv *priv = dev_get_drvdata(dev);
+       u8 control;
+
+       /*
+        * Only the values that we read from the RTC are set. We leave
+        * tm_wday, tm_yday and tm_isdst untouched. Even though the
+        * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+        * by the RTC when initially set to a non-zero value.
+        */
+       spin_lock_irq(&priv->lock);
+       control = readb(&priv->reg->control);
+       writeb(control | M48T35_RTC_READ, &priv->reg->control);
+       tm->tm_sec = readb(&priv->reg->sec);
+       tm->tm_min = readb(&priv->reg->min);
+       tm->tm_hour = readb(&priv->reg->hour);
+       tm->tm_mday = readb(&priv->reg->date);
+       tm->tm_mon = readb(&priv->reg->month);
+       tm->tm_year = readb(&priv->reg->year);
+       writeb(control, &priv->reg->control);
+       spin_unlock_irq(&priv->lock);
+
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon);
+       tm->tm_year = bcd2bin(tm->tm_year);
+
+       /*
+        * Account for differences between how the RTC uses the values
+        * and how they are defined in a struct rtc_time;
+        */
+       tm->tm_year += 70;
+       if (tm->tm_year <= 69)
+               tm->tm_year += 100;
+
+       tm->tm_mon--;
+       return rtc_valid_tm(tm);
+}
+
+static int m48t35_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct m48t35_priv *priv = dev_get_drvdata(dev);
+       unsigned char mon, day, hrs, min, sec;
+       unsigned int yrs;
+       u8 control;
+
+       yrs = tm->tm_year + 1900;
+       mon = tm->tm_mon + 1;   /* tm_mon starts at zero */
+       day = tm->tm_mday;
+       hrs = tm->tm_hour;
+       min = tm->tm_min;
+       sec = tm->tm_sec;
+
+       if (yrs < 1970)
+               return -EINVAL;
+
+       yrs -= 1970;
+       if (yrs > 255)    /* They are unsigned */
+               return -EINVAL;
+
+       if (yrs > 169)
+               return -EINVAL;
+
+       if (yrs >= 100)
+               yrs -= 100;
+
+       sec = bin2bcd(sec);
+       min = bin2bcd(min);
+       hrs = bin2bcd(hrs);
+       day = bin2bcd(day);
+       mon = bin2bcd(mon);
+       yrs = bin2bcd(yrs);
+
+       spin_lock_irq(&priv->lock);
+       control = readb(&priv->reg->control);
+       writeb(control | M48T35_RTC_SET, &priv->reg->control);
+       writeb(yrs, &priv->reg->year);
+       writeb(mon, &priv->reg->month);
+       writeb(day, &priv->reg->date);
+       writeb(hrs, &priv->reg->hour);
+       writeb(min, &priv->reg->min);
+       writeb(sec, &priv->reg->sec);
+       writeb(control, &priv->reg->control);
+       spin_unlock_irq(&priv->lock);
+       return 0;
+}
+
+static const struct rtc_class_ops m48t35_ops = {
+       .read_time      = m48t35_read_time,
+       .set_time       = m48t35_set_time,
+};
+
+static int __devinit m48t35_probe(struct platform_device *pdev)
+{
+       struct rtc_device *rtc;
+       struct resource *res;
+       struct m48t35_priv *priv;
+       int ret = 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       priv = kzalloc(sizeof(struct m48t35_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->size = res->end - res->start + 1;
+       /*
+        * kludge: remove the #ifndef after ioc3 resource
+        * conflicts are resolved
+        */
+#ifndef CONFIG_SGI_IP27
+       if (!request_mem_region(res->start, priv->size, pdev->name)) {
+               ret = -EBUSY;
+               goto out;
+       }
+#endif
+       priv->baseaddr = res->start;
+       priv->reg = ioremap(priv->baseaddr, priv->size);
+       if (!priv->reg) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       spin_lock_init(&priv->lock);
+       rtc = rtc_device_register("m48t35", &pdev->dev,
+                                 &m48t35_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc);
+               goto out;
+       }
+       priv->rtc = rtc;
+       platform_set_drvdata(pdev, priv);
+       return 0;
+
+out:
+       if (priv->rtc)
+               rtc_device_unregister(priv->rtc);
+       if (priv->reg)
+               iounmap(priv->reg);
+       if (priv->baseaddr)
+               release_mem_region(priv->baseaddr, priv->size);
+       kfree(priv);
+       return ret;
+}
+
+static int __devexit m48t35_remove(struct platform_device *pdev)
+{
+       struct m48t35_priv *priv = platform_get_drvdata(pdev);
+
+       rtc_device_unregister(priv->rtc);
+       iounmap(priv->reg);
+#ifndef CONFIG_SGI_IP27
+       release_mem_region(priv->baseaddr, priv->size);
+#endif
+       kfree(priv);
+       return 0;
+}
+
+static struct platform_driver m48t35_platform_driver = {
+       .driver         = {
+               .name   = "rtc-m48t35",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = m48t35_probe,
+       .remove         = __devexit_p(m48t35_remove),
+};
+
+static int __init m48t35_init(void)
+{
+       return platform_driver_register(&m48t35_platform_driver);
+}
+
+static void __exit m48t35_exit(void)
+{
+       platform_driver_unregister(&m48t35_platform_driver);
+}
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
+MODULE_DESCRIPTION("M48T35 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:rtc-m48t35");
+
+module_init(m48t35_init);
+module_exit(m48t35_exit);
index ded3c0abad835736152c093d9ae5dc0402afec58..12c9cd25cad8b2b3df1843ba74d247f592334e41 100644 (file)
 #include <linux/rtc.h>
 #include <linux/delay.h>
 
-#define DRV_NAME "max6900"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 /*
  * register indices
  */
-#define MAX6900_REG_SC                 0       /* seconds      00-59 */
-#define MAX6900_REG_MN                 1       /* minutes      00-59 */
-#define MAX6900_REG_HR                 2       /* hours        00-23 */
-#define MAX6900_REG_DT                 3       /* day of month 00-31 */
-#define MAX6900_REG_MO                 4       /* month        01-12 */
-#define MAX6900_REG_DW                 5       /* day of week   1-7  */
-#define MAX6900_REG_YR                 6       /* year         00-99 */
+#define MAX6900_REG_SC                 0       /* seconds      00-59 */
+#define MAX6900_REG_MN                 1       /* minutes      00-59 */
+#define MAX6900_REG_HR                 2       /* hours        00-23 */
+#define MAX6900_REG_DT                 3       /* day of month 00-31 */
+#define MAX6900_REG_MO                 4       /* month        01-12 */
+#define MAX6900_REG_DW                 5       /* day of week   1-7  */
+#define MAX6900_REG_YR                 6       /* year         00-99 */
 #define MAX6900_REG_CT                 7       /* control */
                                                /* register 8 is undocumented */
 #define MAX6900_REG_CENTURY            9       /* century */
@@ -39,7 +38,6 @@
 
 #define MAX6900_REG_CT_WP              (1 << 7)        /* Write Protect */
 
-
 /*
  * register read/write commands
  */
 
 #define MAX6900_IDLE_TIME_AFTER_WRITE  3       /* specification says 2.5 mS */
 
-#define MAX6900_I2C_ADDR               0xa0
-
-static const unsigned short normal_i2c[] = {
-       MAX6900_I2C_ADDR >> 1,
-       I2C_CLIENT_END
-};
-
-I2C_CLIENT_INSMOD;                     /* defines addr_data */
-
-static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind);
+static struct i2c_driver max6900_driver;
 
 static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
 {
@@ -69,36 +58,35 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf)
        u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ };
        struct i2c_msg msgs[4] = {
                {
-                       .addr   = client->addr,
-                       .flags  = 0, /* write */
-                       .len    = sizeof(reg_burst_read),
-                       .buf    = reg_burst_read
-               },
+                .addr = client->addr,
+                .flags = 0,    /* write */
+                .len = sizeof(reg_burst_read),
+                .buf = reg_burst_read}
+               ,
                {
-                       .addr   = client->addr,
-                       .flags  = I2C_M_RD,
-                       .len    = MAX6900_BURST_LEN,
-                       .buf    = buf
-               },
+                .addr = client->addr,
+                .flags = I2C_M_RD,
+                .len = MAX6900_BURST_LEN,
+                .buf = buf}
+               ,
                {
-                       .addr   = client->addr,
-                       .flags  = 0, /* write */
-                       .len    = sizeof(reg_century_read),
-                       .buf    = reg_century_read
-               },
+                .addr = client->addr,
+                .flags = 0,    /* write */
+                .len = sizeof(reg_century_read),
+                .buf = reg_century_read}
+               ,
                {
-                       .addr   = client->addr,
-                       .flags  = I2C_M_RD,
-                       .len    = sizeof(buf[MAX6900_REG_CENTURY]),
-                       .buf    = &buf[MAX6900_REG_CENTURY]
-               }
+                .addr = client->addr,
+                .flags = I2C_M_RD,
+                .len = sizeof(buf[MAX6900_REG_CENTURY]),
+                .buf = &buf[MAX6900_REG_CENTURY]
+                }
        };
        int rc;
 
        rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
        if (rc != ARRAY_SIZE(msgs)) {
-               dev_err(&client->dev, "%s: register read failed\n",
-                       __func__);
+               dev_err(&client->dev, "%s: register read failed\n", __func__);
                return -EIO;
        }
        return 0;
@@ -109,20 +97,18 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
        u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE };
        struct i2c_msg century_msgs[1] = {
                {
-                       .addr   = client->addr,
-                       .flags  = 0, /* write */
-                       .len    = sizeof(i2c_century_buf),
-                       .buf    = i2c_century_buf
-               }
+                .addr = client->addr,
+                .flags = 0,    /* write */
+                .len = sizeof(i2c_century_buf),
+                .buf = i2c_century_buf}
        };
        u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE };
        struct i2c_msg burst_msgs[1] = {
                {
-                       .addr   = client->addr,
-                       .flags  = 0, /* write */
-                       .len    = sizeof(i2c_burst_buf),
-                       .buf    = i2c_burst_buf
-               }
+                .addr = client->addr,
+                .flags = 0,    /* write */
+                .len = sizeof(i2c_burst_buf),
+                .buf = i2c_burst_buf}
        };
        int rc;
 
@@ -133,10 +119,12 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
         * bit as part of the burst write.
         */
        i2c_century_buf[1] = buf[MAX6900_REG_CENTURY];
+
        rc = i2c_transfer(client->adapter, century_msgs,
                          ARRAY_SIZE(century_msgs));
        if (rc != ARRAY_SIZE(century_msgs))
                goto write_failed;
+
        msleep(MAX6900_IDLE_TIME_AFTER_WRITE);
 
        memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN);
@@ -148,45 +136,11 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf)
 
        return 0;
 
-write_failed:
-       dev_err(&client->dev, "%s: register write failed\n",
-               __func__);
+ write_failed:
+       dev_err(&client->dev, "%s: register write failed\n", __func__);
        return -EIO;
 }
 
-static int max6900_i2c_validate_client(struct i2c_client *client)
-{
-       u8 regs[MAX6900_REG_LEN];
-       u8 zero_mask[] = {
-               0x80,   /* seconds */
-               0x80,   /* minutes */
-               0x40,   /* hours */
-               0xc0,   /* day of month */
-               0xe0,   /* month */
-               0xf8,   /* day of week */
-               0x00,   /* year */
-               0x7f,   /* control */
-       };
-       int i;
-       int rc;
-       int reserved;
-
-       reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ);
-       if (reserved != 0x07)
-               return -ENODEV;
-
-       rc = max6900_i2c_read_regs(client, regs);
-       if (rc < 0)
-               return rc;
-
-       for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) {
-               if (regs[i] & zero_mask[i])
-                       return -ENODEV;
-       }
-
-       return 0;
-}
-
 static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 {
        int rc;
@@ -202,7 +156,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
        tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]);
        tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1;
        tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) +
-                     BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
+           BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
        tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]);
 
        return 0;
@@ -211,7 +165,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 static int max6900_i2c_clear_write_protect(struct i2c_client *client)
 {
        int rc;
-       rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0);
+       rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0);
        if (rc < 0) {
                dev_err(&client->dev, "%s: control register write failed\n",
                        __func__);
@@ -220,8 +174,8 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client)
        return 0;
 }
 
-static int max6900_i2c_set_time(struct i2c_client *client,
-                               struct rtc_time const *tm)
+static int
+max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 {
        u8 regs[MAX6900_REG_LEN];
        int rc;
@@ -258,89 +212,49 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm)
        return max6900_i2c_set_time(to_i2c_client(dev), tm);
 }
 
-static int max6900_attach_adapter(struct i2c_adapter *adapter)
-{
-       return i2c_probe(adapter, &addr_data, max6900_probe);
-}
-
-static int max6900_detach_client(struct i2c_client *client)
+static int max6900_remove(struct i2c_client *client)
 {
-       struct rtc_device *const rtc = i2c_get_clientdata(client);
+       struct rtc_device *rtc = i2c_get_clientdata(client);
 
        if (rtc)
                rtc_device_unregister(rtc);
 
-       return i2c_detach_client(client);
+       return 0;
 }
 
-static struct i2c_driver max6900_driver = {
-       .driver         = {
-               .name   = DRV_NAME,
-       },
-       .id             = I2C_DRIVERID_MAX6900,
-       .attach_adapter = max6900_attach_adapter,
-       .detach_client  = max6900_detach_client,
-};
-
 static const struct rtc_class_ops max6900_rtc_ops = {
-       .read_time      = max6900_rtc_read_time,
-       .set_time       = max6900_rtc_set_time,
+       .read_time = max6900_rtc_read_time,
+       .set_time = max6900_rtc_set_time,
 };
 
-static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind)
+static int
+max6900_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-       int rc = 0;
-       struct i2c_client *client = NULL;
-       struct rtc_device *rtc = NULL;
-
-       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
-               rc = -ENODEV;
-               goto failout;
-       }
-
-       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (client == NULL) {
-               rc = -ENOMEM;
-               goto failout;
-       }
-
-       client->addr = addr;
-       client->adapter = adapter;
-       client->driver = &max6900_driver;
-       strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE);
-
-       if (kind < 0) {
-               rc = max6900_i2c_validate_client(client);
-               if (rc < 0)
-                       goto failout;
-       }
+       struct rtc_device *rtc;
 
-       rc = i2c_attach_client(client);
-       if (rc < 0)
-               goto failout;
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
 
-       dev_info(&client->dev,
-                "chip found, driver version " DRV_VERSION "\n");
+       dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
        rtc = rtc_device_register(max6900_driver.driver.name,
-                                 &client->dev,
-                                 &max6900_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               rc = PTR_ERR(rtc);
-               goto failout_detach;
-       }
+                                 &client->dev, &max6900_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
 
        i2c_set_clientdata(client, rtc);
 
        return 0;
-
-failout_detach:
-       i2c_detach_client(client);
-failout:
-       kfree(client);
-       return rc;
 }
 
+static struct i2c_driver max6900_driver = {
+       .driver = {
+                  .name = "rtc-max6900",
+                  },
+       .probe = max6900_probe,
+       .remove = max6900_remove,
+};
+
 static int __init max6900_init(void)
 {
        return i2c_add_driver(&max6900_driver);
@@ -352,6 +266,7 @@ static void __exit max6900_exit(void)
 }
 
 MODULE_DESCRIPTION("Maxim MAX6900 RTC driver");
+MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
index 748a502a63558fd499e26d56338132aabcae85f2..a829f20ad6d6eb140d56d246ab620af0640507d7 100644 (file)
@@ -179,58 +179,6 @@ struct pcf8563_limit
        unsigned char max;
 };
 
-static int pcf8563_validate_client(struct i2c_client *client)
-{
-       int i;
-
-       static const struct pcf8563_limit pattern[] = {
-               /* register, mask, min, max */
-               { PCF8563_REG_SC,       0x7F,   0,      59      },
-               { PCF8563_REG_MN,       0x7F,   0,      59      },
-               { PCF8563_REG_HR,       0x3F,   0,      23      },
-               { PCF8563_REG_DM,       0x3F,   0,      31      },
-               { PCF8563_REG_MO,       0x1F,   0,      12      },
-       };
-
-       /* check limits (only registers with bcd values) */
-       for (i = 0; i < ARRAY_SIZE(pattern); i++) {
-               int xfer;
-               unsigned char value;
-               unsigned char buf = pattern[i].reg;
-
-               struct i2c_msg msgs[] = {
-                       { client->addr, 0, 1, &buf },
-                       { client->addr, I2C_M_RD, 1, &buf },
-               };
-
-               xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-
-               if (xfer != ARRAY_SIZE(msgs)) {
-                       dev_err(&client->dev,
-                               "%s: could not read register 0x%02X\n",
-                               __func__, pattern[i].reg);
-
-                       return -EIO;
-               }
-
-               value = BCD2BIN(buf & pattern[i].mask);
-
-               if (value > pattern[i].max ||
-                       value < pattern[i].min) {
-                       dev_dbg(&client->dev,
-                               "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, "
-                               "max=%d, value=%d, raw=0x%02X\n",
-                               __func__, i, pattern[i].reg, pattern[i].mask,
-                               pattern[i].min, pattern[i].max,
-                               value, buf);
-
-                       return -ENODEV;
-               }
-       }
-
-       return 0;
-}
-
 static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        return pcf8563_get_datetime(to_i2c_client(dev), tm);
@@ -262,12 +210,6 @@ static int pcf8563_probe(struct i2c_client *client,
        if (!pcf8563)
                return -ENOMEM;
 
-       /* Verify the chip is really an PCF8563 */
-       if (pcf8563_validate_client(client) < 0) {
-               err = -ENODEV;
-               goto exit_kfree;
-       }
-
        dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
        pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
index 8448eeb9d675f8ca37c79e506ba63143ea7bf1a2..826153552157d3d4d328fe372fa2dd2fbf025ac6 100644 (file)
@@ -34,15 +34,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int pl030_open(struct device *dev)
-{
-       return 0;
-}
-
-static void pl030_release(struct device *dev)
-{
-}
-
 static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
        return -ENOIOCTLCMD;
@@ -104,8 +95,6 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm)
 }
 
 static const struct rtc_class_ops pl030_ops = {
-       .open           = pl030_open,
-       .release        = pl030_release,
        .ioctl          = pl030_ioctl,
        .read_time      = pl030_read_time,
        .set_time       = pl030_set_time,
index 08b4610ec5a6ca218567f25c552516effa33b6fa..333eec689d2feae84723d8622b972d936552c55f 100644 (file)
@@ -45,18 +45,6 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int pl031_open(struct device *dev)
-{
-       /*
-        * We request IRQ in pl031_probe, so nothing to do here...
-        */
-       return 0;
-}
-
-static void pl031_release(struct device *dev)
-{
-}
-
 static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
        struct pl031_local *ldata = dev_get_drvdata(dev);
@@ -118,8 +106,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 }
 
 static const struct rtc_class_ops pl031_ops = {
-       .open = pl031_open,
-       .release = pl031_release,
        .ioctl = pl031_ioctl,
        .read_time = pl031_read_time,
        .set_time = pl031_set_time,
index 56caf6b2c3e5d2fceface127d7dc197a839e0dac..8b561958fb1e62056c62ef2aabe37742ab2cd395 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs
+ * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs
  *
  * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net>
  * Copyright (C) 2006 Tower Technologies
+ * Copyright (C) 2008 Paul Mundt
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -13,7 +14,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 
-#define DRV_VERSION "0.5"
+#define DRV_VERSION "0.6"
 
 
 /*
@@ -51,7 +52,8 @@
 #      define RS5C_CTRL1_CT4           (4 << 0)        /* 1 Hz level irq */
 #define RS5C_REG_CTRL2         15
 #      define RS5C372_CTRL2_24         (1 << 5)
-#      define RS5C_CTRL2_XSTP          (1 << 4)
+#      define R2025_CTRL2_XST          (1 << 5)
+#      define RS5C_CTRL2_XSTP          (1 << 4)        /* only if !R2025S/D */
 #      define RS5C_CTRL2_CTFG          (1 << 2)
 #      define RS5C_CTRL2_AAFG          (1 << 1)        /* or WAFG */
 #      define RS5C_CTRL2_BAFG          (1 << 0)        /* or DAFG */
@@ -63,6 +65,7 @@
 
 enum rtc_type {
        rtc_undef = 0,
+       rtc_r2025sd,
        rtc_rs5c372a,
        rtc_rs5c372b,
        rtc_rv5c386,
@@ -70,6 +73,7 @@ enum rtc_type {
 };
 
 static const struct i2c_device_id rs5c372_id[] = {
+       { "r2025sd", rtc_r2025sd },
        { "rs5c372a", rtc_rs5c372a },
        { "rs5c372b", rtc_rs5c372b },
        { "rv5c386", rtc_rv5c386 },
@@ -89,6 +93,7 @@ struct rs5c372 {
        enum rtc_type           type;
        unsigned                time24:1;
        unsigned                has_irq:1;
+       unsigned                smbus:1;
        char                    buf[17];
        char                    *regs;
 };
@@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
         *
         * The first method doesn't work with the iop3xx adapter driver, on at
         * least 80219 chips; this works around that bug.
+        *
+        * The third method on the other hand doesn't work for the SMBus-only
+        * configurations, so we use the the first method there, stripping off
+        * the extra register in the process.
         */
-       if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
-               dev_warn(&client->dev, "can't read registers\n");
-               return -EIO;
+       if (rs5c->smbus) {
+               int addr = RS5C_ADDR(RS5C372_REG_SECS);
+               int size = sizeof(rs5c->buf) - 1;
+
+               if (i2c_smbus_read_i2c_block_data(client, addr, size,
+                                                 rs5c->buf + 1) != size) {
+                       dev_warn(&client->dev, "can't read registers\n");
+                       return -EIO;
+               }
+       } else {
+               if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
+                       dev_warn(&client->dev, "can't read registers\n");
+                       return -EIO;
+               }
        }
 
        dev_dbg(&client->dev,
@@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
        struct rs5c372  *rs5c = i2c_get_clientdata(client);
        unsigned char   buf[8];
+       int             addr;
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                tm->tm_sec, tm->tm_min, tm->tm_hour,
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
-       buf[0] = RS5C_ADDR(RS5C372_REG_SECS);
-       buf[1] = BIN2BCD(tm->tm_sec);
-       buf[2] = BIN2BCD(tm->tm_min);
-       buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour);
-       buf[4] = BIN2BCD(tm->tm_wday);
-       buf[5] = BIN2BCD(tm->tm_mday);
-       buf[6] = BIN2BCD(tm->tm_mon + 1);
-       buf[7] = BIN2BCD(tm->tm_year - 100);
+       addr   = RS5C_ADDR(RS5C372_REG_SECS);
+       buf[0] = BIN2BCD(tm->tm_sec);
+       buf[1] = BIN2BCD(tm->tm_min);
+       buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour);
+       buf[3] = BIN2BCD(tm->tm_wday);
+       buf[4] = BIN2BCD(tm->tm_mday);
+       buf[5] = BIN2BCD(tm->tm_mon + 1);
+       buf[6] = BIN2BCD(tm->tm_year - 100);
 
-       if ((i2c_master_send(client, buf, 8)) != 8) {
+       if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) {
                dev_err(&client->dev, "%s: write error\n", __func__);
                return -EIO;
        }
@@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
        struct i2c_client       *client = to_i2c_client(dev);
        struct rs5c372          *rs5c = i2c_get_clientdata(client);
-       unsigned char           buf[2];
-       int                     status;
+       unsigned char           buf;
+       int                     status, addr;
 
-       buf[1] = rs5c->regs[RS5C_REG_CTRL1];
+       buf = rs5c->regs[RS5C_REG_CTRL1];
        switch (cmd) {
        case RTC_UIE_OFF:
        case RTC_UIE_ON:
                /* some 327a modes use a different IRQ pin for 1Hz irqs */
                if (rs5c->type == rtc_rs5c372a
-                               && (buf[1] & RS5C372A_CTRL1_SL1))
+                               && (buf & RS5C372A_CTRL1_SL1))
                        return -ENOIOCTLCMD;
        case RTC_AIE_OFF:
        case RTC_AIE_ON:
@@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
        if (status < 0)
                return status;
 
-       buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
+       addr = RS5C_ADDR(RS5C_REG_CTRL1);
        switch (cmd) {
        case RTC_AIE_OFF:       /* alarm off */
-               buf[1] &= ~RS5C_CTRL1_AALE;
+               buf &= ~RS5C_CTRL1_AALE;
                break;
        case RTC_AIE_ON:        /* alarm on */
-               buf[1] |= RS5C_CTRL1_AALE;
+               buf |= RS5C_CTRL1_AALE;
                break;
        case RTC_UIE_OFF:       /* update off */
-               buf[1] &= ~RS5C_CTRL1_CT_MASK;
+               buf &= ~RS5C_CTRL1_CT_MASK;
                break;
        case RTC_UIE_ON:        /* update on */
-               buf[1] &= ~RS5C_CTRL1_CT_MASK;
-               buf[1] |= RS5C_CTRL1_CT4;
+               buf &= ~RS5C_CTRL1_CT_MASK;
+               buf |= RS5C_CTRL1_CT4;
                break;
        }
-       if ((i2c_master_send(client, buf, 2)) != 2) {
+
+       if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
                printk(KERN_WARNING "%s: can't update alarm\n",
                        rs5c->rtc->name);
                status = -EIO;
        } else
-               rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+               rs5c->regs[RS5C_REG_CTRL1] = buf;
+
        return status;
 }
 
@@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 {
        struct i2c_client       *client = to_i2c_client(dev);
        struct rs5c372          *rs5c = i2c_get_clientdata(client);
-       int                     status;
-       unsigned char           buf[4];
+       int                     status, addr, i;
+       unsigned char           buf[3];
 
        /* only handle up to 24 hours in the future, like RTC_ALM_SET */
        if (t->time.tm_mday != -1
@@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        if (status < 0)
                return status;
        if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) {
-               buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
-               buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
-               if (i2c_master_send(client, buf, 2) != 2) {
+               addr = RS5C_ADDR(RS5C_REG_CTRL1);
+               buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE;
+               if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) {
                        pr_debug("%s: can't disable alarm\n", rs5c->rtc->name);
                        return -EIO;
                }
-               rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+               rs5c->regs[RS5C_REG_CTRL1] = buf[0];
        }
 
        /* set alarm */
-       buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN);
-       buf[1] = BIN2BCD(t->time.tm_min);
-       buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour);
-       buf[3] = 0x7f;  /* any/all days */
-       if ((i2c_master_send(client, buf, 4)) != 4) {
-               pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
-               return -EIO;
+       buf[0] = BIN2BCD(t->time.tm_min);
+       buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
+       buf[2] = 0x7f;  /* any/all days */
+
+       for (i = 0; i < sizeof(buf); i++) {
+               addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i);
+               if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) {
+                       pr_debug("%s: can't set alarm time\n", rs5c->rtc->name);
+                       return -EIO;
+               }
        }
 
        /* ... and maybe enable its irq */
        if (t->enabled) {
-               buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
-               buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
-               if ((i2c_master_send(client, buf, 2)) != 2)
+               addr = RS5C_ADDR(RS5C_REG_CTRL1);
+               buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE;
+               if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0)
                        printk(KERN_WARNING "%s: can't enable alarm\n",
                                rs5c->rtc->name);
-               rs5c->regs[RS5C_REG_CTRL1] = buf[1];
+               rs5c->regs[RS5C_REG_CTRL1] = buf[0];
        }
 
        return 0;
@@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev)
 
 static struct i2c_driver rs5c372_driver;
 
+static int rs5c_oscillator_setup(struct rs5c372 *rs5c372)
+{
+       unsigned char buf[2];
+       int addr, i, ret = 0;
+
+       if (rs5c372->type == rtc_r2025sd) {
+               if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST))
+                       return ret;
+               rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST;
+       } else {
+               if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP))
+                       return ret;
+               rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
+       }
+
+       addr   = RS5C_ADDR(RS5C_REG_CTRL1);
+       buf[0] = rs5c372->regs[RS5C_REG_CTRL1];
+       buf[1] = rs5c372->regs[RS5C_REG_CTRL2];
+
+       /* use 24hr mode */
+       switch (rs5c372->type) {
+       case rtc_rs5c372a:
+       case rtc_rs5c372b:
+               buf[1] |= RS5C372_CTRL2_24;
+               rs5c372->time24 = 1;
+               break;
+       case rtc_r2025sd:
+       case rtc_rv5c386:
+       case rtc_rv5c387a:
+               buf[0] |= RV5C387_CTRL1_24;
+               rs5c372->time24 = 1;
+               break;
+       default:
+               /* impossible */
+               break;
+       }
+
+       for (i = 0; i < sizeof(buf); i++) {
+               addr = RS5C_ADDR(RS5C_REG_CTRL1 + i);
+               ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]);
+               if (unlikely(ret < 0))
+                       return ret;
+       }
+
+       rs5c372->regs[RS5C_REG_CTRL1] = buf[0];
+       rs5c372->regs[RS5C_REG_CTRL2] = buf[1];
+
+       return 0;
+}
+
 static int rs5c372_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        int err = 0;
+       int smbus_mode = 0;
        struct rs5c372 *rs5c372;
        struct rtc_time tm;
 
        dev_dbg(&client->dev, "%s\n", __func__);
 
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               err = -ENODEV;
-               goto exit;
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+                       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) {
+               /*
+                * If we don't have any master mode adapter, try breaking
+                * it down in to the barest of capabilities.
+                */
+               if (i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_BYTE_DATA |
+                               I2C_FUNC_SMBUS_I2C_BLOCK))
+                       smbus_mode = 1;
+               else {
+                       /* Still no good, give up */
+                       err = -ENODEV;
+                       goto exit;
+               }
        }
 
        if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
@@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client,
 
        /* we read registers 0x0f then 0x00-0x0f; skip the first one */
        rs5c372->regs = &rs5c372->buf[1];
+       rs5c372->smbus = smbus_mode;
 
        err = rs5c_get_regs(rs5c372);
        if (err < 0)
@@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client,
                if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24)
                        rs5c372->time24 = 1;
                break;
+       case rtc_r2025sd:
        case rtc_rv5c386:
        case rtc_rv5c387a:
                if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
@@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client,
 
        /* if the oscillator lost power and no other software (like
         * the bootloader) set it up, do it here.
+        *
+        * The R2025S/D does this a little differently than the other
+        * parts, so we special case that..
         */
-       if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) {
-               unsigned char buf[3];
-
-               rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP;
-
-               buf[0] = RS5C_ADDR(RS5C_REG_CTRL1);
-               buf[1] = rs5c372->regs[RS5C_REG_CTRL1];
-               buf[2] = rs5c372->regs[RS5C_REG_CTRL2];
-
-               /* use 24hr mode */
-               switch (rs5c372->type) {
-               case rtc_rs5c372a:
-               case rtc_rs5c372b:
-                       buf[2] |= RS5C372_CTRL2_24;
-                       rs5c372->time24 = 1;
-                       break;
-               case rtc_rv5c386:
-               case rtc_rv5c387a:
-                       buf[1] |= RV5C387_CTRL1_24;
-                       rs5c372->time24 = 1;
-                       break;
-               default:
-                       /* impossible */
-                       break;
-               }
-
-               if ((i2c_master_send(client, buf, 3)) != 3) {
-                       dev_err(&client->dev, "setup error\n");
-                       goto exit_kfree;
-               }
-               rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
-               rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
+       err = rs5c_oscillator_setup(rs5c372);
+       if (unlikely(err < 0)) {
+               dev_err(&client->dev, "setup error\n");
+               goto exit_kfree;
        }
 
        if (rs5c372_get_datetime(client, &tm) < 0)
@@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client,
 
        dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
                        ({ char *s; switch (rs5c372->type) {
+                       case rtc_r2025sd:       s = "r2025sd"; break;
                        case rtc_rs5c372a:      s = "rs5c372a"; break;
                        case rtc_rs5c372b:      s = "rs5c372b"; break;
                        case rtc_rv5c386:       s = "rv5c386"; break;
@@ -667,7 +734,8 @@ module_exit(rs5c372_exit);
 
 MODULE_AUTHOR(
                "Pavel Mironchik <pmironchik@optifacio.net>, "
-               "Alessandro Zummo <a.zummo@towertech.it>");
+               "Alessandro Zummo <a.zummo@towertech.it>, "
+               "Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
index 1f88e9e914ec97d41c139519ab6e2e34c77ea4e2..fcead4c4cd1f339b59b84de1c2d34ea95f38f9f1 100644 (file)
@@ -257,12 +257,6 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
        spin_unlock_irq(&rtc->lock);
 }
 
-static void sh_rtc_release(struct device *dev)
-{
-       sh_rtc_setpie(dev, 0);
-       sh_rtc_setaie(dev, 0);
-}
-
 static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
 {
        struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -559,7 +553,6 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq)
 }
 
 static struct rtc_class_ops sh_rtc_ops = {
-       .release        = sh_rtc_release,
        .ioctl          = sh_rtc_ioctl,
        .read_time      = sh_rtc_read_time,
        .set_time       = sh_rtc_set_time,
index 31d3c8c28588b9f272104aadd83df86512da2200..9a7e920315fa76c6af27d307c913df0b184dadad 100644 (file)
@@ -215,17 +215,6 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void stk17ta8_rtc_release(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-       if (pdata->irq >= 0) {
-               pdata->irqen = 0;
-               stk17ta8_rtc_update_alarm(pdata);
-       }
-}
-
 static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd,
                            unsigned long arg)
 {
@@ -254,7 +243,6 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = {
        .set_time       = stk17ta8_rtc_set_time,
        .read_alarm     = stk17ta8_rtc_read_alarm,
        .set_alarm      = stk17ta8_rtc_set_alarm,
-       .release        = stk17ta8_rtc_release,
        .ioctl          = stk17ta8_rtc_ioctl,
 };
 
index d18e6d2e0b49dbac1f63d8a62483326ea7a1dea7..40759c33477d1d38bca2400f034affbf24e3efcc 100644 (file)
@@ -418,25 +418,22 @@ fs3270_open(struct inode *inode, struct file *filp)
 {
        struct fs3270 *fp;
        struct idal_buffer *ib;
-       int minor, rc;
+       int minor, rc = 0;
 
        if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
                return -ENODEV;
-       lock_kernel();
        minor = iminor(filp->f_path.dentry->d_inode);
        /* Check for minor 0 multiplexer. */
        if (minor == 0) {
-               struct tty_struct *tty;
-               mutex_lock(&tty_mutex);
-               tty = get_current_tty();
+               struct tty_struct *tty = get_current_tty();
                if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
-                       mutex_unlock(&tty_mutex);
-                       rc = -ENODEV;
-                       goto out;
+                       tty_kref_put(tty);
+                       return -ENODEV;
                }
                minor = tty->index + RAW3270_FIRSTMINOR;
-               mutex_unlock(&tty_mutex);
+               tty_kref_put(tty);
        }
+       lock_kernel();
        /* Check if some other program is already using fullscreen mode. */
        fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
        if (!IS_ERR(fp)) {
@@ -478,7 +475,7 @@ fs3270_open(struct inode *inode, struct file *filp)
        filp->private_data = fp;
 out:
        unlock_kernel();
-       return 0;
+       return rc;
 }
 
 /*
index 1792b2c0130e2c3948ddab8e4798790a7af7b99c..0b15cf107ec97d9162506d1acc23d678416692a3 100644 (file)
@@ -1168,19 +1168,17 @@ static int raw3270_create_attributes(struct raw3270 *rp)
        if (rc)
                goto out;
 
-       rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
-                                            MKDEV(IBM_TTY3270_MAJOR, rp->minor),
-                                            NULL,
-                                            "tty%s", dev_name(&rp->cdev->dev));
+       rp->clttydev = device_create(class3270, &rp->cdev->dev,
+                                    MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL,
+                                    "tty%s", dev_name(&rp->cdev->dev));
        if (IS_ERR(rp->clttydev)) {
                rc = PTR_ERR(rp->clttydev);
                goto out_ttydev;
        }
 
-       rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
-                                            MKDEV(IBM_FS3270_MAJOR, rp->minor),
-                                            NULL,
-                                            "tub%s", dev_name(&rp->cdev->dev));
+       rp->cltubdev = device_create(class3270, &rp->cdev->dev,
+                                    MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL,
+                                    "tub%s", dev_name(&rp->cdev->dev));
        if (!IS_ERR(rp->cltubdev))
                goto out;
 
index 12c2a5aaf31b47e88587957b7f31cb6a24edff7b..ddc914ccea8fccef284bd467cd9a4fe7eb4c625a 100644 (file)
@@ -69,9 +69,9 @@ struct tape_class_device *register_tape_dev(
        if (rc)
                goto fail_with_cdev;
 
-       tcd->class_device = device_create_drvdata(tape_class, device,
-                                                 tcd->char_device->dev,
-                                                 NULL, "%s", tcd->device_name);
+       tcd->class_device = device_create(tape_class, device,
+                                         tcd->char_device->dev, NULL,
+                                         "%s", tcd->device_name);
        rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
        if (rc)
                goto fail_with_cdev;
index 42173cc34610f41417b877387dd052517638b6b8..24762727bc27ff80243951dd47a984128af3ed61 100644 (file)
@@ -747,10 +747,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
                device_unregister(dev);
                return ret;
        }
-       priv->class_device = device_create_drvdata(vmlogrdr_class, dev,
-                                                  MKDEV(vmlogrdr_major,
-                                                        priv->minor_num),
-                                                  priv, "%s", dev_name(dev));
+       priv->class_device = device_create(vmlogrdr_class, dev,
+                                          MKDEV(vmlogrdr_major,
+                                                priv->minor_num),
+                                          priv, "%s", dev_name(dev));
        if (IS_ERR(priv->class_device)) {
                ret = PTR_ERR(priv->class_device);
                priv->class_device=NULL;
index 6fdfa5ddeca8f686938f0b52d4bb28b504bfcddc..9020eba620eee22fe8ae36bd0716596c38ae9a7f 100644 (file)
@@ -896,9 +896,8 @@ static int ur_set_online(struct ccw_device *cdev)
                goto fail_free_cdev;
        }
 
-       urd->device = device_create_drvdata(vmur_class, NULL,
-                                           urd->char_device->dev, NULL,
-                                           "%s", node_id);
+       urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
+                                   NULL, "%s", node_id);
        if (IS_ERR(urd->device)) {
                rc = PTR_ERR(urd->device);
                TRACE("ur_set_online: device_create rc=%d\n", rc);
index 8f83fc994f508ef6069a1a9cc67eb30b196e945d..f5e618562c5ff9b1be02d014a022ca13e98e10ef 100644 (file)
@@ -2913,7 +2913,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
        if (ret != 0) {
                printk(KERN_WARNING
                        "claw: ccw_device_set_online %s WRITE failed "
-                      "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev)
+                      "with ret = %d\n", dev_name(&cgdev->cdev[WRITE]->dev),
                       ret);
                goto out;
        }
index cbe470493bf01487c6e99ff09f51945732dcfbb3..19f5d5ed85e087b73cce2e24db1bcbc8d92d6a02 100644 (file)
@@ -1673,7 +1673,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
 
 done:
        if (rc) {
-               ctcm_pr_info("ctcmpc       :  %s() failed\n", __FUNCTION__);
+               ctcm_pr_info("ctcmpc       :  %s() failed\n", __func__);
                priv->xid->xid2_flag2 = 0x40;
                grp->saved_xid2->xid2_flag2 = 0x40;
        }
index d3b211af4e1cd259a4d38bec0193a7792090d991..403ecad48d4b95ba5bdb5897803e496862c6b09f 100644 (file)
@@ -1640,6 +1640,7 @@ config ATARI_SCSI
        tristate "Atari native SCSI support"
        depends on ATARI && SCSI
        select SCSI_SPI_ATTRS
+       select NVRAM
        ---help---
          If you have an Atari with built-in NCR5380 SCSI controller (TT,
          Falcon, ...) say Y to get it supported. Of course also, if you have
@@ -1670,14 +1671,6 @@ config ATARI_SCSI_RESET_BOOT
          boot process fractionally longer but may assist recovery from errors
          that leave the devices with SCSI operations partway completed.
 
-config TT_DMA_EMUL
-       bool "Hades SCSI DMA emulator"
-       depends on ATARI_SCSI && HADES
-       help
-         This option enables code which emulates the TT SCSI DMA chip on the
-         Hades. This increases the SCSI transfer rates at least ten times
-         compared to PIO transfers.
-
 config MAC_SCSI
        bool "Macintosh NCR5380 SCSI"
        depends on MAC && SCSI=y
diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c
deleted file mode 100644 (file)
index cdc710e..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * atari_dma_emul.c -- TT SCSI DMA emulator for the Hades.
- *
- * Copyright 1997 Wout Klaren <W.Klaren@inter.nl.net>
- *
- * 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.
- *
- * This code was written using the Hades TOS source code as a
- * reference. This source code can be found on the home page
- * of Medusa Computer Systems.
- *
- * Version 0.1, 1997-09-24.
- * 
- * This code should be considered experimental. It has only been
- * tested on a Hades with a 68060. It might not work on a Hades
- * with a 68040. Make backups of your hard drives before using
- * this code.
- */
-
-#include <linux/compiler.h>
-#include <asm/thread_info.h>
-#include <asm/uaccess.h>
-
-#define hades_dma_ctrl         (*(unsigned char *) 0xffff8717)
-#define hades_psdm_reg         (*(unsigned char *) 0xffff8741)
-
-#define TRANSFER_SIZE          16
-
-struct m68040_frame {
-       unsigned long  effaddr;  /* effective address */
-       unsigned short ssw;      /* special status word */
-       unsigned short wb3s;     /* write back 3 status */
-       unsigned short wb2s;     /* write back 2 status */
-       unsigned short wb1s;     /* write back 1 status */
-       unsigned long  faddr;    /* fault address */
-       unsigned long  wb3a;     /* write back 3 address */
-       unsigned long  wb3d;     /* write back 3 data */
-       unsigned long  wb2a;     /* write back 2 address */
-       unsigned long  wb2d;     /* write back 2 data */
-       unsigned long  wb1a;     /* write back 1 address */
-       unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
-       unsigned long  pd1;      /* push data 1*/
-       unsigned long  pd2;      /* push data 2*/
-       unsigned long  pd3;      /* push data 3*/
-};
-
-static void writeback (unsigned short wbs, unsigned long wba,
-                      unsigned long wbd, void *old_buserr)
-{
-       mm_segment_t fs = get_fs();
-       static void *save_buserr;
-
-       __asm__ __volatile__ ("movec.l  %%vbr,%%a0\n\t"
-                             "move.l   %0,8(%%a0)\n\t"
-                             :
-                             : "r" (&&bus_error)
-                             : "a0" );
-
-       save_buserr = old_buserr;
-
-       set_fs (MAKE_MM_SEG(wbs & WBTM_040));
-
-       switch (wbs & WBSIZ_040) {
-           case BA_SIZE_BYTE:
-               put_user (wbd & 0xff, (char *)wba);
-               break;
-           case BA_SIZE_WORD:
-               put_user (wbd & 0xffff, (short *)wba);
-               break;
-           case BA_SIZE_LONG:
-               put_user (wbd, (int *)wba);
-               break;
-       }
-
-       set_fs (fs);
-       return;
-
-bus_error:
-       __asm__ __volatile__ ("cmp.l    %0,2(%%sp)\n\t"
-                             "bcs.s    .jump_old\n\t"
-                             "cmp.l    %1,2(%%sp)\n\t"
-                             "bls.s    .restore_old\n"
-                       ".jump_old:\n\t"
-                             "move.l   %2,-(%%sp)\n\t"
-                             "rts\n"
-                       ".restore_old:\n\t"
-                             "move.l   %%a0,-(%%sp)\n\t"
-                             "movec.l  %%vbr,%%a0\n\t"
-                             "move.l   %2,8(%%a0)\n\t"
-                             "move.l   (%%sp)+,%%a0\n\t"
-                             "rte\n\t"
-                             :
-                             : "i" (writeback), "i" (&&bus_error),
-                               "m" (save_buserr) );
-}
-
-/*
- * static inline void set_restdata_reg(unsigned char *cur_addr)
- *
- * Set the rest data register if necessary.
- */
-
-static inline void set_restdata_reg(unsigned char *cur_addr)
-{
-       if (((long) cur_addr & ~3) != 0)
-               tt_scsi_dma.dma_restdata =
-                       *((unsigned long *) ((long) cur_addr & ~3));
-}
-
-/*
- * void hades_dma_emulator(int irq, void *dummy)
- * 
- * This code emulates TT SCSI DMA on the Hades.
- * 
- * Note the following:
- * 
- * 1. When there is no byte available to read from the SCSI bus, or
- *    when a byte cannot yet bet written to the SCSI bus, a bus
- *    error occurs when reading or writing the pseudo DMA data
- *    register (hades_psdm_reg). We have to catch this bus error
- *    and try again to read or write the byte. If after several tries
- *    we still get a bus error, the interrupt handler is left. When
- *    the byte can be read or written, the interrupt handler is
- *    called again.
- * 
- * 2. The SCSI interrupt must be disabled in this interrupt handler.
- * 
- * 3. If we set the EOP signal, the SCSI controller still expects one
- *    byte to be read or written. Therefore the last byte is transferred
- *    separately, after setting the EOP signal.
- * 
- * 4. When this function is left, the address pointer (start_addr) is
- *    converted to a physical address. Because it points one byte
- *    further than the last transferred byte, it can point outside the
- *    current page. If virt_to_phys() is called with this address we
- *    might get an access error. Therefore virt_to_phys() is called with
- *    start_addr - 1 if the count has reached zero. The result is
- *    increased with one.
- */
-
-static irqreturn_t hades_dma_emulator(int irq, void *dummy)
-{
-       unsigned long dma_base;
-       register unsigned long dma_cnt asm ("d3");
-       static long save_buserr;
-       register unsigned long save_sp asm ("d4");
-       register int tries asm ("d5");
-       register unsigned char *start_addr asm ("a3"), *end_addr asm ("a4");
-       register unsigned char *eff_addr;
-       register unsigned char *psdm_reg;
-       unsigned long rem;
-
-       atari_disable_irq(IRQ_TT_MFP_SCSI);
-
-       /*
-        * Read the dma address and count registers.
-        */
-
-       dma_base = SCSI_DMA_READ_P(dma_addr);
-       dma_cnt = SCSI_DMA_READ_P(dma_cnt);
-
-       /*
-        * Check if DMA is still enabled.
-        */
-
-       if ((tt_scsi_dma.dma_ctrl & 2) == 0)
-       {
-               atari_enable_irq(IRQ_TT_MFP_SCSI);
-               return IRQ_HANDLED;
-       }
-
-       if (dma_cnt == 0)
-       {
-               printk(KERN_NOTICE "DMA emulation: count is zero.\n");
-               tt_scsi_dma.dma_ctrl &= 0xfd;   /* DMA ready. */
-               atari_enable_irq(IRQ_TT_MFP_SCSI);
-               return IRQ_HANDLED;
-       }
-
-       /*
-        * Install new bus error routine.
-        */
-
-       __asm__ __volatile__ ("movec.l  %%vbr,%%a0\n\t"
-                             "move.l   8(%%a0),%0\n\t"
-                             "move.l   %1,8(%%a0)\n\t"
-                             : "=&r" (save_buserr)
-                             : "r" (&&scsi_bus_error)
-                             : "a0" );
-
-       hades_dma_ctrl &= 0xfc;         /* Bus error and EOP off. */
-
-       /*
-        * Save the stack pointer.
-        */
-
-       __asm__ __volatile__ ("move.l   %%sp,%0\n\t"
-                             : "=&r" (save_sp) );
-
-       tries = 100;                    /* Maximum number of bus errors. */
-       start_addr = phys_to_virt(dma_base);
-       end_addr = start_addr + dma_cnt;
-
-scsi_loop:
-       dma_cnt--;
-       rem = dma_cnt & (TRANSFER_SIZE - 1);
-       dma_cnt &= ~(TRANSFER_SIZE - 1);
-       psdm_reg = &hades_psdm_reg;
-
-       if (tt_scsi_dma.dma_ctrl & 1)   /* Read or write? */
-       {
-               /*
-                * SCSI write. Abort when count is zero.
-                */
-
-               switch (rem)
-               {
-               case 0:
-                       while (dma_cnt > 0)
-                       {
-                               dma_cnt -= TRANSFER_SIZE;
-
-                               *psdm_reg = *start_addr++;
-               case 15:
-                               *psdm_reg = *start_addr++;
-               case 14:
-                               *psdm_reg = *start_addr++;
-               case 13:
-                               *psdm_reg = *start_addr++;
-               case 12:
-                               *psdm_reg = *start_addr++;
-               case 11:
-                               *psdm_reg = *start_addr++;
-               case 10:
-                               *psdm_reg = *start_addr++;
-               case 9:
-                               *psdm_reg = *start_addr++;
-               case 8:
-                               *psdm_reg = *start_addr++;
-               case 7:
-                               *psdm_reg = *start_addr++;
-               case 6:
-                               *psdm_reg = *start_addr++;
-               case 5:
-                               *psdm_reg = *start_addr++;
-               case 4:
-                               *psdm_reg = *start_addr++;
-               case 3:
-                               *psdm_reg = *start_addr++;
-               case 2:
-                               *psdm_reg = *start_addr++;
-               case 1:
-                               *psdm_reg = *start_addr++;
-                       }
-               }
-
-               hades_dma_ctrl |= 1;    /* Set EOP. */
-               udelay(10);
-               *psdm_reg = *start_addr++;      /* Dummy byte. */
-               tt_scsi_dma.dma_ctrl &= 0xfd;   /* DMA ready. */
-       }
-       else
-       {
-               /*
-                * SCSI read. Abort when count is zero.
-                */
-
-               switch (rem)
-               {
-               case 0:
-                       while (dma_cnt > 0)
-                       {
-                               dma_cnt -= TRANSFER_SIZE;
-
-                               *start_addr++ = *psdm_reg;
-               case 15:
-                               *start_addr++ = *psdm_reg;
-               case 14:
-                               *start_addr++ = *psdm_reg;
-               case 13:
-                               *start_addr++ = *psdm_reg;
-               case 12:
-                               *start_addr++ = *psdm_reg;
-               case 11:
-                               *start_addr++ = *psdm_reg;
-               case 10:
-                               *start_addr++ = *psdm_reg;
-               case 9:
-                               *start_addr++ = *psdm_reg;
-               case 8:
-                               *start_addr++ = *psdm_reg;
-               case 7:
-                               *start_addr++ = *psdm_reg;
-               case 6:
-                               *start_addr++ = *psdm_reg;
-               case 5:
-                               *start_addr++ = *psdm_reg;
-               case 4:
-                               *start_addr++ = *psdm_reg;
-               case 3:
-                               *start_addr++ = *psdm_reg;
-               case 2:
-                               *start_addr++ = *psdm_reg;
-               case 1:
-                               *start_addr++ = *psdm_reg;
-                       }
-               }
-
-               hades_dma_ctrl |= 1;    /* Set EOP. */
-               udelay(10);
-               *start_addr++ = *psdm_reg;
-               tt_scsi_dma.dma_ctrl &= 0xfd;   /* DMA ready. */
-
-               set_restdata_reg(start_addr);
-       }
-
-       if (start_addr != end_addr)
-               printk(KERN_CRIT "DMA emulation: FATAL: Count is not zero at end of transfer.\n");
-
-       dma_cnt = end_addr - start_addr;
-
-scsi_end:
-       dma_base = (dma_cnt == 0) ? virt_to_phys(start_addr - 1) + 1 :  
-                                   virt_to_phys(start_addr);
-
-       SCSI_DMA_WRITE_P(dma_addr, dma_base);
-       SCSI_DMA_WRITE_P(dma_cnt, dma_cnt);
-
-       /*
-        * Restore old bus error routine.
-        */
-
-       __asm__ __volatile__ ("movec.l  %%vbr,%%a0\n\t"
-                             "move.l   %0,8(%%a0)\n\t"
-                             :
-                             : "r" (save_buserr)
-                             : "a0" );
-
-       atari_enable_irq(IRQ_TT_MFP_SCSI);
-
-       return IRQ_HANDLED;
-
-scsi_bus_error:
-       /*
-        * First check if the bus error is caused by our code.
-        * If not, call the original handler.
-        */
-
-       __asm__ __volatile__ ("cmp.l    %0,2(%%sp)\n\t"
-                             "bcs.s    .old_vector\n\t"
-                             "cmp.l    %1,2(%%sp)\n\t"
-                             "bls.s    .scsi_buserr\n"
-                       ".old_vector:\n\t"
-                             "move.l   %2,-(%%sp)\n\t"
-                             "rts\n"
-                       ".scsi_buserr:\n\t"
-                             :
-                             : "i" (&&scsi_loop), "i" (&&scsi_end),
-                               "m" (save_buserr) );
-
-       if (CPU_IS_060)
-       {
-               /*
-                * Get effective address and restore the stack.
-                */
-
-               __asm__ __volatile__ ("move.l   8(%%sp),%0\n\t"
-                                     "move.l   %1,%%sp\n\t"
-                                     : "=a&" (eff_addr)
-                                     : "r" (save_sp) );
-       }
-       else
-       {
-               register struct m68040_frame *frame;
-
-               __asm__ __volatile__ ("lea      8(%%sp),%0\n\t"
-                                     : "=a&" (frame) );
-
-               if (tt_scsi_dma.dma_ctrl & 1)
-               {
-                       /*
-                        * Bus error while writing.
-                        */
-
-                       if (frame->wb3s & WBV_040)
-                       {
-                               if (frame->wb3a == (long) &hades_psdm_reg)
-                                       start_addr--;
-                               else
-                                       writeback(frame->wb3s, frame->wb3a,
-                                                 frame->wb3d, &&scsi_bus_error);
-                       }
-
-                       if (frame->wb2s & WBV_040)
-                       {
-                               if (frame->wb2a == (long) &hades_psdm_reg)
-                                       start_addr--;
-                               else
-                                       writeback(frame->wb2s, frame->wb2a,
-                                                 frame->wb2d, &&scsi_bus_error);
-                       }
-
-                       if (frame->wb1s & WBV_040)
-                       {
-                               if (frame->wb1a == (long) &hades_psdm_reg)
-                                       start_addr--;
-                       }
-               }
-               else
-               {
-                       /*
-                        * Bus error while reading.
-                        */
-
-                       if (frame->wb3s & WBV_040)
-                               writeback(frame->wb3s, frame->wb3a,
-                                         frame->wb3d, &&scsi_bus_error);
-               }
-
-               eff_addr = (unsigned char *) frame->faddr;
-
-               __asm__ __volatile__ ("move.l   %0,%%sp\n\t"
-                                     :
-                                     : "r" (save_sp) );
-       }
-
-       dma_cnt = end_addr - start_addr;
-
-       if (eff_addr == &hades_psdm_reg)
-       {
-               /*
-                * Bus error occurred while reading the pseudo
-                * DMA register. Time out.
-                */
-
-               tries--;
-
-               if (tries <= 0)
-               {
-                       if ((tt_scsi_dma.dma_ctrl & 1) == 0)    /* Read or write? */
-                               set_restdata_reg(start_addr);
-
-                       if (dma_cnt <= 1)
-                               printk(KERN_CRIT "DMA emulation: Fatal "
-                                      "error while %s the last byte.\n",
-                                      (tt_scsi_dma.dma_ctrl & 1)
-                                      ? "writing" : "reading");
-
-                       goto scsi_end;
-               }
-               else
-                       goto scsi_loop;
-       }
-       else
-       {
-               /*
-                * Bus error during pseudo DMA transfer.
-                * Terminate the DMA transfer.
-                */
-
-               hades_dma_ctrl |= 3;    /* Set EOP and bus error. */
-               if ((tt_scsi_dma.dma_ctrl & 1) == 0)    /* Read or write? */
-                       set_restdata_reg(start_addr);
-               goto scsi_end;
-       }
-}
index f5732d8f67fec793badb30948d369710e9260a55..21fe07f9df87be3ebd5222d8ce15eaea2e04d5d4 100644 (file)
@@ -249,10 +249,6 @@ static int setup_hostid = -1;
 module_param(setup_hostid, int, 0);
 
 
-#if defined(CONFIG_TT_DMA_EMUL)
-#include "atari_dma_emul.c"
-#endif
-
 #if defined(REAL_DMA)
 
 static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
@@ -695,21 +691,8 @@ int atari_scsi_detect(struct scsi_host_template *host)
 #ifdef REAL_DMA
                tt_scsi_dma.dma_ctrl = 0;
                atari_dma_residual = 0;
-#ifdef CONFIG_TT_DMA_EMUL
-               if (MACH_IS_HADES) {
-                       if (request_irq(IRQ_AUTO_2, hades_dma_emulator,
-                                        IRQ_TYPE_PRIO, "Hades DMA emulator",
-                                        hades_dma_emulator)) {
-                               printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting (MACH_IS_HADES)",IRQ_AUTO_2);
-                               free_irq(IRQ_TT_MFP_SCSI, instance);
-                               scsi_unregister(atari_scsi_host);
-                               atari_stram_free(atari_dma_buffer);
-                               atari_dma_buffer = 0;
-                               return 0;
-                       }
-               }
-#endif
-               if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+
+               if (MACH_IS_MEDUSA) {
                        /* While the read overruns (described by Drew Eckhardt in
                         * NCR5380.c) never happened on TTs, they do in fact on the Medusa
                         * (This was the cause why SCSI didn't work right for so long
@@ -1007,11 +990,7 @@ static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
                                        Scsi_Cmnd *cmd, int write_flag)
 {
        unsigned long   possible_len, limit;
-#ifndef CONFIG_TT_DMA_EMUL
-       if (MACH_IS_HADES)
-               /* Hades has no SCSI DMA at all :-( Always force use of PIO */
-               return 0;
-#endif
+
        if (IS_A_TT())
                /* TT SCSI DMA can transfer arbitrary #bytes */
                return wanted_len;
index 3c257fe0893e51c9740f226b752a559321cb95a4..88ecf94ad979f92d737fb24adb25ef0fe2a58125 100644 (file)
@@ -914,9 +914,9 @@ static int ch_probe(struct device *dev)
        ch->minor = minor;
        sprintf(ch->name,"ch%d",ch->minor);
 
-       class_dev = device_create_drvdata(ch_sysfs_class, dev,
-                                         MKDEV(SCSI_CHANGER_MAJOR, ch->minor),
-                                         ch, "s%s", ch->name);
+       class_dev = device_create(ch_sysfs_class, dev,
+                                 MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
+                                 "s%s", ch->name);
        if (IS_ERR(class_dev)) {
                printk(KERN_WARNING "ch%d: device_create failed\n",
                       ch->minor);
index 1fe0901e81192d91dad44c4773908c1f6492d39a..8aba4fdfb5222b40d93a8e231fd1b69858ddecdc 100644 (file)
@@ -271,7 +271,7 @@ rebuild_sys_tab:
                pHba->initialized = TRUE;
                pHba->state &= ~DPTI_STATE_RESET;
                if (adpt_sysfs_class) {
-                       struct device *dev = device_create_drvdata(adpt_sysfs_class,
+                       struct device *dev = device_create(adpt_sysfs_class,
                                NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
                                "dpti%d", pHba->unit);
                        if (IS_ERR(dev)) {
index 90212ac33be3f1cc39217ef88430e986f9fe6d8a..740bad435995268112883ff77c61af58e93ce8b6 100644 (file)
@@ -82,7 +82,6 @@ typedef struct ide_scsi_obj {
        struct gendisk          *disk;
        struct Scsi_Host        *host;
 
-       struct ide_atapi_pc *pc;                /* Current packet command */
        unsigned long transform;                /* SCSI cmd translation layer */
        unsigned long log;                      /* log flags */
 } idescsi_scsi_t;
@@ -137,10 +136,10 @@ static void ide_scsi_hex_dump(u8 *data, int len)
 
 static int idescsi_end_request(ide_drive_t *, int, int);
 
-static void ide_scsi_callback(ide_drive_t *drive)
+static void ide_scsi_callback(ide_drive_t *drive, int dsc)
 {
        idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-       struct ide_atapi_pc *pc = scsi->pc;
+       struct ide_atapi_pc *pc = drive->pc;
 
        if (pc->flags & PC_FLAG_TIMEDOUT)
                debug_log("%s: got timed out packet %lu at %lu\n", __func__,
@@ -267,49 +266,10 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
        spin_unlock_irqrestore(host->host_lock, flags);
        kfree(pc);
        blk_put_request(rq);
-       scsi->pc = NULL;
+       drive->pc = NULL;
        return 0;
 }
 
-static inline unsigned long get_timeout(struct ide_atapi_pc *pc)
-{
-       return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
-}
-
-static int idescsi_expiry(ide_drive_t *drive)
-{
-       idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-       struct ide_atapi_pc   *pc   = scsi->pc;
-
-       debug_log("%s called for %lu at %lu\n", __func__,
-                 pc->scsi_cmd->serial_number, jiffies);
-
-       pc->flags |= PC_FLAG_TIMEDOUT;
-
-       return 0;                                       /* we do not want the ide subsystem to retry */
-}
-
-/*
- *     Our interrupt handler.
- */
-static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
-{
-       idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-       struct ide_atapi_pc *pc = scsi->pc;
-
-       return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc),
-                          idescsi_expiry, NULL, NULL, NULL,
-                          ide_io_buffers);
-}
-
-static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
-{
-       idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
-       return ide_transfer_pc(drive, scsi->pc, idescsi_pc_intr,
-                              get_timeout(scsi->pc), idescsi_expiry);
-}
-
 static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
 {
        switch (pc->c[0]) {
@@ -352,13 +312,10 @@ static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
 static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
 {
-       idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
        /* Set the current packet command */
-       scsi->pc = pc;
+       drive->pc = pc;
 
-       return ide_issue_pc(drive, pc, idescsi_transfer_pc,
-                           get_timeout(pc), idescsi_expiry);
+       return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);
 }
 
 /*
@@ -374,7 +331,8 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
        if (blk_sense_request(rq) || blk_special_request(rq)) {
                struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
 
-               if (drive->using_dma && !idescsi_map_sg(drive, pc))
+               if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&
+                   idescsi_map_sg(drive, pc) == 0)
                        pc->flags |= PC_FLAG_DMA_OK;
 
                return idescsi_issue_pc(drive, pc);
@@ -427,14 +385,14 @@ static const struct ide_proc_devset idescsi_settings[] = {
  */
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
-       if ((drive->id[ATA_ID_CONFIG] & 0x0060) == 0x20)
-               set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
        clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
        set_bit(IDESCSI_LOG_CMD, &scsi->log);
 #endif /* IDESCSI_DEBUG_LOG */
 
-       drive->pc_callback = ide_scsi_callback;
+       drive->pc_callback       = ide_scsi_callback;
+       drive->pc_update_buffers = NULL;
+       drive->pc_io_buffers     = ide_io_buffers;
 
        ide_proc_register_driver(drive, scsi->driver);
 }
@@ -456,7 +414,7 @@ static void ide_scsi_remove(ide_drive_t *drive)
 
        ide_scsi_put(scsi);
 
-       drive->scsi = 0;
+       drive->dev_flags &= ~IDE_DFLAG_SCSI;
 }
 
 static int ide_scsi_probe(ide_drive_t *);
@@ -477,7 +435,6 @@ static ide_driver_t idescsi_driver = {
        .probe                  = ide_scsi_probe,
        .remove                 = ide_scsi_remove,
        .version                = IDESCSI_VERSION,
-       .media                  = ide_scsi,
        .do_request             = idescsi_do_request,
        .end_request            = idescsi_end_request,
        .error                  = idescsi_atapi_error,
@@ -622,6 +579,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
        int             busy;
        int             ret   = FAILED;
 
+       struct ide_atapi_pc *pc;
+
        /* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
 
        if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
@@ -642,26 +601,27 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
        spin_lock_irq(&ide_lock);
 
        /* If there is no pc running we're done (our interrupt took care of it) */
-       if (!scsi->pc) {
+       pc = drive->pc;
+       if (pc == NULL) {
                ret = SUCCESS;
                goto ide_unlock;
        }
 
        /* It's somewhere in flight. Does ide subsystem agree? */
-       if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
-           elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
+       if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
+           elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {
                /*
                 * FIXME - not sure this condition can ever occur
                 */
                printk (KERN_ERR "ide-scsi: cmd aborted!\n");
 
-               if (blk_sense_request(scsi->pc->rq))
-                       kfree(scsi->pc->buf);
+               if (blk_sense_request(pc->rq))
+                       kfree(pc->buf);
                /* we need to call blk_put_request twice. */
-               blk_put_request(scsi->pc->rq);
-               blk_put_request(scsi->pc->rq);
-               kfree(scsi->pc);
-               scsi->pc = NULL;
+               blk_put_request(pc->rq);
+               blk_put_request(pc->rq);
+               kfree(pc);
+               drive->pc = NULL;
 
                ret = SUCCESS;
        }
@@ -683,6 +643,8 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
        int             ready = 0;
        int             ret   = SUCCESS;
 
+       struct ide_atapi_pc *pc;
+
        /* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
 
        if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
@@ -697,7 +659,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
        spin_lock_irq(cmd->device->host->host_lock);
        spin_lock(&ide_lock);
 
-       if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+       pc = drive->pc;
+
+       if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
                printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
                spin_unlock(&ide_lock);
                spin_unlock_irq(cmd->device->host->host_lock);
@@ -708,9 +672,9 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
        if (__blk_end_request(req, -EIO, 0))
                BUG();
        if (blk_sense_request(req))
-               kfree(scsi->pc->buf);
-       kfree(scsi->pc);
-       scsi->pc = NULL;
+               kfree(pc->buf);
+       kfree(pc);
+       drive->pc = NULL;
        blk_put_request(req);
 
        /* now nuke the drive queue */
@@ -801,7 +765,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
            !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
                return -ENODEV;
 
-       drive->scsi = 1;
+       drive->dev_flags |= IDE_DFLAG_SCSI;
 
        g = alloc_disk(1 << PARTN_BITS);
        if (!g)
@@ -842,7 +806,7 @@ static int ide_scsi_probe(ide_drive_t *drive)
 
        put_disk(g);
 out_host_put:
-       drive->scsi = 0;
+       drive->dev_flags &= ~IDE_DFLAG_SCSI;
        scsi_host_put(host);
        return err;
 }
index 1c79f9794f4e82bf1e5f30da63bda2b9ace3418b..0ea78d9a37db1a6b0da5b0a18f93fba2aa826a4e 100644 (file)
@@ -5708,7 +5708,8 @@ static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * S
        struct device *osst_member;
        int err;
 
-       osst_member = device_create_drvdata(osst_sysfs_class, device, dev, STp, "%s", name);
+       osst_member = device_create(osst_sysfs_class, device, dev, STp,
+                                   "%s", name);
        if (IS_ERR(osst_member)) {
                printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
                return PTR_ERR(osst_member);
index 2dd0dc9a9aedbed19fbf4169394b5a73ed376e7c..165ff884f48edeb6278dff3939695ab1ee83d361 100644 (file)
@@ -140,44 +140,41 @@ static void aha152x_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int aha152x_config_check(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cfg,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
+{
+       /* For New Media T&J, look for a SCSI window */
+       if (cfg->io.win[0].len >= 0x20)
+               p_dev->io.BasePort1 = cfg->io.win[0].base;
+       else if ((cfg->io.nwin > 1) &&
+                (cfg->io.win[1].len >= 0x20))
+               p_dev->io.BasePort1 = cfg->io.win[1].base;
+       if ((cfg->io.nwin > 0) &&
+           (p_dev->io.BasePort1 < 0xffff)) {
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -EINVAL;
+}
+
 static int aha152x_config_cs(struct pcmcia_device *link)
 {
     scsi_info_t *info = link->priv;
     struct aha152x_setup s;
-    tuple_t tuple;
-    cisparse_t parse;
-    int i, last_ret, last_fn;
-    u_char tuple_data[64];
+    int last_ret, last_fn;
     struct Scsi_Host *host;
-    
+
     DEBUG(0, "aha152x_config(0x%p)\n", link);
 
-    tuple.TupleData = tuple_data;
-    tuple.TupleDataMax = 64;
-    tuple.TupleOffset = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (1) {
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-           goto next_entry;
-       /* For New Media T&J, look for a SCSI window */
-       if (parse.cftable_entry.io.win[0].len >= 0x20)
-           link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-       else if ((parse.cftable_entry.io.nwin > 1) &&
-                (parse.cftable_entry.io.win[1].len >= 0x20))
-           link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
-       if ((parse.cftable_entry.io.nwin > 0) &&
-           (link->io.BasePort1 < 0xffff)) {
-           link->conf.ConfigIndex = parse.cftable_entry.index;
-           i = pcmcia_request_io(link, &link->io);
-           if (i == CS_SUCCESS) break;
-       }
-    next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+    last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
+    if (last_ret) {
+       cs_error(link, RequestIO, last_ret);
+       goto failed;
     }
-    
+
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     
@@ -208,6 +205,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
 
 cs_failed:
     cs_error(link, last_fn, last_ret);
+failed:
     aha152x_release_cs(link);
     return -ENODEV;
 }
index d8b99351b053b256e3ad0bd4af7854ef5f77ba65..06254f46a0ddda146322e0b106faa13b90bb9882 100644 (file)
@@ -123,34 +123,30 @@ static void fdomain_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int fdomain_config_check(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cfg,
+                               cistpl_cftable_entry_t *dflt,
+                               unsigned int vcc,
+                               void *priv_data)
+{
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
+
 static int fdomain_config(struct pcmcia_device *link)
 {
     scsi_info_t *info = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    int i, last_ret, last_fn;
-    u_char tuple_data[64];
+    int last_ret, last_fn;
     char str[22];
     struct Scsi_Host *host;
 
     DEBUG(0, "fdomain_config(0x%p)\n", link);
 
-    tuple.TupleData = tuple_data;
-    tuple.TupleDataMax = 64;
-    tuple.TupleOffset = 0;
-
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (1) {
-       if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-           goto next_entry;
-       link->conf.ConfigIndex = parse.cftable_entry.index;
-       link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-       i = pcmcia_request_io(link, &link->io);
-       if (i == CS_SUCCESS) break;
-    next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+    last_ret = pcmcia_loop_config(link, fdomain_config_check, NULL);
+    if (last_ret) {
+           cs_error(link, RequestIO, last_ret);
+           goto failed;
     }
 
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -181,6 +177,7 @@ static int fdomain_config(struct pcmcia_device *link)
 
 cs_failed:
     cs_error(link, last_fn, last_ret);
+failed:
     fdomain_release(link);
     return -ENODEV;
 } /* fdomain_config */
index 24e6cb8396e35e9bcebe890e9352f1cddc613c80..11a61ea8d5d917d8d6e8478313885ee99cb20ad8 100644 (file)
@@ -1606,133 +1606,129 @@ static void nsp_cs_detach(struct pcmcia_device *link)
     is received, to configure the PCMCIA socket, and to make the
     ethernet device available to the system.
 ======================================================================*/
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-/*====================================================================*/
-static int nsp_cs_config(struct pcmcia_device *link)
-{
-       int               ret;
-       scsi_info_t      *info   = link->priv;
-       tuple_t           tuple;
-       cisparse_t        parse;
-       int               last_ret, last_fn;
-       unsigned char     tuple_data[64];
-       config_info_t     conf;
-       win_req_t         req;
-       memreq_t          map;
-       cistpl_cftable_entry_t dflt = { 0 };
-       struct Scsi_Host *host;
-       nsp_hw_data      *data = &nsp_data_base;
-
-       nsp_dbg(NSP_DEBUG_INIT, "in");
-
-       tuple.Attributes      = 0;
-       tuple.TupleData       = tuple_data;
-       tuple.TupleDataMax    = sizeof(tuple_data);
-       tuple.TupleOffset     = 0;
-
-       /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
 
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+struct nsp_cs_configdata {
+       nsp_hw_data             *data;
+       win_req_t               req;
+};
 
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
+static int nsp_cs_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cfg,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
+{
+       struct nsp_cs_configdata *cfg_mem = priv_data;
 
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
-               if (cfg->index == 0) { goto next_entry; }
-               link->conf.ConfigIndex = cfg->index;
+       if (cfg->index == 0)
+               return -ENODEV;
 
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
+       /* Does this card need audio output? */
+       if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+               p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+               p_dev->conf.Status = CCSR_AUDIO_ENA;
+       }
 
-               /* Use power settings for Vcc and Vpp if present */
-               /*  Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
-                               goto next_entry;
-                       }
-               } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
-                               goto next_entry;
-                       }
+       /* Use power settings for Vcc and Vpp if present */
+       /*  Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+                       return -ENODEV;
+               else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+                       if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
+                               return -ENODEV;
                }
 
                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       link->conf.Vpp =
+                       p_dev->conf.Vpp =
                                cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-               } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-                       link->conf.Vpp =
-                               dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+               } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
+                       p_dev->conf.Vpp =
+                               dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                }
 
                /* Do we need to allocate an interrupt? */
-               if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-               }
+               if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+                       p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
                /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+               p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+               if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+                       p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
                        if (!(io->flags & CISTPL_IO_8BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+                               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
                        if (!(io->flags & CISTPL_IO_16BIT))
-                               link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
+                               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+                       p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+                       p_dev->io.BasePort1 = io->win[0].base;
+                       p_dev->io.NumPorts1 = io->win[0].len;
                        if (io->nwin > 1) {
-                               link->io.Attributes2 = link->io.Attributes1;
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
+                               p_dev->io.Attributes2 = p_dev->io.Attributes1;
+                               p_dev->io.BasePort2 = io->win[1].base;
+                               p_dev->io.NumPorts2 = io->win[1].len;
                        }
                        /* This reserves IO space but doesn't actually enable it */
-                       if (pcmcia_request_io(link, &link->io) != 0)
+                       if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
                                goto next_entry;
                }
 
-               if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
-                       cistpl_mem_t *mem =
-                               (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
-                       req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-                       req.Attributes |= WIN_ENABLE;
-                       req.Base = mem->win[0].host_addr;
-                       req.Size = mem->win[0].len;
-                       if (req.Size < 0x1000) {
-                               req.Size = 0x1000;
-                       }
-                       req.AccessSpeed = 0;
-                       if (pcmcia_request_window(&link, &req, &link->win) != 0)
+               if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+                       memreq_t        map;
+                       cistpl_mem_t    *mem =
+                               (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+                       cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+                       cfg_mem->req.Attributes |= WIN_ENABLE;
+                       cfg_mem->req.Base = mem->win[0].host_addr;
+                       cfg_mem->req.Size = mem->win[0].len;
+                       if (cfg_mem->req.Size < 0x1000)
+                               cfg_mem->req.Size = 0x1000;
+                       cfg_mem->req.AccessSpeed = 0;
+                       if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
                                goto next_entry;
                        map.Page = 0; map.CardOffset = mem->win[0].card_addr;
-                       if (pcmcia_map_mem_page(link->win, &map) != 0)
+                       if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
                                goto next_entry;
 
-                       data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
-                       data->MmioLength  = req.Size;
+                       cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
+                       cfg_mem->data->MmioLength  = cfg_mem->req.Size;
                }
                /* If we got this far, we're cool! */
-               break;
-
-       next_entry:
-               nsp_dbg(NSP_DEBUG_INIT, "next");
-               pcmcia_disable_device(link);
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+               return 0;
        }
 
+next_entry:
+       nsp_dbg(NSP_DEBUG_INIT, "next");
+       pcmcia_disable_device(p_dev);
+       return -ENODEV;
+}
+
+static int nsp_cs_config(struct pcmcia_device *link)
+{
+       int               ret;
+       scsi_info_t      *info   = link->priv;
+       struct nsp_cs_configdata *cfg_mem;
+       struct Scsi_Host *host;
+       nsp_hw_data      *data = &nsp_data_base;
+
+       nsp_dbg(NSP_DEBUG_INIT, "in");
+
+       cfg_mem = kzalloc(sizeof(cfg_mem), GFP_KERNEL);
+       if (!cfg_mem)
+               return -ENOMEM;
+       cfg_mem->data = data;
+
+       ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+               goto cs_failed;
+
        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-               CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
+               if (pcmcia_request_irq(link, &link->irq))
+                       goto cs_failed;
        }
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
+       ret = pcmcia_request_configuration(link, &link->conf);
+       if (ret)
+               goto cs_failed;
 
        if (free_ports) {
                if (link->io.BasePort1) {
@@ -1790,20 +1786,20 @@ static int nsp_cs_config(struct pcmcia_device *link)
                printk(" & 0x%04x-0x%04x", link->io.BasePort2,
                       link->io.BasePort2+link->io.NumPorts2-1);
        if (link->win)
-               printk(", mem 0x%06lx-0x%06lx", req.Base,
-                      req.Base+req.Size-1);
+               printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
+                      cfg_mem->req.Base+cfg_mem->req.Size-1);
        printk("\n");
 
+       kfree(cfg_mem);
        return 0;
 
  cs_failed:
        nsp_dbg(NSP_DEBUG_INIT, "config fail");
-       cs_error(link, last_fn, last_ret);
        nsp_cs_release(link);
+       kfree(cfg_mem);
 
        return -ENODEV;
 } /* nsp_cs_config */
-#undef CS_CHECK
 
 
 /*======================================================================
index 67c5a58d17df7fb11eca2c8e427a61719d57c086..20c3e5e6d88ad369fedf8f059bb6e7c597ecc826 100644 (file)
@@ -195,39 +195,33 @@ static void qlogic_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int qlogic_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cfg,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
+{
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       p_dev->io.NumPorts1 = cfg->io.win[0].len;
+
+       if (p_dev->io.BasePort1 == 0)
+               return -ENODEV;
+
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int qlogic_config(struct pcmcia_device * link)
 {
        scsi_info_t *info = link->priv;
-       tuple_t tuple;
-       cisparse_t parse;
-       int i, last_ret, last_fn;
-       unsigned short tuple_data[32];
+       int last_ret, last_fn;
        struct Scsi_Host *host;
 
        DEBUG(0, "qlogic_config(0x%p)\n", link);
 
-       info->manf_id = link->manf_id;
-
-       tuple.TupleData = (cisdata_t *) tuple_data;
-       tuple.TupleDataMax = 64;
-       tuple.TupleOffset = 0;
-
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
-               link->conf.ConfigIndex = parse.cftable_entry.index;
-               link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-               link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-               if (link->io.BasePort1 != 0) {
-                       i = pcmcia_request_io(link, &link->io);
-                       if (i == CS_SUCCESS)
-                               break;
-               }
-             next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+       last_ret = pcmcia_loop_config(link, qlogic_config_check, NULL);
+       if (last_ret) {
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -262,6 +256,7 @@ static int qlogic_config(struct pcmcia_device * link)
 cs_failed:
        cs_error(link, last_fn, last_ret);
        pcmcia_disable_device(link);
+failed:
        return -ENODEV;
 
 }                              /* qlogic_config */
index 0be232b58ffb795e5d878f3aa400eee8dab5b673..b330c11a1752378e95dd831dc053646a63d3171a 100644 (file)
@@ -700,15 +700,27 @@ static struct scsi_host_template sym53c500_driver_template = {
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
+static int SYM53C500_config_check(struct pcmcia_device *p_dev,
+                                 cistpl_cftable_entry_t *cfg,
+                                 cistpl_cftable_entry_t *dflt,
+                                 unsigned int vcc,
+                                 void *priv_data)
+{
+       p_dev->io.BasePort1 = cfg->io.win[0].base;
+       p_dev->io.NumPorts1 = cfg->io.win[0].len;
+
+       if (p_dev->io.BasePort1 == 0)
+               return -ENODEV;
+
+       return pcmcia_request_io(p_dev, &p_dev->io);
+}
+
 static int
 SYM53C500_config(struct pcmcia_device *link)
 {
        struct scsi_info_t *info = link->priv;
-       tuple_t tuple;
-       cisparse_t parse;
-       int i, last_ret, last_fn;
+       int last_ret, last_fn;
        int irq_level, port_base;
-       unsigned short tuple_data[32];
        struct Scsi_Host *host;
        struct scsi_host_template *tpnt = &sym53c500_driver_template;
        struct sym53c500_data *data;
@@ -717,27 +729,10 @@ SYM53C500_config(struct pcmcia_device *link)
 
        info->manf_id = link->manf_id;
 
-       tuple.TupleData = (cisdata_t *)tuple_data;
-       tuple.TupleDataMax = 64;
-       tuple.TupleOffset = 0;
-
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                   pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
-               link->conf.ConfigIndex = parse.cftable_entry.index;
-               link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
-               link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
-
-               if (link->io.BasePort1 != 0) {
-                       i = pcmcia_request_io(link, &link->io);
-                       if (i == CS_SUCCESS)
-                               break;
-               }
-next_entry:
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
+       last_ret = pcmcia_loop_config(link, SYM53C500_config_check, NULL);
+       if (last_ret) {
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@@ -831,6 +826,7 @@ err_release:
 
 cs_failed:
        cs_error(link, last_fn, last_ret);
+failed:
        SYM53C500_release(link);
        return -ENODEV;
 } /* SYM53C500_config */
index ba9b9bbd4e7385e8d83f3ed4f4a1151b96ab3a1f..93bd59a1ed79b80bde26a459b45b0a0d40ae7f83 100644 (file)
@@ -1450,12 +1450,10 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf)
        if (sg_sysfs_valid) {
                struct device *sg_class_member;
 
-               sg_class_member = device_create_drvdata(sg_sysfs_class,
-                                                       cl_dev->parent,
-                                                       MKDEV(SCSI_GENERIC_MAJOR,
-                                                             sdp->index),
-                                                       sdp,
-                                                       "%s", disk->disk_name);
+               sg_class_member = device_create(sg_sysfs_class, cl_dev->parent,
+                                               MKDEV(SCSI_GENERIC_MAJOR,
+                                                     sdp->index),
+                                               sdp, "%s", disk->disk_name);
                if (IS_ERR(sg_class_member)) {
                        printk(KERN_ERR "sg_add: "
                               "device_create failed\n");
index c2bb53e3d941faee5d29f5902ac757093102d772..5c28d08f18f46a1bc3f28c5451f84606af747f7c 100644 (file)
@@ -4428,13 +4428,10 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
                snprintf(name, 10, "%s%s%s", rew ? "n" : "",
                         STp->disk->disk_name, st_formats[i]);
                st_class_member =
-                       device_create_drvdata(st_sysfs_class,
-                                             &STp->device->sdev_gendev,
-                                             MKDEV(SCSI_TAPE_MAJOR,
-                                                   TAPE_MINOR(dev_num,
-                                                             mode, rew)),
-                                             &STp->modes[mode],
-                                             "%s", name);
+                       device_create(st_sysfs_class, &STp->device->sdev_gendev,
+                                     MKDEV(SCSI_TAPE_MAJOR,
+                                           TAPE_MINOR(dev_num, mode, rew)),
+                                     &STp->modes[mode], "%s", name);
                if (IS_ERR(st_class_member)) {
                        printk(KERN_WARNING "st%d: device_create failed\n",
                               dev_num);
index 9ccc563d87303604c8cd63f355040177c30faf81..1528de23a6504987f78038db7be1e933e4762364 100644 (file)
 
 #include "8250.h"
 
+#ifdef CONFIG_SPARC
+#include "suncore.h"
+#endif
+
 /*
  * Configuration:
  *   share_irqs - whether we pass IRQF_SHARED to request_irq().  This option
@@ -53,6 +57,13 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
 
 static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
 
+static struct uart_driver serial8250_reg;
+
+static int serial_index(struct uart_port *port)
+{
+       return (serial8250_reg.minor - 64) + port->line;
+}
+
 /*
  * Debugging.
  */
@@ -536,7 +547,7 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
 /*
  * FIFO support.
  */
-static inline void serial8250_clear_fifos(struct uart_8250_port *p)
+static void serial8250_clear_fifos(struct uart_8250_port *p)
 {
        if (p->capabilities & UART_CAP_FIFO) {
                serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -551,7 +562,7 @@ static inline void serial8250_clear_fifos(struct uart_8250_port *p)
  * capability" bit enabled.  Note that on XR16C850s, we need to
  * reset LCR to write to IER.
  */
-static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
 {
        if (p->capabilities & UART_CAP_SLEEP) {
                if (p->capabilities & UART_CAP_EFR) {
@@ -993,7 +1004,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
                return;
 
        DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ",
-                       up->port.line, up->port.iobase, up->port.membase);
+                      serial_index(&up->port), up->port.iobase, up->port.membase);
 
        /*
         * We really do need global IRQs disabled here - we're going to
@@ -1128,8 +1139,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        if (up->capabilities != uart_config[up->port.type].flags) {
                printk(KERN_WARNING
                       "ttyS%d: detected caps %08x should be %08x\n",
-                       up->port.line, up->capabilities,
-                       uart_config[up->port.type].flags);
+                      serial_index(&up->port), up->capabilities,
+                      uart_config[up->port.type].flags);
        }
 
        up->port.fifosize = uart_config[up->port.type].fifo_size;
@@ -1424,8 +1435,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
 /*
  * This handles the interrupt from one port.
  */
-static inline void
-serial8250_handle_port(struct uart_8250_port *up)
+static void serial8250_handle_port(struct uart_8250_port *up)
 {
        unsigned int status;
        unsigned long flags;
@@ -1719,7 +1729,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
 /*
  *     Wait for transmitter & holding register to empty
  */
-static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
 {
        unsigned int status, tmout = 10000;
 
@@ -1854,7 +1864,8 @@ static int serial8250_startup(struct uart_port *port)
         */
        if (!(up->port.flags & UPF_BUGGY_UART) &&
            (serial_inp(up, UART_LSR) == 0xff)) {
-               printk("ttyS%d: LSR safety check engaged!\n", up->port.line);
+               printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+                      serial_index(&up->port));
                return -ENODEV;
        }
 
@@ -1909,7 +1920,8 @@ static int serial8250_startup(struct uart_port *port)
                 */
                if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
                        up->bugs |= UART_BUG_THRE;
-                       pr_debug("ttyS%d - using backup timer\n", port->line);
+                       pr_debug("ttyS%d - using backup timer\n",
+                                serial_index(port));
                }
        }
 
@@ -1969,7 +1981,7 @@ static int serial8250_startup(struct uart_port *port)
                if (!(up->bugs & UART_BUG_TXEN)) {
                        up->bugs |= UART_BUG_TXEN;
                        pr_debug("ttyS%d - enabling bad tx status workarounds\n",
-                                port->line);
+                                serial_index(port));
                }
        } else {
                up->bugs &= ~UART_BUG_TXEN;
@@ -2211,9 +2223,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
                serial_outp(up, UART_EFR, efr);
        }
 
-#ifdef CONFIG_ARCH_OMAP15XX
+#ifdef CONFIG_ARCH_OMAP
        /* Workaround to enable 115200 baud on OMAP1510 internal ports */
-       if (cpu_is_omap1510() && is_omap_port((unsigned int)up->port.membase)) {
+       if (cpu_is_omap1510() && is_omap_port(up)) {
                if (baud == 115200) {
                        quot = 1;
                        serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
@@ -2266,18 +2278,27 @@ serial8250_pm(struct uart_port *port, unsigned int state,
                p->pm(port, state, oldstate);
 }
 
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+       if (pt->port.iotype == UPIO_AU)
+               return 0x100000;
+#ifdef CONFIG_ARCH_OMAP
+       if (is_omap_port(pt))
+               return 0x16 << pt->port.regshift;
+#endif
+       return 8 << pt->port.regshift;
+}
+
 /*
  * Resource handling.
  */
 static int serial8250_request_std_resource(struct uart_8250_port *up)
 {
-       unsigned int size = 8 << up->port.regshift;
+       unsigned int size = serial8250_port_size(up);
        int ret = 0;
 
        switch (up->port.iotype) {
        case UPIO_AU:
-               size = 0x100000;
-               /* fall thru */
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
@@ -2311,12 +2332,10 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
 
 static void serial8250_release_std_resource(struct uart_8250_port *up)
 {
-       unsigned int size = 8 << up->port.regshift;
+       unsigned int size = serial8250_port_size(up);
 
        switch (up->port.iotype) {
        case UPIO_AU:
-               size = 0x100000;
-               /* fall thru */
        case UPIO_TSI:
        case UPIO_MEM32:
        case UPIO_MEM:
@@ -2630,7 +2649,6 @@ static int serial8250_console_early_setup(void)
        return serial8250_find_port_for_earlycon();
 }
 
-static struct uart_driver serial8250_reg;
 static struct console serial8250_console = {
        .name           = "ttyS",
        .write          = serial8250_console_write,
@@ -2677,7 +2695,6 @@ static struct uart_driver serial8250_reg = {
        .dev_name               = "ttyS",
        .major                  = TTY_MAJOR,
        .minor                  = 64,
-       .nr                     = UART_NR,
        .cons                   = SERIAL8250_CONSOLE,
 };
 
@@ -2962,7 +2979,12 @@ static int __init serial8250_init(void)
        for (i = 0; i < NR_IRQS; i++)
                spin_lock_init(&irq_lists[i].lock);
 
+#ifdef CONFIG_SPARC
+       ret = sunserial_register_minors(&serial8250_reg, UART_NR);
+#else
+       serial8250_reg.nr = UART_NR;
        ret = uart_register_driver(&serial8250_reg);
+#endif
        if (ret)
                goto out;
 
@@ -2987,7 +3009,11 @@ static int __init serial8250_init(void)
  put_dev:
        platform_device_put(serial8250_isa_devs);
  unreg_uart_drv:
+#ifdef CONFIG_SPARC
+       sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
        uart_unregister_driver(&serial8250_reg);
+#endif
  out:
        return ret;
 }
@@ -3006,7 +3032,11 @@ static void __exit serial8250_exit(void)
        platform_driver_unregister(&serial8250_isa_driver);
        platform_device_unregister(isa_dev);
 
+#ifdef CONFIG_SPARC
+       sunserial_unregister_minors(&serial8250_reg, UART_NR);
+#else
        uart_unregister_driver(&serial8250_reg);
+#endif
 }
 
 module_init(serial8250_init);
index c2f23933155b1cbfdff132b035f76d84b143a73a..c014ffb110e98c8b4801d47c4884ddead3a4b492 100644 (file)
@@ -2041,9 +2041,9 @@ static int pciserial_resume_one(struct pci_dev *dev)
                 * The device may have been disabled.  Re-enable it.
                 */
                err = pci_enable_device(dev);
+               /* FIXME: We cannot simply error out here */
                if (err)
-                       return err;
-
+                       printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
                pciserial_resume_ports(priv);
        }
        return 0;
index 77cb34270fc18699ad754c4d848bf27cc7e27942..db783b77a881b9a74cbf298f3442433a6b5eeb4c 100644 (file)
@@ -9,7 +9,6 @@ menu "Serial drivers"
 # The new 8250/16550 serial drivers
 config SERIAL_8250
        tristate "8250/16550 and compatible serial support"
-       depends on (BROKEN || !SPARC)
        select SERIAL_CORE
        ---help---
          This selects whether you want to include the driver for the standard
@@ -994,24 +993,12 @@ config SERIAL_68328_RTS_CTS
        bool "Support RTS/CTS on 68328 serial port"
        depends on SERIAL_68328
 
-config SERIAL_COLDFIRE
-       bool "ColdFire serial support (DEPRECATED)"
-       depends on COLDFIRE
-       help
-         This driver supports the built-in serial ports of the Motorola ColdFire
-         family of CPUs.
-         This driver is deprecated because it supports only the old interface
-         for serial drivers and features like magic keys are not working.
-         Please switch to the new style driver because this driver will be
-         removed soon.
-
 config SERIAL_MCF
-       bool "Coldfire serial support (new style driver)"
+       bool "Coldfire serial support"
        depends on COLDFIRE
        select SERIAL_CORE
        help
-         This new serial driver supports the Freescale Coldfire serial ports
-         using the new serial driver subsystem.
+         This serial driver supports the Freescale Coldfire serial ports.
 
 config SERIAL_MCF_BAUDRATE
        int "Default baudrate for Coldfire serial ports"
@@ -1136,42 +1123,6 @@ config SERIAL_CPM_CONSOLE
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
-config SERIAL_CPM_SCC1
-       bool "Support for SCC1 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SCC1 as a serial port
-
-config SERIAL_CPM_SCC2
-       bool "Support for SCC2 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SCC2 as a serial port
-
-config SERIAL_CPM_SCC3
-       bool "Support for SCC3 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SCC3 as a serial port
-
-config SERIAL_CPM_SCC4
-       bool "Support for SCC4 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SCC4 as a serial port
-
-config SERIAL_CPM_SMC1
-       bool "Support for SMC1 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SMC1 as a serial port
-
-config SERIAL_CPM_SMC2
-       bool "Support for SMC2 serial port"
-       depends on SERIAL_CPM=y
-       help
-         Select this option to use SMC2 as a serial port
-
 config SERIAL_SGI_L1_CONSOLE
        bool "SGI Altix L1 serial console support"
        depends on IA64_GENERIC || IA64_SGI_SN2
index 7e7383e890d8b98c8b620252896ba9caf731f589..0c17c8ddb19d314be93614760224aed72e838e49 100644 (file)
@@ -4,6 +4,16 @@
 
 obj-$(CONFIG_SERIAL_CORE) += serial_core.o
 obj-$(CONFIG_SERIAL_21285) += 21285.o
+
+# These Sparc drivers have to appear before others such as 8250
+# which share ttySx minor node space.  Otherwise console device
+# names change and other unplesantries.
+obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
+obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
+obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
+obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
+obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
+
 obj-$(CONFIG_SERIAL_8250) += 8250.o
 obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
 obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
@@ -31,16 +41,10 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
 obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
-obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
-obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
-obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
-obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
-obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
-obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
 obj-$(CONFIG_SERIAL_MCF) += mcf.o
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
 obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
index 4a0d30bed9f12729355272560f66bff6aeb9649e..569f0e2476c690259e6234911db7c33c4998c4b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip Serial Driver
  *
- * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2008 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -42,6 +42,9 @@
 #define BFIN_SERIAL_MAJOR      204
 #define BFIN_SERIAL_MINOR      64
 
+static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
+static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
+
 /*
  * Setup for console. Argument comes from the menuconfig
  */
@@ -126,13 +129,13 @@ static int kgdb_entry_state;
 void kgdb_put_debug_char(int chr)
 {
        struct bfin_serial_port *uart;
-       
+
        if (CONFIG_KGDB_UART_PORT < 0
                || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
                uart = &bfin_serial_ports[0];
        else
                uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-       
+
        while (!(UART_GET_LSR(uart) & THRE)) {
                SSYNC();
        }
@@ -152,7 +155,7 @@ int kgdb_get_debug_char(void)
                uart = &bfin_serial_ports[0];
        else
                uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-       
+
        while(!(UART_GET_LSR(uart) & DR)) {
                SSYNC();
        }
@@ -298,7 +301,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
        bfin_serial_mctrl_check(uart);
 
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
-               bfin_serial_stop_tx(&uart->port);
+#ifdef CONFIG_BF54x
+               /* Clear TFI bit */
+               UART_PUT_LSR(uart, TFI);
+#endif
+               UART_CLEAR_IER(uart, ETBEI);
                return;
        }
 
@@ -317,9 +324,6 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&uart->port);
-
-       if (uart_circ_empty(xmit))
-               bfin_serial_stop_tx(&uart->port);
 }
 
 static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
@@ -645,6 +649,42 @@ static int bfin_serial_startup(struct uart_port *port)
                free_irq(uart->port.irq, uart);
                return -EBUSY;
        }
+
+# ifdef CONFIG_BF54x
+       {
+               unsigned uart_dma_ch_rx, uart_dma_ch_tx;
+
+               switch (uart->port.irq) {
+               case IRQ_UART3_RX:
+                       uart_dma_ch_rx = CH_UART3_RX;
+                       uart_dma_ch_tx = CH_UART3_TX;
+                       break;
+               case IRQ_UART2_RX:
+                       uart_dma_ch_rx = CH_UART2_RX;
+                       uart_dma_ch_tx = CH_UART2_TX;
+                       break;
+               default:
+                       uart_dma_ch_rx = uart_dma_ch_tx = 0;
+                       break;
+               };
+
+               if (uart_dma_ch_rx &&
+                       request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) {
+                       printk(KERN_NOTICE"Fail to attach UART interrupt\n");
+                       free_irq(uart->port.irq, uart);
+                       free_irq(uart->port.irq + 1, uart);
+                       return -EBUSY;
+               }
+               if (uart_dma_ch_tx &&
+                       request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) {
+                       printk(KERN_NOTICE "Fail to attach UART interrupt\n");
+                       free_dma(uart_dma_ch_rx);
+                       free_irq(uart->port.irq, uart);
+                       free_irq(uart->port.irq + 1, uart);
+                       return -EBUSY;
+               }
+       }
+# endif
 #endif
        UART_SET_IER(uart, ERBFI);
        return 0;
@@ -662,6 +702,20 @@ static void bfin_serial_shutdown(struct uart_port *port)
        del_timer(&(uart->rx_dma_timer));
        dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0);
 #else
+#ifdef CONFIG_BF54x
+       switch (uart->port.irq) {
+       case IRQ_UART3_RX:
+               free_dma(CH_UART3_RX);
+               free_dma(CH_UART3_TX);
+               break;
+       case IRQ_UART2_RX:
+               free_dma(CH_UART2_RX);
+               free_dma(CH_UART2_TX);
+               break;
+       default:
+               break;
+       };
+#endif
 #ifdef CONFIG_KGDB_UART
        if (uart->port.line != CONFIG_KGDB_UART_PORT)
 #endif
@@ -757,6 +811,9 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
        val |= UCEN;
        UART_PUT_GCTL(uart, val);
 
+       /* Port speed changed, update the per-port timeout. */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
        spin_unlock_irqrestore(&uart->port.lock, flags);
 }
 
@@ -859,8 +916,9 @@ static void __init bfin_serial_init_ports(void)
                return;
        first = 0;
 
-       for (i = 0; i < nr_ports; i++) {
+       for (i = 0; i < nr_active_ports; i++) {
                bfin_serial_ports[i].port.uartclk   = get_sclk();
+               bfin_serial_ports[i].port.fifosize  = BFIN_UART_TX_FIFO_SIZE;
                bfin_serial_ports[i].port.ops       = &bfin_serial_pops;
                bfin_serial_ports[i].port.line      = i;
                bfin_serial_ports[i].port.iotype    = UPIO_MEM;
@@ -961,7 +1019,7 @@ bfin_serial_console_setup(struct console *co, char *options)
         * if so, search for the first available port that does have
         * console support.
         */
-       if (co->index == -1 || co->index >= nr_ports)
+       if (co->index == -1 || co->index >= nr_active_ports)
                co->index = 0;
        uart = &bfin_serial_ports[co->index];
 
@@ -1056,7 +1114,7 @@ static __init void early_serial_write(struct console *con, const char *s,
        }
 }
 
-static struct __init console bfin_early_serial_console = {
+static struct __initdata console bfin_early_serial_console = {
        .name = "early_BFuart",
        .write = early_serial_write,
        .device = uart_console_device,
@@ -1072,7 +1130,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port,
        struct bfin_serial_port *uart;
        struct ktermios t;
 
-       if (port == -1 || port >= nr_ports)
+       if (port == -1 || port >= nr_active_ports)
                port = 0;
        bfin_serial_init_ports();
        bfin_early_serial_console.index = port;
@@ -1100,20 +1158,26 @@ static struct uart_driver bfin_serial_reg = {
 
 static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state)
 {
-       struct bfin_serial_port *uart = platform_get_drvdata(dev);
+       int i;
 
-       if (uart)
-               uart_suspend_port(&bfin_serial_reg, &uart->port);
+       for (i = 0; i < nr_active_ports; i++) {
+               if (bfin_serial_ports[i].port.dev != &dev->dev)
+                       continue;
+               uart_suspend_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+       }
 
        return 0;
 }
 
 static int bfin_serial_resume(struct platform_device *dev)
 {
-       struct bfin_serial_port *uart = platform_get_drvdata(dev);
+       int i;
 
-       if (uart)
-               uart_resume_port(&bfin_serial_reg, &uart->port);
+       for (i = 0; i < nr_active_ports; i++) {
+               if (bfin_serial_ports[i].port.dev != &dev->dev)
+                       continue;
+               uart_resume_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+       }
 
        return 0;
 }
@@ -1128,32 +1192,31 @@ static int bfin_serial_probe(struct platform_device *dev)
                        break;
 
        if (i < dev->num_resources) {
-               for (i = 0; i < nr_ports; i++, res++) {
+               for (i = 0; i < nr_active_ports; i++, res++) {
                        if (bfin_serial_ports[i].port.mapbase != res->start)
                                continue;
                        bfin_serial_ports[i].port.dev = &dev->dev;
                        uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
-                       platform_set_drvdata(dev, &bfin_serial_ports[i]);
                }
        }
 
        return 0;
 }
 
-static int bfin_serial_remove(struct platform_device *pdev)
+static int bfin_serial_remove(struct platform_device *dev)
 {
-       struct bfin_serial_port *uart = platform_get_drvdata(pdev);
-
+       int i;
 
+       for (i = 0; i < nr_active_ports; i++) {
+               if (bfin_serial_ports[i].port.dev != &dev->dev)
+                       continue;
+               uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
+               bfin_serial_ports[i].port.dev = NULL;
 #ifdef CONFIG_SERIAL_BFIN_CTSRTS
-       gpio_free(uart->cts_pin);
-       gpio_free(uart->rts_pin);
+               gpio_free(bfin_serial_ports[i].cts_pin);
+               gpio_free(bfin_serial_ports[i].rts_pin);
 #endif
-
-       platform_set_drvdata(pdev, NULL);
-
-       if (uart)
-               uart_remove_one_port(&bfin_serial_reg, &uart->port);
+       }
 
        return 0;
 }
index 25efca5a7a1ffe423b0757f2a89f660390537e20..a6c4d744495e3b694894c35453bbac4a0baff512 100644 (file)
@@ -1333,6 +1333,9 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev,
        if (ret)
                return ret;
 
+       /* initialize the device pointer for the port */
+       pinfo->port.dev = &ofdev->dev;
+
        return uart_add_one_port(&cpm_reg, &pinfo->port);
 }
 
index 0f0aff06c596cf60fc6207c591fd96bda14d370d..1b94c56ec23914a0c7a44acd04ebe61594f39273 100644 (file)
@@ -100,7 +100,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
                mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
                dma_addr = (u32)cpm_dpram_phys(mem_addr);
        } else
-               mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+               mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
                                              GFP_KERNEL);
 
        if (mem_addr == NULL) {
@@ -127,8 +127,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 
 void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
 {
-       dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
-                                              pinfo->rx_fifosize) +
+       dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+                                                         pinfo->rx_fifosize) +
                          L1_CACHE_ALIGN(pinfo->tx_nrfifos *
                                         pinfo->tx_fifosize), pinfo->mem_addr,
                          pinfo->dma_addr);
index b8db4d3eed3686ec758e9a11ad783e83c3e0d7b7..141c0a3333ad3c8ac8140b5c52b5588a21daf6b2 100644 (file)
@@ -136,7 +136,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
                dma_addr = virt_to_bus(mem_addr);
        }
        else
-               mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+               mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
                                              GFP_KERNEL);
 
        if (mem_addr == NULL) {
@@ -163,8 +163,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 
 void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
 {
-       dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
-                                              pinfo->rx_fifosize) +
+       dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+                                                         pinfo->rx_fifosize) +
                          L1_CACHE_ALIGN(pinfo->tx_nrfifos *
                                         pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
                          pinfo->dma_addr);
index bf94a770bb445d4b2d13ed71865f18fb982bfb0e..211c21797ce016ef8646a8c04a32f5affd35ed17 100644 (file)
@@ -457,7 +457,6 @@ static struct e100_serial rs_table[] = {
 #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
 
 static struct ktermios *serial_termios[NR_PORTS];
-static struct ktermios *serial_termios_locked[NR_PORTS];
 #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
 static struct fast_timer fast_timers[NR_PORTS];
 #endif
@@ -4419,6 +4418,7 @@ rs_init(void)
                        rs485_pa_bit)) {
                printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
                        "RS485 pin\n");
+               put_tty_driver(driver);
                return -EBUSY;
        }
 #endif
@@ -4427,6 +4427,7 @@ rs_init(void)
                        rs485_port_g_bit)) {
                printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
                        "RS485 pin\n");
+               put_tty_driver(driver);
                return -EBUSY;
        }
 #endif
@@ -4446,8 +4447,6 @@ rs_init(void)
        driver->init_termios.c_ispeed = 115200;
        driver->init_termios.c_ospeed = 115200;
        driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-       driver->termios = serial_termios;
-       driver->termios_locked = serial_termios_locked;
 
        tty_set_operations(driver, &rs_ops);
         serial_driver = driver;
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
deleted file mode 100644 (file)
index fbe3835..0000000
+++ /dev/null
@@ -1,1965 +0,0 @@
-#warning This driver is deprecated. Check Kconfig for details.
-/*
- * mcfserial.c -- serial driver for ColdFire internal UARTS.
- *
- * Copyright (C) 1999-2003 Greg Ungerer <gerg@snapgear.com>
- * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com> 
- * Copyright (C) 2001-2002 SnapGear Inc. <www.snapgear.com> 
- *
- * Based on code from 68332serial.c which was:
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 TSHG
- * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org>
- *
- * Changes:
- * 08/07/2003    Daniele Bellucci <bellucda@tiscali.it>
- *               some cleanups in mcfrs_write.
- *
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/delay.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/nettel.h>
-#include <asm/uaccess.h>
-#include "mcfserial.h"
-
-struct timer_list mcfrs_timer_struct;
-
-/*
- *     Default console baud rate,  we use this as the default
- *     for all ports so init can just open /dev/console and
- *     keep going.  Perhaps one day the cflag settings for the
- *     console can be used instead.
- */
-#if defined(CONFIG_HW_FEITH)
-#define        CONSOLE_BAUD_RATE       38400
-#define        DEFAULT_CBAUD           B38400
-#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \
-      defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO)
-#define CONSOLE_BAUD_RATE      115200
-#define DEFAULT_CBAUD          B115200
-#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
-      defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET)
-#define        CONSOLE_BAUD_RATE       19200
-#define        DEFAULT_CBAUD           B19200
-#endif
-
-#ifndef CONSOLE_BAUD_RATE
-#define        CONSOLE_BAUD_RATE       9600
-#define        DEFAULT_CBAUD           B9600
-#endif
-
-int mcfrs_console_inited = 0;
-int mcfrs_console_port = -1;
-int mcfrs_console_baud = CONSOLE_BAUD_RATE;
-int mcfrs_console_cbaud = DEFAULT_CBAUD;
-
-/*
- *     Driver data structures.
- */
-static struct tty_driver *mcfrs_serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* Debugging...
- */
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x)
-#define        IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
-#else
-#define        IRQBASE 73
-#endif
-
-/*
- *     Configuration table, UARTs to look for at startup.
- */
-static struct mcf_serial mcfrs_table[] = {
-       {  /* ttyS0 */
-               .magic = 0,
-               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE1),
-               .irq = IRQBASE,
-               .flags = ASYNC_BOOT_AUTOCONF,
-       },
-#ifdef MCFUART_BASE2
-       {  /* ttyS1 */
-               .magic = 0,
-               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2),
-               .irq = IRQBASE+1,
-               .flags = ASYNC_BOOT_AUTOCONF,
-       },
-#endif
-#ifdef MCFUART_BASE3
-       {  /* ttyS2 */
-               .magic = 0,
-               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3),
-               .irq = IRQBASE+2,
-               .flags = ASYNC_BOOT_AUTOCONF,
-       },
-#endif
-#ifdef MCFUART_BASE4
-       {  /* ttyS3 */
-               .magic = 0,
-               .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4),
-               .irq = IRQBASE+3,
-               .flags = ASYNC_BOOT_AUTOCONF,
-       },
-#endif
-};
-
-
-#define        NR_PORTS        (sizeof(mcfrs_table) / sizeof(struct mcf_serial))
-
-/*
- * This is used to figure out the divisor speeds and the timeouts.
- */
-static int mcfrs_baud_table[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 230400, 460800, 0
-};
-#define MCFRS_BAUD_TABLE_SIZE \
-                       (sizeof(mcfrs_baud_table)/sizeof(mcfrs_baud_table[0]))
-
-
-#ifdef CONFIG_MAGIC_SYSRQ
-/*
- *     Magic system request keys. Used for debugging...
- */
-extern int     magic_sysrq_key(int ch);
-#endif
-
-
-/*
- *     Forware declarations...
- */
-static void    mcfrs_change_speed(struct mcf_serial *info);
-static void    mcfrs_wait_until_sent(struct tty_struct *tty, int timeout);
-
-
-static inline int serial_paranoia_check(struct mcf_serial *info,
-                                       char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-       static const char badmagic[] =
-               "MCFRS(warning): bad magic number for serial struct %s in %s\n";
-       static const char badinfo[] =
-               "MCFRS(warning): null mcf_serial for %s in %s\n";
-
-       if (!info) {
-               printk(badinfo, name, routine);
-               return 1;
-       }
-       if (info->magic != SERIAL_MAGIC) {
-               printk(badmagic, name, routine);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-/*
- *     Sets or clears DTR and RTS on the requested line.
- */
-static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-       
-#if 0
-       printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n",
-               __FILE__, __LINE__, info, dtr, rts);
-#endif
-
-       local_irq_save(flags);
-       if (dtr >= 0) {
-#ifdef MCFPP_DTR0
-               if (info->line)
-                       mcf_setppdata(MCFPP_DTR1, (dtr ? 0 : MCFPP_DTR1));
-               else
-                       mcf_setppdata(MCFPP_DTR0, (dtr ? 0 : MCFPP_DTR0));
-#endif
-       }
-       if (rts >= 0) {
-               uartp = info->addr;
-               if (rts) {
-                       info->sigs |= TIOCM_RTS;
-                       uartp[MCFUART_UOP1] = MCFUART_UOP_RTS;
-               } else {
-                       info->sigs &= ~TIOCM_RTS;
-                       uartp[MCFUART_UOP0] = MCFUART_UOP_RTS;
-               }
-       }
-       local_irq_restore(flags);
-       return;
-}
-
-/*
- *     Gets values of serial signals.
- */
-static int mcfrs_getsignals(struct mcf_serial *info)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-       int                     sigs;
-#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
-       unsigned short          ppdata;
-#endif
-
-#if 0
-       printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__);
-#endif
-
-       local_irq_save(flags);
-       uartp = info->addr;
-       sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS;
-       sigs |= (info->sigs & TIOCM_RTS);
-
-#ifdef MCFPP_DCD0
-{
-       unsigned int ppdata;
-       ppdata = mcf_getppdata();
-       if (info->line == 0) {
-               sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD;
-               sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR;
-       } else if (info->line == 1) {
-               sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD;
-               sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR;
-       }
-}
-#endif
-
-       local_irq_restore(flags);
-       return(sigs);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_stop() and mcfrs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void mcfrs_stop(struct tty_struct *tty)
-{
-       volatile unsigned char  *uartp;
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_stop"))
-               return;
-       
-       local_irq_save(flags);
-       uartp = info->addr;
-       info->imr &= ~MCFUART_UIR_TXREADY;
-       uartp[MCFUART_UIMR] = info->imr;
-       local_irq_restore(flags);
-}
-
-static void mcfrs_start(struct tty_struct *tty)
-{
-       volatile unsigned char  *uartp;
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-       
-       if (serial_paranoia_check(info, tty->name, "mcfrs_start"))
-               return;
-
-       local_irq_save(flags);
-       if (info->xmit_cnt && info->xmit_buf) {
-               uartp = info->addr;
-               info->imr |= MCFUART_UIR_TXREADY;
-               uartp[MCFUART_UIMR] = info->imr;
-       }
-       local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * mcfrs_interrupt().  They were separated out for readability's sake.
- *
- * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * mcfrs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- * 
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- *                             - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-static inline void receive_chars(struct mcf_serial *info)
-{
-       volatile unsigned char  *uartp;
-       struct tty_struct       *tty = info->port.tty;
-       unsigned char           status, ch, flag;
-
-       if (!tty)
-               return;
-
-       uartp = info->addr;
-
-       while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
-               ch = uartp[MCFUART_URB];
-               info->stats.rx++;
-
-#ifdef CONFIG_MAGIC_SYSRQ
-               if (mcfrs_console_inited && (info->line == mcfrs_console_port)) {
-                       if (magic_sysrq_key(ch))
-                               continue;
-               }
-#endif
-
-               flag = TTY_NORMAL;
-               if (status & MCFUART_USR_RXERR) {
-                       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
-                       if (status & MCFUART_USR_RXBREAK) {
-                               info->stats.rxbreak++;
-                               flag = TTY_BREAK;
-                       } else if (status & MCFUART_USR_RXPARITY) {
-                               info->stats.rxparity++;
-                               flag = TTY_PARITY;
-                       } else if (status & MCFUART_USR_RXOVERRUN) {
-                               info->stats.rxoverrun++;
-                               flag = TTY_OVERRUN;
-                       } else if (status & MCFUART_USR_RXFRAMING) {
-                               info->stats.rxframing++;
-                               flag = TTY_FRAME;
-                       }
-               }
-               tty_insert_flip_char(tty, ch, flag);
-       }
-       tty_schedule_flip(tty);
-       return;
-}
-
-static inline void transmit_chars(struct mcf_serial *info)
-{
-       volatile unsigned char  *uartp;
-
-       uartp = info->addr;
-
-       if (info->x_char) {
-               /* Send special char - probably flow control */
-               uartp[MCFUART_UTB] = info->x_char;
-               info->x_char = 0;
-               info->stats.tx++;
-       }
-
-       if ((info->xmit_cnt <= 0) || info->port.tty->stopped) {
-               info->imr &= ~MCFUART_UIR_TXREADY;
-               uartp[MCFUART_UIMR] = info->imr;
-               return;
-       }
-
-       while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) {
-               uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
-               info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-               info->stats.tx++;
-               if (--info->xmit_cnt <= 0)
-                       break;
-       }
-
-       if (info->xmit_cnt < WAKEUP_CHARS)
-               schedule_work(&info->tqueue);
-       return;
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-irqreturn_t mcfrs_interrupt(int irq, void *dev_id)
-{
-       struct mcf_serial       *info;
-       unsigned char           isr;
-
-       info = &mcfrs_table[(irq - IRQBASE)];
-       isr = info->addr[MCFUART_UISR] & info->imr;
-
-       if (isr & MCFUART_UIR_RXREADY)
-               receive_chars(info);
-       if (isr & MCFUART_UIR_TXREADY)
-               transmit_chars(info);
-       return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-static void mcfrs_offintr(struct work_struct *work)
-{
-       struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue);
-       struct tty_struct *tty = info->port.tty;
-       
-       if (tty)
-               tty_wakeup(tty);
-}
-
-
-/*
- *     Change of state on a DCD line.
- */
-void mcfrs_modem_change(struct mcf_serial *info, int dcd)
-{
-       if (info->count == 0)
-               return;
-
-       if (info->flags & ASYNC_CHECK_CD) {
-               if (dcd)
-                       wake_up_interruptible(&info->open_wait);
-               else 
-                       schedule_work(&info->tqueue_hangup);
-       }
-}
-
-
-#ifdef MCFPP_DCD0
-
-unsigned short mcfrs_ppstatus;
-
-/*
- * This subroutine is called when the RS_TIMER goes off. It is used
- * to monitor the state of the DCD lines - since they have no edge
- * sensors and interrupt generators.
- */
-static void mcfrs_timer(void)
-{
-       unsigned int    ppstatus, dcdval, i;
-
-       ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1);
-
-       if (ppstatus != mcfrs_ppstatus) {
-               for (i = 0; (i < 2); i++) {
-                       dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0);
-                       if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) {
-                               mcfrs_modem_change(&mcfrs_table[i],
-                                       ((ppstatus & dcdval) ? 0 : 1));
-                       }
-               }
-       }
-       mcfrs_ppstatus = ppstatus;
-
-       /* Re-arm timer */
-       mcfrs_timer_struct.expires = jiffies + HZ/25;
-       add_timer(&mcfrs_timer_struct);
-}
-
-#endif /* MCFPP_DCD0 */
-
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred. The path of
- * hangup processing is:
- *
- *     serial interrupt routine -> (scheduler tqueue) ->
- *     do_serial_hangup() -> tty->hangup() -> mcfrs_hangup()
- * 
- */
-static void do_serial_hangup(struct work_struct *work)
-{
-       struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup);
-       struct tty_struct *tty = info->port.tty;
-       
-       if (tty)
-               tty_hangup(tty);
-}
-
-static int startup(struct mcf_serial * info)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-       
-       if (info->flags & ASYNC_INITIALIZED)
-               return 0;
-
-       if (!info->xmit_buf) {
-               info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL);
-               if (!info->xmit_buf)
-                       return -ENOMEM;
-       }
-
-       local_irq_save(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-       printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
-
-       /*
-        *      Reset UART, get it into known state...
-        */
-       uartp = info->addr;
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
-       mcfrs_setsignals(info, 1, 1);
-
-       if (info->port.tty)
-               clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-       /*
-        * and set the speed of the serial port
-        */
-       mcfrs_change_speed(info);
-
-       /*
-        * Lastly enable the UART transmitter and receiver, and
-        * interrupt enables.
-        */
-       info->imr = MCFUART_UIR_RXREADY;
-       uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
-       uartp[MCFUART_UIMR] = info->imr;
-
-       info->flags |= ASYNC_INITIALIZED;
-       local_irq_restore(flags);
-       return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct mcf_serial * info)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-
-       if (!(info->flags & ASYNC_INITIALIZED))
-               return;
-
-#ifdef SERIAL_DEBUG_OPEN
-       printk("Shutting down serial port %d (irq %d)....\n", info->line,
-              info->irq);
-#endif
-       
-       local_irq_save(flags);
-
-       uartp = info->addr;
-       uartp[MCFUART_UIMR] = 0;  /* mask all interrupts */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
-
-       if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
-               mcfrs_setsignals(info, 0, 0);
-
-       if (info->xmit_buf) {
-               free_page((unsigned long) info->xmit_buf);
-               info->xmit_buf = 0;
-       }
-
-       if (info->port.tty)
-               set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-       
-       info->flags &= ~ASYNC_INITIALIZED;
-       local_irq_restore(flags);
-}
-
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void mcfrs_change_speed(struct mcf_serial *info)
-{
-       volatile unsigned char  *uartp;
-       unsigned int            baudclk, cflag;
-       unsigned long           flags;
-       unsigned char           mr1, mr2;
-       int                     i;
-#ifdef CONFIG_M5272
-       unsigned int            fraction;
-#endif
-
-       if (!info->port.tty || !info->port.tty->termios)
-               return;
-       cflag = info->port.tty->termios->c_cflag;
-       if (info->addr == 0)
-               return;
-
-#if 0
-       printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__);
-#endif
-
-       i = cflag & CBAUD;
-       if (i & CBAUDEX) {
-               i &= ~CBAUDEX;
-               if (i < 1 || i > 4)
-                       info->port.tty->termios->c_cflag &= ~CBAUDEX;
-               else
-                       i += 15;
-       }
-       if (i == 0) {
-               mcfrs_setsignals(info, 0, -1);
-               return;
-       }
-
-       /* compute the baudrate clock */
-#ifdef CONFIG_M5272
-       /*
-        * For the MCF5272, also compute the baudrate fraction.
-        */
-       baudclk = (MCF_BUSCLK / mcfrs_baud_table[i]) / 32;
-       fraction = MCF_BUSCLK - (baudclk * 32 * mcfrs_baud_table[i]);
-       fraction *= 16;
-       fraction /= (32 * mcfrs_baud_table[i]);
-#else
-       baudclk = ((MCF_BUSCLK / mcfrs_baud_table[i]) + 16) / 32;
-#endif
-
-       info->baud = mcfrs_baud_table[i];
-
-       mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
-       mr2 = 0;
-
-       switch (cflag & CSIZE) {
-       case CS5:       mr1 |= MCFUART_MR1_CS5; break;
-       case CS6:       mr1 |= MCFUART_MR1_CS6; break;
-       case CS7:       mr1 |= MCFUART_MR1_CS7; break;
-       case CS8:
-       default:        mr1 |= MCFUART_MR1_CS8; break;
-       }
-
-       if (cflag & PARENB) {
-               if (cflag & CMSPAR) {
-                       if (cflag & PARODD)
-                               mr1 |= MCFUART_MR1_PARITYMARK;
-                       else
-                               mr1 |= MCFUART_MR1_PARITYSPACE;
-               } else {
-                       if (cflag & PARODD)
-                               mr1 |= MCFUART_MR1_PARITYODD;
-                       else
-                               mr1 |= MCFUART_MR1_PARITYEVEN;
-               }
-       } else {
-               mr1 |= MCFUART_MR1_PARITYNONE;
-       }
-
-       if (cflag & CSTOPB)
-               mr2 |= MCFUART_MR2_STOP2;
-       else
-               mr2 |= MCFUART_MR2_STOP1;
-
-       if (cflag & CRTSCTS) {
-               mr1 |= MCFUART_MR1_RXRTS;
-               mr2 |= MCFUART_MR2_TXCTS;
-       }
-
-       if (cflag & CLOCAL)
-               info->flags &= ~ASYNC_CHECK_CD;
-       else
-               info->flags |= ASYNC_CHECK_CD;
-
-       uartp = info->addr;
-
-       local_irq_save(flags);
-#if 0
-       printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__,
-               mr1, mr2, baudclk);
-#endif
-       /*
-         Note: pg 12-16 of MCF5206e User's Manual states that a
-         software reset should be performed prior to changing
-         UMR1,2, UCSR, UACR, bit 7
-       */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;    /* reset RX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;    /* reset TX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
-       uartp[MCFUART_UMR] = mr1;
-       uartp[MCFUART_UMR] = mr2;
-       uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8;  /* set msb byte */
-       uartp[MCFUART_UBG2] = (baudclk & 0xff);         /* set lsb byte */
-#ifdef CONFIG_M5272
-       uartp[MCFUART_UFPD] = (fraction & 0xf);         /* set fraction */
-#endif
-       uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
-       uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
-       mcfrs_setsignals(info, 1, -1);
-       local_irq_restore(flags);
-       return;
-}
-
-static void mcfrs_flush_chars(struct tty_struct *tty)
-{
-       volatile unsigned char  *uartp;
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_flush_chars"))
-               return;
-
-       uartp = (volatile unsigned char *) info->addr;
-
-       /*
-        * re-enable receiver interrupt
-        */
-       local_irq_save(flags);
-       if ((!(info->imr & MCFUART_UIR_RXREADY)) &&
-           (info->flags & ASYNC_INITIALIZED) ) {
-               info->imr |= MCFUART_UIR_RXREADY;
-               uartp[MCFUART_UIMR] = info->imr;
-       }
-       local_irq_restore(flags);
-
-       if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-           !info->xmit_buf)
-               return;
-
-       /* Enable transmitter */
-       local_irq_save(flags);
-       info->imr |= MCFUART_UIR_TXREADY;
-       uartp[MCFUART_UIMR] = info->imr;
-       local_irq_restore(flags);
-}
-
-static int mcfrs_write(struct tty_struct * tty,
-                   const unsigned char *buf, int count)
-{
-       volatile unsigned char  *uartp;
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-       int                     c, total = 0;
-
-#if 0
-       printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n",
-               __FILE__, __LINE__, (int)tty, (int)buf, count);
-#endif
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_write"))
-               return 0;
-
-       if (!tty || !info->xmit_buf)
-               return 0;
-       
-       local_save_flags(flags);
-       while (1) {
-               local_irq_disable();            
-               c = min(count, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1,
-                       ((int)SERIAL_XMIT_SIZE) - info->xmit_head));
-               local_irq_restore(flags);
-
-               if (c <= 0)
-                       break;
-
-               memcpy(info->xmit_buf + info->xmit_head, buf, c);
-
-               local_irq_disable();
-               info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-               info->xmit_cnt += c;
-               local_irq_restore(flags);
-
-               buf += c;
-               count -= c;
-               total += c;
-       }
-
-       local_irq_disable();
-       uartp = info->addr;
-       info->imr |= MCFUART_UIR_TXREADY;
-       uartp[MCFUART_UIMR] = info->imr;
-       local_irq_restore(flags);
-
-       return total;
-}
-
-static int mcfrs_write_room(struct tty_struct *tty)
-{
-       struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-       int     ret;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_write_room"))
-               return 0;
-       ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-       if (ret < 0)
-               ret = 0;
-       return ret;
-}
-
-static int mcfrs_chars_in_buffer(struct tty_struct *tty)
-{
-       struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_chars_in_buffer"))
-               return 0;
-       return info->xmit_cnt;
-}
-
-static void mcfrs_flush_buffer(struct tty_struct *tty)
-{
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_flush_buffer"))
-               return;
-
-       local_irq_save(flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       local_irq_restore(flags);
-
-       tty_wakeup(tty);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_throttle()
- * 
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void mcfrs_throttle(struct tty_struct * tty)
-{
-       struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-       char    buf[64];
-       
-       printk("throttle %s: %d....\n", tty_name(tty, buf),
-              tty->ldisc.chars_in_buffer(tty));
-#endif
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_throttle"))
-               return;
-       
-       if (I_IXOFF(tty))
-               info->x_char = STOP_CHAR(tty);
-
-       /* Turn off RTS line (do this atomic) */
-}
-
-static void mcfrs_unthrottle(struct tty_struct * tty)
-{
-       struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-       char    buf[64];
-       
-       printk("unthrottle %s: %d....\n", tty_name(tty, buf),
-              tty->ldisc.chars_in_buffer(tty));
-#endif
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_unthrottle"))
-               return;
-       
-       if (I_IXOFF(tty)) {
-               if (info->x_char)
-                       info->x_char = 0;
-               else
-                       info->x_char = START_CHAR(tty);
-       }
-
-       /* Assert RTS line (do this atomic) */
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct mcf_serial * info,
-                          struct serial_struct * retinfo)
-{
-       struct serial_struct tmp;
-  
-       if (!retinfo)
-               return -EFAULT;
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.type = info->type;
-       tmp.line = info->line;
-       tmp.port = (unsigned int) info->addr;
-       tmp.irq = info->irq;
-       tmp.flags = info->flags;
-       tmp.baud_base = info->baud_base;
-       tmp.close_delay = info->close_delay;
-       tmp.closing_wait = info->closing_wait;
-       tmp.custom_divisor = info->custom_divisor;
-       return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-static int set_serial_info(struct mcf_serial * info,
-                          struct serial_struct * new_info)
-{
-       struct serial_struct new_serial;
-       struct mcf_serial old_info;
-       int     retval = 0;
-
-       if (!new_info)
-               return -EFAULT;
-       if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-               return -EFAULT;
-       old_info = *info;
-
-       if (!capable(CAP_SYS_ADMIN)) {
-               if ((new_serial.baud_base != info->baud_base) ||
-                   (new_serial.type != info->type) ||
-                   (new_serial.close_delay != info->close_delay) ||
-                   ((new_serial.flags & ~ASYNC_USR_MASK) !=
-                    (info->flags & ~ASYNC_USR_MASK)))
-                       return -EPERM;
-               info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-                              (new_serial.flags & ASYNC_USR_MASK));
-               info->custom_divisor = new_serial.custom_divisor;
-               goto check_and_exit;
-       }
-
-       if (info->count > 1)
-               return -EBUSY;
-
-       /*
-        * OK, past this point, all the error checking has been done.
-        * At this point, we start making changes.....
-        */
-
-       info->baud_base = new_serial.baud_base;
-       info->flags = ((info->flags & ~ASYNC_FLAGS) |
-                       (new_serial.flags & ASYNC_FLAGS));
-       info->type = new_serial.type;
-       info->close_delay = new_serial.close_delay;
-       info->closing_wait = new_serial.closing_wait;
-
-check_and_exit:
-       retval = startup(info);
-       return retval;
-}
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *         is emptied.  On bus types like RS485, the transmitter must
- *         release the bus after transmitting. This must be done when
- *         the transmit shift register is empty, not be done when the
- *         transmit holding register is empty.  This functionality
- *         allows an RS485 driver to be written in user space. 
- */
-static int get_lsr_info(struct mcf_serial * info, unsigned int *value)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-       unsigned char           status;
-
-       local_irq_save(flags);
-       uartp = info->addr;
-       status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0;
-       local_irq_restore(flags);
-
-       return put_user(status,value);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(        struct mcf_serial * info, int duration)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-
-       if (!info->addr)
-               return;
-       set_current_state(TASK_INTERRUPTIBLE);
-       uartp = info->addr;
-
-       local_irq_save(flags);
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART;
-       schedule_timeout(duration);
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP;
-       local_irq_restore(flags);
-}
-
-static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file)
-{
-       struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       return mcfrs_getsignals(info);
-}
-
-static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file,
-                         unsigned int set, unsigned int clear)
-{
-       struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-       int rts = -1, dtr = -1;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       if (set & TIOCM_RTS)
-               rts = 1;
-       if (set & TIOCM_DTR)
-               dtr = 1;
-       if (clear & TIOCM_RTS)
-               rts = 0;
-       if (clear & TIOCM_DTR)
-               dtr = 0;
-
-       mcfrs_setsignals(info, dtr, rts);
-
-       return 0;
-}
-
-static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
-                   unsigned int cmd, unsigned long arg)
-{
-       struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-       int retval, error;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl"))
-               return -ENODEV;
-
-       if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-           (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
-           (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
-               if (tty->flags & (1 << TTY_IO_ERROR))
-                   return -EIO;
-       }
-       
-       switch (cmd) {
-               case TCSBRK:    /* SVID version: non-zero arg --> no break */
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       if (!arg)
-                               send_break(info, HZ/4); /* 1/4 second */
-                       return 0;
-               case TCSBRKP:   /* support for POSIX tcsendbreak() */
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       send_break(info, arg ? arg*(HZ/10) : HZ/4);
-                       return 0;
-               case TIOCGSERIAL:
-                       if (access_ok(VERIFY_WRITE, (void *) arg,
-                                               sizeof(struct serial_struct)))
-                               return get_serial_info(info,
-                                              (struct serial_struct *) arg);
-                       return -EFAULT;
-               case TIOCSSERIAL:
-                       return set_serial_info(info,
-                                              (struct serial_struct *) arg);
-               case TIOCSERGETLSR: /* Get line status register */
-                       if (access_ok(VERIFY_WRITE, (void *) arg,
-                                               sizeof(unsigned int)))
-                               return get_lsr_info(info, (unsigned int *) arg);
-                       return -EFAULT;
-               case TIOCSERGSTRUCT:
-                       error = copy_to_user((struct mcf_serial *) arg,
-                                   info, sizeof(struct mcf_serial));
-                       if (error)
-                               return -EFAULT;
-                       return 0;
-                       
-#ifdef TIOCSET422
-               case TIOCSET422: {
-                       unsigned int val;
-                       get_user(val, (unsigned int *) arg);
-                       mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11));
-                       break;
-               }
-               case TIOCGET422: {
-                       unsigned int val;
-                       val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1;
-                       put_user(val, (unsigned int *) arg);
-                       break;
-               }
-#endif
-
-               default:
-                       return -ENOIOCTLCMD;
-               }
-       return 0;
-}
-
-static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-       struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
-
-       if (tty->termios->c_cflag == old_termios->c_cflag)
-               return;
-
-       mcfrs_change_speed(info);
-
-       if ((old_termios->c_cflag & CRTSCTS) &&
-           !(tty->termios->c_cflag & CRTSCTS)) {
-               tty->hw_stopped = 0;
-               mcfrs_setsignals(info, -1, 1);
-#if 0
-               mcfrs_start(tty);
-#endif
-       }
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_close()
- * 
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * S structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void mcfrs_close(struct tty_struct *tty, struct file * filp)
-{
-       volatile unsigned char  *uartp;
-       struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
-       unsigned long           flags;
-
-       if (!info || serial_paranoia_check(info, tty->name, "mcfrs_close"))
-               return;
-       
-       local_irq_save(flags);
-       
-       if (tty_hung_up_p(filp)) {
-               local_irq_restore(flags);
-               return;
-       }
-       
-#ifdef SERIAL_DEBUG_OPEN
-       printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count);
-#endif
-       if ((tty->count == 1) && (info->count != 1)) {
-               /*
-                * Uh, oh.  tty->count is 1, which means that the tty
-                * structure will be freed.  Info->count should always
-                * be one in these conditions.  If it's greater than
-                * one, we've got real problems, since it means the
-                * serial port won't be shutdown.
-                */
-               printk("MCFRS: bad serial port count; tty->count is 1, "
-                      "info->count is %d\n", info->count);
-               info->count = 1;
-       }
-       if (--info->count < 0) {
-               printk("MCFRS: bad serial port count for ttyS%d: %d\n",
-                      info->line, info->count);
-               info->count = 0;
-       }
-       if (info->count) {
-               local_irq_restore(flags);
-               return;
-       }
-       info->flags |= ASYNC_CLOSING;
-
-       /*
-        * Now we wait for the transmit buffer to clear; and we notify 
-        * the line discipline to only process XON/XOFF characters.
-        */
-       tty->closing = 1;
-       if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, info->closing_wait);
-
-       /*
-        * At this point we stop accepting input.  To do this, we
-        * disable the receive line status interrupts, and tell the
-        * interrupt driver to stop checking the data ready bit in the
-        * line status register.
-        */
-       info->imr &= ~MCFUART_UIR_RXREADY;
-       uartp = info->addr;
-       uartp[MCFUART_UIMR] = info->imr;
-
-#if 0
-       /* FIXME: do we need to keep this enabled for console?? */
-       if (mcfrs_console_inited && (mcfrs_console_port == info->line)) {
-               /* Do not disable the UART */ ;
-       } else
-#endif
-       shutdown(info);
-       mcfrs_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-       
-       tty->closing = 0;
-       info->event = 0;
-       info->port.tty = NULL;
-#if 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);
-       }
-#endif 
-       if (info->blocked_open) {
-               if (info->close_delay) {
-                       msleep_interruptible(jiffies_to_msecs(info->close_delay));
-               }
-               wake_up_interruptible(&info->open_wait);
-       }
-       info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-       wake_up_interruptible(&info->close_wait);
-       local_irq_restore(flags);
-}
-
-/*
- * mcfrs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void
-mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-#ifdef CONFIG_M5272
-#define        MCF5272_FIFO_SIZE       25              /* fifo size + shift reg */
-
-       struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-       volatile unsigned char *uartp;
-       unsigned long orig_jiffies, fifo_time, char_time, fifo_cnt;
-
-       if (serial_paranoia_check(info, tty->name, "mcfrs_wait_until_sent"))
-               return;
-
-       orig_jiffies = jiffies;
-
-       /*
-        * Set the check interval to be 1/5 of the approximate time
-        * to send the entire fifo, and make it at least 1.  The check
-        * interval should also be less than the timeout.
-        *
-        * Note: we have to use pretty tight timings here to satisfy
-        * the NIST-PCTS.
-        */
-       lock_kernel();
-
-       fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud;
-       char_time = fifo_time / 5;
-       if (char_time == 0)
-               char_time = 1;
-       if (timeout && timeout < char_time)
-               char_time = timeout;
-
-       /*
-        * Clamp the timeout period at 2 * the time to empty the
-        * fifo.  Just to be safe, set the minimum at .5 seconds.
-        */
-       fifo_time *= 2;
-       if (fifo_time < (HZ/2))
-               fifo_time = HZ/2;
-       if (!timeout || timeout > fifo_time)
-               timeout = fifo_time;
-
-       /*
-        * Account for the number of bytes in the UART
-        * transmitter FIFO plus any byte being shifted out.
-        */
-       uartp = (volatile unsigned char *) info->addr;
-       for (;;) {
-               fifo_cnt = (uartp[MCFUART_UTF] & MCFUART_UTF_TXB);
-               if ((uartp[MCFUART_USR] & (MCFUART_USR_TXREADY|
-                               MCFUART_USR_TXEMPTY)) ==
-                       MCFUART_USR_TXREADY)
-                       fifo_cnt++;
-               if (fifo_cnt == 0)
-                       break;
-               msleep_interruptible(jiffies_to_msecs(char_time));
-               if (signal_pending(current))
-                       break;
-               if (timeout && time_after(jiffies, orig_jiffies + timeout))
-                       break;
-       }
-       unlock_kernel();
-#else
-       /*
-        * For the other coldfire models, assume all data has been sent
-        */
-#endif
-}
-
-/*
- * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void mcfrs_hangup(struct tty_struct *tty)
-{
-       struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
-       
-       if (serial_paranoia_check(info, tty->name, "mcfrs_hangup"))
-               return;
-       
-       mcfrs_flush_buffer(tty);
-       shutdown(info);
-       info->event = 0;
-       info->count = 0;
-       info->flags &= ~ASYNC_NORMAL_ACTIVE;
-       info->port.tty = NULL;
-       wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * mcfrs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-                          struct mcf_serial *info)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       int     retval;
-       int     do_clocal = 0;
-
-       /*
-        * If the device is in the middle of being closed, then block
-        * until it's done, and then try again.
-        */
-       if (info->flags & ASYNC_CLOSING) {
-               interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-               if (info->flags & ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               else
-                       return -ERESTARTSYS;
-#else
-               return -EAGAIN;
-#endif
-       }
-       
-       /*
-        * If non-blocking mode is set, or the port is not enabled,
-        * then make the check up front and then exit.
-        */
-       if ((filp->f_flags & O_NONBLOCK) ||
-           (tty->flags & (1 << TTY_IO_ERROR))) {
-               info->flags |= ASYNC_NORMAL_ACTIVE;
-               return 0;
-       }
-
-       if (tty->termios->c_cflag & CLOCAL)
-               do_clocal = 1;
-
-       /*
-        * Block waiting for the carrier detect and the line to become
-        * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->count is dropped by one, so that
-        * mcfrs_close() knows when to free things.  We restore it upon
-        * exit, either normal or abnormal.
-        */
-       retval = 0;
-       add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-       printk("block_til_ready before block: ttyS%d, count = %d\n",
-              info->line, info->count);
-#endif
-       info->count--;
-       info->blocked_open++;
-       while (1) {
-               local_irq_disable();
-               mcfrs_setsignals(info, 1, 1);
-               local_irq_enable();
-               current->state = TASK_INTERRUPTIBLE;
-               if (tty_hung_up_p(filp) ||
-                   !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-                       if (info->flags & ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;  
-#else
-                       retval = -EAGAIN;
-#endif
-                       break;
-               }
-               if (!(info->flags & ASYNC_CLOSING) &&
-                   (do_clocal || (mcfrs_getsignals(info) & TIOCM_CD)))
-                       break;
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-#ifdef SERIAL_DEBUG_OPEN
-               printk("block_til_ready blocking: ttyS%d, count = %d\n",
-                      info->line, info->count);
-#endif
-               schedule();
-       }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&info->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
-               info->count++;
-       info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-       printk("block_til_ready after blocking: ttyS%d, count = %d\n",
-              info->line, info->count);
-#endif
-       if (retval)
-               return retval;
-       info->flags |= ASYNC_NORMAL_ACTIVE;
-       return 0;
-}      
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-int mcfrs_open(struct tty_struct *tty, struct file * filp)
-{
-       struct mcf_serial       *info;
-       int                     retval, line;
-
-       line = tty->index;
-       if ((line < 0) || (line >= NR_PORTS))
-               return -ENODEV;
-       info = mcfrs_table + line;
-       if (serial_paranoia_check(info, tty->name, "mcfrs_open"))
-               return -ENODEV;
-#ifdef SERIAL_DEBUG_OPEN
-       printk("mcfrs_open %s, count = %d\n", tty->name, info->count);
-#endif
-       info->count++;
-       tty->driver_data = info;
-       info->port.tty = tty;
-
-       /*
-        * Start up serial port
-        */
-       retval = startup(info);
-       if (retval)
-               return retval;
-
-       retval = block_til_ready(tty, filp, info);
-       if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-               printk("mcfrs_open returning after block_til_ready with %d\n",
-                      retval);
-#endif
-               return retval;
-       }
-
-#ifdef SERIAL_DEBUG_OPEN
-       printk("mcfrs_open %s successful...\n", tty->name);
-#endif
-       return 0;
-}
-
-/*
- *     Based on the line number set up the internal interrupt stuff.
- */
-static void mcfrs_irqinit(struct mcf_serial *info)
-{
-#if defined(CONFIG_M5272)
-       volatile unsigned long  *icrp;
-       volatile unsigned long  *portp;
-       volatile unsigned char  *uartp;
-
-       uartp = info->addr;
-       icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2);
-
-       switch (info->line) {
-       case 0:
-               *icrp = 0xe0000000;
-               break;
-       case 1:
-               *icrp = 0x0e000000;
-               break;
-       default:
-               printk("MCFRS: don't know how to handle UART %d interrupt?\n",
-                       info->line);
-               return;
-       }
-
-       /* Enable the output lines for the serial ports */
-       portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PBCNT);
-       *portp = (*portp & ~0x000000ff) | 0x00000055;
-       portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
-       *portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-       volatile unsigned char *icrp, *uartp;
-       volatile unsigned long *imrp;
-
-       uartp = info->addr;
-
-       icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
-               MCFINTC_ICR0 + MCFINT_UART0 + info->line);
-       *icrp = 0x30 + info->line; /* level 6, line based priority */
-
-       imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
-               MCFINTC_IMRL);
-       *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
-#if defined(CONFIG_M527x)
-       {
-               /*
-                * External Pin Mask Setting & Enable External Pin for Interface
-                * mrcbis@aliceposta.it
-                */
-               u16 *serpin_enable_mask;
-               serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART);
-               if (info->line == 0)
-                       *serpin_enable_mask |= UART0_ENABLE_MASK;
-               else if (info->line == 1)
-                       *serpin_enable_mask |= UART1_ENABLE_MASK;
-               else if (info->line == 2)
-                       *serpin_enable_mask |= UART2_ENABLE_MASK;
-       }
-#endif
-#if defined(CONFIG_M528x)
-       /* make sure PUAPAR is set for UART0 and UART1 */
-       if (info->line < 2) {
-               volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR);
-               *portp |= (0x03 << (info->line * 2));
-       }
-#endif
-#elif defined(CONFIG_M520x)
-       volatile unsigned char *icrp, *uartp;
-       volatile unsigned long *imrp;
-
-       uartp = info->addr;
-
-       icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
-               MCFINTC_ICR0 + MCFINT_UART0 + info->line);
-       *icrp = 0x03;
-
-       imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
-               MCFINTC_IMRL);
-       *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
-       if (info->line < 2) {
-               unsigned short *uart_par;
-               uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART);
-               if (info->line == 0)
-                       *uart_par |=  MCF_GPIO_PAR_UART_PAR_UTXD0
-                                 | MCF_GPIO_PAR_UART_PAR_URXD0;
-               else if (info->line == 1)
-                       *uart_par |=  MCF_GPIO_PAR_UART_PAR_UTXD1
-                                 | MCF_GPIO_PAR_UART_PAR_URXD1;
-               } else if (info->line == 2) {
-                       unsigned char *feci2c_par;
-                       feci2c_par = (unsigned char *)(MCF_IPSBAR +  MCF_GPIO_PAR_FECI2C);
-                       *feci2c_par &= ~0x0F;
-                       *feci2c_par |=  MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
-                                   | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
-               }
-#elif defined(CONFIG_M532x)
-       volatile unsigned char *uartp;
-       uartp = info->addr;
-       switch (info->line) {
-       case 0:
-               MCF_INTC0_ICR26 = 0x3;
-               MCF_INTC0_CIMR = 26;
-               /* GPIO initialization */
-               MCF_GPIO_PAR_UART |= 0x000F;
-               break;
-       case 1:
-               MCF_INTC0_ICR27 = 0x3;
-               MCF_INTC0_CIMR = 27;
-               /* GPIO initialization */
-               MCF_GPIO_PAR_UART |= 0x0FF0;
-               break;
-       case 2:
-               MCF_INTC0_ICR28 = 0x3;
-               MCF_INTC0_CIMR = 28;
-               /* GPIOs also must be initalized, depends on board */
-               break;
-       }
-#else
-       volatile unsigned char  *icrp, *uartp;
-
-       switch (info->line) {
-       case 0:
-               icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR);
-               *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
-                       MCFSIM_ICR_PRI1;
-               mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
-               break;
-       case 1:
-               icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR);
-               *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
-                       MCFSIM_ICR_PRI2;
-               mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
-               break;
-       default:
-               printk("MCFRS: don't know how to handle UART %d interrupt?\n",
-                       info->line);
-               return;
-       }
-
-       uartp = info->addr;
-       uartp[MCFUART_UIVR] = info->irq;
-#endif
-
-       /* Clear mask, so no surprise interrupts. */
-       uartp[MCFUART_UIMR] = 0;
-
-       if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED,
-           "ColdFire UART", NULL)) {
-               printk("MCFRS: Unable to attach ColdFire UART %d interrupt "
-                       "vector=%d\n", info->line, info->irq);
-       }
-
-       return;
-}
-
-
-char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n";
-
-
-/*
- * Serial stats reporting...
- */
-int mcfrs_readproc(char *page, char **start, off_t off, int count,
-                        int *eof, void *data)
-{
-       struct mcf_serial       *info;
-       char                    str[20];
-       int                     len, sigs, i;
-
-       len = sprintf(page, mcfrs_drivername);
-       for (i = 0; (i < NR_PORTS); i++) {
-               info = &mcfrs_table[i];
-               len += sprintf((page + len), "%d: port:%x irq=%d baud:%d ",
-                       i, (unsigned int) info->addr, info->irq, info->baud);
-               if (info->stats.rx || info->stats.tx)
-                       len += sprintf((page + len), "tx:%d rx:%d ",
-                       info->stats.tx, info->stats.rx);
-               if (info->stats.rxframing)
-                       len += sprintf((page + len), "fe:%d ",
-                       info->stats.rxframing);
-               if (info->stats.rxparity)
-                       len += sprintf((page + len), "pe:%d ",
-                       info->stats.rxparity);
-               if (info->stats.rxbreak)
-                       len += sprintf((page + len), "brk:%d ",
-                       info->stats.rxbreak);
-               if (info->stats.rxoverrun)
-                       len += sprintf((page + len), "oe:%d ",
-                       info->stats.rxoverrun);
-
-               str[0] = str[1] = 0;
-               if ((sigs = mcfrs_getsignals(info))) {
-                       if (sigs & TIOCM_RTS)
-                               strcat(str, "|RTS");
-                       if (sigs & TIOCM_CTS)
-                               strcat(str, "|CTS");
-                       if (sigs & TIOCM_DTR)
-                               strcat(str, "|DTR");
-                       if (sigs & TIOCM_CD)
-                               strcat(str, "|CD");
-               }
-
-               len += sprintf((page + len), "%s\n", &str[1]);
-       }
-
-       return(len);
-}
-
-
-/* Finally, routines used to initialize the serial driver. */
-
-static void show_serial_version(void)
-{
-       printk(mcfrs_drivername);
-}
-
-static const struct tty_operations mcfrs_ops = {
-       .open = mcfrs_open,
-       .close = mcfrs_close,
-       .write = mcfrs_write,
-       .flush_chars = mcfrs_flush_chars,
-       .write_room = mcfrs_write_room,
-       .chars_in_buffer = mcfrs_chars_in_buffer,
-       .flush_buffer = mcfrs_flush_buffer,
-       .ioctl = mcfrs_ioctl,
-       .throttle = mcfrs_throttle,
-       .unthrottle = mcfrs_unthrottle,
-       .set_termios = mcfrs_set_termios,
-       .stop = mcfrs_stop,
-       .start = mcfrs_start,
-       .hangup = mcfrs_hangup,
-       .read_proc = mcfrs_readproc,
-       .wait_until_sent = mcfrs_wait_until_sent,
-       .tiocmget = mcfrs_tiocmget,
-       .tiocmset = mcfrs_tiocmset,
-};
-
-/* mcfrs_init inits the driver */
-static int __init
-mcfrs_init(void)
-{
-       struct mcf_serial       *info;
-       unsigned long           flags;
-       int                     i;
-
-       /* Setup base handler, and timer table. */
-#ifdef MCFPP_DCD0
-       init_timer(&mcfrs_timer_struct);
-       mcfrs_timer_struct.function = mcfrs_timer;
-       mcfrs_timer_struct.data = 0;
-       mcfrs_timer_struct.expires = jiffies + HZ/25;
-       add_timer(&mcfrs_timer_struct);
-       mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1);
-#endif
-       mcfrs_serial_driver = alloc_tty_driver(NR_PORTS);
-       if (!mcfrs_serial_driver)
-               return -ENOMEM;
-
-       show_serial_version();
-
-       /* Initialize the tty_driver structure */
-       mcfrs_serial_driver->owner = THIS_MODULE;
-       mcfrs_serial_driver->name = "ttyS";
-       mcfrs_serial_driver->driver_name = "mcfserial";
-       mcfrs_serial_driver->major = TTY_MAJOR;
-       mcfrs_serial_driver->minor_start = 64;
-       mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-       mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-       mcfrs_serial_driver->init_termios = tty_std_termios;
-
-       mcfrs_serial_driver->init_termios.c_cflag =
-               mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL;
-       mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-
-       tty_set_operations(mcfrs_serial_driver, &mcfrs_ops);
-
-       if (tty_register_driver(mcfrs_serial_driver)) {
-               printk("MCFRS: Couldn't register serial driver\n");
-               put_tty_driver(mcfrs_serial_driver);
-               return(-EBUSY);
-       }
-
-       local_irq_save(flags);
-
-       /*
-        *      Configure all the attached serial ports.
-        */
-       for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) {
-               info->magic = SERIAL_MAGIC;
-               info->line = i;
-               info->port.tty = NULL;
-               info->custom_divisor = 16;
-               info->close_delay = 50;
-               info->closing_wait = 3000;
-               info->x_char = 0;
-               info->event = 0;
-               info->count = 0;
-               info->blocked_open = 0;
-               INIT_WORK(&info->tqueue, mcfrs_offintr);
-               INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
-               init_waitqueue_head(&info->open_wait);
-               init_waitqueue_head(&info->close_wait);
-
-               info->imr = 0;
-               mcfrs_setsignals(info, 0, 0);
-               mcfrs_irqinit(info);
-
-               printk("ttyS%d at 0x%04x (irq = %d)", info->line,
-                       (unsigned int) info->addr, info->irq);
-               printk(" is a builtin ColdFire UART\n");
-       }
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-module_init(mcfrs_init);
-
-/****************************************************************************/
-/*                          Serial Console                                  */
-/****************************************************************************/
-
-/*
- *     Quick and dirty UART initialization, for console output.
- */
-
-void mcfrs_init_console(void)
-{
-       volatile unsigned char  *uartp;
-       unsigned int            clk;
-
-       /*
-        *      Reset UART, get it into known state...
-        */
-       uartp = (volatile unsigned char *) (MCF_MBAR +
-               (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
-
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
-       uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR;  /* reset MR pointer */
-
-       /*
-        * Set port for defined baud , 8 data bits, 1 stop bit, no parity.
-        */
-       uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
-       uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
-
-#ifdef CONFIG_M5272
-{
-       /*
-        * For the MCF5272, also compute the baudrate fraction.
-        */
-       int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud);
-       fraction *= 16;
-       fraction /= (32 * mcfrs_console_baud);
-       uartp[MCFUART_UFPD] = (fraction & 0xf);         /* set fraction */
-       clk = (MCF_BUSCLK / mcfrs_console_baud) / 32;
-}
-#else
-       clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */
-#endif
-
-       uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8;  /* set msb baud */
-       uartp[MCFUART_UBG2] = (clk & 0xff);  /* set lsb baud */
-       uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
-       uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
-
-       mcfrs_console_inited++;
-       return;
-}
-
-
-/*
- *     Setup for console. Argument comes from the boot command line.
- */
-
-int mcfrs_console_setup(struct console *cp, char *arg)
-{
-       int             i, n = CONSOLE_BAUD_RATE;
-
-       if (!cp)
-               return(-1);
-
-       if (!strncmp(cp->name, "ttyS", 4))
-               mcfrs_console_port = cp->index;
-       else if (!strncmp(cp->name, "cua", 3))
-               mcfrs_console_port = cp->index;
-       else
-               return(-1);
-
-       if (arg)
-               n = simple_strtoul(arg,NULL,0);
-       for (i = 0; i < MCFRS_BAUD_TABLE_SIZE; i++)
-               if (mcfrs_baud_table[i] == n)
-                       break;
-       if (i < MCFRS_BAUD_TABLE_SIZE) {
-               mcfrs_console_baud = n;
-               mcfrs_console_cbaud = 0;
-               if (i > 15) {
-                       mcfrs_console_cbaud |= CBAUDEX;
-                       i -= 15;
-               }
-               mcfrs_console_cbaud |= i;
-       }
-       mcfrs_init_console(); /* make sure baud rate changes */
-       return(0);
-}
-
-
-static struct tty_driver *mcfrs_console_device(struct console *c, int *index)
-{
-       *index = c->index;
-       return mcfrs_serial_driver;
-}
-
-
-/*
- *     Output a single character, using UART polled mode.
- *     This is used for console output.
- */
-
-int mcfrs_put_char(char ch)
-{
-       volatile unsigned char  *uartp;
-       unsigned long           flags;
-       int                     i;
-
-       uartp = (volatile unsigned char *) (MCF_MBAR +
-               (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
-
-       local_irq_save(flags);
-       for (i = 0; (i < 0x10000); i++) {
-               if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY)
-                       break;
-       }
-       if (i < 0x10000) {
-               uartp[MCFUART_UTB] = ch;
-               for (i = 0; (i < 0x10000); i++)
-                       if (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY)
-                               break;
-       }
-       if (i >= 0x10000)
-               mcfrs_init_console(); /* try and get it back */
-       local_irq_restore(flags);
-
-       return 1;
-}
-
-
-/*
- * rs_console_write is registered for printk output.
- */
-
-void mcfrs_console_write(struct console *cp, const char *p, unsigned len)
-{
-       if (!mcfrs_console_inited)
-               mcfrs_init_console();
-       while (len-- > 0) {
-               if (*p == '\n')
-                       mcfrs_put_char('\r');
-               mcfrs_put_char(*p++);
-       }
-}
-
-/*
- * declare our consoles
- */
-
-struct console mcfrs_console = {
-       .name           = "ttyS",
-       .write          = mcfrs_console_write,
-       .device         = mcfrs_console_device,
-       .setup          = mcfrs_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-};
-
-static int __init mcfrs_console_init(void)
-{
-       register_console(&mcfrs_console);
-       return 0;
-}
-
-console_initcall(mcfrs_console_init);
-
-/****************************************************************************/
diff --git a/drivers/serial/mcfserial.h b/drivers/serial/mcfserial.h
deleted file mode 100644 (file)
index 56420e2..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * mcfserial.c -- serial driver for ColdFire internal UARTS.
- *
- * Copyright (c) 1999 Greg Ungerer <gerg@snapgear.com>
- * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com>
- * Copyright (c) 2002 SnapGear Inc., <www.snapgear.com>
- *
- * Based on code from 68332serial.c which was:
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998 TSHG
- * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org>
- */ 
-#ifndef _MCF_SERIAL_H
-#define _MCF_SERIAL_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-/*
- *     Define a local serial stats structure.
- */
-
-struct mcf_stats {
-       unsigned int    rx;
-       unsigned int    tx;
-       unsigned int    rxbreak;
-       unsigned int    rxframing;
-       unsigned int    rxparity;
-       unsigned int    rxoverrun;
-};
-
-
-/*
- * This is our internal structure for each serial port's state.
- * Each serial port has one of these structures associated with it.
- */
-
-struct mcf_serial {
-       int                     magic;
-       volatile unsigned char  *addr;          /* UART memory address */
-       int                     irq;
-       int                     flags;          /* defined in tty.h */
-       int                     type;           /* UART type */
-       struct tty_struct       *tty;
-       unsigned char           imr;            /* Software imr register */
-       unsigned int            baud;
-       int                     sigs;
-       int                     custom_divisor;
-       int                     x_char; /* xon/xoff character */
-       int                     baud_base;
-       int                     close_delay;
-       unsigned short          closing_wait;
-       unsigned short          closing_wait2;
-       unsigned long           event;
-       int                     line;
-       int                     count;      /* # of fd on device */
-       int                     blocked_open; /* # of blocked opens */
-       unsigned char           *xmit_buf;
-       int                     xmit_head;
-       int                     xmit_tail;
-       int                     xmit_cnt;
-       struct mcf_stats        stats;
-       struct work_struct      tqueue;
-       struct work_struct      tqueue_hangup;
-       wait_queue_head_t       open_wait;
-       wait_queue_head_t       close_wait;
-
-};
-
-#endif /* __KERNEL__ */
-
-#endif /* _MCF_SERIAL_H */
index 36126070d9af8ad10071600b4d53bdb9d947d661..6117d3db0b668980618991a2f66f578410f6e1a7 100644 (file)
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-
-#if defined(CONFIG_PPC_MERGE)
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
 
 #include <asm/mpc52xx.h>
 #include <asm/mpc512x.h>
@@ -107,12 +102,11 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
         *        it's cleared, then a memset(...,0,...) should be added to
         *        the console_init
         */
-#if defined(CONFIG_PPC_MERGE)
+
 /* lookup table for matching device nodes to index numbers */
 static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
 
 static void mpc52xx_uart_of_enumerate(void);
-#endif
 
 
 #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
@@ -255,17 +249,12 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
 /* Search for bus-frequency property in this node or a parent */
 static unsigned long mpc52xx_getuartclk(void *p)
 {
-#if defined(CONFIG_PPC_MERGE)
        /*
         * 5200 UARTs have a / 32 prescaler
         * but the generic serial code assumes 16
         * so return ipb freq / 2
         */
        return mpc52xx_find_ipb_freq(p) / 2;
-#else
-       pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n");
-       return NULL;
-#endif
 }
 
 static struct psc_ops mpc52xx_psc_ops = {
@@ -886,10 +875,6 @@ mpc52xx_console_get_options(struct uart_port *port,
 
        /* CT{U,L}R are write-only ! */
        *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
-#if !defined(CONFIG_PPC_MERGE)
-       if (__res.bi_baudrate)
-               *baud = __res.bi_baudrate;
-#endif
 
        /* Parse them */
        switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
@@ -946,42 +931,6 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
        psc_ops->cw_restore_ints(port);
 }
 
-#if !defined(CONFIG_PPC_MERGE)
-static int __init
-mpc52xx_console_setup(struct console *co, char *options)
-{
-       struct uart_port *port = &mpc52xx_uart_ports[co->index];
-
-       int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
-               return -EINVAL;
-
-       /* Basic port init. Needed since we use some uart_??? func before
-        * real init for early access */
-       spin_lock_init(&port->lock);
-       port->uartclk   = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
-       port->ops       = &mpc52xx_uart_ops;
-       port->mapbase   = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
-
-       /* We ioremap ourself */
-       port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
-       if (port->membase == NULL)
-               return -EINVAL;
-
-       /* Setup the port parameters accoding to options */
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-       else
-               mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-#else
 
 static int __init
 mpc52xx_console_setup(struct console *co, char *options)
@@ -1053,7 +1002,6 @@ mpc52xx_console_setup(struct console *co, char *options)
 
        return uart_set_options(port, co, baud, parity, bits, flow);
 }
-#endif /* defined(CONFIG_PPC_MERGE) */
 
 
 static struct uart_driver mpc52xx_uart_driver;
@@ -1072,9 +1020,7 @@ static struct console mpc52xx_console = {
 static int __init
 mpc52xx_console_init(void)
 {
-#if defined(CONFIG_PPC_MERGE)
        mpc52xx_uart_of_enumerate();
-#endif
        register_console(&mpc52xx_console);
        return 0;
 }
@@ -1100,115 +1046,6 @@ static struct uart_driver mpc52xx_uart_driver = {
        .cons           = MPC52xx_PSC_CONSOLE,
 };
 
-
-#if !defined(CONFIG_PPC_MERGE)
-/* ======================================================================== */
-/* Platform Driver                                                          */
-/* ======================================================================== */
-
-static int __devinit
-mpc52xx_uart_probe(struct platform_device *dev)
-{
-       struct resource *res = dev->resource;
-
-       struct uart_port *port = NULL;
-       int i, idx, ret;
-
-       /* Check validity & presence */
-       idx = dev->id;
-       if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
-               return -EINVAL;
-
-       if (!mpc52xx_match_psc_function(idx, "uart"))
-               return -ENODEV;
-
-       /* Init the port structure */
-       port = &mpc52xx_uart_ports[idx];
-
-       spin_lock_init(&port->lock);
-       port->uartclk   = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
-       port->fifosize  = 512;
-       port->iotype    = UPIO_MEM;
-       port->flags     = UPF_BOOT_AUTOCONF |
-                         (uart_console(port) ? 0 : UPF_IOREMAP);
-       port->line      = idx;
-       port->ops       = &mpc52xx_uart_ops;
-       port->dev       = &dev->dev;
-
-       /* Search for IRQ and mapbase */
-       for (i = 0 ; i < dev->num_resources ; i++, res++) {
-               if (res->flags & IORESOURCE_MEM)
-                       port->mapbase = res->start;
-               else if (res->flags & IORESOURCE_IRQ)
-                       port->irq = res->start;
-       }
-       if (!port->irq || !port->mapbase)
-               return -EINVAL;
-
-       /* Add the port to the uart sub-system */
-       ret = uart_add_one_port(&mpc52xx_uart_driver, port);
-       if (!ret)
-               platform_set_drvdata(dev, (void *)port);
-
-       return ret;
-}
-
-static int
-mpc52xx_uart_remove(struct platform_device *dev)
-{
-       struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-       platform_set_drvdata(dev, NULL);
-
-       if (port)
-               uart_remove_one_port(&mpc52xx_uart_driver, port);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-       if (port)
-               uart_suspend_port(&mpc52xx_uart_driver, port);
-
-       return 0;
-}
-
-static int
-mpc52xx_uart_resume(struct platform_device *dev)
-{
-       struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-       if (port)
-               uart_resume_port(&mpc52xx_uart_driver, port);
-
-       return 0;
-}
-#endif
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc");
-
-static struct platform_driver mpc52xx_uart_platform_driver = {
-       .probe          = mpc52xx_uart_probe,
-       .remove         = mpc52xx_uart_remove,
-#ifdef CONFIG_PM
-       .suspend        = mpc52xx_uart_suspend,
-       .resume         = mpc52xx_uart_resume,
-#endif
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "mpc52xx-psc",
-       },
-};
-#endif /* !defined(CONFIG_PPC_MERGE) */
-
-
-#if defined(CONFIG_PPC_MERGE)
 /* ======================================================================== */
 /* OF Platform Driver                                                       */
 /* ======================================================================== */
@@ -1402,7 +1239,6 @@ static struct of_platform_driver mpc52xx_uart_of_driver = {
                .name   = "mpc52xx-psc-uart",
        },
 };
-#endif /* defined(CONFIG_PPC_MERGE) */
 
 
 /* ======================================================================== */
@@ -1423,7 +1259,6 @@ mpc52xx_uart_init(void)
                return ret;
        }
 
-#if defined(CONFIG_PPC_MERGE)
        mpc52xx_uart_of_enumerate();
 
        ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
@@ -1433,16 +1268,6 @@ mpc52xx_uart_init(void)
                uart_unregister_driver(&mpc52xx_uart_driver);
                return ret;
        }
-#else
-       psc_ops = &mpc52xx_psc_ops;
-       ret = platform_driver_register(&mpc52xx_uart_platform_driver);
-       if (ret) {
-               printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
-                      __FILE__, ret);
-               uart_unregister_driver(&mpc52xx_uart_driver);
-               return ret;
-       }
-#endif
 
        return 0;
 }
@@ -1450,11 +1275,7 @@ mpc52xx_uart_init(void)
 static void __exit
 mpc52xx_uart_exit(void)
 {
-#if defined(CONFIG_PPC_MERGE)
        of_unregister_platform_driver(&mpc52xx_uart_of_driver);
-#else
-       platform_driver_unregister(&mpc52xx_uart_platform_driver);
-#endif
        uart_unregister_driver(&mpc52xx_uart_driver);
 }
 
index c8b4266ac35fdad490af228ae86479cac300b1a3..4873f2978bd2357e9a23b9f5ae745d7f0baa5cdd 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include "samsung.h"
index 40a2531b55410897ec5d744b0931943e33caec23..87c182ef71b8662e4e6de1772cb2ada44b96b235 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include "samsung.h"
index d0170319c729b6cf847ba2e33cd34754b44bc0e4..fd017b37556868ca2268d28101770e028d6538b0 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include "samsung.h"
index d4a2b17b24985fe350352e389ccb42a836dcd2ad..317d239ab74043cf10ada65e9329d4da0d3e87fe 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/irq.h>
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include "samsung.h"
index 5a88b3f9fe9b676d1b04a175ca7801c0de447b16..1e219d3d0352b29499c60086000b149ad8a902af 100644 (file)
@@ -47,7 +47,7 @@
 
 #include <mach/hardware.h>
 
-#include <asm/plat-s3c/regs-serial.h>
+#include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
 #include "samsung.h"
index f977c98cfa956749cb3bd37211d30bb6115d2190..6bdf3362e3b1e5f743ae8bad1f0bc8c9f682bf08 100644 (file)
@@ -2051,7 +2051,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
                                        "transmitter\n",
                               port->dev ? port->dev->bus_id : "",
                               port->dev ? ": " : "",
-                              drv->dev_name, port->line);
+                              drv->dev_name,
+                              drv->tty_driver->name_base + port->line);
 
                ops->shutdown(port);
        }
@@ -2154,12 +2155,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
 
        switch (port->iotype) {
        case UPIO_PORT:
-               snprintf(address, sizeof(address),
-                        "I/O 0x%x", port->iobase);
+               snprintf(address, sizeof(address), "I/O 0x%lx", port->iobase);
                break;
        case UPIO_HUB6:
                snprintf(address, sizeof(address),
-                        "I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+                        "I/O 0x%lx offset 0x%x", port->iobase, port->hub6);
                break;
        case UPIO_MEM:
        case UPIO_MEM32:
@@ -2177,7 +2177,9 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
        printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
               port->dev ? port->dev->bus_id : "",
               port->dev ? ": " : "",
-              drv->dev_name, port->line, address, port->irq, uart_type(port));
+              drv->dev_name,
+              drv->tty_driver->name_base + port->line,
+              address, port->irq, uart_type(port));
 }
 
 static void
index 164d2a42eb59fe5a5a58e9ea26d13830d493a28c..7546aa887fa7565417fe3a9f14956f5e9e314e40 100644 (file)
@@ -431,131 +431,103 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
 {
        int i;
        i = pcmcia_get_first_tuple(handle, tuple);
-       if (i != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
-       i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != CS_SUCCESS)
+       if (i != 0)
                return i;
-       return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int
-next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
-{
-       int i;
-       i = pcmcia_get_next_tuple(handle, tuple);
-       if (i != CS_SUCCESS)
-               return CS_NO_MORE_ITEMS;
        i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != CS_SUCCESS)
+       if (i != 0)
                return i;
-       return pcmcia_parse_tuple(handle, tuple, parse);
+       return pcmcia_parse_tuple(tuple, parse);
 }
 
 /*====================================================================*/
 
-static int simple_config(struct pcmcia_device *link)
+static int simple_config_check(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cf,
+                              cistpl_cftable_entry_t *dflt,
+                              unsigned int vcc,
+                              void *priv_data)
 {
-       static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        static const int size_table[2] = { 8, 16 };
-       struct serial_info *info = link->priv;
-       struct serial_cfg_mem *cfg_mem;
-       tuple_t *tuple;
-       u_char *buf;
-       cisparse_t *parse;
-       cistpl_cftable_entry_t *cf;
-       config_info_t config;
-       int i, j, try;
-       int s;
+       int *try = priv_data;
+
+       if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+       if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
+           && (cf->io.win[0].base != 0)) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
+                       16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -EINVAL;
+}
 
-       cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
-       if (!cfg_mem)
-               return -1;
+static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
+                                       cistpl_cftable_entry_t *cf,
+                                       cistpl_cftable_entry_t *dflt,
+                                       unsigned int vcc,
+                                       void *priv_data)
+{
+       static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+       int j;
+
+       if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+               for (j = 0; j < 5; j++) {
+                       p_dev->io.BasePort1 = base[j];
+                       p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
+}
 
-       tuple = &cfg_mem->tuple;
-       parse = &cfg_mem->parse;
-       cf = &parse->cftable_entry;
-       buf = cfg_mem->buf;
+static int simple_config(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i = -ENODEV, try;
 
        /* If the card is already configured, look up the port and irq */
-       i = pcmcia_get_configuration_info(link, &config);
-       if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
+       if (link->function_config) {
                unsigned int port = 0;
-               if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
-                       port = config.BasePort2;
+               if ((link->io.BasePort2 != 0) &&
+                   (link->io.NumPorts2 == 8)) {
+                       port = link->io.BasePort2;
                        info->slave = 1;
                } else if ((info->manfid == MANFID_OSITECH) &&
-                          (config.NumPorts1 == 0x40)) {
-                       port = config.BasePort1 + 0x28;
+                          (link->io.NumPorts1 == 0x40)) {
+                       port = link->io.BasePort1 + 0x28;
                        info->slave = 1;
                }
                if (info->slave) {
-                       kfree(cfg_mem);
-                       return setup_serial(link, info, port, config.AssignedIRQ);
+                       return setup_serial(link, info, port,
+                                           link->irq.AssignedIRQ);
                }
        }
 
-       /* First pass: look for a config entry that looks normal. */
-       tuple->TupleData = (cisdata_t *) buf;
-       tuple->TupleOffset = 0;
-       tuple->TupleDataMax = 255;
-       tuple->Attributes = 0;
-       tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       /* Two tries: without IO aliases, then with aliases */
-       for (s = 0; s < 2; s++) {
-               for (try = 0; try < 2; try++) {
-                       i = first_tuple(link, 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.Vpp =
-                                           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, &link->io);
-                                       if (i == CS_SUCCESS)
-                                               goto found_port;
-                               }
-next_entry:
-                               i = next_tuple(link, tuple, parse);
-                       }
-               }
-       }
+       /* First pass: look for a config entry that looks normal.
+        * Two tries: without IO aliases, then with aliases */
+       for (try = 0; try < 4; try++)
+               if (!pcmcia_loop_config(link, simple_config_check, &try))
+                       goto found_port;
+
        /* 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. */
-       i = first_tuple(link, tuple, parse);
-       while (i != CS_NO_MORE_ITEMS) {
-               if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
-                   ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-                       link->conf.ConfigIndex = cf->index;
-                       for (j = 0; j < 5; j++) {
-                               link->io.BasePort1 = base[j];
-                               link->io.IOAddrLines = base[j] ? 16 : 3;
-                               i = pcmcia_request_io(link, &link->io);
-                               if (i == CS_SUCCESS)
-                                       goto found_port;
-                       }
-               }
-               i = next_tuple(link, tuple, parse);
-       }
+       if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
+               goto found_port;
 
-      found_port:
-       if (i != CS_SUCCESS) {
-               printk(KERN_NOTICE
-                      "serial_cs: no usable port range found, giving up\n");
-               cs_error(link, RequestIO, i);
-               kfree(cfg_mem);
-               return -1;
-       }
+       printk(KERN_NOTICE
+              "serial_cs: no usable port range found, giving up\n");
+       cs_error(link, RequestIO, i);
+       return -1;
 
+found_port:
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestIRQ, i);
                link->irq.AssignedIRQ = 0;
        }
@@ -569,88 +541,76 @@ next_entry:
                info->quirk->config(link);
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
-               kfree(cfg_mem);
                return -1;
        }
-       kfree(cfg_mem);
        return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
 }
 
-static int multi_config(struct pcmcia_device * link)
+static int multi_config_check(struct pcmcia_device *p_dev,
+                             cistpl_cftable_entry_t *cf,
+                             cistpl_cftable_entry_t *dflt,
+                             unsigned int vcc,
+                             void *priv_data)
 {
-       struct serial_info *info = link->priv;
-       struct serial_cfg_mem *cfg_mem;
-       tuple_t *tuple;
-       u_char *buf;
-       cisparse_t *parse;
-       cistpl_cftable_entry_t *cf;
-       int i, rc, base2 = 0;
+       int *base2 = priv_data;
+
+       /* The quad port cards have bad CIS's, so just look for a
+          window larger than 8 ports and assume it will be right */
+       if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+                       *base2 = p_dev->io.BasePort1 + 8;
+                       return 0;
+               }
+       }
+       return -ENODEV;
+}
 
-       cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
-       if (!cfg_mem)
-               return -1;
-       tuple = &cfg_mem->tuple;
-       parse = &cfg_mem->parse;
-       cf = &parse->cftable_entry;
-       buf = cfg_mem->buf;
+static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
+                                      cistpl_cftable_entry_t *cf,
+                                      cistpl_cftable_entry_t *dflt,
+                                      unsigned int vcc,
+                                      void *priv_data)
+{
+       int *base2 = priv_data;
+
+       if (cf->io.nwin == 2) {
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               p_dev->io.BasePort2 = cf->io.win[1].base;
+               p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+               if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+                       *base2 = p_dev->io.BasePort2;
+                       return 0;
+               }
+       }
+       return -ENODEV;
+}
 
-       tuple->TupleData = (cisdata_t *) buf;
-       tuple->TupleOffset = 0;
-       tuple->TupleDataMax = 255;
-       tuple->Attributes = 0;
-       tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+static int multi_config(struct pcmcia_device *link)
+{
+       struct serial_info *info = link->priv;
+       int i, base2 = 0;
 
        /* First, look for a generic full-sized window */
        link->io.NumPorts1 = info->multi * 8;
-       i = first_tuple(link, tuple, parse);
-       while (i != CS_NO_MORE_ITEMS) {
-               /* The quad port cards have bad CIS's, so just look for a
-                  window larger than 8 ports and assume it will be right */
-               if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
-                   (cf->io.win[0].len > 8)) {
-                       link->conf.ConfigIndex = cf->index;
-                       link->io.BasePort1 = cf->io.win[0].base;
-                       link->io.IOAddrLines =
-                           cf->io.flags & CISTPL_IO_LINES_MASK;
-                       i = pcmcia_request_io(link, &link->io);
-                       base2 = link->io.BasePort1 + 8;
-                       if (i == CS_SUCCESS)
-                               break;
-               }
-               i = next_tuple(link, tuple, parse);
-       }
-
-       /* If that didn't work, look for two windows */
-       if (i != CS_SUCCESS) {
+       if (pcmcia_loop_config(link, multi_config_check, &base2)) {
+               /* If that didn't work, look for two windows */
                link->io.NumPorts1 = link->io.NumPorts2 = 8;
                info->multi = 2;
-               i = first_tuple(link, tuple, parse);
-               while (i != CS_NO_MORE_ITEMS) {
-                       if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
-                               link->conf.ConfigIndex = cf->index;
-                               link->io.BasePort1 = cf->io.win[0].base;
-                               link->io.BasePort2 = cf->io.win[1].base;
-                               link->io.IOAddrLines =
-                                   cf->io.flags & CISTPL_IO_LINES_MASK;
-                               i = pcmcia_request_io(link, &link->io);
-                               base2 = link->io.BasePort2;
-                               if (i == CS_SUCCESS)
-                                       break;
-                       }
-                       i = next_tuple(link, tuple, parse);
+               if (pcmcia_loop_config(link, multi_config_check_notpicky,
+                                      &base2)) {
+                       printk(KERN_NOTICE "serial_cs: no usable port range"
+                              "found, giving up\n");
+                       return -ENODEV;
                }
        }
 
-       if (i != CS_SUCCESS) {
-               cs_error(link, RequestIO, i);
-               rc = -1;
-               goto free_cfg_mem;
-       }
-
        i = pcmcia_request_irq(link, &link->irq);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
+               /* FIXME: comment does not fit, error handling does not fit */
                printk(KERN_NOTICE
                       "serial_cs: no usable port range found, giving up\n");
                cs_error(link, RequestIRQ, i);
@@ -664,10 +624,9 @@ static int multi_config(struct pcmcia_device * link)
                info->quirk->config(link);
 
        i = pcmcia_request_configuration(link, &link->conf);
-       if (i != CS_SUCCESS) {
+       if (i != 0) {
                cs_error(link, RequestConfiguration, i);
-               rc = -1;
-               goto free_cfg_mem;
+               return -ENODEV;
        }
 
        /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -678,7 +637,8 @@ static int multi_config(struct pcmcia_device * link)
                                info->prodid == PRODID_POSSIO_GCC)) {
                int err;
 
-               if (cf->index == 1 || cf->index == 3) {
+               if (link->conf.ConfigIndex == 1 ||
+                   link->conf.ConfigIndex == 3) {
                        err = setup_serial(link, info, base2,
                                        link->irq.AssignedIRQ);
                        base2 = link->io.BasePort1;
@@ -695,18 +655,14 @@ static int multi_config(struct pcmcia_device * link)
                if (info->quirk && info->quirk->wakeup)
                        info->quirk->wakeup(link);
 
-               rc = 0;
-               goto free_cfg_mem;
+               return 0;
        }
 
        setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
        for (i = 0; i < info->multi - 1; i++)
                setup_serial(link, info, base2 + (8 * i),
                                link->irq.AssignedIRQ);
-       rc = 0;
-free_cfg_mem:
-       kfree(cfg_mem);
-       return rc;
+       return 0;
 }
 
 /*======================================================================
@@ -746,7 +702,7 @@ static int serial_config(struct pcmcia_device * link)
        /* Is this a compliant multifunction card? */
        tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
        tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
-       info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS);
+       info->multi = (first_tuple(link, tuple, parse) == 0);
 
        /* Is this a multiport card? */
        tuple->DesiredTuple = CISTPL_MANFID;
@@ -770,7 +726,7 @@ static int serial_config(struct pcmcia_device * link)
            ((link->func_id == CISTPL_FUNCID_MULTI) ||
             (link->func_id == CISTPL_FUNCID_SERIAL))) {
                tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-               if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
+               if (first_tuple(link, tuple, parse) == 0) {
                        if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
                                info->multi = cf->io.win[0].len >> 3;
                        if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
index 5c5d18dcb6aca4b0443b9bb8d3d5b2579b5705c0..539c933b335f306b2dc92182785ab09cf271cec6 100644 (file)
@@ -1009,7 +1009,7 @@ static int qe_uart_request_port(struct uart_port *port)
        rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
        tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
 
-       bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr,
+       bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr,
                GFP_KERNEL);
        if (!bd_virt) {
                dev_err(port->dev, "could not allocate buffer descriptors\n");
@@ -1051,7 +1051,7 @@ static void qe_uart_release_port(struct uart_port *port)
                container_of(port, struct uart_qe_port, port);
        struct ucc_slow_private *uccs = qe_port->us_private;
 
-       dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt,
+       dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt,
                          qe_port->bd_dma_addr);
 
        ucc_slow_free(uccs);
index 25eda71f4bf4c29c442633c5ff2914dad2839e5a..0debe11b67b494a2f0ea4d49cb95598e43217c3d 100644 (file)
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-
-#if defined(CONFIG_PPC_MERGE)
 #include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
-
 #include <linux/workqueue.h>
 #include <linux/completion.h>
 #include <linux/io.h>
@@ -108,13 +102,13 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
         * Because psc->ccr is defined as 16bit register instead of 32bit
         * just set the lower byte of BitClkDiv
         */
-       ccr = in_be16(&psc->ccr);
+       ccr = in_be16((u16 __iomem *)&psc->ccr);
        ccr &= 0xFF00;
        if (cs->speed_hz)
                ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
        else /* by default SPI Clk 1MHz */
                ccr |= (MCLK / 1000000 - 1) & 0xFF;
-       out_be16(&psc->ccr, ccr);
+       out_be16((u16 __iomem *)&psc->ccr, ccr);
        mps->bits_per_word = cs->bits_per_word;
 
        if (mps->activate_cs)
@@ -347,7 +341,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
        /* Configure 8bit codec mode as a SPI master and use EOF flags */
        /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
        out_be32(&psc->sicr, 0x0180C800);
-       out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+       out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
 
        /* Set 2ms DTL delay */
        out_8(&psc->ctur, 0x00);
@@ -471,53 +465,6 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
        return 0;
 }
 
-#if !defined(CONFIG_PPC_MERGE)
-static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
-{
-       switch(dev->id) {
-       case 1:
-       case 2:
-       case 3:
-       case 6:
-               return mpc52xx_psc_spi_do_probe(&dev->dev,
-                       MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
-                       MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
-{
-       return mpc52xx_psc_spi_do_remove(&dev->dev);
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc-spi");
-
-static struct platform_driver mpc52xx_psc_spi_platform_driver = {
-       .remove = __exit_p(mpc52xx_psc_spi_remove),
-       .driver = {
-               .name = "mpc52xx-psc-spi",
-               .owner = THIS_MODULE,
-       },
-};
-
-static int __init mpc52xx_psc_spi_init(void)
-{
-       return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
-                       mpc52xx_psc_spi_probe);
-}
-module_init(mpc52xx_psc_spi_init);
-
-static void __exit mpc52xx_psc_spi_exit(void)
-{
-       platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
-}
-module_exit(mpc52xx_psc_spi_exit);
-
-#else  /* defined(CONFIG_PPC_MERGE) */
-
 static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
        const struct of_device_id *match)
 {
@@ -586,8 +533,6 @@ static void __exit mpc52xx_psc_spi_exit(void)
 }
 module_exit(mpc52xx_psc_spi_exit);
 
-#endif /* defined(CONFIG_PPC_MERGE) */
-
 MODULE_AUTHOR("Dragos Carp");
 MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
 MODULE_LICENSE("GPL");
index 9d2186fd74aaf7eaca9f9954dde88d1dc11e7c36..454a2712e6290ee0f0f085667a0baec9ec6bb027 100644 (file)
@@ -119,12 +119,14 @@ struct omap2_mcspi {
        struct clk              *fck;
        /* Virtual base address of the controller */
        void __iomem            *base;
+       unsigned long           phys;
        /* SPI1 has 4 channels, while SPI2 has 2 */
        struct omap2_mcspi_dma  *dma_channels;
 };
 
 struct omap2_mcspi_cs {
        void __iomem            *base;
+       unsigned long           phys;
        int                     word_len;
 };
 
@@ -233,7 +235,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        c = count;
        word_len = cs->word_len;
 
-       base = (unsigned long) io_v2p(cs->base);
+       base = cs->phys;
        tx_reg = base + OMAP2_MCSPI_TX0;
        rx_reg = base + OMAP2_MCSPI_RX0;
        rx = xfer->rx_buf;
@@ -633,6 +635,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
                if (!cs)
                        return -ENOMEM;
                cs->base = mcspi->base + spi->chip_select * 0x14;
+               cs->phys = mcspi->phys + spi->chip_select * 0x14;
                spi->controller_state = cs;
        }
 
@@ -1005,7 +1008,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       mcspi->base = (void __iomem *) io_p2v(r->start);
+       mcspi->phys = r->start;
+       mcspi->base = ioremap(r->start, r->end - r->start + 1);
+       if (!mcspi->base) {
+               dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
+               status = -ENOMEM;
+               goto err1aa;
+       }
 
        INIT_WORK(&mcspi->work, omap2_mcspi_work);
 
@@ -1055,6 +1064,8 @@ err3:
 err2:
        clk_put(mcspi->ick);
 err1a:
+       iounmap(mcspi->base);
+err1aa:
        release_mem_region(r->start, (r->end - r->start) + 1);
 err1:
        spi_master_put(master);
@@ -1067,6 +1078,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
        struct omap2_mcspi      *mcspi;
        struct omap2_mcspi_dma  *dma_channels;
        struct resource         *r;
+       void __iomem *base;
 
        master = dev_get_drvdata(&pdev->dev);
        mcspi = spi_master_get_devdata(master);
@@ -1078,7 +1090,9 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(r->start, (r->end - r->start) + 1);
 
+       base = mcspi->base;
        spi_unregister_master(master);
+       iounmap(base);
        kfree(dma_channels);
 
        return 0;
index 5515eb97d7c57ebacdcc7c4379822af0dd5bb751..bab6ff061e9145a95dad6756d6cbc4b25e69e671 100644 (file)
@@ -59,7 +59,6 @@
  * and irqs should show there too...
  */
 #define UWIRE_BASE_PHYS                0xFFFB3000
-#define UWIRE_BASE             ((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS))
 
 /* uWire Registers: */
 #define UWIRE_IO_SIZE 0x20
@@ -103,16 +102,21 @@ struct uwire_state {
 };
 
 /* REVISIT compile time constant for idx_shift? */
+/*
+ * Or, put it in a structure which is used throughout the driver;
+ * that avoids having to issue two loads for each bit of static data.
+ */
 static unsigned int uwire_idx_shift;
+static void __iomem *uwire_base;
 
 static inline void uwire_write_reg(int idx, u16 val)
 {
-       __raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift));
+       __raw_writew(val, uwire_base + (idx << uwire_idx_shift));
 }
 
 static inline u16 uwire_read_reg(int idx)
 {
-       return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift));
+       return __raw_readw(uwire_base + (idx << uwire_idx_shift));
 }
 
 static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
@@ -492,6 +496,14 @@ static int __init uwire_probe(struct platform_device *pdev)
                return -ENODEV;
 
        uwire = spi_master_get_devdata(master);
+
+       uwire_base = ioremap(UWIRE_BASE_PHYS, UWIRE_IO_SIZE);
+       if (!uwire_base) {
+               dev_dbg(&pdev->dev, "can't ioremap UWIRE\n");
+               spi_master_put(master);
+               return -ENOMEM;
+       }
+
        dev_set_drvdata(&pdev->dev, uwire);
 
        uwire->ck = clk_get(&pdev->dev, "armxor_ck");
@@ -520,8 +532,10 @@ static int __init uwire_probe(struct platform_device *pdev)
        uwire->bitbang.txrx_bufs = uwire_txrx;
 
        status = spi_bitbang_start(&uwire->bitbang);
-       if (status < 0)
+       if (status < 0) {
                uwire_off(uwire);
+               iounmap(uwire_base);
+       }
        return status;
 }
 
@@ -534,6 +548,7 @@ static int __exit uwire_remove(struct platform_device *pdev)
 
        status = spi_bitbang_stop(&uwire->bitbang);
        uwire_off(uwire);
+       iounmap(uwire_base);
        return status;
 }
 
index b872bfaf4bd2c0e4706c1551db8da94324622983..014becb7d53007b20099b9b9c84d0eb09d19e5dc 100644 (file)
@@ -364,6 +364,11 @@ static int orion_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
+       /* Fix ac timing if required.   */
+       if (orion_spi->spi_info->enable_clock_fix)
+               orion_spi_setbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
+                                 (1 << 14));
+
        if (spi->bits_per_word == 0)
                spi->bits_per_word = 8;
 
index d47d3636227fe90e435fc03a8f59fd49860b1220..dae87b1a4c6effa5c18cff538c3a634a846a2957 100644 (file)
@@ -47,6 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 
 #define MAX_BUSES 3
 
+#define RX_THRESH_DFLT         8
+#define TX_THRESH_DFLT         8
+#define TIMOUT_DFLT            1000
+
 #define DMA_INT_MASK           (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
 #define RESET_DMA_CHANNEL      (DCSR_NODESC | DMA_INT_MASK)
 #define IS_DMA_ALIGNED(x)      ((((u32)(x)) & 0x07) == 0)
@@ -1171,6 +1175,8 @@ static int setup(struct spi_device *spi)
        struct driver_data *drv_data = spi_master_get_devdata(spi->master);
        struct ssp_device *ssp = drv_data->ssp;
        unsigned int clk_div;
+       uint tx_thres = TX_THRESH_DFLT;
+       uint rx_thres = RX_THRESH_DFLT;
 
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
@@ -1209,8 +1215,7 @@ static int setup(struct spi_device *spi)
 
                chip->cs_control = null_cs_control;
                chip->enable_dma = 0;
-               chip->timeout = 1000;
-               chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
+               chip->timeout = TIMOUT_DFLT;
                chip->dma_burst_size = drv_data->master_info->enable_dma ?
                                        DCMD_BURST8 : 0;
        }
@@ -1224,22 +1229,21 @@ static int setup(struct spi_device *spi)
        if (chip_info) {
                if (chip_info->cs_control)
                        chip->cs_control = chip_info->cs_control;
-
-               chip->timeout = chip_info->timeout;
-
-               chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) &
-                                                               SSCR1_RFT) |
-                               (SSCR1_TxTresh(chip_info->tx_threshold) &
-                                                               SSCR1_TFT);
-
-               chip->enable_dma = chip_info->dma_burst_size != 0
-                                       && drv_data->master_info->enable_dma;
+               if (chip_info->timeout)
+                       chip->timeout = chip_info->timeout;
+               if (chip_info->tx_threshold)
+                       tx_thres = chip_info->tx_threshold;
+               if (chip_info->rx_threshold)
+                       rx_thres = chip_info->rx_threshold;
+               chip->enable_dma = drv_data->master_info->enable_dma;
                chip->dma_threshold = 0;
-
                if (chip_info->enable_loopback)
                        chip->cr1 = SSCR1_LBM;
        }
 
+       chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
+                       (SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
+
        /* set dma burst and threshold outside of chip_info path so that if
         * chip_info goes away after setting chip->enable_dma, the
         * burst and threshold can still respond to changes in bits_per_word */
@@ -1268,17 +1272,19 @@ static int setup(struct spi_device *spi)
 
        /* NOTE:  PXA25x_SSP _could_ use external clocking ... */
        if (drv_data->ssp_type != PXA25x_SSP)
-               dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+               dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
                                spi->bits_per_word,
                                clk_get_rate(ssp->clk)
                                        / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
-                               spi->mode & 0x3);
+                               spi->mode & 0x3,
+                               chip->enable_dma ? "DMA" : "PIO");
        else
-               dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n",
+               dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n",
                                spi->bits_per_word,
-                               clk_get_rate(ssp->clk)
+                               clk_get_rate(ssp->clk) / 2
                                        / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
-                               spi->mode & 0x3);
+                               spi->mode & 0x3,
+                               chip->enable_dma ? "DMA" : "PIO");
 
        if (spi->bits_per_word <= 8) {
                chip->n_bytes = 1;
@@ -1407,9 +1413,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct pxa2xx_spi_master *platform_info;
        struct spi_master *master;
-       struct driver_data *drv_data = NULL;
+       struct driver_data *drv_data;
        struct ssp_device *ssp;
-       int status = 0;
+       int status;
 
        platform_info = dev->platform_data;
 
@@ -1422,7 +1428,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
        /* Allocate master with space for drv_data and null dma buffer */
        master = spi_alloc_master(dev, sizeof(struct driver_data) + 16);
        if (!master) {
-               dev_err(&pdev->dev, "can not alloc spi_master\n");
+               dev_err(&pdev->dev, "cannot alloc spi_master\n");
                ssp_free(ssp);
                return -ENOMEM;
        }
@@ -1458,7 +1464,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 
        status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data);
        if (status < 0) {
-               dev_err(&pdev->dev, "can not get IRQ\n");
+               dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq);
                goto out_error_master_alloc;
        }
 
@@ -1498,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
 
        /* Load default SSP configuration */
        write_SSCR0(0, drv_data->ioaddr);
-       write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr);
+       write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+                               SSCR1_TxTresh(TX_THRESH_DFLT),
+                               drv_data->ioaddr);
        write_SSCR0(SSCR0_SerClkDiv(2)
                        | SSCR0_Motorola
                        | SSCR0_DataSize(8),
index 75e86865234c924a67bb94d39c3fc259a6925b5a..3734dc9708e12669070ab984cc2fe9f0fbee1b70 100644 (file)
@@ -660,7 +660,7 @@ int spi_write_then_read(struct spi_device *spi,
 
        int                     status;
        struct spi_message      message;
-       struct spi_transfer     x[2];
+       struct spi_transfer     x;
        u8                      *local_buf;
 
        /* Use preallocated DMA-safe buffer.  We can't avoid copying here,
@@ -671,15 +671,9 @@ int spi_write_then_read(struct spi_device *spi,
                return -EINVAL;
 
        spi_message_init(&message);
-       memset(x, 0, sizeof x);
-       if (n_tx) {
-               x[0].len = n_tx;
-               spi_message_add_tail(&x[0], &message);
-       }
-       if (n_rx) {
-               x[1].len = n_rx;
-               spi_message_add_tail(&x[1], &message);
-       }
+       memset(&x, 0, sizeof x);
+       x.len = n_tx + n_rx;
+       spi_message_add_tail(&x, &message);
 
        /* ... unless someone else is using the pre-allocated buffer */
        if (!mutex_trylock(&lock)) {
@@ -690,15 +684,15 @@ int spi_write_then_read(struct spi_device *spi,
                local_buf = buf;
 
        memcpy(local_buf, txbuf, n_tx);
-       x[0].tx_buf = local_buf;
-       x[1].rx_buf = local_buf + n_tx;
+       x.tx_buf = local_buf;
+       x.rx_buf = local_buf;
 
        /* do the i/o */
        status = spi_sync(spi, &message);
        if (status == 0)
-               memcpy(rxbuf, x[1].rx_buf, n_rx);
+               memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
 
-       if (x[0].tx_buf == buf)
+       if (x.tx_buf == buf)
                mutex_unlock(&lock);
        else
                kfree(local_buf);
@@ -744,5 +738,5 @@ err0:
  * driver registration) _could_ be dynamically linked (modular) ... costs
  * include needing to have boardinfo data structures be much more public.
  */
-subsys_initcall(spi_init);
+postcore_initcall(spi_init);
 
index 3eb414b84a9d5a2f82482bec675e22c969d4c224..c252cbac00f1d14ef273f53dea2ca7f39edd38b5 100644 (file)
@@ -247,6 +247,9 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
        writeb(0xff, hw->regs + S3C2410_SPPRE);
        writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
        writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
+
+       if (hw->pdata && hw->pdata->gpio_setup)
+               hw->pdata->gpio_setup(hw->pdata, 1);
 }
 
 static int __init s3c24xx_spi_probe(struct platform_device *pdev)
@@ -412,6 +415,9 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
 {
        struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
 
+       if (hw->pdata && hw->pdata->gpio_setup)
+               hw->pdata->gpio_setup(hw->pdata, 0);
+
        clk_disable(hw->clk);
        return 0;
 }
index e5e0cfed5e3b3fedff7f81983a73f4b94a9de8ca..89a43755a453bb265ebfa789adca222a8cce1ebe 100644 (file)
@@ -583,10 +583,9 @@ static int spidev_probe(struct spi_device *spi)
                struct device *dev;
 
                spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
-               dev = device_create_drvdata(spidev_class, &spi->dev,
-                               spidev->devt, spidev,
-                               "spidev%d.%d",
-                               spi->master->bus_num, spi->chip_select);
+               dev = device_create(spidev_class, &spi->dev, spidev->devt,
+                                   spidev, "spidev%d.%d",
+                                   spi->master->bus_num, spi->chip_select);
                status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
        } else {
                dev_dbg(&spi->dev, "no minor number available!\n");
index 24c2a46c14760cbb879f1e367aff8774e01ac7b2..fbfadbac67e887d190ac1c93b87d957cf90146fa 100644 (file)
@@ -80,7 +80,7 @@ static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
        reg.Action = CS_WRITE;
        reg.Value = value;
        res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-       if (unlikely(res != CS_SUCCESS))
+       if (unlikely(res != 0))
                return -EBUSY;
 
        return 0;
@@ -96,7 +96,7 @@ static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
        reg.Offset = offset;
        reg.Action = CS_READ;
        res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-       if (unlikely(res != CS_SUCCESS))
+       if (unlikely(res != 0))
                return -EBUSY;
        *value = reg.Value;
 
@@ -638,17 +638,17 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-       GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
+       GOTO_ERROR_ON(res != 0, "MAC first tpl");
        res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-       GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
+       GOTO_ERROR_ON(res != 0, "MAC first tpl data");
        while (1) {
                GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
                if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
                        break;
                res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-               GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
+               GOTO_ERROR_ON(res != 0, "MAC next tpl");
                res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-               GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
+               GOTO_ERROR_ON(res != 0, "MAC next tpl data");
        }
        GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
        memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
@@ -659,9 +659,9 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
        tuple.TupleData = buf;
        tuple.TupleDataMax = sizeof(buf);
        res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-       GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
+       GOTO_ERROR_ON(res != 0, "VEN first tpl");
        res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-       GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
+       GOTO_ERROR_ON(res != 0, "VEN first tpl data");
        while (1) {
                GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
                switch (tuple.TupleData[0]) {
@@ -733,11 +733,11 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
                        break;
                }
                res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-               if (res == CS_NO_MORE_ITEMS)
+               if (res == -ENOSPC)
                        break;
-               GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
+               GOTO_ERROR_ON(res != 0, "VEN next tpl");
                res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-               GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
+               GOTO_ERROR_ON(res != 0, "VEN next tpl data");
        }
 
        return 0;
index ec7aeb502d1548ecbfd64c521518c11857e308de..41b6530b8f251d0a2d5193eb58297ee3a99f30ac 100644 (file)
@@ -42,8 +42,6 @@
  ***************************************************************************/
 
 /*
- * $Log: ixj.c,v $
- *
  * Revision 4.8  2003/07/09 19:39:00  Daniele Bellucci
  * Audit some copy_*_user and minor cleanup.
  *
index ff9a29b76336335b5ad8e3e61e3b52524c607714..347c3ed1d9f15fbe1edd10944b6b44b72ace07ac 100644 (file)
@@ -124,65 +124,53 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
        return;
 }
 
+static int ixj_config_check(struct pcmcia_device *p_dev,
+                           cistpl_cftable_entry_t *cfg,
+                           cistpl_cftable_entry_t *dflt,
+                           unsigned int vcc,
+                           void *priv_data)
+{
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+               if (io->nwin == 2) {
+                       p_dev->io.BasePort2 = io->win[1].base;
+                       p_dev->io.NumPorts2 = io->win[1].len;
+               }
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       }
+       return -ENODEV;
+}
+
 static int ixj_config(struct pcmcia_device * link)
 {
        IXJ *j;
        ixj_info_t *info;
-       tuple_t tuple;
-       u_short buf[128];
-       cisparse_t parse;
-       cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
-       cistpl_cftable_entry_t dflt =
-       {
-               0
-       };
-       int last_ret, last_fn;
+       cistpl_cftable_entry_t dflt = { 0 };
+
        info = link->priv;
        DEBUG(0, "ixj_config(0x%p)\n", link);
-       tuple.TupleData = (cisdata_t *) buf;
-       tuple.TupleOffset = 0;
-       tuple.TupleDataMax = 255;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       tuple.Attributes = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-                               pcmcia_parse_tuple(link, &tuple, &parse) != 0)
-                       goto next_entry;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-                       link->conf.ConfigIndex = cfg->index;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-                       if (io->nwin == 2) {
-                               link->io.BasePort2 = io->win[1].base;
-                               link->io.NumPorts2 = io->win[1].len;
-                       }
-                       if (pcmcia_request_io(link, &link->io) != 0)
-                               goto next_entry;
-                       /* If we've got this far, we're done */
-                       break;
-               }
-             next_entry:
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-                       dflt = *cfg;
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-       }
 
-       CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+       if (pcmcia_loop_config(link, ixj_config_check, &dflt))
+               goto cs_failed;
+
+       if (pcmcia_request_configuration(link, &link->conf))
+               goto cs_failed;
 
        /*
         *      Register the card with the core.
-        */     
-       j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10);
+        */
+       j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10);
 
        info->ndev = 1;
        info->node.major = PHONE_MAJOR;
        link->dev_node = &info->node;
        ixj_get_serial(link, j);
        return 0;
+
       cs_failed:
-       cs_error(link, last_fn, last_ret);
        ixj_cs_release(link);
        return -ENODEV;
 }
index 4190be64917f416be6f4809929bf0e23b78a755d..04b954cfce7608827a821138df74db9caccb9f80 100644 (file)
@@ -58,4 +58,17 @@ config UIO_SMX
 
          If you compile this as a module, it will be called uio_smx.
 
+config UIO_SERCOS3
+       tristate "Automata Sercos III PCI card driver"
+       default n
+       help
+         Userspace I/O interface for the Sercos III PCI card from
+         Automata GmbH. The userspace part of this driver will be
+         available for download from the Automata GmbH web site.
+
+         Automata GmbH:        http://www.automataweb.com
+         Sercos III interface: http://www.sercos.com
+
+         If you compile this as a module, it will be called uio_sercos3.
+
 endif
index 8667bbdef904fc3ddd2df2d1208938f5fdcc2a7e..e69558149859f0dd36b1d0433190d6e06773aafa 100644 (file)
@@ -3,3 +3,4 @@ obj-$(CONFIG_UIO_CIF)   += uio_cif.o
 obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)  += uio_pdrv_genirq.o
 obj-$(CONFIG_UIO_SMX)  += uio_smx.o
+obj-$(CONFIG_UIO_SERCOS3)      += uio_sercos3.o
index 3a6934bf713134edc3f53b68e25bf913ec3215e4..5dccf057a7dd41a5f31f69ec4d5d7982615655ec 100644 (file)
@@ -67,6 +67,11 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
        return sprintf(buf, "0x%lx\n", mem->size);
 }
 
+static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
+{
+       return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
+}
+
 struct uio_sysfs_entry {
        struct attribute attr;
        ssize_t (*show)(struct uio_mem *, char *);
@@ -77,10 +82,13 @@ static struct uio_sysfs_entry addr_attribute =
        __ATTR(addr, S_IRUGO, map_addr_show, NULL);
 static struct uio_sysfs_entry size_attribute =
        __ATTR(size, S_IRUGO, map_size_show, NULL);
+static struct uio_sysfs_entry offset_attribute =
+       __ATTR(offset, S_IRUGO, map_offset_show, NULL);
 
 static struct attribute *attrs[] = {
        &addr_attribute.attr,
        &size_attribute.attr,
+       &offset_attribute.attr,
        NULL,   /* need to NULL terminate the list of attributes */
 };
 
@@ -482,15 +490,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct uio_device *idev = vma->vm_private_data;
        struct page *page;
+       unsigned long offset;
 
        int mi = uio_find_mem_index(vma);
        if (mi < 0)
                return VM_FAULT_SIGBUS;
 
+       /*
+        * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
+        * to use mem[N].
+        */
+       offset = (vmf->pgoff - mi) << PAGE_SHIFT;
+
        if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
-               page = virt_to_page(idev->info->mem[mi].addr);
+               page = virt_to_page(idev->info->mem[mi].addr + offset);
        else
-               page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
+               page = vmalloc_to_page((void *)idev->info->mem[mi].addr
+                                                       + offset);
        get_page(page);
        vmf->page = page;
        return 0;
@@ -682,9 +698,9 @@ int __uio_register_device(struct module *owner,
        if (ret)
                goto err_get_minor;
 
-       idev->dev = device_create_drvdata(uio_class->class, parent,
-                                         MKDEV(uio_major, idev->minor), idev,
-                                         "uio%d", idev->minor);
+       idev->dev = device_create(uio_class->class, parent,
+                                 MKDEV(uio_major, idev->minor), idev,
+                                 "uio%d", idev->minor);
        if (IS_ERR(idev->dev)) {
                printk(KERN_ERR "UIO: device register failed\n");
                ret = PTR_ERR(idev->dev);
index 0b4ef39cd85d289d3aee60264dd6044bee1f0b8b..d494ce9288c37e9b59c34962c66b291f7185a313 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/uio_driver.h>
 #include <linux/stringify.h>
 
-#define DRIVER_NAME "uio"
+#define DRIVER_NAME "uio_pdrv"
 
 struct uio_platdata {
        struct uio_info *uioinfo;
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
new file mode 100644 (file)
index 0000000..a6d1b2b
--- /dev/null
@@ -0,0 +1,243 @@
+/* sercos3: UIO driver for the Automata Sercos III PCI card
+
+   Copyright (C) 2008 Linutronix GmbH
+     Author: John Ogness <john.ogness@linutronix.de>
+
+   This is a straight-forward UIO driver, where interrupts are disabled
+   by the interrupt handler and re-enabled via a write to the UIO device
+   by the userspace-part.
+
+   The only part that may seem odd is the use of a logical OR when
+   storing and restoring enabled interrupts. This is done because the
+   userspace-part could directly modify the Interrupt Enable Register
+   at any time. To reduce possible conflicts, the kernel driver uses
+   a logical OR to make more controlled changes (rather than blindly
+   overwriting previous values).
+
+   Race conditions exist if the userspace-part directly modifies the
+   Interrupt Enable Register while in operation. The consequences are
+   that certain interrupts would fail to be enabled or disabled. For
+   this reason, the userspace-part should only directly modify the
+   Interrupt Enable Register at the beginning (to get things going).
+   The userspace-part can safely disable interrupts at any time using
+   a write to the UIO device.
+*/
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+#include <linux/io.h>
+
+/* ID's for SERCOS III PCI card (PLX 9030) */
+#define SERCOS_SUB_VENDOR_ID  0x1971
+#define SERCOS_SUB_SYSID_3530 0x3530
+#define SERCOS_SUB_SYSID_3535 0x3535
+#define SERCOS_SUB_SYSID_3780 0x3780
+
+/* Interrupt Enable Register */
+#define IER0_OFFSET 0x08
+
+/* Interrupt Status Register */
+#define ISR0_OFFSET 0x18
+
+struct sercos3_priv {
+       u32 ier0_cache;
+       spinlock_t ier0_cache_lock;
+};
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_disable_interrupts(struct uio_info *info,
+                                      struct sercos3_priv *priv)
+{
+       void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+       /* add enabled interrupts to cache */
+       priv->ier0_cache |= ioread32(ier0);
+
+       /* disable interrupts */
+       iowrite32(0, ier0);
+}
+
+/* this function assumes ier0_cache_lock is locked! */
+static void sercos3_enable_interrupts(struct uio_info *info,
+                                     struct sercos3_priv *priv)
+{
+       void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+       /* restore previously enabled interrupts */
+       iowrite32(ioread32(ier0) | priv->ier0_cache, ier0);
+       priv->ier0_cache = 0;
+}
+
+static irqreturn_t sercos3_handler(int irq, struct uio_info *info)
+{
+       struct sercos3_priv *priv = info->priv;
+       void __iomem *isr0 = info->mem[3].internal_addr + ISR0_OFFSET;
+       void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
+
+       if (!(ioread32(isr0) & ioread32(ier0)))
+               return IRQ_NONE;
+
+       spin_lock(&priv->ier0_cache_lock);
+       sercos3_disable_interrupts(info, priv);
+       spin_unlock(&priv->ier0_cache_lock);
+
+       return IRQ_HANDLED;
+}
+
+static int sercos3_irqcontrol(struct uio_info *info, s32 irq_on)
+{
+       struct sercos3_priv *priv = info->priv;
+
+       spin_lock_irq(&priv->ier0_cache_lock);
+       if (irq_on)
+               sercos3_enable_interrupts(info, priv);
+       else
+               sercos3_disable_interrupts(info, priv);
+       spin_unlock_irq(&priv->ier0_cache_lock);
+
+       return 0;
+}
+
+static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
+                              int n, int pci_bar)
+{
+       info->mem[n].addr = pci_resource_start(dev, pci_bar);
+       if (!info->mem[n].addr)
+               return -1;
+       info->mem[n].internal_addr = ioremap(pci_resource_start(dev, pci_bar),
+                                            pci_resource_len(dev, pci_bar));
+       if (!info->mem[n].internal_addr)
+               return -1;
+       info->mem[n].size = pci_resource_len(dev, pci_bar);
+       info->mem[n].memtype = UIO_MEM_PHYS;
+       return 0;
+}
+
+static int __devinit sercos3_pci_probe(struct pci_dev *dev,
+                                      const struct pci_device_id *id)
+{
+       struct uio_info *info;
+       struct sercos3_priv *priv;
+       int i;
+
+       info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       priv = kzalloc(sizeof(struct sercos3_priv), GFP_KERNEL);
+       if (!priv)
+               goto out_free;
+
+       if (pci_enable_device(dev))
+               goto out_free_priv;
+
+       if (pci_request_regions(dev, "sercos3"))
+               goto out_disable;
+
+       /* we only need PCI BAR's 0, 2, 3, 4, 5 */
+       if (sercos3_setup_iomem(dev, info, 0, 0))
+               goto out_unmap;
+       if (sercos3_setup_iomem(dev, info, 1, 2))
+               goto out_unmap;
+       if (sercos3_setup_iomem(dev, info, 2, 3))
+               goto out_unmap;
+       if (sercos3_setup_iomem(dev, info, 3, 4))
+               goto out_unmap;
+       if (sercos3_setup_iomem(dev, info, 4, 5))
+               goto out_unmap;
+
+       spin_lock_init(&priv->ier0_cache_lock);
+       info->priv = priv;
+       info->name = "Sercos_III_PCI";
+       info->version = "0.0.1";
+       info->irq = dev->irq;
+       info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
+       info->handler = sercos3_handler;
+       info->irqcontrol = sercos3_irqcontrol;
+
+       pci_set_drvdata(dev, info);
+
+       if (uio_register_device(&dev->dev, info))
+               goto out_unmap;
+
+       return 0;
+
+out_unmap:
+       for (i = 0; i < 5; i++) {
+               if (info->mem[i].internal_addr)
+                       iounmap(info->mem[i].internal_addr);
+       }
+       pci_release_regions(dev);
+out_disable:
+       pci_disable_device(dev);
+out_free_priv:
+       kfree(priv);
+out_free:
+       kfree(info);
+       return -ENODEV;
+}
+
+static void sercos3_pci_remove(struct pci_dev *dev)
+{
+       struct uio_info *info = pci_get_drvdata(dev);
+       int i;
+
+       uio_unregister_device(info);
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+       pci_set_drvdata(dev, NULL);
+       for (i = 0; i < 5; i++) {
+               if (info->mem[i].internal_addr)
+                       iounmap(info->mem[i].internal_addr);
+       }
+       kfree(info->priv);
+       kfree(info);
+}
+
+static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
+       {
+               .vendor =       PCI_VENDOR_ID_PLX,
+               .device =       PCI_DEVICE_ID_PLX_9030,
+               .subvendor =    SERCOS_SUB_VENDOR_ID,
+               .subdevice =    SERCOS_SUB_SYSID_3530,
+       },
+       {
+               .vendor =       PCI_VENDOR_ID_PLX,
+               .device =       PCI_DEVICE_ID_PLX_9030,
+               .subvendor =    SERCOS_SUB_VENDOR_ID,
+               .subdevice =    SERCOS_SUB_SYSID_3535,
+       },
+       {
+               .vendor =       PCI_VENDOR_ID_PLX,
+               .device =       PCI_DEVICE_ID_PLX_9030,
+               .subvendor =    SERCOS_SUB_VENDOR_ID,
+               .subdevice =    SERCOS_SUB_SYSID_3780,
+       },
+       { 0, }
+};
+
+static struct pci_driver sercos3_pci_driver = {
+       .name = "sercos3",
+       .id_table = sercos3_pci_ids,
+       .probe = sercos3_pci_probe,
+       .remove = sercos3_pci_remove,
+};
+
+static int __init sercos3_init_module(void)
+{
+       return pci_register_driver(&sercos3_pci_driver);
+}
+
+static void __exit sercos3_exit_module(void)
+{
+       pci_unregister_driver(&sercos3_pci_driver);
+}
+
+module_init(sercos3_init_module);
+module_exit(sercos3_exit_module);
+
+MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card");
+MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
+MODULE_LICENSE("GPL v2");
index 20290c5b15625c3b4272765ff95eefa3feb07b88..7a4fa791dc196f18a042e4c203ca21b5a0313e97 100644 (file)
@@ -1729,9 +1729,9 @@ static int usb_classdev_add(struct usb_device *dev)
 {
        struct device *cldev;
 
-       cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
-                                     dev->dev.devt, NULL, "usbdev%d.%d",
-                                     dev->bus->busnum, dev->devnum);
+       cldev = device_create(usb_classdev_class, &dev->dev, dev->dev.devt,
+                             NULL, "usbdev%d.%d", dev->bus->busnum,
+                             dev->devnum);
        if (IS_ERR(cldev))
                return PTR_ERR(cldev);
        dev->usb_classdev = cldev;
index 6b1b229e38cd1d28790d5f29e54eebbe3efe2fb8..55f7f310924b99f434ba6201525c2b85b48e27ba 100644 (file)
@@ -196,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
                ++temp;
        else
                temp = name;
-       intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
-                                             MKDEV(USB_MAJOR, minor), NULL,
-                                             "%s", temp);
+       intf->usb_dev = device_create(usb_class->class, &intf->dev,
+                                     MKDEV(USB_MAJOR, minor), NULL,
+                                     "%s", temp);
        if (IS_ERR(intf->usb_dev)) {
                down_write(&minor_rwsem);
                usb_minors[intf->minor] = NULL;
index 8ab389dca2b91c49bfdb75e900a1c5a5dde3d334..c8035a8216bdb5017435c7ad49a5d555b2cce8e9 100644 (file)
@@ -818,9 +818,8 @@ static int usb_register_bus(struct usb_bus *bus)
        set_bit (busnum, busmap.busmap);
        bus->busnum = busnum;
 
-       bus->dev = device_create_drvdata(usb_host_class, bus->controller,
-                                        MKDEV(0, 0), bus,
-                                        "usb_host%d", busnum);
+       bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
+                                bus, "usb_host%d", busnum);
        result = PTR_ERR(bus->dev);
        if (IS_ERR(bus->dev))
                goto error_create_class_dev;
index db410e92c80da6f9d489ce77fe3942e4b414fc64..77fa7a0808019f55033d05b03d94f8118a010a0f 100644 (file)
@@ -97,7 +97,7 @@ enum {
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_devuid, "devuid=%u"},
        {Opt_devgid, "devgid=%u"},
        {Opt_devmode, "devmode=%o"},
index fcb5cb9094d905d7e26c35a7dae074fc28b633bd..2267fa0b51b20e28e230b9cd5a802a9b3ea44f5f 100644 (file)
@@ -22,24 +22,15 @@ obj-$(CONFIG_USB_M66592)    += m66592-udc.o
 #
 # USB gadget drivers
 #
-C_UTILS =      composite.o usbstring.o config.o epautoconf.o
-
-g_zero-objs                    := zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
-g_ether-objs                   := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
-g_serial-objs                  := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
-g_midi-objs                    := gmidi.o usbstring.o config.o epautoconf.o
+g_zero-objs                    := zero.o
+g_ether-objs                   := ether.o
+g_serial-objs                  := serial.o
+g_midi-objs                    := gmidi.o
 gadgetfs-objs                  := inode.o
-g_file_storage-objs            := file_storage.o usbstring.o config.o \
-                                       epautoconf.o
-g_printer-objs                 := printer.o usbstring.o config.o \
-                                       epautoconf.o
-g_cdc-objs                     := cdc2.o u_ether.o f_ecm.o \
-                                       u_serial.o f_acm.o $(C_UTILS)
+g_file_storage-objs            := file_storage.o
+g_printer-objs                 := printer.o
+g_cdc-objs                     := cdc2.o
 
-ifeq ($(CONFIG_USB_ETH_RNDIS),y)
-       g_ether-objs            += f_rndis.o rndis.o
-endif
 obj-$(CONFIG_USB_ZERO)         += g_zero.o
 obj-$(CONFIG_USB_ETH)          += g_ether.o
 obj-$(CONFIG_USB_GADGETFS)     += gadgetfs.o
index a39a4b940c33c93aa129fb5aab06fd4c326e556d..a724fc149850ad30deef93e73b6da96879cadd99 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+#include "u_serial.c"
+#include "f_acm.c"
+#include "f_ecm.c"
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_device_descriptor device_desc = {
        .bLength =              sizeof device_desc,
        .bDescriptorType =      USB_DT_DEVICE,
@@ -148,7 +167,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
        int                     status;
 
        if (!can_support_ecm(cdev->gadget)) {
-               ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+               dev_err(&gadget->dev, "controller '%s' not usable\n",
+                               gadget->name);
                return -EINVAL;
        }
 
@@ -203,7 +223,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
        if (status < 0)
                goto fail1;
 
-       INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+       dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+                       DRIVER_DESC);
 
        return 0;
 
index bcac2e68660d5ba51fd8c253fa136c4385e9c058..944c8e889ab4368bae56b96a679aeb590323648a 100644 (file)
@@ -96,6 +96,28 @@ static inline bool has_rndis(void)
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_ecm.c"
+#include "f_subset.c"
+#ifdef CONFIG_USB_ETH_RNDIS
+#include "f_rndis.c"
+#include "rndis.c"
+#endif
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
 /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
@@ -293,7 +315,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
                 * but if the controller isn't recognized at all then
                 * that assumption is a bit more likely to be wrong.
                 */
-               WARNING(cdev, "controller '%s' not recognized; trying %s\n",
+               dev_warn(&gadget->dev,
+                               "controller '%s' not recognized; trying %s\n",
                                gadget->name,
                                eth_config_driver.label);
                device_desc.bcdDevice =
@@ -332,7 +355,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        if (status < 0)
                goto fail;
 
-       INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+       dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
+                       DRIVER_DESC);
 
        return 0;
 
index a2b5c092bda039bdf0c1cd70b7d4bc2d6445cc99..4ae579948e54dc67288499cea56929b220e98ebe 100644 (file)
@@ -83,7 +83,7 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
 }
 
 /* peak (theoretical) bulk transfer rate in bits-per-second */
-static inline unsigned bitrate(struct usb_gadget *g)
+static inline unsigned ecm_bitrate(struct usb_gadget *g)
 {
        if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
                return 13 * 512 * 8 * 1000 * 8;
@@ -107,7 +107,7 @@ static inline unsigned bitrate(struct usb_gadget *g)
  */
 
 #define LOG2_STATUS_INTERVAL_MSEC      5       /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT               16      /* 8 byte header + data */
+#define ECM_STATUS_BYTECOUNT           16      /* 8 byte header + data */
 
 
 /* interface descriptor: */
@@ -125,8 +125,8 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
        /* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc header_desc __initdata = {
-       .bLength =              sizeof header_desc,
+static struct usb_cdc_header_desc ecm_header_desc __initdata = {
+       .bLength =              sizeof ecm_header_desc,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubType =   USB_CDC_HEADER_TYPE,
 
@@ -141,8 +141,8 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
        /* .bSlaveInterface0 =  DYNAMIC */
 };
 
-static struct usb_cdc_ether_desc ether_desc __initdata = {
-       .bLength =              sizeof ether_desc,
+static struct usb_cdc_ether_desc ecm_desc __initdata = {
+       .bLength =              sizeof ecm_desc,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubType =   USB_CDC_ETHERNET_TYPE,
 
@@ -186,17 +186,17 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       __constant_cpu_to_le16(STATUS_BYTECOUNT),
+       .wMaxPacketSize =       __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
        .bInterval =            1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -204,7 +204,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -212,34 +212,34 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
        /* CDC ECM control descriptors */
        (struct usb_descriptor_header *) &ecm_control_intf,
-       (struct usb_descriptor_header *) &header_desc,
+       (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
-       (struct usb_descriptor_header *) &ether_desc,
+       (struct usb_descriptor_header *) &ecm_desc,
        /* NOTE: status endpoint might need to be removed */
-       (struct usb_descriptor_header *) &fs_notify_desc,
+       (struct usb_descriptor_header *) &fs_ecm_notify_desc,
        /* data interface, altsettings 0 and 1 */
        (struct usb_descriptor_header *) &ecm_data_nop_intf,
        (struct usb_descriptor_header *) &ecm_data_intf,
-       (struct usb_descriptor_header *) &fs_in_desc,
-       (struct usb_descriptor_header *) &fs_out_desc,
+       (struct usb_descriptor_header *) &fs_ecm_in_desc,
+       (struct usb_descriptor_header *) &fs_ecm_out_desc,
        NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       __constant_cpu_to_le16(STATUS_BYTECOUNT),
+       .wMaxPacketSize =       __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
        .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
 };
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
        .wMaxPacketSize =       __constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -257,19 +257,19 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
        .wMaxPacketSize =       __constant_cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
        /* CDC ECM control descriptors */
        (struct usb_descriptor_header *) &ecm_control_intf,
-       (struct usb_descriptor_header *) &header_desc,
+       (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
-       (struct usb_descriptor_header *) &ether_desc,
+       (struct usb_descriptor_header *) &ecm_desc,
        /* NOTE: status endpoint might need to be removed */
-       (struct usb_descriptor_header *) &hs_notify_desc,
+       (struct usb_descriptor_header *) &hs_ecm_notify_desc,
        /* data interface, altsettings 0 and 1 */
        (struct usb_descriptor_header *) &ecm_data_nop_intf,
        (struct usb_descriptor_header *) &ecm_data_intf,
-       (struct usb_descriptor_header *) &hs_in_desc,
-       (struct usb_descriptor_header *) &hs_out_desc,
+       (struct usb_descriptor_header *) &hs_ecm_in_desc,
+       (struct usb_descriptor_header *) &hs_ecm_out_desc,
        NULL,
 };
 
@@ -329,14 +329,14 @@ static void ecm_do_notify(struct f_ecm *ecm)
                event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
                event->wValue = cpu_to_le16(0);
                event->wLength = cpu_to_le16(8);
-               req->length = STATUS_BYTECOUNT;
+               req->length = ECM_STATUS_BYTECOUNT;
 
                /* SPEED_CHANGE data is up/down speeds in bits/sec */
                data = req->buf + sizeof *event;
-               data[0] = cpu_to_le32(bitrate(cdev->gadget));
+               data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
                data[1] = data[0];
 
-               DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+               DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
                ecm->notify_state = ECM_NOTIFY_NONE;
                break;
        }
@@ -628,13 +628,13 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        status = -ENODEV;
 
        /* allocate instance-specific endpoints */
-       ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
        if (!ep)
                goto fail;
        ecm->port.in_ep = ep;
        ep->driver_data = cdev; /* claim */
 
-       ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
        if (!ep)
                goto fail;
        ecm->port.out_ep = ep;
@@ -644,7 +644,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
         * don't treat it that way.  It's simpler, and some newer CDC
         * profiles (wireless handsets) no longer treat it as optional.
         */
-       ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
        if (!ep)
                goto fail;
        ecm->notify = ep;
@@ -656,47 +656,47 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
        if (!ecm->notify_req)
                goto fail;
-       ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+       ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
        if (!ecm->notify_req->buf)
                goto fail;
        ecm->notify_req->context = ecm;
        ecm->notify_req->complete = ecm_notify_complete;
 
        /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(eth_fs_function);
+       f->descriptors = usb_copy_descriptors(ecm_fs_function);
        if (!f->descriptors)
                goto fail;
 
-       ecm->fs.in = usb_find_endpoint(eth_fs_function,
-                       f->descriptors, &fs_in_desc);
-       ecm->fs.out = usb_find_endpoint(eth_fs_function,
-                       f->descriptors, &fs_out_desc);
-       ecm->fs.notify = usb_find_endpoint(eth_fs_function,
-                       f->descriptors, &fs_notify_desc);
+       ecm->fs.in = usb_find_endpoint(ecm_fs_function,
+                       f->descriptors, &fs_ecm_in_desc);
+       ecm->fs.out = usb_find_endpoint(ecm_fs_function,
+                       f->descriptors, &fs_ecm_out_desc);
+       ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
+                       f->descriptors, &fs_ecm_notify_desc);
 
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
        if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_in_desc.bEndpointAddress =
-                               fs_in_desc.bEndpointAddress;
-               hs_out_desc.bEndpointAddress =
-                               fs_out_desc.bEndpointAddress;
-               hs_notify_desc.bEndpointAddress =
-                               fs_notify_desc.bEndpointAddress;
+               hs_ecm_in_desc.bEndpointAddress =
+                               fs_ecm_in_desc.bEndpointAddress;
+               hs_ecm_out_desc.bEndpointAddress =
+                               fs_ecm_out_desc.bEndpointAddress;
+               hs_ecm_notify_desc.bEndpointAddress =
+                               fs_ecm_notify_desc.bEndpointAddress;
 
                /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+               f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
                if (!f->hs_descriptors)
                        goto fail;
 
-               ecm->hs.in = usb_find_endpoint(eth_hs_function,
-                               f->hs_descriptors, &hs_in_desc);
-               ecm->hs.out = usb_find_endpoint(eth_hs_function,
-                               f->hs_descriptors, &hs_out_desc);
-               ecm->hs.notify = usb_find_endpoint(eth_hs_function,
-                               f->hs_descriptors, &hs_notify_desc);
+               ecm->hs.in = usb_find_endpoint(ecm_hs_function,
+                               f->hs_descriptors, &hs_ecm_in_desc);
+               ecm->hs.out = usb_find_endpoint(ecm_hs_function,
+                               f->hs_descriptors, &hs_ecm_out_desc);
+               ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
+                               f->hs_descriptors, &hs_ecm_notify_desc);
        }
 
        /* NOTE:  all that is done without knowing or caring about
@@ -795,7 +795,7 @@ int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
                if (status < 0)
                        return status;
                ecm_string_defs[1].id = status;
-               ether_desc.iMACAddress = status;
+               ecm_desc.iMACAddress = status;
        }
 
        /* allocate and initialize one new instance */
index eda4cde72c824c1aac2de550cfe24e7ae2ca5929..87dde012dacc8d251e25fc1d23eb73eeb1cf684a 100644 (file)
@@ -70,7 +70,7 @@ static struct usb_interface_descriptor loopback_intf = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_source_desc = {
+static struct usb_endpoint_descriptor fs_loop_source_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -78,7 +78,7 @@ static struct usb_endpoint_descriptor fs_source_desc = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_sink_desc = {
+static struct usb_endpoint_descriptor fs_loop_sink_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -88,14 +88,14 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
 
 static struct usb_descriptor_header *fs_loopback_descs[] = {
        (struct usb_descriptor_header *) &loopback_intf,
-       (struct usb_descriptor_header *) &fs_sink_desc,
-       (struct usb_descriptor_header *) &fs_source_desc,
+       (struct usb_descriptor_header *) &fs_loop_sink_desc,
+       (struct usb_descriptor_header *) &fs_loop_source_desc,
        NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_source_desc = {
+static struct usb_endpoint_descriptor hs_loop_source_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -103,7 +103,7 @@ static struct usb_endpoint_descriptor hs_source_desc = {
        .wMaxPacketSize =       __constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_sink_desc = {
+static struct usb_endpoint_descriptor hs_loop_sink_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -113,8 +113,8 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
 
 static struct usb_descriptor_header *hs_loopback_descs[] = {
        (struct usb_descriptor_header *) &loopback_intf,
-       (struct usb_descriptor_header *) &hs_source_desc,
-       (struct usb_descriptor_header *) &hs_sink_desc,
+       (struct usb_descriptor_header *) &hs_loop_source_desc,
+       (struct usb_descriptor_header *) &hs_loop_sink_desc,
        NULL,
 };
 
@@ -152,7 +152,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
 
        /* allocate endpoints */
 
-       loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+       loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
        if (!loop->in_ep) {
 autoconf_fail:
                ERROR(cdev, "%s: can't autoconfigure on %s\n",
@@ -161,17 +161,17 @@ autoconf_fail:
        }
        loop->in_ep->driver_data = cdev;        /* claim */
 
-       loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+       loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
        if (!loop->out_ep)
                goto autoconf_fail;
        loop->out_ep->driver_data = cdev;       /* claim */
 
        /* support high speed hardware */
        if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_source_desc.bEndpointAddress =
-                               fs_source_desc.bEndpointAddress;
-               hs_sink_desc.bEndpointAddress =
-                               fs_sink_desc.bEndpointAddress;
+               hs_loop_source_desc.bEndpointAddress =
+                               fs_loop_source_desc.bEndpointAddress;
+               hs_loop_sink_desc.bEndpointAddress =
+                               fs_loop_sink_desc.bEndpointAddress;
                f->hs_descriptors = hs_loopback_descs;
        }
 
@@ -255,8 +255,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
        struct usb_request                      *req;
        unsigned                                i;
 
-       src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
-       sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+       src = ep_choose(cdev->gadget,
+                       &hs_loop_source_desc, &fs_loop_source_desc);
+       sink = ep_choose(cdev->gadget,
+                       &hs_loop_sink_desc, &fs_loop_sink_desc);
 
        /* one endpoint writes data back IN to the host */
        ep = loop->in_ep;
index acb8d233aa1d24a02a5acc855a040755b809013b..fe1832875771539ec72d0fa693968a548a26fd79 100644 (file)
@@ -103,8 +103,8 @@ static struct usb_interface_descriptor subset_data_intf __initdata = {
        /* .iInterface = DYNAMIC */
 };
 
-static struct usb_cdc_header_desc header_desc __initdata = {
-       .bLength =              sizeof header_desc,
+static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+       .bLength =              sizeof mdlm_header_desc,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubType =   USB_CDC_HEADER_TYPE,
 
@@ -152,7 +152,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -160,7 +160,7 @@ static struct usb_endpoint_descriptor fs_in_desc __initdata = {
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -170,18 +170,18 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
 
 static struct usb_descriptor_header *fs_eth_function[] __initdata = {
        (struct usb_descriptor_header *) &subset_data_intf,
-       (struct usb_descriptor_header *) &header_desc,
+       (struct usb_descriptor_header *) &mdlm_header_desc,
        (struct usb_descriptor_header *) &mdlm_desc,
        (struct usb_descriptor_header *) &mdlm_detail_desc,
        (struct usb_descriptor_header *) &ether_desc,
-       (struct usb_descriptor_header *) &fs_in_desc,
-       (struct usb_descriptor_header *) &fs_out_desc,
+       (struct usb_descriptor_header *) &fs_subset_in_desc,
+       (struct usb_descriptor_header *) &fs_subset_out_desc,
        NULL,
 };
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -189,7 +189,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
        .wMaxPacketSize =       __constant_cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
 
@@ -199,12 +199,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
 
 static struct usb_descriptor_header *hs_eth_function[] __initdata = {
        (struct usb_descriptor_header *) &subset_data_intf,
-       (struct usb_descriptor_header *) &header_desc,
+       (struct usb_descriptor_header *) &mdlm_header_desc,
        (struct usb_descriptor_header *) &mdlm_desc,
        (struct usb_descriptor_header *) &mdlm_detail_desc,
        (struct usb_descriptor_header *) &ether_desc,
-       (struct usb_descriptor_header *) &hs_in_desc,
-       (struct usb_descriptor_header *) &hs_out_desc,
+       (struct usb_descriptor_header *) &hs_subset_in_desc,
+       (struct usb_descriptor_header *) &hs_subset_out_desc,
        NULL,
 };
 
@@ -281,13 +281,13 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        status = -ENODEV;
 
        /* allocate instance-specific endpoints */
-       ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_in_desc);
        if (!ep)
                goto fail;
        geth->port.in_ep = ep;
        ep->driver_data = cdev; /* claim */
 
-       ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+       ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
        if (!ep)
                goto fail;
        geth->port.out_ep = ep;
@@ -297,9 +297,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        f->descriptors = usb_copy_descriptors(fs_eth_function);
 
        geth->fs.in = usb_find_endpoint(fs_eth_function,
-                       f->descriptors, &fs_in_desc);
+                       f->descriptors, &fs_subset_in_desc);
        geth->fs.out = usb_find_endpoint(fs_eth_function,
-                       f->descriptors, &fs_out_desc);
+                       f->descriptors, &fs_subset_out_desc);
 
 
        /* support all relevant hardware speeds... we expect that when
@@ -307,18 +307,18 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
         * both speeds
         */
        if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_in_desc.bEndpointAddress =
-                               fs_in_desc.bEndpointAddress;
-               hs_out_desc.bEndpointAddress =
-                               fs_out_desc.bEndpointAddress;
+               hs_subset_in_desc.bEndpointAddress =
+                               fs_subset_in_desc.bEndpointAddress;
+               hs_subset_out_desc.bEndpointAddress =
+                               fs_subset_out_desc.bEndpointAddress;
 
                /* copy descriptors, and track endpoint copies */
                f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
 
                geth->hs.in = usb_find_endpoint(hs_eth_function,
-                               f->hs_descriptors, &hs_in_desc);
+                               f->hs_descriptors, &hs_subset_in_desc);
                geth->hs.out = usb_find_endpoint(hs_eth_function,
-                               f->hs_descriptors, &hs_out_desc);
+                               f->hs_descriptors, &hs_subset_out_desc);
        }
 
        /* NOTE:  all that is done without knowing or caring about
index ea2c31d18080d2a23025979a4c798f5133ceba48..0c632d22a6315a116beb9bb28a06b0d273322478 100644 (file)
 #include "gadget_chips.h"
 
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
 /*-------------------------------------------------------------------------*/
 
 #define DRIVER_DESC            "File-backed Storage Gadget"
index ea8651e3da1a53a205ffe67e88889b87d5073a89..6eee760410d6c052492cc854ea11cbc1ac840ffa 100644 (file)
 
 #include "gadget_chips.h"
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
+
 MODULE_AUTHOR("Ben Williamson");
 MODULE_LICENSE("GPL v2");
 
index e0090085b78ee74824ff2a3940a419a129e9570b..2b3b9e1dd2ee2987c3ee1420802a7544af2597f9 100644 (file)
 
 #include "gadget_chips.h"
 
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+/*-------------------------------------------------------------------------*/
+
 #define DRIVER_DESC            "Printer Gadget"
 #define DRIVER_VERSION         "2007 OCT 06"
 
@@ -1360,8 +1374,8 @@ printer_bind(struct usb_gadget *gadget)
 
 
        /* Setup the sysfs files for the printer gadget. */
-       dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
-                                         g_printer_devno, NULL, "g_printer");
+       dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
+                                 NULL, "g_printer");
        if (IS_ERR(dev->pdev)) {
                ERROR(dev, "Failed to create device: g_printer\n");
                goto fail;
index 7228e856223626dab7e568eb0f1252391758a95b..8c26f5ea2b839070fe2afb6d8a41c66a36aeaafa 100644 (file)
@@ -57,11 +57,6 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
 #define rndis_debug            0
 #endif
 
-#define DBG(str,args...) do { \
-       if (rndis_debug) \
-               pr_debug(str , ## args); \
-       } while (0)
-
 #define RNDIS_MAX_CONFIGS      1
 
 
@@ -183,9 +178,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        if (!resp) return -ENOMEM;
 
        if (buf_len && rndis_debug > 1) {
-               DBG("query OID %08x value, len %d:\n", OID, buf_len);
+               pr_debug("query OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
-                       DBG("%03d: %08x %08x %08x %08x\n", i,
+                       pr_debug("%03d: %08x %08x %08x %08x\n", i,
                                get_unaligned_le32(&buf[i]),
                                get_unaligned_le32(&buf[i + 4]),
                                get_unaligned_le32(&buf[i + 8]),
@@ -209,7 +204,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_SUPPORTED_LIST:
-               DBG("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
+               pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
                length = sizeof (oid_supported_list);
                count  = length / sizeof (u32);
                for (i = 0; i < count; i++)
@@ -219,7 +214,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_HARDWARE_STATUS:
-               DBG("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
+               pr_debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
                /* Bogus question!
                 * Hardware must be ready to receive high level protocols.
                 * BTW:
@@ -232,14 +227,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MEDIA_SUPPORTED:
-               DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
+               pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MEDIA_IN_USE:
-               DBG("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
+               pr_debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
                /* one medium, one transport... (maybe you do it better) */
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
                retval = 0;
@@ -247,7 +242,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_MAXIMUM_FRAME_SIZE:
-               DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
+               pr_debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -258,7 +253,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_LINK_SPEED:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_LINK_SPEED\n", __func__);
+                       pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
                if (rndis_per_dev_params [configNr].media_state
                                == NDIS_MEDIA_STATE_DISCONNECTED)
                        *outbuf = __constant_cpu_to_le32 (0);
@@ -270,7 +265,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-               DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
+               pr_debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -280,7 +275,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RECEIVE_BLOCK_SIZE:
-               DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
+               pr_debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        *outbuf = cpu_to_le32 (
                                rndis_per_dev_params [configNr].dev->mtu);
@@ -290,7 +285,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_ID:
-               DBG("%s: OID_GEN_VENDOR_ID\n", __func__);
+               pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
                *outbuf = cpu_to_le32 (
                        rndis_per_dev_params [configNr].vendorID);
                retval = 0;
@@ -298,7 +293,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_VENDOR_DESCRIPTION:
-               DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
+               pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
                length = strlen (rndis_per_dev_params [configNr].vendorDescr);
                memcpy (outbuf,
                        rndis_per_dev_params [configNr].vendorDescr, length);
@@ -306,7 +301,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
 
        case OID_GEN_VENDOR_DRIVER_VERSION:
-               DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
+               pr_debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
                /* Created as LE */
                *outbuf = rndis_driver_version;
                retval = 0;
@@ -314,14 +309,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_CURRENT_PACKET_FILTER:
-               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
+               pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
                *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_GEN_MAXIMUM_TOTAL_SIZE:
-               DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
+               pr_debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
                *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
                retval = 0;
                break;
@@ -329,14 +324,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_MEDIA_CONNECT_STATUS:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
+                       pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
                *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
                                                .media_state);
                retval = 0;
                break;
 
        case OID_GEN_PHYSICAL_MEDIUM:
-               DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
+               pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -346,7 +341,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
         * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
         */
        case OID_GEN_MAC_OPTIONS:               /* from WinME */
-               DBG("%s: OID_GEN_MAC_OPTIONS\n", __func__);
+               pr_debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
                *outbuf = __constant_cpu_to_le32(
                          NDIS_MAC_OPTION_RECEIVE_SERIALIZED
                        | NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -358,7 +353,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_OK:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_XMIT_OK\n", __func__);
+                       pr_debug("%s: OID_GEN_XMIT_OK\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->tx_packets
                                - stats->tx_errors - stats->tx_dropped);
@@ -369,7 +364,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_OK:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_RCV_OK\n", __func__);
+                       pr_debug("%s: OID_GEN_RCV_OK\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->rx_packets
                                - stats->rx_errors - stats->rx_dropped);
@@ -380,7 +375,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_XMIT_ERROR:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
+                       pr_debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->tx_errors);
                        retval = 0;
@@ -390,7 +385,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
        /* mandatory */
        case OID_GEN_RCV_ERROR:
                if (rndis_debug > 1)
-                       DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
+                       pr_debug("%s: OID_GEN_RCV_ERROR\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->rx_errors);
                        retval = 0;
@@ -399,7 +394,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_GEN_RCV_NO_BUFFER:
-               DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
+               pr_debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->rx_dropped);
                        retval = 0;
@@ -410,7 +405,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_PERMANENT_ADDRESS:
-               DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
+               pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -422,7 +417,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_CURRENT_ADDRESS:
-               DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
+               pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
                if (rndis_per_dev_params [configNr].dev) {
                        length = ETH_ALEN;
                        memcpy (outbuf,
@@ -434,7 +429,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MULTICAST_LIST:
-               DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+               pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (0xE0000000);
                retval = 0;
@@ -442,21 +437,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_MAXIMUM_LIST_SIZE:
-               DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
+               pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
                /* Multicast base address only */
                *outbuf = __constant_cpu_to_le32 (1);
                retval = 0;
                break;
 
        case OID_802_3_MAC_OPTIONS:
-               DBG("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+               pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
                break;
 
        /* ieee802.3 statistics OIDs (table 4-4) */
 
        /* mandatory */
        case OID_802_3_RCV_ERROR_ALIGNMENT:
-               DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
+               pr_debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
                if (stats) {
                        *outbuf = cpu_to_le32(stats->rx_frame_errors);
                        retval = 0;
@@ -465,14 +460,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        /* mandatory */
        case OID_802_3_XMIT_ONE_COLLISION:
-               DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
+               pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
 
        /* mandatory */
        case OID_802_3_XMIT_MORE_COLLISIONS:
-               DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
+               pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
                *outbuf = __constant_cpu_to_le32 (0);
                retval = 0;
                break;
@@ -504,9 +499,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                return -ENOMEM;
 
        if (buf_len && rndis_debug > 1) {
-               DBG("set OID %08x value, len %d:\n", OID, buf_len);
+               pr_debug("set OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
-                       DBG("%03d: %08x %08x %08x %08x\n", i,
+                       pr_debug("%03d: %08x %08x %08x %08x\n", i,
                                get_unaligned_le32(&buf[i]),
                                get_unaligned_le32(&buf[i + 4]),
                                get_unaligned_le32(&buf[i + 8]),
@@ -525,7 +520,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                 *      MULTICAST, ALL_MULTICAST, BROADCAST
                 */
                *params->filter = (u16)get_unaligned_le32(buf);
-               DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+               pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
                        __func__, *params->filter);
 
                /* this call has a significant side effect:  it's
@@ -547,7 +542,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 
        case OID_802_3_MULTICAST_LIST:
                /* I think we can ignore this */
-               DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
+               pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
                retval = 0;
                break;
 
@@ -606,7 +601,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
        rndis_resp_t            *r;
        struct rndis_params     *params = rndis_per_dev_params + configNr;
 
-       // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+       /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
        if (!params->dev)
                return -ENOTSUPP;
 
@@ -659,15 +654,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
        BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
 #ifdef VERBOSE_DEBUG
-       DBG("%s: Length: %d\n", __func__, BufLength);
-       DBG("%s: Offset: %d\n", __func__, BufOffset);
-       DBG("%s: InfoBuffer: ", __func__);
+       pr_debug("%s: Length: %d\n", __func__, BufLength);
+       pr_debug("%s: Offset: %d\n", __func__, BufOffset);
+       pr_debug("%s: InfoBuffer: ", __func__);
 
        for (i = 0; i < BufLength; i++) {
-               DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+               pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
        }
 
-       DBG("\n");
+       pr_debug("\n");
 #endif
 
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -821,14 +816,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
        /* For USB: responses may take up to 10 seconds */
        switch (MsgType) {
        case REMOTE_NDIS_INITIALIZE_MSG:
-               DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+               pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
                        __func__ );
                params->state = RNDIS_INITIALIZED;
                return  rndis_init_response (configNr,
                                        (rndis_init_msg_type *) buf);
 
        case REMOTE_NDIS_HALT_MSG:
-               DBG("%s: REMOTE_NDIS_HALT_MSG\n",
+               pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
                        __func__ );
                params->state = RNDIS_UNINITIALIZED;
                if (params->dev) {
@@ -846,7 +841,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                                        (rndis_set_msg_type *) buf);
 
        case REMOTE_NDIS_RESET_MSG:
-               DBG("%s: REMOTE_NDIS_RESET_MSG\n",
+               pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
                        __func__ );
                return rndis_reset_response (configNr,
                                        (rndis_reset_msg_type *) buf);
@@ -854,7 +849,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
        case REMOTE_NDIS_KEEPALIVE_MSG:
                /* For USB: host does this every 5 seconds */
                if (rndis_debug > 1)
-                       DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+                       pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
                                __func__ );
                return rndis_keepalive_response (configNr,
                                                 (rndis_keepalive_msg_type *)
@@ -870,7 +865,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                {
                        unsigned i;
                        for (i = 0; i < MsgLength; i += 16) {
-                               DBG("%03d: "
+                               pr_debug("%03d: "
                                        " %02x %02x %02x %02x"
                                        " %02x %02x %02x %02x"
                                        " %02x %02x %02x %02x"
@@ -905,18 +900,18 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
                        rndis_per_dev_params [i].used = 1;
                        rndis_per_dev_params [i].resp_avail = resp_avail;
                        rndis_per_dev_params [i].v = v;
-                       DBG("%s: configNr = %d\n", __func__, i);
+                       pr_debug("%s: configNr = %d\n", __func__, i);
                        return i;
                }
        }
-       DBG("failed\n");
+       pr_debug("failed\n");
 
        return -ENODEV;
 }
 
 void rndis_deregister (int configNr)
 {
-       DBG("%s: \n", __func__ );
+       pr_debug("%s: \n", __func__);
 
        if (configNr >= RNDIS_MAX_CONFIGS) return;
        rndis_per_dev_params [configNr].used = 0;
@@ -926,7 +921,7 @@ void rndis_deregister (int configNr)
 
 int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 {
-       DBG("%s:\n", __func__ );
+       pr_debug("%s:\n", __func__);
        if (!dev)
                return -EINVAL;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -939,7 +934,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 
 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 {
-       DBG("%s:\n", __func__ );
+       pr_debug("%s:\n", __func__);
        if (!vendorDescr) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
@@ -951,7 +946,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
 
 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
 {
-       DBG("%s: %u %u\n", __func__, medium, speed);
+       pr_debug("%s: %u %u\n", __func__, medium, speed);
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
        rndis_per_dev_params [configNr].medium = medium;
@@ -1114,7 +1109,7 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
                        break;
                default:
                        if (fl_speed) p->speed = speed;
-                       else DBG("%c is not valid\n", c);
+                       else pr_debug("%c is not valid\n", c);
                        break;
                }
 
@@ -1159,12 +1154,12 @@ int __init rndis_init (void)
                                        &rndis_proc_fops,
                                        (void *)(rndis_per_dev_params + i))))
                {
-                       DBG("%s :remove entries", __func__);
+                       pr_debug("%s :remove entries", __func__);
                        while (i) {
                                sprintf (name, NAME_TEMPLATE, --i);
                                remove_proc_entry (name, NULL);
                        }
-                       DBG("\n");
+                       pr_debug("\n");
                        return -EIO;
                }
 #endif
index b3699afff002f4115b4c3ffaf1b975638aa88f1f..3faa7a7022df24926270d27399cfa92c69062b0e 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_acm.c"
+#include "f_serial.c"
+#include "u_serial.c"
+
+/*-------------------------------------------------------------------------*/
+
 /* Thanks to NetChip Technologies for donating this product ID.
 *
 * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
index 3791e6271903e7384a2a6773281d323c9de4b833..dbd575a194f3c895e46827a605d9e8984e388fb1 100644 (file)
@@ -52,7 +52,7 @@
  * this single "physical" link to be used by multiple virtual links.)
  */
 
-#define DRIVER_VERSION "29-May-2008"
+#define UETH__VERSION  "29-May-2008"
 
 struct eth_dev {
        /* lock is held while accessing port_usb
@@ -170,7 +170,7 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
        struct eth_dev  *dev = netdev_priv(net);
 
        strlcpy(p->driver, "g_ether", sizeof p->driver);
-       strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+       strlcpy(p->version, UETH__VERSION, sizeof p->version);
        strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
        strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
 }
index aa0bd4f126a1e5f7892e1ce645b187d88e4ea7f1..361d9659ac48726aa583d69accd2196edc3bd9df 100644 (file)
 #include "gadget_chips.h"
 
 
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Kbuild is not very cooperative with respect to linking separately
+ * compiled library objects into one module.  So for now we won't use
+ * separate compilation ... ensuring init/exit sections work to shrink
+ * the runtime footprint, and giving us at least some parts of what
+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ */
+#include "composite.c"
+#include "usbstring.c"
+#include "config.c"
+#include "epautoconf.c"
+
+#include "f_sourcesink.c"
+#include "f_loopback.c"
+
 /*-------------------------------------------------------------------------*/
 
 #define DRIVER_VERSION         "Cinco de Mayo 2008"
index 95b3ec89c126cdd0609306c034ae348a1324a184..52218562962481cdae48bff20594e845fb11ea5d 100644 (file)
@@ -344,7 +344,12 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
                goto err1;
        }
 
-       hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (!hcd->regs) {
+               dev_err(&pdev->dev, "can't ioremap OHCI HCD\n");
+               retval = -ENOMEM;
+               goto err2;
+       }
 
        ohci = hcd_to_ohci(hcd);
        ohci_hcd_init(ohci);
@@ -355,11 +360,11 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                retval = -ENXIO;
-               goto err2;
+               goto err3;
        }
        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
        if (retval)
-               goto err2;
+               goto err3;
 
        host_initialized = 1;
 
@@ -367,6 +372,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
                omap_ohci_clock_power(0);
 
        return 0;
+err3:
+       iounmap(hcd->regs);
 err2:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err1:
@@ -401,6 +408,7 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
        }
        if (machine_is_omap_osk())
                omap_free_gpio(9);
+       iounmap(hcd->regs);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        clk_put(usb_dc_ck);
index 5da63f5350053eed6edff1a39824580ed25e83b1..516848dd9b48b2aed0193c77d8b0cbcbc765b7a6 100644 (file)
@@ -112,7 +112,8 @@ static struct platform_device platform_dev = {
        .num_resources          = ARRAY_SIZE(resources),
 };
 
-static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
+static int sl811_hc_init(struct device *parent, resource_size_t base_addr,
+                        int irq)
 {
        if (platform_dev.dev.parent)
                return -EBUSY;
@@ -155,97 +156,72 @@ static void sl811_cs_release(struct pcmcia_device * link)
        platform_device_unregister(&platform_dev);
 }
 
+static int sl811_cs_config_check(struct pcmcia_device *p_dev,
+                                cistpl_cftable_entry_t *cfg,
+                                cistpl_cftable_entry_t *dflt,
+                                unsigned int vcc,
+                                void *priv_data)
+{
+       if (cfg->index == 0)
+               return -ENODEV;
+
+       /* Use power settings for Vcc and Vpp if present */
+       /*  Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+               if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+                       return -ENODEV;
+       } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+               if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+                       return -ENODEV;
+               }
+
+       if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+       else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp =
+                       dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+       /* we need an interrupt */
+       if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+               p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+       /* IO window settings */
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+
+               p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+               p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               p_dev->io.BasePort1 = io->win[0].base;
+               p_dev->io.NumPorts1 = io->win[0].len;
+
+               return pcmcia_request_io(p_dev, &p_dev->io);
+       }
+       pcmcia_disable_device(p_dev);
+       return -ENODEV;
+}
+
+
 static int sl811_cs_config(struct pcmcia_device *link)
 {
        struct device           *parent = &handle_to_dev(link);
        local_info_t            *dev = link->priv;
-       tuple_t                 tuple;
-       cisparse_t              parse;
        int                     last_fn, last_ret;
-       u_char                  buf[64];
-       config_info_t           conf;
-       cistpl_cftable_entry_t  dflt = { 0 };
 
        DBG(0, "sl811_cs_config(0x%p)\n", link);
 
-       /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo,
-                       pcmcia_get_configuration_info(link, &conf));
-
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t  *cfg = &(parse.cftable_entry);
-
-               if (pcmcia_get_tuple_data(link, &tuple) != 0
-                               || pcmcia_parse_tuple(link, &tuple, &parse)
-                                               != 0)
-                       goto next_entry;
-
-               if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
-                       dflt = *cfg;
-               }
-
-               if (cfg->index == 0)
-                       goto next_entry;
-
-               link->conf.ConfigIndex = cfg->index;
-
-               /* Use power settings for Vcc and Vpp if present */
-               /*  Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-                       if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
-                                       != conf.Vcc)
-                               goto next_entry;
-               } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
-                       if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
-                                       != conf.Vcc)
-                               goto next_entry;
-               }
-
-               if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-               else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
-                       link->conf.Vpp =
-                               dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-               /* we need an interrupt */
-               if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-                       link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-               /* IO window settings */
-               link->io.NumPorts1 = link->io.NumPorts2 = 0;
-               if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-                       cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-
-                       link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-                       link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-                       link->io.BasePort1 = io->win[0].base;
-                       link->io.NumPorts1 = io->win[0].len;
-
-                       if (pcmcia_request_io(link, &link->io) != 0)
-                               goto next_entry;
-               }
-               break;
-
-next_entry:
-               pcmcia_disable_device(link);
-               last_ret = pcmcia_get_next_tuple(link, &tuple);
-       }
+       if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
+               goto failed;
 
        /* require an IRQ and two registers */
        if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
-               goto cs_failed;
+               goto failed;
        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                CS_CHECK(RequestIRQ,
                        pcmcia_request_irq(link, &link->irq));
        else
-               goto cs_failed;
+               goto failed;
 
        CS_CHECK(RequestConfiguration,
                pcmcia_request_configuration(link, &link->conf));
@@ -266,8 +242,9 @@ next_entry:
        if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
                        < 0) {
 cs_failed:
-               printk("sl811_cs_config failed\n");
                cs_error(link, last_fn, last_ret);
+failed:
+               printk(KERN_WARNING "sl811_cs_config failed\n");
                sl811_cs_release(link);
                return  -ENODEV;
        }
index db645936eedd3b5f8f5aff71a9eee85a12223757..1f0c2cf26e5d54532ad23a384c1ede813b625b3b 100644 (file)
@@ -123,14 +123,10 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
 
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 {
-       if (!list_empty(&td->list)) {
-               dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
-               WARN_ON(1);
-       }
-       if (!list_empty(&td->fl_list)) {
-               dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
-               WARN_ON(1);
-       }
+       if (!list_empty(&td->list))
+               dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td);
+       if (!list_empty(&td->fl_list))
+               dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td);
 
        dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
@@ -295,10 +291,8 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
 static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
        WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
-       if (!list_empty(&qh->queue)) {
-               dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
-               WARN_ON(1);
-       }
+       if (!list_empty(&qh->queue))
+               dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh);
 
        list_del(&qh->node);
        if (qh->udev) {
@@ -746,11 +740,9 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
 {
        struct uhci_td *td, *tmp;
 
-       if (!list_empty(&urbp->node)) {
-               dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
+       if (!list_empty(&urbp->node))
+               dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n",
                                urbp->urb);
-               WARN_ON(1);
-       }
 
        list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
                uhci_remove_td_from_urbp(td);
index 4cfa25b0f44e5620bc45b4447eee62737bf523f2..cc8e0a926f9991749be2cc48cce5a17a8bea9d79 100644 (file)
@@ -595,9 +595,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
         } while(value);
         kit->dev_no = bit;
 
-       kit->dev = device_create_drvdata(phidget_class, &kit->udev->dev,
-                                       MKDEV(0, 0), kit,
-                                       "interfacekit%d", kit->dev_no);
+       kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0),
+                                kit, "interfacekit%d", kit->dev_no);
         if (IS_ERR(kit->dev)) {
                 rc = PTR_ERR(kit->dev);
                 kit->dev = NULL;
index 9b4696f21b22849079b062336b7ef93aa1ed757e..38088b44349eb86695fc837fe54fc84ee1e2e482 100644 (file)
@@ -365,9 +365,8 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
        } while(value);
        mc->dev_no = bit;
 
-       mc->dev = device_create_drvdata(phidget_class, &mc->udev->dev,
-                                       MKDEV(0, 0), mc,
-                                       "motorcontrol%d", mc->dev_no);
+       mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc,
+                               "motorcontrol%d", mc->dev_no);
        if (IS_ERR(mc->dev)) {
                rc = PTR_ERR(mc->dev);
                mc->dev = NULL;
index 1ca7ddb41d4dfe0014381391766bf8898947aa69..bef6fe16364b47c77c03ddc580744fa310a6daa5 100644 (file)
@@ -275,9 +275,8 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
         } while (value);
        dev->dev_no = bit;
 
-       dev->dev = device_create_drvdata(phidget_class, &dev->udev->dev,
-                                        MKDEV(0, 0), dev,
-                                        "servo%d", dev->dev_no);
+       dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0),
+                                dev, "servo%d", dev->dev_no);
        if (IS_ERR(dev->dev)) {
                rc = PTR_ERR(dev->dev);
                dev->dev = NULL;
index 6566fc0a322853a50b8f212d6b82df868da9b4d5..c9de3f027aab07a9907b331f25c7723ac012d8e3 100644 (file)
@@ -1162,9 +1162,9 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
        if (minor >= MON_BIN_MAX_MINOR)
                return 0;
 
-       dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
-                                   MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
-                                   "usbmon%d", minor);
+       dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
+                           MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+                           "usbmon%d", minor);
        if (IS_ERR(dev))
                return 0;
 
index 79ea98c66fa8d8c1f91ef2b045e9fc19d52375de..99fb7dc59c4540911b01a2cd72662dbcd54cf113 100644 (file)
@@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work)
         * 64 bytes, to ensure I do not get throttled.
         * Ask USB mailing list for better aproach.
         */
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
 
        if (!tty) {
                schedule_work(&priv->rx_work);
@@ -283,12 +283,13 @@ static void aircable_read(struct work_struct *work)
        count = min(64, serial_buf_data_avail(priv->rx_buf));
 
        if (count <= 0)
-               return; /* We have finished sending everything. */
+               goto out; /* We have finished sending everything. */
 
        tty_prepare_flip_string(tty, &data, count);
        if (!data) {
-               err("%s- kzalloc(%d) failed.", __func__, count);
-               return;
+               dev_err(&port->dev, "%s- kzalloc(%d) failed.",
+                                                       __func__, count);
+               goto out;
        }
 
        serial_buf_get(priv->rx_buf, data, count);
@@ -297,7 +298,8 @@ static void aircable_read(struct work_struct *work)
 
        if (serial_buf_data_avail(priv->rx_buf))
                schedule_work(&priv->rx_work);
-
+out:           
+       tty_kref_put(tty);
        return;
 }
 /* End of private methods */
@@ -495,7 +497,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __func__,
                                urb->actual_length, urb->transfer_buffer);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                if (urb->actual_length <= 2) {
                        /* This is an incomplete package */
@@ -527,6 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
                }
                aircable_read(&priv->rx_work);
        }
+       tty_kref_put(tty);
 
        /* Schedule the next read _if_ we are still open */
        if (port->port.count) {
index 2ebe06c3405a219d7d6a7200f0956baf2c466555..1913bc7c5f0b6c6d38b17f1ab709435e1f6d6417 100644 (file)
@@ -322,7 +322,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)
         * to look in to this before committing any code.
         */
        if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                /* Overrun Error */
                if (priv->last_lsr & BELKIN_SA_LSR_OE) {
                }
@@ -335,6 +335,7 @@ static void belkin_sa_read_int_callback(struct urb *urb)
                /* Break Indicator */
                if (priv->last_lsr & BELKIN_SA_LSR_BI) {
                }
+               tty_kref_put(tty);
        }
 #endif
        spin_unlock_irqrestore(&priv->lock, flags);
index e980766bb84bed3fc05abb203dc3c3bc02b7daff..5b20de130e08399045e3134dff18bfb8543af5f4 100644 (file)
@@ -117,7 +117,7 @@ static int usb_console_setup(struct console *co, char *options)
        }
 
        port = serial->port[0];
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
 
        info->port = port;
 
@@ -143,7 +143,7 @@ static int usb_console_setup(struct console *co, char *options)
                        }
                        memset(&dummy, 0, sizeof(struct ktermios));
                        tty->termios = termios;
-                       port->port.tty = tty;
+                       tty_port_tty_set(&port->port, tty);
                }
 
                /* only call the device specific open if this
@@ -163,7 +163,7 @@ static int usb_console_setup(struct console *co, char *options)
                        tty_termios_encode_baud_rate(termios, baud, baud);
                        serial->type->set_termios(tty, port, &dummy);
 
-                       port->port.tty = NULL;
+                       tty_port_tty_set(&port->port, NULL);
                        kfree(termios);
                        kfree(tty);
                }
@@ -176,7 +176,7 @@ out:
        return retval;
 free_termios:
        kfree(termios);
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
 free_tty:
        kfree(tty);
 reset_open_count:
index b4d72351cb9697964fafc3ac8f2f1a4bf90cc15b..94ef36c4764bcc3378e839055299b8356848c8df 100644 (file)
@@ -384,7 +384,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
                return;
        }
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (!tty) {
                dbg("%s - ignoring since device not open\n", __func__);
                return;
@@ -394,6 +394,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb)
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        spin_lock(&priv->lock);
 
index 22837a3f2f899e963f0d944814d222bcd2e494f5..f3514a91f9154836366e7de1804d94a163d795a8 100644 (file)
@@ -1286,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb)
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (!tty) {
                dbg("%s - bad tty pointer - exiting", __func__);
                return;
@@ -1362,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb)
                                        data[i]);
                        tty_insert_flip_char(tty, data[i], tty_flag);
                }
-               tty_flip_buffer_push(port->port.tty);
+               tty_flip_buffer_push(tty);
        }
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -1371,6 +1371,7 @@ static void cypress_read_int_callback(struct urb *urb)
        spin_unlock_irqrestore(&priv->lock, flags);
 
 continue_read:
+       tty_kref_put(tty);
 
        /* Continue trying to always read... unless the port has closed. */
 
index 240aad1acaab80f8a802b6b67cd4f3ffed911a9d..5756ac6d6c923ccf30a4ba66f2c036599bf203cd 100644 (file)
@@ -604,7 +604,9 @@ static void digi_wakeup_write_lock(struct work_struct *work)
 
 static void digi_wakeup_write(struct usb_serial_port *port)
 {
-       tty_wakeup(port->port.tty);
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
+       tty_wakeup(tty);
+       tty_kref_put(tty);
 }
 
 
@@ -1668,7 +1670,7 @@ static int digi_read_inb_callback(struct urb *urb)
 {
 
        struct usb_serial_port *port = urb->context;
-       struct tty_struct *tty = port->port.tty;
+       struct tty_struct *tty;
        struct digi_port *priv = usb_get_serial_port_data(port);
        int opcode = ((unsigned char *)urb->transfer_buffer)[0];
        int len = ((unsigned char *)urb->transfer_buffer)[1];
@@ -1692,6 +1694,7 @@ static int digi_read_inb_callback(struct urb *urb)
                return -1;
        }
 
+       tty = tty_port_tty_get(&port->port);
        spin_lock(&priv->dp_port_lock);
 
        /* check for throttle; if set, do not resubmit read urb */
@@ -1735,6 +1738,7 @@ static int digi_read_inb_callback(struct urb *urb)
                }
        }
        spin_unlock(&priv->dp_port_lock);
+       tty_kref_put(tty);
 
        if (opcode == DIGI_CMD_RECEIVE_DISABLE)
                dbg("%s: got RECEIVE_DISABLE", __func__);
@@ -1760,6 +1764,7 @@ static int digi_read_oob_callback(struct urb *urb)
 
        struct usb_serial_port *port = urb->context;
        struct usb_serial *serial = port->serial;
+       struct tty_struct *tty;
        struct digi_port *priv = usb_get_serial_port_data(port);
        int opcode, line, status, val;
        int i;
@@ -1787,10 +1792,11 @@ static int digi_read_oob_callback(struct urb *urb)
                if (priv == NULL)
                        return -1;
 
+               tty = tty_port_tty_get(&port->port);
                rts = 0;
                if (port->port.count)
-                       rts = port->port.tty->termios->c_cflag & CRTSCTS;
-
+                       rts = tty->termios->c_cflag & CRTSCTS;
+               
                if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
                        spin_lock(&priv->dp_port_lock);
                        /* convert from digi flags to termiox flags */
@@ -1798,14 +1804,14 @@ static int digi_read_oob_callback(struct urb *urb)
                                priv->dp_modem_signals |= TIOCM_CTS;
                                /* port must be open to use tty struct */
                                if (rts) {
-                                       port->port.tty->hw_stopped = 0;
+                                       tty->hw_stopped = 0;
                                        digi_wakeup_write(port);
                                }
                        } else {
                                priv->dp_modem_signals &= ~TIOCM_CTS;
                                /* port must be open to use tty struct */
                                if (rts)
-                                       port->port.tty->hw_stopped = 1;
+                                       tty->hw_stopped = 1;
                        }
                        if (val & DIGI_READ_INPUT_SIGNALS_DSR)
                                priv->dp_modem_signals |= TIOCM_DSR;
@@ -1830,6 +1836,7 @@ static int digi_read_oob_callback(struct urb *urb)
                } else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
                        wake_up_interruptible(&priv->dp_flush_wait);
                }
+               tty_kref_put(tty);
        }
        return 0;
 
index a6ab5b58d9ca5c6456a9a56eb7606e4fb18c4b0e..1072e847280fd88df4a5fc1f9770d5a36a051692 100644 (file)
@@ -33,9 +33,8 @@
  *     Moved MOD_DEC_USE_COUNT to end of empeg_close().
  *
  * (12/03/2000) gb
- *     Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to
- *     empeg_open(). This notifies the tty driver that the termios have
- *     changed.
+ *     Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open().
+ *     This notifies the tty driver that the termios have changed.
  *
  * (11/13/2000) gb
  *     Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
@@ -354,7 +353,7 @@ static void empeg_read_bulk_callback(struct urb *urb)
 
        usb_serial_debug_data(debug, &port->dev, __func__,
                                                urb->actual_length, data);
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
 
        if (urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
@@ -362,6 +361,7 @@ static void empeg_read_bulk_callback(struct urb *urb)
                tty_flip_buffer_push(tty);
                bytes_in += urb->actual_length;
        }
+       tty_kref_put(tty);
 
        /* Continue trying to always read  */
        usb_fill_bulk_urb(
index 3dc93b542b30634cd23bbbe012b16034c84f6449..c2ac129557aae7dd599ccfbca2a3ddfcebd8aeb5 100644 (file)
@@ -860,7 +860,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
 
        kfree(buf);
        if (rv < 0) {
-               err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
+               dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
                                __func__,
                                (set & TIOCM_DTR) ? "HIGH" :
                                (clear & TIOCM_DTR) ? "LOW" : "unchanged",
@@ -1808,7 +1808,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
        if (port->port.count <= 0)
                return;
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (!tty) {
                dbg("%s - bad tty pointer - exiting", __func__);
                return;
@@ -1817,7 +1817,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
        priv = usb_get_serial_port_data(port);
        if (!priv) {
                dbg("%s - bad port private data pointer - exiting", __func__);
-               return;
+               goto out;
        }
 
        if (urb != port->read_urb)
@@ -1827,7 +1827,7 @@ static void ftdi_read_bulk_callback(struct urb *urb)
                /* This will happen at close every time so it is a dbg not an
                   err */
                dbg("(this is ok on close) nonzero read bulk status received: %d", status);
-               return;
+               goto out;
        }
 
        /* count data bytes, but not status bytes */
@@ -1838,7 +1838,8 @@ static void ftdi_read_bulk_callback(struct urb *urb)
        spin_unlock_irqrestore(&priv->rx_lock, flags);
 
        ftdi_process_read(&priv->rx_work.work);
-
+out:
+       tty_kref_put(tty);
 } /* ftdi_read_bulk_callback */
 
 
@@ -1863,7 +1864,7 @@ static void ftdi_process_read(struct work_struct *work)
        if (port->port.count <= 0)
                return;
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (!tty) {
                dbg("%s - bad tty pointer - exiting", __func__);
                return;
@@ -1872,13 +1873,13 @@ static void ftdi_process_read(struct work_struct *work)
        priv = usb_get_serial_port_data(port);
        if (!priv) {
                dbg("%s - bad port private data pointer - exiting", __func__);
-               return;
+               goto out;
        }
 
        urb = port->read_urb;
        if (!urb) {
                dbg("%s - bad read_urb pointer - exiting", __func__);
-               return;
+               goto out;
        }
 
        data = urb->transfer_buffer;
@@ -2020,7 +2021,7 @@ static void ftdi_process_read(struct work_struct *work)
                        schedule_delayed_work(&priv->rx_work, 1);
                else
                        dbg("%s - port is closed", __func__);
-               return;
+               goto out;
        }
 
        /* urb is completely processed */
@@ -2041,6 +2042,8 @@ static void ftdi_process_read(struct work_struct *work)
                        err("%s - failed resubmitting read urb, error %d",
                                                        __func__, result);
        }
+out:
+       tty_kref_put(tty);
 } /* ftdi_process_read */
 
 
@@ -2256,7 +2259,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
                           0, 0,
                           buf, 1, WDR_TIMEOUT);
                if (ret < 0) {
-                       err("%s Could not get modem status of device - err: %d", __func__,
+                       dbg("%s Could not get modem status of device - err: %d", __func__,
                            ret);
                        return ret;
                }
@@ -2275,7 +2278,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
                                   0, priv->interface,
                                   buf, 2, WDR_TIMEOUT);
                if (ret < 0) {
-                       err("%s Could not get modem status of device - err: %d", __func__,
+                       dbg("%s Could not get modem status of device - err: %d", __func__,
                            ret);
                        return ret;
                }
index d95382088075923ab47ae4fc869784e03c0520d4..2ad0569bcf19ec7ceeee03ccf3ac3f3af55d1cca 100644 (file)
@@ -276,7 +276,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
 static void send_to_tty(struct usb_serial_port *port,
                        char *data, unsigned int actual_length)
 {
-       struct tty_struct *tty = port->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
 
        if (tty && actual_length) {
 
@@ -287,6 +287,7 @@ static void send_to_tty(struct usb_serial_port *port,
                tty_insert_flip_string(tty, data, actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 }
 
 
index fe84c88ec20cae94b9d1990b1e48be0ef87cb364..814909f1ee630b34092e7e22fa6f764e0a1d9e3a 100644 (file)
@@ -330,7 +330,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
 static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
 {
        struct urb *urb = port->read_urb;
-       struct tty_struct *tty = port->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
        int room;
 
        /* Push data to tty */
@@ -341,6 +341,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
                        tty_flip_buffer_push(tty);
                }
        }
+       tty_kref_put(tty);
 
        resubmit_read_urb(port, GFP_ATOMIC);
 }
index bfa508ddb0fed3f97062bf66e16326b765dbcbe1..611f97fd62f1b0eb2799cb58941fa8c0d5921e50 100644 (file)
@@ -600,6 +600,7 @@ static void edge_interrupt_callback(struct urb *urb)
        struct edgeport_serial  *edge_serial = urb->context;
        struct edgeport_port *edge_port;
        struct usb_serial_port *port;
+       struct tty_struct *tty;
        unsigned char *data = urb->transfer_buffer;
        int length = urb->actual_length;
        int bytes_avail;
@@ -675,9 +676,12 @@ static void edge_interrupt_callback(struct urb *urb)
 
                                        /* tell the tty driver that something
                                           has changed */
-                                       if (edge_port->port->port.tty)
-                                               tty_wakeup(edge_port->port->port.tty);
-
+                                       tty = tty_port_tty_get(
+                                               &edge_port->port->port);
+                                       if (tty) {
+                                               tty_wakeup(tty);
+                                               tty_kref_put(tty);
+                                       }
                                        /* Since we have more credit, check
                                           if more data can be sent */
                                        send_more_port_data(edge_serial,
@@ -778,13 +782,14 @@ static void edge_bulk_out_data_callback(struct urb *urb)
                    __func__, status);
        }
 
-       tty = edge_port->port->port.tty;
+       tty = tty_port_tty_get(&edge_port->port->port);
 
        if (tty && edge_port->open) {
                /* let the tty driver wakeup if it has a special
                   write_wakeup function */
                tty_wakeup(tty);
        }
+       tty_kref_put(tty);
 
        /* Release the Write URB */
        edge_port->write_in_progress = false;
@@ -826,11 +831,12 @@ static void edge_bulk_out_cmd_callback(struct urb *urb)
        }
 
        /* Get pointer to tty */
-       tty = edge_port->port->port.tty;
+       tty = tty_port_tty_get(&edge_port->port->port);
 
        /* tell the tty driver that something has changed */
        if (tty && edge_port->open)
                tty_wakeup(tty);
+       tty_kref_put(tty);
 
        /* we have completed the command */
        edge_port->commandPending = false;
@@ -1932,11 +1938,13 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
                                                        edge_serial->rxPort];
                                edge_port = usb_get_serial_port_data(port);
                                if (edge_port->open) {
-                                       tty = edge_port->port->port.tty;
+                                       tty = tty_port_tty_get(
+                                               &edge_port->port->port);
                                        if (tty) {
                                                dbg("%s - Sending %d bytes to TTY for port %d",
                                                        __func__, rxLen, edge_serial->rxPort);
                                                edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
+                                               tty_kref_put(tty);
                                        }
                                        edge_port->icount.rx += rxLen;
                                }
@@ -1971,6 +1979,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
 {
        struct usb_serial_port *port;
        struct edgeport_port *edge_port;
+       struct tty_struct *tty;
        __u8 code = edge_serial->rxStatusCode;
 
        /* switch the port pointer to the one being currently talked about */
@@ -2020,10 +2029,12 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
 
                /* send the current line settings to the port so we are
                   in sync with any further termios calls */
-               /* FIXME: locking on tty */
-               if (edge_port->port->port.tty)
-                       change_port_settings(edge_port->port->port.tty,
-                               edge_port, edge_port->port->port.tty->termios);
+               tty = tty_port_tty_get(&edge_port->port->port);
+               if (tty) {
+                       change_port_settings(tty,
+                               edge_port, tty->termios);
+                       tty_kref_put(tty);
+               }
 
                /* we have completed the open */
                edge_port->openPending = false;
@@ -2163,10 +2174,14 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
        }
 
        /* Place LSR data byte into Rx buffer */
-       if (lsrData && edge_port->port->port.tty)
-               edge_tty_recv(&edge_port->port->dev,
-                                       edge_port->port->port.tty, &data, 1);
-
+       if (lsrData) {
+               struct tty_struct *tty =
+                               tty_port_tty_get(&edge_port->port->port);
+               if (tty) {
+                       edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
+                       tty_kref_put(tty);
+               }
+       }
        /* update input line counters */
        icount = &edge_port->icount;
        if (newLsr & LSR_BREAK)
index cb4c54316cf56a935691ceba62971c3fcd5963c9..541dd8e6e7a2a232ea826587efdfab136c75f82b 100644 (file)
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
                                                                int flush)
 {
        int baud_rate;
-       struct tty_struct *tty = port->port->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->port->port);
        wait_queue_t wait;
        unsigned long flags;
 
@@ -599,6 +599,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
        if (flush)
                edge_buf_clear(port->ep_out_buf);
        spin_unlock_irqrestore(&port->ep_lock, flags);
+       tty_kref_put(tty);
 
        /* wait for data to drain from the device */
        timeout += jiffies;
@@ -1554,7 +1555,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
        /* Save the new modem status */
        edge_port->shadow_msr = msr & 0xf0;
 
-       tty = edge_port->port->port.tty;
+       tty = tty_port_tty_get(&edge_port->port->port);
        /* handle CTS flow control */
        if (tty && C_CRTSCTS(tty)) {
                if (msr & EDGEPORT_MSR_CTS) {
@@ -1564,6 +1565,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
                        tty->hw_stopped = 1;
                }
        }
+       tty_kref_put(tty);
 
        return;
 }
@@ -1574,6 +1576,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
        struct async_icount *icount;
        __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
                                                LSR_FRM_ERR | LSR_BREAK));
+       struct tty_struct *tty;
 
        dbg("%s - %02x", __func__, new_lsr);
 
@@ -1587,8 +1590,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
                new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
 
        /* Place LSR data byte into Rx buffer */
-       if (lsr_data && edge_port->port->port.tty)
-               edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
+       if (lsr_data) {
+               tty = tty_port_tty_get(&edge_port->port->port);
+               if (tty) {
+                       edge_tty_recv(&edge_port->port->dev, tty, &data, 1);
+                       tty_kref_put(tty);
+               }
+       }
 
        /* update input line counters */
        icount = &edge_port->icount;
@@ -1749,7 +1757,7 @@ static void edge_bulk_in_callback(struct urb *urb)
                ++data;
        }
 
-       tty = edge_port->port->port.tty;
+       tty = tty_port_tty_get(&edge_port->port->port);
        if (tty && urb->actual_length) {
                usb_serial_debug_data(debug, &edge_port->port->dev,
                                        __func__, urb->actual_length, data);
@@ -1761,6 +1769,7 @@ static void edge_bulk_in_callback(struct urb *urb)
                                                        urb->actual_length);
                edge_port->icount.rx += urb->actual_length;
        }
+       tty_kref_put(tty);
 
 exit:
        /* continue read unless stopped */
@@ -1796,6 +1805,7 @@ static void edge_bulk_out_callback(struct urb *urb)
        struct usb_serial_port *port = urb->context;
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        int status = urb->status;
+       struct tty_struct *tty;
 
        dbg("%s - port %d", __func__, port->number);
 
@@ -1818,7 +1828,9 @@ static void edge_bulk_out_callback(struct urb *urb)
        }
 
        /* send any buffered data */
-       edge_send(port->port.tty);
+       tty = tty_port_tty_get(&port->port);
+       edge_send(tty);
+       tty_kref_put(tty);
 }
 
 static int edge_open(struct tty_struct *tty,
@@ -1876,7 +1888,7 @@ static int edge_open(struct tty_struct *tty,
 
        /* set up the port settings */
        if (tty)
-               edge_set_termios(tty, port, port->port.tty->termios);
+               edge_set_termios(tty, port, tty->termios);
 
        /* open up the port */
 
index cd9a2e138c8b35f3a3cacb4cd60525ed39d179b6..2affa9c118b2450691834141c47344ebe5dcb827 100644 (file)
@@ -764,13 +764,14 @@ static void ipaq_read_bulk_callback(struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __func__,
                                                urb->actual_length, data);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
                bytes_in += urb->actual_length;
        }
+       tty_kref_put(tty);
 
        /* Continue trying to always read  */
        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
index a842025b9b576d4f3e8e678cf386713a9c7baf61..480cac27d646d91a09fc7e289a74b2d4fb9f2139 100644 (file)
@@ -170,12 +170,13 @@ static void ipw_read_bulk_callback(struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __func__,
                                        urb->actual_length, data);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* Continue trying to always read  */
        usb_fill_bulk_urb(port->read_urb, port->serial->dev,
index e59155c6607da7c58dabe8b7d5b83b7957816358..45d4043e04abbcd429a27c4204ee01b8b70105d2 100644 (file)
@@ -465,11 +465,12 @@ static void ir_read_bulk_callback(struct urb *urb)
                        ir_baud = *data & 0x0f;
                usb_serial_debug_data(debug, &port->dev, __func__,
                                                urb->actual_length, data);
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
                        tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
                        tty_flip_buffer_push(tty);
                }
+               tty_kref_put(tty);
 
                /*
                 * No break here.
index ddff37fa633904b28cb7a8ffe41c2a4804491c5f..53710aa7eadd96d7c6f1e535d513465815a7bceb 100644 (file)
@@ -629,13 +629,14 @@ static void read_buf_callback(struct urb *urb)
        }
 
        dbg("%s - %i chars to write", __func__, urb->actual_length);
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (data == NULL)
                dbg("%s - data is NULL !!!", __func__);
        if (tty && urb->actual_length && data) {
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
        iuu_led_activity_on(urb);
 }
 
index 704716f6f6d378c825920c213f3cedd7585b0ab5..15447af48691b5b79140c3303744b868359b1390 100644 (file)
@@ -430,7 +430,7 @@ static void usa26_indat_callback(struct urb *urb)
        }
 
        port =  urb->context;
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
                if ((data[0] & 0x80) == 0) {
@@ -459,6 +459,7 @@ static void usa26_indat_callback(struct urb *urb)
                }
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* Resubmit urb so we continue receiving */
        urb->dev = port->serial->dev;
@@ -513,6 +514,7 @@ static void usa26_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
+       struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
 
@@ -553,12 +555,11 @@ static void       usa26_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (port->port.tty && !C_CLOCAL(port->port.tty)
-           && old_dcd_state != p_priv->dcd_state) {
-               if (old_dcd_state)
-                       tty_hangup(port->port.tty);
-               /*  else */
-               /*      wake_up_interruptible(&p_priv->open_wait); */
+       if (old_dcd_state != p_priv->dcd_state) {
+               tty = tty_port_tty_get(&port->port);
+               if (tty && !C_CLOCAL(tty))
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -604,11 +605,12 @@ static void usa28_indat_callback(struct urb *urb)
                p_priv = usb_get_serial_port_data(port);
                data = urb->transfer_buffer;
 
-               tty = port->port.tty;
-               if (urb->actual_length) {
+               tty =tty_port_tty_get(&port->port);
+               if (tty && urb->actual_length) {
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
                }
+               tty_kref_put(tty);
 
                /* Resubmit urb so we continue receiving */
                urb->dev = port->serial->dev;
@@ -652,6 +654,7 @@ static void usa28_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
+       struct tty_struct                       *tty;
        int old_dcd_state;
        int status = urb->status;
 
@@ -689,12 +692,11 @@ static void       usa28_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (port->port.tty && !C_CLOCAL(port->port.tty)
-           && old_dcd_state != p_priv->dcd_state) {
-               if (old_dcd_state)
-                       tty_hangup(port->port.tty);
-               /*  else */
-               /*      wake_up_interruptible(&p_priv->open_wait); */
+       if( old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+               tty = tty_port_tty_get(&port->port);
+               if (tty && !C_CLOCAL(tty)) 
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
 
                /* Resubmit urb so we continue receiving */
@@ -785,12 +787,11 @@ static void       usa49_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (port->port.tty && !C_CLOCAL(port->port.tty)
-           && old_dcd_state != p_priv->dcd_state) {
-               if (old_dcd_state)
-                       tty_hangup(port->port.tty);
-               /*  else */
-               /*      wake_up_interruptible(&p_priv->open_wait); */
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+               struct tty_struct *tty = tty_port_tty_get(&port->port);
+               if (tty && !C_CLOCAL(tty))
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -827,7 +828,7 @@ static void usa49_indat_callback(struct urb *urb)
        }
 
        port =  urb->context;
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
                if ((data[0] & 0x80) == 0) {
@@ -850,6 +851,7 @@ static void usa49_indat_callback(struct urb *urb)
                }
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* Resubmit urb so we continue receiving */
        urb->dev = port->serial->dev;
@@ -893,7 +895,7 @@ static void usa49wg_indat_callback(struct urb *urb)
                                return;
                        }
                        port = serial->port[data[i++]];
-                       tty = port->port.tty;
+                       tty = tty_port_tty_get(&port->port);
                        len = data[i++];
 
                        /* 0x80 bit is error flag */
@@ -927,6 +929,7 @@ static void usa49wg_indat_callback(struct urb *urb)
                        }
                        if (port->port.count)
                                tty_flip_buffer_push(tty);
+                       tty_kref_put(tty);
                }
        }
 
@@ -967,8 +970,8 @@ static void usa90_indat_callback(struct urb *urb)
        port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
-       tty = port->port.tty;
        if (urb->actual_length) {
+               tty = tty_port_tty_get(&port->port);
                /* if current mode is DMA, looks like usa28 format
                   otherwise looks like usa26 data format */
 
@@ -1004,6 +1007,7 @@ static void usa90_indat_callback(struct urb *urb)
                        }
                }
                tty_flip_buffer_push(tty);
+               tty_kref_put(tty);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -1025,6 +1029,7 @@ static void       usa90_instat_callback(struct urb *urb)
        struct usb_serial                       *serial;
        struct usb_serial_port                  *port;
        struct keyspan_port_private             *p_priv;
+       struct tty_struct                       *tty;
        int old_dcd_state, err;
        int status = urb->status;
 
@@ -1053,12 +1058,11 @@ static void     usa90_instat_callback(struct urb *urb)
        p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
        p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-       if (port->port.tty && !C_CLOCAL(port->port.tty)
-           && old_dcd_state != p_priv->dcd_state) {
-               if (old_dcd_state)
-                       tty_hangup(port->port.tty);
-               /*  else */
-               /*      wake_up_interruptible(&p_priv->open_wait); */
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+               tty = tty_port_tty_get(&port->port);
+               if (tty && !C_CLOCAL(tty))
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -1130,12 +1134,11 @@ static void     usa67_instat_callback(struct urb *urb)
        p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
        p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 
-       if (port->port.tty && !C_CLOCAL(port->port.tty)
-           && old_dcd_state != p_priv->dcd_state) {
-               if (old_dcd_state)
-                       tty_hangup(port->port.tty);
-               /*  else */
-               /*      wake_up_interruptible(&p_priv->open_wait); */
+       if (old_dcd_state != p_priv->dcd_state && old_dcd_state) {
+               struct tty_struct *tty = tty_port_tty_get(&port->port);
+               if (tty && !C_CLOCAL(tty))
+                       tty_hangup(tty);
+               tty_kref_put(tty);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -1332,7 +1335,7 @@ static void keyspan_close(struct tty_struct *tty,
                        stop_urb(p_priv->out_urbs[i]);
                }
        }
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
 }
 
 /* download the firmware to a pre-renumeration device */
index 040040a267d970ff0fe97b057fb1eb7cb8f6df33..99e9a14c5bf65979ddfb2de5c03dc2c50e1b8968 100644 (file)
@@ -172,8 +172,9 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
        struct keyspan_pda_private *priv =
                container_of(work, struct keyspan_pda_private, wakeup_work);
        struct usb_serial_port *port = priv->port;
-
-       tty_wakeup(port->port.tty);
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
+       tty_wakeup(tty);
+       tty_kref_put(tty);
 }
 
 static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -205,7 +206,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
 static void keyspan_pda_rx_interrupt(struct urb *urb)
 {
        struct usb_serial_port *port = urb->context;
-       struct tty_struct *tty = port->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
        unsigned char *data = urb->transfer_buffer;
        int retval;
        int status = urb->status;
@@ -222,7 +223,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
                /* this urb is terminated, clean up */
                dbg("%s - urb shutting down with status: %d",
                    __func__, status);
-               return;
+               goto out;
        default:
                dbg("%s - nonzero urb status received: %d",
                    __func__, status);
@@ -261,8 +262,11 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
        if (retval)
-               err("%s - usb_submit_urb failed with result %d",
-                    __func__, retval);
+               dev_err(&port->dev,
+                       "%s - usb_submit_urb failed with result %d",
+                       __func__, retval);
+out:
+       tty_kref_put(tty);                   
 }
 
 
index b84dddc71124546ec0fd968ae03748975dae6f1a..ff3a07f5102fe11a70e11bfc5c3959116b814d78 100644 (file)
@@ -658,7 +658,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb)
        } else {
                int bytes_sent = ((__u8 *) data)[0] +
                                 ((unsigned int) ((__u8 *) data)[1] << 8);
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                /* we should immediately resubmit the URB, before attempting
                 * to pass the data on to the tty layer. But that needs locking
                 * against re-entry an then mixed-up data because of
@@ -679,6 +679,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb)
                tty_buffer_request_room(tty, bytes_sent);
                tty_insert_flip_string(tty, data + 2, bytes_sent);
                tty_flip_buffer_push(tty);
+               tty_kref_put(tty);
 
                /* again lockless, but debug info only */
                priv->bytes_in += bytes_sent;
index deba28ec77e8e43cab07691bf17ed68624b9d517..cfcf37c2b95703014f39436539619192a11864cc 100644 (file)
@@ -383,7 +383,7 @@ static void kobil_read_int_callback(struct urb *urb)
                return;
        }
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (urb->actual_length) {
 
                /* BEGIN DEBUG */
@@ -405,6 +405,7 @@ static void kobil_read_int_callback(struct urb *urb)
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
        /* someone sets the dev to 0 if the close method has been called */
        port->interrupt_in_urb->dev = port->serial->dev;
 
index 0ded8bd6ec8546a9ff694b2e002ab4b2b6f3758e..9b2cef81cde0284deada9dea2a6faebbee15a43f 100644 (file)
@@ -563,10 +563,11 @@ static void mct_u232_read_int_callback(struct urb *urb)
         * Work-a-round: handle the 'usual' bulk-in pipe here
         */
        if (urb->transfer_buffer_length > 2) {
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                if (urb->actual_length) {
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
+                       tty_kref_put(tty);
                }
                goto exit;
        }
@@ -591,7 +592,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
         * to look in to this before committing any code.
         */
        if (priv->last_lsr & MCT_U232_LSR_ERR) {
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                /* Overrun Error */
                if (priv->last_lsr & MCT_U232_LSR_OE) {
                }
@@ -604,6 +605,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
                /* Break Indicator */
                if (priv->last_lsr & MCT_U232_LSR_BI) {
                }
+               tty_kref_put(tty);
        }
 #endif
        spin_unlock_irqrestore(&priv->lock, flags);
index 7c4917d77c0a4bf5583ddb53806dae79cb308f9b..7b538caec37fa6fc91148a10a157babcb4984fca 100644 (file)
@@ -216,12 +216,13 @@ static void mos7720_bulk_in_callback(struct urb *urb)
 
        data = urb->transfer_buffer;
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        if (!port->read_urb) {
                dbg("URB KILLED !!!");
@@ -262,10 +263,11 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
 
        dbg("Entering .........");
 
-       tty = mos7720_port->port->port.tty;
+       tty = tty_port_tty_get(&mos7720_port->port->port);
 
        if (tty && mos7720_port->open)
                tty_wakeup(tty);
+       tty_kref_put(tty);
 }
 
 /*
@@ -1267,29 +1269,6 @@ static int get_lsr_info(struct tty_struct *tty,
        return 0;
 }
 
-/*
- * get_number_bytes_avail - get number of bytes available
- *
- * Purpose: Let user call ioctl to get the count of number of bytes available.
- */
-static int get_number_bytes_avail(struct moschip_port *mos7720_port,
-                                 unsigned int __user *value)
-{
-       unsigned int result = 0;
-       struct tty_struct *tty = mos7720_port->port->port.tty;
-
-       if (!tty)
-               return -ENOIOCTLCMD;
-
-       result = tty->read_cnt;
-
-       dbg("%s(%d) = %d", __func__,  mos7720_port->port->number, result);
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-
-       return -ENOIOCTLCMD;
-}
-
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                          unsigned int __user *value)
 {
@@ -1409,13 +1388,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
        dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
        switch (cmd) {
-       case TIOCINQ:
-               /* return number of bytes available */
-               dbg("%s (%d) TIOCINQ", __func__,  port->number);
-               return get_number_bytes_avail(mos7720_port,
-                                             (unsigned int __user *)arg);
-               break;
-
        case TIOCSERGETLSR:
                dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
                return get_lsr_info(tty, mos7720_port,
index 09d82062b97384f2402feda9f7401d75a76fb407..60543d79ef56b643d10b0ef78e0206cc717ae631 100644 (file)
@@ -709,12 +709,13 @@ static void mos7840_bulk_in_callback(struct urb *urb)
        dbg("%s", "Entering ........... \n");
 
        if (urb->actual_length) {
-               tty = mos7840_port->port->port.tty;
+               tty = tty_port_tty_get(&mos7840_port->port->port);
                if (tty) {
                        tty_buffer_request_room(tty, urb->actual_length);
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        dbg(" %s \n", data);
                        tty_flip_buffer_push(tty);
+                       tty_kref_put(tty);
                }
                mos7840_port->icount.rx += urb->actual_length;
                smp_wmb();
@@ -773,10 +774,10 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
 
        dbg("%s \n", "Entering .........");
 
-       tty = mos7840_port->port->port.tty;
-
+       tty = tty_port_tty_get(&mos7840_port->port->port);
        if (tty && mos7840_port->open)
                tty_wakeup(tty);
+       tty_kref_put(tty);
 
 }
 
index d6736531a0fab1be65f8fe78a01ffb3bc535a207..bcdcbb822705fd952863dcd5d041abef4d8daad3 100644 (file)
@@ -64,12 +64,13 @@ static void navman_read_int_callback(struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __func__,
                              urb->actual_length, data);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length);
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
 exit:
        result = usb_submit_urb(urb, GFP_ATOMIC);
index ae8e227f3db2c940a9cd0fb65b1be4641162ac95..c4d70b0f1e48cd8026805aa2c47660b46d25b237 100644 (file)
@@ -172,7 +172,7 @@ static int omninet_open(struct tty_struct *tty,
        dbg("%s - port %d", __func__, port->number);
 
        wport = serial->port[1];
-       wport->port.tty = tty;          /* FIXME */
+       tty_port_tty_set(&wport->port, tty);
 
        /* Start reading from the device */
        usb_fill_bulk_urb(port->read_urb, serial->dev,
@@ -229,9 +229,11 @@ static void omninet_read_bulk_callback(struct urb *urb)
        }
 
        if (urb->actual_length && header->oh_len) {
-               tty_insert_flip_string(port->port.tty,
-                       data + OMNINET_DATAOFFSET, header->oh_len);
-               tty_flip_buffer_push(port->port.tty);
+               struct tty_struct *tty = tty_port_tty_get(&port->port);
+               tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET,
+                                                       header->oh_len);
+               tty_flip_buffer_push(tty);
+               tty_kref_put(tty);
        }
 
        /* Continue trying to always read  */
index 73f8277f88f2d26d57dafa9604f4eae5cb0468a9..6b1727e751e3bbc03e0bc5809fef36e44a991d07 100644 (file)
@@ -571,14 +571,14 @@ static void option_indat_callback(struct urb *urb)
                dbg("%s: nonzero status: %d on endpoint %02x.",
                    __func__, status, endpoint);
        } else {
-               tty = port->port.tty;
+               tty = tty_port_tty_get(&port->port);
                if (urb->actual_length) {
                        tty_buffer_request_room(tty, urb->actual_length);
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
-               } else {
+               } else 
                        dbg("%s: empty read urb received", __func__);
-               }
+               tty_kref_put(tty);
 
                /* Resubmit urb so we continue receiving */
                if (port->port.count && status != -ESHUTDOWN) {
@@ -647,9 +647,13 @@ static void option_instat_callback(struct urb *urb)
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-                       if (port->port.tty && !C_CLOCAL(port->port.tty) &&
-                                       old_dcd_state && !portdata->dcd_state)
-                               tty_hangup(port->port.tty);
+                       if (old_dcd_state && !portdata->dcd_state) {
+                               struct tty_struct *tty =
+                                               tty_port_tty_get(&port->port);
+                               if (tty && !C_CLOCAL(tty))
+                                       tty_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                } else {
                        dbg("%s: type %x req %x", __func__,
                                req_pkt->bRequestType, req_pkt->bRequest);
@@ -793,7 +797,7 @@ static void option_close(struct tty_struct *tty,
                for (i = 0; i < N_OUT_URB; i++)
                        usb_kill_urb(portdata->out_urbs[i]);
        }
-       port->port.tty = NULL;  /* FIXME */
+       tty_port_tty_set(&port->port, NULL);
 }
 
 /* Helper functions used by option_setup_urbs */
index 81db5715ee25ef5d0769494a11318c4cf866e0ad..ba551f00f16ff1ec30fbcd90422f1e1112e8c00a 100644 (file)
@@ -224,10 +224,6 @@ struct oti6858_private {
        struct usb_serial_port *port;   /* USB port with which associated */
 };
 
-#undef dbg
-/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */
-#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg)
-
 static void setup_line(struct work_struct *work)
 {
        struct oti6858_private *priv = container_of(work,
@@ -1002,11 +998,12 @@ static void oti6858_read_bulk_callback(struct urb *urb)
                return;
        }
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty != NULL && urb->actual_length > 0) {
                tty_insert_flip_string(tty, data, urb->actual_length);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* schedule the interrupt urb if we are still open */
        if (port->port.count != 0) {
index 1ede1441cb1b8aca43e699d3dbc0d1d45d9b5431..908437847165b4a34d26468891a273f26bf62ab2 100644 (file)
@@ -154,7 +154,6 @@ struct pl2303_private {
        wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
-       u8 termios_initialized;
        enum pl2303_type type;
 };
 
@@ -526,16 +525,6 @@ static void pl2303_set_termios(struct tty_struct *tty,
 
        dbg("%s -  port %d", __func__, port->number);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       if (!priv->termios_initialized) {
-               *(tty->termios) = tty_std_termios;
-               tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-               tty->termios->c_ispeed = 9600;
-               tty->termios->c_ospeed = 9600;
-               priv->termios_initialized = 1;
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        /* The PL2303 is reported to lose bytes if you change
           serial settings even to the same values as before. Thus
           we actually need to filter in this specific case */
@@ -1057,7 +1046,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
                tty_flag = TTY_FRAME;
        dbg("%s - tty_flag = %d", __func__, tty_flag);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length + 1);
                /* overrun is special, not associated with a char */
@@ -1067,7 +1056,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
                        tty_insert_flip_char(tty, data[i], tty_flag);
                tty_flip_buffer_push(tty);
        }
-
+       tty_kref_put(tty);
        /* Schedule the next read _if_ we are still open */
        if (port->port.count) {
                urb->dev = port->serial->dev;
index def52d07a4ea34f817c03b60ecc827655fd05d3a..72903ac9f5c0e1fff02eafbebdcfc6e356ea1e3c 100644 (file)
@@ -217,6 +217,7 @@ static void safe_read_bulk_callback(struct urb *urb)
        struct usb_serial_port *port =  urb->context;
        unsigned char *data = urb->transfer_buffer;
        unsigned char length = urb->actual_length;
+       struct tty_struct *tty;
        int result;
        int status = urb->status;
 
@@ -242,6 +243,7 @@ static void safe_read_bulk_callback(struct urb *urb)
                printk("\n");
        }
 #endif
+       tty = tty_port_tty_get(&port->port);
        if (safe) {
                __u16 fcs;
                fcs = fcs_compute10(data, length, CRC10_INITFCS);
@@ -250,9 +252,9 @@ static void safe_read_bulk_callback(struct urb *urb)
                        if (actual_length <= (length - 2)) {
                                info("%s - actual: %d", __func__,
                                                        actual_length);
-                               tty_insert_flip_string(port->port.tty,
+                               tty_insert_flip_string(tty,
                                                        data, actual_length);
-                               tty_flip_buffer_push(port->port.tty);
+                               tty_flip_buffer_push(tty);
                        } else {
                                err("%s - inconsistent lengths %d:%d",
                                        __func__, actual_length, length);
@@ -261,9 +263,10 @@ static void safe_read_bulk_callback(struct urb *urb)
                        err("%s - bad CRC %x", __func__, fcs);
                }
        } else {
-               tty_insert_flip_string(port->port.tty, data, length);
-               tty_flip_buffer_push(port->port.tty);
+               tty_insert_flip_string(tty, data, length);
+               tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* Continue trying to always read  */
        usb_fill_bulk_urb(urb, port->serial->dev,
index ea1a103c99bea9f23d3a4eb7fb4f846ccbed987f..8b9eaf38367905efc44ae1a6f7bdb216996b1a68 100644 (file)
@@ -440,14 +440,14 @@ static void sierra_indat_callback(struct urb *urb)
                dbg("%s: nonzero status: %d on endpoint %02x.",
                    __func__, status, endpoint);
        } else {
-               tty = port->port.tty;
                if (urb->actual_length) {
+               tty = tty_port_tty_get(&port->port);
                        tty_buffer_request_room(tty, urb->actual_length);
                        tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
-               } else {
+                       tty_kref_put(tty);
+               } else
                        dbg("%s: empty read urb received", __func__);
-               }
 
                /* Resubmit urb so we continue receiving */
                if (port->port.count && status != -ESHUTDOWN) {
@@ -485,6 +485,7 @@ static void sierra_instat_callback(struct urb *urb)
                        unsigned char signals = *((unsigned char *)
                                        urb->transfer_buffer +
                                        sizeof(struct usb_ctrlrequest));
+                       struct tty_struct *tty;
 
                        dbg("%s: signal x%x", __func__, signals);
 
@@ -494,9 +495,11 @@ static void sierra_instat_callback(struct urb *urb)
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-                       if (port->port.tty && !C_CLOCAL(port->port.tty) &&
+                       tty = tty_port_tty_get(&port->port);
+                       if (tty && !C_CLOCAL(tty) &&
                                        old_dcd_state && !portdata->dcd_state)
-                               tty_hangup(port->port.tty);
+                               tty_hangup(tty);
+                       tty_kref_put(tty);
                } else {
                        dbg("%s: type %x req %x", __func__,
                                req_pkt->bRequestType, req_pkt->bRequest);
@@ -616,8 +619,7 @@ static void sierra_close(struct tty_struct *tty,
        }
 
        usb_kill_urb(port->interrupt_in_urb);
-
-       port->port.tty = NULL;  /* FIXME */
+       tty_port_tty_set(&port->port, NULL);
 }
 
 static int sierra_startup(struct usb_serial *serial)
index 283cf6b36b2c0cca7f77c7ce0409c4420faa6753..1533d6e122387317b07576a74239009bc3be9296 100644 (file)
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
                tty_flag = TTY_FRAME;
        dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
                tty_buffer_request_room(tty, urb->actual_length + 1);
                /* overrun is special, not associated with a char */
@@ -765,6 +765,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
                        tty_insert_flip_char(tty, data[i], tty_flag);
                tty_flip_buffer_push(tty);
        }
+       tty_kref_put(tty);
 
        /* Schedule the next read _if_ we are still open */
        if (port->port.count) {
index 9a3e495c769cc92f7abaa59d33d7138fe2e73f73..c90237d48b0e6e8a22e59498e78bfff83c8bf9ed 100644 (file)
@@ -179,7 +179,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
 static int ti_get_lsr(struct ti_port *tport);
 static int ti_get_serial_info(struct ti_port *tport,
        struct serial_struct __user *ret_arg);
-static int ti_set_serial_info(struct ti_port *tport,
+static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
        struct serial_struct __user *new_arg);
 static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
 
@@ -857,8 +857,8 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file,
                                (struct serial_struct __user *)arg);
        case TIOCSSERIAL:
                dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
-               return ti_set_serial_info(tport,
-                                       (struct serial_struct __user *)arg);
+               return ti_set_serial_info(tty, tport,
+                               (struct serial_struct __user *)arg);
        case TIOCMIWAIT:
                dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
                cprev = tport->tp_icount;
@@ -1211,6 +1211,7 @@ static void ti_bulk_in_callback(struct urb *urb)
        struct device *dev = &urb->dev->dev;
        int status = urb->status;
        int retval = 0;
+       struct tty_struct *tty;
 
        dbg("%s", __func__);
 
@@ -1239,20 +1240,22 @@ static void ti_bulk_in_callback(struct urb *urb)
                return;
        }
 
-       if (port->port.tty && urb->actual_length) {
+       tty = tty_port_tty_get(&port->port);
+       if (tty && urb->actual_length) {
                usb_serial_debug_data(debug, dev, __func__,
                        urb->actual_length, urb->transfer_buffer);
 
                if (!tport->tp_is_open)
                        dbg("%s - port closed, dropping data", __func__);
                else
-                       ti_recv(&urb->dev->dev, port->port.tty,
+                       ti_recv(&urb->dev->dev, tty,
                                                urb->transfer_buffer,
                                                urb->actual_length);
 
                spin_lock(&tport->tp_lock);
                tport->tp_icount.rx += urb->actual_length;
                spin_unlock(&tport->tp_lock);
+               tty_kref_put(tty);
        }
 
 exit:
@@ -1330,7 +1333,7 @@ static void ti_send(struct ti_port *tport)
 {
        int count, result;
        struct usb_serial_port *port = tport->tp_port;
-       struct tty_struct *tty = port->port.tty;        /* FIXME */
+       struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */
        unsigned long flags;
 
 
@@ -1338,19 +1341,15 @@ static void ti_send(struct ti_port *tport)
 
        spin_lock_irqsave(&tport->tp_lock, flags);
 
-       if (tport->tp_write_urb_in_use) {
-               spin_unlock_irqrestore(&tport->tp_lock, flags);
-               return;
-       }
+       if (tport->tp_write_urb_in_use)
+               goto unlock;
 
        count = ti_buf_get(tport->tp_write_buf,
                                port->write_urb->transfer_buffer,
                                port->bulk_out_size);
 
-       if (count == 0) {
-               spin_unlock_irqrestore(&tport->tp_lock, flags);
-               return;
-       }
+       if (count == 0)
+               goto unlock;
 
        tport->tp_write_urb_in_use = 1;
 
@@ -1380,7 +1379,13 @@ static void ti_send(struct ti_port *tport)
        /* more room in the buffer for new writes, wakeup */
        if (tty)
                tty_wakeup(tty);
+       tty_kref_put(tty);
        wake_up_interruptible(&tport->tp_write_wait);
+       return;
+unlock:
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
+       tty_kref_put(tty);
+       return;
 }
 
 
@@ -1464,20 +1469,16 @@ static int ti_get_serial_info(struct ti_port *tport,
 }
 
 
-static int ti_set_serial_info(struct ti_port *tport,
+static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
        struct serial_struct __user *new_arg)
 {
-       struct usb_serial_port *port = tport->tp_port;
        struct serial_struct new_serial;
 
        if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
                return -EFAULT;
 
        tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
-       /* FIXME */
-       if (port->port.tty)
-               port->port.tty->low_latency =
-                       (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+       tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
        tport->tp_closing_wait = new_serial.closing_wait;
 
        return 0;
@@ -1510,7 +1511,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
        tport->tp_msr = msr & TI_MSR_MASK;
 
        /* handle CTS flow control */
-       tty = tport->tp_port->port.tty;
+       tty = tty_port_tty_get(&tport->tp_port->port);
        if (tty && C_CRTSCTS(tty)) {
                if (msr & TI_MSR_CTS) {
                        tty->hw_stopped = 0;
@@ -1519,6 +1520,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
                        tty->hw_stopped = 1;
                }
        }
+       tty_kref_put(tty);
 }
 
 
index 4f7f9e3ae0a43fe0fd630aaf4f436637383b0e4d..e7d4246027b23763e2b5ad86215a20029a10d8ed 100644 (file)
@@ -214,7 +214,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
        /* set up our port structure making the tty driver
         * remember our port object, and us it */
        tty->driver_data = port;
-       port->port.tty = tty;
+       tty_port_tty_set(&port->port, tty);
 
        if (port->port.count == 1) {
 
@@ -246,7 +246,7 @@ bailout_module_put:
 bailout_mutex_unlock:
        port->port.count = 0;
        tty->driver_data = NULL;
-       port->port.tty = NULL;
+       tty_port_tty_set(&port->port, NULL);
        mutex_unlock(&port->mutex);
 bailout_kref_put:
        usb_serial_put(serial);
@@ -276,10 +276,11 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
                port->serial->type->close(tty, port, filp);
 
        if (port->port.count == (port->console? 1 : 0)) {
-               if (port->port.tty) {
-                       if (port->port.tty->driver_data)
-                               port->port.tty->driver_data = NULL;
-                       port->port.tty = NULL;
+               struct tty_struct *tty = tty_port_tty_get(&port->port);
+               if (tty) {
+                       if (tty->driver_data)
+                               tty->driver_data = NULL;
+                       tty_port_tty_set(&port->port, NULL);
                }
        }
 
@@ -508,11 +509,12 @@ static void usb_serial_port_work(struct work_struct *work)
        if (!port)
                return;
 
-       tty = port->port.tty;
+       tty = tty_port_tty_get(&port->port);
        if (!tty)
                return;
 
        tty_wakeup(tty);
+       tty_kref_put(tty);
 }
 
 static void port_release(struct device *dev)
@@ -819,6 +821,7 @@ int usb_serial_probe(struct usb_interface *interface,
                port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
                if (!port)
                        goto probe_error;
+               tty_port_init(&port->port);
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
@@ -1040,8 +1043,11 @@ void usb_serial_disconnect(struct usb_interface *interface)
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (port) {
-                       if (port->port.tty)
-                               tty_hangup(port->port.tty);
+                       struct tty_struct *tty = tty_port_tty_get(&port->port);
+                       if (tty) {
+                               tty_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                        kill_traffic(port);
                }
        }
index cf8924f9a2cc1d461436caaefcbcfeb81b0f0168..a6d1c75a1c89eb3f4627744ee2c91a1d6b071a0f 100644 (file)
@@ -499,7 +499,7 @@ static void visor_read_bulk_callback(struct urb *urb)
        int status = urb->status;
        struct tty_struct *tty;
        int result;
-       int available_room;
+       int available_room = 0;
 
        dbg("%s - port %d", __func__, port->number);
 
@@ -512,13 +512,17 @@ static void visor_read_bulk_callback(struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __func__,
                                                urb->actual_length, data);
 
-       tty = port->port.tty;
-       if (tty && urb->actual_length) {
-               available_room = tty_buffer_request_room(tty,
+       if (urb->actual_length) {
+               tty = tty_port_tty_get(&port->port);
+               if (tty) {
+                       available_room = tty_buffer_request_room(tty,
                                                        urb->actual_length);
-               if (available_room) {
-                       tty_insert_flip_string(tty, data, available_room);
-                       tty_flip_buffer_push(tty);
+                       if (available_room) {
+                               tty_insert_flip_string(tty, data,
+                                                       available_room);
+                               tty_flip_buffer_push(tty);
+                       }
+                       tty_kref_put(tty);
                }
                spin_lock(&priv->lock);
                priv->bytes_in += available_room;
index 3a9d14384a4380a85ec0072d1bda7aa653ad5d7c..11c8b97a5177ad6c645861a739cc0f62f30ab667 100644 (file)
@@ -1481,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work)
        struct whiteheat_private *info =
                container_of(work, struct whiteheat_private, rx_work);
        struct usb_serial_port *port = info->port;
-       struct tty_struct *tty = port->port.tty;
+       struct tty_struct *tty = tty_port_tty_get(&port->port);
        struct whiteheat_urb_wrap *wrap;
        struct urb *urb;
        unsigned long flags;
@@ -1493,7 +1493,7 @@ static void rx_data_softint(struct work_struct *work)
        spin_lock_irqsave(&info->lock, flags);
        if (info->flags & THROTTLED) {
                spin_unlock_irqrestore(&info->lock, flags);
-               return;
+               goto out;
        }
 
        list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
@@ -1513,7 +1513,7 @@ static void rx_data_softint(struct work_struct *work)
                                spin_unlock_irqrestore(&info->lock, flags);
                                tty_flip_buffer_push(tty);
                                schedule_work(&info->rx_work);
-                               return;
+                               goto out;
                        }
                        tty_insert_flip_string(tty, urb->transfer_buffer, len);
                        sent += len;
@@ -1536,6 +1536,8 @@ static void rx_data_softint(struct work_struct *work)
 
        if (sent)
                tty_flip_buffer_push(tty);
+out:
+       tty_kref_put(tty);
 }
 
 
index f79c2040758b4ab43d867acaa451c1d2b3891934..0f13448c6f799b05fdebd78e67031610ff25514e 100644 (file)
@@ -76,6 +76,14 @@ config FB_DDC
        select I2C
        default n
 
+config FB_BOOT_VESA_SUPPORT
+       bool
+       depends on FB
+       default n
+       ---help---
+         If true, at least one selected framebuffer driver can take advantage
+         of VESA video modes set at an early boot stage via the vga= parameter.
+
 config FB_CFB_FILLRECT
        tristate
        depends on FB
@@ -254,16 +262,24 @@ config FB_PM2
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        help
-         This is the frame buffer device driver for the Permedia2 AGP frame
-         buffer card from ASK, aka `Graphic Blaster Exxtreme'.  There is a
-         product page at
-         <http://www.ask.com.hk/product/Permedia%202/permedia2.htm>.
+         This is the frame buffer device driver for cards based on
+         the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
+         The driver was tested on the following cards:
+               Diamond FireGL 1000 PRO AGP
+               ELSA Gloria Synergy PCI
+               Appian Jeronimo PRO (both heads) PCI
+               3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
+               Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
+               ASK Graphic Blaster Exxtreme AGP
+
+         To compile this driver as a module, choose M here: the
+         module will be called pm2fb.
 
 config FB_PM2_FIFO_DISCONNECT
        bool "enable FIFO disconnect feature"
        depends on FB_PM2 && PCI
        help
-         Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
+         Support the Permedia2 FIFO disconnect feature.
 
 config FB_ARMCLCD
        tristate "ARM PrimeCell PL110 support"
@@ -673,6 +689,7 @@ config FB_VESA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_BOOT_VESA_SUPPORT
        help
          This is the frame buffer device driver for generic VESA 2.0
          compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -681,23 +698,14 @@ config FB_VESA
 
 config FB_EFI
        bool "EFI-based Framebuffer Support"
-       depends on (FB = y) && X86
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the EFI frame buffer device driver. If the firmware on
-         your platform is UEFI2.0, select Y to add support for
-         Graphics Output Protocol for early console messages to appear.
-
-config FB_IMAC
-       bool "Intel-based Macintosh Framebuffer Support"
        depends on (FB = y) && X86 && EFI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        help
-         This is the frame buffer device driver for the Intel-based Macintosh
+         This is the EFI frame buffer device driver. If the firmware on
+         your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
+         using the EFI framebuffer as your console.
 
 config FB_N411
        tristate "N411 Apollo/Hecuba devkit support"
@@ -1118,6 +1126,7 @@ config FB_INTEL
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_BOOT_VESA_SUPPORT
        help
          This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
@@ -1470,6 +1479,7 @@ config FB_SIS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_BOOT_VESA_SUPPORT
        help
          This is the frame buffer device driver for the SiS 300, 315, 330
          and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@@ -1492,6 +1502,24 @@ config FB_SIS_315
          (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
          as XGI V3XT, V5, V8 and Z7.
 
+config FB_VIA
+       tristate "VIA UniChrome (Pro) and Chrome9 display support"
+       depends on FB && PCI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
+       select I2C_ALGOBIT
+       select I2C
+       help
+         This is the frame buffer device driver for Graphics chips of VIA
+         UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
+         CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
+         /P4M900,VX800)
+         Say Y if you have a VIA UniChrome graphics board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called viafb.
 config FB_NEOMAGIC
        tristate "NeoMagic display support"
        depends on FB && PCI
@@ -1521,25 +1549,25 @@ config FB_KYRO
          module will be called kyrofb.
 
 config FB_3DFX
-       tristate "3Dfx Banshee/Voodoo3 display support"
+       tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
        depends on FB && PCI
        select FB_CFB_IMAGEBLIT
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        help
-         This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
-         chips. Say Y if you have such a graphics board.
+         This driver supports graphics boards with the 3Dfx Banshee,
+         Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
+         such a graphics board.
 
          To compile this driver as a module, choose M here: the
          module will be called tdfxfb.
 
 config FB_3DFX_ACCEL
-       bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)"
+       bool "3Dfx Acceleration functions (EXPERIMENTAL)"
        depends on FB_3DFX && EXPERIMENTAL
        ---help---
-       This will compile the 3Dfx Banshee/Voodoo3 frame buffer device
-       with acceleration functions.
-
+       This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
+       device driver with acceleration functions.
 
 config FB_VOODOO1
        tristate "3Dfx Voodoo Graphics (sst1) support"
@@ -1604,17 +1632,16 @@ config FB_TRIDENT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        ---help---
-         This driver is supposed to support graphics boards with the
-         Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
+         This is the frame buffer device driver for Trident PCI/AGP chipsets.
+         Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
+         and Blade XP.
+         There are also integrated versions of these chips called CyberXXXX,
+         CyberImage or CyberBlade. These chips are mostly found in laptops
          but also on some motherboards. For more information, read
          <file:Documentation/fb/tridentfb.txt>
 
-         Cyberblade/i1 support will be removed soon, use the cyblafb driver
-         instead.
-
          Say Y if you have such a graphics board.
 
-
          To compile this driver as a module, choose M here: the
          module will be called tridentfb.
 
@@ -1869,6 +1896,28 @@ config FB_SH_MOBILE_LCDC
        ---help---
          Frame buffer driver for the on-chip SH-Mobile LCD controller.
 
+config FB_TMIO
+       tristate "Toshiba Mobile IO FrameBuffer support"
+       depends on FB && MFD_CORE
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         Frame buffer driver for the Toshiba Mobile IO integrated as found
+         on the Sharp SL-6000 series
+
+         This driver is also available as a module ( = code which can be
+         inserted and removed from the running kernel whenever you want). The
+         module will be called tmiofb. If you want to compile it as a module,
+         say M here and read <file:Documentation/kbuild/modules.txt>.
+
+         If unsure, say N.
+
+config FB_TMIO_ACCELL
+       bool "tmiofb acceleration"
+       depends on FB_TMIO
+       default y
+
 config FB_S3C2410
        tristate "S3C2410 LCD framebuffer support"
        depends on FB && ARCH_S3C2410
index ad0330bf9be3a7fe6d26aa82869be16dae41856c..248bddc8d0b0bb0e7e970d30dc2427f51b6d6e76 100644 (file)
@@ -42,6 +42,7 @@ obj-$(CONFIG_FB_ATY)            += aty/ macmodes.o
 obj-$(CONFIG_FB_ATY128)                  += aty/ macmodes.o
 obj-$(CONFIG_FB_RADEON)                  += aty/
 obj-$(CONFIG_FB_SIS)             += sis/
+obj-$(CONFIG_FB_VIA)             += via/
 obj-$(CONFIG_FB_KYRO)             += kyro/
 obj-$(CONFIG_FB_SAVAGE)                  += savage/
 obj-$(CONFIG_FB_GEODE)           += geode/
@@ -97,6 +98,7 @@ obj-$(CONFIG_FB_CIRRUS)                 += cirrusfb.o
 obj-$(CONFIG_FB_ASILIANT)        += asiliantfb.o
 obj-$(CONFIG_FB_PXA)             += pxafb.o
 obj-$(CONFIG_FB_W100)            += w100fb.o
+obj-$(CONFIG_FB_TMIO)            += tmiofb.o
 obj-$(CONFIG_FB_AU1100)                  += au1100fb.o
 obj-$(CONFIG_FB_AU1200)                  += au1200fb.o
 obj-$(CONFIG_FB_PMAG_AA)         += pmag-aa-fb.o
@@ -124,7 +126,6 @@ obj-$(CONFIG_FB_CARMINE)          += carminefb.o
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
 obj-$(CONFIG_FB_VESA)             += vesafb.o
-obj-$(CONFIG_FB_IMAC)             += imacfb.o
 obj-$(CONFIG_FB_EFI)              += efifb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
index d38fd5217422f8de3e3b97ecbd5cbd65056a0977..f8d0a57a07cbe3852d4128b0b6d46c8eddefebd5 100644 (file)
@@ -372,6 +372,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
        var->transp.offset = var->transp.length = 0;
        var->xoffset = var->yoffset = 0;
 
+       if (info->fix.smem_len) {
+               unsigned int smem_len = (var->xres_virtual * var->yres_virtual
+                                        * ((var->bits_per_pixel + 7) / 8));
+               if (smem_len > info->fix.smem_len)
+                       return -EINVAL;
+       }
+
        /* Saturate vertical and horizontal timings at maximum values */
        var->vsync_len = min_t(u32, var->vsync_len,
                        (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
index aa95f835024282ca4e88142d9f957d393271c4ee..8718f7349d6b8961eb1ed90d3ce8ea13b75a5853 100644 (file)
@@ -5,61 +5,61 @@
  * --dte
  */
 
-static void radeon_fixup_offset(struct radeonfb_info *rinfo)
+#define FLUSH_CACHE_WORKAROUND 1
+
+void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries)
 {
-       u32 local_base;
-
-       /* *** Ugly workaround *** */
-       /*
-        * On some platforms, the video memory is mapped at 0 in radeon chip space
-        * (like PPCs) by the firmware. X will always move it up so that it's seen
-        * by the chip to be at the same address as the PCI BAR.
-        * That means that when switching back from X, there is a mismatch between
-        * the offsets programmed into the engine. This means that potentially,
-        * accel operations done before radeonfb has a chance to re-init the engine
-        * will have incorrect offsets, and potentially trash system memory !
-        *
-        * The correct fix is for fbcon to never call any accel op before the engine
-        * has properly been re-initialized (by a call to set_var), but this is a
-        * complex fix. This workaround in the meantime, called before every accel
-        * operation, makes sure the offsets are in sync.
-        */
+       int i;
 
-       radeon_fifo_wait (1);
-       local_base = INREG(MC_FB_LOCATION) << 16;
-       if (local_base == rinfo->fb_local_base)
-               return;
+       for (i=0; i<2000000; i++) {
+               rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f;
+               if (rinfo->fifo_free >= entries)
+                       return;
+               udelay(10);
+       }
+       printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
+       /* XXX Todo: attempt to reset the engine */
+}
 
-       rinfo->fb_local_base = local_base;
+static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+       if (entries <= rinfo->fifo_free)
+               rinfo->fifo_free -= entries;
+       else
+               radeon_fifo_update_and_wait(rinfo, entries);
+}
 
-       radeon_fifo_wait (3);
-       OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
-                                    (rinfo->fb_local_base >> 10));
-       OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
-       OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg,
+                                    u32 *cache, u32 new_val)
+{
+       if (new_val == *cache)
+               return;
+       *cache = new_val;
+       radeon_fifo_wait(rinfo, 1);
+       OUTREG(reg, new_val);
 }
 
 static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 
                                   const struct fb_fillrect *region)
 {
-       radeon_fifo_wait(4);  
-  
-       OUTREG(DP_GUI_MASTER_CNTL,  
-               rinfo->dp_gui_master_cntl  /* contains, like GMC_DST_32BPP */
-                | GMC_BRUSH_SOLID_COLOR
-                | ROP3_P);
-       if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
-               OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
-       else
-               OUTREG(DP_BRUSH_FRGD_CLR, region->color);
-       OUTREG(DP_WRITE_MSK, 0xffffffff);
-       OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
-
-       radeon_fifo_wait(2);
+       radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+                         rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P);
+       radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+                         DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+       radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache,
+                         region->color);
+
+       /* Ensure the dst cache is flushed and the engine idle before
+        * issuing the operation.
+        *
+        * This works around engine lockups on some cards
+        */
+#if FLUSH_CACHE_WORKAROUND
+       radeon_fifo_wait(rinfo, 2);
        OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
        OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
-       radeon_fifo_wait(2);  
+#endif
+       radeon_fifo_wait(rinfo, 2);
        OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
        OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
 }
@@ -70,15 +70,14 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
        struct fb_fillrect modded;
        int vxres, vyres;
   
-       if (info->state != FBINFO_STATE_RUNNING)
+       WARN_ON(rinfo->gfx_mode);
+       if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
                return;
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
                cfb_fillrect(info, region);
                return;
        }
 
-       radeon_fixup_offset(rinfo);
-
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
 
@@ -91,6 +90,10 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
        if(modded.dx + modded.width  > vxres) modded.width  = vxres - modded.dx;
        if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
 
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR )
+               modded.color = ((u32 *) (info->pseudo_palette))[region->color];
+
        radeonfb_prim_fillrect(rinfo, &modded);
 }
 
@@ -109,22 +112,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
        if ( xdir < 0 ) { sx += w-1; dx += w-1; }
        if ( ydir < 0 ) { sy += h-1; dy += h-1; }
 
-       radeon_fifo_wait(3);
-       OUTREG(DP_GUI_MASTER_CNTL,
-               rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
-               | GMC_BRUSH_NONE
-               | GMC_SRC_DSTCOLOR
-               | ROP3_S 
-               | DP_SRC_SOURCE_MEMORY );
-       OUTREG(DP_WRITE_MSK, 0xffffffff);
-       OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
-                       | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
-
-       radeon_fifo_wait(2);
+       radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+                         rinfo->dp_gui_mc_base |
+                         GMC_BRUSH_NONE |
+                         GMC_SRC_DATATYPE_COLOR |
+                         ROP3_S |
+                         DP_SRC_SOURCE_MEMORY);
+       radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+                         (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
+                         (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
+
+#if FLUSH_CACHE_WORKAROUND
+       radeon_fifo_wait(rinfo, 2);
        OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
        OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
-
-       radeon_fifo_wait(3);
+#endif
+       radeon_fifo_wait(rinfo, 3);
        OUTREG(SRC_Y_X, (sy << 16) | sx);
        OUTREG(DST_Y_X, (dy << 16) | dx);
        OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
@@ -143,15 +146,14 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        modded.width  = area->width;
        modded.height = area->height;
   
-       if (info->state != FBINFO_STATE_RUNNING)
+       WARN_ON(rinfo->gfx_mode);
+       if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
                return;
        if (info->flags & FBINFO_HWACCEL_DISABLED) {
                cfb_copyarea(info, area);
                return;
        }
 
-       radeon_fixup_offset(rinfo);
-
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
 
@@ -168,13 +170,112 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
        radeonfb_prim_copyarea(rinfo, &modded);
 }
 
+static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo,
+                                   const struct fb_image *image,
+                                   u32 fg, u32 bg)
+{
+       unsigned int src_bytes, dwords;
+       u32 *bits;
+
+       radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
+                         rinfo->dp_gui_mc_base |
+                         GMC_BRUSH_NONE |
+                         GMC_SRC_DATATYPE_MONO_FG_BG |
+                         ROP3_S |
+                         GMC_BYTE_ORDER_MSB_TO_LSB |
+                         DP_SRC_SOURCE_HOST_DATA);
+       radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
+                         DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+       radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg);
+       radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg);
+
+       radeon_fifo_wait(rinfo, 1);
+       OUTREG(DST_Y_X, (image->dy << 16) | image->dx);
+
+       /* Ensure the dst cache is flushed and the engine idle before
+        * issuing the operation.
+        *
+        * This works around engine lockups on some cards
+        */
+#if FLUSH_CACHE_WORKAROUND
+       radeon_fifo_wait(rinfo, 2);
+       OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
+       OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
+#endif
+
+       /* X here pads width to a multiple of 32 and uses the clipper to
+        * adjust the result. Is that really necessary ? Things seem to
+        * work ok for me without that and the doco doesn't seem to imply
+        * there is such a restriction.
+        */
+       OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height);
+
+       src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
+       dwords = (src_bytes + 3) / 4;
+       bits = (u32*)(image->data);
+
+       while(dwords >= 8) {
+               radeon_fifo_wait(rinfo, 8);
+#if BITS_PER_LONG == 64
+               __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0);
+               __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2);
+               __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4);
+               __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6);
+               bits += 8;
+#else
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7);
+#endif
+               dwords -= 8;
+       }
+       while(dwords--) {
+               radeon_fifo_wait(rinfo, 1);
+               __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
+       }
+}
+
 void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        struct radeonfb_info *rinfo = info->par;
+       u32 fg, bg;
 
-       if (info->state != FBINFO_STATE_RUNNING)
+       WARN_ON(rinfo->gfx_mode);
+       if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
+               return;
+
+       if (!image->width || !image->height)
                return;
-       radeon_engine_idle();
+
+       /* We only do 1 bpp color expansion for now */
+       if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
+               goto fallback;
+
+       /* Fallback if running out of the screen. We may do clipping
+        * in the future */
+       if ((image->dx + image->width) > info->var.xres_virtual ||
+           (image->dy + image->height) > info->var.yres_virtual)
+               goto fallback;
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+               fg = ((u32*)(info->pseudo_palette))[image->fg_color];
+               bg = ((u32*)(info->pseudo_palette))[image->bg_color];
+       } else {
+               fg = image->fg_color;
+               bg = image->bg_color;
+       }
+
+       radeonfb_prim_imageblit(rinfo, image, fg, bg);
+       return;
+
+ fallback:
+       radeon_engine_idle(rinfo);
 
        cfb_imageblit(info, image);
 }
@@ -185,7 +286,8 @@ int radeonfb_sync(struct fb_info *info)
 
        if (info->state != FBINFO_STATE_RUNNING)
                return 0;
-       radeon_engine_idle();
+
+       radeon_engine_idle(rinfo);
 
        return 0;
 }
@@ -211,9 +313,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
        host_path_cntl = INREG(HOST_PATH_CNTL);
        rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
 
-       if (rinfo->family == CHIP_FAMILY_R300 ||
-           rinfo->family == CHIP_FAMILY_R350 ||
-           rinfo->family == CHIP_FAMILY_RV350) {
+       if (IS_R300_VARIANT(rinfo)) {
                u32 tmp;
 
                OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -249,9 +349,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
        INREG(HOST_PATH_CNTL);
        OUTREG(HOST_PATH_CNTL, host_path_cntl);
 
-       if (rinfo->family != CHIP_FAMILY_R300 &&
-           rinfo->family != CHIP_FAMILY_R350 &&
-           rinfo->family != CHIP_FAMILY_RV350)
+       if (!IS_R300_VARIANT(rinfo))
                OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
 
        OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -265,15 +363,24 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
        /* disable 3D engine */
        OUTREG(RB3D_CNTL, 0);
 
+       rinfo->fifo_free = 0;
        radeonfb_engine_reset(rinfo);
 
-       radeon_fifo_wait (1);
-       if ((rinfo->family != CHIP_FAMILY_R300) &&
-           (rinfo->family != CHIP_FAMILY_R350) &&
-           (rinfo->family != CHIP_FAMILY_RV350))
+       radeon_fifo_wait(rinfo, 1);
+       if (IS_R300_VARIANT(rinfo)) {
+               OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
+                      RB2D_DC_AUTOFLUSH_ENABLE |
+                      RB2D_DC_DC_DISABLE_IGNORE_PE);
+       } else {
+               /* This needs to be double checked with ATI. Latest X driver
+                * completely "forgets" to set this register on < r3xx, and
+                * we used to just write 0 there... I'll keep the 0 and update
+                * that when we have sorted things out on X side.
+                */
                OUTREG(RB2D_DSTCACHE_MODE, 0);
+       }
 
-       radeon_fifo_wait (3);
+       radeon_fifo_wait(rinfo, 3);
        /* We re-read MC_FB_LOCATION from card as it can have been
         * modified by XFree drivers (ouch !)
         */
@@ -284,41 +391,57 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
        OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
        OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
 
-       radeon_fifo_wait (1);
-#if defined(__BIG_ENDIAN)
+       radeon_fifo_wait(rinfo, 1);
+#ifdef __BIG_ENDIAN
        OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
 #else
        OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
 #endif
-       radeon_fifo_wait (2);
+       radeon_fifo_wait(rinfo, 2);
        OUTREG(DEFAULT_SC_TOP_LEFT, 0);
        OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
                                         DEFAULT_SC_BOTTOM_MAX));
 
+       /* set default DP_GUI_MASTER_CNTL */
        temp = radeon_get_dstbpp(rinfo->depth);
-       rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
+       rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
 
-       radeon_fifo_wait (1);
-       OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
-                                   GMC_BRUSH_SOLID_COLOR |
-                                   GMC_SRC_DATATYPE_COLOR));
+       rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base |
+               GMC_BRUSH_SOLID_COLOR |
+               GMC_SRC_DATATYPE_COLOR;
+       radeon_fifo_wait(rinfo, 1);
+       OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache);
 
-       radeon_fifo_wait (7);
 
        /* clear line drawing regs */
+       radeon_fifo_wait(rinfo, 2);
        OUTREG(DST_LINE_START, 0);
        OUTREG(DST_LINE_END, 0);
 
-       /* set brush color regs */
-       OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
-       OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
-
-       /* set source color regs */
-       OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
-       OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
+       /* set brush and source color regs */
+       rinfo->dp_brush_fg_cache = 0xffffffff;
+       rinfo->dp_brush_bg_cache = 0x00000000;
+       rinfo->dp_src_fg_cache = 0xffffffff;
+       rinfo->dp_src_bg_cache = 0x00000000;
+       radeon_fifo_wait(rinfo, 4);
+       OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache);
+       OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache);
+       OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache);
+       OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache);
+
+       /* Default direction */
+       rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM;
+       radeon_fifo_wait(rinfo, 1);
+       OUTREG(DP_CNTL, rinfo->dp_cntl_cache);
 
        /* default write mask */
+       radeon_fifo_wait(rinfo, 1);
        OUTREG(DP_WRITE_MSK, 0xffffffff);
 
-       radeon_engine_idle ();
+       /* Default to no swapping of host data */
+       radeon_fifo_wait(rinfo, 1);
+       OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE);
+
+       /* Make sure it's settled */
+       radeon_engine_idle(rinfo);
 }
index 1a056adb61c836784fce99d1c0314e710f4948e8..f343ba83f0ae0dbb6e50d25aa8ea95239598b1fd 100644 (file)
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
                level = bd->props.brightness;
 
        del_timer_sync(&rinfo->lvds_timer);
-       radeon_engine_idle();
+       radeon_engine_idle(rinfo);
 
        lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
        if (level > 0) {
index 652273e9f5f9223fc80261d035c114765ea59f71..9a5821c65ebf22fd2d492ee3972002bb2f5cc651 100644 (file)
@@ -852,7 +852,6 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
         if (rinfo->asleep)
                return 0;
 
-       radeon_fifo_wait(2);
         OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
                             * var->bits_per_pixel / 8) & ~7);
         return 0;
@@ -882,7 +881,6 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
                        if (rc)
                                return rc;
 
-                       radeon_fifo_wait(2);
                        if (value & 0x01) {
                                tmp = INREG(LVDS_GEN_CNTL);
 
@@ -940,7 +938,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
        if (rinfo->lock_blank)
                return 0;
 
-       radeon_engine_idle();
+       radeon_engine_idle(rinfo);
 
        val = INREG(CRTC_EXT_CNTL);
         val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
@@ -1048,7 +1046,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
 
        if (rinfo->asleep)
                return 0;
-               
+
        return radeon_screen_blank(rinfo, blank, 0);
 }
 
@@ -1074,8 +1072,6 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
         pindex = regno;
 
         if (!rinfo->asleep) {
-               radeon_fifo_wait(9);
-
                if (rinfo->bpp == 16) {
                        pindex = regno * 8;
 
@@ -1244,8 +1240,6 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
 {
        int i;
 
-       radeon_fifo_wait(20);
-
        /* Workaround from XFree */
        if (rinfo->is_mobility) {
                /* A temporal workaround for the occational blanking on certain laptop
@@ -1286,11 +1280,10 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
        radeon_pll_errata_after_data(rinfo);
 
        /* Set PPLL ref. div */
-       if (rinfo->family == CHIP_FAMILY_R300 ||
+       if (IS_R300_VARIANT(rinfo) ||
            rinfo->family == CHIP_FAMILY_RS300 ||
-           rinfo->family == CHIP_FAMILY_R350 ||
-           rinfo->family == CHIP_FAMILY_RV350 ||
-           rinfo->family == CHIP_FAMILY_RV380 ) {
+           rinfo->family == CHIP_FAMILY_RS400 ||
+           rinfo->family == CHIP_FAMILY_RS480) {
                if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
                        /* When restoring console mode, use saved PPLL_REF_DIV
                         * setting.
@@ -1342,7 +1335,7 @@ static void radeon_lvds_timer_func(unsigned long data)
 {
        struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
 
-       radeon_engine_idle();
+       radeon_engine_idle(rinfo);
 
        OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
 }
@@ -1360,10 +1353,11 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
        if (nomodeset)
                return;
 
+       radeon_engine_idle(rinfo);
+
        if (!regs_only)
                radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
 
-       radeon_fifo_wait(31);
        for (i=0; i<10; i++)
                OUTREG(common_regs[i].reg, common_regs[i].val);
 
@@ -1391,7 +1385,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
        radeon_write_pll_regs(rinfo, mode);
 
        if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-               radeon_fifo_wait(10);
                OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
                OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
                OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@@ -1406,7 +1399,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
        if (!regs_only)
                radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
 
-       radeon_fifo_wait(2);
        OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
        
        return;
@@ -1461,10 +1453,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
                /* Not all chip revs have the same format for this register,
                 * extract the source selection
                 */
-               if (rinfo->family == CHIP_FAMILY_R200 ||
-                   rinfo->family == CHIP_FAMILY_R300 ||
-                   rinfo->family == CHIP_FAMILY_R350 ||
-                   rinfo->family == CHIP_FAMILY_RV350) {
+               if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
                        source = (fp2_gen_cntl >> 10) & 0x3;
                        /* sourced from transform unit, check for transform unit
                         * own source
@@ -1560,7 +1549,7 @@ static int radeonfb_set_par(struct fb_info *info)
        /* We always want engine to be idle on a mode switch, even
         * if we won't actually change the mode
         */
-       radeon_engine_idle();
+       radeon_engine_idle(rinfo);
 
        hSyncStart = mode->xres + mode->right_margin;
        hSyncEnd = hSyncStart + mode->hsync_len;
@@ -1855,7 +1844,6 @@ static int radeonfb_set_par(struct fb_info *info)
        return 0;
 }
 
-
 static struct fb_ops radeonfb_ops = {
        .owner                  = THIS_MODULE,
        .fb_check_var           = radeonfb_check_var,
@@ -1879,6 +1867,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
        info->par = rinfo;
        info->pseudo_palette = rinfo->pseudo_palette;
        info->flags = FBINFO_DEFAULT
+                   | FBINFO_HWACCEL_IMAGEBLIT
                    | FBINFO_HWACCEL_COPYAREA
                    | FBINFO_HWACCEL_FILLRECT
                    | FBINFO_HWACCEL_XPAN
@@ -2005,11 +1994,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
             (rinfo->family == CHIP_FAMILY_RS200) ||
             (rinfo->family == CHIP_FAMILY_RS300) ||
             (rinfo->family == CHIP_FAMILY_RC410) ||
+            (rinfo->family == CHIP_FAMILY_RS400) ||
            (rinfo->family == CHIP_FAMILY_RS480) ) {
           u32 tom = INREG(NB_TOM);
           tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
 
-               radeon_fifo_wait(6);
           OUTREG(MC_FB_LOCATION, tom);
           OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
           OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
index 8c8fa35f1b7c2b13cd6a35341abddcf7ca42d9f5..2c5567175dca60f8bcf8c4e19e2eb78e66807fe9 100644 (file)
@@ -139,12 +139,8 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
 int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
                               u8 **out_edid)
 {
-       u32 reg = rinfo->i2c[conn-1].ddc_reg;
        u8 *edid;
 
-       OUTREG(reg, INREG(reg) &
-                       ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
-
        edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
 
        if (out_edid)
index 675abdafc2d8d047741ed3b8fdf2c0291343440c..3df5015f1d13f540a6bc9b5cbfdd663663604eac 100644 (file)
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 
        if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
                /* Make sure engine is reset */
-               radeon_engine_idle();
+               radeon_engine_idle(rinfo);
                radeonfb_engine_reset(rinfo);
-               radeon_engine_idle();
+               radeon_engine_idle(rinfo);
        }
 
        /* Blank display and LCD */
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
 
                rinfo->asleep = 0;
        } else
-               radeon_engine_idle();
+               radeon_engine_idle(rinfo);
 
        /* Restore display & engine */
        radeon_write_mode (rinfo, &rinfo->state, 1);
index ccbfffd128056c57392f02ff59f2dfe318f5b24e..ea0b5b47acaf437027b0a5b153dd6cc4c5d5e1b3 100644 (file)
@@ -53,6 +53,7 @@ enum radeon_family {
        CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
        CHIP_FAMILY_R420,     /* R420/R423/M18 */
        CHIP_FAMILY_RC410,
+       CHIP_FAMILY_RS400,
        CHIP_FAMILY_RS480,
        CHIP_FAMILY_LAST,
 };
@@ -335,7 +336,15 @@ struct radeonfb_info {
        int                     mon2_type;
        u8                      *mon2_EDID;
 
-       u32                     dp_gui_master_cntl;
+       /* accel bits */
+       u32                     dp_gui_mc_base;
+       u32                     dp_gui_mc_cache;
+       u32                     dp_cntl_cache;
+       u32                     dp_brush_fg_cache;
+       u32                     dp_brush_bg_cache;
+       u32                     dp_src_fg_cache;
+       u32                     dp_src_bg_cache;
+       u32                     fifo_free;
 
        struct pll_info         pll;
 
@@ -347,6 +356,7 @@ struct radeonfb_info {
        int                     lock_blank;
        int                     dynclk;
        int                     no_schedule;
+       int                     gfx_mode;
        enum radeon_pm_mode     pm_mode;
        reinit_function_ptr     reinit_func;
 
@@ -391,8 +401,14 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
 #define OUTREG8(addr,val)      writeb(val, (rinfo->mmio_base)+addr)
 #define INREG16(addr)          readw((rinfo->mmio_base)+addr)
 #define OUTREG16(addr,val)     writew(val, (rinfo->mmio_base)+addr)
+
+#ifdef CONFIG_PPC
+#define INREG(addr)            ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); })
+#define OUTREG(addr,val)       do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0)
+#else
 #define INREG(addr)            readl((rinfo->mmio_base)+addr)
 #define OUTREG(addr,val)       writel(val, (rinfo->mmio_base)+addr)
+#endif
 
 static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
                       u32 val, u32 mask)
@@ -533,16 +549,25 @@ static inline u32 radeon_get_dstbpp(u16 depth)
 /*
  * 2D Engine helper routines
  */
+
+extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries);
+
 static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
 {
        int i;
 
-       /* initiate flush */
-       OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+       /* Initiate flush */
+       OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
                ~RB2D_DC_FLUSH_ALL);
 
+       /* Ensure FIFO is empty, ie, make sure the flush commands
+        * has reached the cache
+        */
+       radeon_fifo_update_and_wait(rinfo, 64);
+
+       /* Wait for the flush to complete */
        for (i=0; i < 2000000; i++) {
-               if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+               if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
                        return;
                udelay(1);
        }
@@ -550,25 +575,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
 }
 
 
-static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
-{
-       int i;
-
-       for (i=0; i<2000000; i++) {
-               if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
-                       return;
-               udelay(1);
-       }
-       printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
-}
-
-
-static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
+static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
 {
        int i;
 
        /* ensure FIFO is empty before waiting for idle */
-       _radeon_fifo_wait (rinfo, 64);
+       radeon_fifo_update_and_wait (rinfo, 64);
 
        for (i=0; i<2000000; i++) {
                if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
@@ -581,8 +593,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
 }
 
 
-#define radeon_engine_idle()           _radeon_engine_idle(rinfo)
-#define radeon_fifo_wait(entries)      _radeon_fifo_wait(rinfo,entries)
 #define radeon_msleep(ms)              _radeon_msleep(rinfo,ms)
 
 
@@ -612,6 +622,7 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
 extern int radeonfb_sync(struct fb_info *info);
 extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
 extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
+extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo);
 
 /* Other functions */
 extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
index 385cba40ea87d4f33e2fe948f973432a8196d14e..06964af761c630295851142dac7690fc1bf11ab5 100644 (file)
@@ -111,6 +111,4 @@ module_exit(mbp_exit);
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
-MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
+MODULE_DEVICE_TABLE(dmi, mbp_device_table);
index e15bb447440a54c21d3b772e4deb51012cd27dbb..c9b191319a9a6ca7cdd047d52fd5e38918db6176 100644 (file)
@@ -535,7 +535,7 @@ static struct fb_ops carminefb_ops = {
        .fb_setcolreg   = carmine_setcolreg,
 };
 
-static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
+static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
                int smem_offset, struct device *device, struct fb_info **rinfo)
 {
        int ret;
index e729fb279645dd34f634be1fb0ddaea60396a7bb..048b139f0e50ce67eaa85d8d228f74fd40a72038 100644 (file)
@@ -327,29 +327,7 @@ static const struct {
 #endif /* CONFIG_ZORRO */
 
 struct cirrusfb_regs {
-       long freq;
-       long nom;
-       long den;
-       long div;
-       long multiplexing;
-       long mclk;
-       long divMCLK;
-
-       long HorizRes;          /* The x resolution in pixel */
-       long HorizTotal;
-       long HorizDispEnd;
-       long HorizBlankStart;
-       long HorizBlankEnd;
-       long HorizSyncStart;
-       long HorizSyncEnd;
-
-       long VertRes;           /* the physical y resolution in scanlines */
-       long VertTotal;
-       long VertDispEnd;
-       long VertSyncStart;
-       long VertSyncEnd;
-       long VertBlankStart;
-       long VertBlankEnd;
+       int multiplexing;
 };
 
 #ifdef CIRRUSFB_DEBUG
@@ -367,110 +345,13 @@ struct cirrusfb_info {
 
        struct cirrusfb_regs currentmode;
        int blank_mode;
+       u32 pseudo_palette[16];
 
-       u32     pseudo_palette[16];
-
-#ifdef CONFIG_ZORRO
-       struct zorro_dev *zdev;
-#endif
-#ifdef CONFIG_PCI
-       struct pci_dev *pdev;
-#endif
        void (*unmap)(struct fb_info *info);
 };
 
-static unsigned cirrusfb_def_mode = 1;
-static int noaccel;
-
-/*
- *    Predefined Video Modes
- */
-
-static const struct {
-       const char *name;
-       struct fb_var_screeninfo var;
-} cirrusfb_predefined[] = {
-       {
-               /* autodetect mode */
-               .name   = "Autodetect",
-       }, {
-               /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
-               .name   = "640x480",
-               .var    = {
-                       .xres           = 640,
-                       .yres           = 480,
-                       .xres_virtual   = 640,
-                       .yres_virtual   = 480,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 40000,
-                       .left_margin    = 48,
-                       .right_margin   = 16,
-                       .upper_margin   = 32,
-                       .lower_margin   = 8,
-                       .hsync_len      = 96,
-                       .vsync_len      = 4,
-                       .sync   = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
-               .name   = "800x600",
-               .var    = {
-                       .xres           = 800,
-                       .yres           = 600,
-                       .xres_virtual   = 800,
-                       .yres_virtual   = 600,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 20000,
-                       .left_margin    = 128,
-                       .right_margin   = 16,
-                       .upper_margin   = 24,
-                       .lower_margin   = 2,
-                       .hsync_len      = 96,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
-                }
-       }, {
-               /*
-                * Modeline from XF86Config:
-                * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
-                */
-               /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
-               .name   = "1024x768",
-               .var    = {
-                       .xres           = 1024,
-                       .yres           = 768,
-                       .xres_virtual   = 1024,
-                       .yres_virtual   = 768,
-                       .bits_per_pixel = 8,
-                       .red            = { .length = 8 },
-                       .green          = { .length = 8 },
-                       .blue           = { .length = 8 },
-                       .width          = -1,
-                       .height         = -1,
-                       .pixclock       = 12500,
-                       .left_margin    = 144,
-                       .right_margin   = 32,
-                       .upper_margin   = 30,
-                       .lower_margin   = 2,
-                       .hsync_len      = 192,
-                       .vsync_len      = 6,
-                       .vmode          = FB_VMODE_NONINTERLACED
-               }
-       }
-};
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(cirrusfb_predefined)
+static int noaccel __devinitdata;
+static char *mode_option __devinitdata = "640x480@60";
 
 /****************************************************************************/
 /**** BEGIN PROTOTYPES ******************************************************/
@@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = {
        .fb_imageblit   = cirrusfb_imageblit,
 };
 
-/*--- Hardware Specific Routines -------------------------------------------*/
-static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
-                               struct cirrusfb_regs *regs,
-                               struct fb_info *info);
 /*--- Internal routines ----------------------------------------------------*/
 static void init_vgachip(struct fb_info *info);
 static void switch_monitor(struct cirrusfb_info *cinfo, int on);
@@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
                              u_short width, u_short height,
                              u_char color, u_short line_length);
 
-static void bestclock(long freq, long *best,
-                     long *nom, long *den,
-                     long *div, long maxfreq);
+static void bestclock(long freq, int *nom, int *den, int *div);
 
 #ifdef CIRRUSFB_DEBUG
 static void cirrusfb_dump(void);
@@ -584,45 +459,28 @@ static int cirrusfb_release(struct fb_info *info, int user)
 /****************************************************************************/
 /**** BEGIN Hardware specific Routines **************************************/
 
-/* Get a good MCLK value */
-static long cirrusfb_get_mclk(long freq, int bpp, long *div)
+/* Check if the MCLK is not a better clock source */
+static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq)
 {
-       long mclk;
+       long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
 
-       assert(div != NULL);
-
-       /* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
-        * Assume a 64-bit data path for now.  The formula is:
-        * ((B * PCLK * 2)/W) * 1.2
-        * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
-       mclk = ((bpp / 8) * freq * 2) / 4;
-       mclk = (mclk * 12) / 10;
-       if (mclk < 50000)
-               mclk = 50000;
-       DPRINTK("Use MCLK of %ld kHz\n", mclk);
-
-       /* Calculate value for SR1F.  Multiply by 2 so we can round up. */
-       mclk = ((mclk * 16) / 14318);
-       mclk = (mclk + 1) / 2;
-       DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
+       /* Read MCLK value */
+       mclk = (14318 * mclk) >> 3;
+       DPRINTK("Read MCLK of %ld kHz\n", mclk);
 
        /* Determine if we should use MCLK instead of VCLK, and if so, what we
-          * should divide it by to get VCLK */
-       switch (freq) {
-       case 24751 ... 25249:
-               *div = 2;
-               DPRINTK("Using VCLK = MCLK/2\n");
-               break;
-       case 49501 ... 50499:
-               *div = 1;
+        * should divide it by to get VCLK
+        */
+
+       if (abs(freq - mclk) < 250) {
                DPRINTK("Using VCLK = MCLK\n");
-               break;
-       default:
-               *div = 0;
-               break;
+               return 1;
+       } else if (abs(freq - (mclk / 2)) < 250) {
+               DPRINTK("Using VCLK = MCLK/2\n");
+               return 2;
        }
 
-       return mclk;
+       return 0;
 }
 
 static int cirrusfb_check_var(struct fb_var_screeninfo *var,
@@ -638,7 +496,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                break;          /* 8 pixel per byte, only 1/4th of mem usable */
        case 8:
        case 16:
-       case 24:
        case 32:
                break;          /* 1 pixel == 1 byte */
        default:
@@ -713,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
                var->blue.length = 5;
                break;
 
-       case 24:
        case 32:
                if (isPReP) {
                        var->red.offset = 8;
@@ -767,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
        long maxclock;
        int maxclockidx = var->bits_per_pixel >> 3;
        struct cirrusfb_info *cinfo = info->par;
-       int xres, hfront, hsync, hback;
-       int yres, vfront, vsync, vback;
 
        switch (var->bits_per_pixel) {
        case 1:
@@ -782,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
                break;
 
        case 16:
-       case 24:
        case 32:
                info->fix.line_length = var->xres_virtual * maxclockidx;
-               info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
                break;
 
        default:
@@ -827,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
        switch (var->bits_per_pixel) {
        case 16:
        case 32:
-               if (regs->HorizRes <= 800)
+               if (var->xres <= 800)
                        /* Xbh has this type of clock for 32-bit */
                        freq /= 2;
                break;
        }
 #endif
-
-       bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
-                 maxclock);
-       regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
-                                       &regs->divMCLK);
-
-       xres = var->xres;
-       hfront = var->right_margin;
-       hsync = var->hsync_len;
-       hback = var->left_margin;
-
-       yres = var->yres;
-       vfront = var->lower_margin;
-       vsync = var->vsync_len;
-       vback = var->upper_margin;
-
-       if (var->vmode & FB_VMODE_DOUBLE) {
-               yres *= 2;
-               vfront *= 2;
-               vsync *= 2;
-               vback *= 2;
-       } else if (var->vmode & FB_VMODE_INTERLACED) {
-               yres = (yres + 1) / 2;
-               vfront = (vfront + 1) / 2;
-               vsync = (vsync + 1) / 2;
-               vback = (vback + 1) / 2;
-       }
-       regs->HorizRes = xres;
-       regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
-       regs->HorizDispEnd = xres / 8 - 1;
-       regs->HorizBlankStart = xres / 8;
-       /* does not count with "-5" */
-       regs->HorizBlankEnd = regs->HorizTotal + 5;
-       regs->HorizSyncStart = (xres + hfront) / 8 + 1;
-       regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
-
-       regs->VertRes = yres;
-       regs->VertTotal = yres + vfront + vsync + vback - 2;
-       regs->VertDispEnd = yres - 1;
-       regs->VertBlankStart = yres;
-       regs->VertBlankEnd = regs->VertTotal;
-       regs->VertSyncStart = yres + vfront - 1;
-       regs->VertSyncEnd = yres + vfront + vsync - 1;
-
-       if (regs->VertRes >= 1024) {
-               regs->VertTotal /= 2;
-               regs->VertSyncStart /= 2;
-               regs->VertSyncEnd /= 2;
-               regs->VertDispEnd /= 2;
-       }
-       if (regs->multiplexing) {
-               regs->HorizTotal /= 2;
-               regs->HorizSyncStart /= 2;
-               regs->HorizSyncEnd /= 2;
-               regs->HorizDispEnd /= 2;
-       }
-
        return 0;
 }
 
-static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
-                               int div)
+static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo,
+                                       int div)
 {
+       unsigned char old1f, old1e;
        assert(cinfo != NULL);
+       old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
 
-       if (div == 2) {
-               /* VCLK = MCLK/2 */
-               unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
-               vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
-               vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
-       } else if (div == 1) {
-               /* VCLK = MCLK */
-               unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
-               vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
-               vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
-       } else {
-               vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
+       if (div) {
+               DPRINTK("Set %s as pixclock source.\n",
+                                       (div == 2) ? "MCLK/2" : "MCLK");
+               old1f |= 0x40;
+               old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
+               if (div == 2)
+                       old1e |= 1;
+
+               vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
        }
+       vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
 }
 
 /*************************************************************************
@@ -927,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
        unsigned char tmp;
        int offset = 0, err;
        const struct cirrusfb_board_info_rec *bi;
+       int hdispend, hsyncstart, hsyncend, htotal;
+       int yres, vdispend, vsyncstart, vsyncend, vtotal;
+       long freq;
+       int nom, den, div;
 
        DPRINTK("ENTER\n");
        DPRINTK("Requested mode: %dx%dx%d\n",
@@ -944,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
 
        bi = &cirrusfb_board_info[cinfo->btype];
 
+       hsyncstart = var->xres + var->right_margin;
+       hsyncend = hsyncstart + var->hsync_len;
+       htotal = (hsyncend + var->left_margin) / 8 - 5;
+       hdispend = var->xres / 8 - 1;
+       hsyncstart = hsyncstart / 8 + 1;
+       hsyncend = hsyncend / 8 + 1;
+
+       yres = var->yres;
+       vsyncstart = yres + var->lower_margin;
+       vsyncend = vsyncstart + var->vsync_len;
+       vtotal = vsyncend + var->upper_margin;
+       vdispend = yres - 1;
+
+       if (var->vmode & FB_VMODE_DOUBLE) {
+               yres *= 2;
+               vsyncstart *= 2;
+               vsyncend *= 2;
+               vtotal *= 2;
+       } else if (var->vmode & FB_VMODE_INTERLACED) {
+               yres = (yres + 1) / 2;
+               vsyncstart = (vsyncstart + 1) / 2;
+               vsyncend = (vsyncend + 1) / 2;
+               vtotal = (vtotal + 1) / 2;
+       }
+
+       vtotal -= 2;
+       vsyncstart -= 1;
+       vsyncend -= 1;
+
+       if (yres >= 1024) {
+               vtotal /= 2;
+               vsyncstart /= 2;
+               vsyncend /= 2;
+               vdispend /= 2;
+       }
+       if (regs.multiplexing) {
+               htotal /= 2;
+               hsyncstart /= 2;
+               hsyncend /= 2;
+               hdispend /= 2;
+       }
        /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
        vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20);   /* previously: 0x00) */
 
        /* if debugging is enabled, all parameters get output before writing */
-       DPRINTK("CRT0: %ld\n", regs.HorizTotal);
-       vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
+       DPRINTK("CRT0: %d\n", htotal);
+       vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
 
-       DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
-       vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
+       DPRINTK("CRT1: %d\n", hdispend);
+       vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
 
-       DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
-       vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
+       DPRINTK("CRT2: %d\n", var->xres / 8);
+       vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
 
        /*  + 128: Compatible read */
-       DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
+       DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
        vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
-                128 + (regs.HorizBlankEnd % 32));
+                128 + ((htotal + 5) % 32));
 
-       DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
-       vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
+       DPRINTK("CRT4: %d\n", hsyncstart);
+       vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
 
-       tmp = regs.HorizSyncEnd % 32;
-       if (regs.HorizBlankEnd & 32)
+       tmp = hsyncend % 32;
+       if ((htotal + 5) & 32)
                tmp += 128;
        DPRINTK("CRT5: %d\n", tmp);
        vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
 
-       DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
-       vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
+       DPRINTK("CRT6: %d\n", vtotal & 0xff);
+       vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
 
        tmp = 16;               /* LineCompare bit #9 */
-       if (regs.VertTotal & 256)
+       if (vtotal & 256)
                tmp |= 1;
-       if (regs.VertDispEnd & 256)
+       if (vdispend & 256)
                tmp |= 2;
-       if (regs.VertSyncStart & 256)
+       if (vsyncstart & 256)
                tmp |= 4;
-       if (regs.VertBlankStart & 256)
+       if ((vdispend + 1) & 256)
                tmp |= 8;
-       if (regs.VertTotal & 512)
+       if (vtotal & 512)
                tmp |= 32;
-       if (regs.VertDispEnd & 512)
+       if (vdispend & 512)
                tmp |= 64;
-       if (regs.VertSyncStart & 512)
+       if (vsyncstart & 512)
                tmp |= 128;
        DPRINTK("CRT7: %d\n", tmp);
        vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
 
        tmp = 0x40;             /* LineCompare bit #8 */
-       if (regs.VertBlankStart & 512)
+       if ((vdispend + 1) & 512)
                tmp |= 0x20;
        if (var->vmode & FB_VMODE_DOUBLE)
                tmp |= 0x80;
        DPRINTK("CRT9: %d\n", tmp);
        vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
 
-       DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
-       vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
+       DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
+       vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
 
-       DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
-       vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
+       DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
+       vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
 
-       DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
-       vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
+       DPRINTK("CRT12: %d\n", vdispend & 0xff);
+       vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
 
-       DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
-       vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
+       DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
+       vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
 
-       DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
-       vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
+       DPRINTK("CRT16: %d\n", vtotal & 0xff);
+       vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
 
        DPRINTK("CRT18: 0xff\n");
        vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
@@ -1021,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
        tmp = 0;
        if (var->vmode & FB_VMODE_INTERLACED)
                tmp |= 1;
-       if (regs.HorizBlankEnd & 64)
+       if ((htotal + 5) & 64)
                tmp |= 16;
-       if (regs.HorizBlankEnd & 128)
+       if ((htotal + 5) & 128)
                tmp |= 32;
-       if (regs.VertBlankEnd & 256)
+       if (vtotal & 256)
                tmp |= 64;
-       if (regs.VertBlankEnd & 512)
+       if (vtotal & 512)
                tmp |= 128;
 
        DPRINTK("CRT1a: %d\n", tmp);
        vga_wcrt(regbase, CL_CRT1A, tmp);
 
+       freq = PICOS2KHZ(var->pixclock);
+       bestclock(freq, &nom, &den, &div);
+
        /* set VCLK0 */
        /* hardware RefClock: 14.31818 MHz */
        /* formula: VClk = (OSC * N) / (D * (1+P)) */
        /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
 
-       vga_wseq(regbase, CL_SEQRB, regs.nom);
-       tmp = regs.den << 1;
-       if (regs.div != 0)
-               tmp |= 1;
+       if (cinfo->btype == BT_ALPINE) {
+               /* if freq is close to mclk or mclk/2 select mclk
+                * as clock source
+                */
+               int divMCLK = cirrusfb_check_mclk(cinfo, freq);
+               if (divMCLK)  {
+                       nom = 0;
+                       cirrusfb_set_mclk_as_source(cinfo, divMCLK);
+               }
+       }
+       if (nom) {
+               vga_wseq(regbase, CL_SEQRB, nom);
+               tmp = den << 1;
+               if (div != 0)
+                       tmp |= 1;
 
-       /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
-       if ((cinfo->btype == BT_SD64) ||
-           (cinfo->btype == BT_ALPINE) ||
-           (cinfo->btype == BT_GD5480))
-               tmp |= 0x80;
+               /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
+               if ((cinfo->btype == BT_SD64) ||
+                   (cinfo->btype == BT_ALPINE) ||
+                   (cinfo->btype == BT_GD5480))
+                       tmp |= 0x80;
 
-       DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
-       vga_wseq(regbase, CL_SEQR1B, tmp);
+               DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
+               vga_wseq(regbase, CL_SEQR1B, tmp);
+       }
 
-       if (regs.VertRes >= 1024)
+       if (yres >= 1024)
                /* 1280x1024 */
                vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
        else
@@ -1066,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
        /* don't know if it would hurt to also program this if no interlaced */
        /* mode is used, but I feel better this way.. :-) */
        if (var->vmode & FB_VMODE_INTERLACED)
-               vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
+               vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
        else
                vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
 
@@ -1240,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
 
                case BT_ALPINE:
                        DPRINTK(" (for GD543x)\n");
-                       cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
                        /* We already set SRF and SR1F */
                        break;
 
@@ -1312,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
 
                case BT_ALPINE:
                        DPRINTK(" (for GD543x)\n");
-                       if (regs.HorizRes >= 1024)
-                               vga_wseq(regbase, CL_SEQR7, 0xa7);
-                       else
-                               vga_wseq(regbase, CL_SEQR7, 0xa3);
-                       cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
+                       vga_wseq(regbase, CL_SEQR7, 0xa7);
                        break;
 
                case BT_GD5480:
@@ -1360,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
         */
 
        else if (var->bits_per_pixel == 32) {
-               DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
+               DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
                switch (cinfo->btype) {
                case BT_SD64:
                        /* Extended Sequencer Mode: 256c col. mode */
@@ -1394,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
                case BT_ALPINE:
                        DPRINTK(" (for GD543x)\n");
                        vga_wseq(regbase, CL_SEQR7, 0xa9);
-                       cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
                        break;
 
                case BT_GD5480:
@@ -1949,8 +1799,6 @@ static void init_vgachip(struct fb_info *info)
        /* misc... */
        WHDR(cinfo, 0); /* Hidden DAC register: - */
 
-       printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
-               info->screen_size);
        DPRINTK("EXIT\n");
        return;
 }
@@ -2122,7 +1970,7 @@ static int release_io_ports;
  * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
  * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
  * seem to have. */
-static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
+static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
 {
        unsigned long mem;
        unsigned char SRF;
@@ -2188,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev,
 
 static void cirrusfb_pci_unmap(struct fb_info *info)
 {
-       struct cirrusfb_info *cinfo = info->par;
-       struct pci_dev *pdev = cinfo->pdev;
+       struct pci_dev *pdev = to_pci_dev(info->device);
 
        iounmap(info->screen_base);
 #if 0 /* if system didn't claim this region, we would... */
@@ -2205,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info)
 static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
-       zorro_release_device(cinfo->zdev);
+       struct zorro_dev *zdev = to_zorro_dev(info->device);
+
+       zorro_release_device(zdev);
 
        if (cinfo->btype == BT_PICASSO4) {
                cinfo->regbase -= 0x600000;
                iounmap((void *)cinfo->regbase);
                iounmap(info->screen_base);
        } else {
-               if (zorro_resource_start(cinfo->zdev) > 0x01000000)
+               if (zorro_resource_start(zdev) > 0x01000000)
                        iounmap(info->screen_base);
        }
 }
 #endif /* CONFIG_ZORRO */
 
-static int cirrusfb_set_fbinfo(struct fb_info *info)
+static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
        struct fb_var_screeninfo *var = &info->var;
@@ -2235,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
        if (cinfo->btype == BT_GD5480) {
                if (var->bits_per_pixel == 16)
                        info->screen_base += 1 * MB_;
-               if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
+               if (var->bits_per_pixel == 32)
                        info->screen_base += 2 * MB_;
        }
 
@@ -2262,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
        return 0;
 }
 
-static int cirrusfb_register(struct fb_info *info)
+static int __devinit cirrusfb_register(struct fb_info *info)
 {
        struct cirrusfb_info *cinfo = info->par;
        int err;
@@ -2278,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info)
        /* sanity checks */
        assert(btype != BT_NONE);
 
+       /* set all the vital stuff */
+       cirrusfb_set_fbinfo(info);
+
        DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
 
-       /* Make pretend we've set the var so our structures are in a "good" */
-       /* state, even though we haven't written the mode to the hw yet...  */
-       info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
+       err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+       if (!err) {
+               DPRINTK("wrong initial video mode\n");
+               err = -EINVAL;
+               goto err_dealloc_cmap;
+       }
+
        info->var.activate = FB_ACTIVATE_NOW;
 
        err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
        if (err < 0) {
                /* should never happen */
                DPRINTK("choking on default var... umm, no good.\n");
-               goto err_unmap_cirrusfb;
+               goto err_dealloc_cmap;
        }
 
-       /* set all the vital stuff */
-       cirrusfb_set_fbinfo(info);
-
        err = register_framebuffer(info);
        if (err < 0) {
                printk(KERN_ERR "cirrusfb: could not register "
@@ -2307,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info)
 
 err_dealloc_cmap:
        fb_dealloc_cmap(&info->cmap);
-err_unmap_cirrusfb:
        cinfo->unmap(info);
        framebuffer_release(info);
        return err;
@@ -2330,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info)
 }
 
 #ifdef CONFIG_PCI
-static int cirrusfb_pci_register(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
+                                          const struct pci_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
@@ -2353,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
        }
 
        cinfo = info->par;
-       cinfo->pdev = pdev;
        cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
 
        DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
@@ -2459,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = {
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_ZORRO
-static int cirrusfb_zorro_register(struct zorro_dev *z,
-                                  const struct zorro_device_id *ent)
+static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
+                                            const struct zorro_device_id *ent)
 {
        struct cirrusfb_info *cinfo;
        struct fb_info *info;
@@ -2489,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        assert(z);
        assert(btype != BT_NONE);
 
-       cinfo->zdev = z;
        board_addr = zorro_resource_start(z);
        board_size = zorro_resource_len(z);
        info->screen_size = size;
@@ -2621,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) {
                return 0;
 
        while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
+               if (!*this_opt)
+                       continue;
 
                DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
 
-               for (i = 0; i < NUM_TOTAL_MODES; i++) {
-                       sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
-                       if (strcmp(this_opt, s) == 0)
-                               cirrusfb_def_mode = i;
-               }
                if (!strcmp(this_opt, "noaccel"))
                        noaccel = 1;
+               else if (!strncmp(this_opt, "mode:", 5))
+                       mode_option = this_opt + 5;
+               else
+                       mode_option = this_opt;
        }
        return 0;
 }
@@ -2657,6 +2507,11 @@ static void __exit cirrusfb_exit(void)
 
 module_init(cirrusfb_init);
 
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "Disable acceleration");
+
 #ifdef MODULE
 module_exit(cirrusfb_exit);
 #endif
@@ -3050,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
  * bestclock() - determine closest possible clock lower(?) than the
  * desired pixel clock
  **************************************************************************/
-static void bestclock(long freq, long *best, long *nom,
-                      long *den, long *div, long maxfreq)
+static void bestclock(long freq, int *nom, int *den, int *div)
 {
-       long n, h, d, f;
+       int n, d;
+       long h, diff;
 
-       assert(best != NULL);
        assert(nom != NULL);
        assert(den != NULL);
        assert(div != NULL);
-       assert(maxfreq > 0);
 
        *nom = 0;
        *den = 0;
@@ -3070,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom,
        if (freq < 8000)
                freq = 8000;
 
-       if (freq > maxfreq)
-               freq = maxfreq;
-
-       *best = 0;
-       f = freq * 10;
+       diff = freq;
 
        for (n = 32; n < 128; n++) {
-               d = (143181 * n) / f;
+               int s = 0;
+
+               d = (14318 * n) / freq;
                if ((d >= 7) && (d <= 63)) {
-                       if (d > 31)
-                               d = (d / 2) * 2;
-                       h = (14318 * n) / d;
-                       if (abs(h - freq) < abs(*best - freq)) {
-                               *best = h;
+                       int temp = d;
+
+                       if (temp > 31) {
+                               s = 1;
+                               temp >>= 1;
+                       }
+                       h = ((14318 * n) / temp) >> s;
+                       h = h > freq ? h - freq : freq - h;
+                       if (h < diff) {
+                               diff = h;
                                *nom = n;
-                               if (d < 32) {
-                                       *den = d;
-                                       *div = 0;
-                               } else {
-                                       *den = d / 2;
-                                       *div = 1;
-                               }
+                               *den = temp;
+                               *div = s;
                        }
                }
-               d = DIV_ROUND_UP(143181 * n, f);
+               d++;
                if ((d >= 7) && (d <= 63)) {
-                       if (d > 31)
-                               d = (d / 2) * 2;
-                       h = (14318 * n) / d;
-                       if (abs(h - freq) < abs(*best - freq)) {
-                               *best = h;
+                       if (d > 31) {
+                               s = 1;
+                               d >>= 1;
+                       }
+                       h = ((14318 * n) / d) >> s;
+                       h = h > freq ? h - freq : freq - h;
+                       if (h < diff) {
+                               diff = h;
                                *nom = n;
-                               if (d < 32) {
-                                       *den = d;
-                                       *div = 0;
-                               } else {
-                                       *den = d / 2;
-                                       *div = 1;
-                               }
+                               *den = d;
+                               *div = s;
                        }
                }
        }
 
        DPRINTK("Best possible values for given frequency:\n");
-       DPRINTK("       best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
+       DPRINTK("       freq: %ld kHz  nom: %d  den: %d  div: %d\n",
                freq, *nom, *den, *div);
 
        DPRINTK("EXIT\n");
index 9cbff84b787d9e4cf17d8ebd7d2dc1822d628f5f..64b3d30027b825395ee2320f70c2e33f7665a0cf 100644 (file)
@@ -1855,8 +1855,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct display *p = &fb_display[vc->vc_num];
        int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
-       unsigned short saved_ec;
-       int ret;
 
        if (fbcon_is_inactive(vc, info))
                return -EINVAL;
@@ -1869,11 +1867,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
         *           whole screen (prevents flicker).
         */
 
-       saved_ec = vc->vc_video_erase_char;
-       vc->vc_video_erase_char = vc->vc_scrl_erase_char;
-
-       ret = 0;
-
        switch (dir) {
        case SM_UP:
                if (count > vc->vc_rows)        /* Maximum realistic size */
@@ -1890,9 +1883,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
-                                   vc->vc_scrl_erase_char,
+                                   vc->vc_video_erase_char,
                                    vc->vc_size_row * count);
-                       ret = 1;
+                       return 1;
                        break;
 
                case SCROLL_WRAP_MOVE:
@@ -1962,10 +1955,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
-                                   vc->vc_scrl_erase_char,
+                                   vc->vc_video_erase_char,
                                    vc->vc_size_row * count);
-                       ret = 1;
-                       break;
+                       return 1;
                }
                break;
 
@@ -1982,9 +1974,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
-                                   vc->vc_scrl_erase_char,
+                                   vc->vc_video_erase_char,
                                    vc->vc_size_row * count);
-                       ret = 1;
+                       return 1;
                        break;
 
                case SCROLL_WRAP_MOVE:
@@ -2052,15 +2044,12 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
-                                   vc->vc_scrl_erase_char,
+                                   vc->vc_video_erase_char,
                                    vc->vc_size_row * count);
-                       ret = 1;
-                       break;
+                       return 1;
                }
-               break;
        }
-       vc->vc_video_erase_char = saved_ec;
-       return ret;
+       return 0;
 }
 
 
@@ -2522,9 +2511,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
                        c = vc->vc_video_erase_char;
                        vc->vc_video_erase_char =
                            ((c & 0xfe00) >> 1) | (c & 0xff);
-                       c = vc->vc_scrl_erase_char;
-                       vc->vc_scrl_erase_char =
-                           ((c & 0xFE00) >> 1) | (c & 0xFF);
                        vc->vc_attr >>= 1;
                }
        } else if (!vc->vc_hi_font_mask && cnt == 512) {
@@ -2555,14 +2541,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
                        if (vc->vc_can_do_color) {
                                vc->vc_video_erase_char =
                                    ((c & 0xff00) << 1) | (c & 0xff);
-                               c = vc->vc_scrl_erase_char;
-                               vc->vc_scrl_erase_char =
-                                   ((c & 0xFF00) << 1) | (c & 0xFF);
                                vc->vc_attr <<= 1;
-                       } else {
+                       } else
                                vc->vc_video_erase_char = c & ~0x100;
-                               vc->vc_scrl_erase_char = c & ~0x100;
-                       }
                }
 
        }
@@ -2996,8 +2977,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
                p = &fb_display[vc->vc_num];
                set_blitting_type(vc, info);
                var_to_display(p, &info->var, info);
-               cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
-               rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
+               cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+               rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
                cols /= vc->vc_font.width;
                rows /= vc->vc_font.height;
                vc_resize(vc, cols, rows);
@@ -3592,8 +3573,8 @@ static int __init fb_console_init(void)
 
        acquire_console_sem();
        fb_register_client(&fbcon_event_notifier);
-       fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
-                                            NULL, "fbcon");
+       fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
+                                    "fbcon");
 
        if (IS_ERR(fbcon_device)) {
                printk(KERN_WARNING "Unable to create device "
index 9901064199bd165599a163deacf45737f7d210c2..dd3eaaad44417781a6cef9a1537ca055812d3d65 100644 (file)
@@ -533,7 +533,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
 
 static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
 {
-       u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
+       u16 eattr = mda_convert_attr(c->vc_video_erase_char);
 
        if (!lines)
                return 0;
index 4055dbdd1b428e0dd978704204e0b182f364301d..491c1c1baf4ccd652eadf85079544686064e3228 100644 (file)
@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
     switch (dir) {
     case SM_UP:
        sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
-       sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+       sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
        break;
 
     case SM_DOWN:
        sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
-       sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
+       sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
        break;
     }
 
index bd1f57b259d9ce50d470b192e021ad95461b8e72..448d209a0bf2109fa14af7d3c6a3b00e08c7df1b 100644 (file)
@@ -239,8 +239,7 @@ static void vgacon_restore_screen(struct vc_data *c)
 
 static int vgacon_scrolldelta(struct vc_data *c, int lines)
 {
-       int start, end, count, soff, diff;
-       void *d, *s;
+       int start, end, count, soff;
 
        if (!lines) {
                c->vc_visible_origin = c->vc_origin;
@@ -287,29 +286,29 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
        if (count > c->vc_rows)
                count = c->vc_rows;
 
-       diff = c->vc_rows - count;
+       if (count) {
+               int copysize;
 
-       d = (void *) c->vc_origin;
-       s = (void *) c->vc_screenbuf;
+               int diff = c->vc_rows - count;
+               void *d = (void *) c->vc_origin;
+               void *s = (void *) c->vc_screenbuf;
 
-       while (count--) {
-               scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
-               d += c->vc_size_row;
-               soff += c->vc_size_row;
+               count *= c->vc_size_row;
+               /* how much memory to end of buffer left? */
+               copysize = min(count, vgacon_scrollback_size - soff);
+               scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+               d += copysize;
+               count -= copysize;
 
-               if (soff >= vgacon_scrollback_size)
-                       soff = 0;
-       }
+               if (count) {
+                       scr_memcpyw(d, vgacon_scrollback, count);
+                       d += count;
+               }
 
-       if (diff == c->vc_rows) {
+               if (diff)
+                       scr_memcpyw(d, s, diff * c->vc_size_row);
+       } else
                vgacon_cursor(c, CM_MOVE);
-       } else {
-               while (diff--) {
-                       scr_memcpyw(d, s, c->vc_size_row);
-                       d += c->vc_size_row;
-                       s += c->vc_size_row;
-               }
-       }
 
        return 1;
 }
@@ -1350,7 +1349,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
                } else
                        c->vc_origin += delta;
                scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
-                                    delta), c->vc_scrl_erase_char,
+                                    delta), c->vc_video_erase_char,
                            delta);
        } else {
                if (oldo - delta < vga_vram_base) {
@@ -1363,7 +1362,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
                } else
                        c->vc_origin -= delta;
                c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
-               scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
+               scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
                            delta);
        }
        c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
index 6ef800bdf4822f4fcf09f4e0e9db002b0d6fb9ba..4830b1bf51e5da7e6fcdadcfe67ce231ea977cc1 100644 (file)
@@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
                mutex_unlock(&allocated_dsp_lock);
 
                if (!ret) {
-                       new_dev->dev = device_create_drvdata(display_class,
-                                                            parent,
-                                                            MKDEV(0,0),
-                                                            new_dev,
-                                                            "display%d",
-                                                            new_dev->idx);
+                       new_dev->dev = device_create(display_class, parent,
+                                                    MKDEV(0, 0), new_dev,
+                                                    "display%d", new_dev->idx);
                        if (!IS_ERR(new_dev->dev)) {
                                new_dev->parent = parent;
                                new_dev->driver = driver;
index bd779ae44b1e21ba90787b4fd5d70c0dc14694fe..daf9b81878a463a62bb81427f8e2e97c1978c2e3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/fb.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
+#include <linux/dmi.h>
 
 #include <video/vga.h>
 
@@ -33,6 +34,105 @@ static struct fb_fix_screeninfo efifb_fix __initdata = {
        .visual                 = FB_VISUAL_TRUECOLOR,
 };
 
+enum {
+       M_I17,          /* 17-Inch iMac */
+       M_I20,          /* 20-Inch iMac */
+       M_I20_SR,       /* 20-Inch iMac (Santa Rosa) */
+       M_I24,          /* 24-Inch iMac */
+       M_MINI,         /* Mac Mini */
+       M_MB,           /* MacBook */
+       M_MB_2,         /* MacBook, 2nd rev. */
+       M_MB_3,         /* MacBook, 3rd rev. */
+       M_MB_SR,        /* MacBook, 2nd gen, (Santa Rosa) */
+       M_MBA,          /* MacBook Air */
+       M_MBP,          /* MacBook Pro */
+       M_MBP_2,        /* MacBook Pro 2nd gen */
+       M_MBP_SR,       /* MacBook Pro (Santa Rosa) */
+       M_MBP_4,        /* MacBook Pro, 4th gen */
+       M_UNKNOWN       /* placeholder */
+};
+
+static struct efifb_dmi_info {
+       char *optname;
+       unsigned long base;
+       int stride;
+       int width;
+       int height;
+} dmi_list[] = {
+       [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
+       [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
+       [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
+       [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
+       [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
+       [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
+       [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
+       [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
+       [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
+       [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
+       [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
+       [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
+};
+
+static int set_system(const struct dmi_system_id *id);
+
+#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid)              \
+       { set_system, name, {                                   \
+               DMI_MATCH(DMI_BIOS_VENDOR, vendor),             \
+               DMI_MATCH(DMI_PRODUCT_NAME, name) },            \
+         &dmi_list[enumid] }
+
+static struct dmi_system_id __initdata dmi_system_table[] = {
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
+       /* At least one of these two will be right; maybe both? */
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
+       /* At least one of these two will be right; maybe both? */
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
+       /* At least one of these two will be right; maybe both? */
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
+       /* At least one of these two will be right; maybe both? */
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
+       EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
+       EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
+       {},
+};
+
+static int set_system(const struct dmi_system_id *id)
+{
+       struct efifb_dmi_info *info = id->driver_data;
+       if (info->base == 0)
+               return -ENODEV;
+
+       printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
+                        "(%dx%d, stride %d)\n", id->ident,
+                        (void *)info->base, info->width, info->height,
+                        info->stride);
+
+       /* Trust the bootloader over the DMI tables */
+       if (screen_info.lfb_base == 0)
+               screen_info.lfb_base = info->base;
+       if (screen_info.lfb_linelength == 0)
+               screen_info.lfb_linelength = info->stride;
+       if (screen_info.lfb_width == 0)
+               screen_info.lfb_width = info->width;
+       if (screen_info.lfb_height == 0)
+               screen_info.lfb_height = info->height;
+
+       return 0;
+}
+
 static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
                           unsigned blue, unsigned transp,
                           struct fb_info *info)
@@ -67,6 +167,38 @@ static struct fb_ops efifb_ops = {
        .fb_imageblit   = cfb_imageblit,
 };
 
+static int __init efifb_setup(char *options)
+{
+       char *this_opt;
+       int i;
+
+       if (!options || !*options)
+               return 0;
+
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               if (!*this_opt) continue;
+
+               for (i = 0; i < M_UNKNOWN; i++) {
+                       if (!strcmp(this_opt, dmi_list[i].optname) &&
+                                       dmi_list[i].base != 0) {
+                               screen_info.lfb_base = dmi_list[i].base;
+                               screen_info.lfb_linelength = dmi_list[i].stride;
+                               screen_info.lfb_width = dmi_list[i].width;
+                               screen_info.lfb_height = dmi_list[i].height;
+                       }
+               }
+               if (!strncmp(this_opt, "base:", 5))
+                       screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
+               else if (!strncmp(this_opt, "stride:", 7))
+                       screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
+               else if (!strncmp(this_opt, "height:", 7))
+                       screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
+               else if (!strncmp(this_opt, "width:", 6))
+                       screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
+       }
+       return 0;
+}
+
 static int __init efifb_probe(struct platform_device *dev)
 {
        struct fb_info *info;
@@ -74,6 +206,26 @@ static int __init efifb_probe(struct platform_device *dev)
        unsigned int size_vmode;
        unsigned int size_remap;
        unsigned int size_total;
+       int request_succeeded = 0;
+
+       printk(KERN_INFO "efifb: probing for efifb\n");
+
+       if (!screen_info.lfb_depth)
+               screen_info.lfb_depth = 32;
+       if (!screen_info.pages)
+               screen_info.pages = 1;
+
+       /* just assume they're all unset if any are */
+       if (!screen_info.blue_size) {
+               screen_info.blue_size = 8;
+               screen_info.blue_pos = 0;
+               screen_info.green_size = 8;
+               screen_info.green_pos = 8;
+               screen_info.red_size = 8;
+               screen_info.red_pos = 16;
+               screen_info.rsvd_size = 8;
+               screen_info.rsvd_pos = 24;
+       }
 
        efifb_fix.smem_start = screen_info.lfb_base;
        efifb_defined.bits_per_pixel = screen_info.lfb_depth;
@@ -98,21 +250,25 @@ static int __init efifb_probe(struct platform_device *dev)
         *                 option to simply use size_total as that
         *                 wastes plenty of kernel address space. */
        size_remap  = size_vmode * 2;
-       if (size_remap < size_vmode)
-               size_remap = size_vmode;
        if (size_remap > size_total)
                size_remap = size_total;
+       if (size_remap % PAGE_SIZE)
+               size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
        efifb_fix.smem_len = size_remap;
 
-       if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb"))
+       if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
+               request_succeeded = 1;
+       } else {
                /* We cannot make this fatal. Sometimes this comes from magic
                   spaces our resource handlers simply don't know about */
                printk(KERN_WARNING
                       "efifb: cannot reserve video memory at 0x%lx\n",
                        efifb_fix.smem_start);
+       }
 
        info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
        if (!info) {
+               printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
                err = -ENOMEM;
                goto err_release_mem;
        }
@@ -125,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev)
                                "0x%x @ 0x%lx\n",
                        efifb_fix.smem_len, efifb_fix.smem_start);
                err = -EIO;
-               goto err_unmap;
+               goto err_release_fb;
        }
 
        printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
@@ -178,25 +334,27 @@ static int __init efifb_probe(struct platform_device *dev)
        info->fix = efifb_fix;
        info->flags = FBINFO_FLAG_DEFAULT;
 
-       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-               err = -ENOMEM;
+       if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
+               printk(KERN_ERR "efifb: cannot allocate colormap\n");
                goto err_unmap;
        }
-       if (register_framebuffer(info) < 0) {
-               err = -EINVAL;
+       if ((err = register_framebuffer(info)) < 0) {
+               printk(KERN_ERR "efifb: cannot register framebuffer\n");
                goto err_fb_dealoc;
        }
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              info->node, info->fix.id);
+               info->node, info->fix.id);
        return 0;
 
 err_fb_dealoc:
        fb_dealloc_cmap(&info->cmap);
 err_unmap:
        iounmap(info->screen_base);
+err_release_fb:
        framebuffer_release(info);
 err_release_mem:
-       release_mem_region(efifb_fix.smem_start, size_total);
+       if (request_succeeded)
+               release_mem_region(efifb_fix.smem_start, size_total);
        return err;
 }
 
@@ -214,9 +372,22 @@ static struct platform_device efifb_device = {
 static int __init efifb_init(void)
 {
        int ret;
+       char *option = NULL;
 
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
                return -ENODEV;
+       dmi_check_system(dmi_system_table);
+
+       if (fb_get_options("efifb", &option))
+               return -ENODEV;
+       efifb_setup(option);
+
+       /* We don't get linelength from UGA Draw Protocol, only from
+        * EFI Graphics Protocol.  So if it's not in DMI, and it's not
+        * passed in from the user, we really can't use the framebuffer.
+        */
+       if (!screen_info.lfb_linelength)
+               return -ENODEV;
 
        ret = platform_driver_register(&efifb_driver);
 
index 0737570030f5e85459b4f926e3a4e8a7aaa09b3d..217c5118ae9e71818ea80014cb2b54cb8c63c707 100644 (file)
@@ -28,9 +28,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
-#ifdef CONFIG_KMOD
 #include <linux/kmod.h>
-#endif
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/efi.h>
@@ -837,13 +835,6 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
        return (cnt) ? cnt : err;
 }
 
-#ifdef CONFIG_KMOD
-static void try_to_load(int fb)
-{
-       request_module("fb%d", fb);
-}
-#endif /* CONFIG_KMOD */
-
 int
 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
 {
@@ -1086,10 +1077,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                    return -EINVAL;
                if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
                    return -EINVAL;
-#ifdef CONFIG_KMOD
                if (!registered_fb[con2fb.framebuffer])
-                   try_to_load(con2fb.framebuffer);
-#endif /* CONFIG_KMOD */
+                   request_module("fb%d", con2fb.framebuffer);
                if (!registered_fb[con2fb.framebuffer])
                    return -EINVAL;
                event.info = info;
@@ -1327,10 +1316,8 @@ fb_open(struct inode *inode, struct file *file)
        if (fbidx >= FB_MAX)
                return -ENODEV;
        lock_kernel();
-#ifdef CONFIG_KMOD
        if (!(info = registered_fb[fbidx]))
-               try_to_load(fbidx);
-#endif /* CONFIG_KMOD */
+               request_module("fb%d", fbidx);
        if (!(info = registered_fb[fbidx])) {
                res = -ENODEV;
                goto out;
@@ -1443,9 +1430,8 @@ register_framebuffer(struct fb_info *fb_info)
                        break;
        fb_info->node = i;
 
-       fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
-                                            MKDEV(FB_MAJOR, i), NULL,
-                                            "fb%d", i);
+       fb_info->dev = device_create(fb_class, fb_info->device,
+                                    MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
        if (IS_ERR(fb_info->dev)) {
                /* Not fatal */
                printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
index 6a0aa180c266e0b3d03e8cc2a4dc890f1605d329..5c1a2c01778fe6e195df9405d0409d7a1a2a09f9 100644 (file)
@@ -564,7 +564,13 @@ static void get_detailed_timing(unsigned char *block,
                mode->sync |= FB_SYNC_VERT_HIGH_ACT;
        mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
                                     (V_ACTIVE + V_BLANKING));
-       mode->vmode = 0;
+       if (INTERLACED) {
+               mode->yres *= 2;
+               mode->upper_margin *= 2;
+               mode->lower_margin *= 2;
+               mode->vsync_len *= 2;
+               mode->vmode |= FB_VMODE_INTERLACED;
+       }
        mode->flag = FB_MODE_IS_DETAILED;
 
        DPRINTK("      %d MHz ",  PIXEL_CLOCK/1000000);
index 9366ef2bb5f7c5748107fa2346daff6d263c9efa..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,376 +0,0 @@
-/*
- * framebuffer driver for Intel Based Mac's
- *
- * (c) 2006 Edgar Hucek <gimli@dark-green.com>
- * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
- *
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/screen_info.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/dmi.h>
-#include <linux/efi.h>
-
-#include <asm/io.h>
-
-#include <video/vga.h>
-
-typedef enum _MAC_TYPE {
-       M_I17,
-       M_I20,
-       M_MINI,
-       M_MACBOOK,
-       M_UNKNOWN
-} MAC_TYPE;
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo imacfb_defined __initdata = {
-       .activate               = FB_ACTIVATE_NOW,
-       .height                 = -1,
-       .width                  = -1,
-       .right_margin           = 32,
-       .upper_margin           = 16,
-       .lower_margin           = 4,
-       .vsync_len              = 4,
-       .vmode                  = FB_VMODE_NONINTERLACED,
-};
-
-static struct fb_fix_screeninfo imacfb_fix __initdata = {
-       .id                     = "IMAC VGA",
-       .type                   = FB_TYPE_PACKED_PIXELS,
-       .accel                  = FB_ACCEL_NONE,
-       .visual                 = FB_VISUAL_TRUECOLOR,
-};
-
-static int inverse;
-static int model               = M_UNKNOWN;
-static int manual_height;
-static int manual_width;
-
-static int set_system(const struct dmi_system_id *id)
-{
-       printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
-               id->ident, (long)id->driver_data);
-
-       model = (long)id->driver_data;
-
-       return 0;
-}
-
-static struct dmi_system_id __initdata dmi_system_table[] = {
-       { set_system, "iMac4,1", {
-         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
-         DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
-       { set_system, "MacBookPro1,1", {
-         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
-         DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
-       { set_system, "MacBook1,1", {
-         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
-         DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
-       { set_system, "Macmini1,1", {
-         DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
-         DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
-       {},
-};
-
-#define        DEFAULT_FB_MEM  1024*1024*16
-
-/* --------------------------------------------------------------------- */
-
-static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                           unsigned blue, unsigned transp,
-                           struct fb_info *info)
-{
-       /*
-        *  Set a single color register. The values supplied are
-        *  already rounded down to the hardware's capabilities
-        *  (according to the entries in the `var' structure). Return
-        *  != 0 for invalid regno.
-        */
-
-       if (regno >= info->cmap.len)
-               return 1;
-
-       if (regno < 16) {
-               red   >>= 8;
-               green >>= 8;
-               blue  >>= 8;
-               ((u32 *)(info->pseudo_palette))[regno] =
-                       (red   << info->var.red.offset)   |
-                       (green << info->var.green.offset) |
-                       (blue  << info->var.blue.offset);
-       }
-       return 0;
-}
-
-static struct fb_ops imacfb_ops = {
-       .owner          = THIS_MODULE,
-       .fb_setcolreg   = imacfb_setcolreg,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
-};
-
-static int __init imacfb_setup(char *options)
-{
-       char *this_opt;
-
-       if (!options || !*options)
-               return 0;
-
-       while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
-
-               if (!strcmp(this_opt, "inverse"))
-                       inverse = 1;
-               else if (!strcmp(this_opt, "i17"))
-                       model = M_I17;
-               else if (!strcmp(this_opt, "i20"))
-                       model = M_I20;
-               else if (!strcmp(this_opt, "mini"))
-                       model = M_MINI;
-               else if (!strcmp(this_opt, "macbook"))
-                       model = M_MACBOOK;
-               else if (!strncmp(this_opt, "height:", 7))
-                       manual_height = simple_strtoul(this_opt+7, NULL, 0);
-               else if (!strncmp(this_opt, "width:", 6))
-                       manual_width = simple_strtoul(this_opt+6, NULL, 0);
-       }
-       return 0;
-}
-
-static int __init imacfb_probe(struct platform_device *dev)
-{
-       struct fb_info *info;
-       int err;
-       unsigned int size_vmode;
-       unsigned int size_remap;
-       unsigned int size_total;
-
-       screen_info.lfb_depth = 32;
-       screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
-       screen_info.pages=1;
-       screen_info.blue_size = 8;
-       screen_info.blue_pos = 0;
-       screen_info.green_size = 8;
-       screen_info.green_pos = 8;
-       screen_info.red_size = 8;
-       screen_info.red_pos = 16;
-       screen_info.rsvd_size = 8;
-       screen_info.rsvd_pos = 24;
-
-       switch (model) {
-       case M_I17:
-               screen_info.lfb_width = 1440;
-               screen_info.lfb_height = 900;
-               screen_info.lfb_linelength = 1472 * 4;
-               screen_info.lfb_base = 0x80010000;
-               break;
-       case M_I20:
-               screen_info.lfb_width = 1680;
-               screen_info.lfb_height = 1050;
-               screen_info.lfb_linelength = 1728 * 4;
-               screen_info.lfb_base = 0x80010000;
-               break;
-       case M_MINI:
-               screen_info.lfb_width = 1024;
-               screen_info.lfb_height = 768;
-               screen_info.lfb_linelength = 2048 * 4;
-               screen_info.lfb_base = 0x80000000;
-               break;
-       case M_MACBOOK:
-               screen_info.lfb_width = 1280;
-               screen_info.lfb_height = 800;
-               screen_info.lfb_linelength = 2048 * 4;
-               screen_info.lfb_base = 0x80000000;
-               break;
-       }
-
-       /* if the user wants to manually specify height/width,
-          we will override the defaults */
-       /* TODO: eventually get auto-detection working */
-       if (manual_height > 0)
-               screen_info.lfb_height = manual_height;
-       if (manual_width > 0)
-               screen_info.lfb_width = manual_width;
-
-       imacfb_fix.smem_start = screen_info.lfb_base;
-       imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
-       imacfb_defined.xres = screen_info.lfb_width;
-       imacfb_defined.yres = screen_info.lfb_height;
-       imacfb_fix.line_length = screen_info.lfb_linelength;
-
-       /*   size_vmode -- that is the amount of memory needed for the
-        *                 used video mode, i.e. the minimum amount of
-        *                 memory we need. */
-       size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
-
-       /*   size_total -- all video memory we have. Used for
-        *                 entries, ressource allocation and bounds
-        *                 checking. */
-       size_total = screen_info.lfb_size * 65536;
-       if (size_total < size_vmode)
-               size_total = size_vmode;
-
-       /*   size_remap -- the amount of video memory we are going to
-        *                 use for imacfb.  With modern cards it is no
-        *                 option to simply use size_total as that
-        *                 wastes plenty of kernel address space. */
-       size_remap  = size_vmode * 2;
-       if (size_remap < size_vmode)
-               size_remap = size_vmode;
-       if (size_remap > size_total)
-               size_remap = size_total;
-       imacfb_fix.smem_len = size_remap;
-
-       if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
-               printk(KERN_WARNING
-                      "imacfb: cannot reserve video memory at 0x%lx\n",
-                       imacfb_fix.smem_start);
-               /* We cannot make this fatal. Sometimes this comes from magic
-                  spaces our resource handlers simply don't know about */
-       }
-
-       info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
-       if (!info) {
-               err = -ENOMEM;
-               goto err_release_mem;
-       }
-       info->pseudo_palette = info->par;
-       info->par = NULL;
-
-       info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
-       if (!info->screen_base) {
-               printk(KERN_ERR "imacfb: abort, cannot ioremap video memory "
-                               "0x%x @ 0x%lx\n",
-                       imacfb_fix.smem_len, imacfb_fix.smem_start);
-               err = -EIO;
-               goto err_unmap;
-       }
-
-       printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
-              "using %dk, total %dk\n",
-              imacfb_fix.smem_start, info->screen_base,
-              size_remap/1024, size_total/1024);
-       printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
-              imacfb_defined.xres, imacfb_defined.yres,
-              imacfb_defined.bits_per_pixel, imacfb_fix.line_length,
-              screen_info.pages);
-
-       imacfb_defined.xres_virtual = imacfb_defined.xres;
-       imacfb_defined.yres_virtual = imacfb_fix.smem_len /
-                                       imacfb_fix.line_length;
-       printk(KERN_INFO "imacfb: scrolling: redraw\n");
-       imacfb_defined.yres_virtual = imacfb_defined.yres;
-
-       /* some dummy values for timing to make fbset happy */
-       imacfb_defined.pixclock     = 10000000 / imacfb_defined.xres *
-                                       1000 / imacfb_defined.yres;
-       imacfb_defined.left_margin  = (imacfb_defined.xres / 8) & 0xf8;
-       imacfb_defined.hsync_len    = (imacfb_defined.xres / 8) & 0xf8;
-
-       imacfb_defined.red.offset    = screen_info.red_pos;
-       imacfb_defined.red.length    = screen_info.red_size;
-       imacfb_defined.green.offset  = screen_info.green_pos;
-       imacfb_defined.green.length  = screen_info.green_size;
-       imacfb_defined.blue.offset   = screen_info.blue_pos;
-       imacfb_defined.blue.length   = screen_info.blue_size;
-       imacfb_defined.transp.offset = screen_info.rsvd_pos;
-       imacfb_defined.transp.length = screen_info.rsvd_size;
-
-       printk(KERN_INFO "imacfb: %s: "
-              "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-              "Truecolor",
-              screen_info.rsvd_size,
-              screen_info.red_size,
-              screen_info.green_size,
-              screen_info.blue_size,
-              screen_info.rsvd_pos,
-              screen_info.red_pos,
-              screen_info.green_pos,
-              screen_info.blue_pos);
-
-       imacfb_fix.ypanstep  = 0;
-       imacfb_fix.ywrapstep = 0;
-
-       /* request failure does not faze us, as vgacon probably has this
-        * region already (FIXME) */
-       request_region(0x3c0, 32, "imacfb");
-
-       info->fbops = &imacfb_ops;
-       info->var = imacfb_defined;
-       info->fix = imacfb_fix;
-       info->flags = FBINFO_FLAG_DEFAULT;
-
-       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
-               err = -ENOMEM;
-               goto err_unmap;
-       }
-       if (register_framebuffer(info)<0) {
-               err = -EINVAL;
-               goto err_fb_dealoc;
-       }
-       printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              info->node, info->fix.id);
-       return 0;
-
-err_fb_dealoc:
-       fb_dealloc_cmap(&info->cmap);
-err_unmap:
-       iounmap(info->screen_base);
-       framebuffer_release(info);
-err_release_mem:
-       release_mem_region(imacfb_fix.smem_start, size_total);
-       return err;
-}
-
-static struct platform_driver imacfb_driver = {
-       .probe  = imacfb_probe,
-       .driver = {
-               .name   = "imacfb",
-       },
-};
-
-static struct platform_device imacfb_device = {
-       .name   = "imacfb",
-};
-
-static int __init imacfb_init(void)
-{
-       int ret;
-       char *option = NULL;
-
-       if (!efi_enabled)
-               return -ENODEV;
-       if (!dmi_check_system(dmi_system_table))
-               return -ENODEV;
-       if (model == M_UNKNOWN)
-               return -ENODEV;
-
-       if (fb_get_options("imacfb", &option))
-               return -ENODEV;
-
-       imacfb_setup(option);
-       ret = platform_driver_register(&imacfb_driver);
-
-       if (!ret) {
-               ret = platform_device_register(&imacfb_device);
-               if (ret)
-                       platform_driver_unregister(&imacfb_driver);
-       }
-       return ret;
-}
-module_init(imacfb_init);
-
-MODULE_LICENSE("GPL");
index 3325fbd68ab3b235a9ec370e59cd96314b414359..a50bea6148044bdf4fb08e1ce49c377fc2aa9939 100644 (file)
@@ -12,9 +12,9 @@
 #endif
 
 /*** Version/name ***/
-#define INTELFB_VERSION                        "0.9.5"
+#define INTELFB_VERSION                        "0.9.6"
 #define INTELFB_MODULE_NAME            "intelfb"
-#define SUPPORTED_CHIPSETS             "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
+#define SUPPORTED_CHIPSETS             "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
 
 
 /*** Debug/feature defines ***/
@@ -58,6 +58,7 @@
 #define PCI_DEVICE_ID_INTEL_915GM      0x2592
 #define PCI_DEVICE_ID_INTEL_945G       0x2772
 #define PCI_DEVICE_ID_INTEL_945GM      0x27A2
+#define PCI_DEVICE_ID_INTEL_945GME     0x27AE
 #define PCI_DEVICE_ID_INTEL_965G       0x29A2
 #define PCI_DEVICE_ID_INTEL_965GM      0x2A02
 
@@ -160,6 +161,7 @@ enum intel_chips {
        INTEL_915GM,
        INTEL_945G,
        INTEL_945GM,
+       INTEL_945GME,
        INTEL_965G,
        INTEL_965GM,
 };
@@ -363,6 +365,7 @@ struct intelfb_info {
                        ((dinfo)->chipset == INTEL_915GM) ||    \
                        ((dinfo)->chipset == INTEL_945G) ||     \
                        ((dinfo)->chipset == INTEL_945GM) ||    \
+                       ((dinfo)->chipset == INTEL_945GME) ||   \
                        ((dinfo)->chipset == INTEL_965G) ||     \
                        ((dinfo)->chipset == INTEL_965GM))
 
index fcf9fadbf5722d328f521af00aa8fe5675e16da0..5d896b81f4e040a32a0fb6a2710c56c170224274 100644 (file)
@@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
                /* has some LVDS + tv-out */
        case INTEL_945G:
        case INTEL_945GM:
+       case INTEL_945GME:
        case INTEL_965G:
        case INTEL_965GM:
                /* SDVO ports have a single control bus - 2 devices */
index e44303f9bc524ea64e86bd00030ffbaa3110dd01..a09e236493576f7602366e66d57781616c5c3933 100644 (file)
@@ -2,7 +2,7 @@
  * intelfb
  *
  * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
- * 945G/945GM/965G/965GM integrated graphics chips.
+ * 945G/945GM/945GME/965G/965GM integrated graphics chips.
  *
  * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
  *                   2004 Sylvain Meyer
  *
  *    04/2008 - Version 0.9.5
  *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
+ *
+ *    08/2008 - Version 0.9.6
+ *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
  */
 
 #include <linux/module.h>
@@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
        { 0, }
@@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
            (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
            (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
            (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
+           (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
            (ent->device == PCI_DEVICE_ID_INTEL_965G) ||
            (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {
 
index 8e6d6a4db0ad85a52d8fd8313fcaf7f9f6884d3b..8b26b27c2db6f5f6ed68853a1ed1f7118e9c7c4d 100644 (file)
@@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
                dinfo->mobile = 1;
                dinfo->pll_index = PLLS_I9xx;
                return 0;
+       case PCI_DEVICE_ID_INTEL_945GME:
+               dinfo->name = "Intel(R) 945GME";
+               dinfo->chipset = INTEL_945GME;
+               dinfo->mobile = 1;
+               dinfo->pll_index = PLLS_I9xx;
+               return 0;
        case PCI_DEVICE_ID_INTEL_965G:
                dinfo->name = "Intel(R) 965G";
                dinfo->chipset = INTEL_965G;
@@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
        case PCI_DEVICE_ID_INTEL_915GM:
        case PCI_DEVICE_ID_INTEL_945G:
        case PCI_DEVICE_ID_INTEL_945GM:
+       case PCI_DEVICE_ID_INTEL_945GME:
        case PCI_DEVICE_ID_INTEL_965G:
        case PCI_DEVICE_ID_INTEL_965GM:
                /* 915, 945 and 965 chipsets support a 256MB aperture.
index c02136202792fab1b97c8d9a6d3938db69c241cb..8e7a275df50c79a13c328785a2909d66aae7a0bb 100644 (file)
@@ -1453,6 +1453,13 @@ static struct board {
                MGA_G100,
                &vbG100,
                "MGA-G100 (AGP)"},
+       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200EV_PCI,        0xFF,
+               0,                      0,
+               DEVF_G200,
+               230000,
+               MGA_G200,
+               &vbG200,
+               "MGA-G200eV (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,  0xFF,
                0,                      0,
                DEVF_G200,
@@ -2118,6 +2125,8 @@ static struct pci_device_id matroxfb_devices[] = {
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
+       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200EV_PCI,
+               PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,
index afeed0611e3e0896cc28e05d355a9fdad73a6d08..df1f757a6161cde2f7d189be4501567af96fd6f2 100644 (file)
@@ -188,7 +188,7 @@ static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
                epd_frame_table[par->dt].wfm_size = user_wfm_size;
 
        if (size != epd_frame_table[par->dt].wfm_size) {
-               dev_err(dev, "Error: unexpected size %d != %d\n", size,
+               dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
                                        epd_frame_table[par->dt].wfm_size);
                return -EINVAL;
        }
index 25172b2a2a941e15fe684e9130293c019467981d..bfb802d26d5af7286a59364c15f50ca9f881e97e 100644 (file)
@@ -426,11 +426,11 @@ static void vgaHWProtect(int on)
 {
        unsigned char tmp;
 
+       tmp = vga_rseq(NULL, 0x01);
        if (on) {
                /*
                 * Turn off screen and disable sequencer.
                 */
-               tmp = vga_rseq(NULL, 0x01);
                vga_wseq(NULL, 0x00, 0x01);             /* Synchronous Reset */
                vga_wseq(NULL, 0x01, tmp | 0x20);       /* disable the display */
 
@@ -439,7 +439,6 @@ static void vgaHWProtect(int on)
                /*
                 * Reenable sequencer, then turn on screen.
                 */
-               tmp = vga_rseq(NULL, 0x01);
                vga_wseq(NULL, 0x01, tmp & ~0x20);      /* reenable display */
                vga_wseq(NULL, 0x00, 0x03);             /* clear synchronousreset */
 
@@ -558,14 +557,12 @@ neofb_open(struct fb_info *info, int user)
 {
        struct neofb_par *par = info->par;
 
-       mutex_lock(&par->open_lock);
        if (!par->ref_count) {
                memset(&par->state, 0, sizeof(struct vgastate));
                par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
                save_vga(&par->state);
        }
        par->ref_count++;
-       mutex_unlock(&par->open_lock);
 
        return 0;
 }
@@ -575,16 +572,13 @@ neofb_release(struct fb_info *info, int user)
 {
        struct neofb_par *par = info->par;
 
-       mutex_lock(&par->open_lock);
-       if (!par->ref_count) {
-               mutex_unlock(&par->open_lock);
+       if (!par->ref_count)
                return -EINVAL;
-       }
+
        if (par->ref_count == 1) {
                restore_vga(&par->state);
        }
        par->ref_count--;
-       mutex_unlock(&par->open_lock);
 
        return 0;
 }
@@ -648,10 +642,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        var->blue.msb_right = 0;
        var->transp.msb_right = 0;
 
+       var->transp.offset = 0;
+       var->transp.length = 0;
        switch (var->bits_per_pixel) {
        case 8:         /* PSEUDOCOLOUR, 256 */
-               var->transp.offset = 0;
-               var->transp.length = 0;
                var->red.offset = 0;
                var->red.length = 8;
                var->green.offset = 0;
@@ -661,8 +655,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                break;
 
        case 16:                /* DIRECTCOLOUR, 64k */
-               var->transp.offset = 0;
-               var->transp.length = 0;
                var->red.offset = 11;
                var->red.length = 5;
                var->green.offset = 5;
@@ -672,8 +664,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                break;
 
        case 24:                /* TRUECOLOUR, 16m */
-               var->transp.offset = 0;
-               var->transp.length = 0;
                var->red.offset = 16;
                var->red.length = 8;
                var->green.offset = 8;
@@ -704,8 +694,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        if (vramlen > 4 * 1024 * 1024)
                vramlen = 4 * 1024 * 1024;
 
-       if (var->yres_virtual < var->yres)
-               var->yres_virtual = var->yres;
        if (var->xres_virtual < var->xres)
                var->xres_virtual = var->xres;
 
@@ -722,8 +710,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
           if it was possible. We should return -EINVAL, but I disagree */
        if (var->yres_virtual < var->yres)
                var->yres = var->yres_virtual;
-       if (var->xres_virtual < var->xres)
-               var->xres = var->xres_virtual;
        if (var->xoffset + var->xres > var->xres_virtual)
                var->xoffset = var->xres_virtual - var->xres;
        if (var->yoffset + var->yres > var->yres_virtual)
@@ -1186,8 +1172,11 @@ static int neofb_set_par(struct fb_info *info)
        return 0;
 }
 
-static void neofb_update_start(struct fb_info *info,
-                              struct fb_var_screeninfo *var)
+/*
+ *    Pan or Wrap the Display
+ */
+static int neofb_pan_display(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
 {
        struct neofb_par *par = info->par;
        struct vgastate *state = &par->state;
@@ -1216,35 +1205,7 @@ static void neofb_update_start(struct fb_info *info,
        vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
 
        neoLock(state);
-}
-
-/*
- *    Pan or Wrap the Display
- */
-static int neofb_pan_display(struct fb_var_screeninfo *var,
-                            struct fb_info *info)
-{
-       u_int y_bottom;
-
-       y_bottom = var->yoffset;
-
-       if (!(var->vmode & FB_VMODE_YWRAP))
-               y_bottom += var->yres;
 
-       if (var->xoffset > (var->xres_virtual - var->xres))
-               return -EINVAL;
-       if (y_bottom > info->var.yres_virtual)
-               return -EINVAL;
-
-       neofb_update_start(info, var);
-
-       info->var.xoffset = var->xoffset;
-       info->var.yoffset = var->yoffset;
-
-       if (var->vmode & FB_VMODE_YWRAP)
-               info->var.vmode |= FB_VMODE_YWRAP;
-       else
-               info->var.vmode &= ~FB_VMODE_YWRAP;
        return 0;
 }
 
@@ -1992,7 +1953,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
 
        info->fix.accel = id->driver_data;
 
-       mutex_init(&par->open_lock);
        par->pci_burst = !nopciburst;
        par->lcd_stretch = !nostretch;
        par->libretto = libretto;
index 6efcf89e7fbe9667e9f4722e91fd8dfeb0964bd3..dfb72f5e4c962ad35098fb07a65252b99be31941 100644 (file)
@@ -156,7 +156,7 @@ struct resmap {
 };
 
 static struct {
-       u32             base;
+       void __iomem    *base;
 
        struct omapfb_mem_desc  mem_desc;
        struct resmap           *res_map[DISPC_MEMTYPE_NUM];
@@ -212,9 +212,9 @@ static void enable_rfbi_mode(int enable)
        dispc_write_reg(DISPC_CONTROL, l);
 
        /* Set bypass mode in RFBI module */
-       l = __raw_readl(io_p2v(RFBI_CONTROL));
+       l = __raw_readl(IO_ADDRESS(RFBI_CONTROL));
        l |= enable ? 0 : (1 << 1);
-       __raw_writel(l, io_p2v(RFBI_CONTROL));
+       __raw_writel(l, IO_ADDRESS(RFBI_CONTROL));
 }
 
 static void set_lcd_data_lines(int data_lines)
@@ -1349,14 +1349,19 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
 
        memset(&dispc, 0, sizeof(dispc));
 
-       dispc.base = io_p2v(DISPC_BASE);
+       dispc.base = ioremap(DISPC_BASE, SZ_1K);
+       if (!dispc.base) {
+               dev_err(fbdev->dev, "can't ioremap DISPC\n");
+               return -ENOMEM;
+       }
+
        dispc.fbdev = fbdev;
        dispc.ext_mode = ext_mode;
 
        init_completion(&dispc.frame_done);
 
        if ((r = get_dss_clocks()) < 0)
-               return r;
+               goto fail0;
 
        enable_interface_clocks(1);
        enable_lcd_clocks(1);
@@ -1414,7 +1419,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
        }
 
        /* L3 firewall setting: enable access to OCM RAM */
-       __raw_writel(0x402000b0, io_p2v(0x680050a0));
+       __raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
 
        if ((r = alloc_palette_ram()) < 0)
                goto fail2;
@@ -1464,7 +1469,8 @@ fail1:
        enable_lcd_clocks(0);
        enable_interface_clocks(0);
        put_dss_clocks();
-
+fail0:
+       iounmap(dispc.base);
        return r;
 }
 
@@ -1481,6 +1487,7 @@ static void omap_dispc_cleanup(void)
        free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
        enable_interface_clocks(0);
        put_dss_clocks();
+       iounmap(dispc.base);
 }
 
 const struct lcd_ctrl omap2_int_ctrl = {
index eb1512b56ce86e3c0c54e4da0607d05750b40112..ef720a78f6d513155d38ae1cba4061c966d0d1fa 100644 (file)
@@ -40,4 +40,6 @@ extern void omap_dispc_enable_digit_out(int enable);
 extern int  omap_dispc_request_irq(void (*callback)(void *data), void *data);
 extern void omap_dispc_free_irq(void);
 
+extern const struct lcd_ctrl omap2_int_ctrl;
+
 #endif
index 88c19d424ef769f32f1fe9fa23996b7214f4e9ec..6ff56430341b862a21dbbbaec416b13f17e484a1 100644 (file)
@@ -47,7 +47,7 @@ static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
        return 0;
 }
 
-struct lcd_panel h4_panel = {
+static struct lcd_panel h4_panel = {
        .name           = "h4",
        .config         = OMAP_LCDC_PANEL_TFT,
 
@@ -91,7 +91,7 @@ static int h4_panel_resume(struct platform_device *pdev)
        return 0;
 }
 
-struct platform_driver h4_panel_driver = {
+static struct platform_driver h4_panel_driver = {
        .probe          = h4_panel_probe,
        .remove         = h4_panel_remove,
        .suspend        = h4_panel_suspend,
index 6a42c6a0cd9991466b1a77781873e05b3171fcd8..4c4f7ee6d733a66e739c6be1e9cd65ad370f8633 100644 (file)
@@ -32,43 +32,43 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
 {
        int r = 0;
 
-       if (omap_request_gpio(14)) {
+       if (gpio_request(14, "lcd_en0")) {
                pr_err(MODULE_NAME ": can't request GPIO 14\n");
                r = -1;
                goto exit;
        }
-       if (omap_request_gpio(15)) {
+       if (gpio_request(15, "lcd_en1")) {
                pr_err(MODULE_NAME ": can't request GPIO 15\n");
-               omap_free_gpio(14);
+               gpio_free(14);
                r = -1;
                goto exit;
        }
        /* configure GPIO(14, 15) as outputs */
-       omap_set_gpio_direction(14, 0);
-       omap_set_gpio_direction(15, 0);
+       gpio_direction_output(14, 0);
+       gpio_direction_output(15, 0);
 exit:
        return r;
 }
 
 static void innovator1610_panel_cleanup(struct lcd_panel *panel)
 {
-       omap_free_gpio(15);
-       omap_free_gpio(14);
+       gpio_free(15);
+       gpio_free(14);
 }
 
 static int innovator1610_panel_enable(struct lcd_panel *panel)
 {
        /* set GPIO14 and GPIO15 high */
-       omap_set_gpio_dataout(14, 1);
-       omap_set_gpio_dataout(15, 1);
+       gpio_set_value(14, 1);
+       gpio_set_value(15, 1);
        return 0;
 }
 
 static void innovator1610_panel_disable(struct lcd_panel *panel)
 {
        /* set GPIO13, GPIO14 and GPIO15 low */
-       omap_set_gpio_dataout(14, 0);
-       omap_set_gpio_dataout(15, 0);
+       gpio_set_value(14, 0);
+       gpio_set_value(15, 0);
 }
 
 static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)
index a4a725f427a487843b03cad5e45abbf4fd230004..379c96d36da5833377e5d5df97085662ed6b52f5 100644 (file)
@@ -29,6 +29,7 @@
 
 static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
 {
+       /* gpio2 was allocated in board init */
        return 0;
 }
 
@@ -47,11 +48,8 @@ static int osk_panel_enable(struct lcd_panel *panel)
        /* Set PWL level */
        omap_writeb(0xFF, OMAP_PWL_ENABLE);
 
-       /* configure GPIO2 as output */
-       omap_set_gpio_direction(2, 0);
-
-       /* set GPIO2 high */
-       omap_set_gpio_dataout(2, 1);
+       /* set GPIO2 high (lcd power enabled) */
+       gpio_set_value(2, 1);
 
        return 0;
 }
@@ -65,7 +63,7 @@ static void osk_panel_disable(struct lcd_panel *panel)
        omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
 
        /* set GPIO2 low */
-       omap_set_gpio_dataout(2, 0);
+       gpio_set_value(2, 0);
 }
 
 static unsigned long osk_panel_get_caps(struct lcd_panel *panel)
index caa6a896cb8b7d84912dceb6a45b7e3871f3c588..e55de201b8ff4508e6de02ae29c970acf9cffb2f 100644 (file)
@@ -81,21 +81,21 @@ static void epson_sendbyte(int flag, unsigned char byte)
        int i, shifter = 0x80;
 
        if (!flag)
-               omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
+               gpio_set_value(_A_LCD_SSC_A0, 0);
        mdelay(2);
-       omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
+       gpio_set_value(A_LCD_SSC_RD, 1);
 
-       omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
+       gpio_set_value(A_LCD_SSC_SD, flag);
 
        OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
        OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
        for (i = 0; i < 8; i++) {
                OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
-               omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
+               gpio_set_value(A_LCD_SSC_SD, shifter & byte);
                OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
                shifter >>= 1;
        }
-       omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+       gpio_set_value(_A_LCD_SSC_A0, 1);
 }
 
 static void init_system(void)
@@ -107,25 +107,18 @@ static void init_system(void)
 static void setup_GPIO(void)
 {
        /* new wave */
-       omap_request_gpio(A_LCD_SSC_RD);
-       omap_request_gpio(A_LCD_SSC_SD);
-       omap_request_gpio(_A_LCD_RESET);
-       omap_request_gpio(_A_LCD_SSC_CS);
-       omap_request_gpio(_A_LCD_SSC_A0);
-
-       /* set all GPIOs to output */
-       omap_set_gpio_direction(A_LCD_SSC_RD, 0);
-       omap_set_gpio_direction(A_LCD_SSC_SD, 0);
-       omap_set_gpio_direction(_A_LCD_RESET, 0);
-       omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
-       omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
-
-       /* set GPIO data */
-       omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
-       omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
-       omap_set_gpio_dataout(_A_LCD_RESET, 0);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
+       gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
+       gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
+       gpio_request(_A_LCD_RESET, "lcd_reset");
+       gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
+       gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
+
+       /* set GPIOs to output, with initial data */
+       gpio_direction_output(A_LCD_SSC_RD, 1);
+       gpio_direction_output(A_LCD_SSC_SD, 0);
+       gpio_direction_output(_A_LCD_RESET, 0);
+       gpio_direction_output(_A_LCD_SSC_CS, 1);
+       gpio_direction_output(_A_LCD_SSC_A0, 1);
 }
 
 static void display_init(void)
@@ -139,61 +132,61 @@ static void display_init(void)
        mdelay(2);
 
        /* reset LCD */
-       omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
+       gpio_set_value(A_LCD_SSC_SD, 1);
        epson_sendbyte(0, 0x25);
 
-       omap_set_gpio_dataout(_A_LCD_RESET, 0);
+       gpio_set_value(_A_LCD_RESET, 0);
        mdelay(10);
-       omap_set_gpio_dataout(_A_LCD_RESET, 1);
+       gpio_set_value(_A_LCD_RESET, 1);
 
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
        mdelay(2);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD, phase 1 */
        epson_sendbyte(0, 0xCA);
        for (i = 0; i < 10; i++)
                epson_sendbyte(1, INIT_1[i]);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 2 */
        epson_sendbyte(0, 0xCB);
        for (i = 0; i < 125; i++)
                epson_sendbyte(1, INIT_2[i]);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 2a */
        epson_sendbyte(0, 0xCC);
        for (i = 0; i < 14; i++)
                epson_sendbyte(1, INIT_3[i]);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 3 */
        epson_sendbyte(0, 0xBC);
        epson_sendbyte(1, 0x08);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 4 */
        epson_sendbyte(0, 0x07);
        epson_sendbyte(1, 0x05);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 5 */
        epson_sendbyte(0, 0x94);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 6 */
        epson_sendbyte(0, 0xC6);
        epson_sendbyte(1, 0x80);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
        mdelay(100); /* used to be 1000 */
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 7 */
        epson_sendbyte(0, 0x16);
@@ -201,8 +194,8 @@ static void display_init(void)
        epson_sendbyte(1, 0x00);
        epson_sendbyte(1, 0xB1);
        epson_sendbyte(1, 0x00);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 8 */
        epson_sendbyte(0, 0x76);
@@ -210,12 +203,12 @@ static void display_init(void)
        epson_sendbyte(1, 0x00);
        epson_sendbyte(1, 0xDB);
        epson_sendbyte(1, 0x00);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        /* init LCD phase 9 */
        epson_sendbyte(0, 0xAF);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
 }
 
 static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
@@ -231,18 +224,18 @@ static void sx1_panel_disable(struct lcd_panel *panel)
 {
        printk(KERN_INFO "SX1: LCD panel disable\n");
        sx1_setmmipower(0);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
 
        epson_sendbyte(0, 0x25);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        epson_sendbyte(0, 0xAE);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
        mdelay(100);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
+       gpio_set_value(_A_LCD_SSC_CS, 0);
 
        epson_sendbyte(0, 0x95);
-       omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
+       gpio_set_value(_A_LCD_SSC_CS, 1);
 }
 
 static int sx1_panel_enable(struct lcd_panel *panel)
index 83514f066712c4d3157b9c3c1c1b2a72d7b82d68..6e2ea7518761cb95b8161080d6adadc0ed2de792 100644 (file)
@@ -34,6 +34,8 @@
 
 #include <asm/mach-types.h>
 
+#include "lcdc.h"
+
 #define MODULE_NAME                    "lcdc"
 
 #define OMAP_LCDC_BASE                 0xfffec000
index adb731e5314a22e5702e98f389e81c33614c78dd..845222270db3f60b01ffdd7278f0c15ac3be2ac1 100644 (file)
@@ -4,4 +4,6 @@
 int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
 void omap_lcdc_free_dma_callback(void);
 
+extern const struct lcd_ctrl omap1_int_ctrl;
+
 #endif
index 51a138bd113c0a42a4d385bf0af2ab4e8b790ab6..5a5e407dc45f713cc9252f11efcf1ae2b113f2a3 100644 (file)
 #include <mach/dma.h>
 #include <mach/omapfb.h>
 
+#include "lcdc.h"
+#include "dispc.h"
+
 #define MODULE_NAME    "omapfb"
 
 static unsigned int    def_accel;
 static unsigned long   def_vram[OMAPFB_PLANE_NUM];
-static int             def_vram_cnt;
+static unsigned int    def_vram_cnt;
 static unsigned long   def_vxres;
 static unsigned long   def_vyres;
 static unsigned int    def_rotate;
@@ -84,12 +87,10 @@ static struct caps_table_struct color_caps[] = {
  * LCD panel
  * ---------------------------------------------------------------------------
  */
-extern struct lcd_ctrl omap1_int_ctrl;
-extern struct lcd_ctrl omap2_int_ctrl;
 extern struct lcd_ctrl hwa742_ctrl;
 extern struct lcd_ctrl blizzard_ctrl;
 
-static struct lcd_ctrl *ctrls[] = {
+static const struct lcd_ctrl *ctrls[] = {
 #ifdef CONFIG_ARCH_OMAP1
        &omap1_int_ctrl,
 #else
@@ -740,7 +741,7 @@ static int omapfb_update_win(struct fb_info *fbi,
        int ret;
 
        omapfb_rqueue_lock(plane->fbdev);
-       ret = omapfb_update_window_async(fbi, win, NULL, 0);
+       ret = omapfb_update_window_async(fbi, win, NULL, NULL);
        omapfb_rqueue_unlock(plane->fbdev);
 
        return ret;
@@ -768,7 +769,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi)
        win.format = 0;
 
        omapfb_rqueue_lock(fbdev);
-       r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
+       r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
        omapfb_rqueue_unlock(fbdev);
 
        return r;
@@ -1047,7 +1048,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
                win.height = 2;
                win.out_width = 2;
                win.out_height = 2;
-               fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
+               fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
        }
        omapfb_rqueue_unlock(fbdev);
 }
index 4a6f13d3facf9d69ed984036d599248f5dfd328e..a13c8dcad2a8429c1a5da98f489a60b0da46ff51 100644 (file)
@@ -59,7 +59,7 @@
 #define DISPC_CONTROL          0x0040
 
 static struct {
-       u32             base;
+       void __iomem    *base;
        void            (*lcdc_callback)(void *data);
        void            *lcdc_callback_data;
        unsigned long   l4_khz;
@@ -518,7 +518,11 @@ static int rfbi_init(struct omapfb_device *fbdev)
        int r;
 
        rfbi.fbdev = fbdev;
-       rfbi.base = io_p2v(RFBI_BASE);
+       rfbi.base = ioremap(RFBI_BASE, SZ_1K);
+       if (!rfbi.base) {
+               dev_err(fbdev->dev, "can't ioremap RFBI\n");
+               return -ENOMEM;
+       }
 
        if ((r = rfbi_get_clocks()) < 0)
                return r;
@@ -566,6 +570,7 @@ static void rfbi_cleanup(void)
 {
        omap_dispc_free_irq();
        rfbi_put_clocks();
+       iounmap(rfbi.base);
 }
 
 const struct lcd_ctrl_extif omap2_ext_if = {
index 6359353c2c67feb92f0d004d2f93fbb1cce35e38..a7694622024925befb1f26692523937146dd3588 100644 (file)
@@ -574,7 +574,12 @@ static int sossi_init(struct omapfb_device *fbdev)
        struct clk *dpll1out_ck;
        int r;
 
-       sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
+       sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
+       if (!sossi.base) {
+               dev_err(fbdev->dev, "can't ioremap SoSSI\n");
+               return -ENOMEM;
+       }
+
        sossi.fbdev = fbdev;
        spin_lock_init(&sossi.lock);
 
@@ -665,6 +670,7 @@ static void sossi_cleanup(void)
 {
        omap_lcdc_free_dma_callback();
        clk_put(sossi.fck);
+       iounmap(sossi.base);
 }
 
 struct lcd_ctrl_extif omap1_ext_if = {
index b829dc7c5edfeb4d9621599aa05d1c0dd296dfa7..a7b01d2724b5110ce4365fa35e8c32c05c6b385c 100644 (file)
 #define dbg(fmt, args...) do { } while (0)
 #endif
 
+static const int __devinitconst s1d13xxxfb_revisions[] = {
+       S1D13506_CHIP_REV,      /* Rev.4 on HP Jornada 7xx S1D13506 */
+       S1D13806_CHIP_REV,      /* Rev.7 on .. */
+};
+
 /*
  * Here we define the default struct fb_fix_screeninfo
  */
@@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
        struct fb_info *info;
        struct s1d13xxxfb_pdata *pdata = NULL;
        int ret = 0;
+       int i;
        u8 revision;
 
        dbg("probe called: device is %p\n", pdev);
@@ -607,10 +613,19 @@ s1d13xxxfb_probe(struct platform_device *pdev)
                goto bail;
        }
 
-       revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
-       if ((revision >> 2) != S1D_CHIP_REV) {
-               printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
-               ret = -ENODEV;
+       revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
+
+       ret = -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) {
+               if (revision == s1d13xxxfb_revisions[i])
+                       ret = 0;
+       }
+
+       if (!ret)
+               printk(KERN_INFO PFX "chip revision %i\n", revision);
+       else {
+               printk(KERN_INFO PFX "unknown chip revision %i\n", revision);
                goto bail;
        }
 
index 4599a4385bc9794337d87ad697b313e9421d8246..14bd3f3680b8e549d6662e4d5779b8b259886a05 100644 (file)
@@ -1195,57 +1195,58 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
                return -ENOMEM;
 
        default_par = info->par;
+       info->fix = tdfx_fix;
 
        /* Configure the default fb_fix_screeninfo first */
        switch (pdev->device) {
        case PCI_DEVICE_ID_3DFX_BANSHEE:
-               strcpy(tdfx_fix.id, "3Dfx Banshee");
+               strcpy(info->fix.id, "3Dfx Banshee");
                default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
                break;
        case PCI_DEVICE_ID_3DFX_VOODOO3:
-               strcpy(tdfx_fix.id, "3Dfx Voodoo3");
+               strcpy(info->fix.id, "3Dfx Voodoo3");
                default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
                break;
        case PCI_DEVICE_ID_3DFX_VOODOO5:
-               strcpy(tdfx_fix.id, "3Dfx Voodoo5");
+               strcpy(info->fix.id, "3Dfx Voodoo5");
                default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
                break;
        }
 
-       tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
-       tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
-       if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,
+       info->fix.mmio_start = pci_resource_start(pdev, 0);
+       info->fix.mmio_len = pci_resource_len(pdev, 0);
+       if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
                                "tdfx regbase")) {
                printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
                goto out_err;
        }
 
        default_par->regbase_virt =
-               ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+               ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
        if (!default_par->regbase_virt) {
                printk(KERN_ERR "fb: Can't remap %s register area.\n",
-                               tdfx_fix.id);
+                               info->fix.id);
                goto out_err_regbase;
        }
 
-       tdfx_fix.smem_start = pci_resource_start(pdev, 1);
-       tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device);
-       if (!tdfx_fix.smem_len) {
-               printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id);
+       info->fix.smem_start = pci_resource_start(pdev, 1);
+       info->fix.smem_len = do_lfb_size(default_par, pdev->device);
+       if (!info->fix.smem_len) {
+               printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
                goto out_err_regbase;
        }
 
-       if (!request_mem_region(tdfx_fix.smem_start,
+       if (!request_mem_region(info->fix.smem_start,
                                pci_resource_len(pdev, 1), "tdfx smem")) {
                printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
                goto out_err_regbase;
        }
 
-       info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
-                                           tdfx_fix.smem_len);
+       info->screen_base = ioremap_nocache(info->fix.smem_start,
+                                           info->fix.smem_len);
        if (!info->screen_base) {
                printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
-                               tdfx_fix.id);
+                               info->fix.id);
                goto out_err_screenbase;
        }
 
@@ -1257,20 +1258,19 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
                goto out_err_screenbase;
        }
 
-       printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id,
-                       tdfx_fix.smem_len >> 10);
+       printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
+                       info->fix.smem_len >> 10);
 
        default_par->mtrr_handle = -1;
        if (!nomtrr)
                default_par->mtrr_handle =
-                       mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len,
+                       mtrr_add(info->fix.smem_start, info->fix.smem_len,
                                 MTRR_TYPE_WRCOMB, 1);
 
-       tdfx_fix.ypanstep       = nopan ? 0 : 1;
-       tdfx_fix.ywrapstep      = nowrap ? 0 : 1;
+       info->fix.ypanstep      = nopan ? 0 : 1;
+       info->fix.ywrapstep     = nowrap ? 0 : 1;
 
        info->fbops             = &tdfxfb_ops;
-       info->fix               = tdfx_fix;
        info->pseudo_palette    = default_par->palette;
        info->flags             = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 #ifdef CONFIG_FB_3DFX_ACCEL
@@ -1323,14 +1323,14 @@ out_err_iobase:
 out_err_screenbase:
        if (info->screen_base)
                iounmap(info->screen_base);
-       release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));
+       release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
 out_err_regbase:
        /*
         * Cleanup after anything that was remapped/allocated.
         */
        if (default_par->regbase_virt)
                iounmap(default_par->regbase_virt);
-       release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
+       release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
 out_err:
        framebuffer_release(info);
        return -ENXIO;
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
new file mode 100644 (file)
index 0000000..2a38001
--- /dev/null
@@ -0,0 +1,1050 @@
+/*
+ * Frame Buffer Device for Toshiba Mobile IO(TMIO) controller
+ *
+ * Copyright(C) 2005-2006 Chris Humbert
+ * Copyright(C) 2005 Dirk Opfer
+ * Copytight(C) 2007,2008 Dmitry Baryshkov
+ *
+ * Based on:
+ *     drivers/video/w100fb.c
+ *     code written by Sharp/Lineo for 2.4 kernels
+ *
+ * This program is free software; you can 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 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+/* Why should fb driver call console functions? because acquire_console_sem() */
+#include <linux/console.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/uaccess.h>
+
+/*
+ * accelerator commands
+ */
+#define TMIOFB_ACC_CSADR(x)    (0x00000000 | ((x) & 0x001ffffe))
+#define TMIOFB_ACC_CHPIX(x)    (0x01000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_CVPIX(x)    (0x02000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PSADR(x)    (0x03000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_PHPIX(x)    (0x04000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVPIX(x)    (0x05000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PHOFS(x)    (0x06000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_PVOFS(x)    (0x07000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_POADR(x)    (0x08000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_RSTR(x)     (0x09000000 | ((x) & 0x000000ff))
+#define TMIOFB_ACC_TCLOR(x)    (0x0A000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_FILL(x)     (0x0B000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_DSADR(x)    (0x0C000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_SSADR(x)    (0x0D000000 | ((x) & 0x00fffffe))
+#define TMIOFB_ACC_DHPIX(x)    (0x0E000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_DVPIX(x)    (0x0F000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SHPIX(x)    (0x10000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_SVPIX(x)    (0x11000000 | ((x) & 0x000003ff))
+#define TMIOFB_ACC_LBINI(x)    (0x12000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_LBK2(x)     (0x13000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBINI(x)   (0x14000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SHBK2(x)    (0x15000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBINI(x)   (0x16000000 | ((x) & 0x0000ffff))
+#define TMIOFB_ACC_SVBK2(x)    (0x17000000 | ((x) & 0x0000ffff))
+
+#define TMIOFB_ACC_CMGO                0x20000000
+#define TMIOFB_ACC_CMGO_CEND   0x00000001
+#define TMIOFB_ACC_CMGO_INT    0x00000002
+#define TMIOFB_ACC_CMGO_CMOD   0x00000010
+#define TMIOFB_ACC_CMGO_CDVRV  0x00000020
+#define TMIOFB_ACC_CMGO_CDHRV  0x00000040
+#define TMIOFB_ACC_CMGO_RUND   0x00008000
+#define TMIOFB_ACC_SCGO                0x21000000
+#define TMIOFB_ACC_SCGO_CEND   0x00000001
+#define TMIOFB_ACC_SCGO_INT    0x00000002
+#define TMIOFB_ACC_SCGO_ROP3   0x00000004
+#define TMIOFB_ACC_SCGO_TRNS   0x00000008
+#define TMIOFB_ACC_SCGO_DVRV   0x00000010
+#define TMIOFB_ACC_SCGO_DHRV   0x00000020
+#define TMIOFB_ACC_SCGO_SVRV   0x00000040
+#define TMIOFB_ACC_SCGO_SHRV   0x00000080
+#define TMIOFB_ACC_SCGO_DSTXY  0x00008000
+#define TMIOFB_ACC_SBGO                0x22000000
+#define TMIOFB_ACC_SBGO_CEND   0x00000001
+#define TMIOFB_ACC_SBGO_INT    0x00000002
+#define TMIOFB_ACC_SBGO_DVRV   0x00000010
+#define TMIOFB_ACC_SBGO_DHRV   0x00000020
+#define TMIOFB_ACC_SBGO_SVRV   0x00000040
+#define TMIOFB_ACC_SBGO_SHRV   0x00000080
+#define TMIOFB_ACC_SBGO_SBMD   0x00000100
+#define TMIOFB_ACC_FLGO                0x23000000
+#define TMIOFB_ACC_FLGO_CEND   0x00000001
+#define TMIOFB_ACC_FLGO_INT    0x00000002
+#define TMIOFB_ACC_FLGO_ROP3   0x00000004
+#define TMIOFB_ACC_LDGO                0x24000000
+#define TMIOFB_ACC_LDGO_CEND   0x00000001
+#define TMIOFB_ACC_LDGO_INT    0x00000002
+#define TMIOFB_ACC_LDGO_ROP3   0x00000004
+#define TMIOFB_ACC_LDGO_ENDPX  0x00000008
+#define TMIOFB_ACC_LDGO_LVRV   0x00000010
+#define TMIOFB_ACC_LDGO_LHRV   0x00000020
+#define TMIOFB_ACC_LDGO_LDMOD  0x00000040
+
+/* a FIFO is always allocated, even if acceleration is not used */
+#define TMIOFB_FIFO_SIZE       512
+
+/*
+ * LCD Host Controller Configuration Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define CCR_CMD                        0x04 /* Command                         */
+#define CCR_REVID              0x08 /* Revision ID                     */
+#define CCR_BASEL              0x10 /* LCD Control Reg Base Addr Low   */
+#define CCR_BASEH              0x12 /* LCD Control Reg Base Addr High  */
+#define CCR_UGCC               0x40 /* Unified Gated Clock Control     */
+#define CCR_GCC                        0x42 /* Gated Clock Control             */
+#define CCR_USC                        0x50 /* Unified Software Clear          */
+#define CCR_VRAMRTC            0x60 /* VRAM Timing Control             */
+                               /* 0x61 VRAM Refresh Control            */
+#define CCR_VRAMSAC            0x62 /* VRAM Access Control             */
+                               /* 0x63 VRAM Status                     */
+#define CCR_VRAMBC             0x64 /* VRAM Block Control              */
+
+/*
+ * LCD Control Register
+ *
+ * This iomem area supports only 16-bit IO.
+ */
+#define LCR_UIS                        0x000 /* Unified Interrupt Status       */
+#define LCR_VHPN               0x008 /* VRAM Horizontal Pixel Number   */
+#define LCR_CFSAL              0x00a /* Command FIFO Start Address Low */
+#define LCR_CFSAH              0x00c /* Command FIFO Start Address High */
+#define LCR_CFS                        0x00e /* Command FIFO Size              */
+#define LCR_CFWS               0x010 /* Command FIFO Writeable Size    */
+#define LCR_BBIE               0x012 /* BitBLT Interrupt Enable        */
+#define LCR_BBISC              0x014 /* BitBLT Interrupt Status and Clear */
+#define LCR_CCS                        0x016 /* Command Count Status           */
+#define LCR_BBES               0x018 /* BitBLT Execution Status        */
+#define LCR_CMDL               0x01c /* Command Low                    */
+#define LCR_CMDH               0x01e /* Command High                   */
+#define LCR_CFC                        0x022 /* Command FIFO Clear             */
+#define LCR_CCIFC              0x024 /* CMOS Camera IF Control         */
+#define LCR_HWT                        0x026 /* Hardware Test                  */
+#define LCR_LCDCCRC            0x100 /* LCDC Clock and Reset Control   */
+#define LCR_LCDCC              0x102 /* LCDC Control                   */
+#define LCR_LCDCOPC            0x104 /* LCDC Output Pin Control        */
+#define LCR_LCDIS              0x108 /* LCD Interrupt Status           */
+#define LCR_LCDIM              0x10a /* LCD Interrupt Mask             */
+#define LCR_LCDIE              0x10c /* LCD Interrupt Enable           */
+#define LCR_GDSAL              0x122 /* Graphics Display Start Address Low */
+#define LCR_GDSAH              0x124 /* Graphics Display Start Address High */
+#define LCR_VHPCL              0x12a /* VRAM Horizontal Pixel Count Low */
+#define LCR_VHPCH              0x12c /* VRAM Horizontal Pixel Count High */
+#define LCR_GM                 0x12e /* Graphic Mode(VRAM access enable) */
+#define LCR_HT                 0x140 /* Horizontal Total               */
+#define LCR_HDS                        0x142 /* Horizontal Display Start       */
+#define LCR_HSS                        0x144 /* H-Sync Start                   */
+#define LCR_HSE                        0x146 /* H-Sync End                     */
+#define LCR_HNP                        0x14c /* Horizontal Number of Pixels    */
+#define LCR_VT                 0x150 /* Vertical Total                 */
+#define LCR_VDS                        0x152 /* Vertical Display Start         */
+#define LCR_VSS                        0x154 /* V-Sync Start                   */
+#define LCR_VSE                        0x156 /* V-Sync End                     */
+#define LCR_CDLN               0x160 /* Current Display Line Number    */
+#define LCR_ILN                        0x162 /* Interrupt Line Number          */
+#define LCR_SP                 0x164 /* Sync Polarity                  */
+#define LCR_MISC               0x166 /* MISC(RGB565 mode)              */
+#define LCR_VIHSS              0x16a /* Video Interface H-Sync Start   */
+#define LCR_VIVS               0x16c /* Video Interface Vertical Start */
+#define LCR_VIVE               0x16e /* Video Interface Vertical End   */
+#define LCR_VIVSS              0x170 /* Video Interface V-Sync Start   */
+#define LCR_VCCIS              0x17e /* Video / CMOS Camera Interface Select */
+#define LCR_VIDWSAL            0x180 /* VI Data Write Start Address Low */
+#define LCR_VIDWSAH            0x182 /* VI Data Write Start Address High */
+#define LCR_VIDRSAL            0x184 /* VI Data Read Start Address Low */
+#define LCR_VIDRSAH            0x186 /* VI Data Read Start Address High */
+#define LCR_VIPDDST            0x188 /* VI Picture Data Display Start Timing */
+#define LCR_VIPDDET            0x186 /* VI Picture Data Display End Timing */
+#define LCR_VIE                        0x18c /* Video Interface Enable         */
+#define LCR_VCS                        0x18e /* Video/Camera Select            */
+#define LCR_VPHWC              0x194 /* Video Picture Horizontal Wait Count */
+#define LCR_VPHS               0x196 /* Video Picture Horizontal Size  */
+#define LCR_VPVWC              0x198 /* Video Picture Vertical Wait Count */
+#define LCR_VPVS               0x19a /* Video Picture Vertical Size    */
+#define LCR_PLHPIX             0x1a0 /* PLHPIX                         */
+#define LCR_XS                 0x1a2 /* XStart                         */
+#define LCR_XCKHW              0x1a4 /* XCK High Width                 */
+#define LCR_STHS               0x1a8 /* STH Start                      */
+#define LCR_VT2                        0x1aa /* Vertical Total                 */
+#define LCR_YCKSW              0x1ac /* YCK Start Wait                 */
+#define LCR_YSTS               0x1ae /* YST Start                      */
+#define LCR_PPOLS              0x1b0 /* #PPOL Start                    */
+#define LCR_PRECW              0x1b2 /* PREC Width                     */
+#define LCR_VCLKHW             0x1b4 /* VCLK High Width                */
+#define LCR_OC                 0x1b6 /* Output Control                 */
+
+static char *mode_option __devinitdata;
+
+struct tmiofb_par {
+       u32                             pseudo_palette[16];
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+       wait_queue_head_t               wait_acc;
+       bool                            use_polling;
+#endif
+
+       void __iomem                    *ccr;
+       void __iomem                    *lcr;
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * reasons for an interrupt:
+ *     uis     bbisc   lcdis
+ *     0100    0001    accelerator command completed
+ *     2000    0001    vsync start
+ *     2000    0002    display start
+ *     2000    0004    line number match(0x1ff mask???)
+ */
+static irqreturn_t tmiofb_irq(int irq, void *__info)
+{
+       struct fb_info *info = __info;
+       struct tmiofb_par *par = info->par;
+       unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC);
+
+
+       /*
+        * We were in polling mode and now we got correct irq.
+        * Switch back to IRQ-based sync of command FIFO
+        */
+       if (unlikely(par->use_polling && irq != -1)) {
+               printk(KERN_INFO "tmiofb: switching to waitq\n");
+               par->use_polling = false;
+       }
+
+       tmio_iowrite16(bbisc, par->lcr + LCR_BBISC);
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+       if (bbisc & 1)
+               wake_up(&par->wait_acc);
+#endif
+
+       return IRQ_HANDLED;
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+
+/*
+ * Turns off the LCD controller and LCD host controller.
+ */
+static int tmiofb_hw_stop(struct platform_device *dev)
+{
+       struct mfd_cell *cell = dev->dev.platform_data;
+       struct tmio_fb_data *data = cell->driver_data;
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct tmiofb_par *par = info->par;
+
+       tmio_iowrite16(0, par->ccr + CCR_UGCC);
+       tmio_iowrite16(0, par->lcr + LCR_GM);
+       data->lcd_set_power(dev, 0);
+       tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+
+       return 0;
+}
+
+/*
+ * Initializes the LCD host controller.
+ */
+static int tmiofb_hw_init(struct platform_device *dev)
+{
+       struct mfd_cell *cell = dev->dev.platform_data;
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct tmiofb_par *par = info->par;
+       const struct resource *nlcr = &cell->resources[0];
+       const struct resource *vram = &cell->resources[2];
+       unsigned long base;
+
+       if (nlcr == NULL || vram == NULL)
+               return -EINVAL;
+
+       base = nlcr->start;
+
+       tmio_iowrite16(0x003a, par->ccr + CCR_UGCC);
+       tmio_iowrite16(0x003a, par->ccr + CCR_GCC);
+       tmio_iowrite16(0x3f00, par->ccr + CCR_USC);
+
+       msleep(2); /* wait for device to settle */
+
+       tmio_iowrite16(0x0000, par->ccr + CCR_USC);
+       tmio_iowrite16(base >> 16, par->ccr + CCR_BASEH);
+       tmio_iowrite16(base, par->ccr + CCR_BASEL);
+       tmio_iowrite16(0x0002, par->ccr + CCR_CMD); /* base address enable */
+       tmio_iowrite16(0x40a8, par->ccr + CCR_VRAMRTC); /* VRAMRC, VRAMTC */
+       tmio_iowrite16(0x0018, par->ccr + CCR_VRAMSAC); /* VRAMSTS, VRAMAC */
+       tmio_iowrite16(0x0002, par->ccr + CCR_VRAMBC);
+       msleep(2); /* wait for device to settle */
+       tmio_iowrite16(0x000b, par->ccr + CCR_VRAMBC);
+
+       base = vram->start + info->screen_size;
+       tmio_iowrite16(base >> 16, par->lcr + LCR_CFSAH);
+       tmio_iowrite16(base, par->lcr + LCR_CFSAL);
+       tmio_iowrite16(TMIOFB_FIFO_SIZE - 1, par->lcr + LCR_CFS);
+       tmio_iowrite16(1, par->lcr + LCR_CFC);
+       tmio_iowrite16(1, par->lcr + LCR_BBIE);
+       tmio_iowrite16(0, par->lcr + LCR_CFWS);
+
+       return 0;
+}
+
+/*
+ * Sets the LCD controller's output resolution and pixel clock
+ */
+static void tmiofb_hw_mode(struct platform_device *dev)
+{
+       struct mfd_cell *cell = dev->dev.platform_data;
+       struct tmio_fb_data *data = cell->driver_data;
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct fb_videomode *mode = info->mode;
+       struct tmiofb_par *par = info->par;
+       unsigned int i;
+
+       tmio_iowrite16(0, par->lcr + LCR_GM);
+       data->lcd_set_power(dev, 0);
+       tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+       data->lcd_mode(dev, mode);
+       data->lcd_set_power(dev, 1);
+
+       tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPN);
+       tmio_iowrite16(0, par->lcr + LCR_GDSAH);
+       tmio_iowrite16(0, par->lcr + LCR_GDSAL);
+       tmio_iowrite16(info->fix.line_length >> 16, par->lcr + LCR_VHPCH);
+       tmio_iowrite16(info->fix.line_length, par->lcr + LCR_VHPCL);
+       tmio_iowrite16(i = 0, par->lcr + LCR_HSS);
+       tmio_iowrite16(i += mode->hsync_len, par->lcr + LCR_HSE);
+       tmio_iowrite16(i += mode->left_margin, par->lcr + LCR_HDS);
+       tmio_iowrite16(i += mode->xres + mode->right_margin, par->lcr + LCR_HT);
+       tmio_iowrite16(mode->xres, par->lcr + LCR_HNP);
+       tmio_iowrite16(i = 0, par->lcr + LCR_VSS);
+       tmio_iowrite16(i += mode->vsync_len, par->lcr + LCR_VSE);
+       tmio_iowrite16(i += mode->upper_margin, par->lcr + LCR_VDS);
+       tmio_iowrite16(i += mode->yres, par->lcr + LCR_ILN);
+       tmio_iowrite16(i += mode->lower_margin, par->lcr + LCR_VT);
+       tmio_iowrite16(3, par->lcr + LCR_MISC); /* RGB565 mode */
+       tmio_iowrite16(1, par->lcr + LCR_GM); /* VRAM enable */
+       tmio_iowrite16(0x4007, par->lcr + LCR_LCDCC);
+       tmio_iowrite16(3, par->lcr + LCR_SP);  /* sync polarity */
+
+       tmio_iowrite16(0x0010, par->lcr + LCR_LCDCCRC);
+       msleep(5); /* wait for device to settle */
+       tmio_iowrite16(0x0014, par->lcr + LCR_LCDCCRC); /* STOP_CKP */
+       msleep(5); /* wait for device to settle */
+       tmio_iowrite16(0x0015, par->lcr + LCR_LCDCCRC); /* STOP_CKP|SOFT_RESET*/
+       tmio_iowrite16(0xfffa, par->lcr + LCR_VCS);
+}
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+static int __must_check
+tmiofb_acc_wait(struct fb_info *info, unsigned int ccs)
+{
+       struct tmiofb_par *par = info->par;
+       /*
+        * This code can be called whith interrupts disabled.
+        * So instead of relaying on irq to trigger the event,
+        * poll the state till the necessary command is executed.
+        */
+       if (irqs_disabled() || par->use_polling) {
+               int i = 0;
+               while (tmio_ioread16(par->lcr + LCR_CCS) > ccs) {
+                       udelay(1);
+                       i++;
+                       if (i > 10000) {
+                               pr_err("tmiofb: timeout waiting for %d\n",
+                                               ccs);
+                               return -ETIMEDOUT;
+                       }
+                       tmiofb_irq(-1, info);
+               }
+       } else {
+               if (!wait_event_interruptible_timeout(par->wait_acc,
+                               tmio_ioread16(par->lcr + LCR_CCS) <= ccs,
+                               1000)) {
+                       pr_err("tmiofb: timeout waiting for %d\n", ccs);
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Writes an accelerator command to the accelerator's FIFO.
+ */
+static int
+tmiofb_acc_write(struct fb_info *info, const u32 *cmd, unsigned int count)
+{
+       struct tmiofb_par *par = info->par;
+       int ret;
+
+       ret = tmiofb_acc_wait(info, TMIOFB_FIFO_SIZE - count);
+       if (ret)
+               return ret;
+
+       for (; count; count--, cmd++) {
+               tmio_iowrite16(*cmd >> 16, par->lcr + LCR_CMDH);
+               tmio_iowrite16(*cmd, par->lcr + LCR_CMDL);
+       }
+
+       return ret;
+}
+
+/*
+ * Wait for the accelerator to finish its operations before writing
+ * to the framebuffer for consistent display output.
+ */
+static int tmiofb_sync(struct fb_info *fbi)
+{
+       struct tmiofb_par *par = fbi->par;
+
+       int ret;
+       int i = 0;
+
+       ret = tmiofb_acc_wait(fbi, 0);
+
+       while (tmio_ioread16(par->lcr + LCR_BBES) & 2) { /* blit active */
+               udelay(1);
+               i++ ;
+               if (i > 10000) {
+                       printk(KERN_ERR "timeout waiting for blit to end!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return ret;
+}
+
+static void
+tmiofb_fillrect(struct fb_info *fbi, const struct fb_fillrect *rect)
+{
+       const u32 cmd[] = {
+               TMIOFB_ACC_DSADR((rect->dy * fbi->mode->xres + rect->dx) * 2),
+               TMIOFB_ACC_DHPIX(rect->width - 1),
+               TMIOFB_ACC_DVPIX(rect->height - 1),
+               TMIOFB_ACC_FILL(rect->color),
+               TMIOFB_ACC_FLGO,
+       };
+
+       if (fbi->state != FBINFO_STATE_RUNNING ||
+           fbi->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_fillrect(fbi, rect);
+               return;
+       }
+
+       tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+
+static void
+tmiofb_copyarea(struct fb_info *fbi, const struct fb_copyarea *area)
+{
+       const u32 cmd[] = {
+               TMIOFB_ACC_DSADR((area->dy * fbi->mode->xres + area->dx) * 2),
+               TMIOFB_ACC_DHPIX(area->width - 1),
+               TMIOFB_ACC_DVPIX(area->height - 1),
+               TMIOFB_ACC_SSADR((area->sy * fbi->mode->xres + area->sx) * 2),
+               TMIOFB_ACC_SCGO,
+       };
+
+       if (fbi->state != FBINFO_STATE_RUNNING ||
+           fbi->flags & FBINFO_HWACCEL_DISABLED) {
+               cfb_copyarea(fbi, area);
+               return;
+       }
+
+       tmiofb_acc_write(fbi, cmd, ARRAY_SIZE(cmd));
+}
+#endif
+
+static void tmiofb_clearscreen(struct fb_info *info)
+{
+       const struct fb_fillrect rect = {
+               .dx     = 0,
+               .dy     = 0,
+               .width  = info->mode->xres,
+               .height = info->mode->yres,
+               .color  = 0,
+               .rop    = ROP_COPY,
+       };
+
+       info->fbops->fb_fillrect(info, &rect);
+}
+
+static int tmiofb_vblank(struct fb_info *fbi, struct fb_vblank *vblank)
+{
+       struct tmiofb_par *par = fbi->par;
+       struct fb_videomode *mode = fbi->mode;
+       unsigned int vcount = tmio_ioread16(par->lcr + LCR_CDLN);
+       unsigned int vds = mode->vsync_len + mode->upper_margin;
+
+       vblank->vcount = vcount;
+       vblank->flags = FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_VCOUNT
+                                               | FB_VBLANK_HAVE_VSYNC;
+
+       if (vcount < mode->vsync_len)
+               vblank->flags |= FB_VBLANK_VSYNCING;
+
+       if (vcount < vds || vcount > vds + mode->yres)
+               vblank->flags |= FB_VBLANK_VBLANKING;
+
+       return 0;
+}
+
+
+static int tmiofb_ioctl(struct fb_info *fbi,
+               unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case FBIOGET_VBLANK: {
+               struct fb_vblank vblank = {0};
+               void __user *argp = (void __user *) arg;
+
+               tmiofb_vblank(fbi, &vblank);
+               if (copy_to_user(argp, &vblank, sizeof vblank))
+                       return -EFAULT;
+               return 0;
+       }
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+       case FBIO_TMIO_ACC_SYNC:
+               tmiofb_sync(fbi);
+               return 0;
+
+       case FBIO_TMIO_ACC_WRITE: {
+               u32 __user *argp = (void __user *) arg;
+               u32 len;
+               u32 acc[16];
+
+               if (get_user(len, argp))
+                       return -EFAULT;
+               if (len > ARRAY_SIZE(acc))
+                       return -EINVAL;
+               if (copy_from_user(acc, argp + 1, sizeof(u32) * len))
+                       return -EFAULT;
+
+               return tmiofb_acc_write(fbi, acc, len);
+       }
+#endif
+       }
+
+       return -ENOTTY;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/* Select the smallest mode that allows the desired resolution to be
+ * displayed.  If desired, the x and y parameters can be rounded up to
+ * match the selected mode.
+ */
+static struct fb_videomode *
+tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+       struct mfd_cell *cell =
+               info->device->platform_data;
+       struct tmio_fb_data *data = cell->driver_data;
+       struct fb_videomode *best = NULL;
+       int i;
+
+       for (i = 0; i < data->num_modes; i++) {
+               struct fb_videomode *mode = data->modes + i;
+
+               if (mode->xres >= var->xres && mode->yres >= var->yres
+                               && (!best || (mode->xres < best->xres
+                                          && mode->yres < best->yres)))
+                       best = mode;
+       }
+
+       return best;
+}
+
+static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+
+       struct fb_videomode *mode;
+       struct mfd_cell *cell =
+               info->device->platform_data;
+       struct tmio_fb_data *data = cell->driver_data;
+
+       mode = tmiofb_find_mode(info, var);
+       if (!mode || var->bits_per_pixel > 16)
+               return -EINVAL;
+
+       fb_videomode_to_var(var, mode);
+
+       var->xres_virtual = mode->xres;
+       var->yres_virtual = info->screen_size / (mode->xres * 2);
+
+       if (var->yres_virtual < var->yres)
+               return -EINVAL;
+
+       var->xoffset = 0;
+       var->yoffset = 0;
+       var->bits_per_pixel = 16;
+       var->grayscale = 0;
+       var->red.offset = 11;
+       var->red.length = 5;
+       var->green.offset = 5;
+       var->green.length = 6;
+       var->blue.offset = 0;
+       var->blue.length = 5;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       var->nonstd = 0;
+       var->height = data->height; /* mm */
+       var->width = data->width; /* mm */
+       var->rotate = 0;
+       return 0;
+}
+
+static int tmiofb_set_par(struct fb_info *info)
+{
+       struct fb_var_screeninfo *var = &info->var;
+       struct fb_videomode *mode;
+
+       mode = tmiofb_find_mode(info, var);
+       if (!mode)
+               return -EINVAL;
+
+       info->mode = mode;
+       info->fix.line_length = info->mode->xres *
+                       var->bits_per_pixel / 8;
+
+       tmiofb_hw_mode(to_platform_device(info->device));
+       tmiofb_clearscreen(info);
+       return 0;
+}
+
+static int tmiofb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       struct tmiofb_par *par = info->par;
+
+       if (regno < ARRAY_SIZE(par->pseudo_palette)) {
+               par->pseudo_palette[regno] =
+                       ((red & 0xf800)) |
+                       ((green & 0xfc00) >>  5) |
+                       ((blue & 0xf800) >> 11);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int tmiofb_blank(int blank, struct fb_info *info)
+{
+       /*
+        * everything is done in lcd/bl drivers.
+        * this is purely to make sysfs happy and work.
+        */
+       return 0;
+}
+
+static struct fb_ops tmiofb_ops = {
+       .owner          = THIS_MODULE,
+
+       .fb_ioctl       = tmiofb_ioctl,
+       .fb_check_var   = tmiofb_check_var,
+       .fb_set_par     = tmiofb_set_par,
+       .fb_setcolreg   = tmiofb_setcolreg,
+       .fb_blank       = tmiofb_blank,
+       .fb_imageblit   = cfb_imageblit,
+#ifdef CONFIG_FB_TMIO_ACCELL
+       .fb_sync        = tmiofb_sync,
+       .fb_fillrect    = tmiofb_fillrect,
+       .fb_copyarea    = tmiofb_copyarea,
+#else
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+#endif
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __devinit tmiofb_probe(struct platform_device *dev)
+{
+       struct mfd_cell *cell = dev->dev.platform_data;
+       struct tmio_fb_data *data = cell->driver_data;
+       struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
+       int irq = platform_get_irq(dev, 0);
+       struct fb_info *info;
+       struct tmiofb_par *par;
+       int retval;
+
+       /*
+        * This is the only way ATM to disable the fb
+        */
+       if (data == NULL) {
+               dev_err(&dev->dev, "NULL platform data!\n");
+               return -EINVAL;
+       }
+
+       info = framebuffer_alloc(sizeof(struct tmiofb_par), &dev->dev);
+
+       if (!info)
+               return -ENOMEM;
+
+       par = info->par;
+
+#ifdef CONFIG_FB_TMIO_ACCELL
+       init_waitqueue_head(&par->wait_acc);
+
+       par->use_polling = true;
+
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA
+                       | FBINFO_HWACCEL_FILLRECT;
+#else
+       info->flags = FBINFO_DEFAULT;
+#endif
+
+       info->fbops = &tmiofb_ops;
+
+       strcpy(info->fix.id, "tmio-fb");
+       info->fix.smem_start = vram->start;
+       info->fix.smem_len = resource_size(vram);
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.visual = FB_VISUAL_TRUECOLOR;
+       info->fix.mmio_start = lcr->start;
+       info->fix.mmio_len = resource_size(lcr);
+       info->fix.accel = FB_ACCEL_NONE;
+       info->screen_size = info->fix.smem_len - (4 * TMIOFB_FIFO_SIZE);
+       info->pseudo_palette = par->pseudo_palette;
+
+       par->ccr = ioremap(ccr->start, resource_size(ccr));
+       if (!par->ccr) {
+               retval = -ENOMEM;
+               goto err_ioremap_ccr;
+       }
+
+       par->lcr = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+       if (!par->lcr) {
+               retval = -ENOMEM;
+               goto err_ioremap_lcr;
+       }
+
+       info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+       if (!info->screen_base) {
+               retval = -ENOMEM;
+               goto err_ioremap_vram;
+       }
+
+       retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED,
+                                       dev->dev.bus_id, info);
+
+       if (retval)
+               goto err_request_irq;
+
+       platform_set_drvdata(dev, info);
+
+       retval = fb_find_mode(&info->var, info, mode_option,
+                       data->modes, data->num_modes,
+                       data->modes, 16);
+       if (!retval) {
+               retval = -EINVAL;
+               goto err_find_mode;
+       }
+
+       if (cell->enable) {
+               retval = cell->enable(dev);
+               if (retval)
+                       goto err_enable;
+       }
+
+       retval = tmiofb_hw_init(dev);
+       if (retval)
+               goto err_hw_init;
+
+       fb_videomode_to_modelist(data->modes, data->num_modes,
+                                &info->modelist);
+
+       retval = register_framebuffer(info);
+       if (retval < 0)
+               goto err_register_framebuffer;
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n",
+                               info->node, info->fix.id);
+
+       return 0;
+
+err_register_framebuffer:
+/*err_set_par:*/
+       tmiofb_hw_stop(dev);
+err_hw_init:
+       if (cell->disable)
+               cell->disable(dev);
+err_enable:
+err_find_mode:
+       platform_set_drvdata(dev, NULL);
+       free_irq(irq, info);
+err_request_irq:
+       iounmap(info->screen_base);
+err_ioremap_vram:
+       iounmap(par->lcr);
+err_ioremap_lcr:
+       iounmap(par->ccr);
+err_ioremap_ccr:
+       framebuffer_release(info);
+       return retval;
+}
+
+static int __devexit tmiofb_remove(struct platform_device *dev)
+{
+       struct mfd_cell *cell = dev->dev.platform_data;
+       struct fb_info *info = platform_get_drvdata(dev);
+       int irq = platform_get_irq(dev, 0);
+       struct tmiofb_par *par;
+
+       if (info) {
+               par = info->par;
+               unregister_framebuffer(info);
+
+               tmiofb_hw_stop(dev);
+
+               if (cell->disable)
+                       cell->disable(dev);
+
+               platform_set_drvdata(dev, NULL);
+
+               free_irq(irq, info);
+
+               iounmap(info->screen_base);
+               iounmap(par->lcr);
+               iounmap(par->ccr);
+
+               framebuffer_release(info);
+       }
+
+       return 0;
+}
+
+#ifdef DEBUG
+static void tmiofb_dump_regs(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct tmiofb_par *par = info->par;
+
+       printk(KERN_DEBUG "lhccr:\n");
+#define CCR_PR(n)      printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+               tmio_ioread16(par->ccr + CCR_ ## n));
+       CCR_PR(CMD);
+       CCR_PR(REVID);
+       CCR_PR(BASEL);
+       CCR_PR(BASEH);
+       CCR_PR(UGCC);
+       CCR_PR(GCC);
+       CCR_PR(USC);
+       CCR_PR(VRAMRTC);
+       CCR_PR(VRAMSAC);
+       CCR_PR(VRAMBC);
+#undef CCR_PR
+
+       printk(KERN_DEBUG "lcr: \n");
+#define LCR_PR(n)      printk(KERN_DEBUG "\t" #n " = \t%04x\n",\
+               tmio_ioread16(par->lcr + LCR_ ## n));
+       LCR_PR(UIS);
+       LCR_PR(VHPN);
+       LCR_PR(CFSAL);
+       LCR_PR(CFSAH);
+       LCR_PR(CFS);
+       LCR_PR(CFWS);
+       LCR_PR(BBIE);
+       LCR_PR(BBISC);
+       LCR_PR(CCS);
+       LCR_PR(BBES);
+       LCR_PR(CMDL);
+       LCR_PR(CMDH);
+       LCR_PR(CFC);
+       LCR_PR(CCIFC);
+       LCR_PR(HWT);
+       LCR_PR(LCDCCRC);
+       LCR_PR(LCDCC);
+       LCR_PR(LCDCOPC);
+       LCR_PR(LCDIS);
+       LCR_PR(LCDIM);
+       LCR_PR(LCDIE);
+       LCR_PR(GDSAL);
+       LCR_PR(GDSAH);
+       LCR_PR(VHPCL);
+       LCR_PR(VHPCH);
+       LCR_PR(GM);
+       LCR_PR(HT);
+       LCR_PR(HDS);
+       LCR_PR(HSS);
+       LCR_PR(HSE);
+       LCR_PR(HNP);
+       LCR_PR(VT);
+       LCR_PR(VDS);
+       LCR_PR(VSS);
+       LCR_PR(VSE);
+       LCR_PR(CDLN);
+       LCR_PR(ILN);
+       LCR_PR(SP);
+       LCR_PR(MISC);
+       LCR_PR(VIHSS);
+       LCR_PR(VIVS);
+       LCR_PR(VIVE);
+       LCR_PR(VIVSS);
+       LCR_PR(VCCIS);
+       LCR_PR(VIDWSAL);
+       LCR_PR(VIDWSAH);
+       LCR_PR(VIDRSAL);
+       LCR_PR(VIDRSAH);
+       LCR_PR(VIPDDST);
+       LCR_PR(VIPDDET);
+       LCR_PR(VIE);
+       LCR_PR(VCS);
+       LCR_PR(VPHWC);
+       LCR_PR(VPHS);
+       LCR_PR(VPVWC);
+       LCR_PR(VPVS);
+       LCR_PR(PLHPIX);
+       LCR_PR(XS);
+       LCR_PR(XCKHW);
+       LCR_PR(STHS);
+       LCR_PR(VT2);
+       LCR_PR(YCKSW);
+       LCR_PR(YSTS);
+       LCR_PR(PPOLS);
+       LCR_PR(PRECW);
+       LCR_PR(VCLKHW);
+       LCR_PR(OC);
+#undef LCR_PR
+}
+#endif
+
+#ifdef CONFIG_PM
+static int tmiofb_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct tmiofb_par *par = info->par;
+       struct mfd_cell *cell = dev->dev.platform_data;
+       int retval = 0;
+
+       acquire_console_sem();
+
+       fb_set_suspend(info, 1);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+
+       /*
+        * The fb should be usable even if interrupts are disabled (and they are
+        * during suspend/resume). Switch temporary to forced polling.
+        */
+       printk(KERN_INFO "tmiofb: switching to polling\n");
+       par->use_polling = true;
+       tmiofb_hw_stop(dev);
+
+       if (cell->suspend)
+               retval = cell->suspend(dev);
+
+       release_console_sem();
+
+       return retval;
+}
+
+static int tmiofb_resume(struct platform_device *dev)
+{
+       struct fb_info *info = platform_get_drvdata(dev);
+       struct mfd_cell *cell = dev->dev.platform_data;
+       int retval;
+
+       acquire_console_sem();
+
+       if (cell->resume) {
+               retval = cell->resume(dev);
+               if (retval)
+                       goto out;
+       }
+
+       tmiofb_irq(-1, info);
+
+       tmiofb_hw_init(dev);
+
+       tmiofb_hw_mode(dev);
+
+       fb_set_suspend(info, 0);
+out:
+       release_console_sem();
+       return retval;
+}
+#else
+#define tmiofb_suspend NULL
+#define tmiofb_resume  NULL
+#endif
+
+static struct platform_driver tmiofb_driver = {
+       .driver.name    = "tmio-fb",
+       .driver.owner   = THIS_MODULE,
+       .probe          = tmiofb_probe,
+       .remove         = __devexit_p(tmiofb_remove),
+       .suspend        = tmiofb_suspend,
+       .resume         = tmiofb_resume,
+};
+
+/*--------------------------------------------------------------------------*/
+
+#ifndef MODULE
+static void __init tmiofb_setup(char *options)
+{
+       char *this_opt;
+
+       if (!options || !*options)
+               return;
+
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               if (!*this_opt)
+                       continue;
+               /*
+                * FIXME
+                */
+       }
+}
+#endif
+
+static int __init tmiofb_init(void)
+{
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("tmiofb", &option))
+               return -ENODEV;
+       tmiofb_setup(option);
+#endif
+       return platform_driver_register(&tmiofb_driver);
+}
+
+static void __exit tmiofb_cleanup(void)
+{
+       platform_driver_unregister(&tmiofb_driver);
+}
+
+module_init(tmiofb_init);
+module_exit(tmiofb_cleanup);
+
+MODULE_DESCRIPTION("TMIO framebuffer driver");
+MODULE_AUTHOR("Chris Humbert, Dirk Opfer, Dmitry Baryshkov");
+MODULE_LICENSE("GPL");
index 50744229c7a947b2d7fc5dfff928664755232165..6c2d37fdd3b91c12beed0bc5de1aaed89f066454 100644 (file)
@@ -516,10 +516,12 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
 
                err = uvesafb_exec(task);
                if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
-                       printk(KERN_ERR "uvesafb: Getting mode info block "
+                       printk(KERN_WARNING "uvesafb: Getting mode info block "
                                "for mode 0x%x failed (eax=0x%x, err=%d)\n",
                                *mode, (u32)task->t.regs.eax, err);
-                       return -EINVAL;
+                       mode++;
+                       par->vbe_modes_cnt--;
+                       continue;
                }
 
                mib = task->buf;
@@ -548,7 +550,10 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
                        mib->depth = mib->bits_per_pixel;
        }
 
-       return 0;
+       if (par->vbe_modes_cnt > 0)
+               return 0;
+       else
+               return -EINVAL;
 }
 
 /*
index e31bca8a0cb2d8a5ecc6394c449bbc91f1705dc1..5b2938903ac2bee26df3de078d6b4106c97ca413 100644 (file)
@@ -58,7 +58,6 @@ struct vga16fb_par {
                unsigned char   ClockingMode;     /* Seq-Controller:01h */
        } vga_state;
        struct vgastate state;
-       struct mutex open_lock;
        unsigned int ref_count;
        int palette_blanked, vesa_blanked, mode, isVGA;
        u8 misc, pel_msk, vss, clkdiv;
@@ -286,7 +285,6 @@ static int vga16fb_open(struct fb_info *info, int user)
 {
        struct vga16fb_par *par = info->par;
 
-       mutex_lock(&par->open_lock);
        if (!par->ref_count) {
                memset(&par->state, 0, sizeof(struct vgastate));
                par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
@@ -294,7 +292,6 @@ static int vga16fb_open(struct fb_info *info, int user)
                save_vga(&par->state);
        }
        par->ref_count++;
-       mutex_unlock(&par->open_lock);
 
        return 0;
 }
@@ -303,15 +300,12 @@ static int vga16fb_release(struct fb_info *info, int user)
 {
        struct vga16fb_par *par = info->par;
 
-       mutex_lock(&par->open_lock);
-       if (!par->ref_count) {
-               mutex_unlock(&par->open_lock);
+       if (!par->ref_count)
                return -EINVAL;
-       }
+
        if (par->ref_count == 1)
                restore_vga(&par->state);
        par->ref_count--;
-       mutex_unlock(&par->open_lock);
 
        return 0;
 }
@@ -1326,7 +1320,6 @@ static int __init vga16fb_probe(struct platform_device *dev)
        printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
        par = info->par;
 
-       mutex_init(&par->open_lock);
        par->isVGA = screen_info.orig_video_isVGA;
        par->palette_blanked = 0;
        par->vesa_blanked = 0;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
new file mode 100644 (file)
index 0000000..e533b4b
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
+#
+
+obj-$(CONFIG_FB_VIA) += viafb.o
+
+viafb-y        :=viafbdev.o hw.o iface.o  via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c
new file mode 100644 (file)
index 0000000..632523f
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+void viafb_init_accel(void)
+{
+       viaparinfo->fbmem_free -= CURSOR_SIZE;
+       viaparinfo->cursor_start = viaparinfo->fbmem_free;
+       viaparinfo->fbmem_used += CURSOR_SIZE;
+
+       /* Reverse 8*1024 memory space for cursor image */
+       viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE);
+       viaparinfo->VQ_start = viaparinfo->fbmem_free;
+       viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1;
+       viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); }
+
+void viafb_init_2d_engine(void)
+{
+       u32 dwVQStartAddr, dwVQEndAddr;
+       u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
+
+       /* init 2D engine regs to reset 2D engine */
+       writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
+
+       /* Init AGP and VQ regs */
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_K8M890:
+       case UNICHROME_P4M900:
+               writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+               writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+               writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+               break;
+
+       default:
+               writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET);
+               writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+               writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET);
+               writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
+               break;
+       }
+       if (viaparinfo->VQ_start != 0) {
+               /* Enable VQ */
+               dwVQStartAddr = viaparinfo->VQ_start;
+               dwVQEndAddr = viaparinfo->VQ_end;
+
+               dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF);
+               dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF);
+               dwVQStartEndH = 0x52000000 |
+                       ((dwVQStartAddr & 0xFF000000) >> 24) |
+                       ((dwVQEndAddr & 0xFF000000) >> 16);
+               dwVQLen = 0x53000000 | (VQ_SIZE >> 3);
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M900:
+                       dwVQStartL |= 0x20000000;
+                       dwVQEndL |= 0x20000000;
+                       dwVQStartEndH |= 0x20000000;
+                       dwVQLen |= 0x20000000;
+                       break;
+               default:
+                       break;
+               }
+
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M900:
+                       writel(0x00100000,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+                       writel(dwVQStartEndH,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       writel(dwVQStartL,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       writel(dwVQEndL,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       writel(dwVQLen,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       writel(0x74301001,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       writel(0x00000000,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       break;
+               default:
+                       writel(0x00FE0000,
+                               viaparinfo->io_virt + VIA_REG_TRANSET);
+                       writel(0x080003FE,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0A00027C,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0B000260,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0C000274,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0D000264,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0E000000,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x0F000020,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x1000027E,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x110002FE,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x200F0060,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+                       writel(0x00000006,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x40008C0F,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x44000000,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x45080C04,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x46800408,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+
+                       writel(dwVQStartEndH,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(dwVQStartL,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(dwVQEndL,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(dwVQLen,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       break;
+               }
+       } else {
+               /* Disable VQ */
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M900:
+                       writel(0x00100000,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSET);
+                       writel(0x74301000,
+                               viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
+                       break;
+               default:
+                       writel(0x00FE0000,
+                               viaparinfo->io_virt + VIA_REG_TRANSET);
+                       writel(0x00000004,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x40008C0F,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x44000000,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x45080C04,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       writel(0x46800408,
+                               viaparinfo->io_virt + VIA_REG_TRANSPACE);
+                       break;
+               }
+       }
+
+       viafb_set_2d_color_depth(viaparinfo->bpp);
+
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
+
+       writel(VIA_PITCH_ENABLE |
+                  (((viaparinfo->hres *
+                     viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres *
+                                                  viaparinfo->
+                                                  bpp >> 3) >> 3) << 16)),
+                                       viaparinfo->io_virt + VIA_REG_PITCH);
+}
+
+void viafb_set_2d_color_depth(int bpp)
+{
+       u32 dwGEMode;
+
+       dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF;
+
+       switch (bpp) {
+       case 16:
+               dwGEMode |= VIA_GEM_16bpp;
+               break;
+       case 32:
+               dwGEMode |= VIA_GEM_32bpp;
+               break;
+       default:
+               dwGEMode |= VIA_GEM_8bpp;
+               break;
+       }
+
+       /* Set BPP and Pitch */
+       writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE);
+}
+
+void viafb_hw_cursor_init(void)
+{
+       /* Set Cursor Image Base Address */
+       writel(viaparinfo->cursor_start,
+               viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
+       writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
+}
+
+void viafb_show_hw_cursor(struct fb_info *info, int Status)
+{
+       u32 temp;
+       u32 iga_path = ((struct viafb_par *)(info->par))->iga_path;
+
+       temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+       switch (Status) {
+       case HW_Cursor_ON:
+               temp |= 0x1;
+               break;
+       case HW_Cursor_OFF:
+               temp &= 0xFFFFFFFE;
+               break;
+       }
+       switch (iga_path) {
+       case IGA2:
+               temp |= 0x80000000;
+               break;
+       case IGA1:
+       default:
+               temp &= 0x7FFFFFFF;
+       }
+       writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+}
+
+int viafb_wait_engine_idle(void)
+{
+       int loop = 0;
+
+       while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) &
+                       VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP))
+               cpu_relax();
+
+       while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) &
+                   (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
+                   (loop++ < MAXLOOP))
+               cpu_relax();
+
+       return loop >= MAXLOOP;
+}
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h
new file mode 100644 (file)
index 0000000..29bf854
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __ACCEL_H__
+#define __ACCEL_H__
+
+#define FB_ACCEL_VIA_UNICHROME  50
+
+/* MMIO Base Address Definition */
+#define MMIO_VGABASE                0x8000
+#define MMIO_CR_READ                (MMIO_VGABASE + 0x3D4)
+#define MMIO_CR_WRITE               (MMIO_VGABASE + 0x3D5)
+#define MMIO_SR_READ                (MMIO_VGABASE + 0x3C4)
+#define MMIO_SR_WRITE               (MMIO_VGABASE + 0x3C5)
+
+/* HW Cursor Status Define */
+#define HW_Cursor_ON    0
+#define HW_Cursor_OFF   1
+
+#define CURSOR_SIZE     (8 * 1024)
+#define VQ_SIZE         (256 * 1024)
+
+#define VIA_MMIO_BLTBASE        0x200000
+#define VIA_MMIO_BLTSIZE        0x200000
+
+/* Defines for 2D registers */
+#define VIA_REG_GECMD           0x000
+#define VIA_REG_GEMODE          0x004
+#define VIA_REG_SRCPOS          0x008
+#define VIA_REG_DSTPOS          0x00C
+/* width and height */
+#define VIA_REG_DIMENSION       0x010
+#define VIA_REG_PATADDR         0x014
+#define VIA_REG_FGCOLOR         0x018
+#define VIA_REG_BGCOLOR         0x01C
+/* top and left of clipping */
+#define VIA_REG_CLIPTL          0x020
+/* bottom and right of clipping */
+#define VIA_REG_CLIPBR          0x024
+#define VIA_REG_OFFSET          0x028
+/* color key control */
+#define VIA_REG_KEYCONTROL      0x02C
+#define VIA_REG_SRCBASE         0x030
+#define VIA_REG_DSTBASE         0x034
+/* pitch of src and dst */
+#define VIA_REG_PITCH           0x038
+#define VIA_REG_MONOPAT0        0x03C
+#define VIA_REG_MONOPAT1        0x040
+/* from 0x100 to 0x1ff */
+#define VIA_REG_COLORPAT        0x100
+
+/* VIA_REG_PITCH(0x38): Pitch Setting */
+#define VIA_PITCH_ENABLE        0x80000000
+
+/* defines for VIA HW cursor registers */
+#define VIA_REG_CURSOR_MODE     0x2D0
+#define VIA_REG_CURSOR_POS      0x2D4
+#define VIA_REG_CURSOR_ORG      0x2D8
+#define VIA_REG_CURSOR_BG       0x2DC
+#define VIA_REG_CURSOR_FG       0x2E0
+
+/* VIA_REG_GEMODE(0x04): GE mode */
+#define VIA_GEM_8bpp            0x00000000
+#define VIA_GEM_16bpp           0x00000100
+#define VIA_GEM_32bpp           0x00000300
+
+/* VIA_REG_GECMD(0x00): 2D Engine Command  */
+#define VIA_GEC_NOOP            0x00000000
+#define VIA_GEC_BLT             0x00000001
+#define VIA_GEC_LINE            0x00000005
+
+/* Rotate Command */
+#define VIA_GEC_ROT             0x00000008
+
+#define VIA_GEC_SRC_XY          0x00000000
+#define VIA_GEC_SRC_LINEAR      0x00000010
+#define VIA_GEC_DST_XY          0x00000000
+#define VIA_GEC_DST_LINRAT      0x00000020
+
+#define VIA_GEC_SRC_FB          0x00000000
+#define VIA_GEC_SRC_SYS         0x00000040
+#define VIA_GEC_DST_FB          0x00000000
+#define VIA_GEC_DST_SYS         0x00000080
+
+/* source is mono */
+#define VIA_GEC_SRC_MONO        0x00000100
+/* pattern is mono */
+#define VIA_GEC_PAT_MONO        0x00000200
+/* mono src is opaque */
+#define VIA_GEC_MSRC_OPAQUE     0x00000000
+/* mono src is transparent */
+#define VIA_GEC_MSRC_TRANS      0x00000400
+/* pattern is in frame buffer */
+#define VIA_GEC_PAT_FB          0x00000000
+/* pattern is from reg setting */
+#define VIA_GEC_PAT_REG         0x00000800
+
+#define VIA_GEC_CLIP_DISABLE    0x00000000
+#define VIA_GEC_CLIP_ENABLE     0x00001000
+
+#define VIA_GEC_FIXCOLOR_PAT    0x00002000
+
+#define VIA_GEC_INCX            0x00000000
+#define VIA_GEC_DECY            0x00004000
+#define VIA_GEC_INCY            0x00000000
+#define VIA_GEC_DECX            0x00008000
+/* mono pattern is opaque */
+#define VIA_GEC_MPAT_OPAQUE     0x00000000
+/* mono pattern is transparent */
+#define VIA_GEC_MPAT_TRANS      0x00010000
+
+#define VIA_GEC_MONO_UNPACK     0x00000000
+#define VIA_GEC_MONO_PACK       0x00020000
+#define VIA_GEC_MONO_DWORD      0x00000000
+#define VIA_GEC_MONO_WORD       0x00040000
+#define VIA_GEC_MONO_BYTE       0x00080000
+
+#define VIA_GEC_LASTPIXEL_ON    0x00000000
+#define VIA_GEC_LASTPIXEL_OFF   0x00100000
+#define VIA_GEC_X_MAJOR         0x00000000
+#define VIA_GEC_Y_MAJOR         0x00200000
+#define VIA_GEC_QUICK_START     0x00800000
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS          0x400
+#define VIA_REG_CR_TRANSET      0x41C
+#define VIA_REG_CR_TRANSPACE   0x420
+#define VIA_REG_TRANSET         0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+
+/* Command Regulator is busy */
+#define VIA_CMD_RGTR_BUSY       0x00000080
+/* 2D Engine is busy */
+#define VIA_2D_ENG_BUSY         0x00000002
+/* 3D Engine is busy */
+#define VIA_3D_ENG_BUSY         0x00000001
+/* Virtual Queue is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000
+
+#define MAXLOOP                 0xFFFFFF
+
+void viafb_init_accel(void);
+void viafb_init_2d_engine(void);
+void set_2d_color_depth(int);
+void viafb_hw_cursor_init(void);
+void viafb_show_hw_cursor(struct fb_info *info, int Status); int
+viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp);
+
+#endif /* __ACCEL_H__ */
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
new file mode 100644 (file)
index 0000000..dde95ed
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __CHIP_H__
+#define __CHIP_H__
+
+#include "global.h"
+
+/***************************************/
+/* Definition Graphic Chip Information */
+/***************************************/
+
+#define     PCI_VIA_VENDOR_ID       0x1106
+
+/* Define VIA Graphic Chip Name */
+#define     UNICHROME_CLE266        1
+#define     UNICHROME_CLE266_DID    0x3122
+#define     CLE266_REVISION_AX      0x0A
+#define     CLE266_REVISION_CX      0x0C
+
+#define     UNICHROME_K400          2
+#define     UNICHROME_K400_DID      0x7205
+
+#define     UNICHROME_K800          3
+#define     UNICHROME_K800_DID      0x3108
+
+#define     UNICHROME_PM800         4
+#define     UNICHROME_PM800_DID     0x3118
+
+#define     UNICHROME_CN700         5
+#define     UNICHROME_CN700_DID     0x3344
+
+#define     UNICHROME_CX700         6
+#define     UNICHROME_CX700_DID     0x3157
+#define     CX700_REVISION_700      0x0
+#define     CX700_REVISION_700M     0x1
+#define     CX700_REVISION_700M2    0x2
+
+#define     UNICHROME_CN750         7
+#define     UNICHROME_CN750_DID     0x3225
+
+#define     UNICHROME_K8M890        8
+#define     UNICHROME_K8M890_DID    0x3230
+
+#define     UNICHROME_P4M890        9
+#define     UNICHROME_P4M890_DID    0x3343
+
+#define     UNICHROME_P4M900        10
+#define     UNICHROME_P4M900_DID    0x3371
+
+#define     UNICHROME_VX800         11
+#define     UNICHROME_VX800_DID     0x1122
+
+/**************************************************/
+/* Definition TMDS Trasmitter Information         */
+/**************************************************/
+
+/* Definition TMDS Trasmitter Index */
+#define     NON_TMDS_TRANSMITTER    0x00
+#define     VT1632_TMDS             0x01
+#define     INTEGRATED_TMDS         0x42
+
+/* Definition TMDS Trasmitter I2C Slave Address */
+#define     VT1632_TMDS_I2C_ADDR    0x10
+
+/**************************************************/
+/* Definition LVDS Trasmitter Information         */
+/**************************************************/
+
+/* Definition LVDS Trasmitter Index */
+#define     NON_LVDS_TRANSMITTER    0x00
+#define     VT1631_LVDS             0x01
+#define     VT1636_LVDS             0x0E
+#define     INTEGRATED_LVDS         0x41
+
+/* Definition Digital Transmitter Mode */
+#define     TX_DATA_12_BITS         0x01
+#define     TX_DATA_24_BITS         0x02
+#define     TX_DATA_DDR_MODE        0x04
+#define     TX_DATA_SDR_MODE        0x08
+
+/* Definition LVDS Trasmitter I2C Slave Address */
+#define     VT1631_LVDS_I2C_ADDR    0x70
+#define     VT3271_LVDS_I2C_ADDR    0x80
+#define     VT1636_LVDS_I2C_ADDR    0x80
+
+struct tmds_chip_information {
+       int tmds_chip_name;
+       int tmds_chip_slave_addr;
+       int dvi_panel_id;
+       int data_mode;
+       int output_interface;
+       int i2c_port;
+       int device_type;
+};
+
+struct lvds_chip_information {
+       int lvds_chip_name;
+       int lvds_chip_slave_addr;
+       int data_mode;
+       int output_interface;
+       int i2c_port;
+};
+
+struct chip_information {
+       int gfx_chip_name;
+       int gfx_chip_revision;
+       int chip_on_slot;
+       struct tmds_chip_information tmds_chip_info;
+       struct lvds_chip_information lvds_chip_info;
+       struct lvds_chip_information lvds_chip_info2;
+};
+
+struct crt_setting_information {
+       int iga_path;
+       int h_active;
+       int v_active;
+       int bpp;
+       int refresh_rate;
+};
+
+struct tmds_setting_information {
+       int iga_path;
+       int h_active;
+       int v_active;
+       int bpp;
+       int refresh_rate;
+       int get_dvi_size_method;
+       int max_pixel_clock;
+       int dvi_panel_size;
+       int dvi_panel_hres;
+       int dvi_panel_vres;
+       int native_size;
+};
+
+struct lvds_setting_information {
+       int iga_path;
+       int h_active;
+       int v_active;
+       int bpp;
+       int refresh_rate;
+       int get_lcd_size_method;
+       int lcd_panel_id;
+       int lcd_panel_size;
+       int lcd_panel_hres;
+       int lcd_panel_vres;
+       int display_method;
+       int device_lcd_dualedge;
+       int LCDDithering;
+       int lcd_mode;
+       u32 vclk;               /*panel mode clock value */
+};
+
+struct GFX_DPA_SETTING {
+       int ClkRangeIndex;
+       u8 DVP0;                /* CR96[3:0] */
+       u8 DVP0DataDri_S1;      /* SR2A[5]   */
+       u8 DVP0DataDri_S;       /* SR1B[1]   */
+       u8 DVP0ClockDri_S1;     /* SR2A[4]   */
+       u8 DVP0ClockDri_S;      /* SR1E[2]   */
+       u8 DVP1;                /* CR9B[3:0] */
+       u8 DVP1Driving;         /* SR65[3:0], Data and Clock driving */
+       u8 DFPHigh;             /* CR97[3:0] */
+       u8 DFPLow;              /* CR99[3:0] */
+
+};
+
+struct VT1636_DPA_SETTING {
+       int PanelSizeID;
+       u8 CLK_SEL_ST1;
+       u8 CLK_SEL_ST2;
+};
+#endif /* __CHIP_H__ */
diff --git a/drivers/video/via/debug.h b/drivers/video/via/debug.h
new file mode 100644 (file)
index 0000000..86eacc2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __DEBUG_H__
+#define __DEBUG_H__
+
+#ifndef VIAFB_DEBUG
+#define VIAFB_DEBUG 0
+#endif
+
+#if VIAFB_DEBUG
+#define DEBUG_MSG(f, a...)   printk(f, ## a)
+#else
+#define DEBUG_MSG(f, a...)
+#endif
+
+#define VIAFB_WARN 0
+#if VIAFB_WARN
+#define WARN_MSG(f, a...)   printk(f, ## a)
+#else
+#define WARN_MSG(f, a...)
+#endif
+
+#endif /* __DEBUG_H__ */
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
new file mode 100644 (file)
index 0000000..d696544
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+static void tmds_register_write(int index, u8 data);
+static int tmds_register_read(int index);
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
+static int check_reduce_blanking_mode(int mode_index,
+       int refresh_rate);
+static int dvi_get_panel_size_from_DDCv1(void);
+static int dvi_get_panel_size_from_DDCv2(void);
+static unsigned char dvi_get_panel_info(void);
+static int viafb_dvi_query_EDID(void);
+
+static int check_tmds_chip(int device_id_subaddr, int device_id)
+{
+       if (tmds_register_read(device_id_subaddr) == device_id)
+               return OK;
+       else
+               return FAIL;
+}
+
+void viafb_init_dvi_size(void)
+{
+       DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
+       DEBUG_MSG(KERN_INFO
+               "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
+                 viaparinfo->tmds_setting_info->get_dvi_size_method);
+
+       switch (viaparinfo->tmds_setting_info->get_dvi_size_method) {
+       case GET_DVI_SIZE_BY_SYSTEM_BIOS:
+               break;
+       case GET_DVI_SZIE_BY_HW_STRAPPING:
+               break;
+       case GET_DVI_SIZE_BY_VGA_BIOS:
+       default:
+               dvi_get_panel_info();
+               break;
+       }
+       return;
+}
+
+int viafb_tmds_trasmitter_identify(void)
+{
+       unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
+
+       /* Turn on ouputting pad */
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_K8M890:
+           /*=* DFP Low Pad on *=*/
+               sr2a = viafb_read_reg(VIASR, SR2A);
+               viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+               break;
+
+       case UNICHROME_P4M900:
+       case UNICHROME_P4M890:
+               /* DFP Low Pad on */
+               sr2a = viafb_read_reg(VIASR, SR2A);
+               viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+               /* DVP0 Pad on */
+               sr1e = viafb_read_reg(VIASR, SR1E);
+               viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
+               break;
+
+       default:
+           /* DVP0/DVP1 Pad on */
+               sr1e = viafb_read_reg(VIASR, SR1E);
+               viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
+                       BIT5 + BIT6 + BIT7);
+           /* SR3E[1]Multi-function selection:
+           0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+               sr3e = viafb_read_reg(VIASR, SR3E);
+               viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
+               break;
+       }
+
+       /* Check for VT1632: */
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
+       viaparinfo->chip_info->
+               tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+       viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX;
+       if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
+               /*
+                * Currently only support 12bits,dual edge,add 24bits mode later
+                */
+               tmds_register_write(0x08, 0x3b);
+
+               DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+               DEBUG_MSG(KERN_INFO "\n %2d",
+                         viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+               DEBUG_MSG(KERN_INFO "\n %2d",
+                         viaparinfo->chip_info->tmds_chip_info.i2c_port);
+               return OK;
+       } else {
+               viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX;
+               if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
+                   != FAIL) {
+                       tmds_register_write(0x08, 0x3b);
+                       DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
+                       DEBUG_MSG(KERN_INFO "\n %2d",
+                                 viaparinfo->chip_info->
+                                 tmds_chip_info.tmds_chip_name);
+                       DEBUG_MSG(KERN_INFO "\n %2d",
+                                 viaparinfo->chip_info->
+                                 tmds_chip_info.i2c_port);
+                       return OK;
+               }
+       }
+
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
+
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
+           ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
+            (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
+               DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
+               return OK;
+       }
+
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_K8M890:
+               viafb_write_reg(SR2A, VIASR, sr2a);
+               break;
+
+       case UNICHROME_P4M900:
+       case UNICHROME_P4M890:
+               viafb_write_reg(SR2A, VIASR, sr2a);
+               viafb_write_reg(SR1E, VIASR, sr1e);
+               break;
+
+       default:
+               viafb_write_reg(SR1E, VIASR, sr1e);
+               viafb_write_reg(SR3E, VIASR, sr3e);
+               break;
+       }
+
+       viaparinfo->chip_info->
+               tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
+       viaparinfo->chip_info->tmds_chip_info.
+               tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
+       return FAIL;
+}
+
+static void tmds_register_write(int index, u8 data)
+{
+       viaparinfo->i2c_stuff.i2c_port =
+               viaparinfo->chip_info->tmds_chip_info.i2c_port;
+
+       viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
+               tmds_chip_slave_addr, index,
+                    data);
+}
+
+static int tmds_register_read(int index)
+{
+       u8 data;
+
+       viaparinfo->i2c_stuff.i2c_port =
+               viaparinfo->chip_info->tmds_chip_info.i2c_port;
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->
+           tmds_chip_info.tmds_chip_slave_addr,
+                       (u8) index, &data);
+       return data;
+}
+
+static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
+{
+       viaparinfo->i2c_stuff.i2c_port =
+               viaparinfo->chip_info->tmds_chip_info.i2c_port;
+       viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
+                        tmds_chip_slave_addr, (u8) index, buff, buff_len);
+       return 0;
+}
+
+static int check_reduce_blanking_mode(int mode_index,
+       int refresh_rate)
+{
+       if (refresh_rate != 60)
+               return false;
+
+       switch (mode_index) {
+               /* Following modes have reduce blanking mode. */
+       case VIA_RES_1360X768:
+       case VIA_RES_1400X1050:
+       case VIA_RES_1440X900:
+       case VIA_RES_1600X900:
+       case VIA_RES_1680X1050:
+       case VIA_RES_1920X1080:
+       case VIA_RES_1920X1200:
+               break;
+
+       default:
+               DEBUG_MSG(KERN_INFO
+                         "This dvi mode %d have no reduce blanking mode!\n",
+                         mode_index);
+               return false;
+       }
+
+       return true;
+}
+
+/* DVI Set Mode */
+void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
+{
+       struct VideoModeTable *videoMode = NULL;
+       struct crt_mode_table *pDviTiming;
+       unsigned long desirePixelClock, maxPixelClock;
+       int status = 0;
+       videoMode = viafb_get_modetbl_pointer(video_index);
+       pDviTiming = videoMode->crtc;
+       desirePixelClock = pDviTiming->clk / 1000000;
+       maxPixelClock = (unsigned long)viaparinfo->
+               tmds_setting_info->max_pixel_clock;
+
+       DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
+
+       if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
+               /*Check if reduce-blanking mode is exist */
+               status =
+                   check_reduce_blanking_mode(video_index,
+                                              pDviTiming->refresh_rate);
+               if (status) {
+                       video_index += 100;     /*Use reduce-blanking mode */
+                       videoMode = viafb_get_modetbl_pointer(video_index);
+                       pDviTiming = videoMode->crtc;
+                       DEBUG_MSG(KERN_INFO
+                                 "DVI use reduce blanking mode %d!!\n",
+                                 video_index);
+               }
+       }
+       viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga);
+       viafb_set_output_path(DEVICE_DVI, set_iga,
+                       viaparinfo->chip_info->tmds_chip_info.output_interface);
+}
+
+/* Sense DVI Connector */
+int viafb_dvi_sense(void)
+{
+       u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
+               RegCR93 = 0, RegCR9B = 0, data;
+       int ret = false;
+
+       DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
+
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               /* DI1 Pad on */
+               RegSR1E = viafb_read_reg(VIASR, SR1E);
+               viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
+
+               /* CR6B[0]VCK Input Selection: 1 = External clock. */
+               RegCR6B = viafb_read_reg(VIACR, CR6B);
+               viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
+
+               /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+                  [0] Software Control Power Sequence */
+               RegCR91 = viafb_read_reg(VIACR, CR91);
+               viafb_write_reg(CR91, VIACR, 0x1D);
+
+               /* CR93[7] DI1 Data Source Selection: 1 = DSP2.
+                  CR93[5] DI1 Clock Source: 1 = internal.
+                  CR93[4] DI1 Clock Polarity.
+                  CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
+               RegCR93 = viafb_read_reg(VIACR, CR93);
+               viafb_write_reg(CR93, VIACR, 0x01);
+       } else {
+               /* DVP0/DVP1 Pad on */
+               RegSR1E = viafb_read_reg(VIASR, SR1E);
+               viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
+
+               /* SR3E[1]Multi-function selection:
+                  0 = Emulate I2C and DDC bus by GPIO2/3/4. */
+               RegSR3E = viafb_read_reg(VIASR, SR3E);
+               viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
+
+               /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
+                  [0] Software Control Power Sequence */
+               RegCR91 = viafb_read_reg(VIACR, CR91);
+               viafb_write_reg(CR91, VIACR, 0x1D);
+
+               /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
+               display.CR9B[2:0] DVP1 Clock Adjust */
+               RegCR9B = viafb_read_reg(VIACR, CR9B);
+               viafb_write_reg(CR9B, VIACR, 0x01);
+       }
+
+       data = (u8) tmds_register_read(0x09);
+       if (data & 0x04)
+               ret = true;
+
+       if (ret == false) {
+               if (viafb_dvi_query_EDID())
+                       ret = true;
+       }
+
+       /* Restore status */
+       viafb_write_reg(SR1E, VIASR, RegSR1E);
+       viafb_write_reg(CR91, VIACR, RegCR91);
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               viafb_write_reg(CR6B, VIACR, RegCR6B);
+               viafb_write_reg(CR93, VIACR, RegCR93);
+       } else {
+               viafb_write_reg(SR3E, VIASR, RegSR3E);
+               viafb_write_reg(CR9B, VIACR, RegCR9B);
+       }
+
+       return ret;
+}
+
+/* Query Flat Panel's EDID Table Version Through DVI Connector */
+static int viafb_dvi_query_EDID(void)
+{
+       u8 data0, data1;
+       int restore;
+
+       DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
+
+       restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+
+       data0 = (u8) tmds_register_read(0x00);
+       data1 = (u8) tmds_register_read(0x01);
+       if ((data0 == 0) && (data1 == 0xFF)) {
+               viaparinfo->chip_info->
+                       tmds_chip_info.tmds_chip_slave_addr = restore;
+               return EDID_VERSION_1;  /* Found EDID1 Table */
+       }
+
+       data0 = (u8) tmds_register_read(0x00);
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+       if (data0 == 0x20)
+               return EDID_VERSION_2;  /* Found EDID2 Table */
+       else
+               return false;
+}
+
+/*
+ *
+ * int dvi_get_panel_size_from_DDCv1(void)
+ *
+ *     - Get Panel Size Using EDID1 Table
+ *
+ * Return Type:    int
+ *
+ */
+static int dvi_get_panel_size_from_DDCv1(void)
+{
+       int i, max_h = 0, max_v = 0, tmp, restore;
+       unsigned char rData;
+       unsigned char EDID_DATA[18];
+
+       DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
+
+       restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+
+       rData = tmds_register_read(0x23);
+       if (rData & 0x3C)
+               max_h = 640;
+       if (rData & 0xC0)
+               max_h = 720;
+       if (rData & 0x03)
+               max_h = 800;
+
+       rData = tmds_register_read(0x24);
+       if (rData & 0xC0)
+               max_h = 800;
+       if (rData & 0x1E)
+               max_h = 1024;
+       if (rData & 0x01)
+               max_h = 1280;
+
+       for (i = 0x25; i < 0x6D; i++) {
+               switch (i) {
+               case 0x26:
+               case 0x28:
+               case 0x2A:
+               case 0x2C:
+               case 0x2E:
+               case 0x30:
+               case 0x32:
+               case 0x34:
+                       rData = tmds_register_read(i);
+                       if (rData == 1)
+                               break;
+                       /* data = (data + 31) * 8 */
+                       tmp = (rData + 31) << 3;
+                       if (tmp > max_h)
+                               max_h = tmp;
+                       break;
+
+               case 0x36:
+               case 0x48:
+               case 0x5A:
+               case 0x6C:
+                       tmds_register_read_bytes(i, EDID_DATA, 10);
+                       if (!(EDID_DATA[0] || EDID_DATA[1])) {
+                               /* The first two byte must be zero. */
+                               if (EDID_DATA[3] == 0xFD) {
+                                       /* To get max pixel clock. */
+                                       viaparinfo->tmds_setting_info->
+                                       max_pixel_clock = EDID_DATA[9] * 10;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       switch (max_h) {
+       case 640:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_640X480;
+               break;
+       case 800:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_800X600;
+               break;
+       case 1024:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1024X768;
+               break;
+       case 1280:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1280X1024;
+               break;
+       case 1400:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1400X1050;
+               break;
+       case 1440:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1440X1050;
+               break;
+       case 1600:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1600X1200;
+               break;
+       case 1920:
+               if (max_v == 1200) {
+                       viaparinfo->tmds_setting_info->dvi_panel_size =
+                               VIA_RES_1920X1200;
+               } else {
+                       viaparinfo->tmds_setting_info->dvi_panel_size =
+                               VIA_RES_1920X1080;
+               }
+
+               break;
+       default:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1024X768;
+               DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\
+                                        set default panel size.\n", max_h);
+               break;
+       }
+
+       DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
+                 viaparinfo->tmds_setting_info->max_pixel_clock);
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+       return viaparinfo->tmds_setting_info->dvi_panel_size;
+}
+
+/*
+ *
+ * int dvi_get_panel_size_from_DDCv2(void)
+ *
+ *     - Get Panel Size Using EDID2 Table
+ *
+ * Return Type:    int
+ *
+ */
+static int dvi_get_panel_size_from_DDCv2(void)
+{
+       int HSize = 0, restore;
+       unsigned char R_Buffer[2];
+
+       DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
+
+       restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2;
+
+       /* Horizontal: 0x76, 0x77 */
+       tmds_register_read_bytes(0x76, R_Buffer, 2);
+       HSize = R_Buffer[0];
+       HSize += R_Buffer[1] << 8;
+
+       switch (HSize) {
+       case 640:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_640X480;
+               break;
+       case 800:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_800X600;
+               break;
+       case 1024:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1024X768;
+               break;
+       case 1280:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1280X1024;
+               break;
+       case 1400:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1400X1050;
+               break;
+       case 1440:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1440X1050;
+               break;
+       case 1600:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1600X1200;
+               break;
+       default:
+               viaparinfo->tmds_setting_info->dvi_panel_size =
+                       VIA_RES_1024X768;
+               DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\
+                                       set default panel size.\n", HSize);
+               break;
+       }
+
+       viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
+       return viaparinfo->tmds_setting_info->dvi_panel_size;
+}
+
+/*
+ *
+ * unsigned char dvi_get_panel_info(void)
+ *
+ *     - Get Panel Size
+ *
+ * Return Type:    unsigned char
+ */
+static unsigned char dvi_get_panel_info(void)
+{
+       unsigned char dvipanelsize;
+       DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
+
+       viafb_dvi_sense();
+       switch (viafb_dvi_query_EDID()) {
+       case 1:
+               dvi_get_panel_size_from_DDCv1();
+               break;
+       case 2:
+               dvi_get_panel_size_from_DDCv2();
+               break;
+       default:
+               break;
+       }
+
+       DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n",
+                 viaparinfo->tmds_setting_info->dvi_panel_size);
+       dvipanelsize = (unsigned char)(viaparinfo->
+               tmds_setting_info->dvi_panel_size);
+       return dvipanelsize;
+}
+
+/* If Disable DVI, turn off pad */
+void viafb_dvi_disable(void)
+{
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DVP0)
+               viafb_write_reg(SR1E, VIASR,
+               viafb_read_reg(VIASR, SR1E) & (~0xC0));
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DVP1)
+               viafb_write_reg(SR1E, VIASR,
+               viafb_read_reg(VIASR, SR1E) & (~0x30));
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
+               viafb_write_reg(SR2A, VIASR,
+               viafb_read_reg(VIASR, SR2A) & (~0x0C));
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
+               viafb_write_reg(SR2A, VIASR,
+               viafb_read_reg(VIASR, SR2A) & (~0x03));
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_TMDS)
+               /* Turn off TMDS power. */
+               viafb_write_reg(CRD2, VIACR,
+               viafb_read_reg(VIACR, CRD2) | 0x08);
+}
+
+/* If Enable DVI, turn off pad */
+void viafb_dvi_enable(void)
+{
+       u8 data;
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DVP0) {
+               viafb_write_reg(SR1E, VIASR,
+                       viafb_read_reg(VIASR, SR1E) | 0xC0);
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+                       tmds_register_write(0x88, 0x3b);
+               else
+                       /*clear CR91[5] to direct on display period
+                          in the secondary diplay path */
+                       viafb_write_reg(CR91, VIACR,
+                       viafb_read_reg(VIACR, CR91) & 0xDF);
+       }
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DVP1) {
+               viafb_write_reg(SR1E, VIASR,
+                       viafb_read_reg(VIASR, SR1E) | 0x30);
+
+               /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+                       tmds_register_write(0x88, 0x3b);
+               } else {
+                       /*clear CR91[5] to direct on display period
+                         in the secondary diplay path */
+                       viafb_write_reg(CR91, VIACR,
+                       viafb_read_reg(VIACR, CR91) & 0xDF);
+               }
+
+               /*fix DVI cannot enable on EPIA-M board */
+               if (viafb_platform_epia_dvi == 1) {
+                       viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
+                       viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
+                       if (viafb_bus_width == 24) {
+                               if (viafb_device_lcd_dualedge == 1)
+                                       data = 0x3F;
+                               else
+                                       data = 0x37;
+                               viafb_i2c_writebyte(viaparinfo->chip_info->
+                                            tmds_chip_info.
+                                            tmds_chip_slave_addr,
+                                            0x08, data);
+                       }
+               }
+       }
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
+               viafb_write_reg(SR2A, VIASR,
+                       viafb_read_reg(VIASR, SR2A) | 0x0C);
+               viafb_write_reg(CR91, VIACR,
+                       viafb_read_reg(VIACR, CR91) & 0xDF);
+       }
+
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
+               viafb_write_reg(SR2A, VIASR,
+                       viafb_read_reg(VIASR, SR2A) | 0x03);
+               viafb_write_reg(CR91, VIACR,
+                       viafb_read_reg(VIACR, CR91) & 0xDF);
+       }
+       if (viaparinfo->chip_info->
+               tmds_chip_info.output_interface == INTERFACE_TMDS) {
+               /* Turn on Display period in the panel path. */
+               viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
+
+               /* Turn on TMDS power. */
+               viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
+       }
+}
+
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
new file mode 100644 (file)
index 0000000..e1ec37f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __DVI_H__
+#define __DVI_H__
+
+/*Definition TMDS Device ID register*/
+#define     VT1632_DEVICE_ID_REG        0x02
+#define     VT1632_DEVICE_ID            0x92
+
+#define     GET_DVI_SIZE_BY_SYSTEM_BIOS     0x01
+#define     GET_DVI_SIZE_BY_VGA_BIOS        0x02
+#define     GET_DVI_SZIE_BY_HW_STRAPPING    0x03
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480,   Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID0_640X480       0x00
+/* Resolution: 800x600,   Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_800x600       0x01
+/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_1024x768      0x02
+/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
+#define     DVI_PANEL_ID1_1280x768      0x03
+/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1280x1024     0x04
+/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1400x1050     0x05
+/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
+#define     DVI_PANEL_ID1_1600x1200     0x06
+
+/* Define the version of EDID*/
+#define     EDID_VERSION_1      1
+#define     EDID_VERSION_2      2
+
+#define     DEV_CONNECT_DVI     0x01
+#define     DEV_CONNECT_HDMI    0x02
+
+struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
+int viafb_dvi_sense(void);
+void viafb_dvi_disable(void);
+void viafb_dvi_enable(void);
+int viafb_tmds_trasmitter_identify(void);
+void viafb_init_dvi_size(void);
+void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga);
+
+#endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
new file mode 100644 (file)
index 0000000..468be24
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+int viafb_platform_epia_dvi = STATE_OFF;
+int viafb_device_lcd_dualedge = STATE_OFF;
+int viafb_bus_width = 12;
+int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
+int viafb_memsize;
+int viafb_DeviceStatus = CRT_Device;
+int viafb_hotplug;
+int viafb_refresh = 60;
+int viafb_refresh1 = 60;
+int viafb_lcd_dsp_method = LCD_EXPANDSION;
+int viafb_lcd_mode = LCD_OPENLDI;
+int viafb_bpp = 32;
+int viafb_bpp1 = 32;
+int viafb_accel = 1;
+int viafb_CRT_ON = 1;
+int viafb_DVI_ON;
+int viafb_LCD_ON ;
+int viafb_LCD2_ON;
+int viafb_SAMM_ON;
+int viafb_dual_fb;
+int viafb_hotplug_Xres = 640;
+int viafb_hotplug_Yres = 480;
+int viafb_hotplug_bpp = 32;
+int viafb_hotplug_refresh = 60;
+unsigned int viafb_second_offset;
+int viafb_second_size;
+int viafb_primary_dev = None_Device;
+void __iomem *viafb_FB_MM;
+unsigned int viafb_second_xres = 640;
+unsigned int viafb_second_yres = 480;
+unsigned int viafb_second_virtual_xres;
+unsigned int viafb_second_virtual_yres;
+int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
+struct fb_cursor viacursor;
+struct fb_info *viafbinfo;
+struct fb_info *viafbinfo1;
+struct viafb_par *viaparinfo;
+struct viafb_par *viaparinfo1;
+
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
new file mode 100644 (file)
index 0000000..8e5263c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __GLOBAL_H__
+#define __GLOBAL_H__
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+
+#include "debug.h"
+
+#include "iface.h"
+#include "viafbdev.h"
+#include "chip.h"
+#include "debug.h"
+#include "accel.h"
+#include "share.h"
+#include "dvi.h"
+#include "viamode.h"
+#include "via_i2c.h"
+#include "hw.h"
+
+#include "lcd.h"
+#include "ioctl.h"
+#include "viamode.h"
+#include "via_utility.h"
+#include "vt1636.h"
+#include "tblDPASetting.h"
+#include "tbl1636.h"
+#include "viafbdev.h"
+
+/* External struct*/
+
+extern int viafb_platform_epia_dvi;
+extern int viafb_device_lcd_dualedge;
+extern int viafb_bus_width;
+extern int viafb_display_hardware_layout;
+extern struct offset offset_reg;
+extern struct viafb_par *viaparinfo;
+extern struct viafb_par *viaparinfo1;
+extern struct fb_info *viafbinfo;
+extern struct fb_info *viafbinfo1;
+extern int viafb_DeviceStatus;
+extern int viafb_refresh;
+extern int viafb_refresh1;
+extern int viafb_lcd_dsp_method;
+extern int viafb_lcd_mode;
+extern int viafb_bpp;
+extern int viafb_bpp1;
+
+extern int viafb_CRT_ON;
+extern int viafb_hotplug_Xres;
+extern int viafb_hotplug_Yres;
+extern int viafb_hotplug_bpp;
+extern int viafb_hotplug_refresh;
+extern int viafb_primary_dev;
+extern void __iomem *viafb_FB_MM;
+extern struct fb_cursor viacursor;
+
+extern unsigned int viafb_second_xres;
+extern unsigned int viafb_second_yres;
+extern int viafb_lcd_panel_id;
+
+#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
new file mode 100644 (file)
index 0000000..fcd53ce
--- /dev/null
@@ -0,0 +1,2865 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+static const struct pci_device_id_info pciidlist[] = {
+       {PCI_VIA_VENDOR_ID, UNICHROME_CLE266_DID, UNICHROME_CLE266},
+       {PCI_VIA_VENDOR_ID, UNICHROME_PM800_DID, UNICHROME_PM800},
+       {PCI_VIA_VENDOR_ID, UNICHROME_K400_DID, UNICHROME_K400},
+       {PCI_VIA_VENDOR_ID, UNICHROME_K800_DID, UNICHROME_K800},
+       {PCI_VIA_VENDOR_ID, UNICHROME_CN700_DID, UNICHROME_CN700},
+       {PCI_VIA_VENDOR_ID, UNICHROME_P4M890_DID, UNICHROME_P4M890},
+       {PCI_VIA_VENDOR_ID, UNICHROME_K8M890_DID, UNICHROME_K8M890},
+       {PCI_VIA_VENDOR_ID, UNICHROME_CX700_DID, UNICHROME_CX700},
+       {PCI_VIA_VENDOR_ID, UNICHROME_P4M900_DID, UNICHROME_P4M900},
+       {PCI_VIA_VENDOR_ID, UNICHROME_CN750_DID, UNICHROME_CN750},
+       {PCI_VIA_VENDOR_ID, UNICHROME_VX800_DID, UNICHROME_VX800},
+       {0, 0, 0}
+};
+
+struct offset offset_reg = {
+       /* IGA1 Offset Register */
+       {IGA1_OFFSET_REG_NUM, {{CR13, 0, 7}, {CR35, 5, 7} } },
+       /* IGA2 Offset Register */
+       {IGA2_OFFSET_REG_NUM, {{CR66, 0, 7}, {CR67, 0, 1} } }
+};
+
+static struct pll_map pll_value[] = {
+       {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M, CX700_25_175M},
+       {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M, CX700_29_581M},
+       {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M, CX700_26_880M},
+       {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M, CX700_31_490M},
+       {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M, CX700_31_500M},
+       {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M, CX700_31_728M},
+       {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M, CX700_32_668M},
+       {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M, CX700_36_000M},
+       {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M, CX700_40_000M},
+       {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M, CX700_41_291M},
+       {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M, CX700_43_163M},
+       {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M, CX700_45_250M},
+       {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M, CX700_46_000M},
+       {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M, CX700_46_996M},
+       {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M, CX700_48_000M},
+       {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M, CX700_48_875M},
+       {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M, CX700_49_500M},
+       {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M, CX700_52_406M},
+       {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M, CX700_52_977M},
+       {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M},
+       {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M},
+       {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, CX700_61_500M},
+       {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M, CX700_65_000M},
+       {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M, CX700_65_178M},
+       {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M, CX700_66_750M},
+       {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M, CX700_68_179M},
+       {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M, CX700_69_924M},
+       {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M, CX700_70_159M},
+       {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M, CX700_72_000M},
+       {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M, CX700_78_750M},
+       {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M, CX700_80_136M},
+       {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M, CX700_83_375M},
+       {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M, CX700_83_950M},
+       {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M, CX700_84_750M},
+       {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M, CX700_85_860M},
+       {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M, CX700_88_750M},
+       {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M, CX700_94_500M},
+       {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M, CX700_97_750M},
+       {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
+        CX700_101_000M},
+       {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
+        CX700_106_500M},
+       {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
+        CX700_108_000M},
+       {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
+        CX700_113_309M},
+       {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
+        CX700_118_840M},
+       {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
+        CX700_119_000M},
+       {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
+        CX700_121_750M},
+       {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
+        CX700_125_104M},
+       {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
+        CX700_133_308M},
+       {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
+        CX700_135_000M},
+       {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
+        CX700_136_700M},
+       {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
+        CX700_138_400M},
+       {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
+        CX700_146_760M},
+       {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
+        CX700_153_920M},
+       {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
+        CX700_156_000M},
+       {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
+        CX700_157_500M},
+       {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
+        CX700_162_000M},
+       {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
+        CX700_187_000M},
+       {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
+        CX700_193_295M},
+       {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
+        CX700_202_500M},
+       {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
+        CX700_204_000M},
+       {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
+        CX700_218_500M},
+       {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
+        CX700_234_000M},
+       {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
+        CX700_267_250M},
+       {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
+        CX700_297_500M},
+       {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M, CX700_74_481M},
+       {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
+        CX700_172_798M},
+       {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
+        CX700_122_614M},
+       {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M, CX700_74_270M},
+       {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
+        CX700_148_500M}
+};
+
+static struct fifo_depth_select display_fifo_depth_reg = {
+       /* IGA1 FIFO Depth_Select */
+       {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
+       /* IGA2 FIFO Depth_Select */
+       {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
+        {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
+};
+
+static struct fifo_threshold_select fifo_threshold_select_reg = {
+       /* IGA1 FIFO Threshold Select */
+       {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
+       /* IGA2 FIFO Threshold Select */
+       {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
+};
+
+static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
+       /* IGA1 FIFO High Threshold Select */
+       {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
+       /* IGA2 FIFO High Threshold Select */
+       {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
+};
+
+static struct display_queue_expire_num display_queue_expire_num_reg = {
+       /* IGA1 Display Queue Expire Num */
+       {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
+       /* IGA2 Display Queue Expire Num */
+       {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
+};
+
+/* Definition Fetch Count Registers*/
+static struct fetch_count fetch_count_reg = {
+       /* IGA1 Fetch Count Register */
+       {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
+       /* IGA2 Fetch Count Register */
+       {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
+};
+
+static struct iga1_crtc_timing iga1_crtc_reg = {
+       /* IGA1 Horizontal Total */
+       {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
+       /* IGA1 Horizontal Addressable Video */
+       {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
+       /* IGA1 Horizontal Blank Start */
+       {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
+       /* IGA1 Horizontal Blank End */
+       {IGA1_HOR_BLANK_END_REG_NUM,
+        {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
+       /* IGA1 Horizontal Sync Start */
+       {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
+       /* IGA1 Horizontal Sync End */
+       {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
+       /* IGA1 Vertical Total */
+       {IGA1_VER_TOTAL_REG_NUM,
+        {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
+       /* IGA1 Vertical Addressable Video */
+       {IGA1_VER_ADDR_REG_NUM,
+        {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
+       /* IGA1 Vertical Blank Start */
+       {IGA1_VER_BLANK_START_REG_NUM,
+        {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
+       /* IGA1 Vertical Blank End */
+       {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
+       /* IGA1 Vertical Sync Start */
+       {IGA1_VER_SYNC_START_REG_NUM,
+        {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
+       /* IGA1 Vertical Sync End */
+       {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
+};
+
+static struct iga2_crtc_timing iga2_crtc_reg = {
+       /* IGA2 Horizontal Total */
+       {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
+       /* IGA2 Horizontal Addressable Video */
+       {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
+       /* IGA2 Horizontal Blank Start */
+       {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
+       /* IGA2 Horizontal Blank End */
+       {IGA2_HOR_BLANK_END_REG_NUM,
+        {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
+       /* IGA2 Horizontal Sync Start */
+       {IGA2_HOR_SYNC_START_REG_NUM,
+        {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
+       /* IGA2 Horizontal Sync End */
+       {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
+       /* IGA2 Vertical Total */
+       {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
+       /* IGA2 Vertical Addressable Video */
+       {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
+       /* IGA2 Vertical Blank Start */
+       {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
+       /* IGA2 Vertical Blank End */
+       {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
+       /* IGA2 Vertical Sync Start */
+       {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
+       /* IGA2 Vertical Sync End */
+       {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
+};
+
+static struct rgbLUT palLUT_table[] = {
+       /* {R,G,B} */
+       /* Index 0x00~0x03 */
+       {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
+                                                                    0x2A,
+                                                                    0x2A},
+       /* Index 0x04~0x07 */
+       {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
+                                                                    0x2A,
+                                                                    0x2A},
+       /* Index 0x08~0x0B */
+       {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
+                                                                    0x3F,
+                                                                    0x3F},
+       /* Index 0x0C~0x0F */
+       {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
+                                                                    0x3F,
+                                                                    0x3F},
+       /* Index 0x10~0x13 */
+       {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
+                                                                    0x0B,
+                                                                    0x0B},
+       /* Index 0x14~0x17 */
+       {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
+                                                                    0x18,
+                                                                    0x18},
+       /* Index 0x18~0x1B */
+       {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
+                                                                    0x28,
+                                                                    0x28},
+       /* Index 0x1C~0x1F */
+       {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
+                                                                    0x3F,
+                                                                    0x3F},
+       /* Index 0x20~0x23 */
+       {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
+                                                                    0x00,
+                                                                    0x3F},
+       /* Index 0x24~0x27 */
+       {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
+                                                                    0x00,
+                                                                    0x10},
+       /* Index 0x28~0x2B */
+       {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
+                                                                    0x2F,
+                                                                    0x00},
+       /* Index 0x2C~0x2F */
+       {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
+                                                                    0x3F,
+                                                                    0x00},
+       /* Index 0x30~0x33 */
+       {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
+                                                                    0x3F,
+                                                                    0x2F},
+       /* Index 0x34~0x37 */
+       {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
+                                                                    0x10,
+                                                                    0x3F},
+       /* Index 0x38~0x3B */
+       {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
+                                                                    0x1F,
+                                                                    0x3F},
+       /* Index 0x3C~0x3F */
+       {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
+                                                                    0x1F,
+                                                                    0x27},
+       /* Index 0x40~0x43 */
+       {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
+                                                                    0x3F,
+                                                                    0x1F},
+       /* Index 0x44~0x47 */
+       {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
+                                                                    0x3F,
+                                                                    0x1F},
+       /* Index 0x48~0x4B */
+       {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
+                                                                    0x3F,
+                                                                    0x37},
+       /* Index 0x4C~0x4F */
+       {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
+                                                                    0x27,
+                                                                    0x3F},
+       /* Index 0x50~0x53 */
+       {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
+                                                                    0x2D,
+                                                                    0x3F},
+       /* Index 0x54~0x57 */
+       {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
+                                                                    0x2D,
+                                                                    0x31},
+       /* Index 0x58~0x5B */
+       {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
+                                                                    0x3A,
+                                                                    0x2D},
+       /* Index 0x5C~0x5F */
+       {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
+                                                                    0x3F,
+                                                                    0x2D},
+       /* Index 0x60~0x63 */
+       {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
+                                                                    0x3F,
+                                                                    0x3A},
+       /* Index 0x64~0x67 */
+       {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
+                                                                    0x31,
+                                                                    0x3F},
+       /* Index 0x68~0x6B */
+       {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
+                                                                    0x00,
+                                                                    0x1C},
+       /* Index 0x6C~0x6F */
+       {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
+                                                                    0x00,
+                                                                    0x07},
+       /* Index 0x70~0x73 */
+       {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
+                                                                    0x15,
+                                                                    0x00},
+       /* Index 0x74~0x77 */
+       {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
+                                                                    0x1C,
+                                                                    0x00},
+       /* Index 0x78~0x7B */
+       {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
+                                                                    0x1C,
+                                                                    0x15},
+       /* Index 0x7C~0x7F */
+       {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
+                                                                    0x07,
+                                                                    0x1C},
+       /* Index 0x80~0x83 */
+       {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
+                                                                    0x0E,
+                                                                    0x1C},
+       /* Index 0x84~0x87 */
+       {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
+                                                                    0x0E,
+                                                                    0x11},
+       /* Index 0x88~0x8B */
+       {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
+                                                                    0x18,
+                                                                    0x0E},
+       /* Index 0x8C~0x8F */
+       {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
+                                                                    0x1C,
+                                                                    0x0E},
+       /* Index 0x90~0x93 */
+       {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
+                                                                    0x1C,
+                                                                    0x18},
+       /* Index 0x94~0x97 */
+       {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
+                                                                    0x11,
+                                                                    0x1C},
+       /* Index 0x98~0x9B */
+       {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
+                                                                    0x14,
+                                                                    0x1C},
+       /* Index 0x9C~0x9F */
+       {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
+                                                                    0x14,
+                                                                    0x16},
+       /* Index 0xA0~0xA3 */
+       {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
+                                                                    0x1A,
+                                                                    0x14},
+       /* Index 0xA4~0xA7 */
+       {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
+                                                                    0x1C,
+                                                                    0x14},
+       /* Index 0xA8~0xAB */
+       {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
+                                                                    0x1C,
+                                                                    0x1A},
+       /* Index 0xAC~0xAF */
+       {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
+                                                                    0x16,
+                                                                    0x1C},
+       /* Index 0xB0~0xB3 */
+       {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
+                                                                    0x00,
+                                                                    0x10},
+       /* Index 0xB4~0xB7 */
+       {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
+                                                                    0x00,
+                                                                    0x04},
+       /* Index 0xB8~0xBB */
+       {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
+                                                                    0x0C,
+                                                                    0x00},
+       /* Index 0xBC~0xBF */
+       {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
+                                                                    0x10,
+                                                                    0x00},
+       /* Index 0xC0~0xC3 */
+       {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
+                                                                    0x10,
+                                                                    0x0C},
+       /* Index 0xC4~0xC7 */
+       {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
+                                                                    0x04,
+                                                                    0x10},
+       /* Index 0xC8~0xCB */
+       {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
+                                                                    0x08,
+                                                                    0x10},
+       /* Index 0xCC~0xCF */
+       {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
+                                                                    0x08,
+                                                                    0x0A},
+       /* Index 0xD0~0xD3 */
+       {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
+                                                                    0x0E,
+                                                                    0x08},
+       /* Index 0xD4~0xD7 */
+       {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
+                                                                    0x10,
+                                                                    0x08},
+       /* Index 0xD8~0xDB */
+       {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
+                                                                    0x10,
+                                                                    0x0E},
+       /* Index 0xDC~0xDF */
+       {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
+                                                                    0x0A,
+                                                                    0x10},
+       /* Index 0xE0~0xE3 */
+       {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
+                                                                    0x0B,
+                                                                    0x10},
+       /* Index 0xE4~0xE7 */
+       {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
+                                                                    0x0B,
+                                                                    0x0C},
+       /* Index 0xE8~0xEB */
+       {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
+                                                                    0x0F,
+                                                                    0x0B},
+       /* Index 0xEC~0xEF */
+       {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
+                                                                    0x10,
+                                                                    0x0B},
+       /* Index 0xF0~0xF3 */
+       {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
+                                                                    0x10,
+                                                                    0x0F},
+       /* Index 0xF4~0xF7 */
+       {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
+                                                                    0x0C,
+                                                                    0x10},
+       /* Index 0xF8~0xFB */
+       {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+                                                                    0x00,
+                                                                    0x00},
+       /* Index 0xFC~0xFF */
+       {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
+                                                                    0x00,
+                                                                    0x00}
+};
+
+static void set_crt_output_path(int set_iga);
+static void dvi_patch_skew_dvp0(void);
+static void dvi_patch_skew_dvp1(void);
+static void dvi_patch_skew_dvp_low(void);
+static void set_dvi_output_path(int set_iga, int output_interface);
+static void set_lcd_output_path(int set_iga, int output_interface);
+static int search_mode_setting(int ModeInfoIndex);
+static void load_fix_bit_crtc_reg(void);
+static void init_gfx_chip_info(void);
+static void init_tmds_chip_info(void);
+static void init_lvds_chip_info(void);
+static void device_screen_off(void);
+static void device_screen_on(void);
+static void set_display_channel(void);
+static void device_off(void);
+static void device_on(void);
+static void enable_second_display_channel(void);
+static void disable_second_display_channel(void);
+static int get_fb_size_from_pci(void);
+
+void viafb_write_reg(u8 index, u16 io_port, u8 data)
+{
+       outb(index, io_port);
+       outb(data, io_port + 1);
+       /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */
+}
+u8 viafb_read_reg(int io_port, u8 index)
+{
+       outb(index, io_port);
+       return inb(io_port + 1);
+}
+
+void viafb_lock_crt(void)
+{
+       viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
+}
+
+void viafb_unlock_crt(void)
+{
+       viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
+       viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
+}
+
+void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
+{
+       u8 tmp;
+
+       outb(index, io_port);
+       tmp = inb(io_port + 1);
+       outb((data & mask) | (tmp & (~mask)), io_port + 1);
+       /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */
+}
+
+void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
+{
+       outb(index, LUT_INDEX_WRITE);
+       outb(r, LUT_DATA);
+       outb(g, LUT_DATA);
+       outb(b, LUT_DATA);
+}
+
+/*Set IGA path for each device*/
+void viafb_set_iga_path(void)
+{
+
+       if (viafb_SAMM_ON == 1) {
+               if (viafb_CRT_ON) {
+                       if (viafb_primary_dev == CRT_Device)
+                               viaparinfo->crt_setting_info->iga_path = IGA1;
+                       else
+                               viaparinfo->crt_setting_info->iga_path = IGA2;
+               }
+
+               if (viafb_DVI_ON) {
+                       if (viafb_primary_dev == DVI_Device)
+                               viaparinfo->tmds_setting_info->iga_path = IGA1;
+                       else
+                               viaparinfo->tmds_setting_info->iga_path = IGA2;
+               }
+
+               if (viafb_LCD_ON) {
+                       if (viafb_primary_dev == LCD_Device) {
+                               if (viafb_dual_fb &&
+                                       (viaparinfo->chip_info->gfx_chip_name ==
+                                       UNICHROME_CLE266)) {
+                                       viaparinfo->
+                                       lvds_setting_info->iga_path = IGA2;
+                                       viaparinfo->
+                                       crt_setting_info->iga_path = IGA1;
+                                       viaparinfo->
+                                       tmds_setting_info->iga_path = IGA1;
+                               } else
+                                       viaparinfo->
+                                       lvds_setting_info->iga_path = IGA1;
+                       } else {
+                               viaparinfo->lvds_setting_info->iga_path = IGA2;
+                       }
+               }
+               if (viafb_LCD2_ON) {
+                       if (LCD2_Device == viafb_primary_dev)
+                               viaparinfo->lvds_setting_info2->iga_path = IGA1;
+                       else
+                               viaparinfo->lvds_setting_info2->iga_path = IGA2;
+               }
+       } else {
+               viafb_SAMM_ON = 0;
+
+               if (viafb_CRT_ON && viafb_LCD_ON) {
+                       viaparinfo->crt_setting_info->iga_path = IGA1;
+                       viaparinfo->lvds_setting_info->iga_path = IGA2;
+               } else if (viafb_CRT_ON && viafb_DVI_ON) {
+                       viaparinfo->crt_setting_info->iga_path = IGA1;
+                       viaparinfo->tmds_setting_info->iga_path = IGA2;
+               } else if (viafb_LCD_ON && viafb_DVI_ON) {
+                       viaparinfo->tmds_setting_info->iga_path = IGA1;
+                       viaparinfo->lvds_setting_info->iga_path = IGA2;
+               } else if (viafb_LCD_ON && viafb_LCD2_ON) {
+                       viaparinfo->lvds_setting_info->iga_path = IGA2;
+                       viaparinfo->lvds_setting_info2->iga_path = IGA2;
+               } else if (viafb_CRT_ON) {
+                       viaparinfo->crt_setting_info->iga_path = IGA1;
+               } else if (viafb_LCD_ON) {
+                       viaparinfo->lvds_setting_info->iga_path = IGA2;
+               } else if (viafb_DVI_ON) {
+                       viaparinfo->tmds_setting_info->iga_path = IGA1;
+               }
+       }
+}
+
+void viafb_set_start_addr(void)
+{
+       unsigned long offset = 0, tmp = 0, size = 0;
+       unsigned long length;
+
+       DEBUG_MSG(KERN_INFO "viafb_set_start_addr!\n");
+       viafb_unlock_crt();
+       /* update starting address of IGA1 */
+       viafb_write_reg(CR0C, VIACR, 0x00);     /*initial starting address */
+       viafb_write_reg(CR0D, VIACR, 0x00);
+       viafb_write_reg(CR34, VIACR, 0x00);
+       viafb_write_reg_mask(CR48, VIACR, 0x00, 0x1F);
+
+       if (viafb_dual_fb) {
+               viaparinfo->iga_path = IGA1;
+               viaparinfo1->iga_path = IGA2;
+       }
+
+       if (viafb_SAMM_ON == 1) {
+               if (!viafb_dual_fb) {
+                       if (viafb_second_size)
+                               size = viafb_second_size * 1024 * 1024;
+                       else
+                               size = 8 * 1024 * 1024;
+               } else {
+
+                       size = viaparinfo1->memsize;
+               }
+               offset = viafb_second_offset;
+               DEBUG_MSG(KERN_INFO
+                         "viafb_second_size=%lx, second start_adddress=%lx\n",
+                         size, offset);
+       }
+       if (viafb_SAMM_ON == 1) {
+               offset = offset >> 3;
+
+               tmp = viafb_read_reg(VIACR, 0x62) & 0x01;
+               tmp |= (offset & 0x7F) << 1;
+               viafb_write_reg(CR62, VIACR, tmp);
+               viafb_write_reg(CR63, VIACR, ((offset & 0x7F80) >> 7));
+               viafb_write_reg(CR64, VIACR, ((offset & 0x7F8000) >> 15));
+               viafb_write_reg(CRA3, VIACR, ((offset & 0x3800000) >> 23));
+       } else {
+               /* update starting address */
+               viafb_write_reg(CR62, VIACR, 0x00);
+               viafb_write_reg(CR63, VIACR, 0x00);
+               viafb_write_reg(CR64, VIACR, 0x00);
+               viafb_write_reg(CRA3, VIACR, 0x00);
+       }
+
+       if (viafb_SAMM_ON == 1) {
+               if (viafb_accel) {
+                       if (!viafb_dual_fb)
+                               length = size - viaparinfo->fbmem_used;
+                       else
+                               length = size - viaparinfo1->fbmem_used;
+               } else
+                       length = size;
+               offset = (unsigned long)(void *)viafb_FB_MM +
+                       viafb_second_offset;
+               memset((void *)offset, 0, length);
+       }
+
+       viafb_lock_crt();
+}
+
+void viafb_set_output_path(int device, int set_iga, int output_interface)
+{
+       switch (device) {
+       case DEVICE_CRT:
+               set_crt_output_path(set_iga);
+               break;
+       case DEVICE_DVI:
+               set_dvi_output_path(set_iga, output_interface);
+               break;
+       case DEVICE_LCD:
+               set_lcd_output_path(set_iga, output_interface);
+               break;
+       }
+}
+
+static void set_crt_output_path(int set_iga)
+{
+       viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+
+       switch (set_iga) {
+       case IGA1:
+               viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
+               break;
+       case IGA2:
+       case IGA1_IGA2:
+               viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
+               viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
+               if (set_iga == IGA1_IGA2)
+                       viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+               break;
+       }
+}
+
+static void dvi_patch_skew_dvp0(void)
+{
+       /* Reset data driving first: */
+       viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
+       viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
+
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_P4M890:
+               {
+                       if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
+                               (viaparinfo->tmds_setting_info->v_active ==
+                               1200))
+                               viafb_write_reg_mask(CR96, VIACR, 0x03,
+                                              BIT0 + BIT1 + BIT2);
+                       else
+                               viafb_write_reg_mask(CR96, VIACR, 0x07,
+                                              BIT0 + BIT1 + BIT2);
+                       break;
+               }
+
+       case UNICHROME_P4M900:
+               {
+                       viafb_write_reg_mask(CR96, VIACR, 0x07,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
+                       viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
+                       break;
+               }
+
+       default:
+               {
+                       break;
+               }
+       }
+}
+
+static void dvi_patch_skew_dvp1(void)
+{
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_CX700:
+               {
+                       break;
+               }
+
+       default:
+               {
+                       break;
+               }
+       }
+}
+
+static void dvi_patch_skew_dvp_low(void)
+{
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_K8M890:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
+                       break;
+               }
+
+       case UNICHROME_P4M900:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x08,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       break;
+               }
+
+       case UNICHROME_P4M890:
+               {
+                       viafb_write_reg_mask(CR99, VIACR, 0x0F,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+                       break;
+               }
+
+       default:
+               {
+                       break;
+               }
+       }
+}
+
+static void set_dvi_output_path(int set_iga, int output_interface)
+{
+       switch (output_interface) {
+       case INTERFACE_DVP0:
+               viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
+
+               if (set_iga == IGA1) {
+                       viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+                       viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 +
+                               BIT5 + BIT7);
+               } else {
+                       viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+                       viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 +
+                               BIT5 + BIT7);
+               }
+
+               viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
+
+               dvi_patch_skew_dvp0();
+               break;
+
+       case INTERFACE_DVP1:
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+                       if (set_iga == IGA1)
+                               viafb_write_reg_mask(CR93, VIACR, 0x21,
+                                              BIT0 + BIT5 + BIT7);
+                       else
+                               viafb_write_reg_mask(CR93, VIACR, 0xA1,
+                                              BIT0 + BIT5 + BIT7);
+               } else {
+                       if (set_iga == IGA1)
+                               viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+                       else
+                               viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+               }
+
+               viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
+               dvi_patch_skew_dvp1();
+               break;
+       case INTERFACE_DFP_HIGH:
+               if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) {
+                       if (set_iga == IGA1) {
+                               viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+                               viafb_write_reg_mask(CR97, VIACR, 0x03,
+                                              BIT0 + BIT1 + BIT4);
+                       } else {
+                               viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+                               viafb_write_reg_mask(CR97, VIACR, 0x13,
+                                              BIT0 + BIT1 + BIT4);
+                       }
+               }
+               viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
+               break;
+
+       case INTERFACE_DFP_LOW:
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+                       break;
+
+               if (set_iga == IGA1) {
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+                       viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+               } else {
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+                       viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+               }
+
+               viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
+               dvi_patch_skew_dvp_low();
+               break;
+
+       case INTERFACE_TMDS:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+               else
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+               break;
+       }
+
+       if (set_iga == IGA2) {
+               enable_second_display_channel();
+               /* Disable LCD Scaling */
+               viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
+       }
+}
+
+static void set_lcd_output_path(int set_iga, int output_interface)
+{
+       DEBUG_MSG(KERN_INFO
+                 "set_lcd_output_path, iga:%d,out_interface:%d\n",
+                 set_iga, output_interface);
+       switch (set_iga) {
+       case IGA1:
+               viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+               viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+               disable_second_display_channel();
+               break;
+
+       case IGA2:
+               viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
+               viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+               enable_second_display_channel();
+               break;
+
+       case IGA1_IGA2:
+               viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
+               viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+
+               disable_second_display_channel();
+               break;
+       }
+
+       switch (output_interface) {
+       case INTERFACE_DVP0:
+               if (set_iga == IGA1) {
+                       viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
+               } else {
+                       viafb_write_reg(CR91, VIACR, 0x00);
+                       viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+               }
+               break;
+
+       case INTERFACE_DVP1:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
+               else {
+                       viafb_write_reg(CR91, VIACR, 0x00);
+                       viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+               }
+               break;
+
+       case INTERFACE_DFP_HIGH:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+               else {
+                       viafb_write_reg(CR91, VIACR, 0x00);
+                       viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+                       viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
+               }
+               break;
+
+       case INTERFACE_DFP_LOW:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+               else {
+                       viafb_write_reg(CR91, VIACR, 0x00);
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+                       viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
+               }
+
+               break;
+
+       case INTERFACE_DFP:
+               if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
+                   || (UNICHROME_P4M890 ==
+                   viaparinfo->chip_info->gfx_chip_name))
+                       viafb_write_reg_mask(CR97, VIACR, 0x84,
+                                      BIT7 + BIT2 + BIT1 + BIT0);
+               if (set_iga == IGA1) {
+                       viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+               } else {
+                       viafb_write_reg(CR91, VIACR, 0x00);
+                       viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+               }
+               break;
+
+       case INTERFACE_LVDS0:
+       case INTERFACE_LVDS0LVDS1:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
+               else
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
+
+               break;
+
+       case INTERFACE_LVDS1:
+               if (set_iga == IGA1)
+                       viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
+               else
+                       viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
+               break;
+       }
+}
+
+/* Search Mode Index */
+static int search_mode_setting(int ModeInfoIndex)
+{
+       int i = 0;
+
+       while ((i < NUM_TOTAL_MODETABLE) &&
+                       (ModeInfoIndex != CLE266Modes[i].ModeIndex))
+               i++;
+       if (i >= NUM_TOTAL_MODETABLE)
+               i = 0;
+       return i;
+
+}
+
+struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
+{
+       struct VideoModeTable *TmpTbl = NULL;
+       TmpTbl = &CLE266Modes[search_mode_setting(Index)];
+       return TmpTbl;
+}
+
+struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
+{
+       struct VideoModeTable *TmpTbl = NULL;
+       int i = 0;
+       while ((i < NUM_TOTAL_CEA_MODES) &&
+                       (Index != CEA_HDMI_Modes[i].ModeIndex))
+               i++;
+       if ((i < NUM_TOTAL_CEA_MODES))
+               TmpTbl = &CEA_HDMI_Modes[i];
+        else {
+               /*Still use general timing if don't find CEA timing */
+               i = 0;
+               while ((i < NUM_TOTAL_MODETABLE) &&
+                               (Index != CLE266Modes[i].ModeIndex))
+                      i++;
+               if (i >= NUM_TOTAL_MODETABLE)
+                       i = 0;
+               TmpTbl = &CLE266Modes[i];
+       }
+       return TmpTbl;
+}
+
+static void load_fix_bit_crtc_reg(void)
+{
+       /* always set to 1 */
+       viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
+       /* line compare should set all bits = 1 (extend modes) */
+       viafb_write_reg(CR18, VIACR, 0xff);
+       /* line compare should set all bits = 1 (extend modes) */
+       viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
+       /* line compare should set all bits = 1 (extend modes) */
+       viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
+       /* line compare should set all bits = 1 (extend modes) */
+       viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
+       /* line compare should set all bits = 1 (extend modes) */
+       viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
+       /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
+       /* extend mode always set to e3h */
+       viafb_write_reg(CR17, VIACR, 0xe3);
+       /* extend mode always set to 0h */
+       viafb_write_reg(CR08, VIACR, 0x00);
+       /* extend mode always set to 0h */
+       viafb_write_reg(CR14, VIACR, 0x00);
+
+       /* If K8M800, enable Prefetch Mode. */
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+               || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
+               viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+           && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
+               viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
+
+}
+
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+       struct io_register *reg,
+             int io_type)
+{
+       int reg_mask;
+       int bit_num = 0;
+       int data;
+       int i, j;
+       int shift_next_reg;
+       int start_index, end_index, cr_index;
+       u16 get_bit;
+
+       for (i = 0; i < viafb_load_reg_num; i++) {
+               reg_mask = 0;
+               data = 0;
+               start_index = reg[i].start_bit;
+               end_index = reg[i].end_bit;
+               cr_index = reg[i].io_addr;
+
+               shift_next_reg = bit_num;
+               for (j = start_index; j <= end_index; j++) {
+                       /*if (bit_num==8) timing_value = timing_value >>8; */
+                       reg_mask = reg_mask | (BIT0 << j);
+                       get_bit = (timing_value & (BIT0 << bit_num));
+                       data =
+                           data | ((get_bit >> shift_next_reg) << start_index);
+                       bit_num++;
+               }
+               if (io_type == VIACR)
+                       viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
+               else
+                       viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
+       }
+
+}
+
+/* Write Registers */
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
+{
+       int i;
+       unsigned char RegTemp;
+
+       /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
+
+       for (i = 0; i < ItemNum; i++) {
+               outb(RegTable[i].index, RegTable[i].port);
+               RegTemp = inb(RegTable[i].port + 1);
+               RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value;
+               outb(RegTemp, RegTable[i].port + 1);
+       }
+}
+
+void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga)
+{
+       int reg_value;
+       int viafb_load_reg_num;
+       struct io_register *reg;
+
+       switch (set_iga) {
+       case IGA1_IGA2:
+       case IGA1:
+               reg_value = IGA1_OFFSET_FORMULA(h_addr, bpp_byte);
+               viafb_load_reg_num = offset_reg.iga1_offset_reg.reg_num;
+               reg = offset_reg.iga1_offset_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+               if (set_iga == IGA1)
+                       break;
+       case IGA2:
+               reg_value = IGA2_OFFSET_FORMULA(h_addr, bpp_byte);
+               viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
+               reg = offset_reg.iga2_offset_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+               break;
+       }
+}
+
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
+{
+       int reg_value;
+       int viafb_load_reg_num;
+       struct io_register *reg = NULL;
+
+       switch (set_iga) {
+       case IGA1_IGA2:
+       case IGA1:
+               reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+               viafb_load_reg_num = fetch_count_reg.
+                       iga1_fetch_count_reg.reg_num;
+               reg = fetch_count_reg.iga1_fetch_count_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+               if (set_iga == IGA1)
+                       break;
+       case IGA2:
+               reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
+               viafb_load_reg_num = fetch_count_reg.
+                       iga2_fetch_count_reg.reg_num;
+               reg = fetch_count_reg.iga2_fetch_count_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+               break;
+       }
+
+}
+
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
+{
+       int reg_value;
+       int viafb_load_reg_num;
+       struct io_register *reg = NULL;
+       int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
+           0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
+       int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
+           0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
+
+       if (set_iga == IGA1) {
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+                       iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           K800_IGA1_FIFO_HIGH_THRESHOLD;
+                       /* If resolution > 1280x1024, expire length = 64, else
+                          expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga1_display_queue_expire_num = 16;
+                       else
+                               iga1_display_queue_expire_num =
+                                   K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+                       iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           P880_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+
+                       /* If resolution > 1280x1024, expire length = 64, else
+                          expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga1_display_queue_expire_num = 16;
+                       else
+                               iga1_display_queue_expire_num =
+                                   P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+                       iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           CN700_IGA1_FIFO_HIGH_THRESHOLD;
+
+                       /* If resolution > 1280x1024, expire length = 64,
+                          else expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga1_display_queue_expire_num = 16;
+                       else
+                               iga1_display_queue_expire_num =
+                                   CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+                       iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           CX700_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+                       iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           K8M890_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+                       iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           P4M890_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+                       iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           P4M900_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+                       iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
+                       iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
+                       iga1_fifo_high_threshold =
+                           VX800_IGA1_FIFO_HIGH_THRESHOLD;
+                       iga1_display_queue_expire_num =
+                           VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               /* Set Display FIFO Depath Select */
+               reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
+               viafb_load_reg_num =
+                   display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
+               reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+               /* Set Display FIFO Threshold Select */
+               reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
+               viafb_load_reg_num =
+                   fifo_threshold_select_reg.
+                   iga1_fifo_threshold_select_reg.reg_num;
+               reg =
+                   fifo_threshold_select_reg.
+                   iga1_fifo_threshold_select_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+               /* Set FIFO High Threshold Select */
+               reg_value =
+                   IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
+               viafb_load_reg_num =
+                   fifo_high_threshold_select_reg.
+                   iga1_fifo_high_threshold_select_reg.reg_num;
+               reg =
+                   fifo_high_threshold_select_reg.
+                   iga1_fifo_high_threshold_select_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+               /* Set Display Queue Expire Num */
+               reg_value =
+                   IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+                   (iga1_display_queue_expire_num);
+               viafb_load_reg_num =
+                   display_queue_expire_num_reg.
+                   iga1_display_queue_expire_num_reg.reg_num;
+               reg =
+                   display_queue_expire_num_reg.
+                   iga1_display_queue_expire_num_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
+
+       } else {
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+                       iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           K800_IGA2_FIFO_HIGH_THRESHOLD;
+
+                       /* If resolution > 1280x1024, expire length = 64,
+                          else  expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga2_display_queue_expire_num = 16;
+                       else
+                               iga2_display_queue_expire_num =
+                                   K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
+                       iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           P880_IGA2_FIFO_HIGH_THRESHOLD;
+
+                       /* If resolution > 1280x1024, expire length = 64,
+                          else  expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga2_display_queue_expire_num = 16;
+                       else
+                               iga2_display_queue_expire_num =
+                                   P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
+                       iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           CN700_IGA2_FIFO_HIGH_THRESHOLD;
+
+                       /* If resolution > 1280x1024, expire length = 64,
+                          else expire length = 128 */
+                       if ((hor_active > 1280) && (ver_active > 1024))
+                               iga2_display_queue_expire_num = 16;
+                       else
+                               iga2_display_queue_expire_num =
+                                   CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+                       iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           CX700_IGA2_FIFO_HIGH_THRESHOLD;
+                       iga2_display_queue_expire_num =
+                           CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
+                       iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           K8M890_IGA2_FIFO_HIGH_THRESHOLD;
+                       iga2_display_queue_expire_num =
+                           K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
+                       iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           P4M890_IGA2_FIFO_HIGH_THRESHOLD;
+                       iga2_display_queue_expire_num =
+                           P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
+                       iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           P4M900_IGA2_FIFO_HIGH_THRESHOLD;
+                       iga2_display_queue_expire_num =
+                           P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
+                       iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
+                       iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
+                       iga2_fifo_high_threshold =
+                           VX800_IGA2_FIFO_HIGH_THRESHOLD;
+                       iga2_display_queue_expire_num =
+                           VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
+               }
+
+               if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
+                       /* Set Display FIFO Depath Select */
+                       reg_value =
+                           IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
+                           - 1;
+                       /* Patch LCD in IGA2 case */
+                       viafb_load_reg_num =
+                           display_fifo_depth_reg.
+                           iga2_fifo_depth_select_reg.reg_num;
+                       reg =
+                           display_fifo_depth_reg.
+                           iga2_fifo_depth_select_reg.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+               } else {
+
+                       /* Set Display FIFO Depath Select */
+                       reg_value =
+                           IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
+                       viafb_load_reg_num =
+                           display_fifo_depth_reg.
+                           iga2_fifo_depth_select_reg.reg_num;
+                       reg =
+                           display_fifo_depth_reg.
+                           iga2_fifo_depth_select_reg.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+               }
+
+               /* Set Display FIFO Threshold Select */
+               reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
+               viafb_load_reg_num =
+                   fifo_threshold_select_reg.
+                   iga2_fifo_threshold_select_reg.reg_num;
+               reg =
+                   fifo_threshold_select_reg.
+                   iga2_fifo_threshold_select_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+               /* Set FIFO High Threshold Select */
+               reg_value =
+                   IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
+               viafb_load_reg_num =
+                   fifo_high_threshold_select_reg.
+                   iga2_fifo_high_threshold_select_reg.reg_num;
+               reg =
+                   fifo_high_threshold_select_reg.
+                   iga2_fifo_high_threshold_select_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+               /* Set Display Queue Expire Num */
+               reg_value =
+                   IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
+                   (iga2_display_queue_expire_num);
+               viafb_load_reg_num =
+                   display_queue_expire_num_reg.
+                   iga2_display_queue_expire_num_reg.reg_num;
+               reg =
+                   display_queue_expire_num_reg.
+                   iga2_display_queue_expire_num_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+
+       }
+
+}
+
+u32 viafb_get_clk_value(int clk)
+{
+       int i;
+
+       for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
+               if (clk == pll_value[i].clk) {
+                       switch (viaparinfo->chip_info->gfx_chip_name) {
+                       case UNICHROME_CLE266:
+                       case UNICHROME_K400:
+                               return pll_value[i].cle266_pll;
+
+                       case UNICHROME_K800:
+                       case UNICHROME_PM800:
+                       case UNICHROME_CN700:
+                               return pll_value[i].k800_pll;
+
+                       case UNICHROME_CX700:
+                       case UNICHROME_K8M890:
+                       case UNICHROME_P4M890:
+                       case UNICHROME_P4M900:
+                       case UNICHROME_VX800:
+                               return pll_value[i].cx700_pll;
+                       }
+               }
+       }
+
+       DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
+       return 0;
+}
+
+/* Set VCLK*/
+void viafb_set_vclock(u32 CLK, int set_iga)
+{
+       unsigned char RegTemp;
+
+       /* H.W. Reset : ON */
+       viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+       if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+               /* Change D,N FOR VCLK */
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CLE266:
+               case UNICHROME_K400:
+                       viafb_write_reg(SR46, VIASR, CLK / 0x100);
+                       viafb_write_reg(SR47, VIASR, CLK % 0x100);
+                       break;
+
+               case UNICHROME_K800:
+               case UNICHROME_PM800:
+               case UNICHROME_CN700:
+               case UNICHROME_CX700:
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M890:
+               case UNICHROME_P4M900:
+               case UNICHROME_VX800:
+                       viafb_write_reg(SR44, VIASR, CLK / 0x10000);
+                       DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
+                       viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
+                       DEBUG_MSG(KERN_INFO "\nSR45=%x",
+                                 (CLK & 0xFFFF) / 0x100);
+                       viafb_write_reg(SR46, VIASR, CLK % 0x100);
+                       DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100);
+                       break;
+               }
+       }
+
+       if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+               /* Change D,N FOR LCK */
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CLE266:
+               case UNICHROME_K400:
+                       viafb_write_reg(SR44, VIASR, CLK / 0x100);
+                       viafb_write_reg(SR45, VIASR, CLK % 0x100);
+                       break;
+
+               case UNICHROME_K800:
+               case UNICHROME_PM800:
+               case UNICHROME_CN700:
+               case UNICHROME_CX700:
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M890:
+               case UNICHROME_P4M900:
+               case UNICHROME_VX800:
+                       viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
+                       viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
+                       viafb_write_reg(SR4C, VIASR, CLK % 0x100);
+                       break;
+               }
+       }
+
+       /* H.W. Reset : OFF */
+       viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+       /* Reset PLL */
+       if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+               viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+               viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+       }
+
+       if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+               viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
+               viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
+       }
+
+       /* Fire! */
+       RegTemp = inb(VIARMisc);
+       outb(RegTemp | (BIT2 + BIT3), VIAWMisc);
+}
+
+void viafb_load_crtc_timing(struct display_timing device_timing,
+       int set_iga)
+{
+       int i;
+       int viafb_load_reg_num = 0;
+       int reg_value = 0;
+       struct io_register *reg = NULL;
+
+       viafb_unlock_crt();
+
+       for (i = 0; i < 12; i++) {
+               if (set_iga == IGA1) {
+                       switch (i) {
+                       case H_TOTAL_INDEX:
+                               reg_value =
+                                   IGA1_HOR_TOTAL_FORMULA(device_timing.
+                                                          hor_total);
+                               viafb_load_reg_num =
+                                       iga1_crtc_reg.hor_total.reg_num;
+                               reg = iga1_crtc_reg.hor_total.reg;
+                               break;
+                       case H_ADDR_INDEX:
+                               reg_value =
+                                   IGA1_HOR_ADDR_FORMULA(device_timing.
+                                                         hor_addr);
+                               viafb_load_reg_num =
+                                       iga1_crtc_reg.hor_addr.reg_num;
+                               reg = iga1_crtc_reg.hor_addr.reg;
+                               break;
+                       case H_BLANK_START_INDEX:
+                               reg_value =
+                                   IGA1_HOR_BLANK_START_FORMULA
+                                   (device_timing.hor_blank_start);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.hor_blank_start.reg_num;
+                               reg = iga1_crtc_reg.hor_blank_start.reg;
+                               break;
+                       case H_BLANK_END_INDEX:
+                               reg_value =
+                                   IGA1_HOR_BLANK_END_FORMULA
+                                   (device_timing.hor_blank_start,
+                                    device_timing.hor_blank_end);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.hor_blank_end.reg_num;
+                               reg = iga1_crtc_reg.hor_blank_end.reg;
+                               break;
+                       case H_SYNC_START_INDEX:
+                               reg_value =
+                                   IGA1_HOR_SYNC_START_FORMULA
+                                   (device_timing.hor_sync_start);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.hor_sync_start.reg_num;
+                               reg = iga1_crtc_reg.hor_sync_start.reg;
+                               break;
+                       case H_SYNC_END_INDEX:
+                               reg_value =
+                                   IGA1_HOR_SYNC_END_FORMULA
+                                   (device_timing.hor_sync_start,
+                                    device_timing.hor_sync_end);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.hor_sync_end.reg_num;
+                               reg = iga1_crtc_reg.hor_sync_end.reg;
+                               break;
+                       case V_TOTAL_INDEX:
+                               reg_value =
+                                   IGA1_VER_TOTAL_FORMULA(device_timing.
+                                                          ver_total);
+                               viafb_load_reg_num =
+                                       iga1_crtc_reg.ver_total.reg_num;
+                               reg = iga1_crtc_reg.ver_total.reg;
+                               break;
+                       case V_ADDR_INDEX:
+                               reg_value =
+                                   IGA1_VER_ADDR_FORMULA(device_timing.
+                                                         ver_addr);
+                               viafb_load_reg_num =
+                                       iga1_crtc_reg.ver_addr.reg_num;
+                               reg = iga1_crtc_reg.ver_addr.reg;
+                               break;
+                       case V_BLANK_START_INDEX:
+                               reg_value =
+                                   IGA1_VER_BLANK_START_FORMULA
+                                   (device_timing.ver_blank_start);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.ver_blank_start.reg_num;
+                               reg = iga1_crtc_reg.ver_blank_start.reg;
+                               break;
+                       case V_BLANK_END_INDEX:
+                               reg_value =
+                                   IGA1_VER_BLANK_END_FORMULA
+                                   (device_timing.ver_blank_start,
+                                    device_timing.ver_blank_end);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.ver_blank_end.reg_num;
+                               reg = iga1_crtc_reg.ver_blank_end.reg;
+                               break;
+                       case V_SYNC_START_INDEX:
+                               reg_value =
+                                   IGA1_VER_SYNC_START_FORMULA
+                                   (device_timing.ver_sync_start);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.ver_sync_start.reg_num;
+                               reg = iga1_crtc_reg.ver_sync_start.reg;
+                               break;
+                       case V_SYNC_END_INDEX:
+                               reg_value =
+                                   IGA1_VER_SYNC_END_FORMULA
+                                   (device_timing.ver_sync_start,
+                                    device_timing.ver_sync_end);
+                               viafb_load_reg_num =
+                                   iga1_crtc_reg.ver_sync_end.reg_num;
+                               reg = iga1_crtc_reg.ver_sync_end.reg;
+                               break;
+
+                       }
+               }
+
+               if (set_iga == IGA2) {
+                       switch (i) {
+                       case H_TOTAL_INDEX:
+                               reg_value =
+                                   IGA2_HOR_TOTAL_FORMULA(device_timing.
+                                                          hor_total);
+                               viafb_load_reg_num =
+                                       iga2_crtc_reg.hor_total.reg_num;
+                               reg = iga2_crtc_reg.hor_total.reg;
+                               break;
+                       case H_ADDR_INDEX:
+                               reg_value =
+                                   IGA2_HOR_ADDR_FORMULA(device_timing.
+                                                         hor_addr);
+                               viafb_load_reg_num =
+                                       iga2_crtc_reg.hor_addr.reg_num;
+                               reg = iga2_crtc_reg.hor_addr.reg;
+                               break;
+                       case H_BLANK_START_INDEX:
+                               reg_value =
+                                   IGA2_HOR_BLANK_START_FORMULA
+                                   (device_timing.hor_blank_start);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.hor_blank_start.reg_num;
+                               reg = iga2_crtc_reg.hor_blank_start.reg;
+                               break;
+                       case H_BLANK_END_INDEX:
+                               reg_value =
+                                   IGA2_HOR_BLANK_END_FORMULA
+                                   (device_timing.hor_blank_start,
+                                    device_timing.hor_blank_end);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.hor_blank_end.reg_num;
+                               reg = iga2_crtc_reg.hor_blank_end.reg;
+                               break;
+                       case H_SYNC_START_INDEX:
+                               reg_value =
+                                   IGA2_HOR_SYNC_START_FORMULA
+                                   (device_timing.hor_sync_start);
+                               if (UNICHROME_CN700 <=
+                                       viaparinfo->chip_info->gfx_chip_name)
+                                       viafb_load_reg_num =
+                                           iga2_crtc_reg.hor_sync_start.
+                                           reg_num;
+                               else
+                                       viafb_load_reg_num = 3;
+                               reg = iga2_crtc_reg.hor_sync_start.reg;
+                               break;
+                       case H_SYNC_END_INDEX:
+                               reg_value =
+                                   IGA2_HOR_SYNC_END_FORMULA
+                                   (device_timing.hor_sync_start,
+                                    device_timing.hor_sync_end);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.hor_sync_end.reg_num;
+                               reg = iga2_crtc_reg.hor_sync_end.reg;
+                               break;
+                       case V_TOTAL_INDEX:
+                               reg_value =
+                                   IGA2_VER_TOTAL_FORMULA(device_timing.
+                                                          ver_total);
+                               viafb_load_reg_num =
+                                       iga2_crtc_reg.ver_total.reg_num;
+                               reg = iga2_crtc_reg.ver_total.reg;
+                               break;
+                       case V_ADDR_INDEX:
+                               reg_value =
+                                   IGA2_VER_ADDR_FORMULA(device_timing.
+                                                         ver_addr);
+                               viafb_load_reg_num =
+                                       iga2_crtc_reg.ver_addr.reg_num;
+                               reg = iga2_crtc_reg.ver_addr.reg;
+                               break;
+                       case V_BLANK_START_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_START_FORMULA
+                                   (device_timing.ver_blank_start);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.ver_blank_start.reg_num;
+                               reg = iga2_crtc_reg.ver_blank_start.reg;
+                               break;
+                       case V_BLANK_END_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_END_FORMULA
+                                   (device_timing.ver_blank_start,
+                                    device_timing.ver_blank_end);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.ver_blank_end.reg_num;
+                               reg = iga2_crtc_reg.ver_blank_end.reg;
+                               break;
+                       case V_SYNC_START_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_START_FORMULA
+                                   (device_timing.ver_sync_start);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.ver_sync_start.reg_num;
+                               reg = iga2_crtc_reg.ver_sync_start.reg;
+                               break;
+                       case V_SYNC_END_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_END_FORMULA
+                                   (device_timing.ver_sync_start,
+                                    device_timing.ver_sync_end);
+                               viafb_load_reg_num =
+                                   iga2_crtc_reg.ver_sync_end.reg_num;
+                               reg = iga2_crtc_reg.ver_sync_end.reg;
+                               break;
+
+                       }
+               }
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+       }
+
+       viafb_lock_crt();
+}
+
+void viafb_set_color_depth(int bpp_byte, int set_iga)
+{
+       if (set_iga == IGA1) {
+               switch (bpp_byte) {
+               case MODE_8BPP:
+                       viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
+                       break;
+               case MODE_16BPP:
+                       viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
+                       break;
+               case MODE_32BPP:
+                       viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
+                       break;
+               }
+       } else {
+               switch (bpp_byte) {
+               case MODE_8BPP:
+                       viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
+                       break;
+               case MODE_16BPP:
+                       viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
+                       break;
+               case MODE_32BPP:
+                       viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
+                       break;
+               }
+       }
+}
+
+void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
+       int mode_index, int bpp_byte, int set_iga)
+{
+       struct VideoModeTable *video_mode;
+       struct display_timing crt_reg;
+       int i;
+       int index = 0;
+       int h_addr, v_addr;
+       u32 pll_D_N;
+
+       video_mode = &CLE266Modes[search_mode_setting(mode_index)];
+
+       for (i = 0; i < video_mode->mode_array; i++) {
+               index = i;
+
+               if (crt_table[i].refresh_rate == viaparinfo->
+                       crt_setting_info->refresh_rate)
+                       break;
+       }
+
+       crt_reg = crt_table[index].crtc;
+
+       /* Mode 640x480 has border, but LCD/DFP didn't have border. */
+       /* So we would delete border. */
+       if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480)
+           && (viaparinfo->crt_setting_info->refresh_rate == 60)) {
+               /* The border is 8 pixels. */
+               crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
+
+               /* Blanking time should add left and right borders. */
+               crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
+       }
+
+       h_addr = crt_reg.hor_addr;
+       v_addr = crt_reg.ver_addr;
+
+       /* update polarity for CRT timing */
+       if (crt_table[index].h_sync_polarity == NEGATIVE) {
+               if (crt_table[index].v_sync_polarity == NEGATIVE)
+                       outb((inb(VIARMisc) & (~(BIT6 + BIT7))) |
+                            (BIT6 + BIT7), VIAWMisc);
+               else
+                       outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6),
+                            VIAWMisc);
+       } else {
+               if (crt_table[index].v_sync_polarity == NEGATIVE)
+                       outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7),
+                            VIAWMisc);
+               else
+                       outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc);
+       }
+
+       if (set_iga == IGA1) {
+               viafb_unlock_crt();
+               viafb_write_reg(CR09, VIACR, 0x00);     /*initial CR09=0 */
+               viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
+               viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+       }
+
+       switch (set_iga) {
+       case IGA1:
+               viafb_load_crtc_timing(crt_reg, IGA1);
+               break;
+       case IGA2:
+               viafb_load_crtc_timing(crt_reg, IGA2);
+               break;
+       }
+
+       load_fix_bit_crtc_reg();
+       viafb_lock_crt();
+       viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+       viafb_load_offset_reg(h_addr, bpp_byte, set_iga);
+       viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
+
+       /* load FIFO */
+       if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+           && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+               viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
+
+       /* load SR Register About Memory and Color part */
+       viafb_set_color_depth(bpp_byte, set_iga);
+
+       pll_D_N = viafb_get_clk_value(crt_table[index].clk);
+       DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
+       viafb_set_vclock(pll_D_N, set_iga);
+
+}
+
+void viafb_init_chip_info(void)
+{
+       init_gfx_chip_info();
+       init_tmds_chip_info();
+       init_lvds_chip_info();
+
+       viaparinfo->crt_setting_info->iga_path = IGA1;
+       viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
+
+       /*Set IGA path for each device */
+       viafb_set_iga_path();
+
+       viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
+       viaparinfo->lvds_setting_info->get_lcd_size_method =
+               GET_LCD_SIZE_BY_USER_SETTING;
+       viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
+       viaparinfo->lvds_setting_info2->display_method =
+               viaparinfo->lvds_setting_info->display_method;
+       viaparinfo->lvds_setting_info2->lcd_mode =
+               viaparinfo->lvds_setting_info->lcd_mode;
+}
+
+void viafb_update_device_setting(int hres, int vres,
+       int bpp, int vmode_refresh, int flag)
+{
+       if (flag == 0) {
+               viaparinfo->crt_setting_info->h_active = hres;
+               viaparinfo->crt_setting_info->v_active = vres;
+               viaparinfo->crt_setting_info->bpp = bpp;
+               viaparinfo->crt_setting_info->refresh_rate =
+                       vmode_refresh;
+
+               viaparinfo->tmds_setting_info->h_active = hres;
+               viaparinfo->tmds_setting_info->v_active = vres;
+               viaparinfo->tmds_setting_info->bpp = bpp;
+               viaparinfo->tmds_setting_info->refresh_rate =
+                       vmode_refresh;
+
+               viaparinfo->lvds_setting_info->h_active = hres;
+               viaparinfo->lvds_setting_info->v_active = vres;
+               viaparinfo->lvds_setting_info->bpp = bpp;
+               viaparinfo->lvds_setting_info->refresh_rate =
+                       vmode_refresh;
+               viaparinfo->lvds_setting_info2->h_active = hres;
+               viaparinfo->lvds_setting_info2->v_active = vres;
+               viaparinfo->lvds_setting_info2->bpp = bpp;
+               viaparinfo->lvds_setting_info2->refresh_rate =
+                       vmode_refresh;
+       } else {
+
+               if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
+                       viaparinfo->tmds_setting_info->h_active = hres;
+                       viaparinfo->tmds_setting_info->v_active = vres;
+                       viaparinfo->tmds_setting_info->bpp = bpp;
+                       viaparinfo->tmds_setting_info->refresh_rate =
+                               vmode_refresh;
+               }
+
+               if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
+                       viaparinfo->lvds_setting_info->h_active = hres;
+                       viaparinfo->lvds_setting_info->v_active = vres;
+                       viaparinfo->lvds_setting_info->bpp = bpp;
+                       viaparinfo->lvds_setting_info->refresh_rate =
+                               vmode_refresh;
+               }
+               if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
+                       viaparinfo->lvds_setting_info2->h_active = hres;
+                       viaparinfo->lvds_setting_info2->v_active = vres;
+                       viaparinfo->lvds_setting_info2->bpp = bpp;
+                       viaparinfo->lvds_setting_info2->refresh_rate =
+                               vmode_refresh;
+               }
+       }
+}
+
+static void init_gfx_chip_info(void)
+{
+       struct pci_dev *pdev = NULL;
+       u32 i;
+       u8 tmp;
+
+       /* Indentify GFX Chip Name */
+       for (i = 0; pciidlist[i].vendor != 0; i++) {
+               pdev = pci_get_device(pciidlist[i].vendor,
+                       pciidlist[i].device, 0);
+               if (pdev)
+                       break;
+       }
+
+       if (!pciidlist[i].vendor)
+               return ;
+
+       viaparinfo->chip_info->gfx_chip_name = pciidlist[i].chip_index;
+
+       /* Check revision of CLE266 Chip */
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               /* CR4F only define in CLE266.CX chip */
+               tmp = viafb_read_reg(VIACR, CR4F);
+               viafb_write_reg(CR4F, VIACR, 0x55);
+               if (viafb_read_reg(VIACR, CR4F) != 0x55)
+                       viaparinfo->chip_info->gfx_chip_revision =
+                       CLE266_REVISION_AX;
+               else
+                       viaparinfo->chip_info->gfx_chip_revision =
+                       CLE266_REVISION_CX;
+               /* restore orignal CR4F value */
+               viafb_write_reg(CR4F, VIACR, tmp);
+       }
+
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+               tmp = viafb_read_reg(VIASR, SR43);
+               DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
+               if (tmp & 0x02) {
+                       viaparinfo->chip_info->gfx_chip_revision =
+                               CX700_REVISION_700M2;
+               } else if (tmp & 0x40) {
+                       viaparinfo->chip_info->gfx_chip_revision =
+                               CX700_REVISION_700M;
+               } else {
+                       viaparinfo->chip_info->gfx_chip_revision =
+                               CX700_REVISION_700;
+               }
+       }
+
+       pci_dev_put(pdev);
+}
+
+static void init_tmds_chip_info(void)
+{
+       viafb_tmds_trasmitter_identify();
+
+       if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
+               output_interface) {
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CX700:
+                       {
+                               /* we should check support by hardware layout.*/
+                               if ((viafb_display_hardware_layout ==
+                                    HW_LAYOUT_DVI_ONLY)
+                                   || (viafb_display_hardware_layout ==
+                                       HW_LAYOUT_LCD_DVI)) {
+                                       viaparinfo->chip_info->tmds_chip_info.
+                                           output_interface = INTERFACE_TMDS;
+                               } else {
+                                       viaparinfo->chip_info->tmds_chip_info.
+                                               output_interface =
+                                               INTERFACE_NONE;
+                               }
+                               break;
+                       }
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M900:
+               case UNICHROME_P4M890:
+                       /* TMDS on PCIE, we set DFPLOW as default. */
+                       viaparinfo->chip_info->tmds_chip_info.output_interface =
+                           INTERFACE_DFP_LOW;
+                       break;
+               default:
+                       {
+                               /* set DVP1 default for DVI */
+                               viaparinfo->chip_info->tmds_chip_info
+                               .output_interface = INTERFACE_DVP1;
+                       }
+               }
+       }
+
+       DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
+                 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
+       viaparinfo->tmds_setting_info->get_dvi_size_method =
+               GET_DVI_SIZE_BY_VGA_BIOS;
+       viafb_init_dvi_size();
+}
+
+static void init_lvds_chip_info(void)
+{
+       if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
+               viaparinfo->lvds_setting_info->get_lcd_size_method =
+                   GET_LCD_SIZE_BY_VGA_BIOS;
+       else
+               viaparinfo->lvds_setting_info->get_lcd_size_method =
+                   GET_LCD_SIZE_BY_USER_SETTING;
+
+       viafb_lvds_trasmitter_identify();
+       viafb_init_lcd_size();
+       viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
+                                  viaparinfo->lvds_setting_info);
+       if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+               viafb_init_lvds_output_interface(&viaparinfo->chip_info->
+                       lvds_chip_info2, viaparinfo->lvds_setting_info2);
+       }
+       /*If CX700,two singel LCD, we need to reassign
+          LCD interface to different LVDS port */
+       if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
+           && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
+               if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
+                       lvds_chip_name) && (INTEGRATED_LVDS ==
+                       viaparinfo->chip_info->
+                       lvds_chip_info2.lvds_chip_name)) {
+                       viaparinfo->chip_info->lvds_chip_info.output_interface =
+                               INTERFACE_LVDS0;
+                       viaparinfo->chip_info->lvds_chip_info2.
+                               output_interface =
+                           INTERFACE_LVDS1;
+               }
+       }
+
+       DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
+                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+       DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
+                 viaparinfo->chip_info->lvds_chip_info.output_interface);
+       DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
+                 viaparinfo->chip_info->lvds_chip_info.output_interface);
+}
+
+void viafb_init_dac(int set_iga)
+{
+       int i;
+       u8 tmp;
+
+       if (set_iga == IGA1) {
+               /* access Primary Display's LUT */
+               viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+               /* turn off LCK */
+               viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
+               for (i = 0; i < 256; i++) {
+                       write_dac_reg(i, palLUT_table[i].red,
+                                     palLUT_table[i].green,
+                                     palLUT_table[i].blue);
+               }
+               /* turn on LCK */
+               viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
+       } else {
+               tmp = viafb_read_reg(VIACR, CR6A);
+               /* access Secondary Display's LUT */
+               viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
+               viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+               for (i = 0; i < 256; i++) {
+                       write_dac_reg(i, palLUT_table[i].red,
+                                     palLUT_table[i].green,
+                                     palLUT_table[i].blue);
+               }
+               /* set IGA1 DAC for default */
+               viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
+               viafb_write_reg(CR6A, VIACR, tmp);
+       }
+}
+
+static void device_screen_off(void)
+{
+       /* turn off CRT screen (IGA1) */
+       viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
+}
+
+static void device_screen_on(void)
+{
+       /* turn on CRT screen (IGA1) */
+       viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
+}
+
+static void set_display_channel(void)
+{
+       /*If viafb_LCD2_ON, on cx700, internal lvds's information
+       is keeped on lvds_setting_info2 */
+       if (viafb_LCD2_ON &&
+               viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
+               /* For dual channel LCD: */
+               /* Set to Dual LVDS channel. */
+               viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+       } else if (viafb_LCD_ON && viafb_DVI_ON) {
+               /* For LCD+DFP: */
+               /* Set to LVDS1 + TMDS channel. */
+               viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
+       } else if (viafb_DVI_ON) {
+               /* Set to single TMDS channel. */
+               viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
+       } else if (viafb_LCD_ON) {
+               if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
+                       /* For dual channel LCD: */
+                       /* Set to Dual LVDS channel. */
+                       viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
+               } else {
+                       /* Set to LVDS0 + LVDS1 channel. */
+                       viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
+               }
+       }
+}
+
+int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
+       int vmode_index1, int hor_res1, int ver_res1, int video_bpp1)
+{
+       int i, j;
+       int port;
+       u8 value, index, mask;
+       struct VideoModeTable *vmode_tbl;
+       struct crt_mode_table *crt_timing;
+       struct VideoModeTable *vmode_tbl1 = NULL;
+       struct crt_mode_table *crt_timing1 = NULL;
+
+       DEBUG_MSG(KERN_INFO "Set Mode!!\n");
+       DEBUG_MSG(KERN_INFO
+                 "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
+                 vmode_index, hor_res, ver_res, video_bpp);
+
+       device_screen_off();
+       vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
+       crt_timing = vmode_tbl->crtc;
+
+       if (viafb_SAMM_ON == 1) {
+               vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
+               crt_timing1 = vmode_tbl1->crtc;
+       }
+
+       inb(VIAStatus);
+       outb(0x00, VIAAR);
+
+       /* Write Common Setting for Video Mode */
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_CLE266:
+               viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
+               break;
+
+       case UNICHROME_K400:
+               viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
+               break;
+
+       case UNICHROME_K800:
+       case UNICHROME_PM800:
+               viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
+               break;
+
+       case UNICHROME_CN700:
+       case UNICHROME_K8M890:
+       case UNICHROME_P4M890:
+       case UNICHROME_P4M900:
+               viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
+               break;
+
+       case UNICHROME_CX700:
+               viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
+
+       case UNICHROME_VX800:
+               viafb_write_regx(VX800_ModeXregs, NUM_TOTAL_VX800_ModeXregs);
+
+               break;
+       }
+
+       device_off();
+
+       /* Fill VPIT Parameters */
+       /* Write Misc Register */
+       outb(VPIT.Misc, VIAWMisc);
+
+       /* Write Sequencer */
+       for (i = 1; i <= StdSR; i++) {
+               outb(i, VIASR);
+               outb(VPIT.SR[i - 1], VIASR + 1);
+       }
+
+       viafb_set_start_addr();
+       viafb_set_iga_path();
+
+       /* Write CRTC */
+       viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1);
+
+       /* Write Graphic Controller */
+       for (i = 0; i < StdGR; i++) {
+               outb(i, VIAGR);
+               outb(VPIT.GR[i], VIAGR + 1);
+       }
+
+       /* Write Attribute Controller */
+       for (i = 0; i < StdAR; i++) {
+               inb(VIAStatus);
+               outb(i, VIAAR);
+               outb(VPIT.AR[i], VIAAR);
+       }
+
+       inb(VIAStatus);
+       outb(0x20, VIAAR);
+
+       /* Update Patch Register */
+
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+           || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) {
+               for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
+                       if (res_patch_table[i].mode_index == vmode_index) {
+                               for (j = 0;
+                                    j < res_patch_table[i].table_length; j++) {
+                                       index =
+                                           res_patch_table[i].
+                                           io_reg_table[j].index;
+                                       port =
+                                           res_patch_table[i].
+                                           io_reg_table[j].port;
+                                       value =
+                                           res_patch_table[i].
+                                           io_reg_table[j].value;
+                                       mask =
+                                           res_patch_table[i].
+                                           io_reg_table[j].mask;
+                                       viafb_write_reg_mask(index, port, value,
+                                                      mask);
+                               }
+                       }
+               }
+       }
+
+       if (viafb_SAMM_ON == 1) {
+               if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
+                   || (viaparinfo->chip_info->gfx_chip_name ==
+                   UNICHROME_K400)) {
+                       for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
+                               if (res_patch_table[i].mode_index ==
+                                   vmode_index1) {
+                                       for (j = 0;
+                                            j <
+                                            res_patch_table[i].
+                                            table_length; j++) {
+                                               index =
+                                                   res_patch_table[i].
+                                                   io_reg_table[j].index;
+                                               port =
+                                                   res_patch_table[i].
+                                                   io_reg_table[j].port;
+                                               value =
+                                                   res_patch_table[i].
+                                                   io_reg_table[j].value;
+                                               mask =
+                                                   res_patch_table[i].
+                                                   io_reg_table[j].mask;
+                                               viafb_write_reg_mask(index,
+                                                       port, value, mask);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* Update Refresh Rate Setting */
+
+       /* Clear On Screen */
+
+       /* CRT set mode */
+       if (viafb_CRT_ON) {
+               if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
+                       IGA2)) {
+                       viafb_fill_crtc_timing(crt_timing1, vmode_index1,
+                               video_bpp1 / 8,
+                               viaparinfo->crt_setting_info->iga_path);
+               } else {
+                       viafb_fill_crtc_timing(crt_timing, vmode_index,
+                               video_bpp / 8,
+                               viaparinfo->crt_setting_info->iga_path);
+               }
+
+               set_crt_output_path(viaparinfo->crt_setting_info->iga_path);
+
+               /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
+               to 8 alignment (1368),there is several pixels (2 pixels)
+               on right side of screen. */
+               if (hor_res % 8) {
+                       viafb_unlock_crt();
+                       viafb_write_reg(CR02, VIACR,
+                               viafb_read_reg(VIACR, CR02) - 1);
+                       viafb_lock_crt();
+               }
+       }
+
+       if (viafb_DVI_ON) {
+               if (viafb_SAMM_ON &&
+                       (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
+                       viafb_dvi_set_mode(viafb_get_mode_index
+                                    (viaparinfo->tmds_setting_info->h_active,
+                                     viaparinfo->tmds_setting_info->
+                                     v_active, 1),
+                                    video_bpp1, viaparinfo->
+                                    tmds_setting_info->iga_path);
+               } else {
+                       viafb_dvi_set_mode(viafb_get_mode_index
+                                    (viaparinfo->tmds_setting_info->h_active,
+                                     viaparinfo->
+                                     tmds_setting_info->v_active, 0),
+                                    video_bpp, viaparinfo->
+                                    tmds_setting_info->iga_path);
+               }
+       }
+
+       if (viafb_LCD_ON) {
+               if (viafb_SAMM_ON &&
+                       (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
+                       viaparinfo->lvds_setting_info->bpp = video_bpp1;
+                       viafb_lcd_set_mode(crt_timing1, viaparinfo->
+                               lvds_setting_info,
+                                    &viaparinfo->chip_info->lvds_chip_info);
+               } else {
+                       /* IGA1 doesn't have LCD scaling, so set it center. */
+                       if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+                               viaparinfo->lvds_setting_info->display_method =
+                                   LCD_CENTERING;
+                       }
+                       viaparinfo->lvds_setting_info->bpp = video_bpp;
+                       viafb_lcd_set_mode(crt_timing, viaparinfo->
+                               lvds_setting_info,
+                                    &viaparinfo->chip_info->lvds_chip_info);
+               }
+       }
+       if (viafb_LCD2_ON) {
+               if (viafb_SAMM_ON &&
+                       (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
+                       viaparinfo->lvds_setting_info2->bpp = video_bpp1;
+                       viafb_lcd_set_mode(crt_timing1, viaparinfo->
+                               lvds_setting_info2,
+                                    &viaparinfo->chip_info->lvds_chip_info2);
+               } else {
+                       /* IGA1 doesn't have LCD scaling, so set it center. */
+                       if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+                               viaparinfo->lvds_setting_info2->display_method =
+                                   LCD_CENTERING;
+                       }
+                       viaparinfo->lvds_setting_info2->bpp = video_bpp;
+                       viafb_lcd_set_mode(crt_timing, viaparinfo->
+                               lvds_setting_info2,
+                                    &viaparinfo->chip_info->lvds_chip_info2);
+               }
+       }
+
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+           && (viafb_LCD_ON || viafb_DVI_ON))
+               set_display_channel();
+
+       /* If set mode normally, save resolution information for hot-plug . */
+       if (!viafb_hotplug) {
+               viafb_hotplug_Xres = hor_res;
+               viafb_hotplug_Yres = ver_res;
+               viafb_hotplug_bpp = video_bpp;
+               viafb_hotplug_refresh = viafb_refresh;
+
+               if (viafb_DVI_ON)
+                       viafb_DeviceStatus = DVI_Device;
+               else
+                       viafb_DeviceStatus = CRT_Device;
+       }
+       device_on();
+
+       if (viafb_SAMM_ON == 1)
+               viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
+
+       device_screen_on();
+       return 1;
+}
+
+int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
+{
+       int i;
+
+       for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
+               if ((hres == res_map_refresh_tbl[i].hres)
+                   && (vres == res_map_refresh_tbl[i].vres)
+                   && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
+                       return res_map_refresh_tbl[i].pixclock;
+       }
+       return RES_640X480_60HZ_PIXCLOCK;
+
+}
+
+int viafb_get_refresh(int hres, int vres, u32 long_refresh)
+{
+#define REFRESH_TOLERANCE 3
+       int i, nearest = -1, diff = REFRESH_TOLERANCE;
+       for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
+               if ((hres == res_map_refresh_tbl[i].hres)
+                   && (vres == res_map_refresh_tbl[i].vres)
+                   && (diff > (abs(long_refresh -
+                   res_map_refresh_tbl[i].vmode_refresh)))) {
+                       diff = abs(long_refresh - res_map_refresh_tbl[i].
+                               vmode_refresh);
+                       nearest = i;
+               }
+       }
+#undef REFRESH_TOLERANCE
+       if (nearest > 0)
+               return res_map_refresh_tbl[nearest].vmode_refresh;
+       return 60;
+}
+
+static void device_off(void)
+{
+       viafb_crt_disable();
+       viafb_dvi_disable();
+       viafb_lcd_disable();
+}
+
+static void device_on(void)
+{
+       if (viafb_CRT_ON == 1)
+               viafb_crt_enable();
+       if (viafb_DVI_ON == 1)
+               viafb_dvi_enable();
+       if (viafb_LCD_ON == 1)
+               viafb_lcd_enable();
+}
+
+void viafb_crt_disable(void)
+{
+       viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
+}
+
+void viafb_crt_enable(void)
+{
+       viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
+}
+
+void viafb_get_mmio_info(unsigned long *mmio_base,
+       unsigned long *mmio_len)
+{
+       struct pci_dev *pdev = NULL;
+       u32 vendor, device;
+       u32 i;
+
+       for (i = 0; pciidlist[i].vendor != 0; i++)
+               if (viaparinfo->chip_info->gfx_chip_name ==
+                       pciidlist[i].chip_index)
+                       break;
+
+       if (!pciidlist[i].vendor)
+               return ;
+
+       vendor = pciidlist[i].vendor;
+       device = pciidlist[i].device;
+
+       pdev = pci_get_device(vendor, device, NULL);
+
+       if (!pdev) {
+               *mmio_base = 0;
+               *mmio_len = 0;
+               return ;
+       }
+
+       *mmio_base = pci_resource_start(pdev, 1);
+       *mmio_len = pci_resource_len(pdev, 1);
+
+       pci_dev_put(pdev);
+}
+
+static void enable_second_display_channel(void)
+{
+       /* to enable second display channel. */
+       viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+       viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
+       viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+static void disable_second_display_channel(void)
+{
+       /* to disable second display channel. */
+       viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
+       viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
+       viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
+}
+
+void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len)
+{
+       struct pci_dev *pdev = NULL;
+       u32 vendor, device;
+       u32 i;
+
+       for (i = 0; pciidlist[i].vendor != 0; i++)
+               if (viaparinfo->chip_info->gfx_chip_name ==
+                       pciidlist[i].chip_index)
+                       break;
+
+       if (!pciidlist[i].vendor)
+               return ;
+
+       vendor = pciidlist[i].vendor;
+       device = pciidlist[i].device;
+
+       pdev = pci_get_device(vendor, device, NULL);
+
+       if (!pdev) {
+               *fb_base = viafb_read_reg(VIASR, SR30) << 24;
+               *fb_len = viafb_get_memsize();
+               DEBUG_MSG(KERN_INFO "Get FB info from SR30!\n");
+               DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+               DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+               return ;
+       }
+
+       *fb_base = (unsigned int)pci_resource_start(pdev, 0);
+       *fb_len = get_fb_size_from_pci();
+       DEBUG_MSG(KERN_INFO "Get FB info from PCI system!\n");
+       DEBUG_MSG(KERN_INFO "fb_base = %08x\n", *fb_base);
+       DEBUG_MSG(KERN_INFO "fb_len = %08x\n", *fb_len);
+
+       pci_dev_put(pdev);
+}
+
+static int get_fb_size_from_pci(void)
+{
+       unsigned long configid, deviceid, FBSize = 0;
+       int VideoMemSize;
+       int DeviceFound = false;
+
+       for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
+               outl(configid, (unsigned long)0xCF8);
+               deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
+
+               switch (deviceid) {
+               case CLE266:
+               case KM400:
+                       outl(configid + 0xE0, (unsigned long)0xCF8);
+                       FBSize = inl((unsigned long)0xCFC);
+                       DeviceFound = true;     /* Found device id */
+                       break;
+
+               case CN400_FUNCTION3:
+               case CN700_FUNCTION3:
+               case CX700_FUNCTION3:
+               case KM800_FUNCTION3:
+               case KM890_FUNCTION3:
+               case P4M890_FUNCTION3:
+               case P4M900_FUNCTION3:
+               case VX800_FUNCTION3:
+                       /*case CN750_FUNCTION3: */
+                       outl(configid + 0xA0, (unsigned long)0xCF8);
+                       FBSize = inl((unsigned long)0xCFC);
+                       DeviceFound = true;     /* Found device id */
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (DeviceFound)
+                       break;
+       }
+
+       DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
+
+       FBSize = FBSize & 0x00007000;
+       DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
+
+       if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) {
+               switch (FBSize) {
+               case 0x00004000:
+                       VideoMemSize = (16 << 20);      /*16M */
+                       break;
+
+               case 0x00005000:
+                       VideoMemSize = (32 << 20);      /*32M */
+                       break;
+
+               case 0x00006000:
+                       VideoMemSize = (64 << 20);      /*64M */
+                       break;
+
+               default:
+                       VideoMemSize = (32 << 20);      /*32M */
+                       break;
+               }
+       } else {
+               switch (FBSize) {
+               case 0x00001000:
+                       VideoMemSize = (8 << 20);       /*8M */
+                       break;
+
+               case 0x00002000:
+                       VideoMemSize = (16 << 20);      /*16M */
+                       break;
+
+               case 0x00003000:
+                       VideoMemSize = (32 << 20);      /*32M */
+                       break;
+
+               case 0x00004000:
+                       VideoMemSize = (64 << 20);      /*64M */
+                       break;
+
+               case 0x00005000:
+                       VideoMemSize = (128 << 20);     /*128M */
+                       break;
+
+               case 0x00006000:
+                       VideoMemSize = (256 << 20);     /*256M */
+                       break;
+
+               default:
+                       VideoMemSize = (32 << 20);      /*32M */
+                       break;
+               }
+       }
+
+       return VideoMemSize;
+}
+
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+                                       *p_gfx_dpa_setting)
+{
+       switch (output_interface) {
+       case INTERFACE_DVP0:
+               {
+                       /* DVP0 Clock Polarity and Adjust: */
+                       viafb_write_reg_mask(CR96, VIACR,
+                                      p_gfx_dpa_setting->DVP0, 0x0F);
+
+                       /* DVP0 Clock and Data Pads Driving: */
+                       viafb_write_reg_mask(SR1E, VIASR,
+                                      p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
+                       viafb_write_reg_mask(SR2A, VIASR,
+                                      p_gfx_dpa_setting->DVP0ClockDri_S1,
+                                      BIT4);
+                       viafb_write_reg_mask(SR1B, VIASR,
+                                      p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
+                       viafb_write_reg_mask(SR2A, VIASR,
+                                      p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
+                       break;
+               }
+
+       case INTERFACE_DVP1:
+               {
+                       /* DVP1 Clock Polarity and Adjust: */
+                       viafb_write_reg_mask(CR9B, VIACR,
+                                      p_gfx_dpa_setting->DVP1, 0x0F);
+
+                       /* DVP1 Clock and Data Pads Driving: */
+                       viafb_write_reg_mask(SR65, VIASR,
+                                      p_gfx_dpa_setting->DVP1Driving, 0x0F);
+                       break;
+               }
+
+       case INTERFACE_DFP_HIGH:
+               {
+                       viafb_write_reg_mask(CR97, VIACR,
+                                      p_gfx_dpa_setting->DFPHigh, 0x0F);
+                       break;
+               }
+
+       case INTERFACE_DFP_LOW:
+               {
+                       viafb_write_reg_mask(CR99, VIACR,
+                                      p_gfx_dpa_setting->DFPLow, 0x0F);
+                       break;
+               }
+
+       case INTERFACE_DFP:
+               {
+                       viafb_write_reg_mask(CR97, VIACR,
+                                      p_gfx_dpa_setting->DFPHigh, 0x0F);
+                       viafb_write_reg_mask(CR99, VIACR,
+                                      p_gfx_dpa_setting->DFPLow, 0x0F);
+                       break;
+               }
+       }
+}
+
+void viafb_memory_pitch_patch(struct fb_info *info)
+{
+       if (info->var.xres != info->var.xres_virtual) {
+               viafb_load_offset_reg(info->var.xres_virtual,
+                               info->var.bits_per_pixel >> 3, IGA1);
+
+               if (viafb_SAMM_ON) {
+                       viafb_load_offset_reg(viafb_second_virtual_xres,
+                               viafb_bpp1 >> 3,
+                                       IGA2);
+               } else {
+                       viafb_load_offset_reg(info->var.xres_virtual,
+                                       info->var.bits_per_pixel >> 3, IGA2);
+               }
+
+       }
+}
+
+/*According var's xres, yres fill var's other timing information*/
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
+                         int mode_index)
+{
+       struct VideoModeTable *vmode_tbl = NULL;
+       struct crt_mode_table *crt_timing = NULL;
+       struct display_timing crt_reg;
+       int i = 0, index = 0;
+       vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
+       crt_timing = vmode_tbl->crtc;
+       for (i = 0; i < vmode_tbl->mode_array; i++) {
+               index = i;
+               if (crt_timing[i].refresh_rate == refresh)
+                       break;
+       }
+
+       crt_reg = crt_timing[index].crtc;
+       switch (var->bits_per_pixel) {
+       case 8:
+               var->red.offset = 0;
+               var->green.offset = 0;
+               var->blue.offset = 0;
+               var->red.length = 6;
+               var->green.length = 6;
+               var->blue.length = 6;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 6;
+               var->blue.length = 5;
+               break;
+       case 32:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               break;
+       default:
+               /* never happed, put here to keep consistent */
+               break;
+       }
+
+       var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
+       var->left_margin =
+           crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
+       var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
+       var->hsync_len = crt_reg.hor_sync_end;
+       var->upper_margin =
+           crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
+       var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
+       var->vsync_len = crt_reg.ver_sync_end;
+}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
new file mode 100644 (file)
index 0000000..6ff38fa
--- /dev/null
@@ -0,0 +1,933 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __HW_H__
+#define __HW_H__
+
+#include "global.h"
+
+/***************************************************
+* Definition IGA1 Design Method of CRTC Registers *
+****************************************************/
+#define IGA1_HOR_TOTAL_FORMULA(x)           (((x)/8)-5)
+#define IGA1_HOR_ADDR_FORMULA(x)            (((x)/8)-1)
+#define IGA1_HOR_BLANK_START_FORMULA(x)     (((x)/8)-1)
+#define IGA1_HOR_BLANK_END_FORMULA(x, y)     (((x+y)/8)-1)
+#define IGA1_HOR_SYNC_START_FORMULA(x)      ((x)/8)
+#define IGA1_HOR_SYNC_END_FORMULA(x, y)      ((x+y)/8)
+
+#define IGA1_VER_TOTAL_FORMULA(x)           ((x)-2)
+#define IGA1_VER_ADDR_FORMULA(x)            ((x)-1)
+#define IGA1_VER_BLANK_START_FORMULA(x)     ((x)-1)
+#define IGA1_VER_BLANK_END_FORMULA(x, y)     ((x+y)-1)
+#define IGA1_VER_SYNC_START_FORMULA(x)      ((x)-1)
+#define IGA1_VER_SYNC_END_FORMULA(x, y)      ((x+y)-1)
+
+/***************************************************
+** Definition IGA2 Design Method of CRTC Registers *
+****************************************************/
+#define IGA2_HOR_TOTAL_FORMULA(x)           ((x)-1)
+#define IGA2_HOR_ADDR_FORMULA(x)            ((x)-1)
+#define IGA2_HOR_BLANK_START_FORMULA(x)     ((x)-1)
+#define IGA2_HOR_BLANK_END_FORMULA(x, y)     ((x+y)-1)
+#define IGA2_HOR_SYNC_START_FORMULA(x)      ((x)-1)
+#define IGA2_HOR_SYNC_END_FORMULA(x, y)      ((x+y)-1)
+
+#define IGA2_VER_TOTAL_FORMULA(x)           ((x)-1)
+#define IGA2_VER_ADDR_FORMULA(x)            ((x)-1)
+#define IGA2_VER_BLANK_START_FORMULA(x)     ((x)-1)
+#define IGA2_VER_BLANK_END_FORMULA(x, y)     ((x+y)-1)
+#define IGA2_VER_SYNC_START_FORMULA(x)      ((x)-1)
+#define IGA2_VER_SYNC_END_FORMULA(x, y)      ((x+y)-1)
+
+/**********************************************************/
+/* Definition IGA2 Design Method of CRTC Shadow Registers */
+/**********************************************************/
+#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x)           ((x/8)-5)
+#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y)     (((x+y)/8)-1)
+#define IGA2_VER_TOTAL_SHADOW_FORMULA(x)           ((x)-2)
+#define IGA2_VER_ADDR_SHADOW_FORMULA(x)            ((x)-1)
+#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x)     ((x)-1)
+#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y)     ((x+y)-1)
+#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x)      (x)
+#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y)      (x+y)
+
+/* Define Register Number for IGA1 CRTC Timing */
+
+/* location: {CR00,0,7},{CR36,3,3} */
+#define IGA1_HOR_TOTAL_REG_NUM         2
+/* location: {CR01,0,7} */
+#define IGA1_HOR_ADDR_REG_NUM          1
+/* location: {CR02,0,7} */
+#define IGA1_HOR_BLANK_START_REG_NUM    1
+/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
+#define IGA1_HOR_BLANK_END_REG_NUM     3
+/* location: {CR04,0,7},{CR33,4,4} */
+#define IGA1_HOR_SYNC_START_REG_NUM    2
+/* location: {CR05,0,4} */
+#define IGA1_HOR_SYNC_END_REG_NUM       1
+/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
+#define IGA1_VER_TOTAL_REG_NUM          4
+/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
+#define IGA1_VER_ADDR_REG_NUM           4
+/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
+#define IGA1_VER_BLANK_START_REG_NUM    4
+/* location: {CR16,0,7} */
+#define IGA1_VER_BLANK_END_REG_NUM      1
+/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
+#define IGA1_VER_SYNC_START_REG_NUM     4
+/* location: {CR11,0,3} */
+#define IGA1_VER_SYNC_END_REG_NUM       1
+
+/* Define Register Number for IGA2 Shadow CRTC Timing */
+
+/* location: {CR6D,0,7},{CR71,3,3} */
+#define IGA2_SHADOW_HOR_TOTAL_REG_NUM       2
+/* location: {CR6E,0,7} */
+#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM   1
+/* location: {CR6F,0,7},{CR71,0,2} */
+#define IGA2_SHADOW_VER_TOTAL_REG_NUM       2
+/* location: {CR70,0,7},{CR71,4,6} */
+#define IGA2_SHADOW_VER_ADDR_REG_NUM        2
+/* location: {CR72,0,7},{CR74,4,6} */
+#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
+/* location: {CR73,0,7},{CR74,0,2} */
+#define IGA2_SHADOW_VER_BLANK_END_REG_NUM   2
+/* location: {CR75,0,7},{CR76,4,6} */
+#define IGA2_SHADOW_VER_SYNC_START_REG_NUM  2
+/* location: {CR76,0,3} */
+#define IGA2_SHADOW_VER_SYNC_END_REG_NUM    1
+
+/* Define Register Number for IGA2 CRTC Timing */
+
+/* location: {CR50,0,7},{CR55,0,3} */
+#define IGA2_HOR_TOTAL_REG_NUM          2
+/* location: {CR51,0,7},{CR55,4,6} */
+#define IGA2_HOR_ADDR_REG_NUM           2
+/* location: {CR52,0,7},{CR54,0,2} */
+#define IGA2_HOR_BLANK_START_REG_NUM    2
+/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
+is reserved, so it may have problem to set 1600x1200 on IGA2. */
+/*             Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
+#define IGA2_HOR_BLANK_END_REG_NUM      3
+/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
+/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
+#define IGA2_HOR_SYNC_START_REG_NUM     4
+
+/* location: {CR57,0,7},{CR5C,6,6} */
+#define IGA2_HOR_SYNC_END_REG_NUM       2
+/* location: {CR58,0,7},{CR5D,0,2} */
+#define IGA2_VER_TOTAL_REG_NUM          2
+/* location: {CR59,0,7},{CR5D,3,5} */
+#define IGA2_VER_ADDR_REG_NUM           2
+/* location: {CR5A,0,7},{CR5C,0,2} */
+#define IGA2_VER_BLANK_START_REG_NUM    2
+/* location: {CR5E,0,7},{CR5C,3,5} */
+#define IGA2_VER_BLANK_END_REG_NUM      2
+/* location: {CR5E,0,7},{CR5F,5,7} */
+#define IGA2_VER_SYNC_START_REG_NUM     2
+/* location: {CR5F,0,4} */
+#define IGA2_VER_SYNC_END_REG_NUM       1
+
+/* Define Offset and Fetch Count Register*/
+
+/* location: {CR13,0,7},{CR35,5,7} */
+#define IGA1_OFFSET_REG_NUM             2
+/* 8 bytes alignment. */
+#define IGA1_OFFSER_ALIGN_BYTE          8
+/* x: H resolution, y: color depth */
+#define IGA1_OFFSET_FORMULA(x, y)        ((x*y)/IGA1_OFFSER_ALIGN_BYTE)
+/* location: {SR1C,0,7},{SR1D,0,1} */
+#define IGA1_FETCH_COUNT_REG_NUM        2
+/* 16 bytes alignment. */
+#define IGA1_FETCH_COUNT_ALIGN_BYTE     16
+/* x: H resolution, y: color depth */
+#define IGA1_FETCH_COUNT_PATCH_VALUE    4
+#define IGA1_FETCH_COUNT_FORMULA(x, y)   \
+       (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
+
+/* location: {CR66,0,7},{CR67,0,1} */
+#define IGA2_OFFSET_REG_NUM             2
+#define IGA2_OFFSET_ALIGN_BYTE          8
+/* x: H resolution, y: color depth */
+#define IGA2_OFFSET_FORMULA(x, y)        ((x*y)/IGA2_OFFSET_ALIGN_BYTE)
+/* location: {CR65,0,7},{CR67,2,3} */
+#define IGA2_FETCH_COUNT_REG_NUM        2
+#define IGA2_FETCH_COUNT_ALIGN_BYTE     16
+#define IGA2_FETCH_COUNT_PATCH_VALUE    0
+#define IGA2_FETCH_COUNT_FORMULA(x, y)   \
+       (((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
+
+/* Staring Address*/
+
+/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
+#define IGA1_STARTING_ADDR_REG_NUM      4
+/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
+#define IGA2_STARTING_ADDR_REG_NUM      3
+
+/* Define Display OFFSET*/
+/* These value are by HW suggested value*/
+/* location: {SR17,0,7} */
+#define K800_IGA1_FIFO_MAX_DEPTH                384
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K800_IGA1_FIFO_THRESHOLD                328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K800_IGA1_FIFO_HIGH_THRESHOLD           296
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+                               /* because HW only 5 bits */
+#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K800_IGA2_FIFO_MAX_DEPTH                384
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K800_IGA2_FIFO_THRESHOLD                328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K800_IGA2_FIFO_HIGH_THRESHOLD           296
+/* location: {CR94,0,6} */
+#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
+
+/* location: {SR17,0,7} */
+#define P880_IGA1_FIFO_MAX_DEPTH                192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P880_IGA1_FIFO_THRESHOLD                128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P880_IGA1_FIFO_HIGH_THRESHOLD           64
+/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
+                               /* because HW only 5 bits */
+#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      0
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P880_IGA2_FIFO_MAX_DEPTH                96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P880_IGA2_FIFO_THRESHOLD                64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P880_IGA2_FIFO_HIGH_THRESHOLD           32
+/* location: {CR94,0,6} */
+#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM      128
+
+/* VT3314 chipset*/
+
+/* location: {SR17,0,7} */
+#define CN700_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CN700_IGA1_FIFO_THRESHOLD               80
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CN700_IGA1_FIFO_HIGH_THRESHOLD          64
+/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
+                               because HW only 5 bits */
+#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     0
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CN700_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CN700_IGA2_FIFO_THRESHOLD               80
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CN700_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+/* For VT3324, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define CX700_IGA1_FIFO_MAX_DEPTH               192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define CX700_IGA1_FIFO_THRESHOLD               128
+/* location: {SR18,0,5},{SR18,7,7} */
+#define CX700_IGA1_FIFO_HIGH_THRESHOLD          128
+/* location: {SR22,0,4} */
+#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define CX700_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define CX700_IGA2_FIFO_THRESHOLD               64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define CX700_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+/* VT3336 chipset*/
+/* location: {SR17,0,7} */
+#define K8M890_IGA1_FIFO_MAX_DEPTH               360
+/* location: {SR16,0,5},{SR16,7,7} */
+#define K8M890_IGA1_FIFO_THRESHOLD               328
+/* location: {SR18,0,5},{SR18,7,7} */
+#define K8M890_IGA1_FIFO_HIGH_THRESHOLD          296
+/* location: {SR22,0,4}. */
+#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define K8M890_IGA2_FIFO_MAX_DEPTH               360
+/* location: {CR68,0,3},{CR95,4,6} */
+#define K8M890_IGA2_FIFO_THRESHOLD               328
+/* location: {CR92,0,3},{CR95,0,2} */
+#define K8M890_IGA2_FIFO_HIGH_THRESHOLD          296
+/* location: {CR94,0,6} */
+#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     124
+
+/* VT3327 chipset*/
+/* location: {SR17,0,7} */
+#define P4M890_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M890_IGA1_FIFO_THRESHOLD               76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M890_IGA1_FIFO_HIGH_THRESHOLD          64
+/* location: {SR22,0,4}. (32/4) =8 */
+#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M890_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M890_IGA2_FIFO_THRESHOLD               76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M890_IGA2_FIFO_HIGH_THRESHOLD          64
+/* location: {CR94,0,6} */
+#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
+
+/* VT3364 chipset*/
+/* location: {SR17,0,7} */
+#define P4M900_IGA1_FIFO_MAX_DEPTH               96
+/* location: {SR16,0,5},{SR16,7,7} */
+#define P4M900_IGA1_FIFO_THRESHOLD               76
+/* location: {SR18,0,5},{SR18,7,7} */
+#define P4M900_IGA1_FIFO_HIGH_THRESHOLD          76
+/* location: {SR22,0,4}. */
+#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM     32
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define P4M900_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define P4M900_IGA2_FIFO_THRESHOLD               76
+/* location: {CR92,0,3},{CR95,0,2} */
+#define P4M900_IGA2_FIFO_HIGH_THRESHOLD          76
+/* location: {CR94,0,6} */
+#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     32
+
+/* For VT3353, these values are suggested by HW */
+/* location: {SR17,0,7} */
+#define VX800_IGA1_FIFO_MAX_DEPTH               192
+/* location: {SR16,0,5},{SR16,7,7} */
+#define VX800_IGA1_FIFO_THRESHOLD               152
+/* location: {SR18,0,5},{SR18,7,7} */
+#define VX800_IGA1_FIFO_HIGH_THRESHOLD          152
+/* location: {SR22,0,4} */
+#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM      64
+/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
+#define VX800_IGA2_FIFO_MAX_DEPTH               96
+/* location: {CR68,0,3},{CR95,4,6} */
+#define VX800_IGA2_FIFO_THRESHOLD               64
+/* location: {CR92,0,3},{CR95,0,2} */
+#define VX800_IGA2_FIFO_HIGH_THRESHOLD          32
+/* location: {CR94,0,6} */
+#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM     128
+
+#define IGA1_FIFO_DEPTH_SELECT_REG_NUM          1
+#define IGA1_FIFO_THRESHOLD_REG_NUM             2
+#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM        2
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
+
+#define IGA2_FIFO_DEPTH_SELECT_REG_NUM          3
+#define IGA2_FIFO_THRESHOLD_REG_NUM             2
+#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM        2
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM   1
+
+#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x)                   ((x/2)-1)
+#define IGA1_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
+#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
+#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
+#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x)                   (((x/2)/4)-1)
+#define IGA2_FIFO_THRESHOLD_FORMULA(x)                      (x/4)
+#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x)            (x/4)
+#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x)                 (x/4)
+
+/************************************************************************/
+/*  LCD Timing                                                          */
+/************************************************************************/
+
+/* 500 ms = 500000 us */
+#define LCD_POWER_SEQ_TD0               500000
+/* 50 ms = 50000 us */
+#define LCD_POWER_SEQ_TD1               50000
+/* 0 us */
+#define LCD_POWER_SEQ_TD2               0
+/* 210 ms = 210000 us */
+#define LCD_POWER_SEQ_TD3               210000
+/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
+#define CLE266_POWER_SEQ_UNIT           71
+/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
+#define K800_POWER_SEQ_UNIT             142
+/* 2^13 * (1/14.31818M) = 572.1 us */
+#define P880_POWER_SEQ_UNIT             572
+
+#define CLE266_POWER_SEQ_FORMULA(x)     ((x)/CLE266_POWER_SEQ_UNIT)
+#define K800_POWER_SEQ_FORMULA(x)       ((x)/K800_POWER_SEQ_UNIT)
+#define P880_POWER_SEQ_FORMULA(x)       ((x)/P880_POWER_SEQ_UNIT)
+
+/* location: {CR8B,0,7},{CR8F,0,3} */
+#define LCD_POWER_SEQ_TD0_REG_NUM       2
+/* location: {CR8C,0,7},{CR8F,4,7} */
+#define LCD_POWER_SEQ_TD1_REG_NUM       2
+/* location: {CR8D,0,7},{CR90,0,3} */
+#define LCD_POWER_SEQ_TD2_REG_NUM       2
+/* location: {CR8E,0,7},{CR90,4,7} */
+#define LCD_POWER_SEQ_TD3_REG_NUM       2
+
+/* LCD Scaling factor*/
+/* x: indicate setting horizontal size*/
+/* y: indicate panel horizontal size*/
+
+/* Horizontal scaling factor 10 bits (2^10) */
+#define CLE266_LCD_HOR_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
+/* Vertical scaling factor 10 bits (2^10) */
+#define CLE266_LCD_VER_SCF_FORMULA(x, y)   (((x-1)*1024)/(y-1))
+/* Horizontal scaling factor 10 bits (2^12) */
+#define K800_LCD_HOR_SCF_FORMULA(x, y)     (((x-1)*4096)/(y-1))
+/* Vertical scaling factor 10 bits (2^11) */
+#define K800_LCD_VER_SCF_FORMULA(x, y)     (((x-1)*2048)/(y-1))
+
+/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM  3
+/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM  3
+/* location: {CR77,0,7},{CR79,4,5} */
+#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE  2
+/* location: {CR78,0,7},{CR79,6,7} */
+#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE  2
+
+/************************************************
+ *****     Define IGA1 Display Timing       *****
+ ************************************************/
+struct io_register {
+       u8 io_addr;
+       u8 start_bit;
+       u8 end_bit;
+};
+
+/* IGA1 Horizontal Total */
+struct iga1_hor_total {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA1 Horizontal Addressable Video */
+struct iga1_hor_addr {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
+};
+
+/* IGA1 Horizontal Blank Start */
+struct iga1_hor_blank_start {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
+};
+
+/* IGA1 Horizontal Blank End */
+struct iga1_hor_blank_end {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA1 Horizontal Sync Start */
+struct iga1_hor_sync_start {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
+};
+
+/* IGA1 Horizontal Sync End */
+struct iga1_hor_sync_end {
+       int reg_num;
+       struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
+};
+
+/* IGA1 Vertical Total */
+struct iga1_ver_total {
+       int reg_num;
+       struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
+};
+
+/* IGA1 Vertical Addressable Video */
+struct iga1_ver_addr {
+       int reg_num;
+       struct io_register reg[IGA1_VER_ADDR_REG_NUM];
+};
+
+/* IGA1 Vertical Blank Start */
+struct iga1_ver_blank_start {
+       int reg_num;
+       struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA1 Vertical Blank End */
+struct iga1_ver_blank_end {
+       int reg_num;
+       struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA1 Vertical Sync Start */
+struct iga1_ver_sync_start {
+       int reg_num;
+       struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA1 Vertical Sync End */
+struct iga1_ver_sync_end {
+       int reg_num;
+       struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
+};
+
+/*****************************************************
+**      Define IGA2 Shadow Display Timing         ****
+*****************************************************/
+
+/* IGA2 Shadow Horizontal Total */
+struct iga2_shadow_hor_total {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Horizontal Blank End */
+struct iga2_shadow_hor_blank_end {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Total */
+struct iga2_shadow_ver_total {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Addressable Video */
+struct iga2_shadow_ver_addr {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank Start */
+struct iga2_shadow_ver_blank_start {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Blank End */
+struct iga2_shadow_ver_blank_end {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync Start */
+struct iga2_shadow_ver_sync_start {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Shadow Vertical Sync End */
+struct iga2_shadow_ver_sync_end {
+       int reg_num;
+       struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
+};
+
+/*****************************************************
+**      Define IGA2 Display Timing                ****
+******************************************************/
+
+/* IGA2 Horizontal Total */
+struct iga2_hor_total {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
+};
+
+/* IGA2 Horizontal Addressable Video */
+struct iga2_hor_addr {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
+};
+
+/* IGA2 Horizontal Blank Start */
+struct iga2_hor_blank_start {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Horizontal Blank End */
+struct iga2_hor_blank_end {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Horizontal Sync Start */
+struct iga2_hor_sync_start {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Horizontal Sync End */
+struct iga2_hor_sync_end {
+       int reg_num;
+       struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
+};
+
+/* IGA2 Vertical Total */
+struct iga2_ver_total {
+       int reg_num;
+       struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
+};
+
+/* IGA2 Vertical Addressable Video */
+struct iga2_ver_addr {
+       int reg_num;
+       struct io_register reg[IGA2_VER_ADDR_REG_NUM];
+};
+
+/* IGA2 Vertical Blank Start */
+struct iga2_ver_blank_start {
+       int reg_num;
+       struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
+};
+
+/* IGA2 Vertical Blank End */
+struct iga2_ver_blank_end {
+       int reg_num;
+       struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
+};
+
+/* IGA2 Vertical Sync Start */
+struct iga2_ver_sync_start {
+       int reg_num;
+       struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
+};
+
+/* IGA2 Vertical Sync End */
+struct iga2_ver_sync_end {
+       int reg_num;
+       struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
+};
+
+/* IGA1 Offset Register */
+struct iga1_offset {
+       int reg_num;
+       struct io_register reg[IGA1_OFFSET_REG_NUM];
+};
+
+/* IGA2 Offset Register */
+struct iga2_offset {
+       int reg_num;
+       struct io_register reg[IGA2_OFFSET_REG_NUM];
+};
+
+struct offset {
+       struct iga1_offset iga1_offset_reg;
+       struct iga2_offset iga2_offset_reg;
+};
+
+/* IGA1 Fetch Count Register */
+struct iga1_fetch_count {
+       int reg_num;
+       struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
+};
+
+/* IGA2 Fetch Count Register */
+struct iga2_fetch_count {
+       int reg_num;
+       struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
+};
+
+struct fetch_count {
+       struct iga1_fetch_count iga1_fetch_count_reg;
+       struct iga2_fetch_count iga2_fetch_count_reg;
+};
+
+/* Starting Address Register */
+struct iga1_starting_addr {
+       int reg_num;
+       struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
+};
+
+struct iga2_starting_addr {
+       int reg_num;
+       struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
+};
+
+struct starting_addr {
+       struct iga1_starting_addr iga1_starting_addr_reg;
+       struct iga2_starting_addr iga2_starting_addr_reg;
+};
+
+/* LCD Power Sequence Timer */
+struct lcd_pwd_seq_td0 {
+       int reg_num;
+       struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
+};
+
+struct lcd_pwd_seq_td1 {
+       int reg_num;
+       struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
+};
+
+struct lcd_pwd_seq_td2 {
+       int reg_num;
+       struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
+};
+
+struct lcd_pwd_seq_td3 {
+       int reg_num;
+       struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
+};
+
+struct _lcd_pwd_seq_timer {
+       struct lcd_pwd_seq_td0 td0;
+       struct lcd_pwd_seq_td1 td1;
+       struct lcd_pwd_seq_td2 td2;
+       struct lcd_pwd_seq_td3 td3;
+};
+
+/* LCD Scaling Factor */
+struct _lcd_hor_scaling_factor {
+       int reg_num;
+       struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_ver_scaling_factor {
+       int reg_num;
+       struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
+};
+
+struct _lcd_scaling_factor {
+       struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
+       struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
+};
+
+struct pll_map {
+       u32 clk;
+       u32 cle266_pll;
+       u32 k800_pll;
+       u32 cx700_pll;
+};
+
+struct rgbLUT {
+       u8 red;
+       u8 green;
+       u8 blue;
+};
+
+struct lcd_pwd_seq_timer {
+       u16 td0;
+       u16 td1;
+       u16 td2;
+       u16 td3;
+};
+
+/* Display FIFO Relation Registers*/
+struct iga1_fifo_depth_select {
+       int reg_num;
+       struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga1_fifo_threshold_select {
+       int reg_num;
+       struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga1_fifo_high_threshold_select {
+       int reg_num;
+       struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga1_display_queue_expire_num {
+       int reg_num;
+       struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct iga2_fifo_depth_select {
+       int reg_num;
+       struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
+};
+
+struct iga2_fifo_threshold_select {
+       int reg_num;
+       struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
+};
+
+struct iga2_fifo_high_threshold_select {
+       int reg_num;
+       struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
+};
+
+struct iga2_display_queue_expire_num {
+       int reg_num;
+       struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
+};
+
+struct fifo_depth_select {
+       struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
+       struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
+};
+
+struct fifo_threshold_select {
+       struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
+       struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
+};
+
+struct fifo_high_threshold_select {
+       struct iga1_fifo_high_threshold_select
+        iga1_fifo_high_threshold_select_reg;
+       struct iga2_fifo_high_threshold_select
+        iga2_fifo_high_threshold_select_reg;
+};
+
+struct display_queue_expire_num {
+       struct iga1_display_queue_expire_num
+        iga1_display_queue_expire_num_reg;
+       struct iga2_display_queue_expire_num
+        iga2_display_queue_expire_num_reg;
+};
+
+struct iga1_crtc_timing {
+       struct iga1_hor_total hor_total;
+       struct iga1_hor_addr hor_addr;
+       struct iga1_hor_blank_start hor_blank_start;
+       struct iga1_hor_blank_end hor_blank_end;
+       struct iga1_hor_sync_start hor_sync_start;
+       struct iga1_hor_sync_end hor_sync_end;
+       struct iga1_ver_total ver_total;
+       struct iga1_ver_addr ver_addr;
+       struct iga1_ver_blank_start ver_blank_start;
+       struct iga1_ver_blank_end ver_blank_end;
+       struct iga1_ver_sync_start ver_sync_start;
+       struct iga1_ver_sync_end ver_sync_end;
+};
+
+struct iga2_shadow_crtc_timing {
+       struct iga2_shadow_hor_total hor_total_shadow;
+       struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
+       struct iga2_shadow_ver_total ver_total_shadow;
+       struct iga2_shadow_ver_addr ver_addr_shadow;
+       struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
+       struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
+       struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
+       struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
+};
+
+struct iga2_crtc_timing {
+       struct iga2_hor_total hor_total;
+       struct iga2_hor_addr hor_addr;
+       struct iga2_hor_blank_start hor_blank_start;
+       struct iga2_hor_blank_end hor_blank_end;
+       struct iga2_hor_sync_start hor_sync_start;
+       struct iga2_hor_sync_end hor_sync_end;
+       struct iga2_ver_total ver_total;
+       struct iga2_ver_addr ver_addr;
+       struct iga2_ver_blank_start ver_blank_start;
+       struct iga2_ver_blank_end ver_blank_end;
+       struct iga2_ver_sync_start ver_sync_start;
+       struct iga2_ver_sync_end ver_sync_end;
+};
+
+/* device ID */
+#define CLE266              0x3123
+#define KM400               0x3205
+#define CN400_FUNCTION2     0x2259
+#define CN400_FUNCTION3     0x3259
+/* support VT3314 chipset */
+#define CN700_FUNCTION2     0x2314
+#define CN700_FUNCTION3     0x3208
+/* VT3324 chipset */
+#define CX700_FUNCTION2     0x2324
+#define CX700_FUNCTION3     0x3324
+/* VT3204 chipset*/
+#define KM800_FUNCTION3      0x3204
+/* VT3336 chipset*/
+#define KM890_FUNCTION3      0x3336
+/* VT3327 chipset*/
+#define P4M890_FUNCTION3     0x3327
+/* VT3293 chipset*/
+#define CN750_FUNCTION3     0x3208
+/* VT3364 chipset*/
+#define P4M900_FUNCTION3    0x3364
+/* VT3353 chipset*/
+#define VX800_FUNCTION3     0x3353
+
+#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
+
+struct IODATA {
+       u8 Index;
+       u8 Mask;
+       u8 Data;
+};
+
+struct pci_device_id_info {
+       u32 vendor;
+       u32 device;
+       u32 chip_index;
+};
+
+extern unsigned int viafb_second_virtual_xres;
+extern unsigned int viafb_second_offset;
+extern int viafb_second_size;
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_accel;
+extern int viafb_hotplug;
+
+void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
+void viafb_set_output_path(int device, int set_iga,
+       int output_interface);
+void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
+                     int mode_index, int bpp_byte, int set_iga);
+
+void viafb_set_vclock(u32 CLK, int set_iga);
+void viafb_load_reg(int timing_value, int viafb_load_reg_num,
+       struct io_register *reg,
+             int io_type);
+void viafb_crt_disable(void);
+void viafb_crt_enable(void);
+void init_ad9389(void);
+/* Access I/O Function */
+void viafb_write_reg(u8 index, u16 io_port, u8 data);
+u8 viafb_read_reg(int io_port, u8 index);
+void viafb_lock_crt(void);
+void viafb_unlock_crt(void);
+void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga);
+void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
+void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
+struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
+u32 viafb_get_clk_value(int clk);
+void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
+void viafb_set_color_depth(int bpp_byte, int set_iga);
+void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
+                                       *p_gfx_dpa_setting);
+
+int viafb_setmode(int vmode_index, int hor_res, int ver_res,
+           int video_bpp, int vmode_index1, int hor_res1,
+           int ver_res1, int video_bpp1);
+void viafb_init_chip_info(void);
+void viafb_init_dac(int set_iga);
+int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
+int viafb_get_refresh(int hres, int vres, u32 float_refresh);
+void viafb_update_device_setting(int hres, int vres, int bpp,
+                          int vmode_refresh, int flag);
+void viafb_get_mmio_info(unsigned long *mmio_base,
+       unsigned long *mmio_len);
+
+void viafb_set_iga_path(void);
+void viafb_set_start_addr(void);
+void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
+
+#endif /* __HW_H__ */
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c
new file mode 100644 (file)
index 0000000..1570636
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+/* Get frame buffer size from VGA BIOS */
+
+unsigned int viafb_get_memsize(void)
+{
+       unsigned int m;
+
+       /* If memory size provided by user */
+       if (viafb_memsize)
+               m = viafb_memsize * Mb;
+       else {
+               m = (unsigned int)viafb_read_reg(VIASR, SR39);
+               m = m * (4 * Mb);
+
+               if ((m < (16 * Mb)) || (m > (64 * Mb)))
+                       m = 16 * Mb;
+       }
+       DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
+       return m;
+}
+
+/* Get Video Buffer Starting Physical Address(back door)*/
+
+unsigned long viafb_get_videobuf_addr(void)
+{
+       struct pci_dev *pdev = NULL;
+       unsigned char sys_mem;
+       unsigned char video_mem;
+       unsigned long sys_mem_size;
+       unsigned long video_mem_size;
+       /*system memory = 256 MB, video memory 64 MB */
+       unsigned long vmem_starting_adr = 0x0C000000;
+
+       pdev =
+           (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
+                                            VIA_K800_BRIDGE_DID, NULL);
+       if (pdev != NULL) {
+               pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
+                                    &sys_mem);
+               pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
+                                    &video_mem);
+               video_mem = (video_mem & 0x70) >> 4;
+               sys_mem_size = ((unsigned long)sys_mem) << 24;
+               if (video_mem != 0)
+                       video_mem_size = (1 << (video_mem)) * 1024 * 1024;
+               else
+                       video_mem_size = 0;
+
+               vmem_starting_adr = sys_mem_size - video_mem_size;
+               pci_dev_put(pdev);
+       }
+
+       DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
+                 vmem_starting_adr);
+       return vmem_starting_adr;
+}
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h
new file mode 100644 (file)
index 0000000..790ec3e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __IFACE_H__
+#define __IFACE_H__
+
+#define Kb  (1024)
+#define Mb  (Kb*Kb)
+
+#define VIA_K800_BRIDGE_VID         0x1106
+#define VIA_K800_BRIDGE_DID         0x3204
+
+#define VIA_K800_SYSTEM_MEMORY_REG  0x47
+#define VIA_K800_VIDEO_MEMORY_REG   0xA1
+
+extern int viafb_memsize;
+unsigned int viafb_get_memsize(void);
+unsigned long viafb_get_videobuf_addr(void);
+
+#endif /* __IFACE_H__ */
diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c
new file mode 100644 (file)
index 0000000..da03c07
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+int viafb_ioctl_get_viafb_info(u_long arg)
+{
+       struct viafb_ioctl_info viainfo;
+
+       viainfo.viafb_id = VIAID;
+       viainfo.vendor_id = PCI_VIA_VENDOR_ID;
+
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_CLE266:
+               viainfo.device_id = UNICHROME_CLE266_DID;
+               break;
+
+       case UNICHROME_K400:
+               viainfo.device_id = UNICHROME_K400_DID;
+               break;
+
+       case UNICHROME_K800:
+               viainfo.device_id = UNICHROME_K800_DID;
+               break;
+
+       case UNICHROME_PM800:
+               viainfo.device_id = UNICHROME_PM800_DID;
+               break;
+
+       case UNICHROME_CN700:
+               viainfo.device_id = UNICHROME_CN700_DID;
+               break;
+
+       case UNICHROME_CX700:
+               viainfo.device_id = UNICHROME_CX700_DID;
+               break;
+
+       case UNICHROME_K8M890:
+               viainfo.device_id = UNICHROME_K8M890_DID;
+               break;
+
+       case UNICHROME_P4M890:
+               viainfo.device_id = UNICHROME_P4M890_DID;
+               break;
+
+       case UNICHROME_P4M900:
+               viainfo.device_id = UNICHROME_P4M900_DID;
+               break;
+       }
+
+       viainfo.version = VERSION_MAJOR;
+       viainfo.revision = VERSION_MINOR;
+
+       if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+/* Hot-Plug Priority: DVI > CRT*/
+int viafb_ioctl_hotplug(int hres, int vres, int bpp)
+{
+       int DVIsense, status = 0;
+       DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
+
+       if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
+               NON_TMDS_TRANSMITTER) {
+               DVIsense = viafb_dvi_sense();
+
+               if (DVIsense) {
+                       DEBUG_MSG(KERN_INFO "DVI Attached...\n");
+                       if (viafb_DeviceStatus != DVI_Device) {
+                               viafb_DVI_ON = 1;
+                               viafb_CRT_ON = 0;
+                               viafb_LCD_ON = 0;
+                               viafb_DeviceStatus = DVI_Device;
+                               return viafb_DeviceStatus;
+                       }
+                       status = 1;
+               } else
+                       DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
+       }
+
+       if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
+               viafb_CRT_ON = 1;
+               viafb_DVI_ON = 0;
+               viafb_LCD_ON = 0;
+
+               viafb_DeviceStatus = CRT_Device;
+               return viafb_DeviceStatus;
+       }
+
+       return 0;
+}
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h
new file mode 100644 (file)
index 0000000..842fe30
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __IOCTL_H__
+#define __IOCTL_H__
+
+#ifndef __user
+#define __user
+#endif
+
+/* VIAFB IOCTL definition */
+#define VIAFB_GET_INFO_SIZE            0x56494101      /* 'VIA\01' */
+#define VIAFB_GET_INFO                 0x56494102      /* 'VIA\02' */
+#define VIAFB_HOTPLUG                  0x56494103      /* 'VIA\03' */
+#define VIAFB_SET_HOTPLUG_FLAG         0x56494104      /* 'VIA\04' */
+#define VIAFB_GET_RESOLUTION           0x56494105      /* 'VIA\05' */
+#define VIAFB_GET_SAMM_INFO            0x56494107      /* 'VIA\07' */
+#define VIAFB_TURN_ON_OUTPUT_DEVICE     0x56494108     /* 'VIA\08' */
+#define VIAFB_TURN_OFF_OUTPUT_DEVICE    0x56494109     /* 'VIA\09' */
+#define VIAFB_SET_DEVICE               0x5649410A
+#define VIAFB_GET_DEVICE               0x5649410B
+#define VIAFB_GET_DRIVER_VERSION       0x56494112      /* 'VIA\12' */
+#define VIAFB_GET_CHIP_INFO            0x56494113      /* 'VIA\13' */
+#define VIAFB_SET_DEVICE_INFO           0x56494114
+#define VIAFB_GET_DEVICE_INFO           0x56494115
+
+#define VIAFB_GET_DEVICE_SUPPORT       0x56494118
+#define VIAFB_GET_DEVICE_CONNECT       0x56494119
+#define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A
+#define VIAFB_GET_DRIVER_NAME          0x56494122
+#define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123
+#define VIAFB_GET_GAMMA_LUT            0x56494124
+#define VIAFB_SET_GAMMA_LUT            0x56494125
+#define VIAFB_GET_GAMMA_SUPPORT_STATE  0x56494126
+#define VIAFB_SET_VIDEO_DEVICE         0x56494127
+#define VIAFB_GET_VIDEO_DEVICE         0x56494128
+#define VIAFB_SET_SECOND_MODE          0x56494129
+#define VIAFB_SYNC_SURFACE             0x56494130
+#define VIAFB_GET_DRIVER_CAPS          0x56494131
+#define VIAFB_GET_IGA_SCALING_INFO     0x56494132
+#define VIAFB_GET_PANEL_MAX_SIZE       0x56494133
+#define VIAFB_GET_PANEL_MAX_POSITION   0x56494134
+#define VIAFB_SET_PANEL_SIZE           0x56494135
+#define VIAFB_SET_PANEL_POSITION        0x56494136
+#define VIAFB_GET_PANEL_POSITION        0x56494137
+#define VIAFB_GET_PANEL_SIZE           0x56494138
+
+#define None_Device 0x00
+#define CRT_Device  0x01
+#define LCD_Device  0x02
+#define DVI_Device  0x08
+#define CRT2_Device 0x10
+#define LCD2_Device 0x40
+
+#define OP_LCD_CENTERING   0x01
+#define OP_LCD_PANEL_ID    0x02
+#define OP_LCD_MODE        0x03
+
+/*SAMM operation flag*/
+#define OP_SAMM            0x80
+
+#define LCD_PANEL_ID_MAXIMUM   22
+
+#define STATE_ON            0x1
+#define STATE_OFF           0x0
+#define STATE_DEFAULT       0xFFFF
+
+#define MAX_ACTIVE_DEV_NUM  2
+
+struct device_t {
+       unsigned short crt:1;
+       unsigned short dvi:1;
+       unsigned short lcd:1;
+       unsigned short samm:1;
+       unsigned short lcd_dsp_cent:1;
+       unsigned char lcd_mode:1;
+       unsigned short epia_dvi:1;
+       unsigned short lcd_dual_edge:1;
+       unsigned short lcd2:1;
+
+       unsigned short primary_dev;
+       unsigned char lcd_panel_id;
+       unsigned short xres, yres;
+       unsigned short xres1, yres1;
+       unsigned short refresh;
+       unsigned short bpp;
+       unsigned short refresh1;
+       unsigned short bpp1;
+       unsigned short sequence;
+       unsigned short bus_width;
+};
+
+struct viafb_ioctl_info {
+       u32 viafb_id;           /* for identifying viafb */
+#define VIAID       0x56494146 /* Identify myself with 'VIAF' */
+       u16 vendor_id;
+       u16 device_id;
+       u8 version;
+       u8 revision;
+       u8 reserved[246];       /* for future use */
+};
+
+struct viafb_ioctl_mode {
+       u32 xres;
+       u32 yres;
+       u32 refresh;
+       u32 bpp;
+       u32 xres_sec;
+       u32 yres_sec;
+       u32 virtual_xres_sec;
+       u32 virtual_yres_sec;
+       u32 refresh_sec;
+       u32 bpp_sec;
+};
+struct viafb_ioctl_samm {
+       u32 samm_status;
+       u32 size_prim;
+       u32 size_sec;
+       u32 mem_base;
+       u32 offset_sec;
+};
+
+struct viafb_driver_version {
+       int iMajorNum;
+       int iKernelNum;
+       int iOSNum;
+       int iMinorNum;
+};
+
+struct viafb_ioctl_lcd_attribute {
+       unsigned int panel_id;
+       unsigned int display_center;
+       unsigned int lcd_mode;
+};
+
+struct viafb_ioctl_setting {
+       /* Enable or disable active devices */
+       unsigned short device_flag;
+       /* Indicate which device should be turn on or turn off. */
+       unsigned short device_status;
+       unsigned int reserved;
+       /* Indicate which LCD's attribute can be changed. */
+       unsigned short lcd_operation_flag;
+       /* 1: SAMM ON  0: SAMM OFF */
+       unsigned short samm_status;
+       /* horizontal resolution of first device */
+       unsigned short first_dev_hor_res;
+       /* vertical resolution of first device */
+       unsigned short first_dev_ver_res;
+       /* horizontal resolution of second device */
+       unsigned short second_dev_hor_res;
+       /* vertical resolution of second device */
+       unsigned short second_dev_ver_res;
+       /* refresh rate of first device */
+       unsigned short first_dev_refresh;
+       /* bpp of first device */
+       unsigned short first_dev_bpp;
+       /* refresh rate of second device */
+       unsigned short second_dev_refresh;
+       /* bpp of second device */
+       unsigned short second_dev_bpp;
+       /* Indicate which device are primary display device. */
+       unsigned int primary_device;
+       /* Indicate which device will show video. only valid in duoview mode */
+       unsigned int video_device_status;
+       unsigned int struct_reserved[34];
+       struct viafb_ioctl_lcd_attribute lcd_attributes;
+};
+
+struct _UTFunctionCaps {
+       unsigned int dw3DScalingState;
+       unsigned int reserved[31];
+};
+
+struct _POSITIONVALUE {
+       unsigned int dwX;
+       unsigned int dwY;
+};
+
+struct _panel_size_pos_info {
+       unsigned int device_type;
+       int x;
+       int y;
+};
+
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+int viafb_ioctl_get_viafb_info(u_long arg);
+int viafb_ioctl_hotplug(int hres, int vres, int bpp);
+
+#endif /* __IOCTL_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
new file mode 100644 (file)
index 0000000..6c7290a
--- /dev/null
@@ -0,0 +1,1821 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+#include "lcdtbl.h"
+
+static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
+       /* IGA2 Shadow Horizontal Total */
+       {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
+       /* IGA2 Shadow Horizontal Blank End */
+       {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
+       /* IGA2 Shadow Vertical Total */
+       {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
+       /* IGA2 Shadow Vertical Addressable Video */
+       {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
+       /* IGA2 Shadow Vertical Blank Start */
+       {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
+        {{CR72, 0, 7}, {CR74, 4, 6} } },
+       /* IGA2 Shadow Vertical Blank End */
+       {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
+       /* IGA2 Shadow Vertical Sync Start */
+       {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
+       /* IGA2 Shadow Vertical Sync End */
+       {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
+};
+
+static struct _lcd_scaling_factor lcd_scaling_factor = {
+       /* LCD Horizontal Scaling Factor Register */
+       {LCD_HOR_SCALING_FACTOR_REG_NUM,
+        {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
+       /* LCD Vertical Scaling Factor Register */
+       {LCD_VER_SCALING_FACTOR_REG_NUM,
+        {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
+};
+static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
+       /* LCD Horizontal Scaling Factor Register */
+       {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
+       /* LCD Vertical Scaling Factor Register */
+       {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
+};
+
+static int check_lvds_chip(int device_id_subaddr, int device_id);
+static bool lvds_identify_integratedlvds(void);
+static int fp_id_to_vindex(int panel_id);
+static int lvds_register_read(int index);
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+                     int panel_vres);
+static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
+       int panel_id);
+static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
+       int panel_id);
+static void load_lcd_patch_regs(int set_hres, int set_vres,
+       int panel_id, int set_iga);
+static void via_pitch_alignment_patch_lcd(
+       struct lvds_setting_information *plvds_setting_info,
+                                  struct lvds_chip_information
+                                  *plvds_chip_info);
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info);
+static void lcd_patch_skew(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+
+static void integrated_lvds_disable(struct lvds_setting_information
+                            *plvds_setting_info,
+                            struct lvds_chip_information *plvds_chip_info);
+static void integrated_lvds_enable(struct lvds_setting_information
+                           *plvds_setting_info,
+                           struct lvds_chip_information *plvds_chip_info);
+static void lcd_powersequence_off(void);
+static void lcd_powersequence_on(void);
+static void fill_lcd_format(void);
+static void check_diport_of_integrated_lvds(
+       struct lvds_chip_information *plvds_chip_info,
+                                    struct lvds_setting_information
+                                    *plvds_setting_info);
+static struct display_timing lcd_centering_timging(struct display_timing
+                                           mode_crt_reg,
+                                          struct display_timing panel_crt_reg);
+static void load_crtc_shadow_timing(struct display_timing mode_timing,
+                            struct display_timing panel_timing);
+static void viafb_load_scaling_factor_for_p4m900(int set_hres,
+       int set_vres, int panel_hres, int panel_vres);
+
+static int check_lvds_chip(int device_id_subaddr, int device_id)
+{
+       if (lvds_register_read(device_id_subaddr) == device_id)
+               return OK;
+       else
+               return FAIL;
+}
+
+void viafb_init_lcd_size(void)
+{
+       DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
+       DEBUG_MSG(KERN_INFO
+               "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
+               viaparinfo->lvds_setting_info->get_lcd_size_method);
+
+       switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
+       case GET_LCD_SIZE_BY_SYSTEM_BIOS:
+               break;
+       case GET_LCD_SZIE_BY_HW_STRAPPING:
+               break;
+       case GET_LCD_SIZE_BY_VGA_BIOS:
+               DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
+               viaparinfo->lvds_setting_info->lcd_panel_size =
+                   fp_id_to_vindex(viafb_lcd_panel_id);
+               DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
+                         viaparinfo->lvds_setting_info->lcd_panel_id);
+               DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
+                         viaparinfo->lvds_setting_info->lcd_panel_size);
+               break;
+       case GET_LCD_SIZE_BY_USER_SETTING:
+               DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
+               viaparinfo->lvds_setting_info->lcd_panel_size =
+                   fp_id_to_vindex(viafb_lcd_panel_id);
+               DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
+                         viaparinfo->lvds_setting_info->lcd_panel_id);
+               DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
+                         viaparinfo->lvds_setting_info->lcd_panel_size);
+               break;
+       default:
+               DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID1_800X600;
+               viaparinfo->lvds_setting_info->lcd_panel_size =
+                   fp_id_to_vindex(LCD_PANEL_ID1_800X600);
+       }
+       viaparinfo->lvds_setting_info2->lcd_panel_id =
+               viaparinfo->lvds_setting_info->lcd_panel_id;
+       viaparinfo->lvds_setting_info2->lcd_panel_size =
+               viaparinfo->lvds_setting_info->lcd_panel_size;
+       viaparinfo->lvds_setting_info2->lcd_panel_hres =
+               viaparinfo->lvds_setting_info->lcd_panel_hres;
+       viaparinfo->lvds_setting_info2->lcd_panel_vres =
+               viaparinfo->lvds_setting_info->lcd_panel_vres;
+       viaparinfo->lvds_setting_info2->device_lcd_dualedge =
+           viaparinfo->lvds_setting_info->device_lcd_dualedge;
+       viaparinfo->lvds_setting_info2->LCDDithering =
+               viaparinfo->lvds_setting_info->LCDDithering;
+}
+
+static bool lvds_identify_integratedlvds(void)
+{
+       if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
+               /* Two dual channel LCD (Internal LVDS + External LVDS): */
+               /* If we have an external LVDS, such as VT1636, we should
+                  have its chip ID already. */
+               if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+                       viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+                           INTEGRATED_LVDS;
+                       DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
+                                 (Internal LVDS + External LVDS)\n");
+               } else {
+                       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+                           INTEGRATED_LVDS;
+                       DEBUG_MSG(KERN_INFO "Not found external LVDS,\
+                                 so can't support two dual channel LVDS!\n");
+               }
+       } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
+               /* Two single channel LCD (Internal LVDS + Internal LVDS): */
+               viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+               INTEGRATED_LVDS;
+               viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
+                       INTEGRATED_LVDS;
+               DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
+                         (Internal LVDS + Internal LVDS)\n");
+       } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
+               /* If we have found external LVDS, just use it,
+                  otherwise, we will use internal LVDS as default. */
+               if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+                       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+                           INTEGRATED_LVDS;
+                       DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
+               }
+       } else {
+               viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+                       NON_LVDS_TRANSMITTER;
+               DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
+               return false;
+       }
+
+       return true;
+}
+
+int viafb_lvds_trasmitter_identify(void)
+{
+       viaparinfo->i2c_stuff.i2c_port = I2CPORTINDEX;
+       if (viafb_lvds_identify_vt1636()) {
+               viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
+               DEBUG_MSG(KERN_INFO
+                         "Found VIA VT1636 LVDS on port i2c 0x31 \n");
+       } else {
+               viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
+               if (viafb_lvds_identify_vt1636()) {
+                       viaparinfo->chip_info->lvds_chip_info.i2c_port =
+                               GPIOPORTINDEX;
+                       DEBUG_MSG(KERN_INFO
+                                 "Found VIA VT1636 LVDS on port gpio 0x2c \n");
+               }
+       }
+
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
+               lvds_identify_integratedlvds();
+
+       if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+               return true;
+       /* Check for VT1631: */
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+               VT1631_LVDS_I2C_ADDR;
+
+       if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
+               DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
+               DEBUG_MSG(KERN_INFO "\n %2d",
+                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+               DEBUG_MSG(KERN_INFO "\n %2d",
+                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
+               return OK;
+       }
+
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+               NON_LVDS_TRANSMITTER;
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+               VT1631_LVDS_I2C_ADDR;
+       return FAIL;
+}
+
+static int fp_id_to_vindex(int panel_id)
+{
+       DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
+
+       if (panel_id > LCD_PANEL_ID_MAXIMUM)
+               viafb_lcd_panel_id = panel_id =
+               viafb_read_reg(VIACR, CR3F) & 0x0F;
+
+       switch (panel_id) {
+       case 0x0:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID0_640X480;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_640X480;
+               break;
+       case 0x1:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID1_800X600;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_800X600;
+               break;
+       case 0x2:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID2_1024X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1024X768;
+               break;
+       case 0x3:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID3_1280X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1280X768;
+               break;
+       case 0x4:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID4_1280X1024;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1280X1024;
+               break;
+       case 0x5:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID5_1400X1050;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1400X1050;
+               break;
+       case 0x6:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID6_1600X1200;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1600X1200;
+               break;
+       case 0x8:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_IDA_800X480;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_800X480;
+               break;
+       case 0x9:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID2_1024X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1024X768;
+               break;
+       case 0xA:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID2_1024X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1024X768;
+               break;
+       case 0xB:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID2_1024X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1024X768;
+               break;
+       case 0xC:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID3_1280X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1280X768;
+               break;
+       case 0xD:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID4_1280X1024;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1280X1024;
+               break;
+       case 0xE:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID5_1400X1050;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1400X1050;
+               break;
+       case 0xF:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID6_1600X1200;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1600X1200;
+               break;
+       case 0x10:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID7_1366X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1368X768;
+               break;
+       case 0x11:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID8_1024X600;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1024X600;
+               break;
+       case 0x12:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID3_1280X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1280X768;
+               break;
+       case 0x13:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID9_1280X800;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_1280X800;
+               break;
+       case 0x14:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_IDB_1360X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1360X768;
+               break;
+       case 0x15:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID3_1280X768;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
+               viaparinfo->lvds_setting_info->LCDDithering = 0;
+               return VIA_RES_1280X768;
+               break;
+       case 0x16:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_IDC_480X640;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_480X640;
+               break;
+       default:
+               viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
+               viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
+               viaparinfo->lvds_setting_info->lcd_panel_id =
+                       LCD_PANEL_ID1_800X600;
+               viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
+               viaparinfo->lvds_setting_info->LCDDithering = 1;
+               return VIA_RES_800X600;
+       }
+}
+
+static int lvds_register_read(int index)
+{
+       u8 data;
+
+       viaparinfo->i2c_stuff.i2c_port = GPIOPORTINDEX;
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->
+           lvds_chip_info.lvds_chip_slave_addr,
+                       (u8) index, &data);
+       return data;
+}
+
+static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
+                     int panel_vres)
+{
+       int reg_value = 0;
+       int viafb_load_reg_num;
+       struct io_register *reg = NULL;
+
+       DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
+
+       /* LCD Scaling Enable */
+       viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
+       if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
+               viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
+                                              panel_hres, panel_vres);
+               return;
+       }
+
+       /* Check if expansion for horizontal */
+       if (set_hres != panel_hres) {
+               /* Load Horizontal Scaling Factor */
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CLE266:
+               case UNICHROME_K400:
+                       reg_value =
+                           CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+                       viafb_load_reg_num =
+                           lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
+                           reg_num;
+                       reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+                       break;
+               case UNICHROME_K800:
+               case UNICHROME_PM800:
+               case UNICHROME_CN700:
+               case UNICHROME_CX700:
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M890:
+                       reg_value =
+                           K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+                       /* Horizontal scaling enabled */
+                       viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
+                       viafb_load_reg_num =
+                           lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
+                       reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+                       break;
+               }
+
+               DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
+       } else {
+               /* Horizontal scaling disabled */
+               viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
+       }
+
+       /* Check if expansion for vertical */
+       if (set_vres != panel_vres) {
+               /* Load Vertical Scaling Factor */
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CLE266:
+               case UNICHROME_K400:
+                       reg_value =
+                           CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+                       viafb_load_reg_num =
+                           lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
+                           reg_num;
+                       reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+                       break;
+               case UNICHROME_K800:
+               case UNICHROME_PM800:
+               case UNICHROME_CN700:
+               case UNICHROME_CX700:
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M890:
+                       reg_value =
+                           K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+                       /* Vertical scaling enabled */
+                       viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
+                       viafb_load_reg_num =
+                           lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
+                       reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_num, reg, VIACR);
+                       break;
+               }
+
+               DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
+       } else {
+               /* Vertical scaling disabled */
+               viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
+       }
+}
+
+static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
+       int panel_id)
+{
+       int vmode_index;
+       int reg_num = 0;
+       struct io_reg *lcd_patch_reg = NULL;
+
+       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+       else
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+       switch (panel_id) {
+               /* LCD 800x600 */
+       case LCD_PANEL_ID1_800X600:
+               switch (vmode_index) {
+               case VIA_RES_640X400:
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
+                       lcd_patch_reg = K400_LCD_RES_6X4_8X6;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
+                       lcd_patch_reg = K400_LCD_RES_7X4_8X6;
+                       break;
+               }
+               break;
+
+               /* LCD 1024x768 */
+       case LCD_PANEL_ID2_1024X768:
+               switch (vmode_index) {
+               case VIA_RES_640X400:
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
+                       lcd_patch_reg = K400_LCD_RES_6X4_10X7;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
+                       lcd_patch_reg = K400_LCD_RES_7X4_10X7;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
+                       lcd_patch_reg = K400_LCD_RES_8X6_10X7;
+                       break;
+               }
+               break;
+
+               /* LCD 1280x1024 */
+       case LCD_PANEL_ID4_1280X1024:
+               switch (vmode_index) {
+               case VIA_RES_640X400:
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
+                       lcd_patch_reg = K400_LCD_RES_6X4_12X10;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
+                       lcd_patch_reg = K400_LCD_RES_7X4_12X10;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
+                       lcd_patch_reg = K400_LCD_RES_8X6_12X10;
+                       break;
+               case VIA_RES_1024X768:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
+                       lcd_patch_reg = K400_LCD_RES_10X7_12X10;
+                       break;
+
+               }
+               break;
+
+               /* LCD 1400x1050 */
+       case LCD_PANEL_ID5_1400X1050:
+               switch (vmode_index) {
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
+                       lcd_patch_reg = K400_LCD_RES_6X4_14X10;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
+                       lcd_patch_reg = K400_LCD_RES_8X6_14X10;
+                       break;
+               case VIA_RES_1024X768:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
+                       lcd_patch_reg = K400_LCD_RES_10X7_14X10;
+                       break;
+               case VIA_RES_1280X768:
+               case VIA_RES_1280X800:
+               case VIA_RES_1280X960:
+               case VIA_RES_1280X1024:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
+                       lcd_patch_reg = K400_LCD_RES_12X10_14X10;
+                       break;
+               }
+               break;
+
+               /* LCD 1600x1200 */
+       case LCD_PANEL_ID6_1600X1200:
+               switch (vmode_index) {
+               case VIA_RES_640X400:
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
+                       lcd_patch_reg = K400_LCD_RES_6X4_16X12;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
+                       lcd_patch_reg = K400_LCD_RES_7X4_16X12;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
+                       lcd_patch_reg = K400_LCD_RES_8X6_16X12;
+                       break;
+               case VIA_RES_1024X768:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
+                       lcd_patch_reg = K400_LCD_RES_10X7_16X12;
+                       break;
+               case VIA_RES_1280X768:
+               case VIA_RES_1280X800:
+               case VIA_RES_1280X960:
+               case VIA_RES_1280X1024:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
+                       lcd_patch_reg = K400_LCD_RES_12X10_16X12;
+                       break;
+               }
+               break;
+
+               /* LCD 1366x768 */
+       case LCD_PANEL_ID7_1366X768:
+               switch (vmode_index) {
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
+                       lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
+                       lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
+                       lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
+                       break;
+               case VIA_RES_1024X768:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
+                       lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
+                       break;
+               case VIA_RES_1280X768:
+               case VIA_RES_1280X800:
+               case VIA_RES_1280X960:
+               case VIA_RES_1280X1024:
+                       reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
+                       lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
+                       break;
+               }
+               break;
+
+               /* LCD 1360x768 */
+       case LCD_PANEL_IDB_1360X768:
+               break;
+       }
+       if (reg_num != 0) {
+               /* H.W. Reset : ON */
+               viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+               viafb_write_regx(lcd_patch_reg, reg_num);
+
+               /* H.W. Reset : OFF */
+               viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+               /* Reset PLL */
+               viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+               viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+
+               /* Fire! */
+               outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
+       }
+}
+
+static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
+       int panel_id)
+{
+       int vmode_index;
+       int reg_num = 0;
+       struct io_reg *lcd_patch_reg = NULL;
+
+       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+       else
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+
+       switch (panel_id) {
+       case LCD_PANEL_ID5_1400X1050:
+               switch (vmode_index) {
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
+                       lcd_patch_reg = P880_LCD_RES_6X4_14X10;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
+                       lcd_patch_reg = P880_LCD_RES_8X6_14X10;
+                       break;
+               }
+               break;
+       case LCD_PANEL_ID6_1600X1200:
+               switch (vmode_index) {
+               case VIA_RES_640X400:
+               case VIA_RES_640X480:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
+                       lcd_patch_reg = P880_LCD_RES_6X4_16X12;
+                       break;
+               case VIA_RES_720X480:
+               case VIA_RES_720X576:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
+                       lcd_patch_reg = P880_LCD_RES_7X4_16X12;
+                       break;
+               case VIA_RES_800X600:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
+                       lcd_patch_reg = P880_LCD_RES_8X6_16X12;
+                       break;
+               case VIA_RES_1024X768:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
+                       lcd_patch_reg = P880_LCD_RES_10X7_16X12;
+                       break;
+               case VIA_RES_1280X768:
+               case VIA_RES_1280X960:
+               case VIA_RES_1280X1024:
+                       reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
+                       lcd_patch_reg = P880_LCD_RES_12X10_16X12;
+                       break;
+               }
+               break;
+
+       }
+       if (reg_num != 0) {
+               /* H.W. Reset : ON */
+               viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
+
+               viafb_write_regx(lcd_patch_reg, reg_num);
+
+               /* H.W. Reset : OFF */
+               viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
+
+               /* Reset PLL */
+               viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
+               viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
+
+               /* Fire! */
+               outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
+       }
+}
+
+static void load_lcd_patch_regs(int set_hres, int set_vres,
+       int panel_id, int set_iga)
+{
+       int vmode_index;
+
+       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
+       else
+               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+
+       viafb_unlock_crt();
+
+       /* Patch for simultaneous & Expansion */
+       if ((set_iga == IGA1_IGA2) &&
+               (viaparinfo->lvds_setting_info->display_method ==
+           LCD_EXPANDSION)) {
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CLE266:
+               case UNICHROME_K400:
+                       load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
+                       break;
+               case UNICHROME_K800:
+                       break;
+               case UNICHROME_PM800:
+               case UNICHROME_CN700:
+               case UNICHROME_CX700:
+                       load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
+               }
+       }
+
+       viafb_lock_crt();
+}
+
+static void via_pitch_alignment_patch_lcd(
+       struct lvds_setting_information *plvds_setting_info,
+                                  struct lvds_chip_information
+                                  *plvds_chip_info)
+{
+       unsigned char cr13, cr35, cr65, cr66, cr67;
+       unsigned long dwScreenPitch = 0;
+       unsigned long dwPitch;
+
+       dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
+       if (dwPitch & 0x1F) {
+               dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
+               if (plvds_setting_info->iga_path == IGA2) {
+                       if (plvds_setting_info->bpp > 8) {
+                               cr66 = (unsigned char)(dwScreenPitch & 0xFF);
+                               viafb_write_reg(CR66, VIACR, cr66);
+                               cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
+                               cr67 |=
+                                   (unsigned
+                                    char)((dwScreenPitch & 0x300) >> 8);
+                               viafb_write_reg(CR67, VIACR, cr67);
+                       }
+
+                       /* Fetch Count */
+                       cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
+                       cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
+                       viafb_write_reg(CR67, VIACR, cr67);
+                       cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
+                       cr65 += 2;
+                       viafb_write_reg(CR65, VIACR, cr65);
+               } else {
+                       if (plvds_setting_info->bpp > 8) {
+                               cr13 = (unsigned char)(dwScreenPitch & 0xFF);
+                               viafb_write_reg(CR13, VIACR, cr13);
+                               cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
+                               cr35 |=
+                                   (unsigned
+                                    char)((dwScreenPitch & 0x700) >> 3);
+                               viafb_write_reg(CR35, VIACR, cr35);
+                       }
+               }
+       }
+}
+static void lcd_patch_skew_dvp0(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info)
+{
+       if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_P4M900:
+                       viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
+                                                   plvds_chip_info);
+                       break;
+               case UNICHROME_P4M890:
+                       viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
+                                                   plvds_chip_info);
+                       break;
+               }
+       }
+}
+static void lcd_patch_skew_dvp1(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info)
+{
+       if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CX700:
+                       viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
+                                                   plvds_chip_info);
+                       break;
+               }
+       }
+}
+static void lcd_patch_skew(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+       DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
+       switch (plvds_chip_info->output_interface) {
+       case INTERFACE_DVP0:
+               lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
+               break;
+       case INTERFACE_DVP1:
+               lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
+               break;
+       case INTERFACE_DFP_LOW:
+               if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
+                       viafb_write_reg_mask(CR99, VIACR, 0x08,
+                                      BIT0 + BIT1 + BIT2 + BIT3);
+               }
+               break;
+       }
+}
+
+/* LCD Set Mode */
+void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
+                 struct lvds_setting_information *plvds_setting_info,
+                 struct lvds_chip_information *plvds_chip_info)
+{
+       int video_index = plvds_setting_info->lcd_panel_size;
+       int set_iga = plvds_setting_info->iga_path;
+       int mode_bpp = plvds_setting_info->bpp;
+       int viafb_load_reg_num = 0;
+       int reg_value = 0;
+       int set_hres, set_vres;
+       int panel_hres, panel_vres;
+       u32 pll_D_N;
+       int offset;
+       struct io_register *reg = NULL;
+       struct display_timing mode_crt_reg, panel_crt_reg;
+       struct crt_mode_table *panel_crt_table = NULL;
+       struct VideoModeTable *vmode_tbl = NULL;
+
+       DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
+       /* Get mode table */
+       mode_crt_reg = mode_crt_table->crtc;
+       /* Get panel table Pointer */
+       vmode_tbl = viafb_get_modetbl_pointer(video_index);
+       panel_crt_table = vmode_tbl->crtc;
+       panel_crt_reg = panel_crt_table->crtc;
+       DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
+       set_hres = plvds_setting_info->h_active;
+       set_vres = plvds_setting_info->v_active;
+       panel_hres = plvds_setting_info->lcd_panel_hres;
+       panel_vres = plvds_setting_info->lcd_panel_vres;
+       if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
+               viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
+       plvds_setting_info->vclk = panel_crt_table->clk;
+       if (set_iga == IGA1) {
+               /* IGA1 doesn't have LCD scaling, so set it as centering. */
+               viafb_load_crtc_timing(lcd_centering_timging
+                                (mode_crt_reg, panel_crt_reg), IGA1);
+       } else {
+               /* Expansion */
+               if ((plvds_setting_info->display_method ==
+                    LCD_EXPANDSION) & ((set_hres != panel_hres)
+                                       || (set_vres != panel_vres))) {
+                       /* expansion timing IGA2 loaded panel set timing*/
+                       viafb_load_crtc_timing(panel_crt_reg, IGA2);
+                       DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
+                       load_lcd_scaling(set_hres, set_vres, panel_hres,
+                                        panel_vres);
+                       DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
+               } else {        /* Centering */
+                       /* centering timing IGA2 always loaded panel
+                          and mode releative timing */
+                       viafb_load_crtc_timing(lcd_centering_timging
+                                        (mode_crt_reg, panel_crt_reg), IGA2);
+                       viafb_write_reg_mask(CR79, VIACR, 0x00,
+                               BIT0 + BIT1 + BIT2);
+                       /* LCD scaling disabled */
+               }
+       }
+
+       if (set_iga == IGA1_IGA2) {
+               load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
+               /* Fill shadow registers */
+
+               switch (plvds_setting_info->lcd_panel_id) {
+               case LCD_PANEL_ID0_640X480:
+                       offset = 80;
+                       break;
+               case LCD_PANEL_ID1_800X600:
+               case LCD_PANEL_IDA_800X480:
+                       offset = 110;
+                       break;
+               case LCD_PANEL_ID2_1024X768:
+                       offset = 150;
+                       break;
+               case LCD_PANEL_ID3_1280X768:
+               case LCD_PANEL_ID4_1280X1024:
+               case LCD_PANEL_ID5_1400X1050:
+               case LCD_PANEL_ID9_1280X800:
+                       offset = 190;
+                       break;
+               case LCD_PANEL_ID6_1600X1200:
+                       offset = 250;
+                       break;
+               case LCD_PANEL_ID7_1366X768:
+               case LCD_PANEL_IDB_1360X768:
+                       offset = 212;
+                       break;
+               default:
+                       offset = 140;
+                       break;
+               }
+
+               /* Offset for simultaneous */
+               reg_value = offset;
+               viafb_load_reg_num = offset_reg.iga2_offset_reg.reg_num;
+               reg = offset_reg.iga2_offset_reg.reg;
+               viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
+               DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
+               viafb_load_fetch_count_reg(set_hres, 4, IGA2);
+               /* Fetch count for simultaneous */
+       } else {                /* SAMM */
+               /* Offset for IGA2 only */
+               viafb_load_offset_reg(set_hres, mode_bpp / 8, set_iga);
+               /* Fetch count for IGA2 only */
+               viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
+
+               if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+                   && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+                       viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
+
+               viafb_set_color_depth(mode_bpp / 8, set_iga);
+       }
+
+       fill_lcd_format();
+
+       pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
+       DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
+       viafb_set_vclock(pll_D_N, set_iga);
+
+       viafb_set_output_path(DEVICE_LCD, set_iga,
+               plvds_chip_info->output_interface);
+       lcd_patch_skew(plvds_setting_info, plvds_chip_info);
+
+       /* If K8M800, enable LCD Prefetch Mode. */
+       if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
+           || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
+               viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
+
+       load_lcd_patch_regs(set_hres, set_vres,
+                           plvds_setting_info->lcd_panel_id, set_iga);
+
+       DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
+
+       /* Patch for non 32bit alignment mode */
+       via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
+}
+
+static void integrated_lvds_disable(struct lvds_setting_information
+                            *plvds_setting_info,
+                            struct lvds_chip_information *plvds_chip_info)
+{
+       bool turn_off_first_powersequence = false;
+       bool turn_off_second_powersequence = false;
+       if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
+               turn_off_first_powersequence = true;
+       if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
+               turn_off_first_powersequence = true;
+       if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
+               turn_off_second_powersequence = true;
+       if (turn_off_second_powersequence) {
+               /* Use second power sequence control: */
+
+               /* Turn off power sequence. */
+               viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
+
+               /* Turn off back light. */
+               viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
+       }
+       if (turn_off_first_powersequence) {
+               /* Use first power sequence control: */
+
+               /* Turn off power sequence. */
+               viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
+
+               /* Turn off back light. */
+               viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
+       }
+
+       /* Turn DFP High/Low Pad off. */
+       viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
+
+       /* Power off LVDS channel. */
+       switch (plvds_chip_info->output_interface) {
+       case INTERFACE_LVDS0:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
+                       break;
+               }
+
+       case INTERFACE_LVDS1:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
+                       break;
+               }
+
+       case INTERFACE_LVDS0LVDS1:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
+                       break;
+               }
+       }
+}
+
+static void integrated_lvds_enable(struct lvds_setting_information
+                           *plvds_setting_info,
+                           struct lvds_chip_information *plvds_chip_info)
+{
+       bool turn_on_first_powersequence = false;
+       bool turn_on_second_powersequence = false;
+
+       DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
+                 plvds_chip_info->output_interface);
+       if (plvds_setting_info->lcd_mode == LCD_SPWG)
+               viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
+        else
+               viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
+       if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
+               turn_on_first_powersequence = true;
+       if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
+               turn_on_first_powersequence = true;
+       if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
+               turn_on_second_powersequence = true;
+
+       if (turn_on_second_powersequence) {
+               /* Use second power sequence control: */
+
+               /* Use hardware control power sequence. */
+               viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
+
+               /* Turn on back light. */
+               viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
+
+               /* Turn on hardware power sequence. */
+               viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
+       }
+       if (turn_on_first_powersequence) {
+               /* Use first power sequence control: */
+
+               /* Use hardware control power sequence. */
+               viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
+
+               /* Turn on back light. */
+               viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
+
+               /* Turn on hardware power sequence. */
+               viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+       }
+
+       /* Turn DFP High/Low pad on. */
+       viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
+
+       /* Power on LVDS channel. */
+       switch (plvds_chip_info->output_interface) {
+       case INTERFACE_LVDS0:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
+                       break;
+               }
+
+       case INTERFACE_LVDS1:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
+                       break;
+               }
+
+       case INTERFACE_LVDS0LVDS1:
+               {
+                       viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
+                       break;
+               }
+       }
+}
+
+void viafb_lcd_disable(void)
+{
+
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               lcd_powersequence_off();
+               /* DI1 pad off */
+               viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
+       } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+               if (viafb_LCD2_ON
+                   && (INTEGRATED_LVDS ==
+                       viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+                       integrated_lvds_disable(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info2);
+               if (INTEGRATED_LVDS ==
+                       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+                       integrated_lvds_disable(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info);
+               if (VT1636_LVDS == viaparinfo->chip_info->
+                       lvds_chip_info.lvds_chip_name)
+                       viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info);
+       } else if (VT1636_LVDS ==
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+               viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
+                                   &viaparinfo->chip_info->lvds_chip_info);
+       } else {
+               /* DFP-HL pad off          */
+               viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
+               /* Backlight off           */
+               viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
+               /* 24 bit DI data paht off */
+               viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
+               /* Simultaneout disabled   */
+               viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
+       }
+
+       /* Disable expansion bit   */
+       viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
+       /* CRT path set to IGA1    */
+       viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
+       /* Simultaneout disabled   */
+       viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
+       /* IGA2 path disabled      */
+       viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
+
+}
+
+void viafb_lcd_enable(void)
+{
+       if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
+               /* DI1 pad on */
+               viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
+               lcd_powersequence_on();
+       } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
+               if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
+                       viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
+                       integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
+                               &viaparinfo->chip_info->lvds_chip_info2);
+               if (INTEGRATED_LVDS ==
+                       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
+                       integrated_lvds_enable(viaparinfo->lvds_setting_info,
+                               &viaparinfo->chip_info->lvds_chip_info);
+               if (VT1636_LVDS == viaparinfo->chip_info->
+                       lvds_chip_info.lvds_chip_name)
+                       viafb_enable_lvds_vt1636(viaparinfo->
+                       lvds_setting_info, &viaparinfo->chip_info->
+                       lvds_chip_info);
+       } else if (VT1636_LVDS ==
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+               viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
+                                  &viaparinfo->chip_info->lvds_chip_info);
+       } else {
+               /* DFP-HL pad on           */
+               viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
+               /* Backlight on            */
+               viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
+               /* 24 bit DI data paht on  */
+               viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
+
+               /* Set data source selection bit by iga path */
+               if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+                       /* DFP-H set to IGA1       */
+                       viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
+                       /* DFP-L set to IGA1       */
+                       viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
+               } else {
+                       /* DFP-H set to IGA2       */
+                       viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
+                       /* DFP-L set to IGA2       */
+                       viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
+               }
+               /* LCD enabled             */
+               viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
+       }
+
+       if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
+           || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
+               /* CRT path set to IGA2    */
+               viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
+               /* IGA2 path disabled      */
+               viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
+               /* IGA2 path enabled       */
+       } else {                /* IGA2 */
+               viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
+       }
+
+}
+
+static void lcd_powersequence_off(void)
+{
+       int i, mask, data;
+
+       /* Software control power sequence */
+       viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+       for (i = 0; i < 3; i++) {
+               mask = PowerSequenceOff[0][i];
+               data = PowerSequenceOff[1][i] & mask;
+               viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+               udelay(PowerSequenceOff[2][i]);
+       }
+
+       /* Disable LCD */
+       viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
+}
+
+static void lcd_powersequence_on(void)
+{
+       int i, mask, data;
+
+       /* Software control power sequence */
+       viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
+
+       /* Enable LCD */
+       viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
+
+       for (i = 0; i < 3; i++) {
+               mask = PowerSequenceOn[0][i];
+               data = PowerSequenceOn[1][i] & mask;
+               viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
+               udelay(PowerSequenceOn[2][i]);
+       }
+
+       udelay(1);
+}
+
+static void fill_lcd_format(void)
+{
+       u8 bdithering = 0, bdual = 0;
+
+       if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
+               bdual = BIT4;
+       if (viaparinfo->lvds_setting_info->LCDDithering)
+               bdithering = BIT0;
+       /* Dual & Dithering */
+       viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
+}
+
+static void check_diport_of_integrated_lvds(
+       struct lvds_chip_information *plvds_chip_info,
+                                    struct lvds_setting_information
+                                    *plvds_setting_info)
+{
+       /* Determine LCD DI Port by hardware layout. */
+       switch (viafb_display_hardware_layout) {
+       case HW_LAYOUT_LCD_ONLY:
+               {
+                       if (plvds_setting_info->device_lcd_dualedge) {
+                               plvds_chip_info->output_interface =
+                                   INTERFACE_LVDS0LVDS1;
+                       } else {
+                               plvds_chip_info->output_interface =
+                                   INTERFACE_LVDS0;
+                       }
+
+                       break;
+               }
+
+       case HW_LAYOUT_DVI_ONLY:
+               {
+                       plvds_chip_info->output_interface = INTERFACE_NONE;
+                       break;
+               }
+
+       case HW_LAYOUT_LCD1_LCD2:
+       case HW_LAYOUT_LCD_EXTERNAL_LCD2:
+               {
+                       plvds_chip_info->output_interface =
+                           INTERFACE_LVDS0LVDS1;
+                       break;
+               }
+
+       case HW_LAYOUT_LCD_DVI:
+               {
+                       plvds_chip_info->output_interface = INTERFACE_LVDS1;
+                       break;
+               }
+
+       default:
+               {
+                       plvds_chip_info->output_interface = INTERFACE_LVDS1;
+                       break;
+               }
+       }
+
+       DEBUG_MSG(KERN_INFO
+                 "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
+                 viafb_display_hardware_layout,
+                 plvds_chip_info->output_interface);
+}
+
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+                               *plvds_chip_info,
+                               struct lvds_setting_information
+                               *plvds_setting_info)
+{
+       if (INTERFACE_NONE != plvds_chip_info->output_interface) {
+               /*Do nothing, lcd port is specified by module parameter */
+               return;
+       }
+
+       switch (plvds_chip_info->lvds_chip_name) {
+
+       case VT1636_LVDS:
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_CX700:
+                       plvds_chip_info->output_interface = INTERFACE_DVP1;
+                       break;
+               case UNICHROME_CN700:
+                       plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+                       break;
+               default:
+                       plvds_chip_info->output_interface = INTERFACE_DVP0;
+                       break;
+               }
+               break;
+
+       case INTEGRATED_LVDS:
+               check_diport_of_integrated_lvds(plvds_chip_info,
+                                               plvds_setting_info);
+               break;
+
+       default:
+               switch (viaparinfo->chip_info->gfx_chip_name) {
+               case UNICHROME_K8M890:
+               case UNICHROME_P4M900:
+               case UNICHROME_P4M890:
+                       plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
+                       break;
+               default:
+                       plvds_chip_info->output_interface = INTERFACE_DFP;
+                       break;
+               }
+               break;
+       }
+}
+
+static struct display_timing lcd_centering_timging(struct display_timing
+                                           mode_crt_reg,
+                                           struct display_timing panel_crt_reg)
+{
+       struct display_timing crt_reg;
+
+       crt_reg.hor_total = panel_crt_reg.hor_total;
+       crt_reg.hor_addr = mode_crt_reg.hor_addr;
+       crt_reg.hor_blank_start =
+           (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
+           crt_reg.hor_addr;
+       crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
+       crt_reg.hor_sync_start =
+           (panel_crt_reg.hor_sync_start -
+            panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
+       crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
+
+       crt_reg.ver_total = panel_crt_reg.ver_total;
+       crt_reg.ver_addr = mode_crt_reg.ver_addr;
+       crt_reg.ver_blank_start =
+           (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
+           crt_reg.ver_addr;
+       crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
+       crt_reg.ver_sync_start =
+           (panel_crt_reg.ver_sync_start -
+            panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
+       crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
+
+       return crt_reg;
+}
+
+static void load_crtc_shadow_timing(struct display_timing mode_timing,
+                            struct display_timing panel_timing)
+{
+       struct io_register *reg = NULL;
+       int i;
+       int viafb_load_reg_Num = 0;
+       int reg_value = 0;
+
+       if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
+               /* Expansion */
+               for (i = 12; i < 20; i++) {
+                       switch (i) {
+                       case H_TOTAL_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_HOR_TOTAL_SHADOW_FORMULA
+                                   (panel_timing.hor_total);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.hor_total_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
+                               break;
+                       case H_BLANK_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_HOR_BLANK_END_SHADOW_FORMULA
+                                   (panel_timing.hor_blank_start,
+                                    panel_timing.hor_blank_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   hor_blank_end_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   hor_blank_end_shadow.reg;
+                               break;
+                       case V_TOTAL_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_TOTAL_SHADOW_FORMULA
+                                   (panel_timing.ver_total);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_total_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
+                               break;
+                       case V_ADDR_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_ADDR_SHADOW_FORMULA
+                                   (panel_timing.ver_addr);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_addr_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
+                               break;
+                       case V_BLANK_SATRT_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_START_SHADOW_FORMULA
+                                   (panel_timing.ver_blank_start);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_start_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_start_shadow.reg;
+                               break;
+                       case V_BLANK_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_END_SHADOW_FORMULA
+                                   (panel_timing.ver_blank_start,
+                                    panel_timing.ver_blank_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_end_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_end_shadow.reg;
+                               break;
+                       case V_SYNC_SATRT_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_START_SHADOW_FORMULA
+                                   (panel_timing.ver_sync_start);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_sync_start_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_sync_start_shadow.reg;
+                               break;
+                       case V_SYNC_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_END_SHADOW_FORMULA
+                                   (panel_timing.ver_sync_start,
+                                    panel_timing.ver_sync_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_sync_end_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_sync_end_shadow.reg;
+                               break;
+                       }
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_Num, reg, VIACR);
+               }
+       } else {                /* Centering */
+               for (i = 12; i < 20; i++) {
+                       switch (i) {
+                       case H_TOTAL_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_HOR_TOTAL_SHADOW_FORMULA
+                                   (panel_timing.hor_total);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.hor_total_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
+                               break;
+                       case H_BLANK_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_HOR_BLANK_END_SHADOW_FORMULA
+                                   (panel_timing.hor_blank_start,
+                                    panel_timing.hor_blank_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   hor_blank_end_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   hor_blank_end_shadow.reg;
+                               break;
+                       case V_TOTAL_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_TOTAL_SHADOW_FORMULA
+                                   (panel_timing.ver_total);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_total_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
+                               break;
+                       case V_ADDR_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_ADDR_SHADOW_FORMULA
+                                   (mode_timing.ver_addr);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_addr_shadow.
+                                   reg_num;
+                               reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
+                               break;
+                       case V_BLANK_SATRT_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_START_SHADOW_FORMULA
+                                   (mode_timing.ver_blank_start);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_start_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_start_shadow.reg;
+                               break;
+                       case V_BLANK_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_BLANK_END_SHADOW_FORMULA
+                                   (panel_timing.ver_blank_start,
+                                    panel_timing.ver_blank_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_end_shadow.reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.
+                                   ver_blank_end_shadow.reg;
+                               break;
+                       case V_SYNC_SATRT_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_START_SHADOW_FORMULA(
+                                   (panel_timing.ver_sync_start -
+                                   panel_timing.ver_blank_start) +
+                                   (panel_timing.ver_addr -
+                                   mode_timing.ver_addr) / 2 +
+                                   mode_timing.ver_addr);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_sync_start_shadow.
+                                   reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.ver_sync_start_shadow.
+                                   reg;
+                               break;
+                       case V_SYNC_END_SHADOW_INDEX:
+                               reg_value =
+                                   IGA2_VER_SYNC_END_SHADOW_FORMULA(
+                                   (panel_timing.ver_sync_start -
+                                   panel_timing.ver_blank_start) +
+                                   (panel_timing.ver_addr -
+                                   mode_timing.ver_addr) / 2 +
+                                   mode_timing.ver_addr,
+                                   panel_timing.ver_sync_end);
+                               viafb_load_reg_Num =
+                                   iga2_shadow_crtc_reg.ver_sync_end_shadow.
+                                   reg_num;
+                               reg =
+                                   iga2_shadow_crtc_reg.ver_sync_end_shadow.
+                                   reg;
+                               break;
+                       }
+                       viafb_load_reg(reg_value,
+                               viafb_load_reg_Num, reg, VIACR);
+               }
+       }
+}
+
+bool viafb_lcd_get_mobile_state(bool *mobile)
+{
+       unsigned char *romptr, *tableptr;
+       u8 core_base;
+       unsigned char *biosptr;
+       /* Rom address */
+       u32 romaddr = 0x000C0000;
+       u16 start_pattern = 0;
+
+       biosptr = ioremap(romaddr, 0x10000);
+
+       memcpy(&start_pattern, biosptr, 2);
+       /* Compare pattern */
+       if (start_pattern == 0xAA55) {
+               /* Get the start of Table */
+               /* 0x1B means BIOS offset position */
+               romptr = biosptr + 0x1B;
+               tableptr = biosptr + *((u16 *) romptr);
+
+               /* Get the start of biosver structure */
+               /* 18 means BIOS version position. */
+               romptr = tableptr + 18;
+               romptr = biosptr + *((u16 *) romptr);
+
+               /* The offset should be 44, but the
+                  actual image is less three char. */
+               /* pRom += 44; */
+               romptr += 41;
+
+               core_base = *romptr++;
+
+               if (core_base & 0x8)
+                       *mobile = false;
+               else
+                       *mobile = true;
+               /* release memory */
+               iounmap(biosptr);
+
+               return true;
+       } else {
+               iounmap(biosptr);
+               return false;
+       }
+}
+
+static void viafb_load_scaling_factor_for_p4m900(int set_hres,
+       int set_vres, int panel_hres, int panel_vres)
+{
+       int h_scaling_factor;
+       int v_scaling_factor;
+       u8 cra2 = 0;
+       u8 cr77 = 0;
+       u8 cr78 = 0;
+       u8 cr79 = 0;
+       u8 cr9f = 0;
+       /* Check if expansion for horizontal */
+       if (set_hres < panel_hres) {
+               /* Load Horizontal Scaling Factor */
+
+               /* For VIA_K8M800 or later chipsets. */
+               h_scaling_factor =
+                   K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
+               /* HSCaleFactor[1:0] at CR9F[1:0] */
+               cr9f = h_scaling_factor & 0x0003;
+               /* HSCaleFactor[9:2] at CR77[7:0] */
+               cr77 = (h_scaling_factor & 0x03FC) >> 2;
+               /* HSCaleFactor[11:10] at CR79[5:4] */
+               cr79 = (h_scaling_factor & 0x0C00) >> 10;
+               cr79 <<= 4;
+
+               /* Horizontal scaling enabled */
+               cra2 = 0xC0;
+
+               DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
+                         h_scaling_factor);
+       } else {
+               /* Horizontal scaling disabled */
+               cra2 = 0x00;
+       }
+
+       /* Check if expansion for vertical */
+       if (set_vres < panel_vres) {
+               /* Load Vertical Scaling Factor */
+
+               /* For VIA_K8M800 or later chipsets. */
+               v_scaling_factor =
+                   K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
+
+               /* Vertical scaling enabled */
+               cra2 |= 0x08;
+               /* VSCaleFactor[0] at CR79[3] */
+               cr79 |= ((v_scaling_factor & 0x0001) << 3);
+               /* VSCaleFactor[8:1] at CR78[7:0] */
+               cr78 |= (v_scaling_factor & 0x01FE) >> 1;
+               /* VSCaleFactor[10:9] at CR79[7:6] */
+               cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
+
+               DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
+                         v_scaling_factor);
+       } else {
+               /* Vertical scaling disabled */
+               cra2 |= 0x00;
+       }
+
+       viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
+       viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
+       viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
+       viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
+       viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
+}
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
new file mode 100644 (file)
index 0000000..071f47c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __LCD_H__
+#define __LCD_H__
+
+/*Definition TMDS Device ID register*/
+#define     VT1631_DEVICE_ID_REG        0x02
+#define     VT1631_DEVICE_ID            0x92
+
+#define     VT3271_DEVICE_ID_REG        0x02
+#define     VT3271_DEVICE_ID            0x71
+
+#define     GET_LCD_SIZE_BY_SYSTEM_BIOS     0x01
+#define     GET_LCD_SIZE_BY_VGA_BIOS        0x02
+#define     GET_LCD_SZIE_BY_HW_STRAPPING    0x03
+#define     GET_LCD_SIZE_BY_USER_SETTING    0x04
+
+/* Definition DVI Panel ID*/
+/* Resolution: 640x480,   Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID0_640X480       0x00
+/* Resolution: 800x600,   Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID1_800X600       0x01
+/* Resolution: 1024x768,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID2_1024X768      0x02
+/* Resolution: 1280x768,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_ID3_1280X768      0x03
+/* Resolution: 1280x1024, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID4_1280X1024     0x04
+/* Resolution: 1400x1050, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID5_1400X1050     0x05
+/* Resolution: 1600x1200, Channel: dual,   Dithering: Enable */
+#define     LCD_PANEL_ID6_1600X1200     0x06
+/* Resolution: 1366x768,  Channel: single, Dithering: Disable */
+#define     LCD_PANEL_ID7_1366X768      0x07
+/* Resolution: 1024x600,  Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_ID8_1024X600      0x08
+/* Resolution: 1280x800,  Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_ID9_1280X800      0x09
+/* Resolution: 800x480,   Channel: single, Dithering: Enable*/
+#define     LCD_PANEL_IDA_800X480       0x0A
+/* Resolution: 1360x768,   Channel: single, Dithering: Disable*/
+#define     LCD_PANEL_IDB_1360X768     0x0B
+/* Resolution: 480x640,  Channel: single, Dithering: Enable */
+#define     LCD_PANEL_IDC_480X640      0x0C
+
+
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+                       *plvds_setting_info,
+                       struct lvds_chip_information *plvds_chip_info);
+void viafb_lcd_disable(void);
+void viafb_lcd_enable(void);
+void viafb_init_lcd_size(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+                               *plvds_chip_info,
+                               struct lvds_setting_information
+                               *plvds_setting_info);
+void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
+                 struct lvds_setting_information *plvds_setting_info,
+                 struct lvds_chip_information *plvds_chip_info);
+int viafb_lvds_trasmitter_identify(void);
+void viafb_init_lvds_output_interface(struct lvds_chip_information
+                               *plvds_chip_info,
+                               struct lvds_setting_information
+                               *plvds_setting_info);
+bool viafb_lcd_get_mobile_state(bool *mobile);
+void viafb_load_crtc_timing(struct display_timing device_timing,
+       int set_iga);
+
+#endif /* __LCD_H__ */
diff --git a/drivers/video/via/lcdtbl.h b/drivers/video/via/lcdtbl.h
new file mode 100644 (file)
index 0000000..6f3dd80
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __LCDTBL_H__
+#define __LCDTBL_H__
+
+#include "share.h"
+
+/* CLE266 Software Power Sequence */
+/* {Mask}, {Data}, {Delay} */
+int PowerSequenceOn[3][3] =
+    { {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} };
+int PowerSequenceOff[3][3] =
+    { {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} };
+
+/* ++++++ P880 ++++++ */
+/*   Panel 1600x1200   */
+struct io_reg P880_LCD_RES_6X4_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x5E},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xD6}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR44, 0xFF, 0x7D}, {VIASR, SR45, 0xFF, 0x8C},
+       {VIASR, SR46, 0xFF, 0x02}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_6X4_16X12 ARRAY_SIZE(P880_LCD_RES_6X4_16X12)
+
+struct io_reg P880_LCD_RES_7X4_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x78},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR44, 0xFF, 0x78}, {VIASR, SR45, 0xFF, 0x8C},
+       {VIASR, SR46, 0xFF, 0x01}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_7X4_16X12 ARRAY_SIZE(P880_LCD_RES_7X4_16X12)
+
+struct io_reg P880_LCD_RES_8X6_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR44, 0xFF, 0x6D}, {VIASR, SR45, 0xFF, 0x88},
+       {VIASR, SR46, 0xFF, 0x03}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_8X6_16X12 ARRAY_SIZE(P880_LCD_RES_8X6_16X12)
+
+struct io_reg P880_LCD_RES_10X7_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xAF},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR44, 0xFF, 0x92}, {VIASR, SR45, 0xFF, 0x88},
+       {VIASR, SR46, 0xFF, 0x03}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_10X7_16X12 ARRAY_SIZE(P880_LCD_RES_10X7_16X12)
+
+struct io_reg P880_LCD_RES_12X10_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xD4},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR44, 0xFF, 0xF6}, {VIASR, SR45, 0xFF, 0x88},
+       {VIASR, SR46, 0xFF, 0x05}
+
+};
+
+#define NUM_TOTAL_P880_LCD_RES_12X10_16X12 ARRAY_SIZE(P880_LCD_RES_12X10_16X12)
+
+/*   Panel 1400x1050   */
+struct io_reg P880_LCD_RES_6X4_14X10[] = {
+       /* 640x480                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x63},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR44, 0xFF, 0xC6}, {VIASR, SR45, 0xFF, 0x8C},
+       {VIASR, SR46, 0xFF, 0x05}
+};
+
+#define NUM_TOTAL_P880_LCD_RES_6X4_14X10 ARRAY_SIZE(P880_LCD_RES_6X4_14X10)
+
+struct io_reg P880_LCD_RES_8X6_14X10[] = {
+       /* 800x600                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR44, 0xFF, 0x06}, {VIASR, SR45, 0xFF, 0x8D},
+       {VIASR, SR46, 0xFF, 0x05}
+};
+
+#define NUM_TOTAL_P880_LCD_RES_8X6_14X10 ARRAY_SIZE(P880_LCD_RES_8X6_14X10)
+
+/* ++++++ K400 ++++++ */
+/*   Panel 1600x1200   */
+struct io_reg K400_LCD_RES_6X4_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x5E},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xDA}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x7F}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_16X12 ARRAY_SIZE(K400_LCD_RES_6X4_16X12)
+
+struct io_reg K400_LCD_RES_7X4_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x78},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x46}, {VIASR, SR47, 0xFF, 0x3D}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_16X12 ARRAY_SIZE(K400_LCD_RES_7X4_16X12)
+
+struct io_reg K400_LCD_RES_8X6_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x85}, {VIASR, SR47, 0xFF, 0x6F}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_16X12 ARRAY_SIZE(K400_LCD_RES_8X6_16X12)
+
+struct io_reg K400_LCD_RES_10X7_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xAF},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x45}, {VIASR, SR47, 0xFF, 0x4A}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_16X12 ARRAY_SIZE(K400_LCD_RES_10X7_16X12)
+
+struct io_reg K400_LCD_RES_12X10_16X12[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
+       {VIACR, CR5D, 0x40, 0x40},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xD4},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x47}, {VIASR, SR47, 0xFF, 0x7C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_16X12 ARRAY_SIZE(K400_LCD_RES_12X10_16X12)
+
+/*   Panel 1400x1050   */
+struct io_reg K400_LCD_RES_6X4_14X10[] = {
+       /* 640x400                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x63},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_14X10 ARRAY_SIZE(K400_LCD_RES_6X4_14X10)
+
+struct io_reg K400_LCD_RES_8X6_14X10[] = {
+       /* 800x600                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_14X10 ARRAY_SIZE(K400_LCD_RES_8X6_14X10)
+
+struct io_reg K400_LCD_RES_10X7_14X10[] = {
+       /* 1024x768                         */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xA7},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_14X10 ARRAY_SIZE(K400_LCD_RES_10X7_14X10)
+
+struct io_reg K400_LCD_RES_12X10_14X10[] = {
+       /* 1280x768, 1280x960, 1280x1024    */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xD2},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_14X10 ARRAY_SIZE(K400_LCD_RES_12X10_14X10)
+
+/* ++++++ K400 ++++++ */
+/*   Panel 1366x768   */
+struct io_reg K400_LCD_RES_6X4_1366X7[] = {
+       /* 640x400                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x64},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_1366X7 ARRAY_SIZE(K400_LCD_RES_6X4_1366X7)
+
+struct io_reg K400_LCD_RES_7X4_1366X7[] = {
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x75},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_1366X7 ARRAY_SIZE(K400_LCD_RES_7X4_1366X7)
+
+struct io_reg K400_LCD_RES_8X6_1366X7[] = {
+       /* 800x600                          */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x82},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_1366X7 ARRAY_SIZE(K400_LCD_RES_8X6_1366X7)
+
+struct io_reg K400_LCD_RES_10X7_1366X7[] = {
+       /* 1024x768                         */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xA7},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_1366X7 ARRAY_SIZE(K400_LCD_RES_10X7_1366X7)
+
+struct io_reg K400_LCD_RES_12X10_1366X7[] = {
+       /* 1280x768, 1280x960, 1280x1024    */
+       /* IGA2 Horizontal Total            */
+       {VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
+       /* IGA2 Horizontal Blank End        */
+       {VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
+       {VIACR, CR5D, 0x40, 0x24},
+       /* IGA2 Horizontal Total Shadow     */
+       {VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
+       /* IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xD2},
+       /* IGA2 Offset                      */
+       {VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
+       /* VCLK                             */
+       {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_12X10_1366X7\
+                       ARRAY_SIZE(K400_LCD_RES_12X10_1366X7)
+
+/* ++++++ K400 ++++++ */
+/*   Panel 1280x1024   */
+struct io_reg K400_LCD_RES_6X4_12X10[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+       {VIACR, CR5D, 0x40, 0x1C},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x34},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x63},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xAA}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_12X10 ARRAY_SIZE(K400_LCD_RES_6X4_12X10)
+
+struct io_reg K400_LCD_RES_7X4_12X10[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+       {VIACR, CR5D, 0x40, 0x1C},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x68}, {VIACR, CR71, 0x08, 0x34},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x6C},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xA8}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0xED}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_12X10 ARRAY_SIZE(K400_LCD_RES_7X4_12X10)
+
+struct io_reg K400_LCD_RES_8X6_12X10[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+       {VIACR, CR5D, 0x40, 0x1C},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x34},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_12X10 ARRAY_SIZE(K400_LCD_RES_8X6_12X10)
+
+struct io_reg K400_LCD_RES_10X7_12X10[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
+       {VIACR, CR5D, 0x40, 0x1C},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x34},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0xA7},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x04},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_10X7_12X10 ARRAY_SIZE(K400_LCD_RES_10X7_12X10)
+
+/* ++++++ K400 ++++++ */
+/*   Panel 1024x768    */
+struct io_reg K400_LCD_RES_6X4_10X7[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x64},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_10X7 ARRAY_SIZE(K400_LCD_RES_6X4_10X7)
+
+struct io_reg K400_LCD_RES_7X4_10X7[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x75},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_10X7 ARRAY_SIZE(K400_LCD_RES_7X4_10X7)
+
+struct io_reg K400_LCD_RES_8X6_10X7[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
+       {VIACR, CR5D, 0x40, 0x13},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x82},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_8X6_10X7 ARRAY_SIZE(K400_LCD_RES_8X6_10X7)
+
+/* ++++++ K400 ++++++ */
+/*   Panel 800x600     */
+struct io_reg K400_LCD_RES_6X4_8X6[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x1A}, {VIACR, CR55, 0x0F, 0x34},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x1A}, {VIACR, CR54, 0x38, 0xE3},
+       {VIACR, CR5D, 0x40, 0x12},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x22},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x63},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0x6E}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0x86}, {VIASR, SR47, 0xFF, 0xB3}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_6X4_8X6 ARRAY_SIZE(K400_LCD_RES_6X4_8X6)
+
+struct io_reg K400_LCD_RES_7X4_8X6[] = {
+       /*IGA2 Horizontal Total */
+       {VIACR, CR50, 0xFF, 0x1F}, {VIACR, CR55, 0x0F, 0x34},
+       /*IGA2 Horizontal Blank End */
+       {VIACR, CR53, 0xFF, 0x1F}, {VIACR, CR54, 0x38, 0xE3},
+       {VIACR, CR5D, 0x40, 0x12},
+       /*IGA2 Horizontal Total Shadow */
+       {VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x22},
+       /*IGA2 Horizontal Blank End Shadow */
+       {VIACR, CR6E, 0xFF, 0x83},
+       /*IGA2 Offset */
+       {VIACR, CR66, 0xFF, 0x78}, {VIACR, CR67, 0x03, 0x00},
+        /*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x59}
+};
+
+#define NUM_TOTAL_K400_LCD_RES_7X4_8X6 ARRAY_SIZE(K400_LCD_RES_7X4_8X6)
+
+#endif /* __LCDTBL_H__ */
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
new file mode 100644 (file)
index 0000000..2e1254d
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __SHARE_H__
+#define __SHARE_H__
+
+/* Define Return Value */
+#define FAIL        -1
+#define OK          1
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Define Bit Field */
+#define BIT0    0x01
+#define BIT1    0x02
+#define BIT2    0x04
+#define BIT3    0x08
+#define BIT4    0x10
+#define BIT5    0x20
+#define BIT6    0x40
+#define BIT7    0x80
+
+/* Video Memory Size */
+#define VIDEO_MEMORY_SIZE_16M    0x1000000
+
+/* Definition Mode Index
+*/
+#define     VIA_RES_640X480                    0
+#define     VIA_RES_800X600                    1
+#define     VIA_RES_1024X768                   2
+#define     VIA_RES_1152X864                   3
+#define     VIA_RES_1280X1024                  4
+#define     VIA_RES_1600X1200                  5
+#define     VIA_RES_1440X1050                  6
+#define     VIA_RES_1280X768                   7
+#define     VIA_RES_1280X960                   8
+#define     VIA_RES_1920X1440                  9
+#define     VIA_RES_848X480                    10
+#define     VIA_RES_1400X1050                  11
+#define     VIA_RES_720X480                    12
+#define     VIA_RES_720X576                    13
+#define     VIA_RES_1024X512                   14
+#define     VIA_RES_856X480                    15
+#define     VIA_RES_1024X576                   16
+#define     VIA_RES_640X400                    17
+#define     VIA_RES_1280X720                   18
+#define     VIA_RES_1920X1080                  19
+#define     VIA_RES_800X480                    20
+#define     VIA_RES_1368X768                   21
+#define     VIA_RES_1024X600                   22
+#define     VIA_RES_1280X800                   23
+#define     VIA_RES_1680X1050                  24
+#define     VIA_RES_960X600                    25
+#define     VIA_RES_1000X600                   26
+#define     VIA_RES_1088X612                   27
+#define     VIA_RES_1152X720                   28
+#define     VIA_RES_1200X720                   29
+#define     VIA_RES_1280X600                   30
+#define     VIA_RES_1360X768                   31
+#define     VIA_RES_1366X768                   32
+#define     VIA_RES_1440X900                   33
+#define     VIA_RES_1600X900                   34
+#define     VIA_RES_1600X1024                  35
+#define     VIA_RES_1792X1344                  36
+#define     VIA_RES_1856X1392                  37
+#define     VIA_RES_1920X1200                  38
+#define     VIA_RES_2048X1536                  39
+#define     VIA_RES_480X640                    40
+
+/*Reduce Blanking*/
+#define     VIA_RES_1360X768_RB                131
+#define     VIA_RES_1440X900_RB                133
+#define     VIA_RES_1400X1050_RB               111
+#define     VIA_RES_1600X900_RB                134
+#define     VIA_RES_1680X1050_RB               124
+#define     VIA_RES_1920X1080_RB               119
+#define     VIA_RES_1920X1200_RB               138
+
+#define     VIA_RES_INVALID                    255
+
+/* standard VGA IO port
+*/
+#define VIARMisc    0x3CC
+#define VIAWMisc    0x3C2
+#define VIAStatus   0x3DA
+#define VIACR       0x3D4
+#define VIASR       0x3C4
+#define VIAGR       0x3CE
+#define VIAAR       0x3C0
+
+#define StdCR       0x19
+#define StdSR       0x04
+#define StdGR       0x09
+#define StdAR       0x14
+
+#define PatchCR     11
+
+/* Display path */
+#define IGA1        1
+#define IGA2        2
+#define IGA1_IGA2   3
+
+/* Define Color Depth  */
+#define MODE_8BPP       1
+#define MODE_16BPP      2
+#define MODE_32BPP      4
+
+#define GR20    0x20
+#define GR21    0x21
+#define GR22    0x22
+
+/* Sequencer Registers */
+#define SR01    0x01
+#define SR10    0x10
+#define SR12    0x12
+#define SR15    0x15
+#define SR16    0x16
+#define SR17    0x17
+#define SR18    0x18
+#define SR1B    0x1B
+#define SR1A    0x1A
+#define SR1C    0x1C
+#define SR1D    0x1D
+#define SR1E    0x1E
+#define SR1F    0x1F
+#define SR20    0x20
+#define SR21    0x21
+#define SR22    0x22
+#define SR2A    0x2A
+#define SR2D    0x2D
+#define SR2E    0x2E
+
+#define SR30    0x30
+#define SR39    0x39
+#define SR3D    0x3D
+#define SR3E    0x3E
+#define SR3F    0x3F
+#define SR40    0x40
+#define SR43    0x43
+#define SR44    0x44
+#define SR45    0x45
+#define SR46    0x46
+#define SR47    0x47
+#define SR48    0x48
+#define SR49    0x49
+#define SR4A    0x4A
+#define SR4B    0x4B
+#define SR4C    0x4C
+#define SR52    0x52
+#define SR5E    0x5E
+#define SR65    0x65
+
+/* CRT Controller Registers */
+#define CR00    0x00
+#define CR01    0x01
+#define CR02    0x02
+#define CR03    0x03
+#define CR04    0x04
+#define CR05    0x05
+#define CR06    0x06
+#define CR07    0x07
+#define CR08    0x08
+#define CR09    0x09
+#define CR0A    0x0A
+#define CR0B    0x0B
+#define CR0C    0x0C
+#define CR0D    0x0D
+#define CR0E    0x0E
+#define CR0F    0x0F
+#define CR10    0x10
+#define CR11    0x11
+#define CR12    0x12
+#define CR13    0x13
+#define CR14    0x14
+#define CR15    0x15
+#define CR16    0x16
+#define CR17    0x17
+#define CR18    0x18
+
+/* Extend CRT Controller Registers */
+#define CR30    0x30
+#define CR31    0x31
+#define CR32    0x32
+#define CR33    0x33
+#define CR34    0x34
+#define CR35    0x35
+#define CR36    0x36
+#define CR37    0x37
+#define CR38    0x38
+#define CR39    0x39
+#define CR3A    0x3A
+#define CR3B    0x3B
+#define CR3C    0x3C
+#define CR3D    0x3D
+#define CR3E    0x3E
+#define CR3F    0x3F
+#define CR40    0x40
+#define CR41    0x41
+#define CR42    0x42
+#define CR43    0x43
+#define CR44    0x44
+#define CR45    0x45
+#define CR46    0x46
+#define CR47    0x47
+#define CR48    0x48
+#define CR49    0x49
+#define CR4A    0x4A
+#define CR4B    0x4B
+#define CR4C    0x4C
+#define CR4D    0x4D
+#define CR4E    0x4E
+#define CR4F    0x4F
+#define CR50    0x50
+#define CR51    0x51
+#define CR52    0x52
+#define CR53    0x53
+#define CR54    0x54
+#define CR55    0x55
+#define CR56    0x56
+#define CR57    0x57
+#define CR58    0x58
+#define CR59    0x59
+#define CR5A    0x5A
+#define CR5B    0x5B
+#define CR5C    0x5C
+#define CR5D    0x5D
+#define CR5E    0x5E
+#define CR5F    0x5F
+#define CR60    0x60
+#define CR61    0x61
+#define CR62    0x62
+#define CR63    0x63
+#define CR64    0x64
+#define CR65    0x65
+#define CR66    0x66
+#define CR67    0x67
+#define CR68    0x68
+#define CR69    0x69
+#define CR6A    0x6A
+#define CR6B    0x6B
+#define CR6C    0x6C
+#define CR6D    0x6D
+#define CR6E    0x6E
+#define CR6F    0x6F
+#define CR70    0x70
+#define CR71    0x71
+#define CR72    0x72
+#define CR73    0x73
+#define CR74    0x74
+#define CR75    0x75
+#define CR76    0x76
+#define CR77    0x77
+#define CR78    0x78
+#define CR79    0x79
+#define CR7A    0x7A
+#define CR7B    0x7B
+#define CR7C    0x7C
+#define CR7D    0x7D
+#define CR7E    0x7E
+#define CR7F    0x7F
+#define CR80    0x80
+#define CR81    0x81
+#define CR82    0x82
+#define CR83    0x83
+#define CR84    0x84
+#define CR85    0x85
+#define CR86    0x86
+#define CR87    0x87
+#define CR88    0x88
+#define CR89    0x89
+#define CR8A    0x8A
+#define CR8B    0x8B
+#define CR8C    0x8C
+#define CR8D    0x8D
+#define CR8E    0x8E
+#define CR8F    0x8F
+#define CR90    0x90
+#define CR91    0x91
+#define CR92    0x92
+#define CR93    0x93
+#define CR94    0x94
+#define CR95    0x95
+#define CR96    0x96
+#define CR97    0x97
+#define CR98    0x98
+#define CR99    0x99
+#define CR9A    0x9A
+#define CR9B    0x9B
+#define CR9C    0x9C
+#define CR9D    0x9D
+#define CR9E    0x9E
+#define CR9F    0x9F
+#define CRA0    0xA0
+#define CRA1    0xA1
+#define CRA2    0xA2
+#define CRA3    0xA3
+#define CRD2    0xD2
+#define CRD3    0xD3
+#define CRD4    0xD4
+
+/* LUT Table*/
+#define LUT_DATA             0x3C9     /* DACDATA */
+#define LUT_INDEX_READ       0x3C7     /* DACRX */
+#define LUT_INDEX_WRITE      0x3C8     /* DACWX */
+#define DACMASK              0x3C6
+
+/* Definition Device */
+#define DEVICE_CRT  0x01
+#define DEVICE_DVI  0x03
+#define DEVICE_LCD  0x04
+
+/* Device output interface */
+#define INTERFACE_NONE          0x00
+#define INTERFACE_ANALOG_RGB    0x01
+#define INTERFACE_DVP0          0x02
+#define INTERFACE_DVP1          0x03
+#define INTERFACE_DFP_HIGH      0x04
+#define INTERFACE_DFP_LOW       0x05
+#define INTERFACE_DFP           0x06
+#define INTERFACE_LVDS0         0x07
+#define INTERFACE_LVDS1         0x08
+#define INTERFACE_LVDS0LVDS1    0x09
+#define INTERFACE_TMDS          0x0A
+
+#define HW_LAYOUT_LCD_ONLY      0x01
+#define HW_LAYOUT_DVI_ONLY      0x02
+#define HW_LAYOUT_LCD_DVI       0x03
+#define HW_LAYOUT_LCD1_LCD2     0x04
+#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
+
+/* Definition Refresh Rate */
+#define REFRESH_50      50
+#define REFRESH_60      60
+#define REFRESH_75      75
+#define REFRESH_85      85
+#define REFRESH_100     100
+#define REFRESH_120     120
+
+/* Definition Sync Polarity*/
+#define NEGATIVE        1
+#define POSITIVE        0
+
+/*480x640@60 Sync Polarity (GTF)
+*/
+#define M480X640_R60_HSP        NEGATIVE
+#define M480X640_R60_VSP        POSITIVE
+
+/*640x480@60 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R60_HSP        NEGATIVE
+#define M640X480_R60_VSP        NEGATIVE
+
+/*640x480@75 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R75_HSP        NEGATIVE
+#define M640X480_R75_VSP        NEGATIVE
+
+/*640x480@85 Sync Polarity (VESA Mode)
+*/
+#define M640X480_R85_HSP        NEGATIVE
+#define M640X480_R85_VSP        NEGATIVE
+
+/*640x480@100 Sync Polarity (GTF Mode)
+*/
+#define M640X480_R100_HSP       NEGATIVE
+#define M640X480_R100_VSP       POSITIVE
+
+/*640x480@120 Sync Polarity (GTF Mode)
+*/
+#define M640X480_R120_HSP       NEGATIVE
+#define M640X480_R120_VSP       POSITIVE
+
+/*720x480@60 Sync Polarity  (GTF Mode)
+*/
+#define M720X480_R60_HSP        NEGATIVE
+#define M720X480_R60_VSP        POSITIVE
+
+/*720x576@60 Sync Polarity  (GTF Mode)
+*/
+#define M720X576_R60_HSP        NEGATIVE
+#define M720X576_R60_VSP        POSITIVE
+
+/*800x600@60 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R60_HSP        POSITIVE
+#define M800X600_R60_VSP        POSITIVE
+
+/*800x600@75 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R75_HSP        POSITIVE
+#define M800X600_R75_VSP        POSITIVE
+
+/*800x600@85 Sync Polarity (VESA Mode)
+*/
+#define M800X600_R85_HSP        POSITIVE
+#define M800X600_R85_VSP        POSITIVE
+
+/*800x600@100 Sync Polarity (GTF Mode)
+*/
+#define M800X600_R100_HSP       NEGATIVE
+#define M800X600_R100_VSP       POSITIVE
+
+/*800x600@120 Sync Polarity (GTF Mode)
+*/
+#define M800X600_R120_HSP       NEGATIVE
+#define M800X600_R120_VSP       POSITIVE
+
+/*800x480@60 Sync Polarity  (CVT Mode)
+*/
+#define M800X480_R60_HSP        NEGATIVE
+#define M800X480_R60_VSP        POSITIVE
+
+/*848x480@60 Sync Polarity  (CVT Mode)
+*/
+#define M848X480_R60_HSP        NEGATIVE
+#define M848X480_R60_VSP        POSITIVE
+
+/*852x480@60 Sync Polarity  (GTF Mode)
+*/
+#define M852X480_R60_HSP        NEGATIVE
+#define M852X480_R60_VSP        POSITIVE
+
+/*1024x512@60 Sync Polarity (GTF Mode)
+*/
+#define M1024X512_R60_HSP       NEGATIVE
+#define M1024X512_R60_VSP       POSITIVE
+
+/*1024x600@60 Sync Polarity (GTF Mode)
+*/
+#define M1024X600_R60_HSP       NEGATIVE
+#define M1024X600_R60_VSP       POSITIVE
+
+/*1024x768@60 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R60_HSP       NEGATIVE
+#define M1024X768_R60_VSP       NEGATIVE
+
+/*1024x768@75 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R75_HSP       POSITIVE
+#define M1024X768_R75_VSP       POSITIVE
+
+/*1024x768@85 Sync Polarity (VESA Mode)
+*/
+#define M1024X768_R85_HSP       POSITIVE
+#define M1024X768_R85_VSP       POSITIVE
+
+/*1024x768@100 Sync Polarity (GTF Mode)
+*/
+#define M1024X768_R100_HSP      NEGATIVE
+#define M1024X768_R100_VSP      POSITIVE
+
+/*1152x864@75 Sync Polarity (VESA Mode)
+*/
+#define M1152X864_R75_HSP       POSITIVE
+#define M1152X864_R75_VSP       POSITIVE
+
+/*1280x720@60 Sync Polarity  (GTF Mode)
+*/
+#define M1280X720_R60_HSP       NEGATIVE
+#define M1280X720_R60_VSP       POSITIVE
+
+/* 1280x768@50 Sync Polarity  (GTF Mode) */
+#define M1280X768_R50_HSP       NEGATIVE
+#define M1280X768_R50_VSP       POSITIVE
+
+/*1280x768@60 Sync Polarity  (GTF Mode)
+*/
+#define M1280X768_R60_HSP       NEGATIVE
+#define M1280X768_R60_VSP       POSITIVE
+
+/*1280x800@60 Sync Polarity  (CVT Mode)
+*/
+#define M1280X800_R60_HSP       NEGATIVE
+#define M1280X800_R60_VSP       POSITIVE
+
+/*1280x960@60 Sync Polarity (VESA Mode)
+*/
+#define M1280X960_R60_HSP       POSITIVE
+#define M1280X960_R60_VSP       POSITIVE
+
+/*1280x1024@60 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R60_HSP      POSITIVE
+#define M1280X1024_R60_VSP      POSITIVE
+
+/* 1360x768@60 Sync Polarity (CVT Mode) */
+#define M1360X768_R60_HSP       POSITIVE
+#define M1360X768_R60_VSP       POSITIVE
+
+/* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1360X768_RB_R60_HSP       POSITIVE
+#define M1360X768_RB_R60_VSP       NEGATIVE
+
+/* 1368x768@50 Sync Polarity (GTF Mode) */
+#define M1368X768_R50_HSP       NEGATIVE
+#define M1368X768_R50_VSP       POSITIVE
+
+/* 1368x768@60 Sync Polarity (VESA Mode) */
+#define M1368X768_R60_HSP       NEGATIVE
+#define M1368X768_R60_VSP       POSITIVE
+
+/*1280x1024@75 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R75_HSP      POSITIVE
+#define M1280X1024_R75_VSP      POSITIVE
+
+/*1280x1024@85 Sync Polarity (VESA Mode)
+*/
+#define M1280X1024_R85_HSP      POSITIVE
+#define M1280X1024_R85_VSP      POSITIVE
+
+/*1440x1050@60 Sync Polarity (GTF Mode)
+*/
+#define M1440X1050_R60_HSP      NEGATIVE
+#define M1440X1050_R60_VSP      POSITIVE
+
+/*1600x1200@60 Sync Polarity (VESA Mode)
+*/
+#define M1600X1200_R60_HSP      POSITIVE
+#define M1600X1200_R60_VSP      POSITIVE
+
+/*1600x1200@75 Sync Polarity (VESA Mode)
+*/
+#define M1600X1200_R75_HSP      POSITIVE
+#define M1600X1200_R75_VSP      POSITIVE
+
+/* 1680x1050@60 Sync Polarity (CVT Mode) */
+#define M1680x1050_R60_HSP      NEGATIVE
+#define M1680x1050_R60_VSP      NEGATIVE
+
+/* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1680x1050_RB_R60_HSP      POSITIVE
+#define M1680x1050_RB_R60_VSP      NEGATIVE
+
+/* 1680x1050@75 Sync Polarity (CVT Mode) */
+#define M1680x1050_R75_HSP      NEGATIVE
+#define M1680x1050_R75_VSP      POSITIVE
+
+/*1920x1080@60 Sync Polarity (CVT Mode)
+*/
+#define M1920X1080_R60_HSP      NEGATIVE
+#define M1920X1080_R60_VSP      POSITIVE
+
+/* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1920X1080_RB_R60_HSP  POSITIVE
+#define M1920X1080_RB_R60_VSP  NEGATIVE
+
+/*1920x1440@60 Sync Polarity (VESA Mode)
+*/
+#define M1920X1440_R60_HSP      NEGATIVE
+#define M1920X1440_R60_VSP      POSITIVE
+
+/*1920x1440@75 Sync Polarity (VESA Mode)
+*/
+#define M1920X1440_R75_HSP      NEGATIVE
+#define M1920X1440_R75_VSP      POSITIVE
+
+#if 0
+/* 1400x1050@60 Sync Polarity (VESA Mode) */
+#define M1400X1050_R60_HSP      NEGATIVE
+#define M1400X1050_R60_VSP      NEGATIVE
+#endif
+
+/* 1400x1050@60 Sync Polarity (CVT Mode) */
+#define M1400X1050_R60_HSP      NEGATIVE
+#define M1400X1050_R60_VSP      POSITIVE
+
+/* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1400X1050_RB_R60_HSP      POSITIVE
+#define M1400X1050_RB_R60_VSP      NEGATIVE
+
+/* 1400x1050@75 Sync Polarity (CVT Mode) */
+#define M1400X1050_R75_HSP      NEGATIVE
+#define M1400X1050_R75_VSP      POSITIVE
+
+/* 960x600@60 Sync Polarity (CVT Mode) */
+#define M960X600_R60_HSP        NEGATIVE
+#define M960X600_R60_VSP        POSITIVE
+
+/* 1000x600@60 Sync Polarity (GTF Mode) */
+#define M1000X600_R60_HSP       NEGATIVE
+#define M1000X600_R60_VSP       POSITIVE
+
+/* 1024x576@60 Sync Polarity (GTF Mode) */
+#define M1024X576_R60_HSP       NEGATIVE
+#define M1024X576_R60_VSP       POSITIVE
+
+/*1024x600@60 Sync Polarity (GTF Mode)*/
+#define M1024X600_R60_HSP       NEGATIVE
+#define M1024X600_R60_VSP       POSITIVE
+
+/* 1088x612@60 Sync Polarity (CVT Mode) */
+#define M1088X612_R60_HSP       NEGATIVE
+#define M1088X612_R60_VSP       POSITIVE
+
+/* 1152x720@60 Sync Polarity (CVT Mode) */
+#define M1152X720_R60_HSP       NEGATIVE
+#define M1152X720_R60_VSP       POSITIVE
+
+/* 1200x720@60 Sync Polarity (GTF Mode) */
+#define M1200X720_R60_HSP       NEGATIVE
+#define M1200X720_R60_VSP       POSITIVE
+
+/* 1280x600@60 Sync Polarity (GTF Mode) */
+#define M1280x600_R60_HSP       NEGATIVE
+#define M1280x600_R60_VSP       POSITIVE
+
+/* 1280x720@50 Sync Polarity  (GTF Mode) */
+#define M1280X720_R50_HSP       NEGATIVE
+#define M1280X720_R50_VSP       POSITIVE
+
+/* 1280x720@60 Sync Polarity  (CEA Mode) */
+#define M1280X720_CEA_R60_HSP       POSITIVE
+#define M1280X720_CEA_R60_VSP       POSITIVE
+
+/* 1440x900@60 Sync Polarity (CVT Mode) */
+#define M1440X900_R60_HSP       NEGATIVE
+#define M1440X900_R60_VSP       POSITIVE
+
+/* 1440x900@75 Sync Polarity (CVT Mode) */
+#define M1440X900_R75_HSP       NEGATIVE
+#define M1440X900_R75_VSP       POSITIVE
+
+/* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1440X900_RB_R60_HSP       POSITIVE
+#define M1440X900_RB_R60_VSP       NEGATIVE
+
+/* 1600x900@60 Sync Polarity (CVT Mode) */
+#define M1600X900_R60_HSP       NEGATIVE
+#define M1600X900_R60_VSP       POSITIVE
+
+/* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1600X900_RB_R60_HSP       POSITIVE
+#define M1600X900_RB_R60_VSP       NEGATIVE
+
+/* 1600x1024@60 Sync Polarity (GTF Mode) */
+#define M1600X1024_R60_HSP      NEGATIVE
+#define M1600X1024_R60_VSP      POSITIVE
+
+/* 1792x1344@60 Sync Polarity (DMT Mode) */
+#define M1792x1344_R60_HSP      NEGATIVE
+#define M1792x1344_R60_VSP      POSITIVE
+
+/* 1856x1392@60 Sync Polarity (DMT Mode) */
+#define M1856x1392_R60_HSP      NEGATIVE
+#define M1856x1392_R60_VSP      POSITIVE
+
+/* 1920x1200@60 Sync Polarity (CVT Mode) */
+#define M1920X1200_R60_HSP      NEGATIVE
+#define M1920X1200_R60_VSP      POSITIVE
+
+/* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */
+#define M1920X1200_RB_R60_HSP  POSITIVE
+#define M1920X1200_RB_R60_VSP  NEGATIVE
+
+/* 1920x1080@60 Sync Polarity  (CEA Mode) */
+#define M1920X1080_CEA_R60_HSP       POSITIVE
+#define M1920X1080_CEA_R60_VSP       POSITIVE
+
+/* 2048x1536@60 Sync Polarity (CVT Mode) */
+#define M2048x1536_R60_HSP      NEGATIVE
+#define M2048x1536_R60_VSP      POSITIVE
+
+/* define PLL index: */
+#define CLK_25_175M     25175000
+#define CLK_26_880M     26880000
+#define CLK_29_581M     29581000
+#define CLK_31_490M     31490000
+#define CLK_31_500M     31500000
+#define CLK_31_728M     31728000
+#define CLK_32_668M     32688000
+#define CLK_36_000M     36000000
+#define CLK_40_000M     40000000
+#define CLK_41_291M     41291000
+#define CLK_43_163M     43163000
+#define CLK_45_250M     45250000       /* 45.46MHz */
+#define CLK_46_000M     46000000
+#define CLK_46_996M     46996000
+#define CLK_48_000M     48000000
+#define CLK_48_875M     48875000
+#define CLK_49_500M     49500000
+#define CLK_52_406M     52406000
+#define CLK_52_977M     52977000
+#define CLK_56_250M     56250000
+#define CLK_60_466M     60466000
+#define CLK_61_500M     61500000
+#define CLK_65_000M     65000000
+#define CLK_65_178M     65178000
+#define CLK_66_750M     66750000       /* 67.116MHz */
+#define CLK_68_179M     68179000
+#define CLK_69_924M     69924000
+#define CLK_70_159M     70159000
+#define CLK_72_000M     72000000
+#define CLK_74_270M     74270000
+#define CLK_78_750M     78750000
+#define CLK_80_136M     80136000
+#define CLK_83_375M     83375000
+#define CLK_83_950M     83950000
+#define CLK_84_750M     84750000       /* 84.537Mhz */
+#define CLK_85_860M     85860000
+#define CLK_88_750M     88750000
+#define CLK_94_500M     94500000
+#define CLK_97_750M     97750000
+#define CLK_101_000M    101000000
+#define CLK_106_500M    106500000
+#define CLK_108_000M    108000000
+#define CLK_113_309M    113309000
+#define CLK_118_840M    118840000
+#define CLK_119_000M    119000000
+#define CLK_121_750M    121750000      /* 121.704MHz */
+#define CLK_125_104M    125104000
+#define CLK_133_308M    133308000
+#define CLK_135_000M    135000000
+#define CLK_136_700M    136700000
+#define CLK_138_400M    138400000
+#define CLK_146_760M    146760000
+#define CLK_148_500M    148500000
+
+#define CLK_153_920M    153920000
+#define CLK_156_000M    156000000
+#define CLK_157_500M    157500000
+#define CLK_162_000M    162000000
+#define CLK_187_000M    187000000
+#define CLK_193_295M    193295000
+#define CLK_202_500M    202500000
+#define CLK_204_000M    204000000
+#define CLK_218_500M    218500000
+#define CLK_234_000M    234000000
+#define CLK_267_250M    267250000
+#define CLK_297_500M    297500000
+#define CLK_74_481M     74481000
+#define CLK_172_798M    172798000
+#define CLK_122_614M    122614000
+
+/* CLE266 PLL value
+*/
+#define CLE266_PLL_25_175M     0x0000C763
+#define CLE266_PLL_26_880M     0x0000440F
+#define CLE266_PLL_29_581M     0x00008421
+#define CLE266_PLL_31_490M     0x00004721
+#define CLE266_PLL_31_500M     0x0000C3B5
+#define CLE266_PLL_31_728M     0x0000471F
+#define CLE266_PLL_32_668M     0x0000C449
+#define CLE266_PLL_36_000M     0x0000C5E5
+#define CLE266_PLL_40_000M     0x0000C459
+#define CLE266_PLL_41_291M     0x00004417
+#define CLE266_PLL_43_163M     0x0000C579
+#define CLE266_PLL_45_250M     0x0000C57F      /* 45.46MHz */
+#define CLE266_PLL_46_000M     0x0000875A
+#define CLE266_PLL_46_996M     0x0000C4E9
+#define CLE266_PLL_48_000M     0x00001443
+#define CLE266_PLL_48_875M     0x00001D63
+#define CLE266_PLL_49_500M     0x00008653
+#define CLE266_PLL_52_406M     0x0000C475
+#define CLE266_PLL_52_977M     0x00004525
+#define CLE266_PLL_56_250M     0x000047B7
+#define CLE266_PLL_60_466M     0x0000494C
+#define CLE266_PLL_61_500M     0x00001456
+#define CLE266_PLL_65_000M     0x000086ED
+#define CLE266_PLL_65_178M     0x0000855B
+#define CLE266_PLL_66_750M     0x0000844B      /* 67.116MHz */
+#define CLE266_PLL_68_179M     0x00000413
+#define CLE266_PLL_69_924M     0x00001153
+#define CLE266_PLL_70_159M     0x00001462
+#define CLE266_PLL_72_000M     0x00001879
+#define CLE266_PLL_74_270M     0x00004853
+#define CLE266_PLL_78_750M     0x00004321
+#define CLE266_PLL_80_136M     0x0000051C
+#define CLE266_PLL_83_375M     0x0000C25D
+#define CLE266_PLL_83_950M     0x00000729
+#define CLE266_PLL_84_750M     0x00008576      /* 84.537MHz */
+#define CLE266_PLL_85_860M     0x00004754
+#define CLE266_PLL_88_750M     0x0000051F
+#define CLE266_PLL_94_500M     0x00000521
+#define CLE266_PLL_97_750M     0x00004652
+#define CLE266_PLL_101_000M    0x0000497F
+#define CLE266_PLL_106_500M    0x00008477      /* 106.491463 MHz */
+#define CLE266_PLL_108_000M    0x00008479
+#define CLE266_PLL_113_309M    0x00000C5F
+#define CLE266_PLL_118_840M    0x00004553
+#define CLE266_PLL_119_000M    0x00000D6C
+#define CLE266_PLL_121_750M    0x00004555      /* 121.704MHz */
+#define CLE266_PLL_125_104M    0x000006B5
+#define CLE266_PLL_133_308M    0x0000465F
+#define CLE266_PLL_135_000M    0x0000455E
+#define CLE266_PLL_136_700M    0x00000C73
+#define CLE266_PLL_138_400M    0x00000957
+#define CLE266_PLL_146_760M    0x00004567
+#define CLE266_PLL_148_500M    0x00000853
+#define CLE266_PLL_153_920M    0x00000856
+#define CLE266_PLL_156_000M    0x0000456D
+#define CLE266_PLL_157_500M    0x000005B7
+#define CLE266_PLL_162_000M    0x00004571
+#define CLE266_PLL_187_000M    0x00000976
+#define CLE266_PLL_193_295M    0x0000086C
+#define CLE266_PLL_202_500M    0x00000763
+#define CLE266_PLL_204_000M    0x00000764
+#define CLE266_PLL_218_500M    0x0000065C
+#define CLE266_PLL_234_000M    0x00000662
+#define CLE266_PLL_267_250M    0x00000670
+#define CLE266_PLL_297_500M    0x000005E6
+#define CLE266_PLL_74_481M     0x0000051A
+#define CLE266_PLL_172_798M    0x00004579
+#define CLE266_PLL_122_614M    0x0000073C
+
+/* K800 PLL value
+*/
+#define K800_PLL_25_175M     0x00539001
+#define K800_PLL_26_880M     0x001C8C80
+#define K800_PLL_29_581M     0x00409080
+#define K800_PLL_31_490M     0x006F9001
+#define K800_PLL_31_500M     0x008B9002
+#define K800_PLL_31_728M     0x00AF9003
+#define K800_PLL_32_668M     0x00909002
+#define K800_PLL_36_000M     0x009F9002
+#define K800_PLL_40_000M     0x00578C02
+#define K800_PLL_41_291M     0x00438C01
+#define K800_PLL_43_163M     0x00778C03
+#define K800_PLL_45_250M     0x007D8C83        /* 45.46MHz */
+#define K800_PLL_46_000M     0x00658C02
+#define K800_PLL_46_996M     0x00818C83
+#define K800_PLL_48_000M     0x00848C83
+#define K800_PLL_48_875M     0x00508C81
+#define K800_PLL_49_500M     0x00518C01
+#define K800_PLL_52_406M     0x00738C02
+#define K800_PLL_52_977M     0x00928C83
+#define K800_PLL_56_250M     0x007C8C02
+#define K800_PLL_60_466M     0x00A78C83
+#define K800_PLL_61_500M     0x00AA8C83
+#define K800_PLL_65_000M     0x006B8C01
+#define K800_PLL_65_178M     0x00B48C83
+#define K800_PLL_66_750M     0x00948C82        /* 67.116MHz */
+#define K800_PLL_68_179M     0x00708C01
+#define K800_PLL_69_924M     0x00C18C83
+#define K800_PLL_70_159M     0x00C28C83
+#define K800_PLL_72_000M     0x009F8C82
+#define K800_PLL_74_270M     0x00ce0c03
+#define K800_PLL_78_750M     0x00408801
+#define K800_PLL_80_136M     0x00428801
+#define K800_PLL_83_375M     0x005B0882
+#define K800_PLL_83_950M     0x00738803
+#define K800_PLL_84_750M     0x00748883        /* 84.477MHz */
+#define K800_PLL_85_860M     0x00768883
+#define K800_PLL_88_750M     0x007A8883
+#define K800_PLL_94_500M     0x00828803
+#define K800_PLL_97_750M     0x00878883
+#define K800_PLL_101_000M    0x008B8883
+#define K800_PLL_106_500M    0x00758882        /* 106.491463 MHz */
+#define K800_PLL_108_000M    0x00778882
+#define K800_PLL_113_309M    0x005D8881
+#define K800_PLL_118_840M    0x00A48883
+#define K800_PLL_119_000M    0x00838882
+#define K800_PLL_121_750M    0x00A88883        /* 121.704MHz */
+#define K800_PLL_125_104M    0x00688801
+#define K800_PLL_133_308M    0x005D8801
+#define K800_PLL_135_000M    0x001A4081
+#define K800_PLL_136_700M    0x00BD8883
+#define K800_PLL_138_400M    0x00728881
+#define K800_PLL_146_760M    0x00CC8883
+#define K800_PLL_148_500M    0x00ce0803
+#define K800_PLL_153_920M    0x00548482
+#define K800_PLL_156_000M    0x006B8483
+#define K800_PLL_157_500M    0x00142080
+#define K800_PLL_162_000M    0x006F8483
+#define K800_PLL_187_000M    0x00818483
+#define K800_PLL_193_295M    0x004F8481
+#define K800_PLL_202_500M    0x00538481
+#define K800_PLL_204_000M    0x008D8483
+#define K800_PLL_218_500M    0x00978483
+#define K800_PLL_234_000M    0x00608401
+#define K800_PLL_267_250M    0x006E8481
+#define K800_PLL_297_500M    0x00A48402
+#define K800_PLL_74_481M     0x007B8C81
+#define K800_PLL_172_798M    0x00778483
+#define K800_PLL_122_614M    0x00878882
+
+/* PLL for VT3324 */
+#define CX700_25_175M     0x008B1003
+#define CX700_26_719M     0x00931003
+#define CX700_26_880M     0x00941003
+#define CX700_29_581M     0x00A49003
+#define CX700_31_490M     0x00AE1003
+#define CX700_31_500M     0x00AE1003
+#define CX700_31_728M     0x00AF1003
+#define CX700_32_668M     0x00B51003
+#define CX700_36_000M     0x00C81003
+#define CX700_40_000M     0x006E0C03
+#define CX700_41_291M     0x00710C03
+#define CX700_43_163M     0x00770C03
+#define CX700_45_250M     0x007D0C03   /* 45.46MHz */
+#define CX700_46_000M     0x007F0C03
+#define CX700_46_996M     0x00818C83
+#define CX700_48_000M     0x00840C03
+#define CX700_48_875M     0x00508C81
+#define CX700_49_500M     0x00880C03
+#define CX700_52_406M     0x00730C02
+#define CX700_52_977M     0x00920C03
+#define CX700_56_250M     0x009B0C03
+#define CX700_60_466M     0x00460C00
+#define CX700_61_500M     0x00AA0C03
+#define CX700_65_000M     0x006B0C01
+#define CX700_65_178M     0x006B0C01
+#define CX700_66_750M     0x00940C02   /*67.116MHz */
+#define CX700_68_179M     0x00BC0C03
+#define CX700_69_924M     0x00C10C03
+#define CX700_70_159M     0x00C20C03
+#define CX700_72_000M     0x009F0C02
+#define CX700_74_270M     0x00CE0C03
+#define CX700_74_481M     0x00CE0C03
+#define CX700_78_750M     0x006C0803
+#define CX700_80_136M     0x006E0803
+#define CX700_83_375M     0x005B0882
+#define CX700_83_950M     0x00730803
+#define CX700_84_750M     0x00740803   /* 84.537Mhz */
+#define CX700_85_860M     0x00760803
+#define CX700_88_750M     0x00AC8885
+#define CX700_94_500M     0x00820803
+#define CX700_97_750M     0x00870803
+#define CX700_101_000M    0x008B0803
+#define CX700_106_500M    0x00750802
+#define CX700_108_000M    0x00950803
+#define CX700_113_309M    0x005D0801
+#define CX700_118_840M    0x00A40803
+#define CX700_119_000M    0x00830802
+#define CX700_121_750M    0x00420800   /* 121.704MHz */
+#define CX700_125_104M    0x00AD0803
+#define CX700_133_308M    0x00930802
+#define CX700_135_000M    0x00950802
+#define CX700_136_700M    0x00BD0803
+#define CX700_138_400M    0x00720801
+#define CX700_146_760M    0x00CC0803
+#define CX700_148_500M    0x00a40802
+#define CX700_153_920M    0x00540402
+#define CX700_156_000M    0x006B0403
+#define CX700_157_500M    0x006C0403
+#define CX700_162_000M    0x006F0403
+#define CX700_172_798M    0x00770403
+#define CX700_187_000M    0x00810403
+#define CX700_193_295M    0x00850403
+#define CX700_202_500M    0x008C0403
+#define CX700_204_000M    0x008D0403
+#define CX700_218_500M    0x00970403
+#define CX700_234_000M    0x00600401
+#define CX700_267_250M    0x00B90403
+#define CX700_297_500M    0x00CE0403
+#define CX700_122_614M    0x00870802
+
+/* Definition CRTC Timing Index */
+#define H_TOTAL_INDEX               0
+#define H_ADDR_INDEX                1
+#define H_BLANK_START_INDEX         2
+#define H_BLANK_END_INDEX           3
+#define H_SYNC_START_INDEX          4
+#define H_SYNC_END_INDEX            5
+#define V_TOTAL_INDEX               6
+#define V_ADDR_INDEX                7
+#define V_BLANK_START_INDEX         8
+#define V_BLANK_END_INDEX           9
+#define V_SYNC_START_INDEX          10
+#define V_SYNC_END_INDEX            11
+#define H_TOTAL_SHADOW_INDEX        12
+#define H_BLANK_END_SHADOW_INDEX    13
+#define V_TOTAL_SHADOW_INDEX        14
+#define V_ADDR_SHADOW_INDEX         15
+#define V_BLANK_SATRT_SHADOW_INDEX  16
+#define V_BLANK_END_SHADOW_INDEX    17
+#define V_SYNC_SATRT_SHADOW_INDEX   18
+#define V_SYNC_END_SHADOW_INDEX     19
+
+/* Definition Video Mode Pixel Clock (picoseconds)
+*/
+#define RES_480X640_60HZ_PIXCLOCK    39722
+#define RES_640X480_60HZ_PIXCLOCK    39722
+#define RES_640X480_75HZ_PIXCLOCK    31747
+#define RES_640X480_85HZ_PIXCLOCK    27777
+#define RES_640X480_100HZ_PIXCLOCK   23168
+#define RES_640X480_120HZ_PIXCLOCK   19081
+#define RES_720X480_60HZ_PIXCLOCK    37020
+#define RES_720X576_60HZ_PIXCLOCK    30611
+#define RES_800X600_60HZ_PIXCLOCK    25000
+#define RES_800X600_75HZ_PIXCLOCK    20203
+#define RES_800X600_85HZ_PIXCLOCK    17777
+#define RES_800X600_100HZ_PIXCLOCK   14667
+#define RES_800X600_120HZ_PIXCLOCK   11912
+#define RES_800X480_60HZ_PIXCLOCK    33805
+#define RES_848X480_60HZ_PIXCLOCK    31756
+#define RES_856X480_60HZ_PIXCLOCK    31518
+#define RES_1024X512_60HZ_PIXCLOCK   24218
+#define RES_1024X600_60HZ_PIXCLOCK   20460
+#define RES_1024X768_60HZ_PIXCLOCK   15385
+#define RES_1024X768_75HZ_PIXCLOCK   12699
+#define RES_1024X768_85HZ_PIXCLOCK   10582
+#define RES_1024X768_100HZ_PIXCLOCK  8825
+#define RES_1152X864_75HZ_PIXCLOCK   9259
+#define RES_1280X768_60HZ_PIXCLOCK   12480
+#define RES_1280X800_60HZ_PIXCLOCK   11994
+#define RES_1280X960_60HZ_PIXCLOCK   9259
+#define RES_1280X1024_60HZ_PIXCLOCK  9260
+#define RES_1280X1024_75HZ_PIXCLOCK  7408
+#define RES_1280X768_85HZ_PIXCLOCK   6349
+#define RES_1440X1050_60HZ_PIXCLOCK  7993
+#define RES_1600X1200_60HZ_PIXCLOCK  6172
+#define RES_1600X1200_75HZ_PIXCLOCK  4938
+#define RES_1280X720_60HZ_PIXCLOCK   13426
+#define RES_1920X1080_60HZ_PIXCLOCK  5787
+#define RES_1400X1050_60HZ_PIXCLOCK  8214
+#define RES_1400X1050_75HZ_PIXCLOCK  6410
+#define RES_1368X768_60HZ_PIXCLOCK   11647
+#define RES_960X600_60HZ_PIXCLOCK      22099
+#define RES_1000X600_60HZ_PIXCLOCK    20834
+#define RES_1024X576_60HZ_PIXCLOCK    21278
+#define RES_1088X612_60HZ_PIXCLOCK    18877
+#define RES_1152X720_60HZ_PIXCLOCK    14981
+#define RES_1200X720_60HZ_PIXCLOCK    14253
+#define RES_1280X600_60HZ_PIXCLOCK    16260
+#define RES_1280X720_50HZ_PIXCLOCK    16538
+#define RES_1280X768_50HZ_PIXCLOCK    15342
+#define RES_1366X768_50HZ_PIXCLOCK    14301
+#define RES_1366X768_60HZ_PIXCLOCK    11646
+#define RES_1360X768_60HZ_PIXCLOCK    11799
+#define RES_1440X900_60HZ_PIXCLOCK    9390
+#define RES_1440X900_75HZ_PIXCLOCK    7315
+#define RES_1600X900_60HZ_PIXCLOCK    8415
+#define RES_1600X1024_60HZ_PIXCLOCK   7315
+#define RES_1680X1050_60HZ_PIXCLOCK   6814
+#define RES_1680X1050_75HZ_PIXCLOCK   5348
+#define RES_1792X1344_60HZ_PIXCLOCK   4902
+#define RES_1856X1392_60HZ_PIXCLOCK   4577
+#define RES_1920X1200_60HZ_PIXCLOCK   5173
+#define RES_1920X1440_60HZ_PIXCLOCK   4274
+#define RES_1920X1440_75HZ_PIXCLOCK   3367
+#define RES_2048X1536_60HZ_PIXCLOCK   3742
+
+#define RES_1360X768_RB_60HZ_PIXCLOCK 13889
+#define RES_1400X1050_RB_60HZ_PIXCLOCK 9901
+#define RES_1440X900_RB_60HZ_PIXCLOCK   11268
+#define RES_1600X900_RB_60HZ_PIXCLOCK   10230
+#define RES_1680X1050_RB_60HZ_PIXCLOCK 8403
+#define RES_1920X1080_RB_60HZ_PIXCLOCK 7225
+#define RES_1920X1200_RB_60HZ_PIXCLOCK 6497
+
+/* LCD display method
+*/
+#define     LCD_EXPANDSION              0x00
+#define     LCD_CENTERING               0x01
+
+/* LCD mode
+*/
+#define     LCD_OPENLDI               0x00
+#define     LCD_SPWG                  0x01
+
+/* Define display timing
+*/
+struct display_timing {
+       u16 hor_total;
+       u16 hor_addr;
+       u16 hor_blank_start;
+       u16 hor_blank_end;
+       u16 hor_sync_start;
+       u16 hor_sync_end;
+       u16 ver_total;
+       u16 ver_addr;
+       u16 ver_blank_start;
+       u16 ver_blank_end;
+       u16 ver_sync_start;
+       u16 ver_sync_end;
+};
+
+struct crt_mode_table {
+       int refresh_rate;
+       unsigned long clk;
+       int h_sync_polarity;
+       int v_sync_polarity;
+       struct display_timing crtc;
+};
+
+struct io_reg {
+       int port;
+       u8 index;
+       u8 mask;
+       u8 value;
+};
+
+#endif /* __SHARE_H__ */
diff --git a/drivers/video/via/tbl1636.c b/drivers/video/via/tbl1636.c
new file mode 100644 (file)
index 0000000..2d84534
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+struct IODATA COMMON_INIT_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       /* Set panel power sequence timing */
+       {0x10, 0xC0, 0x00},
+       /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
+       {0x0B, 0xFF, 0x40},
+       /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
+       {0x0C, 0xFF, 0x31},
+       /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
+       {0x0D, 0xFF, 0x31},
+       /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
+       {0x0E, 0xFF, 0x68},
+       /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
+       {0x0F, 0xFF, 0x68},
+       /* LVDS output power up */
+       {0x09, 0xA0, 0xA0},
+       /* turn on back light */
+       {0x10, 0x33, 0x13}
+};
+
+struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x08, 0xF0, 0xE0}      /* Input Data Mode Select */
+};
+
+struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x08, 0xF0, 0x00}      /* Input Data Mode Select */
+};
+
+struct IODATA DITHERING_ENABLE_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x0A, 0x70, 0x50}
+};
+
+struct IODATA DITHERING_DISABLE_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x0A, 0x70, 0x00}
+};
+
+struct IODATA VDD_ON_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x10, 0x20, 0x20}
+};
+
+struct IODATA VDD_OFF_TBL_VT1636[] = {
+/*  Index, Mask, Value */
+       {0x10, 0x20, 0x00}
+};
diff --git a/drivers/video/via/tbl1636.h b/drivers/video/via/tbl1636.h
new file mode 100644 (file)
index 0000000..d906055
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 _TBL1636_H_
+#define _TBL1636_H_
+#include "hw.h"
+
+extern struct IODATA COMMON_INIT_TBL_VT1636[8];
+extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1];
+extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1];
+extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1];
+extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1];
+extern struct IODATA VDD_ON_TBL_VT1636[1];
+extern struct IODATA VDD_OFF_TBL_VT1636[1];
+
+#endif /* _VIA_TBL1636_H_ */
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c
new file mode 100644 (file)
index 0000000..0c4c8cc
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+/* For VT3324: */
+struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = {
+       /* Panel ID,       CLK_SEL_ST1[09],    CLK_SEL_ST2[08] */
+       {LCD_PANEL_ID0_640X480, 0x00, 0x00},    /* For 640x480   */
+       {LCD_PANEL_ID1_800X600, 0x00, 0x00},    /* For 800x600   */
+       {LCD_PANEL_ID2_1024X768, 0x00, 0x00},   /* For 1024x768  */
+       {LCD_PANEL_ID3_1280X768, 0x00, 0x00},   /* For 1280x768  */
+       {LCD_PANEL_ID4_1280X1024, 0x00, 0x00},  /* For 1280x1024 */
+       {LCD_PANEL_ID5_1400X1050, 0x00, 0x00},  /* For 1400x1050 */
+       {LCD_PANEL_ID6_1600X1200, 0x0B, 0x03}   /* For 1600x1200 */
+};
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
+/*  ClkRange, DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+                                       DVP1Driving, DFPHigh, DFPLow */
+/*  CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+                                       SR65,        CR97,    CR99   */
+       /* LCK/VCK < 30000000 will use this value */
+       {DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+        0x00},
+       /* 30000000 < LCK/VCK < 50000000 will use this value */
+       {DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+        0x00},
+       /* 50000000 < LCK/VCK < 70000000 will use this value */
+       {DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+        0x00},
+       /* 70000000 < LCK/VCK < 100000000 will use this value */
+       {DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+        0x00},
+       /* 100000000 < LCK/VCK < 15000000 will use this value */
+       {DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+        0x00},
+       /* 15000000 < LCK/VCK will use this value */
+       {DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
+        0x00},
+};
+
+/* For VT3327: */
+struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = {
+       /* Panel ID,       CLK_SEL_ST1[09],    CLK_SEL_ST2[08] */
+       {LCD_PANEL_ID0_640X480, 0x00, 0x00},    /* For 640x480   */
+       {LCD_PANEL_ID1_800X600, 0x00, 0x00},    /* For 800x600   */
+       {LCD_PANEL_ID2_1024X768, 0x00, 0x00},   /* For 1024x768  */
+       {LCD_PANEL_ID3_1280X768, 0x00, 0x00},   /* For 1280x768  */
+       {LCD_PANEL_ID4_1280X1024, 0x00, 0x00},  /* For 1280x1024 */
+       {LCD_PANEL_ID5_1400X1050, 0x00, 0x00},  /* For 1400x1050 */
+       {LCD_PANEL_ID6_1600X1200, 0x00, 0x00}   /* For 1600x1200 */
+};
+
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
+/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+                                       DVP1Driving, DFPHigh,   DFPLow */
+/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+                                       SR65,        CR97,      CR99   */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
+};
+
+/* For VT3364: */
+struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
+/*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
+                                       DVP1Driving, DFPHigh,   DFPLow */
+/*   CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
+                                       SR65,        CR97,      CR99   */
+/* LCK/VCK < 30000000 will use this value */
+{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 30000000 < LCK/VCK < 50000000 will use this value */
+{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 50000000 < LCK/VCK < 70000000 will use this value */
+{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 70000000 < LCK/VCK < 100000000 will use this value */
+{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 100000000 < LCK/VCK < 15000000 will use this value */
+{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
+/* 15000000 < LCK/VCK will use this value */
+{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
+};
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
new file mode 100644 (file)
index 0000000..b065a83
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 _TBLDPASETTING_H_
+#define _TBLDPASETTING_H_
+#include "global.h"
+
+#define DPA_CLK_30M       30000000
+#define DPA_CLK_50M       50000000
+#define DPA_CLK_70M       70000000
+#define DPA_CLK_100M      100000000
+#define DPA_CLK_150M      150000000
+
+enum DPA_RANGE {
+       DPA_CLK_RANGE_30M,
+       DPA_CLK_RANGE_30_50M,
+       DPA_CLK_RANGE_50_70M,
+       DPA_CLK_RANGE_70_100M,
+       DPA_CLK_RANGE_100_150M,
+       DPA_CLK_RANGE_150M
+};
+
+extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
+extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
+extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
+
+#endif
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
new file mode 100644 (file)
index 0000000..0f3ed4e
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+static void via_i2c_setscl(void *data, int state)
+{
+       u8 val;
+       struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+       val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
+       if (state)
+               val |= 0x20;
+       else
+               val &= ~0x20;
+       switch (via_i2c_chan->i2c_port) {
+       case I2CPORTINDEX:
+               val |= 0x01;
+               break;
+       case GPIOPORTINDEX:
+               val |= 0x80;
+               break;
+       default:
+               DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
+       }
+       viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
+}
+
+static int via_i2c_getscl(void *data)
+{
+       struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+       if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08)
+               return 1;
+       return 0;
+}
+
+static int via_i2c_getsda(void *data)
+{
+       struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+       if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04)
+               return 1;
+       return 0;
+}
+
+static void via_i2c_setsda(void *data, int state)
+{
+       u8 val;
+       struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
+
+       val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
+       if (state)
+               val |= 0x10;
+       else
+               val &= ~0x10;
+       switch (via_i2c_chan->i2c_port) {
+       case I2CPORTINDEX:
+               val |= 0x01;
+               break;
+       case GPIOPORTINDEX:
+               val |= 0x40;
+               break;
+       default:
+               DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
+       }
+       viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
+}
+
+int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
+{
+       u8 mm1[] = {0x00};
+       struct i2c_msg msgs[2];
+
+       *pdata = 0;
+       msgs[0].flags = 0;
+       msgs[1].flags = I2C_M_RD;
+       msgs[0].addr = msgs[1].addr = slave_addr / 2;
+       mm1[0] = index;
+       msgs[0].len = 1; msgs[1].len = 1;
+       msgs[0].buf = mm1; msgs[1].buf = pdata;
+       i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
+
+       return 0;
+}
+
+int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
+{
+       u8 msg[2] = { index, data };
+       struct i2c_msg msgs;
+
+       msgs.flags = 0;
+       msgs.addr = slave_addr / 2;
+       msgs.len = 2;
+       msgs.buf = msg;
+       return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1);
+}
+
+int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
+{
+       u8 mm1[] = {0x00};
+       struct i2c_msg msgs[2];
+
+       msgs[0].flags = 0;
+       msgs[1].flags = I2C_M_RD;
+       msgs[0].addr = msgs[1].addr = slave_addr / 2;
+       mm1[0] = index;
+       msgs[0].len = 1; msgs[1].len = buff_len;
+       msgs[0].buf = mm1; msgs[1].buf = buff;
+       i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
+       return 0;
+}
+
+int viafb_create_i2c_bus(void *viapar)
+{
+       int ret;
+       struct viafb_par *par = (struct viafb_par *)viapar;
+
+       strcpy(par->i2c_stuff.adapter.name, "via_i2c");
+       par->i2c_stuff.i2c_port = 0x0;
+       par->i2c_stuff.adapter.owner = THIS_MODULE;
+       par->i2c_stuff.adapter.id = 0x01FFFF;
+       par->i2c_stuff.adapter.class = 0;
+       par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo;
+       par->i2c_stuff.adapter.dev.parent = NULL;
+       par->i2c_stuff.algo.setsda = via_i2c_setsda;
+       par->i2c_stuff.algo.setscl = via_i2c_setscl;
+       par->i2c_stuff.algo.getsda = via_i2c_getsda;
+       par->i2c_stuff.algo.getscl = via_i2c_getscl;
+       par->i2c_stuff.algo.udelay = 40;
+       par->i2c_stuff.algo.timeout = 20;
+       par->i2c_stuff.algo.data = &par->i2c_stuff;
+
+       i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff);
+
+       /* Raise SCL and SDA */
+       par->i2c_stuff.i2c_port = I2CPORTINDEX;
+       via_i2c_setsda(&par->i2c_stuff, 1);
+       via_i2c_setscl(&par->i2c_stuff, 1);
+
+       par->i2c_stuff.i2c_port = GPIOPORTINDEX;
+       via_i2c_setsda(&par->i2c_stuff, 1);
+       via_i2c_setscl(&par->i2c_stuff, 1);
+       udelay(20);
+
+       ret = i2c_bit_add_bus(&par->i2c_stuff.adapter);
+       if (ret == 0)
+               DEBUG_MSG("I2C bus %s registered.\n",
+               par->i2c_stuff.adapter.name);
+       else
+               DEBUG_MSG("Failed to register I2C bus %s.\n",
+                       par->i2c_stuff.adapter.name);
+       return ret;
+}
+
+void viafb_delete_i2c_buss(void *par)
+{
+       i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter);
+}
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h
new file mode 100644 (file)
index 0000000..3a13242
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __VIA_I2C_H__
+#define __VIA_I2C_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+struct via_i2c_stuff {
+       u16 i2c_port;                   /* GPIO or I2C port */
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo;
+};
+
+#define I2CPORT           0x3c4
+#define I2CPORTINDEX      0x31
+#define GPIOPORT          0x3C4
+#define GPIOPORTINDEX     0x2C
+#define I2C_BUS             1
+#define GPIO_BUS            2
+#define DELAYPORT           0x3C3
+
+int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata);
+int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
+int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
+int viafb_create_i2c_bus(void *par);
+void viafb_delete_i2c_buss(void *par);
+#endif /* __VIA_I2C_H__ */
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
new file mode 100644 (file)
index 0000000..d53c3d5
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+void viafb_get_device_support_state(u32 *support_state)
+{
+       *support_state = CRT_Device;
+
+       if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
+               *support_state |= DVI_Device;
+
+       if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
+               *support_state |= LCD_Device;
+}
+
+void viafb_get_device_connect_state(u32 *connect_state)
+{
+       bool mobile = false;
+
+       *connect_state = CRT_Device;
+
+       if (viafb_dvi_sense())
+               *connect_state |= DVI_Device;
+
+       viafb_lcd_get_mobile_state(&mobile);
+       if (mobile)
+               *connect_state |= LCD_Device;
+}
+
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
+{
+       unsigned int support_state = 0;
+
+       switch (viafb_lcd_panel_id) {
+       case LCD_PANEL_ID0_640X480:
+               if ((xres < 640) && (yres < 480))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID1_800X600:
+               if ((xres < 800) && (yres < 600))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID2_1024X768:
+               if ((xres < 1024) && (yres < 768))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID3_1280X768:
+               if ((xres < 1280) && (yres < 768))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID4_1280X1024:
+               if ((xres < 1280) && (yres < 1024))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID5_1400X1050:
+               if ((xres < 1400) && (yres < 1050))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID6_1600X1200:
+               if ((xres < 1600) && (yres < 1200))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID7_1366X768:
+               if ((xres < 1366) && (yres < 768))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID8_1024X600:
+               if ((xres < 1024) && (yres < 600))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_ID9_1280X800:
+               if ((xres < 1280) && (yres < 800))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_IDA_800X480:
+               if ((xres < 800) && (yres < 480))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_IDB_1360X768:
+               if ((xres < 1360) && (yres < 768))
+                       support_state = true;
+               break;
+
+       case LCD_PANEL_IDC_480X640:
+               if ((xres < 480) && (yres < 640))
+                       support_state = true;
+               break;
+
+       default:
+               support_state = false;
+               break;
+       }
+
+       return support_state;
+}
+
+/*====================================================================*/
+/*                      Gamma Function Implementation*/
+/*====================================================================*/
+
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
+{
+       int i, sr1a;
+       int active_device_amount = 0;
+       int device_status = viafb_DeviceStatus;
+
+       for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
+               if (device_status & 1)
+                       active_device_amount++;
+               device_status >>= 1;
+       }
+
+       /* 8 bpp mode can't adjust gamma */
+       if (bpp == 8)
+               return ;
+
+       /* Enable Gamma */
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_CLE266:
+       case UNICHROME_K400:
+               viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+               break;
+
+       case UNICHROME_K800:
+       case UNICHROME_PM800:
+       case UNICHROME_CN700:
+       case UNICHROME_CX700:
+       case UNICHROME_K8M890:
+       case UNICHROME_P4M890:
+       case UNICHROME_P4M900:
+               viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+               break;
+       }
+       sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
+       viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+       /* Fill IGA1 Gamma Table */
+       outb(0, LUT_INDEX_WRITE);
+       for (i = 0; i < 256; i++) {
+               outb(gamma_table[i] >> 16, LUT_DATA);
+               outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+               outb(gamma_table[i] & 0xFF, LUT_DATA);
+       }
+
+       /* If adjust Gamma value in SAMM, fill IGA1,
+          IGA2 Gamma table simultanous. */
+       /* Switch to IGA2 Gamma Table */
+       if ((active_device_amount > 1) &&
+               !((viaparinfo->chip_info->gfx_chip_name ==
+               UNICHROME_CLE266) &&
+               (viaparinfo->chip_info->gfx_chip_revision < 15))) {
+               viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
+               viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
+
+               /* Fill IGA2 Gamma Table */
+               outb(0, LUT_INDEX_WRITE);
+               for (i = 0; i < 256; i++) {
+                       outb(gamma_table[i] >> 16, LUT_DATA);
+                       outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
+                       outb(gamma_table[i] & 0xFF, LUT_DATA);
+               }
+       }
+       viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_table(unsigned int *gamma_table)
+{
+       unsigned char color_r, color_g, color_b;
+       unsigned char sr1a = 0;
+       int i;
+
+       /* Enable Gamma */
+       switch (viaparinfo->chip_info->gfx_chip_name) {
+       case UNICHROME_CLE266:
+       case UNICHROME_K400:
+               viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
+               break;
+
+       case UNICHROME_K800:
+       case UNICHROME_PM800:
+       case UNICHROME_CN700:
+       case UNICHROME_CX700:
+       case UNICHROME_K8M890:
+       case UNICHROME_P4M890:
+       case UNICHROME_P4M900:
+               viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
+               break;
+       }
+       sr1a = viafb_read_reg(VIASR, SR1A);
+       viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
+
+       /* Reading gamma table to get color value */
+       outb(0, LUT_INDEX_READ);
+       for (i = 0; i < 256; i++) {
+               color_r = inb(LUT_DATA);
+               color_g = inb(LUT_DATA);
+               color_b = inb(LUT_DATA);
+               gamma_table[i] =
+                   ((((u32) color_r) << 16) |
+                    (((u16) color_g) << 8)) | color_b;
+       }
+       viafb_write_reg(SR1A, VIASR, sr1a);
+}
+
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
+{
+       if (bpp == 8)
+               *support_state = None_Device;
+       else
+               *support_state = CRT_Device | DVI_Device | LCD_Device;
+}
+
+int viafb_input_parameter_converter(int parameter_value)
+{
+       int result;
+
+       if (parameter_value >= 1 && parameter_value <= 9)
+               result = 1 << (parameter_value - 1);
+       else
+               result = 1;
+
+       return result;
+}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
new file mode 100644 (file)
index 0000000..2fd4552
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __VIAUTILITY_H__
+#define __VIAUTILITY_H__
+
+/* These functions are used to get infomation about device's state */
+void viafb_get_device_support_state(u32 *support_state);
+void viafb_get_device_connect_state(u32 *connect_state);
+bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
+
+/* These function are used to access gamma table */
+void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
+void viafb_get_gamma_table(unsigned int *gamma_table);
+void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
+int viafb_input_parameter_converter(int parameter_value);
+
+#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
new file mode 100644 (file)
index 0000000..0132eae
--- /dev/null
@@ -0,0 +1,2571 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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>
+#define _MASTER_FILE
+
+#include "global.h"
+
+static int MAX_CURS = 32;
+static struct fb_var_screeninfo default_var;
+static char *viafb_name = "Via";
+static u32 pseudo_pal[17];
+
+/* video mode */
+static char *viafb_mode = "640x480";
+static char *viafb_mode1 = "640x480";
+static int viafb_resMode = VIA_RES_640X480;
+
+/* Added for specifying active devices.*/
+char *viafb_active_dev = "";
+
+/* Added for specifying video on devices.*/
+char *viafb_video_dev = "";
+
+/*Added for specify lcd output port*/
+char *viafb_lcd_port = "";
+char *viafb_dvi_port = "";
+
+static void viafb_set_device(struct device_t active_dev);
+static int apply_device_setting(struct viafb_ioctl_setting setting_info,
+                        struct fb_info *info);
+static void apply_second_mode_setting(struct fb_var_screeninfo
+       *sec_var);
+static void retrieve_device_setting(struct viafb_ioctl_setting
+       *setting_info);
+static void viafb_set_video_device(u32 video_dev_info);
+static void viafb_get_video_device(u32 *video_dev_info);
+
+/* Mode information */
+static const struct viafb_modeinfo viafb_modentry[] = {
+       {480, 640, VIA_RES_480X640, "480x640"},
+       {640, 480, VIA_RES_640X480, "640x480"},
+       {800, 480, VIA_RES_800X480, "800x480"},
+       {800, 600, VIA_RES_800X600, "800x600"},
+       {1024, 768, VIA_RES_1024X768, "1024x768"},
+       {1152, 864, VIA_RES_1152X864, "1152x864"},
+       {1280, 1024, VIA_RES_1280X1024, "1280x1024"},
+       {1600, 1200, VIA_RES_1600X1200, "1600x1200"},
+       {1440, 1050, VIA_RES_1440X1050, "1440x1050"},
+       {1280, 768, VIA_RES_1280X768, "1280x768"},
+       {1280, 800, VIA_RES_1280X800, "1280x800"},
+       {1280, 960, VIA_RES_1280X960, "1280x960"},
+       {1920, 1440, VIA_RES_1920X1440, "1920x1440"},
+       {848, 480, VIA_RES_848X480, "848x480"},
+       {1400, 1050, VIA_RES_1400X1050, "1400x1050"},
+       {720, 480, VIA_RES_720X480, "720x480"},
+       {720, 576, VIA_RES_720X576, "720x576"},
+       {1024, 512, VIA_RES_1024X512, "1024x512"},
+       {1024, 576, VIA_RES_1024X576, "1024x576"},
+       {1024, 600, VIA_RES_1024X600, "1024x600"},
+       {1280, 720, VIA_RES_1280X720, "1280x720"},
+       {1920, 1080, VIA_RES_1920X1080, "1920x1080"},
+       {1366, 768, VIA_RES_1368X768, "1368x768"},
+       {1680, 1050, VIA_RES_1680X1050, "1680x1050"},
+       {960, 600, VIA_RES_960X600, "960x600"},
+       {1000, 600, VIA_RES_1000X600, "1000x600"},
+       {1024, 576, VIA_RES_1024X576, "1024x576"},
+       {1024, 600, VIA_RES_1024X600, "1024x600"},
+       {1088, 612, VIA_RES_1088X612, "1088x612"},
+       {1152, 720, VIA_RES_1152X720, "1152x720"},
+       {1200, 720, VIA_RES_1200X720, "1200x720"},
+       {1280, 600, VIA_RES_1280X600, "1280x600"},
+       {1360, 768, VIA_RES_1360X768, "1360x768"},
+       {1440, 900, VIA_RES_1440X900, "1440x900"},
+       {1600, 900, VIA_RES_1600X900, "1600x900"},
+       {1600, 1024, VIA_RES_1600X1024, "1600x1024"},
+       {1792, 1344, VIA_RES_1792X1344, "1792x1344"},
+       {1856, 1392, VIA_RES_1856X1392, "1856x1392"},
+       {1920, 1200, VIA_RES_1920X1200, "1920x1200"},
+       {2048, 1536, VIA_RES_2048X1536, "2048x1536"},
+       {0, 0, VIA_RES_INVALID, "640x480"}
+};
+
+static struct fb_ops viafb_ops;
+
+static int viafb_update_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+       struct viafb_par *ppar;
+       ppar = info->par;
+
+       DEBUG_MSG(KERN_INFO "viafb_update_fix!\n");
+
+       fix->visual =
+           ppar->bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+       fix->line_length = ppar->linelength;
+
+       return 0;
+}
+
+
+static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
+       struct viafb_par *viaparinfo)
+{
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+       strcpy(fix->id, viafb_name);
+
+       fix->smem_start = viaparinfo->fbmem;
+       fix->smem_len = viaparinfo->fbmem_free;
+       fix->mmio_start = viaparinfo->mmio_base;
+       fix->mmio_len = viaparinfo->mmio_len;
+
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->type_aux = 0;
+
+       fix->xpanstep = fix->ywrapstep = 0;
+       fix->ypanstep = 1;
+
+       /* Just tell the accel name */
+       viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
+}
+static int viafb_open(struct fb_info *info, int user)
+{
+       DEBUG_MSG(KERN_INFO "viafb_open!\n");
+       return 0;
+}
+
+static int viafb_release(struct fb_info *info, int user)
+{
+       DEBUG_MSG(KERN_INFO "viafb_release!\n");
+       return 0;
+}
+
+static void viafb_update_viafb_par(struct fb_info *info)
+{
+       struct viafb_par *ppar;
+
+       ppar = info->par;
+       ppar->bpp = info->var.bits_per_pixel;
+       ppar->linelength = ((info->var.xres_virtual + 7) & ~7) * ppar->bpp / 8;
+       ppar->hres = info->var.xres;
+       ppar->vres = info->var.yres;
+       ppar->xoffset = info->var.xoffset;
+       ppar->yoffset = info->var.yoffset;
+}
+
+static int viafb_check_var(struct fb_var_screeninfo *var,
+       struct fb_info *info)
+{
+       int vmode_index, htotal, vtotal;
+       struct viafb_par *ppar;
+       u32 long_refresh;
+       struct viafb_par *p_viafb_par;
+       ppar = info->par;
+
+
+       DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
+       /* Sanity check */
+       /* HW neither support interlacte nor double-scaned mode */
+       if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
+               return -EINVAL;
+
+       vmode_index = viafb_get_mode_index(var->xres, var->yres, 0);
+       if (vmode_index == VIA_RES_INVALID) {
+               DEBUG_MSG(KERN_INFO
+                         "viafb: Mode %dx%dx%d not supported!!\n",
+                         var->xres, var->yres, var->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       if (24 == var->bits_per_pixel)
+               var->bits_per_pixel = 32;
+
+       if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
+               var->bits_per_pixel != 32)
+               return -EINVAL;
+
+       if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
+               /*32 pixel alignment */
+               var->xres_virtual = (var->xres_virtual + 31) & ~31;
+       if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+               ppar->memsize)
+               return -EINVAL;
+
+       /* Based on var passed in to calculate the refresh,
+        * because our driver use some modes special.
+        */
+       htotal = var->xres + var->left_margin +
+       var->right_margin + var->hsync_len;
+       vtotal = var->yres + var->upper_margin +
+               var->lower_margin + var->vsync_len;
+       long_refresh = 1000000000UL / var->pixclock * 1000;
+       long_refresh /= (htotal * vtotal);
+
+       viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
+
+       /* Adjust var according to our driver's own table */
+       viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
+
+       /* This is indeed a patch for VT3353 */
+       if (!info->par)
+               return -1;
+       p_viafb_par = (struct viafb_par *)info->par;
+       if (p_viafb_par->chip_info->gfx_chip_name == UNICHROME_VX800)
+               var->accel_flags = 0;
+
+       return 0;
+}
+
+static int viafb_set_par(struct fb_info *info)
+{
+       int vmode_index;
+       int vmode_index1 = 0;
+       DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
+
+       viafb_update_device_setting(info->var.xres, info->var.yres,
+                             info->var.bits_per_pixel, viafb_refresh, 0);
+
+       vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0);
+
+       if (viafb_SAMM_ON == 1) {
+               DEBUG_MSG(KERN_INFO
+               "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
+                         viafb_second_xres, viafb_second_yres, viafb_bpp1);
+               vmode_index1 = viafb_get_mode_index(viafb_second_xres,
+                       viafb_second_yres, 1);
+               DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
+                       vmode_index1);
+
+               viafb_update_device_setting(viafb_second_xres,
+                       viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
+       }
+
+       if (vmode_index != VIA_RES_INVALID) {
+               viafb_setmode(vmode_index, info->var.xres, info->var.yres,
+                       info->var.bits_per_pixel, vmode_index1,
+                       viafb_second_xres, viafb_second_yres, viafb_bpp1);
+
+               /*We should set memory offset according virtual_x */
+               /*Fix me:put this function into viafb_setmode */
+               viafb_memory_pitch_patch(info);
+
+               /* Update ***fb_par information */
+               viafb_update_viafb_par(info);
+
+               /* Update other fixed information */
+               viafb_update_fix(&info->fix, info);
+               viafb_bpp = info->var.bits_per_pixel;
+               /* Update viafb_accel, it is necessary to our 2D accelerate */
+               viafb_accel = info->var.accel_flags;
+
+               if (viafb_accel)
+                       viafb_set_2d_color_depth(info->var.bits_per_pixel);
+       }
+
+       return 0;
+}
+
+/* Set one color register */
+static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+unsigned blue, unsigned transp, struct fb_info *info)
+{
+       u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
+       unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
+       DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
+       if (regno >= cmap_entries)
+               return 1;
+       if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
+               /*
+                * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
+                */
+               outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
+               rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
+       }
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               outb(0x1A, 0x3C4);
+               sr1a = inb(0x3C5);
+               outb(0x1B, 0x3C4);
+               sr1b = inb(0x3C5);
+               outb(0x67, 0x3D4);
+               cr67 = inb(0x3D5);
+               outb(0x6A, 0x3D4);
+               cr6a = inb(0x3D5);
+
+               /* Map the 3C6/7/8/9 to the IGA2 */
+               outb(0x1A, 0x3C4);
+               outb(sr1a | 0x01, 0x3C5);
+               /* Second Display Engine colck always on */
+               outb(0x1B, 0x3C4);
+               outb(sr1b | 0x80, 0x3C5);
+               /* Second Display Color Depth 8 */
+               outb(0x67, 0x3D4);
+               outb(cr67 & 0x3F, 0x3D5);
+               outb(0x6A, 0x3D4);
+               /* Second Display Channel Reset CR6A[6]) */
+               outb(cr6a & 0xBF, 0x3D5);
+               /* Second Display Channel Enable CR6A[7] */
+               outb(cr6a | 0x80, 0x3D5);
+               /* Second Display Channel stop reset) */
+               outb(cr6a | 0x40, 0x3D5);
+
+               /* Bit mask of palette */
+               outb(0xFF, 0x3c6);
+               /* Write one register of IGA2 */
+               outb(regno, 0x3C8);
+               if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
+                       rev >= 15) {
+                       shift = 8;
+                       viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
+                       viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
+               } else {
+                       shift = 10;
+                       viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
+                       viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
+               }
+               outb(red >> shift, 0x3C9);
+               outb(green >> shift, 0x3C9);
+               outb(blue >> shift, 0x3C9);
+
+               /* Map the 3C6/7/8/9 to the IGA1 */
+               outb(0x1A, 0x3C4);
+               outb(sr1a & 0xFE, 0x3C5);
+               /* Bit mask of palette */
+               outb(0xFF, 0x3c6);
+               /* Write one register of IGA1 */
+               outb(regno, 0x3C8);
+               outb(red >> shift, 0x3C9);
+               outb(green >> shift, 0x3C9);
+               outb(blue >> shift, 0x3C9);
+
+               outb(0x1A, 0x3C4);
+               outb(sr1a, 0x3C5);
+               outb(0x1B, 0x3C4);
+               outb(sr1b, 0x3C5);
+               outb(0x67, 0x3D4);
+               outb(cr67, 0x3D5);
+               outb(0x6A, 0x3D4);
+               outb(cr6a, 0x3D5);
+               break;
+       case 16:
+               ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
+                   ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+               break;
+       case 32:
+               ((u32 *) info->pseudo_palette)[regno] =
+                   ((transp & 0xFF00) << 16) |
+                   ((red & 0xFF00) << 8) |
+                   ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
+               break;
+       }
+
+       return 0;
+
+}
+
+/*CALLED BY: fb_set_cmap */
+/*           fb_set_var, pass 256 colors */
+/*CALLED BY: fb_set_cmap */
+/*           fbcon_set_palette, pass 16 colors */
+static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+       u32 len = cmap->len;
+       u32 i;
+       u16 *pred = cmap->red;
+       u16 *pgreen = cmap->green;
+       u16 *pblue = cmap->blue;
+       u16 *ptransp = cmap->transp;
+       u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
+       if (len > 256)
+               return 1;
+       if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
+               /*
+                * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
+                * rev.
+                */
+               outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
+               rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
+       }
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               outb(0x1A, 0x3C4);
+               sr1a = inb(0x3C5);
+               outb(0x1B, 0x3C4);
+               sr1b = inb(0x3C5);
+               outb(0x67, 0x3D4);
+               cr67 = inb(0x3D5);
+               outb(0x6A, 0x3D4);
+               cr6a = inb(0x3D5);
+               /* Map the 3C6/7/8/9 to the IGA2 */
+               outb(0x1A, 0x3C4);
+               outb(sr1a | 0x01, 0x3C5);
+               outb(0x1B, 0x3C4);
+               /* Second Display Engine colck always on */
+               outb(sr1b | 0x80, 0x3C5);
+               outb(0x67, 0x3D4);
+               /* Second Display Color Depth 8 */
+               outb(cr67 & 0x3F, 0x3D5);
+               outb(0x6A, 0x3D4);
+               /* Second Display Channel Reset CR6A[6]) */
+               outb(cr6a & 0xBF, 0x3D5);
+               /* Second Display Channel Enable CR6A[7] */
+               outb(cr6a | 0x80, 0x3D5);
+               /* Second Display Channel stop reset) */
+               outb(cr6a | 0xC0, 0x3D5);
+
+               /* Bit mask of palette */
+               outb(0xFF, 0x3c6);
+               outb(0x00, 0x3C8);
+               if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
+                       rev >= 15) {
+                       shift = 8;
+                       viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
+                       viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
+               } else {
+                       shift = 10;
+                       viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
+                       viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
+               }
+               for (i = 0; i < len; i++) {
+                       outb((*(pred + i)) >> shift, 0x3C9);
+                       outb((*(pgreen + i)) >> shift, 0x3C9);
+                       outb((*(pblue + i)) >> shift, 0x3C9);
+               }
+
+               outb(0x1A, 0x3C4);
+               /* Map the 3C6/7/8/9 to the IGA1 */
+               outb(sr1a & 0xFE, 0x3C5);
+               /* Bit mask of palette */
+               outb(0xFF, 0x3c6);
+               outb(0x00, 0x3C8);
+               for (i = 0; i < len; i++) {
+                       outb((*(pred + i)) >> shift, 0x3C9);
+                       outb((*(pgreen + i)) >> shift, 0x3C9);
+                       outb((*(pblue + i)) >> shift, 0x3C9);
+               }
+
+               outb(0x1A, 0x3C4);
+               outb(sr1a, 0x3C5);
+               outb(0x1B, 0x3C4);
+               outb(sr1b, 0x3C5);
+               outb(0x67, 0x3D4);
+               outb(cr67, 0x3D5);
+               outb(0x6A, 0x3D4);
+               outb(cr6a, 0x3D5);
+               break;
+       case 16:
+               if (len > 17)
+                       return 0;       /* Because static u32 pseudo_pal[17]; */
+               for (i = 0; i < len; i++)
+                       ((u32 *) info->pseudo_palette)[i] =
+                           (*(pred + i) & 0xF800) |
+                           ((*(pgreen + i) & 0xFC00) >> 5) |
+                           ((*(pblue + i) & 0xF800) >> 11);
+               break;
+       case 32:
+               if (len > 17)
+                       return 0;
+               if (ptransp) {
+                       for (i = 0; i < len; i++)
+                               ((u32 *) info->pseudo_palette)[i] =
+                                   ((*(ptransp + i) & 0xFF00) << 16) |
+                                   ((*(pred + i) & 0xFF00) << 8) |
+                                   ((*(pgreen + i) & 0xFF00)) |
+                                   ((*(pblue + i) & 0xFF00) >> 8);
+               } else {
+                       for (i = 0; i < len; i++)
+                               ((u32 *) info->pseudo_palette)[i] =
+                                   0x00000000 |
+                                   ((*(pred + i) & 0xFF00) << 8) |
+                                   ((*(pgreen + i) & 0xFF00)) |
+                                   ((*(pblue + i) & 0xFF00) >> 8);
+               }
+               break;
+       }
+       return 0;
+}
+
+static int viafb_pan_display(struct fb_var_screeninfo *var,
+       struct fb_info *info)
+{
+       unsigned int offset;
+
+       DEBUG_MSG(KERN_INFO "viafb_pan_display!\n");
+
+       offset = (var->xoffset + (var->yoffset * var->xres_virtual)) *
+           var->bits_per_pixel / 16;
+
+       DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
+
+       viafb_write_reg_mask(0x48, 0x3d4, ((offset >> 24) & 0x3), 0x3);
+       viafb_write_reg_mask(0x34, 0x3d4, ((offset >> 16) & 0xff), 0xff);
+       viafb_write_reg_mask(0x0c, 0x3d4, ((offset >> 8) & 0xff), 0xff);
+       viafb_write_reg_mask(0x0d, 0x3d4, (offset & 0xff), 0xff);
+
+       return 0;
+}
+
+static int viafb_blank(int blank_mode, struct fb_info *info)
+{
+       DEBUG_MSG(KERN_INFO "viafb_blank!\n");
+       /* clear DPMS setting */
+
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               /* Screen: On, HSync: On, VSync: On */
+               /* control CRT monitor power management */
+               viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
+               break;
+       case FB_BLANK_HSYNC_SUSPEND:
+               /* Screen: Off, HSync: Off, VSync: On */
+               /* control CRT monitor power management */
+               viafb_write_reg_mask(CR36, VIACR, 0x10, BIT4 + BIT5);
+               break;
+       case FB_BLANK_VSYNC_SUSPEND:
+               /* Screen: Off, HSync: On, VSync: Off */
+               /* control CRT monitor power management */
+               viafb_write_reg_mask(CR36, VIACR, 0x20, BIT4 + BIT5);
+               break;
+       case FB_BLANK_POWERDOWN:
+               /* Screen: Off, HSync: Off, VSync: Off */
+               /* control CRT monitor power management */
+               viafb_write_reg_mask(CR36, VIACR, 0x30, BIT4 + BIT5);
+               break;
+       }
+
+       return 0;
+}
+
+static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+{
+       struct viafb_ioctl_mode viamode;
+       struct viafb_ioctl_samm viasamm;
+       struct viafb_driver_version driver_version;
+       struct fb_var_screeninfo sec_var;
+       struct _panel_size_pos_info panel_pos_size_para;
+       u32 state_info = 0;
+       u32 viainfo_size = sizeof(struct viafb_ioctl_info);
+       u32 *viafb_gamma_table;
+       char driver_name[] = "viafb";
+
+       u32 __user *argp = (u32 __user *) arg;
+       u32 gpu32;
+       u32 video_dev_info = 0;
+       struct viafb_ioctl_setting viafb_setting = {};
+       struct device_t active_dev = {};
+
+       DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
+
+       switch (cmd) {
+       case VIAFB_GET_CHIP_INFO:
+               if (copy_to_user(argp, viaparinfo->chip_info,
+                               sizeof(struct chip_information)))
+                       return -EFAULT;
+               break;
+       case VIAFB_GET_INFO_SIZE:
+               return put_user(viainfo_size, argp);
+       case VIAFB_GET_INFO:
+               return viafb_ioctl_get_viafb_info(arg);
+       case VIAFB_HOTPLUG:
+               return put_user(viafb_ioctl_hotplug(info->var.xres,
+                                             info->var.yres,
+                                             info->var.bits_per_pixel), argp);
+       case VIAFB_SET_HOTPLUG_FLAG:
+               if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+                       return -EFAULT;
+               viafb_hotplug = (gpu32) ? 1 : 0;
+               break;
+       case VIAFB_GET_RESOLUTION:
+               viamode.xres = (u32) viafb_hotplug_Xres;
+               viamode.yres = (u32) viafb_hotplug_Yres;
+               viamode.refresh = (u32) viafb_hotplug_refresh;
+               viamode.bpp = (u32) viafb_hotplug_bpp;
+               if (viafb_SAMM_ON == 1) {
+                       viamode.xres_sec = viafb_second_xres;
+                       viamode.yres_sec = viafb_second_yres;
+                       viamode.virtual_xres_sec = viafb_second_virtual_xres;
+                       viamode.virtual_yres_sec = viafb_second_virtual_yres;
+                       viamode.refresh_sec = viafb_refresh1;
+                       viamode.bpp_sec = viafb_bpp1;
+               } else {
+                       viamode.xres_sec = 0;
+                       viamode.yres_sec = 0;
+                       viamode.virtual_xres_sec = 0;
+                       viamode.virtual_yres_sec = 0;
+                       viamode.refresh_sec = 0;
+                       viamode.bpp_sec = 0;
+               }
+               if (copy_to_user(argp, &viamode, sizeof(viamode)))
+                       return -EFAULT;
+               break;
+       case VIAFB_GET_SAMM_INFO:
+               viasamm.samm_status = viafb_SAMM_ON;
+
+               if (viafb_SAMM_ON == 1) {
+                       if (viafb_dual_fb) {
+                               viasamm.size_prim = viaparinfo->fbmem_free;
+                               viasamm.size_sec = viaparinfo1->fbmem_free;
+                       } else {
+                               if (viafb_second_size) {
+                                       viasamm.size_prim =
+                                           viaparinfo->fbmem_free -
+                                           viafb_second_size * 1024 * 1024;
+                                       viasamm.size_sec =
+                                           viafb_second_size * 1024 * 1024;
+                               } else {
+                                       viasamm.size_prim =
+                                           viaparinfo->fbmem_free >> 1;
+                                       viasamm.size_sec =
+                                           (viaparinfo->fbmem_free >> 1);
+                               }
+                       }
+                       viasamm.mem_base = viaparinfo->fbmem;
+                       viasamm.offset_sec = viafb_second_offset;
+               } else {
+                       viasamm.size_prim =
+                           viaparinfo->memsize - viaparinfo->fbmem_used;
+                       viasamm.size_sec = 0;
+                       viasamm.mem_base = viaparinfo->fbmem;
+                       viasamm.offset_sec = 0;
+               }
+
+               if (copy_to_user(argp, &viasamm, sizeof(viasamm)))
+                       return -EFAULT;
+
+               break;
+       case VIAFB_TURN_ON_OUTPUT_DEVICE:
+               if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+                       return -EFAULT;
+               if (gpu32 & CRT_Device)
+                       viafb_crt_enable();
+               if (gpu32 & DVI_Device)
+                       viafb_dvi_enable();
+               if (gpu32 & LCD_Device)
+                       viafb_lcd_enable();
+               break;
+       case VIAFB_TURN_OFF_OUTPUT_DEVICE:
+               if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
+                       return -EFAULT;
+               if (gpu32 & CRT_Device)
+                       viafb_crt_disable();
+               if (gpu32 & DVI_Device)
+                       viafb_dvi_disable();
+               if (gpu32 & LCD_Device)
+                       viafb_lcd_disable();
+               break;
+       case VIAFB_SET_DEVICE:
+               if (copy_from_user(&active_dev, (void *)argp,
+                       sizeof(active_dev)))
+                       return -EFAULT;
+               viafb_set_device(active_dev);
+               viafb_set_par(info);
+               break;
+       case VIAFB_GET_DEVICE:
+               active_dev.crt = viafb_CRT_ON;
+               active_dev.dvi = viafb_DVI_ON;
+               active_dev.lcd = viafb_LCD_ON;
+               active_dev.samm = viafb_SAMM_ON;
+               active_dev.primary_dev = viafb_primary_dev;
+
+               active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
+               active_dev.lcd_panel_id = viafb_lcd_panel_id;
+               active_dev.lcd_mode = viafb_lcd_mode;
+
+               active_dev.xres = viafb_hotplug_Xres;
+               active_dev.yres = viafb_hotplug_Yres;
+
+               active_dev.xres1 = viafb_second_xres;
+               active_dev.yres1 = viafb_second_yres;
+
+               active_dev.bpp = viafb_bpp;
+               active_dev.bpp1 = viafb_bpp1;
+               active_dev.refresh = viafb_refresh;
+               active_dev.refresh1 = viafb_refresh1;
+
+               active_dev.epia_dvi = viafb_platform_epia_dvi;
+               active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
+               active_dev.bus_width = viafb_bus_width;
+
+               if (copy_to_user(argp, &active_dev, sizeof(active_dev)))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_GET_DRIVER_VERSION:
+               driver_version.iMajorNum = VERSION_MAJOR;
+               driver_version.iKernelNum = VERSION_KERNEL;
+               driver_version.iOSNum = VERSION_OS;
+               driver_version.iMinorNum = VERSION_MINOR;
+
+               if (copy_to_user(argp, &driver_version,
+                       sizeof(driver_version)))
+                       return -EFAULT;
+
+               break;
+
+       case VIAFB_SET_DEVICE_INFO:
+               if (copy_from_user(&viafb_setting,
+                       argp, sizeof(viafb_setting)))
+                       return -EFAULT;
+               if (apply_device_setting(viafb_setting, info) < 0)
+                       return -EINVAL;
+
+               break;
+
+       case VIAFB_SET_SECOND_MODE:
+               if (copy_from_user(&sec_var, argp, sizeof(sec_var)))
+                       return -EFAULT;
+               apply_second_mode_setting(&sec_var);
+               break;
+
+       case VIAFB_GET_DEVICE_INFO:
+
+               retrieve_device_setting(&viafb_setting);
+
+               if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting)))
+                       return -EFAULT;
+
+               break;
+
+       case VIAFB_GET_DEVICE_SUPPORT:
+               viafb_get_device_support_state(&state_info);
+               if (put_user(state_info, argp))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_GET_DEVICE_CONNECT:
+               viafb_get_device_connect_state(&state_info);
+               if (put_user(state_info, argp))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_GET_PANEL_SUPPORT_EXPAND:
+               state_info =
+                   viafb_lcd_get_support_expand_state(info->var.xres,
+                                                info->var.yres);
+               if (put_user(state_info, argp))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_GET_DRIVER_NAME:
+               if (copy_to_user(argp, driver_name, sizeof(driver_name)))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_SET_GAMMA_LUT:
+               viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+               if (!viafb_gamma_table)
+                       return -ENOMEM;
+               if (copy_from_user(viafb_gamma_table, argp,
+                               sizeof(viafb_gamma_table))) {
+                       kfree(viafb_gamma_table);
+                       return -EFAULT;
+               }
+               viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
+               kfree(viafb_gamma_table);
+               break;
+
+       case VIAFB_GET_GAMMA_LUT:
+               viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+               if (!viafb_gamma_table)
+                       return -ENOMEM;
+               viafb_get_gamma_table(viafb_gamma_table);
+               if (copy_to_user(argp, viafb_gamma_table,
+                       sizeof(viafb_gamma_table))) {
+                       kfree(viafb_gamma_table);
+                       return -EFAULT;
+               }
+               kfree(viafb_gamma_table);
+               break;
+
+       case VIAFB_GET_GAMMA_SUPPORT_STATE:
+               viafb_get_gamma_support_state(viafb_bpp, &state_info);
+               if (put_user(state_info, argp))
+                       return -EFAULT;
+               break;
+       case VIAFB_SET_VIDEO_DEVICE:
+               get_user(video_dev_info, argp);
+               viafb_set_video_device(video_dev_info);
+               break;
+       case VIAFB_GET_VIDEO_DEVICE:
+               viafb_get_video_device(&video_dev_info);
+               if (put_user(video_dev_info, argp))
+                       return -EFAULT;
+               break;
+       case VIAFB_SYNC_SURFACE:
+               DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
+               break;
+       case VIAFB_GET_DRIVER_CAPS:
+               break;
+
+       case VIAFB_GET_PANEL_MAX_SIZE:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               panel_pos_size_para.x = panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &panel_pos_size_para,
+                    sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+       case VIAFB_GET_PANEL_MAX_POSITION:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               panel_pos_size_para.x = panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &panel_pos_size_para,
+                    sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_GET_PANEL_POSITION:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               panel_pos_size_para.x = panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &panel_pos_size_para,
+                    sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+       case VIAFB_GET_PANEL_SIZE:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               panel_pos_size_para.x = panel_pos_size_para.y = 0;
+               if (copy_to_user(argp, &panel_pos_size_para,
+                    sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+
+       case VIAFB_SET_PANEL_POSITION:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+       case VIAFB_SET_PANEL_SIZE:
+               if (copy_from_user
+                   (&panel_pos_size_para, argp, sizeof(panel_pos_size_para)))
+                       return -EFAULT;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void viafb_fillrect(struct fb_info *info,
+       const struct fb_fillrect *rect)
+{
+       u32 col = 0, rop = 0;
+       int pitch;
+
+       if (!viafb_accel)
+               return cfb_fillrect(info, rect);
+
+       if (!rect->width || !rect->height)
+               return;
+
+       switch (rect->rop) {
+       case ROP_XOR:
+               rop = 0x5A;
+               break;
+       case ROP_COPY:
+       default:
+               rop = 0xF0;
+               break;
+       }
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               col = rect->color;
+               break;
+       case 16:
+               col = ((u32 *) (info->pseudo_palette))[rect->color];
+               break;
+       case 32:
+               col = ((u32 *) (info->pseudo_palette))[rect->color];
+               break;
+       }
+
+       /* BitBlt Source Address */
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+       /* Source Base Address */
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+       /* Destination Base Address */
+       writel(((unsigned long) (info->screen_base) -
+                  (unsigned long) viafb_FB_MM) >> 3,
+                  viaparinfo->io_virt + VIA_REG_DSTBASE);
+       /* Pitch */
+       pitch = (info->var.xres_virtual + 7) & ~7;
+       writel(VIA_PITCH_ENABLE |
+                  (((pitch *
+                     info->var.bits_per_pixel >> 3) >> 3) |
+                     (((pitch * info->
+                     var.bits_per_pixel >> 3) >> 3) << 16)),
+                     viaparinfo->io_virt + VIA_REG_PITCH);
+       /* BitBlt Destination Address */
+       writel(((rect->dy << 16) | rect->dx),
+               viaparinfo->io_virt + VIA_REG_DSTPOS);
+       /* Dimension: width & height */
+       writel((((rect->height - 1) << 16) | (rect->width - 1)),
+               viaparinfo->io_virt + VIA_REG_DIMENSION);
+       /* Forground color or Destination color */
+       writel(col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+       /* GE Command */
+       writel((0x01 | 0x2000 | (rop << 24)),
+               viaparinfo->io_virt + VIA_REG_GECMD);
+
+}
+
+static void viafb_copyarea(struct fb_info *info,
+       const struct fb_copyarea *area)
+{
+       u32 dy = area->dy, sy = area->sy, direction = 0x0;
+       u32 sx = area->sx, dx = area->dx, width = area->width;
+       int pitch;
+
+       DEBUG_MSG(KERN_INFO "viafb_copyarea!!\n");
+
+       if (!viafb_accel)
+               return cfb_copyarea(info, area);
+
+       if (!area->width || !area->height)
+               return;
+
+       if (sy < dy) {
+               dy += area->height - 1;
+               sy += area->height - 1;
+               direction |= 0x4000;
+       }
+
+       if (sx < dx) {
+               dx += width - 1;
+               sx += width - 1;
+               direction |= 0x8000;
+       }
+
+       /* Source Base Address */
+       writel(((unsigned long) (info->screen_base) -
+                  (unsigned long) viafb_FB_MM) >> 3,
+                  viaparinfo->io_virt + VIA_REG_SRCBASE);
+       /* Destination Base Address */
+       writel(((unsigned long) (info->screen_base) -
+                  (unsigned long) viafb_FB_MM) >> 3,
+                  viaparinfo->io_virt + VIA_REG_DSTBASE);
+       /* Pitch */
+       pitch = (info->var.xres_virtual + 7) & ~7;
+       /* VIA_PITCH_ENABLE can be omitted now. */
+       writel(VIA_PITCH_ENABLE |
+                  (((pitch *
+                     info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
+                                                               info->var.
+                                                               bits_per_pixel
+                                                               >> 3) >> 3)
+                                                             << 16)),
+                               viaparinfo->io_virt + VIA_REG_PITCH);
+       /* BitBlt Source Address */
+       writel(((sy << 16) | sx), viaparinfo->io_virt + VIA_REG_SRCPOS);
+       /* BitBlt Destination Address */
+       writel(((dy << 16) | dx), viaparinfo->io_virt + VIA_REG_DSTPOS);
+       /* Dimension: width & height */
+       writel((((area->height - 1) << 16) | (area->width - 1)),
+                  viaparinfo->io_virt + VIA_REG_DIMENSION);
+       /* GE Command */
+       writel((0x01 | direction | (0xCC << 24)),
+               viaparinfo->io_virt + VIA_REG_GECMD);
+
+}
+
+static void viafb_imageblit(struct fb_info *info,
+       const struct fb_image *image)
+{
+       u32 size, bg_col = 0, fg_col = 0, *udata;
+       int i;
+       int pitch;
+
+       if (!viafb_accel)
+               return cfb_imageblit(info, image);
+
+       udata = (u32 *) image->data;
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               bg_col = image->bg_color;
+               fg_col = image->fg_color;
+               break;
+       case 16:
+               bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
+               fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
+               break;
+       case 32:
+               bg_col = ((u32 *) (info->pseudo_palette))[image->bg_color];
+               fg_col = ((u32 *) (info->pseudo_palette))[image->fg_color];
+               break;
+       }
+       size = image->width * image->height;
+
+       /* Source Base Address */
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
+       /* Destination Base Address */
+       writel(((unsigned long) (info->screen_base) -
+                  (unsigned long) viafb_FB_MM) >> 3,
+                  viaparinfo->io_virt + VIA_REG_DSTBASE);
+       /* Pitch */
+       pitch = (info->var.xres_virtual + 7) & ~7;
+       writel(VIA_PITCH_ENABLE |
+                  (((pitch *
+                     info->var.bits_per_pixel >> 3) >> 3) | (((pitch *
+                                                               info->var.
+                                                               bits_per_pixel
+                                                               >> 3) >> 3)
+                                                             << 16)),
+                               viaparinfo->io_virt + VIA_REG_PITCH);
+       /* BitBlt Source Address */
+       writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
+       /* BitBlt Destination Address */
+       writel(((image->dy << 16) | image->dx),
+               viaparinfo->io_virt + VIA_REG_DSTPOS);
+       /* Dimension: width & height */
+       writel((((image->height - 1) << 16) | (image->width - 1)),
+                  viaparinfo->io_virt + VIA_REG_DIMENSION);
+       /* fb color */
+       writel(fg_col, viaparinfo->io_virt + VIA_REG_FGCOLOR);
+       /* bg color */
+       writel(bg_col, viaparinfo->io_virt + VIA_REG_BGCOLOR);
+       /* GE Command */
+       writel(0xCC020142, viaparinfo->io_virt + VIA_REG_GECMD);
+
+       for (i = 0; i < size / 4; i++) {
+               writel(*udata, viaparinfo->io_virt + VIA_MMIO_BLTBASE);
+               udata++;
+       }
+
+}
+
+static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+       u8 data[CURSOR_SIZE / 8];
+       u32 data_bak[CURSOR_SIZE / 32];
+       u32 temp, xx, yy, bg_col = 0, fg_col = 0;
+       int size, i, j = 0;
+       static int hw_cursor;
+       struct viafb_par *p_viafb_par;
+
+       if (viafb_accel)
+               hw_cursor = 1;
+
+       if (!viafb_accel) {
+               if (hw_cursor) {
+                       viafb_show_hw_cursor(info, HW_Cursor_OFF);
+                       hw_cursor = 0;
+               }
+               return -ENODEV;
+       }
+
+       if ((((struct viafb_par *)(info->par))->iga_path == IGA2)
+           && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
+               return -ENODEV;
+
+       /* When duoview and using lcd , use soft cursor */
+       if (viafb_LCD_ON || ((struct viafb_par *)(info->par))->duoview)
+               return -ENODEV;
+
+       viafb_show_hw_cursor(info, HW_Cursor_OFF);
+       viacursor = *cursor;
+
+       if (cursor->set & FB_CUR_SETHOT) {
+               viacursor.hot = cursor->hot;
+               temp = ((viacursor.hot.x) << 16) + viacursor.hot.y;
+               writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
+       }
+
+       if (cursor->set & FB_CUR_SETPOS) {
+               viacursor.image.dx = cursor->image.dx;
+               viacursor.image.dy = cursor->image.dy;
+               yy = cursor->image.dy - info->var.yoffset;
+               xx = cursor->image.dx - info->var.xoffset;
+               temp = yy & 0xFFFF;
+               temp |= (xx << 16);
+               writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
+       }
+
+       if (cursor->set & FB_CUR_SETSIZE) {
+               temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+
+               if ((cursor->image.width <= 32)
+                   && (cursor->image.height <= 32)) {
+                       MAX_CURS = 32;
+                       temp |= 0x2;
+               } else if ((cursor->image.width <= 64)
+                          && (cursor->image.height <= 64)) {
+                       MAX_CURS = 64;
+                       temp &= 0xFFFFFFFD;
+               } else {
+                       DEBUG_MSG(KERN_INFO
+                       "The cursor image is biger than 64x64 bits...\n");
+                       return -ENXIO;
+               }
+               writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
+
+               viacursor.image.height = cursor->image.height;
+               viacursor.image.width = cursor->image.width;
+       }
+
+       if (cursor->set & FB_CUR_SETCMAP) {
+               viacursor.image.fg_color = cursor->image.fg_color;
+               viacursor.image.bg_color = cursor->image.bg_color;
+
+               switch (info->var.bits_per_pixel) {
+               case 8:
+               case 16:
+               case 32:
+                       bg_col =
+                           (0xFF << 24) |
+                           (((info->cmap.red)[viacursor.image.bg_color] &
+                           0xFF00) << 8) |
+                           ((info->cmap.green)[viacursor.image.bg_color] &
+                           0xFF00) |
+                           (((info->cmap.blue)[viacursor.image.bg_color] &
+                           0xFF00) >> 8);
+                       fg_col =
+                           (0xFF << 24) |
+                           (((info->cmap.red)[viacursor.image.fg_color] &
+                           0xFF00) << 8) |
+                           ((info->cmap.green)[viacursor.image.fg_color] &
+                           0xFF00) |
+                           (((info->cmap.blue)[viacursor.image.fg_color] &
+                           0xFF00) >> 8);
+                       break;
+               default:
+                       return 0;
+               }
+
+               /* This is indeed a patch for VT3324/VT3353 */
+               if (!info->par)
+                       return 0;
+               p_viafb_par = (struct viafb_par *)info->par;
+
+               if ((p_viafb_par->chip_info->gfx_chip_name ==
+                       UNICHROME_CX700) ||
+                       ((p_viafb_par->chip_info->gfx_chip_name ==
+                       UNICHROME_VX800))) {
+                       bg_col =
+                           (((info->cmap.red)[viacursor.image.bg_color] &
+                           0xFFC0) << 14) |
+                           (((info->cmap.green)[viacursor.image.bg_color] &
+                           0xFFC0) << 4) |
+                           (((info->cmap.blue)[viacursor.image.bg_color] &
+                           0xFFC0) >> 6);
+                       fg_col =
+                           (((info->cmap.red)[viacursor.image.fg_color] &
+                           0xFFC0) << 14) |
+                           (((info->cmap.green)[viacursor.image.fg_color] &
+                           0xFFC0) << 4) |
+                           (((info->cmap.blue)[viacursor.image.fg_color] &
+                           0xFFC0) >> 6);
+               }
+
+               writel(bg_col, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
+               writel(fg_col, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
+       }
+
+       if (cursor->set & FB_CUR_SETSHAPE) {
+               size =
+                   ((viacursor.image.width + 7) >> 3) *
+                   viacursor.image.height;
+
+               if (MAX_CURS == 32) {
+                       for (i = 0; i < (CURSOR_SIZE / 32); i++) {
+                               data_bak[i] = 0x0;
+                               data_bak[i + 1] = 0xFFFFFFFF;
+                               i += 1;
+                       }
+               } else if (MAX_CURS == 64) {
+                       for (i = 0; i < (CURSOR_SIZE / 32); i++) {
+                               data_bak[i] = 0x0;
+                               data_bak[i + 1] = 0x0;
+                               data_bak[i + 2] = 0xFFFFFFFF;
+                               data_bak[i + 3] = 0xFFFFFFFF;
+                               i += 3;
+                       }
+               }
+
+               switch (viacursor.rop) {
+               case ROP_XOR:
+                       for (i = 0; i < size; i++)
+                               data[i] = viacursor.mask[i];
+                       break;
+               case ROP_COPY:
+
+                       for (i = 0; i < size; i++)
+                               data[i] = viacursor.mask[i];
+                       break;
+               default:
+                       break;
+               }
+
+               if (MAX_CURS == 32) {
+                       for (i = 0; i < size; i++) {
+                               data_bak[j] = (u32) data[i];
+                               data_bak[j + 1] = ~data_bak[j];
+                               j += 2;
+                       }
+               } else if (MAX_CURS == 64) {
+                       for (i = 0; i < size; i++) {
+                               data_bak[j] = (u32) data[i];
+                               data_bak[j + 1] = 0x0;
+                               data_bak[j + 2] = ~data_bak[j];
+                               data_bak[j + 3] = ~data_bak[j + 1];
+                               j += 4;
+                       }
+               }
+
+               memcpy(((struct viafb_par *)(info->par))->fbmem_virt +
+                      ((struct viafb_par *)(info->par))->cursor_start,
+                      data_bak, CURSOR_SIZE);
+       }
+
+       if (viacursor.enable)
+               viafb_show_hw_cursor(info, HW_Cursor_ON);
+
+       return 0;
+}
+
+static int viafb_sync(struct fb_info *info)
+{
+       if (viafb_accel)
+               viafb_wait_engine_idle();
+       return 0;
+}
+
+int viafb_get_mode_index(int hres, int vres, int flag)
+{
+       u32 i;
+       DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
+
+       for (i = 0; viafb_modentry[i].mode_index != VIA_RES_INVALID; i++)
+               if (viafb_modentry[i].xres == hres &&
+                       viafb_modentry[i].yres == vres)
+                       break;
+
+       viafb_resMode = viafb_modentry[i].mode_index;
+       if (flag)
+               viafb_mode1 = viafb_modentry[i].mode_res;
+       else
+               viafb_mode = viafb_modentry[i].mode_res;
+
+       return viafb_resMode;
+}
+
+static void check_available_device_to_enable(int device_id)
+{
+       int device_num = 0;
+
+       /* Initialize: */
+       viafb_CRT_ON = STATE_OFF;
+       viafb_DVI_ON = STATE_OFF;
+       viafb_LCD_ON = STATE_OFF;
+       viafb_LCD2_ON = STATE_OFF;
+       viafb_DeviceStatus = None_Device;
+
+       if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+               viafb_CRT_ON = STATE_ON;
+               device_num++;
+               viafb_DeviceStatus |= CRT_Device;
+       }
+
+       if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+               viafb_DVI_ON = STATE_ON;
+               device_num++;
+               viafb_DeviceStatus |= DVI_Device;
+       }
+
+       if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+               viafb_LCD_ON = STATE_ON;
+               device_num++;
+               viafb_DeviceStatus |= LCD_Device;
+       }
+
+       if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
+               viafb_LCD2_ON = STATE_ON;
+               device_num++;
+               viafb_DeviceStatus |= LCD2_Device;
+       }
+
+       if (viafb_DeviceStatus == None_Device) {
+               /* Use CRT as default active device: */
+               viafb_CRT_ON = STATE_ON;
+               viafb_DeviceStatus = CRT_Device;
+       }
+       DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus);
+}
+
+static void viafb_set_device(struct device_t active_dev)
+{
+       /* Check available device to enable: */
+       int device_id = None_Device;
+       if (active_dev.crt)
+               device_id |= CRT_Device;
+       if (active_dev.dvi)
+               device_id |= DVI_Device;
+       if (active_dev.lcd)
+               device_id |= LCD_Device;
+
+       check_available_device_to_enable(device_id);
+
+       /* Check property of LCD: */
+       if (viafb_LCD_ON) {
+               if (active_dev.lcd_dsp_cent) {
+                       viaparinfo->lvds_setting_info->display_method =
+                               viafb_lcd_dsp_method = LCD_CENTERING;
+               } else {
+                       viaparinfo->lvds_setting_info->display_method =
+                               viafb_lcd_dsp_method = LCD_EXPANDSION;
+               }
+
+               if (active_dev.lcd_mode == LCD_SPWG) {
+                       viaparinfo->lvds_setting_info->lcd_mode =
+                               viafb_lcd_mode = LCD_SPWG;
+               } else {
+                       viaparinfo->lvds_setting_info->lcd_mode =
+                               viafb_lcd_mode = LCD_OPENLDI;
+               }
+
+               if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) {
+                       viafb_lcd_panel_id = active_dev.lcd_panel_id;
+                       viafb_init_lcd_size();
+               }
+       }
+
+       /* Check property of mode: */
+       if (!active_dev.xres1)
+               viafb_second_xres = 640;
+       else
+               viafb_second_xres = active_dev.xres1;
+       if (!active_dev.yres1)
+               viafb_second_yres = 480;
+       else
+               viafb_second_yres = active_dev.yres1;
+       if (active_dev.bpp != 0)
+               viafb_bpp = active_dev.bpp;
+       if (active_dev.bpp1 != 0)
+               viafb_bpp1 = active_dev.bpp1;
+       if (active_dev.refresh != 0)
+               viafb_refresh = active_dev.refresh;
+       if (active_dev.refresh1 != 0)
+               viafb_refresh1 = active_dev.refresh1;
+       if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON))
+               viafb_SAMM_ON = active_dev.samm;
+       viafb_primary_dev = active_dev.primary_dev;
+
+       viafb_set_start_addr();
+       viafb_set_iga_path();
+}
+
+static void viafb_set_video_device(u32 video_dev_info)
+{
+       viaparinfo->video_on_crt = STATE_OFF;
+       viaparinfo->video_on_dvi = STATE_OFF;
+       viaparinfo->video_on_lcd = STATE_OFF;
+
+       /* Check available device to enable: */
+       if ((video_dev_info & CRT_Device) == CRT_Device)
+               viaparinfo->video_on_crt = STATE_ON;
+       else if ((video_dev_info & DVI_Device) == DVI_Device)
+               viaparinfo->video_on_dvi = STATE_ON;
+       else if ((video_dev_info & LCD_Device) == LCD_Device)
+               viaparinfo->video_on_lcd = STATE_ON;
+}
+
+static void viafb_get_video_device(u32 *video_dev_info)
+{
+       *video_dev_info = None_Device;
+       if (viaparinfo->video_on_crt == STATE_ON)
+               *video_dev_info |= CRT_Device;
+       else if (viaparinfo->video_on_dvi == STATE_ON)
+               *video_dev_info |= DVI_Device;
+       else if (viaparinfo->video_on_lcd == STATE_ON)
+               *video_dev_info |= LCD_Device;
+}
+
+static int get_primary_device(void)
+{
+       int primary_device = 0;
+       /* Rule: device on iga1 path are the primary device. */
+       if (viafb_SAMM_ON) {
+               if (viafb_CRT_ON) {
+                       if (viaparinfo->crt_setting_info->iga_path == IGA1) {
+                               DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n",
+                                       viaparinfo->
+                                       crt_setting_info->iga_path);
+                               primary_device = CRT_Device;
+                       }
+               }
+               if (viafb_DVI_ON) {
+                       if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
+                               DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
+                                       viaparinfo->
+                                       tmds_setting_info->iga_path);
+                               primary_device = DVI_Device;
+                       }
+               }
+               if (viafb_LCD_ON) {
+                       if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
+                               DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
+                                       viaparinfo->
+                                       lvds_setting_info->iga_path);
+                               primary_device = LCD_Device;
+                       }
+               }
+               if (viafb_LCD2_ON) {
+                       if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
+                               DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
+                                       viaparinfo->
+                                       lvds_setting_info2->iga_path);
+                               primary_device = LCD2_Device;
+                       }
+               }
+       }
+       return primary_device;
+}
+
+static u8 is_duoview(void)
+{
+       if (0 == viafb_SAMM_ON) {
+               if (viafb_LCD_ON + viafb_LCD2_ON +
+                       viafb_DVI_ON + viafb_CRT_ON == 2)
+                       return true;
+               return false;
+       } else {
+               return false;
+       }
+}
+
+static void apply_second_mode_setting(struct fb_var_screeninfo
+       *sec_var)
+{
+       u32 htotal, vtotal, long_refresh;
+
+       htotal = sec_var->xres + sec_var->left_margin +
+               sec_var->right_margin + sec_var->hsync_len;
+       vtotal = sec_var->yres + sec_var->upper_margin +
+               sec_var->lower_margin + sec_var->vsync_len;
+       if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) {
+               /*Is 32 bytes alignment? */
+               /*32 pixel alignment */
+               sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31;
+       }
+
+       htotal = sec_var->xres + sec_var->left_margin +
+               sec_var->right_margin + sec_var->hsync_len;
+       vtotal = sec_var->yres + sec_var->upper_margin +
+               sec_var->lower_margin + sec_var->vsync_len;
+       long_refresh = 1000000000UL / sec_var->pixclock * 1000;
+       long_refresh /= (htotal * vtotal);
+
+       viafb_second_xres = sec_var->xres;
+       viafb_second_yres = sec_var->yres;
+       viafb_second_virtual_xres = sec_var->xres_virtual;
+       viafb_second_virtual_yres = sec_var->yres_virtual;
+       viafb_bpp1 = sec_var->bits_per_pixel;
+       viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres,
+               long_refresh);
+}
+
+static int apply_device_setting(struct viafb_ioctl_setting setting_info,
+       struct fb_info *info)
+{
+       int need_set_mode = 0;
+       DEBUG_MSG(KERN_INFO "apply_device_setting\n");
+
+       if (setting_info.device_flag) {
+               need_set_mode = 1;
+               check_available_device_to_enable(setting_info.device_status);
+       }
+
+       /* Unlock LCD's operation according to LCD flag
+          and check if the setting value is valid. */
+       /* If the value is valid, apply the new setting value to the device. */
+       if (viafb_LCD_ON) {
+               if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) {
+                       need_set_mode = 1;
+                       if (setting_info.lcd_attributes.display_center) {
+                               /* Centering */
+                               viaparinfo->lvds_setting_info->display_method =
+                                   LCD_CENTERING;
+                               viafb_lcd_dsp_method = LCD_CENTERING;
+                               viaparinfo->lvds_setting_info2->display_method =
+                                   viafb_lcd_dsp_method = LCD_CENTERING;
+                       } else {
+                               /* expandsion */
+                               viaparinfo->lvds_setting_info->display_method =
+                                   LCD_EXPANDSION;
+                               viafb_lcd_dsp_method = LCD_EXPANDSION;
+                               viaparinfo->lvds_setting_info2->display_method =
+                                   LCD_EXPANDSION;
+                               viafb_lcd_dsp_method = LCD_EXPANDSION;
+                       }
+               }
+
+               if (setting_info.lcd_operation_flag & OP_LCD_MODE) {
+                       need_set_mode = 1;
+                       if (setting_info.lcd_attributes.lcd_mode ==
+                               LCD_SPWG) {
+                               viaparinfo->lvds_setting_info->lcd_mode =
+                                       viafb_lcd_mode = LCD_SPWG;
+                       } else {
+                               viaparinfo->lvds_setting_info->lcd_mode =
+                                       viafb_lcd_mode = LCD_OPENLDI;
+                       }
+                       viaparinfo->lvds_setting_info2->lcd_mode =
+                           viaparinfo->lvds_setting_info->lcd_mode;
+               }
+
+               if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) {
+                       need_set_mode = 1;
+                       if (setting_info.lcd_attributes.panel_id <=
+                           LCD_PANEL_ID_MAXIMUM) {
+                               viafb_lcd_panel_id =
+                                   setting_info.lcd_attributes.panel_id;
+                               viafb_init_lcd_size();
+                       }
+               }
+       }
+
+       if (0 != (setting_info.samm_status & OP_SAMM)) {
+               setting_info.samm_status =
+                   setting_info.samm_status & (~OP_SAMM);
+               if (setting_info.samm_status == 0
+                   || setting_info.samm_status == 1) {
+                       viafb_SAMM_ON = setting_info.samm_status;
+
+                       if (viafb_SAMM_ON)
+                               viafb_primary_dev = setting_info.primary_device;
+
+                       viafb_set_start_addr();
+                       viafb_set_iga_path();
+               }
+               need_set_mode = 1;
+       }
+
+       viaparinfo->duoview = is_duoview();
+
+       if (!need_set_mode) {
+               ;
+       } else {
+               viafb_set_iga_path();
+               viafb_set_par(info);
+       }
+       return true;
+}
+
+static void retrieve_device_setting(struct viafb_ioctl_setting
+       *setting_info)
+{
+
+       /* get device status */
+       if (viafb_CRT_ON == 1)
+               setting_info->device_status = CRT_Device;
+       if (viafb_DVI_ON == 1)
+               setting_info->device_status |= DVI_Device;
+       if (viafb_LCD_ON == 1)
+               setting_info->device_status |= LCD_Device;
+       if (viafb_LCD2_ON == 1)
+               setting_info->device_status |= LCD2_Device;
+       if ((viaparinfo->video_on_crt == 1) && (viafb_CRT_ON == 1)) {
+               setting_info->video_device_status =
+                       viaparinfo->crt_setting_info->iga_path;
+       } else if ((viaparinfo->video_on_dvi == 1) && (viafb_DVI_ON == 1)) {
+               setting_info->video_device_status =
+                       viaparinfo->tmds_setting_info->iga_path;
+       } else if ((viaparinfo->video_on_lcd == 1) && (viafb_LCD_ON == 1)) {
+               setting_info->video_device_status =
+                       viaparinfo->lvds_setting_info->iga_path;
+       } else {
+               setting_info->video_device_status = 0;
+       }
+
+       setting_info->samm_status = viafb_SAMM_ON;
+       setting_info->primary_device = get_primary_device();
+
+       setting_info->first_dev_bpp = viafb_bpp;
+       setting_info->second_dev_bpp = viafb_bpp1;
+
+       setting_info->first_dev_refresh = viafb_refresh;
+       setting_info->second_dev_refresh = viafb_refresh1;
+
+       setting_info->first_dev_hor_res = viafb_hotplug_Xres;
+       setting_info->first_dev_ver_res = viafb_hotplug_Yres;
+       setting_info->second_dev_hor_res = viafb_second_xres;
+       setting_info->second_dev_ver_res = viafb_second_yres;
+
+       /* Get lcd attributes */
+       setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
+       setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
+       setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
+}
+
+static void parse_active_dev(void)
+{
+       viafb_CRT_ON = STATE_OFF;
+       viafb_DVI_ON = STATE_OFF;
+       viafb_LCD_ON = STATE_OFF;
+       viafb_LCD2_ON = STATE_OFF;
+       /* 1. Modify the active status of devices. */
+       /* 2. Keep the order of devices, so we can set corresponding
+          IGA path to devices in SAMM case. */
+       /*    Note: The previous of active_dev is primary device,
+          and the following is secondary device. */
+       if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) {
+               /* CRT+DVI */
+               viafb_CRT_ON = STATE_ON;
+               viafb_DVI_ON = STATE_ON;
+               viafb_primary_dev = CRT_Device;
+       } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) {
+               /* DVI+CRT */
+               viafb_CRT_ON = STATE_ON;
+               viafb_DVI_ON = STATE_ON;
+               viafb_primary_dev = DVI_Device;
+       } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) {
+               /* CRT+LCD */
+               viafb_CRT_ON = STATE_ON;
+               viafb_LCD_ON = STATE_ON;
+               viafb_primary_dev = CRT_Device;
+       } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) {
+               /* LCD+CRT */
+               viafb_CRT_ON = STATE_ON;
+               viafb_LCD_ON = STATE_ON;
+               viafb_primary_dev = LCD_Device;
+       } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) {
+               /* DVI+LCD */
+               viafb_DVI_ON = STATE_ON;
+               viafb_LCD_ON = STATE_ON;
+               viafb_primary_dev = DVI_Device;
+       } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) {
+               /* LCD+DVI */
+               viafb_DVI_ON = STATE_ON;
+               viafb_LCD_ON = STATE_ON;
+               viafb_primary_dev = LCD_Device;
+       } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) {
+               viafb_LCD_ON = STATE_ON;
+               viafb_LCD2_ON = STATE_ON;
+               viafb_primary_dev = LCD_Device;
+       } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) {
+               viafb_LCD_ON = STATE_ON;
+               viafb_LCD2_ON = STATE_ON;
+               viafb_primary_dev = LCD2_Device;
+       } else if (!strncmp(viafb_active_dev, "CRT", 3)) {
+               /* CRT only */
+               viafb_CRT_ON = STATE_ON;
+               viafb_SAMM_ON = STATE_OFF;
+       } else if (!strncmp(viafb_active_dev, "DVI", 3)) {
+               /* DVI only */
+               viafb_DVI_ON = STATE_ON;
+               viafb_SAMM_ON = STATE_OFF;
+       } else if (!strncmp(viafb_active_dev, "LCD", 3)) {
+               /* LCD only */
+               viafb_LCD_ON = STATE_ON;
+               viafb_SAMM_ON = STATE_OFF;
+       } else {
+               viafb_CRT_ON = STATE_ON;
+               viafb_SAMM_ON = STATE_OFF;
+       }
+       viaparinfo->duoview = is_duoview();
+}
+
+static void parse_video_dev(void)
+{
+       viaparinfo->video_on_crt = STATE_OFF;
+       viaparinfo->video_on_dvi = STATE_OFF;
+       viaparinfo->video_on_lcd = STATE_OFF;
+
+       if (!strncmp(viafb_video_dev, "CRT", 3)) {
+               /* Video on CRT */
+               viaparinfo->video_on_crt = STATE_ON;
+       } else if (!strncmp(viafb_video_dev, "DVI", 3)) {
+               /* Video on DVI */
+               viaparinfo->video_on_dvi = STATE_ON;
+       } else if (!strncmp(viafb_video_dev, "LCD", 3)) {
+               /* Video on LCD */
+               viaparinfo->video_on_lcd = STATE_ON;
+       }
+}
+
+static int parse_port(char *opt_str, int *output_interface)
+{
+       if (!strncmp(opt_str, "DVP0", 4))
+               *output_interface = INTERFACE_DVP0;
+       else if (!strncmp(opt_str, "DVP1", 4))
+               *output_interface = INTERFACE_DVP1;
+       else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
+               *output_interface = INTERFACE_DFP;
+       else if (!strncmp(opt_str, "DFP_HIGH", 8))
+               *output_interface = INTERFACE_DFP_HIGH;
+       else if (!strncmp(opt_str, "DFP_LOW", 7))
+               *output_interface = INTERFACE_DFP_LOW;
+       else
+               *output_interface = INTERFACE_NONE;
+       return 0;
+}
+
+static void parse_lcd_port(void)
+{
+       parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
+               output_interface);
+       /*Initialize to avoid unexpected behavior */
+       viaparinfo->chip_info->lvds_chip_info2.output_interface =
+       INTERFACE_NONE;
+
+       DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
+                 viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
+                 output_interface);
+}
+
+static void parse_dvi_port(void)
+{
+       parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
+               output_interface);
+
+       DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
+                 viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
+                 output_interface);
+}
+
+/*
+ * The proc filesystem read/write function, a simple proc implement to
+ * get/set the value of DPA  DVP0,   DVP0DataDriving,  DVP0ClockDriving, DVP1,
+ * DVP1Driving, DFPHigh, DFPLow CR96,   SR2A[5], SR1B[1], SR2A[4], SR1E[2],
+ * CR9B,    SR65,    CR97,    CR99
+ */
+static int viafb_dvp0_proc_read(char *buf, char **start, off_t offset,
+int count, int *eof, void *data)
+{
+       int len = 0;
+       u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
+       dvp0_data_dri =
+           (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
+           (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
+       dvp0_clk_dri =
+           (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
+           (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
+       dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
+       len +=
+           sprintf(buf + len, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
+       *eof = 1;               /*Inform kernel end of data */
+       return len;
+}
+static int viafb_dvp0_proc_write(struct file *file,
+       const char __user *buffer, unsigned long count, void *data)
+{
+       char buf[20], *value, *pbuf;
+       u8 reg_val = 0;
+       unsigned long length, i;
+       if (count < 1)
+               return -EINVAL;
+       length = count > 20 ? 20 : count;
+       if (copy_from_user(&buf[0], buffer, length))
+               return -EFAULT;
+       buf[length - 1] = '\0'; /*Ensure end string */
+       pbuf = &buf[0];
+       for (i = 0; i < 3; i++) {
+               value = strsep(&pbuf, " ");
+               if (value != NULL) {
+                       strict_strtoul(value, 0, (unsigned long *)&reg_val);
+                       DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
+                                 reg_val);
+                       switch (i) {
+                       case 0:
+                               viafb_write_reg_mask(CR96, VIACR,
+                                       reg_val, 0x0f);
+                               break;
+                       case 1:
+                               viafb_write_reg_mask(SR2A, VIASR,
+                                       reg_val << 4, BIT5);
+                               viafb_write_reg_mask(SR1B, VIASR,
+                                       reg_val << 1, BIT1);
+                               break;
+                       case 2:
+                               viafb_write_reg_mask(SR2A, VIASR,
+                                       reg_val << 3, BIT4);
+                               viafb_write_reg_mask(SR1E, VIASR,
+                                       reg_val << 2, BIT2);
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       break;
+               }
+       }
+       return count;
+}
+static int viafb_dvp1_proc_read(char *buf, char **start, off_t offset,
+       int count, int *eof, void *data)
+{
+       int len = 0;
+       u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
+       dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
+       dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
+       dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
+       len +=
+           sprintf(buf + len, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
+       *eof = 1;               /*Inform kernel end of data */
+       return len;
+}
+static int viafb_dvp1_proc_write(struct file *file,
+       const char __user *buffer, unsigned long count, void *data)
+{
+       char buf[20], *value, *pbuf;
+       u8 reg_val = 0;
+       unsigned long length, i;
+       if (count < 1)
+               return -EINVAL;
+       length = count > 20 ? 20 : count;
+       if (copy_from_user(&buf[0], buffer, length))
+               return -EFAULT;
+       buf[length - 1] = '\0'; /*Ensure end string */
+       pbuf = &buf[0];
+       for (i = 0; i < 3; i++) {
+               value = strsep(&pbuf, " ");
+               if (value != NULL) {
+                       strict_strtoul(value, 0, (unsigned long *)&reg_val);
+                       switch (i) {
+                       case 0:
+                               viafb_write_reg_mask(CR9B, VIACR,
+                                       reg_val, 0x0f);
+                               break;
+                       case 1:
+                               viafb_write_reg_mask(SR65, VIASR,
+                                       reg_val << 2, 0x0c);
+                               break;
+                       case 2:
+                               viafb_write_reg_mask(SR65, VIASR,
+                                       reg_val, 0x03);
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       break;
+               }
+       }
+       return count;
+}
+
+static int viafb_dfph_proc_read(char *buf, char **start, off_t offset,
+       int count, int *eof, void *data)
+{
+       int len = 0;
+       u8 dfp_high = 0;
+       dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
+       len += sprintf(buf + len, "%x\n", dfp_high);
+       *eof = 1;               /*Inform kernel end of data */
+       return len;
+}
+static int viafb_dfph_proc_write(struct file *file,
+       const char __user *buffer, unsigned long count, void *data)
+{
+       char buf[20];
+       u8 reg_val = 0;
+       unsigned long length;
+       if (count < 1)
+               return -EINVAL;
+       length = count > 20 ? 20 : count;
+       if (copy_from_user(&buf[0], buffer, length))
+               return -EFAULT;
+       buf[length - 1] = '\0'; /*Ensure end string */
+       strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+       viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
+       return count;
+}
+static int viafb_dfpl_proc_read(char *buf, char **start, off_t offset,
+       int count, int *eof, void *data)
+{
+       int len = 0;
+       u8 dfp_low = 0;
+       dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
+       len += sprintf(buf + len, "%x\n", dfp_low);
+       *eof = 1;               /*Inform kernel end of data */
+       return len;
+}
+static int viafb_dfpl_proc_write(struct file *file,
+       const char __user *buffer, unsigned long count, void *data)
+{
+       char buf[20];
+       u8 reg_val = 0;
+       unsigned long length;
+       if (count < 1)
+               return -EINVAL;
+       length = count > 20 ? 20 : count;
+       if (copy_from_user(&buf[0], buffer, length))
+               return -EFAULT;
+       buf[length - 1] = '\0'; /*Ensure end string */
+       strict_strtoul(&buf[0], 0, (unsigned long *)&reg_val);
+       viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
+       return count;
+}
+static int viafb_vt1636_proc_read(char *buf, char **start,
+       off_t offset, int count, int *eof, void *data)
+{
+       int len = 0;
+       u8 vt1636_08 = 0, vt1636_09 = 0;
+       switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+       case VT1636_LVDS:
+               vt1636_08 =
+                   viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+                   &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
+               vt1636_09 =
+                   viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
+                   &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
+               len += sprintf(buf + len, "%x %x\n", vt1636_08, vt1636_09);
+               break;
+       default:
+               break;
+       }
+       switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+       case VT1636_LVDS:
+               vt1636_08 =
+                   viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+                       &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
+               vt1636_09 =
+                   viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
+                       &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
+               len += sprintf(buf + len, " %x %x\n", vt1636_08, vt1636_09);
+               break;
+       default:
+               break;
+       }
+       *eof = 1;               /*Inform kernel end of data */
+       return len;
+}
+static int viafb_vt1636_proc_write(struct file *file,
+       const char __user *buffer, unsigned long count, void *data)
+{
+       char buf[30], *value, *pbuf;
+       struct IODATA reg_val;
+       unsigned long length, i;
+       if (count < 1)
+               return -EINVAL;
+       length = count > 30 ? 30 : count;
+       if (copy_from_user(&buf[0], buffer, length))
+               return -EFAULT;
+       buf[length - 1] = '\0'; /*Ensure end string */
+       pbuf = &buf[0];
+       switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
+       case VT1636_LVDS:
+               for (i = 0; i < 2; i++) {
+                       value = strsep(&pbuf, " ");
+                       if (value != NULL) {
+                               strict_strtoul(value, 0,
+                                       (unsigned long *)&reg_val.Data);
+                               switch (i) {
+                               case 0:
+                                       reg_val.Index = 0x08;
+                                       reg_val.Mask = 0x0f;
+                                       viafb_gpio_i2c_write_mask_lvds
+                                           (viaparinfo->lvds_setting_info,
+                                           &viaparinfo->
+                                           chip_info->lvds_chip_info,
+                                            reg_val);
+                                       break;
+                               case 1:
+                                       reg_val.Index = 0x09;
+                                       reg_val.Mask = 0x1f;
+                                       viafb_gpio_i2c_write_mask_lvds
+                                           (viaparinfo->lvds_setting_info,
+                                           &viaparinfo->
+                                           chip_info->lvds_chip_info,
+                                            reg_val);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+       switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+       case VT1636_LVDS:
+               for (i = 0; i < 2; i++) {
+                       value = strsep(&pbuf, " ");
+                       if (value != NULL) {
+                               strict_strtoul(value, 0,
+                                       (unsigned long *)&reg_val.Data);
+                               switch (i) {
+                               case 0:
+                                       reg_val.Index = 0x08;
+                                       reg_val.Mask = 0x0f;
+                                       viafb_gpio_i2c_write_mask_lvds
+                                           (viaparinfo->lvds_setting_info2,
+                                           &viaparinfo->
+                                           chip_info->lvds_chip_info2,
+                                            reg_val);
+                                       break;
+                               case 1:
+                                       reg_val.Index = 0x09;
+                                       reg_val.Mask = 0x1f;
+                                       viafb_gpio_i2c_write_mask_lvds
+                                           (viaparinfo->lvds_setting_info2,
+                                           &viaparinfo->
+                                           chip_info->lvds_chip_info2,
+                                            reg_val);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+       return count;
+}
+
+static void viafb_init_proc(struct proc_dir_entry *viafb_entry)
+{
+       struct proc_dir_entry *entry;
+       viafb_entry = proc_mkdir("viafb", NULL);
+       if (viafb_entry) {
+               entry = create_proc_entry("dvp0", 0, viafb_entry);
+               if (entry) {
+                       entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dvp0_proc_read;
+                       entry->write_proc = viafb_dvp0_proc_write;
+               }
+               entry = create_proc_entry("dvp1", 0, viafb_entry);
+               if (entry) {
+                       entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dvp1_proc_read;
+                       entry->write_proc = viafb_dvp1_proc_write;
+               }
+               entry = create_proc_entry("dfph", 0, viafb_entry);
+               if (entry) {
+                       entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dfph_proc_read;
+                       entry->write_proc = viafb_dfph_proc_write;
+               }
+               entry = create_proc_entry("dfpl", 0, viafb_entry);
+               if (entry) {
+                       entry->owner = THIS_MODULE;
+                       entry->read_proc = viafb_dfpl_proc_read;
+                       entry->write_proc = viafb_dfpl_proc_write;
+               }
+               if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info.
+                       lvds_chip_name || VT1636_LVDS ==
+                   viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
+                       entry = create_proc_entry("vt1636", 0, viafb_entry);
+                       if (entry) {
+                               entry->owner = THIS_MODULE;
+                               entry->read_proc = viafb_vt1636_proc_read;
+                               entry->write_proc = viafb_vt1636_proc_write;
+                       }
+               }
+
+       }
+}
+static void viafb_remove_proc(struct proc_dir_entry *viafb_entry)
+{
+       /* no problem if it was not registered */
+       remove_proc_entry("dvp0", viafb_entry);/* parent dir */
+       remove_proc_entry("dvp1", viafb_entry);
+       remove_proc_entry("dfph", viafb_entry);
+       remove_proc_entry("dfpl", viafb_entry);
+       remove_proc_entry("vt1636", viafb_entry);
+       remove_proc_entry("vt1625", viafb_entry);
+}
+
+static int __devinit via_pci_probe(void)
+{
+       unsigned int default_xres, default_yres;
+       char *tmpc, *tmpm;
+       char *tmpc_sec, *tmpm_sec;
+       int vmode_index;
+       u32 tmds_length, lvds_length, crt_length, chip_length, viafb_par_length;
+
+       DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
+
+       viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
+       tmds_length = ALIGN(sizeof(struct tmds_setting_information),
+               BITS_PER_LONG/8);
+       lvds_length = ALIGN(sizeof(struct lvds_setting_information),
+               BITS_PER_LONG/8);
+       crt_length = ALIGN(sizeof(struct lvds_setting_information),
+               BITS_PER_LONG/8);
+       chip_length = ALIGN(sizeof(struct chip_information), BITS_PER_LONG/8);
+
+       /* Allocate fb_info and ***_par here, also including some other needed
+        * variables
+       */
+       viafbinfo = framebuffer_alloc(viafb_par_length + 2 * lvds_length +
+       tmds_length + crt_length + chip_length, NULL);
+       if (!viafbinfo) {
+               printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
+               return -ENODEV;
+       }
+
+       viaparinfo = (struct viafb_par *)viafbinfo->par;
+       viaparinfo->tmds_setting_info = (struct tmds_setting_information *)
+               ((unsigned long)viaparinfo + viafb_par_length);
+       viaparinfo->lvds_setting_info = (struct lvds_setting_information *)
+               ((unsigned long)viaparinfo->tmds_setting_info + tmds_length);
+       viaparinfo->lvds_setting_info2 = (struct lvds_setting_information *)
+               ((unsigned long)viaparinfo->lvds_setting_info + lvds_length);
+       viaparinfo->crt_setting_info = (struct crt_setting_information *)
+               ((unsigned long)viaparinfo->lvds_setting_info2 + lvds_length);
+       viaparinfo->chip_info = (struct chip_information *)
+               ((unsigned long)viaparinfo->crt_setting_info + crt_length);
+
+       if (viafb_dual_fb)
+               viafb_SAMM_ON = 1;
+       parse_active_dev();
+       parse_video_dev();
+       parse_lcd_port();
+       parse_dvi_port();
+
+       /* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */
+       if (!viafb_SAMM_ON)
+               viafb_dual_fb = 0;
+
+       /* Set up I2C bus stuff */
+       viafb_create_i2c_bus(viaparinfo);
+
+       viafb_init_chip_info();
+       viafb_get_fb_info(&viaparinfo->fbmem, &viaparinfo->memsize);
+       viaparinfo->fbmem_free = viaparinfo->memsize;
+       viaparinfo->fbmem_used = 0;
+       viaparinfo->fbmem_virt = ioremap_nocache(viaparinfo->fbmem,
+               viaparinfo->memsize);
+       viafbinfo->screen_base = (char *)viaparinfo->fbmem_virt;
+
+       if (!viaparinfo->fbmem_virt) {
+               printk(KERN_INFO "ioremap failed\n");
+               return -1;
+       }
+
+       viafb_get_mmio_info(&viaparinfo->mmio_base, &viaparinfo->mmio_len);
+       viaparinfo->io_virt = ioremap_nocache(viaparinfo->mmio_base,
+               viaparinfo->mmio_len);
+
+       viafbinfo->node = 0;
+       viafbinfo->fbops = &viafb_ops;
+       viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+       viafbinfo->pseudo_palette = pseudo_pal;
+       if (viafb_accel) {
+               viafb_init_accel();
+               viafb_init_2d_engine();
+               viafb_hw_cursor_init();
+       }
+
+       if (viafb_second_size && (viafb_second_size < 8)) {
+               viafb_second_offset = viaparinfo->fbmem_free -
+                       viafb_second_size * 1024 * 1024;
+       } else {
+               viafb_second_size = 8;
+               viafb_second_offset = viaparinfo->fbmem_free -
+                       viafb_second_size * 1024 * 1024;
+       }
+
+       viafb_FB_MM = viaparinfo->fbmem_virt;
+       tmpm = viafb_mode;
+       tmpc = strsep(&tmpm, "x");
+       strict_strtoul(tmpc, 0, (unsigned long *)&default_xres);
+       strict_strtoul(tmpm, 0, (unsigned long *)&default_yres);
+
+       vmode_index = viafb_get_mode_index(default_xres, default_yres, 0);
+       DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
+
+       if (viafb_SAMM_ON == 1) {
+               if (strcmp(viafb_mode, viafb_mode1)) {
+                       tmpm_sec = viafb_mode1;
+                       tmpc_sec = strsep(&tmpm_sec, "x");
+                       strict_strtoul(tmpc_sec, 0,
+                               (unsigned long *)&viafb_second_xres);
+                       strict_strtoul(tmpm_sec, 0,
+                               (unsigned long *)&viafb_second_yres);
+               } else {
+                       viafb_second_xres = default_xres;
+                       viafb_second_yres = default_yres;
+               }
+               if (0 == viafb_second_virtual_xres) {
+                       switch (viafb_second_xres) {
+                       case 1400:
+                               viafb_second_virtual_xres = 1408;
+                               break;
+                       default:
+                               viafb_second_virtual_xres = viafb_second_xres;
+                               break;
+                       }
+               }
+               if (0 == viafb_second_virtual_yres)
+                       viafb_second_virtual_yres = viafb_second_yres;
+       }
+
+       switch (viafb_bpp) {
+       case 0 ... 8:
+               viafb_bpp = 8;
+               break;
+       case 9 ... 16:
+               viafb_bpp = 16;
+               break;
+       case 17 ... 32:
+               viafb_bpp = 32;
+               break;
+       default:
+               viafb_bpp = 8;
+       }
+       default_var.xres = default_xres;
+       default_var.yres = default_yres;
+       switch (default_xres) {
+       case 1400:
+               default_var.xres_virtual = 1408;
+               break;
+       default:
+               default_var.xres_virtual = default_xres;
+               break;
+       }
+       default_var.yres_virtual = default_yres;
+       default_var.bits_per_pixel = viafb_bpp;
+       if (default_var.bits_per_pixel == 15)
+               default_var.bits_per_pixel = 16;
+       default_var.pixclock =
+           viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
+       default_var.left_margin = (default_xres >> 3) & 0xf8;
+       default_var.right_margin = 32;
+       default_var.upper_margin = 16;
+       default_var.lower_margin = 4;
+       default_var.hsync_len = default_var.left_margin;
+       default_var.vsync_len = 4;
+       default_var.accel_flags = 0;
+
+       if (viafb_accel) {
+               viafbinfo->flags |=
+                   (FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+                    FBINFO_HWACCEL_IMAGEBLIT);
+               default_var.accel_flags |= FB_ACCELF_TEXT;
+       } else
+               viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
+
+       if (viafb_dual_fb) {
+               viafbinfo1 = framebuffer_alloc(viafb_par_length, NULL);
+               if (!viafbinfo1) {
+                       printk(KERN_ERR
+                       "allocate the second framebuffer struct error\n");
+                       framebuffer_release(viafbinfo);
+                       return -ENOMEM;
+               }
+               viaparinfo1 = viafbinfo1->par;
+               memcpy(viaparinfo1, viaparinfo, viafb_par_length);
+               viaparinfo1->memsize = viaparinfo->memsize -
+                       viafb_second_offset;
+               viaparinfo->memsize = viafb_second_offset;
+               viaparinfo1->fbmem_virt = viaparinfo->fbmem_virt +
+                       viafb_second_offset;
+               viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
+
+               viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
+               viaparinfo1->fbmem_free = viaparinfo1->memsize -
+                       viaparinfo1->fbmem_used;
+               viaparinfo->fbmem_free = viaparinfo->memsize;
+               viaparinfo->fbmem_used = 0;
+               if (viafb_accel) {
+                       viaparinfo1->cursor_start =
+                           viaparinfo->cursor_start - viafb_second_offset;
+                       viaparinfo1->VQ_start = viaparinfo->VQ_start -
+                               viafb_second_offset;
+                       viaparinfo1->VQ_end = viaparinfo->VQ_end -
+                               viafb_second_offset;
+               }
+
+               memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
+               viafbinfo1->screen_base = viafbinfo->screen_base +
+                       viafb_second_offset;
+               viafbinfo1->fix.smem_start = viaparinfo1->fbmem;
+               viafbinfo1->fix.smem_len = viaparinfo1->fbmem_free;
+
+               default_var.xres = viafb_second_xres;
+               default_var.yres = viafb_second_yres;
+               default_var.xres_virtual = viafb_second_virtual_xres;
+               default_var.yres_virtual = viafb_second_virtual_yres;
+               if (viafb_bpp1 != viafb_bpp)
+                       viafb_bpp1 = viafb_bpp;
+               default_var.bits_per_pixel = viafb_bpp1;
+               default_var.pixclock =
+                   viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
+                   viafb_refresh);
+               default_var.left_margin = (viafb_second_xres >> 3) & 0xf8;
+               default_var.right_margin = 32;
+               default_var.upper_margin = 16;
+               default_var.lower_margin = 4;
+               default_var.hsync_len = default_var.left_margin;
+               default_var.vsync_len = 4;
+
+               viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
+               viafb_check_var(&default_var, viafbinfo1);
+               viafbinfo1->var = default_var;
+               viafb_update_viafb_par(viafbinfo);
+               viafb_update_fix(&viafbinfo1->fix, viafbinfo1);
+       }
+
+       viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
+       viafb_check_var(&default_var, viafbinfo);
+       viafbinfo->var = default_var;
+       viafb_update_viafb_par(viafbinfo);
+       viafb_update_fix(&viafbinfo->fix, viafbinfo);
+       default_var.activate = FB_ACTIVATE_NOW;
+       fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
+
+       if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
+           && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
+               if (register_framebuffer(viafbinfo1) < 0)
+                       return -EINVAL;
+       }
+       if (register_framebuffer(viafbinfo) < 0)
+               return -EINVAL;
+
+       if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
+                       || (viaparinfo->chip_info->gfx_chip_name !=
+                       UNICHROME_CLE266))) {
+               if (register_framebuffer(viafbinfo1) < 0)
+                       return -EINVAL;
+       }
+       DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
+                 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
+                 default_var.yres, default_var.bits_per_pixel);
+
+       viafb_init_proc(viaparinfo->proc_entry);
+       viafb_init_dac(IGA2);
+       return 0;
+}
+
+static void __devexit via_pci_remove(void)
+{
+       DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
+       fb_dealloc_cmap(&viafbinfo->cmap);
+       unregister_framebuffer(viafbinfo);
+       if (viafb_dual_fb)
+               unregister_framebuffer(viafbinfo1);
+       iounmap((void *)viaparinfo->fbmem_virt);
+       iounmap(viaparinfo->io_virt);
+
+       viafb_delete_i2c_buss(viaparinfo);
+
+       framebuffer_release(viafbinfo);
+       if (viafb_dual_fb)
+               framebuffer_release(viafbinfo1);
+
+       viafb_remove_proc(viaparinfo->proc_entry);
+}
+
+#ifndef MODULE
+static int __init viafb_setup(char *options)
+{
+       char *this_opt;
+       DEBUG_MSG(KERN_INFO "viafb_setup!\n");
+
+       if (!options || !*options)
+               return 0;
+
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               if (!*this_opt)
+                       continue;
+
+               if (!strncmp(this_opt, "viafb_mode1=", 12))
+                       viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
+               else if (!strncmp(this_opt, "viafb_mode=", 11))
+                       viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
+               else if (!strncmp(this_opt, "viafb_bpp1=", 11))
+                       strict_strtoul(this_opt + 11, 0,
+                               (unsigned long *)&viafb_bpp1);
+               else if (!strncmp(this_opt, "viafb_bpp=", 10))
+                       strict_strtoul(this_opt + 10, 0,
+                               (unsigned long *)&viafb_bpp);
+               else if (!strncmp(this_opt, "viafb_refresh1=", 15))
+                       strict_strtoul(this_opt + 15, 0,
+                               (unsigned long *)&viafb_refresh1);
+               else if (!strncmp(this_opt, "viafb_refresh=", 14))
+                       strict_strtoul(this_opt + 14, 0,
+                               (unsigned long *)&viafb_refresh);
+               else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21))
+                       strict_strtoul(this_opt + 21, 0,
+                               (unsigned long *)&viafb_lcd_dsp_method);
+               else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19))
+                       strict_strtoul(this_opt + 19, 0,
+                               (unsigned long *)&viafb_lcd_panel_id);
+               else if (!strncmp(this_opt, "viafb_accel=", 12))
+                       strict_strtoul(this_opt + 12, 0,
+                               (unsigned long *)&viafb_accel);
+               else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14))
+                       strict_strtoul(this_opt + 14, 0,
+                               (unsigned long *)&viafb_SAMM_ON);
+               else if (!strncmp(this_opt, "viafb_active_dev=", 17))
+                       viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
+               else if (!strncmp(this_opt,
+                       "viafb_display_hardware_layout=", 30))
+                       strict_strtoul(this_opt + 30, 0,
+                       (unsigned long *)&viafb_display_hardware_layout);
+               else if (!strncmp(this_opt, "viafb_second_size=", 18))
+                       strict_strtoul(this_opt + 18, 0,
+                               (unsigned long *)&viafb_second_size);
+               else if (!strncmp(this_opt,
+                       "viafb_platform_epia_dvi=", 24))
+                       strict_strtoul(this_opt + 24, 0,
+                               (unsigned long *)&viafb_platform_epia_dvi);
+               else if (!strncmp(this_opt,
+                       "viafb_device_lcd_dualedge=", 26))
+                       strict_strtoul(this_opt + 26, 0,
+                               (unsigned long *)&viafb_device_lcd_dualedge);
+               else if (!strncmp(this_opt, "viafb_bus_width=", 16))
+                       strict_strtoul(this_opt + 16, 0,
+                               (unsigned long *)&viafb_bus_width);
+               else if (!strncmp(this_opt, "viafb_lcd_mode=", 15))
+                       strict_strtoul(this_opt + 15, 0,
+                               (unsigned long *)&viafb_lcd_mode);
+               else if (!strncmp(this_opt, "viafb_video_dev=", 16))
+                       viafb_video_dev = kstrdup(this_opt + 16, GFP_KERNEL);
+               else if (!strncmp(this_opt, "viafb_lcd_port=", 15))
+                       viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
+               else if (!strncmp(this_opt, "viafb_dvi_port=", 15))
+                       viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
+       }
+       return 0;
+}
+#endif
+
+static int __init viafb_init(void)
+{
+#ifndef MODULE
+       char *option = NULL;
+       if (fb_get_options("viafb", &option))
+               return -ENODEV;
+       viafb_setup(option);
+#endif
+       printk(KERN_INFO
+       "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
+              VERSION_MAJOR, VERSION_MINOR);
+       return via_pci_probe();
+}
+
+static void __exit viafb_exit(void)
+{
+       DEBUG_MSG(KERN_INFO "viafb_exit!\n");
+       via_pci_remove();
+}
+
+static struct fb_ops viafb_ops = {
+       .owner = THIS_MODULE,
+       .fb_open = viafb_open,
+       .fb_release = viafb_release,
+       .fb_check_var = viafb_check_var,
+       .fb_set_par = viafb_set_par,
+       .fb_setcolreg = viafb_setcolreg,
+       .fb_pan_display = viafb_pan_display,
+       .fb_blank = viafb_blank,
+       .fb_fillrect = viafb_fillrect,
+       .fb_copyarea = viafb_copyarea,
+       .fb_imageblit = viafb_imageblit,
+       .fb_cursor = viafb_cursor,
+       .fb_ioctl = viafb_ioctl,
+       .fb_sync = viafb_sync,
+       .fb_setcmap = viafb_setcmap,
+};
+
+module_init(viafb_init);
+module_exit(viafb_exit);
+
+#ifdef MODULE
+module_param(viafb_memsize, int, 0);
+
+module_param(viafb_mode, charp, 0);
+MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
+
+module_param(viafb_mode1, charp, 0);
+MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
+
+module_param(viafb_bpp, int, 0);
+MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
+
+module_param(viafb_bpp1, int, 0);
+MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
+
+module_param(viafb_refresh, int, 0);
+MODULE_PARM_DESC(viafb_refresh,
+       "Set CRT viafb_refresh rate (default = 60)");
+
+module_param(viafb_refresh1, int, 0);
+MODULE_PARM_DESC(viafb_refresh1,
+       "Set CRT refresh rate (default = 60)");
+
+module_param(viafb_lcd_panel_id, int, 0);
+MODULE_PARM_DESC(viafb_lcd_panel_id,
+       "Set Flat Panel type(Default=1024x768)");
+
+module_param(viafb_lcd_dsp_method, int, 0);
+MODULE_PARM_DESC(viafb_lcd_dsp_method,
+       "Set Flat Panel display scaling method.(Default=Expandsion)");
+
+module_param(viafb_SAMM_ON, int, 0);
+MODULE_PARM_DESC(viafb_SAMM_ON,
+       "Turn on/off flag of SAMM(Default=OFF)");
+
+module_param(viafb_accel, int, 0);
+MODULE_PARM_DESC(viafb_accel,
+       "Set 2D Hardware Acceleration.(Default = OFF)");
+
+module_param(viafb_active_dev, charp, 0);
+MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
+
+module_param(viafb_display_hardware_layout, int, 0);
+MODULE_PARM_DESC(viafb_display_hardware_layout,
+       "Display Hardware Layout (LCD Only, DVI Only...,etc)");
+
+module_param(viafb_second_size, int, 0);
+MODULE_PARM_DESC(viafb_second_size,
+       "Set secondary device memory size");
+
+module_param(viafb_dual_fb, int, 0);
+MODULE_PARM_DESC(viafb_dual_fb,
+       "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
+
+module_param(viafb_platform_epia_dvi, int, 0);
+MODULE_PARM_DESC(viafb_platform_epia_dvi,
+       "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
+
+module_param(viafb_device_lcd_dualedge, int, 0);
+MODULE_PARM_DESC(viafb_device_lcd_dualedge,
+       "Turn on/off flag of dual edge panel.(Default = OFF)");
+
+module_param(viafb_bus_width, int, 0);
+MODULE_PARM_DESC(viafb_bus_width,
+       "Set bus width of panel.(Default = 12)");
+
+module_param(viafb_lcd_mode, int, 0);
+MODULE_PARM_DESC(viafb_lcd_mode,
+       "Set Flat Panel mode(Default=OPENLDI)");
+
+module_param(viafb_video_dev, charp, 0);
+MODULE_PARM_DESC(viafb_video_dev, "Specify video devices.");
+
+module_param(viafb_lcd_port, charp, 0);
+MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
+
+module_param(viafb_dvi_port, charp, 0);
+MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
+
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
new file mode 100644 (file)
index 0000000..a4158e8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __VIAFBDEV_H__
+#define __VIAFBDEV_H__
+
+#include <linux/proc_fs.h>
+#include <linux/fb.h>
+
+#include "ioctl.h"
+#include "share.h"
+#include "chip.h"
+#include "hw.h"
+#include "via_i2c.h"
+
+#define VERSION_MAJOR       2
+#define VERSION_KERNEL      6  /* For kernel 2.6 */
+
+#define VERSION_OS          0  /* 0: for 32 bits OS, 1: for 64 bits OS */
+#define VERSION_MINOR       4
+
+struct viafb_par {
+       int bpp;
+       int hres;
+       int vres;
+       int linelength;
+       u32 xoffset;
+       u32 yoffset;
+
+       void __iomem *fbmem_virt;       /*framebuffer virtual memory address */
+       void __iomem *io_virt;  /*iospace virtual memory address */
+       unsigned int fbmem;     /*framebuffer physical memory address */
+       unsigned int memsize;   /*size of fbmem */
+       unsigned int io;        /*io space address */
+       unsigned long mmio_base;        /*mmio base address */
+       unsigned long mmio_len; /*mmio base length */
+       u32 fbmem_free;         /* Free FB memory */
+       u32 fbmem_used;         /* Use FB memory size */
+       u32 cursor_start;       /* Cursor Start Address */
+       u32 VQ_start;           /* Virtual Queue Start Address */
+       u32 VQ_end;             /* Virtual Queue End Address */
+       u32 iga_path;
+       struct proc_dir_entry *proc_entry;      /*viafb proc entry */
+       u8 duoview;             /*Is working in duoview mode? */
+
+       /* I2C stuff */
+       struct via_i2c_stuff i2c_stuff;
+
+       /* All the information will be needed to set engine */
+       struct tmds_setting_information *tmds_setting_info;
+       struct crt_setting_information *crt_setting_info;
+       struct lvds_setting_information *lvds_setting_info;
+       struct lvds_setting_information *lvds_setting_info2;
+       struct chip_information *chip_info;
+
+       /* some information related to video playing */
+       int video_on_crt;
+       int video_on_dvi;
+       int video_on_lcd;
+
+};
+struct viafb_modeinfo {
+       u32 xres;
+       u32 yres;
+       int mode_index;
+       char *mode_res;
+};
+extern unsigned int viafb_second_virtual_yres;
+extern unsigned int viafb_second_virtual_xres;
+extern unsigned int viafb_second_offset;
+extern int viafb_second_size;
+extern int viafb_SAMM_ON;
+extern int viafb_dual_fb;
+extern int viafb_LCD2_ON;
+extern int viafb_LCD_ON;
+extern int viafb_DVI_ON;
+extern int viafb_accel;
+extern int viafb_hotplug;
+extern int viafb_memsize;
+
+extern int strict_strtoul(const char *cp, unsigned int base,
+       unsigned long *res);
+
+void viafb_memory_pitch_patch(struct fb_info *info);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
+                         int mode_index);
+int viafb_get_mode_index(int hres, int vres, int flag);
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information
+       *plvds_chip_info, u8 index);
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+                             *plvds_setting_info, struct lvds_chip_information
+                             *plvds_chip_info, struct IODATA io_data);
+#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
new file mode 100644 (file)
index 0000000..6dcf583
--- /dev/null
@@ -0,0 +1,1086 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+struct res_map_refresh res_map_refresh_tbl[] = {
+/*hres, vres, vclock, vmode_refresh*/
+       {480, 640, RES_480X640_60HZ_PIXCLOCK, 60},
+       {640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
+       {640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
+       {640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
+       {640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
+       {640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
+       {720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
+       {720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
+       {800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
+       {800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
+       {800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
+       {800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
+       {800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
+       {800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
+       {848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
+       {856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
+       {1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60},
+       {1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60},
+       {1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60},
+       {1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75},
+       {1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85},
+       {1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100},
+/*  {1152,864, RES_1152X864_70HZ_PIXCLOCK,  70},*/
+       {1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75},
+       {1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60},
+       {1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60},
+       {1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60},
+       {1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60},
+       {1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75},
+       {1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85},
+       {1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60},
+       {1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60},
+       {1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75},
+       {1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60},
+       {1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60},
+       {1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60},
+       {1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75},
+       {1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60},
+       {960, 600, RES_960X600_60HZ_PIXCLOCK, 60},
+       {1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60},
+       {1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60},
+       {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
+       {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
+       {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
+       {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
+       {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
+       {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
+       {1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60},
+       {1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50},
+       {1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60},
+       {1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60},
+       {1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75},
+       {1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60},
+       {1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60},
+       {1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60},
+       {1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75},
+       {1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60},
+       {1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60},
+       {1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60},
+       {1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60},
+       {1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75},
+       {2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60}
+};
+
+struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1E, 0x0F, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIACR, CR0A, 0xFF, 0x1E},     /* Cursor Start                        */
+{VIACR, CR0B, 0xFF, 0x00},     /* Cursor End                          */
+{VIACR, CR0E, 0xFF, 0x00},     /* Cursor Location High                */
+{VIACR, CR0F, 0xFF, 0x00},     /* Cursor Localtion Low                */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR62, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR63, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR64, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01},     /* LCD Scaling Parameter 1             */
+{VIACR, CR7B, 0xFF, 0x02},     /* LCD Scaling Parameter 2             */
+{VIACR, CR7C, 0xFF, 0x03},     /* LCD Scaling Parameter 3             */
+{VIACR, CR7D, 0xFF, 0x04},     /* LCD Scaling Parameter 4             */
+{VIACR, CR7E, 0xFF, 0x07},     /* LCD Scaling Parameter 5             */
+{VIACR, CR7F, 0xFF, 0x0A},     /* LCD Scaling Parameter 6             */
+{VIACR, CR80, 0xFF, 0x0D},     /* LCD Scaling Parameter 7             */
+{VIACR, CR81, 0xFF, 0x13},     /* LCD Scaling Parameter 8             */
+{VIACR, CR82, 0xFF, 0x16},     /* LCD Scaling Parameter 9             */
+{VIACR, CR83, 0xFF, 0x19},     /* LCD Scaling Parameter 10            */
+{VIACR, CR84, 0xFF, 0x1C},     /* LCD Scaling Parameter 11            */
+{VIACR, CR85, 0xFF, 0x1D},     /* LCD Scaling Parameter 12            */
+{VIACR, CR86, 0xFF, 0x1E},     /* LCD Scaling Parameter 13            */
+{VIACR, CR87, 0xFF, 0x1F},     /* LCD Scaling Parameter 14            */
+{VIACR, CR88, 0xFF, 0x40},     /* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},     /* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},     /* LCD Timing Control 1                */
+{VIACR, CR8B, 0xFF, 0x69},     /* LCD Power Sequence Control 0        */
+{VIACR, CR8C, 0xFF, 0x57},     /* LCD Power Sequence Control 1        */
+{VIACR, CR8D, 0xFF, 0x00},     /* LCD Power Sequence Control 2        */
+{VIACR, CR8E, 0xFF, 0x7B},     /* LCD Power Sequence Control 3        */
+{VIACR, CR8F, 0xFF, 0x03},     /* LCD Power Sequence Control 4        */
+{VIACR, CR90, 0xFF, 0x30},     /* LCD Power Sequence Control 5        */
+{VIACR, CR91, 0xFF, 0xA0},     /* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00}
+};
+
+/* Video Mode Table for VT3314 chipset*/
+/* Common Setting for Video Mode */
+struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x82},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1F, 0xFF, 0x00},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR22, 0xFF, 0x1F},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR2E, 0xFF, 0xFF},
+{VIASR, SR3F, 0xFF, 0xFF},
+{VIASR, SR40, 0xF7, 0x00},
+{VIASR, CR30, 0xFF, 0x04},
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0x7F, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0xFF, 0x31},
+{VIACR, CR41, 0xFF, 0x80},
+{VIACR, CR42, 0xFF, 0x00},
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00},     /*Horizontal Retrace Start bit[11] should be 0*/
+{VIACR, CR62, 0xFF, 0x00},     /* Secondary Display Starting Address */
+{VIACR, CR63, 0xFF, 0x00},     /* Secondary Display Starting Address */
+{VIACR, CR64, 0xFF, 0x00},     /* Secondary Display Starting Address */
+{VIACR, CR68, 0xFF, 0x67},     /* Default FIFO For IGA2 */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFD, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR77, 0xFF, 0x00},     /* LCD scaling Factor */
+{VIACR, CR78, 0xFF, 0x00},     /* LCD scaling Factor */
+{VIACR, CR79, 0xFF, 0x00},     /* LCD scaling Factor */
+{VIACR, CR9F, 0x03, 0x00},     /* LCD scaling Factor */
+{VIACR, CR7A, 0xFF, 0x01},     /* LCD Scaling Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02},     /* LCD Scaling Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03},     /* LCD Scaling Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04},     /* LCD Scaling Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07},     /* LCD Scaling Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A},     /* LCD Scaling Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D},     /* LCD Scaling Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13},     /* LCD Scaling Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16},     /* LCD Scaling Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19},     /* LCD Scaling Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C},     /* LCD Scaling Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D},     /* LCD Scaling Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E},     /* LCD Scaling Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F},     /* LCD Scaling Parameter 14 */
+{VIACR, CR88, 0xFF, 0x40},     /* LCD Panel Type */
+{VIACR, CR89, 0xFF, 0x00},     /* LCD Timing Control 0 */
+{VIACR, CR8A, 0xFF, 0x88},     /* LCD Timing Control 1 */
+{VIACR, CR8B, 0xFF, 0x5D},     /* LCD Power Sequence Control 0 */
+{VIACR, CR8C, 0xFF, 0x2B},     /* LCD Power Sequence Control 1 */
+{VIACR, CR8D, 0xFF, 0x6F},     /* LCD Power Sequence Control 2 */
+{VIACR, CR8E, 0xFF, 0x2B},     /* LCD Power Sequence Control 3 */
+{VIACR, CR8F, 0xFF, 0x01},     /* LCD Power Sequence Control 4 */
+{VIACR, CR90, 0xFF, 0x01},     /* LCD Power Sequence Control 5 */
+{VIACR, CR91, 0xFF, 0xA0},     /* 24/12 bit LVDS Data off */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CR9D, 0xFF, 0x80},
+{VIACR, CR9E, 0xFF, 0x80}
+};
+
+struct io_reg KM400_ModeXregs[] = {
+       {VIASR, SR10, 0xFF, 0x01},      /* Unlock Register                 */
+       {VIASR, SR16, 0xFF, 0x08},      /* Display FIFO threshold Control  */
+       {VIASR, SR17, 0xFF, 0x1F},      /* Display FIFO Control            */
+       {VIASR, SR18, 0xFF, 0x4E},      /* GFX PREQ threshold              */
+       {VIASR, SR1A, 0xFF, 0x0a},      /* GFX PREQ threshold              */
+       {VIASR, SR1F, 0xFF, 0x00},      /* Memory Control 0                */
+       {VIASR, SR1B, 0xFF, 0xF0},      /* Power Management Control 0      */
+       {VIASR, SR1E, 0xFF, 0x01},      /* Power Management Control        */
+       {VIASR, SR20, 0xFF, 0x00},      /* Sequencer Arbiter Control 0     */
+       {VIASR, SR21, 0xFF, 0x00},      /* Sequencer Arbiter Control 1     */
+       {VIASR, SR22, 0xFF, 0x1F},      /* Display Arbiter Control 1       */
+       {VIASR, SR2A, 0xFF, 0x00},      /* Power Management Control 5      */
+       {VIASR, SR2D, 0xFF, 0xFF},      /* Power Management Control 1      */
+       {VIASR, SR2E, 0xFF, 0xFF},      /* Power Management Control 2      */
+       {VIACR, CR0A, 0xFF, 0x1E},      /* Cursor Start                    */
+       {VIACR, CR0B, 0xFF, 0x00},      /* Cursor End                      */
+       {VIACR, CR0E, 0xFF, 0x00},      /* Cursor Location High            */
+       {VIACR, CR0F, 0xFF, 0x00},      /* Cursor Localtion Low            */
+       {VIACR, CR33, 0xFF, 0x00},
+       {VIACR, CR55, 0x80, 0x00},
+       {VIACR, CR5D, 0x80, 0x00},
+       {VIACR, CR36, 0xFF, 0x01},      /* Power Mangement 3                  */
+       {VIACR, CR62, 0xFF, 0x00},      /* Secondary Display Starting Address */
+       {VIACR, CR63, 0xFF, 0x00},      /* Secondary Display Starting Address */
+       {VIACR, CR64, 0xFF, 0x00},      /* Secondary Display Starting Address */
+       {VIACR, CR68, 0xFF, 0x67},      /* Default FIFO For IGA2              */
+       {VIACR, CR6A, 0x20, 0x20},      /* Extended FIFO On                   */
+       {VIACR, CR7A, 0xFF, 0x01},      /* LCD Scaling Parameter 1            */
+       {VIACR, CR7B, 0xFF, 0x02},      /* LCD Scaling Parameter 2            */
+       {VIACR, CR7C, 0xFF, 0x03},      /* LCD Scaling Parameter 3            */
+       {VIACR, CR7D, 0xFF, 0x04},      /* LCD Scaling Parameter 4            */
+       {VIACR, CR7E, 0xFF, 0x07},      /* LCD Scaling Parameter 5            */
+       {VIACR, CR7F, 0xFF, 0x0A},      /* LCD Scaling Parameter 6            */
+       {VIACR, CR80, 0xFF, 0x0D},      /* LCD Scaling Parameter 7            */
+       {VIACR, CR81, 0xFF, 0x13},      /* LCD Scaling Parameter 8            */
+       {VIACR, CR82, 0xFF, 0x16},      /* LCD Scaling Parameter 9            */
+       {VIACR, CR83, 0xFF, 0x19},      /* LCD Scaling Parameter 10           */
+       {VIACR, CR84, 0xFF, 0x1C},      /* LCD Scaling Parameter 11           */
+       {VIACR, CR85, 0xFF, 0x1D},      /* LCD Scaling Parameter 12           */
+       {VIACR, CR86, 0xFF, 0x1E},      /* LCD Scaling Parameter 13           */
+       {VIACR, CR87, 0xFF, 0x1F},      /* LCD Scaling Parameter 14           */
+       {VIACR, CR88, 0xFF, 0x40},      /* LCD Panel Type                     */
+       {VIACR, CR89, 0xFF, 0x00},      /* LCD Timing Control 0               */
+       {VIACR, CR8A, 0xFF, 0x88},      /* LCD Timing Control 1               */
+       {VIACR, CR8B, 0xFF, 0x2D},      /* LCD Power Sequence Control 0       */
+       {VIACR, CR8C, 0xFF, 0x2D},      /* LCD Power Sequence Control 1       */
+       {VIACR, CR8D, 0xFF, 0xC8},      /* LCD Power Sequence Control 2       */
+       {VIACR, CR8E, 0xFF, 0x36},      /* LCD Power Sequence Control 3       */
+       {VIACR, CR8F, 0xFF, 0x00},      /* LCD Power Sequence Control 4       */
+       {VIACR, CR90, 0xFF, 0x10},      /* LCD Power Sequence Control 5       */
+       {VIACR, CR91, 0xFF, 0xA0},      /* 24/12 bit LVDS Data off            */
+       {VIACR, CR96, 0xFF, 0x03},      /* DVP0        ; DVP0 Clock Skew */
+       {VIACR, CR97, 0xFF, 0x03},      /* DFP high    ; DFPH Clock Skew */
+       {VIACR, CR99, 0xFF, 0x03},      /* DFP low           ; DFPL Clock Skew*/
+       {VIACR, CR9B, 0xFF, 0x07}       /* DVI on DVP1       ; DVP1 Clock Skew*/
+};
+
+/* For VT3324: Common Setting for Video Mode */
+struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIASR, SR2D, 0xFF, 0xFF},     /* VCK and LCK PLL power on.           */
+{VIACR, CR0A, 0xFF, 0x1E},     /* Cursor Start                        */
+{VIACR, CR0B, 0xFF, 0x00},     /* Cursor End                          */
+{VIACR, CR0E, 0xFF, 0x00},     /* Cursor Location High                */
+{VIACR, CR0F, 0xFF, 0x00},     /* Cursor Localtion Low                */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR47, 0xC8, 0x00},     /* Clear VCK Plus. */
+{VIACR, CR62, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR63, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR64, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CRA3, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01},     /* LCD Scaling Parameter 1             */
+{VIACR, CR7B, 0xFF, 0x02},     /* LCD Scaling Parameter 2             */
+{VIACR, CR7C, 0xFF, 0x03},     /* LCD Scaling Parameter 3             */
+{VIACR, CR7D, 0xFF, 0x04},     /* LCD Scaling Parameter 4             */
+{VIACR, CR7E, 0xFF, 0x07},     /* LCD Scaling Parameter 5             */
+{VIACR, CR7F, 0xFF, 0x0A},     /* LCD Scaling Parameter 6             */
+{VIACR, CR80, 0xFF, 0x0D},     /* LCD Scaling Parameter 7             */
+{VIACR, CR81, 0xFF, 0x13},     /* LCD Scaling Parameter 8             */
+{VIACR, CR82, 0xFF, 0x16},     /* LCD Scaling Parameter 9             */
+{VIACR, CR83, 0xFF, 0x19},     /* LCD Scaling Parameter 10            */
+{VIACR, CR84, 0xFF, 0x1C},     /* LCD Scaling Parameter 11            */
+{VIACR, CR85, 0xFF, 0x1D},     /* LCD Scaling Parameter 12            */
+{VIACR, CR86, 0xFF, 0x1E},     /* LCD Scaling Parameter 13            */
+{VIACR, CR87, 0xFF, 0x1F},     /* LCD Scaling Parameter 14            */
+{VIACR, CR88, 0xFF, 0x40},     /* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},     /* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},     /* LCD Timing Control 1                */
+{VIACR, CRD4, 0xFF, 0x81},     /* Second power sequence control       */
+{VIACR, CR8B, 0xFF, 0x5D},     /* LCD Power Sequence Control 0        */
+{VIACR, CR8C, 0xFF, 0x2B},     /* LCD Power Sequence Control 1        */
+{VIACR, CR8D, 0xFF, 0x6F},     /* LCD Power Sequence Control 2        */
+{VIACR, CR8E, 0xFF, 0x2B},     /* LCD Power Sequence Control 3        */
+{VIACR, CR8F, 0xFF, 0x01},     /* LCD Power Sequence Control 4        */
+{VIACR, CR90, 0xFF, 0x01},     /* LCD Power Sequence Control 5        */
+{VIACR, CR91, 0xFF, 0x80},     /* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CRD2, 0xFF, 0xFF}      /* TMDS/LVDS control register.         */
+};
+
+/* For VT3353: Common Setting for Video Mode */
+struct io_reg VX800_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+{VIASR, SR1B, 0xFF, 0xF0},
+{VIASR, SR1E, 0xFF, 0x01},
+{VIASR, SR2A, 0xFF, 0x00},
+{VIASR, SR2D, 0xFF, 0xFF},     /* VCK and LCK PLL power on.           */
+{VIACR, CR0A, 0xFF, 0x1E},     /* Cursor Start                        */
+{VIACR, CR0B, 0xFF, 0x00},     /* Cursor End                          */
+{VIACR, CR0E, 0xFF, 0x00},     /* Cursor Location High                */
+{VIACR, CR0F, 0xFF, 0x00},     /* Cursor Localtion Low                */
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR33, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR47, 0xC8, 0x00},     /* Clear VCK Plus. */
+{VIACR, CR62, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR63, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR64, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CRA3, 0xFF, 0x00},     /* Secondary Display Starting Address  */
+{VIACR, CR69, 0xFF, 0x00},
+{VIACR, CR6A, 0xFF, 0x40},
+{VIACR, CR6B, 0xFF, 0x00},
+{VIACR, CR6C, 0xFF, 0x00},
+{VIACR, CR7A, 0xFF, 0x01},     /* LCD Scaling Parameter 1             */
+{VIACR, CR7B, 0xFF, 0x02},     /* LCD Scaling Parameter 2             */
+{VIACR, CR7C, 0xFF, 0x03},     /* LCD Scaling Parameter 3             */
+{VIACR, CR7D, 0xFF, 0x04},     /* LCD Scaling Parameter 4             */
+{VIACR, CR7E, 0xFF, 0x07},     /* LCD Scaling Parameter 5             */
+{VIACR, CR7F, 0xFF, 0x0A},     /* LCD Scaling Parameter 6             */
+{VIACR, CR80, 0xFF, 0x0D},     /* LCD Scaling Parameter 7             */
+{VIACR, CR81, 0xFF, 0x13},     /* LCD Scaling Parameter 8             */
+{VIACR, CR82, 0xFF, 0x16},     /* LCD Scaling Parameter 9             */
+{VIACR, CR83, 0xFF, 0x19},     /* LCD Scaling Parameter 10            */
+{VIACR, CR84, 0xFF, 0x1C},     /* LCD Scaling Parameter 11            */
+{VIACR, CR85, 0xFF, 0x1D},     /* LCD Scaling Parameter 12            */
+{VIACR, CR86, 0xFF, 0x1E},     /* LCD Scaling Parameter 13            */
+{VIACR, CR87, 0xFF, 0x1F},     /* LCD Scaling Parameter 14            */
+{VIACR, CR88, 0xFF, 0x40},     /* LCD Panel Type                      */
+{VIACR, CR89, 0xFF, 0x00},     /* LCD Timing Control 0                */
+{VIACR, CR8A, 0xFF, 0x88},     /* LCD Timing Control 1                */
+{VIACR, CRD4, 0xFF, 0x81},     /* Second power sequence control       */
+{VIACR, CR8B, 0xFF, 0x5D},     /* LCD Power Sequence Control 0        */
+{VIACR, CR8C, 0xFF, 0x2B},     /* LCD Power Sequence Control 1        */
+{VIACR, CR8D, 0xFF, 0x6F},     /* LCD Power Sequence Control 2        */
+{VIACR, CR8E, 0xFF, 0x2B},     /* LCD Power Sequence Control 3        */
+{VIACR, CR8F, 0xFF, 0x01},     /* LCD Power Sequence Control 4        */
+{VIACR, CR90, 0xFF, 0x01},     /* LCD Power Sequence Control 5        */
+{VIACR, CR91, 0xFF, 0x80},     /* 24/12 bit LVDS Data off             */
+{VIACR, CR96, 0xFF, 0x00},
+{VIACR, CR97, 0xFF, 0x00},
+{VIACR, CR99, 0xFF, 0x00},
+{VIACR, CR9B, 0xFF, 0x00},
+{VIACR, CRD2, 0xFF, 0xFF}      /* TMDS/LVDS control register.         */
+};
+
+/* Video Mode Table */
+/* Common Setting for Video Mode */
+struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
+{VIASR, SR2A, 0x0F, 0x00},
+{VIASR, SR15, 0x02, 0x02},
+{VIASR, SR16, 0xBF, 0x08},
+{VIASR, SR17, 0xFF, 0x1F},
+{VIASR, SR18, 0xFF, 0x4E},
+{VIASR, SR1A, 0xFB, 0x08},
+
+{VIACR, CR32, 0xFF, 0x00},
+{VIACR, CR34, 0xFF, 0x00},
+{VIACR, CR35, 0xFF, 0x00},
+{VIACR, CR36, 0x08, 0x00},
+{VIACR, CR6A, 0xFF, 0x80},
+{VIACR, CR6A, 0xFF, 0xC0},
+
+{VIACR, CR55, 0x80, 0x00},
+{VIACR, CR5D, 0x80, 0x00},
+
+{VIAGR, GR20, 0xFF, 0x00},
+{VIAGR, GR21, 0xFF, 0x00},
+{VIAGR, GR22, 0xFF, 0x00},
+       /* LCD Parameters */
+{VIACR, CR7A, 0xFF, 0x01},     /* LCD Parameter 1 */
+{VIACR, CR7B, 0xFF, 0x02},     /* LCD Parameter 2 */
+{VIACR, CR7C, 0xFF, 0x03},     /* LCD Parameter 3 */
+{VIACR, CR7D, 0xFF, 0x04},     /* LCD Parameter 4 */
+{VIACR, CR7E, 0xFF, 0x07},     /* LCD Parameter 5 */
+{VIACR, CR7F, 0xFF, 0x0A},     /* LCD Parameter 6 */
+{VIACR, CR80, 0xFF, 0x0D},     /* LCD Parameter 7 */
+{VIACR, CR81, 0xFF, 0x13},     /* LCD Parameter 8 */
+{VIACR, CR82, 0xFF, 0x16},     /* LCD Parameter 9 */
+{VIACR, CR83, 0xFF, 0x19},     /* LCD Parameter 10 */
+{VIACR, CR84, 0xFF, 0x1C},     /* LCD Parameter 11 */
+{VIACR, CR85, 0xFF, 0x1D},     /* LCD Parameter 12 */
+{VIACR, CR86, 0xFF, 0x1E},     /* LCD Parameter 13 */
+{VIACR, CR87, 0xFF, 0x1F},     /* LCD Parameter 14 */
+
+};
+
+/* Mode:1024X768 */
+struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
+{VIASR, 0x18, 0xFF, 0x4C}
+};
+
+struct patch_table res_patch_table[] = {
+       {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768}
+};
+
+/* struct VPITTable {
+       unsigned char  Misc;
+       unsigned char  SR[StdSR];
+       unsigned char  CR[StdCR];
+       unsigned char  GR[StdGR];
+       unsigned char  AR[StdAR];
+ };*/
+
+struct VPITTable VPIT = {
+       /* Msic */
+       0xC7,
+       /* Sequencer */
+       {0x01, 0x0F, 0x00, 0x0E},
+       /* Graphic Controller */
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
+       /* Attribute Controller */
+       {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+        0x01, 0x00, 0x0F, 0x00}
+};
+
+/********************/
+/* Mode Table       */
+/********************/
+
+/* 480x640 */
+struct crt_mode_table CRTM480x640[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP,
+        {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} }     /* GTF*/
+};
+
+/* 640x480*/
+struct crt_mode_table CRTM640x480[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP,
+        {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
+       {REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP,
+        {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
+       {REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP,
+        {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} },
+       {REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP,
+        {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/
+           {REFRESH_120, CLK_52_406M, M640X480_R120_HSP,
+            M640X480_R120_VSP,
+            {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481,
+             3} } /*GTF*/
+};
+
+/*720x480 (GTF)*/
+struct crt_mode_table CRTM720x480[] = {
+       /*r_rate,vclk,hsp,vsp      */
+       /*HT, HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP,
+        {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} }
+
+};
+
+/*720x576 (GTF)*/
+struct crt_mode_table CRTM720x576[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP,
+        {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} }
+};
+
+/* 800x480 (CVT) */
+struct crt_mode_table CRTM800x480[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP,
+        {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} }
+};
+
+/* 800x600*/
+struct crt_mode_table CRTM800x600[] = {
+       /*r_rate,vclk,hsp,vsp     */
+       /*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP,
+        {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} },
+       {REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP,
+        {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} },
+       {REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP,
+        {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} },
+       {REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP,
+        {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} },
+       {REFRESH_120, CLK_83_950M, M800X600_R120_HSP,
+                 M800X600_R120_VSP,
+                 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601,
+                  3} }
+};
+
+/* 848x480 (CVT) */
+struct crt_mode_table CRTM848x480[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP,
+        {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} }
+};
+
+/*856x480 (GTF) convert to 852x480*/
+struct crt_mode_table CRTM852x480[] = {
+       /*r_rate,vclk,hsp,vsp     */
+       /*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP,
+       {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
+};
+
+/*1024x512 (GTF)*/
+struct crt_mode_table CRTM1024x512[] = {
+       /*r_rate,vclk,hsp,vsp     */
+       /*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP,
+        {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
+
+};
+
+/* 1024x600*/
+struct crt_mode_table CRTM1024x600[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP,
+        {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
+};
+
+/* 1024x768*/
+struct crt_mode_table CRTM1024x768[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP,
+       {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
+       {REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP,
+       {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
+       {REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP,
+       {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
+       {REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP,
+       {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
+};
+
+/* 1152x864*/
+struct crt_mode_table CRTM1152x864[] = {
+       /*r_rate,vclk,hsp,vsp      */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP,
+        {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
+
+};
+
+/* 1280x720 (HDMI 720P)*/
+struct crt_mode_table CRTM1280x720[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE      */
+       {REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP,
+        {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
+       {REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP,
+        {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
+};
+
+/*1280x768 (GTF)*/
+struct crt_mode_table CRTM1280x768[] = {
+       /*r_rate,vclk,hsp,vsp     */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP,
+        {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
+       {REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP,
+        {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
+};
+
+/* 1280x800 (CVT) */
+struct crt_mode_table CRTM1280x800[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP,
+        {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
+};
+
+/*1280x960*/
+struct crt_mode_table CRTM1280x960[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP,
+        {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
+};
+
+/* 1280x1024*/
+struct crt_mode_table CRTM1280x1024[] = {
+       /*r_rate,vclk,,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
+        {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
+         3} },
+       {REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
+        {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
+         3} },
+       {REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
+        {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
+};
+
+/* 1368x768 (GTF) */
+struct crt_mode_table CRTM1368x768[] = {
+       /* r_rate,  vclk, hsp, vsp */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+        {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
+};
+
+/*1440x1050 (GTF)*/
+struct crt_mode_table CRTM1440x1050[] = {
+       /*r_rate,vclk,hsp,vsp      */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
+        {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
+};
+
+/* 1600x1200*/
+struct crt_mode_table CRTM1600x1200[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
+        {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
+         3} },
+       {REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
+        {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
+
+};
+
+/* 1680x1050 (CVT) */
+struct crt_mode_table CRTM1680x1050[] = {
+       /* r_rate,          vclk,              hsp,             vsp  */
+       /* HT,  HA,  HBS, HBE, HSS, HSE,    VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
+        {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
+         6} },
+       {REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
+        {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
+};
+
+/* 1680x1050 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1680x1050_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE,    VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP,
+        M1680x1050_RB_R60_VSP,
+        {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
+};
+
+/* 1920x1080 (CVT)*/
+struct crt_mode_table CRTM1920x1080[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
+        {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
+};
+
+/* 1920x1080 (CVT with Reduce Blanking) */
+struct crt_mode_table CRTM1920x1080_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP,
+        M1920X1080_RB_R60_VSP,
+        {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
+};
+
+/* 1920x1440*/
+struct crt_mode_table CRTM1920x1440[] = {
+       /*r_rate,vclk,hsp,vsp */
+       /*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
+        {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
+         3} },
+       {REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
+        {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
+};
+
+/* 1400x1050 (CVT) */
+struct crt_mode_table CRTM1400x1050[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
+        {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
+         4} },
+       {REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
+        {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
+};
+
+/* 1400x1050 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1400x1050_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP,
+        M1400X1050_RB_R60_VSP,
+        {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
+};
+
+/* 960x600 (CVT) */
+struct crt_mode_table CRTM960x600[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP,
+        {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
+};
+
+/* 1000x600 (GTF) */
+struct crt_mode_table CRTM1000x600[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP,
+        {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
+};
+
+/* 1024x576 (GTF) */
+struct crt_mode_table CRTM1024x576[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP,
+        {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
+};
+
+/* 1088x612 (CVT) */
+struct crt_mode_table CRTM1088x612[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP,
+        {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
+};
+
+/* 1152x720 (CVT) */
+struct crt_mode_table CRTM1152x720[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP,
+        {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
+};
+
+/* 1200x720 (GTF) */
+struct crt_mode_table CRTM1200x720[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP,
+        {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
+};
+
+/* 1280x600 (GTF) */
+struct crt_mode_table CRTM1280x600[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE, VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP,
+        {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
+};
+
+/* 1360x768 (CVT) */
+struct crt_mode_table CRTM1360x768[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP,
+        {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
+};
+
+/* 1360x768 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1360x768_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP,
+        M1360X768_RB_R60_VSP,
+        {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
+};
+
+/* 1366x768 (GTF) */
+struct crt_mode_table CRTM1366x768[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+        {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
+       {REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP,
+        {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
+};
+
+/* 1440x900 (CVT) */
+struct crt_mode_table CRTM1440x900[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP,
+        {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
+       {REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP,
+        {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
+};
+
+/* 1440x900 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1440x900_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP,
+        M1440X900_RB_R60_VSP,
+        {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
+};
+
+/* 1600x900 (CVT) */
+struct crt_mode_table CRTM1600x900[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP,
+        {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
+};
+
+/* 1600x900 (CVT Reduce Blanking) */
+struct crt_mode_table CRTM1600x900_RB[] = {
+       /* r_rate,        vclk,           hsp,        vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP,
+        M1600X900_RB_R60_VSP,
+        {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
+};
+
+/* 1600x1024 (GTF) */
+struct crt_mode_table CRTM1600x1024[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
+        {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
+};
+
+/* 1792x1344 (DMT) */
+struct crt_mode_table CRTM1792x1344[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
+        {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
+};
+
+/* 1856x1392 (DMT) */
+struct crt_mode_table CRTM1856x1392[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
+        {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
+};
+
+/* 1920x1200 (CVT) */
+struct crt_mode_table CRTM1920x1200[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
+        {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
+};
+
+/* 1920x1200 (CVT with Reduce Blanking) */
+struct crt_mode_table CRTM1920x1200_RB[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
+       {REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP,
+        M1920X1200_RB_R60_VSP,
+        {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
+};
+
+/* 2048x1536 (CVT) */
+struct crt_mode_table CRTM2048x1536[] = {
+       /* r_rate,          vclk,              hsp,             vsp   */
+       /* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
+       {REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
+        {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
+};
+
+/* Video Mode Table */
+/* struct VideoModeTable {*/
+/*  int                               ModeIndex;*/
+/*  struct crt_mode_table             *crtc;*/
+/*  int                               mode_array;*/
+/* };*/
+struct VideoModeTable CLE266Modes[] = {
+       /* Display : 480x640 (GTF) */
+       {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)},
+
+       /* Display : 640x480 */
+       {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)},
+
+       /* Display : 720x480 (GTF) */
+       {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)},
+
+       /* Display : 720x576 (GTF) */
+       {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)},
+
+       /* Display : 800x600 */
+       {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)},
+
+       /* Display : 800x480 (CVT) */
+       {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)},
+
+       /* Display : 848x480 (CVT) */
+       {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)},
+
+       /* Display : 852x480 (GTF) */
+       {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)},
+
+       /* Display : 1024x512 (GTF) */
+       {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
+
+       /* Display : 1024x600 */
+       {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
+
+       /* Display : 1024x576 (GTF) */
+       /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */
+
+       /* Display : 1024x768 */
+       {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
+
+       /* Display : 1152x864 */
+       {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
+
+       /* Display : 1280x768 (GTF) */
+       {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
+
+       /* Display : 960x600 (CVT) */
+       {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)},
+
+       /* Display : 1000x600 (GTF) */
+       {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
+
+       /* Display : 1024x576 (GTF) */
+       {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
+
+       /* Display : 1088x612 (GTF) */
+       {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
+
+       /* Display : 1152x720 (CVT) */
+       {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
+
+       /* Display : 1200x720 (GTF) */
+       {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
+
+       /* Display : 1280x600 (GTF) */
+       {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
+
+       /* Display : 1280x800 (CVT) */
+       {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
+
+       /* Display : 1280x800 (GTF) */
+       /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */
+
+       /* Display : 1280x960 */
+       {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
+
+       /* Display : 1280x1024 */
+       {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
+
+       /* Display : 1360x768 (CVT) */
+       {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
+
+       /* Display : 1360x768 (CVT Reduce Blanking) */
+       {VIA_RES_1360X768_RB, CRTM1360x768_RB,
+        ARRAY_SIZE(CRTM1360x768_RB)},
+
+       /* Display : 1366x768 */
+       {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
+
+       /* Display : 1368x768 (GTF) */
+       /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */
+       /* Display : 1368x768 (GTF) */
+       {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
+
+       /* Display : 1440x900 (CVT) */
+       {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
+
+       /* Display : 1440x900 (CVT Reduce Blanking) */
+       {VIA_RES_1440X900_RB, CRTM1440x900_RB,
+        ARRAY_SIZE(CRTM1440x900_RB)},
+
+       /* Display : 1440x1050 (GTF) */
+       {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
+
+       /* Display : 1400x1050 (CVT Reduce Blanking) */
+       {VIA_RES_1400X1050_RB, CRTM1400x1050_RB,
+        ARRAY_SIZE(CRTM1400x1050_RB)},
+
+       /* Display : 1600x900 (CVT) */
+       {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
+
+       /* Display : 1600x900 (CVT Reduce Blanking) */
+       {VIA_RES_1600X900_RB, CRTM1600x900_RB,
+        ARRAY_SIZE(CRTM1600x900_RB)},
+
+       /* Display : 1600x1024 (GTF) */
+       {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
+
+       /* Display : 1600x1200 */
+       {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
+
+       /* Display : 1680x1050 (CVT) */
+       {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
+
+       /* Display : 1680x1050 (CVT Reduce Blanking) */
+       {VIA_RES_1680X1050_RB, CRTM1680x1050_RB,
+        ARRAY_SIZE(CRTM1680x1050_RB)},
+
+       /* Display : 1792x1344 (DMT) */
+       {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
+
+       /* Display : 1856x1392 (DMT) */
+       {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
+
+       /* Display : 1920x1440 */
+       {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
+
+       /* Display : 2048x1536 */
+       {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
+
+       /* Display : 1280x720 */
+       {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
+
+       /* Display : 1920x1080 (CVT) */
+       {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
+
+       /* Display : 1920x1080 (CVT Reduce Blanking) */
+       {VIA_RES_1920X1080_RB, CRTM1920x1080_RB,
+        ARRAY_SIZE(CRTM1920x1080_RB)},
+
+       /* Display : 1920x1200 (CVT) */
+       {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
+
+       /* Display : 1920x1200 (CVT Reduce Blanking) */
+       {VIA_RES_1920X1200_RB, CRTM1920x1200_RB,
+        ARRAY_SIZE(CRTM1920x1200_RB)},
+
+       /* Display : 1400x1050 (CVT) */
+       {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
+};
+struct crt_mode_table CEAM1280x720[] = {
+       {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
+        M1280X720_CEA_R60_VSP,
+        /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,   VA,  VBS, VBE, VSS, VSE */
+        {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
+};
+struct crt_mode_table CEAM1920x1080[] = {
+       {REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP,
+        M1920X1080_CEA_R60_VSP,
+        /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,  VA, VBS, VBE,  VSS, VSE */
+        {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
+};
+struct VideoModeTable CEA_HDMI_Modes[] = {
+       /* Display : 1280x720 */
+       {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
+       {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
+};
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
new file mode 100644 (file)
index 0000000..1a5de50
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 __VIAMODE_H__
+#define __VIAMODE_H__
+
+#include "global.h"
+
+struct VPITTable {
+       unsigned char Misc;
+       unsigned char SR[StdSR];
+       unsigned char GR[StdGR];
+       unsigned char AR[StdAR];
+};
+
+struct VideoModeTable {
+       int ModeIndex;
+       struct crt_mode_table *crtc;
+       int mode_array;
+};
+
+struct patch_table {
+       int mode_index;
+       int table_length;
+       struct io_reg *io_reg_table;
+};
+
+struct res_map_refresh {
+       int hres;
+       int vres;
+       int pixclock;
+       int vmode_refresh;
+};
+
+#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl)
+#define NUM_TOTAL_CEA_MODES  ARRAY_SIZE(CEA_HDMI_Modes)
+#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs)
+#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs)
+#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs)
+#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs)
+#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs)
+#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs)
+#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table)
+#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes)
+
+/********************/
+/* Mode Table       */
+/********************/
+
+/* 480x640 */
+extern struct crt_mode_table CRTM480x640[1];
+/* 640x480*/
+extern struct crt_mode_table CRTM640x480[5];
+/*720x480 (GTF)*/
+extern struct crt_mode_table CRTM720x480[1];
+/*720x576 (GTF)*/
+extern struct crt_mode_table CRTM720x576[1];
+/* 800x480 (CVT) */
+extern struct crt_mode_table CRTM800x480[1];
+/* 800x600*/
+extern struct crt_mode_table CRTM800x600[5];
+/* 848x480 (CVT) */
+extern struct crt_mode_table CRTM848x480[1];
+/*856x480 (GTF) convert to 852x480*/
+extern struct crt_mode_table CRTM852x480[1];
+/*1024x512 (GTF)*/
+extern struct crt_mode_table CRTM1024x512[1];
+/* 1024x600*/
+extern struct crt_mode_table CRTM1024x600[1];
+/* 1024x768*/
+extern struct crt_mode_table CRTM1024x768[4];
+/* 1152x864*/
+extern struct crt_mode_table CRTM1152x864[1];
+/* 1280x720 (HDMI 720P)*/
+extern struct crt_mode_table CRTM1280x720[2];
+/*1280x768 (GTF)*/
+extern struct crt_mode_table CRTM1280x768[2];
+/* 1280x800 (CVT) */
+extern struct crt_mode_table CRTM1280x800[1];
+/*1280x960*/
+extern struct crt_mode_table CRTM1280x960[1];
+/* 1280x1024*/
+extern struct crt_mode_table CRTM1280x1024[3];
+/* 1368x768 (GTF) */
+extern struct crt_mode_table CRTM1368x768[1];
+/*1440x1050 (GTF)*/
+extern struct crt_mode_table CRTM1440x1050[1];
+/* 1600x1200*/
+extern struct crt_mode_table CRTM1600x1200[2];
+/* 1680x1050 (CVT) */
+extern struct crt_mode_table CRTM1680x1050[2];
+/* 1680x1050 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1680x1050_RB[1];
+/* 1920x1080 (CVT)*/
+extern struct crt_mode_table CRTM1920x1080[1];
+/* 1920x1080 (CVT with Reduce Blanking) */
+extern struct crt_mode_table CRTM1920x1080_RB[1];
+/* 1920x1440*/
+extern struct crt_mode_table CRTM1920x1440[2];
+/* 1400x1050 (CVT) */
+extern struct crt_mode_table CRTM1400x1050[2];
+/* 1400x1050 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1400x1050_RB[1];
+/* 960x600 (CVT) */
+extern struct crt_mode_table CRTM960x600[1];
+/* 1000x600 (GTF) */
+extern struct crt_mode_table CRTM1000x600[1];
+/* 1024x576 (GTF) */
+extern struct crt_mode_table CRTM1024x576[1];
+/* 1088x612 (CVT) */
+extern struct crt_mode_table CRTM1088x612[1];
+/* 1152x720 (CVT) */
+extern struct crt_mode_table CRTM1152x720[1];
+/* 1200x720 (GTF) */
+extern struct crt_mode_table CRTM1200x720[1];
+/* 1280x600 (GTF) */
+extern struct crt_mode_table CRTM1280x600[1];
+/* 1360x768 (CVT) */
+extern struct crt_mode_table CRTM1360x768[1];
+/* 1360x768 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1360x768_RB[1];
+/* 1366x768 (GTF) */
+extern struct crt_mode_table CRTM1366x768[2];
+/* 1440x900 (CVT) */
+extern struct crt_mode_table CRTM1440x900[2];
+/* 1440x900 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1440x900_RB[1];
+/* 1600x900 (CVT) */
+extern struct crt_mode_table CRTM1600x900[1];
+/* 1600x900 (CVT Reduce Blanking) */
+extern struct crt_mode_table CRTM1600x900_RB[1];
+/* 1600x1024 (GTF) */
+extern struct crt_mode_table CRTM1600x1024[1];
+/* 1792x1344 (DMT) */
+extern struct crt_mode_table CRTM1792x1344[1];
+/* 1856x1392 (DMT) */
+extern struct crt_mode_table CRTM1856x1392[1];
+/* 1920x1200 (CVT) */
+extern struct crt_mode_table CRTM1920x1200[1];
+/* 1920x1200 (CVT with Reduce Blanking) */
+extern struct crt_mode_table CRTM1920x1200_RB[1];
+/* 2048x1536 (CVT) */
+extern struct crt_mode_table CRTM2048x1536[1];
+extern struct VideoModeTable CLE266Modes[47];
+extern struct crt_mode_table CEAM1280x720[1];
+extern struct crt_mode_table CEAM1920x1080[1];
+extern struct VideoModeTable CEA_HDMI_Modes[2];
+
+extern struct res_map_refresh res_map_refresh_tbl[61];
+extern struct io_reg CN400_ModeXregs[52];
+extern struct io_reg CN700_ModeXregs[66];
+extern struct io_reg KM400_ModeXregs[55];
+extern struct io_reg CX700_ModeXregs[58];
+extern struct io_reg VX800_ModeXregs[58];
+extern struct io_reg CLE266_ModeXregs[32];
+extern struct io_reg PM1024x768[2];
+extern struct patch_table res_patch_table[1];
+extern struct VPITTable VPIT;
+#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
new file mode 100644 (file)
index 0000000..322a9f9
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
+
+u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+       u8 index)
+{
+       u8 data;
+
+       viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
+       viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
+
+       return data;
+}
+
+void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
+                             *plvds_setting_info, struct lvds_chip_information
+                             *plvds_chip_info, struct IODATA io_data)
+{
+       int index, data;
+
+       viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
+
+       index = io_data.Index;
+       data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
+               index);
+       data = (data & (~io_data.Mask)) | io_data.Data;
+
+       viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data);
+}
+
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
+{
+       int reg_num, i;
+
+       /* Common settings: */
+       reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
+
+       for (i = 0; i < reg_num; i++) {
+               viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+                                        plvds_chip_info,
+                                        COMMON_INIT_TBL_VT1636[i]);
+       }
+
+       /* Input Data Mode Select */
+       if (plvds_setting_info->device_lcd_dualedge) {
+               viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+                                        plvds_chip_info,
+                                        DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
+       } else {
+               viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+                                        plvds_chip_info,
+                                        SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
+       }
+
+       if (plvds_setting_info->LCDDithering) {
+               viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+                                        plvds_chip_info,
+                                        DITHERING_ENABLE_TBL_VT1636[0]);
+       } else {
+               viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+                                        plvds_chip_info,
+                                        DITHERING_DISABLE_TBL_VT1636[0]);
+       }
+}
+
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+                       *plvds_setting_info,
+                       struct lvds_chip_information *plvds_chip_info)
+{
+
+       viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+                                VDD_ON_TBL_VT1636[0]);
+
+       /* Pad on: */
+       switch (plvds_chip_info->output_interface) {
+       case INTERFACE_DVP0:
+               {
+                       viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
+                       break;
+               }
+
+       case INTERFACE_DVP1:
+               {
+                       viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
+                       break;
+               }
+
+       case INTERFACE_DFP_LOW:
+               {
+                       viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
+                       break;
+               }
+
+       case INTERFACE_DFP_HIGH:
+               {
+                       viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
+                       break;
+               }
+
+       }
+}
+
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info)
+{
+
+       viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+                                VDD_OFF_TBL_VT1636[0]);
+
+       /* Pad off: */
+       switch (plvds_chip_info->output_interface) {
+       case INTERFACE_DVP0:
+               {
+                       viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
+                       break;
+               }
+
+       case INTERFACE_DVP1:
+               {
+                       viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
+                       break;
+               }
+
+       case INTERFACE_DFP_LOW:
+               {
+                       viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
+                       break;
+               }
+
+       case INTERFACE_DFP_HIGH:
+               {
+                       viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
+                       break;
+               }
+
+       }
+}
+
+bool viafb_lvds_identify_vt1636(void)
+{
+       u8 Buffer[2];
+
+       DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
+
+       /* Sense VT1636 LVDS Transmiter */
+       viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
+       VT1636_LVDS_I2C_ADDR;
+
+       /* Check vendor ID first: */
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+       lvds_chip_slave_addr,
+                   0x00, &Buffer[0]);
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+               lvds_chip_slave_addr,
+                   0x01, &Buffer[1]);
+
+       if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
+               return false;
+
+       /* Check Chip ID: */
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+       lvds_chip_slave_addr,
+                   0x02, &Buffer[0]);
+       viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
+               lvds_chip_slave_addr,
+                   0x03, &Buffer[1]);
+       if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
+               viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
+                       VT1636_LVDS;
+               return true;
+       }
+
+       return false;
+}
+
+static int get_clk_range_index(u32 Clk)
+{
+       if (Clk < DPA_CLK_30M)
+               return DPA_CLK_RANGE_30M;
+       else if (Clk < DPA_CLK_50M)
+               return DPA_CLK_RANGE_30_50M;
+       else if (Clk < DPA_CLK_70M)
+               return DPA_CLK_RANGE_50_70M;
+       else if (Clk < DPA_CLK_100M)
+               return DPA_CLK_RANGE_70_100M;
+       else if (Clk < DPA_CLK_150M)
+               return DPA_CLK_RANGE_100_150M;
+       else
+               return DPA_CLK_RANGE_150M;
+}
+
+static int get_lvds_dpa_setting_index(int panel_size_id,
+                            struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
+                              int tbl_size)
+{
+       int i;
+
+       for (i = 0; i < tbl_size; i++) {
+               if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
+                       return i;
+
+               p_vt1636_dpasetting_tbl++;
+       }
+
+       return 0;
+}
+
+static void set_dpa_vt1636(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
+                   struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
+{
+       struct IODATA io_data;
+
+       io_data.Index = 0x09;
+       io_data.Mask = 0x1F;
+       io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
+       viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
+               plvds_chip_info, io_data);
+
+       io_data.Index = 0x08;
+       io_data.Mask = 0x0F;
+       io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
+       viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
+               io_data);
+}
+
+void viafb_vt1636_patch_skew_on_vt3324(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info)
+{
+       int index, size;
+
+       DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
+
+       /* Graphics DPA settings: */
+       index = get_clk_range_index(plvds_setting_info->vclk);
+       viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+                   &GFX_DPA_SETTING_TBL_VT3324[index]);
+
+       /* LVDS Transmitter DPA settings: */
+       size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
+       index =
+           get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
+                                      VT1636_DPA_SETTING_TBL_VT3324, size);
+       set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
+                      &VT1636_DPA_SETTING_TBL_VT3324[index]);
+}
+
+void viafb_vt1636_patch_skew_on_vt3327(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info)
+{
+       int index, size;
+
+       DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
+
+       /* Graphics DPA settings: */
+       index = get_clk_range_index(plvds_setting_info->vclk);
+       viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+                   &GFX_DPA_SETTING_TBL_VT3327[index]);
+
+       /* LVDS Transmitter DPA settings: */
+       size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
+       index =
+           get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
+                                      VT1636_DPA_SETTING_TBL_VT3327, size);
+       set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
+                      &VT1636_DPA_SETTING_TBL_VT3327[index]);
+}
+
+void viafb_vt1636_patch_skew_on_vt3364(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info)
+{
+       int index;
+
+       DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
+
+       /* Graphics DPA settings: */
+       index = get_clk_range_index(plvds_setting_info->vclk);
+       viafb_set_dpa_gfx(plvds_chip_info->output_interface,
+                   &GFX_DPA_SETTING_TBL_VT3364[index]);
+}
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h
new file mode 100644 (file)
index 0000000..2a150c5
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 _VT1636_H_
+#define _VT1636_H_
+#include "chip.h"
+bool viafb_lvds_identify_vt1636(void);
+void viafb_init_lvds_vt1636(struct lvds_setting_information
+       *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
+void viafb_enable_lvds_vt1636(struct lvds_setting_information
+                       *plvds_setting_info,
+                       struct lvds_chip_information *plvds_chip_info);
+void viafb_disable_lvds_vt1636(struct lvds_setting_information
+                        *plvds_setting_info,
+                        struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3324(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3327(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info);
+void viafb_vt1636_patch_skew_on_vt3364(
+       struct lvds_setting_information *plvds_setting_info,
+       struct lvds_chip_information *plvds_chip_info);
+
+#endif
index 10211e493001582e0a5b27f549a4c9c00f3a6e5a..29e144f81cbe2e8953f1947c745419d1894a0620 100644 (file)
@@ -160,8 +160,10 @@ static int ds1wm_reset(struct ds1wm_data *ds1wm_data)
         *     625 us - 60 us - 240 us - 100 ns = 324.9 us
         *
         * We'll wait a bit longer just to be sure.
+        * Was udelay(500), but if it is going to busywait the cpu that long,
+        * might as well come back later.
         */
-       udelay(500);
+       msleep(1);
 
        ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
                DS1WM_INTEN_ERBF | DS1WM_INTEN_ETMT | DS1WM_INTEN_EPD |
@@ -274,8 +276,8 @@ static u8 ds1wm_reset_bus(void *data)
        return 0;
 }
 
-static void ds1wm_search(void *data, u8 search_type,
-                        w1_slave_found_callback slave_found)
+static void ds1wm_search(void *data, struct w1_master *master_dev,
+                       u8 search_type, w1_slave_found_callback slave_found)
 {
        struct ds1wm_data *ds1wm_data = data;
        int i;
@@ -313,7 +315,7 @@ static void ds1wm_search(void *data, u8 search_type,
        ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA);
        ds1wm_reset(ds1wm_data);
 
-       slave_found(ds1wm_data, rom_id);
+       slave_found(master_dev, rom_id);
 }
 
 /* --------------------------------------------------------------------- */
index b63b5e044a4cc7aa641c26ea1de8906f7a4656c4..59ad6e95af8f0b0dded05413115c45bee2d2276b 100644 (file)
@@ -88,7 +88,7 @@
 #define COMM_DT                                0x2000
 #define COMM_SPU                       0x1000
 #define COMM_F                         0x0800
-#define COMM_NTP                       0x0400
+#define COMM_NTF                       0x0400
 #define COMM_ICP                       0x0200
 #define COMM_RST                       0x0100
 
 #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_IDLE                                0x20  /* DS2490 is currently idle */
 #define ST_EPOF                                0x80
 
+/* Result Register flags */
+#define RR_DETECT                      0xA5 /* New device detected */
+#define RR_NRS                         0x01 /* Reset no presence or ... */
+#define RR_SH                          0x02 /* short on reset or set path */
+#define RR_APP                         0x04 /* alarming presence on reset */
+#define RR_VPP                         0x08 /* 12V expected not seen */
+#define RR_CMP                         0x10 /* compare error */
+#define RR_CRC                         0x20 /* CRC error detected */
+#define RR_RDP                         0x40 /* redirected page */
+#define RR_EOS                         0x80 /* end of search error */
+
 #define SPEED_NORMAL                   0x00
 #define SPEED_FLEXIBLE                 0x01
 #define SPEED_OVERDRIVE                        0x02
@@ -131,6 +137,15 @@ struct ds_device
 
        int                     ep[NUM_EP];
 
+       /* Strong PullUp
+        * 0: pullup not active, else duration in milliseconds
+        */
+       int                     spu_sleep;
+       /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup
+        * should be active or not for writes.
+        */
+       u16                     spu_bit;
+
        struct w1_bus_master    master;
 };
 
@@ -164,7 +179,6 @@ MODULE_DEVICE_TABLE(usb, ds_id_table);
 static int ds_probe(struct usb_interface *, const struct usb_device_id *);
 static void ds_disconnect(struct usb_interface *);
 
-static inline void ds_dump_status(unsigned char *, unsigned char *, int);
 static int ds_send_control(struct ds_device *, u16, u16);
 static int ds_send_control_cmd(struct ds_device *, u16, u16);
 
@@ -192,7 +206,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
 
        return err;
 }
-#if 0
+
 static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
 {
        int err;
@@ -207,7 +221,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
 
        return err;
 }
-#endif
+
 static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
 {
        int err;
@@ -223,11 +237,6 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
        return err;
 }
 
-static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
-{
-       printk("%45s: %8x\n", str, buf[off]);
-}
-
 static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
                                 unsigned char *buf, int size)
 {
@@ -248,62 +257,81 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
        return count;
 }
 
-static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off)
 {
-       unsigned char buf[64];
-       int count, err = 0, i;
-
-       memcpy(st, buf, sizeof(*st));
+       printk(KERN_INFO "%45s: %8x\n", str, buf[off]);
+}
 
-       count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
-       if (count < 0)
-               return err;
+static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count)
+{
+       int i;
 
-       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+       printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
        for (i=0; i<count; ++i)
                printk("%02x ", buf[i]);
-       printk("\n");
+       printk(KERN_INFO "\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);
+               ds_print_msg(buf, "enable flag", 0);
+               ds_print_msg(buf, "1-wire speed", 1);
+               ds_print_msg(buf, "strong pullup duration", 2);
+               ds_print_msg(buf, "programming pulse duration", 3);
+               ds_print_msg(buf, "pulldown slew rate control", 4);
+               ds_print_msg(buf, "write-1 low time", 5);
+               ds_print_msg(buf, "data sample offset/write-0 recovery time",
+                       6);
+               ds_print_msg(buf, "reserved (test register)", 7);
+               ds_print_msg(buf, "device status flags", 8);
+               ds_print_msg(buf, "communication command byte 1", 9);
+               ds_print_msg(buf, "communication command byte 2", 10);
+               ds_print_msg(buf, "communication command buffer status", 11);
+               ds_print_msg(buf, "1-wire data output buffer status", 12);
+               ds_print_msg(buf, "1-wire data input buffer status", 13);
+               ds_print_msg(buf, "reserved", 14);
+               ds_print_msg(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;
+       for (i = 16; i < count; ++i) {
+               if (buf[i] == RR_DETECT) {
+                       ds_print_msg(buf, "new device detect", i);
+                       continue;
+               }
+               ds_print_msg(buf, "Result Register Value: ", i);
+               if (buf[i] & RR_NRS)
+                       printk(KERN_INFO "NRS: Reset no presence or ...\n");
+               if (buf[i] & RR_SH)
+                       printk(KERN_INFO "SH: short on reset or set path\n");
+               if (buf[i] & RR_APP)
+                       printk(KERN_INFO "APP: alarming presence on reset\n");
+               if (buf[i] & RR_VPP)
+                       printk(KERN_INFO "VPP: 12V expected not seen\n");
+               if (buf[i] & RR_CMP)
+                       printk(KERN_INFO "CMP: compare error\n");
+               if (buf[i] & RR_CRC)
+                       printk(KERN_INFO "CRC: CRC error detected\n");
+               if (buf[i] & RR_RDP)
+                       printk(KERN_INFO "RDP: redirected page\n");
+               if (buf[i] & RR_EOS)
+                       printk(KERN_INFO "EOS: end of search error\n");
        }
-#endif
+}
 
-       return err;
+static void ds_reset_device(struct ds_device *dev)
+{
+       ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+       /* Always allow strong pullup which allow individual writes to use
+        * the strong pullup.
+        */
+       if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE))
+               printk(KERN_ERR "ds_reset_device: "
+                       "Error allowing strong pullup\n");
+       /* Chip strong pullup time was cleared. */
+       if (dev->spu_sleep) {
+               /* lower 4 bits are 0, see ds_set_pullup */
+               u8 del = dev->spu_sleep>>4;
+               if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del))
+                       printk(KERN_ERR "ds_reset_device: "
+                               "Error setting duration\n");
+       }
 }
 
 static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
@@ -311,13 +339,27 @@ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
        int count, err;
        struct ds_status st;
 
+       /* Careful on size.  If size is less than what is available in
+        * the input buffer, the device fails the bulk transfer and
+        * clears the input buffer.  It could read the maximum size of
+        * the data buffer, but then do you return the first, last, or
+        * some set of the middle size bytes?  As long as the rest of
+        * the code is correct there will be size bytes waiting.  A
+        * call to ds_wait_status will wait until the device is idle
+        * and any data to be received would have been available.
+        */
        count = 0;
        err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
                                buf, size, &count, 1000);
        if (err < 0) {
+               u8 buf[0x20];
+               int count;
+
                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);
+
+               count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+               ds_dump_status(dev, buf, count);
                return err;
        }
 
@@ -341,7 +383,8 @@ static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
        count = 0;
        err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
        if (err < 0) {
-               printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+               printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: "
+                       "err=%d.\n", dev->ep[EP_DATA_OUT], err);
                return err;
        }
 
@@ -397,7 +440,7 @@ int ds_detect(struct ds_device *dev, struct ds_status *st)
        if (err)
                return err;
 
-       err = ds_recv_status(dev, st);
+       err = ds_dump_status(dev, st);
 
        return err;
 }
@@ -420,33 +463,49 @@ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
                        printk("\n");
                }
 #endif
-       } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+       } while (!(buf[0x08] & ST_IDLE) && !(err < 0) && ++count < 100);
+
+       if (err >= 16 && st->status & ST_EPOF) {
+               printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+               ds_reset_device(dev);
+               /* Always dump the device status. */
+               count = 101;
+       }
 
+       /* Dump the status for errors or if there is extended return data.
+        * The extended status includes new device detection (maybe someone
+        * can do something with it).
+        */
+       if (err > 16 || count >= 100 || err < 0)
+               ds_dump_status(dev, buf, err);
 
-       if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
-               ds_recv_status(dev, st);
+       /* Extended data isn't an error.  Well, a short is, but the dump
+        * would have already told the user that and we can't do anything
+        * about it in software anyway.
+        */
+       if (count >= 100 || err < 0)
                return -1;
-       else
+       else
                return 0;
 }
 
-static int ds_reset(struct ds_device *dev, struct ds_status *st)
+static int ds_reset(struct ds_device *dev)
 {
        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);
+       /* Other potentionally interesting flags for reset.
+        *
+        * COMM_NTF: Return result register feedback.  This could be used to
+        * detect some conditions such as short, alarming presence, or
+        * detect if a new device was detected.
+        *
+        * COMM_SE which allows SPEED_NORMAL, SPEED_FLEXIBLE, SPEED_OVERDRIVE:
+        * Select the data transfer rate.
+        */
+       err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_IM, 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;
 }
 
@@ -471,60 +530,43 @@ static int ds_set_speed(struct ds_device *dev, int speed)
 }
 #endif  /*  0  */
 
-static int ds_start_pulse(struct ds_device *dev, int delay)
+static int ds_set_pullup(struct ds_device *dev, int delay)
 {
-       int err;
+       int err = 0;
        u8 del = 1 + (u8)(delay >> 4);
-       struct ds_status st;
-
-#if 0
-       err = ds_stop_pulse(dev, 10);
-       if (err)
+       /* Just storing delay would not get the trunication and roundup. */
+       int ms = del<<4;
+
+       /* Enable spu_bit if a delay is set. */
+       dev->spu_bit = delay ? COMM_SPU : 0;
+       /* If delay is zero, it has already been disabled, if the time is
+        * the same as the hardware was last programmed to, there is also
+        * nothing more to do.  Compare with the recalculated value ms
+        * rather than del or delay which can have a different value.
+        */
+       if (delay == 0 || ms == dev->spu_sleep)
                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);
+       dev->spu_sleep = ms;
 
        return err;
 }
 
 static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
 {
-       int err, count;
+       int err;
        struct ds_status st;
-       u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
-       u16 cmd;
 
-       err = ds_send_control(dev, value, 0);
+       err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0),
+               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;
-       }
+       ds_wait_status(dev, &st);
 
        err = ds_recv_data(dev, tbit, sizeof(*tbit));
        if (err < 0)
@@ -533,12 +575,18 @@ static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
        return 0;
 }
 
+#if 0
 static 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);
+       /* Set COMM_ICP to write without a readback.  Note, this will
+        * produce one time slot, a down followed by an up with COMM_D
+        * only determing the timing.
+        */
+       err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP |
+               (bit ? COMM_D : 0), 0);
        if (err)
                return err;
 
@@ -546,6 +594,7 @@ static int ds_write_bit(struct ds_device *dev, u8 bit)
 
        return 0;
 }
+#endif
 
 static int ds_write_byte(struct ds_device *dev, u8 byte)
 {
@@ -553,10 +602,13 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
        struct ds_status st;
        u8 rbyte;
 
-       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
        if (err)
                return err;
 
+       if (dev->spu_bit)
+               msleep(dev->spu_sleep);
+
        err = ds_wait_status(dev, &st);
        if (err)
                return err;
@@ -565,8 +617,6 @@ static int ds_write_byte(struct ds_device *dev, u8 byte)
        if (err < 0)
                return err;
 
-       ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
        return !(byte == rbyte);
 }
 
@@ -602,7 +652,7 @@ static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
        if (err < 0)
                return err;
 
-       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len);
        if (err)
                return err;
 
@@ -623,20 +673,19 @@ static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
        if (err < 0)
                return err;
 
-       ds_wait_status(dev, &st);
-
-       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+       err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len);
        if (err)
                return err;
 
+       if (dev->spu_bit)
+               msleep(dev->spu_sleep);
+
        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);
 }
 
@@ -728,6 +777,7 @@ static u8 ds9490r_touch_bit(void *data, u8 bit)
        return ret;
 }
 
+#if 0
 static void ds9490r_write_bit(void *data, u8 bit)
 {
        struct ds_device *dev = data;
@@ -735,13 +785,6 @@ static void ds9490r_write_bit(void *data, u8 bit)
        ds_write_bit(dev, bit);
 }
 
-static void ds9490r_write_byte(void *data, u8 byte)
-{
-       struct ds_device *dev = data;
-
-       ds_write_byte(dev, byte);
-}
-
 static u8 ds9490r_read_bit(void *data)
 {
        struct ds_device *dev = data;
@@ -754,6 +797,14 @@ static u8 ds9490r_read_bit(void *data)
 
        return bit & 1;
 }
+#endif
+
+static void ds9490r_write_byte(void *data, u8 byte)
+{
+       struct ds_device *dev = data;
+
+       ds_write_byte(dev, byte);
+}
 
 static u8 ds9490r_read_byte(void *data)
 {
@@ -790,31 +841,58 @@ static u8 ds9490r_read_block(void *data, u8 *buf, int len)
 static u8 ds9490r_reset(void *data)
 {
        struct ds_device *dev = data;
-       struct ds_status st;
        int err;
 
-       memset(&st, 0, sizeof(st));
-
-       err = ds_reset(dev, &st);
+       err = ds_reset(dev);
        if (err)
                return 1;
 
        return 0;
 }
 
+static u8 ds9490r_set_pullup(void *data, int delay)
+{
+       struct ds_device *dev = data;
+
+       if (ds_set_pullup(dev, delay))
+               return 1;
+
+       return 0;
+}
+
 static int ds_w1_init(struct ds_device *dev)
 {
        memset(&dev->master, 0, sizeof(struct w1_bus_master));
 
+       /* Reset the device as it can be in a bad state.
+        * This is necessary because a block write will wait for data
+        * to be placed in the output buffer and block any later
+        * commands which will keep accumulating and the device will
+        * not be idle.  Another case is removing the ds2490 module
+        * while a bus search is in progress, somehow a few commands
+        * get through, but the input transfers fail leaving data in
+        * the input buffer.  This will cause the next read to fail
+        * see the note in ds_recv_data.
+        */
+       ds_reset_device(dev);
+
        dev->master.data        = dev;
        dev->master.touch_bit   = &ds9490r_touch_bit;
+       /* read_bit and write_bit in w1_bus_master are expected to set and
+        * sample the line level.  For write_bit that means it is expected to
+        * set it to that value and leave it there.  ds2490 only supports an
+        * individual time slot at the lowest level.  The requirement from
+        * pulling the bus state down to reading the state is 15us, something
+        * that isn't realistic on the USB bus anyway.
        dev->master.read_bit    = &ds9490r_read_bit;
        dev->master.write_bit   = &ds9490r_write_bit;
+       */
        dev->master.read_byte   = &ds9490r_read_byte;
        dev->master.write_byte  = &ds9490r_write_byte;
        dev->master.read_block  = &ds9490r_read_block;
        dev->master.write_block = &ds9490r_write_block;
        dev->master.reset_bus   = &ds9490r_reset;
+       dev->master.set_pullup  = &ds9490r_set_pullup;
 
        return w1_add_master_device(&dev->master);
 }
@@ -838,6 +916,8 @@ static int ds_probe(struct usb_interface *intf,
                printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
                return -ENOMEM;
        }
+       dev->spu_sleep = 0;
+       dev->spu_bit = 0;
        dev->udev = usb_get_dev(udev);
        if (!dev->udev) {
                err = -ENOMEM;
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
new file mode 100644 (file)
index 0000000..2c6c0cf
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * w1_ds2431.c - w1 family 2d (DS2431) driver
+ *
+ * Copyright (c) 2008 Bernhard Weirich <bernhard.weirich@riedel.net>
+ *
+ * Heavily inspired by w1_DS2433 driver from Ben Gardner <bgardner@wabtec.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+
+#define W1_F2D_EEPROM_SIZE             128
+#define W1_F2D_PAGE_COUNT              4
+#define W1_F2D_PAGE_BITS               5
+#define W1_F2D_PAGE_SIZE               (1<<W1_F2D_PAGE_BITS)
+#define W1_F2D_PAGE_MASK               0x1F
+
+#define W1_F2D_SCRATCH_BITS  3
+#define W1_F2D_SCRATCH_SIZE  (1<<W1_F2D_SCRATCH_BITS)
+#define W1_F2D_SCRATCH_MASK  (W1_F2D_SCRATCH_SIZE-1)
+
+#define W1_F2D_READ_EEPROM     0xF0
+#define W1_F2D_WRITE_SCRATCH   0x0F
+#define W1_F2D_READ_SCRATCH    0xAA
+#define W1_F2D_COPY_SCRATCH    0x55
+
+
+#define W1_F2D_TPROG_MS                11
+
+#define W1_F2D_READ_RETRIES            10
+#define W1_F2D_READ_MAXLEN             8
+
+/*
+ * Check the file size bounds and adjusts count as needed.
+ * This would not be needed if the file size didn't reset to 0 after a write.
+ */
+static inline size_t w1_f2d_fix_count(loff_t off, size_t count, size_t size)
+{
+       if (off > size)
+               return 0;
+
+       if ((off + count) > size)
+               return size - off;
+
+       return count;
+}
+
+/*
+ * Read a block from W1 ROM two times and compares the results.
+ * If they are equal they are returned, otherwise the read
+ * is repeated W1_F2D_READ_RETRIES times.
+ *
+ * count must not exceed W1_F2D_READ_MAXLEN.
+ */
+static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
+{
+       u8 wrbuf[3];
+       u8 cmp[W1_F2D_READ_MAXLEN];
+       int tries = W1_F2D_READ_RETRIES;
+
+       do {
+               wrbuf[0] = W1_F2D_READ_EEPROM;
+               wrbuf[1] = off & 0xff;
+               wrbuf[2] = off >> 8;
+
+               if (w1_reset_select_slave(sl))
+                       return -1;
+
+               w1_write_block(sl->master, wrbuf, 3);
+               w1_read_block(sl->master, buf, count);
+
+               if (w1_reset_select_slave(sl))
+                       return -1;
+
+               w1_write_block(sl->master, wrbuf, 3);
+               w1_read_block(sl->master, cmp, count);
+
+               if (!memcmp(cmp, buf, count))
+                       return 0;
+       } while (--tries);
+
+       dev_err(&sl->dev, "proof reading failed %d times\n",
+                       W1_F2D_READ_RETRIES);
+
+       return -1;
+}
+
+static ssize_t w1_f2d_read_bin(struct kobject *kobj,
+                              struct bin_attribute *bin_attr,
+                              char *buf, loff_t off, size_t count)
+{
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       int todo = count;
+
+       count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE);
+       if (count == 0)
+               return 0;
+
+       mutex_lock(&sl->master->mutex);
+
+       /* read directly from the EEPROM in chunks of W1_F2D_READ_MAXLEN */
+       while (todo > 0) {
+               int block_read;
+
+               if (todo >= W1_F2D_READ_MAXLEN)
+                       block_read = W1_F2D_READ_MAXLEN;
+               else
+                       block_read = todo;
+
+               if (w1_f2d_readblock(sl, off, block_read, buf) < 0)
+                       count = -EIO;
+
+               todo -= W1_F2D_READ_MAXLEN;
+               buf += W1_F2D_READ_MAXLEN;
+               off += W1_F2D_READ_MAXLEN;
+       }
+
+       mutex_unlock(&sl->master->mutex);
+
+       return count;
+}
+
+/*
+ * Writes to the scratchpad and reads it back for verification.
+ * Then copies the scratchpad to EEPROM.
+ * The data must be aligned at W1_F2D_SCRATCH_SIZE bytes and
+ * must be W1_F2D_SCRATCH_SIZE bytes long.
+ * The master must be locked.
+ *
+ * @param sl   The slave structure
+ * @param addr Address for the write
+ * @param len   length must be <= (W1_F2D_PAGE_SIZE - (addr & W1_F2D_PAGE_MASK))
+ * @param data The data to write
+ * @return     0=Success -1=failure
+ */
+static int w1_f2d_write(struct w1_slave *sl, int addr, int len, const u8 *data)
+{
+       int tries = W1_F2D_READ_RETRIES;
+       u8 wrbuf[4];
+       u8 rdbuf[W1_F2D_SCRATCH_SIZE + 3];
+       u8 es = (addr + len - 1) % W1_F2D_SCRATCH_SIZE;
+
+retry:
+
+       /* Write the data to the scratchpad */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       wrbuf[0] = W1_F2D_WRITE_SCRATCH;
+       wrbuf[1] = addr & 0xff;
+       wrbuf[2] = addr >> 8;
+
+       w1_write_block(sl->master, wrbuf, 3);
+       w1_write_block(sl->master, data, len);
+
+       /* Read the scratchpad and verify */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       w1_write_8(sl->master, W1_F2D_READ_SCRATCH);
+       w1_read_block(sl->master, rdbuf, len + 3);
+
+       /* Compare what was read against the data written */
+       if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
+           (rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) {
+
+               if (--tries)
+                       goto retry;
+
+               dev_err(&sl->dev,
+                       "could not write to eeprom, scratchpad compare failed %d times\n",
+                       W1_F2D_READ_RETRIES);
+
+               return -1;
+       }
+
+       /* Copy the scratchpad to EEPROM */
+       if (w1_reset_select_slave(sl))
+               return -1;
+
+       wrbuf[0] = W1_F2D_COPY_SCRATCH;
+       wrbuf[3] = es;
+       w1_write_block(sl->master, wrbuf, 4);
+
+       /* Sleep for tprog ms to wait for the write to complete */
+       msleep(W1_F2D_TPROG_MS);
+
+       /* Reset the bus to wake up the EEPROM  */
+       w1_reset_bus(sl->master);
+
+       return 0;
+}
+
+static ssize_t w1_f2d_write_bin(struct kobject *kobj,
+                               struct bin_attribute *bin_attr,
+                               char *buf, loff_t off, size_t count)
+{
+       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       int addr, len;
+       int copy;
+
+       count = w1_f2d_fix_count(off, count, W1_F2D_EEPROM_SIZE);
+       if (count == 0)
+               return 0;
+
+       mutex_lock(&sl->master->mutex);
+
+       /* Can only write data in blocks of the size of the scratchpad */
+       addr = off;
+       len = count;
+       while (len > 0) {
+
+               /* if len too short or addr not aligned */
+               if (len < W1_F2D_SCRATCH_SIZE || addr & W1_F2D_SCRATCH_MASK) {
+                       char tmp[W1_F2D_SCRATCH_SIZE];
+
+                       /* read the block and update the parts to be written */
+                       if (w1_f2d_readblock(sl, addr & ~W1_F2D_SCRATCH_MASK,
+                                       W1_F2D_SCRATCH_SIZE, tmp)) {
+                               count = -EIO;
+                               goto out_up;
+                       }
+
+                       /* copy at most to the boundary of the PAGE or len */
+                       copy = W1_F2D_SCRATCH_SIZE -
+                               (addr & W1_F2D_SCRATCH_MASK);
+
+                       if (copy > len)
+                               copy = len;
+
+                       memcpy(&tmp[addr & W1_F2D_SCRATCH_MASK], buf, copy);
+                       if (w1_f2d_write(sl, addr & ~W1_F2D_SCRATCH_MASK,
+                                       W1_F2D_SCRATCH_SIZE, tmp) < 0) {
+                               count = -EIO;
+                               goto out_up;
+                       }
+               } else {
+
+                       copy = W1_F2D_SCRATCH_SIZE;
+                       if (w1_f2d_write(sl, addr, copy, buf) < 0) {
+                               count = -EIO;
+                               goto out_up;
+                       }
+               }
+               buf += copy;
+               addr += copy;
+               len -= copy;
+       }
+
+out_up:
+       mutex_unlock(&sl->master->mutex);
+
+       return count;
+}
+
+static struct bin_attribute w1_f2d_bin_attr = {
+       .attr = {
+               .name = "eeprom",
+               .mode = S_IRUGO | S_IWUSR,
+       },
+       .size = W1_F2D_EEPROM_SIZE,
+       .read = w1_f2d_read_bin,
+       .write = w1_f2d_write_bin,
+};
+
+static int w1_f2d_add_slave(struct w1_slave *sl)
+{
+       return sysfs_create_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
+}
+
+static void w1_f2d_remove_slave(struct w1_slave *sl)
+{
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_f2d_bin_attr);
+}
+
+static struct w1_family_ops w1_f2d_fops = {
+       .add_slave      = w1_f2d_add_slave,
+       .remove_slave   = w1_f2d_remove_slave,
+};
+
+static struct w1_family w1_family_2d = {
+       .fid = W1_EEPROM_DS2431,
+       .fops = &w1_f2d_fops,
+};
+
+static int __init w1_f2d_init(void)
+{
+       return w1_register_family(&w1_family_2d);
+}
+
+static void __exit w1_f2d_fini(void)
+{
+       w1_unregister_family(&w1_family_2d);
+}
+
+module_init(w1_f2d_init);
+module_exit(w1_f2d_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bernhard Weirich <bernhard.weirich@riedel.net>");
+MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM");
index fb28acaeed6c4ab01235f09b764b8d0b7e1b20b6..2c8dff9f77da13396b0d02207e15d486ddbd5d4e 100644 (file)
@@ -37,31 +37,33 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
+/* Allow the strong pullup to be disabled, but default to enabled.
+ * If it was disabled a parasite powered device might not get the require
+ * current to do a temperature conversion.  If it is enabled parasite powered
+ * devices have a better chance of getting the current required.
+ */
+static int w1_strong_pullup = 1;
+module_param_named(strong_pullup, w1_strong_pullup, int, 0);
+
 static u8 bad_roms[][9] = {
                                {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
                                {}
                        };
 
-static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
-                                char *, loff_t, size_t);
+static ssize_t w1_therm_read(struct device *device,
+       struct device_attribute *attr, char *buf);
 
-static struct bin_attribute w1_therm_bin_attr = {
-       .attr = {
-               .name = "w1_slave",
-               .mode = S_IRUGO,
-       },
-       .size = W1_SLAVE_DATA_SIZE,
-       .read = w1_therm_read_bin,
-};
+static struct device_attribute w1_therm_attr =
+       __ATTR(w1_slave, S_IRUGO, w1_therm_read, NULL);
 
 static int w1_therm_add_slave(struct w1_slave *sl)
 {
-       return sysfs_create_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+       return device_create_file(&sl->dev, &w1_therm_attr);
 }
 
 static void w1_therm_remove_slave(struct w1_slave *sl)
 {
-       sysfs_remove_bin_file(&sl->dev.kobj, &w1_therm_bin_attr);
+       device_remove_file(&sl->dev, &w1_therm_attr);
 }
 
 static struct w1_family_ops w1_therm_fops = {
@@ -160,30 +162,19 @@ static int w1_therm_check_rom(u8 rom[9])
        return 0;
 }
 
-static ssize_t w1_therm_read_bin(struct kobject *kobj,
-                                struct bin_attribute *bin_attr,
-                                char *buf, loff_t off, size_t count)
+static ssize_t w1_therm_read(struct device *device,
+       struct device_attribute *attr, char *buf)
 {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
+       struct w1_slave *sl = dev_to_w1_slave(device);
        struct w1_master *dev = sl->master;
        u8 rom[9], crc, verdict;
        int i, max_trying = 10;
+       ssize_t c = PAGE_SIZE;
 
-       mutex_lock(&sl->master->mutex);
+       mutex_lock(&dev->mutex);
 
-       if (off > W1_SLAVE_DATA_SIZE) {
-               count = 0;
-               goto out;
-       }
-       if (off + count > W1_SLAVE_DATA_SIZE) {
-               count = 0;
-               goto out;
-       }
-
-       memset(buf, 0, count);
        memset(rom, 0, sizeof(rom));
 
-       count = 0;
        verdict = 0;
        crc = 0;
 
@@ -192,15 +183,20 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj,
                        int count = 0;
                        unsigned int tm = 750;
 
+                       /* 750ms strong pullup (or delay) after the convert */
+                       if (w1_strong_pullup)
+                               w1_next_pullup(dev, tm);
                        w1_write_8(dev, W1_CONVERT_TEMP);
-
-                       msleep(tm);
+                       if (!w1_strong_pullup)
+                               msleep(tm);
 
                        if (!w1_reset_select_slave(sl)) {
 
                                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);
+                                       dev_warn(device, "w1_read_block() "
+                                               "returned %u instead of 9.\n",
+                                               count);
                                }
 
                                crc = w1_calc_crc8(rom, 8);
@@ -215,22 +211,22 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj,
        }
 
        for (i = 0; i < 9; ++i)
-               count += sprintf(buf + count, "%02x ", rom[i]);
-       count += sprintf(buf + count, ": crc=%02x %s\n",
+               c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rom[i]);
+       c -= snprintf(buf + PAGE_SIZE - c, c, ": crc=%02x %s\n",
                           crc, (verdict) ? "YES" : "NO");
        if (verdict)
                memcpy(sl->rom, rom, sizeof(sl->rom));
        else
-               dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
+               dev_warn(device, "18S20 doesn't respond to CONVERT_TEMP.\n");
 
        for (i = 0; i < 9; ++i)
-               count += sprintf(buf + count, "%02x ", sl->rom[i]);
+               c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", sl->rom[i]);
 
-       count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
-out:
+       c -= snprintf(buf + PAGE_SIZE - c, c, "t=%d\n",
+               w1_convert_temp(rom, sl->family->fid));
        mutex_unlock(&dev->mutex);
 
-       return count;
+       return PAGE_SIZE - c;
 }
 
 static int __init w1_therm_init(void)
index 7293c9b11f9160e2b80f89e8e9c63d6bdfd6553f..3b615d4022ee98f8abd155d33301220a51386cae 100644 (file)
@@ -46,19 +46,17 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
 static int w1_timeout = 10;
-static int w1_control_timeout = 1;
 int w1_max_slave_count = 10;
 int w1_max_slave_ttl = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
-module_param_named(control_timeout, w1_control_timeout, int, 0);
 module_param_named(max_slave_count, w1_max_slave_count, int, 0);
 module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
 
 DEFINE_MUTEX(w1_mlock);
 LIST_HEAD(w1_masters);
 
-static struct task_struct *w1_control_thread;
+static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn);
 
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
@@ -83,10 +81,10 @@ static void w1_slave_release(struct device *dev)
 {
        struct w1_slave *sl = dev_to_w1_slave(dev);
 
-       printk("%s: Releasing %s.\n", __func__, sl->name);
+       dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
 
        while (atomic_read(&sl->refcnt)) {
-               printk("Waiting for %s to become free: refcnt=%d.\n",
+               dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
                                sl->name, atomic_read(&sl->refcnt));
                if (msleep_interruptible(1000))
                        flush_signals(current);
@@ -105,35 +103,20 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a
        return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_slave_read_id(struct kobject *kobj,
-                               struct bin_attribute *bin_attr,
-                               char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read_id(struct device *dev,
+       struct device_attribute *attr, char *buf)
 {
-       struct w1_slave *sl = kobj_to_w1_slave(kobj);
-
-       if (off > 8) {
-               count = 0;
-       } else {
-               if (off + count > 8)
-                       count = 8 - off;
-
-               memcpy(buf, (u8 *)&sl->reg_num, count);
-       }
+       struct w1_slave *sl = dev_to_w1_slave(dev);
+       ssize_t count = sizeof(sl->reg_num);
 
+       memcpy(buf, (u8 *)&sl->reg_num, count);
        return count;
 }
 
 static struct device_attribute w1_slave_attr_name =
        __ATTR(name, S_IRUGO, w1_slave_read_name, NULL);
-
-static struct bin_attribute w1_slave_attr_bin_id = {
-      .attr = {
-              .name = "id",
-              .mode = S_IRUGO,
-      },
-      .size = 8,
-      .read = w1_slave_read_id,
-};
+static struct device_attribute w1_slave_attr_id =
+       __ATTR(id, S_IRUGO, w1_slave_read_id, NULL);
 
 /* Default family */
 
@@ -250,11 +233,16 @@ static ssize_t w1_master_attribute_store_search(struct device * dev,
                                                struct device_attribute *attr,
                                                const char * buf, size_t count)
 {
+       long tmp;
        struct w1_master *md = dev_to_w1_master(dev);
 
+       if (strict_strtol(buf, 0, &tmp) == -EINVAL)
+               return -EINVAL;
+
        mutex_lock(&md->mutex);
-       md->search_count = simple_strtol(buf, NULL, 0);
+       md->search_count = tmp;
        mutex_unlock(&md->mutex);
+       wake_up_process(md->thread);
 
        return count;
 }
@@ -273,6 +261,38 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
        return count;
 }
 
+static ssize_t w1_master_attribute_store_pullup(struct device *dev,
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       long tmp;
+       struct w1_master *md = dev_to_w1_master(dev);
+
+       if (strict_strtol(buf, 0, &tmp) == -EINVAL)
+               return -EINVAL;
+
+       mutex_lock(&md->mutex);
+       md->enable_pullup = tmp;
+       mutex_unlock(&md->mutex);
+       wake_up_process(md->thread);
+
+       return count;
+}
+
+static ssize_t w1_master_attribute_show_pullup(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf)
+{
+       struct w1_master *md = dev_to_w1_master(dev);
+       ssize_t count;
+
+       mutex_lock(&md->mutex);
+       count = sprintf(buf, "%d\n", md->enable_pullup);
+       mutex_unlock(&md->mutex);
+
+       return count;
+}
+
 static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct w1_master *md = dev_to_w1_master(dev);
@@ -324,7 +344,8 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
        return count;
 }
 
-static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t w1_master_attribute_show_slaves(struct device *dev,
+       struct device_attribute *attr, char *buf)
 {
        struct w1_master *md = dev_to_w1_master(dev);
        int c = PAGE_SIZE;
@@ -349,6 +370,135 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device
        return PAGE_SIZE - c;
 }
 
+static ssize_t w1_master_attribute_show_add(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       int c = PAGE_SIZE;
+       c -= snprintf(buf+PAGE_SIZE - c, c,
+               "write device id xx-xxxxxxxxxxxx to add slave\n");
+       return PAGE_SIZE - c;
+}
+
+static int w1_atoreg_num(struct device *dev, const char *buf, size_t count,
+       struct w1_reg_num *rn)
+{
+       unsigned int family;
+       unsigned long long id;
+       int i;
+       u64 rn64_le;
+
+       /* The CRC value isn't read from the user because the sysfs directory
+        * doesn't include it and most messages from the bus search don't
+        * print it either.  It would be unreasonable for the user to then
+        * provide it.
+        */
+       const char *error_msg = "bad slave string format, expecting "
+               "ff-dddddddddddd\n";
+
+       if (buf[2] != '-') {
+               dev_err(dev, "%s", error_msg);
+               return -EINVAL;
+       }
+       i = sscanf(buf, "%02x-%012llx", &family, &id);
+       if (i != 2) {
+               dev_err(dev, "%s", error_msg);
+               return -EINVAL;
+       }
+       rn->family = family;
+       rn->id = id;
+
+       rn64_le = cpu_to_le64(*(u64 *)rn);
+       rn->crc = w1_calc_crc8((u8 *)&rn64_le, 7);
+
+#if 0
+       dev_info(dev, "With CRC device is %02x.%012llx.%02x.\n",
+                 rn->family, (unsigned long long)rn->id, rn->crc);
+#endif
+
+       return 0;
+}
+
+/* Searches the slaves in the w1_master and returns a pointer or NULL.
+ * Note: must hold the mutex
+ */
+static struct w1_slave *w1_slave_search_device(struct w1_master *dev,
+       struct w1_reg_num *rn)
+{
+       struct w1_slave *sl;
+       list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+               if (sl->reg_num.family == rn->family &&
+                               sl->reg_num.id == rn->id &&
+                               sl->reg_num.crc == rn->crc) {
+                       return sl;
+               }
+       }
+       return NULL;
+}
+
+static ssize_t w1_master_attribute_store_add(struct device *dev,
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct w1_master *md = dev_to_w1_master(dev);
+       struct w1_reg_num rn;
+       struct w1_slave *sl;
+       ssize_t result = count;
+
+       if (w1_atoreg_num(dev, buf, count, &rn))
+               return -EINVAL;
+
+       mutex_lock(&md->mutex);
+       sl = w1_slave_search_device(md, &rn);
+       /* It would be nice to do a targeted search one the one-wire bus
+        * for the new device to see if it is out there or not.  But the
+        * current search doesn't support that.
+        */
+       if (sl) {
+               dev_info(dev, "Device %s already exists\n", sl->name);
+               result = -EINVAL;
+       } else {
+               w1_attach_slave_device(md, &rn);
+       }
+       mutex_unlock(&md->mutex);
+
+       return result;
+}
+
+static ssize_t w1_master_attribute_show_remove(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       int c = PAGE_SIZE;
+       c -= snprintf(buf+PAGE_SIZE - c, c,
+               "write device id xx-xxxxxxxxxxxx to remove slave\n");
+       return PAGE_SIZE - c;
+}
+
+static ssize_t w1_master_attribute_store_remove(struct device *dev,
+                                               struct device_attribute *attr,
+                                               const char *buf, size_t count)
+{
+       struct w1_master *md = dev_to_w1_master(dev);
+       struct w1_reg_num rn;
+       struct w1_slave *sl;
+       ssize_t result = count;
+
+       if (w1_atoreg_num(dev, buf, count, &rn))
+               return -EINVAL;
+
+       mutex_lock(&md->mutex);
+       sl = w1_slave_search_device(md, &rn);
+       if (sl) {
+               w1_slave_detach(sl);
+       } else {
+               dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family,
+                       (unsigned long long)rn.id);
+               result = -EINVAL;
+       }
+       mutex_unlock(&md->mutex);
+
+       return result;
+}
+
 #define W1_MASTER_ATTR_RO(_name, _mode)                                \
        struct device_attribute w1_master_attribute_##_name =   \
                __ATTR(w1_master_##_name, _mode,                \
@@ -368,6 +518,9 @@ static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
 static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
 static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
 static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(pullup, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(add, S_IRUGO | S_IWUGO);
+static W1_MASTER_ATTR_RW(remove, S_IRUGO | S_IWUGO);
 
 static struct attribute *w1_master_default_attrs[] = {
        &w1_master_attribute_name.attr,
@@ -378,6 +531,9 @@ static struct attribute *w1_master_default_attrs[] = {
        &w1_master_attribute_timeout.attr,
        &w1_master_attribute_pointer.attr,
        &w1_master_attribute_search.attr,
+       &w1_master_attribute_pullup.attr,
+       &w1_master_attribute_add.attr,
+       &w1_master_attribute_remove.attr,
        NULL
 };
 
@@ -390,7 +546,7 @@ int w1_create_master_attributes(struct w1_master *master)
        return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
 }
 
-static void w1_destroy_master_attributes(struct w1_master *master)
+void w1_destroy_master_attributes(struct w1_master *master)
 {
        sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
 }
@@ -479,7 +635,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        }
 
        /* Create "id" entry */
-       err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+       err = device_create_file(&sl->dev, &w1_slave_attr_id);
        if (err < 0) {
                dev_err(&sl->dev,
                        "sysfs file creation for [%s] failed. err=%d\n",
@@ -501,7 +657,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        return 0;
 
 out_rem2:
-       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+       device_remove_file(&sl->dev, &w1_slave_attr_id);
 out_rem1:
        device_remove_file(&sl->dev, &w1_slave_attr_name);
 out_unreg:
@@ -567,7 +723,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
        return 0;
 }
 
-static void w1_slave_detach(struct w1_slave *sl)
+void w1_slave_detach(struct w1_slave *sl)
 {
        struct w1_netlink_msg msg;
 
@@ -583,7 +739,7 @@ static void w1_slave_detach(struct w1_slave *sl)
        msg.type = W1_SLAVE_REMOVE;
        w1_netlink_send(sl->master, &msg);
 
-       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_attr_bin_id);
+       device_remove_file(&sl->dev, &w1_slave_attr_id);
        device_remove_file(&sl->dev, &w1_slave_attr_name);
        device_unregister(&sl->dev);
 
@@ -591,24 +747,6 @@ static void w1_slave_detach(struct w1_slave *sl)
        kfree(sl);
 }
 
-static struct w1_master *w1_search_master(void *data)
-{
-       struct w1_master *dev;
-       int found = 0;
-
-       mutex_lock(&w1_mlock);
-       list_for_each_entry(dev, &w1_masters, w1_master_entry) {
-               if (dev->bus_master->data == data) {
-                       found = 1;
-                       atomic_inc(&dev->refcnt);
-                       break;
-               }
-       }
-       mutex_unlock(&w1_mlock);
-
-       return (found)?dev:NULL;
-}
-
 struct w1_master *w1_search_master_id(u32 id)
 {
        struct w1_master *dev;
@@ -656,55 +794,56 @@ struct w1_slave *w1_search_slave(struct w1_reg_num *id)
        return (found)?sl:NULL;
 }
 
-void w1_reconnect_slaves(struct w1_family *f)
+void w1_reconnect_slaves(struct w1_family *f, int attach)
 {
+       struct w1_slave *sl, *sln;
        struct w1_master *dev;
 
        mutex_lock(&w1_mlock);
        list_for_each_entry(dev, &w1_masters, w1_master_entry) {
-               dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
-                               dev->name, f->fid);
-               set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+               dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
+                       "for family %02x.\n", dev->name, f->fid);
+               mutex_lock(&dev->mutex);
+               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+                       /* If it is a new family, slaves with the default
+                        * family driver and are that family will be
+                        * connected.  If the family is going away, devices
+                        * matching that family are reconneced.
+                        */
+                       if ((attach && sl->family->fid == W1_FAMILY_DEFAULT
+                               && sl->reg_num.family == f->fid) ||
+                               (!attach && sl->family->fid == f->fid)) {
+                               struct w1_reg_num rn;
+
+                               memcpy(&rn, &sl->reg_num, sizeof(rn));
+                               w1_slave_detach(sl);
+
+                               w1_attach_slave_device(dev, &rn);
+                       }
+               }
+               dev_dbg(&dev->dev, "Reconnecting slaves in device %s "
+                       "has been finished.\n", dev->name);
+               mutex_unlock(&dev->mutex);
        }
        mutex_unlock(&w1_mlock);
 }
 
-static void w1_slave_found(void *data, u64 rn)
+static void w1_slave_found(struct w1_master *dev, u64 rn)
 {
-       int slave_count;
        struct w1_slave *sl;
-       struct list_head *ent;
        struct w1_reg_num *tmp;
-       struct w1_master *dev;
        u64 rn_le = cpu_to_le64(rn);
 
-       dev = w1_search_master(data);
-       if (!dev) {
-               printk(KERN_ERR "Failed to find w1 master device for data %p, "
-                      "it is impossible.\n", data);
-               return;
-       }
+       atomic_inc(&dev->refcnt);
 
        tmp = (struct w1_reg_num *) &rn;
 
-       slave_count = 0;
-       list_for_each(ent, &dev->slist) {
-
-               sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
-               if (sl->reg_num.family == tmp->family &&
-                   sl->reg_num.id == tmp->id &&
-                   sl->reg_num.crc == tmp->crc) {
-                       set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
-                       break;
-               }
-
-               slave_count++;
-       }
-
-       if (slave_count == dev->slave_count &&
-               rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn_le, 7)) {
-               w1_attach_slave_device(dev, tmp);
+       sl = w1_slave_search_device(dev, tmp);
+       if (sl) {
+               set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+       } else {
+               if (rn && tmp->crc == w1_calc_crc8((u8 *)&rn_le, 7))
+                       w1_attach_slave_device(dev, tmp);
        }
 
        atomic_dec(&dev->refcnt);
@@ -779,80 +918,20 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
                        /* extract the direction taken & update the device number */
                        tmp64 = (triplet_ret >> 2);
                        rn |= (tmp64 << i);
+
+                       if (kthread_should_stop()) {
+                               dev_dbg(&dev->dev, "Abort w1_search\n");
+                               return;
+                       }
                }
 
                if ( (triplet_ret & 0x03) != 0x03 ) {
                        if ( (desc_bit == last_zero) || (last_zero < 0))
                                last_device = 1;
                        desc_bit = last_zero;
-                       cb(dev->bus_master->data, rn);
-               }
-       }
-}
-
-static int w1_control(void *data)
-{
-       struct w1_slave *sl, *sln;
-       struct w1_master *dev, *n;
-       int have_to_wait = 0;
-
-       set_freezable();
-       while (!kthread_should_stop() || have_to_wait) {
-               have_to_wait = 0;
-
-               try_to_freeze();
-               msleep_interruptible(w1_control_timeout * 1000);
-
-               list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
-                       if (!kthread_should_stop() && !dev->flags)
-                               continue;
-                       /*
-                        * Little race: we can create thread but not set the flag.
-                        * Get a chance for external process to set flag up.
-                        */
-                       if (!dev->initialized) {
-                               have_to_wait = 1;
-                               continue;
-                       }
-
-                       if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
-                               set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
-
-                               mutex_lock(&w1_mlock);
-                               list_del(&dev->w1_master_entry);
-                               mutex_unlock(&w1_mlock);
-
-                               mutex_lock(&dev->mutex);
-                               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-                                       w1_slave_detach(sl);
-                               }
-                               w1_destroy_master_attributes(dev);
-                               mutex_unlock(&dev->mutex);
-                               atomic_dec(&dev->refcnt);
-                               continue;
-                       }
-
-                       if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
-                               dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
-                               mutex_lock(&dev->mutex);
-                               list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-                                       if (sl->family->fid == W1_FAMILY_DEFAULT) {
-                                               struct w1_reg_num rn;
-
-                                               memcpy(&rn, &sl->reg_num, sizeof(rn));
-                                               w1_slave_detach(sl);
-
-                                               w1_attach_slave_device(dev, &rn);
-                                       }
-                               }
-                               dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name);
-                               clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
-                               mutex_unlock(&dev->mutex);
-                       }
+                       cb(dev, rn);
                }
        }
-
-       return 0;
 }
 
 void w1_search_process(struct w1_master *dev, u8 search_type)
@@ -878,23 +957,29 @@ void w1_search_process(struct w1_master *dev, u8 search_type)
 int w1_process(void *data)
 {
        struct w1_master *dev = (struct w1_master *) data;
+       /* As long as w1_timeout is only set by a module parameter the sleep
+        * time can be calculated in jiffies once.
+        */
+       const unsigned long jtime = msecs_to_jiffies(w1_timeout * 1000);
+
+       while (!kthread_should_stop()) {
+               if (dev->search_count) {
+                       mutex_lock(&dev->mutex);
+                       w1_search_process(dev, W1_SEARCH);
+                       mutex_unlock(&dev->mutex);
+               }
 
-       while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
                try_to_freeze();
-               msleep_interruptible(w1_timeout * 1000);
+               __set_current_state(TASK_INTERRUPTIBLE);
 
-               if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
+               if (kthread_should_stop())
                        break;
 
-               if (!dev->initialized)
-                       continue;
-
-               if (dev->search_count == 0)
-                       continue;
-
-               mutex_lock(&dev->mutex);
-               w1_search_process(dev, W1_SEARCH);
-               mutex_unlock(&dev->mutex);
+               /* Only sleep when the search is active. */
+               if (dev->search_count)
+                       schedule_timeout(jtime);
+               else
+                       schedule();
        }
 
        atomic_dec(&dev->refcnt);
@@ -932,18 +1017,13 @@ static int w1_init(void)
                goto err_out_master_unregister;
        }
 
-       w1_control_thread = kthread_run(w1_control, NULL, "w1_control");
-       if (IS_ERR(w1_control_thread)) {
-               retval = PTR_ERR(w1_control_thread);
-               printk(KERN_ERR "Failed to create control thread. err=%d\n",
-                       retval);
-               goto err_out_slave_unregister;
-       }
-
        return 0;
 
+#if 0
+/* For undoing the slave register if there was a step after it. */
 err_out_slave_unregister:
        driver_unregister(&w1_slave_driver);
+#endif
 
 err_out_master_unregister:
        driver_unregister(&w1_master_driver);
@@ -959,13 +1039,12 @@ static void w1_fini(void)
 {
        struct w1_master *dev;
 
+       /* Set netlink removal messages and some cleanup */
        list_for_each_entry(dev, &w1_masters, w1_master_entry)
                __w1_remove_master_device(dev);
 
        w1_fini_netlink();
 
-       kthread_stop(w1_control_thread);
-
        driver_unregister(&w1_slave_driver);
        driver_unregister(&w1_master_driver);
        bus_unregister(&w1_bus_type);
index f1df5343f4ad4a25ab87f7c1782216f1135eec33..cdaa6fffbfc73c2c6bd6be3eefdd2a600ca3f82e 100644 (file)
@@ -46,7 +46,6 @@ struct w1_reg_num
 #include "w1_family.h"
 
 #define W1_MAXNAMELEN          32
-#define W1_SLAVE_DATA_SIZE     128
 
 #define W1_SEARCH              0xF0
 #define W1_ALARM_SEARCH                0xEC
@@ -77,7 +76,7 @@ struct w1_slave
        struct completion       released;
 };
 
-typedef void (* w1_slave_found_callback)(void *, u64);
+typedef void (*w1_slave_found_callback)(struct w1_master *, u64);
 
 
 /**
@@ -142,12 +141,18 @@ struct w1_bus_master
         */
        u8              (*reset_bus)(void *);
 
-       /** Really nice hardware can handles the different types of ROM search */
-       void            (*search)(void *, u8, w1_slave_found_callback);
-};
+       /**
+        * Put out a strong pull-up pulse of the specified duration.
+        * @return -1=Error, 0=completed
+        */
+       u8              (*set_pullup)(void *, int);
 
-#define W1_MASTER_NEED_EXIT            0
-#define W1_MASTER_NEED_RECONNECT       1
+       /** Really nice hardware can handles the different types of ROM search
+        *  w1_master* is passed to the slave found callback.
+        */
+       void            (*search)(void *, struct w1_master *,
+               u8, w1_slave_found_callback);
+};
 
 struct w1_master
 {
@@ -167,7 +172,10 @@ struct w1_master
        void                    *priv;
        int                     priv_size;
 
-       long                    flags;
+       /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */
+       int                     enable_pullup;
+       /** 5V strong pullup duration in milliseconds, zero disabled. */
+       int                     pullup_duration;
 
        struct task_struct      *thread;
        struct mutex            mutex;
@@ -181,12 +189,21 @@ struct w1_master
 };
 
 int w1_create_master_attributes(struct w1_master *);
+void w1_destroy_master_attributes(struct w1_master *master);
 void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
 void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
 struct w1_slave *w1_search_slave(struct w1_reg_num *id);
 void w1_search_process(struct w1_master *dev, u8 search_type);
 struct w1_master *w1_search_master_id(u32 id);
 
+/* Disconnect and reconnect devices in the given family.  Used for finding
+ * unclaimed devices after a family has been registered or releasing devices
+ * after a family has been unregistered.  Set attach to 1 when a new family
+ * has just been registered, to 0 when it has been unregistered.
+ */
+void w1_reconnect_slaves(struct w1_family *f, int attach);
+void w1_slave_detach(struct w1_slave *sl);
+
 u8 w1_triplet(struct w1_master *dev, int bdir);
 void w1_write_8(struct w1_master *, u8);
 int w1_reset_bus(struct w1_master *);
@@ -194,6 +211,7 @@ u8 w1_calc_crc8(u8 *, int);
 void w1_write_block(struct w1_master *, const u8 *, int);
 u8 w1_read_block(struct w1_master *, u8 *, int);
 int w1_reset_select_slave(struct w1_slave *sl);
+void w1_next_pullup(struct w1_master *, int);
 
 static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
 {
index a3c95bd6890af7ae20a8c63b00d3b0082f714ad0..4a099041f28a8a80a73b0d4d63da6be496efbdc8 100644 (file)
@@ -48,12 +48,12 @@ int w1_register_family(struct w1_family *newf)
 
        if (!ret) {
                atomic_set(&newf->refcnt, 0);
-               newf->need_exit = 0;
                list_add_tail(&newf->family_entry, &w1_families);
        }
        spin_unlock(&w1_flock);
 
-       w1_reconnect_slaves(newf);
+       /* check default devices against the new set of drivers */
+       w1_reconnect_slaves(newf, 1);
 
        return ret;
 }
@@ -72,11 +72,11 @@ void w1_unregister_family(struct w1_family *fent)
                        break;
                }
        }
-
-       fent->need_exit = 1;
-
        spin_unlock(&w1_flock);
 
+       /* deatch devices using this family code */
+       w1_reconnect_slaves(fent, 0);
+
        while (atomic_read(&fent->refcnt)) {
                printk(KERN_INFO "Waiting for family %u to become free: refcnt=%d.\n",
                                fent->fid, atomic_read(&fent->refcnt));
@@ -109,8 +109,7 @@ struct w1_family * w1_family_registered(u8 fid)
 
 static void __w1_family_put(struct w1_family *f)
 {
-       if (atomic_dec_and_test(&f->refcnt))
-               f->need_exit = 1;
+       atomic_dec(&f->refcnt);
 }
 
 void w1_family_put(struct w1_family *f)
index ef1e1dafa19a36c61a24d2fa126d9f9bd4cda118..3ca1b9298f2143dea98a2973021cdafe254bad38 100644 (file)
@@ -33,6 +33,7 @@
 #define W1_THERM_DS1822        0x22
 #define W1_EEPROM_DS2433       0x23
 #define W1_THERM_DS18B20       0x28
+#define W1_EEPROM_DS2431       0x2D
 #define W1_FAMILY_DS2760       0x30
 
 #define MAXNAMELEN             32
@@ -53,7 +54,6 @@ struct w1_family
        struct w1_family_ops    *fops;
 
        atomic_t                refcnt;
-       u8                      need_exit;
 };
 
 extern spinlock_t w1_flock;
@@ -63,6 +63,5 @@ void __w1_family_get(struct w1_family *);
 struct w1_family * w1_family_registered(u8);
 void w1_unregister_family(struct w1_family *);
 int w1_register_family(struct w1_family *);
-void w1_reconnect_slaves(struct w1_family *f);
 
 #endif /* __W1_FAMILY_H */
index 6840dfebe4d4c82a5abc242a8ee1d66570f100ab..a3a54567bfba87f041b8d0735aa7d96996a604d8 100644 (file)
 #include "w1_netlink.h"
 #include "w1_int.h"
 
-static u32 w1_ids = 1;
+static int w1_search_count = -1; /* Default is continual scan */
+module_param_named(search_count, w1_search_count, int, 0);
+
+static int w1_enable_pullup = 1;
+module_param_named(enable_pullup, w1_enable_pullup, int, 0);
 
 static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
                                       struct device_driver *driver,
@@ -59,8 +63,12 @@ static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
        dev->initialized        = 0;
        dev->id                 = id;
        dev->slave_ttl          = slave_ttl;
-        dev->search_count      = -1; /* continual scan */
+       dev->search_count       = w1_search_count;
+       dev->enable_pullup      = w1_enable_pullup;
 
+       /* 1 for w1_process to decrement
+        * 1 for __w1_remove_master_device to decrement
+        */
        atomic_set(&dev->refcnt, 2);
 
        INIT_LIST_HEAD(&dev->slist);
@@ -93,9 +101,10 @@ static void w1_free_dev(struct w1_master *dev)
 
 int w1_add_master_device(struct w1_bus_master *master)
 {
-       struct w1_master *dev;
+       struct w1_master *dev, *entry;
        int retval = 0;
        struct w1_netlink_msg msg;
+       int id, found;
 
         /* validate minimum functionality */
         if (!(master->touch_bit && master->reset_bus) &&
@@ -104,10 +113,50 @@ int w1_add_master_device(struct w1_bus_master *master)
                printk(KERN_ERR "w1_add_master_device: invalid function set\n");
                return(-EINVAL);
         }
+       /* While it would be electrically possible to make a device that
+        * generated a strong pullup in bit bang mode, only hardare that
+        * controls 1-wire time frames are even expected to support a strong
+        * pullup.  w1_io.c would need to support calling set_pullup before
+        * the last write_bit operation of a w1_write_8 which it currently
+        * doesn't.
+        */
+       if (!master->write_byte && !master->touch_bit && master->set_pullup) {
+               printk(KERN_ERR "w1_add_master_device: set_pullup requires "
+                       "write_byte or touch_bit, disabling\n");
+               master->set_pullup = NULL;
+       }
+
+       /* Lock until the device is added (or not) to w1_masters. */
+       mutex_lock(&w1_mlock);
+       /* Search for the first available id (starting at 1). */
+       id = 0;
+       do {
+               ++id;
+               found = 0;
+               list_for_each_entry(entry, &w1_masters, w1_master_entry) {
+                       if (entry->id == id) {
+                               found = 1;
+                               break;
+                       }
+               }
+       } while (found);
 
-       dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_master_driver, &w1_master_device);
-       if (!dev)
+       dev = w1_alloc_dev(id, w1_max_slave_count, w1_max_slave_ttl,
+               &w1_master_driver, &w1_master_device);
+       if (!dev) {
+               mutex_unlock(&w1_mlock);
                return -ENOMEM;
+       }
+
+       retval =  w1_create_master_attributes(dev);
+       if (retval) {
+               mutex_unlock(&w1_mlock);
+               goto err_out_free_dev;
+       }
+
+       memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
+
+       dev->initialized = 1;
 
        dev->thread = kthread_run(&w1_process, dev, "%s", dev->name);
        if (IS_ERR(dev->thread)) {
@@ -115,18 +164,10 @@ int w1_add_master_device(struct w1_bus_master *master)
                dev_err(&dev->dev,
                         "Failed to create new kernel thread. err=%d\n",
                         retval);
-               goto err_out_free_dev;
+               mutex_unlock(&w1_mlock);
+               goto err_out_rm_attr;
        }
 
-       retval =  w1_create_master_attributes(dev);
-       if (retval)
-               goto err_out_kill_thread;
-
-       memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
-
-       dev->initialized = 1;
-
-       mutex_lock(&w1_mlock);
        list_add(&dev->w1_master_entry, &w1_masters);
        mutex_unlock(&w1_mlock);
 
@@ -137,8 +178,12 @@ int w1_add_master_device(struct w1_bus_master *master)
 
        return 0;
 
+#if 0 /* Thread cleanup code, not required currently. */
 err_out_kill_thread:
        kthread_stop(dev->thread);
+#endif
+err_out_rm_attr:
+       w1_destroy_master_attributes(dev);
 err_out_free_dev:
        w1_free_dev(dev);
 
@@ -148,10 +193,21 @@ err_out_free_dev:
 void __w1_remove_master_device(struct w1_master *dev)
 {
        struct w1_netlink_msg msg;
+       struct w1_slave *sl, *sln;
 
-       set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
        kthread_stop(dev->thread);
 
+       mutex_lock(&w1_mlock);
+       list_del(&dev->w1_master_entry);
+       mutex_unlock(&w1_mlock);
+
+       mutex_lock(&dev->mutex);
+       list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry)
+               w1_slave_detach(sl);
+       w1_destroy_master_attributes(dev);
+       mutex_unlock(&dev->mutex);
+       atomic_dec(&dev->refcnt);
+
        while (atomic_read(&dev->refcnt)) {
                dev_info(&dev->dev, "Waiting for %s to become free: refcnt=%d.\n",
                                dev->name, atomic_read(&dev->refcnt));
index 30b6fbf83bd4a9fcead97864e679d6c7bd222d07..f4f82f1f486ebdd2c70c9ff80c5fdb4e99f03fe2 100644 (file)
@@ -92,6 +92,40 @@ static void w1_write_bit(struct w1_master *dev, int bit)
        }
 }
 
+/**
+ * Pre-write operation, currently only supporting strong pullups.
+ * Program the hardware for a strong pullup, if one has been requested and
+ * the hardware supports it.
+ *
+ * @param dev     the master device
+ */
+static void w1_pre_write(struct w1_master *dev)
+{
+       if (dev->pullup_duration &&
+               dev->enable_pullup && dev->bus_master->set_pullup) {
+               dev->bus_master->set_pullup(dev->bus_master->data,
+                       dev->pullup_duration);
+       }
+}
+
+/**
+ * Post-write operation, currently only supporting strong pullups.
+ * If a strong pullup was requested, clear it if the hardware supports
+ * them, or execute the delay otherwise, in either case clear the request.
+ *
+ * @param dev     the master device
+ */
+static void w1_post_write(struct w1_master *dev)
+{
+       if (dev->pullup_duration) {
+               if (dev->enable_pullup && dev->bus_master->set_pullup)
+                       dev->bus_master->set_pullup(dev->bus_master->data, 0);
+               else
+                       msleep(dev->pullup_duration);
+               dev->pullup_duration = 0;
+       }
+}
+
 /**
  * Writes 8 bits.
  *
@@ -102,11 +136,17 @@ void w1_write_8(struct w1_master *dev, u8 byte)
 {
        int i;
 
-       if (dev->bus_master->write_byte)
+       if (dev->bus_master->write_byte) {
+               w1_pre_write(dev);
                dev->bus_master->write_byte(dev->bus_master->data, byte);
+       }
        else
-               for (i = 0; i < 8; ++i)
+               for (i = 0; i < 8; ++i) {
+                       if (i == 7)
+                               w1_pre_write(dev);
                        w1_touch_bit(dev, (byte >> i) & 0x1);
+               }
+       w1_post_write(dev);
 }
 EXPORT_SYMBOL_GPL(w1_write_8);
 
@@ -203,11 +243,14 @@ void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 {
        int i;
 
-       if (dev->bus_master->write_block)
+       if (dev->bus_master->write_block) {
+               w1_pre_write(dev);
                dev->bus_master->write_block(dev->bus_master->data, buf, len);
+       }
        else
                for (i = 0; i < len; ++i)
-                       w1_write_8(dev, buf[i]);
+                       w1_write_8(dev, buf[i]); /* calls w1_pre_write */
+       w1_post_write(dev);
 }
 EXPORT_SYMBOL_GPL(w1_write_block);
 
@@ -250,12 +293,24 @@ int w1_reset_bus(struct w1_master *dev)
                result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
        else {
                dev->bus_master->write_bit(dev->bus_master->data, 0);
+               /* minimum 480, max ? us
+                * be nice and sleep, except 18b20 spec lists 960us maximum,
+                * so until we can sleep with microsecond accuracy, spin.
+                * Feel free to come up with some other way to give up the
+                * cpu for such a short amount of time AND get it back in
+                * the maximum amount of time.
+                */
                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);
+               /* minmum 70 (above) + 410 = 480 us
+                * There aren't any timing requirements between a reset and
+                * the following transactions.  Sleeping is safe here.
+                */
+               /* w1_delay(410); min required time */
+               msleep(1);
        }
 
        return result;
@@ -277,7 +332,8 @@ void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_cal
 {
        dev->attempts++;
        if (dev->bus_master->search)
-               dev->bus_master->search(dev->bus_master->data, search_type, cb);
+               dev->bus_master->search(dev->bus_master->data, dev,
+                       search_type, cb);
        else
                w1_search(dev, search_type, cb);
 }
@@ -305,3 +361,20 @@ int w1_reset_select_slave(struct w1_slave *sl)
        return 0;
 }
 EXPORT_SYMBOL_GPL(w1_reset_select_slave);
+
+/**
+ * Put out a strong pull-up of the specified duration after the next write
+ * operation.  Not all hardware supports strong pullups.  Hardware that
+ * doesn't support strong pullups will sleep for the given time after the
+ * write operation without a strong pullup.  This is a one shot request for
+ * the next write, specifying zero will clear a previous request.
+ * The w1 master lock must be held.
+ *
+ * @param delay        time in milliseconds
+ * @return     0=success, anything else=error
+ */
+void w1_next_pullup(struct w1_master *dev, int delay)
+{
+       dev->pullup_duration = delay;
+}
+EXPORT_SYMBOL_GPL(w1_next_pullup);
index 047c791427aa573069a39fb9060d53c59c9d8308..c061c3f18e7cbc47d427c03610e88f8d95d5cdf4 100644 (file)
@@ -55,7 +55,7 @@ enum {
        Opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_debug, "debug=%x"},
        {Opt_dfltuid, "dfltuid=%u"},
        {Opt_dfltgid, "dfltgid=%u"},
index f54a157a029689fae2556c2f3989f6475e123ec7..9e9d70c02a07c9a8876f71c3445ac5092c563810 100644 (file)
@@ -220,17 +220,16 @@ config JBD
        tristate
        help
          This is a generic journalling layer for block devices.  It is
-         currently used by the ext3 and OCFS2 file systems, but it could
-         also be used to add journal support to other file systems or block
+         currently used by the ext3 file system, but it could also be
+         used to add journal support to other file systems or block
          devices such as RAID or LVM.
 
-         If you are using the ext3 or OCFS2 file systems, you need to
-         say Y here. If you are not using ext3 OCFS2 then you will probably
-         want to say N.
+         If you are using the ext3 file system, you need to say Y here.
+         If you are not using ext3 then you will probably want to say N.
 
          To compile this device as a module, choose M here: the module will be
-         called jbd.  If you are compiling ext3 or OCFS2 into the kernel,
-         you cannot compile this code as a module.
+         called jbd.  If you are compiling ext3 into the kernel, you
+         cannot compile this code as a module.
 
 config JBD_DEBUG
        bool "JBD (ext3) debugging support"
@@ -254,15 +253,16 @@ config JBD2
        help
          This is a generic journaling layer for block devices that support
          both 32-bit and 64-bit block numbers.  It is currently used by
-         the ext4 filesystem, but it could also be used to add
+         the ext4 and OCFS2 filesystems, but it could also be used to add
          journal support to other file systems or block devices such
          as RAID or LVM.
 
-         If you are using ext4, you need to say Y here. If you are not
-         using ext4 then you will probably want to say N.
+         If you are using ext4 or OCFS2, you need to say Y here.
+         If you are not using ext4 or OCFS2 then you will
+         probably want to say N.
 
          To compile this device as a module, choose M here. The module will be
-         called jbd2.  If you are compiling ext4 into the kernel,
+         called jbd2.  If you are compiling ext4 or OCFS2 into the kernel,
          you cannot compile this code as a module.
 
 config JBD2_DEBUG
@@ -433,6 +433,14 @@ config FS_POSIX_ACL
        bool
        default n
 
+config FILE_LOCKING
+       bool "Enable POSIX file locking API" if EMBEDDED
+       default y
+       help
+         This option enables standard file locking support, required
+          for filesystems like NFS and for the flock() system
+          call. Disabling this option saves about 11k.
+
 source "fs/xfs/Kconfig"
 source "fs/gfs2/Kconfig"
 
@@ -440,7 +448,7 @@ config OCFS2_FS
        tristate "OCFS2 file system support"
        depends on NET && SYSFS
        select CONFIGFS_FS
-       select JBD
+       select JBD2
        select CRC32
        help
          OCFS2 is a general purpose extent based shared disk cluster file
@@ -511,6 +519,16 @@ config OCFS2_DEBUG_FS
          this option for debugging only as it is likely to decrease
          performance of the filesystem.
 
+config OCFS2_COMPAT_JBD
+       bool "Use JBD for compatibility"
+       depends on OCFS2_FS
+       default n
+       select JBD
+       help
+         The ocfs2 filesystem now uses JBD2 for its journalling.  JBD2
+         is backwards compatible with JBD.  It is safe to say N here.
+         However, if you really want to use the original JBD, say Y here.
+
 endif # BLOCK
 
 config DNOTIFY
@@ -1779,6 +1797,28 @@ config SUNRPC_XPRT_RDMA
 
          If unsure, say N.
 
+config SUNRPC_REGISTER_V4
+       bool "Register local RPC services via rpcbind v4 (EXPERIMENTAL)"
+       depends on SUNRPC && EXPERIMENTAL
+       default n
+       help
+         Sun added support for registering RPC services at an IPv6
+         address by creating two new versions of the rpcbind protocol
+         (RFC 1833).
+
+         This option enables support in the kernel RPC server for
+         registering kernel RPC services via version 4 of the rpcbind
+         protocol.  If you enable this option, you must run a portmapper
+         daemon that supports rpcbind protocol version 4.
+
+         Serving NFS over IPv6 from knfsd (the kernel's NFS server)
+         requires that you enable this option and use a portmapper that
+         supports rpcbind version 4.
+
+         If unsure, say N to get traditional behavior (register kernel
+         RPC services using only rpcbind version 2).  Distributions
+         using the legacy Linux portmapper daemon must say N here.
+
 config RPCSEC_GSS_KRB5
        tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
        depends on SUNRPC && EXPERIMENTAL
index 4a551af6f3fc956ffc4032e4c79d16c3b61294df..801db1341811d6eace2732c7238bfd9190ffff1f 100644 (file)
@@ -25,7 +25,7 @@ config BINFMT_ELF
 
 config COMPAT_BINFMT_ELF
        bool
-       depends on COMPAT && MMU
+       depends on COMPAT && BINFMT_ELF
 
 config BINFMT_ELF_FDPIC
        bool "Kernel support for FDPIC ELF binaries"
@@ -59,10 +59,12 @@ config BINFMT_SHARED_FLAT
        help
          Support FLAT shared libraries
 
+config HAVE_AOUT
+       def_bool n
+
 config BINFMT_AOUT
        tristate "Kernel support for a.out and ECOFF binaries"
-       depends on ARCH_SUPPORTS_AOUT && \
-               (X86_32 || ALPHA || ARM || M68K)
+       depends on HAVE_AOUT
        ---help---
          A.out (Assembler.OUTput) is a set of formats for libraries and
          executables used in the earliest versions of UNIX.  Linux used
index de404b00eb0cad255e28667472d7d2d75c43635a..d0c69f57e5bfdebd65a668443428c44373360ab0 100644 (file)
@@ -7,8 +7,8 @@
 
 obj-y :=       open.o read_write.o file_table.o super.o \
                char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-               ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
-               attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
+               ioctl.o readdir.o select.o fifo.o dcache.o inode.o \
+               attr.o bad_inode.o file.o filesystems.o namespace.o \
                seq_file.o xattr.o libfs.o fs-writeback.o \
                pnode.o drop_caches.o splice.o sync.o utimes.o \
                stack.o
@@ -27,6 +27,8 @@ obj-$(CONFIG_ANON_INODES)     += anon_inodes.o
 obj-$(CONFIG_SIGNALFD)         += signalfd.o
 obj-$(CONFIG_TIMERFD)          += timerfd.o
 obj-$(CONFIG_EVENTFD)          += eventfd.o
+obj-$(CONFIG_AIO)               += aio.o
+obj-$(CONFIG_FILE_LOCKING)      += locks.o
 obj-$(CONFIG_COMPAT)           += compat.o compat_ioctl.o
 
 nfsd-$(CONFIG_NFSD)            := nfsctl.o
index 26f3b43726bb98d88f1bdfbd7de19579844300de..7f83a46f2b7e45502e7c761775f96498280a32e5 100644 (file)
@@ -157,7 +157,7 @@ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
 
 enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err};
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
        {Opt_ownmask, "ownmask=%o"},
index 3a89094f93d0f1c772526be731648e90b3e5f002..8989c93193ed227e84c786e629f1fd4f1e81ce4c 100644 (file)
@@ -135,7 +135,7 @@ enum {
        Opt_verbose, Opt_volume, Opt_ignore, Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_bs, "bs=%u"},
        {Opt_mode, "mode=%o"},
        {Opt_mufs, "mufs"},
index 525f7c56e068d877e95dedea3a15dafc116fdb41..a3901769a96c4231b3b6c0cf88b9d3e6746f7468 100644 (file)
@@ -50,8 +50,8 @@ const struct address_space_operations afs_fs_aops = {
        .launder_page   = afs_launder_page,
        .releasepage    = afs_releasepage,
        .invalidatepage = afs_invalidatepage,
-       .prepare_write  = afs_prepare_write,
-       .commit_write   = afs_commit_write,
+       .write_begin    = afs_write_begin,
+       .write_end      = afs_write_end,
        .writepage      = afs_writepage,
        .writepages     = afs_writepages,
 };
index 3cb6920ff30bc6ee7f22a98a390b04119d1ae81c..67f259d99cd6f11afae3b9296b74f0f5bdde3065 100644 (file)
@@ -728,8 +728,12 @@ extern int afs_volume_release_fileserver(struct afs_vnode *,
  */
 extern int afs_set_page_dirty(struct page *);
 extern void afs_put_writeback(struct afs_writeback *);
-extern int afs_prepare_write(struct file *, struct page *, unsigned, unsigned);
-extern int afs_commit_write(struct file *, struct page *, unsigned, unsigned);
+extern int afs_write_begin(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata);
+extern int afs_write_end(struct file *file, struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata);
 extern int afs_writepage(struct page *, struct writeback_control *);
 extern int afs_writepages(struct address_space *, struct writeback_control *);
 extern int afs_write_inode(struct inode *, int);
index 250d8c4d66e40f765c383ed4531ead183112faad..aee239a048cbfad919a40bfd70fa8fcb37de26fb 100644 (file)
@@ -64,7 +64,7 @@ enum {
        afs_opt_vol,
 };
 
-static match_table_t afs_options_list = {
+static const match_table_t afs_options_list = {
        { afs_opt_cell,         "cell=%s"       },
        { afs_opt_rwpath,       "rwpath"        },
        { afs_opt_vol,          "vol=%s"        },
index 065b4e10681ae2e449b700ad01c9d3f1c75cd9ab..d6b85dab35fcc71a16ba310bb11848c7ae7e891d 100644 (file)
@@ -84,15 +84,23 @@ void afs_put_writeback(struct afs_writeback *wb)
  * partly or wholly fill a page that's under preparation for writing
  */
 static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
-                        unsigned start, unsigned len, struct page *page)
+                        loff_t pos, unsigned len, struct page *page)
 {
+       loff_t i_size;
+       unsigned eof;
        int ret;
 
-       _enter(",,%u,%u", start, len);
+       _enter(",,%llu,%u", (unsigned long long)pos, len);
 
-       ASSERTCMP(start + len, <=, PAGE_SIZE);
+       ASSERTCMP(len, <=, PAGE_CACHE_SIZE);
 
-       ret = afs_vnode_fetch_data(vnode, key, start, len, page);
+       i_size = i_size_read(&vnode->vfs_inode);
+       if (pos + len > i_size)
+               eof = i_size;
+       else
+               eof = PAGE_CACHE_SIZE;
+
+       ret = afs_vnode_fetch_data(vnode, key, 0, eof, page);
        if (ret < 0) {
                if (ret == -ENOENT) {
                        _debug("got NOENT from server"
@@ -106,110 +114,56 @@ static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
        return ret;
 }
 
-/*
- * prepare a page for being written to
- */
-static int afs_prepare_page(struct afs_vnode *vnode, struct page *page,
-                           struct key *key, unsigned offset, unsigned to)
-{
-       unsigned eof, tail, start, stop, len;
-       loff_t i_size, pos;
-       void *p;
-       int ret;
-
-       _enter("");
-
-       if (offset == 0 && to == PAGE_SIZE)
-               return 0;
-
-       p = kmap_atomic(page, KM_USER0);
-
-       i_size = i_size_read(&vnode->vfs_inode);
-       pos = (loff_t) page->index << PAGE_SHIFT;
-       if (pos >= i_size) {
-               /* partial write, page beyond EOF */
-               _debug("beyond");
-               if (offset > 0)
-                       memset(p, 0, offset);
-               if (to < PAGE_SIZE)
-                       memset(p + to, 0, PAGE_SIZE - to);
-               kunmap_atomic(p, KM_USER0);
-               return 0;
-       }
-
-       if (i_size - pos >= PAGE_SIZE) {
-               /* partial write, page entirely before EOF */
-               _debug("before");
-               tail = eof = PAGE_SIZE;
-       } else {
-               /* partial write, page overlaps EOF */
-               eof = i_size - pos;
-               _debug("overlap %u", eof);
-               tail = max(eof, to);
-               if (tail < PAGE_SIZE)
-                       memset(p + tail, 0, PAGE_SIZE - tail);
-               if (offset > eof)
-                       memset(p + eof, 0, PAGE_SIZE - eof);
-       }
-
-       kunmap_atomic(p, KM_USER0);
-
-       ret = 0;
-       if (offset > 0 || eof > to) {
-               /* need to fill one or two bits that aren't going to be written
-                * (cover both fillers in one read if there are two) */
-               start = (offset > 0) ? 0 : to;
-               stop = (eof > to) ? eof : offset;
-               len = stop - start;
-               _debug("wr=%u-%u av=0-%u rd=%u@%u",
-                      offset, to, eof, start, len);
-               ret = afs_fill_page(vnode, key, start, len, page);
-       }
-
-       _leave(" = %d", ret);
-       return ret;
-}
-
 /*
  * prepare to perform part of a write to a page
- * - the caller holds the page locked, preventing it from being written out or
- *   modified by anyone else
  */
-int afs_prepare_write(struct file *file, struct page *page,
-                     unsigned offset, unsigned to)
+int afs_write_begin(struct file *file, struct address_space *mapping,
+                   loff_t pos, unsigned len, unsigned flags,
+                   struct page **pagep, void **fsdata)
 {
        struct afs_writeback *candidate, *wb;
        struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
+       struct page *page;
        struct key *key = file->private_data;
-       pgoff_t index;
+       unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+       unsigned to = from + len;
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        int ret;
 
        _enter("{%x:%u},{%lx},%u,%u",
-              vnode->fid.vid, vnode->fid.vnode, page->index, offset, to);
+              vnode->fid.vid, vnode->fid.vnode, index, from, to);
 
        candidate = kzalloc(sizeof(*candidate), GFP_KERNEL);
        if (!candidate)
                return -ENOMEM;
        candidate->vnode = vnode;
-       candidate->first = candidate->last = page->index;
-       candidate->offset_first = offset;
+       candidate->first = candidate->last = index;
+       candidate->offset_first = from;
        candidate->to_last = to;
        candidate->usage = 1;
        candidate->state = AFS_WBACK_PENDING;
        init_waitqueue_head(&candidate->waitq);
 
+       page = __grab_cache_page(mapping, index);
+       if (!page) {
+               kfree(candidate);
+               return -ENOMEM;
+       }
+       *pagep = page;
+       /* page won't leak in error case: it eventually gets cleaned off LRU */
+
        if (!PageUptodate(page)) {
                _debug("not up to date");
-               ret = afs_prepare_page(vnode, page, key, offset, to);
+               ret = afs_fill_page(vnode, key, pos, len, page);
                if (ret < 0) {
                        kfree(candidate);
                        _leave(" = %d [prep]", ret);
                        return ret;
                }
+               SetPageUptodate(page);
        }
 
 try_again:
-       index = page->index;
        spin_lock(&vnode->writeback_lock);
 
        /* see if this page is already pending a writeback under a suitable key
@@ -242,8 +196,8 @@ try_again:
 subsume_in_current_wb:
        _debug("subsume");
        ASSERTRANGE(wb->first, <=, index, <=, wb->last);
-       if (index == wb->first && offset < wb->offset_first)
-               wb->offset_first = offset;
+       if (index == wb->first && from < wb->offset_first)
+               wb->offset_first = from;
        if (index == wb->last && to > wb->to_last)
                wb->to_last = to;
        spin_unlock(&vnode->writeback_lock);
@@ -289,17 +243,17 @@ flush_conflicting_wb:
 /*
  * finalise part of a write to a page
  */
-int afs_commit_write(struct file *file, struct page *page,
-                    unsigned offset, unsigned to)
+int afs_write_end(struct file *file, struct address_space *mapping,
+                 loff_t pos, unsigned len, unsigned copied,
+                 struct page *page, void *fsdata)
 {
        struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode);
        loff_t i_size, maybe_i_size;
 
-       _enter("{%x:%u},{%lx},%u,%u",
-              vnode->fid.vid, vnode->fid.vnode, page->index, offset, to);
+       _enter("{%x:%u},{%lx}",
+              vnode->fid.vid, vnode->fid.vnode, page->index);
 
-       maybe_i_size = (loff_t) page->index << PAGE_SHIFT;
-       maybe_i_size += to;
+       maybe_i_size = pos + copied;
 
        i_size = i_size_read(&vnode->vfs_inode);
        if (maybe_i_size > i_size) {
@@ -310,12 +264,13 @@ int afs_commit_write(struct file *file, struct page *page,
                spin_unlock(&vnode->writeback_lock);
        }
 
-       SetPageUptodate(page);
        set_page_dirty(page);
        if (PageDirty(page))
                _debug("dirtied");
+       unlock_page(page);
+       page_cache_release(page);
 
-       return 0;
+       return copied;
 }
 
 /*
index dda510d31f840dbba96834619a668f723bc99e16..b70eea1e8c59c586b89ee13d72cf641e76cabee4 100644 (file)
@@ -59,7 +59,7 @@ static const struct super_operations autofs_sops = {
 
 enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
 
-static match_table_t autofs_tokens = {
+static const match_table_t autofs_tokens = {
        {Opt_fd, "fd=%u"},
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
index f2c3b79e94d2be98f9535474ba34f86d1ebb5d92..a811c1f7d9abda7c2be12071a63e0b0502adeb2e 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_AUTOFS4_FS) += autofs4.o
 
-autofs4-objs := init.o inode.o root.o symlink.o waitq.o expire.o
+autofs4-objs := init.o inode.o root.o symlink.o waitq.o expire.o dev-ioctl.o
index 69a2f5c9231943f6adbe4497915b294fe7991a28..e0f16da00e54294912bfd3a36fab3a09d0f1741f 100644 (file)
@@ -14,6 +14,7 @@
 /* Internal header file for autofs */
 
 #include <linux/auto_fs4.h>
+#include <linux/auto_dev-ioctl.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
 
 #define AUTOFS_IOC_FIRST     AUTOFS_IOC_READY
 #define AUTOFS_IOC_COUNT     32
 
+#define AUTOFS_DEV_IOCTL_IOC_FIRST     (AUTOFS_DEV_IOCTL_VERSION)
+#define AUTOFS_DEV_IOCTL_IOC_COUNT     (AUTOFS_IOC_COUNT - 11)
+
+#define AUTOFS_TYPE_TRIGGER    (AUTOFS_TYPE_DIRECT|AUTOFS_TYPE_OFFSET)
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 /* #define DEBUG */
 
 #ifdef DEBUG
-#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __func__ , ##args); } while(0)
+#define DPRINTK(fmt, args...)                          \
+do {                                                   \
+       printk(KERN_DEBUG "pid %d: %s: " fmt "\n",      \
+               current->pid, __func__, ##args);        \
+} while (0)
 #else
-#define DPRINTK(fmt,args...) do {} while(0)
+#define DPRINTK(fmt, args...) do {} while (0)
 #endif
 
+#define AUTOFS_WARN(fmt, args...)                      \
+do {                                                   \
+       printk(KERN_WARNING "pid %d: %s: " fmt "\n",    \
+               current->pid, __func__, ##args);        \
+} while (0)
+
+#define AUTOFS_ERROR(fmt, args...)                     \
+do {                                                   \
+       printk(KERN_ERR "pid %d: %s: " fmt "\n",        \
+               current->pid, __func__, ##args);        \
+} while (0)
+
 /* Unified info structure.  This is pointed to by both the dentry and
    inode structures.  Each file in the filesystem has an instance of this
    structure.  It holds a reference to the dentry, so dentries are never
@@ -61,6 +83,9 @@ struct autofs_info {
        unsigned long last_used;
        atomic_t count;
 
+       uid_t uid;
+       gid_t gid;
+
        mode_t  mode;
        size_t  size;
 
@@ -92,10 +117,6 @@ struct autofs_wait_queue {
 
 #define AUTOFS_SBI_MAGIC 0x6d4a556d
 
-#define AUTOFS_TYPE_INDIRECT     0x0001
-#define AUTOFS_TYPE_DIRECT       0x0002
-#define AUTOFS_TYPE_OFFSET       0x0004
-
 struct autofs_sb_info {
        u32 magic;
        int pipefd;
@@ -169,6 +190,17 @@ int autofs4_expire_run(struct super_block *, struct vfsmount *,
                        struct autofs_packet_expire __user *);
 int autofs4_expire_multi(struct super_block *, struct vfsmount *,
                        struct autofs_sb_info *, int __user *);
+struct dentry *autofs4_expire_direct(struct super_block *sb,
+                                    struct vfsmount *mnt,
+                                    struct autofs_sb_info *sbi, int how);
+struct dentry *autofs4_expire_indirect(struct super_block *sb,
+                                      struct vfsmount *mnt,
+                                      struct autofs_sb_info *sbi, int how);
+
+/* Device node initialization */
+
+int autofs_dev_ioctl_init(void);
+void autofs_dev_ioctl_exit(void);
 
 /* Operations structures */
 
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
new file mode 100644 (file)
index 0000000..625abf5
--- /dev/null
@@ -0,0 +1,863 @@
+/*
+ * Copyright 2008 Red Hat, Inc. All rights reserved.
+ * Copyright 2008 Ian Kent <raven@themaw.net>
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/namei.h>
+#include <linux/fcntl.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/sched.h>
+#include <linux/compat.h>
+#include <linux/syscalls.h>
+#include <linux/smp_lock.h>
+#include <linux/magic.h>
+#include <linux/dcache.h>
+#include <linux/uaccess.h>
+
+#include "autofs_i.h"
+
+/*
+ * This module implements an interface for routing autofs ioctl control
+ * commands via a miscellaneous device file.
+ *
+ * The alternate interface is needed because we need to be able open
+ * an ioctl file descriptor on an autofs mount that may be covered by
+ * another mount. This situation arises when starting automount(8)
+ * or other user space daemon which uses direct mounts or offset
+ * mounts (used for autofs lazy mount/umount of nested mount trees),
+ * which have been left busy at at service shutdown.
+ */
+
+#define AUTOFS_DEV_IOCTL_SIZE  sizeof(struct autofs_dev_ioctl)
+
+typedef int (*ioctl_fn)(struct file *, struct autofs_sb_info *,
+                       struct autofs_dev_ioctl *);
+
+static int check_name(const char *name)
+{
+       if (!strchr(name, '/'))
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ * Check a string doesn't overrun the chunk of
+ * memory we copied from user land.
+ */
+static int invalid_str(char *str, void *end)
+{
+       while ((void *) str <= end)
+               if (!*str++)
+                       return 0;
+       return -EINVAL;
+}
+
+/*
+ * Check that the user compiled against correct version of autofs
+ * misc device code.
+ *
+ * As well as checking the version compatibility this always copies
+ * the kernel interface version out.
+ */
+static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
+{
+       int err = 0;
+
+       if ((AUTOFS_DEV_IOCTL_VERSION_MAJOR != param->ver_major) ||
+           (AUTOFS_DEV_IOCTL_VERSION_MINOR < param->ver_minor)) {
+               AUTOFS_WARN("ioctl control interface version mismatch: "
+                    "kernel(%u.%u), user(%u.%u), cmd(%d)",
+                    AUTOFS_DEV_IOCTL_VERSION_MAJOR,
+                    AUTOFS_DEV_IOCTL_VERSION_MINOR,
+                    param->ver_major, param->ver_minor, cmd);
+               err = -EINVAL;
+       }
+
+       /* Fill in the kernel version. */
+       param->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
+       param->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
+
+       return err;
+}
+
+/*
+ * Copy parameter control struct, including a possible path allocated
+ * at the end of the struct.
+ */
+static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
+{
+       struct autofs_dev_ioctl tmp, *ads;
+
+       if (copy_from_user(&tmp, in, sizeof(tmp)))
+               return ERR_PTR(-EFAULT);
+
+       if (tmp.size < sizeof(tmp))
+               return ERR_PTR(-EINVAL);
+
+       ads = kmalloc(tmp.size, GFP_KERNEL);
+       if (!ads)
+               return ERR_PTR(-ENOMEM);
+
+       if (copy_from_user(ads, in, tmp.size)) {
+               kfree(ads);
+               return ERR_PTR(-EFAULT);
+       }
+
+       return ads;
+}
+
+static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
+{
+       kfree(param);
+       return;
+}
+
+/*
+ * Check sanity of parameter control fields and if a path is present
+ * check that it has a "/" and is terminated.
+ */
+static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
+{
+       int err = -EINVAL;
+
+       if (check_dev_ioctl_version(cmd, param)) {
+               AUTOFS_WARN("invalid device control module version "
+                    "supplied for cmd(0x%08x)", cmd);
+               goto out;
+       }
+
+       if (param->size > sizeof(*param)) {
+               err = check_name(param->path);
+               if (err) {
+                       AUTOFS_WARN("invalid path supplied for cmd(0x%08x)",
+                                   cmd);
+                       goto out;
+               }
+
+               err = invalid_str(param->path,
+                                (void *) ((size_t) param + param->size));
+               if (err) {
+                       AUTOFS_WARN("invalid path supplied for cmd(0x%08x)",
+                                   cmd);
+                       goto out;
+               }
+       }
+
+       err = 0;
+out:
+       return err;
+}
+
+/*
+ * Get the autofs super block info struct from the file opened on
+ * the autofs mount point.
+ */
+static struct autofs_sb_info *autofs_dev_ioctl_sbi(struct file *f)
+{
+       struct autofs_sb_info *sbi = NULL;
+       struct inode *inode;
+
+       if (f) {
+               inode = f->f_path.dentry->d_inode;
+               sbi = autofs4_sbi(inode->i_sb);
+       }
+       return sbi;
+}
+
+/* Return autofs module protocol version */
+static int autofs_dev_ioctl_protover(struct file *fp,
+                                    struct autofs_sb_info *sbi,
+                                    struct autofs_dev_ioctl *param)
+{
+       param->arg1 = sbi->version;
+       return 0;
+}
+
+/* Return autofs module protocol sub version */
+static int autofs_dev_ioctl_protosubver(struct file *fp,
+                                       struct autofs_sb_info *sbi,
+                                       struct autofs_dev_ioctl *param)
+{
+       param->arg1 = sbi->sub_version;
+       return 0;
+}
+
+/*
+ * Walk down the mount stack looking for an autofs mount that
+ * has the requested device number (aka. new_encode_dev(sb->s_dev).
+ */
+static int autofs_dev_ioctl_find_super(struct nameidata *nd, dev_t devno)
+{
+       struct dentry *dentry;
+       struct inode *inode;
+       struct super_block *sb;
+       dev_t s_dev;
+       unsigned int err;
+
+       err = -ENOENT;
+
+       /* Lookup the dentry name at the base of our mount point */
+       dentry = d_lookup(nd->path.dentry, &nd->last);
+       if (!dentry)
+               goto out;
+
+       dput(nd->path.dentry);
+       nd->path.dentry = dentry;
+
+       /* And follow the mount stack looking for our autofs mount */
+       while (follow_down(&nd->path.mnt, &nd->path.dentry)) {
+               inode = nd->path.dentry->d_inode;
+               if (!inode)
+                       break;
+
+               sb = inode->i_sb;
+               s_dev = new_encode_dev(sb->s_dev);
+               if (devno == s_dev) {
+                       if (sb->s_magic == AUTOFS_SUPER_MAGIC) {
+                               err = 0;
+                               break;
+                       }
+               }
+       }
+out:
+       return err;
+}
+
+/*
+ * Walk down the mount stack looking for an autofs mount that
+ * has the requested mount type (ie. indirect, direct or offset).
+ */
+static int autofs_dev_ioctl_find_sbi_type(struct nameidata *nd, unsigned int type)
+{
+       struct dentry *dentry;
+       struct autofs_info *ino;
+       unsigned int err;
+
+       err = -ENOENT;
+
+       /* Lookup the dentry name at the base of our mount point */
+       dentry = d_lookup(nd->path.dentry, &nd->last);
+       if (!dentry)
+               goto out;
+
+       dput(nd->path.dentry);
+       nd->path.dentry = dentry;
+
+       /* And follow the mount stack looking for our autofs mount */
+       while (follow_down(&nd->path.mnt, &nd->path.dentry)) {
+               ino = autofs4_dentry_ino(nd->path.dentry);
+               if (ino && ino->sbi->type & type) {
+                       err = 0;
+                       break;
+               }
+       }
+out:
+       return err;
+}
+
+static void autofs_dev_ioctl_fd_install(unsigned int fd, struct file *file)
+{
+       struct files_struct *files = current->files;
+       struct fdtable *fdt;
+
+       spin_lock(&files->file_lock);
+       fdt = files_fdtable(files);
+       BUG_ON(fdt->fd[fd] != NULL);
+       rcu_assign_pointer(fdt->fd[fd], file);
+       FD_SET(fd, fdt->close_on_exec);
+       spin_unlock(&files->file_lock);
+}
+
+
+/*
+ * Open a file descriptor on the autofs mount point corresponding
+ * to the given path and device number (aka. new_encode_dev(sb->s_dev)).
+ */
+static int autofs_dev_ioctl_open_mountpoint(const char *path, dev_t devid)
+{
+       struct file *filp;
+       struct nameidata nd;
+       int err, fd;
+
+       fd = get_unused_fd();
+       if (likely(fd >= 0)) {
+               /* Get nameidata of the parent directory */
+               err = path_lookup(path, LOOKUP_PARENT, &nd);
+               if (err)
+                       goto out;
+
+               /*
+                * Search down, within the parent, looking for an
+                * autofs super block that has the device number
+                * corresponding to the autofs fs we want to open.
+                */
+               err = autofs_dev_ioctl_find_super(&nd, devid);
+               if (err) {
+                       path_put(&nd.path);
+                       goto out;
+               }
+
+               filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
+               if (IS_ERR(filp)) {
+                       err = PTR_ERR(filp);
+                       goto out;
+               }
+
+               autofs_dev_ioctl_fd_install(fd, filp);
+       }
+
+       return fd;
+
+out:
+       put_unused_fd(fd);
+       return err;
+}
+
+/* Open a file descriptor on an autofs mount point */
+static int autofs_dev_ioctl_openmount(struct file *fp,
+                                     struct autofs_sb_info *sbi,
+                                     struct autofs_dev_ioctl *param)
+{
+       const char *path;
+       dev_t devid;
+       int err, fd;
+
+       /* param->path has already been checked */
+       if (!param->arg1)
+               return -EINVAL;
+
+       param->ioctlfd = -1;
+
+       path = param->path;
+       devid = param->arg1;
+
+       err = 0;
+       fd = autofs_dev_ioctl_open_mountpoint(path, devid);
+       if (unlikely(fd < 0)) {
+               err = fd;
+               goto out;
+       }
+
+       param->ioctlfd = fd;
+out:
+       return err;
+}
+
+/* Close file descriptor allocated above (user can also use close(2)). */
+static int autofs_dev_ioctl_closemount(struct file *fp,
+                                      struct autofs_sb_info *sbi,
+                                      struct autofs_dev_ioctl *param)
+{
+       return sys_close(param->ioctlfd);
+}
+
+/*
+ * Send "ready" status for an existing wait (either a mount or an expire
+ * request).
+ */
+static int autofs_dev_ioctl_ready(struct file *fp,
+                                 struct autofs_sb_info *sbi,
+                                 struct autofs_dev_ioctl *param)
+{
+       autofs_wqt_t token;
+
+       token = (autofs_wqt_t) param->arg1;
+       return autofs4_wait_release(sbi, token, 0);
+}
+
+/*
+ * Send "fail" status for an existing wait (either a mount or an expire
+ * request).
+ */
+static int autofs_dev_ioctl_fail(struct file *fp,
+                                struct autofs_sb_info *sbi,
+                                struct autofs_dev_ioctl *param)
+{
+       autofs_wqt_t token;
+       int status;
+
+       token = (autofs_wqt_t) param->arg1;
+       status = param->arg2 ? param->arg2 : -ENOENT;
+       return autofs4_wait_release(sbi, token, status);
+}
+
+/*
+ * Set the pipe fd for kernel communication to the daemon.
+ *
+ * Normally this is set at mount using an option but if we
+ * are reconnecting to a busy mount then we need to use this
+ * to tell the autofs mount about the new kernel pipe fd. In
+ * order to protect mounts against incorrectly setting the
+ * pipefd we also require that the autofs mount be catatonic.
+ *
+ * This also sets the process group id used to identify the
+ * controlling process (eg. the owning automount(8) daemon).
+ */
+static int autofs_dev_ioctl_setpipefd(struct file *fp,
+                                     struct autofs_sb_info *sbi,
+                                     struct autofs_dev_ioctl *param)
+{
+       int pipefd;
+       int err = 0;
+
+       if (param->arg1 == -1)
+               return -EINVAL;
+
+       pipefd = param->arg1;
+
+       mutex_lock(&sbi->wq_mutex);
+       if (!sbi->catatonic) {
+               mutex_unlock(&sbi->wq_mutex);
+               return -EBUSY;
+       } else {
+               struct file *pipe = fget(pipefd);
+               if (!pipe->f_op || !pipe->f_op->write) {
+                       err = -EPIPE;
+                       fput(pipe);
+                       goto out;
+               }
+               sbi->oz_pgrp = task_pgrp_nr(current);
+               sbi->pipefd = pipefd;
+               sbi->pipe = pipe;
+               sbi->catatonic = 0;
+       }
+out:
+       mutex_unlock(&sbi->wq_mutex);
+       return err;
+}
+
+/*
+ * Make the autofs mount point catatonic, no longer responsive to
+ * mount requests. Also closes the kernel pipe file descriptor.
+ */
+static int autofs_dev_ioctl_catatonic(struct file *fp,
+                                     struct autofs_sb_info *sbi,
+                                     struct autofs_dev_ioctl *param)
+{
+       autofs4_catatonic_mode(sbi);
+       return 0;
+}
+
+/* Set the autofs mount timeout */
+static int autofs_dev_ioctl_timeout(struct file *fp,
+                                   struct autofs_sb_info *sbi,
+                                   struct autofs_dev_ioctl *param)
+{
+       unsigned long timeout;
+
+       timeout = param->arg1;
+       param->arg1 = sbi->exp_timeout / HZ;
+       sbi->exp_timeout = timeout * HZ;
+       return 0;
+}
+
+/*
+ * Return the uid and gid of the last request for the mount
+ *
+ * When reconstructing an autofs mount tree with active mounts
+ * we need to re-connect to mounts that may have used the original
+ * process uid and gid (or string variations of them) for mount
+ * lookups within the map entry.
+ */
+static int autofs_dev_ioctl_requester(struct file *fp,
+                                     struct autofs_sb_info *sbi,
+                                     struct autofs_dev_ioctl *param)
+{
+       struct autofs_info *ino;
+       struct nameidata nd;
+       const char *path;
+       dev_t devid;
+       int err = -ENOENT;
+
+       if (param->size <= sizeof(*param)) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       path = param->path;
+       devid = sbi->sb->s_dev;
+
+       param->arg1 = param->arg2 = -1;
+
+       /* Get nameidata of the parent directory */
+       err = path_lookup(path, LOOKUP_PARENT, &nd);
+       if (err)
+               goto out;
+
+       err = autofs_dev_ioctl_find_super(&nd, devid);
+       if (err)
+               goto out_release;
+
+       ino = autofs4_dentry_ino(nd.path.dentry);
+       if (ino) {
+               err = 0;
+               autofs4_expire_wait(nd.path.dentry);
+               spin_lock(&sbi->fs_lock);
+               param->arg1 = ino->uid;
+               param->arg2 = ino->gid;
+               spin_unlock(&sbi->fs_lock);
+       }
+
+out_release:
+       path_put(&nd.path);
+out:
+       return err;
+}
+
+/*
+ * Call repeatedly until it returns -EAGAIN, meaning there's nothing
+ * more that can be done.
+ */
+static int autofs_dev_ioctl_expire(struct file *fp,
+                                  struct autofs_sb_info *sbi,
+                                  struct autofs_dev_ioctl *param)
+{
+       struct dentry *dentry;
+       struct vfsmount *mnt;
+       int err = -EAGAIN;
+       int how;
+
+       how = param->arg1;
+       mnt = fp->f_path.mnt;
+
+       if (sbi->type & AUTOFS_TYPE_TRIGGER)
+               dentry = autofs4_expire_direct(sbi->sb, mnt, sbi, how);
+       else
+               dentry = autofs4_expire_indirect(sbi->sb, mnt, sbi, how);
+
+       if (dentry) {
+               struct autofs_info *ino = autofs4_dentry_ino(dentry);
+
+               /*
+                * This is synchronous because it makes the daemon a
+                * little easier
+               */
+               err = autofs4_wait(sbi, dentry, NFY_EXPIRE);
+
+               spin_lock(&sbi->fs_lock);
+               if (ino->flags & AUTOFS_INF_MOUNTPOINT) {
+                       ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
+                       sbi->sb->s_root->d_mounted++;
+               }
+               ino->flags &= ~AUTOFS_INF_EXPIRING;
+               complete_all(&ino->expire_complete);
+               spin_unlock(&sbi->fs_lock);
+               dput(dentry);
+       }
+
+       return err;
+}
+
+/* Check if autofs mount point is in use */
+static int autofs_dev_ioctl_askumount(struct file *fp,
+                                     struct autofs_sb_info *sbi,
+                                     struct autofs_dev_ioctl *param)
+{
+       param->arg1 = 0;
+       if (may_umount(fp->f_path.mnt))
+               param->arg1 = 1;
+       return 0;
+}
+
+/*
+ * Check if the given path is a mountpoint.
+ *
+ * If we are supplied with the file descriptor of an autofs
+ * mount we're looking for a specific mount. In this case
+ * the path is considered a mountpoint if it is itself a
+ * mountpoint or contains a mount, such as a multi-mount
+ * without a root mount. In this case we return 1 if the
+ * path is a mount point and the super magic of the covering
+ * mount if there is one or 0 if it isn't a mountpoint.
+ *
+ * If we aren't supplied with a file descriptor then we
+ * lookup the nameidata of the path and check if it is the
+ * root of a mount. If a type is given we are looking for
+ * a particular autofs mount and if we don't find a match
+ * we return fail. If the located nameidata path is the
+ * root of a mount we return 1 along with the super magic
+ * of the mount or 0 otherwise.
+ *
+ * In both cases the the device number (as returned by
+ * new_encode_dev()) is also returned.
+ */
+static int autofs_dev_ioctl_ismountpoint(struct file *fp,
+                                        struct autofs_sb_info *sbi,
+                                        struct autofs_dev_ioctl *param)
+{
+       struct nameidata nd;
+       const char *path;
+       unsigned int type;
+       int err = -ENOENT;
+
+       if (param->size <= sizeof(*param)) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       path = param->path;
+       type = param->arg1;
+
+       param->arg1 = 0;
+       param->arg2 = 0;
+
+       if (!fp || param->ioctlfd == -1) {
+               if (type == AUTOFS_TYPE_ANY) {
+                       struct super_block *sb;
+
+                       err = path_lookup(path, LOOKUP_FOLLOW, &nd);
+                       if (err)
+                               goto out;
+
+                       sb = nd.path.dentry->d_sb;
+                       param->arg1 = new_encode_dev(sb->s_dev);
+               } else {
+                       struct autofs_info *ino;
+
+                       err = path_lookup(path, LOOKUP_PARENT, &nd);
+                       if (err)
+                               goto out;
+
+                       err = autofs_dev_ioctl_find_sbi_type(&nd, type);
+                       if (err)
+                               goto out_release;
+
+                       ino = autofs4_dentry_ino(nd.path.dentry);
+                       param->arg1 = autofs4_get_dev(ino->sbi);
+               }
+
+               err = 0;
+               if (nd.path.dentry->d_inode &&
+                   nd.path.mnt->mnt_root == nd.path.dentry) {
+                       err = 1;
+                       param->arg2 = nd.path.dentry->d_inode->i_sb->s_magic;
+               }
+       } else {
+               dev_t devid = new_encode_dev(sbi->sb->s_dev);
+
+               err = path_lookup(path, LOOKUP_PARENT, &nd);
+               if (err)
+                       goto out;
+
+               err = autofs_dev_ioctl_find_super(&nd, devid);
+               if (err)
+                       goto out_release;
+
+               param->arg1 = autofs4_get_dev(sbi);
+
+               err = have_submounts(nd.path.dentry);
+
+               if (nd.path.mnt->mnt_mountpoint != nd.path.mnt->mnt_root) {
+                       if (follow_down(&nd.path.mnt, &nd.path.dentry)) {
+                               struct inode *inode = nd.path.dentry->d_inode;
+                               param->arg2 = inode->i_sb->s_magic;
+                       }
+               }
+       }
+
+out_release:
+       path_put(&nd.path);
+out:
+       return err;
+}
+
+/*
+ * Our range of ioctl numbers isn't 0 based so we need to shift
+ * the array index by _IOC_NR(AUTOFS_CTL_IOC_FIRST) for the table
+ * lookup.
+ */
+#define cmd_idx(cmd)   (cmd - _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST))
+
+static ioctl_fn lookup_dev_ioctl(unsigned int cmd)
+{
+       static struct {
+               int cmd;
+               ioctl_fn fn;
+       } _ioctls[] = {
+               {cmd_idx(AUTOFS_DEV_IOCTL_VERSION_CMD), NULL},
+               {cmd_idx(AUTOFS_DEV_IOCTL_PROTOVER_CMD),
+                        autofs_dev_ioctl_protover},
+               {cmd_idx(AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD),
+                        autofs_dev_ioctl_protosubver},
+               {cmd_idx(AUTOFS_DEV_IOCTL_OPENMOUNT_CMD),
+                        autofs_dev_ioctl_openmount},
+               {cmd_idx(AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD),
+                        autofs_dev_ioctl_closemount},
+               {cmd_idx(AUTOFS_DEV_IOCTL_READY_CMD),
+                        autofs_dev_ioctl_ready},
+               {cmd_idx(AUTOFS_DEV_IOCTL_FAIL_CMD),
+                        autofs_dev_ioctl_fail},
+               {cmd_idx(AUTOFS_DEV_IOCTL_SETPIPEFD_CMD),
+                        autofs_dev_ioctl_setpipefd},
+               {cmd_idx(AUTOFS_DEV_IOCTL_CATATONIC_CMD),
+                        autofs_dev_ioctl_catatonic},
+               {cmd_idx(AUTOFS_DEV_IOCTL_TIMEOUT_CMD),
+                        autofs_dev_ioctl_timeout},
+               {cmd_idx(AUTOFS_DEV_IOCTL_REQUESTER_CMD),
+                        autofs_dev_ioctl_requester},
+               {cmd_idx(AUTOFS_DEV_IOCTL_EXPIRE_CMD),
+                        autofs_dev_ioctl_expire},
+               {cmd_idx(AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD),
+                        autofs_dev_ioctl_askumount},
+               {cmd_idx(AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD),
+                        autofs_dev_ioctl_ismountpoint}
+       };
+       unsigned int idx = cmd_idx(cmd);
+
+       return (idx >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[idx].fn;
+}
+
+/* ioctl dispatcher */
+static int _autofs_dev_ioctl(unsigned int command, struct autofs_dev_ioctl __user *user)
+{
+       struct autofs_dev_ioctl *param;
+       struct file *fp;
+       struct autofs_sb_info *sbi;
+       unsigned int cmd_first, cmd;
+       ioctl_fn fn = NULL;
+       int err = 0;
+
+       /* only root can play with this */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       cmd_first = _IOC_NR(AUTOFS_DEV_IOCTL_IOC_FIRST);
+       cmd = _IOC_NR(command);
+
+       if (_IOC_TYPE(command) != _IOC_TYPE(AUTOFS_DEV_IOCTL_IOC_FIRST) ||
+           cmd - cmd_first >= AUTOFS_DEV_IOCTL_IOC_COUNT) {
+               return -ENOTTY;
+       }
+
+       /* Copy the parameters into kernel space. */
+       param = copy_dev_ioctl(user);
+       if (IS_ERR(param))
+               return PTR_ERR(param);
+
+       err = validate_dev_ioctl(command, param);
+       if (err)
+               goto out;
+
+       /* The validate routine above always sets the version */
+       if (cmd == AUTOFS_DEV_IOCTL_VERSION_CMD)
+               goto done;
+
+       fn = lookup_dev_ioctl(cmd);
+       if (!fn) {
+               AUTOFS_WARN("unknown command 0x%08x", command);
+               return -ENOTTY;
+       }
+
+       fp = NULL;
+       sbi = NULL;
+
+       /*
+        * For obvious reasons the openmount can't have a file
+        * descriptor yet. We don't take a reference to the
+        * file during close to allow for immediate release.
+        */
+       if (cmd != AUTOFS_DEV_IOCTL_OPENMOUNT_CMD &&
+           cmd != AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD) {
+               fp = fget(param->ioctlfd);
+               if (!fp) {
+                       if (cmd == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD)
+                               goto cont;
+                       err = -EBADF;
+                       goto out;
+               }
+
+               if (!fp->f_op) {
+                       err = -ENOTTY;
+                       fput(fp);
+                       goto out;
+               }
+
+               sbi = autofs_dev_ioctl_sbi(fp);
+               if (!sbi || sbi->magic != AUTOFS_SBI_MAGIC) {
+                       err = -EINVAL;
+                       fput(fp);
+                       goto out;
+               }
+
+               /*
+                * Admin needs to be able to set the mount catatonic in
+                * order to be able to perform the re-open.
+                */
+               if (!autofs4_oz_mode(sbi) &&
+                   cmd != AUTOFS_DEV_IOCTL_CATATONIC_CMD) {
+                       err = -EACCES;
+                       fput(fp);
+                       goto out;
+               }
+       }
+cont:
+       err = fn(fp, sbi, param);
+
+       if (fp)
+               fput(fp);
+done:
+       if (err >= 0 && copy_to_user(user, param, AUTOFS_DEV_IOCTL_SIZE))
+               err = -EFAULT;
+out:
+       free_dev_ioctl(param);
+       return err;
+}
+
+static long autofs_dev_ioctl(struct file *file, uint command, ulong u)
+{
+       int err;
+       err = _autofs_dev_ioctl(command, (struct autofs_dev_ioctl __user *) u);
+       return (long) err;
+}
+
+#ifdef CONFIG_COMPAT
+static long autofs_dev_ioctl_compat(struct file *file, uint command, ulong u)
+{
+       return (long) autofs_dev_ioctl(file, command, (ulong) compat_ptr(u));
+}
+#else
+#define autofs_dev_ioctl_compat NULL
+#endif
+
+static const struct file_operations _dev_ioctl_fops = {
+       .unlocked_ioctl  = autofs_dev_ioctl,
+       .compat_ioctl = autofs_dev_ioctl_compat,
+       .owner   = THIS_MODULE,
+};
+
+static struct miscdevice _autofs_dev_ioctl_misc = {
+       .minor          = MISC_DYNAMIC_MINOR,
+       .name           = AUTOFS_DEVICE_NAME,
+       .fops           = &_dev_ioctl_fops
+};
+
+/* Register/deregister misc character device */
+int autofs_dev_ioctl_init(void)
+{
+       int r;
+
+       r = misc_register(&_autofs_dev_ioctl_misc);
+       if (r) {
+               AUTOFS_ERROR("misc_register failed for control device");
+               return r;
+       }
+
+       return 0;
+}
+
+void autofs_dev_ioctl_exit(void)
+{
+       misc_deregister(&_autofs_dev_ioctl_misc);
+       return;
+}
+
index cdabb796ff018aa65eb20c4d6ec034613ab8e1c8..cde2f8e8935a680bd62243dcc4b92f6909ea7789 100644 (file)
@@ -244,10 +244,10 @@ cont:
 }
 
 /* Check if we can expire a direct mount (possibly a tree) */
-static struct dentry *autofs4_expire_direct(struct super_block *sb,
-                                           struct vfsmount *mnt,
-                                           struct autofs_sb_info *sbi,
-                                           int how)
+struct dentry *autofs4_expire_direct(struct super_block *sb,
+                                    struct vfsmount *mnt,
+                                    struct autofs_sb_info *sbi,
+                                    int how)
 {
        unsigned long timeout;
        struct dentry *root = dget(sb->s_root);
@@ -283,10 +283,10 @@ static struct dentry *autofs4_expire_direct(struct super_block *sb,
  *  - it is unused by any user process
  *  - it has been unused for exp_timeout time
  */
-static struct dentry *autofs4_expire_indirect(struct super_block *sb,
-                                             struct vfsmount *mnt,
-                                             struct autofs_sb_info *sbi,
-                                             int how)
+struct dentry *autofs4_expire_indirect(struct super_block *sb,
+                                      struct vfsmount *mnt,
+                                      struct autofs_sb_info *sbi,
+                                      int how)
 {
        unsigned long timeout;
        struct dentry *root = sb->s_root;
@@ -479,7 +479,7 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
        if (arg && get_user(do_now, arg))
                return -EFAULT;
 
-       if (sbi->type & AUTOFS_TYPE_DIRECT)
+       if (sbi->type & AUTOFS_TYPE_TRIGGER)
                dentry = autofs4_expire_direct(sb, mnt, sbi, do_now);
        else
                dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now);
index 723a1c5e361b2786c8f8ec97e9332b77b1484e15..9722e4bd895725f42361b86d74355c3c4656bfbe 100644 (file)
@@ -29,11 +29,20 @@ static struct file_system_type autofs_fs_type = {
 
 static int __init init_autofs4_fs(void)
 {
-       return register_filesystem(&autofs_fs_type);
+       int err;
+
+       err = register_filesystem(&autofs_fs_type);
+       if (err)
+               return err;
+
+       autofs_dev_ioctl_init();
+
+       return err;
 }
 
 static void __exit exit_autofs4_fs(void)
 {
+       autofs_dev_ioctl_exit();
        unregister_filesystem(&autofs_fs_type);
 }
 
index 7bb3e5ba0537e29e6b11f438619f4ccecb71dac0..c7e65bb30ba02b600e1b51d30e11ce78246ef983 100644 (file)
@@ -53,6 +53,8 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
                atomic_set(&ino->count, 0);
        }
 
+       ino->uid = 0;
+       ino->gid = 0;
        ino->mode = mode;
        ino->last_used = jiffies;
 
@@ -213,7 +215,7 @@ static const struct super_operations autofs4_sops = {
 enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto,
        Opt_indirect, Opt_direct, Opt_offset};
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_fd, "fd=%u"},
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
@@ -288,7 +290,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
                        *type = AUTOFS_TYPE_DIRECT;
                        break;
                case Opt_offset:
-                       *type = AUTOFS_TYPE_DIRECT | AUTOFS_TYPE_OFFSET;
+                       *type = AUTOFS_TYPE_OFFSET;
                        break;
                default:
                        return 1;
@@ -336,7 +338,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        sbi->sb = s;
        sbi->version = 0;
        sbi->sub_version = 0;
-       sbi->type = 0;
+       sbi->type = AUTOFS_TYPE_INDIRECT;
        sbi->min_proto = 0;
        sbi->max_proto = 0;
        mutex_init(&sbi->wq_mutex);
@@ -378,7 +380,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        }
 
        root_inode->i_fop = &autofs4_root_operations;
-       root_inode->i_op = sbi->type & AUTOFS_TYPE_DIRECT ?
+       root_inode->i_op = sbi->type & AUTOFS_TYPE_TRIGGER ?
                        &autofs4_direct_root_inode_operations :
                        &autofs4_indirect_root_inode_operations;
 
index 35216d18d8b56fa5a6b0ff8f07f37771698a0b75..4b67c2a2d77c51fcc93193dbdd6e31dea2defc14 100644 (file)
@@ -337,7 +337,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                 * is very similar for indirect mounts except only dentrys
                 * in the root of the autofs file system may be negative.
                 */
-               if (sbi->type & (AUTOFS_TYPE_DIRECT|AUTOFS_TYPE_OFFSET))
+               if (sbi->type & AUTOFS_TYPE_TRIGGER)
                        return -ENOENT;
                else if (!IS_ROOT(dentry->d_parent))
                        return -ENOENT;
@@ -348,7 +348,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                return -ENOMEM;
 
        /* If this is a direct mount request create a dummy name */
-       if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT))
+       if (IS_ROOT(dentry) && sbi->type & AUTOFS_TYPE_TRIGGER)
                qstr.len = sprintf(name, "%p", dentry);
        else {
                qstr.len = autofs4_getpath(sbi, dentry, &name);
@@ -406,11 +406,11 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                                type = autofs_ptype_expire_multi;
                } else {
                        if (notify == NFY_MOUNT)
-                               type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+                               type = (sbi->type & AUTOFS_TYPE_TRIGGER) ?
                                        autofs_ptype_missing_direct :
                                         autofs_ptype_missing_indirect;
                        else
-                               type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
+                               type = (sbi->type & AUTOFS_TYPE_TRIGGER) ?
                                        autofs_ptype_expire_direct :
                                        autofs_ptype_expire_indirect;
                }
@@ -457,6 +457,40 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 
        status = wq->status;
 
+       /*
+        * For direct and offset mounts we need to track the requester's
+        * uid and gid in the dentry info struct. This is so it can be
+        * supplied, on request, by the misc device ioctl interface.
+        * This is needed during daemon resatart when reconnecting
+        * to existing, active, autofs mounts. The uid and gid (and
+        * related string values) may be used for macro substitution
+        * in autofs mount maps.
+        */
+       if (!status) {
+               struct autofs_info *ino;
+               struct dentry *de = NULL;
+
+               /* direct mount or browsable map */
+               ino = autofs4_dentry_ino(dentry);
+               if (!ino) {
+                       /* If not lookup actual dentry used */
+                       de = d_lookup(dentry->d_parent, &dentry->d_name);
+                       if (de)
+                               ino = autofs4_dentry_ino(de);
+               }
+
+               /* Set mount requester */
+               if (ino) {
+                       spin_lock(&sbi->fs_lock);
+                       ino->uid = wq->uid;
+                       ino->gid = wq->gid;
+                       spin_unlock(&sbi->fs_lock);
+               }
+
+               if (de)
+                       dput(de);
+       }
+
        /* Are we the last process to need status? */
        mutex_lock(&sbi->wq_mutex);
        if (!--wq->wait_ctr)
index e2595c2c403a9bfd01dffc1ac54594356e09e811..7893eaa1e58c695d1cff286c0df64c3647b11e8e 100644 (file)
@@ -55,8 +55,12 @@ enum super_flags {
 };
 
 #define BEFS_BYTEORDER_NATIVE 0x42494745
+#define BEFS_BYTEORDER_NATIVE_LE (__force fs32)cpu_to_le32(BEFS_BYTEORDER_NATIVE)
+#define BEFS_BYTEORDER_NATIVE_BE (__force fs32)cpu_to_be32(BEFS_BYTEORDER_NATIVE)
 
 #define BEFS_SUPER_MAGIC BEFS_SUPER_MAGIC1
+#define BEFS_SUPER_MAGIC1_LE (__force fs32)cpu_to_le32(BEFS_SUPER_MAGIC1)
+#define BEFS_SUPER_MAGIC1_BE (__force fs32)cpu_to_be32(BEFS_SUPER_MAGIC1)
 
 /*
  * Flags of inode
index 740f53672a8a6b305911248ce34dafa2cfaac744..b6dfee37c7b71776201aa320ac6e450e00290cd7 100644 (file)
@@ -650,7 +650,7 @@ enum {
        Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
 };
 
-static match_table_t befs_tokens = {
+static const match_table_t befs_tokens = {
        {Opt_uid, "uid=%d"},
        {Opt_gid, "gid=%d"},
        {Opt_charset, "iocharset=%s"},
@@ -809,8 +809,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
 
        /* account for offset of super block on x86 */
        disk_sb = (befs_super_block *) bh->b_data;
-       if ((le32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1) ||
-           (be32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1)) {
+       if ((disk_sb->magic1 == BEFS_SUPER_MAGIC1_LE) ||
+           (disk_sb->magic1 == BEFS_SUPER_MAGIC1_BE)) {
                befs_debug(sb, "Using PPC superblock location");
        } else {
                befs_debug(sb, "Using x86 superblock location");
index 8c3401ff6d6a2a50013423feedff544b2f946f14..41f2b4d0093e66ed67ab747831cea76fedc397cb 100644 (file)
@@ -26,10 +26,10 @@ befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
        befs_sb_info *befs_sb = BEFS_SB(sb);
 
        /* Check the byte order of the filesystem */
-       if (le32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
+       if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
            befs_sb->byte_order = BEFS_BYTESEX_LE;
-       else if (be32_to_cpu(disk_sb->fs_byte_order) == BEFS_BYTEORDER_NATIVE)
-           befs_sb->byte_order = BEFS_BYTESEX_BE;      
+       else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
+           befs_sb->byte_order = BEFS_BYTESEX_BE;
 
        befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
        befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
index 655ed8d30a86ef7e963414a9cb56d6ed7dc5d3c4..c76afa26edf735c7644e32b931ac675cbbf08454 100644 (file)
@@ -683,7 +683,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                         * switch really is going to happen - do this in
                         * flush_thread().      - akpm
                         */
-                       SET_PERSONALITY(loc->elf_ex, 0);
+                       SET_PERSONALITY(loc->elf_ex);
 
                        interpreter = open_exec(elf_interpreter);
                        retval = PTR_ERR(interpreter);
@@ -734,7 +734,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                        goto out_free_dentry;
        } else {
                /* Executables without an interpreter also need a personality  */
-               SET_PERSONALITY(loc->elf_ex, 0);
+               SET_PERSONALITY(loc->elf_ex);
        }
 
        /* Flush all traces of the currently running executable */
@@ -748,7 +748,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 
        /* Do this immediately, since STACK_TOP as used in setup_arg_pages
           may depend on the personality.  */
-       SET_PERSONALITY(loc->elf_ex, 0);
+       SET_PERSONALITY(loc->elf_ex);
        if (elf_read_implies_exec(loc->elf_ex, executable_stack))
                current->personality |= READ_IMPLIES_EXEC;
 
index 80c1f952ef7814fc36b099457c6ab11c670c1884..0e8367c546248987418191c6ab7b14c5be61bec9 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/fcntl.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/security.h>
 #include <linux/highmem.h>
 #include <linux/highuid.h>
 #include <linux/personality.h>
@@ -455,8 +456,19 @@ error_kill:
 }
 
 /*****************************************************************************/
+
+#ifndef ELF_BASE_PLATFORM
 /*
- * present useful information to the program
+ * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture.
+ * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value
+ * will be copied to the user stack in the same manner as AT_PLATFORM.
+ */
+#define ELF_BASE_PLATFORM NULL
+#endif
+
+/*
+ * present useful information to the program by shovelling it onto the new
+ * process's stack
  */
 static int create_elf_fdpic_tables(struct linux_binprm *bprm,
                                   struct mm_struct *mm,
@@ -466,15 +478,19 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        unsigned long sp, csp, nitems;
        elf_caddr_t __user *argv, *envp;
        size_t platform_len = 0, len;
-       char *k_platform;
-       char __user *u_platform, *p;
+       char *k_platform, *k_base_platform;
+       char __user *u_platform, *u_base_platform, *p;
        long hwcap;
        int loop;
        int nr; /* reset for each csp adjustment */
 
-       /* we're going to shovel a whole load of stuff onto the stack */
 #ifdef CONFIG_MMU
-       sp = bprm->p;
+       /* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
+        * by the processes running on the same package. One thing we can do is
+        * to shuffle the initial stack for them, so we give the architecture
+        * an opportunity to do so here.
+        */
+       sp = arch_align_stack(bprm->p);
 #else
        sp = mm->start_stack;
 
@@ -483,11 +499,14 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
                return -EFAULT;
 #endif
 
-       /* get hold of platform and hardware capabilities masks for the machine
-        * we are running on.  In some cases (Sparc), this info is impossible
-        * to get, in others (i386) it is merely difficult.
-        */
        hwcap = ELF_HWCAP;
+
+       /*
+        * If this architecture has a platform capability string, copy it
+        * to userspace.  In some cases (Sparc), this info is impossible
+        * for userspace to get any other way, in others (i386) it is
+        * merely difficult.
+        */
        k_platform = ELF_PLATFORM;
        u_platform = NULL;
 
@@ -499,19 +518,20 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
                        return -EFAULT;
        }
 
-#if defined(__i386__) && defined(CONFIG_SMP)
-       /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
-        * by the processes running on the same package. One thing we can do is
-        * to shuffle the initial stack for them.
-        *
-        * the conditionals here are unneeded, but kept in to make the code
-        * behaviour the same as pre change unless we have hyperthreaded
-        * processors. This keeps Mr Marcelo Person happier but should be
-        * removed for 2.5
+       /*
+        * If this architecture has a "base" platform capability
+        * string, copy it to userspace.
         */
-       if (smp_num_siblings > 1)
-               sp = sp - ((current->pid % 64) << 7);
-#endif
+       k_base_platform = ELF_BASE_PLATFORM;
+       u_base_platform = NULL;
+
+       if (k_base_platform) {
+               platform_len = strlen(k_base_platform) + 1;
+               sp -= platform_len;
+               u_base_platform = (char __user *) sp;
+               if (__copy_to_user(u_base_platform, k_base_platform, platform_len) != 0)
+                       return -EFAULT;
+       }
 
        sp &= ~7UL;
 
@@ -541,9 +561,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        }
 
        /* force 16 byte _final_ alignment here for generality */
-#define DLINFO_ITEMS 13
+#define DLINFO_ITEMS 15
+
+       nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) +
+               (k_base_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH;
 
-       nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH;
+       if (bprm->interp_flags & BINPRM_FLAGS_EXECFD)
+               nitems++;
 
        csp = sp;
        sp -= nitems * 2 * sizeof(unsigned long);
@@ -575,6 +599,19 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
                            (elf_addr_t) (unsigned long) u_platform);
        }
 
+       if (k_base_platform) {
+               nr = 0;
+               csp -= 2 * sizeof(unsigned long);
+               NEW_AUX_ENT(AT_BASE_PLATFORM,
+                           (elf_addr_t) (unsigned long) u_base_platform);
+       }
+
+       if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
+               nr = 0;
+               csp -= 2 * sizeof(unsigned long);
+               NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
+       }
+
        nr = 0;
        csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
        NEW_AUX_ENT(AT_HWCAP,   hwcap);
@@ -590,6 +627,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
        NEW_AUX_ENT(AT_EUID,    (elf_addr_t) current->euid);
        NEW_AUX_ENT(AT_GID,     (elf_addr_t) current->gid);
        NEW_AUX_ENT(AT_EGID,    (elf_addr_t) current->egid);
+       NEW_AUX_ENT(AT_SECURE,  security_bprm_secureexec(bprm));
+       NEW_AUX_ENT(AT_EXECFN,  bprm->exec);
 
 #ifdef ARCH_DLINFO
        nr = 0;
index f9c88d0c8cedeabcfdca1a5f81a51e1e293a59ea..32fb00b52cd069ed600d9c1a925f2b831621325e 100644 (file)
@@ -43,7 +43,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
                        return -ENOEXEC;
        }
 
-       bprm->sh_bang = 1;      /* Well, the bang-shell is implicit... */
+       bprm->recursion_depth++; /* Well, the bang-shell is implicit... */
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index dfc0197905ca1e9d50ce8ff613261b141d6f8439..ccb781a6a804121e17e317372eb852243303d687 100644 (file)
@@ -229,13 +229,13 @@ static int decompress_exec(
        ret = 10;
        if (buf[3] & EXTRA_FIELD) {
                ret += 2 + buf[10] + (buf[11] << 8);
-               if (unlikely(LBUFSIZE == ret)) {
+               if (unlikely(LBUFSIZE <= ret)) {
                        DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
                        goto out_free_buf;
                }
        }
        if (buf[3] & ORIG_NAME) {
-               for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
+               while (ret < LBUFSIZE && buf[ret++] != 0)
                        ;
                if (unlikely(LBUFSIZE == ret)) {
                        DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
@@ -243,7 +243,7 @@ static int decompress_exec(
                }
        }
        if (buf[3] & COMMENT) {
-               for (;  ret < LBUFSIZE && (buf[ret] != 0); ret++)
+               while (ret < LBUFSIZE && buf[ret++] != 0)
                        ;
                if (unlikely(LBUFSIZE == ret)) {
                        DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
index 8d7e88e02e0f9cc13207d86ee090a2594f79497b..f2744ab4e5b35c415724034f3f5a3a328997cf99 100644 (file)
@@ -117,7 +117,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
                goto _ret;
 
        retval = -ENOEXEC;
-       if (bprm->misc_bang)
+       if (bprm->recursion_depth > BINPRM_MAX_RECURSION)
                goto _ret;
 
        /* to keep locking time low, we copy the interpreter string */
@@ -197,7 +197,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (retval < 0)
                goto _error;
 
-       bprm->misc_bang = 1;
+       bprm->recursion_depth++;
 
        retval = search_binary_handler (bprm, regs);
        if (retval < 0)
index 9e3963f7ebf19f85a1742ff034bbb518d51a6aff..08343505e18455dedebace59a8c489ecb3b1cf7a 100644 (file)
@@ -22,14 +22,15 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
        char interp[BINPRM_BUF_SIZE];
        int retval;
 
-       if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang)) 
+       if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
+           (bprm->recursion_depth > BINPRM_MAX_RECURSION))
                return -ENOEXEC;
        /*
         * This section does the #! interpretation.
         * Sorta complicated, but hopefully it will work.  -TYT
         */
 
-       bprm->sh_bang = 1;
+       bprm->recursion_depth++;
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index 68be580ba289fc3135a0dcd93595ce5b66062206..74e587a5279684f722b5b1733d1444ebf1ee1e35 100644 (file)
@@ -306,3 +306,5 @@ static void __exit exit_som_binfmt(void)
 
 core_initcall(init_som_binfmt);
 module_exit(exit_som_binfmt);
+
+MODULE_LICENSE("GPL");
index 3cb7cda3d780e95026142398f4c52cdf565d93b6..262fa10e213d571c4d14e1c6b08a3c5861e55e03 100644 (file)
@@ -22,9 +22,6 @@
 #include <linux/mutex.h>
 #include <linux/backing-dev.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
 #include "internal.h"
 
 /*
index 0d9b80ec689ccc0741fee358d92f26b34f1bc4c9..cfd29da714d1e9bf9b9f41338c09723ff09422de 100644 (file)
@@ -362,9 +362,8 @@ static int init_coda_psdev(void)
                goto out_chrdev;
        }               
        for (i = 0; i < MAX_CODADEVS; i++)
-               device_create_drvdata(coda_psdev_class, NULL,
-                                     MKDEV(CODA_PSDEV_MAJOR, i),
-                                     NULL, "cfs%d", i);
+               device_create(coda_psdev_class, NULL,
+                             MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
        coda_sysctl_init();
        goto out;
 
index 075d0509970de479c78e796cb4ce11d94945fbb5..5f9ec449c799854e19a9190b489ccf4a23fc0b03 100644 (file)
@@ -137,6 +137,45 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
        return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
 
+static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+{
+       compat_ino_t ino = stat->ino;
+       typeof(ubuf->st_uid) uid = 0;
+       typeof(ubuf->st_gid) gid = 0;
+       int err;
+
+       SET_UID(uid, stat->uid);
+       SET_GID(gid, stat->gid);
+
+       if ((u64) stat->size > MAX_NON_LFS ||
+           !old_valid_dev(stat->dev) ||
+           !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
+       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+               return -EOVERFLOW;
+
+       if (clear_user(ubuf, sizeof(*ubuf)))
+               return -EFAULT;
+
+       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
+       err |= __put_user(ino, &ubuf->st_ino);
+       err |= __put_user(stat->mode, &ubuf->st_mode);
+       err |= __put_user(stat->nlink, &ubuf->st_nlink);
+       err |= __put_user(uid, &ubuf->st_uid);
+       err |= __put_user(gid, &ubuf->st_gid);
+       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
+       err |= __put_user(stat->size, &ubuf->st_size);
+       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
+       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
+       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
+       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
+       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
+       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
+       err |= __put_user(stat->blksize, &ubuf->st_blksize);
+       err |= __put_user(stat->blocks, &ubuf->st_blocks);
+       return err;
+}
+
 asmlinkage long compat_sys_newstat(char __user * filename,
                struct compat_stat __user *statbuf)
 {
@@ -1239,7 +1278,7 @@ static int compat_count(compat_uptr_t __user *argv, int max)
                        if (!p)
                                break;
                        argv++;
-                       if(++i > max)
+                       if (i++ >= max)
                                return -E2BIG;
                }
        }
index 08e28c9bb4164f5e2f549535959fd816d92521ed..3dbe2169cf36358730317f3ac563cf985c3cbc0b 100644 (file)
@@ -26,8 +26,7 @@
 #include <linux/debugfs.h>
 #include <linux/fsnotify.h>
 #include <linux/string.h>
-
-#define DEBUGFS_MAGIC  0x64626720
+#include <linux/magic.h>
 
 static struct vfsmount *debugfs_mount;
 static int debugfs_mount_count;
index 488eb424f662141488cc8a966496776fa66e2dc9..4a714f6c1bede9c62ad9dc22433f7fda3b3a0396 100644 (file)
@@ -27,6 +27,7 @@
 #define DEVPTS_SUPER_MAGIC 0x1cd1
 
 #define DEVPTS_DEFAULT_MODE 0600
+#define PTMX_MINOR     2
 
 extern int pty_limit;                  /* Config limit on Unix98 ptys */
 static DEFINE_IDA(allocated_ptys);
@@ -48,7 +49,7 @@ enum {
        Opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
        {Opt_mode, "mode=%o"},
@@ -169,15 +170,7 @@ static struct file_system_type devpts_fs_type = {
  * to the System V naming convention
  */
 
-static struct dentry *get_node(int num)
-{
-       char s[12];
-       struct dentry *root = devpts_root;
-       mutex_lock(&root->d_inode->i_mutex);
-       return lookup_one_len(s, root, sprintf(s, "%d", num));
-}
-
-int devpts_new_index(void)
+int devpts_new_index(struct inode *ptmx_inode)
 {
        int index;
        int ida_ret;
@@ -205,20 +198,21 @@ retry:
        return index;
 }
 
-void devpts_kill_index(int idx)
+void devpts_kill_index(struct inode *ptmx_inode, int idx)
 {
        mutex_lock(&allocated_ptys_lock);
        ida_remove(&allocated_ptys, idx);
        mutex_unlock(&allocated_ptys_lock);
 }
 
-int devpts_pty_new(struct tty_struct *tty)
+int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 {
        int number = tty->index; /* tty layer puts index from devpts_new_index() in here */
        struct tty_driver *driver = tty->driver;
        dev_t device = MKDEV(driver->major, driver->minor_start+number);
        struct dentry *dentry;
        struct inode *inode = new_inode(devpts_mnt->mnt_sb);
+       char s[12];
 
        /* We're supposed to be given the slave end of a pty */
        BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
@@ -233,10 +227,15 @@ int devpts_pty_new(struct tty_struct *tty)
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        init_special_inode(inode, S_IFCHR|config.mode, device);
        inode->i_private = tty;
+       tty->driver_data = inode;
 
-       dentry = get_node(number);
-       if (!IS_ERR(dentry) && !dentry->d_inode) {
-               d_instantiate(dentry, inode);
+       sprintf(s, "%d", number);
+
+       mutex_lock(&devpts_root->d_inode->i_mutex);
+
+       dentry = d_alloc_name(devpts_root, s);
+       if (!IS_ERR(dentry)) {
+               d_add(dentry, inode);
                fsnotify_create(devpts_root->d_inode, dentry);
        }
 
@@ -245,36 +244,31 @@ int devpts_pty_new(struct tty_struct *tty)
        return 0;
 }
 
-struct tty_struct *devpts_get_tty(int number)
+struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
 {
-       struct dentry *dentry = get_node(number);
-       struct tty_struct *tty;
-
-       tty = NULL;
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode)
-                       tty = dentry->d_inode->i_private;
-               dput(dentry);
-       }
+       BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
-       mutex_unlock(&devpts_root->d_inode->i_mutex);
-
-       return tty;
+       if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
+               return (struct tty_struct *)pts_inode->i_private;
+       return NULL;
 }
 
-void devpts_pty_kill(int number)
+void devpts_pty_kill(struct tty_struct *tty)
 {
-       struct dentry *dentry = get_node(number);
+       struct inode *inode = tty->driver_data;
+       struct dentry *dentry;
 
-       if (!IS_ERR(dentry)) {
-               struct inode *inode = dentry->d_inode;
-               if (inode) {
-                       inode->i_nlink--;
-                       d_delete(dentry);
-                       dput(dentry);
-               }
+       BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
+
+       mutex_lock(&devpts_root->d_inode->i_mutex);
+
+       dentry = d_find_alias(inode);
+       if (dentry && !IS_ERR(dentry)) {
+               inode->i_nlink--;
+               d_delete(dentry);
                dput(dentry);
        }
+
        mutex_unlock(&devpts_root->d_inode->i_mutex);
 }
 
index 9606ee848fd81c98ca9fc2cc496e0452140c9205..af0558dbe8b75a65bbe975f6dede7390ff0dbeb9 100644 (file)
@@ -5,11 +5,11 @@
  *
  * O_DIRECT
  *
- * 04Jul2002   akpm@zip.com.au
+ * 04Jul2002   Andrew Morton
  *             Initial version
  * 11Sep2002   janetinc@us.ibm.com
  *             added readv/writev support.
- * 29Oct2002   akpm@zip.com.au
+ * 29Oct2002   Andrew Morton
  *             rewrote bio_add_page() support.
  * 30Oct2002   pbadari@us.ibm.com
  *             added support for non-aligned IO.
index 8ec4d6cc763317bf8403a7eae3c666ef2b97b136..da30a27f2242c7e2e844b630ea02d12474ce7fdd 100644 (file)
@@ -9,8 +9,6 @@
  * implementation is based on one of the several variants of the LINUX
  * inode-subsystem with added complexity of the diskquota system.
  * 
- * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $
- * 
  * Author:     Marco van Wieringen <mvw@planets.elm.net>
  *
  * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
@@ -895,10 +893,9 @@ static void print_warning(struct dquot *dquot, const int warntype)
            warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot))
                return;
 
-       mutex_lock(&tty_mutex);
        tty = get_current_tty();
        if (!tty)
-               goto out_lock;
+               return;
        tty_write_message(tty, dquot->dq_sb->s_id);
        if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN)
                tty_write_message(tty, ": warning, ");
@@ -926,8 +923,7 @@ static void print_warning(struct dquot *dquot, const int warntype)
                        break;
        }
        tty_write_message(tty, msg);
-out_lock:
-       mutex_unlock(&tty_mutex);
+       tty_kref_put(tty);
 }
 #endif
 
index b4755a85996e9d6be9597fb92c05d668ff88713c..2cc9ee4ad2eb774f144e1d706276c7d037c6bb7d 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o kthread.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o
index b73fb752c5f8e9294ce232f4459efa26a79feed4..3504cf9df358076c840b2fe48f26000b965116e0 100644 (file)
 #define ECRYPTFS_MAX_PKI_NAME_BYTES 16
 #define ECRYPTFS_DEFAULT_NUM_USERS 4
 #define ECRYPTFS_MAX_NUM_USERS 32768
-#define ECRYPTFS_TRANSPORT_NETLINK 0
-#define ECRYPTFS_TRANSPORT_CONNECTOR 1
-#define ECRYPTFS_TRANSPORT_RELAYFS 2
-#define ECRYPTFS_TRANSPORT_MISCDEV 3
-#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_MISCDEV
 #define ECRYPTFS_XATTR_NAME "user.ecryptfs"
 
 #define RFC2440_CIPHER_DES3_EDE 0x02
@@ -400,8 +395,6 @@ struct ecryptfs_msg_ctx {
        struct mutex mux;
 };
 
-extern unsigned int ecryptfs_transport;
-
 struct ecryptfs_daemon;
 
 struct ecryptfs_daemon {
@@ -627,31 +620,20 @@ int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags);
 int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
-int ecryptfs_process_helo(unsigned int transport, uid_t euid,
-                         struct user_namespace *user_ns, struct pid *pid);
+int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns,
+                         struct pid *pid);
 int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
                          struct pid *pid);
 int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
                              struct user_namespace *user_ns, struct pid *pid,
                              u32 seq);
-int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+int ecryptfs_send_message(char *data, int data_len,
                          struct ecryptfs_msg_ctx **msg_ctx);
 int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
                               struct ecryptfs_message **emsg);
-int ecryptfs_init_messaging(unsigned int transport);
-void ecryptfs_release_messaging(unsigned int transport);
+int ecryptfs_init_messaging(void);
+void ecryptfs_release_messaging(void);
 
-int ecryptfs_send_netlink(char *data, int data_len,
-                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
-                         u16 msg_flags, struct pid *daemon_pid);
-int ecryptfs_init_netlink(void);
-void ecryptfs_release_netlink(void);
-
-int ecryptfs_send_connector(char *data, int data_len,
-                           struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
-                           u16 msg_flags, struct pid *daemon_pid);
-int ecryptfs_init_connector(void);
-void ecryptfs_release_connector(void);
 void
 ecryptfs_write_header_metadata(char *virt,
                               struct ecryptfs_crypt_stat *crypt_stat,
index 9244d653743ec02c6d279071095f76c08c834dd6..eb3dc4c7ac066c45c99d26218ccda7f623cae9c6 100644 (file)
@@ -71,12 +71,11 @@ struct ecryptfs_getdents_callback {
        void *dirent;
        struct dentry *dentry;
        filldir_t filldir;
-       int err;
        int filldir_called;
        int entries_written;
 };
 
-/* Inspired by generic filldir in fs/readir.c */
+/* Inspired by generic filldir in fs/readdir.c */
 static int
 ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset,
                 u64 ino, unsigned int d_type)
@@ -125,18 +124,18 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
        buf.dirent = dirent;
        buf.dentry = file->f_path.dentry;
        buf.filldir = filldir;
-retry:
        buf.filldir_called = 0;
        buf.entries_written = 0;
-       buf.err = 0;
        rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf);
-       if (buf.err)
-               rc = buf.err;
-       if (buf.filldir_called && !buf.entries_written)
-               goto retry;
        file->f_pos = lower_file->f_pos;
+       if (rc < 0)
+               goto out;
+       if (buf.filldir_called && !buf.entries_written)
+               goto out;
        if (rc >= 0)
-               fsstack_copy_attr_atime(inode, lower_file->f_path.dentry->d_inode);
+               fsstack_copy_attr_atime(inode,
+                                       lower_file->f_path.dentry->d_inode);
+out:
        return rc;
 }
 
index f5b76a331b9c743a3679ae69022f288c60b0f229..e22bc39613458e98fe35169b4de06412d9a4ec3f 100644 (file)
@@ -234,8 +234,8 @@ parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code,
        }
        i += data_len;
        if (message_len < (i + m_size)) {
-               ecryptfs_printk(KERN_ERR, "The received netlink message is "
-                               "shorter than expected\n");
+               ecryptfs_printk(KERN_ERR, "The message received from ecryptfsd "
+                               "is shorter than expected\n");
                rc = -EIO;
                goto out;
        }
@@ -438,8 +438,8 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        struct ecryptfs_msg_ctx *msg_ctx;
        struct ecryptfs_message *msg = NULL;
        char *auth_tok_sig;
-       char *netlink_message;
-       size_t netlink_message_length;
+       char *payload;
+       size_t payload_len;
        int rc;
 
        rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok);
@@ -449,15 +449,15 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
                goto out;
        }
        rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key),
-                                &netlink_message, &netlink_message_length);
+                                &payload, &payload_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet\n");
                goto out;
        }
-       rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
-                                  netlink_message_length, &msg_ctx);
+       rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+               ecryptfs_printk(KERN_ERR, "Error sending message to "
+                               "ecryptfsd\n");
                goto out;
        }
        rc = ecryptfs_wait_for_response(msg_ctx, &msg);
@@ -1333,23 +1333,22 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
                        struct ecryptfs_key_record *key_rec)
 {
        struct ecryptfs_msg_ctx *msg_ctx = NULL;
-       char *netlink_payload;
-       size_t netlink_payload_length;
+       char *payload = NULL;
+       size_t payload_len;
        struct ecryptfs_message *msg;
        int rc;
 
        rc = write_tag_66_packet(auth_tok->token.private_key.signature,
                                 ecryptfs_code_for_cipher_string(crypt_stat),
-                                crypt_stat, &netlink_payload,
-                                &netlink_payload_length);
+                                crypt_stat, &payload, &payload_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
                goto out;
        }
-       rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload,
-                                  netlink_payload_length, &msg_ctx);
+       rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+               ecryptfs_printk(KERN_ERR, "Error sending message to "
+                               "ecryptfsd\n");
                goto out;
        }
        rc = ecryptfs_wait_for_response(msg_ctx, &msg);
@@ -1364,8 +1363,7 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
                ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n");
        kfree(msg);
 out:
-       if (netlink_payload)
-               kfree(netlink_payload);
+       kfree(payload);
        return rc;
 }
 /**
index 448dfd597b5f5d696a480bd33148873317598b84..046e027a4cb192705a49caf27048ac79cf35badb 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/namei.h>
 #include <linux/skbuff.h>
 #include <linux/crypto.h>
-#include <linux/netlink.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/key.h>
@@ -49,8 +48,7 @@ MODULE_PARM_DESC(ecryptfs_verbosity,
                 "0, which is Quiet)");
 
 /**
- * Module parameter that defines the number of netlink message buffer
- * elements
+ * Module parameter that defines the number of message buffer elements
  */
 unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS;
 
@@ -60,9 +58,9 @@ MODULE_PARM_DESC(ecryptfs_message_buf_len,
 
 /**
  * Module parameter that defines the maximum guaranteed amount of time to wait
- * for a response through netlink.  The actual sleep time will be, more than
+ * for a response from ecryptfsd.  The actual sleep time will be, more than
  * likely, a small amount greater than this specified value, but only less if
- * the netlink message successfully arrives.
+ * the message successfully arrives.
  */
 signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ;
 
@@ -83,8 +81,6 @@ module_param(ecryptfs_number_of_users, uint, 0);
 MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of "
                 "concurrent users of eCryptfs");
 
-unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT;
-
 void __ecryptfs_printk(const char *fmt, ...)
 {
        va_list args;
@@ -211,7 +207,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
        ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
        ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {ecryptfs_opt_sig, "sig=%s"},
        {ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"},
        {ecryptfs_opt_cipher, "cipher=%s"},
@@ -779,10 +775,11 @@ static int __init ecryptfs_init(void)
                       "rc = [%d]\n", __func__, rc);
                goto out_do_sysfs_unregistration;
        }
-       rc = ecryptfs_init_messaging(ecryptfs_transport);
+       rc = ecryptfs_init_messaging();
        if (rc) {
                printk(KERN_ERR "Failure occured while attempting to "
-                               "initialize the eCryptfs netlink socket\n");
+                               "initialize the communications channel to "
+                               "ecryptfsd\n");
                goto out_destroy_kthread;
        }
        rc = ecryptfs_init_crypto();
@@ -797,7 +794,7 @@ static int __init ecryptfs_init(void)
 
        goto out;
 out_release_messaging:
-       ecryptfs_release_messaging(ecryptfs_transport);
+       ecryptfs_release_messaging();
 out_destroy_kthread:
        ecryptfs_destroy_kthread();
 out_do_sysfs_unregistration:
@@ -818,7 +815,7 @@ static void __exit ecryptfs_exit(void)
        if (rc)
                printk(KERN_ERR "Failure whilst attempting to destroy crypto; "
                       "rc = [%d]\n", rc);
-       ecryptfs_release_messaging(ecryptfs_transport);
+       ecryptfs_release_messaging();
        ecryptfs_destroy_kthread();
        do_sysfs_unregistration();
        unregister_filesystem(&ecryptfs_fs_type);
index 1b5c20058acbeefddc1031f5700993da2e799c58..c6983978a31eda7218fa921b954848e2d4a5c42c 100644 (file)
@@ -134,12 +134,11 @@ out:
 }
 
 static int
-ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
-                            u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx);
+ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
+                            struct ecryptfs_msg_ctx **msg_ctx);
 
 /**
  * ecryptfs_send_raw_message
- * @transport: Transport type
  * @msg_type: Message type
  * @daemon: Daemon struct for recipient of message
  *
@@ -150,38 +149,25 @@ ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
  *
  * Returns zero on success; non-zero otherwise
  */
-static int ecryptfs_send_raw_message(unsigned int transport, u8 msg_type,
+static int ecryptfs_send_raw_message(u8 msg_type,
                                     struct ecryptfs_daemon *daemon)
 {
        struct ecryptfs_msg_ctx *msg_ctx;
        int rc;
 
-       switch(transport) {
-       case ECRYPTFS_TRANSPORT_NETLINK:
-               rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0,
-                                          daemon->pid);
-               break;
-       case ECRYPTFS_TRANSPORT_MISCDEV:
-               rc = ecryptfs_send_message_locked(transport, NULL, 0, msg_type,
-                                                 &msg_ctx);
-               if (rc) {
-                       printk(KERN_ERR "%s: Error whilst attempting to send "
-                              "message via procfs; rc = [%d]\n", __func__, rc);
-                       goto out;
-               }
-               /* Raw messages are logically context-free (e.g., no
-                * reply is expected), so we set the state of the
-                * ecryptfs_msg_ctx object to indicate that it should
-                * be freed as soon as the transport sends out the message. */
-               mutex_lock(&msg_ctx->mux);
-               msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_NO_REPLY;
-               mutex_unlock(&msg_ctx->mux);
-               break;
-       case ECRYPTFS_TRANSPORT_CONNECTOR:
-       case ECRYPTFS_TRANSPORT_RELAYFS:
-       default:
-               rc = -ENOSYS;
+       rc = ecryptfs_send_message_locked(NULL, 0, msg_type, &msg_ctx);
+       if (rc) {
+               printk(KERN_ERR "%s: Error whilst attempting to send "
+                      "message to ecryptfsd; rc = [%d]\n", __func__, rc);
+               goto out;
        }
+       /* Raw messages are logically context-free (e.g., no
+        * reply is expected), so we set the state of the
+        * ecryptfs_msg_ctx object to indicate that it should
+        * be freed as soon as the message is sent. */
+       mutex_lock(&msg_ctx->mux);
+       msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_NO_REPLY;
+       mutex_unlock(&msg_ctx->mux);
 out:
        return rc;
 }
@@ -227,7 +213,6 @@ out:
 
 /**
  * ecryptfs_process_helo
- * @transport: The underlying transport (netlink, etc.)
  * @euid: The user ID owner of the message
  * @user_ns: The namespace in which @euid applies
  * @pid: The process ID for the userspace program that sent the
@@ -239,8 +224,8 @@ out:
  * Returns zero after adding a new daemon to the hash list;
  * non-zero otherwise.
  */
-int ecryptfs_process_helo(unsigned int transport, uid_t euid,
-                         struct user_namespace *user_ns, struct pid *pid)
+int ecryptfs_process_helo(uid_t euid, struct user_namespace *user_ns,
+                         struct pid *pid)
 {
        struct ecryptfs_daemon *new_daemon;
        struct ecryptfs_daemon *old_daemon;
@@ -252,8 +237,7 @@ int ecryptfs_process_helo(unsigned int transport, uid_t euid,
                printk(KERN_WARNING "Received request from user [%d] "
                       "to register daemon [0x%p]; unregistering daemon "
                       "[0x%p]\n", euid, pid, old_daemon->pid);
-               rc = ecryptfs_send_raw_message(transport, ECRYPTFS_MSG_QUIT,
-                                              old_daemon);
+               rc = ecryptfs_send_raw_message(ECRYPTFS_MSG_QUIT, old_daemon);
                if (rc)
                        printk(KERN_WARNING "Failed to send QUIT "
                               "message to daemon [0x%p]; rc = [%d]\n",
@@ -467,8 +451,6 @@ out:
 
 /**
  * ecryptfs_send_message_locked
- * @transport: The transport over which to send the message (i.e.,
- *             netlink)
  * @data: The data to send
  * @data_len: The length of data
  * @msg_ctx: The message context allocated for the send
@@ -478,8 +460,8 @@ out:
  * Returns zero on success; non-zero otherwise
  */
 static int
-ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
-                            u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx)
+ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type,
+                            struct ecryptfs_msg_ctx **msg_ctx)
 {
        struct ecryptfs_daemon *daemon;
        int rc;
@@ -503,20 +485,8 @@ ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
        ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
        mutex_unlock(&(*msg_ctx)->mux);
        mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
-       switch (transport) {
-       case ECRYPTFS_TRANSPORT_NETLINK:
-               rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, msg_type,
-                                          0, daemon->pid);
-               break;
-       case ECRYPTFS_TRANSPORT_MISCDEV:
-               rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type,
-                                          0, daemon);
-               break;
-       case ECRYPTFS_TRANSPORT_CONNECTOR:
-       case ECRYPTFS_TRANSPORT_RELAYFS:
-       default:
-               rc = -ENOSYS;
-       }
+       rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type, 0,
+                                  daemon);
        if (rc)
                printk(KERN_ERR "%s: Error attempting to send message to "
                       "userspace daemon; rc = [%d]\n", __func__, rc);
@@ -526,8 +496,6 @@ out:
 
 /**
  * ecryptfs_send_message
- * @transport: The transport over which to send the message (i.e.,
- *             netlink)
  * @data: The data to send
  * @data_len: The length of data
  * @msg_ctx: The message context allocated for the send
@@ -536,14 +504,14 @@ out:
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+int ecryptfs_send_message(char *data, int data_len,
                          struct ecryptfs_msg_ctx **msg_ctx)
 {
        int rc;
 
        mutex_lock(&ecryptfs_daemon_hash_mux);
-       rc = ecryptfs_send_message_locked(transport, data, data_len,
-                                         ECRYPTFS_MSG_REQUEST, msg_ctx);
+       rc = ecryptfs_send_message_locked(data, data_len, ECRYPTFS_MSG_REQUEST,
+                                         msg_ctx);
        mutex_unlock(&ecryptfs_daemon_hash_mux);
        return rc;
 }
@@ -586,7 +554,7 @@ sleep:
        return rc;
 }
 
-int ecryptfs_init_messaging(unsigned int transport)
+int ecryptfs_init_messaging(void)
 {
        int i;
        int rc = 0;
@@ -639,27 +607,14 @@ int ecryptfs_init_messaging(unsigned int transport)
                mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
        }
        mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
-       switch(transport) {
-       case ECRYPTFS_TRANSPORT_NETLINK:
-               rc = ecryptfs_init_netlink();
-               if (rc)
-                       ecryptfs_release_messaging(transport);
-               break;
-       case ECRYPTFS_TRANSPORT_MISCDEV:
-               rc = ecryptfs_init_ecryptfs_miscdev();
-               if (rc)
-                       ecryptfs_release_messaging(transport);
-               break;
-       case ECRYPTFS_TRANSPORT_CONNECTOR:
-       case ECRYPTFS_TRANSPORT_RELAYFS:
-       default:
-               rc = -ENOSYS;
-       }
+       rc = ecryptfs_init_ecryptfs_miscdev();
+       if (rc)
+               ecryptfs_release_messaging();
 out:
        return rc;
 }
 
-void ecryptfs_release_messaging(unsigned int transport)
+void ecryptfs_release_messaging(void)
 {
        if (ecryptfs_msg_ctx_arr) {
                int i;
@@ -698,17 +653,6 @@ void ecryptfs_release_messaging(unsigned int transport)
                kfree(ecryptfs_daemon_hash);
                mutex_unlock(&ecryptfs_daemon_hash_mux);
        }
-       switch(transport) {
-       case ECRYPTFS_TRANSPORT_NETLINK:
-               ecryptfs_release_netlink();
-               break;
-       case ECRYPTFS_TRANSPORT_MISCDEV:
-               ecryptfs_destroy_ecryptfs_miscdev();
-               break;
-       case ECRYPTFS_TRANSPORT_CONNECTOR:
-       case ECRYPTFS_TRANSPORT_RELAYFS:
-       default:
-               break;
-       }
+       ecryptfs_destroy_ecryptfs_miscdev();
        return;
 }
index 245c2dc02d5cfa96d1fe60818ae849555ef5e991..04d7b3fa1ac6cd7679237cd2188a385c67bf960c 100644 (file)
@@ -265,22 +265,34 @@ out:
 }
 
 /**
- * ecryptfs_prepare_write
+ * ecryptfs_write_begin
  * @file: The eCryptfs file
- * @page: The eCryptfs page
- * @from: The start byte from which we will write
- * @to: The end byte to which we will write
+ * @mapping: The eCryptfs object
+ * @pos: The file offset at which to start writing
+ * @len: Length of the write
+ * @flags: Various flags
+ * @pagep: Pointer to return the page
+ * @fsdata: Pointer to return fs data (unused)
  *
  * This function must zero any hole we create
  *
  * Returns zero on success; non-zero otherwise
  */
-static int ecryptfs_prepare_write(struct file *file, struct page *page,
-                                 unsigned from, unsigned to)
+static int ecryptfs_write_begin(struct file *file,
+                       struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned flags,
+                       struct page **pagep, void **fsdata)
 {
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+       struct page *page;
        loff_t prev_page_end_size;
        int rc = 0;
 
+       page = __grab_cache_page(mapping, index);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
        if (!PageUptodate(page)) {
                struct ecryptfs_crypt_stat *crypt_stat =
                        &ecryptfs_inode_to_private(
@@ -289,8 +301,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
                    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
                        rc = ecryptfs_read_lower_page_segment(
-                               page, page->index, 0, PAGE_CACHE_SIZE,
-                               page->mapping->host);
+                               page, index, 0, PAGE_CACHE_SIZE, mapping->host);
                        if (rc) {
                                printk(KERN_ERR "%s: Error attemping to read "
                                       "lower page segment; rc = [%d]\n",
@@ -316,8 +327,8 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                                SetPageUptodate(page);
                        } else {
                                rc = ecryptfs_read_lower_page_segment(
-                                       page, page->index, 0, PAGE_CACHE_SIZE,
-                                       page->mapping->host);
+                                       page, index, 0, PAGE_CACHE_SIZE,
+                                       mapping->host);
                                if (rc) {
                                        printk(KERN_ERR "%s: Error reading "
                                               "page; rc = [%d]\n",
@@ -339,10 +350,10 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                        SetPageUptodate(page);
                }
        }
-       prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
+       prev_page_end_size = ((loff_t)index << PAGE_CACHE_SHIFT);
        /* If creating a page or more of holes, zero them out via truncate.
         * Note, this will increase i_size. */
-       if (page->index != 0) {
+       if (index != 0) {
                if (prev_page_end_size > i_size_read(page->mapping->host)) {
                        rc = ecryptfs_truncate(file->f_path.dentry,
                                               prev_page_end_size);
@@ -357,8 +368,8 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
        }
        /* Writing to a new page, and creating a small hole from start
         * of page?  Zero it out. */
-       if ((i_size_read(page->mapping->host) == prev_page_end_size)
-           && (from != 0))
+       if ((i_size_read(mapping->host) == prev_page_end_size)
+           && (pos != 0))
                zero_user(page, 0, PAGE_CACHE_SIZE);
 out:
        return rc;
@@ -445,21 +456,28 @@ int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode)
 }
 
 /**
- * ecryptfs_commit_write
+ * ecryptfs_write_end
  * @file: The eCryptfs file object
+ * @mapping: The eCryptfs object
+ * @pos: The file position
+ * @len: The length of the data (unused)
+ * @copied: The amount of data copied
  * @page: The eCryptfs page
- * @from: Ignored (we rotate the page IV on each write)
- * @to: Ignored
+ * @fsdata: The fsdata (unused)
  *
  * This is where we encrypt the data and pass the encrypted data to
  * the lower filesystem.  In OpenPGP-compatible mode, we operate on
  * entire underlying packets.
  */
-static int ecryptfs_commit_write(struct file *file, struct page *page,
-                                unsigned from, unsigned to)
+static int ecryptfs_write_end(struct file *file,
+                       struct address_space *mapping,
+                       loff_t pos, unsigned len, unsigned copied,
+                       struct page *page, void *fsdata)
 {
-       loff_t pos;
-       struct inode *ecryptfs_inode = page->mapping->host;
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+       unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+       unsigned to = from + copied;
+       struct inode *ecryptfs_inode = mapping->host;
        struct ecryptfs_crypt_stat *crypt_stat =
                &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)->crypt_stat;
        int rc;
@@ -471,25 +489,22 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
        } else
                ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
        ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
-                       "(page w/ index = [0x%.16x], to = [%d])\n", page->index,
-                       to);
+                       "(page w/ index = [0x%.16x], to = [%d])\n", index, to);
        /* Fills in zeros if 'to' goes beyond inode size */
        rc = fill_zeros_to_end_of_page(page, to);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error attempting to fill "
-                               "zeros in page with index = [0x%.16x]\n",
-                               page->index);
+                       "zeros in page with index = [0x%.16x]\n", index);
                goto out;
        }
        rc = ecryptfs_encrypt_page(page);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper "
-                               "index [0x%.16x])\n", page->index);
+                               "index [0x%.16x])\n", index);
                goto out;
        }
-       pos = (((loff_t)page->index) << PAGE_CACHE_SHIFT) + to;
-       if (pos > i_size_read(ecryptfs_inode)) {
-               i_size_write(ecryptfs_inode, pos);
+       if (pos + copied > i_size_read(ecryptfs_inode)) {
+               i_size_write(ecryptfs_inode, pos + copied);
                ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
                                "[0x%.16x]\n", i_size_read(ecryptfs_inode));
        }
@@ -497,7 +512,11 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
        if (rc)
                printk(KERN_ERR "Error writing inode size to metadata; "
                       "rc = [%d]\n", rc);
+       else
+               rc = copied;
 out:
+       unlock_page(page);
+       page_cache_release(page);
        return rc;
 }
 
@@ -518,7 +537,7 @@ static sector_t ecryptfs_bmap(struct address_space *mapping, sector_t block)
 struct address_space_operations ecryptfs_aops = {
        .writepage = ecryptfs_writepage,
        .readpage = ecryptfs_readpage,
-       .prepare_write = ecryptfs_prepare_write,
-       .commit_write = ecryptfs_commit_write,
+       .write_begin = ecryptfs_write_begin,
+       .write_end = ecryptfs_write_end,
        .bmap = ecryptfs_bmap,
 };
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
deleted file mode 100644 (file)
index e0abad6..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- * eCryptfs: Linux filesystem encryption layer
- *
- * Copyright (C) 2004-2006 International Business Machines Corp.
- *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
- *             Tyler Hicks <tyhicks@ou.edu>
- *
- * This program is free software; you can 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 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 <net/sock.h>
-#include <linux/hash.h>
-#include <linux/random.h>
-#include "ecryptfs_kernel.h"
-
-static struct sock *ecryptfs_nl_sock;
-
-/**
- * ecryptfs_send_netlink
- * @data: The data to include as the payload
- * @data_len: The byte count of the data
- * @msg_ctx: The netlink context that will be used to handle the
- *          response message
- * @msg_type: The type of netlink message to send
- * @msg_flags: The flags to include in the netlink header
- * @daemon_pid: The process id of the daemon to send the message to
- *
- * Sends the data to the specified daemon pid and uses the netlink
- * context element to store the data needed for validation upon
- * receiving the response.  The data and the netlink context can be
- * null if just sending a netlink header is sufficient.  Returns zero
- * upon sending the message; non-zero upon error.
- */
-int ecryptfs_send_netlink(char *data, int data_len,
-                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
-                         u16 msg_flags, struct pid *daemon_pid)
-{
-       struct sk_buff *skb;
-       struct nlmsghdr *nlh;
-       struct ecryptfs_message *msg;
-       size_t payload_len;
-       int rc;
-
-       payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0);
-       skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL);
-       if (!skb) {
-               rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
-               goto out;
-       }
-       nlh = NLMSG_PUT(skb, pid_nr(daemon_pid), msg_ctx ? msg_ctx->counter : 0,
-                       msg_type, payload_len);
-       nlh->nlmsg_flags = msg_flags;
-       if (msg_ctx && payload_len) {
-               msg = (struct ecryptfs_message *)NLMSG_DATA(nlh);
-               msg->index = msg_ctx->index;
-               msg->data_len = data_len;
-               memcpy(msg->data, data, data_len);
-       }
-       rc = netlink_unicast(ecryptfs_nl_sock, skb, pid_nr(daemon_pid), 0);
-       if (rc < 0) {
-               ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
-                               "message; rc = [%d]\n", rc);
-               goto out;
-       }
-       rc = 0;
-       goto out;
-nlmsg_failure:
-       rc = -EMSGSIZE;
-       kfree_skb(skb);
-out:
-       return rc;
-}
-
-/**
- * ecryptfs_process_nl_reponse
- * @skb: The socket buffer containing the netlink message of state
- *       RESPONSE
- *
- * Processes a response message after sending a operation request to
- * userspace.  Attempts to assign the msg to a netlink context element
- * at the index specified in the msg.  The sk_buff and nlmsghdr must
- * be validated before this function. Returns zero upon delivery to
- * desired context element; non-zero upon delivery failure or error.
- */
-static int ecryptfs_process_nl_response(struct sk_buff *skb)
-{
-       struct nlmsghdr *nlh = nlmsg_hdr(skb);
-       struct ecryptfs_message *msg = NLMSG_DATA(nlh);
-       struct pid *pid;
-       int rc;
-
-       if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
-               rc = -EINVAL;
-               ecryptfs_printk(KERN_ERR, "Received netlink message with "
-                               "incorrectly specified data length\n");
-               goto out;
-       }
-       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
-       rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, NULL,
-                                      pid, nlh->nlmsg_seq);
-       put_pid(pid);
-       if (rc)
-               printk(KERN_ERR
-                      "Error processing response message; rc = [%d]\n", rc);
-out:
-       return rc;
-}
-
-/**
- * ecryptfs_process_nl_helo
- * @skb: The socket buffer containing the nlmsghdr in HELO state
- *
- * Gets uid and pid of the skb and adds the values to the daemon id
- * hash. Returns zero after adding a new daemon id to the hash list;
- * non-zero otherwise.
- */
-static int ecryptfs_process_nl_helo(struct sk_buff *skb)
-{
-       struct pid *pid;
-       int rc;
-
-       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
-       rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
-                                  NETLINK_CREDS(skb)->uid, NULL, pid);
-       put_pid(pid);
-       if (rc)
-               printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
-       return rc;
-}
-
-/**
- * ecryptfs_process_nl_quit
- * @skb: The socket buffer containing the nlmsghdr in QUIT state
- *
- * Gets uid and pid of the skb and deletes the corresponding daemon
- * id, if it is the registered that is requesting the
- * deletion. Returns zero after deleting the desired daemon id;
- * non-zero otherwise.
- */
-static int ecryptfs_process_nl_quit(struct sk_buff *skb)
-{
-       struct pid *pid;
-       int rc;
-
-       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
-       rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, NULL, pid);
-       put_pid(pid);
-       if (rc)
-               printk(KERN_WARNING
-                      "Error processing QUIT message; rc = [%d]\n", rc);
-       return rc;
-}
-
-/**
- * ecryptfs_receive_nl_message
- *
- * Callback function called by netlink system when a message arrives.
- * If the message looks to be valid, then an attempt is made to assign
- * it to its desired netlink context element and wake up the process
- * that is waiting for a response.
- */
-static void ecryptfs_receive_nl_message(struct sk_buff *skb)
-{
-       struct nlmsghdr *nlh;
-
-       nlh = nlmsg_hdr(skb);
-       if (!NLMSG_OK(nlh, skb->len)) {
-               ecryptfs_printk(KERN_ERR, "Received corrupt netlink "
-                               "message\n");
-               goto free;
-       }
-       switch (nlh->nlmsg_type) {
-               case ECRYPTFS_MSG_RESPONSE:
-                       if (ecryptfs_process_nl_response(skb)) {
-                               ecryptfs_printk(KERN_WARNING, "Failed to "
-                                               "deliver netlink response to "
-                                               "requesting operation\n");
-                       }
-                       break;
-               case ECRYPTFS_MSG_HELO:
-                       if (ecryptfs_process_nl_helo(skb)) {
-                               ecryptfs_printk(KERN_WARNING, "Failed to "
-                                               "fulfill HELO request\n");
-                       }
-                       break;
-               case ECRYPTFS_MSG_QUIT:
-                       if (ecryptfs_process_nl_quit(skb)) {
-                               ecryptfs_printk(KERN_WARNING, "Failed to "
-                                               "fulfill QUIT request\n");
-                       }
-                       break;
-               default:
-                       ecryptfs_printk(KERN_WARNING, "Dropping netlink "
-                                       "message of unrecognized type [%d]\n",
-                                       nlh->nlmsg_type);
-                       break;
-       }
-free:
-       kfree_skb(skb);
-}
-
-/**
- * ecryptfs_init_netlink
- *
- * Initializes the daemon id hash list, netlink context array, and
- * necessary locks.  Returns zero upon success; non-zero upon error.
- */
-int ecryptfs_init_netlink(void)
-{
-       int rc;
-
-       ecryptfs_nl_sock = netlink_kernel_create(&init_net, NETLINK_ECRYPTFS, 0,
-                                                ecryptfs_receive_nl_message,
-                                                NULL, THIS_MODULE);
-       if (!ecryptfs_nl_sock) {
-               rc = -EIO;
-               ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n");
-               goto out;
-       }
-       ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT;
-       rc = 0;
-out:
-       return rc;
-}
-
-/**
- * ecryptfs_release_netlink
- *
- * Frees all memory used by the netlink context array and releases the
- * netlink socket.
- */
-void ecryptfs_release_netlink(void)
-{
-       netlink_kernel_release(ecryptfs_nl_sock);
-       ecryptfs_nl_sock = NULL;
-}
index 567b134fa1f156f1c886e488771fbcb06ab61089..73b19cfc91fc57510cc96d8863b776748550b65a 100644 (file)
@@ -341,8 +341,6 @@ static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
                        sb->inode_blocks *
                        (EFS_BLOCKSIZE / sizeof(struct efs_dinode));
        buf->f_ffree   = sb->inode_free;        /* free inodes */
-       buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
-       buf->f_fsid.val[1] =  sb->fs_magic        & 0xffff; /* fs ID */
        buf->f_namelen = EFS_MAXNAMELEN;        /* max filename length */
 
        return 0;
index 7cc0eb756b55e99e5f876eaa43c6c4e466b27b05..99368bda0261321290a6afa52ad74a797f79cd54 100644 (file)
@@ -927,14 +927,11 @@ errxit:
        /*
         * During the time we spent in the loop above, some other events
         * might have been queued by the poll callback. We re-insert them
-        * here (in case they are not already queued, or they're one-shot).
+        * inside the main ready-list here.
         */
        for (nepi = ep->ovflist; (epi = nepi) != NULL;
-            nepi = epi->next, epi->next = EP_UNACTIVE_PTR) {
-               if (!ep_is_linked(&epi->rdllink) &&
-                   (epi->event.events & ~EP_PRIVATE_BITS))
-                       list_add_tail(&epi->rdllink, &ep->rdllist);
-       }
+            nepi = epi->next, epi->next = EP_UNACTIVE_PTR)
+               list_add_tail(&epi->rdllink, &ep->rdllist);
        /*
         * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after
         * releasing the lock, events will be queued in the normal way inside
index cecee501ce78805c32c9d007c658fce1e87b0a97..a41e7902ed0bf9ef9e2cd600c31b1acda0576ed4 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
 #include <linux/tracehook.h>
+#include <linux/kmod.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #ifdef __alpha__
 /* for /sbin/loader handling in search_binary_handler() */
 #include <linux/a.out.h>
@@ -391,7 +388,7 @@ static int count(char __user * __user * argv, int max)
                        if (!p)
                                break;
                        argv++;
-                       if(++i > max)
+                       if (i++ >= max)
                                return -E2BIG;
                        cond_resched();
                }
@@ -825,8 +822,6 @@ static int de_thread(struct task_struct *tsk)
                        schedule();
                }
 
-               if (unlikely(task_child_reaper(tsk) == leader))
-                       task_active_pid_ns(tsk)->child_reaper = tsk;
                /*
                 * The only record we have of the real-time age of a
                 * process, regardless of execs it's done, is start_time.
@@ -1189,7 +1184,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        return retval;
 
                /* Remember if the application is TASO.  */
-               bprm->sh_bang = eh->ah.entry < 0x100000000UL;
+               bprm->taso = eh->ah.entry < 0x100000000UL;
 
                bprm->file = file;
                bprm->loader = loader;
@@ -1247,8 +1242,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                read_unlock(&binfmt_lock);
                if (retval != -ENOEXEC || bprm->mm == NULL) {
                        break;
-#ifdef CONFIG_KMOD
-               }else{
+#ifdef CONFIG_MODULES
+               } else {
 #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
                        if (printable(bprm->buf[0]) &&
                            printable(bprm->buf[1]) &&
index 10bb02c3f25cfcdee98897b6d7efe96e5f3ae6a1..6dac7ba2d22d7ff41855b7866f757417612c09ea 100644 (file)
@@ -1295,6 +1295,7 @@ retry_alloc:
         * turn off reservation for this allocation
         */
        if (my_rsv && (free_blocks < windowsz)
+               && (free_blocks > 0)
                && (rsv_is_empty(&my_rsv->rsv_window)))
                my_rsv = NULL;
 
@@ -1332,7 +1333,7 @@ retry_alloc:
                 * free blocks is less than half of the reservation
                 * window size.
                 */
-               if (free_blocks <= (windowsz/2))
+               if (my_rsv && (free_blocks <= (windowsz/2)))
                        continue;
 
                brelse(bitmap_bh);
index a78c6b4af06012a82c6a1ed3095b9ce4fc2e22fb..11a49ce84392a1e39bc1c335273c4f1ab2ee0d8f 100644 (file)
@@ -103,7 +103,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
        return err;
 }
 
-static void ext2_check_page(struct page *page)
+static void ext2_check_page(struct page *page, int quiet)
 {
        struct inode *dir = page->mapping->host;
        struct super_block *sb = dir->i_sb;
@@ -146,10 +146,10 @@ out:
        /* Too bad, we had an error */
 
 Ebadsize:
-       ext2_error(sb, "ext2_check_page",
-               "size of directory #%lu is not a multiple of chunk size",
-               dir->i_ino
-       );
+       if (!quiet)
+               ext2_error(sb, __func__,
+                       "size of directory #%lu is not a multiple "
+                       "of chunk size", dir->i_ino);
        goto fail;
 Eshort:
        error = "rec_len is smaller than minimal";
@@ -166,32 +166,36 @@ Espan:
 Einumber:
        error = "inode out of bounds";
 bad_entry:
-       ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
-               "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
-               dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
-               (unsigned long) le32_to_cpu(p->inode),
-               rec_len, p->name_len);
+       if (!quiet)
+               ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
+                       "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+                       dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
+                       (unsigned long) le32_to_cpu(p->inode),
+                       rec_len, p->name_len);
        goto fail;
 Eend:
-       p = (ext2_dirent *)(kaddr + offs);
-       ext2_error (sb, "ext2_check_page",
-               "entry in directory #%lu spans the page boundary"
-               "offset=%lu, inode=%lu",
-               dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
-               (unsigned long) le32_to_cpu(p->inode));
+       if (!quiet) {
+               p = (ext2_dirent *)(kaddr + offs);
+               ext2_error(sb, "ext2_check_page",
+                       "entry in directory #%lu spans the page boundary"
+                       "offset=%lu, inode=%lu",
+                       dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
+                       (unsigned long) le32_to_cpu(p->inode));
+       }
 fail:
        SetPageChecked(page);
        SetPageError(page);
 }
 
-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
+static struct page * ext2_get_page(struct inode *dir, unsigned long n,
+                                  int quiet)
 {
        struct address_space *mapping = dir->i_mapping;
        struct page *page = read_mapping_page(mapping, n, NULL);
        if (!IS_ERR(page)) {
                kmap(page);
                if (!PageChecked(page))
-                       ext2_check_page(page);
+                       ext2_check_page(page, quiet);
                if (PageError(page))
                        goto fail;
        }
@@ -292,7 +296,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
        for ( ; n < npages; n++, offset = 0) {
                char *kaddr, *limit;
                ext2_dirent *de;
-               struct page *page = ext2_get_page(inode, n);
+               struct page *page = ext2_get_page(inode, n, 0);
 
                if (IS_ERR(page)) {
                        ext2_error(sb, __func__,
@@ -361,6 +365,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
        struct page *page = NULL;
        struct ext2_inode_info *ei = EXT2_I(dir);
        ext2_dirent * de;
+       int dir_has_error = 0;
 
        if (npages == 0)
                goto out;
@@ -374,7 +379,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
        n = start;
        do {
                char *kaddr;
-               page = ext2_get_page(dir, n);
+               page = ext2_get_page(dir, n, dir_has_error);
                if (!IS_ERR(page)) {
                        kaddr = page_address(page);
                        de = (ext2_dirent *) kaddr;
@@ -391,7 +396,9 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
                                de = ext2_next_entry(de);
                        }
                        ext2_put_page(page);
-               }
+               } else
+                       dir_has_error = 1;
+
                if (++n >= npages)
                        n = 0;
                /* next page is past the blocks we've got */
@@ -414,7 +421,7 @@ found:
 
 struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
 {
-       struct page *page = ext2_get_page(dir, 0);
+       struct page *page = ext2_get_page(dir, 0, 0);
        ext2_dirent *de = NULL;
 
        if (!IS_ERR(page)) {
@@ -487,7 +494,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
        for (n = 0; n <= npages; n++) {
                char *dir_end;
 
-               page = ext2_get_page(dir, n);
+               page = ext2_get_page(dir, n, 0);
                err = PTR_ERR(page);
                if (IS_ERR(page))
                        goto out;
@@ -655,14 +662,17 @@ int ext2_empty_dir (struct inode * inode)
 {
        struct page *page = NULL;
        unsigned long i, npages = dir_pages(inode);
+       int dir_has_error = 0;
 
        for (i = 0; i < npages; i++) {
                char *kaddr;
                ext2_dirent * de;
-               page = ext2_get_page(inode, i);
+               page = ext2_get_page(inode, i, dir_has_error);
 
-               if (IS_ERR(page))
+               if (IS_ERR(page)) {
+                       dir_has_error = 1;
                        continue;
+               }
 
                kaddr = page_address(page);
                de = (ext2_dirent *)kaddr;
index fd88c7b43e66b3c7e5eec0594a95eb455fdebae4..647cd888ac87c8933a168e3ff05ca6dbe201e786 100644 (file)
@@ -393,7 +393,7 @@ enum {
        Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_bsd_df, "bsddf"},
        {Opt_minix_df, "minixdf"},
        {Opt_grpid, "grpid"},
index f38a5afc39a160c15b5a9e518ba41dd8bd4da2af..399a96a6c5561666f61c7a8f7cae3a71dbc5b52f 100644 (file)
@@ -760,7 +760,7 @@ enum {
        Opt_grpquota
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_bsd_df, "bsddf"},
        {Opt_minix_df, "minixdf"},
        {Opt_grpid, "grpid"},
index fb940c22ab0da95960f3c5bb757d79ef5a6222a2..dea8f13c2fd98f3457c50faefd84be2c78399adf 100644 (file)
@@ -919,7 +919,7 @@ enum {
        Opt_inode_readahead_blks
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_bsd_df, "bsddf"},
        {Opt_minix_df, "minixdf"},
        {Opt_grpid, "grpid"},
index 80ff3381fa218950b7753db8ac907144f7579e4f..d12cdf2a0406695b43a85e8db5b7f0990d7d2c5a 100644 (file)
@@ -855,7 +855,7 @@ enum {
        Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err,
 };
 
-static match_table_t fat_tokens = {
+static const match_table_t fat_tokens = {
        {Opt_check_r, "check=relaxed"},
        {Opt_check_s, "check=strict"},
        {Opt_check_n, "check=normal"},
@@ -890,14 +890,14 @@ static match_table_t fat_tokens = {
        {Opt_tz_utc, "tz=UTC"},
        {Opt_err, NULL},
 };
-static match_table_t msdos_tokens = {
+static const match_table_t msdos_tokens = {
        {Opt_nodots, "nodots"},
        {Opt_nodots, "dotsOK=no"},
        {Opt_dots, "dots"},
        {Opt_dots, "dotsOK=yes"},
        {Opt_err, NULL}
 };
-static match_table_t vfat_tokens = {
+static const match_table_t vfat_tokens = {
        {Opt_charset, "iocharset=%s"},
        {Opt_shortname_lower, "shortname=lower"},
        {Opt_shortname_win95, "shortname=win95"},
index 25adfc3c693ab4673777801ecc0e014db9624ec8..d0ff0b8cf30988a23ad144f92f8b7543790bbe67 100644 (file)
@@ -8,7 +8,7 @@
  * pages against inodes.  ie: data writeback.  Writeout of the
  * inode itself is not handled here.
  *
- * 10Apr2002   akpm@zip.com.au
+ * 10Apr2002   Andrew Morton
  *             Split out of fs/inode.c
  *             Additions for address_space-based writeback
  */
index d2249f174e207b109e30eaea1701591d0db4631d..6a84388cacff6f3e0cf5a5d9e307bad71610d5df 100644 (file)
@@ -354,7 +354,7 @@ enum {
        OPT_ERR
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {OPT_FD,                        "fd=%u"},
        {OPT_ROOTMODE,                  "rootmode=%o"},
        {OPT_USER_ID,                   "user_id=%u"},
index df48333e6f010596b49aa1bba963ae0856213e3d..f96eb90a2cfa1a58d7a16215e8833e38a6e6fff3 100644 (file)
@@ -46,7 +46,7 @@ enum {
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_lockproto, "lockproto=%s"},
        {Opt_locktable, "locktable=%s"},
        {Opt_hostdata, "hostdata=%s"},
index ba851576ebb13233eb2c84b4dc968f2caa2218f6..6d98f116ca03d610a1477dc77558c899f5abe48d 100644 (file)
@@ -190,6 +190,10 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
 
        fd->search_key->cat.ParID = rec.thread.ParID;
        len = fd->search_key->cat.CName.len = rec.thread.CName.len;
+       if (len > HFS_NAMELEN) {
+               printk(KERN_ERR "hfs: bad catalog namelength\n");
+               return -EIO;
+       }
        memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
        return hfs_brec_find(fd);
 }
index 4abb1047c68992806125c1ad003e91a9f0cdbd41..3c7c7637719cfd6e83531402e0759f38c794e3a6 100644 (file)
@@ -173,7 +173,7 @@ enum {
        opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        { opt_uid, "uid=%u" },
        { opt_gid, "gid=%u" },
        { opt_umask, "umask=%o" },
index d128a25b74d2e78ae14b5e06473629add09d620b..ea30afc2a03c774221cc17341c446d30a0cb341b 100644 (file)
@@ -32,6 +32,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
        mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
        mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
        page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
+       if (IS_ERR(page)) {
+               start = size;
+               goto out;
+       }
        pptr = kmap(page);
        curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
        i = offset % 32;
@@ -73,6 +77,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
                        break;
                page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
                                         NULL);
+               if (IS_ERR(page)) {
+                       start = size;
+                       goto out;
+               }
                curr = pptr = kmap(page);
                if ((size ^ offset) / PAGE_CACHE_BITS)
                        end = pptr + PAGE_CACHE_BITS / 32;
@@ -120,6 +128,10 @@ found:
                offset += PAGE_CACHE_BITS;
                page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
                                         NULL);
+               if (IS_ERR(page)) {
+                       start = size;
+                       goto out;
+               }
                pptr = kmap(page);
                curr = pptr;
                end = pptr + PAGE_CACHE_BITS / 32;
index ba117c445e78d8127e9835fd37a1bd50c07791f0..f6874acb2cf2a3a81a242f1983600eb912b9f607 100644 (file)
@@ -168,6 +168,11 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
                return -EIO;
        }
 
+       if (be16_to_cpu(tmp.thread.nodeName.length) > 255) {
+               printk(KERN_ERR "hfs: catalog name length corrupted\n");
+               return -EIO;
+       }
+
        hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID),
                                 &tmp.thread.nodeName);
        return hfs_brec_find(fd);
index 9997cbf8beb50ece6abfa28dc18f3223037eab01..9699c56d323f1d35a60f2beac0b31059a5207bac 100644 (file)
@@ -25,7 +25,7 @@ enum {
        opt_force, opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        { opt_creator, "creator=%s" },
        { opt_type, "type=%s" },
        { opt_umask, "umask=%o" },
index e834e578c93f8f475f0194831a214e8eb4534138..eb74531a0a8e267bec8491a18a83ed65b1a8d853 100644 (file)
@@ -356,7 +356,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
                printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
-       } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
+       } else if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) && !(sb->s_flags & MS_RDONLY)) {
                printk(KERN_WARNING "hfs: write access to a journaled filesystem is not supported, "
                       "use the force option at your own risk, mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
index b8ae9c90ada0e9a7c9fbd9a93a6d5ddb8d8eb276..29ad461d568f7f4b4241e3e0c4d2239bbe30a277 100644 (file)
@@ -215,7 +215,7 @@ enum {
        Opt_timeshift, Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_help, "help"},
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
index 3f58923fb39bc11c284980c3e53a6d70de3d9a0d..61edc701b0e62eed87d702373e2c9a36d4b23581 100644 (file)
@@ -57,7 +57,7 @@ enum {
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_size,      "size=%s"},
        {Opt_nr_inodes, "nr_inodes=%s"},
        {Opt_mode,      "mode=%o"},
index 26948a6033b69a71d82ba0b281c5efd7aa7dcec4..3f8af0f1505b8d65bab47437a9fe707cfd8be4b1 100644 (file)
@@ -310,7 +310,7 @@ enum {
        Opt_nocompress, Opt_hide, Opt_showassoc, Opt_dmode,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_norock, "norock"},
        {Opt_nojoliet, "nojoliet"},
        {Opt_unhide, "unhide"},
index 3630718be395deaada9cfe0c28d11a877fcc31e7..0dae345e481b4b3ff235691a19ca9384cdddb0d1 100644 (file)
@@ -199,7 +199,7 @@ enum {
        Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_integrity, "integrity"},
        {Opt_nointegrity, "nointegrity"},
        {Opt_iocharset, "iocharset=%s"},
index 7725a0a9a5553bf2db33b0fc81b1f92dbe7b48fc..97f6073ab339b327d4a5448224d18886eb3f42f7 100644 (file)
@@ -5,6 +5,6 @@
 obj-$(CONFIG_LOCKD) += lockd.o
 
 lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
-               svcproc.o svcsubs.o mon.o xdr.o
+               svcproc.o svcsubs.o mon.o xdr.o grace.o
 lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o
 lockd-objs                   := $(lockd-objs-y)
index 0b45fd3a4bfd6dfdb9e6e8d426a46489954822bb..8307dd64bf46ca746d9c973f209626de49627d17 100644 (file)
@@ -54,14 +54,13 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
        u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4;
        int status;
 
-       status = lockd_up(nlm_init->protocol);
+       status = lockd_up();
        if (status < 0)
                return ERR_PTR(status);
 
-       host = nlmclnt_lookup_host((struct sockaddr_in *)nlm_init->address,
+       host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen,
                                   nlm_init->protocol, nlm_version,
-                                  nlm_init->hostname,
-                                  strlen(nlm_init->hostname));
+                                  nlm_init->hostname);
        if (host == NULL) {
                lockd_down();
                return ERR_PTR(-ENOLCK);
@@ -142,7 +141,7 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
 /*
  * The server lockd has called us back to tell us the lock was granted
  */
-__be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
+__be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
 {
        const struct file_lock *fl = &lock->fl;
        const struct nfs_fh *fh = &lock->fh;
@@ -166,7 +165,7 @@ __be32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock
                 */
                if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
                        continue;
-               if (!nlm_cmp_addr(&block->b_host->h_addr, addr))
+               if (!nlm_cmp_addr(nlm_addr(block->b_host), addr))
                        continue;
                if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0)
                        continue;
@@ -216,7 +215,7 @@ reclaimer(void *ptr)
        /* This one ensures that our parent doesn't terminate while the
         * reclaim is in progress */
        lock_kernel();
-       lockd_up(0); /* note: this cannot fail as lockd is already running */
+       lockd_up();     /* note: this cannot fail as lockd is already running */
 
        dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
 
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
new file mode 100644 (file)
index 0000000..183cc1f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Common code for control of lockd and nfsv4 grace periods.
+ */
+
+#include <linux/module.h>
+#include <linux/lockd/bind.h>
+
+static LIST_HEAD(grace_list);
+static DEFINE_SPINLOCK(grace_lock);
+
+/**
+ * locks_start_grace
+ * @lm: who this grace period is for
+ *
+ * A grace period is a period during which locks should not be given
+ * out.  Currently grace periods are only enforced by the two lock
+ * managers (lockd and nfsd), using the locks_in_grace() function to
+ * check when they are in a grace period.
+ *
+ * This function is called to start a grace period.
+ */
+void locks_start_grace(struct lock_manager *lm)
+{
+       spin_lock(&grace_lock);
+       list_add(&lm->list, &grace_list);
+       spin_unlock(&grace_lock);
+}
+EXPORT_SYMBOL_GPL(locks_start_grace);
+
+/**
+ * locks_end_grace
+ * @lm: who this grace period is for
+ *
+ * Call this function to state that the given lock manager is ready to
+ * resume regular locking.  The grace period will not end until all lock
+ * managers that called locks_start_grace() also call locks_end_grace().
+ * Note that callers count on it being safe to call this more than once,
+ * and the second call should be a no-op.
+ */
+void locks_end_grace(struct lock_manager *lm)
+{
+       spin_lock(&grace_lock);
+       list_del_init(&lm->list);
+       spin_unlock(&grace_lock);
+}
+EXPORT_SYMBOL_GPL(locks_end_grace);
+
+/**
+ * locks_in_grace
+ *
+ * Lock managers call this function to determine when it is OK for them
+ * to answer ordinary lock requests, and when they should accept only
+ * lock reclaims.
+ */
+int locks_in_grace(void)
+{
+       return !list_empty(&grace_list);
+}
+EXPORT_SYMBOL_GPL(locks_in_grace);
index a17664c7eacc4542ee8a27a6543c4b548f6efc62..9fd8889097b728b735150ff82b1ff123a503dac7 100644 (file)
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/lockd/lockd.h>
 #include <linux/lockd/sm_inter.h>
 #include <linux/mutex.h>
 
+#include <net/ipv6.h>
 
 #define NLMDBG_FACILITY                NLMDBG_HOSTCACHE
 #define NLM_HOST_NRHASH                32
-#define NLM_ADDRHASH(addr)     (ntohl(addr) & (NLM_HOST_NRHASH-1))
 #define NLM_HOST_REBIND                (60 * HZ)
 #define NLM_HOST_EXPIRE                (300 * HZ)
 #define NLM_HOST_COLLECT       (120 * HZ)
@@ -30,42 +31,115 @@ static unsigned long               next_gc;
 static int                     nrhosts;
 static DEFINE_MUTEX(nlm_host_mutex);
 
-
 static void                    nlm_gc_hosts(void);
-static struct nsm_handle *     __nsm_find(const struct sockaddr_in *,
-                                       const char *, unsigned int, int);
-static struct nsm_handle *     nsm_find(const struct sockaddr_in *sin,
-                                        const char *hostname,
-                                        unsigned int hostname_len);
+static struct nsm_handle       *nsm_find(const struct sockaddr *sap,
+                                               const size_t salen,
+                                               const char *hostname,
+                                               const size_t hostname_len,
+                                               const int create);
+
+struct nlm_lookup_host_info {
+       const int               server;         /* search for server|client */
+       const struct sockaddr   *sap;           /* address to search for */
+       const size_t            salen;          /* it's length */
+       const unsigned short    protocol;       /* transport to search for*/
+       const u32               version;        /* NLM version to search for */
+       const char              *hostname;      /* remote's hostname */
+       const size_t            hostname_len;   /* it's length */
+       const struct sockaddr   *src_sap;       /* our address (optional) */
+       const size_t            src_len;        /* it's length */
+};
+
+/*
+ * Hash function must work well on big- and little-endian platforms
+ */
+static unsigned int __nlm_hash32(const __be32 n)
+{
+       unsigned int hash = (__force u32)n ^ ((__force u32)n >> 16);
+       return hash ^ (hash >> 8);
+}
+
+static unsigned int __nlm_hash_addr4(const struct sockaddr *sap)
+{
+       const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+       return __nlm_hash32(sin->sin_addr.s_addr);
+}
+
+static unsigned int __nlm_hash_addr6(const struct sockaddr *sap)
+{
+       const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+       const struct in6_addr addr = sin6->sin6_addr;
+       return __nlm_hash32(addr.s6_addr32[0]) ^
+              __nlm_hash32(addr.s6_addr32[1]) ^
+              __nlm_hash32(addr.s6_addr32[2]) ^
+              __nlm_hash32(addr.s6_addr32[3]);
+}
+
+static unsigned int nlm_hash_address(const struct sockaddr *sap)
+{
+       unsigned int hash;
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               hash = __nlm_hash_addr4(sap);
+               break;
+       case AF_INET6:
+               hash = __nlm_hash_addr6(sap);
+               break;
+       default:
+               hash = 0;
+       }
+       return hash & (NLM_HOST_NRHASH - 1);
+}
+
+static void nlm_clear_port(struct sockaddr *sap)
+{
+       switch (sap->sa_family) {
+       case AF_INET:
+               ((struct sockaddr_in *)sap)->sin_port = 0;
+               break;
+       case AF_INET6:
+               ((struct sockaddr_in6 *)sap)->sin6_port = 0;
+               break;
+       }
+}
+
+static void nlm_display_address(const struct sockaddr *sap,
+                               char *buf, const size_t len)
+{
+       const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+       const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+
+       switch (sap->sa_family) {
+       case AF_UNSPEC:
+               snprintf(buf, len, "unspecified");
+               break;
+       case AF_INET:
+               snprintf(buf, len, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
+               break;
+       case AF_INET6:
+               if (ipv6_addr_v4mapped(&sin6->sin6_addr))
+                       snprintf(buf, len, NIPQUAD_FMT,
+                                NIPQUAD(sin6->sin6_addr.s6_addr32[3]));
+               else
+                       snprintf(buf, len, NIP6_FMT, NIP6(sin6->sin6_addr));
+               break;
+       default:
+               snprintf(buf, len, "unsupported address family");
+               break;
+       }
+}
 
 /*
  * Common host lookup routine for server & client
  */
-static struct nlm_host *nlm_lookup_host(int server,
-                                       const struct sockaddr_in *sin,
-                                       int proto, u32 version,
-                                       const char *hostname,
-                                       unsigned int hostname_len,
-                                       const struct sockaddr_in *ssin)
+static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
 {
        struct hlist_head *chain;
        struct hlist_node *pos;
        struct nlm_host *host;
        struct nsm_handle *nsm = NULL;
-       int             hash;
-
-       dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
-                       ", p=%d, v=%u, my role=%s, name=%.*s)\n",
-                       NIPQUAD(ssin->sin_addr.s_addr),
-                       NIPQUAD(sin->sin_addr.s_addr), proto, version,
-                       server? "server" : "client",
-                       hostname_len,
-                       hostname? hostname : "<none>");
 
-
-       hash = NLM_ADDRHASH(sin->sin_addr.s_addr);
-
-       /* Lock hash table */
        mutex_lock(&nlm_host_mutex);
 
        if (time_after_eq(jiffies, next_gc))
@@ -78,22 +152,22 @@ static struct nlm_host *nlm_lookup_host(int server,
         * different NLM rpc_clients into one single nlm_host object.
         * This would allow us to have one nlm_host per address.
         */
-       chain = &nlm_hosts[hash];
+       chain = &nlm_hosts[nlm_hash_address(ni->sap)];
        hlist_for_each_entry(host, pos, chain, h_hash) {
-               if (!nlm_cmp_addr(&host->h_addr, sin))
+               if (!nlm_cmp_addr(nlm_addr(host), ni->sap))
                        continue;
 
                /* See if we have an NSM handle for this client */
                if (!nsm)
                        nsm = host->h_nsmhandle;
 
-               if (host->h_proto != proto)
+               if (host->h_proto != ni->protocol)
                        continue;
-               if (host->h_version != version)
+               if (host->h_version != ni->version)
                        continue;
-               if (host->h_server != server)
+               if (host->h_server != ni->server)
                        continue;
-               if (!nlm_cmp_addr(&host->h_saddr, ssin))
+               if (!nlm_cmp_addr(nlm_srcaddr(host), ni->src_sap))
                        continue;
 
                /* Move to head of hash chain. */
@@ -101,30 +175,41 @@ static struct nlm_host *nlm_lookup_host(int server,
                hlist_add_head(&host->h_hash, chain);
 
                nlm_get_host(host);
+               dprintk("lockd: nlm_lookup_host found host %s (%s)\n",
+                               host->h_name, host->h_addrbuf);
                goto out;
        }
-       if (nsm)
-               atomic_inc(&nsm->sm_count);
-
-       host = NULL;
 
-       /* Sadly, the host isn't in our hash table yet. See if
-        * we have an NSM handle for it. If not, create one.
+       /*
+        * The host wasn't in our hash table.  If we don't
+        * have an NSM handle for it yet, create one.
         */
-       if (!nsm && !(nsm = nsm_find(sin, hostname, hostname_len)))
-               goto out;
+       if (nsm)
+               atomic_inc(&nsm->sm_count);
+       else {
+               host = NULL;
+               nsm = nsm_find(ni->sap, ni->salen,
+                               ni->hostname, ni->hostname_len, 1);
+               if (!nsm) {
+                       dprintk("lockd: nlm_lookup_host failed; "
+                               "no nsm handle\n");
+                       goto out;
+               }
+       }
 
        host = kzalloc(sizeof(*host), GFP_KERNEL);
        if (!host) {
                nsm_release(nsm);
+               dprintk("lockd: nlm_lookup_host failed; no memory\n");
                goto out;
        }
        host->h_name       = nsm->sm_name;
-       host->h_addr       = *sin;
-       host->h_addr.sin_port = 0;      /* ouch! */
-       host->h_saddr      = *ssin;
-       host->h_version    = version;
-       host->h_proto      = proto;
+       memcpy(nlm_addr(host), ni->sap, ni->salen);
+       host->h_addrlen = ni->salen;
+       nlm_clear_port(nlm_addr(host));
+       memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len);
+       host->h_version    = ni->version;
+       host->h_proto      = ni->protocol;
        host->h_rpcclnt    = NULL;
        mutex_init(&host->h_mutex);
        host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -135,7 +220,7 @@ static struct nlm_host *nlm_lookup_host(int server,
        host->h_state      = 0;                 /* pseudo NSM state */
        host->h_nsmstate   = 0;                 /* real NSM state */
        host->h_nsmhandle  = nsm;
-       host->h_server     = server;
+       host->h_server     = ni->server;
        hlist_add_head(&host->h_hash, chain);
        INIT_LIST_HEAD(&host->h_lockowners);
        spin_lock_init(&host->h_lock);
@@ -143,6 +228,15 @@ static struct nlm_host *nlm_lookup_host(int server,
        INIT_LIST_HEAD(&host->h_reclaim);
 
        nrhosts++;
+
+       nlm_display_address((struct sockaddr *)&host->h_addr,
+                               host->h_addrbuf, sizeof(host->h_addrbuf));
+       nlm_display_address((struct sockaddr *)&host->h_srcaddr,
+                               host->h_srcaddrbuf, sizeof(host->h_srcaddrbuf));
+
+       dprintk("lockd: nlm_lookup_host created host %s\n",
+                       host->h_name);
+
 out:
        mutex_unlock(&nlm_host_mutex);
        return host;
@@ -170,33 +264,103 @@ nlm_destroy_host(struct nlm_host *host)
        kfree(host);
 }
 
-/*
- * Find an NLM server handle in the cache. If there is none, create it.
+/**
+ * nlmclnt_lookup_host - Find an NLM host handle matching a remote server
+ * @sap: network address of server
+ * @salen: length of server address
+ * @protocol: transport protocol to use
+ * @version: NLM protocol version
+ * @hostname: '\0'-terminated hostname of server
+ *
+ * Returns an nlm_host structure that matches the passed-in
+ * [server address, transport protocol, NLM version, server hostname].
+ * If one doesn't already exist in the host cache, a new handle is
+ * created and returned.
  */
-struct nlm_host *nlmclnt_lookup_host(const struct sockaddr_in *sin,
-                                    int proto, u32 version,
-                                    const char *hostname,
-                                    unsigned int hostname_len)
+struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
+                                    const size_t salen,
+                                    const unsigned short protocol,
+                                    const u32 version, const char *hostname)
 {
-       struct sockaddr_in ssin = {0};
-
-       return nlm_lookup_host(0, sin, proto, version,
-                              hostname, hostname_len, &ssin);
+       const struct sockaddr source = {
+               .sa_family      = AF_UNSPEC,
+       };
+       struct nlm_lookup_host_info ni = {
+               .server         = 0,
+               .sap            = sap,
+               .salen          = salen,
+               .protocol       = protocol,
+               .version        = version,
+               .hostname       = hostname,
+               .hostname_len   = strlen(hostname),
+               .src_sap        = &source,
+               .src_len        = sizeof(source),
+       };
+
+       dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
+                       (hostname ? hostname : "<none>"), version,
+                       (protocol == IPPROTO_UDP ? "udp" : "tcp"));
+
+       return nlm_lookup_host(&ni);
 }
 
-/*
- * Find an NLM client handle in the cache. If there is none, create it.
+/**
+ * nlmsvc_lookup_host - Find an NLM host handle matching a remote client
+ * @rqstp: incoming NLM request
+ * @hostname: name of client host
+ * @hostname_len: length of client hostname
+ *
+ * Returns an nlm_host structure that matches the [client address,
+ * transport protocol, NLM version, client hostname] of the passed-in
+ * NLM request.  If one doesn't already exist in the host cache, a
+ * new handle is created and returned.
+ *
+ * Before possibly creating a new nlm_host, construct a sockaddr
+ * for a specific source address in case the local system has
+ * multiple network addresses.  The family of the address in
+ * rq_daddr is guaranteed to be the same as the family of the
+ * address in rq_addr, so it's safe to use the same family for
+ * the source address.
  */
-struct nlm_host *
-nlmsvc_lookup_host(struct svc_rqst *rqstp,
-                       const char *hostname, unsigned int hostname_len)
+struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
+                                   const char *hostname,
+                                   const size_t hostname_len)
 {
-       struct sockaddr_in ssin = {0};
+       struct sockaddr_in sin = {
+               .sin_family     = AF_INET,
+       };
+       struct sockaddr_in6 sin6 = {
+               .sin6_family    = AF_INET6,
+       };
+       struct nlm_lookup_host_info ni = {
+               .server         = 1,
+               .sap            = svc_addr(rqstp),
+               .salen          = rqstp->rq_addrlen,
+               .protocol       = rqstp->rq_prot,
+               .version        = rqstp->rq_vers,
+               .hostname       = hostname,
+               .hostname_len   = hostname_len,
+               .src_len        = rqstp->rq_addrlen,
+       };
+
+       dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
+                       (int)hostname_len, hostname, rqstp->rq_vers,
+                       (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
+
+       switch (ni.sap->sa_family) {
+       case AF_INET:
+               sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
+               ni.src_sap = (struct sockaddr *)&sin;
+               break;
+       case AF_INET6:
+               ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
+               ni.src_sap = (struct sockaddr *)&sin6;
+               break;
+       default:
+               return NULL;
+       }
 
-       ssin.sin_addr = rqstp->rq_daddr.addr;
-       return nlm_lookup_host(1, svc_addr_in(rqstp),
-                              rqstp->rq_prot, rqstp->rq_vers,
-                              hostname, hostname_len, &ssin);
+       return nlm_lookup_host(&ni);
 }
 
 /*
@@ -207,9 +371,8 @@ nlm_bind_host(struct nlm_host *host)
 {
        struct rpc_clnt *clnt;
 
-       dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
-                       NIPQUAD(host->h_saddr.sin_addr),
-                       NIPQUAD(host->h_addr.sin_addr));
+       dprintk("lockd: nlm_bind_host %s (%s), my addr=%s\n",
+                       host->h_name, host->h_addrbuf, host->h_srcaddrbuf);
 
        /* Lock host handle */
        mutex_lock(&host->h_mutex);
@@ -221,7 +384,7 @@ nlm_bind_host(struct nlm_host *host)
                if (time_after_eq(jiffies, host->h_nextrebind)) {
                        rpc_force_rebind(clnt);
                        host->h_nextrebind = jiffies + NLM_HOST_REBIND;
-                       dprintk("lockd: next rebind in %ld jiffies\n",
+                       dprintk("lockd: next rebind in %lu jiffies\n",
                                        host->h_nextrebind - jiffies);
                }
        } else {
@@ -234,9 +397,9 @@ nlm_bind_host(struct nlm_host *host)
                };
                struct rpc_create_args args = {
                        .protocol       = host->h_proto,
-                       .address        = (struct sockaddr *)&host->h_addr,
-                       .addrsize       = sizeof(host->h_addr),
-                       .saddress       = (struct sockaddr *)&host->h_saddr,
+                       .address        = nlm_addr(host),
+                       .addrsize       = host->h_addrlen,
+                       .saddress       = nlm_srcaddr(host),
                        .timeout        = &timeparms,
                        .servername     = host->h_name,
                        .program        = &nlm_program,
@@ -324,12 +487,16 @@ void nlm_host_rebooted(const struct sockaddr_in *sin,
        struct nsm_handle *nsm;
        struct nlm_host *host;
 
-       dprintk("lockd: nlm_host_rebooted(%s, %u.%u.%u.%u)\n",
-                       hostname, NIPQUAD(sin->sin_addr));
-
-       /* Find the NSM handle for this peer */
-       if (!(nsm = __nsm_find(sin, hostname, hostname_len, 0)))
+       nsm = nsm_find((struct sockaddr *)sin, sizeof(*sin),
+                       hostname, hostname_len, 0);
+       if (nsm == NULL) {
+               dprintk("lockd: never saw rebooted peer '%.*s' before\n",
+                               hostname_len, hostname);
                return;
+       }
+
+       dprintk("lockd: nlm_host_rebooted(%.*s, %s)\n",
+                       hostname_len, hostname, nsm->sm_addrbuf);
 
        /* When reclaiming locks on this peer, make sure that
         * we set up a new notification */
@@ -461,22 +628,23 @@ nlm_gc_hosts(void)
 static LIST_HEAD(nsm_handles);
 static DEFINE_SPINLOCK(nsm_lock);
 
-static struct nsm_handle *
-__nsm_find(const struct sockaddr_in *sin,
-               const char *hostname, unsigned int hostname_len,
-               int create)
+static struct nsm_handle *nsm_find(const struct sockaddr *sap,
+                                  const size_t salen,
+                                  const char *hostname,
+                                  const size_t hostname_len,
+                                  const int create)
 {
        struct nsm_handle *nsm = NULL;
        struct nsm_handle *pos;
 
-       if (!sin)
+       if (!sap)
                return NULL;
 
        if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
                if (printk_ratelimit()) {
                        printk(KERN_WARNING "Invalid hostname \"%.*s\" "
                                            "in NFS lock request\n",
-                               hostname_len, hostname);
+                               (int)hostname_len, hostname);
                }
                return NULL;
        }
@@ -489,7 +657,7 @@ retry:
                        if (strlen(pos->sm_name) != hostname_len
                         || memcmp(pos->sm_name, hostname, hostname_len))
                                continue;
-               } else if (!nlm_cmp_addr(&pos->sm_addr, sin))
+               } else if (!nlm_cmp_addr(nsm_addr(pos), sap))
                        continue;
                atomic_inc(&pos->sm_count);
                kfree(nsm);
@@ -509,10 +677,13 @@ retry:
        if (nsm == NULL)
                return NULL;
 
-       nsm->sm_addr = *sin;
+       memcpy(nsm_addr(nsm), sap, salen);
+       nsm->sm_addrlen = salen;
        nsm->sm_name = (char *) (nsm + 1);
        memcpy(nsm->sm_name, hostname, hostname_len);
        nsm->sm_name[hostname_len] = '\0';
+       nlm_display_address((struct sockaddr *)&nsm->sm_addr,
+                               nsm->sm_addrbuf, sizeof(nsm->sm_addrbuf));
        atomic_set(&nsm->sm_count, 1);
        goto retry;
 
@@ -521,13 +692,6 @@ found:
        return nsm;
 }
 
-static struct nsm_handle *
-nsm_find(const struct sockaddr_in *sin, const char *hostname,
-        unsigned int hostname_len)
-{
-       return __nsm_find(sin, hostname, hostname_len, 1);
-}
-
 /*
  * Release an NSM handle
  */
index e4d563543b11066a1acd17a5beb7d0a8916aa520..4e7e958e8f6753236832ed9ebd82f6bae0746899 100644 (file)
@@ -51,7 +51,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
 
        memset(&args, 0, sizeof(args));
        args.mon_name = nsm->sm_name;
-       args.addr = nsm->sm_addr.sin_addr.s_addr;
+       args.addr = nsm_addr_in(nsm)->sin_addr.s_addr;
        args.prog = NLM_PROGRAM;
        args.vers = 3;
        args.proc = NLMPROC_NSM_NOTIFY;
index 5bd9bf0fa9df09121f8c190d7e47ec8ef7871ede..c631a83931cec9cd56128daf5fc494b8fac9703a 100644 (file)
@@ -51,7 +51,6 @@ static DEFINE_MUTEX(nlmsvc_mutex);
 static unsigned int            nlmsvc_users;
 static struct task_struct      *nlmsvc_task;
 static struct svc_rqst         *nlmsvc_rqst;
-int                            nlmsvc_grace_period;
 unsigned long                  nlmsvc_timeout;
 
 /*
@@ -85,27 +84,23 @@ static unsigned long get_lockd_grace_period(void)
                return nlm_timeout * 5 * HZ;
 }
 
-unsigned long get_nfs_grace_period(void)
-{
-       unsigned long lockdgrace = get_lockd_grace_period();
-       unsigned long nfsdgrace = 0;
-
-       if (nlmsvc_ops)
-               nfsdgrace = nlmsvc_ops->get_grace_period();
-
-       return max(lockdgrace, nfsdgrace);
-}
-EXPORT_SYMBOL(get_nfs_grace_period);
+static struct lock_manager lockd_manager = {
+};
 
-static unsigned long set_grace_period(void)
+static void grace_ender(struct work_struct *not_used)
 {
-       nlmsvc_grace_period = 1;
-       return get_nfs_grace_period() + jiffies;
+       locks_end_grace(&lockd_manager);
 }
 
-static inline void clear_grace_period(void)
+static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
+
+static void set_grace_period(void)
 {
-       nlmsvc_grace_period = 0;
+       unsigned long grace_period = get_lockd_grace_period();
+
+       locks_start_grace(&lockd_manager);
+       cancel_delayed_work_sync(&grace_period_end);
+       schedule_delayed_work(&grace_period_end, grace_period);
 }
 
 /*
@@ -116,7 +111,6 @@ lockd(void *vrqstp)
 {
        int             err = 0, preverr = 0;
        struct svc_rqst *rqstp = vrqstp;
-       unsigned long grace_period_expire;
 
        /* try_to_freeze() is called from svc_recv() */
        set_freezable();
@@ -139,7 +133,7 @@ lockd(void *vrqstp)
                nlm_timeout = LOCKD_DFLT_TIMEO;
        nlmsvc_timeout = nlm_timeout * HZ;
 
-       grace_period_expire = set_grace_period();
+       set_grace_period();
 
        /*
         * The main request loop. We don't terminate until the last
@@ -153,21 +147,12 @@ lockd(void *vrqstp)
                        flush_signals(current);
                        if (nlmsvc_ops) {
                                nlmsvc_invalidate_all();
-                               grace_period_expire = set_grace_period();
+                               set_grace_period();
                        }
                        continue;
                }
 
-               /*
-                * Retry any blocked locks that have been notified by
-                * the VFS. Don't do this during grace period.
-                * (Theoretically, there shouldn't even be blocked locks
-                * during grace period).
-                */
-               if (!nlmsvc_grace_period) {
-                       timeout = nlmsvc_retry_blocked();
-               } else if (time_before(grace_period_expire, jiffies))
-                       clear_grace_period();
+               timeout = nlmsvc_retry_blocked();
 
                /*
                 * Find a socket with data available and call its
@@ -195,6 +180,7 @@ lockd(void *vrqstp)
                svc_process(rqstp);
        }
        flush_signals(current);
+       cancel_delayed_work_sync(&grace_period_end);
        if (nlmsvc_ops)
                nlmsvc_invalidate_all();
        nlm_shutdown_hosts();
@@ -203,25 +189,28 @@ lockd(void *vrqstp)
 }
 
 /*
- * Make any sockets that are needed but not present.
- * If nlm_udpport or nlm_tcpport were set as module
- * options, make those sockets unconditionally
+ * Ensure there are active UDP and TCP listeners for lockd.
+ *
+ * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
+ * local services (such as rpc.statd) still require UDP, and
+ * some NFS servers do not yet support NLM over TCP.
+ *
+ * Returns zero if all listeners are available; otherwise a
+ * negative errno value is returned.
  */
-static int make_socks(struct svc_serv *serv, int proto)
+static int make_socks(struct svc_serv *serv)
 {
        static int warned;
        struct svc_xprt *xprt;
        int err = 0;
 
-       if (proto == IPPROTO_UDP || nlm_udpport) {
-               xprt = svc_find_xprt(serv, "udp", 0, 0);
-               if (!xprt)
-                       err = svc_create_xprt(serv, "udp", nlm_udpport,
-                                             SVC_SOCK_DEFAULTS);
-               else
-                       svc_xprt_put(xprt);
-       }
-       if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) {
+       xprt = svc_find_xprt(serv, "udp", 0, 0);
+       if (!xprt)
+               err = svc_create_xprt(serv, "udp", nlm_udpport,
+                                     SVC_SOCK_DEFAULTS);
+       else
+               svc_xprt_put(xprt);
+       if (err >= 0) {
                xprt = svc_find_xprt(serv, "tcp", 0, 0);
                if (!xprt)
                        err = svc_create_xprt(serv, "tcp", nlm_tcpport,
@@ -241,8 +230,7 @@ static int make_socks(struct svc_serv *serv, int proto)
 /*
  * Bring up the lockd process if it's not already up.
  */
-int
-lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
+int lockd_up(void)
 {
        struct svc_serv *serv;
        int             error = 0;
@@ -251,11 +239,8 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
        /*
         * Check whether we're already up and running.
         */
-       if (nlmsvc_rqst) {
-               if (proto)
-                       error = make_socks(nlmsvc_rqst->rq_server, proto);
+       if (nlmsvc_rqst)
                goto out;
-       }
 
        /*
         * Sanity check: if there's no pid,
@@ -266,13 +251,14 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
                        "lockd_up: no pid, %d users??\n", nlmsvc_users);
 
        error = -ENOMEM;
-       serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
+       serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, AF_INET, NULL);
        if (!serv) {
                printk(KERN_WARNING "lockd_up: create service failed\n");
                goto out;
        }
 
-       if ((error = make_socks(serv, proto)) < 0)
+       error = make_socks(serv);
+       if (error < 0)
                goto destroy_and_out;
 
        /*
index 4a714f64515b06557704b38cf02f8ba7f36f7ea0..014f6ce48172fa73cc5d534bda12096776b39e20 100644 (file)
@@ -88,12 +88,6 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
        dprintk("lockd: TEST4        called\n");
        resp->cookie = argp->cookie;
 
-       /* Don't accept test requests during grace period */
-       if (nlmsvc_grace_period) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rc;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -122,12 +116,6 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        resp->cookie = argp->cookie;
 
-       /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rc;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -146,7 +134,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        /* Now try to lock the file */
        resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
-                                       argp->block, &argp->cookie);
+                                       argp->block, &argp->cookie,
+                                       argp->reclaim);
        if (resp->status == nlm_drop_reply)
                rc = rpc_drop_reply;
        else
@@ -169,7 +158,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -202,7 +191,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -231,7 +220,7 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        dprintk("lockd: GRANTED       called\n");
-       resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
+       resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
        return rpc_success;
 }
@@ -341,7 +330,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
+       if (locks_in_grace() && !argp->reclaim) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -374,7 +363,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -432,11 +421,9 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 {
        struct sockaddr_in      saddr;
 
-       memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
-
        dprintk("lockd: SM_NOTIFY     called\n");
-       if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-        || ntohs(saddr.sin_port) >= 1024) {
+
+       if (!nlm_privileged_requester(rqstp)) {
                char buf[RPC_MAX_ADDRBUFLEN];
                printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
                                svc_print_addr(rqstp, buf, sizeof(buf)));
index cf0d5c2c318d6002330f1bca7965b09e8a047e9d..6063a8e4b9f3223104843bce393882181b890539 100644 (file)
@@ -360,7 +360,7 @@ nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
 __be32
 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
            struct nlm_host *host, struct nlm_lock *lock, int wait,
-           struct nlm_cookie *cookie)
+           struct nlm_cookie *cookie, int reclaim)
 {
        struct nlm_block        *block = NULL;
        int                     error;
@@ -406,6 +406,15 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
                goto out;
        }
 
+       if (locks_in_grace() && !reclaim) {
+               ret = nlm_lck_denied_grace_period;
+               goto out;
+       }
+       if (reclaim && !locks_in_grace()) {
+               ret = nlm_lck_denied_grace_period;
+               goto out;
+       }
+
        if (!wait)
                lock->fl.fl_flags &= ~FL_SLEEP;
        error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
@@ -502,6 +511,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
                goto out;
        }
 
+       if (locks_in_grace()) {
+               ret = nlm_lck_denied_grace_period;
+               goto out;
+       }
        error = vfs_test_lock(file->f_file, &lock->fl);
        if (error == FILE_LOCK_DEFERRED) {
                ret = nlmsvc_defer_lock_rqst(rqstp, block);
@@ -582,6 +595,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
 
+       if (locks_in_grace())
+               return nlm_lck_denied_grace_period;
+
        mutex_lock(&file->f_mutex);
        block = nlmsvc_lookup_block(file, lock);
        mutex_unlock(&file->f_mutex);
index 76262c1986f2d36d1f6765da9acf506736b3b30b..548b0bb2b84d1e7dccb6351bdff03980d276959e 100644 (file)
@@ -117,12 +117,6 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
        dprintk("lockd: TEST          called\n");
        resp->cookie = argp->cookie;
 
-       /* Don't accept test requests during grace period */
-       if (nlmsvc_grace_period) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rc;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -152,12 +146,6 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        resp->cookie = argp->cookie;
 
-       /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
-               resp->status = nlm_lck_denied_grace_period;
-               return rc;
-       }
-
        /* Obtain client and file */
        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
@@ -176,7 +164,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        /* Now try to lock the file */
        resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
-                                              argp->block, &argp->cookie));
+                                              argp->block, &argp->cookie,
+                                              argp->reclaim));
        if (resp->status == nlm_drop_reply)
                rc = rpc_drop_reply;
        else
@@ -199,7 +188,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -232,7 +221,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -261,7 +250,7 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        dprintk("lockd: GRANTED       called\n");
-       resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
+       resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
        return rpc_success;
 }
@@ -373,7 +362,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept new lock requests during grace period */
-       if (nlmsvc_grace_period && !argp->reclaim) {
+       if (locks_in_grace() && !argp->reclaim) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -406,7 +395,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
        resp->cookie = argp->cookie;
 
        /* Don't accept requests during grace period */
-       if (nlmsvc_grace_period) {
+       if (locks_in_grace()) {
                resp->status = nlm_lck_denied_grace_period;
                return rpc_success;
        }
@@ -464,11 +453,9 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 {
        struct sockaddr_in      saddr;
 
-       memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
-
        dprintk("lockd: SM_NOTIFY     called\n");
-       if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-        || ntohs(saddr.sin_port) >= 1024) {
+
+       if (!nlm_privileged_requester(rqstp)) {
                char buf[RPC_MAX_ADDRBUFLEN];
                printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
                                svc_print_addr(rqstp, buf, sizeof(buf)));
index 198b4e55b3732523fbe569cfd927948c3ee70cb0..34c2766e27c7273138af21bdc8b65e9447c71d72 100644 (file)
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
 static int
 nlmsvc_match_ip(void *datap, struct nlm_host *host)
 {
-       return nlm_cmp_addr(&host->h_saddr, datap);
+       return nlm_cmp_addr(nlm_srcaddr(host), datap);
 }
 
 /**
index 3e459e18cc31ba2efeaca67dc9b40ae506604247..1f226290c67cf88a2707f08447d2e92f9a98bfbc 100644 (file)
@@ -351,8 +351,6 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
        argp->state = ntohl(*p++);
        /* Preserve the address in network byte order */
        argp->addr = *p++;
-       argp->vers = *p++;
-       argp->proto = *p++;
        return xdr_argsize_check(rqstp, p);
 }
 
index 43ff9397e6c67fee3504dda5e5c3579c04212cf2..50c493a8ad8e5e1f4fcd10eaa7d2311a35c5285b 100644 (file)
@@ -358,8 +358,6 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp
        argp->state = ntohl(*p++);
        /* Preserve the address in network byte order */
        argp->addr  = *p++;
-       argp->vers  = *p++;
-       argp->proto = *p++;
        return xdr_argsize_check(rqstp, p);
 }
 
index dbcc7af76a15d483a5efc5c1a68aa11566072623..552b80b3facc01414967771ec6d59d9029276cdb 100644 (file)
@@ -6,7 +6,7 @@
  * Contains functions related to preparing and submitting BIOs which contain
  * multiple pagecache pages.
  *
- * 15May2002   akpm@zip.com.au
+ * 15May2002   Andrew Morton
  *             Initial version
  * 27Jun2002   axboe@suse.de
  *             use bio_add_page() to build bio's just the right size
index f447f4b4476cc37b26144ffdfcef83cd80eab53e..6a09760c5960fd427935c2306f5080caa66bce3b 100644 (file)
@@ -105,7 +105,8 @@ int nfs_callback_up(void)
        mutex_lock(&nfs_callback_mutex);
        if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
                goto out;
-       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
+       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
+                               AF_INET, NULL);
        ret = -ENOMEM;
        if (!serv)
                goto out_err;
index 5ee23e7058b305c061a4e1449fdccc722a68eceb..7547600b61741e26eb1bcaa52b4cfbad9349d673 100644 (file)
@@ -675,7 +675,7 @@ static int nfs_init_server(struct nfs_server *server,
        server->nfs_client = clp;
 
        /* Initialise the client representation from the mount data */
-       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+       server->flags = data->flags;
 
        if (data->rsize)
                server->rsize = nfs_block_size(data->rsize, NULL);
@@ -850,7 +850,6 @@ static struct nfs_server *nfs_alloc_server(void)
        INIT_LIST_HEAD(&server->client_link);
        INIT_LIST_HEAD(&server->master_link);
 
-       init_waitqueue_head(&server->active_wq);
        atomic_set(&server->active, 0);
 
        server->io_stats = nfs_alloc_iostats();
@@ -1073,7 +1072,7 @@ static int nfs4_init_server(struct nfs_server *server,
                goto error;
 
        /* Initialise the client representation from the mount data */
-       server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+       server->flags = data->flags;
        server->caps |= NFS_CAP_ATOMIC_OPEN;
 
        if (data->rsize)
index 74f92b717f783ca1974094beabb879ea1adde0cc..2ab70d46ecbc7ac43a0585183adcfe248ac5b127 100644 (file)
@@ -156,6 +156,7 @@ typedef struct {
        decode_dirent_t decode;
        int             plus;
        unsigned long   timestamp;
+       unsigned long   gencount;
        int             timestamp_valid;
 } nfs_readdir_descriptor_t;
 
@@ -177,7 +178,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
        struct file     *file = desc->file;
        struct inode    *inode = file->f_path.dentry->d_inode;
        struct rpc_cred *cred = nfs_file_cred(file);
-       unsigned long   timestamp;
+       unsigned long   timestamp, gencount;
        int             error;
 
        dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
@@ -186,6 +187,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 
  again:
        timestamp = jiffies;
+       gencount = nfs_inc_attr_generation_counter();
        error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
                                          NFS_SERVER(inode)->dtsize, desc->plus);
        if (error < 0) {
@@ -199,6 +201,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
                goto error;
        }
        desc->timestamp = timestamp;
+       desc->gencount = gencount;
        desc->timestamp_valid = 1;
        SetPageUptodate(page);
        /* Ensure consistent page alignment of the data.
@@ -224,9 +227,10 @@ int dir_decode(nfs_readdir_descriptor_t *desc)
        if (IS_ERR(p))
                return PTR_ERR(p);
        desc->ptr = p;
-       if (desc->timestamp_valid)
+       if (desc->timestamp_valid) {
                desc->entry->fattr->time_start = desc->timestamp;
-       else
+               desc->entry->fattr->gencount = desc->gencount;
+       } else
                desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
        return 0;
 }
@@ -471,7 +475,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        int             status;
-       unsigned long   timestamp;
+       unsigned long   timestamp, gencount;
 
        dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
                        (unsigned long long)*desc->dir_cookie);
@@ -482,6 +486,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                goto out;
        }
        timestamp = jiffies;
+       gencount = nfs_inc_attr_generation_counter();
        status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
                                                *desc->dir_cookie, page,
                                                NFS_SERVER(inode)->dtsize,
@@ -490,6 +495,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
        if (status >= 0) {
                desc->timestamp = timestamp;
+               desc->gencount = gencount;
                desc->timestamp_valid = 1;
                if ((status = dir_decode(desc)) == 0)
                        desc->entry->prev_cookie = *desc->dir_cookie;
@@ -655,7 +661,7 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
  */
 void nfs_force_lookup_revalidate(struct inode *dir)
 {
-       NFS_I(dir)->cache_change_attribute = jiffies;
+       NFS_I(dir)->cache_change_attribute++;
 }
 
 /*
@@ -667,6 +673,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
 {
        if (IS_ROOT(dentry))
                return 1;
+       if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
+               return 0;
        if (!nfs_verify_change_attribute(dir, dentry->d_time))
                return 0;
        /* Revalidate nfsi->cache_change_attribute before we declare a match */
@@ -750,6 +758,8 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
        /* Don't revalidate a negative dentry if we're creating a new file */
        if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
                return 0;
+       if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
+               return 1;
        return !nfs_check_verifier(dir, dentry);
 }
 
index 78460657f5cbff1a155a4e5d05ab1ba3ea0e564d..d319b49f8f06f4046c408afe8a290a9e05b7920e 100644 (file)
@@ -188,13 +188,16 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
        /* origin == SEEK_END => we must revalidate the cached file length */
        if (origin == SEEK_END) {
                struct inode *inode = filp->f_mapping->host;
+
                int retval = nfs_revalidate_file_size(inode, filp);
                if (retval < 0)
                        return (loff_t)retval;
-       }
-       lock_kernel();  /* BKL needed? */
-       loff = generic_file_llseek_unlocked(filp, offset, origin);
-       unlock_kernel();
+
+               spin_lock(&inode->i_lock);
+               loff = generic_file_llseek_unlocked(filp, offset, origin);
+               spin_unlock(&inode->i_lock);
+       } else
+               loff = generic_file_llseek_unlocked(filp, offset, origin);
        return loff;
 }
 
@@ -699,13 +702,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
                        filp->f_path.dentry->d_name.name,
                        fl->fl_type, fl->fl_flags);
 
-       /*
-        * No BSD flocks over NFS allowed.
-        * Note: we could try to fake a POSIX lock request here by
-        * using ((u32) filp | 0x80000000) or some such as the pid.
-        * Not sure whether that would be unique, though, or whether
-        * that would break in other places.
-        */
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
 
index 52daefa2f5210ef44a34a6ba0779e791453ba81d..b9195c02a8637c6bf14bc852ae8e8a924605a383 100644 (file)
@@ -305,8 +305,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                        init_special_inode(inode, inode->i_mode, fattr->rdev);
 
                nfsi->read_cache_jiffies = fattr->time_start;
-               nfsi->last_updated = now;
-               nfsi->cache_change_attribute = now;
+               nfsi->attr_gencount = fattr->gencount;
                inode->i_atime = fattr->atime;
                inode->i_mtime = fattr->mtime;
                inode->i_ctime = fattr->ctime;
@@ -453,6 +452,7 @@ out_big:
 void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
 {
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
+               spin_lock(&inode->i_lock);
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
                        mode |= inode->i_mode & ~S_IALLUGO;
@@ -462,7 +462,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
                        inode->i_uid = attr->ia_uid;
                if ((attr->ia_valid & ATTR_GID) != 0)
                        inode->i_gid = attr->ia_gid;
-               spin_lock(&inode->i_lock);
                NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
                spin_unlock(&inode->i_lock);
        }
@@ -472,37 +471,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
        }
 }
 
-static int nfs_wait_schedule(void *word)
-{
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-       schedule();
-       return 0;
-}
-
-/*
- * Wait for the inode to get unlocked.
- */
-static int nfs_wait_on_inode(struct inode *inode)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-       int error;
-
-       error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING,
-                                       nfs_wait_schedule, TASK_KILLABLE);
-
-       return error;
-}
-
-static void nfs_wake_up_inode(struct inode *inode)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-
-       clear_bit(NFS_INO_REVALIDATING, &nfsi->flags);
-       smp_mb__after_clear_bit();
-       wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);
-}
-
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
        struct inode *inode = dentry->d_inode;
@@ -697,20 +665,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
        dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
                inode->i_sb->s_id, (long long)NFS_FILEID(inode));
 
-       nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
        if (is_bad_inode(inode))
-               goto out_nowait;
+               goto out;
        if (NFS_STALE(inode))
-               goto out_nowait;
-
-       status = nfs_wait_on_inode(inode);
-       if (status < 0)
                goto out;
 
-       status = -ESTALE;
        if (NFS_STALE(inode))
                goto out;
 
+       nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
        status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
        if (status != 0) {
                dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
@@ -724,16 +687,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                goto out;
        }
 
-       spin_lock(&inode->i_lock);
-       status = nfs_update_inode(inode, &fattr);
+       status = nfs_refresh_inode(inode, &fattr);
        if (status) {
-               spin_unlock(&inode->i_lock);
                dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
                         inode->i_sb->s_id,
                         (long long)NFS_FILEID(inode), status);
                goto out;
        }
-       spin_unlock(&inode->i_lock);
 
        if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
                nfs_zap_acl_cache(inode);
@@ -743,9 +703,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                (long long)NFS_FILEID(inode));
 
  out:
-       nfs_wake_up_inode(inode);
-
- out_nowait:
        return status;
 }
 
@@ -908,9 +865,6 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
                return -EIO;
        }
 
-       /* Do atomic weak cache consistency updates */
-       nfs_wcc_update_inode(inode, fattr);
-
        if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
                        nfsi->change_attr != fattr->change_attr)
                invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
@@ -939,15 +893,81 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
 
        if (invalid != 0)
                nfsi->cache_validity |= invalid;
-       else
-               nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR
-                               | NFS_INO_INVALID_ATIME
-                               | NFS_INO_REVAL_PAGECACHE);
 
        nfsi->read_cache_jiffies = fattr->time_start;
        return 0;
 }
 
+static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
+{
+       return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0;
+}
+
+static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
+{
+       return nfs_size_to_loff_t(fattr->size) > i_size_read(inode);
+}
+
+static unsigned long nfs_attr_generation_counter;
+
+static unsigned long nfs_read_attr_generation_counter(void)
+{
+       smp_rmb();
+       return nfs_attr_generation_counter;
+}
+
+unsigned long nfs_inc_attr_generation_counter(void)
+{
+       unsigned long ret;
+       smp_rmb();
+       ret = ++nfs_attr_generation_counter;
+       smp_wmb();
+       return ret;
+}
+
+void nfs_fattr_init(struct nfs_fattr *fattr)
+{
+       fattr->valid = 0;
+       fattr->time_start = jiffies;
+       fattr->gencount = nfs_inc_attr_generation_counter();
+}
+
+/**
+ * nfs_inode_attrs_need_update - check if the inode attributes need updating
+ * @inode - pointer to inode
+ * @fattr - attributes
+ *
+ * Attempt to divine whether or not an RPC call reply carrying stale
+ * attributes got scheduled after another call carrying updated ones.
+ *
+ * To do so, the function first assumes that a more recent ctime means
+ * that the attributes in fattr are newer, however it also attempt to
+ * catch the case where ctime either didn't change, or went backwards
+ * (if someone reset the clock on the server) by looking at whether
+ * or not this RPC call was started after the inode was last updated.
+ * Note also the check for wraparound of 'attr_gencount'
+ *
+ * The function returns 'true' if it thinks the attributes in 'fattr' are
+ * more recent than the ones cached in the inode.
+ *
+ */
+static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
+{
+       const struct nfs_inode *nfsi = NFS_I(inode);
+
+       return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 ||
+               nfs_ctime_need_update(inode, fattr) ||
+               nfs_size_need_update(inode, fattr) ||
+               ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
+}
+
+static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+{
+       if (nfs_inode_attrs_need_update(inode, fattr))
+               return nfs_update_inode(inode, fattr);
+       return nfs_check_inode_attributes(inode, fattr);
+}
+
 /**
  * nfs_refresh_inode - try to update the inode attribute cache
  * @inode - pointer to inode
@@ -960,21 +980,28 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
  */
 int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
        int status;
 
        if ((fattr->valid & NFS_ATTR_FATTR) == 0)
                return 0;
        spin_lock(&inode->i_lock);
-       if (time_after(fattr->time_start, nfsi->last_updated))
-               status = nfs_update_inode(inode, fattr);
-       else
-               status = nfs_check_inode_attributes(inode, fattr);
-
+       status = nfs_refresh_inode_locked(inode, fattr);
        spin_unlock(&inode->i_lock);
        return status;
 }
 
+static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+
+       nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
+       if (S_ISDIR(inode->i_mode))
+               nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+       if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+               return 0;
+       return nfs_refresh_inode_locked(inode, fattr);
+}
+
 /**
  * nfs_post_op_update_inode - try to update the inode attribute cache
  * @inode - pointer to inode
@@ -991,14 +1018,12 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
  */
 int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
-       struct nfs_inode *nfsi = NFS_I(inode);
+       int status;
 
        spin_lock(&inode->i_lock);
-       nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
-       if (S_ISDIR(inode->i_mode))
-               nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+       status = nfs_post_op_update_inode_locked(inode, fattr);
        spin_unlock(&inode->i_lock);
-       return nfs_refresh_inode(inode, fattr);
+       return status;
 }
 
 /**
@@ -1014,6 +1039,15 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
  */
 int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr)
 {
+       int status;
+
+       spin_lock(&inode->i_lock);
+       /* Don't do a WCC update if these attributes are already stale */
+       if ((fattr->valid & NFS_ATTR_FATTR) == 0 ||
+                       !nfs_inode_attrs_need_update(inode, fattr)) {
+               fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC);
+               goto out_noforce;
+       }
        if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
                        (fattr->valid & NFS_ATTR_WCC_V4) == 0) {
                fattr->pre_change_attr = NFS_I(inode)->change_attr;
@@ -1026,7 +1060,10 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
                fattr->pre_size = i_size_read(inode);
                fattr->valid |= NFS_ATTR_WCC;
        }
-       return nfs_post_op_update_inode(inode, fattr);
+out_noforce:
+       status = nfs_post_op_update_inode_locked(inode, fattr);
+       spin_unlock(&inode->i_lock);
+       return status;
 }
 
 /*
@@ -1092,7 +1129,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                }
                /* If ctime has changed we should definitely clear access+acl caches */
                if (!timespec_equal(&inode->i_ctime, &fattr->ctime))
-                       invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        } else if (nfsi->change_attr != fattr->change_attr) {
                dprintk("NFS: change_attr change on server for file %s/%ld\n",
                                inode->i_sb->s_id, inode->i_ino);
@@ -1126,6 +1163,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
            inode->i_gid != fattr->gid)
                invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 
+       if (inode->i_nlink != fattr->nlink)
+               invalid |= NFS_INO_INVALID_ATTR;
+
        inode->i_mode = fattr->mode;
        inode->i_nlink = fattr->nlink;
        inode->i_uid = fattr->uid;
@@ -1145,18 +1185,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
                nfsi->attrtimeo_timestamp = now;
-               nfsi->last_updated = now;
+               nfsi->attr_gencount = nfs_inc_attr_generation_counter();
        } else {
                if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
                        if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
                                nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
                        nfsi->attrtimeo_timestamp = now;
                }
-               /*
-                * Avoid jiffy wraparound issues with nfsi->last_updated
-                */
-               if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now))
-                       nfsi->last_updated = nfsi->read_cache_jiffies;
        }
        invalid &= ~NFS_INO_INVALID_ATTR;
        /* Don't invalidate the data if we were to blame */
index 24241fcbb98d7647fb6b07fcda9a9e0aee10139a..d212ee41caf21ce069f92784b229a7214859c58a 100644 (file)
@@ -153,6 +153,7 @@ extern void nfs4_clear_inode(struct inode *);
 void nfs_zap_acl_cache(struct inode *inode);
 
 /* super.c */
+void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *);
 extern struct file_system_type nfs_xdev_fs_type;
 #ifdef CONFIG_NFS_V4
 extern struct file_system_type nfs4_xdev_fs_type;
@@ -163,8 +164,8 @@ extern struct rpc_stat nfs_rpcstat;
 
 extern int __init register_nfs_fs(void);
 extern void __exit unregister_nfs_fs(void);
-extern void nfs_sb_active(struct nfs_server *server);
-extern void nfs_sb_deactive(struct nfs_server *server);
+extern void nfs_sb_active(struct super_block *sb);
+extern void nfs_sb_deactive(struct super_block *sb);
 
 /* namespace.c */
 extern char *nfs_path(const char *base,
@@ -276,3 +277,23 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
                PAGE_SIZE - 1) >> PAGE_SHIFT;
 }
 
+#define IPV6_SCOPE_DELIMITER   '%'
+
+/*
+ * Set the port number in an address.  Be agnostic about the address
+ * family.
+ */
+static inline void nfs_set_port(struct sockaddr *sap, unsigned short port)
+{
+       struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+       struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap;
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               ap->sin_port = htons(port);
+               break;
+       case AF_INET6:
+               ap6->sin6_port = htons(port);
+               break;
+       }
+}
index 779d2eb649c57935f8929f02271e48ca03759151..086a6830d785c10269a3d0251130f14caad9d477 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/nfs_fs.h>
+#include "internal.h"
 
 #ifdef RPC_DEBUG
 # define NFSDBG_FACILITY       NFSDBG_MOUNT
@@ -98,7 +99,7 @@ out_call_err:
 
 out_mnt_err:
        dprintk("NFS: MNT server returned result %d\n", result.status);
-       status = -EACCES;
+       status = nfs_stat_to_errno(result.status);
        goto out;
 }
 
index 66df08dd1cafbb41cdbb7864128b0920e0c8dbd3..64a288ee046d027692f1dc395792609cfe1760aa 100644 (file)
@@ -105,7 +105,10 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
 
        dprintk("--> nfs_follow_mountpoint()\n");
 
-       BUG_ON(IS_ROOT(dentry));
+       err = -ESTALE;
+       if (IS_ROOT(dentry))
+               goto out_err;
+
        dprintk("%s: enter\n", __func__);
        dput(nd->path.dentry);
        nd->path.dentry = dget(dentry);
@@ -189,7 +192,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
                                           struct nfs_clone_mount *mountdata)
 {
 #ifdef CONFIG_NFS_V4
-       struct vfsmount *mnt = NULL;
+       struct vfsmount *mnt = ERR_PTR(-EINVAL);
        switch (server->nfs_client->rpc_ops->version) {
                case 2:
                case 3:
index 423842f51ac91b6c447ce708dd31a2ab6cc513f1..cef62557c87daeadab3f33fa7bd468b979ae59f6 100644 (file)
@@ -229,6 +229,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
 
        dprintk("NFS call getacl\n");
        msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL];
+       nfs_fattr_init(&fattr);
        status = rpc_call_sync(server->client_acl, &msg, 0);
        dprintk("NFS reply getacl: %d\n", status);
 
@@ -322,6 +323,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 
        dprintk("NFS call setacl\n");
        msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL];
+       nfs_fattr_init(&fattr);
        status = rpc_call_sync(server->client_acl, &msg, 0);
        nfs_access_zap_cache(inode);
        nfs_zap_acl_cache(inode);
index 1e750e4574a911e982606265edb63033be870de4..c55be7a7679e27f6c011766add0b2bf8e9cfc447 100644 (file)
@@ -699,7 +699,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 }
 
 static int
-nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle,
                 struct nfs_fsinfo *info)
 {
        struct rpc_message msg = {
@@ -711,11 +711,27 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 
        dprintk("NFS call  fsinfo\n");
        nfs_fattr_init(info->fattr);
-       status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(client, &msg, 0);
        dprintk("NFS reply fsinfo: %d\n", status);
        return status;
 }
 
+/*
+ * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via
+ * nfs_create_server
+ */
+static int
+nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+                  struct nfs_fsinfo *info)
+{
+       int     status;
+
+       status = do_proc_fsinfo(server->client, fhandle, info);
+       if (status && server->nfs_client->cl_rpcclient != server->client)
+               status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info);
+       return status;
+}
+
 static int
 nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
                   struct nfs_pathconf *info)
index b112857301f724665153259aed547503737554ce..30befc39b3c6bd5fd1f93622f2bded67d66d177a 100644 (file)
@@ -93,21 +93,52 @@ static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
        return 0;
 }
 
-/*
- * Check if the string represents a "valid" IPv4 address
- */
-static inline int valid_ipaddr4(const char *buf)
+static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
+                                    char *page, char *page2,
+                                    const struct nfs4_fs_location *location)
 {
-       int rc, count, in[4];
-
-       rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
-       if (rc != 4)
-               return -EINVAL;
-       for (count = 0; count < 4; count++) {
-               if (in[count] > 255)
-                       return -EINVAL;
+       struct vfsmount *mnt = ERR_PTR(-ENOENT);
+       char *mnt_path;
+       int page2len;
+       unsigned int s;
+
+       mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
+       if (IS_ERR(mnt_path))
+               return mnt;
+       mountdata->mnt_path = mnt_path;
+       page2 += strlen(mnt_path) + 1;
+       page2len = PAGE_SIZE - strlen(mnt_path) - 1;
+
+       for (s = 0; s < location->nservers; s++) {
+               const struct nfs4_string *buf = &location->servers[s];
+               struct sockaddr_storage addr;
+
+               if (buf->len <= 0 || buf->len >= PAGE_SIZE)
+                       continue;
+
+               mountdata->addr = (struct sockaddr *)&addr;
+
+               if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
+                       continue;
+               nfs_parse_ip_address(buf->data, buf->len,
+                               mountdata->addr, &mountdata->addrlen);
+               if (mountdata->addr->sa_family == AF_UNSPEC)
+                       continue;
+               nfs_set_port(mountdata->addr, NFS_PORT);
+
+               strncpy(page2, buf->data, page2len);
+               page2[page2len] = '\0';
+               mountdata->hostname = page2;
+
+               snprintf(page, PAGE_SIZE, "%s:%s",
+                               mountdata->hostname,
+                               mountdata->mnt_path);
+
+               mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, mountdata);
+               if (!IS_ERR(mnt))
+                       break;
        }
-       return 0;
+       return mnt;
 }
 
 /**
@@ -128,7 +159,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
                .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
        };
        char *page = NULL, *page2 = NULL;
-       unsigned int s;
        int loc, error;
 
        if (locations == NULL || locations->nlocations <= 0)
@@ -152,53 +182,16 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
                goto out;
        }
 
-       loc = 0;
-       while (loc < locations->nlocations && IS_ERR(mnt)) {
+       for (loc = 0; loc < locations->nlocations; loc++) {
                const struct nfs4_fs_location *location = &locations->locations[loc];
-               char *mnt_path;
 
                if (location == NULL || location->nservers <= 0 ||
-                   location->rootpath.ncomponents == 0) {
-                       loc++;
+                   location->rootpath.ncomponents == 0)
                        continue;
-               }
 
-               mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
-               if (IS_ERR(mnt_path)) {
-                       loc++;
-                       continue;
-               }
-               mountdata.mnt_path = mnt_path;
-
-               s = 0;
-               while (s < location->nservers) {
-                       struct sockaddr_in addr = {
-                               .sin_family     = AF_INET,
-                               .sin_port       = htons(NFS_PORT),
-                       };
-
-                       if (location->servers[s].len <= 0 ||
-                           valid_ipaddr4(location->servers[s].data) < 0) {
-                               s++;
-                               continue;
-                       }
-
-                       mountdata.hostname = location->servers[s].data;
-                       addr.sin_addr.s_addr = in_aton(mountdata.hostname),
-                       mountdata.addr = (struct sockaddr *)&addr;
-                       mountdata.addrlen = sizeof(addr);
-
-                       snprintf(page, PAGE_SIZE, "%s:%s",
-                                       mountdata.hostname,
-                                       mountdata.mnt_path);
-
-                       mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata);
-                       if (!IS_ERR(mnt)) {
-                               break;
-                       }
-                       s++;
-               }
-               loc++;
+               mnt = try_location(&mountdata, page, page2, location);
+               if (!IS_ERR(mnt))
+                       break;
        }
 
 out:
index 46763d1cd3976bca27f4d5dca5d3dd9e36d3453b..8478fc25daee196383f3e40a34999795be41585e 100644 (file)
@@ -127,7 +127,7 @@ enum {
        Opt_err
 };
 
-static match_table_t __initdata tokens = {
+static match_table_t __initconst tokens = {
        {Opt_port, "port=%u"},
        {Opt_rsize, "rsize=%u"},
        {Opt_wsize, "wsize=%u"},
index 4dbb84df1b686995346cf352bc8107b5dd424028..193465210d7cdeec5548f7fbb2fbe0ccfecf2375 100644 (file)
@@ -65,14 +65,20 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 
        dprintk("%s: call getattr\n", __func__);
        nfs_fattr_init(fattr);
-       status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(server->client, &msg, 0);
+       /* Retry with default authentication if different */
+       if (status && server->nfs_client->cl_rpcclient != server->client)
+               status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
        dprintk("%s: reply getattr: %d\n", __func__, status);
        if (status)
                return status;
        dprintk("%s: call statfs\n", __func__);
        msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS];
        msg.rpc_resp = &fsinfo;
-       status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(server->client, &msg, 0);
+       /* Retry with default authentication if different */
+       if (status && server->nfs_client->cl_rpcclient != server->client)
+               status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
        dprintk("%s: reply statfs: %d\n", __func__, status);
        if (status)
                return status;
index e9b20173fef33835e9d87be1a9b67e718b8dfe0a..8b28b95c9e44a6cafe221609111a05bb0c495361 100644 (file)
@@ -91,6 +91,7 @@ enum {
        /* Mount options that take string arguments */
        Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
        Opt_addr, Opt_mountaddr, Opt_clientaddr,
+       Opt_lookupcache,
 
        /* Special mount options */
        Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -98,7 +99,7 @@ enum {
        Opt_err
 };
 
-static match_table_t nfs_mount_option_tokens = {
+static const match_table_t nfs_mount_option_tokens = {
        { Opt_userspace, "bg" },
        { Opt_userspace, "fg" },
        { Opt_userspace, "retry=%s" },
@@ -154,6 +155,8 @@ static match_table_t nfs_mount_option_tokens = {
        { Opt_mounthost, "mounthost=%s" },
        { Opt_mountaddr, "mountaddr=%s" },
 
+       { Opt_lookupcache, "lookupcache=%s" },
+
        { Opt_err, NULL }
 };
 
@@ -163,7 +166,7 @@ enum {
        Opt_xprt_err
 };
 
-static match_table_t nfs_xprt_protocol_tokens = {
+static const match_table_t nfs_xprt_protocol_tokens = {
        { Opt_xprt_udp, "udp" },
        { Opt_xprt_tcp, "tcp" },
        { Opt_xprt_rdma, "rdma" },
@@ -180,7 +183,7 @@ enum {
        Opt_sec_err
 };
 
-static match_table_t nfs_secflavor_tokens = {
+static const match_table_t nfs_secflavor_tokens = {
        { Opt_sec_none, "none" },
        { Opt_sec_none, "null" },
        { Opt_sec_sys, "sys" },
@@ -200,6 +203,22 @@ static match_table_t nfs_secflavor_tokens = {
        { Opt_sec_err, NULL }
 };
 
+enum {
+       Opt_lookupcache_all, Opt_lookupcache_positive,
+       Opt_lookupcache_none,
+
+       Opt_lookupcache_err
+};
+
+static match_table_t nfs_lookupcache_tokens = {
+       { Opt_lookupcache_all, "all" },
+       { Opt_lookupcache_positive, "pos" },
+       { Opt_lookupcache_positive, "positive" },
+       { Opt_lookupcache_none, "none" },
+
+       { Opt_lookupcache_err, NULL }
+};
+
 
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
@@ -209,7 +228,6 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru
 static int nfs_xdev_get_sb(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
 static void nfs_kill_super(struct super_block *);
-static void nfs_put_super(struct super_block *);
 static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 
 static struct file_system_type nfs_fs_type = {
@@ -232,7 +250,6 @@ static const struct super_operations nfs_sops = {
        .alloc_inode    = nfs_alloc_inode,
        .destroy_inode  = nfs_destroy_inode,
        .write_inode    = nfs_write_inode,
-       .put_super      = nfs_put_super,
        .statfs         = nfs_statfs,
        .clear_inode    = nfs_clear_inode,
        .umount_begin   = nfs_umount_begin,
@@ -337,26 +354,20 @@ void __exit unregister_nfs_fs(void)
        unregister_filesystem(&nfs_fs_type);
 }
 
-void nfs_sb_active(struct nfs_server *server)
+void nfs_sb_active(struct super_block *sb)
 {
-       atomic_inc(&server->active);
-}
+       struct nfs_server *server = NFS_SB(sb);
 
-void nfs_sb_deactive(struct nfs_server *server)
-{
-       if (atomic_dec_and_test(&server->active))
-               wake_up(&server->active_wq);
+       if (atomic_inc_return(&server->active) == 1)
+               atomic_inc(&sb->s_active);
 }
 
-static void nfs_put_super(struct super_block *sb)
+void nfs_sb_deactive(struct super_block *sb)
 {
        struct nfs_server *server = NFS_SB(sb);
-       /*
-        * Make sure there are no outstanding ops to this server.
-        * If so, wait for them to finish before allowing the
-        * unmount to continue.
-        */
-       wait_event(server->active_wq, atomic_read(&server->active) == 0);
+
+       if (atomic_dec_and_test(&server->active))
+               deactivate_super(sb);
 }
 
 /*
@@ -663,25 +674,6 @@ static void nfs_umount_begin(struct super_block *sb)
                rpc_killall_tasks(rpc);
 }
 
-/*
- * Set the port number in an address.  Be agnostic about the address family.
- */
-static void nfs_set_port(struct sockaddr *sap, unsigned short port)
-{
-       switch (sap->sa_family) {
-       case AF_INET: {
-               struct sockaddr_in *ap = (struct sockaddr_in *)sap;
-               ap->sin_port = htons(port);
-               break;
-       }
-       case AF_INET6: {
-               struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
-               ap->sin6_port = htons(port);
-               break;
-       }
-       }
-}
-
 /*
  * Sanity-check a server address provided by the mount command.
  *
@@ -724,20 +716,22 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len,
        *addr_len = 0;
 }
 
-#define IPV6_SCOPE_DELIMITER   '%'
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
-                                   const char *delim,
-                                   struct sockaddr_in6 *sin6)
+static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
+                                  const char *delim,
+                                  struct sockaddr_in6 *sin6)
 {
        char *p;
        size_t len;
 
-       if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
-               return ;
+       if ((string + str_len) == delim)
+               return 1;
+
        if (*delim != IPV6_SCOPE_DELIMITER)
-               return;
+               return 0;
+
+       if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
+               return 0;
 
        len = (string + str_len) - delim - 1;
        p = kstrndup(delim + 1, len, GFP_KERNEL);
@@ -750,14 +744,20 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
                        scope_id = dev->ifindex;
                        dev_put(dev);
                } else {
-                       /* scope_id is set to zero on error */
-                       strict_strtoul(p, 10, &scope_id);
+                       if (strict_strtoul(p, 10, &scope_id) == 0) {
+                               kfree(p);
+                               return 0;
+                       }
                }
 
                kfree(p);
+
                sin6->sin6_scope_id = scope_id;
                dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
+               return 1;
        }
+
+       return 0;
 }
 
 static void nfs_parse_ipv6_address(char *string, size_t str_len,
@@ -773,9 +773,11 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
 
                sin6->sin6_family = AF_INET6;
                *addr_len = sizeof(*sin6);
-               if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) {
-                       nfs_parse_ipv6_scope_id(string, str_len, delim, sin6);
-                       return;
+               if (in6_pton(string, str_len, addr,
+                                       IPV6_SCOPE_DELIMITER, &delim) != 0) {
+                       if (nfs_parse_ipv6_scope_id(string, str_len,
+                                                       delim, sin6) != 0)
+                               return;
                }
        }
 
@@ -798,7 +800,7 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len,
  * If there is a problem constructing the new sockaddr, set the address
  * family to AF_UNSPEC.
  */
-static void nfs_parse_ip_address(char *string, size_t str_len,
+void nfs_parse_ip_address(char *string, size_t str_len,
                                 struct sockaddr *sap, size_t *addr_len)
 {
        unsigned int i, colons;
@@ -1258,6 +1260,30 @@ static int nfs_parse_mount_options(char *raw,
                                             &mnt->mount_server.addrlen);
                        kfree(string);
                        break;
+               case Opt_lookupcache:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string,
+                                       nfs_lookupcache_tokens, args);
+                       kfree(string);
+                       switch (token) {
+                               case Opt_lookupcache_all:
+                                       mnt->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
+                                       break;
+                               case Opt_lookupcache_positive:
+                                       mnt->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE;
+                                       mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG;
+                                       break;
+                               case Opt_lookupcache_none:
+                                       mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE;
+                                       break;
+                               default:
+                                       errors++;
+                                       dfprintk(MOUNT, "NFS:   invalid "
+                                                       "lookupcache argument\n");
+                       };
+                       break;
 
                /*
                 * Special options
@@ -1558,7 +1584,7 @@ static int nfs_validate_mount_data(void *options,
                 * Translate to nfs_parsed_mount_data, which nfs_fill_super
                 * can deal with.
                 */
-               args->flags             = data->flags;
+               args->flags             = data->flags & NFS_MOUNT_FLAGMASK;
                args->rsize             = data->rsize;
                args->wsize             = data->wsize;
                args->timeo             = data->timeo;
index f089e5839d7deefe50bc351f98eff7d45fdfd453..ecc295347775e2b2f31a508da1172e307898d234 100644 (file)
@@ -99,7 +99,7 @@ static void nfs_async_unlink_release(void *calldata)
 
        nfs_dec_sillycount(data->dir);
        nfs_free_unlinkdata(data);
-       nfs_sb_deactive(NFS_SB(sb));
+       nfs_sb_deactive(sb);
 }
 
 static const struct rpc_call_ops nfs_unlink_ops = {
@@ -118,6 +118,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
                .rpc_message = &msg,
                .callback_ops = &nfs_unlink_ops,
                .callback_data = data,
+               .workqueue = nfsiod_workqueue,
                .flags = RPC_TASK_ASYNC,
        };
        struct rpc_task *task;
@@ -149,7 +150,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
                nfs_dec_sillycount(dir);
                return 0;
        }
-       nfs_sb_active(NFS_SERVER(dir));
+       nfs_sb_active(dir->i_sb);
        data->args.fh = NFS_FH(dir);
        nfs_fattr_init(&data->res.dir_attr);
 
index 3229e217c773a357cd7735f9cd72351c075dbee1..9f9845859fc1805627c317bc18963473427cbdd2 100644 (file)
@@ -1427,8 +1427,9 @@ static int nfs_write_mapping(struct address_space *mapping, int how)
                .bdi = mapping->backing_dev_info,
                .sync_mode = WB_SYNC_NONE,
                .nr_to_write = LONG_MAX,
+               .range_start = 0,
+               .range_end = LLONG_MAX,
                .for_writepages = 1,
-               .range_cyclic = 1,
        };
        int ret;
 
index 15c6faeec77c118a77b11c50287a6a43828bd9a2..b2786a5f9afefaaea3573303339cd7154ad54bd7 100644 (file)
@@ -70,7 +70,6 @@ nlm_fclose(struct file *filp)
 static struct nlmsvc_binding   nfsd_nlm_ops = {
        .fopen          = nlm_fopen,            /* open file for locking */
        .fclose         = nlm_fclose,           /* close file */
-       .get_grace_period = get_nfs4_grace_period,
 };
 
 void
index 4d617ea28cfc0b699868275db4cd95202e23f989..9dbd2eb91281b14a4f3472c3ac5dad046c4525c9 100644 (file)
@@ -63,7 +63,8 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
                SVCFH_fmt(&argp->fh));
 
        fh_copy(&resp->fh, &argp->fh);
-       nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+       nfserr = fh_verify(rqstp, &resp->fh, 0,
+                       NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
        if (nfserr)
                RETURN_STATUS(nfserr);
 
@@ -530,7 +531,7 @@ nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
        dprintk("nfsd: FSSTAT(3)   %s\n",
                                SVCFH_fmt(&argp->fh));
 
-       nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
+       nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
        fh_put(&argp->fh);
        RETURN_STATUS(nfserr);
 }
@@ -558,7 +559,8 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
        resp->f_maxfilesize = ~(u32) 0;
        resp->f_properties = NFS3_FSF_DEFAULT;
 
-       nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
+       nfserr = fh_verify(rqstp, &argp->fh, 0,
+                       NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
 
        /* Check special features of the file system. May request
         * different read/write sizes for file systems known to have
index 702fa577aa6e075a6fef3a9b31be6ffdb1d3a9c5..094747a1227c18b6ace1726d81ed97487c98169a 100644 (file)
@@ -225,7 +225,8 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
 
        RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
        WRITE32(OP_CB_RECALL);
-       WRITEMEM(&cb_rec->cbr_stateid, sizeof(stateid_t));
+       WRITE32(cb_rec->cbr_stateid.si_generation);
+       WRITEMEM(&cb_rec->cbr_stateid.si_opaque, sizeof(stateid_opaque_t));
        WRITE32(cb_rec->cbr_trunc);
        WRITE32(len);
        WRITEMEM(cb_rec->cbr_fhval, len);
@@ -379,6 +380,7 @@ static int do_probe_callback(void *data)
                .addrsize       = sizeof(addr),
                .timeout        = &timeparms,
                .program        = &cb_program,
+               .prognumber     = cb->cb_prog,
                .version        = nfs_cb_version[1]->number,
                .authflavor     = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
@@ -396,9 +398,6 @@ static int do_probe_callback(void *data)
        addr.sin_port = htons(cb->cb_port);
        addr.sin_addr.s_addr = htonl(cb->cb_addr);
 
-       /* Initialize rpc_stat */
-       memset(args.program->stats, 0, sizeof(struct rpc_stat));
-
        /* Create RPC client */
        client = rpc_create(&args);
        if (IS_ERR(client)) {
index e5b51ffafc6c2c2300fb61f3fb0c0036e0762115..669461e291aecbd7f15e2065c61e86f26cd9d2e7 100644 (file)
@@ -201,10 +201,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        /* Openowner is now set, so sequence id will get bumped.  Now we need
         * these checks before we do any creates: */
        status = nfserr_grace;
-       if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+       if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
                goto out;
        status = nfserr_no_grace;
-       if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+       if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
                goto out;
 
        switch (open->op_claim_type) {
@@ -575,7 +575,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        __be32 status;
 
-       if (nfs4_in_grace())
+       if (locks_in_grace())
                return nfserr_grace;
        status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
                             remove->rm_name, remove->rm_namelen);
@@ -596,7 +596,7 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        if (!cstate->save_fh.fh_dentry)
                return status;
-       if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
+       if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
                                        & NFSEXP_NOSUBTREECHECK))
                return nfserr_grace;
        status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
index 1578d7a2667ec397f3e0689d1445527cf9a38cf4..0cc7ff5d5ab53e4bf0c0c5e4646cac4012f18165 100644 (file)
@@ -61,7 +61,6 @@
 static time_t lease_time = 90;     /* default lease time */
 static time_t user_lease_time = 90;
 static time_t boot_time;
-static int in_grace = 1;
 static u32 current_ownerid = 1;
 static u32 current_fileid = 1;
 static u32 current_delegid = 1;
@@ -1640,7 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
                case NFS4_OPEN_CLAIM_NULL:
                        /* Let's not give out any delegations till everyone's
                         * had the chance to reclaim theirs.... */
-                       if (nfs4_in_grace())
+                       if (locks_in_grace())
                                goto out;
                        if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
                                goto out;
@@ -1816,12 +1815,15 @@ out:
        return status;
 }
 
+struct lock_manager nfsd4_manager = {
+};
+
 static void
-end_grace(void)
+nfsd4_end_grace(void)
 {
        dprintk("NFSD: end of grace period\n");
        nfsd4_recdir_purge_old();
-       in_grace = 0;
+       locks_end_grace(&nfsd4_manager);
 }
 
 static time_t
@@ -1838,8 +1840,8 @@ nfs4_laundromat(void)
        nfs4_lock_state();
 
        dprintk("NFSD: laundromat service - starting\n");
-       if (in_grace)
-               end_grace();
+       if (locks_in_grace())
+               nfsd4_end_grace();
        list_for_each_safe(pos, next, &client_lru) {
                clp = list_entry(pos, struct nfs4_client, cl_lru);
                if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1974,7 +1976,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
                return nfserr_bad_stateid;
        else if (ONE_STATEID(stateid) && (flags & RD_STATE))
                return nfs_ok;
-       else if (nfs4_in_grace()) {
+       else if (locks_in_grace()) {
                /* Answer in remaining cases depends on existance of
                 * conflicting state; so we must wait out the grace period. */
                return nfserr_grace;
@@ -1993,7 +1995,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
 static inline int
 io_during_grace_disallowed(struct inode *inode, int flags)
 {
-       return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
+       return locks_in_grace() && (flags & (RD_STATE | WR_STATE))
                && mandatory_lock(inode);
 }
 
@@ -2693,10 +2695,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        filp = lock_stp->st_vfs_file;
 
        status = nfserr_grace;
-       if (nfs4_in_grace() && !lock->lk_reclaim)
+       if (locks_in_grace() && !lock->lk_reclaim)
                goto out;
        status = nfserr_no_grace;
-       if (!nfs4_in_grace() && lock->lk_reclaim)
+       if (!locks_in_grace() && lock->lk_reclaim)
                goto out;
 
        locks_init_lock(&file_lock);
@@ -2779,7 +2781,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        int error;
        __be32 status;
 
-       if (nfs4_in_grace())
+       if (locks_in_grace())
                return nfserr_grace;
 
        if (check_lock_length(lockt->lt_offset, lockt->lt_length))
@@ -3192,9 +3194,9 @@ __nfs4_state_start(void)
        unsigned long grace_time;
 
        boot_time = get_seconds();
-       grace_time = get_nfs_grace_period();
+       grace_time = get_nfs4_grace_period();
        lease_time = user_lease_time;
-       in_grace = 1;
+       locks_start_grace(&nfsd4_manager);
        printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
               grace_time/HZ);
        laundry_wq = create_singlethread_workqueue("nfsd4");
@@ -3213,12 +3215,6 @@ nfs4_state_start(void)
        return;
 }
 
-int
-nfs4_in_grace(void)
-{
-       return in_grace;
-}
-
 time_t
 nfs4_lease_time(void)
 {
index 14ba4d9b285913f8aea89eae504908eebc56f435..afcdf4b76843a7219e50c66d3d3dba4dde5ae514 100644 (file)
@@ -412,6 +412,18 @@ out_nfserr:
        goto out;
 }
 
+static __be32
+nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
+{
+       DECODE_HEAD;
+
+       READ_BUF(sizeof(stateid_t));
+       READ32(sid->si_generation);
+       COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
+
+       DECODE_TAIL;
+}
+
 static __be32
 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
 {
@@ -429,10 +441,9 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
        DECODE_HEAD;
 
        close->cl_stateowner = NULL;
-       READ_BUF(4 + sizeof(stateid_t));
+       READ_BUF(4);
        READ32(close->cl_seqid);
-       READ32(close->cl_stateid.si_generation);
-       COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
+       return nfsd4_decode_stateid(argp, &close->cl_stateid);
 
        DECODE_TAIL;
 }
@@ -493,13 +504,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 static inline __be32
 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
 {
-       DECODE_HEAD;
-
-       READ_BUF(sizeof(stateid_t));
-       READ32(dr->dr_stateid.si_generation);
-       COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t));
-
-       DECODE_TAIL;
+       return nfsd4_decode_stateid(argp, &dr->dr_stateid);
 }
 
 static inline __be32
@@ -542,20 +547,22 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
        READ32(lock->lk_is_new);
 
        if (lock->lk_is_new) {
-               READ_BUF(36);
+               READ_BUF(4);
                READ32(lock->lk_new_open_seqid);
-               READ32(lock->lk_new_open_stateid.si_generation);
-
-               COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t));
+               status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
+               if (status)
+                       return status;
+               READ_BUF(8 + sizeof(clientid_t));
                READ32(lock->lk_new_lock_seqid);
                COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
                READ32(lock->lk_new_owner.len);
                READ_BUF(lock->lk_new_owner.len);
                READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
        } else {
-               READ_BUF(20);
-               READ32(lock->lk_old_lock_stateid.si_generation);
-               COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t));
+               status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
+               if (status)
+                       return status;
+               READ_BUF(4);
                READ32(lock->lk_old_lock_seqid);
        }
 
@@ -587,13 +594,15 @@ nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
        DECODE_HEAD;
 
        locku->lu_stateowner = NULL;
-       READ_BUF(24 + sizeof(stateid_t));
+       READ_BUF(8);
        READ32(locku->lu_type);
        if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
                goto xdr_error;
        READ32(locku->lu_seqid);
-       READ32(locku->lu_stateid.si_generation);
-       COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
+       status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
+       if (status)
+               return status;
+       READ_BUF(16);
        READ64(locku->lu_offset);
        READ64(locku->lu_length);
 
@@ -678,8 +687,10 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
                READ32(open->op_delegate_type);
                break;
        case NFS4_OPEN_CLAIM_DELEGATE_CUR:
-               READ_BUF(sizeof(stateid_t) + 4);
-               COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+               status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
+               if (status)
+                       return status;
+               READ_BUF(4);
                READ32(open->op_fname.len);
                READ_BUF(open->op_fname.len);
                SAVEMEM(open->op_fname.data, open->op_fname.len);
@@ -699,9 +710,10 @@ nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_con
        DECODE_HEAD;
                    
        open_conf->oc_stateowner = NULL;
-       READ_BUF(4 + sizeof(stateid_t));
-       READ32(open_conf->oc_req_stateid.si_generation);
-       COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
+       status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
+       if (status)
+               return status;
+       READ_BUF(4);
        READ32(open_conf->oc_seqid);
                                                        
        DECODE_TAIL;
@@ -713,9 +725,10 @@ nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_d
        DECODE_HEAD;
                    
        open_down->od_stateowner = NULL;
-       READ_BUF(12 + sizeof(stateid_t));
-       READ32(open_down->od_stateid.si_generation);
-       COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
+       status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
+       if (status)
+               return status;
+       READ_BUF(12);
        READ32(open_down->od_seqid);
        READ32(open_down->od_share_access);
        READ32(open_down->od_share_deny);
@@ -743,9 +756,10 @@ nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
 {
        DECODE_HEAD;
 
-       READ_BUF(sizeof(stateid_t) + 12);
-       READ32(read->rd_stateid.si_generation);
-       COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
+       status = nfsd4_decode_stateid(argp, &read->rd_stateid);
+       if (status)
+               return status;
+       READ_BUF(12);
        READ64(read->rd_offset);
        READ32(read->rd_length);
 
@@ -834,15 +848,13 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
 static __be32
 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
 {
-       DECODE_HEAD;
-
-       READ_BUF(sizeof(stateid_t));
-       READ32(setattr->sa_stateid.si_generation);
-       COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
-       if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
-               goto out;
+       __be32 status;
 
-       DECODE_TAIL;
+       status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
+       if (status)
+               return status;
+       return nfsd4_decode_fattr(argp, setattr->sa_bmval,
+                                 &setattr->sa_iattr, &setattr->sa_acl);
 }
 
 static __be32
@@ -927,9 +939,10 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
        int len;
        DECODE_HEAD;
 
-       READ_BUF(sizeof(stateid_opaque_t) + 20);
-       READ32(write->wr_stateid.si_generation);
-       COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
+       status = nfsd4_decode_stateid(argp, &write->wr_stateid);
+       if (status)
+               return status;
+       READ_BUF(16);
        READ64(write->wr_offset);
        READ32(write->wr_stable_how);
        if (write->wr_stable_how > 2)
@@ -1183,7 +1196,6 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
  * Header routine to setup seqid operation replay cache
  */
 #define ENCODE_SEQID_OP_HEAD                                   \
-       __be32 *p;                                              \
        __be32 *save;                                           \
                                                                \
        save = resp->p;
@@ -1950,6 +1962,17 @@ fail:
        return -EINVAL;
 }
 
+static void
+nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
+{
+       ENCODE_HEAD;
+
+       RESERVE_SPACE(sizeof(stateid_t));
+       WRITE32(sid->si_generation);
+       WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
+       ADJUST_ARGS();
+}
+
 static __be32
 nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
 {
@@ -1969,12 +1992,9 @@ nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_c
 {
        ENCODE_SEQID_OP_HEAD;
 
-       if (!nfserr) {
-               RESERVE_SPACE(sizeof(stateid_t));
-               WRITE32(close->cl_stateid.si_generation);
-               WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
-               ADJUST_ARGS();
-       }
+       if (!nfserr)
+               nfsd4_encode_stateid(resp, &close->cl_stateid);
+
        ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
        return nfserr;
 }
@@ -2074,12 +2094,9 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo
 {
        ENCODE_SEQID_OP_HEAD;
 
-       if (!nfserr) {
-               RESERVE_SPACE(4 + sizeof(stateid_t));
-               WRITE32(lock->lk_resp_stateid.si_generation);
-               WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
-               ADJUST_ARGS();
-       } else if (nfserr == nfserr_denied)
+       if (!nfserr)
+               nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
+       else if (nfserr == nfserr_denied)
                nfsd4_encode_lock_denied(resp, &lock->lk_denied);
 
        ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
@@ -2099,13 +2116,9 @@ nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_l
 {
        ENCODE_SEQID_OP_HEAD;
 
-       if (!nfserr) {
-               RESERVE_SPACE(sizeof(stateid_t));
-               WRITE32(locku->lu_stateid.si_generation);
-               WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
-               ADJUST_ARGS();
-       }
-                                       
+       if (!nfserr)
+               nfsd4_encode_stateid(resp, &locku->lu_stateid);
+
        ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
        return nfserr;
 }
@@ -2128,14 +2141,14 @@ nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_li
 static __be32
 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
 {
+       ENCODE_HEAD;
        ENCODE_SEQID_OP_HEAD;
 
        if (nfserr)
                goto out;
 
-       RESERVE_SPACE(36 + sizeof(stateid_t));
-       WRITE32(open->op_stateid.si_generation);
-       WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
+       nfsd4_encode_stateid(resp, &open->op_stateid);
+       RESERVE_SPACE(40);
        WRITECINFO(open->op_cinfo);
        WRITE32(open->op_rflags);
        WRITE32(2);
@@ -2148,8 +2161,8 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
        case NFS4_OPEN_DELEGATE_NONE:
                break;
        case NFS4_OPEN_DELEGATE_READ:
-               RESERVE_SPACE(20 + sizeof(stateid_t));
-               WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+               nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
+               RESERVE_SPACE(20);
                WRITE32(open->op_recall);
 
                /*
@@ -2162,8 +2175,8 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_op
                ADJUST_ARGS();
                break;
        case NFS4_OPEN_DELEGATE_WRITE:
-               RESERVE_SPACE(32 + sizeof(stateid_t));
-               WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
+               nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
+               RESERVE_SPACE(32);
                WRITE32(0);
 
                /*
@@ -2195,13 +2208,9 @@ static __be32
 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
 {
        ENCODE_SEQID_OP_HEAD;
-                                       
-       if (!nfserr) {
-               RESERVE_SPACE(sizeof(stateid_t));
-               WRITE32(oc->oc_resp_stateid.si_generation);
-               WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
-               ADJUST_ARGS();
-       }
+
+       if (!nfserr)
+               nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
 
        ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
        return nfserr;
@@ -2211,13 +2220,9 @@ static __be32
 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
 {
        ENCODE_SEQID_OP_HEAD;
-                                       
-       if (!nfserr) {
-               RESERVE_SPACE(sizeof(stateid_t));
-               WRITE32(od->od_stateid.si_generation);
-               WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
-               ADJUST_ARGS();
-       }
+
+       if (!nfserr)
+               nfsd4_encode_stateid(resp, &od->od_stateid);
 
        ENCODE_SEQID_OP_TAIL(od->od_stateowner);
        return nfserr;
index c53e65f8f3a2b460d6c01424094b29c8082843a4..97543df58242f1bc54244aeac633a4fc2e139c8f 100644 (file)
@@ -614,10 +614,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
                        return -EINVAL;
                err = nfsd_create_serv();
                if (!err) {
-                       int proto = 0;
-                       err = svc_addsock(nfsd_serv, fd, buf, &proto);
+                       err = svc_addsock(nfsd_serv, fd, buf);
                        if (err >= 0) {
-                               err = lockd_up(proto);
+                               err = lockd_up();
                                if (err < 0)
                                        svc_sock_names(buf+strlen(buf)+1, nfsd_serv, buf);
                        }
index ea37c96f04454e7f1513ca1222aa4eba86f98fb0..cd25d91895a19fc0906b3e5b1891bed123cff15b 100644 (file)
@@ -302,17 +302,27 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
        if (error)
                goto out;
 
-       if (!(access & NFSD_MAY_LOCK)) {
-               /*
-                * pseudoflavor restrictions are not enforced on NLM,
-                * which clients virtually always use auth_sys for,
-                * even while using RPCSEC_GSS for NFS.
-                */
-               error = check_nfsd_access(exp, rqstp);
-               if (error)
-                       goto out;
-       }
+       /*
+        * pseudoflavor restrictions are not enforced on NLM,
+        * which clients virtually always use auth_sys for,
+        * even while using RPCSEC_GSS for NFS.
+        */
+       if (access & NFSD_MAY_LOCK)
+               goto skip_pseudoflavor_check;
+       /*
+        * Clients may expect to be able to use auth_sys during mount,
+        * even if they use gss for everything else; see section 2.3.2
+        * of rfc 2623.
+        */
+       if (access & NFSD_MAY_BYPASS_GSS_ON_ROOT
+                       && exp->ex_path.dentry == dentry)
+               goto skip_pseudoflavor_check;
+
+       error = check_nfsd_access(exp, rqstp);
+       if (error)
+               goto out;
 
+skip_pseudoflavor_check:
        /* Finally, check access permissions. */
        error = nfsd_permission(rqstp, exp, dentry, access);
 
index 0766f95d236a23cf73f247bea43e4d0b28c61844..5cffeca7acef326d87a804eeb87e26bc6c11b67e 100644 (file)
@@ -65,7 +65,8 @@ nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
        dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
        fh_copy(&resp->fh, &argp->fh);
-       nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_NOP);
+       nfserr = fh_verify(rqstp, &resp->fh, 0,
+                       NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
        return nfsd_return_attrs(nfserr, resp);
 }
 
@@ -521,7 +522,8 @@ nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
 
        dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
 
-       nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
+       nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
+                       NFSD_MAY_BYPASS_GSS_ON_ROOT);
        fh_put(&argp->fh);
        return nfserr;
 }
index 80292ff5e924a15ff0130866878cf7669cfd041f..59eeb46f82c5e842c528ff63a905347c2015e15e 100644 (file)
@@ -229,6 +229,7 @@ int nfsd_create_serv(void)
 
        atomic_set(&nfsd_busy, 0);
        nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
+                                     AF_INET,
                                      nfsd_last_thread, nfsd, THIS_MODULE);
        if (nfsd_serv == NULL)
                err = -ENOMEM;
@@ -243,25 +244,20 @@ static int nfsd_init_socks(int port)
        if (!list_empty(&nfsd_serv->sv_permsocks))
                return 0;
 
-       error = lockd_up(IPPROTO_UDP);
-       if (error >= 0) {
-               error = svc_create_xprt(nfsd_serv, "udp", port,
+       error = svc_create_xprt(nfsd_serv, "udp", port,
                                        SVC_SOCK_DEFAULTS);
-               if (error < 0)
-                       lockd_down();
-       }
        if (error < 0)
                return error;
 
-       error = lockd_up(IPPROTO_TCP);
-       if (error >= 0) {
-               error = svc_create_xprt(nfsd_serv, "tcp", port,
+       error = svc_create_xprt(nfsd_serv, "tcp", port,
                                        SVC_SOCK_DEFAULTS);
-               if (error < 0)
-                       lockd_down();
-       }
        if (error < 0)
                return error;
+
+       error = lockd_up();
+       if (error < 0)
+               return error;
+
        return 0;
 }
 
index 18060bed5267451c005345ef19f5a270ee5143aa..aa1d0d6489a119a3e8e00aa301cc9a9719006087 100644 (file)
@@ -83,7 +83,6 @@ struct raparm_hbucket {
        spinlock_t              pb_lock;
 } ____cacheline_aligned_in_smp;
 
-static struct raparms *                raparml;
 #define RAPARM_HASH_BITS       4
 #define RAPARM_HASH_SIZE       (1<<RAPARM_HASH_BITS)
 #define RAPARM_HASH_MASK       (RAPARM_HASH_SIZE-1)
@@ -1866,9 +1865,9 @@ out:
  * N.B. After this call fhp needs an fh_put
  */
 __be32
-nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
+nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access)
 {
-       __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
+       __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access);
        if (!err && vfs_statfs(fhp->fh_dentry,stat))
                err = nfserr_io;
        return err;
@@ -1966,11 +1965,20 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
 void
 nfsd_racache_shutdown(void)
 {
-       if (!raparml)
-               return;
+       struct raparms *raparm, *last_raparm;
+       unsigned int i;
+
        dprintk("nfsd: freeing readahead buffers.\n");
-       kfree(raparml);
-       raparml = NULL;
+
+       for (i = 0; i < RAPARM_HASH_SIZE; i++) {
+               raparm = raparm_hash[i].pb_head;
+               while(raparm) {
+                       last_raparm = raparm;
+                       raparm = raparm->p_next;
+                       kfree(last_raparm);
+               }
+               raparm_hash[i].pb_head = NULL;
+       }
 }
 /*
  * Initialize readahead param cache
@@ -1981,35 +1989,38 @@ nfsd_racache_init(int cache_size)
        int     i;
        int     j = 0;
        int     nperbucket;
+       struct raparms **raparm = NULL;
 
 
-       if (raparml)
+       if (raparm_hash[0].pb_head)
                return 0;
-       if (cache_size < 2*RAPARM_HASH_SIZE)
-               cache_size = 2*RAPARM_HASH_SIZE;
-       raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL);
-
-       if (!raparml) {
-               printk(KERN_WARNING
-                       "nfsd: Could not allocate memory read-ahead cache.\n");
-               return -ENOMEM;
-       }
+       nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
+       if (nperbucket < 2)
+               nperbucket = 2;
+       cache_size = nperbucket * RAPARM_HASH_SIZE;
 
        dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
-       for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
-               raparm_hash[i].pb_head = NULL;
+
+       for (i = 0; i < RAPARM_HASH_SIZE; i++) {
                spin_lock_init(&raparm_hash[i].pb_lock);
-       }
-       nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
-       for (i = 0; i < cache_size - 1; i++) {
-               if (i % nperbucket == 0)
-                       raparm_hash[j++].pb_head = raparml + i;
-               if (i % nperbucket < nperbucket-1)
-                       raparml[i].p_next = raparml + i + 1;
+
+               raparm = &raparm_hash[i].pb_head;
+               for (j = 0; j < nperbucket; j++) {
+                       *raparm = kzalloc(sizeof(struct raparms), GFP_KERNEL);
+                       if (!*raparm)
+                               goto out_nomem;
+                       raparm = &(*raparm)->p_next;
+               }
+               *raparm = NULL;
        }
 
        nfsdstats.ra_size = cache_size;
        return 0;
+
+out_nomem:
+       dprintk("nfsd: kmalloc failed, freeing readahead buffers\n");
+       nfsd_racache_shutdown();
+       return -ENOMEM;
 }
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
index 64965e1c21c46ca2dcb9aae20611a0725e9d4f4b..9b0efdad89100bd60e5a15954b67ca83495cad56 100644 (file)
@@ -13,9 +13,7 @@
 #include <linux/nls.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#ifdef CONFIG_KMOD
 #include <linux/kmod.h>
-#endif
 #include <linux/spinlock.h>
 
 static struct nls_table default_table;
@@ -215,24 +213,7 @@ static struct nls_table *find_nls(char *charset)
 
 struct nls_table *load_nls(char *charset)
 {
-       struct nls_table *nls;
-#ifdef CONFIG_KMOD
-       int ret;
-#endif
-
-       nls = find_nls(charset);
-       if (nls)
-               return nls;
-
-#ifdef CONFIG_KMOD
-       ret = request_module("nls_%s", charset);
-       if (ret != 0) {
-               printk("Unable to load NLS charset %s\n", charset);
-               return NULL;
-       }
-       nls = find_nls(charset);
-#endif
-       return nls;
+       return try_then_request_module(find_nls(charset), "nls_%s", charset);
 }
 
 void unload_nls(struct nls_table *nls)
index f6956de56fdb8e96b0e592f5ed4b95f98a7d3320..589dcdfdfe3cfebab34e7186f46a09407985e774 100644 (file)
@@ -34,7 +34,8 @@ ocfs2-objs := \
        symlink.o               \
        sysfile.o               \
        uptodate.o              \
-       ver.o
+       ver.o                   \
+       xattr.o
 
 ocfs2_stackglue-objs := stackglue.o
 ocfs2_stack_o2cb-objs := stack_o2cb.o
index 29ff57ec5d1f97047549e69f97a5d426b3e60af2..0cc2deb9394c02e1a961c0a1366ae5737b8f32bc 100644 (file)
 
 #include "buffer_head_io.h"
 
+
+/*
+ * Operations for a specific extent tree type.
+ *
+ * To implement an on-disk btree (extent tree) type in ocfs2, add
+ * an ocfs2_extent_tree_operations structure and the matching
+ * ocfs2_init_<thingy>_extent_tree() function.  That's pretty much it
+ * for the allocation portion of the extent tree.
+ */
+struct ocfs2_extent_tree_operations {
+       /*
+        * last_eb_blk is the block number of the right most leaf extent
+        * block.  Most on-disk structures containing an extent tree store
+        * this value for fast access.  The ->eo_set_last_eb_blk() and
+        * ->eo_get_last_eb_blk() operations access this value.  They are
+        *  both required.
+        */
+       void (*eo_set_last_eb_blk)(struct ocfs2_extent_tree *et,
+                                  u64 blkno);
+       u64 (*eo_get_last_eb_blk)(struct ocfs2_extent_tree *et);
+
+       /*
+        * The on-disk structure usually keeps track of how many total
+        * clusters are stored in this extent tree.  This function updates
+        * that value.  new_clusters is the delta, and must be
+        * added to the total.  Required.
+        */
+       void (*eo_update_clusters)(struct inode *inode,
+                                  struct ocfs2_extent_tree *et,
+                                  u32 new_clusters);
+
+       /*
+        * If ->eo_insert_check() exists, it is called before rec is
+        * inserted into the extent tree.  It is optional.
+        */
+       int (*eo_insert_check)(struct inode *inode,
+                              struct ocfs2_extent_tree *et,
+                              struct ocfs2_extent_rec *rec);
+       int (*eo_sanity_check)(struct inode *inode, struct ocfs2_extent_tree *et);
+
+       /*
+        * --------------------------------------------------------------
+        * The remaining are internal to ocfs2_extent_tree and don't have
+        * accessor functions
+        */
+
+       /*
+        * ->eo_fill_root_el() takes et->et_object and sets et->et_root_el.
+        * It is required.
+        */
+       void (*eo_fill_root_el)(struct ocfs2_extent_tree *et);
+
+       /*
+        * ->eo_fill_max_leaf_clusters sets et->et_max_leaf_clusters if
+        * it exists.  If it does not, et->et_max_leaf_clusters is set
+        * to 0 (unlimited).  Optional.
+        */
+       void (*eo_fill_max_leaf_clusters)(struct inode *inode,
+                                         struct ocfs2_extent_tree *et);
+};
+
+
+/*
+ * Pre-declare ocfs2_dinode_et_ops so we can use it as a sanity check
+ * in the methods.
+ */
+static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et);
+static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                        u64 blkno);
+static void ocfs2_dinode_update_clusters(struct inode *inode,
+                                        struct ocfs2_extent_tree *et,
+                                        u32 clusters);
+static int ocfs2_dinode_insert_check(struct inode *inode,
+                                    struct ocfs2_extent_tree *et,
+                                    struct ocfs2_extent_rec *rec);
+static int ocfs2_dinode_sanity_check(struct inode *inode,
+                                    struct ocfs2_extent_tree *et);
+static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et);
+static struct ocfs2_extent_tree_operations ocfs2_dinode_et_ops = {
+       .eo_set_last_eb_blk     = ocfs2_dinode_set_last_eb_blk,
+       .eo_get_last_eb_blk     = ocfs2_dinode_get_last_eb_blk,
+       .eo_update_clusters     = ocfs2_dinode_update_clusters,
+       .eo_insert_check        = ocfs2_dinode_insert_check,
+       .eo_sanity_check        = ocfs2_dinode_sanity_check,
+       .eo_fill_root_el        = ocfs2_dinode_fill_root_el,
+};
+
+static void ocfs2_dinode_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                        u64 blkno)
+{
+       struct ocfs2_dinode *di = et->et_object;
+
+       BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
+       di->i_last_eb_blk = cpu_to_le64(blkno);
+}
+
+static u64 ocfs2_dinode_get_last_eb_blk(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_dinode *di = et->et_object;
+
+       BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
+       return le64_to_cpu(di->i_last_eb_blk);
+}
+
+static void ocfs2_dinode_update_clusters(struct inode *inode,
+                                        struct ocfs2_extent_tree *et,
+                                        u32 clusters)
+{
+       struct ocfs2_dinode *di = et->et_object;
+
+       le32_add_cpu(&di->i_clusters, clusters);
+       spin_lock(&OCFS2_I(inode)->ip_lock);
+       OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
+       spin_unlock(&OCFS2_I(inode)->ip_lock);
+}
+
+static int ocfs2_dinode_insert_check(struct inode *inode,
+                                    struct ocfs2_extent_tree *et,
+                                    struct ocfs2_extent_rec *rec)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
+       mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
+                       (OCFS2_I(inode)->ip_clusters != rec->e_cpos),
+                       "Device %s, asking for sparse allocation: inode %llu, "
+                       "cpos %u, clusters %u\n",
+                       osb->dev_str,
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                       rec->e_cpos,
+                       OCFS2_I(inode)->ip_clusters);
+
+       return 0;
+}
+
+static int ocfs2_dinode_sanity_check(struct inode *inode,
+                                    struct ocfs2_extent_tree *et)
+{
+       int ret = 0;
+       struct ocfs2_dinode *di;
+
+       BUG_ON(et->et_ops != &ocfs2_dinode_et_ops);
+
+       di = et->et_object;
+       if (!OCFS2_IS_VALID_DINODE(di)) {
+               ret = -EIO;
+               ocfs2_error(inode->i_sb,
+                       "Inode %llu has invalid path root",
+                       (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       }
+
+       return ret;
+}
+
+static void ocfs2_dinode_fill_root_el(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_dinode *di = et->et_object;
+
+       et->et_root_el = &di->id2.i_list;
+}
+
+
+static void ocfs2_xattr_value_fill_root_el(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_xattr_value_root *xv = et->et_object;
+
+       et->et_root_el = &xv->xr_list;
+}
+
+static void ocfs2_xattr_value_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                             u64 blkno)
+{
+       struct ocfs2_xattr_value_root *xv =
+               (struct ocfs2_xattr_value_root *)et->et_object;
+
+       xv->xr_last_eb_blk = cpu_to_le64(blkno);
+}
+
+static u64 ocfs2_xattr_value_get_last_eb_blk(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_xattr_value_root *xv =
+               (struct ocfs2_xattr_value_root *) et->et_object;
+
+       return le64_to_cpu(xv->xr_last_eb_blk);
+}
+
+static void ocfs2_xattr_value_update_clusters(struct inode *inode,
+                                             struct ocfs2_extent_tree *et,
+                                             u32 clusters)
+{
+       struct ocfs2_xattr_value_root *xv =
+               (struct ocfs2_xattr_value_root *)et->et_object;
+
+       le32_add_cpu(&xv->xr_clusters, clusters);
+}
+
+static struct ocfs2_extent_tree_operations ocfs2_xattr_value_et_ops = {
+       .eo_set_last_eb_blk     = ocfs2_xattr_value_set_last_eb_blk,
+       .eo_get_last_eb_blk     = ocfs2_xattr_value_get_last_eb_blk,
+       .eo_update_clusters     = ocfs2_xattr_value_update_clusters,
+       .eo_fill_root_el        = ocfs2_xattr_value_fill_root_el,
+};
+
+static void ocfs2_xattr_tree_fill_root_el(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_xattr_block *xb = et->et_object;
+
+       et->et_root_el = &xb->xb_attrs.xb_root.xt_list;
+}
+
+static void ocfs2_xattr_tree_fill_max_leaf_clusters(struct inode *inode,
+                                                   struct ocfs2_extent_tree *et)
+{
+       et->et_max_leaf_clusters =
+               ocfs2_clusters_for_bytes(inode->i_sb,
+                                        OCFS2_MAX_XATTR_TREE_LEAF_SIZE);
+}
+
+static void ocfs2_xattr_tree_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                            u64 blkno)
+{
+       struct ocfs2_xattr_block *xb = et->et_object;
+       struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
+
+       xt->xt_last_eb_blk = cpu_to_le64(blkno);
+}
+
+static u64 ocfs2_xattr_tree_get_last_eb_blk(struct ocfs2_extent_tree *et)
+{
+       struct ocfs2_xattr_block *xb = et->et_object;
+       struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
+
+       return le64_to_cpu(xt->xt_last_eb_blk);
+}
+
+static void ocfs2_xattr_tree_update_clusters(struct inode *inode,
+                                            struct ocfs2_extent_tree *et,
+                                            u32 clusters)
+{
+       struct ocfs2_xattr_block *xb = et->et_object;
+
+       le32_add_cpu(&xb->xb_attrs.xb_root.xt_clusters, clusters);
+}
+
+static struct ocfs2_extent_tree_operations ocfs2_xattr_tree_et_ops = {
+       .eo_set_last_eb_blk     = ocfs2_xattr_tree_set_last_eb_blk,
+       .eo_get_last_eb_blk     = ocfs2_xattr_tree_get_last_eb_blk,
+       .eo_update_clusters     = ocfs2_xattr_tree_update_clusters,
+       .eo_fill_root_el        = ocfs2_xattr_tree_fill_root_el,
+       .eo_fill_max_leaf_clusters = ocfs2_xattr_tree_fill_max_leaf_clusters,
+};
+
+static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
+                                    struct inode *inode,
+                                    struct buffer_head *bh,
+                                    void *obj,
+                                    struct ocfs2_extent_tree_operations *ops)
+{
+       et->et_ops = ops;
+       et->et_root_bh = bh;
+       if (!obj)
+               obj = (void *)bh->b_data;
+       et->et_object = obj;
+
+       et->et_ops->eo_fill_root_el(et);
+       if (!et->et_ops->eo_fill_max_leaf_clusters)
+               et->et_max_leaf_clusters = 0;
+       else
+               et->et_ops->eo_fill_max_leaf_clusters(inode, et);
+}
+
+void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
+                                  struct inode *inode,
+                                  struct buffer_head *bh)
+{
+       __ocfs2_init_extent_tree(et, inode, bh, NULL, &ocfs2_dinode_et_ops);
+}
+
+void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
+                                      struct inode *inode,
+                                      struct buffer_head *bh)
+{
+       __ocfs2_init_extent_tree(et, inode, bh, NULL,
+                                &ocfs2_xattr_tree_et_ops);
+}
+
+void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
+                                       struct inode *inode,
+                                       struct buffer_head *bh,
+                                       struct ocfs2_xattr_value_root *xv)
+{
+       __ocfs2_init_extent_tree(et, inode, bh, xv,
+                                &ocfs2_xattr_value_et_ops);
+}
+
+static inline void ocfs2_et_set_last_eb_blk(struct ocfs2_extent_tree *et,
+                                           u64 new_last_eb_blk)
+{
+       et->et_ops->eo_set_last_eb_blk(et, new_last_eb_blk);
+}
+
+static inline u64 ocfs2_et_get_last_eb_blk(struct ocfs2_extent_tree *et)
+{
+       return et->et_ops->eo_get_last_eb_blk(et);
+}
+
+static inline void ocfs2_et_update_clusters(struct inode *inode,
+                                           struct ocfs2_extent_tree *et,
+                                           u32 clusters)
+{
+       et->et_ops->eo_update_clusters(inode, et, clusters);
+}
+
+static inline int ocfs2_et_insert_check(struct inode *inode,
+                                       struct ocfs2_extent_tree *et,
+                                       struct ocfs2_extent_rec *rec)
+{
+       int ret = 0;
+
+       if (et->et_ops->eo_insert_check)
+               ret = et->et_ops->eo_insert_check(inode, et, rec);
+       return ret;
+}
+
+static inline int ocfs2_et_sanity_check(struct inode *inode,
+                                       struct ocfs2_extent_tree *et)
+{
+       int ret = 0;
+
+       if (et->et_ops->eo_sanity_check)
+               ret = et->et_ops->eo_sanity_check(inode, et);
+       return ret;
+}
+
 static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
 static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
                                         struct ocfs2_extent_block *eb);
@@ -204,17 +538,6 @@ static struct ocfs2_path *ocfs2_new_path(struct buffer_head *root_bh,
        return path;
 }
 
-/*
- * Allocate and initialize a new path based on a disk inode tree.
- */
-static struct ocfs2_path *ocfs2_new_inode_path(struct buffer_head *di_bh)
-{
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
-       struct ocfs2_extent_list *el = &di->id2.i_list;
-
-       return ocfs2_new_path(di_bh, el);
-}
-
 /*
  * Convenience function to journal all components in a path.
  */
@@ -368,39 +691,35 @@ struct ocfs2_merge_ctxt {
  */
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
                           struct inode *inode,
-                          struct ocfs2_dinode *fe)
+                          struct ocfs2_extent_tree *et)
 {
        int retval;
-       struct ocfs2_extent_list *el;
+       struct ocfs2_extent_list *el = NULL;
        struct ocfs2_extent_block *eb;
        struct buffer_head *eb_bh = NULL;
+       u64 last_eb_blk = 0;
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_DINODE(fe)) {
-               OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
-               retval = -EIO;
-               goto bail;
-       }
+       el = et->et_root_el;
+       last_eb_blk = ocfs2_et_get_last_eb_blk(et);
 
-       if (fe->i_last_eb_blk) {
-               retval = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
-                                         &eb_bh, OCFS2_BH_CACHED, inode);
+       if (last_eb_blk) {
+               retval = ocfs2_read_block(inode, last_eb_blk,
+                                         &eb_bh);
                if (retval < 0) {
                        mlog_errno(retval);
                        goto bail;
                }
                eb = (struct ocfs2_extent_block *) eb_bh->b_data;
                el = &eb->h_list;
-       } else
-               el = &fe->id2.i_list;
+       }
 
        BUG_ON(el->l_tree_depth != 0);
 
        retval = le16_to_cpu(el->l_count) - le16_to_cpu(el->l_next_free_rec);
 bail:
-       if (eb_bh)
-               brelse(eb_bh);
+       brelse(eb_bh);
 
        mlog_exit(retval);
        return retval;
@@ -486,8 +805,7 @@ static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
 bail:
        if (status < 0) {
                for(i = 0; i < wanted; i++) {
-                       if (bhs[i])
-                               brelse(bhs[i]);
+                       brelse(bhs[i]);
                        bhs[i] = NULL;
                }
        }
@@ -531,7 +849,7 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list  *el)
 static int ocfs2_add_branch(struct ocfs2_super *osb,
                            handle_t *handle,
                            struct inode *inode,
-                           struct buffer_head *fe_bh,
+                           struct ocfs2_extent_tree *et,
                            struct buffer_head *eb_bh,
                            struct buffer_head **last_eb_bh,
                            struct ocfs2_alloc_context *meta_ac)
@@ -540,7 +858,6 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
        u64 next_blkno, new_last_eb_blk;
        struct buffer_head *bh;
        struct buffer_head **new_eb_bhs = NULL;
-       struct ocfs2_dinode *fe;
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list  *eb_el;
        struct ocfs2_extent_list  *el;
@@ -550,13 +867,11 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
 
        BUG_ON(!last_eb_bh || !*last_eb_bh);
 
-       fe = (struct ocfs2_dinode *) fe_bh->b_data;
-
        if (eb_bh) {
                eb = (struct ocfs2_extent_block *) eb_bh->b_data;
                el = &eb->h_list;
        } else
-               el = &fe->id2.i_list;
+               el = et->et_root_el;
 
        /* we never add a branch to a leaf. */
        BUG_ON(!el->l_tree_depth);
@@ -646,7 +961,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
                mlog_errno(status);
                goto bail;
        }
-       status = ocfs2_journal_access(handle, inode, fe_bh,
+       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -662,7 +977,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
        }
 
        /* Link the new branch into the rest of the tree (el will
-        * either be on the fe, or the extent block passed in. */
+        * either be on the root_bh, or the extent block passed in. */
        i = le16_to_cpu(el->l_next_free_rec);
        el->l_recs[i].e_blkno = cpu_to_le64(next_blkno);
        el->l_recs[i].e_cpos = cpu_to_le32(new_cpos);
@@ -671,7 +986,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
 
        /* fe needs a new last extent block pointer, as does the
         * next_leaf on the previously last-extent-block. */
-       fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
+       ocfs2_et_set_last_eb_blk(et, new_last_eb_blk);
 
        eb = (struct ocfs2_extent_block *) (*last_eb_bh)->b_data;
        eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
@@ -679,7 +994,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
        status = ocfs2_journal_dirty(handle, *last_eb_bh);
        if (status < 0)
                mlog_errno(status);
-       status = ocfs2_journal_dirty(handle, fe_bh);
+       status = ocfs2_journal_dirty(handle, et->et_root_bh);
        if (status < 0)
                mlog_errno(status);
        if (eb_bh) {
@@ -700,8 +1015,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
 bail:
        if (new_eb_bhs) {
                for (i = 0; i < new_blocks; i++)
-                       if (new_eb_bhs[i])
-                               brelse(new_eb_bhs[i]);
+                       brelse(new_eb_bhs[i]);
                kfree(new_eb_bhs);
        }
 
@@ -717,16 +1031,15 @@ bail:
 static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                                  handle_t *handle,
                                  struct inode *inode,
-                                 struct buffer_head *fe_bh,
+                                 struct ocfs2_extent_tree *et,
                                  struct ocfs2_alloc_context *meta_ac,
                                  struct buffer_head **ret_new_eb_bh)
 {
        int status, i;
        u32 new_clusters;
        struct buffer_head *new_eb_bh = NULL;
-       struct ocfs2_dinode *fe;
        struct ocfs2_extent_block *eb;
-       struct ocfs2_extent_list  *fe_el;
+       struct ocfs2_extent_list  *root_el;
        struct ocfs2_extent_list  *eb_el;
 
        mlog_entry_void();
@@ -746,8 +1059,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
        }
 
        eb_el = &eb->h_list;
-       fe = (struct ocfs2_dinode *) fe_bh->b_data;
-       fe_el = &fe->id2.i_list;
+       root_el = et->et_root_el;
 
        status = ocfs2_journal_access(handle, inode, new_eb_bh,
                                      OCFS2_JOURNAL_ACCESS_CREATE);
@@ -756,11 +1068,11 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                goto bail;
        }
 
-       /* copy the fe data into the new extent block */
-       eb_el->l_tree_depth = fe_el->l_tree_depth;
-       eb_el->l_next_free_rec = fe_el->l_next_free_rec;
-       for(i = 0; i < le16_to_cpu(fe_el->l_next_free_rec); i++)
-               eb_el->l_recs[i] = fe_el->l_recs[i];
+       /* copy the root extent list data into the new extent block */
+       eb_el->l_tree_depth = root_el->l_tree_depth;
+       eb_el->l_next_free_rec = root_el->l_next_free_rec;
+       for (i = 0; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+               eb_el->l_recs[i] = root_el->l_recs[i];
 
        status = ocfs2_journal_dirty(handle, new_eb_bh);
        if (status < 0) {
@@ -768,7 +1080,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, inode, fe_bh,
+       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
                                      OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
@@ -777,21 +1089,21 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
 
        new_clusters = ocfs2_sum_rightmost_rec(eb_el);
 
-       /* update fe now */
-       le16_add_cpu(&fe_el->l_tree_depth, 1);
-       fe_el->l_recs[0].e_cpos = 0;
-       fe_el->l_recs[0].e_blkno = eb->h_blkno;
-       fe_el->l_recs[0].e_int_clusters = cpu_to_le32(new_clusters);
-       for(i = 1; i < le16_to_cpu(fe_el->l_next_free_rec); i++)
-               memset(&fe_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
-       fe_el->l_next_free_rec = cpu_to_le16(1);
+       /* update root_bh now */
+       le16_add_cpu(&root_el->l_tree_depth, 1);
+       root_el->l_recs[0].e_cpos = 0;
+       root_el->l_recs[0].e_blkno = eb->h_blkno;
+       root_el->l_recs[0].e_int_clusters = cpu_to_le32(new_clusters);
+       for (i = 1; i < le16_to_cpu(root_el->l_next_free_rec); i++)
+               memset(&root_el->l_recs[i], 0, sizeof(struct ocfs2_extent_rec));
+       root_el->l_next_free_rec = cpu_to_le16(1);
 
        /* If this is our 1st tree depth shift, then last_eb_blk
         * becomes the allocated extent block */
-       if (fe_el->l_tree_depth == cpu_to_le16(1))
-               fe->i_last_eb_blk = eb->h_blkno;
+       if (root_el->l_tree_depth == cpu_to_le16(1))
+               ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
 
-       status = ocfs2_journal_dirty(handle, fe_bh);
+       status = ocfs2_journal_dirty(handle, et->et_root_bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -801,8 +1113,7 @@ static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
        new_eb_bh = NULL;
        status = 0;
 bail:
-       if (new_eb_bh)
-               brelse(new_eb_bh);
+       brelse(new_eb_bh);
 
        mlog_exit(status);
        return status;
@@ -817,22 +1128,21 @@ bail:
  * 1) a lowest extent block is found, then we pass it back in
  *    *lowest_eb_bh and return '0'
  *
- * 2) the search fails to find anything, but the dinode has room. We
+ * 2) the search fails to find anything, but the root_el has room. We
  *    pass NULL back in *lowest_eb_bh, but still return '0'
  *
- * 3) the search fails to find anything AND the dinode is full, in
+ * 3) the search fails to find anything AND the root_el is full, in
  *    which case we return > 0
  *
  * return status < 0 indicates an error.
  */
 static int ocfs2_find_branch_target(struct ocfs2_super *osb,
                                    struct inode *inode,
-                                   struct buffer_head *fe_bh,
+                                   struct ocfs2_extent_tree *et,
                                    struct buffer_head **target_bh)
 {
        int status = 0, i;
        u64 blkno;
-       struct ocfs2_dinode *fe;
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list  *el;
        struct buffer_head *bh = NULL;
@@ -842,8 +1152,7 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
 
        *target_bh = NULL;
 
-       fe = (struct ocfs2_dinode *) fe_bh->b_data;
-       el = &fe->id2.i_list;
+       el = et->et_root_el;
 
        while(le16_to_cpu(el->l_tree_depth) > 1) {
                if (le16_to_cpu(el->l_next_free_rec) == 0) {
@@ -864,13 +1173,10 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
                        goto bail;
                }
 
-               if (bh) {
-                       brelse(bh);
-                       bh = NULL;
-               }
+               brelse(bh);
+               bh = NULL;
 
-               status = ocfs2_read_block(osb, blkno, &bh, OCFS2_BH_CACHED,
-                                         inode);
+               status = ocfs2_read_block(inode, blkno, &bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -886,8 +1192,7 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
 
                if (le16_to_cpu(el->l_next_free_rec) <
                    le16_to_cpu(el->l_count)) {
-                       if (lowest_bh)
-                               brelse(lowest_bh);
+                       brelse(lowest_bh);
                        lowest_bh = bh;
                        get_bh(lowest_bh);
                }
@@ -895,14 +1200,13 @@ static int ocfs2_find_branch_target(struct ocfs2_super *osb,
 
        /* If we didn't find one and the fe doesn't have any room,
         * then return '1' */
-       if (!lowest_bh
-           && (fe->id2.i_list.l_next_free_rec == fe->id2.i_list.l_count))
+       el = et->et_root_el;
+       if (!lowest_bh && (el->l_next_free_rec == el->l_count))
                status = 1;
 
        *target_bh = lowest_bh;
 bail:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
@@ -919,19 +1223,19 @@ bail:
  * *last_eb_bh will be updated by ocfs2_add_branch().
  */
 static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
-                          struct buffer_head *di_bh, int *final_depth,
+                          struct ocfs2_extent_tree *et, int *final_depth,
                           struct buffer_head **last_eb_bh,
                           struct ocfs2_alloc_context *meta_ac)
 {
        int ret, shift;
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
-       int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
+       struct ocfs2_extent_list *el = et->et_root_el;
+       int depth = le16_to_cpu(el->l_tree_depth);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct buffer_head *bh = NULL;
 
        BUG_ON(meta_ac == NULL);
 
-       shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
+       shift = ocfs2_find_branch_target(osb, inode, et, &bh);
        if (shift < 0) {
                ret = shift;
                mlog_errno(ret);
@@ -948,7 +1252,7 @@ static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
                /* ocfs2_shift_tree_depth will return us a buffer with
                 * the new extent block (so we can pass that to
                 * ocfs2_add_branch). */
-               ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
+               ret = ocfs2_shift_tree_depth(osb, handle, inode, et,
                                             meta_ac, &bh);
                if (ret < 0) {
                        mlog_errno(ret);
@@ -975,7 +1279,7 @@ static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
        /* call ocfs2_add_branch to add the final part of the tree with
         * the new data. */
        mlog(0, "add branch. bh = %p\n", bh);
-       ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
+       ret = ocfs2_add_branch(osb, handle, inode, et, bh, last_eb_bh,
                               meta_ac);
        if (ret < 0) {
                mlog_errno(ret);
@@ -1236,8 +1540,7 @@ static int __ocfs2_find_path(struct inode *inode,
 
                brelse(bh);
                bh = NULL;
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,
-                                      &bh, OCFS2_BH_CACHED, inode);
+               ret = ocfs2_read_block(inode, blkno, &bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -2058,11 +2361,11 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                                     struct ocfs2_path *right_path,
                                     int subtree_index,
                                     struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                    int *deleted)
+                                    int *deleted,
+                                    struct ocfs2_extent_tree *et)
 {
        int ret, i, del_right_subtree = 0, right_has_empty = 0;
-       struct buffer_head *root_bh, *di_bh = path_root_bh(right_path);
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+       struct buffer_head *root_bh, *et_root_bh = path_root_bh(right_path);
        struct ocfs2_extent_list *right_leaf_el, *left_leaf_el;
        struct ocfs2_extent_block *eb;
 
@@ -2114,7 +2417,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                 * We have to update i_last_eb_blk during the meta
                 * data delete.
                 */
-               ret = ocfs2_journal_access(handle, inode, di_bh,
+               ret = ocfs2_journal_access(handle, inode, et_root_bh,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
@@ -2189,7 +2492,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                ocfs2_update_edge_lengths(inode, handle, left_path);
 
                eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
-               di->i_last_eb_blk = eb->h_blkno;
+               ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
 
                /*
                 * Removal of the extent in the left leaf was skipped
@@ -2199,7 +2502,7 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
                if (right_has_empty)
                        ocfs2_remove_empty_extent(left_leaf_el);
 
-               ret = ocfs2_journal_dirty(handle, di_bh);
+               ret = ocfs2_journal_dirty(handle, et_root_bh);
                if (ret)
                        mlog_errno(ret);
 
@@ -2322,7 +2625,8 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
                                    handle_t *handle, int orig_credits,
                                    struct ocfs2_path *path,
                                    struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                   struct ocfs2_path **empty_extent_path)
+                                   struct ocfs2_path **empty_extent_path,
+                                   struct ocfs2_extent_tree *et)
 {
        int ret, subtree_root, deleted;
        u32 right_cpos;
@@ -2395,7 +2699,7 @@ static int __ocfs2_rotate_tree_left(struct inode *inode,
 
                ret = ocfs2_rotate_subtree_left(inode, handle, left_path,
                                                right_path, subtree_root,
-                                               dealloc, &deleted);
+                                               dealloc, &deleted, et);
                if (ret == -EAGAIN) {
                        /*
                         * The rotation has to temporarily stop due to
@@ -2438,29 +2742,20 @@ out:
 }
 
 static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
-                                      struct ocfs2_path *path,
-                                      struct ocfs2_cached_dealloc_ctxt *dealloc)
+                               struct ocfs2_path *path,
+                               struct ocfs2_cached_dealloc_ctxt *dealloc,
+                               struct ocfs2_extent_tree *et)
 {
        int ret, subtree_index;
        u32 cpos;
        struct ocfs2_path *left_path = NULL;
-       struct ocfs2_dinode *di;
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
 
-       /*
-        * XXX: This code assumes that the root is an inode, which is
-        * true for now but may change as tree code gets generic.
-        */
-       di = (struct ocfs2_dinode *)path_root_bh(path)->b_data;
-       if (!OCFS2_IS_VALID_DINODE(di)) {
-               ret = -EIO;
-               ocfs2_error(inode->i_sb,
-                           "Inode %llu has invalid path root",
-                           (unsigned long long)OCFS2_I(inode)->ip_blkno);
-               goto out;
-       }
 
+       ret = ocfs2_et_sanity_check(inode, et);
+       if (ret)
+               goto out;
        /*
         * There's two ways we handle this depending on
         * whether path is the only existing one.
@@ -2517,7 +2812,7 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                ocfs2_update_edge_lengths(inode, handle, left_path);
 
                eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
-               di->i_last_eb_blk = eb->h_blkno;
+               ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
        } else {
                /*
                 * 'path' is also the leftmost path which
@@ -2528,12 +2823,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
                 */
                ocfs2_unlink_path(inode, handle, dealloc, path, 1);
 
-               el = &di->id2.i_list;
+               el = et->et_root_el;
                el->l_tree_depth = 0;
                el->l_next_free_rec = 0;
                memset(&el->l_recs[0], 0, sizeof(struct ocfs2_extent_rec));
 
-               di->i_last_eb_blk = 0;
+               ocfs2_et_set_last_eb_blk(et, 0);
        }
 
        ocfs2_journal_dirty(handle, path_root_bh(path));
@@ -2561,7 +2856,8 @@ out:
  */
 static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
                                  struct ocfs2_path *path,
-                                 struct ocfs2_cached_dealloc_ctxt *dealloc)
+                                 struct ocfs2_cached_dealloc_ctxt *dealloc,
+                                 struct ocfs2_extent_tree *et)
 {
        int ret, orig_credits = handle->h_buffer_credits;
        struct ocfs2_path *tmp_path = NULL, *restart_path = NULL;
@@ -2575,7 +2871,7 @@ static int ocfs2_rotate_tree_left(struct inode *inode, handle_t *handle,
        if (path->p_tree_depth == 0) {
 rightmost_no_delete:
                /*
-                * In-inode extents. This is trivially handled, so do
+                * Inline extents. This is trivially handled, so do
                 * it up front.
                 */
                ret = ocfs2_rotate_rightmost_leaf_left(inode, handle,
@@ -2629,7 +2925,7 @@ rightmost_no_delete:
                 */
 
                ret = ocfs2_remove_rightmost_path(inode, handle, path,
-                                                 dealloc);
+                                                 dealloc, et);
                if (ret)
                        mlog_errno(ret);
                goto out;
@@ -2641,7 +2937,7 @@ rightmost_no_delete:
         */
 try_rotate:
        ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits, path,
-                                      dealloc, &restart_path);
+                                      dealloc, &restart_path, et);
        if (ret && ret != -EAGAIN) {
                mlog_errno(ret);
                goto out;
@@ -2653,7 +2949,7 @@ try_rotate:
 
                ret = __ocfs2_rotate_tree_left(inode, handle, orig_credits,
                                               tmp_path, dealloc,
-                                              &restart_path);
+                                              &restart_path, et);
                if (ret && ret != -EAGAIN) {
                        mlog_errno(ret);
                        goto out;
@@ -2939,6 +3235,7 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                                handle_t *handle,
                                struct ocfs2_extent_rec *split_rec,
                                struct ocfs2_cached_dealloc_ctxt *dealloc,
+                               struct ocfs2_extent_tree *et,
                                int index)
 {
        int ret, i, subtree_index = 0, has_empty_extent = 0;
@@ -3059,7 +3356,8 @@ static int ocfs2_merge_rec_left(struct inode *inode,
                    le16_to_cpu(el->l_next_free_rec) == 1) {
 
                        ret = ocfs2_remove_rightmost_path(inode, handle,
-                                                         right_path, dealloc);
+                                                         right_path,
+                                                         dealloc, et);
                        if (ret) {
                                mlog_errno(ret);
                                goto out;
@@ -3086,7 +3384,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                                     int split_index,
                                     struct ocfs2_extent_rec *split_rec,
                                     struct ocfs2_cached_dealloc_ctxt *dealloc,
-                                    struct ocfs2_merge_ctxt *ctxt)
+                                    struct ocfs2_merge_ctxt *ctxt,
+                                    struct ocfs2_extent_tree *et)
 
 {
        int ret = 0;
@@ -3104,7 +3403,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 * illegal.
                 */
                ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                            dealloc);
+                                            dealloc, et);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3147,7 +3446,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0]));
 
                /* The merge left us with an empty extent, remove it. */
-               ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+               ret = ocfs2_rotate_tree_left(inode, handle, path,
+                                            dealloc, et);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -3161,7 +3461,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                 */
                ret = ocfs2_merge_rec_left(inode, path,
                                           handle, rec,
-                                          dealloc,
+                                          dealloc, et,
                                           split_index);
 
                if (ret) {
@@ -3170,7 +3470,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                }
 
                ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                            dealloc);
+                                            dealloc, et);
                /*
                 * Error from this last rotate is not critical, so
                 * print but don't bubble it up.
@@ -3190,7 +3490,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                        ret = ocfs2_merge_rec_left(inode,
                                                   path,
                                                   handle, split_rec,
-                                                  dealloc,
+                                                  dealloc, et,
                                                   split_index);
                        if (ret) {
                                mlog_errno(ret);
@@ -3213,7 +3513,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode,
                         * our leaf. Try to rotate it away.
                         */
                        ret = ocfs2_rotate_tree_left(inode, handle, path,
-                                                    dealloc);
+                                                    dealloc, et);
                        if (ret)
                                mlog_errno(ret);
                        ret = 0;
@@ -3347,16 +3647,6 @@ rotate:
        ocfs2_rotate_leaf(el, insert_rec);
 }
 
-static inline void ocfs2_update_dinode_clusters(struct inode *inode,
-                                               struct ocfs2_dinode *di,
-                                               u32 clusters)
-{
-       le32_add_cpu(&di->i_clusters, clusters);
-       spin_lock(&OCFS2_I(inode)->ip_lock);
-       OCFS2_I(inode)->ip_clusters = le32_to_cpu(di->i_clusters);
-       spin_unlock(&OCFS2_I(inode)->ip_lock);
-}
-
 static void ocfs2_adjust_rightmost_records(struct inode *inode,
                                           handle_t *handle,
                                           struct ocfs2_path *path,
@@ -3558,8 +3848,8 @@ static void ocfs2_split_record(struct inode *inode,
 }
 
 /*
- * This function only does inserts on an allocation b-tree. For dinode
- * lists, ocfs2_insert_at_leaf() is called directly.
+ * This function only does inserts on an allocation b-tree. For tree
+ * depth = 0, ocfs2_insert_at_leaf() is called directly.
  *
  * right_path is the path we want to do the actual insert
  * in. left_path should only be passed in if we need to update that
@@ -3656,7 +3946,7 @@ out:
 
 static int ocfs2_do_insert_extent(struct inode *inode,
                                  handle_t *handle,
-                                 struct buffer_head *di_bh,
+                                 struct ocfs2_extent_tree *et,
                                  struct ocfs2_extent_rec *insert_rec,
                                  struct ocfs2_insert_type *type)
 {
@@ -3664,13 +3954,11 @@ static int ocfs2_do_insert_extent(struct inode *inode,
        u32 cpos;
        struct ocfs2_path *right_path = NULL;
        struct ocfs2_path *left_path = NULL;
-       struct ocfs2_dinode *di;
        struct ocfs2_extent_list *el;
 
-       di = (struct ocfs2_dinode *) di_bh->b_data;
-       el = &di->id2.i_list;
+       el = et->et_root_el;
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
+       ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
                                   OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
@@ -3682,7 +3970,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                goto out_update_clusters;
        }
 
-       right_path = ocfs2_new_inode_path(di_bh);
+       right_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
        if (!right_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -3732,7 +4020,7 @@ static int ocfs2_do_insert_extent(struct inode *inode,
                 * ocfs2_rotate_tree_right() might have extended the
                 * transaction without re-journaling our tree root.
                 */
-               ret = ocfs2_journal_access(handle, inode, di_bh,
+               ret = ocfs2_journal_access(handle, inode, et->et_root_bh,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
                if (ret) {
                        mlog_errno(ret);
@@ -3757,10 +4045,10 @@ static int ocfs2_do_insert_extent(struct inode *inode,
 
 out_update_clusters:
        if (type->ins_split == SPLIT_NONE)
-               ocfs2_update_dinode_clusters(inode, di,
-                                            le16_to_cpu(insert_rec->e_leaf_clusters));
+               ocfs2_et_update_clusters(inode, et,
+                                        le16_to_cpu(insert_rec->e_leaf_clusters));
 
-       ret = ocfs2_journal_dirty(handle, di_bh);
+       ret = ocfs2_journal_dirty(handle, et->et_root_bh);
        if (ret)
                mlog_errno(ret);
 
@@ -3890,7 +4178,8 @@ out:
 static void ocfs2_figure_contig_type(struct inode *inode,
                                     struct ocfs2_insert_type *insert,
                                     struct ocfs2_extent_list *el,
-                                    struct ocfs2_extent_rec *insert_rec)
+                                    struct ocfs2_extent_rec *insert_rec,
+                                    struct ocfs2_extent_tree *et)
 {
        int i;
        enum ocfs2_contig_type contig_type = CONTIG_NONE;
@@ -3906,6 +4195,21 @@ static void ocfs2_figure_contig_type(struct inode *inode,
                }
        }
        insert->ins_contig = contig_type;
+
+       if (insert->ins_contig != CONTIG_NONE) {
+               struct ocfs2_extent_rec *rec =
+                               &el->l_recs[insert->ins_contig_index];
+               unsigned int len = le16_to_cpu(rec->e_leaf_clusters) +
+                                  le16_to_cpu(insert_rec->e_leaf_clusters);
+
+               /*
+                * Caller might want us to limit the size of extents, don't
+                * calculate contiguousness if we might exceed that limit.
+                */
+               if (et->et_max_leaf_clusters &&
+                   (len > et->et_max_leaf_clusters))
+                       insert->ins_contig = CONTIG_NONE;
+       }
 }
 
 /*
@@ -3914,8 +4218,8 @@ static void ocfs2_figure_contig_type(struct inode *inode,
  * ocfs2_figure_appending_type() will figure out whether we'll have to
  * insert at the tail of the rightmost leaf.
  *
- * This should also work against the dinode list for tree's with 0
- * depth. If we consider the dinode list to be the rightmost leaf node
+ * This should also work against the root extent list for tree's with 0
+ * depth. If we consider the root extent list to be the rightmost leaf node
  * then the logic here makes sense.
  */
 static void ocfs2_figure_appending_type(struct ocfs2_insert_type *insert,
@@ -3966,14 +4270,13 @@ set_tail_append:
  * structure.
  */
 static int ocfs2_figure_insert_type(struct inode *inode,
-                                   struct buffer_head *di_bh,
+                                   struct ocfs2_extent_tree *et,
                                    struct buffer_head **last_eb_bh,
                                    struct ocfs2_extent_rec *insert_rec,
                                    int *free_records,
                                    struct ocfs2_insert_type *insert)
 {
        int ret;
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
        struct ocfs2_path *path = NULL;
@@ -3981,7 +4284,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
 
        insert->ins_split = SPLIT_NONE;
 
-       el = &di->id2.i_list;
+       el = et->et_root_el;
        insert->ins_tree_depth = le16_to_cpu(el->l_tree_depth);
 
        if (el->l_tree_depth) {
@@ -3991,9 +4294,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                 * ocfs2_figure_insert_type() and ocfs2_add_branch()
                 * may want it later.
                 */
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                      le64_to_cpu(di->i_last_eb_blk), &bh,
-                                      OCFS2_BH_CACHED, inode);
+               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et), &bh);
                if (ret) {
                        mlog_exit(ret);
                        goto out;
@@ -4014,12 +4315,12 @@ static int ocfs2_figure_insert_type(struct inode *inode,
                le16_to_cpu(el->l_next_free_rec);
 
        if (!insert->ins_tree_depth) {
-               ocfs2_figure_contig_type(inode, insert, el, insert_rec);
+               ocfs2_figure_contig_type(inode, insert, el, insert_rec, et);
                ocfs2_figure_appending_type(insert, el, insert_rec);
                return 0;
        }
 
-       path = ocfs2_new_inode_path(di_bh);
+       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4048,7 +4349,7 @@ static int ocfs2_figure_insert_type(struct inode *inode,
          *     into two types of appends: simple record append, or a
          *     rotate inside the tail leaf.
         */
-       ocfs2_figure_contig_type(inode, insert, el, insert_rec);
+       ocfs2_figure_contig_type(inode, insert, el, insert_rec, et);
 
        /*
         * The insert code isn't quite ready to deal with all cases of
@@ -4069,7 +4370,8 @@ static int ocfs2_figure_insert_type(struct inode *inode,
         * the case that we're doing a tail append, so maybe we can
         * take advantage of that information somehow.
         */
-       if (le64_to_cpu(di->i_last_eb_blk) == path_leaf_bh(path)->b_blocknr) {
+       if (ocfs2_et_get_last_eb_blk(et) ==
+           path_leaf_bh(path)->b_blocknr) {
                /*
                 * Ok, ocfs2_find_path() returned us the rightmost
                 * tree path. This might be an appending insert. There are
@@ -4099,7 +4401,7 @@ out:
 int ocfs2_insert_extent(struct ocfs2_super *osb,
                        handle_t *handle,
                        struct inode *inode,
-                       struct buffer_head *fe_bh,
+                       struct ocfs2_extent_tree *et,
                        u32 cpos,
                        u64 start_blk,
                        u32 new_clusters,
@@ -4112,26 +4414,21 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
        struct ocfs2_insert_type insert = {0, };
        struct ocfs2_extent_rec rec;
 
-       BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL);
-
        mlog(0, "add %u clusters at position %u to inode %llu\n",
             new_clusters, cpos, (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) &&
-                       (OCFS2_I(inode)->ip_clusters != cpos),
-                       "Device %s, asking for sparse allocation: inode %llu, "
-                       "cpos %u, clusters %u\n",
-                       osb->dev_str,
-                       (unsigned long long)OCFS2_I(inode)->ip_blkno, cpos,
-                       OCFS2_I(inode)->ip_clusters);
-
        memset(&rec, 0, sizeof(rec));
        rec.e_cpos = cpu_to_le32(cpos);
        rec.e_blkno = cpu_to_le64(start_blk);
        rec.e_leaf_clusters = cpu_to_le16(new_clusters);
        rec.e_flags = flags;
+       status = ocfs2_et_insert_check(inode, et, &rec);
+       if (status) {
+               mlog_errno(status);
+               goto bail;
+       }
 
-       status = ocfs2_figure_insert_type(inode, fe_bh, &last_eb_bh, &rec,
+       status = ocfs2_figure_insert_type(inode, et, &last_eb_bh, &rec,
                                          &free_records, &insert);
        if (status < 0) {
                mlog_errno(status);
@@ -4145,7 +4442,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
             free_records, insert.ins_tree_depth);
 
        if (insert.ins_contig == CONTIG_NONE && free_records == 0) {
-               status = ocfs2_grow_tree(inode, handle, fe_bh,
+               status = ocfs2_grow_tree(inode, handle, et,
                                         &insert.ins_tree_depth, &last_eb_bh,
                                         meta_ac);
                if (status) {
@@ -4155,17 +4452,124 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
        }
 
        /* Finally, we can add clusters. This might rotate the tree for us. */
-       status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
+       status = ocfs2_do_insert_extent(inode, handle, et, &rec, &insert);
        if (status < 0)
                mlog_errno(status);
-       else
+       else if (et->et_ops == &ocfs2_dinode_et_ops)
                ocfs2_extent_map_insert_rec(inode, &rec);
 
 bail:
-       if (last_eb_bh)
-               brelse(last_eb_bh);
+       brelse(last_eb_bh);
+
+       mlog_exit(status);
+       return status;
+}
+
+/*
+ * Allcate and add clusters into the extent b-tree.
+ * The new clusters(clusters_to_add) will be inserted at logical_offset.
+ * The extent b-tree's root is specified by et, and
+ * it is not limited to the file storage. Any extent tree can use this
+ * function if it implements the proper ocfs2_extent_tree.
+ */
+int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
+                               struct inode *inode,
+                               u32 *logical_offset,
+                               u32 clusters_to_add,
+                               int mark_unwritten,
+                               struct ocfs2_extent_tree *et,
+                               handle_t *handle,
+                               struct ocfs2_alloc_context *data_ac,
+                               struct ocfs2_alloc_context *meta_ac,
+                               enum ocfs2_alloc_restarted *reason_ret)
+{
+       int status = 0;
+       int free_extents;
+       enum ocfs2_alloc_restarted reason = RESTART_NONE;
+       u32 bit_off, num_bits;
+       u64 block;
+       u8 flags = 0;
+
+       BUG_ON(!clusters_to_add);
+
+       if (mark_unwritten)
+               flags = OCFS2_EXT_UNWRITTEN;
+
+       free_extents = ocfs2_num_free_extents(osb, inode, et);
+       if (free_extents < 0) {
+               status = free_extents;
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* there are two cases which could cause us to EAGAIN in the
+        * we-need-more-metadata case:
+        * 1) we haven't reserved *any*
+        * 2) we are so fragmented, we've needed to add metadata too
+        *    many times. */
+       if (!free_extents && !meta_ac) {
+               mlog(0, "we haven't reserved any metadata!\n");
+               status = -EAGAIN;
+               reason = RESTART_META;
+               goto leave;
+       } else if ((!free_extents)
+                  && (ocfs2_alloc_context_bits_left(meta_ac)
+                      < ocfs2_extend_meta_needed(et->et_root_el))) {
+               mlog(0, "filesystem is really fragmented...\n");
+               status = -EAGAIN;
+               reason = RESTART_META;
+               goto leave;
+       }
+
+       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+                                       clusters_to_add, &bit_off, &num_bits);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       BUG_ON(num_bits > clusters_to_add);
 
+       /* reserve our write early -- insert_extent may update the inode */
+       status = ocfs2_journal_access(handle, inode, et->et_root_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
+       mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
+            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+       status = ocfs2_insert_extent(osb, handle, inode, et,
+                                    *logical_offset, block,
+                                    num_bits, flags, meta_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       status = ocfs2_journal_dirty(handle, et->et_root_bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       clusters_to_add -= num_bits;
+       *logical_offset += num_bits;
+
+       if (clusters_to_add) {
+               mlog(0, "need to alloc once more, wanted = %u\n",
+                    clusters_to_add);
+               status = -EAGAIN;
+               reason = RESTART_TRANS;
+       }
+
+leave:
        mlog_exit(status);
+       if (reason_ret)
+               *reason_ret = reason;
        return status;
 }
 
@@ -4192,7 +4596,7 @@ static void ocfs2_make_right_split_rec(struct super_block *sb,
 static int ocfs2_split_and_insert(struct inode *inode,
                                  handle_t *handle,
                                  struct ocfs2_path *path,
-                                 struct buffer_head *di_bh,
+                                 struct ocfs2_extent_tree *et,
                                  struct buffer_head **last_eb_bh,
                                  int split_index,
                                  struct ocfs2_extent_rec *orig_split_rec,
@@ -4206,7 +4610,6 @@ static int ocfs2_split_and_insert(struct inode *inode,
        struct ocfs2_extent_rec split_rec = *orig_split_rec;
        struct ocfs2_insert_type insert;
        struct ocfs2_extent_block *eb;
-       struct ocfs2_dinode *di;
 
 leftright:
        /*
@@ -4215,8 +4618,7 @@ leftright:
         */
        rec = path_leaf_el(path)->l_recs[split_index];
 
-       di = (struct ocfs2_dinode *)di_bh->b_data;
-       rightmost_el = &di->id2.i_list;
+       rightmost_el = et->et_root_el;
 
        depth = le16_to_cpu(rightmost_el->l_tree_depth);
        if (depth) {
@@ -4227,8 +4629,8 @@ leftright:
 
        if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
            le16_to_cpu(rightmost_el->l_count)) {
-               ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, last_eb_bh,
-                                     meta_ac);
+               ret = ocfs2_grow_tree(inode, handle, et,
+                                     &depth, last_eb_bh, meta_ac);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -4265,8 +4667,7 @@ leftright:
                do_leftright = 1;
        }
 
-       ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec,
-                                    &insert);
+       ret = ocfs2_do_insert_extent(inode, handle, et, &split_rec, &insert);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4308,8 +4709,9 @@ out:
  * of the tree is required. All other cases will degrade into a less
  * optimal tree layout.
  *
- * last_eb_bh should be the rightmost leaf block for any inode with a
- * btree. Since a split may grow the tree or a merge might shrink it, the caller cannot trust the contents of that buffer after this call.
+ * last_eb_bh should be the rightmost leaf block for any extent
+ * btree. Since a split may grow the tree or a merge might shrink it,
+ * the caller cannot trust the contents of that buffer after this call.
  *
  * This code is optimized for readability - several passes might be
  * made over certain portions of the tree. All of those blocks will
@@ -4317,7 +4719,7 @@ out:
  * extra overhead is not expressed in terms of disk reads.
  */
 static int __ocfs2_mark_extent_written(struct inode *inode,
-                                      struct buffer_head *di_bh,
+                                      struct ocfs2_extent_tree *et,
                                       handle_t *handle,
                                       struct ocfs2_path *path,
                                       int split_index,
@@ -4357,11 +4759,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
         */
        if (path->p_tree_depth) {
                struct ocfs2_extent_block *eb;
-               struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                      le64_to_cpu(di->i_last_eb_blk),
-                                      &last_eb_bh, OCFS2_BH_CACHED, inode);
+               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et),
+                                      &last_eb_bh);
                if (ret) {
                        mlog_exit(ret);
                        goto out;
@@ -4394,7 +4794,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
                if (ctxt.c_split_covers_rec)
                        el->l_recs[split_index] = *split_rec;
                else
-                       ret = ocfs2_split_and_insert(inode, handle, path, di_bh,
+                       ret = ocfs2_split_and_insert(inode, handle, path, et,
                                                     &last_eb_bh, split_index,
                                                     split_rec, meta_ac);
                if (ret)
@@ -4402,7 +4802,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
        } else {
                ret = ocfs2_try_to_merge_extent(inode, handle, path,
                                                split_index, split_rec,
-                                               dealloc, &ctxt);
+                                               dealloc, &ctxt, et);
                if (ret)
                        mlog_errno(ret);
        }
@@ -4420,7 +4820,8 @@ out:
  *
  * The caller is responsible for passing down meta_ac if we'll need it.
  */
-int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_mark_extent_written(struct inode *inode,
+                             struct ocfs2_extent_tree *et,
                              handle_t *handle, u32 cpos, u32 len, u32 phys,
                              struct ocfs2_alloc_context *meta_ac,
                              struct ocfs2_cached_dealloc_ctxt *dealloc)
@@ -4446,10 +4847,14 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
        /*
         * XXX: This should be fixed up so that we just re-insert the
         * next extent records.
+        *
+        * XXX: This is a hack on the extent tree, maybe it should be
+        * an op?
         */
-       ocfs2_extent_map_trunc(inode, 0);
+       if (et->et_ops == &ocfs2_dinode_et_ops)
+               ocfs2_extent_map_trunc(inode, 0);
 
-       left_path = ocfs2_new_inode_path(di_bh);
+       left_path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
        if (!left_path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4480,8 +4885,9 @@ int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
        split_rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
        split_rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
 
-       ret = __ocfs2_mark_extent_written(inode, di_bh, handle, left_path,
-                                         index, &split_rec, meta_ac, dealloc);
+       ret = __ocfs2_mark_extent_written(inode, et, handle, left_path,
+                                         index, &split_rec, meta_ac,
+                                         dealloc);
        if (ret)
                mlog_errno(ret);
 
@@ -4490,13 +4896,12 @@ out:
        return ret;
 }
 
-static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
+static int ocfs2_split_tree(struct inode *inode, struct ocfs2_extent_tree *et,
                            handle_t *handle, struct ocfs2_path *path,
                            int index, u32 new_range,
                            struct ocfs2_alloc_context *meta_ac)
 {
        int ret, depth, credits = handle->h_buffer_credits;
-       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        struct buffer_head *last_eb_bh = NULL;
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *rightmost_el, *el;
@@ -4513,9 +4918,8 @@ static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
 
        depth = path->p_tree_depth;
        if (depth > 0) {
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                      le64_to_cpu(di->i_last_eb_blk),
-                                      &last_eb_bh, OCFS2_BH_CACHED, inode);
+               ret = ocfs2_read_block(inode, ocfs2_et_get_last_eb_blk(et),
+                                      &last_eb_bh);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -4526,7 +4930,8 @@ static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
        } else
                rightmost_el = path_leaf_el(path);
 
-       credits += path->p_tree_depth + ocfs2_extend_meta_needed(di);
+       credits += path->p_tree_depth +
+                  ocfs2_extend_meta_needed(et->et_root_el);
        ret = ocfs2_extend_trans(handle, credits);
        if (ret) {
                mlog_errno(ret);
@@ -4535,7 +4940,7 @@ static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
 
        if (le16_to_cpu(rightmost_el->l_next_free_rec) ==
            le16_to_cpu(rightmost_el->l_count)) {
-               ret = ocfs2_grow_tree(inode, handle, di_bh, &depth, &last_eb_bh,
+               ret = ocfs2_grow_tree(inode, handle, et, &depth, &last_eb_bh,
                                      meta_ac);
                if (ret) {
                        mlog_errno(ret);
@@ -4549,7 +4954,7 @@ static int ocfs2_split_tree(struct inode *inode, struct buffer_head *di_bh,
        insert.ins_split = SPLIT_RIGHT;
        insert.ins_tree_depth = depth;
 
-       ret = ocfs2_do_insert_extent(inode, handle, di_bh, &split_rec, &insert);
+       ret = ocfs2_do_insert_extent(inode, handle, et, &split_rec, &insert);
        if (ret)
                mlog_errno(ret);
 
@@ -4561,7 +4966,8 @@ out:
 static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
                              struct ocfs2_path *path, int index,
                              struct ocfs2_cached_dealloc_ctxt *dealloc,
-                             u32 cpos, u32 len)
+                             u32 cpos, u32 len,
+                             struct ocfs2_extent_tree *et)
 {
        int ret;
        u32 left_cpos, rec_range, trunc_range;
@@ -4573,7 +4979,7 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
        struct ocfs2_extent_block *eb;
 
        if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) {
-               ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+               ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc, et);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -4704,7 +5110,7 @@ static int ocfs2_truncate_rec(struct inode *inode, handle_t *handle,
 
        ocfs2_journal_dirty(handle, path_leaf_bh(path));
 
-       ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc);
+       ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc, et);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -4715,7 +5121,8 @@ out:
        return ret;
 }
 
-int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_remove_extent(struct inode *inode,
+                       struct ocfs2_extent_tree *et,
                        u32 cpos, u32 len, handle_t *handle,
                        struct ocfs2_alloc_context *meta_ac,
                        struct ocfs2_cached_dealloc_ctxt *dealloc)
@@ -4724,11 +5131,11 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
        u32 rec_range, trunc_range;
        struct ocfs2_extent_rec *rec;
        struct ocfs2_extent_list *el;
-       struct ocfs2_path *path;
+       struct ocfs2_path *path = NULL;
 
        ocfs2_extent_map_trunc(inode, 0);
 
-       path = ocfs2_new_inode_path(di_bh);
+       path = ocfs2_new_path(et->et_root_bh, et->et_root_el);
        if (!path) {
                ret = -ENOMEM;
                mlog_errno(ret);
@@ -4781,13 +5188,13 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
 
        if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) {
                ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
-                                        cpos, len);
+                                        cpos, len, et);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
        } else {
-               ret = ocfs2_split_tree(inode, di_bh, handle, path, index,
+               ret = ocfs2_split_tree(inode, et, handle, path, index,
                                       trunc_range, meta_ac);
                if (ret) {
                        mlog_errno(ret);
@@ -4836,7 +5243,7 @@ int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
                }
 
                ret = ocfs2_truncate_rec(inode, handle, path, index, dealloc,
-                                        cpos, len);
+                                        cpos, len, et);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5179,8 +5586,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
                goto bail;
        }
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
-                                 OCFS2_BH_CACHED, inode);
+       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
        if (status < 0) {
                iput(inode);
                mlog_errno(status);
@@ -5255,8 +5661,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
 bail:
        if (tl_inode)
                iput(tl_inode);
-       if (tl_bh)
-               brelse(tl_bh);
+       brelse(tl_bh);
 
        if (status < 0 && (*tl_copy)) {
                kfree(*tl_copy);
@@ -5999,20 +6404,13 @@ bail:
        return status;
 }
 
-static int ocfs2_writeback_zero_func(handle_t *handle, struct buffer_head *bh)
+static int ocfs2_zero_func(handle_t *handle, struct buffer_head *bh)
 {
        set_buffer_uptodate(bh);
        mark_buffer_dirty(bh);
        return 0;
 }
 
-static int ocfs2_ordered_zero_func(handle_t *handle, struct buffer_head *bh)
-{
-       set_buffer_uptodate(bh);
-       mark_buffer_dirty(bh);
-       return ocfs2_journal_dirty_data(handle, bh);
-}
-
 static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
                                     unsigned int from, unsigned int to,
                                     struct page *page, int zero, u64 *phys)
@@ -6031,17 +6429,18 @@ static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
         * here if they aren't - ocfs2_map_page_blocks()
         * might've skipped some
         */
-       if (ocfs2_should_order_data(inode)) {
-               ret = walk_page_buffers(handle,
-                                       page_buffers(page),
-                                       from, to, &partial,
-                                       ocfs2_ordered_zero_func);
-               if (ret < 0)
-                       mlog_errno(ret);
-       } else {
+       ret = walk_page_buffers(handle, page_buffers(page),
+                               from, to, &partial,
+                               ocfs2_zero_func);
+       if (ret < 0)
+               mlog_errno(ret);
+       else if (ocfs2_should_order_data(inode)) {
+               ret = ocfs2_jbd2_file_inode(handle, inode);
+#ifdef CONFIG_OCFS2_COMPAT_JBD
                ret = walk_page_buffers(handle, page_buffers(page),
                                        from, to, &partial,
-                                       ocfs2_writeback_zero_func);
+                                       ocfs2_journal_dirty_data);
+#endif
                if (ret < 0)
                        mlog_errno(ret);
        }
@@ -6206,20 +6605,29 @@ out:
        return ret;
 }
 
-static void ocfs2_zero_dinode_id2(struct inode *inode, struct ocfs2_dinode *di)
+static void ocfs2_zero_dinode_id2_with_xattr(struct inode *inode,
+                                            struct ocfs2_dinode *di)
 {
        unsigned int blocksize = 1 << inode->i_sb->s_blocksize_bits;
+       unsigned int xattrsize = le16_to_cpu(di->i_xattr_inline_size);
 
-       memset(&di->id2, 0, blocksize - offsetof(struct ocfs2_dinode, id2));
+       if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_XATTR_FL)
+               memset(&di->id2, 0, blocksize -
+                                   offsetof(struct ocfs2_dinode, id2) -
+                                   xattrsize);
+       else
+               memset(&di->id2, 0, blocksize -
+                                   offsetof(struct ocfs2_dinode, id2));
 }
 
 void ocfs2_dinode_new_extent_list(struct inode *inode,
                                  struct ocfs2_dinode *di)
 {
-       ocfs2_zero_dinode_id2(inode, di);
+       ocfs2_zero_dinode_id2_with_xattr(inode, di);
        di->id2.i_list.l_tree_depth = 0;
        di->id2.i_list.l_next_free_rec = 0;
-       di->id2.i_list.l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(inode->i_sb));
+       di->id2.i_list.l_count = cpu_to_le16(
+               ocfs2_extent_recs_per_inode_with_xattr(inode->i_sb, di));
 }
 
 void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di)
@@ -6236,9 +6644,10 @@ void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di)
         * We clear the entire i_data structure here so that all
         * fields can be properly initialized.
         */
-       ocfs2_zero_dinode_id2(inode, di);
+       ocfs2_zero_dinode_id2_with_xattr(inode, di);
 
-       idata->id_count = cpu_to_le16(ocfs2_max_inline_data(inode->i_sb));
+       idata->id_count = cpu_to_le16(
+                       ocfs2_max_inline_data_with_xattr(inode->i_sb, di));
 }
 
 int ocfs2_convert_inline_data_to_extents(struct inode *inode,
@@ -6253,6 +6662,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
        struct ocfs2_alloc_context *data_ac = NULL;
        struct page **pages = NULL;
        loff_t end = osb->s_clustersize;
+       struct ocfs2_extent_tree et;
 
        has_data = i_size_read(inode) ? 1 : 0;
 
@@ -6352,7 +6762,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
                 * this proves to be false, we could always re-build
                 * the in-inode data from our pages.
                 */
-               ret = ocfs2_insert_extent(osb, handle, inode, di_bh,
+               ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
+               ret = ocfs2_insert_extent(osb, handle, inode, &et,
                                          0, block, 1, 0, NULL);
                if (ret) {
                        mlog_errno(ret);
@@ -6395,13 +6806,14 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
        handle_t *handle = NULL;
        struct inode *tl_inode = osb->osb_tl_inode;
        struct ocfs2_path *path = NULL;
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)fe_bh->b_data;
 
        mlog_entry_void();
 
        new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
                                                     i_size_read(inode));
 
-       path = ocfs2_new_inode_path(fe_bh);
+       path = ocfs2_new_path(fe_bh, &di->id2.i_list);
        if (!path) {
                status = -ENOMEM;
                mlog_errno(status);
@@ -6572,8 +6984,8 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
        ocfs2_init_dealloc_ctxt(&(*tc)->tc_dealloc);
 
        if (fe->id2.i_list.l_tree_depth) {
-               status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
-                                         &last_eb_bh, OCFS2_BH_CACHED, inode);
+               status = ocfs2_read_block(inode, le64_to_cpu(fe->i_last_eb_blk),
+                                         &last_eb_bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -6686,8 +7098,7 @@ static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
                mlog(ML_NOTICE,
                     "Truncate completion has non-empty dealloc context\n");
 
-       if (tc->tc_last_eb_bh)
-               brelse(tc->tc_last_eb_bh);
+       brelse(tc->tc_last_eb_bh);
 
        kfree(tc);
 }
index 60cd3d59230c85398babfa7225fe087f2992a739..70257c84cfbe46c092bb78d6f6f2ae00b38505b3 100644 (file)
 #ifndef OCFS2_ALLOC_H
 #define OCFS2_ALLOC_H
 
+
+/*
+ * For xattr tree leaf, we limit the leaf byte size to be 64K.
+ */
+#define OCFS2_MAX_XATTR_TREE_LEAF_SIZE 65536
+
+/*
+ * ocfs2_extent_tree and ocfs2_extent_tree_operations are used to abstract
+ * the b-tree operations in ocfs2. Now all the b-tree operations are not
+ * limited to ocfs2_dinode only. Any data which need to allocate clusters
+ * to store can use b-tree. And it only needs to implement its ocfs2_extent_tree
+ * and operation.
+ *
+ * ocfs2_extent_tree becomes the first-class object for extent tree
+ * manipulation.  Callers of the alloc.c code need to fill it via one of
+ * the ocfs2_init_*_extent_tree() operations below.
+ *
+ * ocfs2_extent_tree contains info for the root of the b-tree, it must have a
+ * root ocfs2_extent_list and a root_bh so that they can be used in the b-tree
+ * functions.
+ * ocfs2_extent_tree_operations abstract the normal operations we do for
+ * the root of extent b-tree.
+ */
+struct ocfs2_extent_tree_operations;
+struct ocfs2_extent_tree {
+       struct ocfs2_extent_tree_operations     *et_ops;
+       struct buffer_head                      *et_root_bh;
+       struct ocfs2_extent_list                *et_root_el;
+       void                                    *et_object;
+       unsigned int                            et_max_leaf_clusters;
+};
+
+/*
+ * ocfs2_init_*_extent_tree() will fill an ocfs2_extent_tree from the
+ * specified object buffer.
+ */
+void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
+                                  struct inode *inode,
+                                  struct buffer_head *bh);
+void ocfs2_init_xattr_tree_extent_tree(struct ocfs2_extent_tree *et,
+                                      struct inode *inode,
+                                      struct buffer_head *bh);
+void ocfs2_init_xattr_value_extent_tree(struct ocfs2_extent_tree *et,
+                                       struct inode *inode,
+                                       struct buffer_head *bh,
+                                       struct ocfs2_xattr_value_root *xv);
+
 struct ocfs2_alloc_context;
 int ocfs2_insert_extent(struct ocfs2_super *osb,
                        handle_t *handle,
                        struct inode *inode,
-                       struct buffer_head *fe_bh,
+                       struct ocfs2_extent_tree *et,
                        u32 cpos,
                        u64 start_blk,
                        u32 new_clusters,
                        u8 flags,
                        struct ocfs2_alloc_context *meta_ac);
+
+enum ocfs2_alloc_restarted {
+       RESTART_NONE = 0,
+       RESTART_TRANS,
+       RESTART_META
+};
+int ocfs2_add_clusters_in_btree(struct ocfs2_super *osb,
+                               struct inode *inode,
+                               u32 *logical_offset,
+                               u32 clusters_to_add,
+                               int mark_unwritten,
+                               struct ocfs2_extent_tree *et,
+                               handle_t *handle,
+                               struct ocfs2_alloc_context *data_ac,
+                               struct ocfs2_alloc_context *meta_ac,
+                               enum ocfs2_alloc_restarted *reason_ret);
 struct ocfs2_cached_dealloc_ctxt;
-int ocfs2_mark_extent_written(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_mark_extent_written(struct inode *inode,
+                             struct ocfs2_extent_tree *et,
                              handle_t *handle, u32 cpos, u32 len, u32 phys,
                              struct ocfs2_alloc_context *meta_ac,
                              struct ocfs2_cached_dealloc_ctxt *dealloc);
-int ocfs2_remove_extent(struct inode *inode, struct buffer_head *di_bh,
+int ocfs2_remove_extent(struct inode *inode,
+                       struct ocfs2_extent_tree *et,
                        u32 cpos, u32 len, handle_t *handle,
                        struct ocfs2_alloc_context *meta_ac,
                        struct ocfs2_cached_dealloc_ctxt *dealloc);
 int ocfs2_num_free_extents(struct ocfs2_super *osb,
                           struct inode *inode,
-                          struct ocfs2_dinode *fe);
-/* how many new metadata chunks would an allocation need at maximum? */
-static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe)
+                          struct ocfs2_extent_tree *et);
+
+/*
+ * how many new metadata chunks would an allocation need at maximum?
+ *
+ * Please note that the caller must make sure that root_el is the root
+ * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
+ * the result may be wrong.
+ */
+static inline int ocfs2_extend_meta_needed(struct ocfs2_extent_list *root_el)
 {
        /*
         * Rather than do all the work of determining how much we need
@@ -59,7 +131,7 @@ static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe)
         * new tree_depth==0 extent_block, and one block at the new
         * top-of-the tree.
         */
-       return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2;
+       return le16_to_cpu(root_el->l_tree_depth) + 2;
 }
 
 void ocfs2_dinode_new_extent_list(struct inode *inode, struct ocfs2_dinode *di);
index a53da1466277abd843b0117f89df9850423ba92b..c22543b3342062f0308ec06a6f74f2334291727f 100644 (file)
@@ -68,9 +68,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
                goto bail;
        }
 
-       status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                 OCFS2_I(inode)->ip_blkno,
-                                 &bh, OCFS2_BH_CACHED, inode);
+       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -128,8 +126,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
        err = 0;
 
 bail:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(err);
        return err;
@@ -261,13 +258,11 @@ static int ocfs2_readpage_inline(struct inode *inode, struct page *page)
 {
        int ret;
        struct buffer_head *di_bh = NULL;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        BUG_ON(!PageLocked(page));
        BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL));
 
-       ret = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &di_bh,
-                              OCFS2_BH_CACHED, inode);
+       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -485,11 +480,14 @@ handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
        }
 
        if (ocfs2_should_order_data(inode)) {
+               ret = ocfs2_jbd2_file_inode(handle, inode);
+#ifdef CONFIG_OCFS2_COMPAT_JBD
                ret = walk_page_buffers(handle,
                                        page_buffers(page),
                                        from, to, NULL,
                                        ocfs2_journal_dirty_data);
-               if (ret < 0) 
+#endif
+               if (ret < 0)
                        mlog_errno(ret);
        }
 out:
@@ -669,7 +667,7 @@ static void ocfs2_invalidatepage(struct page *page, unsigned long offset)
 {
        journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
 
-       journal_invalidatepage(journal, page, offset);
+       jbd2_journal_invalidatepage(journal, page, offset);
 }
 
 static int ocfs2_releasepage(struct page *page, gfp_t wait)
@@ -678,7 +676,7 @@ static int ocfs2_releasepage(struct page *page, gfp_t wait)
 
        if (!page_has_buffers(page))
                return 0;
-       return journal_try_to_free_buffers(journal, page, wait);
+       return jbd2_journal_try_to_free_buffers(journal, page, wait);
 }
 
 static ssize_t ocfs2_direct_IO(int rw,
@@ -1074,11 +1072,15 @@ static void ocfs2_write_failure(struct inode *inode,
                tmppage = wc->w_pages[i];
 
                if (page_has_buffers(tmppage)) {
-                       if (ocfs2_should_order_data(inode))
+                       if (ocfs2_should_order_data(inode)) {
+                               ocfs2_jbd2_file_inode(wc->w_handle, inode);
+#ifdef CONFIG_OCFS2_COMPAT_JBD
                                walk_page_buffers(wc->w_handle,
                                                  page_buffers(tmppage),
                                                  from, to, NULL,
                                                  ocfs2_journal_dirty_data);
+#endif
+                       }
 
                        block_commit_write(tmppage, from, to);
                }
@@ -1242,6 +1244,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
        int ret, i, new, should_zero = 0;
        u64 v_blkno, p_blkno;
        struct inode *inode = mapping->host;
+       struct ocfs2_extent_tree et;
 
        new = phys == 0 ? 1 : 0;
        if (new || unwritten)
@@ -1255,10 +1258,10 @@ static int ocfs2_write_cluster(struct address_space *mapping,
                 * any additional semaphores or cluster locks.
                 */
                tmp_pos = cpos;
-               ret = ocfs2_do_extend_allocation(OCFS2_SB(inode->i_sb), inode,
-                                                &tmp_pos, 1, 0, wc->w_di_bh,
-                                                wc->w_handle, data_ac,
-                                                meta_ac, NULL);
+               ret = ocfs2_add_inode_data(OCFS2_SB(inode->i_sb), inode,
+                                          &tmp_pos, 1, 0, wc->w_di_bh,
+                                          wc->w_handle, data_ac,
+                                          meta_ac, NULL);
                /*
                 * This shouldn't happen because we must have already
                 * calculated the correct meta data allocation required. The
@@ -1276,7 +1279,8 @@ static int ocfs2_write_cluster(struct address_space *mapping,
                        goto out;
                }
        } else if (unwritten) {
-               ret = ocfs2_mark_extent_written(inode, wc->w_di_bh,
+               ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
+               ret = ocfs2_mark_extent_written(inode, &et,
                                                wc->w_handle, cpos, 1, phys,
                                                meta_ac, &wc->w_dealloc);
                if (ret < 0) {
@@ -1665,6 +1669,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
        struct ocfs2_alloc_context *data_ac = NULL;
        struct ocfs2_alloc_context *meta_ac = NULL;
        handle_t *handle;
+       struct ocfs2_extent_tree et;
 
        ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh);
        if (ret) {
@@ -1712,14 +1717,23 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                 * ocfs2_lock_allocators(). It greatly over-estimates
                 * the work to be done.
                 */
-               ret = ocfs2_lock_allocators(inode, di, clusters_to_alloc,
-                                           extents_to_split, &data_ac, &meta_ac);
+               mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u,"
+                    " clusters_to_add = %u, extents_to_split = %u\n",
+                    (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                    (long long)i_size_read(inode), le32_to_cpu(di->i_clusters),
+                    clusters_to_alloc, extents_to_split);
+
+               ocfs2_init_dinode_extent_tree(&et, inode, wc->w_di_bh);
+               ret = ocfs2_lock_allocators(inode, &et,
+                                           clusters_to_alloc, extents_to_split,
+                                           &data_ac, &meta_ac);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
                }
 
-               credits = ocfs2_calc_extend_credits(inode->i_sb, di,
+               credits = ocfs2_calc_extend_credits(inode->i_sb,
+                                                   &di->id2.i_list,
                                                    clusters_to_alloc);
 
        }
@@ -1905,11 +1919,15 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
                }
 
                if (page_has_buffers(tmppage)) {
-                       if (ocfs2_should_order_data(inode))
+                       if (ocfs2_should_order_data(inode)) {
+                               ocfs2_jbd2_file_inode(wc->w_handle, inode);
+#ifdef CONFIG_OCFS2_COMPAT_JBD
                                walk_page_buffers(wc->w_handle,
                                                  page_buffers(tmppage),
                                                  from, to, NULL,
                                                  ocfs2_journal_dirty_data);
+#endif
+                       }
                        block_commit_write(tmppage, from, to);
                }
        }
index f136639f5b41d023ea0f71d9c2bd1b7084c39322..7e947c6724694c74f7a1658392f83e15970fb7cd 100644 (file)
@@ -66,7 +66,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
        /* remove from dirty list before I/O. */
        clear_buffer_dirty(bh);
 
-       get_bh(bh); /* for end_buffer_write_sync() */                   
+       get_bh(bh); /* for end_buffer_write_sync() */
        bh->b_end_io = end_buffer_write_sync;
        submit_bh(WRITE, bh);
 
@@ -88,22 +88,103 @@ out:
        return ret;
 }
 
-int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
-                     struct buffer_head *bhs[], int flags,
-                     struct inode *inode)
+int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
+                          unsigned int nr, struct buffer_head *bhs[])
+{
+       int status = 0;
+       unsigned int i;
+       struct buffer_head *bh;
+
+       if (!nr) {
+               mlog(ML_BH_IO, "No buffers will be read!\n");
+               goto bail;
+       }
+
+       for (i = 0 ; i < nr ; i++) {
+               if (bhs[i] == NULL) {
+                       bhs[i] = sb_getblk(osb->sb, block++);
+                       if (bhs[i] == NULL) {
+                               status = -EIO;
+                               mlog_errno(status);
+                               goto bail;
+                       }
+               }
+               bh = bhs[i];
+
+               if (buffer_jbd(bh)) {
+                       mlog(ML_ERROR,
+                            "trying to sync read a jbd "
+                            "managed bh (blocknr = %llu), skipping\n",
+                            (unsigned long long)bh->b_blocknr);
+                       continue;
+               }
+
+               if (buffer_dirty(bh)) {
+                       /* This should probably be a BUG, or
+                        * at least return an error. */
+                       mlog(ML_ERROR,
+                            "trying to sync read a dirty "
+                            "buffer! (blocknr = %llu), skipping\n",
+                            (unsigned long long)bh->b_blocknr);
+                       continue;
+               }
+
+               lock_buffer(bh);
+               if (buffer_jbd(bh)) {
+                       mlog(ML_ERROR,
+                            "block %llu had the JBD bit set "
+                            "while I was in lock_buffer!",
+                            (unsigned long long)bh->b_blocknr);
+                       BUG();
+               }
+
+               clear_buffer_uptodate(bh);
+               get_bh(bh); /* for end_buffer_read_sync() */
+               bh->b_end_io = end_buffer_read_sync;
+               submit_bh(READ, bh);
+       }
+
+       for (i = nr; i > 0; i--) {
+               bh = bhs[i - 1];
+
+               if (buffer_jbd(bh)) {
+                       mlog(ML_ERROR,
+                            "the journal got the buffer while it was "
+                            "locked for io! (blocknr = %llu)\n",
+                            (unsigned long long)bh->b_blocknr);
+                       BUG();
+               }
+
+               wait_on_buffer(bh);
+               if (!buffer_uptodate(bh)) {
+                       /* Status won't be cleared from here on out,
+                        * so we can safely record this and loop back
+                        * to cleanup the other buffers. */
+                       status = -EIO;
+                       put_bh(bh);
+                       bhs[i - 1] = NULL;
+               }
+       }
+
+bail:
+       return status;
+}
+
+int ocfs2_read_blocks(struct inode *inode, u64 block, int nr,
+                     struct buffer_head *bhs[], int flags)
 {
        int status = 0;
-       struct super_block *sb;
        int i, ignore_cache = 0;
        struct buffer_head *bh;
 
-       mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n",
-                  (unsigned long long)block, nr, flags, inode);
+       mlog_entry("(inode=%p, block=(%llu), nr=(%d), flags=%d)\n",
+                  inode, (unsigned long long)block, nr, flags);
 
+       BUG_ON(!inode);
        BUG_ON((flags & OCFS2_BH_READAHEAD) &&
-              (!inode || !(flags & OCFS2_BH_CACHED)));
+              (flags & OCFS2_BH_IGNORE_CACHE));
 
-       if (osb == NULL || osb->sb == NULL || bhs == NULL) {
+       if (bhs == NULL) {
                status = -EINVAL;
                mlog_errno(status);
                goto bail;
@@ -122,26 +203,19 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
                goto bail;
        }
 
-       sb = osb->sb;
-
-       if (flags & OCFS2_BH_CACHED && !inode)
-               flags &= ~OCFS2_BH_CACHED;
-
-       if (inode)
-               mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
+       mutex_lock(&OCFS2_I(inode)->ip_io_mutex);
        for (i = 0 ; i < nr ; i++) {
                if (bhs[i] == NULL) {
-                       bhs[i] = sb_getblk(sb, block++);
+                       bhs[i] = sb_getblk(inode->i_sb, block++);
                        if (bhs[i] == NULL) {
-                               if (inode)
-                                       mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+                               mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
                                status = -EIO;
                                mlog_errno(status);
                                goto bail;
                        }
                }
                bh = bhs[i];
-               ignore_cache = 0;
+               ignore_cache = (flags & OCFS2_BH_IGNORE_CACHE);
 
                /* There are three read-ahead cases here which we need to
                 * be concerned with. All three assume a buffer has
@@ -167,26 +241,27 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
                 *    before our is-it-in-flight check.
                 */
 
-               if (flags & OCFS2_BH_CACHED &&
-                   !ocfs2_buffer_uptodate(inode, bh)) {
+               if (!ignore_cache && !ocfs2_buffer_uptodate(inode, bh)) {
                        mlog(ML_UPTODATE,
                             "bh (%llu), inode %llu not uptodate\n",
                             (unsigned long long)bh->b_blocknr,
                             (unsigned long long)OCFS2_I(inode)->ip_blkno);
+                       /* We're using ignore_cache here to say
+                        * "go to disk" */
                        ignore_cache = 1;
                }
 
                /* XXX: Can we ever get this and *not* have the cached
                 * flag set? */
                if (buffer_jbd(bh)) {
-                       if (!(flags & OCFS2_BH_CACHED) || ignore_cache)
+                       if (ignore_cache)
                                mlog(ML_BH_IO, "trying to sync read a jbd "
                                               "managed bh (blocknr = %llu)\n",
                                     (unsigned long long)bh->b_blocknr);
                        continue;
                }
 
-               if (!(flags & OCFS2_BH_CACHED) || ignore_cache) {
+               if (ignore_cache) {
                        if (buffer_dirty(bh)) {
                                /* This should probably be a BUG, or
                                 * at least return an error. */
@@ -221,7 +296,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
                         * previously read-ahead buffer may have
                         * completed I/O while we were waiting for the
                         * buffer lock. */
-                       if ((flags & OCFS2_BH_CACHED)
+                       if (!(flags & OCFS2_BH_IGNORE_CACHE)
                            && !(flags & OCFS2_BH_READAHEAD)
                            && ocfs2_buffer_uptodate(inode, bh)) {
                                unlock_buffer(bh);
@@ -265,15 +340,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
                /* Always set the buffer in the cache, even if it was
                 * a forced read, or read-ahead which hasn't yet
                 * completed. */
-               if (inode)
-                       ocfs2_set_buffer_uptodate(inode, bh);
+               ocfs2_set_buffer_uptodate(inode, bh);
        }
-       if (inode)
-               mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
+       mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);
 
        mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", 
             (unsigned long long)block, nr,
-            (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags);
+            ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes",
+            flags);
 
 bail:
 
index c2e78614c3e50970ed01521d5e38e2371adeb388..75e1dcb1ade7d19d92a70684f1d3daaf851c67ed 100644 (file)
 void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
                             int uptodate);
 
-static inline int ocfs2_read_block(struct ocfs2_super          *osb,
+static inline int ocfs2_read_block(struct inode               *inode,
                                   u64                  off,
-                                  struct buffer_head **bh,
-                                  int                  flags,
-                                  struct inode        *inode);
+                                  struct buffer_head **bh);
 
 int ocfs2_write_block(struct ocfs2_super          *osb,
                      struct buffer_head  *bh,
                      struct inode        *inode);
-int ocfs2_read_blocks(struct ocfs2_super          *osb,
+int ocfs2_read_blocks(struct inode       *inode,
                      u64                  block,
                      int                  nr,
                      struct buffer_head  *bhs[],
-                     int                  flags,
-                     struct inode        *inode);
+                     int                  flags);
+int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
+                          unsigned int nr, struct buffer_head *bhs[]);
 
 int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
                                struct buffer_head *bh);
 
-#define OCFS2_BH_CACHED            1
+#define OCFS2_BH_IGNORE_CACHE      1
 #define OCFS2_BH_READAHEAD         8
 
-static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
-                                  struct buffer_head **bh, int flags,
-                                  struct inode *inode)
+static inline int ocfs2_read_block(struct inode *inode, u64 off,
+                                  struct buffer_head **bh)
 {
        int status = 0;
 
@@ -65,8 +63,7 @@ static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
                goto bail;
        }
 
-       status = ocfs2_read_blocks(osb, off, 1, bh,
-                                  flags, inode);
+       status = ocfs2_read_blocks(inode, off, 1, bh, 0);
 
 bail:
        return status;
index 23c732f275293bfdd24dad2d03ddbb07c7c4b8e8..d8a0cb92cef62a6b108696b0a9dae36dcfc9768a 100644 (file)
@@ -109,6 +109,7 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
        define_mask(CONN),
        define_mask(QUORUM),
        define_mask(EXPORT),
+       define_mask(XATTR),
        define_mask(ERROR),
        define_mask(NOTICE),
        define_mask(KTHREAD),
index 597e064bb94fa9333ea40ad0387d7b34fa2005dc..57670c6804713454f02f2a6b18ed5ca41bbbfe6b 100644 (file)
 #define ML_CONN                0x0000000004000000ULL /* net connection management */
 #define ML_QUORUM      0x0000000008000000ULL /* net connection quorum */
 #define ML_EXPORT      0x0000000010000000ULL /* ocfs2 export operations */
+#define ML_XATTR       0x0000000020000000ULL /* ocfs2 extended attributes */
 /* bits that are infrequently given and frequently matched in the high word */
 #define ML_ERROR       0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE      0x0000000200000000ULL /* setn to KERN_NOTICE */
index 9cce563fd6278dde9a4da3db12eabb04e328526e..026e6eb85187844b60ba55eb9893651090ac1c4f 100644 (file)
@@ -82,6 +82,49 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
                               struct ocfs2_alloc_context *meta_ac,
                               struct buffer_head **new_bh);
 
+static struct buffer_head *ocfs2_bread(struct inode *inode,
+                                      int block, int *err, int reada)
+{
+       struct buffer_head *bh = NULL;
+       int tmperr;
+       u64 p_blkno;
+       int readflags = 0;
+
+       if (reada)
+               readflags |= OCFS2_BH_READAHEAD;
+
+       if (((u64)block << inode->i_sb->s_blocksize_bits) >=
+           i_size_read(inode)) {
+               BUG_ON(!reada);
+               return NULL;
+       }
+
+       down_read(&OCFS2_I(inode)->ip_alloc_sem);
+       tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
+                                            NULL);
+       up_read(&OCFS2_I(inode)->ip_alloc_sem);
+       if (tmperr < 0) {
+               mlog_errno(tmperr);
+               goto fail;
+       }
+
+       tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags);
+       if (tmperr < 0)
+               goto fail;
+
+       tmperr = 0;
+
+       *err = 0;
+       return bh;
+
+fail:
+       brelse(bh);
+       bh = NULL;
+
+       *err = -EIO;
+       return NULL;
+}
+
 /*
  * bh passed here can be an inode block or a dir data block, depending
  * on the inode inline data flag.
@@ -188,8 +231,7 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name,
        struct ocfs2_dinode *di;
        struct ocfs2_inline_data *data;
 
-       ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno,
-                              &di_bh, OCFS2_BH_CACHED, dir);
+       ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -260,14 +302,13 @@ restart:
                }
                if ((bh = bh_use[ra_ptr++]) == NULL)
                        goto next;
-               wait_on_buffer(bh);
-               if (!buffer_uptodate(bh)) {
-                       /* read error, skip block & hope for the best */
+               if (ocfs2_read_block(dir, block, &bh)) {
+                       /* read error, skip block & hope for the best.
+                        * ocfs2_read_block() has released the bh. */
                        ocfs2_error(dir->i_sb, "reading directory %llu, "
                                    "offset %lu\n",
                                    (unsigned long long)OCFS2_I(dir)->ip_blkno,
                                    block);
-                       brelse(bh);
                        goto next;
                }
                i = ocfs2_search_dirblock(bh, dir, name, namelen,
@@ -417,8 +458,7 @@ static inline int ocfs2_delete_entry_id(handle_t *handle,
        struct ocfs2_dinode *di;
        struct ocfs2_inline_data *data;
 
-       ret = ocfs2_read_block(OCFS2_SB(dir->i_sb), OCFS2_I(dir)->ip_blkno,
-                              &di_bh, OCFS2_BH_CACHED, dir);
+       ret = ocfs2_read_block(dir, OCFS2_I(dir)->ip_blkno, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -596,8 +636,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
        struct ocfs2_inline_data *data;
        struct ocfs2_dir_entry *de;
 
-       ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno,
-                              &di_bh, OCFS2_BH_CACHED, inode);
+       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
        if (ret) {
                mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
                     (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -716,8 +755,7 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
                        for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
                             i > 0; i--) {
                                tmp = ocfs2_bread(inode, ++blk, &err, 1);
-                               if (tmp)
-                                       brelse(tmp);
+                               brelse(tmp);
                        }
                        last_ra_blk = blk;
                        ra_sectors = 8;
@@ -899,10 +937,8 @@ int ocfs2_find_files_on_disk(const char *name,
 leave:
        if (status < 0) {
                *dirent = NULL;
-               if (*dirent_bh) {
-                       brelse(*dirent_bh);
-                       *dirent_bh = NULL;
-               }
+               brelse(*dirent_bh);
+               *dirent_bh = NULL;
        }
 
        mlog_exit(status);
@@ -951,8 +987,7 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
 
        ret = 0;
 bail:
-       if (dirent_bh)
-               brelse(dirent_bh);
+       brelse(dirent_bh);
 
        mlog_exit(ret);
        return ret;
@@ -1127,8 +1162,7 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
 
        status = 0;
 bail:
-       if (new_bh)
-               brelse(new_bh);
+       brelse(new_bh);
 
        mlog_exit(status);
        return status;
@@ -1192,6 +1226,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
        struct buffer_head *dirdata_bh = NULL;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        handle_t *handle;
+       struct ocfs2_extent_tree et;
+
+       ocfs2_init_dinode_extent_tree(&et, dir, di_bh);
 
        alloc = ocfs2_clusters_for_bytes(sb, bytes);
 
@@ -1305,8 +1342,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
         * This should never fail as our extent list is empty and all
         * related blocks have been journaled already.
         */
-       ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 0, blkno, len, 0,
-                                 NULL);
+       ret = ocfs2_insert_extent(osb, handle, dir, &et, 0, blkno, len,
+                                 0, NULL);
        if (ret) {
                mlog_errno(ret);
                goto out_commit;
@@ -1337,8 +1374,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
                }
                blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
 
-               ret = ocfs2_insert_extent(osb, handle, dir, di_bh, 1, blkno,
-                                         len, 0, NULL);
+               ret = ocfs2_insert_extent(osb, handle, dir, &et, 1,
+                                         blkno, len, 0, NULL);
                if (ret) {
                        mlog_errno(ret);
                        goto out_commit;
@@ -1383,9 +1420,9 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
        if (extend) {
                u32 offset = OCFS2_I(dir)->ip_clusters;
 
-               status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, &offset,
-                                                   1, 0, parent_fe_bh, handle,
-                                                   data_ac, meta_ac, NULL);
+               status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
+                                             1, 0, parent_fe_bh, handle,
+                                             data_ac, meta_ac, NULL);
                BUG_ON(status == -EAGAIN);
                if (status < 0) {
                        mlog_errno(status);
@@ -1430,12 +1467,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        int credits, num_free_extents, drop_alloc_sem = 0;
        loff_t dir_i_size;
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
+       struct ocfs2_extent_list *el = &fe->id2.i_list;
        struct ocfs2_alloc_context *data_ac = NULL;
        struct ocfs2_alloc_context *meta_ac = NULL;
        handle_t *handle = NULL;
        struct buffer_head *new_bh = NULL;
        struct ocfs2_dir_entry * de;
        struct super_block *sb = osb->sb;
+       struct ocfs2_extent_tree et;
 
        mlog_entry_void();
 
@@ -1479,7 +1518,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        spin_lock(&OCFS2_I(dir)->ip_lock);
        if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
                spin_unlock(&OCFS2_I(dir)->ip_lock);
-               num_free_extents = ocfs2_num_free_extents(osb, dir, fe);
+               ocfs2_init_dinode_extent_tree(&et, dir, parent_fe_bh);
+               num_free_extents = ocfs2_num_free_extents(osb, dir, &et);
                if (num_free_extents < 0) {
                        status = num_free_extents;
                        mlog_errno(status);
@@ -1487,7 +1527,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                }
 
                if (!num_free_extents) {
-                       status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac);
+                       status = ocfs2_reserve_new_metadata(osb, el, &meta_ac);
                        if (status < 0) {
                                if (status != -ENOSPC)
                                        mlog_errno(status);
@@ -1502,7 +1542,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                        goto bail;
                }
 
-               credits = ocfs2_calc_extend_credits(sb, fe, 1);
+               credits = ocfs2_calc_extend_credits(sb, el, 1);
        } else {
                spin_unlock(&OCFS2_I(dir)->ip_lock);
                credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
@@ -1568,8 +1608,7 @@ bail:
        if (meta_ac)
                ocfs2_free_alloc_context(meta_ac);
 
-       if (new_bh)
-               brelse(new_bh);
+       brelse(new_bh);
 
        mlog_exit(status);
        return status;
@@ -1696,8 +1735,7 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
 
        status = 0;
 bail:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
@@ -1756,7 +1794,6 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
        *ret_de_bh = bh;
        bh = NULL;
 out:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
        return ret;
 }
index eae3d643a5e4316332b23cabb6f3d7edae4b7a5e..ec684426034b6dc39ab2b772acc918d07cce6ccd 100644 (file)
@@ -2024,8 +2024,7 @@ static int ocfs2_inode_lock_update(struct inode *inode,
        } else {
                /* Boo, we have to go to disk. */
                /* read bh, cast, ocfs2_refresh_inode */
-               status = ocfs2_read_block(OCFS2_SB(inode->i_sb), oi->ip_blkno,
-                                         bh, OCFS2_BH_CACHED, inode);
+               status = ocfs2_read_block(inode, oi->ip_blkno, bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail_refresh;
@@ -2086,11 +2085,7 @@ static int ocfs2_assign_bh(struct inode *inode,
                return 0;
        }
 
-       status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                 OCFS2_I(inode)->ip_blkno,
-                                 ret_bh,
-                                 OCFS2_BH_CACHED,
-                                 inode);
+       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, ret_bh);
        if (status < 0)
                mlog_errno(status);
 
index aed268e80b49173a5a3af264bcd5ca5c7e55ca8a..2baedac582341dbb60986840b29daded17521842 100644 (file)
@@ -293,8 +293,7 @@ static int ocfs2_last_eb_is_empty(struct inode *inode,
        struct ocfs2_extent_block *eb;
        struct ocfs2_extent_list *el;
 
-       ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), last_eb_blk,
-                              &eb_bh, OCFS2_BH_CACHED, inode);
+       ret = ocfs2_read_block(inode, last_eb_blk, &eb_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -382,9 +381,9 @@ static int ocfs2_figure_hole_clusters(struct inode *inode,
                if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL)
                        goto no_more_extents;
 
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+               ret = ocfs2_read_block(inode,
                                       le64_to_cpu(eb->h_next_leaf_blk),
-                                      &next_eb_bh, OCFS2_BH_CACHED, inode);
+                                      &next_eb_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -551,6 +550,66 @@ static void ocfs2_relative_extent_offsets(struct super_block *sb,
                *num_clusters = le16_to_cpu(rec->e_leaf_clusters) - coff;
 }
 
+int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
+                            u32 *p_cluster, u32 *num_clusters,
+                            struct ocfs2_extent_list *el)
+{
+       int ret = 0, i;
+       struct buffer_head *eb_bh = NULL;
+       struct ocfs2_extent_block *eb;
+       struct ocfs2_extent_rec *rec;
+       u32 coff;
+
+       if (el->l_tree_depth) {
+               ret = ocfs2_find_leaf(inode, el, v_cluster, &eb_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               eb = (struct ocfs2_extent_block *) eb_bh->b_data;
+               el = &eb->h_list;
+
+               if (el->l_tree_depth) {
+                       ocfs2_error(inode->i_sb,
+                                   "Inode %lu has non zero tree depth in "
+                                   "xattr leaf block %llu\n", inode->i_ino,
+                                   (unsigned long long)eb_bh->b_blocknr);
+                       ret = -EROFS;
+                       goto out;
+               }
+       }
+
+       i = ocfs2_search_extent_list(el, v_cluster);
+       if (i == -1) {
+               ret = -EROFS;
+               mlog_errno(ret);
+               goto out;
+       } else {
+               rec = &el->l_recs[i];
+               BUG_ON(v_cluster < le32_to_cpu(rec->e_cpos));
+
+               if (!rec->e_blkno) {
+                       ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
+                                   "record (%u, %u, 0) in xattr", inode->i_ino,
+                                   le32_to_cpu(rec->e_cpos),
+                                   ocfs2_rec_clusters(el, rec));
+                       ret = -EROFS;
+                       goto out;
+               }
+               coff = v_cluster - le32_to_cpu(rec->e_cpos);
+               *p_cluster = ocfs2_blocks_to_clusters(inode->i_sb,
+                                                   le64_to_cpu(rec->e_blkno));
+               *p_cluster = *p_cluster + coff;
+               if (num_clusters)
+                       *num_clusters = ocfs2_rec_clusters(el, rec) - coff;
+       }
+out:
+       if (eb_bh)
+               brelse(eb_bh);
+       return ret;
+}
+
 int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
                       u32 *p_cluster, u32 *num_clusters,
                       unsigned int *extent_flags)
@@ -571,8 +630,7 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster,
        if (ret == 0)
                goto out;
 
-       ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno,
-                              &di_bh, OCFS2_BH_CACHED, inode);
+       ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &di_bh);
        if (ret) {
                mlog_errno(ret);
                goto out;
index 1b97490e1ea8d7b431cf40c9bbcab801b3bb4305..1c4aa8b06f348c89b4560f733cdd0e1aefe9e852 100644 (file)
@@ -53,4 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
 int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                 u64 map_start, u64 map_len);
 
+int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
+                            u32 *p_cluster, u32 *num_clusters,
+                            struct ocfs2_extent_list *el);
+
 #endif  /* _EXTENT_MAP_H */
index ed38796052d201f28da44d0ec60d7bf4baf078a8..8d3225a78073f86c682ed21e9b3098a1fef6b843 100644 (file)
@@ -55,6 +55,7 @@
 #include "mmap.h"
 #include "suballoc.h"
 #include "super.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -184,7 +185,7 @@ static int ocfs2_sync_file(struct file *file,
                goto bail;
 
        journal = osb->journal->j_journal;
-       err = journal_force_commit(journal);
+       err = jbd2_journal_force_commit(journal);
 
 bail:
        mlog_exit(err);
@@ -488,7 +489,7 @@ bail:
 }
 
 /*
- * extend allocation only here.
+ * extend file allocation only here.
  * we'll update all the disk stuff, and oip->alloc_size
  *
  * expect stuff to be locked, a transaction started and enough data /
@@ -497,189 +498,25 @@ bail:
  * Will return -EAGAIN, and a reason if a restart is needed.
  * If passed in, *reason will always be set, even in error.
  */
-int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
-                              struct inode *inode,
-                              u32 *logical_offset,
-                              u32 clusters_to_add,
-                              int mark_unwritten,
-                              struct buffer_head *fe_bh,
-                              handle_t *handle,
-                              struct ocfs2_alloc_context *data_ac,
-                              struct ocfs2_alloc_context *meta_ac,
-                              enum ocfs2_alloc_restarted *reason_ret)
+int ocfs2_add_inode_data(struct ocfs2_super *osb,
+                        struct inode *inode,
+                        u32 *logical_offset,
+                        u32 clusters_to_add,
+                        int mark_unwritten,
+                        struct buffer_head *fe_bh,
+                        handle_t *handle,
+                        struct ocfs2_alloc_context *data_ac,
+                        struct ocfs2_alloc_context *meta_ac,
+                        enum ocfs2_alloc_restarted *reason_ret)
 {
-       int status = 0;
-       int free_extents;
-       struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
-       enum ocfs2_alloc_restarted reason = RESTART_NONE;
-       u32 bit_off, num_bits;
-       u64 block;
-       u8 flags = 0;
-
-       BUG_ON(!clusters_to_add);
-
-       if (mark_unwritten)
-               flags = OCFS2_EXT_UNWRITTEN;
-
-       free_extents = ocfs2_num_free_extents(osb, inode, fe);
-       if (free_extents < 0) {
-               status = free_extents;
-               mlog_errno(status);
-               goto leave;
-       }
-
-       /* there are two cases which could cause us to EAGAIN in the
-        * we-need-more-metadata case:
-        * 1) we haven't reserved *any*
-        * 2) we are so fragmented, we've needed to add metadata too
-        *    many times. */
-       if (!free_extents && !meta_ac) {
-               mlog(0, "we haven't reserved any metadata!\n");
-               status = -EAGAIN;
-               reason = RESTART_META;
-               goto leave;
-       } else if ((!free_extents)
-                  && (ocfs2_alloc_context_bits_left(meta_ac)
-                      < ocfs2_extend_meta_needed(fe))) {
-               mlog(0, "filesystem is really fragmented...\n");
-               status = -EAGAIN;
-               reason = RESTART_META;
-               goto leave;
-       }
-
-       status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
-                                       clusters_to_add, &bit_off, &num_bits);
-       if (status < 0) {
-               if (status != -ENOSPC)
-                       mlog_errno(status);
-               goto leave;
-       }
-
-       BUG_ON(num_bits > clusters_to_add);
-
-       /* reserve our write early -- insert_extent may update the inode */
-       status = ocfs2_journal_access(handle, inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-       }
-
-       block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
-       mlog(0, "Allocating %u clusters at block %u for inode %llu\n",
-            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
-       status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
-                                    *logical_offset, block, num_bits,
-                                    flags, meta_ac);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-       }
-
-       status = ocfs2_journal_dirty(handle, fe_bh);
-       if (status < 0) {
-               mlog_errno(status);
-               goto leave;
-       }
-
-       clusters_to_add -= num_bits;
-       *logical_offset += num_bits;
-
-       if (clusters_to_add) {
-               mlog(0, "need to alloc once more, clusters = %u, wanted = "
-                    "%u\n", fe->i_clusters, clusters_to_add);
-               status = -EAGAIN;
-               reason = RESTART_TRANS;
-       }
-
-leave:
-       mlog_exit(status);
-       if (reason_ret)
-               *reason_ret = reason;
-       return status;
-}
-
-/*
- * For a given allocation, determine which allocators will need to be
- * accessed, and lock them, reserving the appropriate number of bits.
- *
- * Sparse file systems call this from ocfs2_write_begin_nolock()
- * and ocfs2_allocate_unwritten_extents().
- *
- * File systems which don't support holes call this from
- * ocfs2_extend_allocation().
- */
-int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-                         u32 clusters_to_add, u32 extents_to_split,
-                         struct ocfs2_alloc_context **data_ac,
-                         struct ocfs2_alloc_context **meta_ac)
-{
-       int ret = 0, num_free_extents;
-       unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-
-       *meta_ac = NULL;
-       if (data_ac)
-               *data_ac = NULL;
-
-       BUG_ON(clusters_to_add != 0 && data_ac == NULL);
-
-       mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
-            "clusters_to_add = %u, extents_to_split = %u\n",
-            (unsigned long long)OCFS2_I(inode)->ip_blkno, (long long)i_size_read(inode),
-            le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
-
-       num_free_extents = ocfs2_num_free_extents(osb, inode, di);
-       if (num_free_extents < 0) {
-               ret = num_free_extents;
-               mlog_errno(ret);
-               goto out;
-       }
-
-       /*
-        * Sparse allocation file systems need to be more conservative
-        * with reserving room for expansion - the actual allocation
-        * happens while we've got a journal handle open so re-taking
-        * a cluster lock (because we ran out of room for another
-        * extent) will violate ordering rules.
-        *
-        * Most of the time we'll only be seeing this 1 cluster at a time
-        * anyway.
-        *
-        * Always lock for any unwritten extents - we might want to
-        * add blocks during a split.
-        */
-       if (!num_free_extents ||
-           (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
-               ret = ocfs2_reserve_new_metadata(osb, di, meta_ac);
-               if (ret < 0) {
-                       if (ret != -ENOSPC)
-                               mlog_errno(ret);
-                       goto out;
-               }
-       }
-
-       if (clusters_to_add == 0)
-               goto out;
-
-       ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
-       if (ret < 0) {
-               if (ret != -ENOSPC)
-                       mlog_errno(ret);
-               goto out;
-       }
-
-out:
-       if (ret) {
-               if (*meta_ac) {
-                       ocfs2_free_alloc_context(*meta_ac);
-                       *meta_ac = NULL;
-               }
+       int ret;
+       struct ocfs2_extent_tree et;
 
-               /*
-                * We cannot have an error and a non null *data_ac.
-                */
-       }
+       ocfs2_init_dinode_extent_tree(&et, inode, fe_bh);
+       ret = ocfs2_add_clusters_in_btree(osb, inode, logical_offset,
+                                          clusters_to_add, mark_unwritten,
+                                          &et, handle,
+                                          data_ac, meta_ac, reason_ret);
 
        return ret;
 }
@@ -698,6 +535,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
        struct ocfs2_alloc_context *meta_ac = NULL;
        enum ocfs2_alloc_restarted why;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_extent_tree et;
 
        mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
 
@@ -707,8 +545,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
         */
        BUG_ON(mark_unwritten && !ocfs2_sparse_alloc(osb));
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
-                                 OCFS2_BH_CACHED, inode);
+       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, &bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -724,14 +561,21 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
 restart_all:
        BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
 
-       status = ocfs2_lock_allocators(inode, fe, clusters_to_add, 0, &data_ac,
-                                      &meta_ac);
+       mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
+            "clusters_to_add = %u\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno,
+            (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
+            clusters_to_add);
+       ocfs2_init_dinode_extent_tree(&et, inode, bh);
+       status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
+                                      &data_ac, &meta_ac);
        if (status) {
                mlog_errno(status);
                goto leave;
        }
 
-       credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add);
+       credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list,
+                                           clusters_to_add);
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
@@ -753,16 +597,16 @@ restarted_transaction:
 
        prev_clusters = OCFS2_I(inode)->ip_clusters;
 
-       status = ocfs2_do_extend_allocation(osb,
-                                           inode,
-                                           &logical_start,
-                                           clusters_to_add,
-                                           mark_unwritten,
-                                           bh,
-                                           handle,
-                                           data_ac,
-                                           meta_ac,
-                                           &why);
+       status = ocfs2_add_inode_data(osb,
+                                     inode,
+                                     &logical_start,
+                                     clusters_to_add,
+                                     mark_unwritten,
+                                     bh,
+                                     handle,
+                                     data_ac,
+                                     meta_ac,
+                                     &why);
        if ((status < 0) && (status != -EAGAIN)) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -789,7 +633,7 @@ restarted_transaction:
                        mlog(0, "restarting transaction.\n");
                        /* TODO: This can be more intelligent. */
                        credits = ocfs2_calc_extend_credits(osb->sb,
-                                                           fe,
+                                                           &fe->id2.i_list,
                                                            clusters_to_add);
                        status = ocfs2_extend_trans(handle, credits);
                        if (status < 0) {
@@ -826,10 +670,8 @@ leave:
                restart_func = 0;
                goto restart_all;
        }
-       if (bh) {
-               brelse(bh);
-               bh = NULL;
-       }
+       brelse(bh);
+       bh = NULL;
 
        mlog_exit(status);
        return status;
@@ -1096,9 +938,15 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
                        goto bail_unlock;
                }
 
-               if (i_size_read(inode) > attr->ia_size)
+               if (i_size_read(inode) > attr->ia_size) {
+                       if (ocfs2_should_order_data(inode)) {
+                               status = ocfs2_begin_ordered_truncate(inode,
+                                                                     attr->ia_size);
+                               if (status)
+                                       goto bail_unlock;
+                       }
                        status = ocfs2_truncate_file(inode, bh, attr->ia_size);
-               else
+               else
                        status = ocfs2_extend_file(inode, bh, attr->ia_size);
                if (status < 0) {
                        if (status != -ENOSPC)
@@ -1140,8 +988,7 @@ bail_unlock_rw:
        if (size_change)
                ocfs2_rw_unlock(inode, 1);
 bail:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
@@ -1284,8 +1131,7 @@ static int ocfs2_write_remove_suid(struct inode *inode)
        struct buffer_head *bh = NULL;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
 
-       ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                              oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+       ret = ocfs2_read_block(inode, oi->ip_blkno, &bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -1311,9 +1157,8 @@ static int ocfs2_allocate_unwritten_extents(struct inode *inode,
        struct buffer_head *di_bh = NULL;
 
        if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
-               ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                      OCFS2_I(inode)->ip_blkno, &di_bh,
-                                      OCFS2_BH_CACHED, inode);
+               ret = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno,
+                                      &di_bh);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -1394,8 +1239,11 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
        handle_t *handle;
        struct ocfs2_alloc_context *meta_ac = NULL;
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+       struct ocfs2_extent_tree et;
 
-       ret = ocfs2_lock_allocators(inode, di, 0, 1, NULL, &meta_ac);
+       ocfs2_init_dinode_extent_tree(&et, inode, di_bh);
+
+       ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
        if (ret) {
                mlog_errno(ret);
                return ret;
@@ -1425,7 +1273,7 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
                goto out;
        }
 
-       ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
+       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
                                  dealloc);
        if (ret) {
                mlog_errno(ret);
@@ -2040,7 +1888,7 @@ out_dio:
                 */
                if (old_size != i_size_read(inode) ||
                    old_clusters != OCFS2_I(inode)->ip_clusters) {
-                       ret = journal_force_commit(osb->journal->j_journal);
+                       ret = jbd2_journal_force_commit(osb->journal->j_journal);
                        if (ret < 0)
                                written = ret;
                }
@@ -2227,6 +2075,10 @@ const struct inode_operations ocfs2_file_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = ocfs2_listxattr,
+       .removexattr    = generic_removexattr,
        .fallocate      = ocfs2_fallocate,
        .fiemap         = ocfs2_fiemap,
 };
@@ -2237,6 +2089,10 @@ const struct inode_operations ocfs2_special_file_iops = {
        .permission     = ocfs2_permission,
 };
 
+/*
+ * Other than ->lock, keep ocfs2_fops and ocfs2_dops in sync with
+ * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
+ */
 const struct file_operations ocfs2_fops = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
@@ -2251,6 +2107,7 @@ const struct file_operations ocfs2_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ocfs2_compat_ioctl,
 #endif
+       .lock           = ocfs2_lock,
        .flock          = ocfs2_flock,
        .splice_read    = ocfs2_file_splice_read,
        .splice_write   = ocfs2_file_splice_write,
@@ -2266,6 +2123,52 @@ const struct file_operations ocfs2_dops = {
        .unlocked_ioctl = ocfs2_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ocfs2_compat_ioctl,
+#endif
+       .lock           = ocfs2_lock,
+       .flock          = ocfs2_flock,
+};
+
+/*
+ * POSIX-lockless variants of our file_operations.
+ *
+ * These will be used if the underlying cluster stack does not support
+ * posix file locking, if the user passes the "localflocks" mount
+ * option, or if we have a local-only fs.
+ *
+ * ocfs2_flock is in here because all stacks handle UNIX file locks,
+ * so we still want it in the case of no stack support for
+ * plocks. Internally, it will do the right thing when asked to ignore
+ * the cluster.
+ */
+const struct file_operations ocfs2_fops_no_plocks = {
+       .llseek         = generic_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .mmap           = ocfs2_mmap,
+       .fsync          = ocfs2_sync_file,
+       .release        = ocfs2_file_release,
+       .open           = ocfs2_file_open,
+       .aio_read       = ocfs2_file_aio_read,
+       .aio_write      = ocfs2_file_aio_write,
+       .unlocked_ioctl = ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ocfs2_compat_ioctl,
+#endif
+       .flock          = ocfs2_flock,
+       .splice_read    = ocfs2_file_splice_read,
+       .splice_write   = ocfs2_file_splice_write,
+};
+
+const struct file_operations ocfs2_dops_no_plocks = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .readdir        = ocfs2_readdir,
+       .fsync          = ocfs2_sync_file,
+       .release        = ocfs2_dir_release,
+       .open           = ocfs2_dir_open,
+       .unlocked_ioctl = ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ocfs2_compat_ioctl,
 #endif
        .flock          = ocfs2_flock,
 };
index 1e27b4d017ea49401ec43445a29d62bcd6b219ce..e92382cbca5fb94c20b963d465c90853a8ab84de 100644 (file)
 
 extern const struct file_operations ocfs2_fops;
 extern const struct file_operations ocfs2_dops;
+extern const struct file_operations ocfs2_fops_no_plocks;
+extern const struct file_operations ocfs2_dops_no_plocks;
 extern const struct inode_operations ocfs2_file_iops;
 extern const struct inode_operations ocfs2_special_file_iops;
 struct ocfs2_alloc_context;
+enum ocfs2_alloc_restarted;
 
 struct ocfs2_file_private {
        struct file             *fp_file;
@@ -38,27 +41,18 @@ struct ocfs2_file_private {
        struct ocfs2_lock_res   fp_flock;
 };
 
-enum ocfs2_alloc_restarted {
-       RESTART_NONE = 0,
-       RESTART_TRANS,
-       RESTART_META
-};
-int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
-                              struct inode *inode,
-                              u32 *logical_offset,
-                              u32 clusters_to_add,
-                              int mark_unwritten,
-                              struct buffer_head *fe_bh,
-                              handle_t *handle,
-                              struct ocfs2_alloc_context *data_ac,
-                              struct ocfs2_alloc_context *meta_ac,
-                              enum ocfs2_alloc_restarted *reason_ret);
+int ocfs2_add_inode_data(struct ocfs2_super *osb,
+                        struct inode *inode,
+                        u32 *logical_offset,
+                        u32 clusters_to_add,
+                        int mark_unwritten,
+                        struct buffer_head *fe_bh,
+                        handle_t *handle,
+                        struct ocfs2_alloc_context *data_ac,
+                        struct ocfs2_alloc_context *meta_ac,
+                        enum ocfs2_alloc_restarted *reason_ret);
 int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size,
                          u64 zero_to);
-int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
-                         u32 clusters_to_add, u32 extents_to_split,
-                         struct ocfs2_alloc_context **data_ac,
-                         struct ocfs2_alloc_context **meta_ac);
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
 int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
                  struct kstat *stat);
index 7e9e4c79aec7bf4b3e4488190f47972821a3945f..4903688f72a9314f03ab66183de3104b54a3eed1 100644 (file)
@@ -49,6 +49,7 @@
 #include "symlink.h"
 #include "sysfile.h"
 #include "uptodate.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -219,6 +220,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        struct super_block *sb;
        struct ocfs2_super *osb;
        int status = -EINVAL;
+       int use_plocks = 1;
 
        mlog_entry("(0x%p, size:%llu)\n", inode,
                   (unsigned long long)le64_to_cpu(fe->i_size));
@@ -226,6 +228,10 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        sb = inode->i_sb;
        osb = OCFS2_SB(sb);
 
+       if ((osb->s_mount_opt & OCFS2_MOUNT_LOCALFLOCKS) ||
+           ocfs2_mount_local(osb) || !ocfs2_stack_supports_plocks())
+               use_plocks = 0;
+
        /* this means that read_inode cannot create a superblock inode
         * today.  change if needed. */
        if (!OCFS2_IS_VALID_DINODE(fe) ||
@@ -295,13 +301,19 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
 
        switch (inode->i_mode & S_IFMT) {
            case S_IFREG:
-                   inode->i_fop = &ocfs2_fops;
+                   if (use_plocks)
+                           inode->i_fop = &ocfs2_fops;
+                   else
+                           inode->i_fop = &ocfs2_fops_no_plocks;
                    inode->i_op = &ocfs2_file_iops;
                    i_size_write(inode, le64_to_cpu(fe->i_size));
                    break;
            case S_IFDIR:
                    inode->i_op = &ocfs2_dir_iops;
-                   inode->i_fop = &ocfs2_dops;
+                   if (use_plocks)
+                           inode->i_fop = &ocfs2_dops;
+                   else
+                           inode->i_fop = &ocfs2_dops_no_plocks;
                    i_size_write(inode, le64_to_cpu(fe->i_size));
                    break;
            case S_IFLNK:
@@ -448,8 +460,11 @@ static int ocfs2_read_locked_inode(struct inode *inode,
                }
        }
 
-       status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0,
-                                 can_lock ? inode : NULL);
+       if (can_lock)
+               status = ocfs2_read_blocks(inode, args->fi_blkno, 1, &bh,
+                                          OCFS2_BH_IGNORE_CACHE);
+       else
+               status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -522,6 +537,9 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
         * data and fast symlinks.
         */
        if (fe->i_clusters) {
+               if (ocfs2_should_order_data(inode))
+                       ocfs2_begin_ordered_truncate(inode, 0);
+
                handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
                if (IS_ERR(handle)) {
                        status = PTR_ERR(handle);
@@ -730,6 +748,13 @@ static int ocfs2_wipe_inode(struct inode *inode,
                goto bail_unlock_dir;
        }
 
+       /*Free extended attribute resources associated with this inode.*/
+       status = ocfs2_xattr_remove(inode, di_bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto bail_unlock_dir;
+       }
+
        status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
                                    orphan_dir_bh);
        if (status < 0)
@@ -1081,6 +1106,8 @@ void ocfs2_clear_inode(struct inode *inode)
        oi->ip_last_trans = 0;
        oi->ip_dir_start_lookup = 0;
        oi->ip_blkno = 0ULL;
+       jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal,
+                                      &oi->ip_jinode);
 
 bail:
        mlog_exit_void();
@@ -1106,58 +1133,6 @@ void ocfs2_drop_inode(struct inode *inode)
        mlog_exit_void();
 }
 
-/*
- * TODO: this should probably be merged into ocfs2_get_block
- *
- * However, you now need to pay attention to the cont_prepare_write()
- * stuff in ocfs2_get_block (that is, ocfs2_get_block pretty much
- * expects never to extend).
- */
-struct buffer_head *ocfs2_bread(struct inode *inode,
-                               int block, int *err, int reada)
-{
-       struct buffer_head *bh = NULL;
-       int tmperr;
-       u64 p_blkno;
-       int readflags = OCFS2_BH_CACHED;
-
-       if (reada)
-               readflags |= OCFS2_BH_READAHEAD;
-
-       if (((u64)block << inode->i_sb->s_blocksize_bits) >=
-           i_size_read(inode)) {
-               BUG_ON(!reada);
-               return NULL;
-       }
-
-       down_read(&OCFS2_I(inode)->ip_alloc_sem);
-       tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
-                                            NULL);
-       up_read(&OCFS2_I(inode)->ip_alloc_sem);
-       if (tmperr < 0) {
-               mlog_errno(tmperr);
-               goto fail;
-       }
-
-       tmperr = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, &bh,
-                                 readflags, inode);
-       if (tmperr < 0)
-               goto fail;
-
-       tmperr = 0;
-
-       *err = 0;
-       return bh;
-
-fail:
-       if (bh) {
-               brelse(bh);
-               bh = NULL;
-       }
-       *err = -EIO;
-       return NULL;
-}
-
 /*
  * This is called from our getattr.
  */
index 390a85596aa01841a5546e9464aa7a24cfcc23ea..2f37af9bcc4aa262197ca0f3108941c4d7d551fb 100644 (file)
@@ -40,6 +40,9 @@ struct ocfs2_inode_info
        /* protects allocation changes on this inode. */
        struct rw_semaphore             ip_alloc_sem;
 
+       /* protects extended attribute changes on this inode */
+       struct rw_semaphore             ip_xattr_sem;
+
        /* These fields are protected by ip_lock */
        spinlock_t                      ip_lock;
        u32                             ip_open_count;
@@ -68,6 +71,7 @@ struct ocfs2_inode_info
        struct ocfs2_extent_map         ip_extent_map;
 
        struct inode                    vfs_inode;
+       struct jbd2_inode               ip_jinode;
 };
 
 /*
@@ -113,8 +117,6 @@ extern struct kmem_cache *ocfs2_inode_cache;
 
 extern const struct address_space_operations ocfs2_aops;
 
-struct buffer_head *ocfs2_bread(struct inode *inode, int block,
-                               int *err, int reada);
 void ocfs2_clear_inode(struct inode *inode);
 void ocfs2_delete_inode(struct inode *inode);
 void ocfs2_drop_inode(struct inode *inode);
index 7b142f0ce995bd07a5116567a0b2b56e65b8dd1b..9fcd36dcc9a05920e5cc3f2d4d001d5bc8a82120 100644 (file)
@@ -102,8 +102,7 @@ bail_unlock:
 bail:
        mutex_unlock(&inode->i_mutex);
 
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
index c47bc2a809c2493703563f7f88e2b4f8a5bf1f9c..81e40677eecbddf989722e51f0336f43d6f84ff8 100644 (file)
@@ -215,9 +215,9 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb)
                goto finally;
        }
 
-       journal_lock_updates(journal->j_journal);
-       status = journal_flush(journal->j_journal);
-       journal_unlock_updates(journal->j_journal);
+       jbd2_journal_lock_updates(journal->j_journal);
+       status = jbd2_journal_flush(journal->j_journal);
+       jbd2_journal_unlock_updates(journal->j_journal);
        if (status < 0) {
                up_write(&journal->j_trans_barrier);
                mlog_errno(status);
@@ -264,7 +264,7 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, int max_buffs)
 
        down_read(&osb->journal->j_trans_barrier);
 
-       handle = journal_start(journal, max_buffs);
+       handle = jbd2_journal_start(journal, max_buffs);
        if (IS_ERR(handle)) {
                up_read(&osb->journal->j_trans_barrier);
 
@@ -290,7 +290,7 @@ int ocfs2_commit_trans(struct ocfs2_super *osb,
 
        BUG_ON(!handle);
 
-       ret = journal_stop(handle);
+       ret = jbd2_journal_stop(handle);
        if (ret < 0)
                mlog_errno(ret);
 
@@ -304,7 +304,7 @@ int ocfs2_commit_trans(struct ocfs2_super *osb,
  * transaction. extend_trans will either extend the current handle by
  * nblocks, or commit it and start a new one with nblocks credits.
  *
- * This might call journal_restart() which will commit dirty buffers
+ * This might call jbd2_journal_restart() which will commit dirty buffers
  * and then restart the transaction. Before calling
  * ocfs2_extend_trans(), any changed blocks should have been
  * dirtied. After calling it, all blocks which need to be changed must
@@ -332,7 +332,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
 #ifdef CONFIG_OCFS2_DEBUG_FS
        status = 1;
 #else
-       status = journal_extend(handle, nblocks);
+       status = jbd2_journal_extend(handle, nblocks);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -340,8 +340,10 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks)
 #endif
 
        if (status > 0) {
-               mlog(0, "journal_extend failed, trying journal_restart\n");
-               status = journal_restart(handle, nblocks);
+               mlog(0,
+                    "jbd2_journal_extend failed, trying "
+                    "jbd2_journal_restart\n");
+               status = jbd2_journal_restart(handle, nblocks);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -393,11 +395,11 @@ int ocfs2_journal_access(handle_t *handle,
        switch (type) {
        case OCFS2_JOURNAL_ACCESS_CREATE:
        case OCFS2_JOURNAL_ACCESS_WRITE:
-               status = journal_get_write_access(handle, bh);
+               status = jbd2_journal_get_write_access(handle, bh);
                break;
 
        case OCFS2_JOURNAL_ACCESS_UNDO:
-               status = journal_get_undo_access(handle, bh);
+               status = jbd2_journal_get_undo_access(handle, bh);
                break;
 
        default:
@@ -422,7 +424,7 @@ int ocfs2_journal_dirty(handle_t *handle,
        mlog_entry("(bh->b_blocknr=%llu)\n",
                   (unsigned long long)bh->b_blocknr);
 
-       status = journal_dirty_metadata(handle, bh);
+       status = jbd2_journal_dirty_metadata(handle, bh);
        if (status < 0)
                mlog(ML_ERROR, "Could not dirty metadata buffer. "
                     "(bh->b_blocknr=%llu)\n",
@@ -432,6 +434,7 @@ int ocfs2_journal_dirty(handle_t *handle,
        return status;
 }
 
+#ifdef CONFIG_OCFS2_COMPAT_JBD
 int ocfs2_journal_dirty_data(handle_t *handle,
                             struct buffer_head *bh)
 {
@@ -443,8 +446,9 @@ int ocfs2_journal_dirty_data(handle_t *handle,
 
        return err;
 }
+#endif
 
-#define OCFS2_DEFAULT_COMMIT_INTERVAL  (HZ * JBD_DEFAULT_MAX_COMMIT_AGE)
+#define OCFS2_DEFAULT_COMMIT_INTERVAL  (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE)
 
 void ocfs2_set_journal_params(struct ocfs2_super *osb)
 {
@@ -457,9 +461,9 @@ void ocfs2_set_journal_params(struct ocfs2_super *osb)
        spin_lock(&journal->j_state_lock);
        journal->j_commit_interval = commit_interval;
        if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
-               journal->j_flags |= JFS_BARRIER;
+               journal->j_flags |= JBD2_BARRIER;
        else
-               journal->j_flags &= ~JFS_BARRIER;
+               journal->j_flags &= ~JBD2_BARRIER;
        spin_unlock(&journal->j_state_lock);
 }
 
@@ -524,14 +528,14 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
        mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters);
 
        /* call the kernels journal init function now */
-       j_journal = journal_init_inode(inode);
+       j_journal = jbd2_journal_init_inode(inode);
        if (j_journal == NULL) {
                mlog(ML_ERROR, "Linux journal layer error\n");
                status = -EINVAL;
                goto done;
        }
 
-       mlog(0, "Returned from journal_init_inode\n");
+       mlog(0, "Returned from jbd2_journal_init_inode\n");
        mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen);
 
        *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) &
@@ -550,8 +554,7 @@ done:
        if (status < 0) {
                if (inode_lock)
                        ocfs2_inode_unlock(inode, 1);
-               if (bh != NULL)
-                       brelse(bh);
+               brelse(bh);
                if (inode) {
                        OCFS2_I(inode)->ip_open_count--;
                        iput(inode);
@@ -639,7 +642,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
        if (journal->j_state != OCFS2_JOURNAL_LOADED)
                goto done;
 
-       /* need to inc inode use count as journal_destroy will iput. */
+       /* need to inc inode use count - jbd2_journal_destroy will iput. */
        if (!igrab(inode))
                BUG();
 
@@ -668,9 +671,9 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
        BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
 
        if (ocfs2_mount_local(osb)) {
-               journal_lock_updates(journal->j_journal);
-               status = journal_flush(journal->j_journal);
-               journal_unlock_updates(journal->j_journal);
+               jbd2_journal_lock_updates(journal->j_journal);
+               status = jbd2_journal_flush(journal->j_journal);
+               jbd2_journal_unlock_updates(journal->j_journal);
                if (status < 0)
                        mlog_errno(status);
        }
@@ -686,7 +689,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb)
        }
 
        /* Shutdown the kernel journal system */
-       journal_destroy(journal->j_journal);
+       jbd2_journal_destroy(journal->j_journal);
 
        OCFS2_I(inode)->ip_open_count--;
 
@@ -711,15 +714,15 @@ static void ocfs2_clear_journal_error(struct super_block *sb,
 {
        int olderr;
 
-       olderr = journal_errno(journal);
+       olderr = jbd2_journal_errno(journal);
        if (olderr) {
                mlog(ML_ERROR, "File system error %d recorded in "
                     "journal %u.\n", olderr, slot);
                mlog(ML_ERROR, "File system on device %s needs checking.\n",
                     sb->s_id);
 
-               journal_ack_err(journal);
-               journal_clear_err(journal);
+               jbd2_journal_ack_err(journal);
+               jbd2_journal_clear_err(journal);
        }
 }
 
@@ -734,7 +737,7 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed)
 
        osb = journal->j_osb;
 
-       status = journal_load(journal->j_journal);
+       status = jbd2_journal_load(journal->j_journal);
        if (status < 0) {
                mlog(ML_ERROR, "Failed to load journal!\n");
                goto done;
@@ -778,7 +781,7 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full)
 
        BUG_ON(!journal);
 
-       status = journal_wipe(journal->j_journal, full);
+       status = jbd2_journal_wipe(journal->j_journal, full);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -847,9 +850,8 @@ static int ocfs2_force_read_journal(struct inode *inode)
 
                /* We are reading journal data which should not
                 * be put in the uptodate cache */
-               status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
-                                          p_blkno, p_blocks, bhs, 0,
-                                          NULL);
+               status = ocfs2_read_blocks_sync(OCFS2_SB(inode->i_sb),
+                                               p_blkno, p_blocks, bhs);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -865,8 +867,7 @@ static int ocfs2_force_read_journal(struct inode *inode)
 
 bail:
        for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++)
-               if (bhs[i])
-                       brelse(bhs[i]);
+               brelse(bhs[i]);
        mlog_exit(status);
        return status;
 }
@@ -1133,7 +1134,8 @@ static int ocfs2_read_journal_inode(struct ocfs2_super *osb,
        }
        SET_INODE_JOURNAL(inode);
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, bh, 0, inode);
+       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1, bh,
+                                  OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1229,19 +1231,19 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        }
 
        mlog(0, "calling journal_init_inode\n");
-       journal = journal_init_inode(inode);
+       journal = jbd2_journal_init_inode(inode);
        if (journal == NULL) {
                mlog(ML_ERROR, "Linux journal layer error\n");
                status = -EIO;
                goto done;
        }
 
-       status = journal_load(journal);
+       status = jbd2_journal_load(journal);
        if (status < 0) {
                mlog_errno(status);
                if (!igrab(inode))
                        BUG();
-               journal_destroy(journal);
+               jbd2_journal_destroy(journal);
                goto done;
        }
 
@@ -1249,9 +1251,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
 
        /* wipe the journal */
        mlog(0, "flushing the journal.\n");
-       journal_lock_updates(journal);
-       status = journal_flush(journal);
-       journal_unlock_updates(journal);
+       jbd2_journal_lock_updates(journal);
+       status = jbd2_journal_flush(journal);
+       jbd2_journal_unlock_updates(journal);
        if (status < 0)
                mlog_errno(status);
 
@@ -1272,7 +1274,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        if (!igrab(inode))
                BUG();
 
-       journal_destroy(journal);
+       jbd2_journal_destroy(journal);
 
 done:
        /* drop the lock on this nodes journal */
@@ -1282,8 +1284,7 @@ done:
        if (inode)
                iput(inode);
 
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
index 2178ebffa05f62c85bb8251958d9b71c48370f0d..d4d14e9a3cea123718e9314c469d6c011a5884ca 100644 (file)
 #define OCFS2_JOURNAL_H
 
 #include <linux/fs.h>
-#include <linux/jbd.h>
+#ifndef CONFIG_OCFS2_COMPAT_JBD
+# include <linux/jbd2.h>
+#else
+# include <linux/jbd.h>
+# include "ocfs2_jbd_compat.h"
+#endif
 
 enum ocfs2_journal_state {
        OCFS2_JOURNAL_FREE = 0,
@@ -215,8 +220,8 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode)
  *                          buffer. Will have to call ocfs2_journal_dirty once
  *                          we've actually dirtied it. Type is one of . or .
  *  ocfs2_journal_dirty    - Mark a journalled buffer as having dirty data.
- *  ocfs2_journal_dirty_data - Indicate that a data buffer should go out before
- *                             the current handle commits.
+ *  ocfs2_jbd2_file_inode  - Mark an inode so that its data goes out before
+ *                           the current handle commits.
  */
 
 /* You must always start_trans with a number of buffs > 0, but it's
@@ -268,8 +273,10 @@ int                  ocfs2_journal_access(handle_t *handle,
  */
 int                  ocfs2_journal_dirty(handle_t *handle,
                                         struct buffer_head *bh);
+#ifdef CONFIG_OCFS2_COMPAT_JBD
 int                  ocfs2_journal_dirty_data(handle_t *handle,
                                              struct buffer_head *bh);
+#endif
 
 /*
  *  Credit Macros:
@@ -283,6 +290,9 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
 /* simple file updates like chmod, etc. */
 #define OCFS2_INODE_UPDATE_CREDITS 1
 
+/* extended attribute block update */
+#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
+
 /* group extend. inode update and last group update. */
 #define OCFS2_GROUP_EXTEND_CREDITS     (OCFS2_INODE_UPDATE_CREDITS + 1)
 
@@ -340,11 +350,23 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
 #define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3              \
                             + OCFS2_UNLINK_CREDITS)
 
+/* global bitmap dinode, group desc., relinked group,
+ * suballocator dinode, group desc., relinked group,
+ * dinode, xattr block */
+#define OCFS2_XATTR_BLOCK_CREATE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + \
+                                         + OCFS2_INODE_UPDATE_CREDITS \
+                                         + OCFS2_XATTR_BLOCK_UPDATE_CREDITS)
+
+/*
+ * Please note that the caller must make sure that root_el is the root
+ * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
+ * the result may be wrong.
+ */
 static inline int ocfs2_calc_extend_credits(struct super_block *sb,
-                                           struct ocfs2_dinode *fe,
+                                           struct ocfs2_extent_list *root_el,
                                            u32 bits_wanted)
 {
-       int bitmap_blocks, sysfile_bitmap_blocks, dinode_blocks;
+       int bitmap_blocks, sysfile_bitmap_blocks, extent_blocks;
 
        /* bitmap dinode, group desc. + relinked group. */
        bitmap_blocks = OCFS2_SUBALLOC_ALLOC;
@@ -355,16 +377,16 @@ static inline int ocfs2_calc_extend_credits(struct super_block *sb,
         * however many metadata chunks needed * a remaining suballoc
         * alloc. */
        sysfile_bitmap_blocks = 1 +
-               (OCFS2_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(fe);
+               (OCFS2_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(root_el);
 
        /* this does not include *new* metadata blocks, which are
-        * accounted for in sysfile_bitmap_blocks. fe +
+        * accounted for in sysfile_bitmap_blocks. root_el +
         * prev. last_eb_blk + blocks along edge of tree.
         * calc_symlink_credits passes because we just need 1
         * credit for the dinode there. */
-       dinode_blocks = 1 + 1 + le16_to_cpu(fe->id2.i_list.l_tree_depth);
+       extent_blocks = 1 + 1 + le16_to_cpu(root_el->l_tree_depth);
 
-       return bitmap_blocks + sysfile_bitmap_blocks + dinode_blocks;
+       return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks;
 }
 
 static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
@@ -415,4 +437,16 @@ static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
        return credits;
 }
 
+static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode)
+{
+       return jbd2_journal_file_inode(handle, &OCFS2_I(inode)->ip_jinode);
+}
+
+static inline int ocfs2_begin_ordered_truncate(struct inode *inode,
+                                              loff_t new_size)
+{
+       return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode,
+                                                  new_size);
+}
+
 #endif /* OCFS2_JOURNAL_H */
index 28e492e4ec88b913964ffd49bcda163fb4f7690f..687b28713c3253631b3588ceb41d90ca51cfa867 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/highmem.h>
 #include <linux/bitops.h>
+#include <linux/debugfs.h>
 
 #define MLOG_MASK_PREFIX ML_DISK_ALLOC
 #include <cluster/masklog.h>
@@ -47,8 +48,6 @@
 
 #define OCFS2_LOCAL_ALLOC(dinode)      (&((dinode)->id2.i_lab))
 
-static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb);
-
 static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);
 
 static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
@@ -75,24 +74,129 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
                                          struct inode *local_alloc_inode);
 
-static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb)
+#ifdef CONFIG_OCFS2_FS_STATS
+
+static int ocfs2_la_debug_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+#define LA_DEBUG_BUF_SZ        PAGE_CACHE_SIZE
+#define LA_DEBUG_VER   1
+static ssize_t ocfs2_la_debug_read(struct file *file, char __user *userbuf,
+                                  size_t count, loff_t *ppos)
+{
+       static DEFINE_MUTEX(la_debug_mutex);
+       struct ocfs2_super *osb = file->private_data;
+       int written, ret;
+       char *buf = osb->local_alloc_debug_buf;
+
+       mutex_lock(&la_debug_mutex);
+       memset(buf, 0, LA_DEBUG_BUF_SZ);
+
+       written = snprintf(buf, LA_DEBUG_BUF_SZ,
+                          "0x%x\t0x%llx\t%u\t%u\t0x%x\n",
+                          LA_DEBUG_VER,
+                          (unsigned long long)osb->la_last_gd,
+                          osb->local_alloc_default_bits,
+                          osb->local_alloc_bits, osb->local_alloc_state);
+
+       ret = simple_read_from_buffer(userbuf, count, ppos, buf, written);
+
+       mutex_unlock(&la_debug_mutex);
+       return ret;
+}
+
+static const struct file_operations ocfs2_la_debug_fops = {
+       .open =         ocfs2_la_debug_open,
+       .read =         ocfs2_la_debug_read,
+};
+
+static void ocfs2_init_la_debug(struct ocfs2_super *osb)
+{
+       osb->local_alloc_debug_buf = kmalloc(LA_DEBUG_BUF_SZ, GFP_NOFS);
+       if (!osb->local_alloc_debug_buf)
+               return;
+
+       osb->local_alloc_debug = debugfs_create_file("local_alloc_stats",
+                                                    S_IFREG|S_IRUSR,
+                                                    osb->osb_debug_root,
+                                                    osb,
+                                                    &ocfs2_la_debug_fops);
+       if (!osb->local_alloc_debug) {
+               kfree(osb->local_alloc_debug_buf);
+               osb->local_alloc_debug_buf = NULL;
+       }
+}
+
+static void ocfs2_shutdown_la_debug(struct ocfs2_super *osb)
+{
+       if (osb->local_alloc_debug)
+               debugfs_remove(osb->local_alloc_debug);
+
+       if (osb->local_alloc_debug_buf)
+               kfree(osb->local_alloc_debug_buf);
+
+       osb->local_alloc_debug_buf = NULL;
+       osb->local_alloc_debug = NULL;
+}
+#else  /* CONFIG_OCFS2_FS_STATS */
+static void ocfs2_init_la_debug(struct ocfs2_super *osb)
+{
+       return;
+}
+static void ocfs2_shutdown_la_debug(struct ocfs2_super *osb)
+{
+       return;
+}
+#endif
+
+static inline int ocfs2_la_state_enabled(struct ocfs2_super *osb)
 {
-       BUG_ON(osb->s_clustersize_bits > 20);
+       return (osb->local_alloc_state == OCFS2_LA_THROTTLED ||
+               osb->local_alloc_state == OCFS2_LA_ENABLED);
+}
 
-       /* Size local alloc windows by the megabyte */
-       return osb->local_alloc_size << (20 - osb->s_clustersize_bits);
+void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb,
+                                     unsigned int num_clusters)
+{
+       spin_lock(&osb->osb_lock);
+       if (osb->local_alloc_state == OCFS2_LA_DISABLED ||
+           osb->local_alloc_state == OCFS2_LA_THROTTLED)
+               if (num_clusters >= osb->local_alloc_default_bits) {
+                       cancel_delayed_work(&osb->la_enable_wq);
+                       osb->local_alloc_state = OCFS2_LA_ENABLED;
+               }
+       spin_unlock(&osb->osb_lock);
+}
+
+void ocfs2_la_enable_worker(struct work_struct *work)
+{
+       struct ocfs2_super *osb =
+               container_of(work, struct ocfs2_super,
+                            la_enable_wq.work);
+       spin_lock(&osb->osb_lock);
+       osb->local_alloc_state = OCFS2_LA_ENABLED;
+       spin_unlock(&osb->osb_lock);
 }
 
 /*
  * Tell us whether a given allocation should use the local alloc
  * file. Otherwise, it has to go to the main bitmap.
+ *
+ * This function does semi-dirty reads of local alloc size and state!
+ * This is ok however, as the values are re-checked once under mutex.
  */
 int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
 {
-       int la_bits = ocfs2_local_alloc_window_bits(osb);
        int ret = 0;
+       int la_bits;
+
+       spin_lock(&osb->osb_lock);
+       la_bits = osb->local_alloc_bits;
 
-       if (osb->local_alloc_state != OCFS2_LA_ENABLED)
+       if (!ocfs2_la_state_enabled(osb))
                goto bail;
 
        /* la_bits should be at least twice the size (in clusters) of
@@ -106,6 +210,7 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
 bail:
        mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n",
             osb->local_alloc_state, (unsigned long long)bits, la_bits, ret);
+       spin_unlock(&osb->osb_lock);
        return ret;
 }
 
@@ -120,14 +225,18 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
 
        mlog_entry_void();
 
-       if (osb->local_alloc_size == 0)
+       ocfs2_init_la_debug(osb);
+
+       if (osb->local_alloc_bits == 0)
                goto bail;
 
-       if (ocfs2_local_alloc_window_bits(osb) >= osb->bitmap_cpg) {
+       if (osb->local_alloc_bits >= osb->bitmap_cpg) {
                mlog(ML_NOTICE, "Requested local alloc window %d is larger "
                     "than max possible %u. Using defaults.\n",
-                    ocfs2_local_alloc_window_bits(osb), (osb->bitmap_cpg - 1));
-               osb->local_alloc_size = OCFS2_DEFAULT_LOCAL_ALLOC_SIZE;
+                    osb->local_alloc_bits, (osb->bitmap_cpg - 1));
+               osb->local_alloc_bits =
+                       ocfs2_megabytes_to_clusters(osb->sb,
+                                                   OCFS2_DEFAULT_LOCAL_ALLOC_SIZE);
        }
 
        /* read the alloc off disk */
@@ -139,8 +248,8 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
                goto bail;
        }
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
-                                 &alloc_bh, 0, inode);
+       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
+                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -185,13 +294,14 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb)
 
 bail:
        if (status < 0)
-               if (alloc_bh)
-                       brelse(alloc_bh);
+               brelse(alloc_bh);
        if (inode)
                iput(inode);
 
-       mlog(0, "Local alloc window bits = %d\n",
-            ocfs2_local_alloc_window_bits(osb));
+       if (status < 0)
+               ocfs2_shutdown_la_debug(osb);
+
+       mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits);
 
        mlog_exit(status);
        return status;
@@ -217,6 +327,11 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
 
        mlog_entry_void();
 
+       cancel_delayed_work(&osb->la_enable_wq);
+       flush_workqueue(ocfs2_wq);
+
+       ocfs2_shutdown_la_debug(osb);
+
        if (osb->local_alloc_state == OCFS2_LA_UNUSED)
                goto out;
 
@@ -295,8 +410,7 @@ out_commit:
        ocfs2_commit_trans(osb, handle);
 
 out_unlock:
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        ocfs2_inode_unlock(main_bm_inode, 1);
 
@@ -345,8 +459,8 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
 
        mutex_lock(&inode->i_mutex);
 
-       status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
-                                 &alloc_bh, 0, inode);
+       status = ocfs2_read_blocks(inode, OCFS2_I(inode)->ip_blkno, 1,
+                                  &alloc_bh, OCFS2_BH_IGNORE_CACHE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -372,8 +486,7 @@ bail:
                *alloc_copy = NULL;
        }
 
-       if (alloc_bh)
-               brelse(alloc_bh);
+       brelse(alloc_bh);
 
        if (inode) {
                mutex_unlock(&inode->i_mutex);
@@ -441,8 +554,7 @@ out_unlock:
 out_mutex:
        mutex_unlock(&main_bm_inode->i_mutex);
 
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        iput(main_bm_inode);
 
@@ -453,8 +565,48 @@ out:
        return status;
 }
 
+/* Check to see if the local alloc window is within ac->ac_max_block */
+static int ocfs2_local_alloc_in_range(struct inode *inode,
+                                     struct ocfs2_alloc_context *ac,
+                                     u32 bits_wanted)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_dinode *alloc;
+       struct ocfs2_local_alloc *la;
+       int start;
+       u64 block_off;
+
+       if (!ac->ac_max_block)
+               return 1;
+
+       alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+       la = OCFS2_LOCAL_ALLOC(alloc);
+
+       start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+       if (start == -1) {
+               mlog_errno(-ENOSPC);
+               return 0;
+       }
+
+       /*
+        * Converting (bm_off + start + bits_wanted) to blocks gives us
+        * the blkno just past our actual allocation.  This is perfect
+        * to compare with ac_max_block.
+        */
+       block_off = ocfs2_clusters_to_blocks(inode->i_sb,
+                                            le32_to_cpu(la->la_bm_off) +
+                                            start + bits_wanted);
+       mlog(0, "Checking %llu against %llu\n",
+            (unsigned long long)block_off,
+            (unsigned long long)ac->ac_max_block);
+       if (block_off > ac->ac_max_block)
+               return 0;
+
+       return 1;
+}
+
 /*
- * make sure we've got at least bitswanted contiguous bits in the
+ * make sure we've got at least bits_wanted contiguous bits in the
  * local alloc. You lose them when you drop i_mutex.
  *
  * We will add ourselves to the transaction passed in, but may start
@@ -485,16 +637,18 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
 
        mutex_lock(&local_alloc_inode->i_mutex);
 
-       if (osb->local_alloc_state != OCFS2_LA_ENABLED) {
-               status = -ENOSPC;
-               goto bail;
-       }
-
-       if (bits_wanted > ocfs2_local_alloc_window_bits(osb)) {
-               mlog(0, "Asking for more than my max window size!\n");
+       /*
+        * We must double check state and allocator bits because
+        * another process may have changed them while holding i_mutex.
+        */
+       spin_lock(&osb->osb_lock);
+       if (!ocfs2_la_state_enabled(osb) ||
+           (bits_wanted > osb->local_alloc_bits)) {
+               spin_unlock(&osb->osb_lock);
                status = -ENOSPC;
                goto bail;
        }
+       spin_unlock(&osb->osb_lock);
 
        alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
 
@@ -522,6 +676,36 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
                                mlog_errno(status);
                        goto bail;
                }
+
+               /*
+                * Under certain conditions, the window slide code
+                * might have reduced the number of bits available or
+                * disabled the the local alloc entirely. Re-check
+                * here and return -ENOSPC if necessary.
+                */
+               status = -ENOSPC;
+               if (!ocfs2_la_state_enabled(osb))
+                       goto bail;
+
+               free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
+                       le32_to_cpu(alloc->id1.bitmap1.i_used);
+               if (bits_wanted > free_bits)
+                       goto bail;
+       }
+
+       if (ac->ac_max_block)
+               mlog(0, "Calling in_range for max block %llu\n",
+                    (unsigned long long)ac->ac_max_block);
+
+       if (!ocfs2_local_alloc_in_range(local_alloc_inode, ac,
+                                       bits_wanted)) {
+               /*
+                * The window is outside ac->ac_max_block.
+                * This errno tells the caller to keep localalloc enabled
+                * but to get the allocation from the main bitmap.
+                */
+               status = -EFBIG;
+               goto bail;
        }
 
        ac->ac_inode = local_alloc_inode;
@@ -789,6 +973,85 @@ bail:
        return status;
 }
 
+enum ocfs2_la_event {
+       OCFS2_LA_EVENT_SLIDE,           /* Normal window slide. */
+       OCFS2_LA_EVENT_FRAGMENTED,      /* The global bitmap has
+                                        * enough bits theoretically
+                                        * free, but a contiguous
+                                        * allocation could not be
+                                        * found. */
+       OCFS2_LA_EVENT_ENOSPC,          /* Global bitmap doesn't have
+                                        * enough bits free to satisfy
+                                        * our request. */
+};
+#define OCFS2_LA_ENABLE_INTERVAL (30 * HZ)
+/*
+ * Given an event, calculate the size of our next local alloc window.
+ *
+ * This should always be called under i_mutex of the local alloc inode
+ * so that local alloc disabling doesn't race with processes trying to
+ * use the allocator.
+ *
+ * Returns the state which the local alloc was left in. This value can
+ * be ignored by some paths.
+ */
+static int ocfs2_recalc_la_window(struct ocfs2_super *osb,
+                                 enum ocfs2_la_event event)
+{
+       unsigned int bits;
+       int state;
+
+       spin_lock(&osb->osb_lock);
+       if (osb->local_alloc_state == OCFS2_LA_DISABLED) {
+               WARN_ON_ONCE(osb->local_alloc_state == OCFS2_LA_DISABLED);
+               goto out_unlock;
+       }
+
+       /*
+        * ENOSPC and fragmentation are treated similarly for now.
+        */
+       if (event == OCFS2_LA_EVENT_ENOSPC ||
+           event == OCFS2_LA_EVENT_FRAGMENTED) {
+               /*
+                * We ran out of contiguous space in the primary
+                * bitmap. Drastically reduce the number of bits used
+                * by local alloc until we have to disable it.
+                */
+               bits = osb->local_alloc_bits >> 1;
+               if (bits > ocfs2_megabytes_to_clusters(osb->sb, 1)) {
+                       /*
+                        * By setting state to THROTTLED, we'll keep
+                        * the number of local alloc bits used down
+                        * until an event occurs which would give us
+                        * reason to assume the bitmap situation might
+                        * have changed.
+                        */
+                       osb->local_alloc_state = OCFS2_LA_THROTTLED;
+                       osb->local_alloc_bits = bits;
+               } else {
+                       osb->local_alloc_state = OCFS2_LA_DISABLED;
+               }
+               queue_delayed_work(ocfs2_wq, &osb->la_enable_wq,
+                                  OCFS2_LA_ENABLE_INTERVAL);
+               goto out_unlock;
+       }
+
+       /*
+        * Don't increase the size of the local alloc window until we
+        * know we might be able to fulfill the request. Otherwise, we
+        * risk bouncing around the global bitmap during periods of
+        * low space.
+        */
+       if (osb->local_alloc_state != OCFS2_LA_THROTTLED)
+               osb->local_alloc_bits = osb->local_alloc_default_bits;
+
+out_unlock:
+       state = osb->local_alloc_state;
+       spin_unlock(&osb->osb_lock);
+
+       return state;
+}
+
 static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
                                                struct ocfs2_alloc_context **ac,
                                                struct inode **bitmap_inode,
@@ -803,12 +1066,21 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
                goto bail;
        }
 
-       (*ac)->ac_bits_wanted = ocfs2_local_alloc_window_bits(osb);
+retry_enospc:
+       (*ac)->ac_bits_wanted = osb->local_alloc_bits;
 
        status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
+       if (status == -ENOSPC) {
+               if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
+                   OCFS2_LA_DISABLED)
+                       goto bail;
+
+               ocfs2_free_ac_resource(*ac);
+               memset(*ac, 0, sizeof(struct ocfs2_alloc_context));
+               goto retry_enospc;
+       }
        if (status < 0) {
-               if (status != -ENOSPC)
-                       mlog_errno(status);
+               mlog_errno(status);
                goto bail;
        }
 
@@ -849,7 +1121,7 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
                     "one\n");
 
        mlog(0, "Allocating %u clusters for a new window.\n",
-            ocfs2_local_alloc_window_bits(osb));
+            osb->local_alloc_bits);
 
        /* Instruct the allocation code to try the most recently used
         * cluster group. We'll re-record the group used this pass
@@ -859,9 +1131,36 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
        /* we used the generic suballoc reserve function, but we set
         * everything up nicely, so there's no reason why we can't use
         * the more specific cluster api to claim bits. */
-       status = ocfs2_claim_clusters(osb, handle, ac,
-                                     ocfs2_local_alloc_window_bits(osb),
+       status = ocfs2_claim_clusters(osb, handle, ac, osb->local_alloc_bits,
                                      &cluster_off, &cluster_count);
+       if (status == -ENOSPC) {
+retry_enospc:
+               /*
+                * Note: We could also try syncing the journal here to
+                * allow use of any free bits which the current
+                * transaction can't give us access to. --Mark
+                */
+               if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_FRAGMENTED) ==
+                   OCFS2_LA_DISABLED)
+                       goto bail;
+
+               status = ocfs2_claim_clusters(osb, handle, ac,
+                                             osb->local_alloc_bits,
+                                             &cluster_off,
+                                             &cluster_count);
+               if (status == -ENOSPC)
+                       goto retry_enospc;
+               /*
+                * We only shrunk the *minimum* number of in our
+                * request - it's entirely possible that the allocator
+                * might give us more than we asked for.
+                */
+               if (status == 0) {
+                       spin_lock(&osb->osb_lock);
+                       osb->local_alloc_bits = cluster_count;
+                       spin_unlock(&osb->osb_lock);
+               }
+       }
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -905,6 +1204,8 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
+       ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_SLIDE);
+
        /* This will lock the main bitmap for us. */
        status = ocfs2_local_alloc_reserve_for_window(osb,
                                                      &ac,
@@ -976,8 +1277,7 @@ bail:
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
-       if (main_bm_bh)
-               brelse(main_bm_bh);
+       brelse(main_bm_bh);
 
        if (main_bm_inode)
                iput(main_bm_inode);
index 3f76631e110c5a6284963cfe186b2c9a0917dabd..ac5ea9f8665342013335591dffc6177c8d193727 100644 (file)
@@ -52,4 +52,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
                                 u32 *bit_off,
                                 u32 *num_bits);
 
+void ocfs2_local_alloc_seen_free_bits(struct ocfs2_super *osb,
+                                     unsigned int num_clusters);
+void ocfs2_la_enable_worker(struct work_struct *work);
+
 #endif /* OCFS2_LOCALALLOC_H */
index 203f8714387799af46db9a3e6280cb0636a8c69b..544ac6245175f26c23249cf916c5001ae8f5d067 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/fcntl.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
@@ -32,6 +33,7 @@
 
 #include "dlmglue.h"
 #include "file.h"
+#include "inode.h"
 #include "locks.h"
 
 static int ocfs2_do_flock(struct file *file, struct inode *inode,
@@ -123,3 +125,16 @@ int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl)
        else
                return ocfs2_do_flock(file, inode, cmd, fl);
 }
+
+int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+       struct inode *inode = file->f_mapping->host;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (!(fl->fl_flags & FL_POSIX))
+               return -ENOLCK;
+       if (__mandatory_lock(inode))
+               return -ENOLCK;
+
+       return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
+}
index 9743ef2324ec98c377473801784745681a4209b4..496d488b271f8ed9736c901582ba2da0bb7ad561 100644 (file)
@@ -27,5 +27,6 @@
 #define OCFS2_LOCKS_H
 
 int ocfs2_flock(struct file *file, int cmd, struct file_lock *fl);
+int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl);
 
 #endif /* OCFS2_LOCKS_H */
index d5d808fe0140f7fb1e590c0255dd045542219bd1..485a6aa0ad39060e9eb27f2897be98026b886d4c 100644 (file)
@@ -60,6 +60,7 @@
 #include "symlink.h"
 #include "sysfile.h"
 #include "uptodate.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -327,14 +328,9 @@ leave:
        if (status == -ENOSPC)
                mlog(0, "Disk is full\n");
 
-       if (new_fe_bh)
-               brelse(new_fe_bh);
-
-       if (de_bh)
-               brelse(de_bh);
-
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
+       brelse(new_fe_bh);
+       brelse(de_bh);
+       brelse(parent_fe_bh);
 
        if ((status < 0) && inode)
                iput(inode);
@@ -647,12 +643,9 @@ out_unlock_inode:
 out:
        ocfs2_inode_unlock(dir, 1);
 
-       if (de_bh)
-               brelse(de_bh);
-       if (fe_bh)
-               brelse(fe_bh);
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
+       brelse(de_bh);
+       brelse(fe_bh);
+       brelse(parent_fe_bh);
 
        mlog_exit(err);
 
@@ -851,17 +844,10 @@ leave:
                iput(orphan_dir);
        }
 
-       if (fe_bh)
-               brelse(fe_bh);
-
-       if (dirent_bh)
-               brelse(dirent_bh);
-
-       if (parent_node_bh)
-               brelse(parent_node_bh);
-
-       if (orphan_entry_bh)
-               brelse(orphan_entry_bh);
+       brelse(fe_bh);
+       brelse(dirent_bh);
+       brelse(parent_node_bh);
+       brelse(orphan_entry_bh);
 
        mlog_exit(status);
 
@@ -1372,24 +1358,15 @@ bail:
 
        if (new_inode)
                iput(new_inode);
-       if (newfe_bh)
-               brelse(newfe_bh);
-       if (old_inode_bh)
-               brelse(old_inode_bh);
-       if (old_dir_bh)
-               brelse(old_dir_bh);
-       if (new_dir_bh)
-               brelse(new_dir_bh);
-       if (new_de_bh)
-               brelse(new_de_bh);
-       if (old_de_bh)
-               brelse(old_de_bh);
-       if (old_inode_de_bh)
-               brelse(old_inode_de_bh);
-       if (orphan_entry_bh)
-               brelse(orphan_entry_bh);
-       if (insert_entry_bh)
-               brelse(insert_entry_bh);
+       brelse(newfe_bh);
+       brelse(old_inode_bh);
+       brelse(old_dir_bh);
+       brelse(new_dir_bh);
+       brelse(new_de_bh);
+       brelse(old_de_bh);
+       brelse(old_inode_de_bh);
+       brelse(orphan_entry_bh);
+       brelse(insert_entry_bh);
 
        mlog_exit(status);
 
@@ -1492,8 +1469,7 @@ bail:
 
        if (bhs) {
                for(i = 0; i < blocks; i++)
-                       if (bhs[i])
-                               brelse(bhs[i]);
+                       brelse(bhs[i]);
                kfree(bhs);
        }
 
@@ -1598,10 +1574,10 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
-               status = ocfs2_do_extend_allocation(osb, inode, &offset, 1, 0,
-                                                   new_fe_bh,
-                                                   handle, data_ac, NULL,
-                                                   NULL);
+               status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
+                                             new_fe_bh,
+                                             handle, data_ac, NULL,
+                                             NULL);
                if (status < 0) {
                        if (status != -ENOSPC && status != -EINTR) {
                                mlog(ML_ERROR,
@@ -1659,12 +1635,9 @@ bail:
 
        ocfs2_inode_unlock(dir, 1);
 
-       if (new_fe_bh)
-               brelse(new_fe_bh);
-       if (parent_fe_bh)
-               brelse(parent_fe_bh);
-       if (de_bh)
-               brelse(de_bh);
+       brelse(new_fe_bh);
+       brelse(parent_fe_bh);
+       brelse(de_bh);
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
        if (data_ac)
@@ -1759,8 +1732,7 @@ leave:
                iput(orphan_dir_inode);
        }
 
-       if (orphan_dir_bh)
-               brelse(orphan_dir_bh);
+       brelse(orphan_dir_bh);
 
        mlog_exit(status);
        return status;
@@ -1780,10 +1752,9 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       status = ocfs2_read_block(osb,
+       status = ocfs2_read_block(orphan_dir_inode,
                                  OCFS2_I(orphan_dir_inode)->ip_blkno,
-                                 &orphan_dir_bh, OCFS2_BH_CACHED,
-                                 orphan_dir_inode);
+                                 &orphan_dir_bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1829,8 +1800,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
             (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
 
 leave:
-       if (orphan_dir_bh)
-               brelse(orphan_dir_bh);
+       brelse(orphan_dir_bh);
 
        mlog_exit(status);
        return status;
@@ -1898,8 +1868,7 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
        }
 
 leave:
-       if (target_de_bh)
-               brelse(target_de_bh);
+       brelse(target_de_bh);
 
        mlog_exit(status);
        return status;
@@ -1918,4 +1887,8 @@ const struct inode_operations ocfs2_dir_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = ocfs2_listxattr,
+       .removexattr    = generic_removexattr,
 };
index 7f625f2b11174c4d0963f4d73971343da1ee04f6..a21a465490c40d0ee0ef3fc3d554d9f2196bdac2 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/mutex.h>
-#include <linux/jbd.h>
+#ifndef CONFIG_OCFS2_COMPAT_JBD
+# include <linux/jbd2.h>
+#else
+# include <linux/jbd.h>
+# include "ocfs2_jbd_compat.h"
+#endif
 
 /* For union ocfs2_dlm_lksb */
 #include "stackglue.h"
@@ -171,9 +176,13 @@ struct ocfs2_alloc_stats
 
 enum ocfs2_local_alloc_state
 {
-       OCFS2_LA_UNUSED = 0,
-       OCFS2_LA_ENABLED,
-       OCFS2_LA_DISABLED
+       OCFS2_LA_UNUSED = 0,    /* Local alloc will never be used for
+                                * this mountpoint. */
+       OCFS2_LA_ENABLED,       /* Local alloc is in use. */
+       OCFS2_LA_THROTTLED,     /* Local alloc is in use, but number
+                                * of bits has been reduced. */
+       OCFS2_LA_DISABLED       /* Local alloc has temporarily been
+                                * disabled. */
 };
 
 enum ocfs2_mount_options
@@ -184,6 +193,8 @@ enum ocfs2_mount_options
        OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */
        OCFS2_MOUNT_DATA_WRITEBACK = 1 << 4, /* No data ordering */
        OCFS2_MOUNT_LOCALFLOCKS = 1 << 5, /* No cluster aware user file locks */
+       OCFS2_MOUNT_NOUSERXATTR = 1 << 6, /* No user xattr */
+       OCFS2_MOUNT_INODE64 = 1 << 7,   /* Allow inode numbers > 2^32 */
 };
 
 #define OCFS2_OSB_SOFT_RO      0x0001
@@ -214,6 +225,7 @@ struct ocfs2_super
        u32 bitmap_cpg;
        u8 *uuid;
        char *uuid_str;
+       u32 uuid_hash;
        u8 *vol_label;
        u64 first_cluster_group_blkno;
        u32 fs_generation;
@@ -241,6 +253,7 @@ struct ocfs2_super
        int s_sectsize_bits;
        int s_clustersize;
        int s_clustersize_bits;
+       unsigned int s_xattr_inline_size;
 
        atomic_t vol_state;
        struct mutex recovery_lock;
@@ -252,11 +265,27 @@ struct ocfs2_super
        struct ocfs2_journal *journal;
        unsigned long osb_commit_interval;
 
-       int local_alloc_size;
-       enum ocfs2_local_alloc_state local_alloc_state;
+       struct delayed_work             la_enable_wq;
+
+       /*
+        * Must hold local alloc i_mutex and osb->osb_lock to change
+        * local_alloc_bits. Reads can be done under either lock.
+        */
+       unsigned int local_alloc_bits;
+       unsigned int local_alloc_default_bits;
+
+       enum ocfs2_local_alloc_state local_alloc_state; /* protected
+                                                        * by osb_lock */
+
        struct buffer_head *local_alloc_bh;
+
        u64 la_last_gd;
 
+#ifdef CONFIG_OCFS2_FS_STATS
+       struct dentry *local_alloc_debug;
+       char *local_alloc_debug_buf;
+#endif
+
        /* Next two fields are for local node slot recovery during
         * mount. */
        int dirty;
@@ -340,6 +369,13 @@ static inline int ocfs2_supports_inline_data(struct ocfs2_super *osb)
        return 0;
 }
 
+static inline int ocfs2_supports_xattr(struct ocfs2_super *osb)
+{
+       if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_XATTR)
+               return 1;
+       return 0;
+}
+
 /* set / clear functions because cluster events can make these happen
  * in parallel so we want the transitions to be atomic. this also
  * means that any future flags osb_flags must be protected by spinlock
@@ -554,6 +590,14 @@ static inline unsigned int ocfs2_pages_per_cluster(struct super_block *sb)
        return pages_per_cluster;
 }
 
+static inline unsigned int ocfs2_megabytes_to_clusters(struct super_block *sb,
+                                                      unsigned int megs)
+{
+       BUILD_BUG_ON(OCFS2_MAX_CLUSTERSIZE > 1048576);
+
+       return megs << (20 - OCFS2_SB(sb)->s_clustersize_bits);
+}
+
 static inline void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb)
 {
        spin_lock(&osb->osb_lock);
index 4f619850ccf7fd8b80bf4888fc39849c6bb93d4b..f24ce3d3f956056c2a1173dd8121076cea3eb079 100644 (file)
@@ -64,6 +64,7 @@
 #define OCFS2_INODE_SIGNATURE          "INODE01"
 #define OCFS2_EXTENT_BLOCK_SIGNATURE   "EXBLK01"
 #define OCFS2_GROUP_DESC_SIGNATURE      "GROUP01"
+#define OCFS2_XATTR_BLOCK_SIGNATURE    "XATTR01"
 
 /* Compatibility flags */
 #define OCFS2_HAS_COMPAT_FEATURE(sb,mask)                      \
@@ -90,7 +91,8 @@
                                         | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
                                         | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
                                         | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP \
-                                        | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK)
+                                        | OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK \
+                                        | OCFS2_FEATURE_INCOMPAT_XATTR)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP   OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 
 /*
 /* Support for data packed into inode blocks */
 #define OCFS2_FEATURE_INCOMPAT_INLINE_DATA     0x0040
 
-/* Support for the extended slot map */
-#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP 0x100
-
-
 /*
  * Support for alternate, userspace cluster stacks.  If set, the superblock
  * field s_cluster_info contains a tag for the alternate stack in use as
  */
 #define OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK 0x0080
 
+/* Support for the extended slot map */
+#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP 0x100
+
+/* Support for extended attributes */
+#define OCFS2_FEATURE_INCOMPAT_XATTR           0x0200
+
 /*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
@@ -299,6 +303,12 @@ struct ocfs2_new_group_input {
  */
 #define OCFS2_DEFAULT_LOCAL_ALLOC_SIZE 8
 
+/*
+ * Inline extended attribute size (in bytes)
+ * The value chosen should be aligned to 16 byte boundaries.
+ */
+#define OCFS2_MIN_XATTR_INLINE_SIZE     256
+
 struct ocfs2_system_inode_info {
        char    *si_name;
        int     si_iflags;
@@ -563,7 +573,7 @@ struct ocfs2_super_block {
 /*40*/ __le16 s_max_slots;             /* Max number of simultaneous mounts
                                           before tunefs required */
        __le16 s_tunefs_flag;
-       __le32 s_reserved1;
+       __le32 s_uuid_hash;             /* hash value of uuid */
        __le64 s_first_cluster_group;   /* Block offset of 1st cluster
                                         * group header */
 /*50*/ __u8  s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
@@ -571,7 +581,11 @@ struct ocfs2_super_block {
 /*A0*/  struct ocfs2_cluster_info s_cluster_info; /* Selected userspace
                                                     stack.  Only valid
                                                     with INCOMPAT flag. */
-/*B8*/  __le64 s_reserved2[17];                /* Fill out superblock */
+/*B8*/ __le16 s_xattr_inline_size;     /* extended attribute inline size
+                                          for this fs*/
+       __le16 s_reserved0;
+       __le32 s_reserved1;
+/*C0*/  __le64 s_reserved2[16];                /* Fill out superblock */
 /*140*/
 
        /*
@@ -621,7 +635,8 @@ struct ocfs2_dinode {
                                           belongs to */
        __le16 i_suballoc_bit;          /* Bit offset in suballocator
                                           block group */
-/*10*/ __le32 i_reserved0;
+/*10*/ __le16 i_reserved0;
+       __le16 i_xattr_inline_size;
        __le32 i_clusters;              /* Cluster count */
        __le32 i_uid;                   /* Owner UID */
        __le32 i_gid;                   /* Owning GID */
@@ -640,11 +655,12 @@ struct ocfs2_dinode {
        __le32 i_atime_nsec;
        __le32 i_ctime_nsec;
        __le32 i_mtime_nsec;
-       __le32 i_attr;
+/*70*/ __le32 i_attr;
        __le16 i_orphaned_slot;         /* Only valid when OCFS2_ORPHANED_FL
                                           was set in i_flags */
        __le16 i_dyn_features;
-/*70*/ __le64 i_reserved2[8];
+       __le64 i_xattr_loc;
+/*80*/ __le64 i_reserved2[7];
 /*B8*/ union {
                __le64 i_pad1;          /* Generic way to refer to this
                                           64bit union */
@@ -715,6 +731,136 @@ struct ocfs2_group_desc
 /*40*/ __u8    bg_bitmap[0];
 };
 
+/*
+ * On disk extended attribute structure for OCFS2.
+ */
+
+/*
+ * ocfs2_xattr_entry indicates one extend attribute.
+ *
+ * Note that it can be stored in inode, one block or one xattr bucket.
+ */
+struct ocfs2_xattr_entry {
+       __le32  xe_name_hash;    /* hash value of xattr prefix+suffix. */
+       __le16  xe_name_offset;  /* byte offset from the 1st etnry in the local
+                                   local xattr storage(inode, xattr block or
+                                   xattr bucket). */
+       __u8    xe_name_len;     /* xattr name len, does't include prefix. */
+       __u8    xe_type;         /* the low 7 bits indicates the name prefix's
+                                 * type and the highest 1 bits indicate whether
+                                 * the EA is stored in the local storage. */
+       __le64  xe_value_size;   /* real xattr value length. */
+};
+
+/*
+ * On disk structure for xattr header.
+ *
+ * One ocfs2_xattr_header describes how many ocfs2_xattr_entry records in
+ * the local xattr storage.
+ */
+struct ocfs2_xattr_header {
+       __le16  xh_count;                       /* contains the count of how
+                                                  many records are in the
+                                                  local xattr storage. */
+       __le16  xh_free_start;                  /* current offset for storing
+                                                  xattr. */
+       __le16  xh_name_value_len;              /* total length of name/value
+                                                  length in this bucket. */
+       __le16  xh_num_buckets;                 /* bucket nums in one extent
+                                                  record, only valid in the
+                                                  first bucket. */
+       __le64  xh_csum;
+       struct ocfs2_xattr_entry xh_entries[0]; /* xattr entry list. */
+};
+
+/*
+ * On disk structure for xattr value root.
+ *
+ * It is used when one extended attribute's size is larger, and we will save it
+ * in an outside cluster. It will stored in a b-tree like file content.
+ */
+struct ocfs2_xattr_value_root {
+/*00*/ __le32  xr_clusters;              /* clusters covered by xattr value. */
+       __le32  xr_reserved0;
+       __le64  xr_last_eb_blk;           /* Pointer to last extent block */
+/*10*/ struct ocfs2_extent_list xr_list; /* Extent record list */
+};
+
+/*
+ * On disk structure for xattr tree root.
+ *
+ * It is used when there are too many extended attributes for one file. These
+ * attributes will be organized and stored in an indexed-btree.
+ */
+struct ocfs2_xattr_tree_root {
+/*00*/ __le32  xt_clusters;              /* clusters covered by xattr. */
+       __le32  xt_reserved0;
+       __le64  xt_last_eb_blk;           /* Pointer to last extent block */
+/*10*/ struct ocfs2_extent_list xt_list; /* Extent record list */
+};
+
+#define OCFS2_XATTR_INDEXED    0x1
+#define OCFS2_HASH_SHIFT       5
+#define OCFS2_XATTR_ROUND      3
+#define OCFS2_XATTR_SIZE(size) (((size) + OCFS2_XATTR_ROUND) & \
+                               ~(OCFS2_XATTR_ROUND))
+
+#define OCFS2_XATTR_BUCKET_SIZE                        4096
+#define OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET      (OCFS2_XATTR_BUCKET_SIZE \
+                                                / OCFS2_MIN_BLOCKSIZE)
+
+/*
+ * On disk structure for xattr block.
+ */
+struct ocfs2_xattr_block {
+/*00*/ __u8    xb_signature[8];     /* Signature for verification */
+       __le16  xb_suballoc_slot;    /* Slot suballocator this
+                                       block belongs to. */
+       __le16  xb_suballoc_bit;     /* Bit offset in suballocator
+                                       block group */
+       __le32  xb_fs_generation;    /* Must match super block */
+/*10*/ __le64  xb_blkno;            /* Offset on disk, in blocks */
+       __le64  xb_csum;
+/*20*/ __le16  xb_flags;            /* Indicates whether this block contains
+                                       real xattr or a xattr tree. */
+       __le16  xb_reserved0;
+       __le32  xb_reserved1;
+       __le64  xb_reserved2;
+/*30*/ union {
+               struct ocfs2_xattr_header xb_header; /* xattr header if this
+                                                       block contains xattr */
+               struct ocfs2_xattr_tree_root xb_root;/* xattr tree root if this
+                                                       block cotains xattr
+                                                       tree. */
+       } xb_attrs;
+};
+
+#define OCFS2_XATTR_ENTRY_LOCAL                0x80
+#define OCFS2_XATTR_TYPE_MASK          0x7F
+static inline void ocfs2_xattr_set_local(struct ocfs2_xattr_entry *xe,
+                                        int local)
+{
+       if (local)
+               xe->xe_type |= OCFS2_XATTR_ENTRY_LOCAL;
+       else
+               xe->xe_type &= ~OCFS2_XATTR_ENTRY_LOCAL;
+}
+
+static inline int ocfs2_xattr_is_local(struct ocfs2_xattr_entry *xe)
+{
+       return xe->xe_type & OCFS2_XATTR_ENTRY_LOCAL;
+}
+
+static inline void ocfs2_xattr_set_type(struct ocfs2_xattr_entry *xe, int type)
+{
+       xe->xe_type |= type & OCFS2_XATTR_TYPE_MASK;
+}
+
+static inline int ocfs2_xattr_get_type(struct ocfs2_xattr_entry *xe)
+{
+       return xe->xe_type & OCFS2_XATTR_TYPE_MASK;
+}
+
 #ifdef __KERNEL__
 static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
 {
@@ -728,6 +874,20 @@ static inline int ocfs2_max_inline_data(struct super_block *sb)
                offsetof(struct ocfs2_dinode, id2.i_data.id_data);
 }
 
+static inline int ocfs2_max_inline_data_with_xattr(struct super_block *sb,
+                                                  struct ocfs2_dinode *di)
+{
+       unsigned int xattrsize = le16_to_cpu(di->i_xattr_inline_size);
+
+       if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_XATTR_FL)
+               return sb->s_blocksize -
+                       offsetof(struct ocfs2_dinode, id2.i_data.id_data) -
+                       xattrsize;
+       else
+               return sb->s_blocksize -
+                       offsetof(struct ocfs2_dinode, id2.i_data.id_data);
+}
+
 static inline int ocfs2_extent_recs_per_inode(struct super_block *sb)
 {
        int size;
@@ -738,6 +898,24 @@ static inline int ocfs2_extent_recs_per_inode(struct super_block *sb)
        return size / sizeof(struct ocfs2_extent_rec);
 }
 
+static inline int ocfs2_extent_recs_per_inode_with_xattr(
+                                               struct super_block *sb,
+                                               struct ocfs2_dinode *di)
+{
+       int size;
+       unsigned int xattrsize = le16_to_cpu(di->i_xattr_inline_size);
+
+       if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_XATTR_FL)
+               size = sb->s_blocksize -
+                       offsetof(struct ocfs2_dinode, id2.i_list.l_recs) -
+                       xattrsize;
+       else
+               size = sb->s_blocksize -
+                       offsetof(struct ocfs2_dinode, id2.i_list.l_recs);
+
+       return size / sizeof(struct ocfs2_extent_rec);
+}
+
 static inline int ocfs2_chain_recs_per_inode(struct super_block *sb)
 {
        int size;
@@ -801,6 +979,17 @@ static inline u64 ocfs2_backup_super_blkno(struct super_block *sb, int index)
        return 0;
 
 }
+
+static inline u16 ocfs2_xattr_recs_per_xb(struct super_block *sb)
+{
+       int size;
+
+       size = sb->s_blocksize -
+               offsetof(struct ocfs2_xattr_block,
+                        xb_attrs.xb_root.xt_list.l_recs);
+
+       return size / sizeof(struct ocfs2_extent_rec);
+}
 #else
 static inline int ocfs2_fast_symlink_chars(int blocksize)
 {
@@ -884,6 +1073,17 @@ static inline uint64_t ocfs2_backup_super_blkno(int blocksize, int index)
 
        return 0;
 }
+
+static inline int ocfs2_xattr_recs_per_xb(int blocksize)
+{
+       int size;
+
+       size = blocksize -
+               offsetof(struct ocfs2_xattr_block,
+                        xb_attrs.xb_root.xt_list.l_recs);
+
+       return size / sizeof(struct ocfs2_extent_rec);
+}
 #endif  /* __KERNEL__ */
 
 
diff --git a/fs/ocfs2/ocfs2_jbd_compat.h b/fs/ocfs2/ocfs2_jbd_compat.h
new file mode 100644 (file)
index 0000000..b91c78f
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_jbd_compat.h
+ *
+ * Compatibility defines for JBD.
+ *
+ * Copyright (C) 2008 Oracle.  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 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.
+ */
+
+#ifndef OCFS2_JBD_COMPAT_H
+#define OCFS2_JBD_COMPAT_H
+
+#ifndef CONFIG_OCFS2_COMPAT_JBD
+# error Should not have been included
+#endif
+
+struct jbd2_inode {
+       unsigned int dummy;
+};
+
+#define JBD2_BARRIER                   JFS_BARRIER
+#define JBD2_DEFAULT_MAX_COMMIT_AGE    JBD_DEFAULT_MAX_COMMIT_AGE
+
+#define jbd2_journal_ack_err                   journal_ack_err
+#define jbd2_journal_clear_err                 journal_clear_err
+#define jbd2_journal_destroy                   journal_destroy
+#define jbd2_journal_dirty_metadata            journal_dirty_metadata
+#define jbd2_journal_errno                     journal_errno
+#define jbd2_journal_extend                    journal_extend
+#define jbd2_journal_flush                     journal_flush
+#define jbd2_journal_force_commit              journal_force_commit
+#define jbd2_journal_get_write_access          journal_get_write_access
+#define jbd2_journal_get_undo_access           journal_get_undo_access
+#define jbd2_journal_init_inode                        journal_init_inode
+#define jbd2_journal_invalidatepage            journal_invalidatepage
+#define jbd2_journal_load                      journal_load
+#define jbd2_journal_lock_updates              journal_lock_updates
+#define jbd2_journal_restart                   journal_restart
+#define jbd2_journal_start                     journal_start
+#define jbd2_journal_start_commit              journal_start_commit
+#define jbd2_journal_stop                      journal_stop
+#define jbd2_journal_try_to_free_buffers       journal_try_to_free_buffers
+#define jbd2_journal_unlock_updates            journal_unlock_updates
+#define jbd2_journal_wipe                      journal_wipe
+#define jbd2_log_wait_commit                   log_wait_commit
+
+static inline int jbd2_journal_file_inode(handle_t *handle,
+                                         struct jbd2_inode *inode)
+{
+       return 0;
+}
+
+static inline int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode,
+                                                     loff_t new_size)
+{
+       return 0;
+}
+
+static inline void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode,
+                                              struct inode *inode)
+{
+       return;
+}
+
+static inline void jbd2_journal_release_jbd_inode(journal_t *journal,
+                                                 struct jbd2_inode *jinode)
+{
+       return;
+}
+
+
+#endif  /* OCFS2_JBD_COMPAT_H */
index 8166968e9015d8634f1987cd8af84f07595c86b9..ffd48db229a75323d31b250e7b5fd885fc7eff63 100644 (file)
@@ -200,7 +200,7 @@ static int update_backups(struct inode * inode, u32 clusters, char *data)
                if (cluster > clusters)
                        break;
 
-               ret = ocfs2_read_block(osb, blkno, &backup, 0, NULL);
+               ret = ocfs2_read_blocks_sync(osb, blkno, 1, &backup);
                if (ret < 0) {
                        mlog_errno(ret);
                        break;
@@ -236,8 +236,8 @@ static void ocfs2_update_super_and_backups(struct inode *inode,
         * update the superblock last.
         * It doesn't matter if the write failed.
         */
-       ret = ocfs2_read_block(osb, OCFS2_SUPER_BLOCK_BLKNO,
-                              &super_bh, 0, NULL);
+       ret = ocfs2_read_blocks_sync(osb, OCFS2_SUPER_BLOCK_BLKNO, 1,
+                                    &super_bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -332,8 +332,7 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
        lgd_blkno = ocfs2_which_cluster_group(main_bm_inode,
                                              first_new_cluster - 1);
 
-       ret = ocfs2_read_block(osb, lgd_blkno, &group_bh, OCFS2_BH_CACHED,
-                              main_bm_inode);
+       ret = ocfs2_read_block(main_bm_inode, lgd_blkno, &group_bh);
        if (ret < 0) {
                mlog_errno(ret);
                goto out_unlock;
@@ -540,7 +539,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
                goto out_unlock;
        }
 
-       ret = ocfs2_read_block(osb, input->group, &group_bh, 0, NULL);
+       ret = ocfs2_read_blocks_sync(osb, input->group, 1, &group_bh);
        if (ret < 0) {
                mlog(ML_ERROR, "Can't read the group descriptor # %llu "
                     "from the device.", (unsigned long long)input->group);
index bb5ff8939bf1ef28a76dfbda74715ea05a4828f7..bdda2d8f85080a5a883c1b01b4cc1fbe68d83d18 100644 (file)
@@ -150,8 +150,8 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
         * be !NULL.  Thus, ocfs2_read_blocks() will ignore blocknr.  If
         * this is not true, the read of -1 (UINT64_MAX) will fail.
         */
-       ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0,
-                               si->si_inode);
+       ret = ocfs2_read_blocks(si->si_inode, -1, si->si_blocks, si->si_bh,
+                               OCFS2_BH_IGNORE_CACHE);
        if (ret == 0) {
                spin_lock(&osb->osb_lock);
                ocfs2_update_slot_info(si);
@@ -404,7 +404,8 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
                     (unsigned long long)blkno);
 
                bh = NULL;  /* Acquire a fresh bh */
-               status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode);
+               status = ocfs2_read_blocks(si->si_inode, blkno, 1, &bh,
+                                          OCFS2_BH_IGNORE_CACHE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
index 353fc35c6748db228172b8476c42ecac8027261c..faec2d879357dbc62f4d85124e2840d26d439be3 100644 (file)
@@ -28,6 +28,7 @@
 #include "ocfs2.h"  /* For struct ocfs2_lock_res */
 #include "stackglue.h"
 
+#include <linux/dlm_plock.h>
 
 /*
  * The control protocol starts with a handshake.  Until the handshake
@@ -746,6 +747,37 @@ static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
 {
 }
 
+static int user_plock(struct ocfs2_cluster_connection *conn,
+                     u64 ino,
+                     struct file *file,
+                     int cmd,
+                     struct file_lock *fl)
+{
+       /*
+        * This more or less just demuxes the plock request into any
+        * one of three dlm calls.
+        *
+        * Internally, fs/dlm will pass these to a misc device, which
+        * a userspace daemon will read and write to.
+        *
+        * For now, cancel requests (which happen internally only),
+        * are turned into unlocks. Most of this function taken from
+        * gfs2_lock.
+        */
+
+       if (cmd == F_CANCELLK) {
+               cmd = F_SETLK;
+               fl->fl_type = F_UNLCK;
+       }
+
+       if (IS_GETLK(cmd))
+               return dlm_posix_get(conn->cc_lockspace, ino, file, fl);
+       else if (fl->fl_type == F_UNLCK)
+               return dlm_posix_unlock(conn->cc_lockspace, ino, file, fl);
+       else
+               return dlm_posix_lock(conn->cc_lockspace, ino, file, cmd, fl);
+}
+
 /*
  * Compare a requested locking protocol version against the current one.
  *
@@ -839,6 +871,7 @@ static struct ocfs2_stack_operations ocfs2_user_plugin_ops = {
        .dlm_unlock     = user_dlm_unlock,
        .lock_status    = user_dlm_lock_status,
        .lock_lvb       = user_dlm_lvb,
+       .plock          = user_plock,
        .dump_lksb      = user_dlm_dump_lksb,
 };
 
index 07f348b8d721064a3753012dc22c7ab21a834d55..68b668b0e60a0a231436fcde4e41bd23083a032d 100644 (file)
@@ -288,6 +288,26 @@ void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
 
+int ocfs2_stack_supports_plocks(void)
+{
+       return active_stack && active_stack->sp_ops->plock;
+}
+EXPORT_SYMBOL_GPL(ocfs2_stack_supports_plocks);
+
+/*
+ * ocfs2_plock() can only be safely called if
+ * ocfs2_stack_supports_plocks() returned true
+ */
+int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
+               struct file *file, int cmd, struct file_lock *fl)
+{
+       WARN_ON_ONCE(active_stack->sp_ops->plock == NULL);
+       if (active_stack->sp_ops->plock)
+               return active_stack->sp_ops->plock(conn, ino, file, cmd, fl);
+       return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(ocfs2_plock);
+
 int ocfs2_cluster_connect(const char *stack_name,
                          const char *group,
                          int grouplen,
index db56281dd1be48d5282ce1aaf0c2b1472c1d8f88..c571af375ef87b98e6e24aad5d44c6fd7e114163 100644 (file)
 #include "dlm/dlmapi.h"
 #include <linux/dlm.h>
 
+/* Needed for plock-related prototypes */
+struct file;
+struct file_lock;
+
 /*
  * dlmconstants.h does not have a LOCAL flag.  We hope to remove it
  * some day, but right now we need it.  Let's fake it.  This value is larger
@@ -186,6 +190,17 @@ struct ocfs2_stack_operations {
         */
        void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
 
+       /*
+        * Cluster-aware posix locks
+        *
+        * This is NULL for stacks which do not support posix locks.
+        */
+       int (*plock)(struct ocfs2_cluster_connection *conn,
+                    u64 ino,
+                    struct file *file,
+                    int cmd,
+                    struct file_lock *fl);
+
        /*
         * This is an optoinal debugging hook.  If provided, the
         * stack can dump debugging information about this lock.
@@ -240,6 +255,10 @@ int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
 void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
 void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
 
+int ocfs2_stack_supports_plocks(void);
+int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
+               struct file *file, int cmd, struct file_lock *fl);
+
 void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
 
 
index d2d278fb9819ee3da92577a367b79f0bdc18681f..c5ff18b46b57524884d9c4b7639f8089e7d3c532 100644 (file)
@@ -62,15 +62,18 @@ static int ocfs2_block_group_fill(handle_t *handle,
                                  struct ocfs2_chain_list *cl);
 static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
                                   struct inode *alloc_inode,
-                                  struct buffer_head *bh);
+                                  struct buffer_head *bh,
+                                  u64 max_block);
 
 static int ocfs2_cluster_group_search(struct inode *inode,
                                      struct buffer_head *group_bh,
                                      u32 bits_wanted, u32 min_bits,
+                                     u64 max_block,
                                      u16 *bit_off, u16 *bits_found);
 static int ocfs2_block_group_search(struct inode *inode,
                                    struct buffer_head *group_bh,
                                    u32 bits_wanted, u32 min_bits,
+                                   u64 max_block,
                                    u16 *bit_off, u16 *bits_found);
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
                                     struct ocfs2_alloc_context *ac,
@@ -110,8 +113,11 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
                                                u64 data_blkno,
                                                u64 *bg_blkno,
                                                u16 *bg_bit_off);
+static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
+                                            u32 bits_wanted, u64 max_block,
+                                            struct ocfs2_alloc_context **ac);
 
-static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
+void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
 {
        struct inode *inode = ac->ac_inode;
 
@@ -124,10 +130,8 @@ static void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac)
                iput(inode);
                ac->ac_inode = NULL;
        }
-       if (ac->ac_bh) {
-               brelse(ac->ac_bh);
-               ac->ac_bh = NULL;
-       }
+       brelse(ac->ac_bh);
+       ac->ac_bh = NULL;
 }
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
@@ -276,7 +280,8 @@ static inline u16 ocfs2_find_smallest_chain(struct ocfs2_chain_list *cl)
  */
 static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
                                   struct inode *alloc_inode,
-                                  struct buffer_head *bh)
+                                  struct buffer_head *bh,
+                                  u64 max_block)
 {
        int status, credits;
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
@@ -294,9 +299,9 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
        mlog_entry_void();
 
        cl = &fe->id2.i_chain;
-       status = ocfs2_reserve_clusters(osb,
-                                       le16_to_cpu(cl->cl_cpg),
-                                       &ac);
+       status = ocfs2_reserve_clusters_with_limit(osb,
+                                                  le16_to_cpu(cl->cl_cpg),
+                                                  max_block, &ac);
        if (status < 0) {
                if (status != -ENOSPC)
                        mlog_errno(status);
@@ -394,8 +399,7 @@ bail:
        if (ac)
                ocfs2_free_alloc_context(ac);
 
-       if (bg_bh)
-               brelse(bg_bh);
+       brelse(bg_bh);
 
        mlog_exit(status);
        return status;
@@ -469,7 +473,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
                        goto bail;
                }
 
-               status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
+               status = ocfs2_block_group_alloc(osb, alloc_inode, bh,
+                                                ac->ac_max_block);
                if (status < 0) {
                        if (status != -ENOSPC)
                                mlog_errno(status);
@@ -486,16 +491,15 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
        get_bh(bh);
        ac->ac_bh = bh;
 bail:
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        mlog_exit(status);
        return status;
 }
 
-int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
-                              struct ocfs2_dinode *fe,
-                              struct ocfs2_alloc_context **ac)
+int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb,
+                                     int blocks,
+                                     struct ocfs2_alloc_context **ac)
 {
        int status;
        u32 slot;
@@ -507,7 +511,7 @@ int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
                goto bail;
        }
 
-       (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
+       (*ac)->ac_bits_wanted = blocks;
        (*ac)->ac_which = OCFS2_AC_USE_META;
        slot = osb->slot_num;
        (*ac)->ac_group_search = ocfs2_block_group_search;
@@ -532,6 +536,15 @@ bail:
        return status;
 }
 
+int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+                              struct ocfs2_extent_list *root_el,
+                              struct ocfs2_alloc_context **ac)
+{
+       return ocfs2_reserve_new_metadata_blocks(osb,
+                                       ocfs2_extend_meta_needed(root_el),
+                                       ac);
+}
+
 static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
                                              struct ocfs2_alloc_context *ac)
 {
@@ -581,6 +594,14 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
 
        (*ac)->ac_group_search = ocfs2_block_group_search;
 
+       /*
+        * stat(2) can't handle i_ino > 32bits, so we tell the
+        * lower levels not to allocate us a block group past that
+        * limit.  The 'inode64' mount option avoids this behavior.
+        */
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64))
+               (*ac)->ac_max_block = (u32)~0U;
+
        /*
         * slot is set when we successfully steal inode from other nodes.
         * It is reset in 3 places:
@@ -661,9 +682,9 @@ bail:
 /* Callers don't need to care which bitmap (local alloc or main) to
  * use so we figure it out for them, but unfortunately this clutters
  * things a bit. */
-int ocfs2_reserve_clusters(struct ocfs2_super *osb,
-                          u32 bits_wanted,
-                          struct ocfs2_alloc_context **ac)
+static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
+                                            u32 bits_wanted, u64 max_block,
+                                            struct ocfs2_alloc_context **ac)
 {
        int status;
 
@@ -677,24 +698,20 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
        }
 
        (*ac)->ac_bits_wanted = bits_wanted;
+       (*ac)->ac_max_block = max_block;
 
        status = -ENOSPC;
        if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
                status = ocfs2_reserve_local_alloc_bits(osb,
                                                        bits_wanted,
                                                        *ac);
-               if ((status < 0) && (status != -ENOSPC)) {
+               if (status == -EFBIG) {
+                       /* The local alloc window is outside ac_max_block.
+                        * use the main bitmap. */
+                       status = -ENOSPC;
+               } else if ((status < 0) && (status != -ENOSPC)) {
                        mlog_errno(status);
                        goto bail;
-               } else if (status == -ENOSPC) {
-                       /* reserve_local_bits will return enospc with
-                        * the local alloc inode still locked, so we
-                        * can change this safely here. */
-                       mlog(0, "Disabling local alloc\n");
-                       /* We set to OCFS2_LA_DISABLED so that umount
-                        * can clean up what's left of the local
-                        * allocation */
-                       osb->local_alloc_state = OCFS2_LA_DISABLED;
                }
        }
 
@@ -718,6 +735,13 @@ bail:
        return status;
 }
 
+int ocfs2_reserve_clusters(struct ocfs2_super *osb,
+                          u32 bits_wanted,
+                          struct ocfs2_alloc_context **ac)
+{
+       return ocfs2_reserve_clusters_with_limit(osb, bits_wanted, 0, ac);
+}
+
 /*
  * More or less lifted from ext3. I'll leave their description below:
  *
@@ -1000,11 +1024,14 @@ static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg
 static int ocfs2_cluster_group_search(struct inode *inode,
                                      struct buffer_head *group_bh,
                                      u32 bits_wanted, u32 min_bits,
+                                     u64 max_block,
                                      u16 *bit_off, u16 *bits_found)
 {
        int search = -ENOSPC;
        int ret;
+       u64 blkoff;
        struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        u16 tmp_off, tmp_found;
        unsigned int max_bits, gd_cluster_off;
 
@@ -1037,6 +1064,17 @@ static int ocfs2_cluster_group_search(struct inode *inode,
                if (ret)
                        return ret;
 
+               if (max_block) {
+                       blkoff = ocfs2_clusters_to_blocks(inode->i_sb,
+                                                         gd_cluster_off +
+                                                         tmp_off + tmp_found);
+                       mlog(0, "Checking %llu against %llu\n",
+                            (unsigned long long)blkoff,
+                            (unsigned long long)max_block);
+                       if (blkoff > max_block)
+                               return -ENOSPC;
+               }
+
                /* ocfs2_block_group_find_clear_bits() might
                 * return success, but we still want to return
                 * -ENOSPC unless it found the minimum number
@@ -1045,6 +1083,12 @@ static int ocfs2_cluster_group_search(struct inode *inode,
                        *bit_off = tmp_off;
                        *bits_found = tmp_found;
                        search = 0; /* success */
+               } else if (tmp_found) {
+                       /*
+                        * Don't show bits which we'll be returning
+                        * for allocation to the local alloc bitmap.
+                        */
+                       ocfs2_local_alloc_seen_free_bits(osb, tmp_found);
                }
        }
 
@@ -1054,19 +1098,31 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 static int ocfs2_block_group_search(struct inode *inode,
                                    struct buffer_head *group_bh,
                                    u32 bits_wanted, u32 min_bits,
+                                   u64 max_block,
                                    u16 *bit_off, u16 *bits_found)
 {
        int ret = -ENOSPC;
+       u64 blkoff;
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
 
        BUG_ON(min_bits != 1);
        BUG_ON(ocfs2_is_cluster_bitmap(inode));
 
-       if (bg->bg_free_bits_count)
+       if (bg->bg_free_bits_count) {
                ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
                                                        group_bh, bits_wanted,
                                                        le16_to_cpu(bg->bg_bits),
                                                        bit_off, bits_found);
+               if (!ret && max_block) {
+                       blkoff = le64_to_cpu(bg->bg_blkno) + *bit_off +
+                               *bits_found;
+                       mlog(0, "Checking %llu against %llu\n",
+                            (unsigned long long)blkoff,
+                            (unsigned long long)max_block);
+                       if (blkoff > max_block)
+                               ret = -ENOSPC;
+               }
+       }
 
        return ret;
 }
@@ -1116,8 +1172,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
        struct ocfs2_group_desc *gd;
        struct inode *alloc_inode = ac->ac_inode;
 
-       ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
-                              &group_bh, OCFS2_BH_CACHED, alloc_inode);
+       ret = ocfs2_read_block(alloc_inode, gd_blkno, &group_bh);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
@@ -1131,7 +1186,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
        }
 
        ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
-                                 bit_off, &found);
+                                 ac->ac_max_block, bit_off, &found);
        if (ret < 0) {
                if (ret != -ENOSPC)
                        mlog_errno(ret);
@@ -1186,9 +1241,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
             bits_wanted, chain,
             (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno);
 
-       status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),
+       status = ocfs2_read_block(alloc_inode,
                                  le64_to_cpu(cl->cl_recs[chain].c_blkno),
-                                 &group_bh, OCFS2_BH_CACHED, alloc_inode);
+                                 &group_bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1204,21 +1259,20 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        /* for now, the chain search is a bit simplistic. We just use
         * the 1st group with any empty bits. */
        while ((status = ac->ac_group_search(alloc_inode, group_bh,
-                                            bits_wanted, min_bits, bit_off,
+                                            bits_wanted, min_bits,
+                                            ac->ac_max_block, bit_off,
                                             &tmp_bits)) == -ENOSPC) {
                if (!bg->bg_next_group)
                        break;
 
-               if (prev_group_bh) {
-                       brelse(prev_group_bh);
-                       prev_group_bh = NULL;
-               }
+               brelse(prev_group_bh);
+               prev_group_bh = NULL;
+
                next_group = le64_to_cpu(bg->bg_next_group);
                prev_group_bh = group_bh;
                group_bh = NULL;
-               status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),
-                                         next_group, &group_bh,
-                                         OCFS2_BH_CACHED, alloc_inode);
+               status = ocfs2_read_block(alloc_inode,
+                                         next_group, &group_bh);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1307,10 +1361,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        *bg_blkno = le64_to_cpu(bg->bg_blkno);
        *bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
-       if (group_bh)
-               brelse(group_bh);
-       if (prev_group_bh)
-               brelse(prev_group_bh);
+       brelse(group_bh);
+       brelse(prev_group_bh);
 
        mlog_exit(status);
        return status;
@@ -1723,7 +1775,6 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
 {
        int status = 0;
        u32 tmp_used;
-       struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) alloc_bh->b_data;
        struct ocfs2_chain_list *cl = &fe->id2.i_chain;
        struct buffer_head *group_bh = NULL;
@@ -1742,8 +1793,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
             (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count,
             (unsigned long long)bg_blkno, start_bit);
 
-       status = ocfs2_read_block(osb, bg_blkno, &group_bh, OCFS2_BH_CACHED,
-                                 alloc_inode);
+       status = ocfs2_read_block(alloc_inode, bg_blkno, &group_bh);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1784,8 +1834,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
        }
 
 bail:
-       if (group_bh)
-               brelse(group_bh);
+       brelse(group_bh);
 
        mlog_exit(status);
        return status;
@@ -1838,9 +1887,15 @@ int ocfs2_free_clusters(handle_t *handle,
        status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
                                          bg_start_bit, bg_blkno,
                                          num_clusters);
-       if (status < 0)
+       if (status < 0) {
                mlog_errno(status);
+               goto out;
+       }
 
+       ocfs2_local_alloc_seen_free_bits(OCFS2_SB(bitmap_inode->i_sb),
+                                        num_clusters);
+
+out:
        mlog_exit(status);
        return status;
 }
@@ -1891,3 +1946,84 @@ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe)
                       (unsigned long long)fe->id2.i_chain.cl_recs[i].c_blkno);
        }
 }
+
+/*
+ * For a given allocation, determine which allocators will need to be
+ * accessed, and lock them, reserving the appropriate number of bits.
+ *
+ * Sparse file systems call this from ocfs2_write_begin_nolock()
+ * and ocfs2_allocate_unwritten_extents().
+ *
+ * File systems which don't support holes call this from
+ * ocfs2_extend_allocation().
+ */
+int ocfs2_lock_allocators(struct inode *inode,
+                         struct ocfs2_extent_tree *et,
+                         u32 clusters_to_add, u32 extents_to_split,
+                         struct ocfs2_alloc_context **data_ac,
+                         struct ocfs2_alloc_context **meta_ac)
+{
+       int ret = 0, num_free_extents;
+       unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       *meta_ac = NULL;
+       if (data_ac)
+               *data_ac = NULL;
+
+       BUG_ON(clusters_to_add != 0 && data_ac == NULL);
+
+       num_free_extents = ocfs2_num_free_extents(osb, inode, et);
+       if (num_free_extents < 0) {
+               ret = num_free_extents;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       /*
+        * Sparse allocation file systems need to be more conservative
+        * with reserving room for expansion - the actual allocation
+        * happens while we've got a journal handle open so re-taking
+        * a cluster lock (because we ran out of room for another
+        * extent) will violate ordering rules.
+        *
+        * Most of the time we'll only be seeing this 1 cluster at a time
+        * anyway.
+        *
+        * Always lock for any unwritten extents - we might want to
+        * add blocks during a split.
+        */
+       if (!num_free_extents ||
+           (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
+               ret = ocfs2_reserve_new_metadata(osb, et->et_root_el, meta_ac);
+               if (ret < 0) {
+                       if (ret != -ENOSPC)
+                               mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       if (clusters_to_add == 0)
+               goto out;
+
+       ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+out:
+       if (ret) {
+               if (*meta_ac) {
+                       ocfs2_free_alloc_context(*meta_ac);
+                       *meta_ac = NULL;
+               }
+
+               /*
+                * We cannot have an error and a non null *data_ac.
+                */
+       }
+
+       return ret;
+}
index 544c600662bd074c1b76ca1c9ead16ab0f24402a..4df159d8f450330d2a2b7ed200dd8ef48c6a0f53 100644 (file)
 
 typedef int (group_search_t)(struct inode *,
                             struct buffer_head *,
-                            u32,
-                            u32,
-                            u16 *,
-                            u16 *);
+                            u32,                       /* bits_wanted */
+                            u32,                       /* min_bits */
+                            u64,                       /* max_block */
+                            u16 *,                     /* *bit_off */
+                            u16 *);                    /* *bits_found */
 
 struct ocfs2_alloc_context {
        struct inode *ac_inode;    /* which bitmap are we allocating from? */
@@ -51,6 +52,8 @@ struct ocfs2_alloc_context {
        group_search_t *ac_group_search;
 
        u64    ac_last_group;
+       u64    ac_max_block;  /* Highest block number to allocate. 0 is
+                                is the same as ~0 - unlimited */
 };
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
@@ -59,9 +62,17 @@ static inline int ocfs2_alloc_context_bits_left(struct ocfs2_alloc_context *ac)
        return ac->ac_bits_wanted - ac->ac_bits_given;
 }
 
+/*
+ * Please note that the caller must make sure that root_el is the root
+ * of extent tree. So for an inode, it should be &fe->id2.i_list. Otherwise
+ * the result may be wrong.
+ */
 int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
-                              struct ocfs2_dinode *fe,
+                              struct ocfs2_extent_list *root_el,
                               struct ocfs2_alloc_context **ac);
+int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb,
+                                     int blocks,
+                                     struct ocfs2_alloc_context **ac);
 int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
                            struct ocfs2_alloc_context **ac);
 int ocfs2_reserve_clusters(struct ocfs2_super *osb,
@@ -147,6 +158,7 @@ static inline int ocfs2_is_cluster_bitmap(struct inode *inode)
  * apis above. */
 int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
                                      struct ocfs2_alloc_context *ac);
+void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac);
 
 /* given a cluster offset, calculate which block group it belongs to
  * and return that block offset. */
@@ -156,4 +168,8 @@ u64 ocfs2_which_cluster_group(struct inode *inode, u32 cluster);
 int ocfs2_check_group_descriptor(struct super_block *sb,
                                 struct ocfs2_dinode *di,
                                 struct ocfs2_group_desc *gd);
+int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_extent_tree *et,
+                         u32 clusters_to_add, u32 extents_to_split,
+                         struct ocfs2_alloc_context **data_ac,
+                         struct ocfs2_alloc_context **meta_ac);
 #endif /* _CHAINALLOC_H_ */
index 88255d3f52b40ba39a847a0bd1976f98e94ab5e7..304b63ac78cfcceeef4759c66c5f72952477909d 100644 (file)
@@ -64,6 +64,7 @@
 #include "sysfile.h"
 #include "uptodate.h"
 #include "ver.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -154,10 +155,13 @@ enum {
        Opt_localalloc,
        Opt_localflocks,
        Opt_stack,
+       Opt_user_xattr,
+       Opt_nouser_xattr,
+       Opt_inode64,
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_barrier, "barrier=%u"},
        {Opt_err_panic, "errors=panic"},
        {Opt_err_ro, "errors=remount-ro"},
@@ -173,6 +177,9 @@ static match_table_t tokens = {
        {Opt_localalloc, "localalloc=%d"},
        {Opt_localflocks, "localflocks"},
        {Opt_stack, "cluster_stack=%s"},
+       {Opt_user_xattr, "user_xattr"},
+       {Opt_nouser_xattr, "nouser_xattr"},
+       {Opt_inode64, "inode64"},
        {Opt_err, NULL}
 };
 
@@ -205,10 +212,11 @@ static int ocfs2_sync_fs(struct super_block *sb, int wait)
                ocfs2_schedule_truncate_log_flush(osb, 0);
        }
 
-       if (journal_start_commit(OCFS2_SB(sb)->journal->j_journal, &target)) {
+       if (jbd2_journal_start_commit(OCFS2_SB(sb)->journal->j_journal,
+                                     &target)) {
                if (wait)
-                       log_wait_commit(OCFS2_SB(sb)->journal->j_journal,
-                                       target);
+                       jbd2_log_wait_commit(OCFS2_SB(sb)->journal->j_journal,
+                                            target);
        }
        return 0;
 }
@@ -325,6 +333,7 @@ static struct inode *ocfs2_alloc_inode(struct super_block *sb)
        if (!oi)
                return NULL;
 
+       jbd2_journal_init_jbd_inode(&oi->ip_jinode, &oi->vfs_inode);
        return &oi->vfs_inode;
 }
 
@@ -406,6 +415,15 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                goto out;
        }
 
+       /* Probably don't want this on remount; it might
+        * mess with other nodes */
+       if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64) &&
+           (parsed_options.mount_opt & OCFS2_MOUNT_INODE64)) {
+               ret = -EINVAL;
+               mlog(ML_ERROR, "Cannot enable inode64 on remount\n");
+               goto out;
+       }
+
        /* We're going to/from readonly mode. */
        if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
                /* Lock here so the check of HARD_RO and the potential
@@ -637,7 +655,8 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        osb->s_atime_quantum = parsed_options.atime_quantum;
        osb->preferred_slot = parsed_options.slot;
        osb->osb_commit_interval = parsed_options.commit_interval;
-       osb->local_alloc_size = parsed_options.localalloc_opt;
+       osb->local_alloc_default_bits = ocfs2_megabytes_to_clusters(sb, parsed_options.localalloc_opt);
+       osb->local_alloc_bits = osb->local_alloc_default_bits;
 
        status = ocfs2_verify_userspace_stack(osb, &parsed_options);
        if (status)
@@ -743,8 +762,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        return status;
 
 read_super_error:
-       if (bh != NULL)
-               brelse(bh);
+       brelse(bh);
 
        if (inode)
                iput(inode);
@@ -847,6 +865,12 @@ static int ocfs2_parse_options(struct super_block *sb,
                case Opt_data_writeback:
                        mopt->mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK;
                        break;
+               case Opt_user_xattr:
+                       mopt->mount_opt &= ~OCFS2_MOUNT_NOUSERXATTR;
+                       break;
+               case Opt_nouser_xattr:
+                       mopt->mount_opt |= OCFS2_MOUNT_NOUSERXATTR;
+                       break;
                case Opt_atime_quantum:
                        if (match_int(&args[0], &option)) {
                                status = 0;
@@ -873,7 +897,7 @@ static int ocfs2_parse_options(struct super_block *sb,
                        if (option < 0)
                                return 0;
                        if (option == 0)
-                               option = JBD_DEFAULT_MAX_COMMIT_AGE;
+                               option = JBD2_DEFAULT_MAX_COMMIT_AGE;
                        mopt->commit_interval = HZ * option;
                        break;
                case Opt_localalloc:
@@ -918,6 +942,9 @@ static int ocfs2_parse_options(struct super_block *sb,
                               OCFS2_STACK_LABEL_LEN);
                        mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
                        break;
+               case Opt_inode64:
+                       mopt->mount_opt |= OCFS2_MOUNT_INODE64;
+                       break;
                default:
                        mlog(ML_ERROR,
                             "Unrecognized mount option \"%s\" "
@@ -938,6 +965,7 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
 {
        struct ocfs2_super *osb = OCFS2_SB(mnt->mnt_sb);
        unsigned long opts = osb->s_mount_opt;
+       unsigned int local_alloc_megs;
 
        if (opts & OCFS2_MOUNT_HB_LOCAL)
                seq_printf(s, ",_netdev,heartbeat=local");
@@ -970,8 +998,9 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
                seq_printf(s, ",commit=%u",
                           (unsigned) (osb->osb_commit_interval / HZ));
 
-       if (osb->local_alloc_size != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE)
-               seq_printf(s, ",localalloc=%d", osb->local_alloc_size);
+       local_alloc_megs = osb->local_alloc_bits >> (20 - osb->s_clustersize_bits);
+       if (local_alloc_megs != OCFS2_DEFAULT_LOCAL_ALLOC_SIZE)
+               seq_printf(s, ",localalloc=%d", local_alloc_megs);
 
        if (opts & OCFS2_MOUNT_LOCALFLOCKS)
                seq_printf(s, ",localflocks,");
@@ -980,6 +1009,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
                seq_printf(s, ",cluster_stack=%.*s", OCFS2_STACK_LABEL_LEN,
                           osb->osb_cluster_stack);
 
+       if (opts & OCFS2_MOUNT_NOUSERXATTR)
+               seq_printf(s, ",nouser_xattr");
+       else
+               seq_printf(s, ",user_xattr");
+
+       if (opts & OCFS2_MOUNT_INODE64)
+               seq_printf(s, ",inode64");
+
        return 0;
 }
 
@@ -1132,6 +1169,7 @@ static void ocfs2_inode_init_once(void *data)
        oi->ip_dir_start_lookup = 0;
 
        init_rwsem(&oi->ip_alloc_sem);
+       init_rwsem(&oi->ip_xattr_sem);
        mutex_init(&oi->ip_io_mutex);
 
        oi->ip_blkno = 0ULL;
@@ -1375,6 +1413,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
        sb->s_fs_info = osb;
        sb->s_op = &ocfs2_sops;
        sb->s_export_op = &ocfs2_export_ops;
+       sb->s_xattr = ocfs2_xattr_handlers;
        sb->s_time_gran = 1;
        sb->s_flags |= MS_NOATIME;
        /* this is needed to support O_LARGEFILE */
@@ -1421,8 +1460,12 @@ static int ocfs2_initialize_super(struct super_block *sb,
 
        osb->slot_num = OCFS2_INVALID_SLOT;
 
+       osb->s_xattr_inline_size = le16_to_cpu(
+                                       di->id2.i_super.s_xattr_inline_size);
+
        osb->local_alloc_state = OCFS2_LA_UNUSED;
        osb->local_alloc_bh = NULL;
+       INIT_DELAYED_WORK(&osb->la_enable_wq, ocfs2_la_enable_worker);
 
        init_waitqueue_head(&osb->osb_mount_event);
 
@@ -1568,6 +1611,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
        osb->first_cluster_group_blkno =
                le64_to_cpu(di->id2.i_super.s_first_cluster_group);
        osb->fs_generation = le32_to_cpu(di->i_fs_generation);
+       osb->uuid_hash = le32_to_cpu(di->id2.i_super.s_uuid_hash);
        mlog(0, "vol_label: %s\n", osb->vol_label);
        mlog(0, "uuid: %s\n", osb->uuid_str);
        mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n",
index ba9dbb51d25b5ed120922d9192e7098d239d7f5c..cbd03dfdc7b987aaef8810adfbce4590e6fdacc8 100644 (file)
@@ -50,6 +50,7 @@
 #include "inode.h"
 #include "journal.h"
 #include "symlink.h"
+#include "xattr.h"
 
 #include "buffer_head_io.h"
 
@@ -83,11 +84,7 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode,
 
        mlog_entry_void();
 
-       status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
-                                 OCFS2_I(inode)->ip_blkno,
-                                 bh,
-                                 OCFS2_BH_CACHED,
-                                 inode);
+       status = ocfs2_read_block(inode, OCFS2_I(inode)->ip_blkno, bh);
        if (status < 0) {
                mlog_errno(status);
                link = ERR_PTR(status);
@@ -157,8 +154,7 @@ bail:
                kunmap(page);
                page_cache_release(page);
        }
-       if (bh)
-               brelse(bh);
+       brelse(bh);
 
        return ERR_PTR(status);
 }
@@ -168,10 +164,18 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
        .follow_link    = ocfs2_follow_link,
        .getattr        = ocfs2_getattr,
        .setattr        = ocfs2_setattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = ocfs2_listxattr,
+       .removexattr    = generic_removexattr,
 };
 const struct inode_operations ocfs2_fast_symlink_inode_operations = {
        .readlink       = ocfs2_readlink,
        .follow_link    = ocfs2_follow_link,
        .getattr        = ocfs2_getattr,
        .setattr        = ocfs2_setattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .listxattr      = ocfs2_listxattr,
+       .removexattr    = generic_removexattr,
 };
index 4da8851f2b23af737df164d0ec64133117f19508..187b99ff03688992fc0f141390ca6bec667fa027 100644 (file)
 #include <linux/highmem.h>
 #include <linux/buffer_head.h>
 #include <linux/rbtree.h>
-#include <linux/jbd.h>
+#ifndef CONFIG_OCFS2_COMPAT_JBD
+# include <linux/jbd2.h>
+#else
+# include <linux/jbd.h>
+#endif
 
 #define MLOG_MASK_PREFIX ML_UPTODATE
 
@@ -511,14 +515,10 @@ static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci,
        ci->ci_num_cached--;
 }
 
-/* Called when we remove a chunk of metadata from an inode. We don't
- * bother reverting things to an inlined array in the case of a remove
- * which moves us back under the limit. */
-void ocfs2_remove_from_cache(struct inode *inode,
-                            struct buffer_head *bh)
+static void ocfs2_remove_block_from_cache(struct inode *inode,
+                                         sector_t block)
 {
        int index;
-       sector_t block = bh->b_blocknr;
        struct ocfs2_meta_cache_item *item = NULL;
        struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
@@ -544,6 +544,30 @@ void ocfs2_remove_from_cache(struct inode *inode,
                kmem_cache_free(ocfs2_uptodate_cachep, item);
 }
 
+/*
+ * Called when we remove a chunk of metadata from an inode. We don't
+ * bother reverting things to an inlined array in the case of a remove
+ * which moves us back under the limit.
+ */
+void ocfs2_remove_from_cache(struct inode *inode,
+                            struct buffer_head *bh)
+{
+       sector_t block = bh->b_blocknr;
+
+       ocfs2_remove_block_from_cache(inode, block);
+}
+
+/* Called when we remove xattr clusters from an inode. */
+void ocfs2_remove_xattr_clusters_from_cache(struct inode *inode,
+                                           sector_t block,
+                                           u32 c_len)
+{
+       unsigned int i, b_len = ocfs2_clusters_to_blocks(inode->i_sb, 1) * c_len;
+
+       for (i = 0; i < b_len; i++, block++)
+               ocfs2_remove_block_from_cache(inode, block);
+}
+
 int __init init_ocfs2_uptodate_cache(void)
 {
        ocfs2_uptodate_cachep = kmem_cache_create("ocfs2_uptodate",
index 2e73206059a857af1ed61960ae77922f40efb786..531b4b3a0c47ffa66fc680fc38dfc890cf09a34b 100644 (file)
@@ -40,6 +40,9 @@ void ocfs2_set_new_buffer_uptodate(struct inode *inode,
                                   struct buffer_head *bh);
 void ocfs2_remove_from_cache(struct inode *inode,
                             struct buffer_head *bh);
+void ocfs2_remove_xattr_clusters_from_cache(struct inode *inode,
+                                           sector_t block,
+                                           u32 c_len);
 int ocfs2_buffer_read_ahead(struct inode *inode,
                            struct buffer_head *bh);
 
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
new file mode 100644 (file)
index 0000000..802c414
--- /dev/null
@@ -0,0 +1,4832 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * xattr.c
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * CREDITS:
+ * Lots of code in this file is taken from ext3.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ */
+
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/uio.h>
+#include <linux/sched.h>
+#include <linux/splice.h>
+#include <linux/mount.h>
+#include <linux/writeback.h>
+#include <linux/falloc.h>
+#include <linux/sort.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#define MLOG_MASK_PREFIX ML_XATTR
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+#include "alloc.h"
+#include "dlmglue.h"
+#include "file.h"
+#include "symlink.h"
+#include "sysfile.h"
+#include "inode.h"
+#include "journal.h"
+#include "ocfs2_fs.h"
+#include "suballoc.h"
+#include "uptodate.h"
+#include "buffer_head_io.h"
+#include "super.h"
+#include "xattr.h"
+
+
+struct ocfs2_xattr_def_value_root {
+       struct ocfs2_xattr_value_root   xv;
+       struct ocfs2_extent_rec         er;
+};
+
+struct ocfs2_xattr_bucket {
+       struct buffer_head *bhs[OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET];
+       struct ocfs2_xattr_header *xh;
+};
+
+#define OCFS2_XATTR_ROOT_SIZE  (sizeof(struct ocfs2_xattr_def_value_root))
+#define OCFS2_XATTR_INLINE_SIZE        80
+
+static struct ocfs2_xattr_def_value_root def_xv = {
+       .xv.xr_list.l_count = cpu_to_le16(1),
+};
+
+struct xattr_handler *ocfs2_xattr_handlers[] = {
+       &ocfs2_xattr_user_handler,
+       &ocfs2_xattr_trusted_handler,
+       NULL
+};
+
+static struct xattr_handler *ocfs2_xattr_handler_map[] = {
+       [OCFS2_XATTR_INDEX_USER]        = &ocfs2_xattr_user_handler,
+       [OCFS2_XATTR_INDEX_TRUSTED]     = &ocfs2_xattr_trusted_handler,
+};
+
+struct ocfs2_xattr_info {
+       int name_index;
+       const char *name;
+       const void *value;
+       size_t value_len;
+};
+
+struct ocfs2_xattr_search {
+       struct buffer_head *inode_bh;
+       /*
+        * xattr_bh point to the block buffer head which has extended attribute
+        * when extended attribute in inode, xattr_bh is equal to inode_bh.
+        */
+       struct buffer_head *xattr_bh;
+       struct ocfs2_xattr_header *header;
+       struct ocfs2_xattr_bucket bucket;
+       void *base;
+       void *end;
+       struct ocfs2_xattr_entry *here;
+       int not_found;
+};
+
+static int ocfs2_xattr_bucket_get_name_value(struct inode *inode,
+                                            struct ocfs2_xattr_header *xh,
+                                            int index,
+                                            int *block_off,
+                                            int *new_offset);
+
+static int ocfs2_xattr_index_block_find(struct inode *inode,
+                                       struct buffer_head *root_bh,
+                                       int name_index,
+                                       const char *name,
+                                       struct ocfs2_xattr_search *xs);
+
+static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
+                                       struct ocfs2_xattr_tree_root *xt,
+                                       char *buffer,
+                                       size_t buffer_size);
+
+static int ocfs2_xattr_create_index_block(struct inode *inode,
+                                         struct ocfs2_xattr_search *xs);
+
+static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
+                                            struct ocfs2_xattr_info *xi,
+                                            struct ocfs2_xattr_search *xs);
+
+static int ocfs2_delete_xattr_index_block(struct inode *inode,
+                                         struct buffer_head *xb_bh);
+
+static inline const char *ocfs2_xattr_prefix(int name_index)
+{
+       struct xattr_handler *handler = NULL;
+
+       if (name_index > 0 && name_index < OCFS2_XATTR_MAX)
+               handler = ocfs2_xattr_handler_map[name_index];
+
+       return handler ? handler->prefix : NULL;
+}
+
+static u32 ocfs2_xattr_name_hash(struct inode *inode,
+                                const char *name,
+                                int name_len)
+{
+       /* Get hash value of uuid from super block */
+       u32 hash = OCFS2_SB(inode->i_sb)->uuid_hash;
+       int i;
+
+       /* hash extended attribute name */
+       for (i = 0; i < name_len; i++) {
+               hash = (hash << OCFS2_HASH_SHIFT) ^
+                      (hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
+                      *name++;
+       }
+
+       return hash;
+}
+
+/*
+ * ocfs2_xattr_hash_entry()
+ *
+ * Compute the hash of an extended attribute.
+ */
+static void ocfs2_xattr_hash_entry(struct inode *inode,
+                                  struct ocfs2_xattr_header *header,
+                                  struct ocfs2_xattr_entry *entry)
+{
+       u32 hash = 0;
+       char *name = (char *)header + le16_to_cpu(entry->xe_name_offset);
+
+       hash = ocfs2_xattr_name_hash(inode, name, entry->xe_name_len);
+       entry->xe_name_hash = cpu_to_le32(hash);
+
+       return;
+}
+
+static int ocfs2_xattr_extend_allocation(struct inode *inode,
+                                        u32 clusters_to_add,
+                                        struct buffer_head *xattr_bh,
+                                        struct ocfs2_xattr_value_root *xv)
+{
+       int status = 0;
+       int restart_func = 0;
+       int credits = 0;
+       handle_t *handle = NULL;
+       struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       enum ocfs2_alloc_restarted why;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters);
+       struct ocfs2_extent_tree et;
+
+       mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add);
+
+       ocfs2_init_xattr_value_extent_tree(&et, inode, xattr_bh, xv);
+
+restart_all:
+
+       status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
+                                      &data_ac, &meta_ac);
+       if (status) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
+                                           clusters_to_add);
+       handle = ocfs2_start_trans(osb, credits);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(status);
+               goto leave;
+       }
+
+restarted_transaction:
+       status = ocfs2_journal_access(handle, inode, xattr_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       prev_clusters = le32_to_cpu(xv->xr_clusters);
+       status = ocfs2_add_clusters_in_btree(osb,
+                                            inode,
+                                            &logical_start,
+                                            clusters_to_add,
+                                            0,
+                                            &et,
+                                            handle,
+                                            data_ac,
+                                            meta_ac,
+                                            &why);
+       if ((status < 0) && (status != -EAGAIN)) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       status = ocfs2_journal_dirty(handle, xattr_bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters;
+
+       if (why != RESTART_NONE && clusters_to_add) {
+               if (why == RESTART_META) {
+                       mlog(0, "restarting function.\n");
+                       restart_func = 1;
+               } else {
+                       BUG_ON(why != RESTART_TRANS);
+
+                       mlog(0, "restarting transaction.\n");
+                       /* TODO: This can be more intelligent. */
+                       credits = ocfs2_calc_extend_credits(osb->sb,
+                                                           et.et_root_el,
+                                                           clusters_to_add);
+                       status = ocfs2_extend_trans(handle, credits);
+                       if (status < 0) {
+                               /* handle still has to be committed at
+                                * this point. */
+                               status = -ENOMEM;
+                               mlog_errno(status);
+                               goto leave;
+                       }
+                       goto restarted_transaction;
+               }
+       }
+
+leave:
+       if (handle) {
+               ocfs2_commit_trans(osb, handle);
+               handle = NULL;
+       }
+       if (data_ac) {
+               ocfs2_free_alloc_context(data_ac);
+               data_ac = NULL;
+       }
+       if (meta_ac) {
+               ocfs2_free_alloc_context(meta_ac);
+               meta_ac = NULL;
+       }
+       if ((!status) && restart_func) {
+               restart_func = 0;
+               goto restart_all;
+       }
+
+       return status;
+}
+
+static int __ocfs2_remove_xattr_range(struct inode *inode,
+                                     struct buffer_head *root_bh,
+                                     struct ocfs2_xattr_value_root *xv,
+                                     u32 cpos, u32 phys_cpos, u32 len,
+                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+       int ret;
+       u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct inode *tl_inode = osb->osb_tl_inode;
+       handle_t *handle;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       struct ocfs2_extent_tree et;
+
+       ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv);
+
+       ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
+       if (ret) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       mutex_lock(&tl_inode->i_mutex);
+
+       if (ocfs2_truncate_log_needs_flush(osb)) {
+               ret = __ocfs2_flush_truncate_log(osb);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, root_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
+                                 dealloc);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       le32_add_cpu(&xv->xr_clusters, -len);
+
+       ret = ocfs2_journal_dirty(handle, root_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_truncate_log_append(osb, handle, phys_blkno, len);
+       if (ret)
+               mlog_errno(ret);
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       mutex_unlock(&tl_inode->i_mutex);
+
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
+       return ret;
+}
+
+static int ocfs2_xattr_shrink_size(struct inode *inode,
+                                  u32 old_clusters,
+                                  u32 new_clusters,
+                                  struct buffer_head *root_bh,
+                                  struct ocfs2_xattr_value_root *xv)
+{
+       int ret = 0;
+       u32 trunc_len, cpos, phys_cpos, alloc_size;
+       u64 block;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_cached_dealloc_ctxt dealloc;
+
+       ocfs2_init_dealloc_ctxt(&dealloc);
+
+       if (old_clusters <= new_clusters)
+               return 0;
+
+       cpos = new_clusters;
+       trunc_len = old_clusters - new_clusters;
+       while (trunc_len) {
+               ret = ocfs2_xattr_get_clusters(inode, cpos, &phys_cpos,
+                                              &alloc_size, &xv->xr_list);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               if (alloc_size > trunc_len)
+                       alloc_size = trunc_len;
+
+               ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos,
+                                                phys_cpos, alloc_size,
+                                                &dealloc);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               block = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
+               ocfs2_remove_xattr_clusters_from_cache(inode, block,
+                                                      alloc_size);
+               cpos += alloc_size;
+               trunc_len -= alloc_size;
+       }
+
+out:
+       ocfs2_schedule_truncate_log_flush(osb, 1);
+       ocfs2_run_deallocs(osb, &dealloc);
+
+       return ret;
+}
+
+static int ocfs2_xattr_value_truncate(struct inode *inode,
+                                     struct buffer_head *root_bh,
+                                     struct ocfs2_xattr_value_root *xv,
+                                     int len)
+{
+       int ret;
+       u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len);
+       u32 old_clusters = le32_to_cpu(xv->xr_clusters);
+
+       if (new_clusters == old_clusters)
+               return 0;
+
+       if (new_clusters > old_clusters)
+               ret = ocfs2_xattr_extend_allocation(inode,
+                                                   new_clusters - old_clusters,
+                                                   root_bh, xv);
+       else
+               ret = ocfs2_xattr_shrink_size(inode,
+                                             old_clusters, new_clusters,
+                                             root_bh, xv);
+
+       return ret;
+}
+
+static int ocfs2_xattr_list_entry(char *buffer, size_t size,
+                                 size_t *result, const char *prefix,
+                                 const char *name, int name_len)
+{
+       char *p = buffer + *result;
+       int prefix_len = strlen(prefix);
+       int total_len = prefix_len + name_len + 1;
+
+       *result += total_len;
+
+       /* we are just looking for how big our buffer needs to be */
+       if (!size)
+               return 0;
+
+       if (*result > size)
+               return -ERANGE;
+
+       memcpy(p, prefix, prefix_len);
+       memcpy(p + prefix_len, name, name_len);
+       p[prefix_len + name_len] = '\0';
+
+       return 0;
+}
+
+static int ocfs2_xattr_list_entries(struct inode *inode,
+                                   struct ocfs2_xattr_header *header,
+                                   char *buffer, size_t buffer_size)
+{
+       size_t result = 0;
+       int i, type, ret;
+       const char *prefix, *name;
+
+       for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) {
+               struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
+               type = ocfs2_xattr_get_type(entry);
+               prefix = ocfs2_xattr_prefix(type);
+
+               if (prefix) {
+                       name = (const char *)header +
+                               le16_to_cpu(entry->xe_name_offset);
+
+                       ret = ocfs2_xattr_list_entry(buffer, buffer_size,
+                                                    &result, prefix, name,
+                                                    entry->xe_name_len);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return result;
+}
+
+static int ocfs2_xattr_ibody_list(struct inode *inode,
+                                 struct ocfs2_dinode *di,
+                                 char *buffer,
+                                 size_t buffer_size)
+{
+       struct ocfs2_xattr_header *header = NULL;
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       int ret = 0;
+
+       if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
+               return ret;
+
+       header = (struct ocfs2_xattr_header *)
+                ((void *)di + inode->i_sb->s_blocksize -
+                le16_to_cpu(di->i_xattr_inline_size));
+
+       ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size);
+
+       return ret;
+}
+
+static int ocfs2_xattr_block_list(struct inode *inode,
+                                 struct ocfs2_dinode *di,
+                                 char *buffer,
+                                 size_t buffer_size)
+{
+       struct buffer_head *blk_bh = NULL;
+       struct ocfs2_xattr_block *xb;
+       int ret = 0;
+
+       if (!di->i_xattr_loc)
+               return ret;
+
+       ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       /*Verify the signature of xattr block*/
+       if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
+                  strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
+               ret = -EFAULT;
+               goto cleanup;
+       }
+
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
+
+       if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
+               struct ocfs2_xattr_header *header = &xb->xb_attrs.xb_header;
+               ret = ocfs2_xattr_list_entries(inode, header,
+                                              buffer, buffer_size);
+       } else {
+               struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
+               ret = ocfs2_xattr_tree_list_index_block(inode, xt,
+                                                  buffer, buffer_size);
+       }
+cleanup:
+       brelse(blk_bh);
+
+       return ret;
+}
+
+ssize_t ocfs2_listxattr(struct dentry *dentry,
+                       char *buffer,
+                       size_t size)
+{
+       int ret = 0, i_ret = 0, b_ret = 0;
+       struct buffer_head *di_bh = NULL;
+       struct ocfs2_dinode *di = NULL;
+       struct ocfs2_inode_info *oi = OCFS2_I(dentry->d_inode);
+
+       if (!ocfs2_supports_xattr(OCFS2_SB(dentry->d_sb)))
+               return -EOPNOTSUPP;
+
+       if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
+               return ret;
+
+       ret = ocfs2_inode_lock(dentry->d_inode, &di_bh, 0);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       di = (struct ocfs2_dinode *)di_bh->b_data;
+
+       down_read(&oi->ip_xattr_sem);
+       i_ret = ocfs2_xattr_ibody_list(dentry->d_inode, di, buffer, size);
+       if (i_ret < 0)
+               b_ret = 0;
+       else {
+               if (buffer) {
+                       buffer += i_ret;
+                       size -= i_ret;
+               }
+               b_ret = ocfs2_xattr_block_list(dentry->d_inode, di,
+                                              buffer, size);
+               if (b_ret < 0)
+                       i_ret = 0;
+       }
+       up_read(&oi->ip_xattr_sem);
+       ocfs2_inode_unlock(dentry->d_inode, 0);
+
+       brelse(di_bh);
+
+       return i_ret + b_ret;
+}
+
+static int ocfs2_xattr_find_entry(int name_index,
+                                 const char *name,
+                                 struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_xattr_entry *entry;
+       size_t name_len;
+       int i, cmp = 1;
+
+       if (name == NULL)
+               return -EINVAL;
+
+       name_len = strlen(name);
+       entry = xs->here;
+       for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
+               cmp = name_index - ocfs2_xattr_get_type(entry);
+               if (!cmp)
+                       cmp = name_len - entry->xe_name_len;
+               if (!cmp)
+                       cmp = memcmp(name, (xs->base +
+                                    le16_to_cpu(entry->xe_name_offset)),
+                                    name_len);
+               if (cmp == 0)
+                       break;
+               entry += 1;
+       }
+       xs->here = entry;
+
+       return cmp ? -ENODATA : 0;
+}
+
+static int ocfs2_xattr_get_value_outside(struct inode *inode,
+                                        struct ocfs2_xattr_value_root *xv,
+                                        void *buffer,
+                                        size_t len)
+{
+       u32 cpos, p_cluster, num_clusters, bpc, clusters;
+       u64 blkno;
+       int i, ret = 0;
+       size_t cplen, blocksize;
+       struct buffer_head *bh = NULL;
+       struct ocfs2_extent_list *el;
+
+       el = &xv->xr_list;
+       clusters = le32_to_cpu(xv->xr_clusters);
+       bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       blocksize = inode->i_sb->s_blocksize;
+
+       cpos = 0;
+       while (cpos < clusters) {
+               ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
+                                              &num_clusters, el);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
+               /* Copy ocfs2_xattr_value */
+               for (i = 0; i < num_clusters * bpc; i++, blkno++) {
+                       ret = ocfs2_read_block(inode, blkno, &bh);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+
+                       cplen = len >= blocksize ? blocksize : len;
+                       memcpy(buffer, bh->b_data, cplen);
+                       len -= cplen;
+                       buffer += cplen;
+
+                       brelse(bh);
+                       bh = NULL;
+                       if (len == 0)
+                               break;
+               }
+               cpos += num_clusters;
+       }
+out:
+       return ret;
+}
+
+static int ocfs2_xattr_ibody_get(struct inode *inode,
+                                int name_index,
+                                const char *name,
+                                void *buffer,
+                                size_t buffer_size,
+                                struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       struct ocfs2_xattr_value_root *xv;
+       size_t size;
+       int ret = 0;
+
+       if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
+               return -ENODATA;
+
+       xs->end = (void *)di + inode->i_sb->s_blocksize;
+       xs->header = (struct ocfs2_xattr_header *)
+                       (xs->end - le16_to_cpu(di->i_xattr_inline_size));
+       xs->base = (void *)xs->header;
+       xs->here = xs->header->xh_entries;
+
+       ret = ocfs2_xattr_find_entry(name_index, name, xs);
+       if (ret)
+               return ret;
+       size = le64_to_cpu(xs->here->xe_value_size);
+       if (buffer) {
+               if (size > buffer_size)
+                       return -ERANGE;
+               if (ocfs2_xattr_is_local(xs->here)) {
+                       memcpy(buffer, (void *)xs->base +
+                              le16_to_cpu(xs->here->xe_name_offset) +
+                              OCFS2_XATTR_SIZE(xs->here->xe_name_len), size);
+               } else {
+                       xv = (struct ocfs2_xattr_value_root *)
+                               (xs->base + le16_to_cpu(
+                                xs->here->xe_name_offset) +
+                               OCFS2_XATTR_SIZE(xs->here->xe_name_len));
+                       ret = ocfs2_xattr_get_value_outside(inode, xv,
+                                                           buffer, size);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               return ret;
+                       }
+               }
+       }
+
+       return size;
+}
+
+static int ocfs2_xattr_block_get(struct inode *inode,
+                                int name_index,
+                                const char *name,
+                                void *buffer,
+                                size_t buffer_size,
+                                struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       struct buffer_head *blk_bh = NULL;
+       struct ocfs2_xattr_block *xb;
+       struct ocfs2_xattr_value_root *xv;
+       size_t size;
+       int ret = -ENODATA, name_offset, name_len, block_off, i;
+
+       if (!di->i_xattr_loc)
+               return ret;
+
+       memset(&xs->bucket, 0, sizeof(xs->bucket));
+
+       ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       /*Verify the signature of xattr block*/
+       if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
+                  strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
+               ret = -EFAULT;
+               goto cleanup;
+       }
+
+       xs->xattr_bh = blk_bh;
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
+
+       if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
+               xs->header = &xb->xb_attrs.xb_header;
+               xs->base = (void *)xs->header;
+               xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
+               xs->here = xs->header->xh_entries;
+
+               ret = ocfs2_xattr_find_entry(name_index, name, xs);
+       } else
+               ret = ocfs2_xattr_index_block_find(inode, blk_bh,
+                                                  name_index,
+                                                  name, xs);
+
+       if (ret)
+               goto cleanup;
+       size = le64_to_cpu(xs->here->xe_value_size);
+       if (buffer) {
+               ret = -ERANGE;
+               if (size > buffer_size)
+                       goto cleanup;
+
+               name_offset = le16_to_cpu(xs->here->xe_name_offset);
+               name_len = OCFS2_XATTR_SIZE(xs->here->xe_name_len);
+               i = xs->here - xs->header->xh_entries;
+
+               if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) {
+                       ret = ocfs2_xattr_bucket_get_name_value(inode,
+                                                               xs->bucket.xh,
+                                                               i,
+                                                               &block_off,
+                                                               &name_offset);
+                       xs->base = xs->bucket.bhs[block_off]->b_data;
+               }
+               if (ocfs2_xattr_is_local(xs->here)) {
+                       memcpy(buffer, (void *)xs->base +
+                              name_offset + name_len, size);
+               } else {
+                       xv = (struct ocfs2_xattr_value_root *)
+                               (xs->base + name_offset + name_len);
+                       ret = ocfs2_xattr_get_value_outside(inode, xv,
+                                                           buffer, size);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               goto cleanup;
+                       }
+               }
+       }
+       ret = size;
+cleanup:
+       for (i = 0; i < OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET; i++)
+               brelse(xs->bucket.bhs[i]);
+       memset(&xs->bucket, 0, sizeof(xs->bucket));
+
+       brelse(blk_bh);
+       return ret;
+}
+
+/* ocfs2_xattr_get()
+ *
+ * Copy an extended attribute into the buffer provided.
+ * Buffer is NULL to compute the size of buffer required.
+ */
+int ocfs2_xattr_get(struct inode *inode,
+                   int name_index,
+                   const char *name,
+                   void *buffer,
+                   size_t buffer_size)
+{
+       int ret;
+       struct ocfs2_dinode *di = NULL;
+       struct buffer_head *di_bh = NULL;
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_xattr_search xis = {
+               .not_found = -ENODATA,
+       };
+       struct ocfs2_xattr_search xbs = {
+               .not_found = -ENODATA,
+       };
+
+       if (!ocfs2_supports_xattr(OCFS2_SB(inode->i_sb)))
+               return -EOPNOTSUPP;
+
+       if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
+               ret = -ENODATA;
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 0);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       xis.inode_bh = xbs.inode_bh = di_bh;
+       di = (struct ocfs2_dinode *)di_bh->b_data;
+
+       down_read(&oi->ip_xattr_sem);
+       ret = ocfs2_xattr_ibody_get(inode, name_index, name, buffer,
+                                   buffer_size, &xis);
+       if (ret == -ENODATA)
+               ret = ocfs2_xattr_block_get(inode, name_index, name, buffer,
+                                           buffer_size, &xbs);
+       up_read(&oi->ip_xattr_sem);
+       ocfs2_inode_unlock(inode, 0);
+
+       brelse(di_bh);
+
+       return ret;
+}
+
+static int __ocfs2_xattr_set_value_outside(struct inode *inode,
+                                          struct ocfs2_xattr_value_root *xv,
+                                          const void *value,
+                                          int value_len)
+{
+       int ret = 0, i, cp_len, credits;
+       u16 blocksize = inode->i_sb->s_blocksize;
+       u32 p_cluster, num_clusters;
+       u32 cpos = 0, bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len);
+       u64 blkno;
+       struct buffer_head *bh = NULL;
+       handle_t *handle;
+
+       BUG_ON(clusters > le32_to_cpu(xv->xr_clusters));
+
+       credits = clusters * bpc;
+       handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), credits);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+
+       while (cpos < clusters) {
+               ret = ocfs2_xattr_get_clusters(inode, cpos, &p_cluster,
+                                              &num_clusters, &xv->xr_list);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+
+               blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster);
+
+               for (i = 0; i < num_clusters * bpc; i++, blkno++) {
+                       ret = ocfs2_read_block(inode, blkno, &bh);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out_commit;
+                       }
+
+                       ret = ocfs2_journal_access(handle,
+                                                  inode,
+                                                  bh,
+                                                  OCFS2_JOURNAL_ACCESS_WRITE);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               goto out_commit;
+                       }
+
+                       cp_len = value_len > blocksize ? blocksize : value_len;
+                       memcpy(bh->b_data, value, cp_len);
+                       value_len -= cp_len;
+                       value += cp_len;
+                       if (cp_len < blocksize)
+                               memset(bh->b_data + cp_len, 0,
+                                      blocksize - cp_len);
+
+                       ret = ocfs2_journal_dirty(handle, bh);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               goto out_commit;
+                       }
+                       brelse(bh);
+                       bh = NULL;
+
+                       /*
+                        * XXX: do we need to empty all the following
+                        * blocks in this cluster?
+                        */
+                       if (!value_len)
+                               break;
+               }
+               cpos += num_clusters;
+       }
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+       brelse(bh);
+
+       return ret;
+}
+
+static int ocfs2_xattr_cleanup(struct inode *inode,
+                              struct ocfs2_xattr_info *xi,
+                              struct ocfs2_xattr_search *xs,
+                              size_t offs)
+{
+       handle_t *handle = NULL;
+       int ret = 0;
+       size_t name_len = strlen(xi->name);
+       void *val = xs->base + offs;
+       size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
+                                  OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+       ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+       /* Decrease xattr count */
+       le16_add_cpu(&xs->header->xh_count, -1);
+       /* Remove the xattr entry and tree root which has already be set*/
+       memset((void *)xs->here, 0, sizeof(struct ocfs2_xattr_entry));
+       memset(val, 0, size);
+
+       ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+       return ret;
+}
+
+static int ocfs2_xattr_update_entry(struct inode *inode,
+                                   struct ocfs2_xattr_info *xi,
+                                   struct ocfs2_xattr_search *xs,
+                                   size_t offs)
+{
+       handle_t *handle = NULL;
+       int ret = 0;
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
+                                  OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+       ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       xs->here->xe_name_offset = cpu_to_le16(offs);
+       xs->here->xe_value_size = cpu_to_le64(xi->value_len);
+       if (xi->value_len <= OCFS2_XATTR_INLINE_SIZE)
+               ocfs2_xattr_set_local(xs->here, 1);
+       else
+               ocfs2_xattr_set_local(xs->here, 0);
+       ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
+
+       ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_set_value_outside()
+ *
+ * Set large size value in B tree.
+ */
+static int ocfs2_xattr_set_value_outside(struct inode *inode,
+                                        struct ocfs2_xattr_info *xi,
+                                        struct ocfs2_xattr_search *xs,
+                                        size_t offs)
+{
+       size_t name_len = strlen(xi->name);
+       void *val = xs->base + offs;
+       struct ocfs2_xattr_value_root *xv = NULL;
+       size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+       int ret = 0;
+
+       memset(val, 0, size);
+       memcpy(val, xi->name, name_len);
+       xv = (struct ocfs2_xattr_value_root *)
+               (val + OCFS2_XATTR_SIZE(name_len));
+       xv->xr_clusters = 0;
+       xv->xr_last_eb_blk = 0;
+       xv->xr_list.l_tree_depth = 0;
+       xv->xr_list.l_count = cpu_to_le16(1);
+       xv->xr_list.l_next_free_rec = 0;
+
+       ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv,
+                                        xi->value_len);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       ret = __ocfs2_xattr_set_value_outside(inode, xv, xi->value,
+                                             xi->value_len);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       ret = ocfs2_xattr_update_entry(inode, xi, xs, offs);
+       if (ret < 0)
+               mlog_errno(ret);
+
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_set_entry_local()
+ *
+ * Set, replace or remove extended attribute in local.
+ */
+static void ocfs2_xattr_set_entry_local(struct inode *inode,
+                                       struct ocfs2_xattr_info *xi,
+                                       struct ocfs2_xattr_search *xs,
+                                       struct ocfs2_xattr_entry *last,
+                                       size_t min_offs)
+{
+       size_t name_len = strlen(xi->name);
+       int i;
+
+       if (xi->value && xs->not_found) {
+               /* Insert the new xattr entry. */
+               le16_add_cpu(&xs->header->xh_count, 1);
+               ocfs2_xattr_set_type(last, xi->name_index);
+               ocfs2_xattr_set_local(last, 1);
+               last->xe_name_len = name_len;
+       } else {
+               void *first_val;
+               void *val;
+               size_t offs, size;
+
+               first_val = xs->base + min_offs;
+               offs = le16_to_cpu(xs->here->xe_name_offset);
+               val = xs->base + offs;
+
+               if (le64_to_cpu(xs->here->xe_value_size) >
+                   OCFS2_XATTR_INLINE_SIZE)
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                               OCFS2_XATTR_ROOT_SIZE;
+               else
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                       OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
+
+               if (xi->value && size == OCFS2_XATTR_SIZE(name_len) +
+                               OCFS2_XATTR_SIZE(xi->value_len)) {
+                       /* The old and the new value have the
+                          same size. Just replace the value. */
+                       ocfs2_xattr_set_local(xs->here, 1);
+                       xs->here->xe_value_size = cpu_to_le64(xi->value_len);
+                       /* Clear value bytes. */
+                       memset(val + OCFS2_XATTR_SIZE(name_len),
+                              0,
+                              OCFS2_XATTR_SIZE(xi->value_len));
+                       memcpy(val + OCFS2_XATTR_SIZE(name_len),
+                              xi->value,
+                              xi->value_len);
+                       return;
+               }
+               /* Remove the old name+value. */
+               memmove(first_val + size, first_val, val - first_val);
+               memset(first_val, 0, size);
+               xs->here->xe_name_hash = 0;
+               xs->here->xe_name_offset = 0;
+               ocfs2_xattr_set_local(xs->here, 1);
+               xs->here->xe_value_size = 0;
+
+               min_offs += size;
+
+               /* Adjust all value offsets. */
+               last = xs->header->xh_entries;
+               for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
+                       size_t o = le16_to_cpu(last->xe_name_offset);
+
+                       if (o < offs)
+                               last->xe_name_offset = cpu_to_le16(o + size);
+                       last += 1;
+               }
+
+               if (!xi->value) {
+                       /* Remove the old entry. */
+                       last -= 1;
+                       memmove(xs->here, xs->here + 1,
+                               (void *)last - (void *)xs->here);
+                       memset(last, 0, sizeof(struct ocfs2_xattr_entry));
+                       le16_add_cpu(&xs->header->xh_count, -1);
+               }
+       }
+       if (xi->value) {
+               /* Insert the new name+value. */
+               size_t size = OCFS2_XATTR_SIZE(name_len) +
+                               OCFS2_XATTR_SIZE(xi->value_len);
+               void *val = xs->base + min_offs - size;
+
+               xs->here->xe_name_offset = cpu_to_le16(min_offs - size);
+               memset(val, 0, size);
+               memcpy(val, xi->name, name_len);
+               memcpy(val + OCFS2_XATTR_SIZE(name_len),
+                      xi->value,
+                      xi->value_len);
+               xs->here->xe_value_size = cpu_to_le64(xi->value_len);
+               ocfs2_xattr_set_local(xs->here, 1);
+               ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
+       }
+
+       return;
+}
+
+/*
+ * ocfs2_xattr_set_entry()
+ *
+ * Set extended attribute entry into inode or block.
+ *
+ * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE,
+ * We first insert tree root(ocfs2_xattr_value_root) with set_entry_local(),
+ * then set value in B tree with set_value_outside().
+ */
+static int ocfs2_xattr_set_entry(struct inode *inode,
+                                struct ocfs2_xattr_info *xi,
+                                struct ocfs2_xattr_search *xs,
+                                int flag)
+{
+       struct ocfs2_xattr_entry *last;
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name);
+       size_t size_l = 0;
+       handle_t *handle = NULL;
+       int free, i, ret;
+       struct ocfs2_xattr_info xi_l = {
+               .name_index = xi->name_index,
+               .name = xi->name,
+               .value = xi->value,
+               .value_len = xi->value_len,
+       };
+
+       /* Compute min_offs, last and free space. */
+       last = xs->header->xh_entries;
+
+       for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
+               size_t offs = le16_to_cpu(last->xe_name_offset);
+               if (offs < min_offs)
+                       min_offs = offs;
+               last += 1;
+       }
+
+       free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+       if (free < 0)
+               return -EFAULT;
+
+       if (!xs->not_found) {
+               size_t size = 0;
+               if (ocfs2_xattr_is_local(xs->here))
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                       OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
+               else
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                               OCFS2_XATTR_ROOT_SIZE;
+               free += (size + sizeof(struct ocfs2_xattr_entry));
+       }
+       /* Check free space in inode or block */
+       if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+               if (free < sizeof(struct ocfs2_xattr_entry) +
+                          OCFS2_XATTR_SIZE(name_len) +
+                          OCFS2_XATTR_ROOT_SIZE) {
+                       ret = -ENOSPC;
+                       goto out;
+               }
+               size_l = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+               xi_l.value = (void *)&def_xv;
+               xi_l.value_len = OCFS2_XATTR_ROOT_SIZE;
+       } else if (xi->value) {
+               if (free < sizeof(struct ocfs2_xattr_entry) +
+                          OCFS2_XATTR_SIZE(name_len) +
+                          OCFS2_XATTR_SIZE(xi->value_len)) {
+                       ret = -ENOSPC;
+                       goto out;
+               }
+       }
+
+       if (!xs->not_found) {
+               /* For existing extended attribute */
+               size_t size = OCFS2_XATTR_SIZE(name_len) +
+                       OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
+               size_t offs = le16_to_cpu(xs->here->xe_name_offset);
+               void *val = xs->base + offs;
+
+               if (ocfs2_xattr_is_local(xs->here) && size == size_l) {
+                       /* Replace existing local xattr with tree root */
+                       ret = ocfs2_xattr_set_value_outside(inode, xi, xs,
+                                                           offs);
+                       if (ret < 0)
+                               mlog_errno(ret);
+                       goto out;
+               } else if (!ocfs2_xattr_is_local(xs->here)) {
+                       /* For existing xattr which has value outside */
+                       struct ocfs2_xattr_value_root *xv = NULL;
+                       xv = (struct ocfs2_xattr_value_root *)(val +
+                               OCFS2_XATTR_SIZE(name_len));
+
+                       if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+                               /*
+                                * If new value need set outside also,
+                                * first truncate old value to new value,
+                                * then set new value with set_value_outside().
+                                */
+                               ret = ocfs2_xattr_value_truncate(inode,
+                                                                xs->xattr_bh,
+                                                                xv,
+                                                                xi->value_len);
+                               if (ret < 0) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+
+                               ret = __ocfs2_xattr_set_value_outside(inode,
+                                                               xv,
+                                                               xi->value,
+                                                               xi->value_len);
+                               if (ret < 0) {
+                                       mlog_errno(ret);
+                                       goto out;
+                               }
+
+                               ret = ocfs2_xattr_update_entry(inode,
+                                                              xi,
+                                                              xs,
+                                                              offs);
+                               if (ret < 0)
+                                       mlog_errno(ret);
+                               goto out;
+                       } else {
+                               /*
+                                * If new value need set in local,
+                                * just trucate old value to zero.
+                                */
+                                ret = ocfs2_xattr_value_truncate(inode,
+                                                                xs->xattr_bh,
+                                                                xv,
+                                                                0);
+                               if (ret < 0)
+                                       mlog_errno(ret);
+                       }
+               }
+       }
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
+                                  OCFS2_INODE_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       if (!(flag & OCFS2_INLINE_XATTR_FL)) {
+               /* set extended attribute in external block. */
+               ret = ocfs2_extend_trans(handle,
+                                        OCFS2_INODE_UPDATE_CREDITS +
+                                        OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+               ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+       }
+
+       /*
+        * Set value in local, include set tree root in local.
+        * This is the first step for value size >INLINE_SIZE.
+        */
+       ocfs2_xattr_set_entry_local(inode, &xi_l, xs, last, min_offs);
+
+       if (!(flag & OCFS2_INLINE_XATTR_FL)) {
+               ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+       }
+
+       if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) &&
+           (flag & OCFS2_INLINE_XATTR_FL)) {
+               struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+               unsigned int xattrsize = osb->s_xattr_inline_size;
+
+               /*
+                * Adjust extent record count or inline data size
+                * to reserve space for extended attribute.
+                */
+               if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+                       struct ocfs2_inline_data *idata = &di->id2.i_data;
+                       le16_add_cpu(&idata->id_count, -xattrsize);
+               } else if (!(ocfs2_inode_is_fast_symlink(inode))) {
+                       struct ocfs2_extent_list *el = &di->id2.i_list;
+                       le16_add_cpu(&el->l_count, -(xattrsize /
+                                       sizeof(struct ocfs2_extent_rec)));
+               }
+               di->i_xattr_inline_size = cpu_to_le16(xattrsize);
+       }
+       /* Update xattr flag */
+       spin_lock(&oi->ip_lock);
+       oi->ip_dyn_features |= flag;
+       di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
+       spin_unlock(&oi->ip_lock);
+       /* Update inode ctime */
+       inode->i_ctime = CURRENT_TIME;
+       di->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+       di->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+
+       ret = ocfs2_journal_dirty(handle, xs->inode_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+
+       if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+               /*
+                * Set value outside in B tree.
+                * This is the second step for value size > INLINE_SIZE.
+                */
+               size_t offs = le16_to_cpu(xs->here->xe_name_offset);
+               ret = ocfs2_xattr_set_value_outside(inode, xi, xs, offs);
+               if (ret < 0) {
+                       int ret2;
+
+                       mlog_errno(ret);
+                       /*
+                        * If set value outside failed, we have to clean
+                        * the junk tree root we have already set in local.
+                        */
+                       ret2 = ocfs2_xattr_cleanup(inode, xi, xs, offs);
+                       if (ret2 < 0)
+                               mlog_errno(ret2);
+               }
+       }
+out:
+       return ret;
+
+}
+
+static int ocfs2_remove_value_outside(struct inode*inode,
+                                     struct buffer_head *bh,
+                                     struct ocfs2_xattr_header *header)
+{
+       int ret = 0, i;
+
+       for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
+               struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
+
+               if (!ocfs2_xattr_is_local(entry)) {
+                       struct ocfs2_xattr_value_root *xv;
+                       void *val;
+
+                       val = (void *)header +
+                               le16_to_cpu(entry->xe_name_offset);
+                       xv = (struct ocfs2_xattr_value_root *)
+                               (val + OCFS2_XATTR_SIZE(entry->xe_name_len));
+                       ret = ocfs2_xattr_value_truncate(inode, bh, xv, 0);
+                       if (ret < 0) {
+                               mlog_errno(ret);
+                               return ret;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+static int ocfs2_xattr_ibody_remove(struct inode *inode,
+                                   struct buffer_head *di_bh)
+{
+
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+       struct ocfs2_xattr_header *header;
+       int ret;
+
+       header = (struct ocfs2_xattr_header *)
+                ((void *)di + inode->i_sb->s_blocksize -
+                le16_to_cpu(di->i_xattr_inline_size));
+
+       ret = ocfs2_remove_value_outside(inode, di_bh, header);
+
+       return ret;
+}
+
+static int ocfs2_xattr_block_remove(struct inode *inode,
+                                   struct buffer_head *blk_bh)
+{
+       struct ocfs2_xattr_block *xb;
+       int ret = 0;
+
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
+       if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
+               struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header);
+               ret = ocfs2_remove_value_outside(inode, blk_bh, header);
+       } else
+               ret = ocfs2_delete_xattr_index_block(inode, blk_bh);
+
+       return ret;
+}
+
+static int ocfs2_xattr_free_block(struct inode *inode,
+                                 u64 block)
+{
+       struct inode *xb_alloc_inode;
+       struct buffer_head *xb_alloc_bh = NULL;
+       struct buffer_head *blk_bh = NULL;
+       struct ocfs2_xattr_block *xb;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       handle_t *handle;
+       int ret = 0;
+       u64 blk, bg_blkno;
+       u16 bit;
+
+       ret = ocfs2_read_block(inode, block, &blk_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       /*Verify the signature of xattr block*/
+       if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
+                  strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = ocfs2_xattr_block_remove(inode, blk_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
+       blk = le64_to_cpu(xb->xb_blkno);
+       bit = le16_to_cpu(xb->xb_suballoc_bit);
+       bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+
+       xb_alloc_inode = ocfs2_get_system_file_inode(osb,
+                               EXTENT_ALLOC_SYSTEM_INODE,
+                               le16_to_cpu(xb->xb_suballoc_slot));
+       if (!xb_alloc_inode) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+       mutex_lock(&xb_alloc_inode->i_mutex);
+
+       ret = ocfs2_inode_lock(xb_alloc_inode, &xb_alloc_bh, 1);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out_mutex;
+       }
+
+       handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out_unlock;
+       }
+
+       ret = ocfs2_free_suballoc_bits(handle, xb_alloc_inode, xb_alloc_bh,
+                                      bit, bg_blkno, 1);
+       if (ret < 0)
+               mlog_errno(ret);
+
+       ocfs2_commit_trans(osb, handle);
+out_unlock:
+       ocfs2_inode_unlock(xb_alloc_inode, 1);
+       brelse(xb_alloc_bh);
+out_mutex:
+       mutex_unlock(&xb_alloc_inode->i_mutex);
+       iput(xb_alloc_inode);
+out:
+       brelse(blk_bh);
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_remove()
+ *
+ * Free extended attribute resources associated with this inode.
+ */
+int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
+{
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+       handle_t *handle;
+       int ret;
+
+       if (!ocfs2_supports_xattr(OCFS2_SB(inode->i_sb)))
+               return 0;
+
+       if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
+               return 0;
+
+       if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
+               ret = ocfs2_xattr_ibody_remove(inode, di_bh);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       if (di->i_xattr_loc) {
+               ret = ocfs2_xattr_free_block(inode,
+                                            le64_to_cpu(di->i_xattr_loc));
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)),
+                                  OCFS2_INODE_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out;
+       }
+       ret = ocfs2_journal_access(handle, inode, di_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       di->i_xattr_loc = 0;
+
+       spin_lock(&oi->ip_lock);
+       oi->ip_dyn_features &= ~(OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL);
+       di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
+       spin_unlock(&oi->ip_lock);
+
+       ret = ocfs2_journal_dirty(handle, di_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+       return ret;
+}
+
+static int ocfs2_xattr_has_space_inline(struct inode *inode,
+                                       struct ocfs2_dinode *di)
+{
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       unsigned int xattrsize = OCFS2_SB(inode->i_sb)->s_xattr_inline_size;
+       int free;
+
+       if (xattrsize < OCFS2_MIN_XATTR_INLINE_SIZE)
+               return 0;
+
+       if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+               struct ocfs2_inline_data *idata = &di->id2.i_data;
+               free = le16_to_cpu(idata->id_count) - le64_to_cpu(di->i_size);
+       } else if (ocfs2_inode_is_fast_symlink(inode)) {
+               free = ocfs2_fast_symlink_chars(inode->i_sb) -
+                       le64_to_cpu(di->i_size);
+       } else {
+               struct ocfs2_extent_list *el = &di->id2.i_list;
+               free = (le16_to_cpu(el->l_count) -
+                       le16_to_cpu(el->l_next_free_rec)) *
+                       sizeof(struct ocfs2_extent_rec);
+       }
+       if (free >= xattrsize)
+               return 1;
+
+       return 0;
+}
+
+/*
+ * ocfs2_xattr_ibody_find()
+ *
+ * Find extended attribute in inode block and
+ * fill search info into struct ocfs2_xattr_search.
+ */
+static int ocfs2_xattr_ibody_find(struct inode *inode,
+                                 int name_index,
+                                 const char *name,
+                                 struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       int ret;
+       int has_space = 0;
+
+       if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE)
+               return 0;
+
+       if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) {
+               down_read(&oi->ip_alloc_sem);
+               has_space = ocfs2_xattr_has_space_inline(inode, di);
+               up_read(&oi->ip_alloc_sem);
+               if (!has_space)
+                       return 0;
+       }
+
+       xs->xattr_bh = xs->inode_bh;
+       xs->end = (void *)di + inode->i_sb->s_blocksize;
+       if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)
+               xs->header = (struct ocfs2_xattr_header *)
+                       (xs->end - le16_to_cpu(di->i_xattr_inline_size));
+       else
+               xs->header = (struct ocfs2_xattr_header *)
+                       (xs->end - OCFS2_SB(inode->i_sb)->s_xattr_inline_size);
+       xs->base = (void *)xs->header;
+       xs->here = xs->header->xh_entries;
+
+       /* Find the named attribute. */
+       if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
+               ret = ocfs2_xattr_find_entry(name_index, name, xs);
+               if (ret && ret != -ENODATA)
+                       return ret;
+               xs->not_found = ret;
+       }
+
+       return 0;
+}
+
+/*
+ * ocfs2_xattr_ibody_set()
+ *
+ * Set, replace or remove an extended attribute into inode block.
+ *
+ */
+static int ocfs2_xattr_ibody_set(struct inode *inode,
+                                struct ocfs2_xattr_info *xi,
+                                struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       int ret;
+
+       if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE)
+               return -ENOSPC;
+
+       down_write(&oi->ip_alloc_sem);
+       if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) {
+               if (!ocfs2_xattr_has_space_inline(inode, di)) {
+                       ret = -ENOSPC;
+                       goto out;
+               }
+       }
+
+       ret = ocfs2_xattr_set_entry(inode, xi, xs,
+                               (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL));
+out:
+       up_write(&oi->ip_alloc_sem);
+
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_block_find()
+ *
+ * Find extended attribute in external block and
+ * fill search info into struct ocfs2_xattr_search.
+ */
+static int ocfs2_xattr_block_find(struct inode *inode,
+                                 int name_index,
+                                 const char *name,
+                                 struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       struct buffer_head *blk_bh = NULL;
+       struct ocfs2_xattr_block *xb;
+       int ret = 0;
+
+       if (!di->i_xattr_loc)
+               return ret;
+
+       ret = ocfs2_read_block(inode, le64_to_cpu(di->i_xattr_loc), &blk_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       /*Verify the signature of xattr block*/
+       if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
+                  strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
+                       ret = -EFAULT;
+                       goto cleanup;
+       }
+
+       xs->xattr_bh = blk_bh;
+       xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
+
+       if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
+               xs->header = &xb->xb_attrs.xb_header;
+               xs->base = (void *)xs->header;
+               xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
+               xs->here = xs->header->xh_entries;
+
+               ret = ocfs2_xattr_find_entry(name_index, name, xs);
+       } else
+               ret = ocfs2_xattr_index_block_find(inode, blk_bh,
+                                                  name_index,
+                                                  name, xs);
+
+       if (ret && ret != -ENODATA) {
+               xs->xattr_bh = NULL;
+               goto cleanup;
+       }
+       xs->not_found = ret;
+       return 0;
+cleanup:
+       brelse(blk_bh);
+
+       return ret;
+}
+
+/*
+ * When all the xattrs are deleted from index btree, the ocfs2_xattr_tree
+ * will be erased and ocfs2_xattr_block will have its ocfs2_xattr_header
+ * re-initialized.
+ */
+static int ocfs2_restore_xattr_block(struct inode *inode,
+                                    struct ocfs2_xattr_search *xs)
+{
+       int ret;
+       handle_t *handle;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_xattr_block *xb =
+               (struct ocfs2_xattr_block *)xs->xattr_bh->b_data;
+       struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
+       u16 xb_flags = le16_to_cpu(xb->xb_flags);
+
+       BUG_ON(!(xb_flags & OCFS2_XATTR_INDEXED) ||
+               le16_to_cpu(el->l_next_free_rec) != 0);
+
+       handle = ocfs2_start_trans(osb, OCFS2_XATTR_BLOCK_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, xs->xattr_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize -
+              offsetof(struct ocfs2_xattr_block, xb_attrs));
+
+       xb->xb_flags = cpu_to_le16(xb_flags & ~OCFS2_XATTR_INDEXED);
+
+       ocfs2_journal_dirty(handle, xs->xattr_bh);
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_block_set()
+ *
+ * Set, replace or remove an extended attribute into external block.
+ *
+ */
+static int ocfs2_xattr_block_set(struct inode *inode,
+                                struct ocfs2_xattr_info *xi,
+                                struct ocfs2_xattr_search *xs)
+{
+       struct buffer_head *new_bh = NULL;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_dinode *di =  (struct ocfs2_dinode *)xs->inode_bh->b_data;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       handle_t *handle = NULL;
+       struct ocfs2_xattr_block *xblk = NULL;
+       u16 suballoc_bit_start;
+       u32 num_got;
+       u64 first_blkno;
+       int ret;
+
+       if (!xs->xattr_bh) {
+               /*
+                * Alloc one external block for extended attribute
+                * outside of inode.
+                */
+               ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+               handle = ocfs2_start_trans(osb,
+                                          OCFS2_XATTR_BLOCK_CREATE_CREDITS);
+               if (IS_ERR(handle)) {
+                       ret = PTR_ERR(handle);
+                       mlog_errno(ret);
+                       goto out;
+               }
+               ret = ocfs2_journal_access(handle, inode, xs->inode_bh,
+                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+
+               ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
+                                          &suballoc_bit_start, &num_got,
+                                          &first_blkno);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+
+               new_bh = sb_getblk(inode->i_sb, first_blkno);
+               ocfs2_set_new_buffer_uptodate(inode, new_bh);
+
+               ret = ocfs2_journal_access(handle, inode, new_bh,
+                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+
+               /* Initialize ocfs2_xattr_block */
+               xs->xattr_bh = new_bh;
+               xblk = (struct ocfs2_xattr_block *)new_bh->b_data;
+               memset(xblk, 0, inode->i_sb->s_blocksize);
+               strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
+               xblk->xb_suballoc_slot = cpu_to_le16(osb->slot_num);
+               xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
+               xblk->xb_fs_generation = cpu_to_le32(osb->fs_generation);
+               xblk->xb_blkno = cpu_to_le64(first_blkno);
+
+               xs->header = &xblk->xb_attrs.xb_header;
+               xs->base = (void *)xs->header;
+               xs->end = (void *)xblk + inode->i_sb->s_blocksize;
+               xs->here = xs->header->xh_entries;
+
+
+               ret = ocfs2_journal_dirty(handle, new_bh);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+               di->i_xattr_loc = cpu_to_le64(first_blkno);
+               ret = ocfs2_journal_dirty(handle, xs->inode_bh);
+               if (ret < 0)
+                       mlog_errno(ret);
+out_commit:
+               ocfs2_commit_trans(osb, handle);
+out:
+               if (meta_ac)
+                       ocfs2_free_alloc_context(meta_ac);
+               if (ret < 0)
+                       return ret;
+       } else
+               xblk = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data;
+
+       if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) {
+               /* Set extended attribute into external block */
+               ret = ocfs2_xattr_set_entry(inode, xi, xs, OCFS2_HAS_XATTR_FL);
+               if (!ret || ret != -ENOSPC)
+                       goto end;
+
+               ret = ocfs2_xattr_create_index_block(inode, xs);
+               if (ret)
+                       goto end;
+       }
+
+       ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs);
+       if (!ret && xblk->xb_attrs.xb_root.xt_list.l_next_free_rec == 0)
+               ret = ocfs2_restore_xattr_block(inode, xs);
+
+end:
+
+       return ret;
+}
+
+/*
+ * ocfs2_xattr_set()
+ *
+ * Set, replace or remove an extended attribute for this inode.
+ * value is NULL to remove an existing extended attribute, else either
+ * create or replace an extended attribute.
+ */
+int ocfs2_xattr_set(struct inode *inode,
+                   int name_index,
+                   const char *name,
+                   const void *value,
+                   size_t value_len,
+                   int flags)
+{
+       struct buffer_head *di_bh = NULL;
+       struct ocfs2_dinode *di;
+       int ret;
+       u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       struct ocfs2_xattr_info xi = {
+               .name_index = name_index,
+               .name = name,
+               .value = value,
+               .value_len = value_len,
+       };
+
+       struct ocfs2_xattr_search xis = {
+               .not_found = -ENODATA,
+       };
+
+       struct ocfs2_xattr_search xbs = {
+               .not_found = -ENODATA,
+       };
+
+       if (!ocfs2_supports_xattr(OCFS2_SB(inode->i_sb)))
+               return -EOPNOTSUPP;
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 1);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+       xis.inode_bh = xbs.inode_bh = di_bh;
+       di = (struct ocfs2_dinode *)di_bh->b_data;
+
+       down_write(&OCFS2_I(inode)->ip_xattr_sem);
+       /*
+        * Scan inode and external block to find the same name
+        * extended attribute and collect search infomation.
+        */
+       ret = ocfs2_xattr_ibody_find(inode, name_index, name, &xis);
+       if (ret)
+               goto cleanup;
+       if (xis.not_found) {
+               ret = ocfs2_xattr_block_find(inode, name_index, name, &xbs);
+               if (ret)
+                       goto cleanup;
+       }
+
+       if (xis.not_found && xbs.not_found) {
+               ret = -ENODATA;
+               if (flags & XATTR_REPLACE)
+                       goto cleanup;
+               ret = 0;
+               if (!value)
+                       goto cleanup;
+       } else {
+               ret = -EEXIST;
+               if (flags & XATTR_CREATE)
+                       goto cleanup;
+       }
+
+       if (!value) {
+               /* Remove existing extended attribute */
+               if (!xis.not_found)
+                       ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
+               else if (!xbs.not_found)
+                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
+       } else {
+               /* We always try to set extended attribute into inode first*/
+               ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
+               if (!ret && !xbs.not_found) {
+                       /*
+                        * If succeed and that extended attribute existing in
+                        * external block, then we will remove it.
+                        */
+                       xi.value = NULL;
+                       xi.value_len = 0;
+                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
+               } else if (ret == -ENOSPC) {
+                       if (di->i_xattr_loc && !xbs.xattr_bh) {
+                               ret = ocfs2_xattr_block_find(inode, name_index,
+                                                            name, &xbs);
+                               if (ret)
+                                       goto cleanup;
+                       }
+                       /*
+                        * If no space in inode, we will set extended attribute
+                        * into external block.
+                        */
+                       ret = ocfs2_xattr_block_set(inode, &xi, &xbs);
+                       if (ret)
+                               goto cleanup;
+                       if (!xis.not_found) {
+                               /*
+                                * If succeed and that extended attribute
+                                * existing in inode, we will remove it.
+                                */
+                               xi.value = NULL;
+                               xi.value_len = 0;
+                               ret = ocfs2_xattr_ibody_set(inode, &xi, &xis);
+                       }
+               }
+       }
+cleanup:
+       up_write(&OCFS2_I(inode)->ip_xattr_sem);
+       ocfs2_inode_unlock(inode, 1);
+       brelse(di_bh);
+       brelse(xbs.xattr_bh);
+       for (i = 0; i < blk_per_bucket; i++)
+               brelse(xbs.bucket.bhs[i]);
+
+       return ret;
+}
+
+/*
+ * Find the xattr extent rec which may contains name_hash.
+ * e_cpos will be the first name hash of the xattr rec.
+ * el must be the ocfs2_xattr_header.xb_attrs.xb_root.xt_list.
+ */
+static int ocfs2_xattr_get_rec(struct inode *inode,
+                              u32 name_hash,
+                              u64 *p_blkno,
+                              u32 *e_cpos,
+                              u32 *num_clusters,
+                              struct ocfs2_extent_list *el)
+{
+       int ret = 0, i;
+       struct buffer_head *eb_bh = NULL;
+       struct ocfs2_extent_block *eb;
+       struct ocfs2_extent_rec *rec = NULL;
+       u64 e_blkno = 0;
+
+       if (el->l_tree_depth) {
+               ret = ocfs2_find_leaf(inode, el, name_hash, &eb_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               eb = (struct ocfs2_extent_block *) eb_bh->b_data;
+               el = &eb->h_list;
+
+               if (el->l_tree_depth) {
+                       ocfs2_error(inode->i_sb,
+                                   "Inode %lu has non zero tree depth in "
+                                   "xattr tree block %llu\n", inode->i_ino,
+                                   (unsigned long long)eb_bh->b_blocknr);
+                       ret = -EROFS;
+                       goto out;
+               }
+       }
+
+       for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
+               rec = &el->l_recs[i];
+
+               if (le32_to_cpu(rec->e_cpos) <= name_hash) {
+                       e_blkno = le64_to_cpu(rec->e_blkno);
+                       break;
+               }
+       }
+
+       if (!e_blkno) {
+               ocfs2_error(inode->i_sb, "Inode %lu has bad extent "
+                           "record (%u, %u, 0) in xattr", inode->i_ino,
+                           le32_to_cpu(rec->e_cpos),
+                           ocfs2_rec_clusters(el, rec));
+               ret = -EROFS;
+               goto out;
+       }
+
+       *p_blkno = le64_to_cpu(rec->e_blkno);
+       *num_clusters = le16_to_cpu(rec->e_leaf_clusters);
+       if (e_cpos)
+               *e_cpos = le32_to_cpu(rec->e_cpos);
+out:
+       brelse(eb_bh);
+       return ret;
+}
+
+typedef int (xattr_bucket_func)(struct inode *inode,
+                               struct ocfs2_xattr_bucket *bucket,
+                               void *para);
+
+static int ocfs2_find_xe_in_bucket(struct inode *inode,
+                                  struct buffer_head *header_bh,
+                                  int name_index,
+                                  const char *name,
+                                  u32 name_hash,
+                                  u16 *xe_index,
+                                  int *found)
+{
+       int i, ret = 0, cmp = 1, block_off, new_offset;
+       struct ocfs2_xattr_header *xh =
+                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       size_t name_len = strlen(name);
+       struct ocfs2_xattr_entry *xe = NULL;
+       struct buffer_head *name_bh = NULL;
+       char *xe_name;
+
+       /*
+        * We don't use binary search in the bucket because there
+        * may be multiple entries with the same name hash.
+        */
+       for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
+               xe = &xh->xh_entries[i];
+
+               if (name_hash > le32_to_cpu(xe->xe_name_hash))
+                       continue;
+               else if (name_hash < le32_to_cpu(xe->xe_name_hash))
+                       break;
+
+               cmp = name_index - ocfs2_xattr_get_type(xe);
+               if (!cmp)
+                       cmp = name_len - xe->xe_name_len;
+               if (cmp)
+                       continue;
+
+               ret = ocfs2_xattr_bucket_get_name_value(inode,
+                                                       xh,
+                                                       i,
+                                                       &block_off,
+                                                       &new_offset);
+               if (ret) {
+                       mlog_errno(ret);
+                       break;
+               }
+
+               ret = ocfs2_read_block(inode, header_bh->b_blocknr + block_off,
+                                      &name_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       break;
+               }
+               xe_name = name_bh->b_data + new_offset;
+
+               cmp = memcmp(name, xe_name, name_len);
+               brelse(name_bh);
+               name_bh = NULL;
+
+               if (cmp == 0) {
+                       *xe_index = i;
+                       *found = 1;
+                       ret = 0;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * Find the specified xattr entry in a series of buckets.
+ * This series start from p_blkno and last for num_clusters.
+ * The ocfs2_xattr_header.xh_num_buckets of the first bucket contains
+ * the num of the valid buckets.
+ *
+ * Return the buffer_head this xattr should reside in. And if the xattr's
+ * hash is in the gap of 2 buckets, return the lower bucket.
+ */
+static int ocfs2_xattr_bucket_find(struct inode *inode,
+                                  int name_index,
+                                  const char *name,
+                                  u32 name_hash,
+                                  u64 p_blkno,
+                                  u32 first_hash,
+                                  u32 num_clusters,
+                                  struct ocfs2_xattr_search *xs)
+{
+       int ret, found = 0;
+       struct buffer_head *bh = NULL;
+       struct buffer_head *lower_bh = NULL;
+       struct ocfs2_xattr_header *xh = NULL;
+       struct ocfs2_xattr_entry *xe = NULL;
+       u16 index = 0;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       int low_bucket = 0, bucket, high_bucket;
+       u32 last_hash;
+       u64 blkno;
+
+       ret = ocfs2_read_block(inode, p_blkno, &bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       xh = (struct ocfs2_xattr_header *)bh->b_data;
+       high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1;
+
+       while (low_bucket <= high_bucket) {
+               brelse(bh);
+               bh = NULL;
+               bucket = (low_bucket + high_bucket) / 2;
+
+               blkno = p_blkno + bucket * blk_per_bucket;
+
+               ret = ocfs2_read_block(inode, blkno, &bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               xh = (struct ocfs2_xattr_header *)bh->b_data;
+               xe = &xh->xh_entries[0];
+               if (name_hash < le32_to_cpu(xe->xe_name_hash)) {
+                       high_bucket = bucket - 1;
+                       continue;
+               }
+
+               /*
+                * Check whether the hash of the last entry in our
+                * bucket is larger than the search one. for an empty
+                * bucket, the last one is also the first one.
+                */
+               if (xh->xh_count)
+                       xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1];
+
+               last_hash = le32_to_cpu(xe->xe_name_hash);
+
+               /* record lower_bh which may be the insert place. */
+               brelse(lower_bh);
+               lower_bh = bh;
+               bh = NULL;
+
+               if (name_hash > le32_to_cpu(xe->xe_name_hash)) {
+                       low_bucket = bucket + 1;
+                       continue;
+               }
+
+               /* the searched xattr should reside in this bucket if exists. */
+               ret = ocfs2_find_xe_in_bucket(inode, lower_bh,
+                                             name_index, name, name_hash,
+                                             &index, &found);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+               break;
+       }
+
+       /*
+        * Record the bucket we have found.
+        * When the xattr's hash value is in the gap of 2 buckets, we will
+        * always set it to the previous bucket.
+        */
+       if (!lower_bh) {
+               /*
+                * We can't find any bucket whose first name_hash is less
+                * than the find name_hash.
+                */
+               BUG_ON(bh->b_blocknr != p_blkno);
+               lower_bh = bh;
+               bh = NULL;
+       }
+       xs->bucket.bhs[0] = lower_bh;
+       xs->bucket.xh = (struct ocfs2_xattr_header *)
+                                       xs->bucket.bhs[0]->b_data;
+       lower_bh = NULL;
+
+       xs->header = xs->bucket.xh;
+       xs->base = xs->bucket.bhs[0]->b_data;
+       xs->end = xs->base + inode->i_sb->s_blocksize;
+
+       if (found) {
+               /*
+                * If we have found the xattr enty, read all the blocks in
+                * this bucket.
+                */
+               ret = ocfs2_read_blocks(inode, xs->bucket.bhs[0]->b_blocknr + 1,
+                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
+                                       0);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               xs->here = &xs->header->xh_entries[index];
+               mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name,
+                    (unsigned long long)xs->bucket.bhs[0]->b_blocknr, index);
+       } else
+               ret = -ENODATA;
+
+out:
+       brelse(bh);
+       brelse(lower_bh);
+       return ret;
+}
+
+static int ocfs2_xattr_index_block_find(struct inode *inode,
+                                       struct buffer_head *root_bh,
+                                       int name_index,
+                                       const char *name,
+                                       struct ocfs2_xattr_search *xs)
+{
+       int ret;
+       struct ocfs2_xattr_block *xb =
+                       (struct ocfs2_xattr_block *)root_bh->b_data;
+       struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root;
+       struct ocfs2_extent_list *el = &xb_root->xt_list;
+       u64 p_blkno = 0;
+       u32 first_hash, num_clusters = 0;
+       u32 name_hash = ocfs2_xattr_name_hash(inode, name, strlen(name));
+
+       if (le16_to_cpu(el->l_next_free_rec) == 0)
+               return -ENODATA;
+
+       mlog(0, "find xattr %s, hash = %u, index = %d in xattr tree\n",
+            name, name_hash, name_index);
+
+       ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &first_hash,
+                                 &num_clusters, el);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash);
+
+       mlog(0, "find xattr extent rec %u clusters from %llu, the first hash "
+            "in the rec is %u\n", num_clusters, p_blkno, first_hash);
+
+       ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash,
+                                     p_blkno, first_hash, num_clusters, xs);
+
+out:
+       return ret;
+}
+
+static int ocfs2_iterate_xattr_buckets(struct inode *inode,
+                                      u64 blkno,
+                                      u32 clusters,
+                                      xattr_bucket_func *func,
+                                      void *para)
+{
+       int i, j, ret = 0;
+       int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb));
+       u32 num_buckets = clusters * bpc;
+       struct ocfs2_xattr_bucket bucket;
+
+       memset(&bucket, 0, sizeof(bucket));
+
+       mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n",
+            clusters, blkno);
+
+       for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
+               ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket,
+                                       bucket.bhs, 0);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               bucket.xh = (struct ocfs2_xattr_header *)bucket.bhs[0]->b_data;
+               /*
+                * The real bucket num in this series of blocks is stored
+                * in the 1st bucket.
+                */
+               if (i == 0)
+                       num_buckets = le16_to_cpu(bucket.xh->xh_num_buckets);
+
+               mlog(0, "iterating xattr bucket %llu, first hash %u\n", blkno,
+                    le32_to_cpu(bucket.xh->xh_entries[0].xe_name_hash));
+               if (func) {
+                       ret = func(inode, &bucket, para);
+                       if (ret) {
+                               mlog_errno(ret);
+                               break;
+                       }
+               }
+
+               for (j = 0; j < blk_per_bucket; j++)
+                       brelse(bucket.bhs[j]);
+               memset(&bucket, 0, sizeof(bucket));
+       }
+
+out:
+       for (j = 0; j < blk_per_bucket; j++)
+               brelse(bucket.bhs[j]);
+
+       return ret;
+}
+
+struct ocfs2_xattr_tree_list {
+       char *buffer;
+       size_t buffer_size;
+       size_t result;
+};
+
+static int ocfs2_xattr_bucket_get_name_value(struct inode *inode,
+                                            struct ocfs2_xattr_header *xh,
+                                            int index,
+                                            int *block_off,
+                                            int *new_offset)
+{
+       u16 name_offset;
+
+       if (index < 0 || index >= le16_to_cpu(xh->xh_count))
+               return -EINVAL;
+
+       name_offset = le16_to_cpu(xh->xh_entries[index].xe_name_offset);
+
+       *block_off = name_offset >> inode->i_sb->s_blocksize_bits;
+       *new_offset = name_offset % inode->i_sb->s_blocksize;
+
+       return 0;
+}
+
+static int ocfs2_list_xattr_bucket(struct inode *inode,
+                                  struct ocfs2_xattr_bucket *bucket,
+                                  void *para)
+{
+       int ret = 0, type;
+       struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para;
+       int i, block_off, new_offset;
+       const char *prefix, *name;
+
+       for (i = 0 ; i < le16_to_cpu(bucket->xh->xh_count); i++) {
+               struct ocfs2_xattr_entry *entry = &bucket->xh->xh_entries[i];
+               type = ocfs2_xattr_get_type(entry);
+               prefix = ocfs2_xattr_prefix(type);
+
+               if (prefix) {
+                       ret = ocfs2_xattr_bucket_get_name_value(inode,
+                                                               bucket->xh,
+                                                               i,
+                                                               &block_off,
+                                                               &new_offset);
+                       if (ret)
+                               break;
+
+                       name = (const char *)bucket->bhs[block_off]->b_data +
+                               new_offset;
+                       ret = ocfs2_xattr_list_entry(xl->buffer,
+                                                    xl->buffer_size,
+                                                    &xl->result,
+                                                    prefix, name,
+                                                    entry->xe_name_len);
+                       if (ret)
+                               break;
+               }
+       }
+
+       return ret;
+}
+
+static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
+                                            struct ocfs2_xattr_tree_root *xt,
+                                            char *buffer,
+                                            size_t buffer_size)
+{
+       struct ocfs2_extent_list *el = &xt->xt_list;
+       int ret = 0;
+       u32 name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
+       u64 p_blkno = 0;
+       struct ocfs2_xattr_tree_list xl = {
+               .buffer = buffer,
+               .buffer_size = buffer_size,
+               .result = 0,
+       };
+
+       if (le16_to_cpu(el->l_next_free_rec) == 0)
+               return 0;
+
+       while (name_hash > 0) {
+               ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno,
+                                         &e_cpos, &num_clusters, el);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters,
+                                                 ocfs2_list_xattr_bucket,
+                                                 &xl);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               if (e_cpos == 0)
+                       break;
+
+               name_hash = e_cpos - 1;
+       }
+
+       ret = xl.result;
+out:
+       return ret;
+}
+
+static int cmp_xe(const void *a, const void *b)
+{
+       const struct ocfs2_xattr_entry *l = a, *r = b;
+       u32 l_hash = le32_to_cpu(l->xe_name_hash);
+       u32 r_hash = le32_to_cpu(r->xe_name_hash);
+
+       if (l_hash > r_hash)
+               return 1;
+       if (l_hash < r_hash)
+               return -1;
+       return 0;
+}
+
+static void swap_xe(void *a, void *b, int size)
+{
+       struct ocfs2_xattr_entry *l = a, *r = b, tmp;
+
+       tmp = *l;
+       memcpy(l, r, sizeof(struct ocfs2_xattr_entry));
+       memcpy(r, &tmp, sizeof(struct ocfs2_xattr_entry));
+}
+
+/*
+ * When the ocfs2_xattr_block is filled up, new bucket will be created
+ * and all the xattr entries will be moved to the new bucket.
+ * Note: we need to sort the entries since they are not saved in order
+ * in the ocfs2_xattr_block.
+ */
+static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode,
+                                          struct buffer_head *xb_bh,
+                                          struct buffer_head *xh_bh,
+                                          struct buffer_head *data_bh)
+{
+       int i, blocksize = inode->i_sb->s_blocksize;
+       u16 offset, size, off_change;
+       struct ocfs2_xattr_entry *xe;
+       struct ocfs2_xattr_block *xb =
+                               (struct ocfs2_xattr_block *)xb_bh->b_data;
+       struct ocfs2_xattr_header *xb_xh = &xb->xb_attrs.xb_header;
+       struct ocfs2_xattr_header *xh =
+                               (struct ocfs2_xattr_header *)xh_bh->b_data;
+       u16 count = le16_to_cpu(xb_xh->xh_count);
+       char *target = xh_bh->b_data, *src = xb_bh->b_data;
+
+       mlog(0, "cp xattr from block %llu to bucket %llu\n",
+            (unsigned long long)xb_bh->b_blocknr,
+            (unsigned long long)xh_bh->b_blocknr);
+
+       memset(xh_bh->b_data, 0, blocksize);
+       if (data_bh)
+               memset(data_bh->b_data, 0, blocksize);
+       /*
+        * Since the xe_name_offset is based on ocfs2_xattr_header,
+        * there is a offset change corresponding to the change of
+        * ocfs2_xattr_header's position.
+        */
+       off_change = offsetof(struct ocfs2_xattr_block, xb_attrs.xb_header);
+       xe = &xb_xh->xh_entries[count - 1];
+       offset = le16_to_cpu(xe->xe_name_offset) + off_change;
+       size = blocksize - offset;
+
+       /* copy all the names and values. */
+       if (data_bh)
+               target = data_bh->b_data;
+       memcpy(target + offset, src + offset, size);
+
+       /* Init new header now. */
+       xh->xh_count = xb_xh->xh_count;
+       xh->xh_num_buckets = cpu_to_le16(1);
+       xh->xh_name_value_len = cpu_to_le16(size);
+       xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE - size);
+
+       /* copy all the entries. */
+       target = xh_bh->b_data;
+       offset = offsetof(struct ocfs2_xattr_header, xh_entries);
+       size = count * sizeof(struct ocfs2_xattr_entry);
+       memcpy(target + offset, (char *)xb_xh + offset, size);
+
+       /* Change the xe offset for all the xe because of the move. */
+       off_change = OCFS2_XATTR_BUCKET_SIZE - blocksize +
+                offsetof(struct ocfs2_xattr_block, xb_attrs.xb_header);
+       for (i = 0; i < count; i++)
+               le16_add_cpu(&xh->xh_entries[i].xe_name_offset, off_change);
+
+       mlog(0, "copy entry: start = %u, size = %u, offset_change = %u\n",
+            offset, size, off_change);
+
+       sort(target + offset, count, sizeof(struct ocfs2_xattr_entry),
+            cmp_xe, swap_xe);
+}
+
+/*
+ * After we move xattr from block to index btree, we have to
+ * update ocfs2_xattr_search to the new xe and base.
+ *
+ * When the entry is in xattr block, xattr_bh indicates the storage place.
+ * While if the entry is in index b-tree, "bucket" indicates the
+ * real place of the xattr.
+ */
+static int ocfs2_xattr_update_xattr_search(struct inode *inode,
+                                          struct ocfs2_xattr_search *xs,
+                                          struct buffer_head *old_bh,
+                                          struct buffer_head *new_bh)
+{
+       int ret = 0;
+       char *buf = old_bh->b_data;
+       struct ocfs2_xattr_block *old_xb = (struct ocfs2_xattr_block *)buf;
+       struct ocfs2_xattr_header *old_xh = &old_xb->xb_attrs.xb_header;
+       int i, blocksize = inode->i_sb->s_blocksize;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       xs->bucket.bhs[0] = new_bh;
+       get_bh(new_bh);
+       xs->bucket.xh = (struct ocfs2_xattr_header *)xs->bucket.bhs[0]->b_data;
+       xs->header = xs->bucket.xh;
+
+       xs->base = new_bh->b_data;
+       xs->end = xs->base + inode->i_sb->s_blocksize;
+
+       if (!xs->not_found) {
+               if (OCFS2_XATTR_BUCKET_SIZE != blocksize) {
+                       ret = ocfs2_read_blocks(inode,
+                                       xs->bucket.bhs[0]->b_blocknr + 1,
+                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
+                                       0);
+                       if (ret) {
+                               mlog_errno(ret);
+                               return ret;
+                       }
+
+                       i = xs->here - old_xh->xh_entries;
+                       xs->here = &xs->header->xh_entries[i];
+               }
+       }
+
+       return ret;
+}
+
+static int ocfs2_xattr_create_index_block(struct inode *inode,
+                                         struct ocfs2_xattr_search *xs)
+{
+       int ret, credits = OCFS2_SUBALLOC_ALLOC;
+       u32 bit_off, len;
+       u64 blkno;
+       handle_t *handle;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_inode_info *oi = OCFS2_I(inode);
+       struct ocfs2_alloc_context *data_ac;
+       struct buffer_head *xh_bh = NULL, *data_bh = NULL;
+       struct buffer_head *xb_bh = xs->xattr_bh;
+       struct ocfs2_xattr_block *xb =
+                       (struct ocfs2_xattr_block *)xb_bh->b_data;
+       struct ocfs2_xattr_tree_root *xr;
+       u16 xb_flags = le16_to_cpu(xb->xb_flags);
+       u16 bpb = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       mlog(0, "create xattr index block for %llu\n",
+            (unsigned long long)xb_bh->b_blocknr);
+
+       BUG_ON(xb_flags & OCFS2_XATTR_INDEXED);
+
+       ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       /*
+        * XXX:
+        * We can use this lock for now, and maybe move to a dedicated mutex
+        * if performance becomes a problem later.
+        */
+       down_write(&oi->ip_alloc_sem);
+
+       /*
+        * 3 more credits, one for xattr block update, one for the 1st block
+        * of the new xattr bucket and one for the value/data.
+        */
+       credits += 3;
+       handle = ocfs2_start_trans(osb, credits);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               goto out_sem;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, xb_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       /*
+        * The bucket may spread in many blocks, and
+        * we will only touch the 1st block and the last block
+        * in the whole bucket(one for entry and one for data).
+        */
+       blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off);
+
+       mlog(0, "allocate 1 cluster from %llu to xattr block\n", blkno);
+
+       xh_bh = sb_getblk(inode->i_sb, blkno);
+       if (!xh_bh) {
+               ret = -EIO;
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ocfs2_set_new_buffer_uptodate(inode, xh_bh);
+
+       ret = ocfs2_journal_access(handle, inode, xh_bh,
+                                  OCFS2_JOURNAL_ACCESS_CREATE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       if (bpb > 1) {
+               data_bh = sb_getblk(inode->i_sb, blkno + bpb - 1);
+               if (!data_bh) {
+                       ret = -EIO;
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+
+               ocfs2_set_new_buffer_uptodate(inode, data_bh);
+
+               ret = ocfs2_journal_access(handle, inode, data_bh,
+                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_commit;
+               }
+       }
+
+       ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xh_bh, data_bh);
+
+       ocfs2_journal_dirty(handle, xh_bh);
+       if (data_bh)
+               ocfs2_journal_dirty(handle, data_bh);
+
+       ocfs2_xattr_update_xattr_search(inode, xs, xb_bh, xh_bh);
+
+       /* Change from ocfs2_xattr_header to ocfs2_xattr_tree_root */
+       memset(&xb->xb_attrs, 0, inode->i_sb->s_blocksize -
+              offsetof(struct ocfs2_xattr_block, xb_attrs));
+
+       xr = &xb->xb_attrs.xb_root;
+       xr->xt_clusters = cpu_to_le32(1);
+       xr->xt_last_eb_blk = 0;
+       xr->xt_list.l_tree_depth = 0;
+       xr->xt_list.l_count = cpu_to_le16(ocfs2_xattr_recs_per_xb(inode->i_sb));
+       xr->xt_list.l_next_free_rec = cpu_to_le16(1);
+
+       xr->xt_list.l_recs[0].e_cpos = 0;
+       xr->xt_list.l_recs[0].e_blkno = cpu_to_le64(blkno);
+       xr->xt_list.l_recs[0].e_leaf_clusters = cpu_to_le16(1);
+
+       xb->xb_flags = cpu_to_le16(xb_flags | OCFS2_XATTR_INDEXED);
+
+       ret = ocfs2_journal_dirty(handle, xb_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+
+out_sem:
+       up_write(&oi->ip_alloc_sem);
+
+out:
+       if (data_ac)
+               ocfs2_free_alloc_context(data_ac);
+
+       brelse(xh_bh);
+       brelse(data_bh);
+
+       return ret;
+}
+
+static int cmp_xe_offset(const void *a, const void *b)
+{
+       const struct ocfs2_xattr_entry *l = a, *r = b;
+       u32 l_name_offset = le16_to_cpu(l->xe_name_offset);
+       u32 r_name_offset = le16_to_cpu(r->xe_name_offset);
+
+       if (l_name_offset < r_name_offset)
+               return 1;
+       if (l_name_offset > r_name_offset)
+               return -1;
+       return 0;
+}
+
+/*
+ * defrag a xattr bucket if we find that the bucket has some
+ * holes beteen name/value pairs.
+ * We will move all the name/value pairs to the end of the bucket
+ * so that we can spare some space for insertion.
+ */
+static int ocfs2_defrag_xattr_bucket(struct inode *inode,
+                                    struct ocfs2_xattr_bucket *bucket)
+{
+       int ret, i;
+       size_t end, offset, len, value_len;
+       struct ocfs2_xattr_header *xh;
+       char *entries, *buf, *bucket_buf = NULL;
+       u64 blkno = bucket->bhs[0]->b_blocknr;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       u16 xh_free_start;
+       size_t blocksize = inode->i_sb->s_blocksize;
+       handle_t *handle;
+       struct buffer_head **bhs;
+       struct ocfs2_xattr_entry *xe;
+
+       bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
+                       GFP_NOFS);
+       if (!bhs)
+               return -ENOMEM;
+
+       ret = ocfs2_read_blocks(inode, blkno, blk_per_bucket, bhs, 0);
+       if (ret)
+               goto out;
+
+       /*
+        * In order to make the operation more efficient and generic,
+        * we copy all the blocks into a contiguous memory and do the
+        * defragment there, so if anything is error, we will not touch
+        * the real block.
+        */
+       bucket_buf = kmalloc(OCFS2_XATTR_BUCKET_SIZE, GFP_NOFS);
+       if (!bucket_buf) {
+               ret = -EIO;
+               goto out;
+       }
+
+       buf = bucket_buf;
+       for (i = 0; i < blk_per_bucket; i++, buf += blocksize)
+               memcpy(buf, bhs[i]->b_data, blocksize);
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), blk_per_bucket);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               ret = ocfs2_journal_access(handle, inode, bhs[i],
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto commit;
+               }
+       }
+
+       xh = (struct ocfs2_xattr_header *)bucket_buf;
+       entries = (char *)xh->xh_entries;
+       xh_free_start = le16_to_cpu(xh->xh_free_start);
+
+       mlog(0, "adjust xattr bucket in %llu, count = %u, "
+            "xh_free_start = %u, xh_name_value_len = %u.\n",
+            blkno, le16_to_cpu(xh->xh_count), xh_free_start,
+            le16_to_cpu(xh->xh_name_value_len));
+
+       /*
+        * sort all the entries by their offset.
+        * the largest will be the first, so that we can
+        * move them to the end one by one.
+        */
+       sort(entries, le16_to_cpu(xh->xh_count),
+            sizeof(struct ocfs2_xattr_entry),
+            cmp_xe_offset, swap_xe);
+
+       /* Move all name/values to the end of the bucket. */
+       xe = xh->xh_entries;
+       end = OCFS2_XATTR_BUCKET_SIZE;
+       for (i = 0; i < le16_to_cpu(xh->xh_count); i++, xe++) {
+               offset = le16_to_cpu(xe->xe_name_offset);
+               if (ocfs2_xattr_is_local(xe))
+                       value_len = OCFS2_XATTR_SIZE(
+                                       le64_to_cpu(xe->xe_value_size));
+               else
+                       value_len = OCFS2_XATTR_ROOT_SIZE;
+               len = OCFS2_XATTR_SIZE(xe->xe_name_len) + value_len;
+
+               /*
+                * We must make sure that the name/value pair
+                * exist in the same block. So adjust end to
+                * the previous block end if needed.
+                */
+               if (((end - len) / blocksize !=
+                       (end - 1) / blocksize))
+                       end = end - end % blocksize;
+
+               if (end > offset + len) {
+                       memmove(bucket_buf + end - len,
+                               bucket_buf + offset, len);
+                       xe->xe_name_offset = cpu_to_le16(end - len);
+               }
+
+               mlog_bug_on_msg(end < offset + len, "Defrag check failed for "
+                               "bucket %llu\n", (unsigned long long)blkno);
+
+               end -= len;
+       }
+
+       mlog_bug_on_msg(xh_free_start > end, "Defrag check failed for "
+                       "bucket %llu\n", (unsigned long long)blkno);
+
+       if (xh_free_start == end)
+               goto commit;
+
+       memset(bucket_buf + xh_free_start, 0, end - xh_free_start);
+       xh->xh_free_start = cpu_to_le16(end);
+
+       /* sort the entries by their name_hash. */
+       sort(entries, le16_to_cpu(xh->xh_count),
+            sizeof(struct ocfs2_xattr_entry),
+            cmp_xe, swap_xe);
+
+       buf = bucket_buf;
+       for (i = 0; i < blk_per_bucket; i++, buf += blocksize) {
+               memcpy(bhs[i]->b_data, buf, blocksize);
+               ocfs2_journal_dirty(handle, bhs[i]);
+       }
+
+commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+
+       if (bhs) {
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(bhs[i]);
+       }
+       kfree(bhs);
+
+       kfree(bucket_buf);
+       return ret;
+}
+
+/*
+ * Move half nums of the xattr bucket in the previous cluster to this new
+ * cluster. We only touch the last cluster of the previous extend record.
+ *
+ * first_bh is the first buffer_head of a series of bucket in the same
+ * extent rec and header_bh is the header of one bucket in this cluster.
+ * They will be updated if we move the data header_bh contains to the new
+ * cluster. first_hash will be set as the 1st xe's name_hash of the new cluster.
+ */
+static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode,
+                                              handle_t *handle,
+                                              struct buffer_head **first_bh,
+                                              struct buffer_head **header_bh,
+                                              u64 new_blkno,
+                                              u64 prev_blkno,
+                                              u32 num_clusters,
+                                              u32 *first_hash)
+{
+       int i, ret, credits;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
+       int blocksize = inode->i_sb->s_blocksize;
+       struct buffer_head *old_bh, *new_bh, *prev_bh, *new_first_bh = NULL;
+       struct ocfs2_xattr_header *new_xh;
+       struct ocfs2_xattr_header *xh =
+                       (struct ocfs2_xattr_header *)((*first_bh)->b_data);
+
+       BUG_ON(le16_to_cpu(xh->xh_num_buckets) < num_buckets);
+       BUG_ON(OCFS2_XATTR_BUCKET_SIZE == osb->s_clustersize);
+
+       prev_bh = *first_bh;
+       get_bh(prev_bh);
+       xh = (struct ocfs2_xattr_header *)prev_bh->b_data;
+
+       prev_blkno += (num_clusters - 1) * bpc + bpc / 2;
+
+       mlog(0, "move half of xattrs in cluster %llu to %llu\n",
+            prev_blkno, new_blkno);
+
+       /*
+        * We need to update the 1st half of the new cluster and
+        * 1 more for the update of the 1st bucket of the previous
+        * extent record.
+        */
+       credits = bpc / 2 + 1;
+       ret = ocfs2_extend_trans(handle, credits);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, prev_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       for (i = 0; i < bpc / 2; i++, prev_blkno++, new_blkno++) {
+               old_bh = new_bh = NULL;
+               new_bh = sb_getblk(inode->i_sb, new_blkno);
+               if (!new_bh) {
+                       ret = -EIO;
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               ocfs2_set_new_buffer_uptodate(inode, new_bh);
+
+               ret = ocfs2_journal_access(handle, inode, new_bh,
+                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       brelse(new_bh);
+                       goto out;
+               }
+
+               ret = ocfs2_read_block(inode, prev_blkno, &old_bh);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       brelse(new_bh);
+                       goto out;
+               }
+
+               memcpy(new_bh->b_data, old_bh->b_data, blocksize);
+
+               if (i == 0) {
+                       new_xh = (struct ocfs2_xattr_header *)new_bh->b_data;
+                       new_xh->xh_num_buckets = cpu_to_le16(num_buckets / 2);
+
+                       if (first_hash)
+                               *first_hash = le32_to_cpu(
+                                       new_xh->xh_entries[0].xe_name_hash);
+                       new_first_bh = new_bh;
+                       get_bh(new_first_bh);
+               }
+
+               ocfs2_journal_dirty(handle, new_bh);
+
+               if (*header_bh == old_bh) {
+                       brelse(*header_bh);
+                       *header_bh = new_bh;
+                       get_bh(*header_bh);
+
+                       brelse(*first_bh);
+                       *first_bh = new_first_bh;
+                       get_bh(*first_bh);
+               }
+               brelse(new_bh);
+               brelse(old_bh);
+       }
+
+       le16_add_cpu(&xh->xh_num_buckets, -(num_buckets / 2));
+
+       ocfs2_journal_dirty(handle, prev_bh);
+out:
+       brelse(prev_bh);
+       brelse(new_first_bh);
+       return ret;
+}
+
+static int ocfs2_read_xattr_bucket(struct inode *inode,
+                                  u64 blkno,
+                                  struct buffer_head **bhs,
+                                  int new)
+{
+       int ret = 0;
+       u16 i, blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       if (!new)
+               return ocfs2_read_blocks(inode, blkno,
+                                        blk_per_bucket, bhs, 0);
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               bhs[i] = sb_getblk(inode->i_sb, blkno + i);
+               if (bhs[i] == NULL) {
+                       ret = -EIO;
+                       mlog_errno(ret);
+                       break;
+               }
+               ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
+       }
+
+       return ret;
+}
+
+/*
+ * Move half num of the xattrs in old bucket(blk) to new bucket(new_blk).
+ * first_hash will record the 1st hash of the new bucket.
+ */
+static int ocfs2_half_xattr_bucket(struct inode *inode,
+                                  handle_t *handle,
+                                  u64 blk,
+                                  u64 new_blk,
+                                  u32 *first_hash,
+                                  int new_bucket_head)
+{
+       int ret, i;
+       u16 count, start, len, name_value_len, xe_len, name_offset;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       struct buffer_head **s_bhs, **t_bhs = NULL;
+       struct ocfs2_xattr_header *xh;
+       struct ocfs2_xattr_entry *xe;
+       int blocksize = inode->i_sb->s_blocksize;
+
+       mlog(0, "move half of xattrs from bucket %llu to %llu\n",
+            blk, new_blk);
+
+       s_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
+       if (!s_bhs)
+               return -ENOMEM;
+
+       ret = ocfs2_read_xattr_bucket(inode, blk, s_bhs, 0);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, s_bhs[0],
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       t_bhs = kcalloc(blk_per_bucket, sizeof(struct buffer_head *), GFP_NOFS);
+       if (!t_bhs) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = ocfs2_read_xattr_bucket(inode, new_blk, t_bhs, new_bucket_head);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               ret = ocfs2_journal_access(handle, inode, t_bhs[i],
+                                          OCFS2_JOURNAL_ACCESS_CREATE);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       /* copy the whole bucket to the new first. */
+       for (i = 0; i < blk_per_bucket; i++)
+               memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
+
+       /* update the new bucket. */
+       xh = (struct ocfs2_xattr_header *)t_bhs[0]->b_data;
+       count = le16_to_cpu(xh->xh_count);
+       start = count / 2;
+
+       /*
+        * Calculate the total name/value len and xh_free_start for
+        * the old bucket first.
+        */
+       name_offset = OCFS2_XATTR_BUCKET_SIZE;
+       name_value_len = 0;
+       for (i = 0; i < start; i++) {
+               xe = &xh->xh_entries[i];
+               xe_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
+               if (ocfs2_xattr_is_local(xe))
+                       xe_len +=
+                          OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
+               else
+                       xe_len += OCFS2_XATTR_ROOT_SIZE;
+               name_value_len += xe_len;
+               if (le16_to_cpu(xe->xe_name_offset) < name_offset)
+                       name_offset = le16_to_cpu(xe->xe_name_offset);
+       }
+
+       /*
+        * Now begin the modification to the new bucket.
+        *
+        * In the new bucket, We just move the xattr entry to the beginning
+        * and don't touch the name/value. So there will be some holes in the
+        * bucket, and they will be removed when ocfs2_defrag_xattr_bucket is
+        * called.
+        */
+       xe = &xh->xh_entries[start];
+       len = sizeof(struct ocfs2_xattr_entry) * (count - start);
+       mlog(0, "mv xattr entry len %d from %d to %d\n", len,
+            (int)((char *)xe - (char *)xh),
+            (int)((char *)xh->xh_entries - (char *)xh));
+       memmove((char *)xh->xh_entries, (char *)xe, len);
+       xe = &xh->xh_entries[count - start];
+       len = sizeof(struct ocfs2_xattr_entry) * start;
+       memset((char *)xe, 0, len);
+
+       le16_add_cpu(&xh->xh_count, -start);
+       le16_add_cpu(&xh->xh_name_value_len, -name_value_len);
+
+       /* Calculate xh_free_start for the new bucket. */
+       xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
+       for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
+               xe = &xh->xh_entries[i];
+               xe_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
+               if (ocfs2_xattr_is_local(xe))
+                       xe_len +=
+                          OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
+               else
+                       xe_len += OCFS2_XATTR_ROOT_SIZE;
+               if (le16_to_cpu(xe->xe_name_offset) <
+                   le16_to_cpu(xh->xh_free_start))
+                       xh->xh_free_start = xe->xe_name_offset;
+       }
+
+       /* set xh->xh_num_buckets for the new xh. */
+       if (new_bucket_head)
+               xh->xh_num_buckets = cpu_to_le16(1);
+       else
+               xh->xh_num_buckets = 0;
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               ocfs2_journal_dirty(handle, t_bhs[i]);
+               if (ret)
+                       mlog_errno(ret);
+       }
+
+       /* store the first_hash of the new bucket. */
+       if (first_hash)
+               *first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash);
+
+       /*
+        * Now only update the 1st block of the old bucket.
+        * Please note that the entry has been sorted already above.
+        */
+       xh = (struct ocfs2_xattr_header *)s_bhs[0]->b_data;
+       memset(&xh->xh_entries[start], 0,
+              sizeof(struct ocfs2_xattr_entry) * (count - start));
+       xh->xh_count = cpu_to_le16(start);
+       xh->xh_free_start = cpu_to_le16(name_offset);
+       xh->xh_name_value_len = cpu_to_le16(name_value_len);
+
+       ocfs2_journal_dirty(handle, s_bhs[0]);
+       if (ret)
+               mlog_errno(ret);
+
+out:
+       if (s_bhs) {
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(s_bhs[i]);
+       }
+       kfree(s_bhs);
+
+       if (t_bhs) {
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(t_bhs[i]);
+       }
+       kfree(t_bhs);
+
+       return ret;
+}
+
+/*
+ * Copy xattr from one bucket to another bucket.
+ *
+ * The caller must make sure that the journal transaction
+ * has enough space for journaling.
+ */
+static int ocfs2_cp_xattr_bucket(struct inode *inode,
+                                handle_t *handle,
+                                u64 s_blkno,
+                                u64 t_blkno,
+                                int t_is_new)
+{
+       int ret, i;
+       int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       int blocksize = inode->i_sb->s_blocksize;
+       struct buffer_head **s_bhs, **t_bhs = NULL;
+
+       BUG_ON(s_blkno == t_blkno);
+
+       mlog(0, "cp bucket %llu to %llu, target is %d\n",
+            s_blkno, t_blkno, t_is_new);
+
+       s_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
+                       GFP_NOFS);
+       if (!s_bhs)
+               return -ENOMEM;
+
+       ret = ocfs2_read_xattr_bucket(inode, s_blkno, s_bhs, 0);
+       if (ret)
+               goto out;
+
+       t_bhs = kzalloc(sizeof(struct buffer_head *) * blk_per_bucket,
+                       GFP_NOFS);
+       if (!t_bhs) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = ocfs2_read_xattr_bucket(inode, t_blkno, t_bhs, t_is_new);
+       if (ret)
+               goto out;
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               ret = ocfs2_journal_access(handle, inode, t_bhs[i],
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret)
+                       goto out;
+       }
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               memcpy(t_bhs[i]->b_data, s_bhs[i]->b_data, blocksize);
+               ocfs2_journal_dirty(handle, t_bhs[i]);
+       }
+
+out:
+       if (s_bhs) {
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(s_bhs[i]);
+       }
+       kfree(s_bhs);
+
+       if (t_bhs) {
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(t_bhs[i]);
+       }
+       kfree(t_bhs);
+
+       return ret;
+}
+
+/*
+ * Copy one xattr cluster from src_blk to to_blk.
+ * The to_blk will become the first bucket header of the cluster, so its
+ * xh_num_buckets will be initialized as the bucket num in the cluster.
+ */
+static int ocfs2_cp_xattr_cluster(struct inode *inode,
+                                 handle_t *handle,
+                                 struct buffer_head *first_bh,
+                                 u64 src_blk,
+                                 u64 to_blk,
+                                 u32 *first_hash)
+{
+       int i, ret, credits;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       int num_buckets = ocfs2_xattr_buckets_per_cluster(osb);
+       struct buffer_head *bh = NULL;
+       struct ocfs2_xattr_header *xh;
+       u64 to_blk_start = to_blk;
+
+       mlog(0, "cp xattrs from cluster %llu to %llu\n", src_blk, to_blk);
+
+       /*
+        * We need to update the new cluster and 1 more for the update of
+        * the 1st bucket of the previous extent rec.
+        */
+       credits = bpc + 1;
+       ret = ocfs2_extend_trans(handle, credits);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, first_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       for (i = 0; i < num_buckets; i++) {
+               ret = ocfs2_cp_xattr_bucket(inode, handle,
+                                           src_blk, to_blk, 1);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               src_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+               to_blk += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       }
+
+       /* update the old bucket header. */
+       xh = (struct ocfs2_xattr_header *)first_bh->b_data;
+       le16_add_cpu(&xh->xh_num_buckets, -num_buckets);
+
+       ocfs2_journal_dirty(handle, first_bh);
+
+       /* update the new bucket header. */
+       ret = ocfs2_read_block(inode, to_blk_start, &bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       xh = (struct ocfs2_xattr_header *)bh->b_data;
+       xh->xh_num_buckets = cpu_to_le16(num_buckets);
+
+       ocfs2_journal_dirty(handle, bh);
+
+       if (first_hash)
+               *first_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash);
+out:
+       brelse(bh);
+       return ret;
+}
+
+/*
+ * Move half of the xattrs in this cluster to the new cluster.
+ * This function should only be called when bucket size == cluster size.
+ * Otherwise ocfs2_mv_xattr_bucket_cross_cluster should be used instead.
+ */
+static int ocfs2_half_xattr_cluster(struct inode *inode,
+                                   handle_t *handle,
+                                   u64 prev_blk,
+                                   u64 new_blk,
+                                   u32 *first_hash)
+{
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       int ret, credits = 2 * blk_per_bucket;
+
+       BUG_ON(OCFS2_XATTR_BUCKET_SIZE < OCFS2_SB(inode->i_sb)->s_clustersize);
+
+       ret = ocfs2_extend_trans(handle, credits);
+       if (ret) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       /* Move half of the xattr in start_blk to the next bucket. */
+       return  ocfs2_half_xattr_bucket(inode, handle, prev_blk,
+                                       new_blk, first_hash, 1);
+}
+
+/*
+ * Move some xattrs from the old cluster to the new one since they are not
+ * contiguous in ocfs2 xattr tree.
+ *
+ * new_blk starts a new separate cluster, and we will move some xattrs from
+ * prev_blk to it. v_start will be set as the first name hash value in this
+ * new cluster so that it can be used as e_cpos during tree insertion and
+ * don't collide with our original b-tree operations. first_bh and header_bh
+ * will also be updated since they will be used in ocfs2_extend_xattr_bucket
+ * to extend the insert bucket.
+ *
+ * The problem is how much xattr should we move to the new one and when should
+ * we update first_bh and header_bh?
+ * 1. If cluster size > bucket size, that means the previous cluster has more
+ *    than 1 bucket, so just move half nums of bucket into the new cluster and
+ *    update the first_bh and header_bh if the insert bucket has been moved
+ *    to the new cluster.
+ * 2. If cluster_size == bucket_size:
+ *    a) If the previous extent rec has more than one cluster and the insert
+ *       place isn't in the last cluster, copy the entire last cluster to the
+ *       new one. This time, we don't need to upate the first_bh and header_bh
+ *       since they will not be moved into the new cluster.
+ *    b) Otherwise, move the bottom half of the xattrs in the last cluster into
+ *       the new one. And we set the extend flag to zero if the insert place is
+ *       moved into the new allocated cluster since no extend is needed.
+ */
+static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode,
+                                           handle_t *handle,
+                                           struct buffer_head **first_bh,
+                                           struct buffer_head **header_bh,
+                                           u64 new_blk,
+                                           u64 prev_blk,
+                                           u32 prev_clusters,
+                                           u32 *v_start,
+                                           int *extend)
+{
+       int ret = 0;
+       int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+
+       mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n",
+            prev_blk, prev_clusters, new_blk);
+
+       if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1)
+               ret = ocfs2_mv_xattr_bucket_cross_cluster(inode,
+                                                         handle,
+                                                         first_bh,
+                                                         header_bh,
+                                                         new_blk,
+                                                         prev_blk,
+                                                         prev_clusters,
+                                                         v_start);
+       else {
+               u64 last_blk = prev_blk + bpc * (prev_clusters - 1);
+
+               if (prev_clusters > 1 && (*header_bh)->b_blocknr != last_blk)
+                       ret = ocfs2_cp_xattr_cluster(inode, handle, *first_bh,
+                                                    last_blk, new_blk,
+                                                    v_start);
+               else {
+                       ret = ocfs2_half_xattr_cluster(inode, handle,
+                                                      last_blk, new_blk,
+                                                      v_start);
+
+                       if ((*header_bh)->b_blocknr == last_blk && extend)
+                               *extend = 0;
+               }
+       }
+
+       return ret;
+}
+
+/*
+ * Add a new cluster for xattr storage.
+ *
+ * If the new cluster is contiguous with the previous one, it will be
+ * appended to the same extent record, and num_clusters will be updated.
+ * If not, we will insert a new extent for it and move some xattrs in
+ * the last cluster into the new allocated one.
+ * We also need to limit the maximum size of a btree leaf, otherwise we'll
+ * lose the benefits of hashing because we'll have to search large leaves.
+ * So now the maximum size is OCFS2_MAX_XATTR_TREE_LEAF_SIZE(or clustersize,
+ * if it's bigger).
+ *
+ * first_bh is the first block of the previous extent rec and header_bh
+ * indicates the bucket we will insert the new xattrs. They will be updated
+ * when the header_bh is moved into the new cluster.
+ */
+static int ocfs2_add_new_xattr_cluster(struct inode *inode,
+                                      struct buffer_head *root_bh,
+                                      struct buffer_head **first_bh,
+                                      struct buffer_head **header_bh,
+                                      u32 *num_clusters,
+                                      u32 prev_cpos,
+                                      u64 prev_blkno,
+                                      int *extend)
+{
+       int ret, credits;
+       u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+       u32 prev_clusters = *num_clusters;
+       u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0;
+       u64 block;
+       handle_t *handle = NULL;
+       struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct ocfs2_extent_tree et;
+
+       mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, "
+            "previous xattr blkno = %llu\n",
+            (unsigned long long)OCFS2_I(inode)->ip_blkno,
+            prev_cpos, prev_blkno);
+
+       ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh);
+
+       ret = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0,
+                                   &data_ac, &meta_ac);
+       if (ret) {
+               mlog_errno(ret);
+               goto leave;
+       }
+
+       credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el,
+                                           clusters_to_add);
+       handle = ocfs2_start_trans(osb, credits);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(ret);
+               goto leave;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, root_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto leave;
+       }
+
+       ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+                                    clusters_to_add, &bit_off, &num_bits);
+       if (ret < 0) {
+               if (ret != -ENOSPC)
+                       mlog_errno(ret);
+               goto leave;
+       }
+
+       BUG_ON(num_bits > clusters_to_add);
+
+       block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
+       mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n",
+            num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
+
+       if (prev_blkno + prev_clusters * bpc == block &&
+           (prev_clusters + num_bits) << osb->s_clustersize_bits <=
+            OCFS2_MAX_XATTR_TREE_LEAF_SIZE) {
+               /*
+                * If this cluster is contiguous with the old one and
+                * adding this new cluster, we don't surpass the limit of
+                * OCFS2_MAX_XATTR_TREE_LEAF_SIZE, cool. We will let it be
+                * initialized and used like other buckets in the previous
+                * cluster.
+                * So add it as a contiguous one. The caller will handle
+                * its init process.
+                */
+               v_start = prev_cpos + prev_clusters;
+               *num_clusters = prev_clusters + num_bits;
+               mlog(0, "Add contiguous %u clusters to previous extent rec.\n",
+                    num_bits);
+       } else {
+               ret = ocfs2_adjust_xattr_cross_cluster(inode,
+                                                      handle,
+                                                      first_bh,
+                                                      header_bh,
+                                                      block,
+                                                      prev_blkno,
+                                                      prev_clusters,
+                                                      &v_start,
+                                                      extend);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto leave;
+               }
+       }
+
+       if (handle->h_buffer_credits < credits) {
+               /*
+                * The journal has been restarted before, and don't
+                * have enough space for the insertion, so extend it
+                * here.
+                */
+               ret = ocfs2_extend_trans(handle, credits);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto leave;
+               }
+       }
+       mlog(0, "Insert %u clusters at block %llu for xattr at %u\n",
+            num_bits, block, v_start);
+       ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block,
+                                 num_bits, 0, meta_ac);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto leave;
+       }
+
+       ret = ocfs2_journal_dirty(handle, root_bh);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto leave;
+       }
+
+leave:
+       if (handle)
+               ocfs2_commit_trans(osb, handle);
+       if (data_ac)
+               ocfs2_free_alloc_context(data_ac);
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
+       return ret;
+}
+
+/*
+ * Extend a new xattr bucket and move xattrs to the end one by one until
+ * We meet with start_bh. Only move half of the xattrs to the bucket after it.
+ */
+static int ocfs2_extend_xattr_bucket(struct inode *inode,
+                                    struct buffer_head *first_bh,
+                                    struct buffer_head *start_bh,
+                                    u32 num_clusters)
+{
+       int ret, credits;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       u64 start_blk = start_bh->b_blocknr, end_blk;
+       u32 num_buckets = num_clusters * ocfs2_xattr_buckets_per_cluster(osb);
+       handle_t *handle;
+       struct ocfs2_xattr_header *first_xh =
+                               (struct ocfs2_xattr_header *)first_bh->b_data;
+       u16 bucket = le16_to_cpu(first_xh->xh_num_buckets);
+
+       mlog(0, "extend xattr bucket in %llu, xattr extend rec starting "
+            "from %llu, len = %u\n", start_blk,
+            (unsigned long long)first_bh->b_blocknr, num_clusters);
+
+       BUG_ON(bucket >= num_buckets);
+
+       end_blk = first_bh->b_blocknr + (bucket - 1) * blk_per_bucket;
+
+       /*
+        * We will touch all the buckets after the start_bh(include it).
+        * Add one more bucket and modify the first_bh.
+        */
+       credits = end_blk - start_blk + 2 * blk_per_bucket + 1;
+       handle = ocfs2_start_trans(osb, credits);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, first_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto commit;
+       }
+
+       while (end_blk != start_blk) {
+               ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk,
+                                           end_blk + blk_per_bucket, 0);
+               if (ret)
+                       goto commit;
+               end_blk -= blk_per_bucket;
+       }
+
+       /* Move half of the xattr in start_blk to the next bucket. */
+       ret = ocfs2_half_xattr_bucket(inode, handle, start_blk,
+                                     start_blk + blk_per_bucket, NULL, 0);
+
+       le16_add_cpu(&first_xh->xh_num_buckets, 1);
+       ocfs2_journal_dirty(handle, first_bh);
+
+commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       return ret;
+}
+
+/*
+ * Add new xattr bucket in an extent record and adjust the buckets accordingly.
+ * xb_bh is the ocfs2_xattr_block.
+ * We will move all the buckets starting from header_bh to the next place. As
+ * for this one, half num of its xattrs will be moved to the next one.
+ *
+ * We will allocate a new cluster if current cluster is full and adjust
+ * header_bh and first_bh if the insert place is moved to the new cluster.
+ */
+static int ocfs2_add_new_xattr_bucket(struct inode *inode,
+                                     struct buffer_head *xb_bh,
+                                     struct buffer_head *header_bh)
+{
+       struct ocfs2_xattr_header *first_xh = NULL;
+       struct buffer_head *first_bh = NULL;
+       struct ocfs2_xattr_block *xb =
+                       (struct ocfs2_xattr_block *)xb_bh->b_data;
+       struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root;
+       struct ocfs2_extent_list *el = &xb_root->xt_list;
+       struct ocfs2_xattr_header *xh =
+                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       u32 name_hash = le32_to_cpu(xh->xh_entries[0].xe_name_hash);
+       struct super_block *sb = inode->i_sb;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
+       int ret, num_buckets, extend = 1;
+       u64 p_blkno;
+       u32 e_cpos, num_clusters;
+
+       mlog(0, "Add new xattr bucket starting form %llu\n",
+            (unsigned long long)header_bh->b_blocknr);
+
+       /*
+        * Add refrence for header_bh here because it may be
+        * changed in ocfs2_add_new_xattr_cluster and we need
+        * to free it in the end.
+        */
+       get_bh(header_bh);
+
+       ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &e_cpos,
+                                 &num_clusters, el);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_read_block(inode, p_blkno, &first_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       num_buckets = ocfs2_xattr_buckets_per_cluster(osb) * num_clusters;
+       first_xh = (struct ocfs2_xattr_header *)first_bh->b_data;
+
+       if (num_buckets == le16_to_cpu(first_xh->xh_num_buckets)) {
+               ret = ocfs2_add_new_xattr_cluster(inode,
+                                                 xb_bh,
+                                                 &first_bh,
+                                                 &header_bh,
+                                                 &num_clusters,
+                                                 e_cpos,
+                                                 p_blkno,
+                                                 &extend);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       if (extend)
+               ret = ocfs2_extend_xattr_bucket(inode,
+                                               first_bh,
+                                               header_bh,
+                                               num_clusters);
+       if (ret)
+               mlog_errno(ret);
+out:
+       brelse(first_bh);
+       brelse(header_bh);
+       return ret;
+}
+
+static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode,
+                                       struct ocfs2_xattr_bucket *bucket,
+                                       int offs)
+{
+       int block_off = offs >> inode->i_sb->s_blocksize_bits;
+
+       offs = offs % inode->i_sb->s_blocksize;
+       return bucket->bhs[block_off]->b_data + offs;
+}
+
+/*
+ * Handle the normal xattr set, including replace, delete and new.
+ *
+ * Note: "local" indicates the real data's locality. So we can't
+ * just its bucket locality by its length.
+ */
+static void ocfs2_xattr_set_entry_normal(struct inode *inode,
+                                        struct ocfs2_xattr_info *xi,
+                                        struct ocfs2_xattr_search *xs,
+                                        u32 name_hash,
+                                        int local)
+{
+       struct ocfs2_xattr_entry *last, *xe;
+       int name_len = strlen(xi->name);
+       struct ocfs2_xattr_header *xh = xs->header;
+       u16 count = le16_to_cpu(xh->xh_count), start;
+       size_t blocksize = inode->i_sb->s_blocksize;
+       char *val;
+       size_t offs, size, new_size;
+
+       last = &xh->xh_entries[count];
+       if (!xs->not_found) {
+               xe = xs->here;
+               offs = le16_to_cpu(xe->xe_name_offset);
+               if (ocfs2_xattr_is_local(xe))
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                       OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
+               else
+                       size = OCFS2_XATTR_SIZE(name_len) +
+                       OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
+
+               /*
+                * If the new value will be stored outside, xi->value has been
+                * initalized as an empty ocfs2_xattr_value_root, and the same
+                * goes with xi->value_len, so we can set new_size safely here.
+                * See ocfs2_xattr_set_in_bucket.
+                */
+               new_size = OCFS2_XATTR_SIZE(name_len) +
+                          OCFS2_XATTR_SIZE(xi->value_len);
+
+               le16_add_cpu(&xh->xh_name_value_len, -size);
+               if (xi->value) {
+                       if (new_size > size)
+                               goto set_new_name_value;
+
+                       /* Now replace the old value with new one. */
+                       if (local)
+                               xe->xe_value_size = cpu_to_le64(xi->value_len);
+                       else
+                               xe->xe_value_size = 0;
+
+                       val = ocfs2_xattr_bucket_get_val(inode,
+                                                        &xs->bucket, offs);
+                       memset(val + OCFS2_XATTR_SIZE(name_len), 0,
+                              size - OCFS2_XATTR_SIZE(name_len));
+                       if (OCFS2_XATTR_SIZE(xi->value_len) > 0)
+                               memcpy(val + OCFS2_XATTR_SIZE(name_len),
+                                      xi->value, xi->value_len);
+
+                       le16_add_cpu(&xh->xh_name_value_len, new_size);
+                       ocfs2_xattr_set_local(xe, local);
+                       return;
+               } else {
+                       /*
+                        * Remove the old entry if there is more than one.
+                        * We don't remove the last entry so that we can
+                        * use it to indicate the hash value of the empty
+                        * bucket.
+                        */
+                       last -= 1;
+                       le16_add_cpu(&xh->xh_count, -1);
+                       if (xh->xh_count) {
+                               memmove(xe, xe + 1,
+                                       (void *)last - (void *)xe);
+                               memset(last, 0,
+                                      sizeof(struct ocfs2_xattr_entry));
+                       } else
+                               xh->xh_free_start =
+                                       cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
+
+                       return;
+               }
+       } else {
+               /* find a new entry for insert. */
+               int low = 0, high = count - 1, tmp;
+               struct ocfs2_xattr_entry *tmp_xe;
+
+               while (low <= high && count) {
+                       tmp = (low + high) / 2;
+                       tmp_xe = &xh->xh_entries[tmp];
+
+                       if (name_hash > le32_to_cpu(tmp_xe->xe_name_hash))
+                               low = tmp + 1;
+                       else if (name_hash <
+                                le32_to_cpu(tmp_xe->xe_name_hash))
+                               high = tmp - 1;
+                       else {
+                               low = tmp;
+                               break;
+                       }
+               }
+
+               xe = &xh->xh_entries[low];
+               if (low != count)
+                       memmove(xe + 1, xe, (void *)last - (void *)xe);
+
+               le16_add_cpu(&xh->xh_count, 1);
+               memset(xe, 0, sizeof(struct ocfs2_xattr_entry));
+               xe->xe_name_hash = cpu_to_le32(name_hash);
+               xe->xe_name_len = name_len;
+               ocfs2_xattr_set_type(xe, xi->name_index);
+       }
+
+set_new_name_value:
+       /* Insert the new name+value. */
+       size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(xi->value_len);
+
+       /*
+        * We must make sure that the name/value pair
+        * exists in the same block.
+        */
+       offs = le16_to_cpu(xh->xh_free_start);
+       start = offs - size;
+
+       if (start >> inode->i_sb->s_blocksize_bits !=
+           (offs - 1) >> inode->i_sb->s_blocksize_bits) {
+               offs = offs - offs % blocksize;
+               xh->xh_free_start = cpu_to_le16(offs);
+       }
+
+       val = ocfs2_xattr_bucket_get_val(inode,
+                                        &xs->bucket, offs - size);
+       xe->xe_name_offset = cpu_to_le16(offs - size);
+
+       memset(val, 0, size);
+       memcpy(val, xi->name, name_len);
+       memcpy(val + OCFS2_XATTR_SIZE(name_len), xi->value, xi->value_len);
+
+       xe->xe_value_size = cpu_to_le64(xi->value_len);
+       ocfs2_xattr_set_local(xe, local);
+       xs->here = xe;
+       le16_add_cpu(&xh->xh_free_start, -size);
+       le16_add_cpu(&xh->xh_name_value_len, size);
+
+       return;
+}
+
+static int ocfs2_xattr_bucket_handle_journal(struct inode *inode,
+                                            handle_t *handle,
+                                            struct ocfs2_xattr_search *xs,
+                                            struct buffer_head **bhs,
+                                            u16 bh_num)
+{
+       int ret = 0, off, block_off;
+       struct ocfs2_xattr_entry *xe = xs->here;
+
+       /*
+        * First calculate all the blocks we should journal_access
+        * and journal_dirty. The first block should always be touched.
+        */
+       ret = ocfs2_journal_dirty(handle, bhs[0]);
+       if (ret)
+               mlog_errno(ret);
+
+       /* calc the data. */
+       off = le16_to_cpu(xe->xe_name_offset);
+       block_off = off >> inode->i_sb->s_blocksize_bits;
+       ret = ocfs2_journal_dirty(handle, bhs[block_off]);
+       if (ret)
+               mlog_errno(ret);
+
+       return ret;
+}
+
+/*
+ * Set the xattr entry in the specified bucket.
+ * The bucket is indicated by xs->bucket and it should have the enough
+ * space for the xattr insertion.
+ */
+static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
+                                          struct ocfs2_xattr_info *xi,
+                                          struct ocfs2_xattr_search *xs,
+                                          u32 name_hash,
+                                          int local)
+{
+       int i, ret;
+       handle_t *handle = NULL;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n",
+            (unsigned long)xi->value_len, xi->name_index,
+            (unsigned long long)xs->bucket.bhs[0]->b_blocknr);
+
+       if (!xs->bucket.bhs[1]) {
+               ret = ocfs2_read_blocks(inode,
+                                       xs->bucket.bhs[0]->b_blocknr + 1,
+                                       blk_per_bucket - 1, &xs->bucket.bhs[1],
+                                       0);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       handle = ocfs2_start_trans(osb, blk_per_bucket);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               handle = NULL;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       for (i = 0; i < blk_per_bucket; i++) {
+               ret = ocfs2_journal_access(handle, inode, xs->bucket.bhs[i],
+                                          OCFS2_JOURNAL_ACCESS_WRITE);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, local);
+
+       /*Only dirty the blocks we have touched in set xattr. */
+       ret = ocfs2_xattr_bucket_handle_journal(inode, handle, xs,
+                                               xs->bucket.bhs, blk_per_bucket);
+       if (ret)
+               mlog_errno(ret);
+out:
+       ocfs2_commit_trans(osb, handle);
+
+       return ret;
+}
+
+static int ocfs2_xattr_value_update_size(struct inode *inode,
+                                        struct buffer_head *xe_bh,
+                                        struct ocfs2_xattr_entry *xe,
+                                        u64 new_size)
+{
+       int ret;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       handle_t *handle = NULL;
+
+       handle = ocfs2_start_trans(osb, 1);
+       if (handle == NULL) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, xe_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret < 0) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       xe->xe_value_size = cpu_to_le64(new_size);
+
+       ret = ocfs2_journal_dirty(handle, xe_bh);
+       if (ret < 0)
+               mlog_errno(ret);
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       return ret;
+}
+
+/*
+ * Truncate the specified xe_off entry in xattr bucket.
+ * bucket is indicated by header_bh and len is the new length.
+ * Both the ocfs2_xattr_value_root and the entry will be updated here.
+ *
+ * Copy the new updated xe and xe_value_root to new_xe and new_xv if needed.
+ */
+static int ocfs2_xattr_bucket_value_truncate(struct inode *inode,
+                                            struct buffer_head *header_bh,
+                                            int xe_off,
+                                            int len)
+{
+       int ret, offset;
+       u64 value_blk;
+       struct buffer_head *value_bh = NULL;
+       struct ocfs2_xattr_value_root *xv;
+       struct ocfs2_xattr_entry *xe;
+       struct ocfs2_xattr_header *xh =
+                       (struct ocfs2_xattr_header *)header_bh->b_data;
+       size_t blocksize = inode->i_sb->s_blocksize;
+
+       xe = &xh->xh_entries[xe_off];
+
+       BUG_ON(!xe || ocfs2_xattr_is_local(xe));
+
+       offset = le16_to_cpu(xe->xe_name_offset) +
+                OCFS2_XATTR_SIZE(xe->xe_name_len);
+
+       value_blk = offset / blocksize;
+
+       /* We don't allow ocfs2_xattr_value to be stored in different block. */
+       BUG_ON(value_blk != (offset + OCFS2_XATTR_ROOT_SIZE - 1) / blocksize);
+       value_blk += header_bh->b_blocknr;
+
+       ret = ocfs2_read_block(inode, value_blk, &value_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       xv = (struct ocfs2_xattr_value_root *)
+               (value_bh->b_data + offset % blocksize);
+
+       mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n",
+            xe_off, (unsigned long long)header_bh->b_blocknr, len);
+       ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_xattr_value_update_size(inode, header_bh, xe, len);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+out:
+       brelse(value_bh);
+       return ret;
+}
+
+static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
+                                               struct ocfs2_xattr_search *xs,
+                                               int len)
+{
+       int ret, offset;
+       struct ocfs2_xattr_entry *xe = xs->here;
+       struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)xs->base;
+
+       BUG_ON(!xs->bucket.bhs[0] || !xe || ocfs2_xattr_is_local(xe));
+
+       offset = xe - xh->xh_entries;
+       ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket.bhs[0],
+                                               offset, len);
+       if (ret)
+               mlog_errno(ret);
+
+       return ret;
+}
+
+static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode,
+                                               struct ocfs2_xattr_search *xs,
+                                               char *val,
+                                               int value_len)
+{
+       int offset;
+       struct ocfs2_xattr_value_root *xv;
+       struct ocfs2_xattr_entry *xe = xs->here;
+
+       BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe));
+
+       offset = le16_to_cpu(xe->xe_name_offset) +
+                OCFS2_XATTR_SIZE(xe->xe_name_len);
+
+       xv = (struct ocfs2_xattr_value_root *)(xs->base + offset);
+
+       return __ocfs2_xattr_set_value_outside(inode, xv, val, value_len);
+}
+
+static int ocfs2_rm_xattr_cluster(struct inode *inode,
+                                 struct buffer_head *root_bh,
+                                 u64 blkno,
+                                 u32 cpos,
+                                 u32 len)
+{
+       int ret;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       struct inode *tl_inode = osb->osb_tl_inode;
+       handle_t *handle;
+       struct ocfs2_xattr_block *xb =
+                       (struct ocfs2_xattr_block *)root_bh->b_data;
+       struct ocfs2_alloc_context *meta_ac = NULL;
+       struct ocfs2_cached_dealloc_ctxt dealloc;
+       struct ocfs2_extent_tree et;
+
+       ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh);
+
+       ocfs2_init_dealloc_ctxt(&dealloc);
+
+       mlog(0, "rm xattr extent rec at %u len = %u, start from %llu\n",
+            cpos, len, (unsigned long long)blkno);
+
+       ocfs2_remove_xattr_clusters_from_cache(inode, blkno, len);
+
+       ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac);
+       if (ret) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       mutex_lock(&tl_inode->i_mutex);
+
+       if (ocfs2_truncate_log_needs_flush(osb)) {
+               ret = __ocfs2_flush_truncate_log(osb);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
+       if (handle == NULL) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, root_bh,
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac,
+                                 &dealloc);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       le32_add_cpu(&xb->xb_attrs.xb_root.xt_clusters, -len);
+
+       ret = ocfs2_journal_dirty(handle, root_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = ocfs2_truncate_log_append(osb, handle, blkno, len);
+       if (ret)
+               mlog_errno(ret);
+
+out_commit:
+       ocfs2_commit_trans(osb, handle);
+out:
+       ocfs2_schedule_truncate_log_flush(osb, 1);
+
+       mutex_unlock(&tl_inode->i_mutex);
+
+       if (meta_ac)
+               ocfs2_free_alloc_context(meta_ac);
+
+       ocfs2_run_deallocs(osb, &dealloc);
+
+       return ret;
+}
+
+static void ocfs2_xattr_bucket_remove_xs(struct inode *inode,
+                                        struct ocfs2_xattr_search *xs)
+{
+       handle_t *handle = NULL;
+       struct ocfs2_xattr_header *xh = xs->bucket.xh;
+       struct ocfs2_xattr_entry *last = &xh->xh_entries[
+                                               le16_to_cpu(xh->xh_count) - 1];
+       int ret = 0;
+
+       handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), 1);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               return;
+       }
+
+       ret = ocfs2_journal_access(handle, inode, xs->bucket.bhs[0],
+                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       /* Remove the old entry. */
+       memmove(xs->here, xs->here + 1,
+               (void *)last - (void *)xs->here);
+       memset(last, 0, sizeof(struct ocfs2_xattr_entry));
+       le16_add_cpu(&xh->xh_count, -1);
+
+       ret = ocfs2_journal_dirty(handle, xs->bucket.bhs[0]);
+       if (ret < 0)
+               mlog_errno(ret);
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+}
+
+/*
+ * Set the xattr name/value in the bucket specified in xs.
+ *
+ * As the new value in xi may be stored in the bucket or in an outside cluster,
+ * we divide the whole process into 3 steps:
+ * 1. insert name/value in the bucket(ocfs2_xattr_set_entry_in_bucket)
+ * 2. truncate of the outside cluster(ocfs2_xattr_bucket_value_truncate_xs)
+ * 3. Set the value to the outside cluster(ocfs2_xattr_bucket_set_value_outside)
+ * 4. If the clusters for the new outside value can't be allocated, we need
+ *    to free the xattr we allocated in set.
+ */
+static int ocfs2_xattr_set_in_bucket(struct inode *inode,
+                                    struct ocfs2_xattr_info *xi,
+                                    struct ocfs2_xattr_search *xs)
+{
+       int ret, local = 1;
+       size_t value_len;
+       char *val = (char *)xi->value;
+       struct ocfs2_xattr_entry *xe = xs->here;
+       u32 name_hash = ocfs2_xattr_name_hash(inode, xi->name,
+                                             strlen(xi->name));
+
+       if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
+               /*
+                * We need to truncate the xattr storage first.
+                *
+                * If both the old and new value are stored to
+                * outside block, we only need to truncate
+                * the storage and then set the value outside.
+                *
+                * If the new value should be stored within block,
+                * we should free all the outside block first and
+                * the modification to the xattr block will be done
+                * by following steps.
+                */
+               if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+                       value_len = xi->value_len;
+               else
+                       value_len = 0;
+
+               ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
+                                                          value_len);
+               if (ret)
+                       goto out;
+
+               if (value_len)
+                       goto set_value_outside;
+       }
+
+       value_len = xi->value_len;
+       /* So we have to handle the inside block change now. */
+       if (value_len > OCFS2_XATTR_INLINE_SIZE) {
+               /*
+                * If the new value will be stored outside of block,
+                * initalize a new empty value root and insert it first.
+                */
+               local = 0;
+               xi->value = &def_xv;
+               xi->value_len = OCFS2_XATTR_ROOT_SIZE;
+       }
+
+       ret = ocfs2_xattr_set_entry_in_bucket(inode, xi, xs, name_hash, local);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       if (value_len <= OCFS2_XATTR_INLINE_SIZE)
+               goto out;
+
+       /* allocate the space now for the outside block storage. */
+       ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
+                                                  value_len);
+       if (ret) {
+               mlog_errno(ret);
+
+               if (xs->not_found) {
+                       /*
+                        * We can't allocate enough clusters for outside
+                        * storage and we have allocated xattr already,
+                        * so need to remove it.
+                        */
+                       ocfs2_xattr_bucket_remove_xs(inode, xs);
+               }
+               goto out;
+       }
+
+set_value_outside:
+       ret = ocfs2_xattr_bucket_set_value_outside(inode, xs, val, value_len);
+out:
+       return ret;
+}
+
+/* check whether the xattr bucket is filled up with the same hash value. */
+static int ocfs2_check_xattr_bucket_collision(struct inode *inode,
+                                             struct ocfs2_xattr_bucket *bucket)
+{
+       struct ocfs2_xattr_header *xh = bucket->xh;
+
+       if (xh->xh_entries[le16_to_cpu(xh->xh_count) - 1].xe_name_hash ==
+           xh->xh_entries[0].xe_name_hash) {
+               mlog(ML_ERROR, "Too much hash collision in xattr bucket %llu, "
+                    "hash = %u\n",
+                    (unsigned long long)bucket->bhs[0]->b_blocknr,
+                    le32_to_cpu(xh->xh_entries[0].xe_name_hash));
+               return -ENOSPC;
+       }
+
+       return 0;
+}
+
+static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
+                                            struct ocfs2_xattr_info *xi,
+                                            struct ocfs2_xattr_search *xs)
+{
+       struct ocfs2_xattr_header *xh;
+       struct ocfs2_xattr_entry *xe;
+       u16 count, header_size, xh_free_start;
+       int i, free, max_free, need, old;
+       size_t value_size = 0, name_len = strlen(xi->name);
+       size_t blocksize = inode->i_sb->s_blocksize;
+       int ret, allocation = 0;
+       u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+
+       mlog_entry("Set xattr %s in xattr index block\n", xi->name);
+
+try_again:
+       xh = xs->header;
+       count = le16_to_cpu(xh->xh_count);
+       xh_free_start = le16_to_cpu(xh->xh_free_start);
+       header_size = sizeof(struct ocfs2_xattr_header) +
+                       count * sizeof(struct ocfs2_xattr_entry);
+       max_free = OCFS2_XATTR_BUCKET_SIZE -
+               le16_to_cpu(xh->xh_name_value_len) - header_size;
+
+       mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
+                       "of %u which exceed block size\n",
+                       (unsigned long long)xs->bucket.bhs[0]->b_blocknr,
+                       header_size);
+
+       if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+               value_size = OCFS2_XATTR_ROOT_SIZE;
+       else if (xi->value)
+               value_size = OCFS2_XATTR_SIZE(xi->value_len);
+
+       if (xs->not_found)
+               need = sizeof(struct ocfs2_xattr_entry) +
+                       OCFS2_XATTR_SIZE(name_len) + value_size;
+       else {
+               need = value_size + OCFS2_XATTR_SIZE(name_len);
+
+               /*
+                * We only replace the old value if the new length is smaller
+                * than the old one. Otherwise we will allocate new space in the
+                * bucket to store it.
+                */
+               xe = xs->here;
+               if (ocfs2_xattr_is_local(xe))
+                       old = OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
+               else
+                       old = OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
+
+               if (old >= value_size)
+                       need = 0;
+       }
+
+       free = xh_free_start - header_size;
+       /*
+        * We need to make sure the new name/value pair
+        * can exist in the same block.
+        */
+       if (xh_free_start % blocksize < need)
+               free -= xh_free_start % blocksize;
+
+       mlog(0, "xs->not_found = %d, in xattr bucket %llu: free = %d, "
+            "need = %d, max_free = %d, xh_free_start = %u, xh_name_value_len ="
+            " %u\n", xs->not_found,
+            (unsigned long long)xs->bucket.bhs[0]->b_blocknr,
+            free, need, max_free, le16_to_cpu(xh->xh_free_start),
+            le16_to_cpu(xh->xh_name_value_len));
+
+       if (free < need || count == ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
+               if (need <= max_free &&
+                   count < ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
+                       /*
+                        * We can create the space by defragment. Since only the
+                        * name/value will be moved, the xe shouldn't be changed
+                        * in xs.
+                        */
+                       ret = ocfs2_defrag_xattr_bucket(inode, &xs->bucket);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out;
+                       }
+
+                       xh_free_start = le16_to_cpu(xh->xh_free_start);
+                       free = xh_free_start - header_size;
+                       if (xh_free_start % blocksize < need)
+                               free -= xh_free_start % blocksize;
+
+                       if (free >= need)
+                               goto xattr_set;
+
+                       mlog(0, "Can't get enough space for xattr insert by "
+                            "defragment. Need %u bytes, but we have %d, so "
+                            "allocate new bucket for it.\n", need, free);
+               }
+
+               /*
+                * We have to add new buckets or clusters and one
+                * allocation should leave us enough space for insert.
+                */
+               BUG_ON(allocation);
+
+               /*
+                * We do not allow for overlapping ranges between buckets. And
+                * the maximum number of collisions we will allow for then is
+                * one bucket's worth, so check it here whether we need to
+                * add a new bucket for the insert.
+                */
+               ret = ocfs2_check_xattr_bucket_collision(inode, &xs->bucket);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               ret = ocfs2_add_new_xattr_bucket(inode,
+                                                xs->xattr_bh,
+                                                xs->bucket.bhs[0]);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               for (i = 0; i < blk_per_bucket; i++)
+                       brelse(xs->bucket.bhs[i]);
+
+               memset(&xs->bucket, 0, sizeof(xs->bucket));
+
+               ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
+                                                  xi->name_index,
+                                                  xi->name, xs);
+               if (ret && ret != -ENODATA)
+                       goto out;
+               xs->not_found = ret;
+               allocation = 1;
+               goto try_again;
+       }
+
+xattr_set:
+       ret = ocfs2_xattr_set_in_bucket(inode, xi, xs);
+out:
+       mlog_exit(ret);
+       return ret;
+}
+
+static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
+                                       struct ocfs2_xattr_bucket *bucket,
+                                       void *para)
+{
+       int ret = 0;
+       struct ocfs2_xattr_header *xh = bucket->xh;
+       u16 i;
+       struct ocfs2_xattr_entry *xe;
+
+       for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
+               xe = &xh->xh_entries[i];
+               if (ocfs2_xattr_is_local(xe))
+                       continue;
+
+               ret = ocfs2_xattr_bucket_value_truncate(inode,
+                                                       bucket->bhs[0],
+                                                       i, 0);
+               if (ret) {
+                       mlog_errno(ret);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int ocfs2_delete_xattr_index_block(struct inode *inode,
+                                         struct buffer_head *xb_bh)
+{
+       struct ocfs2_xattr_block *xb =
+                       (struct ocfs2_xattr_block *)xb_bh->b_data;
+       struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
+       int ret = 0;
+       u32 name_hash = UINT_MAX, e_cpos, num_clusters;
+       u64 p_blkno;
+
+       if (le16_to_cpu(el->l_next_free_rec) == 0)
+               return 0;
+
+       while (name_hash > 0) {
+               ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno,
+                                         &e_cpos, &num_clusters, el);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               ret = ocfs2_iterate_xattr_buckets(inode, p_blkno, num_clusters,
+                                                 ocfs2_delete_xattr_in_bucket,
+                                                 NULL);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               ret = ocfs2_rm_xattr_cluster(inode, xb_bh,
+                                            p_blkno, e_cpos, num_clusters);
+               if (ret) {
+                       mlog_errno(ret);
+                       break;
+               }
+
+               if (e_cpos == 0)
+                       break;
+
+               name_hash = e_cpos - 1;
+       }
+
+out:
+       return ret;
+}
+
+/*
+ * 'trusted' attributes support
+ */
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
+                                      size_t list_size, const char *name,
+                                      size_t name_len)
+{
+       const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX) - 1;
+       const size_t total_len = prefix_len + name_len + 1;
+
+       if (list && total_len <= list_size) {
+               memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+               memcpy(list + prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return total_len;
+}
+
+static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
+                                  void *buffer, size_t size)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED, name,
+                              buffer, size);
+}
+
+static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
+                                  const void *value, size_t size, int flags)
+{
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED, name, value,
+                              size, flags);
+}
+
+struct xattr_handler ocfs2_xattr_trusted_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .list   = ocfs2_xattr_trusted_list,
+       .get    = ocfs2_xattr_trusted_get,
+       .set    = ocfs2_xattr_trusted_set,
+};
+
+
+/*
+ * 'user' attributes support
+ */
+
+#define XATTR_USER_PREFIX "user."
+
+static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
+                                   size_t list_size, const char *name,
+                                   size_t name_len)
+{
+       const size_t prefix_len = sizeof(XATTR_USER_PREFIX) - 1;
+       const size_t total_len = prefix_len + name_len + 1;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
+               return 0;
+
+       if (list && total_len <= list_size) {
+               memcpy(list, XATTR_USER_PREFIX, prefix_len);
+               memcpy(list + prefix_len, name, name_len);
+               list[prefix_len + name_len] = '\0';
+       }
+       return total_len;
+}
+
+static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
+                               void *buffer, size_t size)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
+               return -EOPNOTSUPP;
+       return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
+                              buffer, size);
+}
+
+static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
+                               const void *value, size_t size, int flags)
+{
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
+               return -EOPNOTSUPP;
+
+       return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER, name, value,
+                              size, flags);
+}
+
+struct xattr_handler ocfs2_xattr_user_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .list   = ocfs2_xattr_user_list,
+       .get    = ocfs2_xattr_user_get,
+       .set    = ocfs2_xattr_user_set,
+};
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
new file mode 100644 (file)
index 0000000..c25c7c6
--- /dev/null
@@ -0,0 +1,68 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * xattr.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2008 Oracle.  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.  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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_XATTR_H
+#define OCFS2_XATTR_H
+
+#include <linux/init.h>
+#include <linux/xattr.h>
+
+enum ocfs2_xattr_type {
+       OCFS2_XATTR_INDEX_USER = 1,
+       OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS,
+       OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT,
+       OCFS2_XATTR_INDEX_TRUSTED,
+       OCFS2_XATTR_INDEX_SECURITY,
+       OCFS2_XATTR_MAX
+};
+
+extern struct xattr_handler ocfs2_xattr_user_handler;
+extern struct xattr_handler ocfs2_xattr_trusted_handler;
+
+extern ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
+extern int ocfs2_xattr_get(struct inode *, int, const char *, void *, size_t);
+extern int ocfs2_xattr_set(struct inode *, int, const char *, const void *,
+                          size_t, int);
+extern int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh);
+extern struct xattr_handler *ocfs2_xattr_handlers[];
+
+static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
+{
+       return (1 << osb->s_clustersize_bits) / OCFS2_XATTR_BUCKET_SIZE;
+}
+
+static inline u16 ocfs2_blocks_per_xattr_bucket(struct super_block *sb)
+{
+       return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits);
+}
+
+static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb)
+{
+       u16 len = sb->s_blocksize -
+                offsetof(struct ocfs2_xattr_header, xh_entries);
+
+       return len / sizeof(struct ocfs2_xattr_entry);
+}
+#endif /* OCFS2_XATTR_H */
index d29047b1b9b065a68c6ee7792d8007821736b852..cbf047a847c5e3d6c3558d16cce217b475e9163c 100644 (file)
@@ -346,7 +346,7 @@ enum {
        Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
        {Opt_umask, "umask=%o"},
index 07da9359481c720c045e2a25e154df02ba02e9ff..5596049863bf742eadb115bafe0deef35b209421 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1141,8 +1141,7 @@ EXPORT_SYMBOL(sys_close);
 asmlinkage long sys_vhangup(void)
 {
        if (capable(CAP_SYS_TTY_CONFIG)) {
-               /* XXX: this needs locking */
-               tty_vhangup(current->signal->tty);
+               tty_vhangup_self();
                return 0;
        }
        return -EPERM;
index 3d3e16631472212bca09147967724161e2f4022d..a97b477ac0fc38b4e691f6c980b06cc6d921e05a 100644 (file)
@@ -275,16 +275,6 @@ adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
        id = data[0x1fc] & 15;
        put_dev_sector(sect);
 
-#ifdef CONFIG_BLK_DEV_MFM
-       if (MAJOR(bdev->bd_dev) == MFM_ACORN_MAJOR) {
-               extern void xd_set_geometry(struct block_device *,
-                       unsigned char, unsigned char, unsigned int);
-               xd_set_geometry(bdev, dr->secspertrack, heads, 1);
-               invalidate_bh_lrus();
-               truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
-       }
-#endif
-
        /*
         * Work out start of non-adfs partition.
         */
index 7408227c49c91cefed99f861a90a8bbb85e8b346..fbeb2f372a93dba06f0d9aab1cfb438389a5668e 100644 (file)
@@ -538,10 +538,23 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
                sector_t from = state->parts[p].from;
                if (!size)
                        continue;
+               if (from >= get_capacity(disk)) {
+                       printk(KERN_WARNING
+                              "%s: p%d ignored, start %llu is behind the end of the disk\n",
+                              disk->disk_name, p, (unsigned long long) from);
+                       continue;
+               }
                if (from + size > get_capacity(disk)) {
+                       /*
+                        * we can not ignore partitions of broken tables
+                        * created by for example camera firmware, but we
+                        * limit them to the end of the disk to avoid
+                        * creating invalid block devices
+                        */
                        printk(KERN_WARNING
-                               "%s: p%d exceeds device capacity\n",
-                               disk->disk_name, p);
+                              "%s: p%d size %llu limited to end of disk\n",
+                              disk->disk_name, p, (unsigned long long) size);
+                       size = get_capacity(disk) - from;
                }
                res = add_partition(disk, p, from, size, state->parts[p].flags);
                if (res) {
index 73cd7a418f06e7430b76ba15564fb92472263333..50f8f0600f0657d47de7081883f7dfe0fa460b69 100644 (file)
@@ -57,3 +57,13 @@ config PROC_SYSCTL
          As it is generally a good thing, you should say Y here unless
          building a kernel for install/rescue disks or your system is very
          limited in memory.
+
+config PROC_PAGE_MONITOR
+       default y
+       depends on PROC_FS && MMU
+       bool "Enable /proc page monitoring" if EMBEDDED
+       help
+         Various /proc files exist to monitor process memory utilization:
+         /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
+         /proc/kpagecount, and /proc/kpageflags. Disabling these
+          interfaces will reduce the size of the kernel by approximately 4kb.
index 71c9be59c9c2574045d69c33aa024d618b681b4c..f4bc0e789539f413e080324ab8209575ba349c42 100644 (file)
 #include <asm/processor.h>
 #include "internal.h"
 
-/* Gcc optimizes away "strlen(x)" for constant x */
-#define ADDBUF(buffer, string) \
-do { memcpy(buffer, string, strlen(string)); \
-     buffer += strlen(string); } while (0)
-
 static inline void task_name(struct seq_file *m, struct task_struct *p)
 {
        int i;
@@ -261,7 +256,6 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
        sigemptyset(&ignored);
        sigemptyset(&caught);
 
-       rcu_read_lock();
        if (lock_task_sighand(p, &flags)) {
                pending = p->pending.signal;
                shpending = p->signal->shared_pending.signal;
@@ -272,7 +266,6 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
                qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
                unlock_task_sighand(p, &flags);
        }
-       rcu_read_unlock();
 
        seq_printf(m, "Threads:\t%d\n", num_threads);
        seq_printf(m, "SigQ:\t%lu/%lu\n", qsize, qlim);
index a28840b11b89b5ca0b544f44ce58182544f51eef..b5918ae8ca79a7823bd6a4d3eb0ecfc0b08d30f6 100644 (file)
@@ -148,9 +148,6 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
        return count;
 }
 
-int maps_protect;
-EXPORT_SYMBOL(maps_protect);
-
 static struct fs_struct *get_fs_struct(struct task_struct *task)
 {
        struct fs_struct *fs;
@@ -164,7 +161,6 @@ static struct fs_struct *get_fs_struct(struct task_struct *task)
 
 static int get_nr_threads(struct task_struct *tsk)
 {
-       /* Must be called with the rcu_read_lock held */
        unsigned long flags;
        int count = 0;
 
@@ -471,14 +467,10 @@ static int proc_pid_limits(struct task_struct *task, char *buffer)
 
        struct rlimit rlim[RLIM_NLIMITS];
 
-       rcu_read_lock();
-       if (!lock_task_sighand(task,&flags)) {
-               rcu_read_unlock();
+       if (!lock_task_sighand(task, &flags))
                return 0;
-       }
        memcpy(rlim, task->signal->rlim, sizeof(struct rlimit) * RLIM_NLIMITS);
        unlock_task_sighand(task, &flags);
-       rcu_read_unlock();
 
        /*
         * print the file header
@@ -2443,6 +2435,13 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
 }
 #endif /* CONFIG_TASK_IO_ACCOUNTING */
 
+static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
+                               struct pid *pid, struct task_struct *task)
+{
+       seq_printf(m, "%08x\n", task->personality);
+       return 0;
+}
+
 /*
  * Thread groups
  */
@@ -2459,6 +2458,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("environ",    S_IRUSR, environ),
        INF("auxv",       S_IRUSR, pid_auxv),
        ONE("status",     S_IRUGO, pid_status),
+       ONE("personality", S_IRUSR, pid_personality),
        INF("limits",     S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
@@ -2794,6 +2794,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("environ",   S_IRUSR, environ),
        INF("auxv",      S_IRUSR, pid_auxv),
        ONE("status",    S_IRUGO, pid_status),
+       ONE("personality", S_IRUSR, pid_personality),
        INF("limits",    S_IRUSR, pid_limits),
 #ifdef CONFIG_SCHED_DEBUG
        REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
@@ -3088,9 +3089,7 @@ static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
        generic_fillattr(inode, stat);
 
        if (p) {
-               rcu_read_lock();
                stat->nlink += get_nr_threads(p);
-               rcu_read_unlock();
                put_task_struct(p);
        }
 
index 8bb03f056c282ec1c0b4b256c5f4ed4551182f1c..c6b4fa7e3b49e9a2625bf3a76465c85d7df7eba2 100644 (file)
@@ -342,7 +342,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
        if (!pde->proc_fops) {
                spin_unlock(&pde->pde_unload_lock);
                kfree(pdeo);
-               return rv;
+               return -EINVAL;
        }
        pde->pde_users++;
        open = pde->proc_fops->open;
index 442202314d5322292f87328b3e62b5427b3fa77a..3bfb7b8747b3f027657a217a18ff0a7bc37b6f5d 100644 (file)
@@ -45,8 +45,6 @@ do {                                          \
 extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
 #endif
 
-extern int maps_protect;
-
 extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
                                struct pid *pid, struct task_struct *task);
 extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
index 29e20c6b1f7f75bd9d29de8589648985bad5f4a3..59ea42e1ef03a0a4acdf3f73283d913b740415fd 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/blkdev.h>
 #include <linux/hugetlb.h>
 #include <linux/jiffies.h>
-#include <linux/sysrq.h>
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
 #include <linux/pid_namespace.h>
@@ -68,7 +67,6 @@
 extern int get_hardware_list(char *);
 extern int get_stram_list(char *);
 extern int get_exec_domain_list(char *);
-extern int get_dma_list(char *);
 
 static int proc_calc_metrics(char *page, char **start, off_t off,
                                 int count, int *eof, int len)
@@ -684,6 +682,7 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
        return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
+#ifdef CONFIG_FILE_LOCKING
 static int locks_open(struct inode *inode, struct file *filp)
 {
        return seq_open(filp, &locks_seq_operations);
@@ -695,6 +694,7 @@ static const struct file_operations proc_locks_operations = {
        .llseek         = seq_lseek,
        .release        = seq_release,
 };
+#endif /* CONFIG_FILE_LOCKING */
 
 static int execdomains_read_proc(char *page, char **start, off_t off,
                                 int count, int *eof, void *data)
@@ -703,28 +703,6 @@ static int execdomains_read_proc(char *page, char **start, off_t off,
        return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-#ifdef CONFIG_MAGIC_SYSRQ
-/*
- * writing 'C' to /proc/sysrq-trigger is like sysrq-C
- */
-static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
-                                  size_t count, loff_t *ppos)
-{
-       if (count) {
-               char c;
-
-               if (get_user(c, buf))
-                       return -EFAULT;
-               __handle_sysrq(c, NULL, 0);
-       }
-       return count;
-}
-
-static const struct file_operations proc_sysrq_trigger_operations = {
-       .write          = write_sysrq_trigger,
-};
-#endif
-
 #ifdef CONFIG_PROC_PAGE_MONITOR
 #define KPMSIZE sizeof(u64)
 #define KPMMASK (KPMSIZE - 1)
@@ -888,7 +866,9 @@ void __init proc_misc_init(void)
 #ifdef CONFIG_PRINTK
        proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
 #endif
+#ifdef CONFIG_FILE_LOCKING
        proc_create("locks", 0, NULL, &proc_locks_operations);
+#endif
        proc_create("devices", 0, NULL, &proc_devinfo_operations);
        proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
 #ifdef CONFIG_BLOCK
@@ -931,7 +911,4 @@ void __init proc_misc_init(void)
 #ifdef CONFIG_PROC_VMCORE
        proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
 #endif
-#ifdef CONFIG_MAGIC_SYSRQ
-       proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
-#endif
 }
index f9a8b892718fc2f1a04ce1d169ba1667378832b5..945a81043ba223cd92206077be7847563243f89e 100644 (file)
@@ -66,7 +66,7 @@ static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name)
        return NULL;
 }
 
-struct ctl_table_header *grab_header(struct inode *inode)
+static struct ctl_table_header *grab_header(struct inode *inode)
 {
        if (PROC_I(inode)->sysctl)
                return sysctl_head_grab(PROC_I(inode)->sysctl);
@@ -395,10 +395,10 @@ static struct dentry_operations proc_sys_dentry_operations = {
        .d_compare      = proc_sys_compare,
 };
 
-static struct proc_dir_entry *proc_sys_root;
-
 int proc_sys_init(void)
 {
+       struct proc_dir_entry *proc_sys_root;
+
        proc_sys_root = proc_mkdir("sys", NULL);
        proc_sys_root->proc_iops = &proc_sys_dir_operations;
        proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
index 73d1891ee6259e41f5be2f1d8d2a16948887097d..4806830ea2a1b0515c2faf00f52a6134f0f418c1 100644 (file)
@@ -210,9 +210,6 @@ static int show_map(struct seq_file *m, void *v)
        dev_t dev = 0;
        int len;
 
-       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
-               return -EACCES;
-
        if (file) {
                struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
                dev = inode->i_sb->s_dev;
@@ -742,22 +739,11 @@ const struct file_operations proc_pagemap_operations = {
 #ifdef CONFIG_NUMA
 extern int show_numa_map(struct seq_file *m, void *v);
 
-static int show_numa_map_checked(struct seq_file *m, void *v)
-{
-       struct proc_maps_private *priv = m->private;
-       struct task_struct *task = priv->task;
-
-       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
-               return -EACCES;
-
-       return show_numa_map(m, v);
-}
-
 static const struct seq_operations proc_pid_numa_maps_op = {
         .start  = m_start,
         .next   = m_next,
         .stop   = m_stop,
-        .show   = show_numa_map_checked
+        .show   = show_numa_map,
 };
 
 static int numa_maps_open(struct inode *inode, struct file *file)
index 5d84e7121df819cd0d9eb8b9bd54973edf5b77ed..219bd79ea894f656d57f29c9b4527c41363ab3d1 100644 (file)
@@ -110,11 +110,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
 static int show_map(struct seq_file *m, void *_vml)
 {
        struct vm_list_struct *vml = _vml;
-       struct proc_maps_private *priv = m->private;
-       struct task_struct *task = priv->task;
-
-       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
-               return -EACCES;
 
        return nommu_vma_show(m, vml->vma);
 }
index 9ac0f5e064e09e99f58b428e933b2903a893a5b9..841368b87a29dbb89c68c4539b6203a7e0501905 100644 (file)
@@ -165,14 +165,8 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
        return acc;
 }
 
-static int open_vmcore(struct inode *inode, struct file *filp)
-{
-       return 0;
-}
-
 const struct file_operations proc_vmcore_operations = {
        .read           = read_vmcore,
-       .open           = open_vmcore,
 };
 
 static struct vmcore* __init get_new_element(void)
index b9dbeeca7049451e66281a1561da4f36a913703a..37173fa07d1532c854fef231bda9a0744ce81374 100644 (file)
@@ -8,8 +8,6 @@
 
 /* proc info support a la one created by Sizif@Botik.RU for PGC */
 
-/* $Id: procfs.c,v 1.1.8.2 2001/07/15 17:08:42 god Exp $ */
-
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/seq_file.h>
@@ -621,7 +619,6 @@ int reiserfs_global_version_in_proc(char *buffer, char **start,
 #endif
 
 /*
- * $Log: procfs.c,v $
  * Revision 1.1.8.2  2001/07/15 17:08:42  god
  *  . use get_super() in procfs.c
  *  . remove remove_save_link() from reiserfs_do_truncate()
index bb3cb5b7cdb2479d1b68b9eb2fa2521e54810490..ad92461cbfc3cadb5b2dcbb32725f108cc0f08a9 100644 (file)
@@ -155,7 +155,7 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode,
        xadir = open_xa_dir(inode, flags);
        if (IS_ERR(xadir)) {
                return ERR_CAST(xadir);
-       } else if (xadir && !xadir->d_inode) {
+       } else if (!xadir->d_inode) {
                dput(xadir);
                return ERR_PTR(-ENODATA);
        }
index 006fc64227ddb16b051b85b0a959cfee7bd652a8..66f6e58a7e4bb1a52590f4eecbb4094647c61c4f 100644 (file)
@@ -61,6 +61,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
        int count = min_t(size_t, bytes, PAGE_SIZE);
+       char *temp;
 
        if (size) {
                if (offs > size)
@@ -69,23 +70,33 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
                        count = size - offs;
        }
 
+       temp = kmalloc(count, GFP_KERNEL);
+       if (!temp)
+               return -ENOMEM;
+
        mutex_lock(&bb->mutex);
 
        count = fill_read(dentry, bb->buffer, offs, count);
-       if (count < 0)
-               goto out_unlock;
+       if (count < 0) {
+               mutex_unlock(&bb->mutex);
+               goto out_free;
+       }
 
-       if (copy_to_user(userbuf, bb->buffer, count)) {
+       memcpy(temp, bb->buffer, count);
+
+       mutex_unlock(&bb->mutex);
+
+       if (copy_to_user(userbuf, temp, count)) {
                count = -EFAULT;
-               goto out_unlock;
+               goto out_free;
        }
 
        pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
 
        *off = offs + count;
 
- out_unlock:
-       mutex_unlock(&bb->mutex);
+ out_free:
+       kfree(temp);
        return count;
 }
 
@@ -118,6 +129,7 @@ static ssize_t write(struct file *file, const char __user *userbuf,
        int size = dentry->d_inode->i_size;
        loff_t offs = *off;
        int count = min_t(size_t, bytes, PAGE_SIZE);
+       char *temp;
 
        if (size) {
                if (offs > size)
@@ -126,19 +138,27 @@ static ssize_t write(struct file *file, const char __user *userbuf,
                        count = size - offs;
        }
 
-       mutex_lock(&bb->mutex);
+       temp = kmalloc(count, GFP_KERNEL);
+       if (!temp)
+               return -ENOMEM;
 
-       if (copy_from_user(bb->buffer, userbuf, count)) {
+       if (copy_from_user(temp, userbuf, count)) {
                count = -EFAULT;
-               goto out_unlock;
+               goto out_free;
        }
 
+       mutex_lock(&bb->mutex);
+
+       memcpy(bb->buffer, temp, count);
+
        count = flush_write(dentry, bb->buffer, offs, count);
+       mutex_unlock(&bb->mutex);
+
        if (count > 0)
                *off = offs + count;
 
- out_unlock:
-       mutex_unlock(&bb->mutex);
+out_free:
+       kfree(temp);
        return count;
 }
 
index aedaeba82ae5503a41cbd6ee366601ecb67ae31b..3a05a596e3b4de91dcb522401441b8dc8d959aa9 100644 (file)
@@ -370,17 +370,17 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
        memset(acxt, 0, sizeof(*acxt));
        acxt->parent_sd = parent_sd;
 
-       /* Lookup parent inode.  inode initialization and I_NEW
-        * clearing are protected by sysfs_mutex.  By grabbing it and
-        * looking up with _nowait variant, inode state can be
-        * determined reliably.
+       /* Lookup parent inode.  inode initialization is protected by
+        * sysfs_mutex, so inode existence can be determined by
+        * looking up inode while holding sysfs_mutex.
         */
        mutex_lock(&sysfs_mutex);
 
-       inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
-                               parent_sd);
+       inode = ilookup5(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+                        parent_sd);
+       if (inode) {
+               WARN_ON(inode->i_state & I_NEW);
 
-       if (inode && !(inode->i_state & I_NEW)) {
                /* parent inode available */
                acxt->parent_inode = inode;
 
@@ -393,8 +393,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
                        mutex_lock(&inode->i_mutex);
                        mutex_lock(&sysfs_mutex);
                }
-       } else
-               iput(inode);
+       }
 }
 
 /**
@@ -636,6 +635,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
 
        return sd;
 }
+EXPORT_SYMBOL_GPL(sysfs_get_dirent);
 
 static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
                      const char *name, struct sysfs_dirent **p_sd)
@@ -829,16 +829,12 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
        if (!new_dentry)
                goto out_unlock;
 
-       /* rename kobject and sysfs_dirent */
+       /* rename sysfs_dirent */
        error = -ENOMEM;
        new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
        if (!new_name)
                goto out_unlock;
 
-       error = kobject_set_name(kobj, "%s", new_name);
-       if (error)
-               goto out_unlock;
-
        dup_name = sd->s_name;
        sd->s_name = new_name;
 
index c9e4e5091da14c24b185b67419f3207188150f96..1f4a3f877262f5f6fbf34085f688e50b42471c8e 100644 (file)
 #include <linux/poll.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/limits.h>
 #include <asm/uaccess.h>
 
 #include "sysfs.h"
 
+/* used in crash dumps to help with debugging */
+static char last_sysfs_file[PATH_MAX];
+void sysfs_printk_last_file(void)
+{
+       printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
+}
+
 /*
  * There's one sysfs_buffer for each open file and one
  * sysfs_open_dirent for each sysfs_dirent with one or more open
@@ -328,6 +336,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        struct sysfs_buffer *buffer;
        struct sysfs_ops *ops;
        int error = -EACCES;
+       char *p;
+
+       p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
+       if (p)
+               memmove(last_sysfs_file, p, strlen(p) + 1);
 
        /* need attr_sd for attr and ops, its parent for kobj */
        if (!sysfs_get_active_two(attr_sd))
@@ -440,7 +453,23 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
        return POLLERR|POLLPRI;
 }
 
-void sysfs_notify(struct kobject *k, char *dir, char *attr)
+void sysfs_notify_dirent(struct sysfs_dirent *sd)
+{
+       struct sysfs_open_dirent *od;
+
+       spin_lock(&sysfs_open_dirent_lock);
+
+       od = sd->s_attr.open;
+       if (od) {
+               atomic_inc(&od->event);
+               wake_up_interruptible(&od->poll);
+       }
+
+       spin_unlock(&sysfs_open_dirent_lock);
+}
+EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
+
+void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
 {
        struct sysfs_dirent *sd = k->sd;
 
@@ -450,19 +479,8 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
                sd = sysfs_find_dirent(sd, dir);
        if (sd && attr)
                sd = sysfs_find_dirent(sd, attr);
-       if (sd) {
-               struct sysfs_open_dirent *od;
-
-               spin_lock(&sysfs_open_dirent_lock);
-
-               od = sd->s_attr.open;
-               if (od) {
-                       atomic_inc(&od->event);
-                       wake_up_interruptible(&od->poll);
-               }
-
-               spin_unlock(&sysfs_open_dirent_lock);
-       }
+       if (sd)
+               sysfs_notify_dirent(sd);
 
        mutex_unlock(&sysfs_mutex);
 }
index 14f0023984d74d6a51dedc0791fdfab53f2d5cc4..ab343e371d64682f678646ed02615171e73b2d31 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include "sysfs.h"
 
@@ -115,3 +116,17 @@ out_err:
        sysfs_dir_cachep = NULL;
        goto out;
 }
+
+#undef sysfs_get
+struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+       return __sysfs_get(sd);
+}
+EXPORT_SYMBOL_GPL(sysfs_get);
+
+#undef sysfs_put
+void sysfs_put(struct sysfs_dirent *sd)
+{
+       __sysfs_put(sd);
+}
+EXPORT_SYMBOL_GPL(sysfs_put);
index a5db496f71c717ce63073440a3c9a23138b67d47..93c6d6b27c4ded5596c783ac1bdbe4e4b2590bbd 100644 (file)
@@ -124,7 +124,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
                        struct sysfs_dirent **p_sd);
 void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
-static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
 {
        if (sd) {
                WARN_ON(!atomic_read(&sd->s_count));
@@ -132,12 +132,14 @@ static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
        }
        return sd;
 }
+#define sysfs_get(sd) __sysfs_get(sd)
 
-static inline void sysfs_put(struct sysfs_dirent *sd)
+static inline void __sysfs_put(struct sysfs_dirent *sd)
 {
        if (sd && atomic_dec_and_test(&sd->s_count))
                release_sysfs_dirent(sd);
 }
+#define sysfs_put(sd) __sysfs_put(sd)
 
 /*
  * inode.c
index 3f4902060c7a10aba197a73c07491b7aca4cc84e..9a9220333b3be51399e4fe2c28cb9a60840842fb 100644 (file)
@@ -848,7 +848,7 @@ enum {
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_fast_unmount, "fast_unmount"},
        {Opt_norm_unmount, "norm_unmount"},
        {Opt_err, NULL},
index 5698bbf83bbff90565ad75e46e04d037c457135d..e25e7010627b887bee05a004d55642888a00a291 100644 (file)
@@ -369,7 +369,7 @@ enum {
        Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_novrs,     "novrs"},
        {Opt_nostrict,  "nostrict"},
        {Opt_bs,        "bs=%u"},
index 3141969b456daa5223b5999607958c0b3b33557c..e65212dfb60e06259c5f8737fa1b51db79cbec43 100644 (file)
@@ -309,7 +309,7 @@ enum {
        Opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_type_old, "ufstype=old"},
        {Opt_type_sunx86, "ufstype=sunx86"},
        {Opt_type_sun, "ufstype=sun"},
@@ -1233,7 +1233,7 @@ static int ufs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
        struct ufs_sb_info *sbi = UFS_SB(vfs->mnt_sb);
        unsigned mval = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
-       struct match_token *tp = tokens;
+       const struct match_token *tp = tokens;
 
        while (tp->token != Opt_onerror_panic && tp->token != mval)
                ++tp;
index 18d3c848783511da1848ed56800a47b533be5b3d..e39013619b2619317a77cb8e1ceb3aee05de033f 100644 (file)
@@ -158,7 +158,7 @@ enum {
        Opt_barrier, Opt_nobarrier, Opt_err
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_barrier, "barrier"},
        {Opt_nobarrier, "nobarrier"},
        {Opt_err, NULL}
@@ -1323,7 +1323,7 @@ xfs_fs_remount(
        "XFS: mount option \"%s\" not supported for remount\n", p);
                        return -EINVAL;
 #else
-                       return 0;
+                       break;
 #endif
                }
        }
index 57ab9e9d7593e6213ff2342f55d2dbaaab92ff80..74a9617776a80f728b874ab47f58a5f124d00996 100644 (file)
@@ -467,7 +467,7 @@ struct acpi_integer_overlay {
 /*
  * If ACPI_GET_FUNCTION_NAME was not defined in the compiler-dependent header,
  * define it now. This is the case where there the compiler does not support
- * a __FUNCTION__ macro or equivalent.
+ * a __func__ macro or equivalent.
  */
 #ifndef ACPI_GET_FUNCTION_NAME
 #define ACPI_GET_FUNCTION_NAME          _acpi_function_name
@@ -475,12 +475,12 @@ struct acpi_integer_overlay {
  * The Name parameter should be the procedure name as a quoted string.
  * The function name is also used by the function exit macros below.
  * Note: (const char) is used to be compatible with the debug interfaces
- * and macros such as __FUNCTION__.
+ * and macros such as __func__.
  */
 #define ACPI_FUNCTION_NAME(name)       static const char _acpi_function_name[] = #name;
 
 #else
-/* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */
+/* Compiler supports __func__ (or equivalent) -- Ignore this macro */
 
 #define ACPI_FUNCTION_NAME(name)
 #endif
index 8996dba90cd91bbe07b084baf84bd52b46d2fde8..8e2cdc57b1974f5430b4d39fe681090f9ffd0441 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Function name is used for debug output. Non-ANSI, compiler-dependent */
 
-#define ACPI_GET_FUNCTION_NAME          __FUNCTION__
+#define ACPI_GET_FUNCTION_NAME          __func__
 
 /*
  * This macro is used to tag functions as "printf-like" because
diff --git a/include/asm-arm/plat-s3c/debug-macro.S b/include/asm-arm/plat-s3c/debug-macro.S
deleted file mode 100644 (file)
index 84c40b8..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* linux/include/asm-arm/plat-s3c/debug-macro.S
- *
- * Copyright 2005, 2007 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     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 <asm/plat-s3c/regs-serial.h>
-
-/* The S3C2440 implementations are used by default as they are the
- * most widely re-used */
-
-       .macro fifo_level_s3c2440 rd, rx
-               ldr     \rd, [ \rx, # S3C2410_UFSTAT ]
-               and     \rd, \rd, #S3C2440_UFSTAT_TXMASK
-       .endm
-
-#ifndef fifo_level
-#define fifo_level fifo_level_s3c2410
-#endif
-
-       .macro  fifo_full_s3c2440 rd, rx
-               ldr     \rd, [ \rx, # S3C2410_UFSTAT ]
-               tst     \rd, #S3C2440_UFSTAT_TXFULL
-       .endm
-
-#ifndef fifo_full
-#define fifo_full fifo_full_s3c2440
-#endif
-
-       .macro  senduart,rd,rx
-               strb    \rd, [\rx, # S3C2410_UTXH ]
-       .endm
-
-       .macro  busyuart, rd, rx
-               ldr     \rd, [ \rx, # S3C2410_UFCON ]
-               tst     \rd, #S3C2410_UFCON_FIFOMODE    @ fifo enabled?
-               beq     1001f                           @
-               @ FIFO enabled...
-1003:
-               fifo_full \rd, \rx
-               bne     1003b
-               b       1002f
-
-1001:
-               @ busy waiting for non fifo
-               ldr     \rd, [ \rx, # S3C2410_UTRSTAT ]
-               tst     \rd, #S3C2410_UTRSTAT_TXFE
-               beq     1001b
-
-1002:          @ exit busyuart
-       .endm
-
-       .macro  waituart,rd,rx
-               ldr     \rd, [ \rx, # S3C2410_UFCON ]
-               tst     \rd, #S3C2410_UFCON_FIFOMODE    @ fifo enabled?
-               beq     1001f                           @
-               @ FIFO enabled...
-1003:
-               fifo_level \rd, \rx
-               teq     \rd, #0
-               bne     1003b
-               b       1002f
-1001:
-               @ idle waiting for non fifo
-               ldr     \rd, [ \rx, # S3C2410_UTRSTAT ]
-               tst     \rd, #S3C2410_UTRSTAT_TXFE
-               beq     1001b
-
-1002:          @ exit busyuart
-       .endm
diff --git a/include/asm-arm/plat-s3c/map.h b/include/asm-arm/plat-s3c/map.h
deleted file mode 100644 (file)
index b84289d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* linux/include/asm-arm/plat-s3c/map.h
- *
- * Copyright 2003, 2007 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - Memory map definitions (virtual addresses)
- *
- * This program is free software; you can 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_PLAT_MAP_H
-#define __ASM_PLAT_MAP_H __FILE__
-
-/* Fit all our registers in at 0xF4000000 upwards, trying to use as
- * little of the VA space as possible so vmalloc and friends have a
- * better chance of getting memory.
- *
- * we try to ensure stuff like the IRQ registers are available for
- * an single MOVS instruction (ie, only 8 bits of set data)
- */
-
-#define S3C_ADDR_BASE  (0xF4000000)
-
-#ifndef __ASSEMBLY__
-#define S3C_ADDR(x)    ((void __iomem __force *)S3C_ADDR_BASE + (x))
-#else
-#define S3C_ADDR(x)    (S3C_ADDR_BASE + (x))
-#endif
-
-#define S3C_VA_IRQ     S3C_ADDR(0x00000000)    /* irq controller(s) */
-#define S3C_VA_SYS     S3C_ADDR(0x00100000)    /* system control */
-#define S3C_VA_MEM     S3C_ADDR(0x00200000)    /* system control */
-#define S3C_VA_TIMER   S3C_ADDR(0x00300000)    /* timer block */
-#define S3C_VA_WATCHDOG        S3C_ADDR(0x00400000)    /* watchdog */
-#define S3C_VA_UART    S3C_ADDR(0x01000000)    /* UART */
-
-#endif /* __ASM_PLAT_MAP_H */
diff --git a/include/asm-arm/plat-s3c/regs-adc.h b/include/asm-arm/plat-s3c/regs-adc.h
deleted file mode 100644 (file)
index 4323ccc..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
- *
- * Copyright (c) 2004 Shannon Holland <holland@loser.net>
- *
- * This program is free software; yosu can 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 ADC registers
-*/
-
-#ifndef __ASM_ARCH_REGS_ADC_H
-#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
-
-#define S3C2410_ADCREG(x) (x)
-
-#define S3C2410_ADCCON    S3C2410_ADCREG(0x00)
-#define S3C2410_ADCTSC    S3C2410_ADCREG(0x04)
-#define S3C2410_ADCDLY    S3C2410_ADCREG(0x08)
-#define S3C2410_ADCDAT0           S3C2410_ADCREG(0x0C)
-#define S3C2410_ADCDAT1           S3C2410_ADCREG(0x10)
-
-
-/* ADCCON Register Bits */
-#define S3C2410_ADCCON_ECFLG           (1<<15)
-#define S3C2410_ADCCON_PRSCEN          (1<<14)
-#define S3C2410_ADCCON_PRSCVL(x)       (((x)&0xFF)<<6)
-#define S3C2410_ADCCON_PRSCVLMASK      (0xFF<<6)
-#define S3C2410_ADCCON_SELMUX(x)       (((x)&0x7)<<3)
-#define S3C2410_ADCCON_MUXMASK         (0x7<<3)
-#define S3C2410_ADCCON_STDBM           (1<<2)
-#define S3C2410_ADCCON_READ_START      (1<<1)
-#define S3C2410_ADCCON_ENABLE_START    (1<<0)
-#define S3C2410_ADCCON_STARTMASK       (0x3<<0)
-
-
-/* ADCTSC Register Bits */
-#define S3C2410_ADCTSC_YM_SEN          (1<<7)
-#define S3C2410_ADCTSC_YP_SEN          (1<<6)
-#define S3C2410_ADCTSC_XM_SEN          (1<<5)
-#define S3C2410_ADCTSC_XP_SEN          (1<<4)
-#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
-#define S3C2410_ADCTSC_AUTO_PST                (1<<2)
-#define S3C2410_ADCTSC_XY_PST(x)       (((x)&0x3)<<0)
-
-/* ADCDAT0 Bits */
-#define S3C2410_ADCDAT0_UPDOWN         (1<<15)
-#define S3C2410_ADCDAT0_AUTO_PST       (1<<14)
-#define S3C2410_ADCDAT0_XY_PST         (0x3<<12)
-#define S3C2410_ADCDAT0_XPDATA_MASK    (0x03FF)
-
-/* ADCDAT1 Bits */
-#define S3C2410_ADCDAT1_UPDOWN         (1<<15)
-#define S3C2410_ADCDAT1_AUTO_PST       (1<<14)
-#define S3C2410_ADCDAT1_XY_PST         (0x3<<12)
-#define S3C2410_ADCDAT1_YPDATA_MASK    (0x03FF)
-
-#endif /* __ASM_ARCH_REGS_ADC_H */
-
-
diff --git a/include/asm-arm/plat-s3c/regs-serial.h b/include/asm-arm/plat-s3c/regs-serial.h
deleted file mode 100644 (file)
index a0daa64..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-serial.h
- *
- *  From linux/include/asm-arm/hardware/serial_s3c2410.h
- *
- *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
- *
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- *  Additional defines, (c) 2003 Simtec Electronics (linux@simtec.co.uk)
- *
- *  Adapted from:
- *
- *  Internal header file for MX1ADS serial ports (UART1 & 2)
- *
- *  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_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define S3C24XX_VA_UART0      (S3C_VA_UART)
-#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
-#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
-#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
-
-#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
-#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
-#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
-#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
-
-#define S3C2410_URXH     (0x24)
-#define S3C2410_UTXH     (0x20)
-#define S3C2410_ULCON    (0x00)
-#define S3C2410_UCON     (0x04)
-#define S3C2410_UFCON    (0x08)
-#define S3C2410_UMCON    (0x0C)
-#define S3C2410_UBRDIV   (0x28)
-#define S3C2410_UTRSTAT          (0x10)
-#define S3C2410_UERSTAT          (0x14)
-#define S3C2410_UFSTAT   (0x18)
-#define S3C2410_UMSTAT   (0x1C)
-
-#define S3C2410_LCON_CFGMASK     ((0xF<<3)|(0x3))
-
-#define S3C2410_LCON_CS5         (0x0)
-#define S3C2410_LCON_CS6         (0x1)
-#define S3C2410_LCON_CS7         (0x2)
-#define S3C2410_LCON_CS8         (0x3)
-#define S3C2410_LCON_CSMASK      (0x3)
-
-#define S3C2410_LCON_PNONE       (0x0)
-#define S3C2410_LCON_PEVEN       (0x5 << 3)
-#define S3C2410_LCON_PODD        (0x4 << 3)
-#define S3C2410_LCON_PMASK       (0x7 << 3)
-
-#define S3C2410_LCON_STOPB       (1<<2)
-#define S3C2410_LCON_IRM          (1<<6)
-
-#define S3C2440_UCON_CLKMASK     (3<<10)
-#define S3C2440_UCON_PCLK        (0<<10)
-#define S3C2440_UCON_UCLK        (1<<10)
-#define S3C2440_UCON_PCLK2       (2<<10)
-#define S3C2440_UCON_FCLK        (3<<10)
-#define S3C2443_UCON_EPLL        (3<<10)
-
-#define S3C2440_UCON2_FCLK_EN    (1<<15)
-#define S3C2440_UCON0_DIVMASK    (15 << 12)
-#define S3C2440_UCON1_DIVMASK    (15 << 12)
-#define S3C2440_UCON2_DIVMASK    (7 << 12)
-#define S3C2440_UCON_DIVSHIFT    (12)
-
-#define S3C2412_UCON_CLKMASK   (3<<10)
-#define S3C2412_UCON_UCLK      (1<<10)
-#define S3C2412_UCON_USYSCLK   (3<<10)
-#define S3C2412_UCON_PCLK      (0<<10)
-#define S3C2412_UCON_PCLK2     (2<<10)
-
-#define S3C2410_UCON_UCLK        (1<<10)
-#define S3C2410_UCON_SBREAK      (1<<4)
-
-#define S3C2410_UCON_TXILEVEL    (1<<9)
-#define S3C2410_UCON_RXILEVEL    (1<<8)
-#define S3C2410_UCON_TXIRQMODE   (1<<2)
-#define S3C2410_UCON_RXIRQMODE   (1<<0)
-#define S3C2410_UCON_RXFIFO_TOI          (1<<7)
-#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
-#define S3C2443_UCON_LOOPBACK    (1<<5)
-
-#define S3C2410_UCON_DEFAULT     (S3C2410_UCON_TXILEVEL  | \
-                                  S3C2410_UCON_RXILEVEL  | \
-                                  S3C2410_UCON_TXIRQMODE | \
-                                  S3C2410_UCON_RXIRQMODE | \
-                                  S3C2410_UCON_RXFIFO_TOI)
-
-#define S3C2410_UFCON_FIFOMODE   (1<<0)
-#define S3C2410_UFCON_TXTRIG0    (0<<6)
-#define S3C2410_UFCON_RXTRIG8    (1<<4)
-#define S3C2410_UFCON_RXTRIG12   (2<<4)
-
-/* S3C2440 FIFO trigger levels */
-#define S3C2440_UFCON_RXTRIG1    (0<<4)
-#define S3C2440_UFCON_RXTRIG8    (1<<4)
-#define S3C2440_UFCON_RXTRIG16   (2<<4)
-#define S3C2440_UFCON_RXTRIG32   (3<<4)
-
-#define S3C2440_UFCON_TXTRIG0    (0<<6)
-#define S3C2440_UFCON_TXTRIG16   (1<<6)
-#define S3C2440_UFCON_TXTRIG32   (2<<6)
-#define S3C2440_UFCON_TXTRIG48   (3<<6)
-
-#define S3C2410_UFCON_RESETBOTH          (3<<1)
-#define S3C2410_UFCON_RESETTX    (1<<2)
-#define S3C2410_UFCON_RESETRX    (1<<1)
-
-#define S3C2410_UFCON_DEFAULT    (S3C2410_UFCON_FIFOMODE | \
-                                  S3C2410_UFCON_TXTRIG0  | \
-                                  S3C2410_UFCON_RXTRIG8 )
-
-#define        S3C2410_UMCOM_AFC         (1<<4)
-#define        S3C2410_UMCOM_RTS_LOW     (1<<0)
-
-#define S3C2412_UMCON_AFC_63   (0<<5)          /* same as s3c2443 */
-#define S3C2412_UMCON_AFC_56   (1<<5)
-#define S3C2412_UMCON_AFC_48   (2<<5)
-#define S3C2412_UMCON_AFC_40   (3<<5)
-#define S3C2412_UMCON_AFC_32   (4<<5)
-#define S3C2412_UMCON_AFC_24   (5<<5)
-#define S3C2412_UMCON_AFC_16   (6<<5)
-#define S3C2412_UMCON_AFC_8    (7<<5)
-
-#define S3C2410_UFSTAT_TXFULL    (1<<9)
-#define S3C2410_UFSTAT_RXFULL    (1<<8)
-#define S3C2410_UFSTAT_TXMASK    (15<<4)
-#define S3C2410_UFSTAT_TXSHIFT   (4)
-#define S3C2410_UFSTAT_RXMASK    (15<<0)
-#define S3C2410_UFSTAT_RXSHIFT   (0)
-
-/* UFSTAT S3C2443 same as S3C2440 */
-#define S3C2440_UFSTAT_TXFULL    (1<<14)
-#define S3C2440_UFSTAT_RXFULL    (1<<6)
-#define S3C2440_UFSTAT_TXSHIFT   (8)
-#define S3C2440_UFSTAT_RXSHIFT   (0)
-#define S3C2440_UFSTAT_TXMASK    (63<<8)
-#define S3C2440_UFSTAT_RXMASK    (63)
-
-#define S3C2410_UTRSTAT_TXE      (1<<2)
-#define S3C2410_UTRSTAT_TXFE     (1<<1)
-#define S3C2410_UTRSTAT_RXDR     (1<<0)
-
-#define S3C2410_UERSTAT_OVERRUN          (1<<0)
-#define S3C2410_UERSTAT_FRAME    (1<<2)
-#define S3C2410_UERSTAT_BREAK    (1<<3)
-#define S3C2443_UERSTAT_PARITY   (1<<1)
-
-#define S3C2410_UERSTAT_ANY      (S3C2410_UERSTAT_OVERRUN | \
-                                  S3C2410_UERSTAT_FRAME | \
-                                  S3C2410_UERSTAT_BREAK)
-
-#define S3C2410_UMSTAT_CTS       (1<<0)
-#define S3C2410_UMSTAT_DeltaCTS          (1<<2)
-
-#define S3C2443_DIVSLOT                  (0x2C)
-
-#ifndef __ASSEMBLY__
-
-/* struct s3c24xx_uart_clksrc
- *
- * this structure defines a named clock source that can be used for the
- * uart, so that the best clock can be selected for the requested baud
- * rate.
- *
- * min_baud and max_baud define the range of baud-rates this clock is
- * acceptable for, if they are both zero, it is assumed any baud rate that
- * can be generated from this clock will be used.
- *
- * divisor gives the divisor from the clock to the one seen by the uart
-*/
-
-struct s3c24xx_uart_clksrc {
-       const char      *name;
-       unsigned int     divisor;
-       unsigned int     min_baud;
-       unsigned int     max_baud;
-};
-
-/* configuration structure for per-machine configurations for the
- * serial port
- *
- * the pointer is setup by the machine specific initialisation from the
- * arch/arm/mach-s3c2410/ directory.
-*/
-
-struct s3c2410_uartcfg {
-       unsigned char      hwport;       /* hardware port number */
-       unsigned char      unused;
-       unsigned short     flags;
-       upf_t              uart_flags;   /* default uart flags */
-
-       unsigned long      ucon;         /* value of ucon for port */
-       unsigned long      ulcon;        /* value of ulcon for port */
-       unsigned long      ufcon;        /* value of ufcon for port */
-
-       struct s3c24xx_uart_clksrc *clocks;
-       unsigned int                clocks_size;
-};
-
-/* s3c24xx_uart_devs
- *
- * this is exported from the core as we cannot use driver_register(),
- * or platform_add_device() before the console_initcall()
-*/
-
-extern struct platform_device *s3c24xx_uart_devs[3];
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff --git a/include/asm-arm/plat-s3c/regs-timer.h b/include/asm-arm/plat-s3c/regs-timer.h
deleted file mode 100644 (file)
index cc0eedd..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-timer.h
- *
- * Copyright (c) 2003 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 Timer configuration
-*/
-
-
-#ifndef __ASM_ARCH_REGS_TIMER_H
-#define __ASM_ARCH_REGS_TIMER_H
-
-#define S3C_TIMERREG(x) (S3C_VA_TIMER + (x))
-#define S3C_TIMERREG2(tmr,reg) S3C_TIMERREG((reg)+0x0c+((tmr)*0x0c))
-
-#define S3C2410_TCFG0        S3C_TIMERREG(0x00)
-#define S3C2410_TCFG1        S3C_TIMERREG(0x04)
-#define S3C2410_TCON         S3C_TIMERREG(0x08)
-
-#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)
-#define S3C2410_TCFG1_MUX4_DIV8          (2<<16)
-#define S3C2410_TCFG1_MUX4_DIV16  (3<<16)
-#define S3C2410_TCFG1_MUX4_TCLK1  (4<<16)
-#define S3C2410_TCFG1_MUX4_MASK          (15<<16)
-#define S3C2410_TCFG1_MUX4_SHIFT  (16)
-
-#define S3C2410_TCFG1_MUX3_DIV2          (0<<12)
-#define S3C2410_TCFG1_MUX3_DIV4          (1<<12)
-#define S3C2410_TCFG1_MUX3_DIV8          (2<<12)
-#define S3C2410_TCFG1_MUX3_DIV16  (3<<12)
-#define S3C2410_TCFG1_MUX3_TCLK1  (4<<12)
-#define S3C2410_TCFG1_MUX3_MASK          (15<<12)
-
-
-#define S3C2410_TCFG1_MUX2_DIV2          (0<<8)
-#define S3C2410_TCFG1_MUX2_DIV4          (1<<8)
-#define S3C2410_TCFG1_MUX2_DIV8          (2<<8)
-#define S3C2410_TCFG1_MUX2_DIV16  (3<<8)
-#define S3C2410_TCFG1_MUX2_TCLK1  (4<<8)
-#define S3C2410_TCFG1_MUX2_MASK          (15<<8)
-
-
-#define S3C2410_TCFG1_MUX1_DIV2          (0<<4)
-#define S3C2410_TCFG1_MUX1_DIV4          (1<<4)
-#define S3C2410_TCFG1_MUX1_DIV8          (2<<4)
-#define S3C2410_TCFG1_MUX1_DIV16  (3<<4)
-#define S3C2410_TCFG1_MUX1_TCLK0  (4<<4)
-#define S3C2410_TCFG1_MUX1_MASK          (15<<4)
-
-#define S3C2410_TCFG1_MUX0_DIV2          (0<<0)
-#define S3C2410_TCFG1_MUX0_DIV4          (1<<0)
-#define S3C2410_TCFG1_MUX0_DIV8          (2<<0)
-#define S3C2410_TCFG1_MUX0_DIV16  (3<<0)
-#define S3C2410_TCFG1_MUX0_TCLK0  (4<<0)
-#define S3C2410_TCFG1_MUX0_MASK          (15<<0)
-
-#define S3C2410_TCFG1_MUX_DIV2   (0<<0)
-#define S3C2410_TCFG1_MUX_DIV4   (1<<0)
-#define S3C2410_TCFG1_MUX_DIV8   (2<<0)
-#define S3C2410_TCFG1_MUX_DIV16   (3<<0)
-#define S3C2410_TCFG1_MUX_TCLK    (4<<0)
-#define S3C2410_TCFG1_MUX_MASK   (15<<0)
-
-#define S3C2410_TCFG1_SHIFT(x)   ((x) * 4)
-
-/* for each timer, we have an count buffer, an compare buffer and
- * an observation buffer
-*/
-
-/* WARNING - timer 4 has no buffer reg, and it's observation is at +4 */
-
-#define S3C2410_TCNTB(tmr)    S3C_TIMERREG2(tmr, 0x00)
-#define S3C2410_TCMPB(tmr)    S3C_TIMERREG2(tmr, 0x04)
-#define S3C2410_TCNTO(tmr)    S3C_TIMERREG2(tmr, (((tmr) == 4) ? 0x04 : 0x08))
-
-#define S3C2410_TCON_T4RELOAD    (1<<22)
-#define S3C2410_TCON_T4MANUALUPD  (1<<21)
-#define S3C2410_TCON_T4START     (1<<20)
-
-#define S3C2410_TCON_T3RELOAD    (1<<19)
-#define S3C2410_TCON_T3INVERT    (1<<18)
-#define S3C2410_TCON_T3MANUALUPD  (1<<17)
-#define S3C2410_TCON_T3START     (1<<16)
-
-#define S3C2410_TCON_T2RELOAD    (1<<15)
-#define S3C2410_TCON_T2INVERT    (1<<14)
-#define S3C2410_TCON_T2MANUALUPD  (1<<13)
-#define S3C2410_TCON_T2START     (1<<12)
-
-#define S3C2410_TCON_T1RELOAD    (1<<11)
-#define S3C2410_TCON_T1INVERT    (1<<10)
-#define S3C2410_TCON_T1MANUALUPD  (1<<9)
-#define S3C2410_TCON_T1START     (1<<8)
-
-#define S3C2410_TCON_T0DEADZONE          (1<<4)
-#define S3C2410_TCON_T0RELOAD    (1<<3)
-#define S3C2410_TCON_T0INVERT    (1<<2)
-#define S3C2410_TCON_T0MANUALUPD  (1<<1)
-#define S3C2410_TCON_T0START     (1<<0)
-
-#endif /*  __ASM_ARCH_REGS_TIMER_H */
-
-
-
diff --git a/include/asm-arm/plat-s3c/uncompress.h b/include/asm-arm/plat-s3c/uncompress.h
deleted file mode 100644 (file)
index 19b9eda..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* linux/include/asm-arm/plat-s3c/uncompress.h
- *
- * Copyright 2003, 2007 Simtec Electronics
- *     http://armlinux.simtec.co.uk/
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - uncompress code
- *
- * This program is free software; you can 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_PLAT_UNCOMPRESS_H
-#define __ASM_PLAT_UNCOMPRESS_H
-
-typedef unsigned int upf_t;    /* cannot include linux/serial_core.h */
-
-/* uart setup */
-
-static unsigned int fifo_mask;
-static unsigned int fifo_max;
-
-/* forward declerations */
-
-static void arch_detect_cpu(void);
-
-/* defines for UART registers */
-
-#include <asm/plat-s3c/regs-serial.h>
-#include <asm/plat-s3c/regs-watchdog.h>
-
-/* working in physical space... */
-#undef S3C2410_WDOGREG
-#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
-
-/* how many bytes we allow into the FIFO at a time in FIFO mode */
-#define FIFO_MAX        (14)
-
-#define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT)
-
-static __inline__ void
-uart_wr(unsigned int reg, unsigned int val)
-{
-       volatile unsigned int *ptr;
-
-       ptr = (volatile unsigned int *)(reg + uart_base);
-       *ptr = val;
-}
-
-static __inline__ unsigned int
-uart_rd(unsigned int reg)
-{
-       volatile unsigned int *ptr;
-
-       ptr = (volatile unsigned int *)(reg + uart_base);
-       return *ptr;
-}
-
-/* we can deal with the case the UARTs are being run
- * in FIFO mode, so that we don't hold up our execution
- * waiting for tx to happen...
-*/
-
-static void putc(int ch)
-{
-       if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
-               int level;
-
-               while (1) {
-                       level = uart_rd(S3C2410_UFSTAT);
-                       level &= fifo_mask;
-
-                       if (level < fifo_max)
-                               break;
-               }
-
-       } else {
-               /* not using fifos */
-
-               while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
-                       barrier();
-       }
-
-       /* write byte to transmission register */
-       uart_wr(S3C2410_UTXH, ch);
-}
-
-static inline void flush(void)
-{
-}
-
-#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
-
-/* CONFIG_S3C_BOOT_WATCHDOG
- *
- * Simple boot-time watchdog setup, to reboot the system if there is
- * any problem with the boot process
-*/
-
-#ifdef CONFIG_S3C_BOOT_WATCHDOG
-
-#define WDOG_COUNT (0xff00)
-
-static inline void arch_decomp_wdog(void)
-{
-       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-}
-
-static void arch_decomp_wdog_start(void)
-{
-       __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
-       __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
-}
-
-#else
-#define arch_decomp_wdog_start()
-#define arch_decomp_wdog()
-#endif
-
-#ifdef CONFIG_S3C_BOOT_ERROR_RESET
-
-static void arch_decomp_error(const char *x)
-{
-       putstr("\n\n");
-       putstr(x);
-       putstr("\n\n -- System resetting\n");
-
-       __raw_writel(0x4000, S3C2410_WTDAT);
-       __raw_writel(0x4000, S3C2410_WTCNT);
-       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
-
-       while(1);
-}
-
-#define arch_error arch_decomp_error
-#endif
-
-static void error(char *err);
-
-static void
-arch_decomp_setup(void)
-{
-       /* we may need to setup the uart(s) here if we are not running
-        * on an BAST... the BAST will have left the uarts configured
-        * after calling linux.
-        */
-
-       arch_detect_cpu();
-       arch_decomp_wdog_start();
-}
-
-
-#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff --git a/include/asm-arm/plat-s3c24xx/clock.h b/include/asm-arm/plat-s3c24xx/clock.h
deleted file mode 100644 (file)
index 235b753..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/clock.h
- * linux/arch/arm/mach-s3c2410/clock.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *     http://www.simtec.co.uk/products/SWLINUX/
- *     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;
-       int                   id;
-       int                   usage;
-       unsigned long         rate;
-       unsigned long         ctrlbit;
-
-       int                 (*enable)(struct clk *, int enable);
-       int                 (*set_rate)(struct clk *c, unsigned long rate);
-       unsigned long       (*get_rate)(struct clk *c);
-       unsigned long       (*round_rate)(struct clk *c, unsigned long rate);
-       int                 (*set_parent)(struct clk *c, struct clk *parent);
-};
-
-/* other clocks which may be registered by board support */
-
-extern struct clk s3c24xx_dclk0;
-extern struct clk s3c24xx_dclk1;
-extern struct clk s3c24xx_clkout0;
-extern struct clk s3c24xx_clkout1;
-extern struct clk s3c24xx_uclk;
-
-extern struct clk clk_usb_bus;
-
-/* core clock support */
-
-extern struct clk clk_f;
-extern struct clk clk_h;
-extern struct clk clk_p;
-extern struct clk clk_mpll;
-extern struct clk clk_upll;
-extern struct clk clk_xtal;
-
-/* exports for arch/arm/mach-s3c2410
- *
- * Please DO NOT use these outside of arch/arm/mach-s3c2410
-*/
-
-extern struct mutex clocks_mutex;
-
-extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
-
-extern int s3c24xx_register_clock(struct clk *clk);
-extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
-
-extern int s3c24xx_setup_clocks(unsigned long xtal,
-                               unsigned long fclk,
-                               unsigned long hclk,
-                               unsigned long pclk);
diff --git a/include/asm-arm/plat-s3c24xx/common-smdk.h b/include/asm-arm/plat-s3c24xx/common-smdk.h
deleted file mode 100644 (file)
index 58d9094..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Common code for SMDK2410 and SMDK2440 boards
- *
- * http://www.fluff.org/ben/smdk2440/
- *
- * This program is free software; you can 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 smdk_machine_init(void);
diff --git a/include/asm-arm/plat-s3c24xx/cpu.h b/include/asm-arm/plat-s3c24xx/cpu.h
deleted file mode 100644 (file)
index 23e420e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/cpu.h
- *
- * Copyright (c) 2004-2005 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.
-*/
-
-/* todo - fix when rmk changes iodescs to use `void __iomem *` */
-
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
-
-/* forward declaration */
-struct s3c24xx_uart_resources;
-struct platform_device;
-struct s3c2410_uartcfg;
-struct map_desc;
-
-/* core initialisation functions */
-
-extern void s3c24xx_init_irq(void);
-
-extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
-
-extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c24xx_init_clocks(int xtal);
-
-extern void s3c24xx_init_uartdevs(char *name,
-                                 struct s3c24xx_uart_resources *res,
-                                 struct s3c2410_uartcfg *cfg, int no);
-
-/* timer for 2410/2440 */
-
-struct sys_timer;
-extern struct sys_timer s3c24xx_timer;
-
-/* system device classes */
-
-extern struct sysdev_class s3c2410_sysclass;
-extern struct sysdev_class s3c2412_sysclass;
-extern struct sysdev_class s3c2440_sysclass;
-extern struct sysdev_class s3c2442_sysclass;
-extern struct sysdev_class s3c2443_sysclass;
diff --git a/include/asm-arm/plat-s3c24xx/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
deleted file mode 100644 (file)
index badaac9..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/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.
-*/
-#include <linux/platform_device.h>
-
-struct s3c24xx_uart_resources {
-       struct resource         *resources;
-       unsigned long            nr_resources;
-};
-
-extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
-
-extern struct platform_device *s3c24xx_uart_devs[];
-extern struct platform_device *s3c24xx_uart_src[];
-
-extern struct platform_device s3c_device_timer[];
-
-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_hsmmc;
-
-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_usbgadget;
-
-/* s3c2440 specific devices */
-
-#ifdef CONFIG_CPU_S3C2440
-
-extern struct platform_device s3c_device_camif;
-
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
deleted file mode 100644 (file)
index c78efe3..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/dma.h
- *
- * Copyright (C) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA 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.
-*/
-
-extern struct sysdev_class dma_sysclass;
-extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-#define DMA_CH_VALID           (1<<31)
-#define DMA_CH_NEVER           (1<<30)
-
-struct s3c24xx_dma_addr {
-       unsigned long           from;
-       unsigned long           to;
-};
-
-/* struct s3c24xx_dma_map
- *
- * this holds the mapping information for the channel selected
- * to be connected to the specified device
-*/
-
-struct s3c24xx_dma_map {
-       const char              *name;
-       struct s3c24xx_dma_addr  hw_addr;
-
-       unsigned long            channels[S3C2410_DMA_CHANNELS];
-       unsigned long            channels_rx[S3C2410_DMA_CHANNELS];
-};
-
-struct s3c24xx_dma_selection {
-       struct s3c24xx_dma_map  *map;
-       unsigned long            map_size;
-       unsigned long            dcon_mask;
-
-       void    (*select)(struct s3c2410_dma_chan *chan,
-                         struct s3c24xx_dma_map *map);
-
-       void    (*direction)(struct s3c2410_dma_chan *chan,
-                            struct s3c24xx_dma_map *map,
-                            enum s3c2410_dmasrc dir);
-};
-
-extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
-
-/* struct s3c24xx_dma_order_ch
- *
- * channel map for one of the `enum dma_ch` dma channels. the list
- * entry contains a set of low-level channel numbers, orred with
- * DMA_CH_VALID, which are checked in the order in the array.
-*/
-
-struct s3c24xx_dma_order_ch {
-       unsigned int    list[S3C2410_DMA_CHANNELS];     /* list of channels */
-       unsigned int    flags;                          /* flags */
-};
-
-/* struct s3c24xx_dma_order
- *
- * information provided by either the core or the board to give the
- * dma system a hint on how to allocate channels
-*/
-
-struct s3c24xx_dma_order {
-       struct s3c24xx_dma_order_ch     channels[DMACH_MAX];
-};
-
-extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
-
-/* DMA init code, called from the cpu support code */
-
-extern int s3c2410_dma_init(void);
-
-extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
-                           unsigned int stride);
diff --git a/include/asm-arm/plat-s3c24xx/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
deleted file mode 100644 (file)
index 45746a9..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/irq.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU IRQ 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.
-*/
-
-#define irqdbf(x...)
-#define irqdbf2(x...)
-
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
-/* these are exported for arch/arm/mach-* usage */
-extern struct irq_chip s3c_irq_level_chip;
-extern struct irq_chip s3c_irq_chip;
-
-static inline void
-s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
-               int subcheck)
-{
-       unsigned long mask;
-       unsigned long submask;
-
-       submask = __raw_readl(S3C2410_INTSUBMSK);
-       mask = __raw_readl(S3C2410_INTMSK);
-
-       submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
-
-       /* check to see if we need to mask the parent IRQ */
-
-       if ((submask  & subcheck) == subcheck) {
-               __raw_writel(mask | parentbit, S3C2410_INTMSK);
-       }
-
-       /* write back masks */
-       __raw_writel(submask, S3C2410_INTSUBMSK);
-
-}
-
-static inline void
-s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
-{
-       unsigned long mask;
-       unsigned long submask;
-
-       submask = __raw_readl(S3C2410_INTSUBMSK);
-       mask = __raw_readl(S3C2410_INTMSK);
-
-       submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
-       mask &= ~parentbit;
-
-       /* write back masks */
-       __raw_writel(submask, S3C2410_INTSUBMSK);
-       __raw_writel(mask, S3C2410_INTMSK);
-}
-
-
-static inline void
-s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-       unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-       s3c_irqsub_mask(irqno, parentmask, group);
-
-       __raw_writel(bit, S3C2410_SUBSRCPND);
-
-       /* only ack parent if we've got all the irqs (seems we must
-        * ack, all and hope that the irq system retriggers ok when
-        * the interrupt goes off again)
-        */
-
-       if (1) {
-               __raw_writel(parentmask, S3C2410_SRCPND);
-               __raw_writel(parentmask, S3C2410_INTPND);
-       }
-}
-
-static inline void
-s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
-{
-       unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
-
-       __raw_writel(bit, S3C2410_SUBSRCPND);
-
-       /* only ack parent if we've got all the irqs (seems we must
-        * ack, all and hope that the irq system retriggers ok when
-        * the interrupt goes off again)
-        */
-
-       if (1) {
-               __raw_writel(parentmask, S3C2410_SRCPND);
-               __raw_writel(parentmask, S3C2410_INTPND);
-       }
-}
-
-/* exported for use in arch/arm/mach-s3c2410 */
-
-#ifdef CONFIG_PM
-extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
-#else
-#define s3c_irq_wake NULL
-#endif
-
-extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/include/asm-arm/plat-s3c24xx/pm.h b/include/asm-arm/plat-s3c24xx/pm.h
deleted file mode 100644 (file)
index cc62366..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/pm.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.
-*/
-
-/* s3c2410_pm_init
- *
- * called from board at initialisation time to setup the power
- * management
-*/
-
-#ifdef CONFIG_PM
-
-extern __init int s3c2410_pm_init(void);
-
-#else
-
-static inline int s3c2410_pm_init(void)
-{
-       return 0;
-}
-#endif
-
-/* configuration for the IRQ mask over sleep */
-extern unsigned long s3c_irqwake_intmask;
-extern unsigned long s3c_irqwake_eintmask;
-
-/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
-extern unsigned long s3c_irqwake_intallow;
-extern unsigned long s3c_irqwake_eintallow;
-
-/* per-cpu sleep functions */
-
-extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
-
-/* Flags for PM Control */
-
-extern unsigned long s3c_pm_flags;
-
-/* from sleep.S */
-
-extern int  s3c2410_cpu_save(unsigned long *saveblk);
-extern void s3c2410_cpu_suspend(void);
-extern void s3c2410_cpu_resume(void);
-
-extern unsigned long s3c2410_sleep_save_phys;
-
-/* sleep save info */
-
-struct sleep_save {
-       void __iomem    *reg;
-       unsigned long   val;
-};
-
-#define SAVE_ITEM(x) \
-       { .reg = (x) }
-
-extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
-extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
-
-#ifdef CONFIG_PM
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2400.h b/include/asm-arm/plat-s3c24xx/s3c2400.h
deleted file mode 100644 (file)
index 3a5a168..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2400 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:
- *     09-Fev-2006 LCVR  First version, based on s3c2410.h
-*/
-
-#ifdef CONFIG_CPU_S3C2400
-
-extern  int s3c2400_init(void);
-
-extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2400_init_clocks(int xtal);
-
-#else
-#define s3c2400_init_clocks NULL
-#define s3c2400_init_uarts NULL
-#define s3c2400_map_io NULL
-#define s3c2400_init NULL
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2410.h b/include/asm-arm/plat-s3c24xx/s3c2410.h
deleted file mode 100644 (file)
index 3cd1ec6..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 machine directory
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#ifdef CONFIG_CPU_S3C2410
-
-extern  int s3c2410_init(void);
-
-extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2410_init_clocks(int xtal);
-
-#else
-#define s3c2410_init_clocks NULL
-#define s3c2410_init_uarts NULL
-#define s3c2410_map_io NULL
-#define s3c2410_init NULL
-#endif
-
-extern int s3c2410_baseclk_add(void);
diff --git a/include/asm-arm/plat-s3c24xx/s3c2412.h b/include/asm-arm/plat-s3c24xx/s3c2412.h
deleted file mode 100644 (file)
index 3ec9768..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2412 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2412
-
-extern  int s3c2412_init(void);
-
-extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2412_init_clocks(int xtal);
-
-extern  int s3c2412_baseclk_add(void);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2440.h b/include/asm-arm/plat-s3c24xx/s3c2440.h
deleted file mode 100644 (file)
index 107853b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
- *
- * Copyright (c) 2004-2005 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-#else
-#define s3c2440_init NULL
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2442.h b/include/asm-arm/plat-s3c24xx/s3c2442.h
deleted file mode 100644 (file)
index 451a23a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2442 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-#else
-#define s3c2442_init NULL
-#endif
diff --git a/include/asm-arm/plat-s3c24xx/s3c2443.h b/include/asm-arm/plat-s3c24xx/s3c2443.h
deleted file mode 100644 (file)
index 11d83b5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2443 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.
-*/
-
-#ifdef CONFIG_CPU_S3C2443
-
-struct s3c2410_uartcfg;
-
-extern  int s3c2443_init(void);
-
-extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
-
-extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c2443_init_clocks(int xtal);
-
-extern  int s3c2443_baseclk_add(void);
-
-#else
-#define s3c2443_init_clocks NULL
-#define s3c2443_init_uarts NULL
-#define s3c2443_map_io NULL
-#define s3c2443_init NULL
-#endif
diff --git a/include/asm-cris/a.out.h b/include/asm-cris/a.out.h
deleted file mode 100644 (file)
index c82e9f9..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __CRIS_A_OUT_H__
-#define __CRIS_A_OUT_H__
-
-/* we don't support a.out binaries on Linux/CRIS anyway, so this is
- * not really used but still needed because binfmt_elf.c for some reason
- * wants to know about a.out even if there is no interpreter available...
- */
-
-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)
-
-#endif
index 001f64ad11e8c5e002003427b6833c402a3f26d7..f0d17fbc81bae8a53c33ae6473661cfe7ea108b7 100644 (file)
@@ -88,6 +88,6 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif
index 9fb946bb7dc98c26cc8b43b2e3686647238e0d86..7279ec07d62e32007f91a01bfe58a20014283a4d 100644 (file)
@@ -137,6 +137,6 @@ do {                                                                                        \
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif
index 839a2fbffa0f34c8c428b6a5793a407749e69ac8..6c61c05b2e0cfe36844b1d7466879b9f4c4f4f69 100644 (file)
@@ -13,7 +13,7 @@
 #define _ASM_UNALIGNED_H
 
 #include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/be_struct.h>
 #include <linux/unaligned/generic.h>
 
 #define get_unaligned  __get_unaligned_be
index edc6ba82e090961a841cd37b54cb6abc0311b4d7..0f6dabd4b5175488081fc8395a30b9a5d5e5f217 100644 (file)
@@ -22,7 +22,7 @@ struct bug_entry {
 
 #ifndef HAVE_ARCH_BUG
 #define BUG() do { \
-       printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
+       printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
        panic("BUG!"); \
 } while (0)
 #endif
index 0f99ad38b012f93ef10ccb5b0f9105b4e7f8daab..81797ec9ab2917413ba28d166adb267726c8f177 100644 (file)
@@ -35,11 +35,17 @@ struct module;
  * @label: for diagnostics
  * @dev: optional device providing the GPIOs
  * @owner: helps prevent removal of modules exporting active GPIOs
+ * @request: optional hook for chip-specific activation, such as
+ *     enabling module power and clock; may sleep
+ * @free: optional hook for chip-specific deactivation, such as
+ *     disabling module power and clock; may sleep
  * @direction_input: configures signal "offset" as input, or returns error
  * @get: returns value for signal "offset"; for output signals this
  *     returns either the value actually sensed, or zero
  * @direction_output: configures signal "offset" as output, or returns error
  * @set: assigns output value for signal "offset"
+ * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
+ *     implementation may not sleep
  * @dbg_show: optional routine to show contents in debugfs; default code
  *     will be used when this is omitted, but custom code can show extra
  *     state (such as pullup/pulldown configuration).
@@ -61,10 +67,15 @@ struct module;
  * is calculated by subtracting @base from the gpio number.
  */
 struct gpio_chip {
-       char                    *label;
+       const char              *label;
        struct device           *dev;
        struct module           *owner;
 
+       int                     (*request)(struct gpio_chip *chip,
+                                               unsigned offset);
+       void                    (*free)(struct gpio_chip *chip,
+                                               unsigned offset);
+
        int                     (*direction_input)(struct gpio_chip *chip,
                                                unsigned offset);
        int                     (*get)(struct gpio_chip *chip,
@@ -73,6 +84,10 @@ struct gpio_chip {
                                                unsigned offset, int value);
        void                    (*set)(struct gpio_chip *chip,
                                                unsigned offset, int value);
+
+       int                     (*to_irq)(struct gpio_chip *chip,
+                                               unsigned offset);
+
        void                    (*dbg_show)(struct seq_file *s,
                                                struct gpio_chip *chip);
        int                     base;
@@ -112,6 +127,7 @@ extern void __gpio_set_value(unsigned gpio, int value);
 
 extern int __gpio_cansleep(unsigned gpio);
 
+extern int __gpio_to_irq(unsigned gpio);
 
 #ifdef CONFIG_GPIO_SYSFS
 
index 1d01043e797d94180f79ef026e5abafedc94bb1b..6129d6802149f89e269f957fa62e181d819fac60 100644 (file)
@@ -6,33 +6,64 @@
 typedef __kernel_fsid_t        fsid_t;
 #endif
 
+/*
+ * Most 64-bit platforms use 'long', while most 32-bit platforms use '__u32'.
+ * Yes, they differ in signedness as well as size.
+ * Special cases can override it for themselves -- except for S390x, which
+ * is just a little too special for us. And MIPS, which I'm not touching
+ * with a 10' pole.
+ */
+#ifndef __statfs_word
+#if BITS_PER_LONG == 64
+#define __statfs_word long
+#else
+#define __statfs_word __u32
+#endif
+#endif
+
 struct statfs {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u32 f_blocks;
-       __u32 f_bfree;
-       __u32 f_bavail;
-       __u32 f_files;
-       __u32 f_ffree;
+       __statfs_word f_type;
+       __statfs_word f_bsize;
+       __statfs_word f_blocks;
+       __statfs_word f_bfree;
+       __statfs_word f_bavail;
+       __statfs_word f_files;
+       __statfs_word f_ffree;
        __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
+       __statfs_word f_namelen;
+       __statfs_word f_frsize;
+       __statfs_word f_spare[5];
 };
 
+/*
+ * ARM needs to avoid the 32-bit padding at the end, for consistency
+ * between EABI and OABI 
+ */
+#ifndef ARCH_PACK_STATFS64
+#define ARCH_PACK_STATFS64
+#endif
+
 struct statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
+       __statfs_word f_type;
+       __statfs_word f_bsize;
        __u64 f_blocks;
        __u64 f_bfree;
        __u64 f_bavail;
        __u64 f_files;
        __u64 f_ffree;
        __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-};
+       __statfs_word f_namelen;
+       __statfs_word f_frsize;
+       __statfs_word f_spare[5];
+} ARCH_PACK_STATFS64;
+
+/* 
+ * IA64 and x86_64 need to avoid the 32-bit padding at the end,
+ * to be compatible with the i386 ABI
+ */
+#ifndef ARCH_PACK_COMPAT_STATFS64
+#define ARCH_PACK_COMPAT_STATFS64
+#endif
 
 struct compat_statfs64 {
        __u32 f_type;
@@ -46,6 +77,6 @@ struct compat_statfs64 {
        __u32 f_namelen;
        __u32 f_frsize;
        __u32 f_spare[5];
-};
+} ARCH_PACK_COMPAT_STATFS64;
 
 #endif
index 7440a0dceddba276b59199d14e64a1ee2f232b36..74c5faf26c053a137768d5f4224d466945bc3253 100644 (file)
        CPU_DISCARD(init.data)                                          \
        CPU_DISCARD(init.rodata)                                        \
        MEM_DISCARD(init.data)                                          \
-       MEM_DISCARD(init.rodata)
+       MEM_DISCARD(init.rodata)                                        \
+       /* implement dynamic printk debug */                            \
+       VMLINUX_SYMBOL(__start___verbose_strings) = .;                  \
+       *(__verbose_strings)                                            \
+       VMLINUX_SYMBOL(__stop___verbose_strings) = .;                   \
+       . = ALIGN(8);                                                   \
+       VMLINUX_SYMBOL(__start___verbose) = .;                          \
+       *(__verbose)                                                    \
+       VMLINUX_SYMBOL(__stop___verbose) = .;
 
 #define INIT_TEXT                                                      \
        *(.init.text)                                                   \
diff --git a/include/asm-h8300/timer.h b/include/asm-h8300/timer.h
new file mode 100644 (file)
index 0000000..def8046
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __H8300_TIMER_H
+#define __H8300_TIMER_H
+
+void h8300_timer_tick(void);
+void h8300_timer_setup(void);
+void h8300_gettod(unsigned int *year, unsigned int *mon, unsigned int *day,
+                  unsigned int *hour, unsigned int *min, unsigned int *sec);
+
+#define TIMER_FREQ (CONFIG_CPU_CLOCK*10000) /* Timer input freq. */
+
+#define calc_param(cnt, div, rate, limit)                      \
+do {                                                           \
+       cnt = TIMER_FREQ / HZ;                                  \
+       for (div = 0; div < ARRAY_SIZE(divide_rate); div++) {   \
+               if (rate[div] == 0)                             \
+                       continue;                               \
+               if ((cnt / rate[div]) > limit)                  \
+                       break;                                  \
+       }                                                       \
+       if (div == ARRAY_SIZE(divide_rate))                     \
+               panic("Timer counter overflow");                \
+       cnt /= divide_rate[div];                                \
+} while(0)
+
+#endif
diff --git a/include/asm-m32r/a.out.h b/include/asm-m32r/a.out.h
deleted file mode 100644 (file)
index ab150f5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_M32R_A_OUT_H
-#define _ASM_M32R_A_OUT_H
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* _ASM_M32R_A_OUT_H */
index 67bcd77494a5697942ae2363f19478bdc7fd2197..0cc34c94bf2bf26a087a73a11ea32302d48eebf6 100644 (file)
@@ -129,6 +129,6 @@ typedef elf_fpreg_t elf_fpregset_t;
    intent than poking at uname or /proc/cpuinfo.  */
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif  /* _ASM_M32R__ELF_H */
index ecf007df77437cb14396bcd55ad24e9439677d48..1412b4ab202f1e753324e734d42dc92bbb635e7e 100644 (file)
@@ -39,7 +39,6 @@ extern int atari_dont_touch_floppy_select;
 #define MACH_IS_TT     ((atari_mch_cookie >> 16) == ATARI_MCH_TT)
 #define MACH_IS_FALCON ((atari_mch_cookie >> 16) == ATARI_MCH_FALCON)
 #define MACH_IS_MEDUSA (atari_mch_type == ATARI_MACH_MEDUSA)
-#define MACH_IS_HADES  (atari_mch_type == ATARI_MACH_HADES)
 #define MACH_IS_AB40   (atari_mch_type == ATARI_MACH_AB40)
 
 /* values for atari_switches */
index 91f7944333d49d6ce2f861036cddf0492ce76b9c..26f505488c1197dbe004cc6486d8c41c7285ab65 100644 (file)
@@ -74,6 +74,14 @@ extern void dma_sync_single_for_device(struct device *, dma_addr_t, size_t,
 extern void dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
                                   enum dma_data_direction);
 
+static inline void dma_sync_single_range_for_device(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+       /* just sync everything for now */
+       dma_sync_single_for_device(dev, dma_handle, offset + size, direction);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
                                           size_t size, enum dma_data_direction dir)
 {
@@ -84,6 +92,14 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *s
 {
 }
 
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+       /* just sync everything for now */
+       dma_sync_single_for_cpu(dev, dma_handle, offset + size, direction);
+}
+
 static inline int dma_mapping_error(struct device *dev, dma_addr_t handle)
 {
        return 0;
index d0c9e61e57b448e5aca2f4955467c72d2b3a7758..4240fbc946f86699b4211398c6ced340c9c4a0a8 100644 (file)
 extern int request_dma(unsigned int dmanr, const char * device_id);    /* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);      /* release it again */
 
-#ifdef CONFIG_PCI
-extern int isa_dma_bridge_buggy;
-#else
 #define isa_dma_bridge_buggy    (0)
-#endif
 
 #endif /* _M68K_DMA_H */
index 14ea42152b9785c75925414b7a971212e122604e..0b0f49eb876b11db0ce7eb6cd1703be2657fbd54 100644 (file)
@@ -114,6 +114,6 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 
 #endif
index f8f6b185d793b16d7dfe8781098524ea991ee762..5202f5a5b420acbeaf50868cd604768bbf6f9444 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 /* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
+#if defined(MACH_ATARI_ONLY)
        /* block out HSYNC on the atari */
 #define ALLOWINT       (~0x400)
 #define        MAX_NOINT_IPL   3
index 657187f0c7c2f0ef834817e622c330727d2bcd82..9e673e3bd4344ae2947b752deb50e0a58db8bb59 100644 (file)
@@ -7,15 +7,12 @@
  *            - added skeleton for GG-II and Amiga PCMCIA
  * 2/3/01 RZ: - moved a few more defs into raw_io.h
  *
- * inX/outX/readX/writeX should not be used by any driver unless it does
- * ISA or PCI access. Other drivers should use function defined in raw_io.h
+ * inX/outX should not be used by any driver unless it does
+ * ISA access. Other drivers should use function defined in raw_io.h
  * or define its own macros on top of these.
  *
- *    inX(),outX()              are for PCI and ISA I/O
- *    readX(),writeX()          are for PCI memory
+ *    inX(),outX()              are for ISA I/O
  *    isa_readX(),isa_writeX()  are for ISA memory
- *
- * moved mem{cpy,set}_*io inside CONFIG_PCI
  */
 
 #ifndef _IO_H
@@ -256,10 +253,7 @@ static inline void isa_delay(void)
        (ISA_SEX ? raw_outsl(isa_itl(port), (u32 *)(buf), (nr)) :  \
                   raw_outsw_swapw(isa_itw(port), (u16 *)(buf), (nr)<<1))
 
-#endif  /* CONFIG_ISA */
-
 
-#if defined(CONFIG_ISA) && !defined(CONFIG_PCI)
 #define inb     isa_inb
 #define inb_p   isa_inb_p
 #define outb    isa_outb
@@ -282,55 +276,9 @@ static inline void isa_delay(void)
 #define readw   isa_readw
 #define writeb  isa_writeb
 #define writew  isa_writew
-#endif /* CONFIG_ISA */
-
-#if defined(CONFIG_PCI)
-
-#define readl(addr)      in_le32(addr)
-#define writel(val,addr) out_le32((addr),(val))
-
-/* those can be defined for both ISA and PCI - it won't work though */
-#define readb(addr)       in_8(addr)
-#define readw(addr)       in_le16(addr)
-#define writeb(val,addr)  out_8((addr),(val))
-#define writew(val,addr)  out_le16((addr),(val))
 
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
+#else  /* CONFIG_ISA */
 
-#ifndef CONFIG_ISA
-#define inb(port)      in_8(port)
-#define outb(val,port) out_8((port),(val))
-#define inw(port)      in_le16(port)
-#define outw(val,port) out_le16((port),(val))
-#define inl(port)      in_le32(port)
-#define outl(val,port) out_le32((port),(val))
-
-#else
-/*
- * kernel with both ISA and PCI compiled in, those have
- * conflicting defs for in/out. Simply consider port < 1024
- * ISA and everything else PCI. read,write not defined
- * in this case
- */
-#define inb(port) ((port)<1024 ? isa_inb(port) : in_8(port))
-#define inb_p(port) ((port)<1024 ? isa_inb_p(port) : in_8(port))
-#define inw(port) ((port)<1024 ? isa_inw(port) : in_le16(port))
-#define inw_p(port) ((port)<1024 ? isa_inw_p(port) : in_le16(port))
-#define inl(port) ((port)<1024 ? isa_inl(port) : in_le32(port))
-#define inl_p(port) ((port)<1024 ? isa_inl_p(port) : in_le32(port))
-
-#define outb(val,port) ((port)<1024 ? isa_outb((val),(port)) : out_8((port),(val)))
-#define outb_p(val,port) ((port)<1024 ? isa_outb_p((val),(port)) : out_8((port),(val)))
-#define outw(val,port) ((port)<1024 ? isa_outw((val),(port)) : out_le16((port),(val)))
-#define outw_p(val,port) ((port)<1024 ? isa_outw_p((val),(port)) : out_le16((port),(val)))
-#define outl(val,port) ((port)<1024 ? isa_outl((val),(port)) : out_le32((port),(val)))
-#define outl_p(val,port) ((port)<1024 ? isa_outl_p((val),(port)) : out_le32((port),(val)))
-#endif
-#endif /* CONFIG_PCI */
-
-#if !defined(CONFIG_ISA) && !defined(CONFIG_PCI)
 /*
  * We need to define dummy functions for GENERIC_IOMAP support.
  */
@@ -357,11 +305,11 @@ static inline void isa_delay(void)
 #define writeb(val,addr) out_8((addr),(val))
 #define readw(addr)      in_le16(addr)
 #define writew(val,addr) out_le16((addr),(val))
-#endif
-#if !defined(CONFIG_PCI)
+
+#endif /* CONFIG_ISA */
+
 #define readl(addr)      in_le32(addr)
 #define writel(val,addr) out_le32((addr),(val))
-#endif
 
 #define mmiowb()
 
index 678cb0b52314dac16a1cfb9fc9dbd44b5eeeed16..4ad0aea48ab4e9d2b5c96a278d09c2f3eadb3ce5 100644 (file)
@@ -1,52 +1,7 @@
 #ifndef _ASM_M68K_PCI_H
 #define _ASM_M68K_PCI_H
 
-/*
- * asm-m68k/pci_m68k.h - m68k specific PCI declarations.
- *
- * Written by Wout Klaren.
- */
-
-#include <asm/scatterlist.h>
-
-struct pci_ops;
-
-/*
- * Structure with hardware dependent information and functions of the
- * PCI bus.
- */
-
-struct pci_bus_info
-{
-       /*
-        * Resources of the PCI bus.
-        */
-
-       struct resource mem_space;
-       struct resource io_space;
-
-       /*
-        * System dependent functions.
-        */
-
-       struct pci_ops *m68k_pci_ops;
-
-       void (*fixup)(int pci_modify);
-       void (*conf_device)(struct pci_dev *dev);
-};
-
-#define pcibios_assign_all_busses()    0
-#define pcibios_scan_all_fns(a, b)     0
-
-static inline void pcibios_set_master(struct pci_dev *dev)
-{
-       /* No special bus mastering setup handling */
-}
-
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
-       /* We don't do dynamic PCI IRQ allocation */
-}
+#include <asm-generic/pci-dma-compat.h>
 
 /* The PCI address space does equal the physical memory
  * address space.  The networking and block device layers use
index dea32fbc7e51c1c5bc995a1aa69ab57f6b1cf6f5..22ab05c9c52b707a961e456430bd13f6153224f7 100644 (file)
@@ -40,15 +40,9 @@ static inline void *phys_to_virt(unsigned long address)
 
 /*
  * IO bus memory addresses are 1:1 with the physical address,
- * except on the PCI bus of the Hades.
  */
-#ifdef CONFIG_HADES
-#define virt_to_bus(a) (virt_to_phys(a) + (MACH_IS_HADES ? 0x80000000 : 0))
-#define bus_to_virt(a) (phys_to_virt((a) - (MACH_IS_HADES ? 0x80000000 : 0)))
-#else
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
-#endif
 
 #endif
 #endif
diff --git a/include/asm-mips/cevt-r4k.h b/include/asm-mips/cevt-r4k.h
deleted file mode 100644 (file)
index fa4328f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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) 2008 Kevin D. Kissell
- */
-
-/*
- * Definitions used for common event timer implementation
- * for MIPS 4K-type processors and their MIPS MT variants.
- * Avoids unsightly extern declarations in C files.
- */
-#ifndef __ASM_CEVT_R4K_H
-#define __ASM_CEVT_R4K_H
-
-DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
-
-void mips_event_handler(struct clock_event_device *dev);
-int c0_compare_int_usable(void);
-void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *);
-irqreturn_t c0_compare_interrupt(int, void *);
-
-extern struct irqaction c0_compare_irqaction;
-extern int cp0_timer_irq_installed;
-
-/*
- * Possibly handle a performance counter interrupt.
- * Return true if the timer interrupt should not be checked
- */
-
-static inline int handle_perf_irq(int r2)
-{
-       /*
-        * The performance counter overflow interrupt may be shared with the
-        * timer interrupt (cp0_perfcount_irq < 0). If it is and a
-        * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
-        * and we can't reliably determine if a counter interrupt has also
-        * happened (!r2) then don't check for a timer interrupt.
-        */
-       return (cp0_perfcount_irq < 0) &&
-               perf_irq() == IRQ_HANDLED &&
-               !r2;
-}
-
-#endif /* __ASM_CEVT_R4K_H */
index 256a70466ca4385ca9478303131e29c88129c4b6..bf09f8bb392eef17bf41441050b5adb6e9920d0b 100644 (file)
@@ -141,7 +141,7 @@ do {                                                \
 #define ELF_PLATFORM  (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
 #endif
 
 #endif /* _ASM_ELF_H */
diff --git a/include/asm-parisc/a.out.h b/include/asm-parisc/a.out.h
deleted file mode 100644 (file)
index eb04e34..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __PARISC_A_OUT_H__
-#define __PARISC_A_OUT_H__
-
-struct exec
-{
-  unsigned int 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)
-
-#endif /* __A_OUT_GNU_H__ */
index d0a4a82628181578a943ae082c60ae8b63959411..7fa675799e6d2cad21304698f7dec833a12224e7 100644 (file)
@@ -236,7 +236,7 @@ typedef unsigned long elf_greg_t;
 
 #define ELF_PLATFORM  ("PARISC\0")
 
-#define SET_PERSONALITY(ex, ibcs2) \
+#define SET_PERSONALITY(ex) \
        current->personality = PER_LINUX; \
        current->thread.map_base = DEFAULT_MAP_BASE; \
        current->thread.task_size = DEFAULT_TASK_SIZE \
index 1d2b8130b23d61ee1f1be7c9430e58f682a847ef..324bea905dc6a90c760f32306f78db51600c219e 100644 (file)
@@ -1,58 +1,7 @@
 #ifndef _PARISC_STATFS_H
 #define _PARISC_STATFS_H
 
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t        fsid_t;
-
-#endif
-
-/*
- * It appears that PARISC could be 64 _or_ 32 bit.
- * 64-bit fields must be explicitly 64-bit in statfs64.
- */
-struct statfs {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct statfs64 {
-       long f_type;
-       long f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-};
+#define __statfs_word long
+#include <asm-generic/statfs.h>
 
 #endif
index 23d6893e8617d6ccfa0deb9819587d6f3d1452f6..d0da9d7c53716fc294fd1d1c26759d03da784469 100644 (file)
@@ -86,7 +86,7 @@ extern long elf_aux_hwcap;
 extern char * elf_aux_platform;
 #define ELF_PLATFORM (elf_aux_platform)
 
-#define SET_PERSONALITY(ex, ibcs2) do { } while (0)
+#define SET_PERSONALITY(ex) do { } while (0)
 
 extern unsigned long vsyscall_ehdr;
 extern unsigned long vsyscall_end;
index d3b90b7ac3e9820921272b12642f193803b142f5..af9463cd8ce51f936af61c14d8ce217bf3eb5eec 100644 (file)
@@ -5,7 +5,7 @@
 extern long elf_aux_hwcap;
 #define ELF_HWCAP (elf_aux_hwcap)
 
-#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+#define SET_PERSONALITY(ex) do ; while(0)
 
 #define ELF_EXEC_PAGESIZE 4096
 
index 3b2d5224a7e166947be5ce2baa9ae720e696a7e3..6e8a9195e95266ff55276e7de633782e970a646b 100644 (file)
@@ -114,6 +114,6 @@ extern long elf_aux_hwcap;
 
 #define ELF_PLATFORM "x86_64"
 
-#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+#define SET_PERSONALITY(ex) do ; while(0)
 
 #endif
index ebc307817e98cc2c7999c883066d6b06134f6a16..f06adac7938c746f87b02939205b3d3370c100a0 100644 (file)
@@ -351,20 +351,16 @@ static inline void set_system_intr_gate(unsigned int n, void *addr)
        _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
 }
 
-static inline void set_trap_gate(unsigned int n, void *addr)
+static inline void set_system_trap_gate(unsigned int n, void *addr)
 {
        BUG_ON((unsigned)n > 0xFF);
-       _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+       _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
 }
 
-static inline void set_system_gate(unsigned int n, void *addr)
+static inline void set_trap_gate(unsigned int n, void *addr)
 {
        BUG_ON((unsigned)n > 0xFF);
-#ifdef CONFIG_X86_32
-       _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
-#else
-       _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
-#endif
+       _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
 }
 
 static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
@@ -379,7 +375,7 @@ static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
        _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
 }
 
-static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist)
 {
        BUG_ON((unsigned)n > 0xFF);
        _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
index 5c4745bec9061c0febdfb21ab4534c89c8f354f9..26bc15f01e78a3faa7d7b4b540ab57741e3d94da 100644 (file)
@@ -186,7 +186,7 @@ do {                                                        \
        set_fs(USER_DS);                                \
 } while (0)
 
-#define COMPAT_SET_PERSONALITY(ex, ibcs2)              \
+#define COMPAT_SET_PERSONALITY(ex)                     \
 do {                                                   \
        if (test_thread_flag(TIF_IA32))                 \
                clear_thread_flag(TIF_ABI_PENDING);     \
@@ -267,7 +267,7 @@ extern int force_personality32;
    For the moment, we have only optimizations for the Intel generations,
    but that could change... */
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
+#define SET_PERSONALITY(ex) set_personality_64bit()
 
 /*
  * An executable for which elf_read_implies_exec() returns TRUE will
index bd2c44d1f7ac356f6e09a277763b9d1d585454c2..aae50c2fb303db35d3bab0f2cfdd1a854f1b4fb2 100644 (file)
@@ -171,7 +171,7 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
                        int new_apicid = cpu_to_logical_apicid(cpu);
                        if (apicid_cluster(apicid) !=
                                        apicid_cluster(new_apicid)){
-                               printk ("%s: Not a valid mask!\n",__FUNCTION__);
+                               printk ("%s: Not a valid mask!\n", __func__);
 #if defined CONFIG_ES7000_CLUSTERED_APIC
                                return 0xFF;
 #else
index 7b5c889d8e7d52bab6e7e0bd233c519940addc76..ed5a3caae1411017c415e11505d081d5a6374768 100644 (file)
@@ -5,6 +5,7 @@
 
 extern int parse_unisys_oem (char *oemptr);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
+extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr);
 extern void setup_unisys(void);
 
 #ifndef CONFIG_X86_GENERICARCH
index 784e3e759866cc0025b4dd4e9af77aeedddcdd1d..8844002da0e05df5e421846603c9b8a017bdd0a6 100644 (file)
@@ -94,10 +94,10 @@ enum fixed_addresses {
         * can have a single pgd entry and a single pte table:
         */
 #define NR_FIX_BTMAPS          64
-#define FIX_BTMAPS_NESTING     4
+#define FIX_BTMAPS_SLOTS       4
        FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
                        (__end_of_permanent_fixed_addresses & 255),
-       FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+       FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
        FIX_WP_TEST,
 #ifdef CONFIG_ACPI
        FIX_ACPI_BEGIN,
index dafb24bc0424efd4b94ed18ae2ce5e1dcf4d0260..dab4751d13070491e66038af1264db9880eda7a2 100644 (file)
@@ -49,6 +49,7 @@ enum fixed_addresses {
 #ifdef CONFIG_PARAVIRT
        FIX_PARAVIRT_BOOTMAP,
 #endif
+       __end_of_permanent_fixed_addresses,
 #ifdef CONFIG_ACPI
        FIX_ACPI_BEGIN,
        FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
@@ -56,19 +57,18 @@ enum fixed_addresses {
 #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
        FIX_OHCI1394_BASE,
 #endif
-       __end_of_permanent_fixed_addresses,
        /*
         * 256 temporary boot-time mappings, used by early_ioremap(),
         * before ioremap() is functional.
         *
-        * We round it up to the next 512 pages boundary so that we
+        * We round it up to the next 256 pages boundary so that we
         * can have a single pgd entry and a single pte table:
         */
 #define NR_FIX_BTMAPS          64
-#define FIX_BTMAPS_NESTING     4
-       FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
-                       (__end_of_permanent_fixed_addresses & 511),
-       FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+#define FIX_BTMAPS_SLOTS       4
+       FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+                       (__end_of_permanent_fixed_addresses & 255),
+       FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
        __end_of_fixed_addresses
 };
 
index 72b7719523bfa9f26efc333ed0efb160ad37d997..a233f835e0b52a49ed02077409a7e52de22aa9a0 100644 (file)
@@ -5,20 +5,6 @@
 
 #include <linux/compiler.h>
 
-/*
- * early_ioremap() and early_iounmap() are for temporary early boot-time
- * mappings, before the real ioremap() is functional.
- * A boot-time mapping is currently limited to at most 16 pages.
- */
-#ifndef __ASSEMBLY__
-extern void early_ioremap_init(void);
-extern void early_ioremap_clear(void);
-extern void early_ioremap_reset(void);
-extern void *early_ioremap(unsigned long offset, unsigned long size);
-extern void early_iounmap(void *addr, unsigned long size);
-extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
-#endif
-
 #define build_mmio_read(name, size, type, reg, barrier) \
 static inline type name(const volatile void __iomem *addr) \
 { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
@@ -97,6 +83,7 @@ extern void early_ioremap_init(void);
 extern void early_ioremap_clear(void);
 extern void early_ioremap_reset(void);
 extern void *early_ioremap(unsigned long offset, unsigned long size);
+extern void *early_memremap(unsigned long offset, unsigned long size);
 extern void early_iounmap(void *addr, unsigned long size);
 extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
 
index 64429e9431a8aef1089c25c8c00c18b64cd93663..ee6e086b7dfec848998c241a21b6b3baca9be5f4 100644 (file)
@@ -165,9 +165,6 @@ static inline void *phys_to_virt(unsigned long address)
 
 #include <asm-generic/iomap.h>
 
-extern void *early_ioremap(unsigned long addr, unsigned long size);
-extern void early_iounmap(void *addr, unsigned long size);
-
 /*
  * This one maps high address device memory and turns off caching for that area.
  * it's useful if some control registers are in such an area and write combining
index 33660351239968bd22205ed9e4b45e674bc67e96..06752a649044d2029c4c555f006635ff41d6b9f5 100644 (file)
 #define TCSETS2                _IOW('T', 0x2B, struct termios2)
 #define TCSETSW2       _IOW('T', 0x2C, struct termios2)
 #define TCSETSF2       _IOW('T', 0x2D, struct termios2)
+#define TIOCGRS485     0x542E
+#define TIOCSRS485     0x542F
 #define TIOCGPTN       _IOR('T', 0x30, unsigned int)
                                /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK     _IOW('T', 0x31, int)  /* Lock/unlock Pty */
+#define TCGETX         0x5432 /* SYS5 TCGETX compatibility */
+#define TCSETX         0x5433
+#define TCSETXF                0x5434
+#define TCSETXW                0x5435
 
 #define FIONCLEX       0x5450
 #define FIOCLEX                0x5451
index 546ad3110feaef59c2a607e98593d8e38f17b272..961e746da977d470092b9ab912cf1d3f2531a4b7 100644 (file)
@@ -8,7 +8,7 @@ extern int force_iommu, no_iommu;
 extern int iommu_detected;
 extern int dmar_disabled;
 
-extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len);
+extern unsigned long iommu_nr_pages(unsigned long addr, unsigned long len);
 
 #ifdef CONFIG_GART_IOMMU
 extern int gart_iommu_aperture;
index 424acb48cd61baf681f7d71fb6b4ad56e1cfc3ee..2bdab21f0898dedee3ad1bf495b73b7ae0d3f997 100644 (file)
@@ -166,27 +166,6 @@ static inline int raw_irqs_disabled(void)
        return raw_irqs_disabled_flags(flags);
 }
 
-/*
- * makes the traced hardirq state match with the machine state
- *
- * should be a rarely used function, only in places where its
- * otherwise impossible to know the irq state, like in traps.
- */
-static inline void trace_hardirqs_fixup_flags(unsigned long flags)
-{
-       if (raw_irqs_disabled_flags(flags))
-               trace_hardirqs_off();
-       else
-               trace_hardirqs_on();
-}
-
-static inline void trace_hardirqs_fixup(void)
-{
-       unsigned long flags = __raw_local_save_flags();
-
-       trace_hardirqs_fixup_flags(flags);
-}
-
 #else
 
 #ifdef CONFIG_X86_64
index 5ec3ad3e825c4dadfcbcff6b6f9c880f6ec02c7a..fbbab66ee9dfb9c8385e2ff40f92e245b887f924 100644 (file)
@@ -27,10 +27,9 @@ extern void printk_address(unsigned long address, int reliable);
 extern void die(const char *, struct pt_regs *,long);
 extern int __must_check __die(const char *, struct pt_regs *, long);
 extern void show_registers(struct pt_regs *regs);
-extern void __show_registers(struct pt_regs *, int all);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
                       unsigned long *sp, unsigned long bp);
-extern void __show_regs(struct pt_regs *regs);
+extern void __show_regs(struct pt_regs *regs, int all);
 extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
 extern void oops_end(unsigned long, struct pt_regs *, int signr);
index bd8407863c13127f1ed7ce1384fce4086e135022..8a0748d01036711c509e99d2d5121fbd81100380 100644 (file)
@@ -82,15 +82,6 @@ struct kprobe_ctlblk {
        struct prev_kprobe prev_kprobe;
 };
 
-/* 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->flags & X86_EFLAGS_IF)
-               local_irq_enable();
-}
-
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
                                    unsigned long val, void *data);
index 78e954db1e7f60066ea2cd232bf4d38a99821e57..ba0dd791fadf2d20560b5f16b3c6c0ab72e39789 100644 (file)
@@ -208,26 +208,4 @@ struct kvm_pit_channel_state {
 struct kvm_pit_state {
        struct kvm_pit_channel_state channels[3];
 };
-
-#define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
-#define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
-#define KVM_TRC_PEND_INTR        (KVM_TRC_HANDLER + 0x04)
-#define KVM_TRC_IO_READ          (KVM_TRC_HANDLER + 0x05)
-#define KVM_TRC_IO_WRITE         (KVM_TRC_HANDLER + 0x06)
-#define KVM_TRC_CR_READ          (KVM_TRC_HANDLER + 0x07)
-#define KVM_TRC_CR_WRITE         (KVM_TRC_HANDLER + 0x08)
-#define KVM_TRC_DR_READ          (KVM_TRC_HANDLER + 0x09)
-#define KVM_TRC_DR_WRITE         (KVM_TRC_HANDLER + 0x0A)
-#define KVM_TRC_MSR_READ         (KVM_TRC_HANDLER + 0x0B)
-#define KVM_TRC_MSR_WRITE        (KVM_TRC_HANDLER + 0x0C)
-#define KVM_TRC_CPUID            (KVM_TRC_HANDLER + 0x0D)
-#define KVM_TRC_INTR             (KVM_TRC_HANDLER + 0x0E)
-#define KVM_TRC_NMI              (KVM_TRC_HANDLER + 0x0F)
-#define KVM_TRC_VMMCALL          (KVM_TRC_HANDLER + 0x10)
-#define KVM_TRC_HLT              (KVM_TRC_HANDLER + 0x11)
-#define KVM_TRC_CLTS             (KVM_TRC_HANDLER + 0x12)
-#define KVM_TRC_LMSW             (KVM_TRC_HANDLER + 0x13)
-#define KVM_TRC_APIC_ACCESS      (KVM_TRC_HANDLER + 0x14)
-#define KVM_TRC_TDP_FAULT        (KVM_TRC_HANDLER + 0x15)
-
 #endif /* ASM_X86__KVM_H */
index 69794547f514f5f249b65acf55ba8d5fd5c12685..411fb8cfb24e6b4d856dc234b5fe37309fb3a3cb 100644 (file)
 #define KVM_PAGES_PER_HPAGE (KVM_HPAGE_SIZE / PAGE_SIZE)
 
 #define DE_VECTOR 0
+#define DB_VECTOR 1
+#define BP_VECTOR 3
+#define OF_VECTOR 4
+#define BR_VECTOR 5
 #define UD_VECTOR 6
 #define NM_VECTOR 7
 #define DF_VECTOR 8
@@ -65,6 +69,7 @@
 #define SS_VECTOR 12
 #define GP_VECTOR 13
 #define PF_VECTOR 14
+#define MF_VECTOR 16
 #define MC_VECTOR 18
 
 #define SELECTOR_TI_MASK (1 << 2)
@@ -89,7 +94,7 @@ extern struct list_head vm_list;
 struct kvm_vcpu;
 struct kvm;
 
-enum {
+enum kvm_reg {
        VCPU_REGS_RAX = 0,
        VCPU_REGS_RCX = 1,
        VCPU_REGS_RDX = 2,
@@ -108,6 +113,7 @@ enum {
        VCPU_REGS_R14 = 14,
        VCPU_REGS_R15 = 15,
 #endif
+       VCPU_REGS_RIP,
        NR_VCPU_REGS
 };
 
@@ -189,10 +195,20 @@ struct kvm_mmu_page {
                                    */
        int multimapped;         /* More than one parent_pte? */
        int root_count;          /* Currently serving as active root */
+       bool unsync;
+       bool unsync_children;
        union {
                u64 *parent_pte;               /* !multimapped */
                struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */
        };
+       DECLARE_BITMAP(unsync_child_bitmap, 512);
+};
+
+struct kvm_pv_mmu_op_buffer {
+       void *ptr;
+       unsigned len;
+       unsigned processed;
+       char buf[512] __aligned(sizeof(long));
 };
 
 /*
@@ -207,6 +223,9 @@ struct kvm_mmu {
        gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
        void (*prefetch_page)(struct kvm_vcpu *vcpu,
                              struct kvm_mmu_page *page);
+       int (*sync_page)(struct kvm_vcpu *vcpu,
+                        struct kvm_mmu_page *sp);
+       void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
        hpa_t root_hpa;
        int root_level;
        int shadow_root_level;
@@ -219,8 +238,13 @@ struct kvm_vcpu_arch {
        int interrupt_window_open;
        unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
        DECLARE_BITMAP(irq_pending, KVM_NR_INTERRUPTS);
-       unsigned long regs[NR_VCPU_REGS]; /* for rsp: vcpu_load_rsp_rip() */
-       unsigned long rip;      /* needs vcpu_load_rsp_rip() */
+       /*
+        * rip and regs accesses must go through
+        * kvm_{register,rip}_{read,write} functions.
+        */
+       unsigned long regs[NR_VCPU_REGS];
+       u32 regs_avail;
+       u32 regs_dirty;
 
        unsigned long cr0;
        unsigned long cr2;
@@ -237,6 +261,9 @@ struct kvm_vcpu_arch {
        bool tpr_access_reporting;
 
        struct kvm_mmu mmu;
+       /* only needed in kvm_pv_mmu_op() path, but it's hot so
+        * put it here to avoid allocation */
+       struct kvm_pv_mmu_op_buffer mmu_op_buffer;
 
        struct kvm_mmu_memory_cache mmu_pte_chain_cache;
        struct kvm_mmu_memory_cache mmu_rmap_desc_cache;
@@ -269,6 +296,11 @@ struct kvm_vcpu_arch {
                u32 error_code;
        } exception;
 
+       struct kvm_queued_interrupt {
+               bool pending;
+               u8 nr;
+       } interrupt;
+
        struct {
                int active;
                u8 save_iopl;
@@ -294,6 +326,7 @@ struct kvm_vcpu_arch {
        struct page *time_page;
 
        bool nmi_pending;
+       bool nmi_injected;
 
        u64 mtrr[0x100];
 };
@@ -316,9 +349,12 @@ struct kvm_arch{
         * Hash table of struct kvm_mmu_page.
         */
        struct list_head active_mmu_pages;
+       struct list_head assigned_dev_head;
+       struct dmar_domain *intel_iommu_domain;
        struct kvm_pic *vpic;
        struct kvm_ioapic *vioapic;
        struct kvm_pit *vpit;
+       struct hlist_head irq_ack_notifier_list;
 
        int round_robin_prev_vcpu;
        unsigned int tss_addr;
@@ -338,6 +374,7 @@ struct kvm_vm_stat {
        u32 mmu_flooded;
        u32 mmu_recycled;
        u32 mmu_cache_miss;
+       u32 mmu_unsync;
        u32 remote_tlb_flush;
        u32 lpages;
 };
@@ -364,6 +401,7 @@ struct kvm_vcpu_stat {
        u32 insn_emulation;
        u32 insn_emulation_fail;
        u32 hypercalls;
+       u32 irq_injections;
 };
 
 struct descriptor_table {
@@ -414,8 +452,7 @@ struct kvm_x86_ops {
        unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr);
        void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value,
                       int *exception);
-       void (*cache_regs)(struct kvm_vcpu *vcpu);
-       void (*decache_regs)(struct kvm_vcpu *vcpu);
+       void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
        unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
        void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
 
@@ -528,6 +565,8 @@ void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
 void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2,
                           u32 error_code);
 
+void kvm_pic_set_irq(void *opaque, int irq, int level);
+
 void kvm_inject_nmi(struct kvm_vcpu *vcpu);
 
 void fx_init(struct kvm_vcpu *vcpu);
@@ -550,12 +589,14 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
 void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
+void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
 int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
 
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
+void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
 
 void kvm_enable_tdp(void);
 void kvm_disable_tdp(void);
@@ -686,33 +727,6 @@ enum {
        TASK_SWITCH_GATE = 3,
 };
 
-#define KVMTRACE_5D(evt, vcpu, d1, d2, d3, d4, d5, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 5, d1, d2, d3, d4, d5)
-#define KVMTRACE_4D(evt, vcpu, d1, d2, d3, d4, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 4, d1, d2, d3, d4, 0)
-#define KVMTRACE_3D(evt, vcpu, d1, d2, d3, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 3, d1, d2, d3, 0, 0)
-#define KVMTRACE_2D(evt, vcpu, d1, d2, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 2, d1, d2, 0, 0, 0)
-#define KVMTRACE_1D(evt, vcpu, d1, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 1, d1, 0, 0, 0, 0)
-#define KVMTRACE_0D(evt, vcpu, name) \
-       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
-                                               vcpu, 0, 0, 0, 0, 0, 0)
-
-#ifdef CONFIG_64BIT
-# define KVM_EX_ENTRY ".quad"
-# define KVM_EX_PUSH "pushq"
-#else
-# define KVM_EX_ENTRY ".long"
-# define KVM_EX_PUSH "pushl"
-#endif
-
 /*
  * Hardware virtualization extension instructions may fault if a
  * reboot turns off virtualization while processes are running.
@@ -724,11 +738,11 @@ asmlinkage void kvm_handle_fault_on_reboot(void);
        "666: " insn "\n\t" \
        ".pushsection .fixup, \"ax\" \n" \
        "667: \n\t" \
-       KVM_EX_PUSH " $666b \n\t" \
+       __ASM_SIZE(push) " $666b \n\t"        \
        "jmp kvm_handle_fault_on_reboot \n\t" \
        ".popsection \n\t" \
        ".pushsection __ex_table, \"a\" \n\t" \
-       KVM_EX_ENTRY " 666b, 667b \n\t" \
+       _ASM_PTR " 666b, 667b \n\t" \
        ".popsection"
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
index de9ac3f5c4ce547c2a204cac41c4010da2839fe7..ff8778f26b84e3a9125b4a4f383b69ab649c5b20 100644 (file)
@@ -7,12 +7,6 @@
 
 #include <asm/mc146818rtc.h>
 
-static inline void clear_mem_error(unsigned char reason)
-{
-       reason = (reason & 0xf) | 4;
-       outb(reason, 0x61);
-}
-
 static inline unsigned char get_nmi_reason(void)
 {
        return inb(0x61);
index 48dc3e0c07d9a27b828ea614689a939e0baa581b..864f2005fc1d323f27bc853608ce74eefd32698e 100644 (file)
@@ -52,8 +52,6 @@ struct mod_arch_specific {};
 #define MODULE_PROC_FAMILY "EFFICEON "
 #elif defined CONFIG_MWINCHIPC6
 #define MODULE_PROC_FAMILY "WINCHIPC6 "
-#elif defined CONFIG_MWINCHIP2
-#define MODULE_PROC_FAMILY "WINCHIP2 "
 #elif defined CONFIG_MWINCHIP3D
 #define MODULE_PROC_FAMILY "WINCHIP3D "
 #elif defined CONFIG_MCYRIXIII
index 0bb43301a2022ca8d3a23f8ce6a3459476caf7b7..dabd10f0bbee25359a54d7104344813371b742ab 100644 (file)
 #define MSR_IA32_EBL_CR_POWERON                0x0000002a
 #define MSR_IA32_FEATURE_CONTROL        0x0000003a
 
+#define FEATURE_CONTROL_LOCKED         (1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED  (1<<2)
+
 #define MSR_IA32_APICBASE              0x0000001b
 #define MSR_IA32_APICBASE_BSP          (1<<8)
 #define MSR_IA32_APICBASE_ENABLE       (1<<11)
index d5e715f024dcc79d2818d78c2f651ac8d1b32807..a53f829a97c581c7b4a0d3cd77e4a0ea2cdf4ae3 100644 (file)
  */
 int do_nmi_callback(struct pt_regs *regs, int cpu);
 
-#ifdef CONFIG_X86_64
-extern void default_do_nmi(struct pt_regs *);
-#endif
-
 extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
 extern int check_nmi_watchdog(void);
 extern int nmi_watchdog_enabled;
index c91574776751396207f1aa2ce903e15a82239d47..d4f1d5791fc186f29a9a60d4fe182d80f05038e4 100644 (file)
@@ -179,6 +179,7 @@ static inline pteval_t native_pte_flags(pte_t pte)
 #endif /* CONFIG_PARAVIRT */
 
 #define __pa(x)                __phys_addr((unsigned long)(x))
+#define __pa_nodebug(x)        __phys_addr_nodebug((unsigned long)(x))
 /* __pa_symbol should be used for C visible symbols.
    This seems to be the official gcc blessed way to do such arithmetic. */
 #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x)))
@@ -188,9 +189,14 @@ static inline pteval_t native_pte_flags(pte_t pte)
 #define __boot_va(x)           __va(x)
 #define __boot_pa(x)           __pa(x)
 
+/*
+ * virt_to_page(kaddr) returns a valid pointer if and only if
+ * virt_addr_valid(kaddr) returns true.
+ */
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
-#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+extern bool __virt_addr_valid(unsigned long kaddr);
+#define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr))
 
 #endif /* __ASSEMBLY__ */
 
index 9c5a737a9af9878ee128d15a90505afd6f733737..bdf5dba4cfb0a85d0d8aee9c4a557b6c1d4f4a15 100644 (file)
 #endif
 #define THREAD_SIZE    (PAGE_SIZE << THREAD_ORDER)
 
+#define STACKFAULT_STACK 0
+#define DOUBLEFAULT_STACK 1
+#define NMI_STACK 0
+#define DEBUG_STACK 0
+#define MCE_STACK 0
+#define N_EXCEPTION_STACKS 1
 
 #ifdef CONFIG_X86_PAE
 /* 44=32+12, the limit we can fit into an unsigned long pfn */
@@ -33,7 +39,6 @@ typedef u64   pmdval_t;
 typedef u64    pudval_t;
 typedef u64    pgdval_t;
 typedef u64    pgprotval_t;
-typedef u64    phys_addr_t;
 
 typedef union {
        struct {
@@ -54,7 +59,6 @@ typedef unsigned long pmdval_t;
 typedef unsigned long  pudval_t;
 typedef unsigned long  pgdval_t;
 typedef unsigned long  pgprotval_t;
-typedef unsigned long  phys_addr_t;
 
 typedef union {
        pteval_t pte;
@@ -73,11 +77,11 @@ typedef struct page *pgtable_t;
 #endif
 
 #ifndef __ASSEMBLY__
-#define __phys_addr_const(x)   ((x) - PAGE_OFFSET)
+#define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET)
 #ifdef CONFIG_DEBUG_VIRTUAL
 extern unsigned long __phys_addr(unsigned long);
 #else
-#define __phys_addr(x)         ((x) - PAGE_OFFSET)
+#define __phys_addr(x)         __phys_addr_nodebug(x)
 #endif
 #define __phys_reloc_hide(x)   RELOC_HIDE((x), 0)
 
index 5e64acfed0a4882b1bf392e0541b03df8d53734f..49380b8c7e25fbafa26243860abe03d105b7a97a 100644 (file)
@@ -79,7 +79,6 @@ typedef unsigned long pmdval_t;
 typedef unsigned long  pudval_t;
 typedef unsigned long  pgdval_t;
 typedef unsigned long  pgprotval_t;
-typedef unsigned long  phys_addr_t;
 
 typedef struct page *pgtable_t;
 
index ed932453ef26a3538ce3fd2c7670dfc78c18d9b9..88a53b1a17f03f486e9a22a138b30b2e422e6544 100644 (file)
@@ -15,7 +15,7 @@
 #define _PAGE_BIT_PAT          7       /* on 4KB pages */
 #define _PAGE_BIT_GLOBAL       8       /* Global TLB entry PPro+ */
 #define _PAGE_BIT_UNUSED1      9       /* available for programmer */
-#define _PAGE_BIT_UNUSED2      10
+#define _PAGE_BIT_IOMAP                10      /* flag used to indicate IO mapping */
 #define _PAGE_BIT_UNUSED3      11
 #define _PAGE_BIT_PAT_LARGE    12      /* On 2MB or 1GB pages */
 #define _PAGE_BIT_SPECIAL      _PAGE_BIT_UNUSED1
@@ -32,7 +32,7 @@
 #define _PAGE_PSE      (_AT(pteval_t, 1) << _PAGE_BIT_PSE)
 #define _PAGE_GLOBAL   (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
 #define _PAGE_UNUSED1  (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
-#define _PAGE_UNUSED2  (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2)
+#define _PAGE_IOMAP    (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
 #define _PAGE_UNUSED3  (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
 #define _PAGE_PAT      (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
 #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
 #define __PAGE_KERNEL_LARGE_NOCACHE    (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC       (__PAGE_KERNEL_EXEC | _PAGE_PSE)
 
+#define __PAGE_KERNEL_IO               (__PAGE_KERNEL | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_NOCACHE       (__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_UC_MINUS      (__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_WC            (__PAGE_KERNEL_WC | _PAGE_IOMAP)
+
 #define PAGE_KERNEL                    __pgprot(__PAGE_KERNEL)
 #define PAGE_KERNEL_RO                 __pgprot(__PAGE_KERNEL_RO)
 #define PAGE_KERNEL_EXEC               __pgprot(__PAGE_KERNEL_EXEC)
 #define PAGE_KERNEL_VSYSCALL           __pgprot(__PAGE_KERNEL_VSYSCALL)
 #define PAGE_KERNEL_VSYSCALL_NOCACHE   __pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
 
+#define PAGE_KERNEL_IO                 __pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE         __pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#define PAGE_KERNEL_IO_UC_MINUS                __pgprot(__PAGE_KERNEL_IO_UC_MINUS)
+#define PAGE_KERNEL_IO_WC              __pgprot(__PAGE_KERNEL_IO_WC)
+
 /*         xwr */
 #define __P000 PAGE_NONE
 #define __P001 PAGE_READONLY
 #ifdef CONFIG_X86_64
 #define __PAGE_KERNEL_IDENT_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC
 #else
+/*
+ * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
+ * bits are combined, this will alow user to access the high address mapped
+ * VDSO in the presence of CONFIG_COMPAT_VDSO
+ */
 #define PTE_IDENT_ATTR  0x003          /* PRESENT+RW */
-#define PDE_IDENT_ATTR  0x063          /* PRESENT+RW+DIRTY+ACCESSED */
+#define PDE_IDENT_ATTR  0x067          /* PRESENT+RW+USER+DIRTY+ACCESSED */
 #define PGD_IDENT_ATTR  0x001          /* PRESENT (no other attributes) */
 #endif
 
@@ -196,7 +211,7 @@ static inline int pte_exec(pte_t pte)
 
 static inline int pte_special(pte_t pte)
 {
-       return pte_val(pte) & _PAGE_SPECIAL;
+       return pte_flags(pte) & _PAGE_SPECIAL;
 }
 
 static inline unsigned long pte_pfn(pte_t pte)
index ac578f11c1c563e03cb31bf3e1a61fdfe2288c34..a2025525a15ab20dca199a9e3acf95b2d1d7fcff 100644 (file)
@@ -174,12 +174,8 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 
 extern unsigned long
 convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
-
-#ifdef CONFIG_X86_32
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
                         int error_code, int si_code);
-#endif
-
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 extern long syscall_trace_enter(struct pt_regs *);
index 1a38f68348007a64dfabf488dd623bef2a463f42..ad29e277fd6d6dd9d114e33b6113c42d03bf5d2c 100644 (file)
@@ -6,6 +6,7 @@
 
 /* some helper functions for xen and kvm pv clock sources */
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
+unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
 void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
                            struct pvclock_vcpu_time_info *vcpu,
                            struct timespec *ts);
index ea5f0a8686f7539e32e92f801574454c9b3a6846..5d6e6945489152932b8e0f1216a035fc53e9fb33 100644 (file)
  * Matching rules for certain types of segments.
  */
 
-/* Matches only __KERNEL_CS, ignoring PnP / USER / APM segments */
-#define SEGMENT_IS_KERNEL_CODE(x) (((x) & 0xfc) == GDT_ENTRY_KERNEL_CS * 8)
-
-/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
-#define SEGMENT_IS_FLAT_CODE(x)  (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
-
 /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
 #define SEGMENT_IS_PNP_CODE(x)   (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
 
index 6df2615f9138728cfd29ea2ac46a0194c1fd1555..a6afc29f2dd9981e713a36d3ec14b507796415bf 100644 (file)
@@ -141,6 +141,8 @@ void play_dead_common(void);
 void native_send_call_func_ipi(cpumask_t mask);
 void native_send_call_func_single_ipi(int cpu);
 
+extern void prefill_possible_map(void);
+
 void smp_store_cpu_info(int id);
 #define cpu_physical_id(cpu)   per_cpu(x86_cpu_to_apicid, cpu)
 
@@ -149,15 +151,11 @@ static inline int num_booting_cpus(void)
 {
        return cpus_weight(cpu_callout_map);
 }
-#endif /* CONFIG_SMP */
-
-#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_CPU)
-extern void prefill_possible_map(void);
 #else
 static inline void prefill_possible_map(void)
 {
 }
-#endif
+#endif /* CONFIG_SMP */
 
 extern unsigned disabled_cpus __cpuinitdata;
 
index 3f005bc3aa5bb0e35c6421927f6ad999d8181a1f..ca5dc19dd461f95368b38fc9fb8c96bebd86d58d 100644 (file)
@@ -1,63 +1,12 @@
 #ifndef ASM_X86__STATFS_H
 #define ASM_X86__STATFS_H
 
-#ifdef __i386__
-#include <asm-generic/statfs.h>
-#else
-
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t        fsid_t;
-
-#endif
-
 /*
- * This is ugly -- we're already 64-bit clean, so just duplicate the
- * definitions.
+ * We need compat_statfs64 to be packed, because the i386 ABI won't
+ * add padding at the end to bring it to a multiple of 8 bytes, but
+ * the x86_64 ABI will.
  */
-struct statfs {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
-
-struct statfs64 {
-       long f_type;
-       long f_bsize;
-       long f_blocks;
-       long f_bfree;
-       long f_bavail;
-       long f_files;
-       long f_ffree;
-       __kernel_fsid_t f_fsid;
-       long f_namelen;
-       long f_frsize;
-       long f_spare[5];
-};
+#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
 
-struct compat_statfs64 {
-       __u32 f_type;
-       __u32 f_bsize;
-       __u64 f_blocks;
-       __u64 f_bfree;
-       __u64 f_bavail;
-       __u64 f_files;
-       __u64 f_ffree;
-       __kernel_fsid_t f_fsid;
-       __u32 f_namelen;
-       __u32 f_frsize;
-       __u32 f_spare[5];
-} __attribute__((packed));
-
-#endif /* !__i386__ */
+#include <asm-generic/statfs.h>
 #endif /* ASM_X86__STATFS_H */
index c5b2e4b10358dd6beda71fb8b5a318d9ee341dff..394b00bb5e72542b3bfd4ecc2efbee58157cf3a9 100644 (file)
@@ -160,7 +160,7 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
                        int new_apicid = cpu_to_logical_apicid(cpu);
                        if (apicid_cluster(apicid) !=
                                        apicid_cluster(new_apicid)){
-                               printk ("%s: Not a valid mask!\n",__FUNCTION__);
+                               printk ("%s: Not a valid mask!\n", __func__);
                                return 0xFF;
                        }
                        apicid = apicid | new_apicid;
index 34505dd7b24de4ad67b968f93b3fc24156700206..b20c894660f95ee1d056d86a238e2bb116cb673c 100644 (file)
@@ -64,7 +64,10 @@ do {                                                                 \
                                                                        \
                       /* regparm parameters for __switch_to(): */      \
                       [prev]     "a" (prev),                           \
-                      [next]     "d" (next));                          \
+                      [next]     "d" (next)                            \
+                                                                       \
+                    : /* reloaded segment registers */                 \
+                       "memory");                                      \
 } while (0)
 
 /*
index 7a692baa51ae1548cf255c514ec4521a77a815b3..6c3dc2c65751fbb832d8c7fa26dc318c401c80b2 100644 (file)
@@ -3,7 +3,12 @@
 
 #include <asm/debugreg.h>
 
-/* Common in X86_32 and X86_64 */
+#ifdef CONFIG_X86_32
+#define dotraplinkage
+#else
+#define dotraplinkage asmlinkage
+#endif
+
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
 asmlinkage void nmi(void);
@@ -12,31 +17,47 @@ asmlinkage void overflow(void);
 asmlinkage void bounds(void);
 asmlinkage void invalid_op(void);
 asmlinkage void device_not_available(void);
+#ifdef CONFIG_X86_64
+asmlinkage void double_fault(void);
+#endif
 asmlinkage void coprocessor_segment_overrun(void);
 asmlinkage void invalid_TSS(void);
 asmlinkage void segment_not_present(void);
 asmlinkage void stack_segment(void);
 asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
+asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void coprocessor_error(void);
-asmlinkage void simd_coprocessor_error(void);
 asmlinkage void alignment_check(void);
-asmlinkage void spurious_interrupt_bug(void);
 #ifdef CONFIG_X86_MCE
 asmlinkage void machine_check(void);
 #endif /* CONFIG_X86_MCE */
+asmlinkage void simd_coprocessor_error(void);
 
-void do_divide_error(struct pt_regs *, long);
-void do_overflow(struct pt_regs *, long);
-void do_bounds(struct pt_regs *, long);
-void do_coprocessor_segment_overrun(struct pt_regs *, long);
-void do_invalid_TSS(struct pt_regs *, long);
-void do_segment_not_present(struct pt_regs *, long);
-void do_stack_segment(struct pt_regs *, long);
-void do_alignment_check(struct pt_regs *, long);
-void do_invalid_op(struct pt_regs *, long);
-void do_general_protection(struct pt_regs *, long);
-void do_nmi(struct pt_regs *, long);
+dotraplinkage void do_divide_error(struct pt_regs *, long);
+dotraplinkage void do_debug(struct pt_regs *, long);
+dotraplinkage void do_nmi(struct pt_regs *, long);
+dotraplinkage void do_int3(struct pt_regs *, long);
+dotraplinkage void do_overflow(struct pt_regs *, long);
+dotraplinkage void do_bounds(struct pt_regs *, long);
+dotraplinkage void do_invalid_op(struct pt_regs *, long);
+dotraplinkage void do_device_not_available(struct pt_regs *, long);
+dotraplinkage void do_coprocessor_segment_overrun(struct pt_regs *, long);
+dotraplinkage void do_invalid_TSS(struct pt_regs *, long);
+dotraplinkage void do_segment_not_present(struct pt_regs *, long);
+dotraplinkage void do_stack_segment(struct pt_regs *, long);
+dotraplinkage void do_general_protection(struct pt_regs *, long);
+dotraplinkage void do_page_fault(struct pt_regs *, unsigned long);
+dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long);
+dotraplinkage void do_coprocessor_error(struct pt_regs *, long);
+dotraplinkage void do_alignment_check(struct pt_regs *, long);
+#ifdef CONFIG_X86_MCE
+dotraplinkage void do_machine_check(struct pt_regs *, long);
+#endif
+dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
+#ifdef CONFIG_X86_32
+dotraplinkage void do_iret_error(struct pt_regs *, long);
+#endif
 
 static inline int get_si_code(unsigned long condition)
 {
@@ -52,31 +73,9 @@ extern int panic_on_unrecovered_nmi;
 extern int kstack_depth_to_print;
 
 #ifdef CONFIG_X86_32
-
-void do_iret_error(struct pt_regs *, long);
-void do_int3(struct pt_regs *, long);
-void do_debug(struct pt_regs *, long);
 void math_error(void __user *);
-void do_coprocessor_error(struct pt_regs *, long);
-void do_simd_coprocessor_error(struct pt_regs *, long);
-void do_spurious_interrupt_bug(struct pt_regs *, long);
 unsigned long patch_espfix_desc(unsigned long, unsigned long);
 asmlinkage void math_emulate(long);
+#endif
 
-void do_page_fault(struct pt_regs *regs, unsigned long error_code);
-
-#else /* CONFIG_X86_32 */
-
-asmlinkage void double_fault(void);
-
-asmlinkage void do_int3(struct pt_regs *, long);
-asmlinkage void do_stack_segment(struct pt_regs *, long);
-asmlinkage void do_debug(struct pt_regs *, unsigned long);
-asmlinkage void do_coprocessor_error(struct pt_regs *);
-asmlinkage void do_simd_coprocessor_error(struct pt_regs *);
-asmlinkage void do_spurious_interrupt_bug(struct pt_regs *);
-
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code);
-
-#endif /* CONFIG_X86_32 */
 #endif /* ASM_X86__TRAPS_H */
index c50185dccec192bdef7e0d936863d5503cc304d5..d5eada0a48d9bea73e8dcadeaf2379dc69ee3639 100644 (file)
@@ -76,13 +76,13 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
 static inline xmaddr_t phys_to_machine(xpaddr_t phys)
 {
        unsigned offset = phys.paddr & ~PAGE_MASK;
-       return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
+       return XMADDR(PFN_PHYS(pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset);
 }
 
 static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 {
        unsigned offset = machine.maddr & ~PAGE_MASK;
-       return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
+       return XPADDR(PFN_PHYS(mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset);
 }
 
 /*
diff --git a/include/asm-xtensa/a.out.h b/include/asm-xtensa/a.out.h
deleted file mode 100644 (file)
index fdf1370..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-xtensa/a.out.h
- *
- * Dummy a.out file. Xtensa does not support the a.out format, but the kernel
- * seems to depend on it.
- *
- * 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 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_A_OUT_H
-#define _XTENSA_A_OUT_H
-
-struct exec
-{
-  unsigned long a_info;
-  unsigned a_text;
-  unsigned a_data;
-  unsigned a_bss;
-  unsigned a_syms;
-  unsigned a_entry;
-  unsigned a_trsize;
-  unsigned a_drsize;
-};
-
-#endif /* _XTENSA_A_OUT_H */
index ca6e5101a2cba6fb021fec6891193653660ecd64..c3f53e755ca5c16fabff550b1c7859c6521c9e17 100644 (file)
@@ -189,7 +189,7 @@ typedef struct {
 #endif
 } elf_xtregs_t;
 
-#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
 
 struct task_struct;
 
index 282a504bd1dbefed45609eae5c5bf02edd1bc49b..bf9aca548f14a931f33e35bfed8a8efb4036e8e8 100644 (file)
@@ -107,6 +107,7 @@ header-y += keyctl.h
 header-y += limits.h
 header-y += magic.h
 header-y += major.h
+header-y += map_to_7segment.h
 header-y += matroxfb.h
 header-y += meye.h
 header-y += minix_fs.h
index 09b276c35227f43ef120d3e729dc0d27f68e303e..f6b8cf99b596a30820215766fb7e680dedf7e6e1 100644 (file)
@@ -204,12 +204,21 @@ struct kioctx {
 /* prototypes */
 extern unsigned aio_max_size;
 
+#ifdef CONFIG_AIO
 extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
 extern int aio_put_req(struct kiocb *iocb);
 extern void kick_iocb(struct kiocb *iocb);
 extern int aio_complete(struct kiocb *iocb, long res, long res2);
 struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
+#else
+static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
+static inline int aio_put_req(struct kiocb *iocb) { return 0; }
+static inline void kick_iocb(struct kiocb *iocb) { }
+static inline int aio_complete(struct kiocb *iocb, long res, long res2) { return 0; }
+struct mm_struct;
+static inline void exit_aio(struct mm_struct *mm) { }
+#endif /* CONFIG_AIO */
 
 #define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
 
diff --git a/include/linux/auto_dev-ioctl.h b/include/linux/auto_dev-ioctl.h
new file mode 100644 (file)
index 0000000..f4d05cc
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2008 Red Hat, Inc. All rights reserved.
+ * Copyright 2008 Ian Kent <raven@themaw.net>
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ */
+
+#ifndef _LINUX_AUTO_DEV_IOCTL_H
+#define _LINUX_AUTO_DEV_IOCTL_H
+
+#include <linux/types.h>
+
+#define AUTOFS_DEVICE_NAME             "autofs"
+
+#define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1
+#define AUTOFS_DEV_IOCTL_VERSION_MINOR 0
+
+#define AUTOFS_DEVID_LEN               16
+
+#define AUTOFS_DEV_IOCTL_SIZE          sizeof(struct autofs_dev_ioctl)
+
+/*
+ * An ioctl interface for autofs mount point control.
+ */
+
+/*
+ * All the ioctls use this structure.
+ * When sending a path size must account for the total length
+ * of the chunk of memory otherwise is is the size of the
+ * structure.
+ */
+
+struct autofs_dev_ioctl {
+       __u32 ver_major;
+       __u32 ver_minor;
+       __u32 size;             /* total size of data passed in
+                                * including this struct */
+       __s32 ioctlfd;          /* automount command fd */
+
+       __u32 arg1;             /* Command parameters */
+       __u32 arg2;
+
+       char path[0];
+};
+
+static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in)
+{
+       in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
+       in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
+       in->size = sizeof(struct autofs_dev_ioctl);
+       in->ioctlfd = -1;
+       in->arg1 = 0;
+       in->arg2 = 0;
+       return;
+}
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to autofs-dev-ioctl.c:lookup_ioctl()
+ */
+enum {
+       /* Get various version info */
+       AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71,
+       AUTOFS_DEV_IOCTL_PROTOVER_CMD,
+       AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD,
+
+       /* Open mount ioctl fd */
+       AUTOFS_DEV_IOCTL_OPENMOUNT_CMD,
+
+       /* Close mount ioctl fd */
+       AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD,
+
+       /* Mount/expire status returns */
+       AUTOFS_DEV_IOCTL_READY_CMD,
+       AUTOFS_DEV_IOCTL_FAIL_CMD,
+
+       /* Activate/deactivate autofs mount */
+       AUTOFS_DEV_IOCTL_SETPIPEFD_CMD,
+       AUTOFS_DEV_IOCTL_CATATONIC_CMD,
+
+       /* Expiry timeout */
+       AUTOFS_DEV_IOCTL_TIMEOUT_CMD,
+
+       /* Get mount last requesting uid and gid */
+       AUTOFS_DEV_IOCTL_REQUESTER_CMD,
+
+       /* Check for eligible expire candidates */
+       AUTOFS_DEV_IOCTL_EXPIRE_CMD,
+
+       /* Request busy status */
+       AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD,
+
+       /* Check if path is a mountpoint */
+       AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD,
+};
+
+#define AUTOFS_IOCTL 0x93
+
+#define AUTOFS_DEV_IOCTL_VERSION \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_VERSION_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_PROTOVER \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_PROTOVER_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_PROTOSUBVER \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_OPENMOUNT \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_CLOSEMOUNT \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_READY \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_READY_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_FAIL \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_FAIL_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_SETPIPEFD \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_CATATONIC \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_CATATONIC_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_TIMEOUT \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_TIMEOUT_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_REQUESTER \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_REQUESTER_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_EXPIRE \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_EXPIRE_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_ASKUMOUNT \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, struct autofs_dev_ioctl)
+
+#define AUTOFS_DEV_IOCTL_ISMOUNTPOINT \
+       _IOWR(AUTOFS_IOCTL, \
+             AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl)
+
+#endif /* _LINUX_AUTO_DEV_IOCTL_H */
index b785c6f8644dc28ca92793f96c31ab0b53ab4c85..2253716d4b92227a2d6deb49a20b53b7088ece9d 100644 (file)
 #define AUTOFS_MIN_PROTO_VERSION       3
 #define AUTOFS_MAX_PROTO_VERSION       5
 
-#define AUTOFS_PROTO_SUBVERSION                0
+#define AUTOFS_PROTO_SUBVERSION                1
 
 /* Mask for expire behaviour */
 #define AUTOFS_EXP_IMMEDIATE           1
 #define AUTOFS_EXP_LEAVES              2
 
+#define AUTOFS_TYPE_ANY                        0x0000
+#define AUTOFS_TYPE_INDIRECT           0x0001
+#define AUTOFS_TYPE_DIRECT             0x0002
+#define AUTOFS_TYPE_OFFSET             0x0004
+
 /* Daemon notification packet types */
 enum autofs_notify {
        NFY_NONE,
index 826f62350805ed782976008db013203061306744..7394b5b349ffc82c2ea42e51188dc3839229fed1 100644 (file)
@@ -36,6 +36,10 @@ struct linux_binprm{
        unsigned long p; /* current top of mem */
        unsigned int sh_bang:1,
                     misc_bang:1;
+#ifdef __alpha__
+       unsigned int taso:1;
+#endif
+       unsigned int recursion_depth;
        struct file * file;
        int e_uid, e_gid;
        kernel_cap_t cap_post_exec_permitted;
@@ -58,6 +62,7 @@ struct linux_binprm{
 #define BINPRM_FLAGS_EXECFD_BIT 1
 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT)
 
+#define BINPRM_MAX_RECURSION 4
 
 /*
  * This structure defines the functions that are used to load the binary formats that
index c98dd7cb7076f44484a68643995f10fd1bbc2ff8..30934e4bfaab7b9e3197e0d7410579c0737bf2c7 100644 (file)
@@ -326,7 +326,8 @@ struct cgroup_subsys {
         */
        void (*mm_owner_changed)(struct cgroup_subsys *ss,
                                        struct cgroup *old,
-                                       struct cgroup *new);
+                                       struct cgroup *new,
+                                       struct task_struct *p);
        int subsys_id;
        int active;
        int disabled;
index 5ca8c6fddb56216291e5233c9b37cee09076b269..778777316ea4bc3747983e2c9ed60ed5e1d321dc 100644 (file)
@@ -35,6 +35,8 @@ struct clk;
  * clk_get may return different clock producers depending on @dev.)
  *
  * Drivers must assume that the clock source is not enabled.
+ *
+ * clk_get should not be called from within interrupt context.
  */
 struct clk *clk_get(struct device *dev, const char *id);
 
@@ -76,6 +78,8 @@ unsigned long clk_get_rate(struct clk *clk);
  * Note: drivers must ensure that all clk_enable calls made on this
  * clock source are balanced by clk_disable calls prior to calling
  * this function.
+ *
+ * clk_put should not be called from within interrupt context.
  */
 void clk_put(struct clk *clk);
 
index cf8d11cad5aef24dd99c57c3f7406d9ea4c541d6..f061a1ea1b74d74fa7a3391bb47c6bbdca4d0b3e 100644 (file)
@@ -78,7 +78,6 @@ typedef struct {
        compat_sigset_word      sig[_COMPAT_NSIG_WORDS];
 } compat_sigset_t;
 
-extern int cp_compat_stat(struct kstat *, struct compat_stat __user *);
 extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *);
 extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *);
 
@@ -235,6 +234,11 @@ extern int get_compat_itimerspec(struct itimerspec *dst,
 extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
                                 const struct itimerspec *src);
 
+asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
+               struct timezone __user *tz);
+asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
+               struct timezone __user *tz);
+
 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
 
 extern int compat_printk(const char *fmt, ...);
index b03f80a078bee4f8d822dd90fc73545def4adcce..d71f7c0f931b34b63bfacde2b06d19ffc5001616 100644 (file)
@@ -53,7 +53,6 @@ struct vc_data {
        unsigned short  vc_hi_font_mask;        /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
        struct console_font vc_font;            /* Current VC font set */
        unsigned short  vc_video_erase_char;    /* Background erase character */
-       unsigned short  vc_scrl_erase_char;     /* Erase character for scroll */
        /* VT terminal data */
        unsigned int    vc_state;               /* Escape sequence parser state */
        unsigned int    vc_npar,vc_par[NPAR];   /* Parameters of current escape sequence */
index 246937c9cbc780db2cc30b542453d401bcd6c334..987f5912720a2d6ffd6d32a33a062e3b4ef27892 100644 (file)
@@ -90,6 +90,9 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
                                  struct device_driver *start, void *data,
                                  int (*fn)(struct device_driver *, void *));
 
+void bus_sort_breadthfirst(struct bus_type *bus,
+                          int (*compare)(const struct device *a,
+                                         const struct device *b));
 /*
  * Bus notifiers: Get notified of addition/removal of devices
  * and binding/unbinding of drivers to devices.
@@ -502,7 +505,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
                                    dev_t devt, void *drvdata,
                                    const char *fmt, ...)
                                    __attribute__((format(printf, 5, 6)));
-#define device_create_drvdata  device_create
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
@@ -551,7 +553,11 @@ extern const char *dev_driver_string(const struct device *dev);
 #define dev_info(dev, format, arg...)          \
        dev_printk(KERN_INFO , dev , format , ## arg)
 
-#ifdef DEBUG
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define dev_dbg(dev, format, ...) do { \
+       dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
+       } while (0)
+#elif defined(DEBUG)
 #define dev_dbg(dev, format, arg...)           \
        dev_printk(KERN_DEBUG , dev , format , ## arg)
 #else
@@ -567,6 +573,14 @@ extern const char *dev_driver_string(const struct device *dev);
        ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; })
 #endif
 
+/*
+ * dev_WARN() acts like dev_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define dev_WARN(dev, format, arg...) \
+       WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg);
+
 /* Create alias, so I can be autoloaded. */
 #define MODULE_ALIAS_CHARDEV(major,minor) \
        MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
index 154769cad3f31c7207b3113ec5e00753a4684ee2..5ce0e5fd712e0fe67d0e05b455fffbb85c16fb7c 100644 (file)
 
 #ifdef CONFIG_UNIX98_PTYS
 
-int devpts_new_index(void);
-void devpts_kill_index(int idx);
-int devpts_pty_new(struct tty_struct *tty);      /* mknod in devpts */
-struct tty_struct *devpts_get_tty(int number);  /* get tty structure */
-void devpts_pty_kill(int number);               /* unlink */
+int devpts_new_index(struct inode *ptmx_inode);
+void devpts_kill_index(struct inode *ptmx_inode, int idx);
+/* mknod in devpts */
+int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty);
+/* get tty structure */
+struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number);
+/* unlink */
+void devpts_pty_kill(struct tty_struct *tty);
 
 #else
 
 /* Dummy stubs in the no-pty case */
-static inline int devpts_new_index(void) { return -EINVAL; }
-static inline void devpts_kill_index(int idx) { }
-static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; }
-static inline struct tty_struct *devpts_get_tty(int number) { return NULL; }
-static inline void devpts_pty_kill(int number) { }
+static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
+static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
+static inline int devpts_pty_new(struct inode *ptmx_inode,
+                               struct tty_struct *tty)
+{
+       return -EINVAL;
+}
+static inline struct tty_struct *devpts_get_tty(struct inode *pts_inode,
+               int number)
+{
+       return NULL;
+}
+static inline void devpts_pty_kill(struct tty_struct *tty) { }
 
 #endif
 
diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h
new file mode 100644 (file)
index 0000000..bff5c65
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef _DMA_REMAPPING_H
+#define _DMA_REMAPPING_H
+
+/*
+ * We need a fixed PAGE_SIZE of 4K irrespective of
+ * arch PAGE_SIZE for IOMMU page tables.
+ */
+#define PAGE_SHIFT_4K          (12)
+#define PAGE_SIZE_4K           (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K           (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr)    (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+#define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT_4K)
+#define DMA_32BIT_PFN          IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN          IOVA_PFN(DMA_64BIT_MASK)
+
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+       u64     val;
+       u64     rsvd1;
+};
+#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+       return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+       root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+       root->val |= value & PAGE_MASK_4K;
+}
+
+struct context_entry;
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+       return (struct context_entry *)
+               (root_present(root)?phys_to_virt(
+               root->val & PAGE_MASK_4K):
+               NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+       u64 lo;
+       u64 hi;
+};
+#define context_present(c) ((c).lo & 1)
+#define context_fault_disable(c) (((c).lo >> 1) & 1)
+#define context_translation_type(c) (((c).lo >> 2) & 3)
+#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
+#define context_address_width(c) ((c).hi &  7)
+#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
+
+#define context_set_present(c) do {(c).lo |= 1;} while (0)
+#define context_set_fault_enable(c) \
+       do {(c).lo &= (((u64)-1) << 2) | 1;} while (0)
+#define context_set_translation_type(c, val) \
+       do { \
+               (c).lo &= (((u64)-1) << 4) | 3; \
+               (c).lo |= ((val) & 3) << 2; \
+       } while (0)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define context_set_address_root(c, val) \
+       do {(c).lo |= (val) & PAGE_MASK_4K;} while (0)
+#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0)
+#define context_set_domain_id(c, val) \
+       do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0)
+#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0)
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+       u64 val;
+};
+#define dma_clear_pte(p)       do {(p).val = 0;} while (0)
+
+#define DMA_PTE_READ (1)
+#define DMA_PTE_WRITE (2)
+
+#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0)
+#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0)
+#define dma_set_pte_prot(p, prot) \
+               do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0)
+#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_set_pte_addr(p, addr) do {\
+               (p).val |= ((addr) & PAGE_MASK_4K); } while (0)
+#define dma_pte_present(p) (((p).val & 3) != 0)
+
+struct intel_iommu;
+
+struct dmar_domain {
+       int     id;                     /* domain id */
+       struct intel_iommu *iommu;      /* back pointer to owning iommu */
+
+       struct list_head devices;       /* all devices' list */
+       struct iova_domain iovad;       /* iova's that belong to this domain */
+
+       struct dma_pte  *pgd;           /* virtual address */
+       spinlock_t      mapping_lock;   /* page table lock */
+       int             gaw;            /* max guest address width */
+
+       /* adjusted guest address width, 0 is level 2 30-bit */
+       int             agaw;
+
+#define DOMAIN_FLAG_MULTIPLE_DEVICES 1
+       int             flags;
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+       struct list_head link;  /* link to domain siblings */
+       struct list_head global; /* link to global list */
+       u8 bus;                 /* PCI bus numer */
+       u8 devfn;               /* PCI devfn number */
+       struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+       struct dmar_domain *domain; /* pointer to domain */
+};
+
+extern int init_dmars(void);
+extern void free_dmar_iommu(struct intel_iommu *iommu);
+
+extern int dmar_disabled;
+
+#ifndef CONFIG_DMAR_GFX_WA
+static inline void iommu_prepare_gfx_mapping(void)
+{
+       return;
+}
+#endif /* !CONFIG_DMAR_GFX_WA */
+
+#endif
index 2a063b64133fcd23307e57b6b396fa935eb7c808..e5084eb5943a5f35fc82680e3a83103f19a46019 100644 (file)
@@ -2,29 +2,9 @@
 #define __DMI_H__
 
 #include <linux/list.h>
+#include <linux/mod_devicetable.h>
 
-enum dmi_field {
-       DMI_NONE,
-       DMI_BIOS_VENDOR,
-       DMI_BIOS_VERSION,
-       DMI_BIOS_DATE,
-       DMI_SYS_VENDOR,
-       DMI_PRODUCT_NAME,
-       DMI_PRODUCT_VERSION,
-       DMI_PRODUCT_SERIAL,
-       DMI_PRODUCT_UUID,
-       DMI_BOARD_VENDOR,
-       DMI_BOARD_NAME,
-       DMI_BOARD_VERSION,
-       DMI_BOARD_SERIAL,
-       DMI_BOARD_ASSET_TAG,
-       DMI_CHASSIS_VENDOR,
-       DMI_CHASSIS_TYPE,
-       DMI_CHASSIS_VERSION,
-       DMI_CHASSIS_SERIAL,
-       DMI_CHASSIS_ASSET_TAG,
-       DMI_STRING_MAX,
-};
+/* enum dmi_field is in mod_devicetable.h */
 
 enum dmi_device_type {
        DMI_DEV_TYPE_ANY = 0,
@@ -48,23 +28,6 @@ struct dmi_header {
        u16 handle;
 };
 
-/*
- *     DMI callbacks for problem boards
- */
-struct dmi_strmatch {
-       u8 slot;
-       char *substr;
-};
-
-struct dmi_system_id {
-       int (*callback)(const struct dmi_system_id *);
-       const char *ident;
-       struct dmi_strmatch matches[4];
-       void *driver_data;
-};
-
-#define DMI_MATCH(a, b)        { a, b }
-
 struct dmi_device {
        struct list_head list;
        int type;
index d8989860e4cefba476e8e31566690e4f687e88de..45ea0aa0aeb9e8ca8f48a8d628e60fd32a58a8e7 100644 (file)
@@ -8,8 +8,6 @@
 #ifndef __LINUX_DS1286_H
 #define __LINUX_DS1286_H
 
-#include <asm/ds1286.h>
-
 /**********************************************************************
  * register summary
  **********************************************************************/
index c8cbd90ba3757ace87522db09dc63ff36fbea0a0..6e4ace27027691fa42c4920bcf5bf4e60e12494d 100644 (file)
@@ -62,6 +62,7 @@ typedef enum fe_caps {
        FE_CAN_HIERARCHY_AUTO           = 0x100000,
        FE_CAN_8VSB                     = 0x200000,
        FE_CAN_16VSB                    = 0x400000,
+       FE_HAS_EXTENDED_CAPS            = 0x800000,   // We need more bitspace for newer APIs, indicate this.
        FE_NEEDS_BENDING                = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
        FE_CAN_RECOVER                  = 0x40000000, // frontend can recover from a cable unplug automatically
        FE_CAN_MUTE_TS                  = 0x80000000  // frontend can stop spurious TS data output
@@ -147,7 +148,9 @@ typedef enum fe_code_rate {
        FEC_6_7,
        FEC_7_8,
        FEC_8_9,
-       FEC_AUTO
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
 } fe_code_rate_t;
 
 
@@ -160,7 +163,10 @@ typedef enum fe_modulation {
        QAM_256,
        QAM_AUTO,
        VSB_8,
-       VSB_16
+       VSB_16,
+       PSK_8,
+       APSK_16,
+       DQPSK,
 } fe_modulation_t;
 
 typedef enum fe_transmit_mode {
@@ -239,6 +245,106 @@ struct dvb_frontend_event {
        struct dvb_frontend_parameters parameters;
 };
 
+/* S2API Commands */
+#define DTV_UNDEFINED          0
+#define DTV_TUNE               1
+#define DTV_CLEAR              2
+#define DTV_FREQUENCY          3
+#define DTV_MODULATION         4
+#define DTV_BANDWIDTH_HZ       5
+#define DTV_INVERSION          6
+#define DTV_DISEQC_MASTER      7
+#define DTV_SYMBOL_RATE                8
+#define DTV_INNER_FEC          9
+#define DTV_VOLTAGE            10
+#define DTV_TONE               11
+#define DTV_PILOT              12
+#define DTV_ROLLOFF            13
+#define DTV_DISEQC_SLAVE_REPLY 14
+
+/* Basic enumeration set for querying unlimited capabilities */
+#define DTV_FE_CAPABILITY_COUNT        15
+#define DTV_FE_CAPABILITY      16
+#define DTV_DELIVERY_SYSTEM    17
+
+#define DTV_API_VERSION                                35
+#define DTV_API_VERSION                                35
+#define DTV_CODE_RATE_HP                       36
+#define DTV_CODE_RATE_LP                       37
+#define DTV_GUARD_INTERVAL                     38
+#define DTV_TRANSMISSION_MODE                  39
+#define DTV_HIERARCHY                          40
+
+#define DTV_MAX_COMMAND                                DTV_HIERARCHY
+
+typedef enum fe_pilot {
+       PILOT_ON,
+       PILOT_OFF,
+       PILOT_AUTO,
+} fe_pilot_t;
+
+typedef enum fe_rolloff {
+       ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
+       ROLLOFF_20,
+       ROLLOFF_25,
+       ROLLOFF_AUTO,
+} fe_rolloff_t;
+
+typedef enum fe_delivery_system {
+       SYS_UNDEFINED,
+       SYS_DVBC_ANNEX_AC,
+       SYS_DVBC_ANNEX_B,
+       SYS_DVBT,
+       SYS_DVBS,
+       SYS_DVBS2,
+       SYS_DVBH,
+       SYS_ISDBT,
+       SYS_ISDBS,
+       SYS_ISDBC,
+       SYS_ATSC,
+       SYS_ATSCMH,
+       SYS_DMBTH,
+       SYS_CMMB,
+       SYS_DAB,
+} fe_delivery_system_t;
+
+struct dtv_cmds_h {
+       char    *name;          /* A display name for debugging purposes */
+
+       __u32   cmd;            /* A unique ID */
+
+       /* Flags */
+       __u32   set:1;          /* Either a set or get property */
+       __u32   buffer:1;       /* Does this property use the buffer? */
+       __u32   reserved:30;    /* Align */
+};
+
+struct dtv_property {
+       __u32 cmd;
+       __u32 reserved[3];
+       union {
+               __u32 data;
+               struct {
+                       __u8 data[32];
+                       __u32 len;
+                       __u32 reserved1[3];
+                       void *reserved2;
+               } buffer;
+       } u;
+       int result;
+} __attribute__ ((packed));
+
+/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
+#define DTV_IOCTL_MAX_MSGS 64
+
+struct dtv_properties {
+       __u32 num;
+       struct dtv_property *props;
+};
+
+#define FE_SET_PROPERTY                   _IOW('o', 82, struct dtv_properties)
+#define FE_GET_PROPERTY                   _IOR('o', 83, struct dtv_properties)
+
 
 /**
  * When set, this flag will disable any zigzagging or other "normal" tuning
index 126e0c26cb091aa6a647dd0f8359662d143d3ed8..25b823b81734e969db634b384f5bc52031a4b16e 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef _DVBVERSION_H_
 #define _DVBVERSION_H_
 
-#define DVB_API_VERSION 3
-#define DVB_API_VERSION_MINOR 2
+#define DVB_API_VERSION 5
+#define DVB_API_VERSION_MINOR 0
 
 #endif /*_DVBVERSION_H_*/
diff --git a/include/linux/dynamic_printk.h b/include/linux/dynamic_printk.h
new file mode 100644 (file)
index 0000000..2d528d0
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef _DYNAMIC_PRINTK_H
+#define _DYNAMIC_PRINTK_H
+
+#define DYNAMIC_DEBUG_HASH_BITS 6
+#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
+
+#define TYPE_BOOLEAN 1
+
+#define DYNAMIC_ENABLED_ALL 0
+#define DYNAMIC_ENABLED_NONE 1
+#define DYNAMIC_ENABLED_SOME 2
+
+extern int dynamic_enabled;
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+extern long long dynamic_printk_enabled;
+extern long long dynamic_printk_enabled2;
+
+struct mod_debug {
+       char *modname;
+       char *logical_modname;
+       char *flag_names;
+       int type;
+       int hash;
+       int hash2;
+} __attribute__((aligned(8)));
+
+int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
+                                       char *flags, int hash, int hash2);
+
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+extern int unregister_dynamic_debug_module(char *mod_name);
+extern int __dynamic_dbg_enabled_helper(char *modname, int type,
+                                       int value, int hash);
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({         \
+       int __ret = 0;                                                       \
+       if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) &&       \
+                       (dynamic_printk_enabled2 & (1LL << DEBUG_HASH2))))   \
+                       __ret = __dynamic_dbg_enabled_helper(module, type,   \
+                                                               value, hash);\
+       __ret; })
+
+#define dynamic_pr_debug(fmt, ...) do {                                            \
+       static char mod_name[]                                              \
+       __attribute__((section("__verbose_strings")))                       \
+        = KBUILD_MODNAME;                                                  \
+       static struct mod_debug descriptor                                  \
+       __used                                                              \
+       __attribute__((section("__verbose"), aligned(8))) =                 \
+       { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+       if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,             \
+                                               0, 0, DEBUG_HASH))          \
+               printk(KERN_DEBUG KBUILD_MODNAME ":" fmt,                   \
+                               ##__VA_ARGS__);                             \
+       } while (0)
+
+#define dynamic_dev_dbg(dev, format, ...) do {                             \
+       static char mod_name[]                                              \
+       __attribute__((section("__verbose_strings")))                       \
+        = KBUILD_MODNAME;                                                  \
+       static struct mod_debug descriptor                                  \
+       __used                                                              \
+       __attribute__((section("__verbose"), aligned(8))) =                 \
+       { mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
+       if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN,             \
+                                               0, 0, DEBUG_HASH))          \
+                       dev_printk(KERN_DEBUG, dev,                         \
+                                       KBUILD_MODNAME ": " format,         \
+                                       ##__VA_ARGS__);                     \
+       } while (0)
+
+#else
+
+static inline int unregister_dynamic_debug_module(const char *mod_name)
+{
+       return 0;
+}
+static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
+                                               int value, int hash)
+{
+       return 0;
+}
+
+#define __dynamic_dbg_enabled(module, type, value, level, hash)  ({ 0; })
+#define dynamic_pr_debug(fmt, ...)  do { } while (0)
+#define dynamic_dev_dbg(dev, format, ...)  do { } while (0)
+#endif
+
+#endif
index 2efe7b863cff361301d4a73c1c4e46338d0b02b1..78c775a83f7cd041acaa872ae455676a06a0e096 100644 (file)
@@ -47,7 +47,7 @@
 #ifdef EXT2FS_DEBUG
 #      define ext2_debug(f, a...)      { \
                                        printk ("EXT2-fs DEBUG (%s, %d): %s:", \
-                                               __FILE__, __LINE__, __FUNCTION__); \
+                                               __FILE__, __LINE__, __func__); \
                                        printk (f, ## a); \
                                        }
 #else
index 8120fa1bc2357008f63c06c78d3304c781bf9341..159d9b476cd7f404c0ae33facd7189e7efe477ad 100644 (file)
@@ -43,7 +43,7 @@
 #define ext3_debug(f, a...)                                            \
        do {                                                            \
                printk (KERN_DEBUG "EXT3-fs DEBUG (%s, %d): %s:",       \
-                       __FILE__, __LINE__, __FUNCTION__);              \
+                       __FILE__, __LINE__, __func__);          \
                printk (KERN_DEBUG f, ## a);                            \
        } while (0)
 #else
@@ -871,7 +871,7 @@ extern void ext3_update_dynamic_rev (struct super_block *sb);
 #define ext3_std_error(sb, errno)                              \
 do {                                                           \
        if ((errno))                                            \
-               __ext3_std_error((sb), __FUNCTION__, (errno));  \
+               __ext3_std_error((sb), __func__, (errno));      \
 } while (0)
 
 /*
index 8c43b13a02fe1df033f161ab91d69cdd7a389858..cf82d519be408b7b97a2a0edd3e796d5eff8c2b5 100644 (file)
@@ -137,17 +137,17 @@ int __ext3_journal_dirty_metadata(const char *where,
                                handle_t *handle, struct buffer_head *bh);
 
 #define ext3_journal_get_undo_access(handle, bh) \
-       __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
+       __ext3_journal_get_undo_access(__func__, (handle), (bh))
 #define ext3_journal_get_write_access(handle, bh) \
-       __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
+       __ext3_journal_get_write_access(__func__, (handle), (bh))
 #define ext3_journal_revoke(handle, blocknr, bh) \
-       __ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
+       __ext3_journal_revoke(__func__, (handle), (blocknr), (bh))
 #define ext3_journal_get_create_access(handle, bh) \
-       __ext3_journal_get_create_access(__FUNCTION__, (handle), (bh))
+       __ext3_journal_get_create_access(__func__, (handle), (bh))
 #define ext3_journal_dirty_metadata(handle, bh) \
-       __ext3_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
+       __ext3_journal_dirty_metadata(__func__, (handle), (bh))
 #define ext3_journal_forget(handle, bh) \
-       __ext3_journal_forget(__FUNCTION__, (handle), (bh))
+       __ext3_journal_forget(__func__, (handle), (bh))
 
 int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
 
@@ -160,7 +160,7 @@ static inline handle_t *ext3_journal_start(struct inode *inode, int nblocks)
 }
 
 #define ext3_journal_stop(handle) \
-       __ext3_journal_stop(__FUNCTION__, (handle))
+       __ext3_journal_stop(__func__, (handle))
 
 static inline handle_t *ext3_journal_current_handle(void)
 {
index 0f0e271f97fa1f0fa7248cafc9c579e8be20fe00..4d078e99c01799ec31ecc3f2387d7305e806b46d 100644 (file)
@@ -154,8 +154,13 @@ struct fw_cdev_event_iso_interrupt {
  * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
  * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
  *
- * Convenience union for userspace use.  Events could be read(2) into a char
- * buffer and then cast to this union for further processing.
+ * Convenience union for userspace use.  Events could be read(2) into an
+ * appropriately aligned char buffer and then cast to this union for further
+ * processing.  Note that for a request, response or iso_interrupt event,
+ * the data[] or header[] may make the size of the full event larger than
+ * sizeof(union fw_cdev_event).  Also note that if you attempt to read(2)
+ * an event into a buffer that is not large enough for it, the data that does
+ * not fit will be discarded so that the next read(2) will return a new event.
  */
 union fw_cdev_event {
        struct fw_cdev_event_common common;
index 44e3cb2f1966d86b4a422fa616b97f485a150c95..a6a625be13fce0c66ca8d034ec69a2ca956be356 100644 (file)
@@ -947,6 +947,14 @@ struct lock_manager_operations {
        int (*fl_change)(struct file_lock **, int);
 };
 
+struct lock_manager {
+       struct list_head list;
+};
+
+void locks_start_grace(struct lock_manager *);
+void locks_end_grace(struct lock_manager *);
+int locks_in_grace(void);
+
 /* that will die - we need it for nfs_lock_info */
 #include <linux/nfs_fs_i.h>
 
@@ -988,6 +996,13 @@ struct file_lock {
 
 #include <linux/fcntl.h>
 
+extern void send_sigio(struct fown_struct *fown, int fd, int band);
+
+/* fs/sync.c */
+extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
+                       loff_t endbyte, unsigned int flags);
+
+#ifdef CONFIG_FILE_LOCKING
 extern int fcntl_getlk(struct file *, struct flock __user *);
 extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
                        struct flock __user *);
@@ -998,14 +1013,9 @@ extern int fcntl_setlk64(unsigned int, struct file *, unsigned int,
                        struct flock64 __user *);
 #endif
 
-extern void send_sigio(struct fown_struct *fown, int fd, int band);
 extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
 extern int fcntl_getlease(struct file *filp);
 
-/* fs/sync.c */
-extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
-                       loff_t endbyte, unsigned int flags);
-
 /* fs/locks.c */
 extern void locks_init_lock(struct file_lock *);
 extern void locks_copy_lock(struct file_lock *, struct file_lock *);
@@ -1028,6 +1038,37 @@ extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
 extern struct seq_operations locks_seq_operations;
+#else /* !CONFIG_FILE_LOCKING */
+#define fcntl_getlk(a, b) ({ -EINVAL; })
+#define fcntl_setlk(a, b, c, d) ({ -EACCES; })
+#if BITS_PER_LONG == 32
+#define fcntl_getlk64(a, b) ({ -EINVAL; })
+#define fcntl_setlk64(a, b, c, d) ({ -EACCES; })
+#endif
+#define fcntl_setlease(a, b, c) ({ 0; })
+#define fcntl_getlease(a) ({ 0; })
+#define locks_init_lock(a) ({ })
+#define __locks_copy_lock(a, b) ({ })
+#define locks_copy_lock(a, b) ({ })
+#define locks_remove_posix(a, b) ({ })
+#define locks_remove_flock(a) ({ })
+#define posix_test_lock(a, b) ({ 0; })
+#define posix_lock_file(a, b, c) ({ -ENOLCK; })
+#define posix_lock_file_wait(a, b) ({ -ENOLCK; })
+#define posix_unblock_lock(a, b) (-ENOENT)
+#define vfs_test_lock(a, b) ({ 0; })
+#define vfs_lock_file(a, b, c, d) (-ENOLCK)
+#define vfs_cancel_lock(a, b) ({ 0; })
+#define flock_lock_file_wait(a, b) ({ -ENOLCK; })
+#define __break_lease(a, b) ({ 0; })
+#define lease_get_mtime(a, b) ({ })
+#define generic_setlease(a, b, c) ({ -EINVAL; })
+#define vfs_setlease(a, b, c) ({ -EINVAL; })
+#define lease_modify(a, b) ({ -EINVAL; })
+#define lock_may_read(a, b, c) ({ 1; })
+#define lock_may_write(a, b, c) ({ 1; })
+#endif /* !CONFIG_FILE_LOCKING */
+
 
 struct fasync_struct {
        int     magic;
@@ -1575,9 +1616,12 @@ extern int vfs_statfs(struct dentry *, struct kstatfs *);
 /* /sys/fs */
 extern struct kobject *fs_kobj;
 
+extern int rw_verify_area(int, struct file *, loff_t *, size_t);
+
 #define FLOCK_VERIFY_READ  1
 #define FLOCK_VERIFY_WRITE 2
 
+#ifdef CONFIG_FILE_LOCKING
 extern int locks_mandatory_locked(struct inode *);
 extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t);
 
@@ -1608,8 +1652,6 @@ static inline int locks_verify_locked(struct inode *inode)
        return 0;
 }
 
-extern int rw_verify_area(int, struct file *, loff_t *, size_t);
-
 static inline int locks_verify_truncate(struct inode *inode,
                                    struct file *filp,
                                    loff_t size)
@@ -1630,6 +1672,15 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
                return __break_lease(inode, mode);
        return 0;
 }
+#else /* !CONFIG_FILE_LOCKING */
+#define locks_mandatory_locked(a) ({ 0; })
+#define locks_mandatory_area(a, b, c, d, e) ({ 0; })
+#define __mandatory_lock(a) ({ 0; })
+#define mandatory_lock(a) ({ 0; })
+#define locks_verify_locked(a) ({ 0; })
+#define locks_verify_truncate(a, b, c) ({ 0; })
+#define break_lease(a, b) ({ 0; })
+#endif /* CONFIG_FILE_LOCKING */
 
 /* fs/open.c */
 
index f64e29c0ef3f57be1b03aeb0703fe30f58ffbbeb..0cd825f7363a7aa61005b53eb658b7e3dfa66b3d 100644 (file)
@@ -146,10 +146,11 @@ static inline void gameport_unpin_driver(struct gameport *gameport)
        mutex_unlock(&gameport->drv_mutex);
 }
 
-void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
-static inline void gameport_register_driver(struct gameport_driver *drv)
+int __gameport_register_driver(struct gameport_driver *drv,
+                               struct module *owner, const char *mod_name);
+static inline int __must_check gameport_register_driver(struct gameport_driver *drv)
 {
-       __gameport_register_driver(drv, THIS_MODULE);
+       return __gameport_register_driver(drv, THIS_MODULE, KBUILD_MODNAME);
 }
 
 void gameport_unregister_driver(struct gameport_driver *drv);
index 730a20b83576b4ab39d81810085c20d61eec0225..e10c49a5b96e9ed300d670871af2edbaaf23add1 100644 (file)
@@ -8,6 +8,7 @@
 
 #else
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 
@@ -32,6 +33,8 @@ static inline int gpio_request(unsigned gpio, const char *label)
 
 static inline void gpio_free(unsigned gpio)
 {
+       might_sleep();
+
        /* GPIO can never have been requested */
        WARN_ON(1);
 }
index ac4e678a04edb497f9194b7eb4939c88bf8bec10..f13bca2dd53b806303577cb298562a3a426b79b4 100644 (file)
@@ -67,6 +67,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/mod_devicetable.h> /* hid_device_id */
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/input.h>
@@ -245,6 +246,19 @@ struct hid_item {
 #define HID_OUTPUT_REPORT      1
 #define HID_FEATURE_REPORT     2
 
+/*
+ * HID connect requests
+ */
+
+#define HID_CONNECT_HIDINPUT           0x01
+#define HID_CONNECT_HIDINPUT_FORCE     0x02
+#define HID_CONNECT_HIDRAW             0x04
+#define HID_CONNECT_HIDDEV             0x08
+#define HID_CONNECT_HIDDEV_FORCE       0x10
+#define HID_CONNECT_FF                 0x20
+#define HID_CONNECT_DEFAULT    (HID_CONNECT_HIDINPUT|HID_CONNECT_HIDRAW| \
+               HID_CONNECT_HIDDEV|HID_CONNECT_FF)
+
 /*
  * HID device quirks.
  */
@@ -256,48 +270,11 @@ struct hid_item {
 
 #define HID_QUIRK_INVERT                       0x00000001
 #define HID_QUIRK_NOTOUCH                      0x00000002
-#define HID_QUIRK_IGNORE                       0x00000004
 #define HID_QUIRK_NOGET                                0x00000008
-#define HID_QUIRK_HIDDEV                       0x00000010
 #define HID_QUIRK_BADPAD                       0x00000020
 #define HID_QUIRK_MULTI_INPUT                  0x00000040
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_7          0x00000080
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_5          0x00000100
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON         0x00000200
-#define HID_QUIRK_MIGHTYMOUSE                  0x00000400
-#define HID_QUIRK_APPLE_HAS_FN                 0x00000800
-#define HID_QUIRK_APPLE_FN_ON                  0x00001000
-#define HID_QUIRK_INVERT_HWHEEL                        0x00002000
-#define HID_QUIRK_APPLE_ISO_KEYBOARD           0x00004000
-#define HID_QUIRK_BAD_RELATIVE_KEYS            0x00008000
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00010000
-#define HID_QUIRK_IGNORE_MOUSE                 0x00020000
-#define HID_QUIRK_SONY_PS3_CONTROLLER          0x00040000
-#define HID_QUIRK_DUPLICATE_USAGES             0x00080000
-#define HID_QUIRK_RESET_LEDS                   0x00100000
-#define HID_QUIRK_HIDINPUT                     0x00200000
-#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL        0x00400000
-#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP     0x00800000
-#define HID_QUIRK_IGNORE_HIDINPUT              0x01000000
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_B8         0x02000000
-#define HID_QUIRK_HWHEEL_WHEEL_INVERT          0x04000000
-#define HID_QUIRK_MICROSOFT_KEYS               0x08000000
 #define HID_QUIRK_FULLSPEED_INTERVAL           0x10000000
-#define HID_QUIRK_APPLE_NUMLOCK_EMULATION      0x20000000
-
-/*
- * Separate quirks for runtime report descriptor fixup
- */
-
-#define HID_QUIRK_RDESC_CYMOTION               0x00000001
-#define HID_QUIRK_RDESC_LOGITECH               0x00000002
-#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX                0x00000004
-#define HID_QUIRK_RDESC_PETALYNX               0x00000008
-#define HID_QUIRK_RDESC_MACBOOK_JIS            0x00000010
-#define HID_QUIRK_RDESC_BUTTON_CONSUMER                0x00000020
-#define HID_QUIRK_RDESC_SAMSUNG_REMOTE         0x00000040
-#define HID_QUIRK_RDESC_MICROSOFT_RECV_1028    0x00000080
-#define HID_QUIRK_RDESC_SUNPLUS_WDESKTOP       0x00000100
 
 /*
  * This is the global environment of the parser. This information is
@@ -411,12 +388,21 @@ struct hid_report_enum {
 struct hid_control_fifo {
        unsigned char dir;
        struct hid_report *report;
+       char *raw_report;
+};
+
+struct hid_output_fifo {
+       struct hid_report *report;
+       char *raw_report;
 };
 
 #define HID_CLAIMED_INPUT      1
 #define HID_CLAIMED_HIDDEV     2
 #define HID_CLAIMED_HIDRAW     4
 
+#define HID_STAT_ADDED         1
+#define HID_STAT_PARSED                2
+
 #define HID_CTRL_RUNNING       1
 #define HID_OUT_RUNNING                2
 #define HID_IN_RUNNING         3
@@ -431,22 +417,28 @@ struct hid_input {
        struct input_dev *input;
 };
 
+struct hid_driver;
+struct hid_ll_driver;
+
 struct hid_device {                                                    /* device report descriptor */
-        __u8 *rdesc;
+       __u8 *rdesc;
        unsigned rsize;
        struct hid_collection *collection;                              /* List of HID collections */
        unsigned collection_size;                                       /* Number of allocated hid_collections */
        unsigned maxcollection;                                         /* Number of parsed collections */
        unsigned maxapplication;                                        /* Number of applications */
-       unsigned short bus;                                             /* BUS ID */
-       unsigned short vendor;                                          /* Vendor ID */
-       unsigned short product;                                         /* Product ID */
-       unsigned version;                                               /* HID version */
+       __u16 bus;                                                      /* BUS ID */
+       __u32 vendor;                                                   /* Vendor ID */
+       __u32 product;                                                  /* Product ID */
+       __u32 version;                                                  /* HID version */
        unsigned country;                                               /* HID country */
        struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-       struct device *dev;                                             /* device */
+       struct device dev;                                              /* device */
+       struct hid_driver *driver;
+       struct hid_ll_driver *ll_driver;
 
+       unsigned int status;                                            /* see STAT flags above */
        unsigned claimed;                                               /* Claimed by hidinput, hiddev? */
        unsigned quirks;                                                /* Various quirks the device can pull on us */
 
@@ -462,26 +454,29 @@ struct hid_device {                                                       /* device report descriptor */
 
        void *driver_data;
 
-       __s32 delayed_value;                                            /* For A4 Tech mice hwheel quirk */
-
-       /* device-specific function pointers */
-       int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
-       int (*hid_open) (struct hid_device *);
-       void (*hid_close) (struct hid_device *);
+       /* temporary hid_ff handling (until moved to the drivers) */
+       int (*ff_init)(struct hid_device *);
 
        /* hiddev event handler */
+       int (*hiddev_connect)(struct hid_device *, unsigned int);
        void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
                                  struct hid_usage *, __s32);
        void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 
        /* handler for raw output data, used by hidraw */
        int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-       unsigned long apple_pressed_fn[BITS_TO_LONGS(KEY_CNT)];
-       unsigned long pb_pressed_numlock[BITS_TO_LONGS(KEY_CNT)];
-#endif
 };
 
+static inline void *hid_get_drvdata(struct hid_device *hdev)
+{
+       return dev_get_drvdata(&hdev->dev);
+}
+
+static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
+{
+       dev_set_drvdata(&hdev->dev, data);
+}
+
 #define HID_GLOBAL_STACK_SIZE 4
 #define HID_COLLECTION_STACK_SIZE 4
 
@@ -510,6 +505,107 @@ struct hid_descriptor {
        struct hid_class_descriptor desc[1];
 } __attribute__ ((packed));
 
+#define HID_DEVICE(b, ven, prod) \
+       .bus = (b), \
+       .vendor = (ven), .product = (prod)
+
+#define HID_USB_DEVICE(ven, prod)      HID_DEVICE(BUS_USB, ven, prod)
+#define HID_BLUETOOTH_DEVICE(ven, prod)        HID_DEVICE(BUS_BLUETOOTH, ven, prod)
+
+#define HID_REPORT_ID(rep) \
+       .report_type = (rep)
+#define HID_USAGE_ID(uhid, utype, ucode) \
+       .usage_hid = (uhid), .usage_type = (utype), .usage_code = (ucode)
+/* we don't want to catch types and codes equal to 0 */
+#define HID_TERMINATOR         (HID_ANY_ID - 1)
+
+struct hid_report_id {
+       __u32 report_type;
+};
+struct hid_usage_id {
+       __u32 usage_hid;
+       __u32 usage_type;
+       __u32 usage_code;
+};
+
+/**
+ * struct hid_driver
+ * @name: driver name (e.g. "Footech_bar-wheel")
+ * @id_table: which devices is this driver for (must be non-NULL for probe
+ *           to be called)
+ * @probe: new device inserted
+ * @remove: device removed (NULL if not a hot-plug capable driver)
+ * @report_table: on which reports to call raw_event (NULL means all)
+ * @raw_event: if report in report_table, this hook is called (NULL means nop)
+ * @usage_table: on which events to call event (NULL means all)
+ * @event: if usage in usage_table, this hook is called (NULL means nop)
+ * @report_fixup: called before report descriptor parsing (NULL means nop)
+ * @input_mapping: invoked on input registering before mapping an usage
+ * @input_mapped: invoked on input registering after mapping an usage
+ *
+ * raw_event and event should return 0 on no action performed, 1 when no
+ * further processing should be done and negative on error
+ *
+ * input_mapping shall return a negative value to completely ignore this usage
+ * (e.g. doubled or invalid usage), zero to continue with parsing of this
+ * usage by generic code (no special handling needed) or positive to skip
+ * generic parsing (needed special handling which was done in the hook already)
+ * input_mapped shall return negative to inform the layer that this usage
+ * should not be considered for further processing or zero to notify that
+ * no processing was performed and should be done in a generic manner
+ * Both these functions may be NULL which means the same behavior as returning
+ * zero from them.
+ */
+struct hid_driver {
+       char *name;
+       const struct hid_device_id *id_table;
+
+       int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
+       void (*remove)(struct hid_device *dev);
+
+       const struct hid_report_id *report_table;
+       int (*raw_event)(struct hid_device *hdev, struct hid_report *report,
+                       u8 *data, int size);
+       const struct hid_usage_id *usage_table;
+       int (*event)(struct hid_device *hdev, struct hid_field *field,
+                       struct hid_usage *usage, __s32 value);
+
+       void (*report_fixup)(struct hid_device *hdev, __u8 *buf,
+                       unsigned int size);
+
+       int (*input_mapping)(struct hid_device *hdev,
+                       struct hid_input *hidinput, struct hid_field *field,
+                       struct hid_usage *usage, unsigned long **bit, int *max);
+       int (*input_mapped)(struct hid_device *hdev,
+                       struct hid_input *hidinput, struct hid_field *field,
+                       struct hid_usage *usage, unsigned long **bit, int *max);
+/* private: */
+       struct device_driver driver;
+};
+
+/**
+ * hid_ll_driver - low level driver callbacks
+ * @start: called on probe to start the device
+ * @stop: called on remove
+ * @open: called by input layer on open
+ * @close: called by input layer on close
+ * @hidinput_input_event: event input event (e.g. ff or leds)
+ * @parse: this method is called only once to parse the device data,
+ *        shouldn't allocate anything to not leak memory
+ */
+struct hid_ll_driver {
+       int (*start)(struct hid_device *hdev);
+       void (*stop)(struct hid_device *hdev);
+
+       int (*open)(struct hid_device *hdev);
+       void (*close)(struct hid_device *hdev);
+
+       int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
+                       unsigned int code, int value);
+
+       int (*parse)(struct hid_device *hdev);
+};
+
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002))
@@ -520,43 +616,157 @@ struct hid_descriptor {
 extern int hid_debug;
 #endif
 
+extern int hid_add_device(struct hid_device *);
+extern void hid_destroy_device(struct hid_device *);
+
+extern int __must_check __hid_register_driver(struct hid_driver *,
+               struct module *, const char *mod_name);
+static inline int __must_check hid_register_driver(struct hid_driver *driver)
+{
+       return __hid_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
+}
+extern void hid_unregister_driver(struct hid_driver *);
+
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
-extern int hidinput_connect(struct hid_device *);
+extern int hidinput_connect(struct hid_device *hid, unsigned int force);
 extern void hidinput_disconnect(struct hid_device *);
 
 int hid_set_field(struct hid_field *, unsigned, __s32);
 int hid_input_report(struct hid_device *, int type, u8 *, int, int);
 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
-int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *);
-int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
 void hid_output_report(struct hid_report *report, __u8 *data);
-void hid_free_device(struct hid_device *device);
-struct hid_device *hid_parse_report(__u8 *start, unsigned size);
+struct hid_device *hid_allocate_device(void);
+int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
+int hid_connect(struct hid_device *hid, unsigned int connect_mask);
+
+/**
+ * hid_map_usage - map usage input bits
+ *
+ * @hidinput: hidinput which we are interested in
+ * @usage: usage to fill in
+ * @bit: pointer to input->{}bit (out parameter)
+ * @max: maximal valid usage->code to consider later (out parameter)
+ * @type: input event type (EV_KEY, EV_REL, ...)
+ * @c: code which corresponds to this usage and type
+ */
+static inline void hid_map_usage(struct hid_input *hidinput,
+               struct hid_usage *usage, unsigned long **bit, int *max,
+               __u8 type, __u16 c)
+{
+       struct input_dev *input = hidinput->input;
+
+       usage->type = type;
+       usage->code = c;
+
+       switch (type) {
+       case EV_ABS:
+               *bit = input->absbit;
+               *max = ABS_MAX;
+               break;
+       case EV_REL:
+               *bit = input->relbit;
+               *max = REL_MAX;
+               break;
+       case EV_KEY:
+               *bit = input->keybit;
+               *max = KEY_MAX;
+               break;
+       case EV_LED:
+               *bit = input->ledbit;
+               *max = LED_MAX;
+               break;
+       }
+}
+
+/**
+ * hid_map_usage_clear - map usage input bits and clear the input bit
+ *
+ * The same as hid_map_usage, except the @c bit is also cleared in supported
+ * bits (@bit).
+ */
+static inline void hid_map_usage_clear(struct hid_input *hidinput,
+               struct hid_usage *usage, unsigned long **bit, int *max,
+               __u8 type, __u16 c)
+{
+       hid_map_usage(hidinput, usage, bit, max, type, c);
+       clear_bit(c, *bit);
+}
+
+/**
+ * hid_parse - parse HW reports
+ *
+ * @hdev: hid device
+ *
+ * Call this from probe after you set up the device (if needed). Your
+ * report_fixup will be called (if non-NULL) after reading raw report from
+ * device before passing it to hid layer for real parsing.
+ */
+static inline int __must_check hid_parse(struct hid_device *hdev)
+{
+       int ret;
+
+       if (hdev->status & HID_STAT_PARSED)
+               return 0;
+
+       ret = hdev->ll_driver->parse(hdev);
+       if (!ret)
+               hdev->status |= HID_STAT_PARSED;
+
+       return ret;
+}
+
+/**
+ * hid_hw_start - start underlaying HW
+ *
+ * @hdev: hid device
+ * @connect_mask: which outputs to connect, see HID_CONNECT_*
+ *
+ * Call this in probe function *after* hid_parse. This will setup HW buffers
+ * and start the device (if not deffered to device open). hid_hw_stop must be
+ * called if this was successfull.
+ */
+static inline int __must_check hid_hw_start(struct hid_device *hdev,
+               unsigned int connect_mask)
+{
+       int ret = hdev->ll_driver->start(hdev);
+       if (ret || !connect_mask)
+               return ret;
+       ret = hid_connect(hdev, connect_mask);
+       if (ret)
+               hdev->ll_driver->stop(hdev);
+       return ret;
+}
+
+/**
+ * hid_hw_stop - stop underlaying HW
+ *
+ * @hdev: hid device
+ *
+ * This is usually called from remove function or from probe when something
+ * failed and hid_hw_start was called already.
+ */
+static inline void hid_hw_stop(struct hid_device *hdev)
+{
+       hdev->ll_driver->stop(hdev);
+}
+
+void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
+               int interrupt);
+
+extern int hid_generic_init(void);
+extern void hid_generic_exit(void);
 
 /* HID quirks API */
 u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
 int usbhid_quirks_init(char **quirks_param);
 void usbhid_quirks_exit(void);
-void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
-
-#ifdef CONFIG_HID_FF
-int hid_ff_init(struct hid_device *hid);
+void usbhid_set_leds(struct hid_device *hid);
 
-int hid_lgff_init(struct hid_device *hid);
-int hid_lg2ff_init(struct hid_device *hid);
-int hid_plff_init(struct hid_device *hid);
-int hid_tmff_init(struct hid_device *hid);
-int hid_zpff_init(struct hid_device *hid);
 #ifdef CONFIG_HID_PID
 int hid_pidff_init(struct hid_device *hid);
 #else
-static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
-#endif
-
-#else
-static inline int hid_ff_init(struct hid_device *hid) { return -1; }
+#define hid_pidff_init NULL
 #endif
 
 #ifdef CONFIG_HID_DEBUG
@@ -572,10 +782,23 @@ dbg_hid(const char *fmt, ...)
        return 0;
 }
 #define dbg_hid_line dbg_hid
-#endif
+#endif /* HID_DEBUG */
 
 #define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
                __FILE__ , ## arg)
-#endif
+#endif /* HID_FF */
+
+#ifdef CONFIG_HID_COMPAT
+#define HID_COMPAT_LOAD_DRIVER(name)   \
+void hid_compat_##name(void) { }       \
+EXPORT_SYMBOL(hid_compat_##name)
+#else
+#define HID_COMPAT_LOAD_DRIVER(name)
+#endif /* HID_COMPAT */
+#define HID_COMPAT_CALL_DRIVER(name)   do {    \
+       extern void hid_compat_##name(void);    \
+       hid_compat_##name();                    \
+} while (0)
+
 #endif
 
index a416b904ba900c2bae4453547bb8f01f818fe251..c760ae0eb6a12b8842297388d2d86ec14f20291c 100644 (file)
@@ -182,26 +182,28 @@ struct hiddev_usage_ref_multi {
 /* To traverse the input report descriptor info for a HID device, perform the 
  * following:
  *
- *  rinfo.report_type = HID_REPORT_TYPE_INPUT;
- *  rinfo.report_id = HID_REPORT_ID_FIRST;
- *  ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+ * rinfo.report_type = HID_REPORT_TYPE_INPUT;
+ * rinfo.report_id = HID_REPORT_ID_FIRST;
+ * ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
  *
- *  while (ret >= 0) {
- *      for (i = 0; i < rinfo.num_fields; i++) { 
- *         finfo.report_type = rinfo.report_type;
- *          finfo.report_id = rinfo.report_id;
- *          finfo.field_index = i;
- *          ioctl(fd, HIDIOCGFIELDINFO, &finfo);
- *          for (j = 0; j < finfo.maxusage; j++) {
- *              uref.field_index = i;
- *             uref.usage_index = j;
- *             ioctl(fd, HIDIOCGUCODE, &uref);
- *             ioctl(fd, HIDIOCGUSAGE, &uref);
- *          }
- *     }
- *     rinfo.report_id |= HID_REPORT_ID_NEXT;
- *     ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
- *  }
+ * while (ret >= 0) {
+ *     for (i = 0; i < rinfo.num_fields; i++) {
+ *             finfo.report_type = rinfo.report_type;
+ *             finfo.report_id = rinfo.report_id;
+ *             finfo.field_index = i;
+ *             ioctl(fd, HIDIOCGFIELDINFO, &finfo);
+ *             for (j = 0; j < finfo.maxusage; j++) {
+ *                     uref.report_type = rinfo.report_type;
+ *                     uref.report_id = rinfo.report_id;
+ *                     uref.field_index = i;
+ *                     uref.usage_index = j;
+ *                     ioctl(fd, HIDIOCGUCODE, &uref);
+ *                     ioctl(fd, HIDIOCGUSAGE, &uref);
+ *             }
+ *     }
+ *     rinfo.report_id |= HID_REPORT_ID_NEXT;
+ *     ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+ * }
  */
 
 
@@ -217,7 +219,7 @@ struct hid_field;
 struct hid_report;
 
 #ifdef CONFIG_USB_HIDDEV
-int hiddev_connect(struct hid_device *);
+int hiddev_connect(struct hid_device *hid, unsigned int force);
 void hiddev_disconnect(struct hid_device *);
 void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
                      struct hid_usage *usage, __s32 value);
@@ -225,7 +227,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
 int __init hiddev_init(void);
 void hiddev_exit(void);
 #else
-static inline int hiddev_connect(struct hid_device *hid) { return -1; }
+static inline int hiddev_connect(struct hid_device *hid,
+               unsigned int force)
+{ return -1; }
 static inline void hiddev_disconnect(struct hid_device *hid) { }
 static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
                      struct hid_usage *usage, __s32 value) { }
index 2dc29ce6c8e482da3a640290d517da90a525e422..79f63a27bcef0817752cc5c27762ae81a2fb9092 100644 (file)
@@ -37,6 +37,7 @@ struct hpet {
 #define        hpet_compare    _u1._hpet_compare
 
 #define        HPET_MAX_TIMERS (32)
+#define        HPET_MAX_IRQ    (32)
 
 /*
  * HPET general capabilities register
@@ -64,7 +65,7 @@ struct hpet {
  */
 
 #define        Tn_INT_ROUTE_CAP_MASK           (0xffffffff00000000ULL)
-#define        Tn_INI_ROUTE_CAP_SHIFT          (32UL)
+#define        Tn_INT_ROUTE_CAP_SHIFT          (32UL)
 #define        Tn_FSB_INT_DELCAP_MASK          (0x8000UL)
 #define        Tn_FSB_INT_DELCAP_SHIFT         (15)
 #define        Tn_FSB_EN_CNF_MASK              (0x4000UL)
@@ -91,23 +92,14 @@ struct hpet {
  * exported interfaces
  */
 
-struct hpet_task {
-       void (*ht_func) (void *);
-       void *ht_data;
-       void *ht_opaque;
-};
-
 struct hpet_data {
        unsigned long hd_phys_address;
        void __iomem *hd_address;
        unsigned short hd_nirqs;
-       unsigned short hd_flags;
        unsigned int hd_state;  /* timer allocated */
        unsigned int hd_irq[HPET_MAX_TIMERS];
 };
 
-#define        HPET_DATA_PLATFORM      0x0001  /* platform call to hpet_alloc */
-
 static inline void hpet_reserve_timer(struct hpet_data *hd, int timer)
 {
        hd->hd_state |= (1 << timer);
@@ -125,7 +117,7 @@ struct hpet_info {
        unsigned short hi_timer;
 };
 
-#define        HPET_INFO_PERIODIC      0x0001  /* timer is periodic */
+#define HPET_INFO_PERIODIC     0x0010  /* periodic-capable comparator */
 
 #define        HPET_IE_ON      _IO('h', 0x01)  /* interrupt on */
 #define        HPET_IE_OFF     _IO('h', 0x02)  /* interrupt off */
index bf34c5f4c0511abc17c664655559918e2da01ef5..493435bcdbe52189c9e55fab95b03a614447a799 100644 (file)
@@ -41,7 +41,6 @@
 #define I2C_DRIVERID_SAA7110   22      /* video decoder                */
 #define I2C_DRIVERID_SAA5249   24      /* SAA5249 and compatibles      */
 #define I2C_DRIVERID_PCF8583   25      /* real time clock              */
-#define I2C_DRIVERID_SAB3036   26      /* SAB3036 tuner                */
 #define I2C_DRIVERID_TDA7432   27      /* Stereo sound processor       */
 #define I2C_DRIVERID_TVMIXER    28      /* Mixer driver for tv cards    */
 #define I2C_DRIVERID_TVAUDIO    29      /* Generic TV sound driver      */
index 75ae6d8aba4fff5167faf5e8b570f78956ccef91..4c4e57d1f19d74c245c7e70e09c5e9428f838089 100644 (file)
@@ -570,7 +570,6 @@ struct i2o_controller {
 #endif
        spinlock_t lock;        /* lock for controller
                                   configuration */
-
        void *driver_data[I2O_MAX_DRIVERS];     /* storage for drivers */
 };
 
@@ -691,289 +690,22 @@ static inline u32 i2o_dma_high(dma_addr_t dma_addr)
 };
 #endif
 
-/**
- *     i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
- *     @c: I2O controller for which the calculation should be done
- *     @body_size: maximum body size used for message in 32-bit words.
- *
- *     Return the maximum number of SG elements in a SG list.
- */
-static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
-{
-       i2o_status_block *sb = c->status_block.virt;
-       u16 sg_count =
-           (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
-           body_size;
-
-       if (c->pae_support) {
-               /*
-                * for 64-bit a SG attribute element must be added and each
-                * SG element needs 12 bytes instead of 8.
-                */
-               sg_count -= 2;
-               sg_count /= 3;
-       } else
-               sg_count /= 2;
-
-       if (c->short_req && (sg_count > 8))
-               sg_count = 8;
-
-       return sg_count;
-};
-
-/**
- *     i2o_dma_map_single - Map pointer to controller and fill in I2O message.
- *     @c: I2O controller
- *     @ptr: pointer to the data which should be mapped
- *     @size: size of data in bytes
- *     @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
- *     @sg_ptr: pointer to the SG list inside the I2O message
- *
- *     This function does all necessary DMA handling and also writes the I2O
- *     SGL elements into the I2O message. For details on DMA handling see also
- *     dma_map_single(). The pointer sg_ptr will only be set to the end of the
- *     SG list if the allocation was successful.
- *
- *     Returns DMA address which must be checked for failures using
- *     dma_mapping_error().
- */
-static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
+extern u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size);
+extern dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
                                            size_t size,
                                            enum dma_data_direction direction,
-                                           u32 ** sg_ptr)
-{
-       u32 sg_flags;
-       u32 *mptr = *sg_ptr;
-       dma_addr_t dma_addr;
-
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               sg_flags = 0xd4000000;
-               break;
-       case DMA_FROM_DEVICE:
-               sg_flags = 0xd0000000;
-               break;
-       default:
-               return 0;
-       }
-
-       dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
-       if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
-               if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
-                       *mptr++ = cpu_to_le32(0x7C020002);
-                       *mptr++ = cpu_to_le32(PAGE_SIZE);
-               }
-#endif
-
-               *mptr++ = cpu_to_le32(sg_flags | size);
-               *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
-               if ((sizeof(dma_addr_t) > 4) && c->pae_support)
-                       *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));
-#endif
-               *sg_ptr = mptr;
-       }
-       return dma_addr;
-};
-
-/**
- *     i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
- *     @c: I2O controller
- *     @sg: SG list to be mapped
- *     @sg_count: number of elements in the SG list
- *     @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
- *     @sg_ptr: pointer to the SG list inside the I2O message
- *
- *     This function does all necessary DMA handling and also writes the I2O
- *     SGL elements into the I2O message. For details on DMA handling see also
- *     dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
- *     list if the allocation was successful.
- *
- *     Returns 0 on failure or 1 on success.
- */
-static inline int i2o_dma_map_sg(struct i2o_controller *c,
+                                           u32 ** sg_ptr);
+extern int i2o_dma_map_sg(struct i2o_controller *c,
                                 struct scatterlist *sg, int sg_count,
                                 enum dma_data_direction direction,
-                                u32 ** sg_ptr)
-{
-       u32 sg_flags;
-       u32 *mptr = *sg_ptr;
-
-       switch (direction) {
-       case DMA_TO_DEVICE:
-               sg_flags = 0x14000000;
-               break;
-       case DMA_FROM_DEVICE:
-               sg_flags = 0x10000000;
-               break;
-       default:
-               return 0;
-       }
-
-       sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
-       if (!sg_count)
-               return 0;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
-       if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
-               *mptr++ = cpu_to_le32(0x7C020002);
-               *mptr++ = cpu_to_le32(PAGE_SIZE);
-       }
-#endif
-
-       while (sg_count-- > 0) {
-               if (!sg_count)
-                       sg_flags |= 0xC0000000;
-               *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));
-               *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
-               if ((sizeof(dma_addr_t) > 4) && c->pae_support)
-                       *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
-#endif
-               sg = sg_next(sg);
-       }
-       *sg_ptr = mptr;
-
-       return 1;
-};
-
-/**
- *     i2o_dma_alloc - Allocate DMA memory
- *     @dev: struct device pointer to the PCI device of the I2O controller
- *     @addr: i2o_dma struct which should get the DMA buffer
- *     @len: length of the new DMA memory
- *     @gfp_mask: GFP mask
- *
- *     Allocate a coherent DMA memory and write the pointers into addr.
- *
- *     Returns 0 on success or -ENOMEM on failure.
- */
-static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
-                               size_t len, gfp_t gfp_mask)
-{
-       struct pci_dev *pdev = to_pci_dev(dev);
-       int dma_64 = 0;
-
-       if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
-               dma_64 = 1;
-               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
-                       return -ENOMEM;
-       }
-
-       addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
-
-       if ((sizeof(dma_addr_t) > 4) && dma_64)
-               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
-                       printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
-
-       if (!addr->virt)
-               return -ENOMEM;
-
-       memset(addr->virt, 0, len);
-       addr->len = len;
-
-       return 0;
-};
-
-/**
- *     i2o_dma_free - Free DMA memory
- *     @dev: struct device pointer to the PCI device of the I2O controller
- *     @addr: i2o_dma struct which contains the DMA buffer
- *
- *     Free a coherent DMA memory and set virtual address of addr to NULL.
- */
-static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
-{
-       if (addr->virt) {
-               if (addr->phys)
-                       dma_free_coherent(dev, addr->len, addr->virt,
-                                         addr->phys);
-               else
-                       kfree(addr->virt);
-               addr->virt = NULL;
-       }
-};
-
-/**
- *     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.
- */
-static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
-                                 size_t len, gfp_t gfp_mask)
-{
-       i2o_dma_free(dev, addr);
-
-       if (len)
-               return i2o_dma_alloc(dev, addr, len, gfp_mask);
-
-       return 0;
-};
-
-/*
- *     i2o_pool_alloc - Allocate an slab cache and mempool
- *     @mempool: pointer to struct i2o_pool to write data into.
- *     @name: name which is used to identify cache
- *     @size: size of each object
- *     @min_nr: minimum number of objects
- *
- *     First allocates a slab cache with name and size. Then allocates a
- *     mempool which uses the slab cache for allocation and freeing.
- *
- *     Returns 0 on success or negative error code on failure.
- */
-static inline int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
-                                size_t size, int min_nr)
-{
-       pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-       if (!pool->name)
-               goto exit;
-       strcpy(pool->name, name);
-
-       pool->slab =
-           kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);
-       if (!pool->slab)
-               goto free_name;
-
-       pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);
-       if (!pool->mempool)
-               goto free_slab;
-
-       return 0;
-
-      free_slab:
-       kmem_cache_destroy(pool->slab);
-
-      free_name:
-       kfree(pool->name);
-
-      exit:
-       return -ENOMEM;
-};
-
-/*
- *     i2o_pool_free - Free slab cache and mempool again
- *     @mempool: pointer to struct i2o_pool which should be freed
- *
- *     Note that you have to return all objects to the mempool again before
- *     calling i2o_pool_free().
- */
-static inline void i2o_pool_free(struct i2o_pool *pool)
-{
-       mempool_destroy(pool->mempool);
-       kmem_cache_destroy(pool->slab);
-       kfree(pool->name);
-};
-
+                                u32 ** sg_ptr);
+extern int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len);
+extern void i2o_dma_free(struct device *dev, struct i2o_dma *addr);
+extern int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
+                                                               size_t len);
+extern int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
+                                size_t size, int min_nr);
+extern void i2o_pool_free(struct i2o_pool *pool);
 /* I2O driver (OSM) functions */
 extern int i2o_driver_register(struct i2o_driver *);
 extern void i2o_driver_unregister(struct i2o_driver *);
index 03067443198a3baf0e5bef0c3ba0dfa05499fd1d..a93a8dd33118f5fe900e2e6a2e79672bdb1f1319 100644 (file)
@@ -40,16 +40,18 @@ struct icmp6hdr {
                 struct icmpv6_nd_ra {
                        __u8            hop_limit;
 #if defined(__LITTLE_ENDIAN_BITFIELD)
-                       __u8            reserved:4,
+                       __u8            reserved:3,
                                        router_pref:2,
+                                       home_agent:1,
                                        other:1,
                                        managed:1;
 
 #elif defined(__BIG_ENDIAN_BITFIELD)
                        __u8            managed:1,
                                        other:1,
+                                       home_agent:1,
                                        router_pref:2,
-                                       reserved:4;
+                                       reserved:3;
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
index a9d82d6e6bdd68e05e0e6eb016a619d6526f6ece..c47e371554c1ccb122945ab087eb4c9914480010 100644 (file)
@@ -48,12 +48,6 @@ typedef unsigned char        byte;   /* used everywhere */
 #define ERROR_RESET    3       /* Reset controller every 4th retry */
 #define ERROR_RECAL    1       /* Recalibrate every 2nd retry */
 
-/*
- * state flags
- */
-
-#define DMA_PIO_RETRY  1       /* retrying in PIO */
-
 #define HWIF(drive)            ((ide_hwif_t *)((drive)->hwif))
 #define HWGROUP(drive)         ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
 
@@ -162,6 +156,8 @@ enum {
  */
 #define REQ_DRIVE_RESET                0x20
 #define REQ_DEVSET_EXEC                0x21
+#define REQ_PARK_HEADS         0x22
+#define REQ_UNPARK_HEADS       0x23
 
 /*
  * Check for an interrupt and acknowledge the interrupt status
@@ -268,8 +264,6 @@ static inline int __ide_default_irq(unsigned long base)
  * set_geometry        : respecify drive geometry
  * recalibrate : seek to cyl 0
  * set_multmode        : set multmode count
- * set_tune    : tune interface for drive
- * serviced    : service command
  * reserved    : unused
  */
 typedef union {
@@ -278,42 +272,10 @@ typedef union {
                unsigned set_geometry   : 1;
                unsigned recalibrate    : 1;
                unsigned set_multmode   : 1;
-               unsigned set_tune       : 1;
-               unsigned serviced       : 1;
-               unsigned reserved       : 3;
+               unsigned reserved       : 5;
        } b;
 } special_t;
 
-/*
- * ATA-IDE Select Register, aka Device-Head
- *
- * head                : always zeros here
- * unit                : drive select number: 0/1
- * bit5                : always 1
- * lba         : using LBA instead of CHS
- * bit7                : always 1
- */
-typedef union {
-       unsigned all                    : 8;
-       struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-               unsigned head           : 4;
-               unsigned unit           : 1;
-               unsigned bit5           : 1;
-               unsigned lba            : 1;
-               unsigned bit7           : 1;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-               unsigned bit7           : 1;
-               unsigned lba            : 1;
-               unsigned bit5           : 1;
-               unsigned unit           : 1;
-               unsigned head           : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-       } b;
-} select_t, ata_select_t;
-
 /*
  * Status returned from various ide_ functions
  */
@@ -322,6 +284,175 @@ typedef enum {
        ide_started,    /* a drive operation was started, handler was set */
 } ide_startstop_t;
 
+enum {
+       IDE_TFLAG_LBA48                 = (1 << 0),
+       IDE_TFLAG_FLAGGED               = (1 << 2),
+       IDE_TFLAG_OUT_DATA              = (1 << 3),
+       IDE_TFLAG_OUT_HOB_FEATURE       = (1 << 4),
+       IDE_TFLAG_OUT_HOB_NSECT         = (1 << 5),
+       IDE_TFLAG_OUT_HOB_LBAL          = (1 << 6),
+       IDE_TFLAG_OUT_HOB_LBAM          = (1 << 7),
+       IDE_TFLAG_OUT_HOB_LBAH          = (1 << 8),
+       IDE_TFLAG_OUT_HOB               = IDE_TFLAG_OUT_HOB_FEATURE |
+                                         IDE_TFLAG_OUT_HOB_NSECT |
+                                         IDE_TFLAG_OUT_HOB_LBAL |
+                                         IDE_TFLAG_OUT_HOB_LBAM |
+                                         IDE_TFLAG_OUT_HOB_LBAH,
+       IDE_TFLAG_OUT_FEATURE           = (1 << 9),
+       IDE_TFLAG_OUT_NSECT             = (1 << 10),
+       IDE_TFLAG_OUT_LBAL              = (1 << 11),
+       IDE_TFLAG_OUT_LBAM              = (1 << 12),
+       IDE_TFLAG_OUT_LBAH              = (1 << 13),
+       IDE_TFLAG_OUT_TF                = IDE_TFLAG_OUT_FEATURE |
+                                         IDE_TFLAG_OUT_NSECT |
+                                         IDE_TFLAG_OUT_LBAL |
+                                         IDE_TFLAG_OUT_LBAM |
+                                         IDE_TFLAG_OUT_LBAH,
+       IDE_TFLAG_OUT_DEVICE            = (1 << 14),
+       IDE_TFLAG_WRITE                 = (1 << 15),
+       IDE_TFLAG_FLAGGED_SET_IN_FLAGS  = (1 << 16),
+       IDE_TFLAG_IN_DATA               = (1 << 17),
+       IDE_TFLAG_CUSTOM_HANDLER        = (1 << 18),
+       IDE_TFLAG_DMA_PIO_FALLBACK      = (1 << 19),
+       IDE_TFLAG_IN_HOB_FEATURE        = (1 << 20),
+       IDE_TFLAG_IN_HOB_NSECT          = (1 << 21),
+       IDE_TFLAG_IN_HOB_LBAL           = (1 << 22),
+       IDE_TFLAG_IN_HOB_LBAM           = (1 << 23),
+       IDE_TFLAG_IN_HOB_LBAH           = (1 << 24),
+       IDE_TFLAG_IN_HOB_LBA            = IDE_TFLAG_IN_HOB_LBAL |
+                                         IDE_TFLAG_IN_HOB_LBAM |
+                                         IDE_TFLAG_IN_HOB_LBAH,
+       IDE_TFLAG_IN_HOB                = IDE_TFLAG_IN_HOB_FEATURE |
+                                         IDE_TFLAG_IN_HOB_NSECT |
+                                         IDE_TFLAG_IN_HOB_LBA,
+       IDE_TFLAG_IN_FEATURE            = (1 << 1),
+       IDE_TFLAG_IN_NSECT              = (1 << 25),
+       IDE_TFLAG_IN_LBAL               = (1 << 26),
+       IDE_TFLAG_IN_LBAM               = (1 << 27),
+       IDE_TFLAG_IN_LBAH               = (1 << 28),
+       IDE_TFLAG_IN_LBA                = IDE_TFLAG_IN_LBAL |
+                                         IDE_TFLAG_IN_LBAM |
+                                         IDE_TFLAG_IN_LBAH,
+       IDE_TFLAG_IN_TF                 = IDE_TFLAG_IN_NSECT |
+                                         IDE_TFLAG_IN_LBA,
+       IDE_TFLAG_IN_DEVICE             = (1 << 29),
+       IDE_TFLAG_HOB                   = IDE_TFLAG_OUT_HOB |
+                                         IDE_TFLAG_IN_HOB,
+       IDE_TFLAG_TF                    = IDE_TFLAG_OUT_TF |
+                                         IDE_TFLAG_IN_TF,
+       IDE_TFLAG_DEVICE                = IDE_TFLAG_OUT_DEVICE |
+                                         IDE_TFLAG_IN_DEVICE,
+       /* force 16-bit I/O operations */
+       IDE_TFLAG_IO_16BIT              = (1 << 30),
+       /* ide_task_t was allocated using kmalloc() */
+       IDE_TFLAG_DYN                   = (1 << 31),
+};
+
+struct ide_taskfile {
+       u8      hob_data;       /*  0: high data byte (for TASKFILE IOCTL) */
+
+       u8      hob_feature;    /*  1-5: additional data to support LBA48 */
+       u8      hob_nsect;
+       u8      hob_lbal;
+       u8      hob_lbam;
+       u8      hob_lbah;
+
+       u8      data;           /*  6: low data byte (for TASKFILE IOCTL) */
+
+       union {                 /*  7: */
+               u8 error;       /*   read:  error */
+               u8 feature;     /*  write: feature */
+       };
+
+       u8      nsect;          /*  8: number of sectors */
+       u8      lbal;           /*  9: LBA low */
+       u8      lbam;           /* 10: LBA mid */
+       u8      lbah;           /* 11: LBA high */
+
+       u8      device;         /* 12: device select */
+
+       union {                 /* 13: */
+               u8 status;      /*  read: status  */
+               u8 command;     /* write: command */
+       };
+};
+
+typedef struct ide_task_s {
+       union {
+               struct ide_taskfile     tf;
+               u8                      tf_array[14];
+       };
+       u32                     tf_flags;
+       int                     data_phase;
+       struct request          *rq;            /* copy of request */
+       void                    *special;       /* valid_t generally */
+} ide_task_t;
+
+/* ATAPI packet command flags */
+enum {
+       /* set when an error is considered normal - no retry (ide-tape) */
+       PC_FLAG_ABORT                   = (1 << 0),
+       PC_FLAG_SUPPRESS_ERROR          = (1 << 1),
+       PC_FLAG_WAIT_FOR_DSC            = (1 << 2),
+       PC_FLAG_DMA_OK                  = (1 << 3),
+       PC_FLAG_DMA_IN_PROGRESS         = (1 << 4),
+       PC_FLAG_DMA_ERROR               = (1 << 5),
+       PC_FLAG_WRITING                 = (1 << 6),
+       /* command timed out */
+       PC_FLAG_TIMEDOUT                = (1 << 7),
+};
+
+/*
+ * With each packet command, we allocate a buffer of IDE_PC_BUFFER_SIZE bytes.
+ * This is used for several packet commands (not for READ/WRITE commands).
+ */
+#define IDE_PC_BUFFER_SIZE     256
+
+struct ide_atapi_pc {
+       /* actual packet bytes */
+       u8 c[12];
+       /* incremented on each retry */
+       int retries;
+       int error;
+
+       /* bytes to transfer */
+       int req_xfer;
+       /* bytes actually transferred */
+       int xferred;
+
+       /* data buffer */
+       u8 *buf;
+       /* current buffer position */
+       u8 *cur_pos;
+       int buf_size;
+       /* missing/available data on the current buffer */
+       int b_count;
+
+       /* the corresponding request */
+       struct request *rq;
+
+       unsigned long flags;
+
+       /*
+        * those are more or less driver-specific and some of them are subject
+        * to change/removal later.
+        */
+       u8 pc_buf[IDE_PC_BUFFER_SIZE];
+
+       /* idetape only */
+       struct idetape_bh *bh;
+       char *b_data;
+
+       /* idescsi only for now */
+       struct scatterlist *sg;
+       unsigned int sg_cnt;
+
+       struct scsi_cmnd *scsi_cmd;
+       void (*done) (struct scsi_cmnd *);
+
+       unsigned long timeout;
+};
+
 struct ide_devset;
 struct ide_driver_s;
 
@@ -394,6 +525,62 @@ enum {
        IDE_AFLAG_NO_AUTOCLOSE          = (1 << 29),
 };
 
+/* device flags */
+enum {
+       /* restore settings after device reset */
+       IDE_DFLAG_KEEP_SETTINGS         = (1 << 0),
+       /* device is using DMA for read/write */
+       IDE_DFLAG_USING_DMA             = (1 << 1),
+       /* okay to unmask other IRQs */
+       IDE_DFLAG_UNMASK                = (1 << 2),
+       /* don't attempt flushes */
+       IDE_DFLAG_NOFLUSH               = (1 << 3),
+       /* DSC overlap */
+       IDE_DFLAG_DSC_OVERLAP           = (1 << 4),
+       /* give potential excess bandwidth */
+       IDE_DFLAG_NICE1                 = (1 << 5),
+       /* device is physically present */
+       IDE_DFLAG_PRESENT               = (1 << 6),
+       /* device ejected hint */
+       IDE_DFLAG_DEAD                  = (1 << 7),
+       /* id read from device (synthetic if not set) */
+       IDE_DFLAG_ID_READ               = (1 << 8),
+       IDE_DFLAG_NOPROBE               = (1 << 9),
+       /* need to do check_media_change() */
+       IDE_DFLAG_REMOVABLE             = (1 << 10),
+       /* needed for removable devices */
+       IDE_DFLAG_ATTACH                = (1 << 11),
+       IDE_DFLAG_FORCED_GEOM           = (1 << 12),
+       /* disallow setting unmask bit */
+       IDE_DFLAG_NO_UNMASK             = (1 << 13),
+       /* disallow enabling 32-bit I/O */
+       IDE_DFLAG_NO_IO_32BIT           = (1 << 14),
+       /* for removable only: door lock/unlock works */
+       IDE_DFLAG_DOORLOCKING           = (1 << 15),
+       /* disallow DMA */
+       IDE_DFLAG_NODMA                 = (1 << 16),
+       /* powermanagment told us not to do anything, so sleep nicely */
+       IDE_DFLAG_BLOCKED               = (1 << 17),
+       /* ide-scsi emulation */
+       IDE_DFLAG_SCSI                  = (1 << 18),
+       /* sleeping & sleep field valid */
+       IDE_DFLAG_SLEEPING              = (1 << 19),
+       IDE_DFLAG_POST_RESET            = (1 << 20),
+       IDE_DFLAG_UDMA33_WARNED         = (1 << 21),
+       IDE_DFLAG_LBA48                 = (1 << 22),
+       /* status of write cache */
+       IDE_DFLAG_WCACHE                = (1 << 23),
+       /* used for ignoring ATA_DF */
+       IDE_DFLAG_NOWERR                = (1 << 24),
+       /* retrying in PIO */
+       IDE_DFLAG_DMA_PIO_RETRY         = (1 << 25),
+       IDE_DFLAG_LBA                   = (1 << 26),
+       /* don't unload heads */
+       IDE_DFLAG_NO_UNLOAD             = (1 << 27),
+       /* heads unloaded, please don't reset port */
+       IDE_DFLAG_PARKED                = (1 << 28)
+};
+
 struct ide_drive_s {
        char            name[4];        /* drive name, such as "hda" */
         char            driver_req[10];        /* requests specific driver */
@@ -410,43 +597,19 @@ struct ide_drive_s {
 #endif
        struct hwif_s           *hwif;  /* actually (ide_hwif_t *) */
 
+       unsigned long dev_flags;
+
        unsigned long sleep;            /* sleep until this time */
        unsigned long service_start;    /* time we started last request */
        unsigned long service_time;     /* service time of last request */
        unsigned long timeout;          /* max time to wait for irq */
 
        special_t       special;        /* special action flags */
-       select_t        select;         /* basic drive/head select reg value */
 
+       u8      select;                 /* basic drive/head select reg value */
        u8      retry_pio;              /* retrying dma capable host in pio */
-       u8      state;                  /* retry state */
        u8      waiting_for_dma;        /* dma currently in progress */
-
-       unsigned keep_settings  : 1;    /* restore settings after drive reset */
-       unsigned using_dma      : 1;    /* disk is using dma for read/write */
-       unsigned unmask         : 1;    /* okay to unmask other irqs */
-       unsigned noflush        : 1;    /* don't attempt flushes */
-       unsigned dsc_overlap    : 1;    /* DSC overlap */
-       unsigned nice1          : 1;    /* give potential excess bandwidth */
-       unsigned present        : 1;    /* drive is physically present */
-       unsigned dead           : 1;    /* device ejected hint */
-       unsigned id_read        : 1;    /* 1=id read from disk 0 = synthetic */
-       unsigned noprobe        : 1;    /* from:  hdx=noprobe */
-       unsigned removable      : 1;    /* 1 if need to do check_media_change */
-       unsigned attach         : 1;    /* needed for removable devices */
-       unsigned forced_geom    : 1;    /* 1 if hdx=c,h,s was given at boot */
-       unsigned no_unmask      : 1;    /* disallow setting unmask bit */
-       unsigned no_io_32bit    : 1;    /* disallow enabling 32bit I/O */
-       unsigned doorlocking    : 1;    /* for removable only: door lock/unlock works */
-       unsigned nodma          : 1;    /* disallow DMA */
-       unsigned blocked        : 1;    /* 1=powermanagment told us not to do anything, so sleep nicely */
-       unsigned scsi           : 1;    /* 0=default, 1=ide-scsi emulation */
-       unsigned sleeping       : 1;    /* 1=sleeping & sleep field valid */
-       unsigned post_reset     : 1;
-       unsigned udma33_warned  : 1;
-       unsigned addressing     : 2;    /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */
-       unsigned wcache         : 1;    /* status of write cache */
-       unsigned nowerr         : 1;    /* used for ignoring ATA_DF */
+       u8      dma;                    /* atapi dma flag */
 
         u8     quirk_list;     /* considered quirky, set for a specific host */
         u8     init_speed;     /* transfer rate set at boot */
@@ -458,7 +621,6 @@ struct ide_drive_s {
        u8      ready_stat;     /* min status value for drive ready */
        u8      mult_count;     /* current multiple sector setting */
        u8      mult_req;       /* requested multiple sector setting */
-       u8      tune_req;       /* requested drive tuning setting */
        u8      io_32bit;       /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
        u8      bad_wstat;      /* used for ignoring ATA_DF */
        u8      head;           /* "real" number of heads */
@@ -466,6 +628,9 @@ struct ide_drive_s {
        u8      bios_head;      /* BIOS/fdisk/LILO number of heads */
        u8      bios_sect;      /* BIOS/fdisk/LILO sectors per track */
 
+       /* delay this long before sending packet command */
+       u8 pc_delay;
+
        unsigned int    bios_cyl;       /* BIOS/fdisk/LILO number of cyls */
        unsigned int    cyl;            /* "real" number of cyls */
        unsigned int    drive_data;     /* used by set_pio_mode/selectproc */
@@ -477,6 +642,9 @@ struct ide_drive_s {
 
        int             lun;            /* logical unit */
        int             crc_count;      /* crc counter to reduce drive speed */
+
+       unsigned long   debug_mask;     /* debugging levels switch */
+
 #ifdef CONFIG_BLK_DEV_IDEACPI
        struct ide_acpi_drive_link *acpidata;
 #endif
@@ -484,17 +652,32 @@ struct ide_drive_s {
        struct device   gendev;
        struct completion gendev_rel_comp;      /* to deal with device release() */
 
+       /* current packet command */
+       struct ide_atapi_pc *pc;
+
        /* callback for packet commands */
-       void (*pc_callback)(struct ide_drive_s *);
+       void (*pc_callback)(struct ide_drive_s *, int);
+
+       void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
+       int  (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
+                             unsigned int, int);
 
        unsigned long atapi_flags;
+
+       struct ide_atapi_pc request_sense_pc;
+       struct request request_sense_rq;
 };
 
 typedef struct ide_drive_s ide_drive_t;
 
-#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
+#define to_ide_device(dev)             container_of(dev, ide_drive_t, gendev)
+
+#define to_ide_drv(obj, cont_type)     \
+       container_of(obj, struct cont_type, kref)
+
+#define ide_drv_g(disk, cont_type)     \
+       container_of((disk)->private_data, struct cont_type, driver)
 
-struct ide_task_s;
 struct ide_port_info;
 
 struct ide_tp_ops {
@@ -528,6 +711,7 @@ extern const struct ide_tp_ops default_tp_ops;
  * @resetproc:         routine to reset controller after a disk reset
  * @maskproc:          special host masking for drive selection
  * @quirkproc:         check host's drive quirk list
+ * @clear_irq:         clear IRQ
  *
  * @mdma_filter:       filter MDMA modes
  * @udma_filter:       filter UDMA modes
@@ -544,6 +728,7 @@ struct ide_port_ops {
        void    (*resetproc)(ide_drive_t *);
        void    (*maskproc)(ide_drive_t *, int);
        void    (*quirkproc)(ide_drive_t *);
+       void    (*clear_irq)(ide_drive_t *);
 
        u8      (*mdma_filter)(ide_drive_t *);
        u8      (*udma_filter)(ide_drive_t *);
@@ -606,12 +791,16 @@ typedef struct hwif_s {
        const struct ide_port_ops       *port_ops;
        const struct ide_dma_ops        *dma_ops;
 
-       void (*ide_dma_clear_irq)(ide_drive_t *drive);
-
        /* dma physical region descriptor table (cpu view) */
        unsigned int    *dmatable_cpu;
        /* dma physical region descriptor table (dma view) */
        dma_addr_t      dmatable_dma;
+
+       /* maximum number of PRD table entries */
+       int prd_max_nents;
+       /* PRD entry size in bytes */
+       int prd_ent_size;
+
        /* Scatter-gather list used to build the above */
        struct scatterlist *sg_table;
        int sg_max_nents;               /* Maximum number of entries in it */
@@ -621,6 +810,8 @@ typedef struct hwif_s {
        /* data phase of the active command (currently only valid for PIO/DMA) */
        int             data_phase;
 
+       struct ide_task_s task;         /* current command */
+
        unsigned int nsect;
        unsigned int nleft;
        struct scatterlist *cursg;
@@ -649,15 +840,15 @@ typedef struct hwif_s {
 
        void            *hwif_data;     /* extra hwif data */
 
-       unsigned dma;
-
 #ifdef CONFIG_BLK_DEV_IDEACPI
        struct ide_acpi_hwif_link *acpidata;
 #endif
 } ____cacheline_internodealigned_in_smp ide_hwif_t;
 
+#define MAX_HOST_PORTS 4
+
 struct ide_host {
-       ide_hwif_t      *ports[MAX_HWIFS];
+       ide_hwif_t      *ports[MAX_HOST_PORTS];
        unsigned int    n_ports;
        struct device   *dev[2];
        unsigned int    (*init_chipset)(struct pci_dev *);
@@ -739,6 +930,22 @@ static int set_##name(ide_drive_t *drive, int arg) \
        return 0; \
 }
 
+#define ide_devset_get_flag(name, flag) \
+static int get_##name(ide_drive_t *drive) \
+{ \
+       return !!(drive->dev_flags & flag); \
+}
+
+#define ide_devset_set_flag(name, flag) \
+static int set_##name(ide_drive_t *drive, int arg) \
+{ \
+       if (arg) \
+               drive->dev_flags |= flag; \
+       else \
+               drive->dev_flags &= ~flag; \
+       return 0; \
+}
+
 #define __IDE_DEVSET(_name, _flags, _get, _set) \
 const struct ide_devset ide_devset_##_name = \
        __DEVSET(_flags, _get, _set)
@@ -752,8 +959,11 @@ IDE_DEVSET(_name, 0, get_##_func, set_##_func)
 #define ide_devset_w(_name, _func) \
 IDE_DEVSET(_name, 0, NULL, set_##_func)
 
-#define ide_devset_rw_sync(_name, _func) \
-IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
+#define ide_ext_devset_rw(_name, _func) \
+__IDE_DEVSET(_name, 0, get_##_func, set_##_func)
+
+#define ide_ext_devset_rw_sync(_name, _func) \
+__IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
 
 #define ide_decl_devset(_name) \
 extern const struct ide_devset ide_devset_##_name
@@ -764,71 +974,6 @@ ide_decl_devset(pio_mode);
 ide_decl_devset(unmaskirq);
 ide_decl_devset(using_dma);
 
-/* ATAPI packet command flags */
-enum {
-       /* set when an error is considered normal - no retry (ide-tape) */
-       PC_FLAG_ABORT                   = (1 << 0),
-       PC_FLAG_SUPPRESS_ERROR          = (1 << 1),
-       PC_FLAG_WAIT_FOR_DSC            = (1 << 2),
-       PC_FLAG_DMA_OK                  = (1 << 3),
-       PC_FLAG_DMA_IN_PROGRESS         = (1 << 4),
-       PC_FLAG_DMA_ERROR               = (1 << 5),
-       PC_FLAG_WRITING                 = (1 << 6),
-       /* command timed out */
-       PC_FLAG_TIMEDOUT                = (1 << 7),
-};
-
-/*
- * With each packet command, we allocate a buffer of IDE_PC_BUFFER_SIZE bytes.
- * This is used for several packet commands (not for READ/WRITE commands).
- */
-#define IDE_PC_BUFFER_SIZE     256
-
-struct ide_atapi_pc {
-       /* actual packet bytes */
-       u8 c[12];
-       /* incremented on each retry */
-       int retries;
-       int error;
-
-       /* bytes to transfer */
-       int req_xfer;
-       /* bytes actually transferred */
-       int xferred;
-
-       /* data buffer */
-       u8 *buf;
-       /* current buffer position */
-       u8 *cur_pos;
-       int buf_size;
-       /* missing/available data on the current buffer */
-       int b_count;
-
-       /* the corresponding request */
-       struct request *rq;
-
-       unsigned long flags;
-
-       /*
-        * those are more or less driver-specific and some of them are subject
-        * to change/removal later.
-        */
-       u8 pc_buf[IDE_PC_BUFFER_SIZE];
-
-       /* idetape only */
-       struct idetape_bh *bh;
-       char *b_data;
-
-       /* idescsi only for now */
-       struct scatterlist *sg;
-       unsigned int sg_cnt;
-
-       struct scsi_cmnd *scsi_cmd;
-       void (*done) (struct scsi_cmnd *);
-
-       unsigned long timeout;
-};
-
 #ifdef CONFIG_IDE_PROC_FS
 /*
  * /proc/ide interface
@@ -839,6 +984,11 @@ ide_devset_get(_name, _field); \
 ide_devset_set(_name, _field); \
 IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
 
+#define ide_devset_rw_flag(_name, _field) \
+ide_devset_get_flag(_name, _field); \
+ide_devset_set_flag(_name, _field); \
+IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
+
 struct ide_proc_devset {
        const char              *name;
        const struct ide_devset *setting;
@@ -905,37 +1055,55 @@ static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *
 #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
 #endif
 
+enum {
+       /* enter/exit functions */
+       IDE_DBG_FUNC =                  (1 << 0),
+       /* sense key/asc handling */
+       IDE_DBG_SENSE =                 (1 << 1),
+       /* packet commands handling */
+       IDE_DBG_PC =                    (1 << 2),
+       /* request handling */
+       IDE_DBG_RQ =                    (1 << 3),
+       /* driver probing/setup */
+       IDE_DBG_PROBE =                 (1 << 4),
+};
+
+/* DRV_NAME has to be defined in the driver before using the macro below */
+#define __ide_debug_log(lvl, fmt, args...)                     \
+{                                                              \
+       if (unlikely(drive->debug_mask & lvl))                  \
+               printk(KERN_INFO DRV_NAME ": " fmt, ## args);   \
+}
+
 /*
- * Power Management step value (rq->pm->pm_step).
- *
- * The step value starts at 0 (ide_pm_state_start_suspend) for a
- * suspend operation or 1000 (ide_pm_state_start_resume) for a
- * resume operation.
+ * Power Management state machine (rq->pm->pm_step).
  *
- * For each step, the core calls the subdriver start_power_step() first.
+ * For each step, the core calls ide_start_power_step() first.
  * This can return:
  *     - ide_stopped : In this case, the core calls us back again unless
  *                     step have been set to ide_power_state_completed.
  *     - ide_started : In this case, the channel is left busy until an
  *                     async event (interrupt) occurs.
- * Typically, start_power_step() will issue a taskfile request with
+ * Typically, ide_start_power_step() will issue a taskfile request with
  * do_rw_taskfile().
  *
- * Upon reception of the interrupt, the core will call complete_power_step()
+ * Upon reception of the interrupt, the core will call ide_complete_power_step()
  * with the error code if any. This routine should update the step value
  * and return. It should not start a new request. The core will call
- * start_power_step for the new step value, unless step have been set to
- * ide_power_state_completed.
- *
- * Subdrivers are expected to define their own additional power
- * steps from 1..999 for suspend and from 1001..1999 for resume,
- * other values are reserved for future use.
+ * ide_start_power_step() for the new step value, unless step have been
+ * set to IDE_PM_COMPLETED.
  */
-
 enum {
-       ide_pm_state_completed          = -1,
-       ide_pm_state_start_suspend      = 0,
-       ide_pm_state_start_resume       = 1000,
+       IDE_PM_START_SUSPEND,
+       IDE_PM_FLUSH_CACHE      = IDE_PM_START_SUSPEND,
+       IDE_PM_STANDBY,
+
+       IDE_PM_START_RESUME,
+       IDE_PM_RESTORE_PIO      = IDE_PM_START_RESUME,
+       IDE_PM_IDLE,
+       IDE_PM_RESTORE_DMA,
+
+       IDE_PM_COMPLETED,
 };
 
 /*
@@ -946,7 +1114,6 @@ enum {
  */
 struct ide_driver_s {
        const char                      *version;
-       u8                              media;
        ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
        int             (*end_request)(ide_drive_t *, int, int);
        ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
@@ -1015,110 +1182,6 @@ extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
 
 extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
 
-enum {
-       IDE_TFLAG_LBA48                 = (1 << 0),
-       IDE_TFLAG_FLAGGED               = (1 << 2),
-       IDE_TFLAG_OUT_DATA              = (1 << 3),
-       IDE_TFLAG_OUT_HOB_FEATURE       = (1 << 4),
-       IDE_TFLAG_OUT_HOB_NSECT         = (1 << 5),
-       IDE_TFLAG_OUT_HOB_LBAL          = (1 << 6),
-       IDE_TFLAG_OUT_HOB_LBAM          = (1 << 7),
-       IDE_TFLAG_OUT_HOB_LBAH          = (1 << 8),
-       IDE_TFLAG_OUT_HOB               = IDE_TFLAG_OUT_HOB_FEATURE |
-                                         IDE_TFLAG_OUT_HOB_NSECT |
-                                         IDE_TFLAG_OUT_HOB_LBAL |
-                                         IDE_TFLAG_OUT_HOB_LBAM |
-                                         IDE_TFLAG_OUT_HOB_LBAH,
-       IDE_TFLAG_OUT_FEATURE           = (1 << 9),
-       IDE_TFLAG_OUT_NSECT             = (1 << 10),
-       IDE_TFLAG_OUT_LBAL              = (1 << 11),
-       IDE_TFLAG_OUT_LBAM              = (1 << 12),
-       IDE_TFLAG_OUT_LBAH              = (1 << 13),
-       IDE_TFLAG_OUT_TF                = IDE_TFLAG_OUT_FEATURE |
-                                         IDE_TFLAG_OUT_NSECT |
-                                         IDE_TFLAG_OUT_LBAL |
-                                         IDE_TFLAG_OUT_LBAM |
-                                         IDE_TFLAG_OUT_LBAH,
-       IDE_TFLAG_OUT_DEVICE            = (1 << 14),
-       IDE_TFLAG_WRITE                 = (1 << 15),
-       IDE_TFLAG_FLAGGED_SET_IN_FLAGS  = (1 << 16),
-       IDE_TFLAG_IN_DATA               = (1 << 17),
-       IDE_TFLAG_CUSTOM_HANDLER        = (1 << 18),
-       IDE_TFLAG_DMA_PIO_FALLBACK      = (1 << 19),
-       IDE_TFLAG_IN_HOB_FEATURE        = (1 << 20),
-       IDE_TFLAG_IN_HOB_NSECT          = (1 << 21),
-       IDE_TFLAG_IN_HOB_LBAL           = (1 << 22),
-       IDE_TFLAG_IN_HOB_LBAM           = (1 << 23),
-       IDE_TFLAG_IN_HOB_LBAH           = (1 << 24),
-       IDE_TFLAG_IN_HOB_LBA            = IDE_TFLAG_IN_HOB_LBAL |
-                                         IDE_TFLAG_IN_HOB_LBAM |
-                                         IDE_TFLAG_IN_HOB_LBAH,
-       IDE_TFLAG_IN_HOB                = IDE_TFLAG_IN_HOB_FEATURE |
-                                         IDE_TFLAG_IN_HOB_NSECT |
-                                         IDE_TFLAG_IN_HOB_LBA,
-       IDE_TFLAG_IN_FEATURE            = (1 << 1),
-       IDE_TFLAG_IN_NSECT              = (1 << 25),
-       IDE_TFLAG_IN_LBAL               = (1 << 26),
-       IDE_TFLAG_IN_LBAM               = (1 << 27),
-       IDE_TFLAG_IN_LBAH               = (1 << 28),
-       IDE_TFLAG_IN_LBA                = IDE_TFLAG_IN_LBAL |
-                                         IDE_TFLAG_IN_LBAM |
-                                         IDE_TFLAG_IN_LBAH,
-       IDE_TFLAG_IN_TF                 = IDE_TFLAG_IN_NSECT |
-                                         IDE_TFLAG_IN_LBA,
-       IDE_TFLAG_IN_DEVICE             = (1 << 29),
-       IDE_TFLAG_HOB                   = IDE_TFLAG_OUT_HOB |
-                                         IDE_TFLAG_IN_HOB,
-       IDE_TFLAG_TF                    = IDE_TFLAG_OUT_TF |
-                                         IDE_TFLAG_IN_TF,
-       IDE_TFLAG_DEVICE                = IDE_TFLAG_OUT_DEVICE |
-                                         IDE_TFLAG_IN_DEVICE,
-       /* force 16-bit I/O operations */
-       IDE_TFLAG_IO_16BIT              = (1 << 30),
-       /* ide_task_t was allocated using kmalloc() */
-       IDE_TFLAG_DYN                   = (1 << 31),
-};
-
-struct ide_taskfile {
-       u8      hob_data;       /*  0: high data byte (for TASKFILE IOCTL) */
-
-       u8      hob_feature;    /*  1-5: additional data to support LBA48 */
-       u8      hob_nsect;
-       u8      hob_lbal;
-       u8      hob_lbam;
-       u8      hob_lbah;
-
-       u8      data;           /*  6: low data byte (for TASKFILE IOCTL) */
-
-       union {                 /*  7: */
-               u8 error;       /*   read:  error */
-               u8 feature;     /*  write: feature */
-       };
-
-       u8      nsect;          /*  8: number of sectors */
-       u8      lbal;           /*  9: LBA low */
-       u8      lbam;           /* 10: LBA mid */
-       u8      lbah;           /* 11: LBA high */
-
-       u8      device;         /* 12: device select */
-
-       union {                 /* 13: */
-               u8 status;      /*  read: status  */
-               u8 command;     /* write: command */
-       };
-};
-
-typedef struct ide_task_s {
-       union {
-               struct ide_taskfile     tf;
-               u8                      tf_array[14];
-       };
-       u32                     tf_flags;
-       int                     data_phase;
-       struct request          *rq;            /* copy of request */
-       void                    *special;       /* valid_t generally */
-} ide_task_t;
-
 void ide_tf_dump(const char *, struct ide_taskfile *);
 
 void ide_exec_command(ide_hwif_t *, u8);
@@ -1150,6 +1213,13 @@ int ide_check_atapi_device(ide_drive_t *, const char *);
 
 void ide_init_pc(struct ide_atapi_pc *);
 
+/* Disk head parking */
+extern wait_queue_head_t ide_park_wq;
+ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
+                     char *buf);
+ssize_t ide_park_store(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t len);
+
 /*
  * Special requests for ide-tape block device strategy routine.
  *
@@ -1163,24 +1233,22 @@ enum {
        REQ_IDETAPE_WRITE       = (1 << 3),
 };
 
-void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *,
-                      struct request *);
 int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *);
 
 int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *);
 int ide_do_start_stop(ide_drive_t *, struct gendisk *, int);
 int ide_set_media_lock(ide_drive_t *, struct gendisk *, int);
+void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
+void ide_retry_pc(ide_drive_t *, struct gendisk *);
+
+static inline unsigned long ide_scsi_get_timeout(struct ide_atapi_pc *pc)
+{
+       return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
+}
+
+int ide_scsi_expiry(ide_drive_t *);
 
-ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
-       ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
-       void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
-       void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
-       int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned int,
-                          int));
-ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *,
-                               ide_handler_t *, unsigned int, ide_expiry_t *);
-ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *,
-                            ide_handler_t *, unsigned int, ide_expiry_t *);
+ide_startstop_t ide_issue_pc(ide_drive_t *, unsigned int, ide_expiry_t *);
 
 ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
 
@@ -1358,6 +1426,7 @@ struct drive_list_entry {
 int ide_in_drive_list(u16 *, const struct drive_list_entry *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
+int ide_dma_good_drive(ide_drive_t *);
 int __ide_dma_bad_drive(ide_drive_t *);
 int ide_id_dma_bug(ide_drive_t *);
 
@@ -1375,25 +1444,29 @@ int ide_set_dma(ide_drive_t *);
 void ide_check_dma_crc(ide_drive_t *);
 ide_startstop_t ide_dma_intr(ide_drive_t *);
 
+int ide_allocate_dma_engine(ide_hwif_t *);
+void ide_release_dma_engine(ide_hwif_t *);
+
 int ide_build_sglist(ide_drive_t *, struct request *);
 void ide_destroy_dmatable(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_SFF
+int config_drive_for_dma(ide_drive_t *);
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
-int ide_allocate_dma_engine(ide_hwif_t *);
-void ide_release_dma_engine(ide_hwif_t *);
-
 void ide_dma_host_set(ide_drive_t *, int);
 extern int ide_dma_setup(ide_drive_t *);
 void ide_dma_exec_cmd(ide_drive_t *, u8);
 extern void ide_dma_start(ide_drive_t *);
-extern int __ide_dma_end(ide_drive_t *);
+int ide_dma_end(ide_drive_t *);
 int ide_dma_test_irq(ide_drive_t *);
-extern void ide_dma_lost_irq(ide_drive_t *);
-extern void ide_dma_timeout(ide_drive_t *);
 extern const struct ide_dma_ops sff_dma_ops;
+#else
+static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
 #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
 
+void ide_dma_lost_irq(ide_drive_t *);
+void ide_dma_timeout(ide_drive_t *);
+
 #else
 static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
 static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
@@ -1404,11 +1477,8 @@ static inline void ide_dma_on(ide_drive_t *drive) { ; }
 static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
 static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
 static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-#ifndef CONFIG_BLK_DEV_IDEDMA_SFF
 static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
-#endif
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
 extern int ide_acpi_exec_tfs(ide_drive_t *drive);
@@ -1436,7 +1506,6 @@ void ide_undecoded_slave(ide_drive_t *);
 
 void ide_port_apply_params(ide_hwif_t *);
 
-struct ide_host *ide_host_alloc_all(const struct ide_port_info *, hw_regs_t **);
 struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **);
 void ide_host_free(struct ide_host *);
 int ide_host_register(struct ide_host *, const struct ide_port_info *,
@@ -1547,6 +1616,6 @@ static inline ide_drive_t *ide_get_pair_dev(ide_drive_t *drive)
 {
        ide_drive_t *peer = &drive->hwif->drives[(drive->dn ^ 1) & 1];
 
-       return peer->present ? peer : NULL;
+       return (peer->dev_flags & IDE_DFLAG_PRESENT) ? peer : NULL;
 }
 #endif /* _IDE_H */
index bf1a53b2682ebf6e4231a679d3a857d4a21598a6..7f3c735f422bed8ff1cdeacc9450d61834f8dd19 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Author:     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Donald Becker, <becker@super.org>
- *             Alan Cox, <alan@redhat.com>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *             Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
  *
  *             This program is free software; you can redistribute it and/or
index ae77daed6c2feb8e1b2b41a0b1b66e03d6cd9327..45de1046dbbf76db53146961e736dde080c56946 100644 (file)
@@ -12,7 +12,7 @@
  *             if_fddi.h is based on previous if_ether.h and if_tr.h work by
  *                     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *                     Donald Becker, <becker@super.org>
- *                     Alan Cox, <alan@redhat.com>
+ *                     Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *                     Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
  *                     Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
  *
index 94d31ca7d71a0936c19e066f3c899184b64eaa66..f0f23516bb5982222fcaf0b4677782137e90a5b1 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Author:     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Donald Becker, <becker@super.org>
- *             Alan Cox, <alan@redhat.com>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *             Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
  *             Jes Sorensen, <Jes.Sorensen@cern.ch>
  *
index 7bb3c095c15b4fb33d0ffd227ac9d39f86b9d297..f734a0ba0698b2ddf7ccf58190205f0b0ac60f7c 100644 (file)
@@ -2,7 +2,7 @@
  *     Linux NET3:     Internet Group Management Protocol  [IGMP]
  *
  *     Authors:
- *             Alan Cox <Alan.Cox@linux.org>
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  *     Extended to talk the BSD extended IGMP protocol of mrouted 3.6
  *
index 93538b696e3d99f2bb30d96b83d3516c66442233..ad63824460e34d2838d0a77833f21121814251cd 100644 (file)
@@ -233,9 +233,6 @@ struct obs_kernel_param {
                __attribute__((aligned((sizeof(long)))))        \
                = { __setup_str_##unique_id, fn, early }
 
-#define __setup_null_param(str, unique_id)                     \
-       __setup_param(str, unique_id, NULL, 0)
-
 #define __setup(str, fn)                                       \
        __setup_param(str, fn, fn, 0)
 
@@ -296,7 +293,6 @@ void __init parse_early_param(void);
        void cleanup_module(void) __attribute__((alias(#exitfn)));
 
 #define __setup_param(str, unique_id, fn)      /* nothing */
-#define __setup_null_param(str, unique_id)     /* nothing */
 #define __setup(str, func)                     /* nothing */
 #endif
 
index a5802c9c81a47831996a93cffc00fcb7190d4089..b86fb5581ce602f5978ff2a06ddc05eb67f19a07 100644 (file)
@@ -577,9 +577,22 @@ struct input_absinfo {
 #define KEY_BRL_DOT9           0x1f9
 #define KEY_BRL_DOT10          0x1fa
 
+#define KEY_NUMERIC_0          0x200   /* used by phones, remote controls, */
+#define KEY_NUMERIC_1          0x201   /* and other keypads */
+#define KEY_NUMERIC_2          0x202
+#define KEY_NUMERIC_3          0x203
+#define KEY_NUMERIC_4          0x204
+#define KEY_NUMERIC_5          0x205
+#define KEY_NUMERIC_6          0x206
+#define KEY_NUMERIC_7          0x207
+#define KEY_NUMERIC_8          0x208
+#define KEY_NUMERIC_9          0x209
+#define KEY_NUMERIC_STAR       0x20a
+#define KEY_NUMERIC_POUND      0x20b
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING    KEY_MUTE
-#define KEY_MAX                        0x1ff
+#define KEY_MAX                        0x2ff
 #define KEY_CNT                        (KEY_MAX+1)
 
 /*
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
new file mode 100644 (file)
index 0000000..2e117f3
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) 2006-2008 Intel Corporation
+ * Author: Ashok Raj <ashok.raj@intel.com>
+ * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+#include <linux/types.h>
+#include <linux/msi.h>
+#include <linux/sysdev.h>
+#include <linux/iova.h>
+#include <linux/io.h>
+#include <linux/dma_remapping.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Intel IOMMU register specification per version 1.0 public spec.
+ */
+
+#define        DMAR_VER_REG    0x0     /* Arch version supported by this IOMMU */
+#define        DMAR_CAP_REG    0x8     /* Hardware supported capabilities */
+#define        DMAR_ECAP_REG   0x10    /* Extended capabilities supported */
+#define        DMAR_GCMD_REG   0x18    /* Global command register */
+#define        DMAR_GSTS_REG   0x1c    /* Global status register */
+#define        DMAR_RTADDR_REG 0x20    /* Root entry table */
+#define        DMAR_CCMD_REG   0x28    /* Context command reg */
+#define        DMAR_FSTS_REG   0x34    /* Fault Status register */
+#define        DMAR_FECTL_REG  0x38    /* Fault control register */
+#define        DMAR_FEDATA_REG 0x3c    /* Fault event interrupt data register */
+#define        DMAR_FEADDR_REG 0x40    /* Fault event interrupt addr register */
+#define        DMAR_FEUADDR_REG 0x44   /* Upper address register */
+#define        DMAR_AFLOG_REG  0x58    /* Advanced Fault control */
+#define        DMAR_PMEN_REG   0x64    /* Enable Protected Memory Region */
+#define        DMAR_PLMBASE_REG 0x68   /* PMRR Low addr */
+#define        DMAR_PLMLIMIT_REG 0x6c  /* PMRR low limit */
+#define        DMAR_PHMBASE_REG 0x70   /* pmrr high base addr */
+#define        DMAR_PHMLIMIT_REG 0x78  /* pmrr high limit */
+#define DMAR_IQH_REG   0x80    /* Invalidation queue head register */
+#define DMAR_IQT_REG   0x88    /* Invalidation queue tail register */
+#define DMAR_IQA_REG   0x90    /* Invalidation queue addr register */
+#define DMAR_ICS_REG   0x98    /* Invalidation complete status register */
+#define DMAR_IRTA_REG  0xb8    /* Interrupt remapping table addr register */
+
+#define OFFSET_STRIDE          (9)
+/*
+#define dmar_readl(dmar, reg) readl(dmar + reg)
+#define dmar_readq(dmar, reg) ({ \
+               u32 lo, hi; \
+               lo = readl(dmar + reg); \
+               hi = readl(dmar + reg + 4); \
+               (((u64) hi) << 32) + lo; })
+*/
+static inline u64 dmar_readq(void __iomem *addr)
+{
+       u32 lo, hi;
+       lo = readl(addr);
+       hi = readl(addr + 4);
+       return (((u64) hi) << 32) + lo;
+}
+
+static inline void dmar_writeq(void __iomem *addr, u64 val)
+{
+       writel((u32)val, addr);
+       writel((u32)(val >> 32), addr + 4);
+}
+
+#define DMAR_VER_MAJOR(v)              (((v) & 0xf0) >> 4)
+#define DMAR_VER_MINOR(v)              ((v) & 0x0f)
+
+/*
+ * Decoding Capability Register
+ */
+#define cap_read_drain(c)      (((c) >> 55) & 1)
+#define cap_write_drain(c)     (((c) >> 54) & 1)
+#define cap_max_amask_val(c)   (((c) >> 48) & 0x3f)
+#define cap_num_fault_regs(c)  ((((c) >> 40) & 0xff) + 1)
+#define cap_pgsel_inv(c)       (((c) >> 39) & 1)
+
+#define cap_super_page_val(c)  (((c) >> 34) & 0xf)
+#define cap_super_offset(c)    (((find_first_bit(&cap_super_page_val(c), 4)) \
+                                       * OFFSET_STRIDE) + 21)
+
+#define cap_fault_reg_offset(c)        ((((c) >> 24) & 0x3ff) * 16)
+#define cap_max_fault_reg_offset(c) \
+       (cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16)
+
+#define cap_zlr(c)             (((c) >> 22) & 1)
+#define cap_isoch(c)           (((c) >> 23) & 1)
+#define cap_mgaw(c)            ((((c) >> 16) & 0x3f) + 1)
+#define cap_sagaw(c)           (((c) >> 8) & 0x1f)
+#define cap_caching_mode(c)    (((c) >> 7) & 1)
+#define cap_phmr(c)            (((c) >> 6) & 1)
+#define cap_plmr(c)            (((c) >> 5) & 1)
+#define cap_rwbf(c)            (((c) >> 4) & 1)
+#define cap_afl(c)             (((c) >> 3) & 1)
+#define cap_ndoms(c)           (((unsigned long)1) << (4 + 2 * ((c) & 0x7)))
+/*
+ * Extended Capability Register
+ */
+
+#define ecap_niotlb_iunits(e)  ((((e) >> 24) & 0xff) + 1)
+#define ecap_iotlb_offset(e)   ((((e) >> 8) & 0x3ff) * 16)
+#define ecap_max_iotlb_offset(e) \
+       (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
+#define ecap_coherent(e)       ((e) & 0x1)
+#define ecap_qis(e)            ((e) & 0x2)
+#define ecap_eim_support(e)    ((e >> 4) & 0x1)
+#define ecap_ir_support(e)     ((e >> 3) & 0x1)
+#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)
+
+
+/* IOTLB_REG */
+#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
+#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
+#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
+#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
+#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
+#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
+#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
+#define DMA_TLB_DID(id)        (((u64)((id) & 0xffff)) << 32)
+#define DMA_TLB_IVT (((u64)1) << 63)
+#define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
+#define DMA_TLB_MAX_SIZE (0x3f)
+
+/* INVALID_DESC */
+#define DMA_ID_TLB_GLOBAL_FLUSH        (((u64)1) << 3)
+#define DMA_ID_TLB_DSI_FLUSH   (((u64)2) << 3)
+#define DMA_ID_TLB_PSI_FLUSH   (((u64)3) << 3)
+#define DMA_ID_TLB_READ_DRAIN  (((u64)1) << 7)
+#define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6)
+#define DMA_ID_TLB_DID(id)     (((u64)((id & 0xffff) << 16)))
+#define DMA_ID_TLB_IH_NONLEAF  (((u64)1) << 6)
+#define DMA_ID_TLB_ADDR(addr)  (addr)
+#define DMA_ID_TLB_ADDR_MASK(mask)     (mask)
+
+/* PMEN_REG */
+#define DMA_PMEN_EPM (((u32)1)<<31)
+#define DMA_PMEN_PRS (((u32)1)<<0)
+
+/* GCMD_REG */
+#define DMA_GCMD_TE (((u32)1) << 31)
+#define DMA_GCMD_SRTP (((u32)1) << 30)
+#define DMA_GCMD_SFL (((u32)1) << 29)
+#define DMA_GCMD_EAFL (((u32)1) << 28)
+#define DMA_GCMD_WBF (((u32)1) << 27)
+#define DMA_GCMD_QIE (((u32)1) << 26)
+#define DMA_GCMD_SIRTP (((u32)1) << 24)
+#define DMA_GCMD_IRE (((u32) 1) << 25)
+
+/* GSTS_REG */
+#define DMA_GSTS_TES (((u32)1) << 31)
+#define DMA_GSTS_RTPS (((u32)1) << 30)
+#define DMA_GSTS_FLS (((u32)1) << 29)
+#define DMA_GSTS_AFLS (((u32)1) << 28)
+#define DMA_GSTS_WBFS (((u32)1) << 27)
+#define DMA_GSTS_QIES (((u32)1) << 26)
+#define DMA_GSTS_IRTPS (((u32)1) << 24)
+#define DMA_GSTS_IRES (((u32)1) << 25)
+
+/* CCMD_REG */
+#define DMA_CCMD_ICC (((u64)1) << 63)
+#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
+#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
+#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
+#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
+#define DMA_CCMD_MASK_NOBIT 0
+#define DMA_CCMD_MASK_1BIT 1
+#define DMA_CCMD_MASK_2BIT 2
+#define DMA_CCMD_MASK_3BIT 3
+#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
+#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
+
+/* FECTL_REG */
+#define DMA_FECTL_IM (((u32)1) << 31)
+
+/* FSTS_REG */
+#define DMA_FSTS_PPF ((u32)2)
+#define DMA_FSTS_PFO ((u32)1)
+#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
+
+/* FRCD_REG, 32 bits access */
+#define DMA_FRCD_F (((u32)1) << 31)
+#define dma_frcd_type(d) ((d >> 30) & 1)
+#define dma_frcd_fault_reason(c) (c & 0xff)
+#define dma_frcd_source_id(c) (c & 0xffff)
+#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
+
+#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */
+
+#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
+{\
+       cycles_t start_time = get_cycles();\
+       while (1) {\
+               sts = op (iommu->reg + offset);\
+               if (cond)\
+                       break;\
+               if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
+                       panic("DMAR hardware is malfunctioning\n");\
+               cpu_relax();\
+       }\
+}
+
+#define QI_LENGTH      256     /* queue length */
+
+enum {
+       QI_FREE,
+       QI_IN_USE,
+       QI_DONE
+};
+
+#define QI_CC_TYPE             0x1
+#define QI_IOTLB_TYPE          0x2
+#define QI_DIOTLB_TYPE         0x3
+#define QI_IEC_TYPE            0x4
+#define QI_IWD_TYPE            0x5
+
+#define QI_IEC_SELECTIVE       (((u64)1) << 4)
+#define QI_IEC_IIDEX(idx)      (((u64)(idx & 0xffff) << 32))
+#define QI_IEC_IM(m)           (((u64)(m & 0x1f) << 27))
+
+#define QI_IWD_STATUS_DATA(d)  (((u64)d) << 32)
+#define QI_IWD_STATUS_WRITE    (((u64)1) << 5)
+
+struct qi_desc {
+       u64 low, high;
+};
+
+struct q_inval {
+       spinlock_t      q_lock;
+       struct qi_desc  *desc;          /* invalidation queue */
+       int             *desc_status;   /* desc status */
+       int             free_head;      /* first free entry */
+       int             free_tail;      /* last free entry */
+       int             free_cnt;
+};
+
+#ifdef CONFIG_INTR_REMAP
+/* 1MB - maximum possible interrupt remapping table size */
+#define INTR_REMAP_PAGE_ORDER  8
+#define INTR_REMAP_TABLE_REG_SIZE      0xf
+
+#define INTR_REMAP_TABLE_ENTRIES       65536
+
+struct ir_table {
+       struct irte *base;
+};
+#endif
+
+struct intel_iommu {
+       void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
+       u64             cap;
+       u64             ecap;
+       int             seg;
+       u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
+       spinlock_t      register_lock; /* protect register handling */
+       int             seq_id; /* sequence id of the iommu */
+
+#ifdef CONFIG_DMAR
+       unsigned long   *domain_ids; /* bitmap of domains */
+       struct dmar_domain **domains; /* ptr to domains */
+       spinlock_t      lock; /* protect context, domain ids */
+       struct root_entry *root_entry; /* virtual address */
+
+       unsigned int irq;
+       unsigned char name[7];    /* Device Name */
+       struct msi_msg saved_msg;
+       struct sys_device sysdev;
+#endif
+       struct q_inval  *qi;            /* Queued invalidation info */
+#ifdef CONFIG_INTR_REMAP
+       struct ir_table *ir_table;      /* Interrupt remapping info */
+#endif
+};
+
+static inline void __iommu_flush_cache(
+       struct intel_iommu *iommu, void *addr, int size)
+{
+       if (!ecap_coherent(iommu->ecap))
+               clflush_cache_range(addr, size);
+}
+
+extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
+
+extern int alloc_iommu(struct dmar_drhd_unit *drhd);
+extern void free_iommu(struct intel_iommu *iommu);
+extern int dmar_enable_qi(struct intel_iommu *iommu);
+extern void qi_global_iec(struct intel_iommu *iommu);
+
+extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
+
+void intel_iommu_domain_exit(struct dmar_domain *domain);
+struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev);
+int intel_iommu_context_mapping(struct dmar_domain *domain,
+                               struct pci_dev *pdev);
+int intel_iommu_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
+                            u64 hpa, size_t size, int prot);
+void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn);
+struct dmar_domain *intel_iommu_find_domain(struct pci_dev *pdev);
+u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova);
+
+#ifdef CONFIG_DMAR
+int intel_iommu_found(void);
+#else /* CONFIG_DMAR */
+static inline int intel_iommu_found(void)
+{
+       return 0;
+}
+#endif /* CONFIG_DMAR */
+
+#endif
index 58ff4e74b2f362bcc2078e76e9c5d10bdfba1f83..54b3623434eca45d1f3758a787d4763aed069b2d 100644 (file)
@@ -252,6 +252,8 @@ enum
        HRTIMER_SOFTIRQ,
 #endif
        RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
+
+       NR_SOFTIRQS
 };
 
 /* softirq mask and active fields moved to irq_cpustat_t in
index a6d0586e2bf76227488045e7e38267a3f69bc455..3b068e5b56710222f43bd86a3a5f849128526171 100644 (file)
@@ -23,4 +23,7 @@ extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
 extern void iommu_area_free(unsigned long *map, unsigned long start,
                            unsigned int nr);
 
+extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
+                                    unsigned long io_page_size);
+
 #endif
index ee9bcc6f32b62efab5c3e93a1b4fe488e7be4448..041e95aac2bf317c40a3c68a45e223b322c80a26 100644 (file)
@@ -34,7 +34,8 @@ struct resource_list {
  */
 #define IORESOURCE_BITS                0x000000ff      /* Bus-specific bits */
 
-#define IORESOURCE_IO          0x00000100      /* Resource type */
+#define IORESOURCE_TYPE_BITS   0x00000f00      /* Resource type */
+#define IORESOURCE_IO          0x00000100
 #define IORESOURCE_MEM         0x00000200
 #define IORESOURCE_IRQ         0x00000400
 #define IORESOURCE_DMA         0x00000800
@@ -126,6 +127,10 @@ static inline resource_size_t resource_size(struct resource *res)
 {
        return res->end - res->start + 1;
 }
+static inline unsigned long resource_type(struct resource *res)
+{
+       return res->flags & IORESOURCE_TYPE_BITS;
+}
 
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)   __request_region(&ioport_resource, (start), (n), (name))
@@ -169,6 +174,7 @@ extern struct resource * __devm_request_region(struct device *dev,
 
 extern void __devm_release_region(struct device *dev, struct resource *parent,
                                  resource_size_t start, resource_size_t n);
+extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
 
 #endif /* __ASSEMBLY__ */
 #endif /* _LINUX_IOPORT_H */
diff --git a/include/linux/iova.h b/include/linux/iova.h
new file mode 100644 (file)
index 0000000..228f6c9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This file is released under the GPLv2.
+ *
+ * Copyright (C) 2006-2008 Intel Corporation
+ * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+ *
+ */
+
+#ifndef _IOVA_H_
+#define _IOVA_H_
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/rbtree.h>
+#include <linux/dma-mapping.h>
+
+/* IO virtual address start page frame number */
+#define IOVA_START_PFN         (1)
+
+/* iova structure */
+struct iova {
+       struct rb_node  node;
+       unsigned long   pfn_hi; /* IOMMU dish out addr hi */
+       unsigned long   pfn_lo; /* IOMMU dish out addr lo */
+};
+
+/* holds all the iova translations for a domain */
+struct iova_domain {
+       spinlock_t      iova_alloc_lock;/* Lock to protect iova  allocation */
+       spinlock_t      iova_rbtree_lock; /* Lock to protect update of rbtree */
+       struct rb_root  rbroot;         /* iova domain rbtree root */
+       struct rb_node  *cached32_node; /* Save last alloced node */
+       unsigned long   dma_32bit_pfn;
+};
+
+struct iova *alloc_iova_mem(void);
+void free_iova_mem(struct iova *iova);
+void free_iova(struct iova_domain *iovad, unsigned long pfn);
+void __free_iova(struct iova_domain *iovad, struct iova *iova);
+struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
+       unsigned long limit_pfn,
+       bool size_aligned);
+struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
+       unsigned long pfn_hi);
+void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
+void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
+struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
+void put_iova_domain(struct iova_domain *iovad);
+
+#endif
index 17ca64b5a66cc253f9284e51e4e8c7c3e8e50544..f2720280b9ec5e12d596baf2e4e8a63a890dc364 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/videodev2.h>
 
 /* ivtv knows several distinct output modes: MPEG streaming,
    YUV streaming, YUV updates through user DMA and the passthrough
index 07a9b52a265418cb4b213ae8b1fff8e6eefbdd9d..7ebbcb1c9ba4e5d6a5a72290c002f37c09617fce 100644 (file)
@@ -61,7 +61,7 @@ extern u8 journal_enable_debug;
        do {                                                            \
                if ((n) <= journal_enable_debug) {                      \
                        printk (KERN_DEBUG "(%s, %d): %s: ",            \
-                               __FILE__, __LINE__, __FUNCTION__);      \
+                               __FILE__, __LINE__, __func__);  \
                        printk (f, ## a);                               \
                }                                                       \
        } while (0)
@@ -984,7 +984,7 @@ extern int  cleanup_journal_tail(journal_t *);
 
 #define jbd_ENOSYS() \
 do {                                                                      \
-       printk (KERN_ERR "JBD unimplemented function %s\n", __FUNCTION__); \
+       printk (KERN_ERR "JBD unimplemented function %s\n", __func__); \
        current->state = TASK_UNINTERRUPTIBLE;                             \
        schedule();                                                        \
 } while (1)
index d2e91ea998fd44b945cb8337cbc0934967b774f9..463d6f10b64f7ffaea2f4fc13e57bc2ca4a95c8e 100644 (file)
@@ -61,7 +61,7 @@ extern u8 jbd2_journal_enable_debug;
        do {                                                            \
                if ((n) <= jbd2_journal_enable_debug) {                 \
                        printk (KERN_DEBUG "(%s, %d): %s: ",            \
-                               __FILE__, __LINE__, __FUNCTION__);      \
+                               __FILE__, __LINE__, __func__);  \
                        printk (f, ## a);                               \
                }                                                       \
        } while (0)
@@ -1143,7 +1143,7 @@ extern int        jbd2_cleanup_journal_tail(journal_t *);
 
 #define jbd_ENOSYS() \
 do {                                                                      \
-       printk (KERN_ERR "JBD unimplemented function %s\n", __FUNCTION__); \
+       printk (KERN_ERR "JBD unimplemented function %s\n", __func__); \
        current->state = TASK_UNINTERRUPTIBLE;                             \
        schedule();                                                        \
 } while (1)
index 8a62d1e84b9b403668000032cd30ab448cced7fb..bb70ebb6a2d5bd9f7435387bb2eb4fa91cbce166 100644 (file)
@@ -3,7 +3,7 @@
  *
  * buffer_head fields for JBD
  *
- * 27 May 2001 Andrew Morton <akpm@digeo.com>
+ * 27 May 2001 Andrew Morton
  *     Created - pulled out of fs.h
  */
 
index b96144887444a222621a4167f646859528887bb5..f3fe34391d8e2664f2d1bef0140b184f879b8e32 100644 (file)
@@ -93,12 +93,10 @@ static inline void print_symbol(const char *fmt, unsigned long addr)
 }
 
 /*
- * Pretty-print a function pointer.
- *
- * ia64 and ppc64 function pointers are really function descriptors,
- * which contain a pointer the real address.
+ * Pretty-print a function pointer.  This function is deprecated.
+ * Please use the "%pF" vsprintf format instead.
  */
-static inline void print_fn_descriptor_symbol(const char *fmt, void *addr)
+static inline void __deprecated print_fn_descriptor_symbol(const char *fmt, void *addr)
 {
 #if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
        addr = *(void **)addr;
index 75d81f157d2edbd7a8aec39ce3cb7cc3bd69a758..6803318fa2ea80cfa15caeaa3684eda5e41bc942 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/log2.h>
 #include <linux/typecheck.h>
 #include <linux/ratelimit.h>
+#include <linux/dynamic_printk.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -213,6 +214,9 @@ static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
                { return false; }
 #endif
 
+extern int printk_needs_cpu(int cpu);
+extern void printk_tick(void);
+
 extern void asmlinkage __attribute__((format(printf, 1, 2)))
        early_printk(const char *fmt, ...);
 
@@ -235,9 +239,10 @@ extern int oops_in_progress;               /* If set, an oops, panic(), BUG() or die() is in
 extern int panic_timeout;
 extern int panic_on_oops;
 extern int panic_on_unrecovered_nmi;
-extern int tainted;
 extern const char *print_tainted(void);
-extern void add_taint(unsigned);
+extern void add_taint(unsigned flag);
+extern int test_taint(unsigned flag);
+extern unsigned long get_taint(void);
 extern int root_mountflags;
 
 /* Values used for system_state */
@@ -250,16 +255,16 @@ extern enum system_states {
        SYSTEM_SUSPEND_DISK,
 } system_state;
 
-#define TAINT_PROPRIETARY_MODULE       (1<<0)
-#define TAINT_FORCED_MODULE            (1<<1)
-#define TAINT_UNSAFE_SMP               (1<<2)
-#define TAINT_FORCED_RMMOD             (1<<3)
-#define TAINT_MACHINE_CHECK            (1<<4)
-#define TAINT_BAD_PAGE                 (1<<5)
-#define TAINT_USER                     (1<<6)
-#define TAINT_DIE                      (1<<7)
-#define TAINT_OVERRIDDEN_ACPI_TABLE    (1<<8)
-#define TAINT_WARN                     (1<<9)
+#define TAINT_PROPRIETARY_MODULE       0
+#define TAINT_FORCED_MODULE            1
+#define TAINT_UNSAFE_SMP               2
+#define TAINT_FORCED_RMMOD             3
+#define TAINT_MACHINE_CHECK            4
+#define TAINT_BAD_PAGE                 5
+#define TAINT_USER                     6
+#define TAINT_DIE                      7
+#define TAINT_OVERRIDDEN_ACPI_TABLE    8
+#define TAINT_WARN                     9
 
 extern void dump_stack(void) __cold;
 
@@ -303,8 +308,12 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 #define pr_info(fmt, arg...) \
        printk(KERN_INFO fmt, ##arg)
 
-#ifdef DEBUG
 /* If you are writing a driver, please use dev_dbg instead */
+#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
+#define pr_debug(fmt, ...) do { \
+       dynamic_pr_debug(fmt, ##__VA_ARGS__); \
+       } while (0)
+#elif defined(DEBUG)
 #define pr_debug(fmt, arg...) \
        printk(KERN_DEBUG fmt, ##arg)
 #else
index a1a91577813c6bfb25ea89c9304f0c2128a87464..92213a9194e15753b91a21170cb641e97d82513d 100644 (file)
@@ -99,4 +99,7 @@ struct file;
 extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
                                    struct file **filp);
 
+extern int usermodehelper_disable(void);
+extern void usermodehelper_enable(void);
+
 #endif /* __LINUX_KMOD_H__ */
index 70a30651cd128cd3dbaf91a366886764abdede33..797fcd7812420596f10f4a768b6641e6277455dc 100644 (file)
@@ -311,22 +311,33 @@ struct kvm_s390_interrupt {
 
 /* This structure represents a single trace buffer record. */
 struct kvm_trace_rec {
-       __u32 event:28;
-       __u32 extra_u32:3;
-       __u32 cycle_in:1;
+       /* variable rec_val
+        * is split into:
+        * bits 0 - 27  -> event id
+        * bits 28 -30  -> number of extra data args of size u32
+        * bits 31      -> binary indicator for if tsc is in record
+        */
+       __u32 rec_val;
        __u32 pid;
        __u32 vcpu_id;
        union {
                struct {
-                       __u64 cycle_u64;
+                       __u64 timestamp;
                        __u32 extra_u32[KVM_TRC_EXTRA_MAX];
-               } __attribute__((packed)) cycle;
+               } __attribute__((packed)) timestamp;
                struct {
                        __u32 extra_u32[KVM_TRC_EXTRA_MAX];
-               } nocycle;
+               } notimestamp;
        } u;
 };
 
+#define TRACE_REC_EVENT_ID(val) \
+               (0x0fffffff & (val))
+#define TRACE_REC_NUM_DATA_ARGS(val) \
+               (0x70000000 & ((val) << 28))
+#define TRACE_REC_TCS(val) \
+               (0x80000000 & ((val) << 31))
+
 #define KVMIO 0xAE
 
 /*
@@ -372,6 +383,10 @@ struct kvm_trace_rec {
 #define KVM_CAP_MP_STATE 14
 #define KVM_CAP_COALESCED_MMIO 15
 #define KVM_CAP_SYNC_MMU 16  /* Changes to host mmap are reflected in guest */
+#if defined(CONFIG_X86)||defined(CONFIG_IA64)
+#define KVM_CAP_DEVICE_ASSIGNMENT 17
+#endif
+#define KVM_CAP_IOMMU 18
 
 /*
  * ioctls for VM fds
@@ -401,6 +416,10 @@ struct kvm_trace_rec {
                        _IOW(KVMIO,  0x67, struct kvm_coalesced_mmio_zone)
 #define KVM_UNREGISTER_COALESCED_MMIO \
                        _IOW(KVMIO,  0x68, struct kvm_coalesced_mmio_zone)
+#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
+                                  struct kvm_assigned_pci_dev)
+#define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
+                           struct kvm_assigned_irq)
 
 /*
  * ioctls for vcpu fds
@@ -440,4 +459,45 @@ struct kvm_trace_rec {
 #define KVM_GET_MP_STATE          _IOR(KVMIO,  0x98, struct kvm_mp_state)
 #define KVM_SET_MP_STATE          _IOW(KVMIO,  0x99, struct kvm_mp_state)
 
+#define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
+#define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
+#define KVM_TRC_PEND_INTR        (KVM_TRC_HANDLER + 0x04)
+#define KVM_TRC_IO_READ          (KVM_TRC_HANDLER + 0x05)
+#define KVM_TRC_IO_WRITE         (KVM_TRC_HANDLER + 0x06)
+#define KVM_TRC_CR_READ          (KVM_TRC_HANDLER + 0x07)
+#define KVM_TRC_CR_WRITE         (KVM_TRC_HANDLER + 0x08)
+#define KVM_TRC_DR_READ          (KVM_TRC_HANDLER + 0x09)
+#define KVM_TRC_DR_WRITE         (KVM_TRC_HANDLER + 0x0A)
+#define KVM_TRC_MSR_READ         (KVM_TRC_HANDLER + 0x0B)
+#define KVM_TRC_MSR_WRITE        (KVM_TRC_HANDLER + 0x0C)
+#define KVM_TRC_CPUID            (KVM_TRC_HANDLER + 0x0D)
+#define KVM_TRC_INTR             (KVM_TRC_HANDLER + 0x0E)
+#define KVM_TRC_NMI              (KVM_TRC_HANDLER + 0x0F)
+#define KVM_TRC_VMMCALL          (KVM_TRC_HANDLER + 0x10)
+#define KVM_TRC_HLT              (KVM_TRC_HANDLER + 0x11)
+#define KVM_TRC_CLTS             (KVM_TRC_HANDLER + 0x12)
+#define KVM_TRC_LMSW             (KVM_TRC_HANDLER + 0x13)
+#define KVM_TRC_APIC_ACCESS      (KVM_TRC_HANDLER + 0x14)
+#define KVM_TRC_TDP_FAULT        (KVM_TRC_HANDLER + 0x15)
+#define KVM_TRC_GTLB_WRITE       (KVM_TRC_HANDLER + 0x16)
+#define KVM_TRC_STLB_WRITE       (KVM_TRC_HANDLER + 0x17)
+#define KVM_TRC_STLB_INVAL       (KVM_TRC_HANDLER + 0x18)
+#define KVM_TRC_PPC_INSTR        (KVM_TRC_HANDLER + 0x19)
+
+struct kvm_assigned_pci_dev {
+       __u32 assigned_dev_id;
+       __u32 busnr;
+       __u32 devfn;
+       __u32 flags;
+};
+
+struct kvm_assigned_irq {
+       __u32 assigned_dev_id;
+       __u32 host_irq;
+       __u32 guest_irq;
+       __u32 flags;
+};
+
+#define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
+
 #endif
index 8525afc53107faaaa993fa6ebae6c2d703eb718c..3833c48fae3a372585475eca6cdfd28ef3124d4a 100644 (file)
@@ -34,6 +34,8 @@
 #define KVM_REQ_MMU_RELOAD         3
 #define KVM_REQ_TRIPLE_FAULT       4
 #define KVM_REQ_PENDING_TIMER      5
+#define KVM_REQ_UNHALT             6
+#define KVM_REQ_MMU_SYNC           7
 
 struct kvm_vcpu;
 extern struct kmem_cache *kvm_vcpu_cache;
@@ -279,12 +281,68 @@ void kvm_free_physmem(struct kvm *kvm);
 
 struct  kvm *kvm_arch_create_vm(void);
 void kvm_arch_destroy_vm(struct kvm *kvm);
+void kvm_free_all_assigned_devices(struct kvm *kvm);
 
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
 
+int kvm_is_mmio_pfn(pfn_t pfn);
+
+struct kvm_irq_ack_notifier {
+       struct hlist_node link;
+       unsigned gsi;
+       void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
+};
+
+struct kvm_assigned_dev_kernel {
+       struct kvm_irq_ack_notifier ack_notifier;
+       struct work_struct interrupt_work;
+       struct list_head list;
+       int assigned_dev_id;
+       int host_busnr;
+       int host_devfn;
+       int host_irq;
+       int guest_irq;
+       int irq_requested;
+       struct pci_dev *dev;
+       struct kvm *kvm;
+};
+void kvm_set_irq(struct kvm *kvm, int irq, int level);
+void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
+void kvm_register_irq_ack_notifier(struct kvm *kvm,
+                                  struct kvm_irq_ack_notifier *kian);
+void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
+                                    struct kvm_irq_ack_notifier *kian);
+
+#ifdef CONFIG_DMAR
+int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn,
+                       unsigned long npages);
+int kvm_iommu_map_guest(struct kvm *kvm,
+                       struct kvm_assigned_dev_kernel *assigned_dev);
+int kvm_iommu_unmap_guest(struct kvm *kvm);
+#else /* CONFIG_DMAR */
+static inline int kvm_iommu_map_pages(struct kvm *kvm,
+                                     gfn_t base_gfn,
+                                     unsigned long npages)
+{
+       return 0;
+}
+
+static inline int kvm_iommu_map_guest(struct kvm *kvm,
+                                     struct kvm_assigned_dev_kernel
+                                     *assigned_dev)
+{
+       return -ENODEV;
+}
+
+static inline int kvm_iommu_unmap_guest(struct kvm *kvm)
+{
+       return 0;
+}
+#endif /* CONFIG_DMAR */
+
 static inline void kvm_guest_enter(void)
 {
        account_system_vtime(current);
@@ -307,6 +365,11 @@ static inline gpa_t gfn_to_gpa(gfn_t gfn)
        return (gpa_t)gfn << PAGE_SHIFT;
 }
 
+static inline hpa_t pfn_to_hpa(pfn_t pfn)
+{
+       return (hpa_t)pfn << PAGE_SHIFT;
+}
+
 static inline void kvm_migrate_timers(struct kvm_vcpu *vcpu)
 {
        set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests);
@@ -326,6 +389,25 @@ struct kvm_stats_debugfs_item {
 extern struct kvm_stats_debugfs_item debugfs_entries[];
 extern struct dentry *kvm_debugfs_dir;
 
+#define KVMTRACE_5D(evt, vcpu, d1, d2, d3, d4, d5, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 5, d1, d2, d3, d4, d5)
+#define KVMTRACE_4D(evt, vcpu, d1, d2, d3, d4, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 4, d1, d2, d3, d4, 0)
+#define KVMTRACE_3D(evt, vcpu, d1, d2, d3, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 3, d1, d2, d3, 0, 0)
+#define KVMTRACE_2D(evt, vcpu, d1, d2, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 2, d1, d2, 0, 0, 0)
+#define KVMTRACE_1D(evt, vcpu, d1, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 1, d1, 0, 0, 0, 0)
+#define KVMTRACE_0D(evt, vcpu, name) \
+       trace_mark(kvm_trace_##name, "%u %p %u %u %u %u %u %u", KVM_TRC_##evt, \
+                                               vcpu, 0, 0, 0, 0, 0, 0)
+
 #ifdef CONFIG_KVM_TRACE
 int kvm_trace_ioctl(unsigned int ioctl, unsigned long arg);
 void kvm_trace_cleanup(void);
index 3d25bcd139d166b1173e4691ffa5670c2950cdb1..e5872dc994c0a0761d601229ced0d77676756397 100644 (file)
@@ -27,7 +27,6 @@ struct nlmsvc_binding {
                                                struct nfs_fh *,
                                                struct file **);
        void                    (*fclose)(struct file *);
-       unsigned long           (*get_grace_period)(void);
 };
 
 extern struct nlmsvc_binding * nlmsvc_ops;
@@ -53,15 +52,7 @@ extern void  nlmclnt_done(struct nlm_host *host);
 
 extern int     nlmclnt_proc(struct nlm_host *host, int cmd,
                                        struct file_lock *fl);
-extern int     lockd_up(int proto);
+extern int     lockd_up(void);
 extern void    lockd_down(void);
 
-unsigned long get_nfs_grace_period(void);
-
-#ifdef CONFIG_NFSD_V4
-unsigned long get_nfs4_grace_period(void);
-#else
-static inline unsigned long get_nfs4_grace_period(void) {return 0;}
-#endif
-
 #endif /* LINUX_LOCKD_BIND_H */
index dbb87ab282e8fd55c718939cdcfa34c4adf2439b..b56d5aa9b194c0d87296b303874d331b84246413 100644 (file)
@@ -12,6 +12,8 @@
 #ifdef __KERNEL__
 
 #include <linux/in.h>
+#include <linux/in6.h>
+#include <net/ipv6.h>
 #include <linux/fs.h>
 #include <linux/kref.h>
 #include <linux/utsname.h>
@@ -38,8 +40,9 @@
  */
 struct nlm_host {
        struct hlist_node       h_hash;         /* doubly linked list */
-       struct sockaddr_in      h_addr;         /* peer address */
-       struct sockaddr_in      h_saddr;        /* our address (optional) */
+       struct sockaddr_storage h_addr;         /* peer address */
+       size_t                  h_addrlen;
+       struct sockaddr_storage h_srcaddr;      /* our address (optional) */
        struct rpc_clnt *       h_rpcclnt;      /* RPC client to talk to peer */
        char *                  h_name;         /* remote hostname */
        u32                     h_version;      /* interface version */
@@ -61,17 +64,55 @@ struct nlm_host {
        struct list_head        h_granted;      /* Locks in GRANTED state */
        struct list_head        h_reclaim;      /* Locks in RECLAIM state */
        struct nsm_handle *     h_nsmhandle;    /* NSM status handle */
+
+       char                    h_addrbuf[48],  /* address eyecatchers */
+                               h_srcaddrbuf[48];
 };
 
 struct nsm_handle {
        struct list_head        sm_link;
        atomic_t                sm_count;
        char *                  sm_name;
-       struct sockaddr_in      sm_addr;
+       struct sockaddr_storage sm_addr;
+       size_t                  sm_addrlen;
        unsigned int            sm_monitored : 1,
                                sm_sticky : 1;  /* don't unmonitor */
+       char                    sm_addrbuf[48]; /* address eyecatcher */
 };
 
+/*
+ * Rigorous type checking on sockaddr type conversions
+ */
+static inline struct sockaddr_in *nlm_addr_in(const struct nlm_host *host)
+{
+       return (struct sockaddr_in *)&host->h_addr;
+}
+
+static inline struct sockaddr *nlm_addr(const struct nlm_host *host)
+{
+       return (struct sockaddr *)&host->h_addr;
+}
+
+static inline struct sockaddr_in *nlm_srcaddr_in(const struct nlm_host *host)
+{
+       return (struct sockaddr_in *)&host->h_srcaddr;
+}
+
+static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host)
+{
+       return (struct sockaddr *)&host->h_srcaddr;
+}
+
+static inline struct sockaddr_in *nsm_addr_in(const struct nsm_handle *handle)
+{
+       return (struct sockaddr_in *)&handle->sm_addr;
+}
+
+static inline struct sockaddr *nsm_addr(const struct nsm_handle *handle)
+{
+       return (struct sockaddr *)&handle->sm_addr;
+}
+
 /*
  * Map an fl_owner_t into a unique 32-bit "pid"
  */
@@ -166,7 +207,8 @@ int           nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *);
 struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl);
 void             nlmclnt_finish_block(struct nlm_wait *block);
 int              nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
-__be32           nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *);
+__be32           nlmclnt_grant(const struct sockaddr *addr,
+                               const struct nlm_lock *lock);
 void             nlmclnt_recovery(struct nlm_host *);
 int              nlmclnt_reclaim(struct nlm_host *, struct file_lock *);
 void             nlmclnt_next_cookie(struct nlm_cookie *);
@@ -174,12 +216,14 @@ void                nlmclnt_next_cookie(struct nlm_cookie *);
 /*
  * Host cache
  */
-struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr_in *sin,
-                                       int proto, u32 version,
+struct nlm_host  *nlmclnt_lookup_host(const struct sockaddr *sap,
+                                       const size_t salen,
+                                       const unsigned short protocol,
+                                       const u32 version,
+                                       const char *hostname);
+struct nlm_host  *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
                                        const char *hostname,
-                                       unsigned int hostname_len);
-struct nlm_host  *nlmsvc_lookup_host(struct svc_rqst *, const char *,
-                                       unsigned int);
+                                       const size_t hostname_len);
 struct rpc_clnt * nlm_bind_host(struct nlm_host *);
 void             nlm_rebind_host(struct nlm_host *);
 struct nlm_host * nlm_get_host(struct nlm_host *);
@@ -201,7 +245,7 @@ typedef int   (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
  */
 __be32           nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
                              struct nlm_host *, struct nlm_lock *, int,
-                             struct nlm_cookie *);
+                             struct nlm_cookie *, int);
 __be32           nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
 __be32           nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
                        struct nlm_host *, struct nlm_lock *,
@@ -233,15 +277,82 @@ static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
        return file->f_file->f_path.dentry->d_inode;
 }
 
+static inline int __nlm_privileged_request4(const struct sockaddr *sap)
+{
+       const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+       return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
+                       (ntohs(sin->sin_port) < 1024);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static inline int __nlm_privileged_request6(const struct sockaddr *sap)
+{
+       const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+       return (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK) &&
+                       (ntohs(sin6->sin6_port) < 1024);
+}
+#else  /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+static inline int __nlm_privileged_request6(const struct sockaddr *sap)
+{
+       return 0;
+}
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
 /*
- * Compare two host addresses (needs modifying for ipv6)
+ * Ensure incoming requests are from local privileged callers.
+ *
+ * Return TRUE if sender is local and is connecting via a privileged port;
+ * otherwise return FALSE.
  */
-static inline int nlm_cmp_addr(const struct sockaddr_in *sin1,
-                              const struct sockaddr_in *sin2)
+static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
 {
+       const struct sockaddr *sap = svc_addr(rqstp);
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               return __nlm_privileged_request4(sap);
+       case AF_INET6:
+               return __nlm_privileged_request6(sap);
+       default:
+               return 0;
+       }
+}
+
+static inline int __nlm_cmp_addr4(const struct sockaddr *sap1,
+                                 const struct sockaddr *sap2)
+{
+       const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
+       const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
        return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
 }
 
+static inline int __nlm_cmp_addr6(const struct sockaddr *sap1,
+                                 const struct sockaddr *sap2)
+{
+       const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
+       const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
+       return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
+}
+
+/*
+ * Compare two host addresses
+ *
+ * Return TRUE if the addresses are the same; otherwise FALSE.
+ */
+static inline int nlm_cmp_addr(const struct sockaddr *sap1,
+                              const struct sockaddr *sap2)
+{
+       if (sap1->sa_family == sap2->sa_family) {
+               switch (sap1->sa_family) {
+               case AF_INET:
+                       return __nlm_cmp_addr4(sap1, sap2);
+               case AF_INET6:
+                       return __nlm_cmp_addr6(sap1, sap2);
+               }
+       }
+       return 0;
+}
+
 /*
  * Compare two NLM locks.
  * When the second lock is of type F_UNLCK, this acts like a wildcard.
index df18fa053bcd7d0a1e1f9665e57efa8929dafb87..d6b3a802c0469a8e65311058167b6e2d5bacd76c 100644 (file)
@@ -81,8 +81,6 @@ struct nlm_reboot {
        unsigned int    len;
        u32             state;
        __be32          addr;
-       __be32          vers;
-       __be32          proto;
 };
 
 /*
index 1fa0c2ce4dec09456f5cb6c2480f6be5e5eb908a..f7f3fdddbef0b5f4f599cd506c524e4c9bf0b911 100644 (file)
@@ -6,6 +6,10 @@
 #define AFS_SUPER_MAGIC                0x5346414F
 #define AUTOFS_SUPER_MAGIC     0x0187
 #define CODA_SUPER_MAGIC       0x73757245
+#define DEBUGFS_MAGIC          0x64626720
+#define SYSFS_MAGIC            0x62656572
+#define SECURITYFS_MAGIC       0x73636673
+#define TMPFS_MAGIC            0x01021994
 #define EFS_SUPER_MAGIC                0x414A53
 #define EXT2_SUPER_MAGIC       0xEF53
 #define EXT3_SUPER_MAGIC       0xEF53
diff --git a/include/linux/map_to_7segment.h b/include/linux/map_to_7segment.h
new file mode 100644 (file)
index 0000000..7df8432
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MAP_TO_7SEGMENT_H
+#define MAP_TO_7SEGMENT_H
+
+/* This file provides translation primitives and tables for the conversion
+ * of (ASCII) characters to a 7-segments notation.
+ *
+ * The 7 segment's wikipedia notation below is used as standard.
+ * See: http://en.wikipedia.org/wiki/Seven_segment_display
+ *
+ * Notation:   +-a-+
+ *             f   b
+ *             +-g-+
+ *             e   c
+ *             +-d-+
+ *
+ * Usage:
+ *
+ *   Register a map variable, and fill it with a character set:
+ *     static SEG7_DEFAULT_MAP(map_seg7);
+ *
+ *
+ *   Then use for conversion:
+ *     seg7 = map_to_seg7(&map_seg7, some_char);
+ *     ...
+ *
+ * In device drivers it is recommended, if required, to make the char map
+ * accessible via the sysfs interface using the following scheme:
+ *
+ * static ssize_t show_map(struct device *dev, char *buf) {
+ *     memcpy(buf, &map_seg7, sizeof(map_seg7));
+ *     return sizeof(map_seg7);
+ * }
+ * static ssize_t store_map(struct device *dev, const char *buf, size_t cnt) {
+ *     if(cnt != sizeof(map_seg7))
+ *             return -EINVAL;
+ *     memcpy(&map_seg7, buf, cnt);
+ *     return cnt;
+ * }
+ * static DEVICE_ATTR(map_seg7, PERMS_RW, show_map, store_map);
+ *
+ * History:
+ * 2005-05-31  RFC linux-kernel@vger.kernel.org
+ */
+#include <linux/errno.h>
+
+
+#define BIT_SEG7_A             0
+#define BIT_SEG7_B             1
+#define BIT_SEG7_C             2
+#define BIT_SEG7_D             3
+#define BIT_SEG7_E             4
+#define BIT_SEG7_F             5
+#define BIT_SEG7_G             6
+#define BIT_SEG7_RESERVED      7
+
+struct seg7_conversion_map {
+       unsigned char   table[128];
+};
+
+static inline int map_to_seg7(struct seg7_conversion_map *map, int c)
+{
+       return c >= 0 && c < sizeof(map->table) ? map->table[c] : -EINVAL;
+}
+
+#define SEG7_CONVERSION_MAP(_name, _map)       \
+       struct seg7_conversion_map _name = { .table = { _map } }
+
+/*
+ * It is recommended to use a facility that allows user space to redefine
+ * custom character sets for LCD devices. Please use a sysfs interface
+ * as described above.
+ */
+#define MAP_TO_SEG7_SYSFS_FILE "map_seg7"
+
+/*******************************************************************************
+ * ASCII conversion table
+ ******************************************************************************/
+
+#define _SEG7(l,a,b,c,d,e,f,g) \
+      (        a<<BIT_SEG7_A | b<<BIT_SEG7_B | c<<BIT_SEG7_C | d<<BIT_SEG7_D | \
+       e<<BIT_SEG7_E | f<<BIT_SEG7_F | g<<BIT_SEG7_G )
+
+#define _MAP_0_32_ASCII_SEG7_NON_PRINTABLE     \
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+
+#define _MAP_33_47_ASCII_SEG7_SYMBOL           \
+ _SEG7('!',0,0,0,0,1,1,0), _SEG7('"',0,1,0,0,0,1,0), _SEG7('#',0,1,1,0,1,1,0),\
+ _SEG7('$',1,0,1,1,0,1,1), _SEG7('%',0,0,1,0,0,1,0), _SEG7('&',1,0,1,1,1,1,1),\
+ _SEG7('\'',0,0,0,0,0,1,0),_SEG7('(',1,0,0,1,1,1,0), _SEG7(')',1,1,1,1,0,0,0),\
+ _SEG7('*',0,1,1,0,1,1,1), _SEG7('+',0,1,1,0,0,0,1), _SEG7(',',0,0,0,0,1,0,0),\
+ _SEG7('-',0,0,0,0,0,0,1), _SEG7('.',0,0,0,0,1,0,0), _SEG7('/',0,1,0,0,1,0,1),
+
+#define _MAP_48_57_ASCII_SEG7_NUMERIC          \
+ _SEG7('0',1,1,1,1,1,1,0), _SEG7('1',0,1,1,0,0,0,0), _SEG7('2',1,1,0,1,1,0,1),\
+ _SEG7('3',1,1,1,1,0,0,1), _SEG7('4',0,1,1,0,0,1,1), _SEG7('5',1,0,1,1,0,1,1),\
+ _SEG7('6',1,0,1,1,1,1,1), _SEG7('7',1,1,1,0,0,0,0), _SEG7('8',1,1,1,1,1,1,1),\
+ _SEG7('9',1,1,1,1,0,1,1),
+
+#define _MAP_58_64_ASCII_SEG7_SYMBOL           \
+ _SEG7(':',0,0,0,1,0,0,1), _SEG7(';',0,0,0,1,0,0,1), _SEG7('<',1,0,0,0,0,1,1),\
+ _SEG7('=',0,0,0,1,0,0,1), _SEG7('>',1,1,0,0,0,0,1), _SEG7('?',1,1,1,0,0,1,0),\
+ _SEG7('@',1,1,0,1,1,1,1),
+
+#define _MAP_65_90_ASCII_SEG7_ALPHA_UPPR       \
+ _SEG7('A',1,1,1,0,1,1,1), _SEG7('B',1,1,1,1,1,1,1), _SEG7('C',1,0,0,1,1,1,0),\
+ _SEG7('D',1,1,1,1,1,1,0), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
+ _SEG7('G',1,1,1,1,0,1,1), _SEG7('H',0,1,1,0,1,1,1), _SEG7('I',0,1,1,0,0,0,0),\
+ _SEG7('J',0,1,1,1,0,0,0), _SEG7('K',0,1,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
+ _SEG7('M',1,1,1,0,1,1,0), _SEG7('N',1,1,1,0,1,1,0), _SEG7('O',1,1,1,1,1,1,0),\
+ _SEG7('P',1,1,0,0,1,1,1), _SEG7('Q',1,1,1,1,1,1,0), _SEG7('R',1,1,1,0,1,1,1),\
+ _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('U',0,1,1,1,1,1,0),\
+ _SEG7('V',0,1,1,1,1,1,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
+ _SEG7('Y',0,1,1,0,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
+
+#define _MAP_91_96_ASCII_SEG7_SYMBOL           \
+ _SEG7('[',1,0,0,1,1,1,0), _SEG7('\\',0,0,1,0,0,1,1),_SEG7(']',1,1,1,1,0,0,0),\
+ _SEG7('^',1,1,0,0,0,1,0), _SEG7('_',0,0,0,1,0,0,0), _SEG7('`',0,1,0,0,0,0,0),
+
+#define _MAP_97_122_ASCII_SEG7_ALPHA_LOWER     \
+ _SEG7('A',1,1,1,0,1,1,1), _SEG7('b',0,0,1,1,1,1,1), _SEG7('c',0,0,0,1,1,0,1),\
+ _SEG7('d',0,1,1,1,1,0,1), _SEG7('E',1,0,0,1,1,1,1), _SEG7('F',1,0,0,0,1,1,1),\
+ _SEG7('G',1,1,1,1,0,1,1), _SEG7('h',0,0,1,0,1,1,1), _SEG7('i',0,0,1,0,0,0,0),\
+ _SEG7('j',0,0,1,1,0,0,0), _SEG7('k',0,0,1,0,1,1,1), _SEG7('L',0,0,0,1,1,1,0),\
+ _SEG7('M',1,1,1,0,1,1,0), _SEG7('n',0,0,1,0,1,0,1), _SEG7('o',0,0,1,1,1,0,1),\
+ _SEG7('P',1,1,0,0,1,1,1), _SEG7('q',1,1,1,0,0,1,1), _SEG7('r',0,0,0,0,1,0,1),\
+ _SEG7('S',1,0,1,1,0,1,1), _SEG7('T',0,0,0,1,1,1,1), _SEG7('u',0,0,1,1,1,0,0),\
+ _SEG7('v',0,0,1,1,1,0,0), _SEG7('W',0,1,1,1,1,1,1), _SEG7('X',0,1,1,0,1,1,1),\
+ _SEG7('y',0,1,1,1,0,1,1), _SEG7('Z',1,1,0,1,1,0,1),
+
+#define _MAP_123_126_ASCII_SEG7_SYMBOL         \
+ _SEG7('{',1,0,0,1,1,1,0), _SEG7('|',0,0,0,0,1,1,0), _SEG7('}',1,1,1,1,0,0,0),\
+ _SEG7('~',1,0,0,0,0,0,0),
+
+/* Maps */
+
+/* This set tries to map as close as possible to the visible characteristics
+ * of the ASCII symbol, lowercase and uppercase letters may differ in
+ * presentation on the display.
+ */
+#define MAP_ASCII7SEG_ALPHANUM                 \
+       _MAP_0_32_ASCII_SEG7_NON_PRINTABLE      \
+       _MAP_33_47_ASCII_SEG7_SYMBOL            \
+       _MAP_48_57_ASCII_SEG7_NUMERIC           \
+       _MAP_58_64_ASCII_SEG7_SYMBOL            \
+       _MAP_65_90_ASCII_SEG7_ALPHA_UPPR        \
+       _MAP_91_96_ASCII_SEG7_SYMBOL            \
+       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
+       _MAP_123_126_ASCII_SEG7_SYMBOL
+
+/* This set tries to map as close as possible to the symbolic characteristics
+ * of the ASCII character for maximum discrimination.
+ * For now this means all alpha chars are in lower case representations.
+ * (This for example facilitates the use of hex numbers with uppercase input.)
+ */
+#define MAP_ASCII7SEG_ALPHANUM_LC                      \
+       _MAP_0_32_ASCII_SEG7_NON_PRINTABLE      \
+       _MAP_33_47_ASCII_SEG7_SYMBOL            \
+       _MAP_48_57_ASCII_SEG7_NUMERIC           \
+       _MAP_58_64_ASCII_SEG7_SYMBOL            \
+       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
+       _MAP_91_96_ASCII_SEG7_SYMBOL            \
+       _MAP_97_122_ASCII_SEG7_ALPHA_LOWER      \
+       _MAP_123_126_ASCII_SEG7_SYMBOL
+
+#define SEG7_DEFAULT_MAP(_name)                \
+       SEG7_CONVERSION_MAP(_name,MAP_ASCII7SEG_ALPHANUM)
+
+#endif /* MAP_TO_7SEGMENT_H */
+
index ec612e66391c62d66dbf26c39e9e2378ccc57a2b..516d955ab8a1bb9e63120a3bb79c0f0d4e08e297 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MFD_TMIO_H
 #define MFD_TMIO_H
 
+#include <linux/fb.h>
+
 #define tmio_ioread8(addr) readb(addr)
 #define tmio_ioread16(addr) readw(addr)
 #define tmio_ioread16_rep(r, b, l) readsw(r, b, l)
@@ -25,4 +27,21 @@ struct tmio_nand_data {
        unsigned int            num_partitions;
 };
 
+#define FBIO_TMIO_ACC_WRITE    0x7C639300
+#define FBIO_TMIO_ACC_SYNC     0x7C639301
+
+struct tmio_fb_data {
+       int                     (*lcd_set_power)(struct platform_device *fb_dev,
+                                                               bool on);
+       int                     (*lcd_mode)(struct platform_device *fb_dev,
+                                       const struct fb_videomode *mode);
+       int                     num_modes;
+       struct fb_videomode     *modes;
+
+       /* in mm: size of screen */
+       int                     height;
+       int                     width;
+};
+
+
 #endif
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
new file mode 100644 (file)
index 0000000..217bb22
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ * audio.h  --  Audio Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_AUDIO_H_
+#define __LINUX_MFD_WM8350_AUDIO_H_
+
+#include <linux/platform_device.h>
+
+#define WM8350_CLOCK_CONTROL_1                  0x28
+#define WM8350_CLOCK_CONTROL_2                  0x29
+#define WM8350_FLL_CONTROL_1                    0x2A
+#define WM8350_FLL_CONTROL_2                    0x2B
+#define WM8350_FLL_CONTROL_3                    0x2C
+#define WM8350_FLL_CONTROL_4                    0x2D
+#define WM8350_DAC_CONTROL                      0x30
+#define WM8350_DAC_DIGITAL_VOLUME_L             0x32
+#define WM8350_DAC_DIGITAL_VOLUME_R             0x33
+#define WM8350_DAC_LR_RATE                      0x35
+#define WM8350_DAC_CLOCK_CONTROL                0x36
+#define WM8350_DAC_MUTE                         0x3A
+#define WM8350_DAC_MUTE_VOLUME                  0x3B
+#define WM8350_DAC_SIDE                         0x3C
+#define WM8350_ADC_CONTROL                      0x40
+#define WM8350_ADC_DIGITAL_VOLUME_L             0x42
+#define WM8350_ADC_DIGITAL_VOLUME_R             0x43
+#define WM8350_ADC_DIVIDER                      0x44
+#define WM8350_ADC_LR_RATE                      0x46
+#define WM8350_INPUT_CONTROL                    0x48
+#define WM8350_IN3_INPUT_CONTROL                0x49
+#define WM8350_MIC_BIAS_CONTROL                 0x4A
+#define WM8350_OUTPUT_CONTROL                   0x4C
+#define WM8350_JACK_DETECT                      0x4D
+#define WM8350_ANTI_POP_CONTROL                 0x4E
+#define WM8350_LEFT_INPUT_VOLUME                0x50
+#define WM8350_RIGHT_INPUT_VOLUME               0x51
+#define WM8350_LEFT_MIXER_CONTROL               0x58
+#define WM8350_RIGHT_MIXER_CONTROL              0x59
+#define WM8350_OUT3_MIXER_CONTROL               0x5C
+#define WM8350_OUT4_MIXER_CONTROL               0x5D
+#define WM8350_OUTPUT_LEFT_MIXER_VOLUME         0x60
+#define WM8350_OUTPUT_RIGHT_MIXER_VOLUME        0x61
+#define WM8350_INPUT_MIXER_VOLUME_L             0x62
+#define WM8350_INPUT_MIXER_VOLUME_R             0x63
+#define WM8350_INPUT_MIXER_VOLUME               0x64
+#define WM8350_LOUT1_VOLUME                     0x68
+#define WM8350_ROUT1_VOLUME                     0x69
+#define WM8350_LOUT2_VOLUME                     0x6A
+#define WM8350_ROUT2_VOLUME                     0x6B
+#define WM8350_BEEP_VOLUME                      0x6F
+#define WM8350_AI_FORMATING                     0x70
+#define WM8350_ADC_DAC_COMP                     0x71
+#define WM8350_AI_ADC_CONTROL                   0x72
+#define WM8350_AI_DAC_CONTROL                   0x73
+#define WM8350_AIF_TEST                         0x74
+#define WM8350_JACK_PIN_STATUS                  0xE7
+
+/* Bit values for R08 (0x08) */
+#define WM8350_CODEC_ISEL_1_5                   0      /* x1.5 */
+#define WM8350_CODEC_ISEL_1_0                   1      /* x1.0 */
+#define WM8350_CODEC_ISEL_0_75                  2      /* x0.75 */
+#define WM8350_CODEC_ISEL_0_5                   3      /* x0.5 */
+
+#define WM8350_VMID_OFF                         0
+#define WM8350_VMID_500K                        1
+#define WM8350_VMID_100K                        2
+#define WM8350_VMID_10K                         3
+
+/*
+ * R40 (0x28) - Clock Control 1
+ */
+#define WM8350_TOCLK_RATE                       0x4000
+#define WM8350_MCLK_SEL                         0x0800
+#define WM8350_MCLK_DIV_MASK                    0x0100
+#define WM8350_BCLK_DIV_MASK                    0x00F0
+#define WM8350_OPCLK_DIV_MASK                   0x0007
+
+/*
+ * R41 (0x29) - Clock Control 2
+ */
+#define WM8350_LRC_ADC_SEL                      0x8000
+#define WM8350_MCLK_DIR                         0x0001
+
+/*
+ * R42 (0x2A) - FLL Control 1
+ */
+#define WM8350_FLL_DITHER_WIDTH_MASK            0x3000
+#define WM8350_FLL_DITHER_HP                    0x0800
+#define WM8350_FLL_OUTDIV_MASK                  0x0700
+#define WM8350_FLL_RSP_RATE_MASK                0x00F0
+#define WM8350_FLL_RATE_MASK                    0x0007
+
+/*
+ * R43 (0x2B) - FLL Control 2
+ */
+#define WM8350_FLL_RATIO_MASK                   0xF800
+#define WM8350_FLL_N_MASK                       0x03FF
+
+/*
+ * R44 (0x2C) - FLL Control 3
+ */
+#define WM8350_FLL_K_MASK                       0xFFFF
+
+/*
+ * R45 (0x2D) - FLL Control 4
+ */
+#define WM8350_FLL_FRAC                         0x0020
+#define WM8350_FLL_SLOW_LOCK_REF                0x0010
+#define WM8350_FLL_CLK_SRC_MASK                 0x0003
+
+/*
+ * R48 (0x30) - DAC Control
+ */
+#define WM8350_DAC_MONO                         0x2000
+#define WM8350_AIF_LRCLKRATE                    0x1000
+#define WM8350_DEEMP_MASK                       0x0030
+#define WM8350_DACL_DATINV                      0x0002
+#define WM8350_DACR_DATINV                      0x0001
+
+/*
+ * R50 (0x32) - DAC Digital Volume L
+ */
+#define WM8350_DAC_VU                           0x0100
+#define WM8350_DACL_VOL_MASK                    0x00FF
+
+/*
+ * R51 (0x33) - DAC Digital Volume R
+ */
+#define WM8350_DAC_VU                           0x0100
+#define WM8350_DACR_VOL_MASK                    0x00FF
+
+/*
+ * R53 (0x35) - DAC LR Rate
+ */
+#define WM8350_DACLRC_ENA                       0x0800
+#define WM8350_DACLRC_RATE_MASK                 0x07FF
+
+/*
+ * R54 (0x36) - DAC Clock Control
+ */
+#define WM8350_DACCLK_POL                       0x0010
+#define WM8350_DAC_CLKDIV_MASK                  0x0007
+
+/*
+ * R58 (0x3A) - DAC Mute
+ */
+#define WM8350_DAC_MUTE_ENA                     0x4000
+
+/*
+ * R59 (0x3B) - DAC Mute Volume
+ */
+#define WM8350_DAC_MUTEMODE                     0x4000
+#define WM8350_DAC_MUTERATE                     0x2000
+#define WM8350_DAC_SB_FILT                      0x1000
+
+/*
+ * R60 (0x3C) - DAC Side
+ */
+#define WM8350_ADC_TO_DACL_MASK                 0x3000
+#define WM8350_ADC_TO_DACR_MASK                 0x0C00
+
+/*
+ * R64 (0x40) - ADC Control
+ */
+#define WM8350_ADC_HPF_CUT_MASK                 0x0300
+#define WM8350_ADCL_DATINV                      0x0002
+#define WM8350_ADCR_DATINV                      0x0001
+
+/*
+ * R66 (0x42) - ADC Digital Volume L
+ */
+#define WM8350_ADC_VU                           0x0100
+#define WM8350_ADCL_VOL_MASK                    0x00FF
+
+/*
+ * R67 (0x43) - ADC Digital Volume R
+ */
+#define WM8350_ADC_VU                           0x0100
+#define WM8350_ADCR_VOL_MASK                    0x00FF
+
+/*
+ * R68 (0x44) - ADC Divider
+ */
+#define WM8350_ADCL_DAC_SVOL_MASK               0x0F00
+#define WM8350_ADCR_DAC_SVOL_MASK               0x00F0
+#define WM8350_ADCCLK_POL                       0x0008
+#define WM8350_ADC_CLKDIV_MASK                  0x0007
+
+/*
+ * R70 (0x46) - ADC LR Rate
+ */
+#define WM8350_ADCLRC_ENA                       0x0800
+#define WM8350_ADCLRC_RATE_MASK                 0x07FF
+
+/*
+ * R72 (0x48) - Input Control
+ */
+#define WM8350_IN2R_ENA                         0x0400
+#define WM8350_IN1RN_ENA                        0x0200
+#define WM8350_IN1RP_ENA                        0x0100
+#define WM8350_IN2L_ENA                         0x0004
+#define WM8350_IN1LN_ENA                        0x0002
+#define WM8350_IN1LP_ENA                        0x0001
+
+/*
+ * R73 (0x49) - IN3 Input Control
+ */
+#define WM8350_IN3R_SHORT                       0x4000
+#define WM8350_IN3L_SHORT                       0x0040
+
+/*
+ * R74 (0x4A) - Mic Bias Control
+ */
+#define WM8350_MICBSEL                          0x4000
+#define WM8350_MCDTHR_MASK                      0x001C
+#define WM8350_MCDSCTHR_MASK                    0x0003
+
+/*
+ * R76 (0x4C) - Output Control
+ */
+#define WM8350_OUT4_VROI                        0x0800
+#define WM8350_OUT3_VROI                        0x0400
+#define WM8350_OUT2_VROI                        0x0200
+#define WM8350_OUT1_VROI                        0x0100
+#define WM8350_OUT2_FB                          0x0004
+#define WM8350_OUT1_FB                          0x0001
+
+/*
+ * R77 (0x4D) - Jack Detect
+ */
+#define WM8350_JDL_ENA                          0x8000
+#define WM8350_JDR_ENA                          0x4000
+
+/*
+ * R78 (0x4E) - Anti Pop Control
+ */
+#define WM8350_ANTI_POP_MASK                    0x0300
+#define WM8350_DIS_OP_LN4_MASK                  0x00C0
+#define WM8350_DIS_OP_LN3_MASK                  0x0030
+#define WM8350_DIS_OP_OUT2_MASK                 0x000C
+#define WM8350_DIS_OP_OUT1_MASK                 0x0003
+
+/*
+ * R80 (0x50) - Left Input Volume
+ */
+#define WM8350_INL_MUTE                         0x4000
+#define WM8350_INL_ZC                           0x2000
+#define WM8350_IN_VU                            0x0100
+#define WM8350_INL_VOL_MASK                     0x00FC
+
+/*
+ * R81 (0x51) - Right Input Volume
+ */
+#define WM8350_INR_MUTE                         0x4000
+#define WM8350_INR_ZC                           0x2000
+#define WM8350_IN_VU                            0x0100
+#define WM8350_INR_VOL_MASK                     0x00FC
+
+/*
+ * R88 (0x58) - Left Mixer Control
+ */
+#define WM8350_DACR_TO_MIXOUTL                  0x1000
+#define WM8350_DACL_TO_MIXOUTL                  0x0800
+#define WM8350_IN3L_TO_MIXOUTL                  0x0004
+#define WM8350_INR_TO_MIXOUTL                   0x0002
+#define WM8350_INL_TO_MIXOUTL                   0x0001
+
+/*
+ * R89 (0x59) - Right Mixer Control
+ */
+#define WM8350_DACR_TO_MIXOUTR                  0x1000
+#define WM8350_DACL_TO_MIXOUTR                  0x0800
+#define WM8350_IN3R_TO_MIXOUTR                  0x0008
+#define WM8350_INR_TO_MIXOUTR                   0x0002
+#define WM8350_INL_TO_MIXOUTR                   0x0001
+
+/*
+ * R92 (0x5C) - OUT3 Mixer Control
+ */
+#define WM8350_DACL_TO_OUT3                     0x0800
+#define WM8350_MIXINL_TO_OUT3                   0x0100
+#define WM8350_OUT4_TO_OUT3                     0x0008
+#define WM8350_MIXOUTL_TO_OUT3                  0x0001
+
+/*
+ * R93 (0x5D) - OUT4 Mixer Control
+ */
+#define WM8350_DACR_TO_OUT4                     0x1000
+#define WM8350_DACL_TO_OUT4                     0x0800
+#define WM8350_OUT4_ATTN                        0x0400
+#define WM8350_MIXINR_TO_OUT4                   0x0200
+#define WM8350_OUT3_TO_OUT4                     0x0004
+#define WM8350_MIXOUTR_TO_OUT4                  0x0002
+#define WM8350_MIXOUTL_TO_OUT4                  0x0001
+
+/*
+ * R96 (0x60) - Output Left Mixer Volume
+ */
+#define WM8350_IN3L_MIXOUTL_VOL_MASK            0x0E00
+#define WM8350_IN3L_MIXOUTL_VOL_SHIFT                9
+#define WM8350_INR_MIXOUTL_VOL_MASK             0x00E0
+#define WM8350_INR_MIXOUTL_VOL_SHIFT                 5
+#define WM8350_INL_MIXOUTL_VOL_MASK             0x000E
+#define WM8350_INL_MIXOUTL_VOL_SHIFT                 1
+
+/* Bit values for R96 (0x60) */
+#define WM8350_IN3L_MIXOUTL_VOL_OFF                  0
+#define WM8350_IN3L_MIXOUTL_VOL_M12DB                1
+#define WM8350_IN3L_MIXOUTL_VOL_M9DB                 2
+#define WM8350_IN3L_MIXOUTL_VOL_M6DB                 3
+#define WM8350_IN3L_MIXOUTL_VOL_M3DB                 4
+#define WM8350_IN3L_MIXOUTL_VOL_0DB                  5
+#define WM8350_IN3L_MIXOUTL_VOL_3DB                  6
+#define WM8350_IN3L_MIXOUTL_VOL_6DB                  7
+
+#define WM8350_INR_MIXOUTL_VOL_OFF                   0
+#define WM8350_INR_MIXOUTL_VOL_M12DB                 1
+#define WM8350_INR_MIXOUTL_VOL_M9DB                  2
+#define WM8350_INR_MIXOUTL_VOL_M6DB                  3
+#define WM8350_INR_MIXOUTL_VOL_M3DB                  4
+#define WM8350_INR_MIXOUTL_VOL_0DB                   5
+#define WM8350_INR_MIXOUTL_VOL_3DB                   6
+#define WM8350_INR_MIXOUTL_VOL_6DB                   7
+
+#define WM8350_INL_MIXOUTL_VOL_OFF                   0
+#define WM8350_INL_MIXOUTL_VOL_M12DB                 1
+#define WM8350_INL_MIXOUTL_VOL_M9DB                  2
+#define WM8350_INL_MIXOUTL_VOL_M6DB                  3
+#define WM8350_INL_MIXOUTL_VOL_M3DB                  4
+#define WM8350_INL_MIXOUTL_VOL_0DB                   5
+#define WM8350_INL_MIXOUTL_VOL_3DB                   6
+#define WM8350_INL_MIXOUTL_VOL_6DB                   7
+
+/*
+ * R97 (0x61) - Output Right Mixer Volume
+ */
+#define WM8350_IN3R_MIXOUTR_VOL_MASK            0xE000
+#define WM8350_IN3R_MIXOUTR_VOL_SHIFT               13
+#define WM8350_INR_MIXOUTR_VOL_MASK             0x00E0
+#define WM8350_INR_MIXOUTR_VOL_SHIFT                 5
+#define WM8350_INL_MIXOUTR_VOL_MASK             0x000E
+#define WM8350_INL_MIXOUTR_VOL_SHIFT                 1
+
+/* Bit values for R96 (0x60) */
+#define WM8350_IN3R_MIXOUTR_VOL_OFF                  0
+#define WM8350_IN3R_MIXOUTR_VOL_M12DB                1
+#define WM8350_IN3R_MIXOUTR_VOL_M9DB                 2
+#define WM8350_IN3R_MIXOUTR_VOL_M6DB                 3
+#define WM8350_IN3R_MIXOUTR_VOL_M3DB                 4
+#define WM8350_IN3R_MIXOUTR_VOL_0DB                  5
+#define WM8350_IN3R_MIXOUTR_VOL_3DB                  6
+#define WM8350_IN3R_MIXOUTR_VOL_6DB                  7
+
+#define WM8350_INR_MIXOUTR_VOL_OFF                   0
+#define WM8350_INR_MIXOUTR_VOL_M12DB                 1
+#define WM8350_INR_MIXOUTR_VOL_M9DB                  2
+#define WM8350_INR_MIXOUTR_VOL_M6DB                  3
+#define WM8350_INR_MIXOUTR_VOL_M3DB                  4
+#define WM8350_INR_MIXOUTR_VOL_0DB                   5
+#define WM8350_INR_MIXOUTR_VOL_3DB                   6
+#define WM8350_INR_MIXOUTR_VOL_6DB                   7
+
+#define WM8350_INL_MIXOUTR_VOL_OFF                   0
+#define WM8350_INL_MIXOUTR_VOL_M12DB                 1
+#define WM8350_INL_MIXOUTR_VOL_M9DB                  2
+#define WM8350_INL_MIXOUTR_VOL_M6DB                  3
+#define WM8350_INL_MIXOUTR_VOL_M3DB                  4
+#define WM8350_INL_MIXOUTR_VOL_0DB                   5
+#define WM8350_INL_MIXOUTR_VOL_3DB                   6
+#define WM8350_INL_MIXOUTR_VOL_6DB                   7
+
+/*
+ * R98 (0x62) - Input Mixer Volume L
+ */
+#define WM8350_IN3L_MIXINL_VOL_MASK             0x0E00
+#define WM8350_IN2L_MIXINL_VOL_MASK             0x000E
+#define WM8350_INL_MIXINL_VOL                   0x0001
+
+/*
+ * R99 (0x63) - Input Mixer Volume R
+ */
+#define WM8350_IN3R_MIXINR_VOL_MASK             0xE000
+#define WM8350_IN2R_MIXINR_VOL_MASK             0x00E0
+#define WM8350_INR_MIXINR_VOL                   0x0001
+
+/*
+ * R100 (0x64) - Input Mixer Volume
+ */
+#define WM8350_OUT4_MIXIN_DST                   0x8000
+#define WM8350_OUT4_MIXIN_VOL_MASK              0x000E
+
+/*
+ * R104 (0x68) - LOUT1 Volume
+ */
+#define WM8350_OUT1L_MUTE                       0x4000
+#define WM8350_OUT1L_ZC                         0x2000
+#define WM8350_OUT1_VU                          0x0100
+#define WM8350_OUT1L_VOL_MASK                   0x00FC
+#define WM8350_OUT1L_VOL_SHIFT                       2
+
+/*
+ * R105 (0x69) - ROUT1 Volume
+ */
+#define WM8350_OUT1R_MUTE                       0x4000
+#define WM8350_OUT1R_ZC                         0x2000
+#define WM8350_OUT1_VU                          0x0100
+#define WM8350_OUT1R_VOL_MASK                   0x00FC
+#define WM8350_OUT1R_VOL_SHIFT                       2
+
+/*
+ * R106 (0x6A) - LOUT2 Volume
+ */
+#define WM8350_OUT2L_MUTE                       0x4000
+#define WM8350_OUT2L_ZC                         0x2000
+#define WM8350_OUT2_VU                          0x0100
+#define WM8350_OUT2L_VOL_MASK                   0x00FC
+
+/*
+ * R107 (0x6B) - ROUT2 Volume
+ */
+#define WM8350_OUT2R_MUTE                       0x4000
+#define WM8350_OUT2R_ZC                         0x2000
+#define WM8350_OUT2R_INV                        0x0400
+#define WM8350_OUT2R_INV_MUTE                   0x0200
+#define WM8350_OUT2_VU                          0x0100
+#define WM8350_OUT2R_VOL_MASK                   0x00FC
+
+/*
+ * R111 (0x6F) - BEEP Volume
+ */
+#define WM8350_IN3R_OUT2R_VOL_MASK              0x00E0
+
+/*
+ * R112 (0x70) - AI Formating
+ */
+#define WM8350_AIF_BCLK_INV                     0x8000
+#define WM8350_AIF_TRI                          0x2000
+#define WM8350_AIF_LRCLK_INV                    0x1000
+#define WM8350_AIF_WL_MASK                      0x0C00
+#define WM8350_AIF_FMT_MASK                     0x0300
+
+/*
+ * R113 (0x71) - ADC DAC COMP
+ */
+#define WM8350_DAC_COMP                         0x0080
+#define WM8350_DAC_COMPMODE                     0x0040
+#define WM8350_ADC_COMP                         0x0020
+#define WM8350_ADC_COMPMODE                     0x0010
+#define WM8350_LOOPBACK                         0x0001
+
+/*
+ * R114 (0x72) - AI ADC Control
+ */
+#define WM8350_AIFADC_PD                        0x0080
+#define WM8350_AIFADCL_SRC                      0x0040
+#define WM8350_AIFADCR_SRC                      0x0020
+#define WM8350_AIFADC_TDM_CHAN                  0x0010
+#define WM8350_AIFADC_TDM                       0x0008
+
+/*
+ * R115 (0x73) - AI DAC Control
+ */
+#define WM8350_BCLK_MSTR                        0x4000
+#define WM8350_AIFDAC_PD                        0x0080
+#define WM8350_DACL_SRC                         0x0040
+#define WM8350_DACR_SRC                         0x0020
+#define WM8350_AIFDAC_TDM_CHAN                  0x0010
+#define WM8350_AIFDAC_TDM                       0x0008
+#define WM8350_DAC_BOOST_MASK                   0x0003
+
+/*
+ * R116 (0x74) - AIF Test
+ */
+#define WM8350_CODEC_BYP                        0x4000
+#define WM8350_AIFADC_WR_TST                    0x2000
+#define WM8350_AIFADC_RD_TST                    0x1000
+#define WM8350_AIFDAC_WR_TST                    0x0800
+#define WM8350_AIFDAC_RD_TST                    0x0400
+#define WM8350_AIFADC_ASYN                      0x0020
+#define WM8350_AIFDAC_ASYN                      0x0010
+
+/*
+ * R231 (0xE7) - Jack Status
+ */
+#define WM8350_JACK_R_LVL                       0x0400
+
+/*
+ * WM8350 Platform setup
+ */
+#define WM8350_S_CURVE_NONE                    0x0
+#define WM8350_S_CURVE_FAST                    0x1
+#define WM8350_S_CURVE_MEDIUM                  0x2
+#define WM8350_S_CURVE_SLOW                    0x3
+
+#define WM8350_DISCHARGE_OFF                   0x0
+#define WM8350_DISCHARGE_FAST                  0x1
+#define WM8350_DISCHARGE_MEDIUM                        0x2
+#define WM8350_DISCHARGE_SLOW                  0x3
+
+#define WM8350_TIE_OFF_500R                    0x0
+#define WM8350_TIE_OFF_30K                     0x1
+
+/*
+ * Clock sources & directions
+ */
+#define WM8350_SYSCLK                          0
+
+#define WM8350_MCLK_SEL_PLL_MCLK               0
+#define WM8350_MCLK_SEL_PLL_DAC                        1
+#define WM8350_MCLK_SEL_PLL_ADC                        2
+#define WM8350_MCLK_SEL_PLL_32K                        3
+#define WM8350_MCLK_SEL_MCLK                   5
+
+#define WM8350_MCLK_DIR_OUT                    0
+#define WM8350_MCLK_DIR_IN                     1
+
+/* clock divider id's */
+#define WM8350_ADC_CLKDIV                      0
+#define WM8350_DAC_CLKDIV                      1
+#define WM8350_BCLK_CLKDIV                     2
+#define WM8350_OPCLK_CLKDIV                    3
+#define WM8350_TO_CLKDIV                       4
+#define WM8350_SYS_CLKDIV                      5
+#define WM8350_DACLR_CLKDIV                    6
+#define WM8350_ADCLR_CLKDIV                    7
+
+/* ADC clock dividers */
+#define WM8350_ADCDIV_1                                0x0
+#define WM8350_ADCDIV_1_5                      0x1
+#define WM8350_ADCDIV_2                                0x2
+#define WM8350_ADCDIV_3                                0x3
+#define WM8350_ADCDIV_4                                0x4
+#define WM8350_ADCDIV_5_5                      0x5
+#define WM8350_ADCDIV_6                                0x6
+
+/* ADC clock dividers */
+#define WM8350_DACDIV_1                                0x0
+#define WM8350_DACDIV_1_5                      0x1
+#define WM8350_DACDIV_2                                0x2
+#define WM8350_DACDIV_3                                0x3
+#define WM8350_DACDIV_4                                0x4
+#define WM8350_DACDIV_5_5                      0x5
+#define WM8350_DACDIV_6                                0x6
+
+/* BCLK clock dividers */
+#define WM8350_BCLK_DIV_1                      (0x0 << 4)
+#define WM8350_BCLK_DIV_1_5                    (0x1 << 4)
+#define WM8350_BCLK_DIV_2                      (0x2 << 4)
+#define WM8350_BCLK_DIV_3                      (0x3 << 4)
+#define WM8350_BCLK_DIV_4                      (0x4 << 4)
+#define WM8350_BCLK_DIV_5_5                    (0x5 << 4)
+#define WM8350_BCLK_DIV_6                      (0x6 << 4)
+#define WM8350_BCLK_DIV_8                      (0x7 << 4)
+#define WM8350_BCLK_DIV_11                     (0x8 << 4)
+#define WM8350_BCLK_DIV_12                     (0x9 << 4)
+#define WM8350_BCLK_DIV_16                     (0xa << 4)
+#define WM8350_BCLK_DIV_22                     (0xb << 4)
+#define WM8350_BCLK_DIV_24                     (0xc << 4)
+#define WM8350_BCLK_DIV_32                     (0xd << 4)
+#define WM8350_BCLK_DIV_44                     (0xe << 4)
+#define WM8350_BCLK_DIV_48                     (0xf << 4)
+
+/* Sys (MCLK) clock dividers */
+#define WM8350_MCLK_DIV_1                      (0x0 << 8)
+#define WM8350_MCLK_DIV_2                      (0x1 << 8)
+
+/* OP clock dividers */
+#define WM8350_OPCLK_DIV_1                     0x0
+#define WM8350_OPCLK_DIV_2                     0x1
+#define WM8350_OPCLK_DIV_3                     0x2
+#define WM8350_OPCLK_DIV_4                     0x3
+#define WM8350_OPCLK_DIV_5_5                   0x4
+#define WM8350_OPCLK_DIV_6                     0x5
+
+/* DAI ID */
+#define WM8350_HIFI_DAI                                0
+
+/*
+ * Audio interrupts.
+ */
+#define WM8350_IRQ_CODEC_JCK_DET_L             39
+#define WM8350_IRQ_CODEC_JCK_DET_R             40
+#define WM8350_IRQ_CODEC_MICSCD                        41
+#define WM8350_IRQ_CODEC_MICD                  42
+
+struct wm8350_codec {
+       struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/comparator.h b/include/linux/mfd/wm8350/comparator.h
new file mode 100644 (file)
index 0000000..0537886
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * comparator.h  --  Comparator Aux ADC for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_COMPARATOR_H_
+#define __LINUX_MFD_WM8350_COMPARATOR_H_
+
+/*
+ * Registers
+ */
+
+#define WM8350_DIGITISER_CONTROL_1              0x90
+#define WM8350_DIGITISER_CONTROL_2              0x91
+#define WM8350_AUX1_READBACK                    0x98
+#define WM8350_AUX2_READBACK                    0x99
+#define WM8350_AUX3_READBACK                    0x9A
+#define WM8350_AUX4_READBACK                    0x9B
+#define WM8350_CHIP_TEMP_READBACK               0x9F
+#define WM8350_GENERIC_COMPARATOR_CONTROL       0xA3
+#define WM8350_GENERIC_COMPARATOR_1             0xA4
+#define WM8350_GENERIC_COMPARATOR_2             0xA5
+#define WM8350_GENERIC_COMPARATOR_3             0xA6
+#define WM8350_GENERIC_COMPARATOR_4             0xA7
+
+/*
+ * R144 (0x90) - Digitiser Control (1)
+ */
+#define WM8350_AUXADC_CTC                       0x4000
+#define WM8350_AUXADC_POLL                      0x2000
+#define WM8350_AUXADC_HIB_MODE                  0x1000
+#define WM8350_AUXADC_SEL8                      0x0080
+#define WM8350_AUXADC_SEL7                      0x0040
+#define WM8350_AUXADC_SEL6                      0x0020
+#define WM8350_AUXADC_SEL5                      0x0010
+#define WM8350_AUXADC_SEL4                      0x0008
+#define WM8350_AUXADC_SEL3                      0x0004
+#define WM8350_AUXADC_SEL2                      0x0002
+#define WM8350_AUXADC_SEL1                      0x0001
+
+/*
+ * R145 (0x91) - Digitiser Control (2)
+ */
+#define WM8350_AUXADC_MASKMODE_MASK             0x3000
+#define WM8350_AUXADC_CRATE_MASK                0x0700
+#define WM8350_AUXADC_CAL                       0x0004
+#define WM8350_AUX_RBMODE                       0x0002
+#define WM8350_AUXADC_WAIT                      0x0001
+
+/*
+ * R152 (0x98) - AUX1 Readback
+ */
+#define WM8350_AUXADC_SCALE1_MASK               0x6000
+#define WM8350_AUXADC_REF1                      0x1000
+#define WM8350_AUXADC_DATA1_MASK                0x0FFF
+
+/*
+ * R153 (0x99) - AUX2 Readback
+ */
+#define WM8350_AUXADC_SCALE2_MASK               0x6000
+#define WM8350_AUXADC_REF2                      0x1000
+#define WM8350_AUXADC_DATA2_MASK                0x0FFF
+
+/*
+ * R154 (0x9A) - AUX3 Readback
+ */
+#define WM8350_AUXADC_SCALE3_MASK               0x6000
+#define WM8350_AUXADC_REF3                      0x1000
+#define WM8350_AUXADC_DATA3_MASK                0x0FFF
+
+/*
+ * R155 (0x9B) - AUX4 Readback
+ */
+#define WM8350_AUXADC_SCALE4_MASK               0x6000
+#define WM8350_AUXADC_REF4                      0x1000
+#define WM8350_AUXADC_DATA4_MASK                0x0FFF
+
+/*
+ * R156 (0x9C) - USB Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_USB_MASK             0x0FFF
+
+/*
+ * R157 (0x9D) - LINE Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_LINE_MASK            0x0FFF
+
+/*
+ * R158 (0x9E) - BATT Voltage Readback
+ */
+#define WM8350_AUXADC_DATA_BATT_MASK            0x0FFF
+
+/*
+ * R159 (0x9F) - Chip Temp Readback
+ */
+#define WM8350_AUXADC_DATA_CHIPTEMP_MASK        0x0FFF
+
+/*
+ * R163 (0xA3) - Generic Comparator Control
+ */
+#define WM8350_DCMP4_ENA                        0x0008
+#define WM8350_DCMP3_ENA                        0x0004
+#define WM8350_DCMP2_ENA                        0x0002
+#define WM8350_DCMP1_ENA                        0x0001
+
+/*
+ * R164 (0xA4) - Generic comparator 1
+ */
+#define WM8350_DCMP1_SRCSEL_MASK                0xE000
+#define WM8350_DCMP1_GT                         0x1000
+#define WM8350_DCMP1_THR_MASK                   0x0FFF
+
+/*
+ * R165 (0xA5) - Generic comparator 2
+ */
+#define WM8350_DCMP2_SRCSEL_MASK                0xE000
+#define WM8350_DCMP2_GT                         0x1000
+#define WM8350_DCMP2_THR_MASK                   0x0FFF
+
+/*
+ * R166 (0xA6) - Generic comparator 3
+ */
+#define WM8350_DCMP3_SRCSEL_MASK                0xE000
+#define WM8350_DCMP3_GT                         0x1000
+#define WM8350_DCMP3_THR_MASK                   0x0FFF
+
+/*
+ * R167 (0xA7) - Generic comparator 4
+ */
+#define WM8350_DCMP4_SRCSEL_MASK                0xE000
+#define WM8350_DCMP4_GT                         0x1000
+#define WM8350_DCMP4_THR_MASK                   0x0FFF
+
+/*
+ * Interrupts.
+ */
+#define WM8350_IRQ_AUXADC_DATARDY              16
+#define WM8350_IRQ_AUXADC_DCOMP4               17
+#define WM8350_IRQ_AUXADC_DCOMP3               18
+#define WM8350_IRQ_AUXADC_DCOMP2               19
+#define WM8350_IRQ_AUXADC_DCOMP1               20
+#define WM8350_IRQ_SYS_HYST_COMP_FAIL          21
+#define WM8350_IRQ_SYS_CHIP_GT115              22
+#define WM8350_IRQ_SYS_CHIP_GT140              23
+
+/*
+ * USB/2, LINE & BATT = ((VRTC * 2) / 4095)) * 10e6 uV
+ * Where VRTC = 2.7 V
+ */
+#define WM8350_AUX_COEFF                       1319
+
+#define WM8350_AUXADC_AUX1                     0
+#define WM8350_AUXADC_AUX2                     1
+#define WM8350_AUXADC_AUX3                     2
+#define WM8350_AUXADC_AUX4                     3
+#define WM8350_AUXADC_USB                      4
+#define WM8350_AUXADC_LINE                     5
+#define WM8350_AUXADC_BATT                     6
+#define WM8350_AUXADC_TEMP                     7
+
+#endif
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
new file mode 100644 (file)
index 0000000..6ebf97f
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+ * core.h  --  Core Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_CORE_H_
+#define __LINUX_MFD_WM8350_CORE_H_
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/gpio.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/mfd/wm8350/rtc.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/wdt.h>
+
+/*
+ * Register values.
+ */
+#define WM8350_RESET_ID                         0x00
+#define WM8350_ID                               0x01
+#define WM8350_SYSTEM_CONTROL_1                 0x03
+#define WM8350_SYSTEM_CONTROL_2                 0x04
+#define WM8350_SYSTEM_HIBERNATE                 0x05
+#define WM8350_INTERFACE_CONTROL                0x06
+#define WM8350_POWER_MGMT_1                     0x08
+#define WM8350_POWER_MGMT_2                     0x09
+#define WM8350_POWER_MGMT_3                     0x0A
+#define WM8350_POWER_MGMT_4                     0x0B
+#define WM8350_POWER_MGMT_5                     0x0C
+#define WM8350_POWER_MGMT_6                     0x0D
+#define WM8350_POWER_MGMT_7                     0x0E
+
+#define WM8350_SYSTEM_INTERRUPTS                0x18
+#define WM8350_INT_STATUS_1                     0x19
+#define WM8350_INT_STATUS_2                     0x1A
+#define WM8350_POWER_UP_INT_STATUS              0x1B
+#define WM8350_UNDER_VOLTAGE_INT_STATUS         0x1C
+#define WM8350_OVER_CURRENT_INT_STATUS          0x1D
+#define WM8350_GPIO_INT_STATUS                  0x1E
+#define WM8350_COMPARATOR_INT_STATUS            0x1F
+#define WM8350_SYSTEM_INTERRUPTS_MASK           0x20
+#define WM8350_INT_STATUS_1_MASK                0x21
+#define WM8350_INT_STATUS_2_MASK                0x22
+#define WM8350_POWER_UP_INT_STATUS_MASK         0x23
+#define WM8350_UNDER_VOLTAGE_INT_STATUS_MASK    0x24
+#define WM8350_OVER_CURRENT_INT_STATUS_MASK     0x25
+#define WM8350_GPIO_INT_STATUS_MASK             0x26
+#define WM8350_COMPARATOR_INT_STATUS_MASK       0x27
+
+#define WM8350_MAX_REGISTER                     0xFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset/ID
+ */
+#define WM8350_SW_RESET_CHIP_ID_MASK            0xFFFF
+
+/*
+ * R1 (0x01) - ID
+ */
+#define WM8350_CHIP_REV_MASK                    0x7000
+#define WM8350_CONF_STS_MASK                    0x0C00
+#define WM8350_CUST_ID_MASK                     0x00FF
+
+/*
+ * R3 (0x03) - System Control 1
+ */
+#define WM8350_CHIP_ON                          0x8000
+#define WM8350_POWERCYCLE                       0x2000
+#define WM8350_VCC_FAULT_OV                     0x1000
+#define WM8350_REG_RSTB_TIME_MASK               0x0C00
+#define WM8350_BG_SLEEP                         0x0200
+#define WM8350_MEM_VALID                        0x0020
+#define WM8350_CHIP_SET_UP                      0x0010
+#define WM8350_ON_DEB_T                         0x0008
+#define WM8350_ON_POL                           0x0002
+#define WM8350_IRQ_POL                          0x0001
+
+/*
+ * R4 (0x04) - System Control 2
+ */
+#define WM8350_USB_SUSPEND_8MA                  0x8000
+#define WM8350_USB_SUSPEND                      0x4000
+#define WM8350_USB_MSTR                         0x2000
+#define WM8350_USB_MSTR_SRC                     0x1000
+#define WM8350_USB_500MA                        0x0800
+#define WM8350_USB_NOLIM                        0x0400
+
+/*
+ * R5 (0x05) - System Hibernate
+ */
+#define WM8350_HIBERNATE                        0x8000
+#define WM8350_WDOG_HIB_MODE                    0x0080
+#define WM8350_REG_HIB_STARTUP_SEQ              0x0040
+#define WM8350_REG_RESET_HIB_MODE               0x0020
+#define WM8350_RST_HIB_MODE                     0x0010
+#define WM8350_IRQ_HIB_MODE                     0x0008
+#define WM8350_MEMRST_HIB_MODE                  0x0004
+#define WM8350_PCCOMP_HIB_MODE                  0x0002
+#define WM8350_TEMPMON_HIB_MODE                 0x0001
+
+/*
+ * R6 (0x06) - Interface Control
+ */
+#define WM8350_USE_DEV_PINS                     0x8000
+#define WM8350_USE_DEV_PINS_MASK                0x8000
+#define WM8350_USE_DEV_PINS_SHIFT                   15
+#define WM8350_DEV_ADDR_MASK                    0x6000
+#define WM8350_DEV_ADDR_SHIFT                       13
+#define WM8350_CONFIG_DONE                      0x1000
+#define WM8350_CONFIG_DONE_MASK                 0x1000
+#define WM8350_CONFIG_DONE_SHIFT                    12
+#define WM8350_RECONFIG_AT_ON                   0x0800
+#define WM8350_RECONFIG_AT_ON_MASK              0x0800
+#define WM8350_RECONFIG_AT_ON_SHIFT                 11
+#define WM8350_AUTOINC                          0x0200
+#define WM8350_AUTOINC_MASK                     0x0200
+#define WM8350_AUTOINC_SHIFT                         9
+#define WM8350_ARA                              0x0100
+#define WM8350_ARA_MASK                         0x0100
+#define WM8350_ARA_SHIFT                             8
+#define WM8350_SPI_CFG                          0x0008
+#define WM8350_SPI_CFG_MASK                     0x0008
+#define WM8350_SPI_CFG_SHIFT                         3
+#define WM8350_SPI_4WIRE                        0x0004
+#define WM8350_SPI_4WIRE_MASK                   0x0004
+#define WM8350_SPI_4WIRE_SHIFT                       2
+#define WM8350_SPI_3WIRE                        0x0002
+#define WM8350_SPI_3WIRE_MASK                   0x0002
+#define WM8350_SPI_3WIRE_SHIFT                       1
+
+/* Bit values for R06 (0x06) */
+#define WM8350_USE_DEV_PINS_PRIMARY                  0
+#define WM8350_USE_DEV_PINS_DEV                      1
+
+#define WM8350_DEV_ADDR_34                           0
+#define WM8350_DEV_ADDR_36                           1
+#define WM8350_DEV_ADDR_3C                           2
+#define WM8350_DEV_ADDR_3E                           3
+
+#define WM8350_CONFIG_DONE_OFF                       0
+#define WM8350_CONFIG_DONE_DONE                      1
+
+#define WM8350_RECONFIG_AT_ON_OFF                    0
+#define WM8350_RECONFIG_AT_ON_ON                     1
+
+#define WM8350_AUTOINC_OFF                           0
+#define WM8350_AUTOINC_ON                            1
+
+#define WM8350_ARA_OFF                               0
+#define WM8350_ARA_ON                                1
+
+#define WM8350_SPI_CFG_CMOS                          0
+#define WM8350_SPI_CFG_OD                            1
+
+#define WM8350_SPI_4WIRE_3WIRE                       0
+#define WM8350_SPI_4WIRE_4WIRE                       1
+
+#define WM8350_SPI_3WIRE_I2C                         0
+#define WM8350_SPI_3WIRE_SPI                         1
+
+/*
+ * R8 (0x08) - Power mgmt (1)
+ */
+#define WM8350_CODEC_ISEL_MASK                  0xC000
+#define WM8350_VBUFEN                           0x2000
+#define WM8350_OUTPUT_DRAIN_EN                  0x0400
+#define WM8350_MIC_DET_ENA                      0x0100
+#define WM8350_BIASEN                           0x0020
+#define WM8350_MICBEN                           0x0010
+#define WM8350_VMIDEN                           0x0004
+#define WM8350_VMID_MASK                        0x0003
+#define WM8350_VMID_SHIFT                            0
+
+/*
+ * R9 (0x09) - Power mgmt (2)
+ */
+#define WM8350_IN3R_ENA                         0x0800
+#define WM8350_IN3L_ENA                         0x0400
+#define WM8350_INR_ENA                          0x0200
+#define WM8350_INL_ENA                          0x0100
+#define WM8350_MIXINR_ENA                       0x0080
+#define WM8350_MIXINL_ENA                       0x0040
+#define WM8350_OUT4_ENA                         0x0020
+#define WM8350_OUT3_ENA                         0x0010
+#define WM8350_MIXOUTR_ENA                      0x0002
+#define WM8350_MIXOUTL_ENA                      0x0001
+
+/*
+ * R10 (0x0A) - Power mgmt (3)
+ */
+#define WM8350_IN3R_TO_OUT2R                    0x0080
+#define WM8350_OUT2R_ENA                        0x0008
+#define WM8350_OUT2L_ENA                        0x0004
+#define WM8350_OUT1R_ENA                        0x0002
+#define WM8350_OUT1L_ENA                        0x0001
+
+/*
+ * R11 (0x0B) - Power mgmt (4)
+ */
+#define WM8350_SYSCLK_ENA                       0x4000
+#define WM8350_ADC_HPF_ENA                      0x2000
+#define WM8350_FLL_ENA                          0x0800
+#define WM8350_FLL_OSC_ENA                      0x0400
+#define WM8350_TOCLK_ENA                        0x0100
+#define WM8350_DACR_ENA                         0x0020
+#define WM8350_DACL_ENA                         0x0010
+#define WM8350_ADCR_ENA                         0x0008
+#define WM8350_ADCL_ENA                         0x0004
+
+/*
+ * R12 (0x0C) - Power mgmt (5)
+ */
+#define WM8350_CODEC_ENA                        0x1000
+#define WM8350_RTC_TICK_ENA                     0x0800
+#define WM8350_OSC32K_ENA                       0x0400
+#define WM8350_CHG_ENA                          0x0200
+#define WM8350_ACC_DET_ENA                      0x0100
+#define WM8350_AUXADC_ENA                       0x0080
+#define WM8350_DCMP4_ENA                        0x0008
+#define WM8350_DCMP3_ENA                        0x0004
+#define WM8350_DCMP2_ENA                        0x0002
+#define WM8350_DCMP1_ENA                        0x0001
+
+/*
+ * R13 (0x0D) - Power mgmt (6)
+ */
+#define WM8350_LS_ENA                           0x8000
+#define WM8350_LDO4_ENA                         0x0800
+#define WM8350_LDO3_ENA                         0x0400
+#define WM8350_LDO2_ENA                         0x0200
+#define WM8350_LDO1_ENA                         0x0100
+#define WM8350_DC6_ENA                          0x0020
+#define WM8350_DC5_ENA                          0x0010
+#define WM8350_DC4_ENA                          0x0008
+#define WM8350_DC3_ENA                          0x0004
+#define WM8350_DC2_ENA                          0x0002
+#define WM8350_DC1_ENA                          0x0001
+
+/*
+ * R14 (0x0E) - Power mgmt (7)
+ */
+#define WM8350_CS2_ENA                          0x0002
+#define WM8350_CS1_ENA                          0x0001
+
+/*
+ * R24 (0x18) - System Interrupts
+ */
+#define WM8350_OC_INT                           0x2000
+#define WM8350_UV_INT                           0x1000
+#define WM8350_PUTO_INT                         0x0800
+#define WM8350_CS_INT                           0x0200
+#define WM8350_EXT_INT                          0x0100
+#define WM8350_CODEC_INT                        0x0080
+#define WM8350_GP_INT                           0x0040
+#define WM8350_AUXADC_INT                       0x0020
+#define WM8350_RTC_INT                          0x0010
+#define WM8350_SYS_INT                          0x0008
+#define WM8350_CHG_INT                          0x0004
+#define WM8350_USB_INT                          0x0002
+#define WM8350_WKUP_INT                         0x0001
+
+/*
+ * R25 (0x19) - Interrupt Status 1
+ */
+#define WM8350_CHG_BAT_HOT_EINT                 0x8000
+#define WM8350_CHG_BAT_COLD_EINT                0x4000
+#define WM8350_CHG_BAT_FAIL_EINT                0x2000
+#define WM8350_CHG_TO_EINT                      0x1000
+#define WM8350_CHG_END_EINT                     0x0800
+#define WM8350_CHG_START_EINT                   0x0400
+#define WM8350_CHG_FAST_RDY_EINT                0x0200
+#define WM8350_RTC_PER_EINT                     0x0080
+#define WM8350_RTC_SEC_EINT                     0x0040
+#define WM8350_RTC_ALM_EINT                     0x0020
+#define WM8350_CHG_VBATT_LT_3P9_EINT            0x0004
+#define WM8350_CHG_VBATT_LT_3P1_EINT            0x0002
+#define WM8350_CHG_VBATT_LT_2P85_EINT           0x0001
+
+/*
+ * R26 (0x1A) - Interrupt Status 2
+ */
+#define WM8350_CS1_EINT                         0x2000
+#define WM8350_CS2_EINT                         0x1000
+#define WM8350_USB_LIMIT_EINT                   0x0400
+#define WM8350_AUXADC_DATARDY_EINT              0x0100
+#define WM8350_AUXADC_DCOMP4_EINT               0x0080
+#define WM8350_AUXADC_DCOMP3_EINT               0x0040
+#define WM8350_AUXADC_DCOMP2_EINT               0x0020
+#define WM8350_AUXADC_DCOMP1_EINT               0x0010
+#define WM8350_SYS_HYST_COMP_FAIL_EINT          0x0008
+#define WM8350_SYS_CHIP_GT115_EINT              0x0004
+#define WM8350_SYS_CHIP_GT140_EINT              0x0002
+#define WM8350_SYS_WDOG_TO_EINT                 0x0001
+
+/*
+ * R27 (0x1B) - Power Up Interrupt Status
+ */
+#define WM8350_PUTO_LDO4_EINT                   0x0800
+#define WM8350_PUTO_LDO3_EINT                   0x0400
+#define WM8350_PUTO_LDO2_EINT                   0x0200
+#define WM8350_PUTO_LDO1_EINT                   0x0100
+#define WM8350_PUTO_DC6_EINT                    0x0020
+#define WM8350_PUTO_DC5_EINT                    0x0010
+#define WM8350_PUTO_DC4_EINT                    0x0008
+#define WM8350_PUTO_DC3_EINT                    0x0004
+#define WM8350_PUTO_DC2_EINT                    0x0002
+#define WM8350_PUTO_DC1_EINT                    0x0001
+
+/*
+ * R28 (0x1C) - Under Voltage Interrupt status
+ */
+#define WM8350_UV_LDO4_EINT                     0x0800
+#define WM8350_UV_LDO3_EINT                     0x0400
+#define WM8350_UV_LDO2_EINT                     0x0200
+#define WM8350_UV_LDO1_EINT                     0x0100
+#define WM8350_UV_DC6_EINT                      0x0020
+#define WM8350_UV_DC5_EINT                      0x0010
+#define WM8350_UV_DC4_EINT                      0x0008
+#define WM8350_UV_DC3_EINT                      0x0004
+#define WM8350_UV_DC2_EINT                      0x0002
+#define WM8350_UV_DC1_EINT                      0x0001
+
+/*
+ * R29 (0x1D) - Over Current Interrupt status
+ */
+#define WM8350_OC_LS_EINT                       0x8000
+
+/*
+ * R30 (0x1E) - GPIO Interrupt Status
+ */
+#define WM8350_GP12_EINT                        0x1000
+#define WM8350_GP11_EINT                        0x0800
+#define WM8350_GP10_EINT                        0x0400
+#define WM8350_GP9_EINT                         0x0200
+#define WM8350_GP8_EINT                         0x0100
+#define WM8350_GP7_EINT                         0x0080
+#define WM8350_GP6_EINT                         0x0040
+#define WM8350_GP5_EINT                         0x0020
+#define WM8350_GP4_EINT                         0x0010
+#define WM8350_GP3_EINT                         0x0008
+#define WM8350_GP2_EINT                         0x0004
+#define WM8350_GP1_EINT                         0x0002
+#define WM8350_GP0_EINT                         0x0001
+
+/*
+ * R31 (0x1F) - Comparator Interrupt Status
+ */
+#define WM8350_EXT_USB_FB_EINT                  0x8000
+#define WM8350_EXT_WALL_FB_EINT                 0x4000
+#define WM8350_EXT_BAT_FB_EINT                  0x2000
+#define WM8350_CODEC_JCK_DET_L_EINT             0x0800
+#define WM8350_CODEC_JCK_DET_R_EINT             0x0400
+#define WM8350_CODEC_MICSCD_EINT                0x0200
+#define WM8350_CODEC_MICD_EINT                  0x0100
+#define WM8350_WKUP_OFF_STATE_EINT              0x0040
+#define WM8350_WKUP_HIB_STATE_EINT              0x0020
+#define WM8350_WKUP_CONV_FAULT_EINT             0x0010
+#define WM8350_WKUP_WDOG_RST_EINT               0x0008
+#define WM8350_WKUP_GP_PWR_ON_EINT              0x0004
+#define WM8350_WKUP_ONKEY_EINT                  0x0002
+#define WM8350_WKUP_GP_WAKEUP_EINT              0x0001
+
+/*
+ * R32 (0x20) - System Interrupts Mask
+ */
+#define WM8350_IM_OC_INT                        0x2000
+#define WM8350_IM_UV_INT                        0x1000
+#define WM8350_IM_PUTO_INT                      0x0800
+#define WM8350_IM_SPARE_INT                     0x0400
+#define WM8350_IM_CS_INT                        0x0200
+#define WM8350_IM_EXT_INT                       0x0100
+#define WM8350_IM_CODEC_INT                     0x0080
+#define WM8350_IM_GP_INT                        0x0040
+#define WM8350_IM_AUXADC_INT                    0x0020
+#define WM8350_IM_RTC_INT                       0x0010
+#define WM8350_IM_SYS_INT                       0x0008
+#define WM8350_IM_CHG_INT                       0x0004
+#define WM8350_IM_USB_INT                       0x0002
+#define WM8350_IM_WKUP_INT                      0x0001
+
+/*
+ * R33 (0x21) - Interrupt Status 1 Mask
+ */
+#define WM8350_IM_CHG_BAT_HOT_EINT              0x8000
+#define WM8350_IM_CHG_BAT_COLD_EINT             0x4000
+#define WM8350_IM_CHG_BAT_FAIL_EINT             0x2000
+#define WM8350_IM_CHG_TO_EINT                   0x1000
+#define WM8350_IM_CHG_END_EINT                  0x0800
+#define WM8350_IM_CHG_START_EINT                0x0400
+#define WM8350_IM_CHG_FAST_RDY_EINT             0x0200
+#define WM8350_IM_RTC_PER_EINT                  0x0080
+#define WM8350_IM_RTC_SEC_EINT                  0x0040
+#define WM8350_IM_RTC_ALM_EINT                  0x0020
+#define WM8350_IM_CHG_VBATT_LT_3P9_EINT         0x0004
+#define WM8350_IM_CHG_VBATT_LT_3P1_EINT         0x0002
+#define WM8350_IM_CHG_VBATT_LT_2P85_EINT        0x0001
+
+/*
+ * R34 (0x22) - Interrupt Status 2 Mask
+ */
+#define WM8350_IM_SPARE2_EINT                   0x8000
+#define WM8350_IM_SPARE1_EINT                   0x4000
+#define WM8350_IM_CS1_EINT                      0x2000
+#define WM8350_IM_CS2_EINT                      0x1000
+#define WM8350_IM_USB_LIMIT_EINT                0x0400
+#define WM8350_IM_AUXADC_DATARDY_EINT           0x0100
+#define WM8350_IM_AUXADC_DCOMP4_EINT            0x0080
+#define WM8350_IM_AUXADC_DCOMP3_EINT            0x0040
+#define WM8350_IM_AUXADC_DCOMP2_EINT            0x0020
+#define WM8350_IM_AUXADC_DCOMP1_EINT            0x0010
+#define WM8350_IM_SYS_HYST_COMP_FAIL_EINT       0x0008
+#define WM8350_IM_SYS_CHIP_GT115_EINT           0x0004
+#define WM8350_IM_SYS_CHIP_GT140_EINT           0x0002
+#define WM8350_IM_SYS_WDOG_TO_EINT              0x0001
+
+/*
+ * R35 (0x23) - Power Up Interrupt Status Mask
+ */
+#define WM8350_IM_PUTO_LDO4_EINT                0x0800
+#define WM8350_IM_PUTO_LDO3_EINT                0x0400
+#define WM8350_IM_PUTO_LDO2_EINT                0x0200
+#define WM8350_IM_PUTO_LDO1_EINT                0x0100
+#define WM8350_IM_PUTO_DC6_EINT                 0x0020
+#define WM8350_IM_PUTO_DC5_EINT                 0x0010
+#define WM8350_IM_PUTO_DC4_EINT                 0x0008
+#define WM8350_IM_PUTO_DC3_EINT                 0x0004
+#define WM8350_IM_PUTO_DC2_EINT                 0x0002
+#define WM8350_IM_PUTO_DC1_EINT                 0x0001
+
+/*
+ * R36 (0x24) - Under Voltage Interrupt status Mask
+ */
+#define WM8350_IM_UV_LDO4_EINT                  0x0800
+#define WM8350_IM_UV_LDO3_EINT                  0x0400
+#define WM8350_IM_UV_LDO2_EINT                  0x0200
+#define WM8350_IM_UV_LDO1_EINT                  0x0100
+#define WM8350_IM_UV_DC6_EINT                   0x0020
+#define WM8350_IM_UV_DC5_EINT                   0x0010
+#define WM8350_IM_UV_DC4_EINT                   0x0008
+#define WM8350_IM_UV_DC3_EINT                   0x0004
+#define WM8350_IM_UV_DC2_EINT                   0x0002
+#define WM8350_IM_UV_DC1_EINT                   0x0001
+
+/*
+ * R37 (0x25) - Over Current Interrupt status Mask
+ */
+#define WM8350_IM_OC_LS_EINT                    0x8000
+
+/*
+ * R38 (0x26) - GPIO Interrupt Status Mask
+ */
+#define WM8350_IM_GP12_EINT                     0x1000
+#define WM8350_IM_GP11_EINT                     0x0800
+#define WM8350_IM_GP10_EINT                     0x0400
+#define WM8350_IM_GP9_EINT                      0x0200
+#define WM8350_IM_GP8_EINT                      0x0100
+#define WM8350_IM_GP7_EINT                      0x0080
+#define WM8350_IM_GP6_EINT                      0x0040
+#define WM8350_IM_GP5_EINT                      0x0020
+#define WM8350_IM_GP4_EINT                      0x0010
+#define WM8350_IM_GP3_EINT                      0x0008
+#define WM8350_IM_GP2_EINT                      0x0004
+#define WM8350_IM_GP1_EINT                      0x0002
+#define WM8350_IM_GP0_EINT                      0x0001
+
+/*
+ * R39 (0x27) - Comparator Interrupt Status Mask
+ */
+#define WM8350_IM_EXT_USB_FB_EINT               0x8000
+#define WM8350_IM_EXT_WALL_FB_EINT              0x4000
+#define WM8350_IM_EXT_BAT_FB_EINT               0x2000
+#define WM8350_IM_CODEC_JCK_DET_L_EINT          0x0800
+#define WM8350_IM_CODEC_JCK_DET_R_EINT          0x0400
+#define WM8350_IM_CODEC_MICSCD_EINT             0x0200
+#define WM8350_IM_CODEC_MICD_EINT               0x0100
+#define WM8350_IM_WKUP_OFF_STATE_EINT           0x0040
+#define WM8350_IM_WKUP_HIB_STATE_EINT           0x0020
+#define WM8350_IM_WKUP_CONV_FAULT_EINT          0x0010
+#define WM8350_IM_WKUP_WDOG_RST_EINT            0x0008
+#define WM8350_IM_WKUP_GP_PWR_ON_EINT           0x0004
+#define WM8350_IM_WKUP_ONKEY_EINT               0x0002
+#define WM8350_IM_WKUP_GP_WAKEUP_EINT           0x0001
+
+/*
+ * R220 (0xDC) - RAM BIST 1
+ */
+#define WM8350_READ_STATUS                      0x0800
+#define WM8350_TSTRAM_CLK                       0x0100
+#define WM8350_TSTRAM_CLK_ENA                   0x0080
+#define WM8350_STARTSEQ                         0x0040
+#define WM8350_READ_SRC                         0x0020
+#define WM8350_COUNT_DIR                        0x0010
+#define WM8350_TSTRAM_MODE_MASK                 0x000E
+#define WM8350_TSTRAM_ENA                       0x0001
+
+/*
+ * R225 (0xE1) - DCDC/LDO status
+ */
+#define WM8350_LS_STS                           0x8000
+#define WM8350_LDO4_STS                         0x0800
+#define WM8350_LDO3_STS                         0x0400
+#define WM8350_LDO2_STS                         0x0200
+#define WM8350_LDO1_STS                         0x0100
+#define WM8350_DC6_STS                          0x0020
+#define WM8350_DC5_STS                          0x0010
+#define WM8350_DC4_STS                          0x0008
+#define WM8350_DC3_STS                          0x0004
+#define WM8350_DC2_STS                          0x0002
+#define WM8350_DC1_STS                          0x0001
+
+/* WM8350 wake up conditions */
+#define WM8350_IRQ_WKUP_OFF_STATE              43
+#define WM8350_IRQ_WKUP_HIB_STATE              44
+#define WM8350_IRQ_WKUP_CONV_FAULT             45
+#define WM8350_IRQ_WKUP_WDOG_RST               46
+#define WM8350_IRQ_WKUP_GP_PWR_ON              47
+#define WM8350_IRQ_WKUP_ONKEY                  48
+#define WM8350_IRQ_WKUP_GP_WAKEUP              49
+
+/* wm8350 chip revisions */
+#define WM8350_REV_E                           0x4
+#define WM8350_REV_F                           0x5
+#define WM8350_REV_G                           0x6
+
+#define WM8350_NUM_IRQ                         63
+
+struct wm8350_reg_access {
+       u16 readable;           /* Mask of readable bits */
+       u16 writable;           /* Mask of writable bits */
+       u16 vol;                /* Mask of volatile bits */
+};
+extern const struct wm8350_reg_access wm8350_reg_io_map[];
+extern const u16 wm8350_mode0_defaults[];
+extern const u16 wm8350_mode1_defaults[];
+extern const u16 wm8350_mode2_defaults[];
+extern const u16 wm8350_mode3_defaults[];
+
+struct wm8350;
+
+struct wm8350_irq {
+       void (*handler) (struct wm8350 *, int, void *);
+       void *data;
+};
+
+struct wm8350 {
+       int rev;                /* chip revision */
+
+       struct device *dev;
+
+       /* device IO */
+       union {
+               struct i2c_client *i2c_client;
+               struct spi_device *spi_device;
+       };
+       int (*read_dev)(struct wm8350 *wm8350, char reg, int size, void *dest);
+       int (*write_dev)(struct wm8350 *wm8350, char reg, int size,
+                        void *src);
+       u16 *reg_cache;
+
+       /* Interrupt handling */
+       struct work_struct irq_work;
+       struct mutex irq_mutex; /* IRQ table mutex */
+       struct wm8350_irq irq[WM8350_NUM_IRQ];
+       int chip_irq;
+
+       /* Client devices */
+       struct wm8350_codec codec;
+       struct wm8350_gpio gpio;
+       struct wm8350_pmic pmic;
+       struct wm8350_power power;
+       struct wm8350_rtc rtc;
+       struct wm8350_wdt wdt;
+};
+
+/**
+ * Data to be supplied by the platform to initialise the WM8350.
+ *
+ * @init: Function called during driver initialisation.  Should be
+ *        used by the platform to configure GPIO functions and similar.
+ */
+struct wm8350_platform_data {
+       int (*init)(struct wm8350 *wm8350);
+};
+
+
+/*
+ * WM8350 device initialisation and exit.
+ */
+int wm8350_device_init(struct wm8350 *wm8350, int irq,
+                      struct wm8350_platform_data *pdata);
+void wm8350_device_exit(struct wm8350 *wm8350);
+
+/*
+ * WM8350 device IO
+ */
+int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask);
+int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask);
+u16 wm8350_reg_read(struct wm8350 *wm8350, int reg);
+int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val);
+int wm8350_reg_lock(struct wm8350 *wm8350);
+int wm8350_reg_unlock(struct wm8350 *wm8350);
+int wm8350_block_read(struct wm8350 *wm8350, int reg, int size, u16 *dest);
+int wm8350_block_write(struct wm8350 *wm8350, int reg, int size, u16 *src);
+
+/*
+ * WM8350 internal interrupts
+ */
+int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+                       void (*handler) (struct wm8350 *, int, void *),
+                       void *data);
+int wm8350_free_irq(struct wm8350 *wm8350, int irq);
+int wm8350_mask_irq(struct wm8350 *wm8350, int irq);
+int wm8350_unmask_irq(struct wm8350 *wm8350, int irq);
+
+
+#endif
diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h
new file mode 100644 (file)
index 0000000..ed91e8f
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * gpio.h  --  GPIO Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_GPIO_H_
+#define __LINUX_MFD_WM8350_GPIO_H_
+
+#include <linux/platform_device.h>
+
+/*
+ * GPIO Registers.
+ */
+#define WM8350_GPIO_DEBOUNCE                    0x80
+#define WM8350_GPIO_PIN_PULL_UP_CONTROL         0x81
+#define WM8350_GPIO_PULL_DOWN_CONTROL           0x82
+#define WM8350_GPIO_INT_MODE                    0x83
+#define WM8350_GPIO_CONTROL                     0x85
+#define WM8350_GPIO_CONFIGURATION_I_O           0x86
+#define WM8350_GPIO_PIN_POLARITY_TYPE           0x87
+#define WM8350_GPIO_FUNCTION_SELECT_1           0x8C
+#define WM8350_GPIO_FUNCTION_SELECT_2           0x8D
+#define WM8350_GPIO_FUNCTION_SELECT_3           0x8E
+#define WM8350_GPIO_FUNCTION_SELECT_4           0x8F
+
+/*
+ * GPIO Functions
+ */
+#define WM8350_GPIO0_GPIO_IN                   0x0
+#define WM8350_GPIO0_GPIO_OUT                  0x0
+#define WM8350_GPIO0_PWR_ON_IN                 0x1
+#define WM8350_GPIO0_PWR_ON_OUT                        0x1
+#define WM8350_GPIO0_LDO_EN_IN                 0x2
+#define WM8350_GPIO0_VRTC_OUT                  0x2
+#define WM8350_GPIO0_LPWR1_IN                  0x3
+#define WM8350_GPIO0_POR_B_OUT                 0x3
+
+#define WM8350_GPIO1_GPIO_IN                   0x0
+#define WM8350_GPIO1_GPIO_OUT                  0x0
+#define WM8350_GPIO1_PWR_ON_IN                 0x1
+#define WM8350_GPIO1_DO_CONF_OUT               0x1
+#define WM8350_GPIO1_LDO_EN_IN                 0x2
+#define WM8350_GPIO1_RESET_OUT                 0x2
+#define WM8350_GPIO1_LPWR2_IN                  0x3
+#define WM8350_GPIO1_MEMRST_OUT                        0x3
+
+#define WM8350_GPIO2_GPIO_IN                   0x0
+#define WM8350_GPIO2_GPIO_OUT                  0x0
+#define WM8350_GPIO2_PWR_ON_IN                 0x1
+#define WM8350_GPIO2_PWR_ON_OUT                        0x1
+#define WM8350_GPIO2_WAKE_UP_IN                        0x2
+#define WM8350_GPIO2_VRTC_OUT                  0x2
+#define WM8350_GPIO2_32KHZ_IN                  0x3
+#define WM8350_GPIO2_32KHZ_OUT                 0x3
+
+#define WM8350_GPIO3_GPIO_IN                   0x0
+#define WM8350_GPIO3_GPIO_OUT                  0x0
+#define WM8350_GPIO3_PWR_ON_IN                 0x1
+#define WM8350_GPIO3_P_CLK_OUT                 0x1
+#define WM8350_GPIO3_LDO_EN_IN                 0x2
+#define WM8350_GPIO3_VRTC_OUT                  0x2
+#define WM8350_GPIO3_PWR_OFF_IN                        0x3
+#define WM8350_GPIO3_32KHZ_OUT                 0x3
+
+#define WM8350_GPIO4_GPIO_IN                   0x0
+#define WM8350_GPIO4_GPIO_OUT                  0x0
+#define WM8350_GPIO4_MR_IN                     0x1
+#define WM8350_GPIO4_MEM_RST_OUT               0x1
+#define WM8350_GPIO4_FLASH_IN                  0x2
+#define WM8350_GPIO4_ADA_OUT                   0x2
+#define WM8350_GPIO4_HIBERNATE_IN              0x3
+#define WM8350_GPIO4_FLASH_OUT                 0x3
+#define WM8350_GPIO4_MICDET_OUT                        0x4
+#define WM8350_GPIO4_MICSHT_OUT                        0x5
+
+#define WM8350_GPIO5_GPIO_IN                   0x0
+#define WM8350_GPIO5_GPIO_OUT                  0x0
+#define WM8350_GPIO5_LPWR1_IN                  0x1
+#define WM8350_GPIO5_P_CLK_OUT                 0x1
+#define WM8350_GPIO5_ADCLRCLK_IN               0x2
+#define WM8350_GPIO5_ADCLRCLK_OUT              0x2
+#define WM8350_GPIO5_HIBERNATE_IN              0x3
+#define WM8350_GPIO5_32KHZ_OUT                 0x3
+#define WM8350_GPIO5_MICDET_OUT                        0x4
+#define WM8350_GPIO5_MICSHT_OUT                        0x5
+#define WM8350_GPIO5_ADA_OUT                   0x6
+#define WM8350_GPIO5_OPCLK_OUT                 0x7
+
+#define WM8350_GPIO6_GPIO_IN                   0x0
+#define WM8350_GPIO6_GPIO_OUT                  0x0
+#define WM8350_GPIO6_LPWR2_IN                  0x1
+#define WM8350_GPIO6_MEMRST_OUT                        0x1
+#define WM8350_GPIO6_FLASH_IN                  0x2
+#define WM8350_GPIO6_ADA_OUT                   0x2
+#define WM8350_GPIO6_HIBERNATE_IN              0x3
+#define WM8350_GPIO6_RTC_OUT                   0x3
+#define WM8350_GPIO6_MICDET_OUT                        0x4
+#define WM8350_GPIO6_MICSHT_OUT                        0x5
+#define WM8350_GPIO6_ADCLRCLKB_OUT             0x6
+#define WM8350_GPIO6_SDOUT_OUT                 0x7
+
+#define WM8350_GPIO7_GPIO_IN                   0x0
+#define WM8350_GPIO7_GPIO_OUT                  0x0
+#define WM8350_GPIO7_LPWR3_IN                  0x1
+#define WM8350_GPIO7_P_CLK_OUT                 0x1
+#define WM8350_GPIO7_MASK_IN                   0x2
+#define WM8350_GPIO7_VCC_FAULT_OUT             0x2
+#define WM8350_GPIO7_HIBERNATE_IN              0x3
+#define WM8350_GPIO7_BATT_FAULT_OUT            0x3
+#define WM8350_GPIO7_MICDET_OUT                        0x4
+#define WM8350_GPIO7_MICSHT_OUT                        0x5
+#define WM8350_GPIO7_ADA_OUT                   0x6
+#define WM8350_GPIO7_CSB_IN                    0x7
+
+#define WM8350_GPIO8_GPIO_IN                   0x0
+#define WM8350_GPIO8_GPIO_OUT                  0x0
+#define WM8350_GPIO8_MR_IN                     0x1
+#define WM8350_GPIO8_VCC_FAULT_OUT             0x1
+#define WM8350_GPIO8_ADCBCLK_IN                        0x2
+#define WM8350_GPIO8_ADCBCLK_OUT               0x2
+#define WM8350_GPIO8_PWR_OFF_IN                        0x3
+#define WM8350_GPIO8_BATT_FAULT_OUT            0x3
+#define WM8350_GPIO8_ALTSCL_IN                 0xf
+
+#define WM8350_GPIO9_GPIO_IN                   0x0
+#define WM8350_GPIO9_GPIO_OUT                  0x0
+#define WM8350_GPIO9_HEARTBEAT_IN              0x1
+#define WM8350_GPIO9_VCC_FAULT_OUT             0x1
+#define WM8350_GPIO9_MASK_IN                   0x2
+#define WM8350_GPIO9_LINE_GT_BATT_OUT          0x2
+#define WM8350_GPIO9_PWR_OFF_IN                        0x3
+#define WM8350_GPIO9_BATT_FAULT_OUT            0x3
+#define WM8350_GPIO9_ALTSDA_OUT                        0xf
+
+#define WM8350_GPIO10_GPIO_IN                  0x0
+#define WM8350_GPIO10_GPIO_OUT                 0x0
+#define WM8350_GPIO10_ISINKC_OUT               0x1
+#define WM8350_GPIO10_PWR_OFF_IN               0x2
+#define WM8350_GPIO10_LINE_GT_BATT_OUT         0x2
+#define WM8350_GPIO10_CHD_IND_IN               0x3
+
+#define WM8350_GPIO11_GPIO_IN                  0x0
+#define WM8350_GPIO11_GPIO_OUT                 0x0
+#define WM8350_GPIO11_ISINKD_OUT               0x1
+#define WM8350_GPIO11_WAKEUP_IN                        0x2
+#define WM8350_GPIO11_LINE_GT_BATT_OUT         0x2
+#define WM8350_GPIO11_CHD_IND_IN               0x3
+
+#define WM8350_GPIO12_GPIO_IN                  0x0
+#define WM8350_GPIO12_GPIO_OUT                 0x0
+#define WM8350_GPIO12_ISINKE_OUT               0x1
+#define WM8350_GPIO12_LINE_GT_BATT_OUT         0x2
+#define WM8350_GPIO12_LINE_EN_OUT              0x3
+#define WM8350_GPIO12_32KHZ_OUT                        0x4
+
+#define WM8350_GPIO_DIR_IN                     0
+#define WM8350_GPIO_DIR_OUT                    1
+#define WM8350_GPIO_ACTIVE_LOW                 0
+#define WM8350_GPIO_ACTIVE_HIGH                        1
+#define WM8350_GPIO_PULL_NONE                  0
+#define WM8350_GPIO_PULL_UP                    1
+#define WM8350_GPIO_PULL_DOWN                  2
+#define WM8350_GPIO_INVERT_OFF                 0
+#define WM8350_GPIO_INVERT_ON                  1
+#define WM8350_GPIO_DEBOUNCE_OFF               0
+#define WM8350_GPIO_DEBOUNCE_ON                        1
+
+/*
+ * R128 (0x80) - GPIO Debounce
+ */
+#define WM8350_GP12_DB                          0x1000
+#define WM8350_GP11_DB                          0x0800
+#define WM8350_GP10_DB                          0x0400
+#define WM8350_GP9_DB                           0x0200
+#define WM8350_GP8_DB                           0x0100
+#define WM8350_GP7_DB                           0x0080
+#define WM8350_GP6_DB                           0x0040
+#define WM8350_GP5_DB                           0x0020
+#define WM8350_GP4_DB                           0x0010
+#define WM8350_GP3_DB                           0x0008
+#define WM8350_GP2_DB                           0x0004
+#define WM8350_GP1_DB                           0x0002
+#define WM8350_GP0_DB                           0x0001
+
+/*
+ * R129 (0x81) - GPIO Pin pull up Control
+ */
+#define WM8350_GP12_PU                          0x1000
+#define WM8350_GP11_PU                          0x0800
+#define WM8350_GP10_PU                          0x0400
+#define WM8350_GP9_PU                           0x0200
+#define WM8350_GP8_PU                           0x0100
+#define WM8350_GP7_PU                           0x0080
+#define WM8350_GP6_PU                           0x0040
+#define WM8350_GP5_PU                           0x0020
+#define WM8350_GP4_PU                           0x0010
+#define WM8350_GP3_PU                           0x0008
+#define WM8350_GP2_PU                           0x0004
+#define WM8350_GP1_PU                           0x0002
+#define WM8350_GP0_PU                           0x0001
+
+/*
+ * R130 (0x82) - GPIO Pull down Control
+ */
+#define WM8350_GP12_PD                          0x1000
+#define WM8350_GP11_PD                          0x0800
+#define WM8350_GP10_PD                          0x0400
+#define WM8350_GP9_PD                           0x0200
+#define WM8350_GP8_PD                           0x0100
+#define WM8350_GP7_PD                           0x0080
+#define WM8350_GP6_PD                           0x0040
+#define WM8350_GP5_PD                           0x0020
+#define WM8350_GP4_PD                           0x0010
+#define WM8350_GP3_PD                           0x0008
+#define WM8350_GP2_PD                           0x0004
+#define WM8350_GP1_PD                           0x0002
+#define WM8350_GP0_PD                           0x0001
+
+/*
+ * R131 (0x83) - GPIO Interrupt Mode
+ */
+#define WM8350_GP12_INTMODE                     0x1000
+#define WM8350_GP11_INTMODE                     0x0800
+#define WM8350_GP10_INTMODE                     0x0400
+#define WM8350_GP9_INTMODE                      0x0200
+#define WM8350_GP8_INTMODE                      0x0100
+#define WM8350_GP7_INTMODE                      0x0080
+#define WM8350_GP6_INTMODE                      0x0040
+#define WM8350_GP5_INTMODE                      0x0020
+#define WM8350_GP4_INTMODE                      0x0010
+#define WM8350_GP3_INTMODE                      0x0008
+#define WM8350_GP2_INTMODE                      0x0004
+#define WM8350_GP1_INTMODE                      0x0002
+#define WM8350_GP0_INTMODE                      0x0001
+
+/*
+ * R133 (0x85) - GPIO Control
+ */
+#define WM8350_GP_DBTIME_MASK                   0x00C0
+
+/*
+ * R134 (0x86) - GPIO Configuration (i/o)
+ */
+#define WM8350_GP12_DIR                         0x1000
+#define WM8350_GP11_DIR                         0x0800
+#define WM8350_GP10_DIR                         0x0400
+#define WM8350_GP9_DIR                          0x0200
+#define WM8350_GP8_DIR                          0x0100
+#define WM8350_GP7_DIR                          0x0080
+#define WM8350_GP6_DIR                          0x0040
+#define WM8350_GP5_DIR                          0x0020
+#define WM8350_GP4_DIR                          0x0010
+#define WM8350_GP3_DIR                          0x0008
+#define WM8350_GP2_DIR                          0x0004
+#define WM8350_GP1_DIR                          0x0002
+#define WM8350_GP0_DIR                          0x0001
+
+/*
+ * R135 (0x87) - GPIO Pin Polarity / Type
+ */
+#define WM8350_GP12_CFG                         0x1000
+#define WM8350_GP11_CFG                         0x0800
+#define WM8350_GP10_CFG                         0x0400
+#define WM8350_GP9_CFG                          0x0200
+#define WM8350_GP8_CFG                          0x0100
+#define WM8350_GP7_CFG                          0x0080
+#define WM8350_GP6_CFG                          0x0040
+#define WM8350_GP5_CFG                          0x0020
+#define WM8350_GP4_CFG                          0x0010
+#define WM8350_GP3_CFG                          0x0008
+#define WM8350_GP2_CFG                          0x0004
+#define WM8350_GP1_CFG                          0x0002
+#define WM8350_GP0_CFG                          0x0001
+
+/*
+ * R140 (0x8C) - GPIO Function Select 1
+ */
+#define WM8350_GP3_FN_MASK                      0xF000
+#define WM8350_GP2_FN_MASK                      0x0F00
+#define WM8350_GP1_FN_MASK                      0x00F0
+#define WM8350_GP0_FN_MASK                      0x000F
+
+/*
+ * R141 (0x8D) - GPIO Function Select 2
+ */
+#define WM8350_GP7_FN_MASK                      0xF000
+#define WM8350_GP6_FN_MASK                      0x0F00
+#define WM8350_GP5_FN_MASK                      0x00F0
+#define WM8350_GP4_FN_MASK                      0x000F
+
+/*
+ * R142 (0x8E) - GPIO Function Select 3
+ */
+#define WM8350_GP11_FN_MASK                     0xF000
+#define WM8350_GP10_FN_MASK                     0x0F00
+#define WM8350_GP9_FN_MASK                      0x00F0
+#define WM8350_GP8_FN_MASK                      0x000F
+
+/*
+ * R143 (0x8F) - GPIO Function Select 4
+ */
+#define WM8350_GP12_FN_MASK                     0x000F
+
+/*
+ * R230 (0xE6) - GPIO Pin Status
+ */
+#define WM8350_GP12_LVL                         0x1000
+#define WM8350_GP11_LVL                         0x0800
+#define WM8350_GP10_LVL                         0x0400
+#define WM8350_GP9_LVL                          0x0200
+#define WM8350_GP8_LVL                          0x0100
+#define WM8350_GP7_LVL                          0x0080
+#define WM8350_GP6_LVL                          0x0040
+#define WM8350_GP5_LVL                          0x0020
+#define WM8350_GP4_LVL                          0x0010
+#define WM8350_GP3_LVL                          0x0008
+#define WM8350_GP2_LVL                          0x0004
+#define WM8350_GP1_LVL                          0x0002
+#define WM8350_GP0_LVL                          0x0001
+
+struct wm8350;
+
+int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
+                      int pol, int pull, int invert, int debounce);
+
+struct wm8350_gpio {
+       struct platform_device *pdev;
+};
+
+/*
+ * GPIO Interrupts
+ */
+#define WM8350_IRQ_GPIO(x)                      (50 + x)
+
+#endif
diff --git a/include/linux/mfd/wm8350/pmic.h b/include/linux/mfd/wm8350/pmic.h
new file mode 100644 (file)
index 0000000..69b69e0
--- /dev/null
@@ -0,0 +1,741 @@
+/*
+ * pmic.h  --  Power Managment Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_PMIC_H
+#define __LINUX_MFD_WM8350_PMIC_H
+
+/*
+ * Register values.
+ */
+
+#define WM8350_CURRENT_SINK_DRIVER_A            0xAC
+#define WM8350_CSA_FLASH_CONTROL                0xAD
+#define WM8350_CURRENT_SINK_DRIVER_B            0xAE
+#define WM8350_CSB_FLASH_CONTROL                0xAF
+#define WM8350_DCDC_LDO_REQUESTED               0xB0
+#define WM8350_DCDC_ACTIVE_OPTIONS              0xB1
+#define WM8350_DCDC_SLEEP_OPTIONS               0xB2
+#define WM8350_POWER_CHECK_COMPARATOR           0xB3
+#define WM8350_DCDC1_CONTROL                    0xB4
+#define WM8350_DCDC1_TIMEOUTS                   0xB5
+#define WM8350_DCDC1_LOW_POWER                  0xB6
+#define WM8350_DCDC2_CONTROL                    0xB7
+#define WM8350_DCDC2_TIMEOUTS                   0xB8
+#define WM8350_DCDC3_CONTROL                    0xBA
+#define WM8350_DCDC3_TIMEOUTS                   0xBB
+#define WM8350_DCDC3_LOW_POWER                  0xBC
+#define WM8350_DCDC4_CONTROL                    0xBD
+#define WM8350_DCDC4_TIMEOUTS                   0xBE
+#define WM8350_DCDC4_LOW_POWER                  0xBF
+#define WM8350_DCDC5_CONTROL                    0xC0
+#define WM8350_DCDC5_TIMEOUTS                   0xC1
+#define WM8350_DCDC6_CONTROL                    0xC3
+#define WM8350_DCDC6_TIMEOUTS                   0xC4
+#define WM8350_DCDC6_LOW_POWER                  0xC5
+#define WM8350_LIMIT_SWITCH_CONTROL             0xC7
+#define WM8350_LDO1_CONTROL                     0xC8
+#define WM8350_LDO1_TIMEOUTS                    0xC9
+#define WM8350_LDO1_LOW_POWER                   0xCA
+#define WM8350_LDO2_CONTROL                     0xCB
+#define WM8350_LDO2_TIMEOUTS                    0xCC
+#define WM8350_LDO2_LOW_POWER                   0xCD
+#define WM8350_LDO3_CONTROL                     0xCE
+#define WM8350_LDO3_TIMEOUTS                    0xCF
+#define WM8350_LDO3_LOW_POWER                   0xD0
+#define WM8350_LDO4_CONTROL                     0xD1
+#define WM8350_LDO4_TIMEOUTS                    0xD2
+#define WM8350_LDO4_LOW_POWER                   0xD3
+#define WM8350_VCC_FAULT_MASKS                  0xD7
+#define WM8350_MAIN_BANDGAP_CONTROL             0xD8
+#define WM8350_OSC_CONTROL                      0xD9
+#define WM8350_RTC_TICK_CONTROL                 0xDA
+#define WM8350_SECURITY                         0xDB
+#define WM8350_RAM_BIST_1                       0xDC
+#define WM8350_DCDC_LDO_STATUS                  0xE1
+#define WM8350_GPIO_PIN_STATUS                  0xE6
+
+#define WM8350_DCDC1_FORCE_PWM                  0xF8
+#define WM8350_DCDC3_FORCE_PWM                  0xFA
+#define WM8350_DCDC4_FORCE_PWM                  0xFB
+#define WM8350_DCDC6_FORCE_PWM                  0xFD
+
+/*
+ * R172 (0xAC) - Current Sink Driver A
+ */
+#define WM8350_CS1_HIB_MODE                     0x1000
+#define WM8350_CS1_HIB_MODE_MASK                0x1000
+#define WM8350_CS1_HIB_MODE_SHIFT                   12
+#define WM8350_CS1_ISEL_MASK                    0x003F
+#define WM8350_CS1_ISEL_SHIFT                        0
+
+/* Bit values for R172 (0xAC) */
+#define WM8350_CS1_HIB_MODE_DISABLE                  0
+#define WM8350_CS1_HIB_MODE_LEAVE                    1
+
+#define WM8350_CS1_ISEL_220M                      0x3F
+
+/*
+ * R173 (0xAD) - CSA Flash control
+ */
+#define WM8350_CS1_FLASH_MODE                   0x8000
+#define WM8350_CS1_TRIGSRC                      0x4000
+#define WM8350_CS1_DRIVE                        0x2000
+#define WM8350_CS1_FLASH_DUR_MASK               0x0300
+#define WM8350_CS1_OFF_RAMP_MASK                0x0030
+#define WM8350_CS1_ON_RAMP_MASK                 0x0003
+
+/*
+ * R174 (0xAE) - Current Sink Driver B
+ */
+#define WM8350_CS2_HIB_MODE                     0x1000
+#define WM8350_CS2_ISEL_MASK                    0x003F
+
+/*
+ * R175 (0xAF) - CSB Flash control
+ */
+#define WM8350_CS2_FLASH_MODE                   0x8000
+#define WM8350_CS2_TRIGSRC                      0x4000
+#define WM8350_CS2_DRIVE                        0x2000
+#define WM8350_CS2_FLASH_DUR_MASK               0x0300
+#define WM8350_CS2_OFF_RAMP_MASK                0x0030
+#define WM8350_CS2_ON_RAMP_MASK                 0x0003
+
+/*
+ * R176 (0xB0) - DCDC/LDO requested
+ */
+#define WM8350_LS_ENA                           0x8000
+#define WM8350_LDO4_ENA                         0x0800
+#define WM8350_LDO3_ENA                         0x0400
+#define WM8350_LDO2_ENA                         0x0200
+#define WM8350_LDO1_ENA                         0x0100
+#define WM8350_DC6_ENA                          0x0020
+#define WM8350_DC5_ENA                          0x0010
+#define WM8350_DC4_ENA                          0x0008
+#define WM8350_DC3_ENA                          0x0004
+#define WM8350_DC2_ENA                          0x0002
+#define WM8350_DC1_ENA                          0x0001
+
+/*
+ * R177 (0xB1) - DCDC Active options
+ */
+#define WM8350_PUTO_MASK                        0x3000
+#define WM8350_PWRUP_DELAY_MASK                 0x0300
+#define WM8350_DC6_ACTIVE                       0x0020
+#define WM8350_DC4_ACTIVE                       0x0008
+#define WM8350_DC3_ACTIVE                       0x0004
+#define WM8350_DC1_ACTIVE                       0x0001
+
+/*
+ * R178 (0xB2) - DCDC Sleep options
+ */
+#define WM8350_DC6_SLEEP                        0x0020
+#define WM8350_DC4_SLEEP                        0x0008
+#define WM8350_DC3_SLEEP                        0x0004
+#define WM8350_DC1_SLEEP                        0x0001
+
+/*
+ * R179 (0xB3) - Power-check comparator
+ */
+#define WM8350_PCCMP_ERRACT                     0x4000
+#define WM8350_PCCMP_RAIL                       0x0100
+#define WM8350_PCCMP_OFF_THR_MASK               0x0070
+#define WM8350_PCCMP_ON_THR_MASK                0x0007
+
+/*
+ * R180 (0xB4) - DCDC1 Control
+ */
+#define WM8350_DC1_OPFLT                        0x0400
+#define WM8350_DC1_VSEL_MASK                    0x007F
+#define WM8350_DC1_VSEL_SHIFT                        0
+
+/*
+ * R181 (0xB5) - DCDC1 Timeouts
+ */
+#define WM8350_DC1_ERRACT_MASK                  0xC000
+#define WM8350_DC1_ERRACT_SHIFT                     14
+#define WM8350_DC1_ENSLOT_MASK                  0x3C00
+#define WM8350_DC1_ENSLOT_SHIFT                     10
+#define WM8350_DC1_SDSLOT_MASK                  0x03C0
+#define WM8350_DC1_UVTO_MASK                    0x0030
+#define WM8350_DC1_SDSLOT_SHIFT                      6
+
+/* Bit values for R181 (0xB5) */
+#define WM8350_DC1_ERRACT_NONE                       0
+#define WM8350_DC1_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC1_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R182 (0xB6) - DCDC1 Low Power
+ */
+#define WM8350_DC1_HIB_MODE_MASK                0x7000
+#define WM8350_DC1_HIB_TRIG_MASK                0x0300
+#define WM8350_DC1_VIMG_MASK                    0x007F
+
+/*
+ * R183 (0xB7) - DCDC2 Control
+ */
+#define WM8350_DC2_MODE                         0x4000
+#define WM8350_DC2_MODE_MASK                    0x4000
+#define WM8350_DC2_MODE_SHIFT                       14
+#define WM8350_DC2_HIB_MODE                     0x1000
+#define WM8350_DC2_HIB_MODE_MASK                0x1000
+#define WM8350_DC2_HIB_MODE_SHIFT                   12
+#define WM8350_DC2_HIB_TRIG_MASK                0x0300
+#define WM8350_DC2_HIB_TRIG_SHIFT                    8
+#define WM8350_DC2_ILIM                         0x0040
+#define WM8350_DC2_ILIM_MASK                    0x0040
+#define WM8350_DC2_ILIM_SHIFT                        6
+#define WM8350_DC2_RMP_MASK                     0x0018
+#define WM8350_DC2_RMP_SHIFT                         3
+#define WM8350_DC2_FBSRC_MASK                   0x0003
+#define WM8350_DC2_FBSRC_SHIFT                       0
+
+/* Bit values for R183 (0xB7) */
+#define WM8350_DC2_MODE_BOOST                        0
+#define WM8350_DC2_MODE_SWITCH                       1
+
+#define WM8350_DC2_HIB_MODE_ACTIVE                   1
+#define WM8350_DC2_HIB_MODE_DISABLE                  0
+
+#define WM8350_DC2_HIB_TRIG_NONE                     0
+#define WM8350_DC2_HIB_TRIG_LPWR1                    1
+#define WM8350_DC2_HIB_TRIG_LPWR2                    2
+#define WM8350_DC2_HIB_TRIG_LPWR3                    3
+
+#define WM8350_DC2_ILIM_HIGH                         0
+#define WM8350_DC2_ILIM_LOW                          1
+
+#define WM8350_DC2_RMP_30V                           0
+#define WM8350_DC2_RMP_20V                           1
+#define WM8350_DC2_RMP_10V                           2
+#define WM8350_DC2_RMP_5V                            3
+
+#define WM8350_DC2_FBSRC_FB2                         0
+#define WM8350_DC2_FBSRC_ISINKA                      1
+#define WM8350_DC2_FBSRC_ISINKB                      2
+#define WM8350_DC2_FBSRC_USB                         3
+
+/*
+ * R184 (0xB8) - DCDC2 Timeouts
+ */
+#define WM8350_DC2_ERRACT_MASK                  0xC000
+#define WM8350_DC2_ERRACT_SHIFT                     14
+#define WM8350_DC2_ENSLOT_MASK                  0x3C00
+#define WM8350_DC2_ENSLOT_SHIFT                     10
+#define WM8350_DC2_SDSLOT_MASK                  0x03C0
+#define WM8350_DC2_UVTO_MASK                    0x0030
+
+/* Bit values for R184 (0xB8) */
+#define WM8350_DC2_ERRACT_NONE                       0
+#define WM8350_DC2_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC2_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R186 (0xBA) - DCDC3 Control
+ */
+#define WM8350_DC3_OPFLT                        0x0400
+#define WM8350_DC3_VSEL_MASK                    0x007F
+#define WM8350_DC3_VSEL_SHIFT                        0
+
+/*
+ * R187 (0xBB) - DCDC3 Timeouts
+ */
+#define WM8350_DC3_ERRACT_MASK                  0xC000
+#define WM8350_DC3_ERRACT_SHIFT                     14
+#define WM8350_DC3_ENSLOT_MASK                  0x3C00
+#define WM8350_DC3_ENSLOT_SHIFT                     10
+#define WM8350_DC3_SDSLOT_MASK                  0x03C0
+#define WM8350_DC3_UVTO_MASK                    0x0030
+#define WM8350_DC3_SDSLOT_SHIFT                      6
+
+/* Bit values for R187 (0xBB) */
+#define WM8350_DC3_ERRACT_NONE                       0
+#define WM8350_DC3_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC3_ERRACT_SHUTDOWN_SYS               2
+/*
+ * R188 (0xBC) - DCDC3 Low Power
+ */
+#define WM8350_DC3_HIB_MODE_MASK                0x7000
+#define WM8350_DC3_HIB_TRIG_MASK                0x0300
+#define WM8350_DC3_VIMG_MASK                    0x007F
+
+/*
+ * R189 (0xBD) - DCDC4 Control
+ */
+#define WM8350_DC4_OPFLT                        0x0400
+#define WM8350_DC4_VSEL_MASK                    0x007F
+#define WM8350_DC4_VSEL_SHIFT                        0
+
+/*
+ * R190 (0xBE) - DCDC4 Timeouts
+ */
+#define WM8350_DC4_ERRACT_MASK                  0xC000
+#define WM8350_DC4_ERRACT_SHIFT                     14
+#define WM8350_DC4_ENSLOT_MASK                  0x3C00
+#define WM8350_DC4_ENSLOT_SHIFT                     10
+#define WM8350_DC4_SDSLOT_MASK                  0x03C0
+#define WM8350_DC4_UVTO_MASK                    0x0030
+#define WM8350_DC4_SDSLOT_SHIFT                      6
+
+/* Bit values for R190 (0xBE) */
+#define WM8350_DC4_ERRACT_NONE                       0
+#define WM8350_DC4_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC4_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R191 (0xBF) - DCDC4 Low Power
+ */
+#define WM8350_DC4_HIB_MODE_MASK                0x7000
+#define WM8350_DC4_HIB_TRIG_MASK                0x0300
+#define WM8350_DC4_VIMG_MASK                    0x007F
+
+/*
+ * R192 (0xC0) - DCDC5 Control
+ */
+#define WM8350_DC5_MODE                         0x4000
+#define WM8350_DC5_MODE_MASK                    0x4000
+#define WM8350_DC5_MODE_SHIFT                       14
+#define WM8350_DC5_HIB_MODE                     0x1000
+#define WM8350_DC5_HIB_MODE_MASK                0x1000
+#define WM8350_DC5_HIB_MODE_SHIFT                   12
+#define WM8350_DC5_HIB_TRIG_MASK                0x0300
+#define WM8350_DC5_HIB_TRIG_SHIFT                    8
+#define WM8350_DC5_ILIM                         0x0040
+#define WM8350_DC5_ILIM_MASK                    0x0040
+#define WM8350_DC5_ILIM_SHIFT                        6
+#define WM8350_DC5_RMP_MASK                     0x0018
+#define WM8350_DC5_RMP_SHIFT                         3
+#define WM8350_DC5_FBSRC_MASK                   0x0003
+#define WM8350_DC5_FBSRC_SHIFT                       0
+
+/* Bit values for R192 (0xC0) */
+#define WM8350_DC5_MODE_BOOST                        0
+#define WM8350_DC5_MODE_SWITCH                       1
+
+#define WM8350_DC5_HIB_MODE_ACTIVE                   1
+#define WM8350_DC5_HIB_MODE_DISABLE                  0
+
+#define WM8350_DC5_HIB_TRIG_NONE                     0
+#define WM8350_DC5_HIB_TRIG_LPWR1                    1
+#define WM8350_DC5_HIB_TRIG_LPWR2                    2
+#define WM8350_DC5_HIB_TRIG_LPWR3                    3
+
+#define WM8350_DC5_ILIM_HIGH                         0
+#define WM8350_DC5_ILIM_LOW                          1
+
+#define WM8350_DC5_RMP_30V                           0
+#define WM8350_DC5_RMP_20V                           1
+#define WM8350_DC5_RMP_10V                           2
+#define WM8350_DC5_RMP_5V                            3
+
+#define WM8350_DC5_FBSRC_FB2                         0
+#define WM8350_DC5_FBSRC_ISINKA                      1
+#define WM8350_DC5_FBSRC_ISINKB                      2
+#define WM8350_DC5_FBSRC_USB                         3
+
+/*
+ * R193 (0xC1) - DCDC5 Timeouts
+ */
+#define WM8350_DC5_ERRACT_MASK                  0xC000
+#define WM8350_DC5_ERRACT_SHIFT                     14
+#define WM8350_DC5_ENSLOT_MASK                  0x3C00
+#define WM8350_DC5_ENSLOT_SHIFT                     10
+#define WM8350_DC5_SDSLOT_MASK                  0x03C0
+#define WM8350_DC5_UVTO_MASK                    0x0030
+#define WM8350_DC5_SDSLOT_SHIFT                      6
+
+/* Bit values for R193 (0xC1) */
+#define WM8350_DC5_ERRACT_NONE                       0
+#define WM8350_DC5_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC5_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R195 (0xC3) - DCDC6 Control
+ */
+#define WM8350_DC6_OPFLT                        0x0400
+#define WM8350_DC6_VSEL_MASK                    0x007F
+#define WM8350_DC6_VSEL_SHIFT                        0
+
+/*
+ * R196 (0xC4) - DCDC6 Timeouts
+ */
+#define WM8350_DC6_ERRACT_MASK                  0xC000
+#define WM8350_DC6_ERRACT_SHIFT                     14
+#define WM8350_DC6_ENSLOT_MASK                  0x3C00
+#define WM8350_DC6_ENSLOT_SHIFT                     10
+#define WM8350_DC6_SDSLOT_MASK                  0x03C0
+#define WM8350_DC6_UVTO_MASK                    0x0030
+#define WM8350_DC6_SDSLOT_SHIFT                      6
+
+/* Bit values for R196 (0xC4) */
+#define WM8350_DC6_ERRACT_NONE                       0
+#define WM8350_DC6_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_DC6_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R197 (0xC5) - DCDC6 Low Power
+ */
+#define WM8350_DC6_HIB_MODE_MASK                0x7000
+#define WM8350_DC6_HIB_TRIG_MASK                0x0300
+#define WM8350_DC6_VIMG_MASK                    0x007F
+
+/*
+ * R199 (0xC7) - Limit Switch Control
+ */
+#define WM8350_LS_ERRACT_MASK                   0xC000
+#define WM8350_LS_ERRACT_SHIFT                      14
+#define WM8350_LS_ENSLOT_MASK                   0x3C00
+#define WM8350_LS_ENSLOT_SHIFT                      10
+#define WM8350_LS_SDSLOT_MASK                   0x03C0
+#define WM8350_LS_SDSLOT_SHIFT                       6
+#define WM8350_LS_HIB_MODE                      0x0010
+#define WM8350_LS_HIB_MODE_MASK                 0x0010
+#define WM8350_LS_HIB_MODE_SHIFT                     4
+#define WM8350_LS_HIB_PROT                      0x0002
+#define WM8350_LS_HIB_PROT_MASK                 0x0002
+#define WM8350_LS_HIB_PROT_SHIFT                     1
+#define WM8350_LS_PROT                          0x0001
+#define WM8350_LS_PROT_MASK                     0x0001
+#define WM8350_LS_PROT_SHIFT                         0
+
+/* Bit values for R199 (0xC7) */
+#define WM8350_LS_ERRACT_NONE                       0
+#define WM8350_LS_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LS_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R200 (0xC8) - LDO1 Control
+ */
+#define WM8350_LDO1_SWI                         0x4000
+#define WM8350_LDO1_OPFLT                       0x0400
+#define WM8350_LDO1_VSEL_MASK                   0x001F
+#define WM8350_LDO1_VSEL_SHIFT                       0
+
+/*
+ * R201 (0xC9) - LDO1 Timeouts
+ */
+#define WM8350_LDO1_ERRACT_MASK                 0xC000
+#define WM8350_LDO1_ERRACT_SHIFT                    14
+#define WM8350_LDO1_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO1_ENSLOT_SHIFT                    10
+#define WM8350_LDO1_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO1_UVTO_MASK                   0x0030
+#define WM8350_LDO1_SDSLOT_SHIFT                     6
+
+/* Bit values for R201 (0xC9) */
+#define WM8350_LDO1_ERRACT_NONE                       0
+#define WM8350_LDO1_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO1_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R202 (0xCA) - LDO1 Low Power
+ */
+#define WM8350_LDO1_HIB_MODE_MASK               0x3000
+#define WM8350_LDO1_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO1_VIMG_MASK                   0x001F
+#define WM8350_LDO1_HIB_MODE_DIS               (0x1 << 12)
+
+
+/*
+ * R203 (0xCB) - LDO2 Control
+ */
+#define WM8350_LDO2_SWI                         0x4000
+#define WM8350_LDO2_OPFLT                       0x0400
+#define WM8350_LDO2_VSEL_MASK                   0x001F
+#define WM8350_LDO2_VSEL_SHIFT                       0
+
+/*
+ * R204 (0xCC) - LDO2 Timeouts
+ */
+#define WM8350_LDO2_ERRACT_MASK                 0xC000
+#define WM8350_LDO2_ERRACT_SHIFT                    14
+#define WM8350_LDO2_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO2_ENSLOT_SHIFT                    10
+#define WM8350_LDO2_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO2_SDSLOT_SHIFT                     6
+
+/* Bit values for R204 (0xCC) */
+#define WM8350_LDO2_ERRACT_NONE                       0
+#define WM8350_LDO2_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO2_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R205 (0xCD) - LDO2 Low Power
+ */
+#define WM8350_LDO2_HIB_MODE_MASK               0x3000
+#define WM8350_LDO2_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO2_VIMG_MASK                   0x001F
+
+/*
+ * R206 (0xCE) - LDO3 Control
+ */
+#define WM8350_LDO3_SWI                         0x4000
+#define WM8350_LDO3_OPFLT                       0x0400
+#define WM8350_LDO3_VSEL_MASK                   0x001F
+#define WM8350_LDO3_VSEL_SHIFT                       0
+
+/*
+ * R207 (0xCF) - LDO3 Timeouts
+ */
+#define WM8350_LDO3_ERRACT_MASK                 0xC000
+#define WM8350_LDO3_ERRACT_SHIFT                    14
+#define WM8350_LDO3_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO3_ENSLOT_SHIFT                    10
+#define WM8350_LDO3_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO3_UVTO_MASK                   0x0030
+#define WM8350_LDO3_SDSLOT_SHIFT                     6
+
+/* Bit values for R207 (0xCF) */
+#define WM8350_LDO3_ERRACT_NONE                       0
+#define WM8350_LDO3_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO3_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R208 (0xD0) - LDO3 Low Power
+ */
+#define WM8350_LDO3_HIB_MODE_MASK               0x3000
+#define WM8350_LDO3_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO3_VIMG_MASK                   0x001F
+
+/*
+ * R209 (0xD1) - LDO4 Control
+ */
+#define WM8350_LDO4_SWI                         0x4000
+#define WM8350_LDO4_OPFLT                       0x0400
+#define WM8350_LDO4_VSEL_MASK                   0x001F
+#define WM8350_LDO4_VSEL_SHIFT                       0
+
+/*
+ * R210 (0xD2) - LDO4 Timeouts
+ */
+#define WM8350_LDO4_ERRACT_MASK                 0xC000
+#define WM8350_LDO4_ERRACT_SHIFT                    14
+#define WM8350_LDO4_ENSLOT_MASK                 0x3C00
+#define WM8350_LDO4_ENSLOT_SHIFT                    10
+#define WM8350_LDO4_SDSLOT_MASK                 0x03C0
+#define WM8350_LDO4_UVTO_MASK                   0x0030
+#define WM8350_LDO4_SDSLOT_SHIFT                     6
+
+/* Bit values for R210 (0xD2) */
+#define WM8350_LDO4_ERRACT_NONE                       0
+#define WM8350_LDO4_ERRACT_SHUTDOWN_CONV              1
+#define WM8350_LDO4_ERRACT_SHUTDOWN_SYS               2
+
+/*
+ * R211 (0xD3) - LDO4 Low Power
+ */
+#define WM8350_LDO4_HIB_MODE_MASK               0x3000
+#define WM8350_LDO4_HIB_TRIG_MASK               0x0300
+#define WM8350_LDO4_VIMG_MASK                   0x001F
+
+/*
+ * R215 (0xD7) - VCC_FAULT Masks
+ */
+#define WM8350_LS_FAULT                         0x8000
+#define WM8350_LDO4_FAULT                       0x0800
+#define WM8350_LDO3_FAULT                       0x0400
+#define WM8350_LDO2_FAULT                       0x0200
+#define WM8350_LDO1_FAULT                       0x0100
+#define WM8350_DC6_FAULT                        0x0020
+#define WM8350_DC5_FAULT                        0x0010
+#define WM8350_DC4_FAULT                        0x0008
+#define WM8350_DC3_FAULT                        0x0004
+#define WM8350_DC2_FAULT                        0x0002
+#define WM8350_DC1_FAULT                        0x0001
+
+/*
+ * R216 (0xD8) - Main Bandgap Control
+ */
+#define WM8350_MBG_LOAD_FUSES                   0x8000
+#define WM8350_MBG_FUSE_WPREP                   0x4000
+#define WM8350_MBG_FUSE_WRITE                   0x2000
+#define WM8350_MBG_FUSE_TRIM_MASK               0x1F00
+#define WM8350_MBG_TRIM_SRC                     0x0020
+#define WM8350_MBG_USER_TRIM_MASK               0x001F
+
+/*
+ * R217 (0xD9) - OSC Control
+ */
+#define WM8350_OSC_LOAD_FUSES                   0x8000
+#define WM8350_OSC_FUSE_WPREP                   0x4000
+#define WM8350_OSC_FUSE_WRITE                   0x2000
+#define WM8350_OSC_FUSE_TRIM_MASK               0x0F00
+#define WM8350_OSC_TRIM_SRC                     0x0020
+#define WM8350_OSC_USER_TRIM_MASK               0x000F
+
+/*
+ * R248 (0xF8) - DCDC1 Force PWM
+ */
+#define WM8350_DCDC1_FORCE_PWM_ENA              0x0010
+
+/*
+ * R250 (0xFA) - DCDC3 Force PWM
+ */
+#define WM8350_DCDC3_FORCE_PWM_ENA              0x0010
+
+/*
+ * R251 (0xFB) - DCDC4 Force PWM
+ */
+#define WM8350_DCDC4_FORCE_PWM_ENA              0x0010
+
+/*
+ * R253 (0xFD) - DCDC1 Force PWM
+ */
+#define WM8350_DCDC6_FORCE_PWM_ENA              0x0010
+
+/*
+ * DCDC's
+ */
+#define WM8350_DCDC_1                          0
+#define WM8350_DCDC_2                          1
+#define WM8350_DCDC_3                          2
+#define WM8350_DCDC_4                          3
+#define WM8350_DCDC_5                          4
+#define WM8350_DCDC_6                          5
+
+/* DCDC modes */
+#define WM8350_DCDC_ACTIVE_STANDBY             0
+#define WM8350_DCDC_ACTIVE_PULSE               1
+#define WM8350_DCDC_SLEEP_NORMAL               0
+#define WM8350_DCDC_SLEEP_LOW                  1
+
+/* DCDC Low power (Hibernate) mode */
+#define WM8350_DCDC_HIB_MODE_CUR               (0 << 12)
+#define WM8350_DCDC_HIB_MODE_IMAGE             (1 << 12)
+#define WM8350_DCDC_HIB_MODE_STANDBY           (2 << 12)
+#define WM8350_DCDC_HIB_MODE_LDO               (4 << 12)
+#define WM8350_DCDC_HIB_MODE_LDO_IM            (5 << 12)
+#define WM8350_DCDC_HIB_MODE_DIS               (7 << 12)
+#define WM8350_DCDC_HIB_MODE_MASK              (7 << 12)
+
+/* DCDC Low Power (Hibernate) signal */
+#define WM8350_DCDC_HIB_SIG_REG                        (0 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR1              (1 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR2              (2 << 8)
+#define WM8350_DCDC_HIB_SIG_LPWR3              (3 << 8)
+
+/* LDO Low power (Hibernate) mode */
+#define WM8350_LDO_HIB_MODE_IMAGE              (0 << 0)
+#define WM8350_LDO_HIB_MODE_DIS                        (1 << 0)
+
+/* LDO Low Power (Hibernate) signal */
+#define WM8350_LDO_HIB_SIG_REG                 (0 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR1               (1 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR2               (2 << 8)
+#define WM8350_LDO_HIB_SIG_LPWR3               (3 << 8)
+
+/*
+ * LDOs
+ */
+#define WM8350_LDO_1                           6
+#define WM8350_LDO_2                           7
+#define WM8350_LDO_3                           8
+#define WM8350_LDO_4                           9
+
+/*
+ * ISINKs
+ */
+#define WM8350_ISINK_A                         10
+#define WM8350_ISINK_B                         11
+
+#define WM8350_ISINK_MODE_BOOST                        0
+#define WM8350_ISINK_MODE_SWITCH               1
+#define WM8350_ISINK_ILIM_NORMAL               0
+#define WM8350_ISINK_ILIM_LOW                  1
+
+#define WM8350_ISINK_FLASH_DISABLE             0
+#define WM8350_ISINK_FLASH_ENABLE              1
+#define WM8350_ISINK_FLASH_TRIG_BIT            0
+#define WM8350_ISINK_FLASH_TRIG_GPIO           1
+#define WM8350_ISINK_FLASH_MODE_EN             (1 << 13)
+#define WM8350_ISINK_FLASH_MODE_DIS            (0 << 13)
+#define WM8350_ISINK_FLASH_DUR_32MS            (0 << 8)
+#define WM8350_ISINK_FLASH_DUR_64MS            (1 << 8)
+#define WM8350_ISINK_FLASH_DUR_96MS            (2 << 8)
+#define WM8350_ISINK_FLASH_DUR_1024MS          (3 << 8)
+#define WM8350_ISINK_FLASH_ON_INSTANT          (0 << 4)
+#define WM8350_ISINK_FLASH_ON_0_25S            (1 << 4)
+#define WM8350_ISINK_FLASH_ON_0_50S            (2 << 4)
+#define WM8350_ISINK_FLASH_ON_1_00S            (3 << 4)
+#define WM8350_ISINK_FLASH_ON_1_95S            (1 << 4)
+#define WM8350_ISINK_FLASH_ON_3_91S            (2 << 4)
+#define WM8350_ISINK_FLASH_ON_7_80S            (3 << 4)
+#define WM8350_ISINK_FLASH_OFF_INSTANT         (0 << 0)
+#define WM8350_ISINK_FLASH_OFF_0_25S           (1 << 0)
+#define WM8350_ISINK_FLASH_OFF_0_50S           (2 << 0)
+#define WM8350_ISINK_FLASH_OFF_1_00S           (3 << 0)
+#define WM8350_ISINK_FLASH_OFF_1_95S           (1 << 0)
+#define WM8350_ISINK_FLASH_OFF_3_91S           (2 << 0)
+#define WM8350_ISINK_FLASH_OFF_7_80S           (3 << 0)
+
+/*
+ * Regulator Interrupts.
+ */
+#define WM8350_IRQ_CS1                         13
+#define WM8350_IRQ_CS2                         14
+#define WM8350_IRQ_UV_LDO4                     25
+#define WM8350_IRQ_UV_LDO3                     26
+#define WM8350_IRQ_UV_LDO2                     27
+#define WM8350_IRQ_UV_LDO1                     28
+#define WM8350_IRQ_UV_DC6                      29
+#define WM8350_IRQ_UV_DC5                      30
+#define WM8350_IRQ_UV_DC4                      31
+#define WM8350_IRQ_UV_DC3                      32
+#define WM8350_IRQ_UV_DC2                      33
+#define WM8350_IRQ_UV_DC1                      34
+#define WM8350_IRQ_OC_LS                       35
+
+#define NUM_WM8350_REGULATORS                  12
+
+struct wm8350;
+struct platform_device;
+struct regulator_init_data;
+
+struct wm8350_pmic {
+       /* ISINK to DCDC mapping */
+       int isink_A_dcdc;
+       int isink_B_dcdc;
+
+       /* hibernate configs */
+       u16 dcdc1_hib_mode;
+       u16 dcdc3_hib_mode;
+       u16 dcdc4_hib_mode;
+       u16 dcdc6_hib_mode;
+
+       /* regulator devices */
+       struct platform_device *pdev[NUM_WM8350_REGULATORS];
+};
+
+int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
+                             struct regulator_init_data *initdata);
+
+/*
+ * Additional DCDC control not supported via regulator API
+ */
+int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
+                        u16 stop, u16 fault);
+int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
+                          u16 ilim, u16 ramp, u16 feedback);
+
+/*
+ * Additional LDO control not supported via regulator API
+ */
+int wm8350_ldo_set_slot(struct wm8350 *wm8350, int ldo, u16 start, u16 stop);
+
+/*
+ * Additional ISINK control not supported via regulator API
+ */
+int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
+                          u16 trigger, u16 duration, u16 on_ramp,
+                          u16 off_ramp, u16 drive);
+
+#endif
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
new file mode 100644 (file)
index 0000000..dfda69e
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * rtc.h  --  RTC driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_RTC_H
+#define __LINUX_MFD_WM8350_RTC_H
+
+#include <linux/platform_device.h>
+
+/*
+ * Register values.
+ */
+#define WM8350_RTC_SECONDS_MINUTES              0x10
+#define WM8350_RTC_HOURS_DAY                    0x11
+#define WM8350_RTC_DATE_MONTH                   0x12
+#define WM8350_RTC_YEAR                         0x13
+#define WM8350_ALARM_SECONDS_MINUTES            0x14
+#define WM8350_ALARM_HOURS_DAY                  0x15
+#define WM8350_ALARM_DATE_MONTH                 0x16
+#define WM8350_RTC_TIME_CONTROL                 0x17
+
+/*
+ * R16 (0x10) - RTC Seconds/Minutes
+ */
+#define WM8350_RTC_MINS_MASK                    0x7F00
+#define WM8350_RTC_MINS_SHIFT                        8
+#define WM8350_RTC_SECS_MASK                    0x007F
+#define WM8350_RTC_SECS_SHIFT                        0
+
+/*
+ * R17 (0x11) - RTC Hours/Day
+ */
+#define WM8350_RTC_DAY_MASK                     0x0700
+#define WM8350_RTC_DAY_SHIFT                         8
+#define WM8350_RTC_HPM_MASK                     0x0020
+#define WM8350_RTC_HPM_SHIFT                         5
+#define WM8350_RTC_HRS_MASK                     0x001F
+#define WM8350_RTC_HRS_SHIFT                         0
+
+/* Bit values for R21 (0x15) */
+#define WM8350_RTC_DAY_SUN                           1
+#define WM8350_RTC_DAY_MON                           2
+#define WM8350_RTC_DAY_TUE                           3
+#define WM8350_RTC_DAY_WED                           4
+#define WM8350_RTC_DAY_THU                           5
+#define WM8350_RTC_DAY_FRI                           6
+#define WM8350_RTC_DAY_SAT                           7
+
+#define WM8350_RTC_HPM_AM                            0
+#define WM8350_RTC_HPM_PM                            1
+
+/*
+ * R18 (0x12) - RTC Date/Month
+ */
+#define WM8350_RTC_MTH_MASK                     0x1F00
+#define WM8350_RTC_MTH_SHIFT                         8
+#define WM8350_RTC_DATE_MASK                    0x003F
+#define WM8350_RTC_DATE_SHIFT                        0
+
+/* Bit values for R22 (0x16) */
+#define WM8350_RTC_MTH_JAN                           1
+#define WM8350_RTC_MTH_FEB                           2
+#define WM8350_RTC_MTH_MAR                           3
+#define WM8350_RTC_MTH_APR                           4
+#define WM8350_RTC_MTH_MAY                           5
+#define WM8350_RTC_MTH_JUN                           6
+#define WM8350_RTC_MTH_JUL                           7
+#define WM8350_RTC_MTH_AUG                           8
+#define WM8350_RTC_MTH_SEP                           9
+#define WM8350_RTC_MTH_OCT                          10
+#define WM8350_RTC_MTH_NOV                          11
+#define WM8350_RTC_MTH_DEC                          12
+#define WM8350_RTC_MTH_JAN_BCD                    0x01
+#define WM8350_RTC_MTH_FEB_BCD                    0x02
+#define WM8350_RTC_MTH_MAR_BCD                    0x03
+#define WM8350_RTC_MTH_APR_BCD                    0x04
+#define WM8350_RTC_MTH_MAY_BCD                    0x05
+#define WM8350_RTC_MTH_JUN_BCD                    0x06
+#define WM8350_RTC_MTH_JUL_BCD                    0x07
+#define WM8350_RTC_MTH_AUG_BCD                    0x08
+#define WM8350_RTC_MTH_SEP_BCD                    0x09
+#define WM8350_RTC_MTH_OCT_BCD                    0x10
+#define WM8350_RTC_MTH_NOV_BCD                    0x11
+#define WM8350_RTC_MTH_DEC_BCD                    0x12
+
+/*
+ * R19 (0x13) - RTC Year
+ */
+#define WM8350_RTC_YHUNDREDS_MASK               0x3F00
+#define WM8350_RTC_YHUNDREDS_SHIFT                   8
+#define WM8350_RTC_YUNITS_MASK                  0x00FF
+#define WM8350_RTC_YUNITS_SHIFT                      0
+
+/*
+ * R20 (0x14) - Alarm Seconds/Minutes
+ */
+#define WM8350_RTC_ALMMINS_MASK                 0x7F00
+#define WM8350_RTC_ALMMINS_SHIFT                     8
+#define WM8350_RTC_ALMSECS_MASK                 0x007F
+#define WM8350_RTC_ALMSECS_SHIFT                     0
+
+/* Bit values for R20 (0x14) */
+#define WM8350_RTC_ALMMINS_DONT_CARE                -1
+#define WM8350_RTC_ALMSECS_DONT_CARE                -1
+
+/*
+ * R21 (0x15) - Alarm Hours/Day
+ */
+#define WM8350_RTC_ALMDAY_MASK                  0x0F00
+#define WM8350_RTC_ALMDAY_SHIFT                      8
+#define WM8350_RTC_ALMHPM_MASK                  0x0020
+#define WM8350_RTC_ALMHPM_SHIFT                      5
+#define WM8350_RTC_ALMHRS_MASK                  0x001F
+#define WM8350_RTC_ALMHRS_SHIFT                      0
+
+/* Bit values for R21 (0x15) */
+#define WM8350_RTC_ALMDAY_DONT_CARE                 -1
+#define WM8350_RTC_ALMDAY_SUN                        1
+#define WM8350_RTC_ALMDAY_MON                        2
+#define WM8350_RTC_ALMDAY_TUE                        3
+#define WM8350_RTC_ALMDAY_WED                        4
+#define WM8350_RTC_ALMDAY_THU                        5
+#define WM8350_RTC_ALMDAY_FRI                        6
+#define WM8350_RTC_ALMDAY_SAT                        7
+
+#define WM8350_RTC_ALMHPM_AM                         0
+#define WM8350_RTC_ALMHPM_PM                         1
+
+#define WM8350_RTC_ALMHRS_DONT_CARE                 -1
+
+/*
+ * R22 (0x16) - Alarm Date/Month
+ */
+#define WM8350_RTC_ALMMTH_MASK                  0x1F00
+#define WM8350_RTC_ALMMTH_SHIFT                      8
+#define WM8350_RTC_ALMDATE_MASK                 0x003F
+#define WM8350_RTC_ALMDATE_SHIFT                     0
+
+/* Bit values for R22 (0x16) */
+#define WM8350_RTC_ALMDATE_DONT_CARE                -1
+
+#define WM8350_RTC_ALMMTH_DONT_CARE                 -1
+#define WM8350_RTC_ALMMTH_JAN                        1
+#define WM8350_RTC_ALMMTH_FEB                        2
+#define WM8350_RTC_ALMMTH_MAR                        3
+#define WM8350_RTC_ALMMTH_APR                        4
+#define WM8350_RTC_ALMMTH_MAY                        5
+#define WM8350_RTC_ALMMTH_JUN                        6
+#define WM8350_RTC_ALMMTH_JUL                        7
+#define WM8350_RTC_ALMMTH_AUG                        8
+#define WM8350_RTC_ALMMTH_SEP                        9
+#define WM8350_RTC_ALMMTH_OCT                       10
+#define WM8350_RTC_ALMMTH_NOV                       11
+#define WM8350_RTC_ALMMTH_DEC                       12
+#define WM8350_RTC_ALMMTH_JAN_BCD                 0x01
+#define WM8350_RTC_ALMMTH_FEB_BCD                 0x02
+#define WM8350_RTC_ALMMTH_MAR_BCD                 0x03
+#define WM8350_RTC_ALMMTH_APR_BCD                 0x04
+#define WM8350_RTC_ALMMTH_MAY_BCD                 0x05
+#define WM8350_RTC_ALMMTH_JUN_BCD                 0x06
+#define WM8350_RTC_ALMMTH_JUL_BCD                 0x07
+#define WM8350_RTC_ALMMTH_AUG_BCD                 0x08
+#define WM8350_RTC_ALMMTH_SEP_BCD                 0x09
+#define WM8350_RTC_ALMMTH_OCT_BCD                 0x10
+#define WM8350_RTC_ALMMTH_NOV_BCD                 0x11
+#define WM8350_RTC_ALMMTH_DEC_BCD                 0x12
+
+/*
+ * R23 (0x17) - RTC Time Control
+ */
+#define WM8350_RTC_BCD                          0x8000
+#define WM8350_RTC_BCD_MASK                     0x8000
+#define WM8350_RTC_BCD_SHIFT                        15
+#define WM8350_RTC_12HR                         0x4000
+#define WM8350_RTC_12HR_MASK                    0x4000
+#define WM8350_RTC_12HR_SHIFT                       14
+#define WM8350_RTC_DST                          0x2000
+#define WM8350_RTC_DST_MASK                     0x2000
+#define WM8350_RTC_DST_SHIFT                        13
+#define WM8350_RTC_SET                          0x0800
+#define WM8350_RTC_SET_MASK                     0x0800
+#define WM8350_RTC_SET_SHIFT                        11
+#define WM8350_RTC_STS                          0x0400
+#define WM8350_RTC_STS_MASK                     0x0400
+#define WM8350_RTC_STS_SHIFT                        10
+#define WM8350_RTC_ALMSET                       0x0200
+#define WM8350_RTC_ALMSET_MASK                  0x0200
+#define WM8350_RTC_ALMSET_SHIFT                      9
+#define WM8350_RTC_ALMSTS                       0x0100
+#define WM8350_RTC_ALMSTS_MASK                  0x0100
+#define WM8350_RTC_ALMSTS_SHIFT                      8
+#define WM8350_RTC_PINT                         0x0070
+#define WM8350_RTC_PINT_MASK                    0x0070
+#define WM8350_RTC_PINT_SHIFT                        4
+#define WM8350_RTC_DSW                          0x000F
+#define WM8350_RTC_DSW_MASK                     0x000F
+#define WM8350_RTC_DSW_SHIFT                         0
+
+/* Bit values for R23 (0x17) */
+#define WM8350_RTC_BCD_BINARY                        0
+#define WM8350_RTC_BCD_BCD                           1
+
+#define WM8350_RTC_12HR_24HR                         0
+#define WM8350_RTC_12HR_12HR                         1
+
+#define WM8350_RTC_DST_DISABLED                      0
+#define WM8350_RTC_DST_ENABLED                       1
+
+#define WM8350_RTC_SET_RUN                           0
+#define WM8350_RTC_SET_SET                           1
+
+#define WM8350_RTC_STS_RUNNING                       0
+#define WM8350_RTC_STS_STOPPED                       1
+
+#define WM8350_RTC_ALMSET_RUN                        0
+#define WM8350_RTC_ALMSET_SET                        1
+
+#define WM8350_RTC_ALMSTS_RUNNING                    0
+#define WM8350_RTC_ALMSTS_STOPPED                    1
+
+#define WM8350_RTC_PINT_DISABLED                     0
+#define WM8350_RTC_PINT_SECS                         1
+#define WM8350_RTC_PINT_MINS                         2
+#define WM8350_RTC_PINT_HRS                          3
+#define WM8350_RTC_PINT_DAYS                         4
+#define WM8350_RTC_PINT_MTHS                         5
+
+#define WM8350_RTC_DSW_DISABLED                      0
+#define WM8350_RTC_DSW_1HZ                           1
+#define WM8350_RTC_DSW_2HZ                           2
+#define WM8350_RTC_DSW_4HZ                           3
+#define WM8350_RTC_DSW_8HZ                           4
+#define WM8350_RTC_DSW_16HZ                          5
+#define WM8350_RTC_DSW_32HZ                          6
+#define WM8350_RTC_DSW_64HZ                          7
+#define WM8350_RTC_DSW_128HZ                         8
+#define WM8350_RTC_DSW_256HZ                         9
+#define WM8350_RTC_DSW_512HZ                        10
+#define WM8350_RTC_DSW_1024HZ                       11
+
+/*
+ * R218 (0xDA) - RTC Tick Control
+ */
+#define WM8350_RTC_TICKSTS                      0x4000
+#define WM8350_RTC_CLKSRC                       0x2000
+#define WM8350_RTC_TRIM_MASK                    0x03FF
+
+/*
+ * RTC Interrupts.
+ */
+#define WM8350_IRQ_RTC_PER                     7
+#define WM8350_IRQ_RTC_SEC                     8
+#define WM8350_IRQ_RTC_ALM                     9
+
+struct wm8350_rtc {
+       struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/supply.h b/include/linux/mfd/wm8350/supply.h
new file mode 100644 (file)
index 0000000..1c8f3cd
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * supply.h  --  Power Supply Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_SUPPLY_H_
+#define __LINUX_MFD_WM8350_SUPPLY_H_
+
+#include <linux/platform_device.h>
+
+/*
+ * Charger registers
+ */
+#define WM8350_BATTERY_CHARGER_CONTROL_1        0xA8
+#define WM8350_BATTERY_CHARGER_CONTROL_2        0xA9
+#define WM8350_BATTERY_CHARGER_CONTROL_3        0xAA
+
+/*
+ * R168 (0xA8) - Battery Charger Control 1
+ */
+#define WM8350_CHG_ENA_R168                     0x8000
+#define WM8350_CHG_THR                          0x2000
+#define WM8350_CHG_EOC_SEL_MASK                 0x1C00
+#define WM8350_CHG_TRICKLE_TEMP_CHOKE           0x0200
+#define WM8350_CHG_TRICKLE_USB_CHOKE            0x0100
+#define WM8350_CHG_RECOVER_T                    0x0080
+#define WM8350_CHG_END_ACT                      0x0040
+#define WM8350_CHG_FAST                         0x0020
+#define WM8350_CHG_FAST_USB_THROTTLE            0x0010
+#define WM8350_CHG_NTC_MON                      0x0008
+#define WM8350_CHG_BATT_HOT_MON                 0x0004
+#define WM8350_CHG_BATT_COLD_MON                0x0002
+#define WM8350_CHG_CHIP_TEMP_MON                0x0001
+
+/*
+ * R169 (0xA9) - Battery Charger Control 2
+ */
+#define WM8350_CHG_ACTIVE                       0x8000
+#define WM8350_CHG_PAUSE                        0x4000
+#define WM8350_CHG_STS_MASK                     0x3000
+#define WM8350_CHG_TIME_MASK                    0x0F00
+#define WM8350_CHG_MASK_WALL_FB                 0x0080
+#define WM8350_CHG_TRICKLE_SEL                  0x0040
+#define WM8350_CHG_VSEL_MASK                    0x0030
+#define WM8350_CHG_ISEL_MASK                    0x000F
+#define WM8350_CHG_STS_OFF                      0x0000
+#define WM8350_CHG_STS_TRICKLE                  0x1000
+#define WM8350_CHG_STS_FAST                     0x2000
+
+/*
+ * R170 (0xAA) - Battery Charger Control 3
+ */
+#define WM8350_CHG_THROTTLE_T_MASK              0x0060
+#define WM8350_CHG_SMART                        0x0010
+#define WM8350_CHG_TIMER_ADJT_MASK              0x000F
+
+/*
+ * Charger Interrupts
+ */
+#define WM8350_IRQ_CHG_BAT_HOT                 0
+#define WM8350_IRQ_CHG_BAT_COLD                        1
+#define WM8350_IRQ_CHG_BAT_FAIL                        2
+#define WM8350_IRQ_CHG_TO                      3
+#define WM8350_IRQ_CHG_END                     4
+#define WM8350_IRQ_CHG_START                   5
+#define WM8350_IRQ_CHG_FAST_RDY                        6
+#define WM8350_IRQ_CHG_VBATT_LT_3P9            10
+#define WM8350_IRQ_CHG_VBATT_LT_3P1            11
+#define WM8350_IRQ_CHG_VBATT_LT_2P85           12
+
+/*
+ * Charger Policy
+ */
+#define WM8350_CHG_TRICKLE_50mA                        (0 << 6)
+#define WM8350_CHG_TRICKLE_100mA               (1 << 6)
+#define WM8350_CHG_4_05V                       (0 << 4)
+#define WM8350_CHG_4_10V                       (1 << 4)
+#define WM8350_CHG_4_15V                       (2 << 4)
+#define WM8350_CHG_4_20V                       (3 << 4)
+#define WM8350_CHG_FAST_LIMIT_mA(x)            ((x / 50) & 0xf)
+#define WM8350_CHG_EOC_mA(x)                   (((x - 10) & 0x7) << 10)
+#define WM8350_CHG_TRICKLE_3_1V                        (0 << 13)
+#define WM8350_CHG_TRICKLE_3_9V                        (1 << 13)
+
+/*
+ * Supply Registers.
+ */
+#define WM8350_USB_VOLTAGE_READBACK             0x9C
+#define WM8350_LINE_VOLTAGE_READBACK            0x9D
+#define WM8350_BATT_VOLTAGE_READBACK            0x9E
+
+/*
+ * Supply Interrupts.
+ */
+#define WM8350_IRQ_USB_LIMIT                   15
+#define WM8350_IRQ_EXT_USB_FB                  36
+#define WM8350_IRQ_EXT_WALL_FB                 37
+#define WM8350_IRQ_EXT_BAT_FB                  38
+
+struct wm8350_power {
+       struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8350/wdt.h b/include/linux/mfd/wm8350/wdt.h
new file mode 100644 (file)
index 0000000..f6135b5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * wdt.h  --  Watchdog Driver for Wolfson WM8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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 __LINUX_MFD_WM8350_WDT_H_
+#define __LINUX_MFD_WM8350_WDT_H_
+
+#include <linux/platform_device.h>
+
+#define WM8350_WDOG_HIB_MODE                    0x0080
+#define WM8350_WDOG_DEBUG                       0x0040
+#define WM8350_WDOG_MODE_MASK                   0x0030
+#define WM8350_WDOG_TO_MASK                     0x0007
+
+#define WM8350_IRQ_SYS_WDOG_TO                 24
+
+struct wm8350_wdt {
+       struct platform_device *pdev;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8400-audio.h b/include/linux/mfd/wm8400-audio.h
new file mode 100644 (file)
index 0000000..b6640e0
--- /dev/null
@@ -0,0 +1,1186 @@
+/*
+ * wm8400 private definitions for audio
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __LINUX_MFD_WM8400_AUDIO_H
+#define __LINUX_MFD_WM8400_AUDIO_H
+
+#include <linux/mfd/wm8400-audio.h>
+
+/*
+ * R2 (0x02) - Power Management (1)
+ */
+#define WM8400_CODEC_ENA                        0x8000  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_MASK                   0x8000  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_SHIFT                      15  /* CODEC_ENA */
+#define WM8400_CODEC_ENA_WIDTH                       1  /* CODEC_ENA */
+#define WM8400_SYSCLK_ENA                       0x4000  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_MASK                  0x4000  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_SHIFT                     14  /* SYSCLK_ENA */
+#define WM8400_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM8400_SPK_MIX_ENA                      0x2000  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_MASK                 0x2000  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_SHIFT                    13  /* SPK_MIX_ENA */
+#define WM8400_SPK_MIX_ENA_WIDTH                     1  /* SPK_MIX_ENA */
+#define WM8400_SPK_ENA                          0x1000  /* SPK_ENA */
+#define WM8400_SPK_ENA_MASK                     0x1000  /* SPK_ENA */
+#define WM8400_SPK_ENA_SHIFT                        12  /* SPK_ENA */
+#define WM8400_SPK_ENA_WIDTH                         1  /* SPK_ENA */
+#define WM8400_OUT3_ENA                         0x0800  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_MASK                    0x0800  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_SHIFT                       11  /* OUT3_ENA */
+#define WM8400_OUT3_ENA_WIDTH                        1  /* OUT3_ENA */
+#define WM8400_OUT4_ENA                         0x0400  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_MASK                    0x0400  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_SHIFT                       10  /* OUT4_ENA */
+#define WM8400_OUT4_ENA_WIDTH                        1  /* OUT4_ENA */
+#define WM8400_LOUT_ENA                         0x0200  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_MASK                    0x0200  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_SHIFT                        9  /* LOUT_ENA */
+#define WM8400_LOUT_ENA_WIDTH                        1  /* LOUT_ENA */
+#define WM8400_ROUT_ENA                         0x0100  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_MASK                    0x0100  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_SHIFT                        8  /* ROUT_ENA */
+#define WM8400_ROUT_ENA_WIDTH                        1  /* ROUT_ENA */
+#define WM8400_MIC1BIAS_ENA                     0x0010  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_MASK                0x0010  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_SHIFT                    4  /* MIC1BIAS_ENA */
+#define WM8400_MIC1BIAS_ENA_WIDTH                    1  /* MIC1BIAS_ENA */
+#define WM8400_VMID_MODE_MASK                   0x0006  /* VMID_MODE - [2:1] */
+#define WM8400_VMID_MODE_SHIFT                       1  /* VMID_MODE - [2:1] */
+#define WM8400_VMID_MODE_WIDTH                       2  /* VMID_MODE - [2:1] */
+#define WM8400_VREF_ENA                         0x0001  /* VREF_ENA */
+#define WM8400_VREF_ENA_MASK                    0x0001  /* VREF_ENA */
+#define WM8400_VREF_ENA_SHIFT                        0  /* VREF_ENA */
+#define WM8400_VREF_ENA_WIDTH                        1  /* VREF_ENA */
+
+/*
+ * R3 (0x03) - Power Management (2)
+ */
+#define WM8400_FLL_ENA                          0x8000  /* FLL_ENA */
+#define WM8400_FLL_ENA_MASK                     0x8000  /* FLL_ENA */
+#define WM8400_FLL_ENA_SHIFT                        15  /* FLL_ENA */
+#define WM8400_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+#define WM8400_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_MASK                   0x4000  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_SHIFT                      14  /* TSHUT_ENA */
+#define WM8400_TSHUT_ENA_WIDTH                       1  /* TSHUT_ENA */
+#define WM8400_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_MASK                 0x2000  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_SHIFT                    13  /* TSHUT_OPDIS */
+#define WM8400_TSHUT_OPDIS_WIDTH                     1  /* TSHUT_OPDIS */
+#define WM8400_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
+#define WM8400_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8400_AINL_ENA                         0x0200  /* AINL_ENA */
+#define WM8400_AINL_ENA_MASK                    0x0200  /* AINL_ENA */
+#define WM8400_AINL_ENA_SHIFT                        9  /* AINL_ENA */
+#define WM8400_AINL_ENA_WIDTH                        1  /* AINL_ENA */
+#define WM8400_AINR_ENA                         0x0100  /* AINR_ENA */
+#define WM8400_AINR_ENA_MASK                    0x0100  /* AINR_ENA */
+#define WM8400_AINR_ENA_SHIFT                        8  /* AINR_ENA */
+#define WM8400_AINR_ENA_WIDTH                        1  /* AINR_ENA */
+#define WM8400_LIN34_ENA                        0x0080  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_MASK                   0x0080  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_SHIFT                       7  /* LIN34_ENA */
+#define WM8400_LIN34_ENA_WIDTH                       1  /* LIN34_ENA */
+#define WM8400_LIN12_ENA                        0x0040  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_MASK                   0x0040  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_SHIFT                       6  /* LIN12_ENA */
+#define WM8400_LIN12_ENA_WIDTH                       1  /* LIN12_ENA */
+#define WM8400_RIN34_ENA                        0x0020  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_MASK                   0x0020  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_SHIFT                       5  /* RIN34_ENA */
+#define WM8400_RIN34_ENA_WIDTH                       1  /* RIN34_ENA */
+#define WM8400_RIN12_ENA                        0x0010  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_MASK                   0x0010  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_SHIFT                       4  /* RIN12_ENA */
+#define WM8400_RIN12_ENA_WIDTH                       1  /* RIN12_ENA */
+#define WM8400_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
+#define WM8400_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8400_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
+#define WM8400_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (3)
+ */
+#define WM8400_LON_ENA                          0x2000  /* LON_ENA */
+#define WM8400_LON_ENA_MASK                     0x2000  /* LON_ENA */
+#define WM8400_LON_ENA_SHIFT                        13  /* LON_ENA */
+#define WM8400_LON_ENA_WIDTH                         1  /* LON_ENA */
+#define WM8400_LOP_ENA                          0x1000  /* LOP_ENA */
+#define WM8400_LOP_ENA_MASK                     0x1000  /* LOP_ENA */
+#define WM8400_LOP_ENA_SHIFT                        12  /* LOP_ENA */
+#define WM8400_LOP_ENA_WIDTH                         1  /* LOP_ENA */
+#define WM8400_RON_ENA                          0x0800  /* RON_ENA */
+#define WM8400_RON_ENA_MASK                     0x0800  /* RON_ENA */
+#define WM8400_RON_ENA_SHIFT                        11  /* RON_ENA */
+#define WM8400_RON_ENA_WIDTH                         1  /* RON_ENA */
+#define WM8400_ROP_ENA                          0x0400  /* ROP_ENA */
+#define WM8400_ROP_ENA_MASK                     0x0400  /* ROP_ENA */
+#define WM8400_ROP_ENA_SHIFT                        10  /* ROP_ENA */
+#define WM8400_ROP_ENA_WIDTH                         1  /* ROP_ENA */
+#define WM8400_LOPGA_ENA                        0x0080  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_MASK                   0x0080  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_SHIFT                       7  /* LOPGA_ENA */
+#define WM8400_LOPGA_ENA_WIDTH                       1  /* LOPGA_ENA */
+#define WM8400_ROPGA_ENA                        0x0040  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_MASK                   0x0040  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_SHIFT                       6  /* ROPGA_ENA */
+#define WM8400_ROPGA_ENA_WIDTH                       1  /* ROPGA_ENA */
+#define WM8400_LOMIX_ENA                        0x0020  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_MASK                   0x0020  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_SHIFT                       5  /* LOMIX_ENA */
+#define WM8400_LOMIX_ENA_WIDTH                       1  /* LOMIX_ENA */
+#define WM8400_ROMIX_ENA                        0x0010  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_MASK                   0x0010  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_SHIFT                       4  /* ROMIX_ENA */
+#define WM8400_ROMIX_ENA_WIDTH                       1  /* ROMIX_ENA */
+#define WM8400_DACL_ENA                         0x0002  /* DACL_ENA */
+#define WM8400_DACL_ENA_MASK                    0x0002  /* DACL_ENA */
+#define WM8400_DACL_ENA_SHIFT                        1  /* DACL_ENA */
+#define WM8400_DACL_ENA_WIDTH                        1  /* DACL_ENA */
+#define WM8400_DACR_ENA                         0x0001  /* DACR_ENA */
+#define WM8400_DACR_ENA_MASK                    0x0001  /* DACR_ENA */
+#define WM8400_DACR_ENA_SHIFT                        0  /* DACR_ENA */
+#define WM8400_DACR_ENA_WIDTH                        1  /* DACR_ENA */
+
+/*
+ * R5 (0x05) - Audio Interface (1)
+ */
+#define WM8400_AIFADCL_SRC                      0x8000  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_MASK                 0x8000  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_SHIFT                    15  /* AIFADCL_SRC */
+#define WM8400_AIFADCL_SRC_WIDTH                     1  /* AIFADCL_SRC */
+#define WM8400_AIFADCR_SRC                      0x4000  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_MASK                 0x4000  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_SHIFT                    14  /* AIFADCR_SRC */
+#define WM8400_AIFADCR_SRC_WIDTH                     1  /* AIFADCR_SRC */
+#define WM8400_AIFADC_TDM                       0x2000  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_MASK                  0x2000  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_SHIFT                     13  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_WIDTH                      1  /* AIFADC_TDM */
+#define WM8400_AIFADC_TDM_CHAN                  0x1000  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_MASK             0x1000  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_SHIFT                12  /* AIFADC_TDM_CHAN */
+#define WM8400_AIFADC_TDM_CHAN_WIDTH                 1  /* AIFADC_TDM_CHAN */
+#define WM8400_AIF_BCLK_INV                     0x0100  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_MASK                0x0100  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_SHIFT                    8  /* AIF_BCLK_INV */
+#define WM8400_AIF_BCLK_INV_WIDTH                    1  /* AIF_BCLK_INV */
+#define WM8400_AIF_LRCLK_INV                    0x0080  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_MASK               0x0080  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_SHIFT                   7  /* AIF_LRCLK_INV */
+#define WM8400_AIF_LRCLK_INV_WIDTH                   1  /* AIF_LRCLK_INV */
+#define WM8400_AIF_WL_MASK                      0x0060  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_SHIFT                          5  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_WIDTH                          2  /* AIF_WL - [6:5] */
+#define WM8400_AIF_WL_16BITS                   (0 << 5)
+#define WM8400_AIF_WL_20BITS                   (1 << 5)
+#define WM8400_AIF_WL_24BITS                   (2 << 5)
+#define WM8400_AIF_WL_32BITS                   (3 << 5)
+#define WM8400_AIF_FMT_MASK                     0x0018  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_SHIFT                         3  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_WIDTH                         2  /* AIF_FMT - [4:3] */
+#define WM8400_AIF_FMT_RIGHTJ                  (0 << 3)
+#define WM8400_AIF_FMT_LEFTJ                   (1 << 3)
+#define WM8400_AIF_FMT_I2S                     (2 << 3)
+#define WM8400_AIF_FMT_DSP                     (3 << 3)
+
+/*
+ * R6 (0x06) - Audio Interface (2)
+ */
+#define WM8400_DACL_SRC                         0x8000  /* DACL_SRC */
+#define WM8400_DACL_SRC_MASK                    0x8000  /* DACL_SRC */
+#define WM8400_DACL_SRC_SHIFT                       15  /* DACL_SRC */
+#define WM8400_DACL_SRC_WIDTH                        1  /* DACL_SRC */
+#define WM8400_DACR_SRC                         0x4000  /* DACR_SRC */
+#define WM8400_DACR_SRC_MASK                    0x4000  /* DACR_SRC */
+#define WM8400_DACR_SRC_SHIFT                       14  /* DACR_SRC */
+#define WM8400_DACR_SRC_WIDTH                        1  /* DACR_SRC */
+#define WM8400_AIFDAC_TDM                       0x2000  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_MASK                  0x2000  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_SHIFT                     13  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_WIDTH                      1  /* AIFDAC_TDM */
+#define WM8400_AIFDAC_TDM_CHAN                  0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_MASK             0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_SHIFT                12  /* AIFDAC_TDM_CHAN */
+#define WM8400_AIFDAC_TDM_CHAN_WIDTH                 1  /* AIFDAC_TDM_CHAN */
+#define WM8400_DAC_BOOST_MASK                   0x0C00  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_BOOST_SHIFT                      10  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_BOOST_WIDTH                       2  /* DAC_BOOST - [11:10] */
+#define WM8400_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8400_DAC_COMP_MASK                    0x0010  /* DAC_COMP */
+#define WM8400_DAC_COMP_SHIFT                        4  /* DAC_COMP */
+#define WM8400_DAC_COMP_WIDTH                        1  /* DAC_COMP */
+#define WM8400_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_MASK                0x0008  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_SHIFT                    3  /* DAC_COMPMODE */
+#define WM8400_DAC_COMPMODE_WIDTH                    1  /* DAC_COMPMODE */
+#define WM8400_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8400_ADC_COMP_MASK                    0x0004  /* ADC_COMP */
+#define WM8400_ADC_COMP_SHIFT                        2  /* ADC_COMP */
+#define WM8400_ADC_COMP_WIDTH                        1  /* ADC_COMP */
+#define WM8400_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_MASK                0x0002  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_SHIFT                    1  /* ADC_COMPMODE */
+#define WM8400_ADC_COMPMODE_WIDTH                    1  /* ADC_COMPMODE */
+#define WM8400_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8400_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8400_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8400_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R7 (0x07) - Clocking (1)
+ */
+#define WM8400_TOCLK_RATE                       0x8000  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_MASK                  0x8000  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_SHIFT                     15  /* TOCLK_RATE */
+#define WM8400_TOCLK_RATE_WIDTH                      1  /* TOCLK_RATE */
+#define WM8400_TOCLK_ENA                        0x4000  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_MASK                   0x4000  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_SHIFT                      14  /* TOCLK_ENA */
+#define WM8400_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+#define WM8400_OPCLKDIV_MASK                    0x1E00  /* OPCLKDIV - [12:9] */
+#define WM8400_OPCLKDIV_SHIFT                        9  /* OPCLKDIV - [12:9] */
+#define WM8400_OPCLKDIV_WIDTH                        4  /* OPCLKDIV - [12:9] */
+#define WM8400_DCLKDIV_MASK                     0x01C0  /* DCLKDIV - [8:6] */
+#define WM8400_DCLKDIV_SHIFT                         6  /* DCLKDIV - [8:6] */
+#define WM8400_DCLKDIV_WIDTH                         3  /* DCLKDIV - [8:6] */
+#define WM8400_BCLK_DIV_MASK                    0x001E  /* BCLK_DIV - [4:1] */
+#define WM8400_BCLK_DIV_SHIFT                        1  /* BCLK_DIV - [4:1] */
+#define WM8400_BCLK_DIV_WIDTH                        4  /* BCLK_DIV - [4:1] */
+
+/*
+ * R8 (0x08) - Clocking (2)
+ */
+#define WM8400_MCLK_SRC                         0x8000  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_MASK                    0x8000  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_SHIFT                       15  /* MCLK_SRC */
+#define WM8400_MCLK_SRC_WIDTH                        1  /* MCLK_SRC */
+#define WM8400_SYSCLK_SRC                       0x4000  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_MASK                  0x4000  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_SHIFT                     14  /* SYSCLK_SRC */
+#define WM8400_SYSCLK_SRC_WIDTH                      1  /* SYSCLK_SRC */
+#define WM8400_CLK_FORCE                        0x2000  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_MASK                   0x2000  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_SHIFT                      13  /* CLK_FORCE */
+#define WM8400_CLK_FORCE_WIDTH                       1  /* CLK_FORCE */
+#define WM8400_MCLK_DIV_MASK                    0x1800  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_DIV_SHIFT                       11  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_DIV_WIDTH                        2  /* MCLK_DIV - [12:11] */
+#define WM8400_MCLK_INV                         0x0400  /* MCLK_INV */
+#define WM8400_MCLK_INV_MASK                    0x0400  /* MCLK_INV */
+#define WM8400_MCLK_INV_SHIFT                       10  /* MCLK_INV */
+#define WM8400_MCLK_INV_WIDTH                        1  /* MCLK_INV */
+#define WM8400_ADC_CLKDIV_MASK                  0x00E0  /* ADC_CLKDIV - [7:5] */
+#define WM8400_ADC_CLKDIV_SHIFT                      5  /* ADC_CLKDIV - [7:5] */
+#define WM8400_ADC_CLKDIV_WIDTH                      3  /* ADC_CLKDIV - [7:5] */
+#define WM8400_DAC_CLKDIV_MASK                  0x001C  /* DAC_CLKDIV - [4:2] */
+#define WM8400_DAC_CLKDIV_SHIFT                      2  /* DAC_CLKDIV - [4:2] */
+#define WM8400_DAC_CLKDIV_WIDTH                      3  /* DAC_CLKDIV - [4:2] */
+
+/*
+ * R9 (0x09) - Audio Interface (3)
+ */
+#define WM8400_AIF_MSTR1                        0x8000  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_MASK                   0x8000  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_SHIFT                      15  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR1_WIDTH                       1  /* AIF_MSTR1 */
+#define WM8400_AIF_MSTR2                        0x4000  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_MASK                   0x4000  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_SHIFT                      14  /* AIF_MSTR2 */
+#define WM8400_AIF_MSTR2_WIDTH                       1  /* AIF_MSTR2 */
+#define WM8400_AIF_SEL                          0x2000  /* AIF_SEL */
+#define WM8400_AIF_SEL_MASK                     0x2000  /* AIF_SEL */
+#define WM8400_AIF_SEL_SHIFT                        13  /* AIF_SEL */
+#define WM8400_AIF_SEL_WIDTH                         1  /* AIF_SEL */
+#define WM8400_ADCLRC_DIR                       0x0800  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_MASK                  0x0800  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_SHIFT                     11  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_DIR_WIDTH                      1  /* ADCLRC_DIR */
+#define WM8400_ADCLRC_RATE_MASK                 0x07FF  /* ADCLRC_RATE - [10:0] */
+#define WM8400_ADCLRC_RATE_SHIFT                     0  /* ADCLRC_RATE - [10:0] */
+#define WM8400_ADCLRC_RATE_WIDTH                    11  /* ADCLRC_RATE - [10:0] */
+
+/*
+ * R10 (0x0A) - Audio Interface (4)
+ */
+#define WM8400_ALRCGPIO1                        0x8000  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_MASK                   0x8000  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_SHIFT                      15  /* ALRCGPIO1 */
+#define WM8400_ALRCGPIO1_WIDTH                       1  /* ALRCGPIO1 */
+#define WM8400_ALRCBGPIO6                       0x4000  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_MASK                  0x4000  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_SHIFT                     14  /* ALRCBGPIO6 */
+#define WM8400_ALRCBGPIO6_WIDTH                      1  /* ALRCBGPIO6 */
+#define WM8400_AIF_TRIS                         0x2000  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_MASK                    0x2000  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_SHIFT                       13  /* AIF_TRIS */
+#define WM8400_AIF_TRIS_WIDTH                        1  /* AIF_TRIS */
+#define WM8400_DACLRC_DIR                       0x0800  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_MASK                  0x0800  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_SHIFT                     11  /* DACLRC_DIR */
+#define WM8400_DACLRC_DIR_WIDTH                      1  /* DACLRC_DIR */
+#define WM8400_DACLRC_RATE_MASK                 0x07FF  /* DACLRC_RATE - [10:0] */
+#define WM8400_DACLRC_RATE_SHIFT                     0  /* DACLRC_RATE - [10:0] */
+#define WM8400_DACLRC_RATE_WIDTH                    11  /* DACLRC_RATE - [10:0] */
+
+/*
+ * R11 (0x0B) - DAC CTRL
+ */
+#define WM8400_DAC_SDMCLK_RATE                  0x2000  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_MASK             0x2000  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_SHIFT                13  /* DAC_SDMCLK_RATE */
+#define WM8400_DAC_SDMCLK_RATE_WIDTH                 1  /* DAC_SDMCLK_RATE */
+#define WM8400_AIF_LRCLKRATE                    0x0400  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_MASK               0x0400  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_SHIFT                  10  /* AIF_LRCLKRATE */
+#define WM8400_AIF_LRCLKRATE_WIDTH                   1  /* AIF_LRCLKRATE */
+#define WM8400_DAC_MONO                         0x0200  /* DAC_MONO */
+#define WM8400_DAC_MONO_MASK                    0x0200  /* DAC_MONO */
+#define WM8400_DAC_MONO_SHIFT                        9  /* DAC_MONO */
+#define WM8400_DAC_MONO_WIDTH                        1  /* DAC_MONO */
+#define WM8400_DAC_SB_FILT                      0x0100  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_MASK                 0x0100  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_SHIFT                     8  /* DAC_SB_FILT */
+#define WM8400_DAC_SB_FILT_WIDTH                     1  /* DAC_SB_FILT */
+#define WM8400_DAC_MUTERATE                     0x0080  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_MASK                0x0080  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_SHIFT                    7  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+#define WM8400_DAC_MUTEMODE                     0x0040  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_MASK                0x0040  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_SHIFT                    6  /* DAC_MUTEMODE */
+#define WM8400_DAC_MUTEMODE_WIDTH                    1  /* DAC_MUTEMODE */
+#define WM8400_DEEMP_MASK                       0x0030  /* DEEMP - [5:4] */
+#define WM8400_DEEMP_SHIFT                           4  /* DEEMP - [5:4] */
+#define WM8400_DEEMP_WIDTH                           2  /* DEEMP - [5:4] */
+#define WM8400_DAC_MUTE                         0x0004  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_MASK                    0x0004  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_SHIFT                        2  /* DAC_MUTE */
+#define WM8400_DAC_MUTE_WIDTH                        1  /* DAC_MUTE */
+#define WM8400_DACL_DATINV                      0x0002  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_MASK                 0x0002  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_SHIFT                     1  /* DACL_DATINV */
+#define WM8400_DACL_DATINV_WIDTH                     1  /* DACL_DATINV */
+#define WM8400_DACR_DATINV                      0x0001  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_MASK                 0x0001  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_SHIFT                     0  /* DACR_DATINV */
+#define WM8400_DACR_DATINV_WIDTH                     1  /* DACR_DATINV */
+
+/*
+ * R12 (0x0C) - Left DAC Digital Volume
+ */
+#define WM8400_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8400_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8400_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8400_DACL_VOL_SHIFT                        0  /* DACL_VOL - [7:0] */
+#define WM8400_DACL_VOL_WIDTH                        8  /* DACL_VOL - [7:0] */
+
+/*
+ * R13 (0x0D) - Right DAC Digital Volume
+ */
+#define WM8400_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8400_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8400_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8400_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8400_DACR_VOL_SHIFT                        0  /* DACR_VOL - [7:0] */
+#define WM8400_DACR_VOL_WIDTH                        8  /* DACR_VOL - [7:0] */
+
+/*
+ * R14 (0x0E) - Digital Side Tone
+ */
+#define WM8400_ADCL_DAC_SVOL_MASK               0x1E00  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCL_DAC_SVOL_SHIFT                   9  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCL_DAC_SVOL_WIDTH                   4  /*   ADCL_DAC_SVOL - [12:9] */
+#define WM8400_ADCR_DAC_SVOL_MASK               0x01E0  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADCR_DAC_SVOL_SHIFT                   5  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADCR_DAC_SVOL_WIDTH                   4  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8400_ADC_TO_DACL_MASK                 0x000C  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACL_SHIFT                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACL_WIDTH                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8400_ADC_TO_DACR_MASK                 0x0003  /* ADC_TO_DACR - [1:0] */
+#define WM8400_ADC_TO_DACR_SHIFT                     0  /* ADC_TO_DACR - [1:0] */
+#define WM8400_ADC_TO_DACR_WIDTH                     2  /* ADC_TO_DACR - [1:0] */
+
+/*
+ * R15 (0x0F) - ADC CTRL
+ */
+#define WM8400_ADC_HPF_ENA                      0x0100  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_MASK                 0x0100  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_SHIFT                     8  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_ENA_WIDTH                     1  /* ADC_HPF_ENA */
+#define WM8400_ADC_HPF_CUT_MASK                 0x0060  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADC_HPF_CUT_SHIFT                     5  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADC_HPF_CUT_WIDTH                     2  /* ADC_HPF_CUT - [6:5] */
+#define WM8400_ADCL_DATINV                      0x0002  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_MASK                 0x0002  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_SHIFT                     1  /* ADCL_DATINV */
+#define WM8400_ADCL_DATINV_WIDTH                     1  /* ADCL_DATINV */
+#define WM8400_ADCR_DATINV                      0x0001  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_MASK                 0x0001  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_SHIFT                     0  /* ADCR_DATINV */
+#define WM8400_ADCR_DATINV_WIDTH                     1  /* ADCR_DATINV */
+
+/*
+ * R16 (0x10) - Left ADC Digital Volume
+ */
+#define WM8400_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8400_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8400_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8400_ADCL_VOL_SHIFT                        0  /* ADCL_VOL - [7:0] */
+#define WM8400_ADCL_VOL_WIDTH                        8  /* ADCL_VOL - [7:0] */
+
+/*
+ * R17 (0x11) - Right ADC Digital Volume
+ */
+#define WM8400_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8400_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8400_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8400_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8400_ADCR_VOL_SHIFT                        0  /* ADCR_VOL - [7:0] */
+#define WM8400_ADCR_VOL_WIDTH                        8  /* ADCR_VOL - [7:0] */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_LI12MUTE                         0x0080  /* LI12MUTE */
+#define WM8400_LI12MUTE_MASK                    0x0080  /* LI12MUTE */
+#define WM8400_LI12MUTE_SHIFT                        7  /* LI12MUTE */
+#define WM8400_LI12MUTE_WIDTH                        1  /* LI12MUTE */
+#define WM8400_LI12ZC                           0x0040  /* LI12ZC */
+#define WM8400_LI12ZC_MASK                      0x0040  /* LI12ZC */
+#define WM8400_LI12ZC_SHIFT                          6  /* LI12ZC */
+#define WM8400_LI12ZC_WIDTH                          1  /* LI12ZC */
+#define WM8400_LIN12VOL_MASK                    0x001F  /* LIN12VOL - [4:0] */
+#define WM8400_LIN12VOL_SHIFT                        0  /* LIN12VOL - [4:0] */
+#define WM8400_LIN12VOL_WIDTH                        5  /* LIN12VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_LI34MUTE                         0x0080  /* LI34MUTE */
+#define WM8400_LI34MUTE_MASK                    0x0080  /* LI34MUTE */
+#define WM8400_LI34MUTE_SHIFT                        7  /* LI34MUTE */
+#define WM8400_LI34MUTE_WIDTH                        1  /* LI34MUTE */
+#define WM8400_LI34ZC                           0x0040  /* LI34ZC */
+#define WM8400_LI34ZC_MASK                      0x0040  /* LI34ZC */
+#define WM8400_LI34ZC_SHIFT                          6  /* LI34ZC */
+#define WM8400_LI34ZC_WIDTH                          1  /* LI34ZC */
+#define WM8400_LIN34VOL_MASK                    0x001F  /* LIN34VOL - [4:0] */
+#define WM8400_LIN34VOL_SHIFT                        0  /* LIN34VOL - [4:0] */
+#define WM8400_LIN34VOL_WIDTH                        5  /* LIN34VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_RI12MUTE                         0x0080  /* RI12MUTE */
+#define WM8400_RI12MUTE_MASK                    0x0080  /* RI12MUTE */
+#define WM8400_RI12MUTE_SHIFT                        7  /* RI12MUTE */
+#define WM8400_RI12MUTE_WIDTH                        1  /* RI12MUTE */
+#define WM8400_RI12ZC                           0x0040  /* RI12ZC */
+#define WM8400_RI12ZC_MASK                      0x0040  /* RI12ZC */
+#define WM8400_RI12ZC_SHIFT                          6  /* RI12ZC */
+#define WM8400_RI12ZC_WIDTH                          1  /* RI12ZC */
+#define WM8400_RIN12VOL_MASK                    0x001F  /* RIN12VOL - [4:0] */
+#define WM8400_RIN12VOL_SHIFT                        0  /* RIN12VOL - [4:0] */
+#define WM8400_RIN12VOL_WIDTH                        5  /* RIN12VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8400_IPVU                             0x0100  /* IPVU */
+#define WM8400_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8400_IPVU_SHIFT                            8  /* IPVU */
+#define WM8400_IPVU_WIDTH                            1  /* IPVU */
+#define WM8400_RI34MUTE                         0x0080  /* RI34MUTE */
+#define WM8400_RI34MUTE_MASK                    0x0080  /* RI34MUTE */
+#define WM8400_RI34MUTE_SHIFT                        7  /* RI34MUTE */
+#define WM8400_RI34MUTE_WIDTH                        1  /* RI34MUTE */
+#define WM8400_RI34ZC                           0x0040  /* RI34ZC */
+#define WM8400_RI34ZC_MASK                      0x0040  /* RI34ZC */
+#define WM8400_RI34ZC_SHIFT                          6  /* RI34ZC */
+#define WM8400_RI34ZC_WIDTH                          1  /* RI34ZC */
+#define WM8400_RIN34VOL_MASK                    0x001F  /* RIN34VOL - [4:0] */
+#define WM8400_RIN34VOL_SHIFT                        0  /* RIN34VOL - [4:0] */
+#define WM8400_RIN34VOL_WIDTH                        5  /* RIN34VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_LOZC                             0x0080  /* LOZC */
+#define WM8400_LOZC_MASK                        0x0080  /* LOZC */
+#define WM8400_LOZC_SHIFT                            7  /* LOZC */
+#define WM8400_LOZC_WIDTH                            1  /* LOZC */
+#define WM8400_LOUTVOL_MASK                     0x007F  /* LOUTVOL - [6:0] */
+#define WM8400_LOUTVOL_SHIFT                         0  /* LOUTVOL - [6:0] */
+#define WM8400_LOUTVOL_WIDTH                         7  /* LOUTVOL - [6:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_ROZC                             0x0080  /* ROZC */
+#define WM8400_ROZC_MASK                        0x0080  /* ROZC */
+#define WM8400_ROZC_SHIFT                            7  /* ROZC */
+#define WM8400_ROZC_WIDTH                            1  /* ROZC */
+#define WM8400_ROUTVOL_MASK                     0x007F  /* ROUTVOL - [6:0] */
+#define WM8400_ROUTVOL_SHIFT                         0  /* ROUTVOL - [6:0] */
+#define WM8400_ROUTVOL_WIDTH                         7  /* ROUTVOL - [6:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8400_LONMUTE                          0x0040  /* LONMUTE */
+#define WM8400_LONMUTE_MASK                     0x0040  /* LONMUTE */
+#define WM8400_LONMUTE_SHIFT                         6  /* LONMUTE */
+#define WM8400_LONMUTE_WIDTH                         1  /* LONMUTE */
+#define WM8400_LOPMUTE                          0x0020  /* LOPMUTE */
+#define WM8400_LOPMUTE_MASK                     0x0020  /* LOPMUTE */
+#define WM8400_LOPMUTE_SHIFT                         5  /* LOPMUTE */
+#define WM8400_LOPMUTE_WIDTH                         1  /* LOPMUTE */
+#define WM8400_LOATTN                           0x0010  /* LOATTN */
+#define WM8400_LOATTN_MASK                      0x0010  /* LOATTN */
+#define WM8400_LOATTN_SHIFT                          4  /* LOATTN */
+#define WM8400_LOATTN_WIDTH                          1  /* LOATTN */
+#define WM8400_RONMUTE                          0x0004  /* RONMUTE */
+#define WM8400_RONMUTE_MASK                     0x0004  /* RONMUTE */
+#define WM8400_RONMUTE_SHIFT                         2  /* RONMUTE */
+#define WM8400_RONMUTE_WIDTH                         1  /* RONMUTE */
+#define WM8400_ROPMUTE                          0x0002  /* ROPMUTE */
+#define WM8400_ROPMUTE_MASK                     0x0002  /* ROPMUTE */
+#define WM8400_ROPMUTE_SHIFT                         1  /* ROPMUTE */
+#define WM8400_ROPMUTE_WIDTH                         1  /* ROPMUTE */
+#define WM8400_ROATTN                           0x0001  /* ROATTN */
+#define WM8400_ROATTN_MASK                      0x0001  /* ROATTN */
+#define WM8400_ROATTN_SHIFT                          0  /* ROATTN */
+#define WM8400_ROATTN_WIDTH                          1  /* ROATTN */
+
+/*
+ * R31 (0x1F) - Out3/4 Volume
+ */
+#define WM8400_OUT3MUTE                         0x0020  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_MASK                    0x0020  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_SHIFT                        5  /* OUT3MUTE */
+#define WM8400_OUT3MUTE_WIDTH                        1  /* OUT3MUTE */
+#define WM8400_OUT3ATTN                         0x0010  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_MASK                    0x0010  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_SHIFT                        4  /* OUT3ATTN */
+#define WM8400_OUT3ATTN_WIDTH                        1  /* OUT3ATTN */
+#define WM8400_OUT4MUTE                         0x0002  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_MASK                    0x0002  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_SHIFT                        1  /* OUT4MUTE */
+#define WM8400_OUT4MUTE_WIDTH                        1  /* OUT4MUTE */
+#define WM8400_OUT4ATTN                         0x0001  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_MASK                    0x0001  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_SHIFT                        0  /* OUT4ATTN */
+#define WM8400_OUT4ATTN_WIDTH                        1  /* OUT4ATTN */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_LOPGAZC                          0x0080  /* LOPGAZC */
+#define WM8400_LOPGAZC_MASK                     0x0080  /* LOPGAZC */
+#define WM8400_LOPGAZC_SHIFT                         7  /* LOPGAZC */
+#define WM8400_LOPGAZC_WIDTH                         1  /* LOPGAZC */
+#define WM8400_LOPGAVOL_MASK                    0x007F  /* LOPGAVOL - [6:0] */
+#define WM8400_LOPGAVOL_SHIFT                        0  /* LOPGAVOL - [6:0] */
+#define WM8400_LOPGAVOL_WIDTH                        7  /* LOPGAVOL - [6:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8400_OPVU                             0x0100  /* OPVU */
+#define WM8400_OPVU_MASK                        0x0100  /* OPVU */
+#define WM8400_OPVU_SHIFT                            8  /* OPVU */
+#define WM8400_OPVU_WIDTH                            1  /* OPVU */
+#define WM8400_ROPGAZC                          0x0080  /* ROPGAZC */
+#define WM8400_ROPGAZC_MASK                     0x0080  /* ROPGAZC */
+#define WM8400_ROPGAZC_SHIFT                         7  /* ROPGAZC */
+#define WM8400_ROPGAZC_WIDTH                         1  /* ROPGAZC */
+#define WM8400_ROPGAVOL_MASK                    0x007F  /* ROPGAVOL - [6:0] */
+#define WM8400_ROPGAVOL_SHIFT                        0  /* ROPGAVOL - [6:0] */
+#define WM8400_ROPGAVOL_WIDTH                        7  /* ROPGAVOL - [6:0] */
+
+/*
+ * R34 (0x22) - Speaker Volume
+ */
+#define WM8400_SPKATTN_MASK                     0x0003  /* SPKATTN - [1:0] */
+#define WM8400_SPKATTN_SHIFT                         0  /* SPKATTN - [1:0] */
+#define WM8400_SPKATTN_WIDTH                         2  /* SPKATTN - [1:0] */
+
+/*
+ * R35 (0x23) - ClassD1
+ */
+#define WM8400_CDMODE                           0x0100  /* CDMODE */
+#define WM8400_CDMODE_MASK                      0x0100  /* CDMODE */
+#define WM8400_CDMODE_SHIFT                          8  /* CDMODE */
+#define WM8400_CDMODE_WIDTH                          1  /* CDMODE */
+#define WM8400_CLASSD_CLK_SEL                   0x0080  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_MASK              0x0080  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_SHIFT                  7  /* CLASSD_CLK_SEL */
+#define WM8400_CLASSD_CLK_SEL_WIDTH                  1  /* CLASSD_CLK_SEL */
+#define WM8400_CD_SRCTRL                        0x0040  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_MASK                   0x0040  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_SHIFT                       6  /* CD_SRCTRL */
+#define WM8400_CD_SRCTRL_WIDTH                       1  /* CD_SRCTRL */
+#define WM8400_SPKNOPOP                         0x0020  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_MASK                    0x0020  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_SHIFT                        5  /* SPKNOPOP */
+#define WM8400_SPKNOPOP_WIDTH                        1  /* SPKNOPOP */
+#define WM8400_DBLERATE                         0x0010  /* DBLERATE */
+#define WM8400_DBLERATE_MASK                    0x0010  /* DBLERATE */
+#define WM8400_DBLERATE_SHIFT                        4  /* DBLERATE */
+#define WM8400_DBLERATE_WIDTH                        1  /* DBLERATE */
+#define WM8400_LOOPTEST                         0x0008  /* LOOPTEST */
+#define WM8400_LOOPTEST_MASK                    0x0008  /* LOOPTEST */
+#define WM8400_LOOPTEST_SHIFT                        3  /* LOOPTEST */
+#define WM8400_LOOPTEST_WIDTH                        1  /* LOOPTEST */
+#define WM8400_HALFABBIAS                       0x0004  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_MASK                  0x0004  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_SHIFT                      2  /* HALFABBIAS */
+#define WM8400_HALFABBIAS_WIDTH                      1  /* HALFABBIAS */
+#define WM8400_TRIDEL_MASK                      0x0003  /* TRIDEL - [1:0] */
+#define WM8400_TRIDEL_SHIFT                          0  /* TRIDEL - [1:0] */
+#define WM8400_TRIDEL_WIDTH                          2  /* TRIDEL - [1:0] */
+
+/*
+ * R37 (0x25) - ClassD3
+ */
+#define WM8400_DCGAIN_MASK                      0x0038  /* DCGAIN - [5:3] */
+#define WM8400_DCGAIN_SHIFT                          3  /* DCGAIN - [5:3] */
+#define WM8400_DCGAIN_WIDTH                          3  /* DCGAIN - [5:3] */
+#define WM8400_ACGAIN_MASK                      0x0007  /* ACGAIN - [2:0] */
+#define WM8400_ACGAIN_SHIFT                          0  /* ACGAIN - [2:0] */
+#define WM8400_ACGAIN_WIDTH                          3  /* ACGAIN - [2:0] */
+
+/*
+ * R39 (0x27) - Input Mixer1
+ */
+#define WM8400_AINLMODE_MASK                    0x000C  /* AINLMODE - [3:2] */
+#define WM8400_AINLMODE_SHIFT                        2  /* AINLMODE - [3:2] */
+#define WM8400_AINLMODE_WIDTH                        2  /* AINLMODE - [3:2] */
+#define WM8400_AINRMODE_MASK                    0x0003  /* AINRMODE - [1:0] */
+#define WM8400_AINRMODE_SHIFT                        0  /* AINRMODE - [1:0] */
+#define WM8400_AINRMODE_WIDTH                        2  /* AINRMODE - [1:0] */
+
+/*
+ * R40 (0x28) - Input Mixer2
+ */
+#define WM8400_LMP4                             0x0080  /* LMP4 */
+#define WM8400_LMP4_MASK                        0x0080  /* LMP4 */
+#define WM8400_LMP4_SHIFT                            7  /* LMP4 */
+#define WM8400_LMP4_WIDTH                            1  /* LMP4 */
+#define WM8400_LMN3                             0x0040  /* LMN3 */
+#define WM8400_LMN3_MASK                        0x0040  /* LMN3 */
+#define WM8400_LMN3_SHIFT                            6  /* LMN3 */
+#define WM8400_LMN3_WIDTH                            1  /* LMN3 */
+#define WM8400_LMP2                             0x0020  /* LMP2 */
+#define WM8400_LMP2_MASK                        0x0020  /* LMP2 */
+#define WM8400_LMP2_SHIFT                            5  /* LMP2 */
+#define WM8400_LMP2_WIDTH                            1  /* LMP2 */
+#define WM8400_LMN1                             0x0010  /* LMN1 */
+#define WM8400_LMN1_MASK                        0x0010  /* LMN1 */
+#define WM8400_LMN1_SHIFT                            4  /* LMN1 */
+#define WM8400_LMN1_WIDTH                            1  /* LMN1 */
+#define WM8400_RMP4                             0x0008  /* RMP4 */
+#define WM8400_RMP4_MASK                        0x0008  /* RMP4 */
+#define WM8400_RMP4_SHIFT                            3  /* RMP4 */
+#define WM8400_RMP4_WIDTH                            1  /* RMP4 */
+#define WM8400_RMN3                             0x0004  /* RMN3 */
+#define WM8400_RMN3_MASK                        0x0004  /* RMN3 */
+#define WM8400_RMN3_SHIFT                            2  /* RMN3 */
+#define WM8400_RMN3_WIDTH                            1  /* RMN3 */
+#define WM8400_RMP2                             0x0002  /* RMP2 */
+#define WM8400_RMP2_MASK                        0x0002  /* RMP2 */
+#define WM8400_RMP2_SHIFT                            1  /* RMP2 */
+#define WM8400_RMP2_WIDTH                            1  /* RMP2 */
+#define WM8400_RMN1                             0x0001  /* RMN1 */
+#define WM8400_RMN1_MASK                        0x0001  /* RMN1 */
+#define WM8400_RMN1_SHIFT                            0  /* RMN1 */
+#define WM8400_RMN1_WIDTH                            1  /* RMN1 */
+
+/*
+ * R41 (0x29) - Input Mixer3
+ */
+#define WM8400_L34MNB                           0x0100  /* L34MNB */
+#define WM8400_L34MNB_MASK                      0x0100  /* L34MNB */
+#define WM8400_L34MNB_SHIFT                          8  /* L34MNB */
+#define WM8400_L34MNB_WIDTH                          1  /* L34MNB */
+#define WM8400_L34MNBST                         0x0080  /* L34MNBST */
+#define WM8400_L34MNBST_MASK                    0x0080  /* L34MNBST */
+#define WM8400_L34MNBST_SHIFT                        7  /* L34MNBST */
+#define WM8400_L34MNBST_WIDTH                        1  /* L34MNBST */
+#define WM8400_L12MNB                           0x0020  /* L12MNB */
+#define WM8400_L12MNB_MASK                      0x0020  /* L12MNB */
+#define WM8400_L12MNB_SHIFT                          5  /* L12MNB */
+#define WM8400_L12MNB_WIDTH                          1  /* L12MNB */
+#define WM8400_L12MNBST                         0x0010  /* L12MNBST */
+#define WM8400_L12MNBST_MASK                    0x0010  /* L12MNBST */
+#define WM8400_L12MNBST_SHIFT                        4  /* L12MNBST */
+#define WM8400_L12MNBST_WIDTH                        1  /* L12MNBST */
+#define WM8400_LDBVOL_MASK                      0x0007  /* LDBVOL - [2:0] */
+#define WM8400_LDBVOL_SHIFT                          0  /* LDBVOL - [2:0] */
+#define WM8400_LDBVOL_WIDTH                          3  /* LDBVOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer4
+ */
+#define WM8400_R34MNB                           0x0100  /* R34MNB */
+#define WM8400_R34MNB_MASK                      0x0100  /* R34MNB */
+#define WM8400_R34MNB_SHIFT                          8  /* R34MNB */
+#define WM8400_R34MNB_WIDTH                          1  /* R34MNB */
+#define WM8400_R34MNBST                         0x0080  /* R34MNBST */
+#define WM8400_R34MNBST_MASK                    0x0080  /* R34MNBST */
+#define WM8400_R34MNBST_SHIFT                        7  /* R34MNBST */
+#define WM8400_R34MNBST_WIDTH                        1  /* R34MNBST */
+#define WM8400_R12MNB                           0x0020  /* R12MNB */
+#define WM8400_R12MNB_MASK                      0x0020  /* R12MNB */
+#define WM8400_R12MNB_SHIFT                          5  /* R12MNB */
+#define WM8400_R12MNB_WIDTH                          1  /* R12MNB */
+#define WM8400_R12MNBST                         0x0010  /* R12MNBST */
+#define WM8400_R12MNBST_MASK                    0x0010  /* R12MNBST */
+#define WM8400_R12MNBST_SHIFT                        4  /* R12MNBST */
+#define WM8400_R12MNBST_WIDTH                        1  /* R12MNBST */
+#define WM8400_RDBVOL_MASK                      0x0007  /* RDBVOL - [2:0] */
+#define WM8400_RDBVOL_SHIFT                          0  /* RDBVOL - [2:0] */
+#define WM8400_RDBVOL_WIDTH                          3  /* RDBVOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer5
+ */
+#define WM8400_LI2BVOL_MASK                     0x01C0  /* LI2BVOL - [8:6] */
+#define WM8400_LI2BVOL_SHIFT                         6  /* LI2BVOL - [8:6] */
+#define WM8400_LI2BVOL_WIDTH                         3  /* LI2BVOL - [8:6] */
+#define WM8400_LR4BVOL_MASK                     0x0038  /* LR4BVOL - [5:3] */
+#define WM8400_LR4BVOL_SHIFT                         3  /* LR4BVOL - [5:3] */
+#define WM8400_LR4BVOL_WIDTH                         3  /* LR4BVOL - [5:3] */
+#define WM8400_LL4BVOL_MASK                     0x0007  /* LL4BVOL - [2:0] */
+#define WM8400_LL4BVOL_SHIFT                         0  /* LL4BVOL - [2:0] */
+#define WM8400_LL4BVOL_WIDTH                         3  /* LL4BVOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer6
+ */
+#define WM8400_RI2BVOL_MASK                     0x01C0  /* RI2BVOL - [8:6] */
+#define WM8400_RI2BVOL_SHIFT                         6  /* RI2BVOL - [8:6] */
+#define WM8400_RI2BVOL_WIDTH                         3  /* RI2BVOL - [8:6] */
+#define WM8400_RL4BVOL_MASK                     0x0038  /* RL4BVOL - [5:3] */
+#define WM8400_RL4BVOL_SHIFT                         3  /* RL4BVOL - [5:3] */
+#define WM8400_RL4BVOL_WIDTH                         3  /* RL4BVOL - [5:3] */
+#define WM8400_RR4BVOL_MASK                     0x0007  /* RR4BVOL - [2:0] */
+#define WM8400_RR4BVOL_SHIFT                         0  /* RR4BVOL - [2:0] */
+#define WM8400_RR4BVOL_WIDTH                         3  /* RR4BVOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer1
+ */
+#define WM8400_LRBLO                            0x0080  /* LRBLO */
+#define WM8400_LRBLO_MASK                       0x0080  /* LRBLO */
+#define WM8400_LRBLO_SHIFT                           7  /* LRBLO */
+#define WM8400_LRBLO_WIDTH                           1  /* LRBLO */
+#define WM8400_LLBLO                            0x0040  /* LLBLO */
+#define WM8400_LLBLO_MASK                       0x0040  /* LLBLO */
+#define WM8400_LLBLO_SHIFT                           6  /* LLBLO */
+#define WM8400_LLBLO_WIDTH                           1  /* LLBLO */
+#define WM8400_LRI3LO                           0x0020  /* LRI3LO */
+#define WM8400_LRI3LO_MASK                      0x0020  /* LRI3LO */
+#define WM8400_LRI3LO_SHIFT                          5  /* LRI3LO */
+#define WM8400_LRI3LO_WIDTH                          1  /* LRI3LO */
+#define WM8400_LLI3LO                           0x0010  /* LLI3LO */
+#define WM8400_LLI3LO_MASK                      0x0010  /* LLI3LO */
+#define WM8400_LLI3LO_SHIFT                          4  /* LLI3LO */
+#define WM8400_LLI3LO_WIDTH                          1  /* LLI3LO */
+#define WM8400_LR12LO                           0x0008  /* LR12LO */
+#define WM8400_LR12LO_MASK                      0x0008  /* LR12LO */
+#define WM8400_LR12LO_SHIFT                          3  /* LR12LO */
+#define WM8400_LR12LO_WIDTH                          1  /* LR12LO */
+#define WM8400_LL12LO                           0x0004  /* LL12LO */
+#define WM8400_LL12LO_MASK                      0x0004  /* LL12LO */
+#define WM8400_LL12LO_SHIFT                          2  /* LL12LO */
+#define WM8400_LL12LO_WIDTH                          1  /* LL12LO */
+#define WM8400_LDLO                             0x0001  /* LDLO */
+#define WM8400_LDLO_MASK                        0x0001  /* LDLO */
+#define WM8400_LDLO_SHIFT                            0  /* LDLO */
+#define WM8400_LDLO_WIDTH                            1  /* LDLO */
+
+/*
+ * R46 (0x2E) - Output Mixer2
+ */
+#define WM8400_RLBRO                            0x0080  /* RLBRO */
+#define WM8400_RLBRO_MASK                       0x0080  /* RLBRO */
+#define WM8400_RLBRO_SHIFT                           7  /* RLBRO */
+#define WM8400_RLBRO_WIDTH                           1  /* RLBRO */
+#define WM8400_RRBRO                            0x0040  /* RRBRO */
+#define WM8400_RRBRO_MASK                       0x0040  /* RRBRO */
+#define WM8400_RRBRO_SHIFT                           6  /* RRBRO */
+#define WM8400_RRBRO_WIDTH                           1  /* RRBRO */
+#define WM8400_RLI3RO                           0x0020  /* RLI3RO */
+#define WM8400_RLI3RO_MASK                      0x0020  /* RLI3RO */
+#define WM8400_RLI3RO_SHIFT                          5  /* RLI3RO */
+#define WM8400_RLI3RO_WIDTH                          1  /* RLI3RO */
+#define WM8400_RRI3RO                           0x0010  /* RRI3RO */
+#define WM8400_RRI3RO_MASK                      0x0010  /* RRI3RO */
+#define WM8400_RRI3RO_SHIFT                          4  /* RRI3RO */
+#define WM8400_RRI3RO_WIDTH                          1  /* RRI3RO */
+#define WM8400_RL12RO                           0x0008  /* RL12RO */
+#define WM8400_RL12RO_MASK                      0x0008  /* RL12RO */
+#define WM8400_RL12RO_SHIFT                          3  /* RL12RO */
+#define WM8400_RL12RO_WIDTH                          1  /* RL12RO */
+#define WM8400_RR12RO                           0x0004  /* RR12RO */
+#define WM8400_RR12RO_MASK                      0x0004  /* RR12RO */
+#define WM8400_RR12RO_SHIFT                          2  /* RR12RO */
+#define WM8400_RR12RO_WIDTH                          1  /* RR12RO */
+#define WM8400_RDRO                             0x0001  /* RDRO */
+#define WM8400_RDRO_MASK                        0x0001  /* RDRO */
+#define WM8400_RDRO_SHIFT                            0  /* RDRO */
+#define WM8400_RDRO_WIDTH                            1  /* RDRO */
+
+/*
+ * R47 (0x2F) - Output Mixer3
+ */
+#define WM8400_LLI3LOVOL_MASK                   0x01C0  /* LLI3LOVOL - [8:6] */
+#define WM8400_LLI3LOVOL_SHIFT                       6  /* LLI3LOVOL - [8:6] */
+#define WM8400_LLI3LOVOL_WIDTH                       3  /* LLI3LOVOL - [8:6] */
+#define WM8400_LR12LOVOL_MASK                   0x0038  /* LR12LOVOL - [5:3] */
+#define WM8400_LR12LOVOL_SHIFT                       3  /* LR12LOVOL - [5:3] */
+#define WM8400_LR12LOVOL_WIDTH                       3  /* LR12LOVOL - [5:3] */
+#define WM8400_LL12LOVOL_MASK                   0x0007  /* LL12LOVOL - [2:0] */
+#define WM8400_LL12LOVOL_SHIFT                       0  /* LL12LOVOL - [2:0] */
+#define WM8400_LL12LOVOL_WIDTH                       3  /* LL12LOVOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer4
+ */
+#define WM8400_RRI3ROVOL_MASK                   0x01C0  /* RRI3ROVOL - [8:6] */
+#define WM8400_RRI3ROVOL_SHIFT                       6  /* RRI3ROVOL - [8:6] */
+#define WM8400_RRI3ROVOL_WIDTH                       3  /* RRI3ROVOL - [8:6] */
+#define WM8400_RL12ROVOL_MASK                   0x0038  /* RL12ROVOL - [5:3] */
+#define WM8400_RL12ROVOL_SHIFT                       3  /* RL12ROVOL - [5:3] */
+#define WM8400_RL12ROVOL_WIDTH                       3  /* RL12ROVOL - [5:3] */
+#define WM8400_RR12ROVOL_MASK                   0x0007  /* RR12ROVOL - [2:0] */
+#define WM8400_RR12ROVOL_SHIFT                       0  /* RR12ROVOL - [2:0] */
+#define WM8400_RR12ROVOL_WIDTH                       3  /* RR12ROVOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer5
+ */
+#define WM8400_LRI3LOVOL_MASK                   0x01C0  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRI3LOVOL_SHIFT                       6  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRI3LOVOL_WIDTH                       3  /* LRI3LOVOL - [8:6] */
+#define WM8400_LRBLOVOL_MASK                    0x0038  /* LRBLOVOL - [5:3] */
+#define WM8400_LRBLOVOL_SHIFT                        3  /* LRBLOVOL - [5:3] */
+#define WM8400_LRBLOVOL_WIDTH                        3  /* LRBLOVOL - [5:3] */
+#define WM8400_LLBLOVOL_MASK                    0x0007  /* LLBLOVOL - [2:0] */
+#define WM8400_LLBLOVOL_SHIFT                        0  /* LLBLOVOL - [2:0] */
+#define WM8400_LLBLOVOL_WIDTH                        3  /* LLBLOVOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer6
+ */
+#define WM8400_RLI3ROVOL_MASK                   0x01C0  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLI3ROVOL_SHIFT                       6  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLI3ROVOL_WIDTH                       3  /* RLI3ROVOL - [8:6] */
+#define WM8400_RLBROVOL_MASK                    0x0038  /* RLBROVOL - [5:3] */
+#define WM8400_RLBROVOL_SHIFT                        3  /* RLBROVOL - [5:3] */
+#define WM8400_RLBROVOL_WIDTH                        3  /* RLBROVOL - [5:3] */
+#define WM8400_RRBROVOL_MASK                    0x0007  /* RRBROVOL - [2:0] */
+#define WM8400_RRBROVOL_SHIFT                        0  /* RRBROVOL - [2:0] */
+#define WM8400_RRBROVOL_WIDTH                        3  /* RRBROVOL - [2:0] */
+
+/*
+ * R51 (0x33) - Out3/4 Mixer
+ */
+#define WM8400_VSEL_MASK                        0x0180  /* VSEL - [8:7] */
+#define WM8400_VSEL_SHIFT                            7  /* VSEL - [8:7] */
+#define WM8400_VSEL_WIDTH                            2  /* VSEL - [8:7] */
+#define WM8400_LI4O3                            0x0020  /* LI4O3 */
+#define WM8400_LI4O3_MASK                       0x0020  /* LI4O3 */
+#define WM8400_LI4O3_SHIFT                           5  /* LI4O3 */
+#define WM8400_LI4O3_WIDTH                           1  /* LI4O3 */
+#define WM8400_LPGAO3                           0x0010  /* LPGAO3 */
+#define WM8400_LPGAO3_MASK                      0x0010  /* LPGAO3 */
+#define WM8400_LPGAO3_SHIFT                          4  /* LPGAO3 */
+#define WM8400_LPGAO3_WIDTH                          1  /* LPGAO3 */
+#define WM8400_RI4O4                            0x0002  /* RI4O4 */
+#define WM8400_RI4O4_MASK                       0x0002  /* RI4O4 */
+#define WM8400_RI4O4_SHIFT                           1  /* RI4O4 */
+#define WM8400_RI4O4_WIDTH                           1  /* RI4O4 */
+#define WM8400_RPGAO4                           0x0001  /* RPGAO4 */
+#define WM8400_RPGAO4_MASK                      0x0001  /* RPGAO4 */
+#define WM8400_RPGAO4_SHIFT                          0  /* RPGAO4 */
+#define WM8400_RPGAO4_WIDTH                          1  /* RPGAO4 */
+
+/*
+ * R52 (0x34) - Line Mixer1
+ */
+#define WM8400_LLOPGALON                        0x0040  /* LLOPGALON */
+#define WM8400_LLOPGALON_MASK                   0x0040  /* LLOPGALON */
+#define WM8400_LLOPGALON_SHIFT                       6  /* LLOPGALON */
+#define WM8400_LLOPGALON_WIDTH                       1  /* LLOPGALON */
+#define WM8400_LROPGALON                        0x0020  /* LROPGALON */
+#define WM8400_LROPGALON_MASK                   0x0020  /* LROPGALON */
+#define WM8400_LROPGALON_SHIFT                       5  /* LROPGALON */
+#define WM8400_LROPGALON_WIDTH                       1  /* LROPGALON */
+#define WM8400_LOPLON                           0x0010  /* LOPLON */
+#define WM8400_LOPLON_MASK                      0x0010  /* LOPLON */
+#define WM8400_LOPLON_SHIFT                          4  /* LOPLON */
+#define WM8400_LOPLON_WIDTH                          1  /* LOPLON */
+#define WM8400_LR12LOP                          0x0004  /* LR12LOP */
+#define WM8400_LR12LOP_MASK                     0x0004  /* LR12LOP */
+#define WM8400_LR12LOP_SHIFT                         2  /* LR12LOP */
+#define WM8400_LR12LOP_WIDTH                         1  /* LR12LOP */
+#define WM8400_LL12LOP                          0x0002  /* LL12LOP */
+#define WM8400_LL12LOP_MASK                     0x0002  /* LL12LOP */
+#define WM8400_LL12LOP_SHIFT                         1  /* LL12LOP */
+#define WM8400_LL12LOP_WIDTH                         1  /* LL12LOP */
+#define WM8400_LLOPGALOP                        0x0001  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_MASK                   0x0001  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_SHIFT                       0  /* LLOPGALOP */
+#define WM8400_LLOPGALOP_WIDTH                       1  /* LLOPGALOP */
+
+/*
+ * R53 (0x35) - Line Mixer2
+ */
+#define WM8400_RROPGARON                        0x0040  /* RROPGARON */
+#define WM8400_RROPGARON_MASK                   0x0040  /* RROPGARON */
+#define WM8400_RROPGARON_SHIFT                       6  /* RROPGARON */
+#define WM8400_RROPGARON_WIDTH                       1  /* RROPGARON */
+#define WM8400_RLOPGARON                        0x0020  /* RLOPGARON */
+#define WM8400_RLOPGARON_MASK                   0x0020  /* RLOPGARON */
+#define WM8400_RLOPGARON_SHIFT                       5  /* RLOPGARON */
+#define WM8400_RLOPGARON_WIDTH                       1  /* RLOPGARON */
+#define WM8400_ROPRON                           0x0010  /* ROPRON */
+#define WM8400_ROPRON_MASK                      0x0010  /* ROPRON */
+#define WM8400_ROPRON_SHIFT                          4  /* ROPRON */
+#define WM8400_ROPRON_WIDTH                          1  /* ROPRON */
+#define WM8400_RL12ROP                          0x0004  /* RL12ROP */
+#define WM8400_RL12ROP_MASK                     0x0004  /* RL12ROP */
+#define WM8400_RL12ROP_SHIFT                         2  /* RL12ROP */
+#define WM8400_RL12ROP_WIDTH                         1  /* RL12ROP */
+#define WM8400_RR12ROP                          0x0002  /* RR12ROP */
+#define WM8400_RR12ROP_MASK                     0x0002  /* RR12ROP */
+#define WM8400_RR12ROP_SHIFT                         1  /* RR12ROP */
+#define WM8400_RR12ROP_WIDTH                         1  /* RR12ROP */
+#define WM8400_RROPGAROP                        0x0001  /* RROPGAROP */
+#define WM8400_RROPGAROP_MASK                   0x0001  /* RROPGAROP */
+#define WM8400_RROPGAROP_SHIFT                       0  /* RROPGAROP */
+#define WM8400_RROPGAROP_WIDTH                       1  /* RROPGAROP */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8400_LB2SPK                           0x0080  /* LB2SPK */
+#define WM8400_LB2SPK_MASK                      0x0080  /* LB2SPK */
+#define WM8400_LB2SPK_SHIFT                          7  /* LB2SPK */
+#define WM8400_LB2SPK_WIDTH                          1  /* LB2SPK */
+#define WM8400_RB2SPK                           0x0040  /* RB2SPK */
+#define WM8400_RB2SPK_MASK                      0x0040  /* RB2SPK */
+#define WM8400_RB2SPK_SHIFT                          6  /* RB2SPK */
+#define WM8400_RB2SPK_WIDTH                          1  /* RB2SPK */
+#define WM8400_LI2SPK                           0x0020  /* LI2SPK */
+#define WM8400_LI2SPK_MASK                      0x0020  /* LI2SPK */
+#define WM8400_LI2SPK_SHIFT                          5  /* LI2SPK */
+#define WM8400_LI2SPK_WIDTH                          1  /* LI2SPK */
+#define WM8400_RI2SPK                           0x0010  /* RI2SPK */
+#define WM8400_RI2SPK_MASK                      0x0010  /* RI2SPK */
+#define WM8400_RI2SPK_SHIFT                          4  /* RI2SPK */
+#define WM8400_RI2SPK_WIDTH                          1  /* RI2SPK */
+#define WM8400_LOPGASPK                         0x0008  /* LOPGASPK */
+#define WM8400_LOPGASPK_MASK                    0x0008  /* LOPGASPK */
+#define WM8400_LOPGASPK_SHIFT                        3  /* LOPGASPK */
+#define WM8400_LOPGASPK_WIDTH                        1  /* LOPGASPK */
+#define WM8400_ROPGASPK                         0x0004  /* ROPGASPK */
+#define WM8400_ROPGASPK_MASK                    0x0004  /* ROPGASPK */
+#define WM8400_ROPGASPK_SHIFT                        2  /* ROPGASPK */
+#define WM8400_ROPGASPK_WIDTH                        1  /* ROPGASPK */
+#define WM8400_LDSPK                            0x0002  /* LDSPK */
+#define WM8400_LDSPK_MASK                       0x0002  /* LDSPK */
+#define WM8400_LDSPK_SHIFT                           1  /* LDSPK */
+#define WM8400_LDSPK_WIDTH                           1  /* LDSPK */
+#define WM8400_RDSPK                            0x0001  /* RDSPK */
+#define WM8400_RDSPK_MASK                       0x0001  /* RDSPK */
+#define WM8400_RDSPK_SHIFT                           0  /* RDSPK */
+#define WM8400_RDSPK_WIDTH                           1  /* RDSPK */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8400_VROI                             0x0001  /* VROI */
+#define WM8400_VROI_MASK                        0x0001  /* VROI */
+#define WM8400_VROI_SHIFT                            0  /* VROI */
+#define WM8400_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP1
+ */
+#define WM8400_DIS_LLINE                        0x0020  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_MASK                   0x0020  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_SHIFT                       5  /* DIS_LLINE */
+#define WM8400_DIS_LLINE_WIDTH                       1  /* DIS_LLINE */
+#define WM8400_DIS_RLINE                        0x0010  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_MASK                   0x0010  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_SHIFT                       4  /* DIS_RLINE */
+#define WM8400_DIS_RLINE_WIDTH                       1  /* DIS_RLINE */
+#define WM8400_DIS_OUT3                         0x0008  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_MASK                    0x0008  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_SHIFT                        3  /* DIS_OUT3 */
+#define WM8400_DIS_OUT3_WIDTH                        1  /* DIS_OUT3 */
+#define WM8400_DIS_OUT4                         0x0004  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_MASK                    0x0004  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_SHIFT                        2  /* DIS_OUT4 */
+#define WM8400_DIS_OUT4_WIDTH                        1  /* DIS_OUT4 */
+#define WM8400_DIS_LOUT                         0x0002  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_MASK                    0x0002  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_SHIFT                        1  /* DIS_LOUT */
+#define WM8400_DIS_LOUT_WIDTH                        1  /* DIS_LOUT */
+#define WM8400_DIS_ROUT                         0x0001  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_MASK                    0x0001  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_SHIFT                        0  /* DIS_ROUT */
+#define WM8400_DIS_ROUT_WIDTH                        1  /* DIS_ROUT */
+
+/*
+ * R57 (0x39) - AntiPOP2
+ */
+#define WM8400_SOFTST                           0x0040  /* SOFTST */
+#define WM8400_SOFTST_MASK                      0x0040  /* SOFTST */
+#define WM8400_SOFTST_SHIFT                          6  /* SOFTST */
+#define WM8400_SOFTST_WIDTH                          1  /* SOFTST */
+#define WM8400_BUFIOEN                          0x0008  /* BUFIOEN */
+#define WM8400_BUFIOEN_MASK                     0x0008  /* BUFIOEN */
+#define WM8400_BUFIOEN_SHIFT                         3  /* BUFIOEN */
+#define WM8400_BUFIOEN_WIDTH                         1  /* BUFIOEN */
+#define WM8400_BUFDCOPEN                        0x0004  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_MASK                   0x0004  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_SHIFT                       2  /* BUFDCOPEN */
+#define WM8400_BUFDCOPEN_WIDTH                       1  /* BUFDCOPEN */
+#define WM8400_POBCTRL                          0x0002  /* POBCTRL */
+#define WM8400_POBCTRL_MASK                     0x0002  /* POBCTRL */
+#define WM8400_POBCTRL_SHIFT                         1  /* POBCTRL */
+#define WM8400_POBCTRL_WIDTH                         1  /* POBCTRL */
+#define WM8400_VMIDTOG                          0x0001  /* VMIDTOG */
+#define WM8400_VMIDTOG_MASK                     0x0001  /* VMIDTOG */
+#define WM8400_VMIDTOG_SHIFT                         0  /* VMIDTOG */
+#define WM8400_VMIDTOG_WIDTH                         1  /* VMIDTOG */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8400_MCDSCTH_MASK                     0x00C0  /* MCDSCTH - [7:6] */
+#define WM8400_MCDSCTH_SHIFT                         6  /* MCDSCTH - [7:6] */
+#define WM8400_MCDSCTH_WIDTH                         2  /* MCDSCTH - [7:6] */
+#define WM8400_MCDTHR_MASK                      0x0038  /* MCDTHR - [5:3] */
+#define WM8400_MCDTHR_SHIFT                          3  /* MCDTHR - [5:3] */
+#define WM8400_MCDTHR_WIDTH                          3  /* MCDTHR - [5:3] */
+#define WM8400_MCD                              0x0004  /* MCD */
+#define WM8400_MCD_MASK                         0x0004  /* MCD */
+#define WM8400_MCD_SHIFT                             2  /* MCD */
+#define WM8400_MCD_WIDTH                             1  /* MCD */
+#define WM8400_MBSEL                            0x0001  /* MBSEL */
+#define WM8400_MBSEL_MASK                       0x0001  /* MBSEL */
+#define WM8400_MBSEL_SHIFT                           0  /* MBSEL */
+#define WM8400_MBSEL_WIDTH                           1  /* MBSEL */
+
+/*
+ * R60 (0x3C) - FLL Control 1
+ */
+#define WM8400_FLL_REF_FREQ                     0x1000  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_MASK                0x1000  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_SHIFT                   12  /* FLL_REF_FREQ */
+#define WM8400_FLL_REF_FREQ_WIDTH                    1  /* FLL_REF_FREQ */
+#define WM8400_FLL_CLK_SRC_MASK                 0x0C00  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_CLK_SRC_SHIFT                    10  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_CLK_SRC_WIDTH                     2  /* FLL_CLK_SRC - [11:10] */
+#define WM8400_FLL_FRAC                         0x0200  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_MASK                    0x0200  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_SHIFT                        9  /* FLL_FRAC */
+#define WM8400_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM8400_FLL_OSC_ENA                      0x0100  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_MASK                 0x0100  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_SHIFT                     8  /* FLL_OSC_ENA */
+#define WM8400_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM8400_FLL_CTRL_RATE_MASK               0x00E0  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_CTRL_RATE_SHIFT                   5  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_CTRL_RATE_WIDTH                   3  /* FLL_CTRL_RATE - [7:5] */
+#define WM8400_FLL_FRATIO_MASK                  0x001F  /* FLL_FRATIO - [4:0] */
+#define WM8400_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [4:0] */
+#define WM8400_FLL_FRATIO_WIDTH                      5  /* FLL_FRATIO - [4:0] */
+
+/*
+ * R61 (0x3D) - FLL Control 2
+ */
+#define WM8400_FLL_K_MASK                       0xFFFF  /* FLL_K - [15:0] */
+#define WM8400_FLL_K_SHIFT                           0  /* FLL_K - [15:0] */
+#define WM8400_FLL_K_WIDTH                          16  /* FLL_K - [15:0] */
+
+/*
+ * R62 (0x3E) - FLL Control 3
+ */
+#define WM8400_FLL_N_MASK                       0x03FF  /* FLL_N - [9:0] */
+#define WM8400_FLL_N_SHIFT                           0  /* FLL_N - [9:0] */
+#define WM8400_FLL_N_WIDTH                          10  /* FLL_N - [9:0] */
+
+/*
+ * R63 (0x3F) - FLL Control 4
+ */
+#define WM8400_FLL_TRK_GAIN_MASK                0x0078  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_TRK_GAIN_SHIFT                    3  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_TRK_GAIN_WIDTH                    4  /* FLL_TRK_GAIN - [6:3] */
+#define WM8400_FLL_OUTDIV_MASK                  0x0007  /* FLL_OUTDIV - [2:0] */
+#define WM8400_FLL_OUTDIV_SHIFT                      0  /* FLL_OUTDIV - [2:0] */
+#define WM8400_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [2:0] */
+
+void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400);
+
+#endif
diff --git a/include/linux/mfd/wm8400-private.h b/include/linux/mfd/wm8400-private.h
new file mode 100644 (file)
index 0000000..2aab4e9
--- /dev/null
@@ -0,0 +1,936 @@
+/*
+ * wm8400 private definitions.
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __LINUX_MFD_WM8400_PRIV_H
+#define __LINUX_MFD_WM8400_PRIV_H
+
+#include <linux/mfd/wm8400.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#define WM8400_REGISTER_COUNT 0x55
+
+struct wm8400 {
+       struct device *dev;
+
+       int (*read_dev)(void *data, char reg, int count, u16 *dst);
+       int (*write_dev)(void *data, char reg, int count, const u16 *src);
+
+       struct mutex io_lock;
+       void *io_data;
+
+       u16 reg_cache[WM8400_REGISTER_COUNT];
+
+       struct platform_device regulators[6];
+};
+
+/*
+ * Register values.
+ */
+#define WM8400_RESET_ID                         0x00
+#define WM8400_ID                               0x01
+#define WM8400_POWER_MANAGEMENT_1               0x02
+#define WM8400_POWER_MANAGEMENT_2               0x03
+#define WM8400_POWER_MANAGEMENT_3               0x04
+#define WM8400_AUDIO_INTERFACE_1                0x05
+#define WM8400_AUDIO_INTERFACE_2                0x06
+#define WM8400_CLOCKING_1                       0x07
+#define WM8400_CLOCKING_2                       0x08
+#define WM8400_AUDIO_INTERFACE_3                0x09
+#define WM8400_AUDIO_INTERFACE_4                0x0A
+#define WM8400_DAC_CTRL                         0x0B
+#define WM8400_LEFT_DAC_DIGITAL_VOLUME          0x0C
+#define WM8400_RIGHT_DAC_DIGITAL_VOLUME         0x0D
+#define WM8400_DIGITAL_SIDE_TONE                0x0E
+#define WM8400_ADC_CTRL                         0x0F
+#define WM8400_LEFT_ADC_DIGITAL_VOLUME          0x10
+#define WM8400_RIGHT_ADC_DIGITAL_VOLUME         0x11
+#define WM8400_GPIO_CTRL_1                      0x12
+#define WM8400_GPIO1_GPIO2                      0x13
+#define WM8400_GPIO3_GPIO4                      0x14
+#define WM8400_GPIO5_GPIO6                      0x15
+#define WM8400_GPIOCTRL_2                       0x16
+#define WM8400_GPIO_POL                         0x17
+#define WM8400_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8400_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8400_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8400_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8400_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8400_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8400_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8400_OUT3_4_VOLUME                    0x1F
+#define WM8400_LEFT_OPGA_VOLUME                 0x20
+#define WM8400_RIGHT_OPGA_VOLUME                0x21
+#define WM8400_SPEAKER_VOLUME                   0x22
+#define WM8400_CLASSD1                          0x23
+#define WM8400_CLASSD3                          0x25
+#define WM8400_INPUT_MIXER1                     0x27
+#define WM8400_INPUT_MIXER2                     0x28
+#define WM8400_INPUT_MIXER3                     0x29
+#define WM8400_INPUT_MIXER4                     0x2A
+#define WM8400_INPUT_MIXER5                     0x2B
+#define WM8400_INPUT_MIXER6                     0x2C
+#define WM8400_OUTPUT_MIXER1                    0x2D
+#define WM8400_OUTPUT_MIXER2                    0x2E
+#define WM8400_OUTPUT_MIXER3                    0x2F
+#define WM8400_OUTPUT_MIXER4                    0x30
+#define WM8400_OUTPUT_MIXER5                    0x31
+#define WM8400_OUTPUT_MIXER6                    0x32
+#define WM8400_OUT3_4_MIXER                     0x33
+#define WM8400_LINE_MIXER1                      0x34
+#define WM8400_LINE_MIXER2                      0x35
+#define WM8400_SPEAKER_MIXER                    0x36
+#define WM8400_ADDITIONAL_CONTROL               0x37
+#define WM8400_ANTIPOP1                         0x38
+#define WM8400_ANTIPOP2                         0x39
+#define WM8400_MICBIAS                          0x3A
+#define WM8400_FLL_CONTROL_1                    0x3C
+#define WM8400_FLL_CONTROL_2                    0x3D
+#define WM8400_FLL_CONTROL_3                    0x3E
+#define WM8400_FLL_CONTROL_4                    0x3F
+#define WM8400_LDO1_CONTROL                     0x41
+#define WM8400_LDO2_CONTROL                     0x42
+#define WM8400_LDO3_CONTROL                     0x43
+#define WM8400_LDO4_CONTROL                     0x44
+#define WM8400_DCDC1_CONTROL_1                  0x46
+#define WM8400_DCDC1_CONTROL_2                  0x47
+#define WM8400_DCDC2_CONTROL_1                  0x48
+#define WM8400_DCDC2_CONTROL_2                  0x49
+#define WM8400_INTERFACE                        0x4B
+#define WM8400_PM_GENERAL                       0x4C
+#define WM8400_PM_SHUTDOWN_CONTROL              0x4E
+#define WM8400_INTERRUPT_STATUS_1               0x4F
+#define WM8400_INTERRUPT_STATUS_1_MASK          0x50
+#define WM8400_INTERRUPT_LEVELS                 0x51
+#define WM8400_SHUTDOWN_REASON                  0x52
+#define WM8400_LINE_CIRCUITS                    0x54
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset/ID
+ */
+#define WM8400_SW_RESET_CHIP_ID_MASK            0xFFFF  /* SW_RESET/CHIP_ID - [15:0] */
+#define WM8400_SW_RESET_CHIP_ID_SHIFT                0  /* SW_RESET/CHIP_ID - [15:0] */
+#define WM8400_SW_RESET_CHIP_ID_WIDTH               16  /* SW_RESET/CHIP_ID - [15:0] */
+
+/*
+ * R1 (0x01) - ID
+ */
+#define WM8400_CHIP_REV_MASK                    0x7000  /* CHIP_REV - [14:12] */
+#define WM8400_CHIP_REV_SHIFT                       12  /* CHIP_REV - [14:12] */
+#define WM8400_CHIP_REV_WIDTH                        3  /* CHIP_REV - [14:12] */
+
+/*
+ * R18 (0x12) - GPIO CTRL 1
+ */
+#define WM8400_IRQ                              0x1000  /* IRQ */
+#define WM8400_IRQ_MASK                         0x1000  /* IRQ */
+#define WM8400_IRQ_SHIFT                            12  /* IRQ */
+#define WM8400_IRQ_WIDTH                             1  /* IRQ */
+#define WM8400_TEMPOK                           0x0800  /* TEMPOK */
+#define WM8400_TEMPOK_MASK                      0x0800  /* TEMPOK */
+#define WM8400_TEMPOK_SHIFT                         11  /* TEMPOK */
+#define WM8400_TEMPOK_WIDTH                          1  /* TEMPOK */
+#define WM8400_MIC1SHRT                         0x0400  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_MASK                    0x0400  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_SHIFT                       10  /* MIC1SHRT */
+#define WM8400_MIC1SHRT_WIDTH                        1  /* MIC1SHRT */
+#define WM8400_MIC1DET                          0x0200  /* MIC1DET */
+#define WM8400_MIC1DET_MASK                     0x0200  /* MIC1DET */
+#define WM8400_MIC1DET_SHIFT                         9  /* MIC1DET */
+#define WM8400_MIC1DET_WIDTH                         1  /* MIC1DET */
+#define WM8400_FLL_LCK                          0x0100  /* FLL_LCK */
+#define WM8400_FLL_LCK_MASK                     0x0100  /* FLL_LCK */
+#define WM8400_FLL_LCK_SHIFT                         8  /* FLL_LCK */
+#define WM8400_FLL_LCK_WIDTH                         1  /* FLL_LCK */
+#define WM8400_GPIO_STATUS_MASK                 0x00FF  /* GPIO_STATUS - [7:0] */
+#define WM8400_GPIO_STATUS_SHIFT                     0  /* GPIO_STATUS - [7:0] */
+#define WM8400_GPIO_STATUS_WIDTH                     8  /* GPIO_STATUS - [7:0] */
+
+/*
+ * R19 (0x13) - GPIO1 & GPIO2
+ */
+#define WM8400_GPIO2_DEB_ENA                    0x8000  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_MASK               0x8000  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_SHIFT                  15  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_DEB_ENA_WIDTH                   1  /* GPIO2_DEB_ENA */
+#define WM8400_GPIO2_IRQ_ENA                    0x4000  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_MASK               0x4000  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_SHIFT                  14  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_IRQ_ENA_WIDTH                   1  /* GPIO2_IRQ_ENA */
+#define WM8400_GPIO2_PU                         0x2000  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_MASK                    0x2000  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_SHIFT                       13  /* GPIO2_PU */
+#define WM8400_GPIO2_PU_WIDTH                        1  /* GPIO2_PU */
+#define WM8400_GPIO2_PD                         0x1000  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_MASK                    0x1000  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_SHIFT                       12  /* GPIO2_PD */
+#define WM8400_GPIO2_PD_WIDTH                        1  /* GPIO2_PD */
+#define WM8400_GPIO2_SEL_MASK                   0x0F00  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO2_SEL_SHIFT                       8  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO2_SEL_WIDTH                       4  /* GPIO2_SEL - [11:8] */
+#define WM8400_GPIO1_DEB_ENA                    0x0080  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_MASK               0x0080  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_SHIFT                   7  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_DEB_ENA_WIDTH                   1  /* GPIO1_DEB_ENA */
+#define WM8400_GPIO1_IRQ_ENA                    0x0040  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_MASK               0x0040  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_SHIFT                   6  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_IRQ_ENA_WIDTH                   1  /* GPIO1_IRQ_ENA */
+#define WM8400_GPIO1_PU                         0x0020  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_MASK                    0x0020  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_SHIFT                        5  /* GPIO1_PU */
+#define WM8400_GPIO1_PU_WIDTH                        1  /* GPIO1_PU */
+#define WM8400_GPIO1_PD                         0x0010  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_MASK                    0x0010  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_SHIFT                        4  /* GPIO1_PD */
+#define WM8400_GPIO1_PD_WIDTH                        1  /* GPIO1_PD */
+#define WM8400_GPIO1_SEL_MASK                   0x000F  /* GPIO1_SEL - [3:0] */
+#define WM8400_GPIO1_SEL_SHIFT                       0  /* GPIO1_SEL - [3:0] */
+#define WM8400_GPIO1_SEL_WIDTH                       4  /* GPIO1_SEL - [3:0] */
+
+/*
+ * R20 (0x14) - GPIO3 & GPIO4
+ */
+#define WM8400_GPIO4_DEB_ENA                    0x8000  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_MASK               0x8000  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_SHIFT                  15  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_DEB_ENA_WIDTH                   1  /* GPIO4_DEB_ENA */
+#define WM8400_GPIO4_IRQ_ENA                    0x4000  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_MASK               0x4000  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_SHIFT                  14  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_IRQ_ENA_WIDTH                   1  /* GPIO4_IRQ_ENA */
+#define WM8400_GPIO4_PU                         0x2000  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_MASK                    0x2000  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_SHIFT                       13  /* GPIO4_PU */
+#define WM8400_GPIO4_PU_WIDTH                        1  /* GPIO4_PU */
+#define WM8400_GPIO4_PD                         0x1000  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_MASK                    0x1000  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_SHIFT                       12  /* GPIO4_PD */
+#define WM8400_GPIO4_PD_WIDTH                        1  /* GPIO4_PD */
+#define WM8400_GPIO4_SEL_MASK                   0x0F00  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO4_SEL_SHIFT                       8  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO4_SEL_WIDTH                       4  /* GPIO4_SEL - [11:8] */
+#define WM8400_GPIO3_DEB_ENA                    0x0080  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_MASK               0x0080  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_SHIFT                   7  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_DEB_ENA_WIDTH                   1  /* GPIO3_DEB_ENA */
+#define WM8400_GPIO3_IRQ_ENA                    0x0040  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_MASK               0x0040  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_SHIFT                   6  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_IRQ_ENA_WIDTH                   1  /* GPIO3_IRQ_ENA */
+#define WM8400_GPIO3_PU                         0x0020  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_MASK                    0x0020  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_SHIFT                        5  /* GPIO3_PU */
+#define WM8400_GPIO3_PU_WIDTH                        1  /* GPIO3_PU */
+#define WM8400_GPIO3_PD                         0x0010  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_MASK                    0x0010  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_SHIFT                        4  /* GPIO3_PD */
+#define WM8400_GPIO3_PD_WIDTH                        1  /* GPIO3_PD */
+#define WM8400_GPIO3_SEL_MASK                   0x000F  /* GPIO3_SEL - [3:0] */
+#define WM8400_GPIO3_SEL_SHIFT                       0  /* GPIO3_SEL - [3:0] */
+#define WM8400_GPIO3_SEL_WIDTH                       4  /* GPIO3_SEL - [3:0] */
+
+/*
+ * R21 (0x15) - GPIO5 & GPIO6
+ */
+#define WM8400_GPIO6_DEB_ENA                    0x8000  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_MASK               0x8000  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_SHIFT                  15  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_DEB_ENA_WIDTH                   1  /* GPIO6_DEB_ENA */
+#define WM8400_GPIO6_IRQ_ENA                    0x4000  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_MASK               0x4000  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_SHIFT                  14  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_IRQ_ENA_WIDTH                   1  /* GPIO6_IRQ_ENA */
+#define WM8400_GPIO6_PU                         0x2000  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_MASK                    0x2000  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_SHIFT                       13  /* GPIO6_PU */
+#define WM8400_GPIO6_PU_WIDTH                        1  /* GPIO6_PU */
+#define WM8400_GPIO6_PD                         0x1000  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_MASK                    0x1000  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_SHIFT                       12  /* GPIO6_PD */
+#define WM8400_GPIO6_PD_WIDTH                        1  /* GPIO6_PD */
+#define WM8400_GPIO6_SEL_MASK                   0x0F00  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO6_SEL_SHIFT                       8  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO6_SEL_WIDTH                       4  /* GPIO6_SEL - [11:8] */
+#define WM8400_GPIO5_DEB_ENA                    0x0080  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_MASK               0x0080  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_SHIFT                   7  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_DEB_ENA_WIDTH                   1  /* GPIO5_DEB_ENA */
+#define WM8400_GPIO5_IRQ_ENA                    0x0040  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_MASK               0x0040  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_SHIFT                   6  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_IRQ_ENA_WIDTH                   1  /* GPIO5_IRQ_ENA */
+#define WM8400_GPIO5_PU                         0x0020  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_MASK                    0x0020  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_SHIFT                        5  /* GPIO5_PU */
+#define WM8400_GPIO5_PU_WIDTH                        1  /* GPIO5_PU */
+#define WM8400_GPIO5_PD                         0x0010  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_MASK                    0x0010  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_SHIFT                        4  /* GPIO5_PD */
+#define WM8400_GPIO5_PD_WIDTH                        1  /* GPIO5_PD */
+#define WM8400_GPIO5_SEL_MASK                   0x000F  /* GPIO5_SEL - [3:0] */
+#define WM8400_GPIO5_SEL_SHIFT                       0  /* GPIO5_SEL - [3:0] */
+#define WM8400_GPIO5_SEL_WIDTH                       4  /* GPIO5_SEL - [3:0] */
+
+/*
+ * R22 (0x16) - GPIOCTRL 2
+ */
+#define WM8400_TEMPOK_IRQ_ENA                   0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_MASK              0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_SHIFT                 11  /* TEMPOK_IRQ_ENA */
+#define WM8400_TEMPOK_IRQ_ENA_WIDTH                  1  /* TEMPOK_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA                 0x0400  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_MASK            0x0400  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_SHIFT               10  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1SHRT_IRQ_ENA_WIDTH                1  /* MIC1SHRT_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA                  0x0200  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_MASK             0x0200  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_SHIFT                 9  /* MIC1DET_IRQ_ENA */
+#define WM8400_MIC1DET_IRQ_ENA_WIDTH                 1  /* MIC1DET_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA                  0x0100  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_MASK             0x0100  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_SHIFT                 8  /* FLL_LCK_IRQ_ENA */
+#define WM8400_FLL_LCK_IRQ_ENA_WIDTH                 1  /* FLL_LCK_IRQ_ENA */
+#define WM8400_GPI8_DEB_ENA                     0x0080  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_MASK                0x0080  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_SHIFT                    7  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_DEB_ENA_WIDTH                    1  /* GPI8_DEB_ENA */
+#define WM8400_GPI8_IRQ_ENA                     0x0040  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_MASK                0x0040  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_SHIFT                    6  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_IRQ_ENA_WIDTH                    1  /* GPI8_IRQ_ENA */
+#define WM8400_GPI8_ENA                         0x0010  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_MASK                    0x0010  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_SHIFT                        4  /* GPI8_ENA */
+#define WM8400_GPI8_ENA_WIDTH                        1  /* GPI8_ENA */
+#define WM8400_GPI7_DEB_ENA                     0x0008  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_MASK                0x0008  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_SHIFT                    3  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_DEB_ENA_WIDTH                    1  /* GPI7_DEB_ENA */
+#define WM8400_GPI7_IRQ_ENA                     0x0004  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_MASK                0x0004  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_SHIFT                    2  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_IRQ_ENA_WIDTH                    1  /* GPI7_IRQ_ENA */
+#define WM8400_GPI7_ENA                         0x0001  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_MASK                    0x0001  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_SHIFT                        0  /* GPI7_ENA */
+#define WM8400_GPI7_ENA_WIDTH                        1  /* GPI7_ENA */
+
+/*
+ * R23 (0x17) - GPIO_POL
+ */
+#define WM8400_IRQ_INV                          0x1000  /* IRQ_INV */
+#define WM8400_IRQ_INV_MASK                     0x1000  /* IRQ_INV */
+#define WM8400_IRQ_INV_SHIFT                        12  /* IRQ_INV */
+#define WM8400_IRQ_INV_WIDTH                         1  /* IRQ_INV */
+#define WM8400_TEMPOK_POL                       0x0800  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_MASK                  0x0800  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_SHIFT                     11  /* TEMPOK_POL */
+#define WM8400_TEMPOK_POL_WIDTH                      1  /* TEMPOK_POL */
+#define WM8400_MIC1SHRT_POL                     0x0400  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_MASK                0x0400  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_SHIFT                   10  /* MIC1SHRT_POL */
+#define WM8400_MIC1SHRT_POL_WIDTH                    1  /* MIC1SHRT_POL */
+#define WM8400_MIC1DET_POL                      0x0200  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_MASK                 0x0200  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_SHIFT                     9  /* MIC1DET_POL */
+#define WM8400_MIC1DET_POL_WIDTH                     1  /* MIC1DET_POL */
+#define WM8400_FLL_LCK_POL                      0x0100  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_MASK                 0x0100  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_SHIFT                     8  /* FLL_LCK_POL */
+#define WM8400_FLL_LCK_POL_WIDTH                     1  /* FLL_LCK_POL */
+#define WM8400_GPIO_POL_MASK                    0x00FF  /* GPIO_POL - [7:0] */
+#define WM8400_GPIO_POL_SHIFT                        0  /* GPIO_POL - [7:0] */
+#define WM8400_GPIO_POL_WIDTH                        8  /* GPIO_POL - [7:0] */
+
+/*
+ * R65 (0x41) - LDO 1 Control
+ */
+#define WM8400_LDO1_ENA                         0x8000  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_MASK                    0x8000  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_SHIFT                       15  /* LDO1_ENA */
+#define WM8400_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
+#define WM8400_LDO1_SWI                         0x4000  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_MASK                    0x4000  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_SHIFT                       14  /* LDO1_SWI */
+#define WM8400_LDO1_SWI_WIDTH                        1  /* LDO1_SWI */
+#define WM8400_LDO1_OPFLT                       0x1000  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_MASK                  0x1000  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_SHIFT                     12  /* LDO1_OPFLT */
+#define WM8400_LDO1_OPFLT_WIDTH                      1  /* LDO1_OPFLT */
+#define WM8400_LDO1_ERRACT                      0x0800  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_MASK                 0x0800  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_SHIFT                    11  /* LDO1_ERRACT */
+#define WM8400_LDO1_ERRACT_WIDTH                     1  /* LDO1_ERRACT */
+#define WM8400_LDO1_HIB_MODE                    0x0400  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_MASK               0x0400  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_SHIFT                  10  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_HIB_MODE_WIDTH                   1  /* LDO1_HIB_MODE */
+#define WM8400_LDO1_VIMG_MASK                   0x03E0  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VIMG_SHIFT                       5  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VIMG_WIDTH                       5  /* LDO1_VIMG - [9:5] */
+#define WM8400_LDO1_VSEL_MASK                   0x001F  /* LDO1_VSEL - [4:0] */
+#define WM8400_LDO1_VSEL_SHIFT                       0  /* LDO1_VSEL - [4:0] */
+#define WM8400_LDO1_VSEL_WIDTH                       5  /* LDO1_VSEL - [4:0] */
+
+/*
+ * R66 (0x42) - LDO 2 Control
+ */
+#define WM8400_LDO2_ENA                         0x8000  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_MASK                    0x8000  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_SHIFT                       15  /* LDO2_ENA */
+#define WM8400_LDO2_ENA_WIDTH                        1  /* LDO2_ENA */
+#define WM8400_LDO2_SWI                         0x4000  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_MASK                    0x4000  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_SHIFT                       14  /* LDO2_SWI */
+#define WM8400_LDO2_SWI_WIDTH                        1  /* LDO2_SWI */
+#define WM8400_LDO2_OPFLT                       0x1000  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_MASK                  0x1000  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_SHIFT                     12  /* LDO2_OPFLT */
+#define WM8400_LDO2_OPFLT_WIDTH                      1  /* LDO2_OPFLT */
+#define WM8400_LDO2_ERRACT                      0x0800  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_MASK                 0x0800  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_SHIFT                    11  /* LDO2_ERRACT */
+#define WM8400_LDO2_ERRACT_WIDTH                     1  /* LDO2_ERRACT */
+#define WM8400_LDO2_HIB_MODE                    0x0400  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_MASK               0x0400  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_SHIFT                  10  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_HIB_MODE_WIDTH                   1  /* LDO2_HIB_MODE */
+#define WM8400_LDO2_VIMG_MASK                   0x03E0  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VIMG_SHIFT                       5  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VIMG_WIDTH                       5  /* LDO2_VIMG - [9:5] */
+#define WM8400_LDO2_VSEL_MASK                   0x001F  /* LDO2_VSEL - [4:0] */
+#define WM8400_LDO2_VSEL_SHIFT                       0  /* LDO2_VSEL - [4:0] */
+#define WM8400_LDO2_VSEL_WIDTH                       5  /* LDO2_VSEL - [4:0] */
+
+/*
+ * R67 (0x43) - LDO 3 Control
+ */
+#define WM8400_LDO3_ENA                         0x8000  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_MASK                    0x8000  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_SHIFT                       15  /* LDO3_ENA */
+#define WM8400_LDO3_ENA_WIDTH                        1  /* LDO3_ENA */
+#define WM8400_LDO3_SWI                         0x4000  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_MASK                    0x4000  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_SHIFT                       14  /* LDO3_SWI */
+#define WM8400_LDO3_SWI_WIDTH                        1  /* LDO3_SWI */
+#define WM8400_LDO3_OPFLT                       0x1000  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_MASK                  0x1000  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_SHIFT                     12  /* LDO3_OPFLT */
+#define WM8400_LDO3_OPFLT_WIDTH                      1  /* LDO3_OPFLT */
+#define WM8400_LDO3_ERRACT                      0x0800  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_MASK                 0x0800  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_SHIFT                    11  /* LDO3_ERRACT */
+#define WM8400_LDO3_ERRACT_WIDTH                     1  /* LDO3_ERRACT */
+#define WM8400_LDO3_HIB_MODE                    0x0400  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_MASK               0x0400  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_SHIFT                  10  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_HIB_MODE_WIDTH                   1  /* LDO3_HIB_MODE */
+#define WM8400_LDO3_VIMG_MASK                   0x03E0  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VIMG_SHIFT                       5  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VIMG_WIDTH                       5  /* LDO3_VIMG - [9:5] */
+#define WM8400_LDO3_VSEL_MASK                   0x001F  /* LDO3_VSEL - [4:0] */
+#define WM8400_LDO3_VSEL_SHIFT                       0  /* LDO3_VSEL - [4:0] */
+#define WM8400_LDO3_VSEL_WIDTH                       5  /* LDO3_VSEL - [4:0] */
+
+/*
+ * R68 (0x44) - LDO 4 Control
+ */
+#define WM8400_LDO4_ENA                         0x8000  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_MASK                    0x8000  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_SHIFT                       15  /* LDO4_ENA */
+#define WM8400_LDO4_ENA_WIDTH                        1  /* LDO4_ENA */
+#define WM8400_LDO4_SWI                         0x4000  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_MASK                    0x4000  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_SHIFT                       14  /* LDO4_SWI */
+#define WM8400_LDO4_SWI_WIDTH                        1  /* LDO4_SWI */
+#define WM8400_LDO4_OPFLT                       0x1000  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_MASK                  0x1000  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_SHIFT                     12  /* LDO4_OPFLT */
+#define WM8400_LDO4_OPFLT_WIDTH                      1  /* LDO4_OPFLT */
+#define WM8400_LDO4_ERRACT                      0x0800  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_MASK                 0x0800  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_SHIFT                    11  /* LDO4_ERRACT */
+#define WM8400_LDO4_ERRACT_WIDTH                     1  /* LDO4_ERRACT */
+#define WM8400_LDO4_HIB_MODE                    0x0400  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_MASK               0x0400  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_SHIFT                  10  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_HIB_MODE_WIDTH                   1  /* LDO4_HIB_MODE */
+#define WM8400_LDO4_VIMG_MASK                   0x03E0  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VIMG_SHIFT                       5  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VIMG_WIDTH                       5  /* LDO4_VIMG - [9:5] */
+#define WM8400_LDO4_VSEL_MASK                   0x001F  /* LDO4_VSEL - [4:0] */
+#define WM8400_LDO4_VSEL_SHIFT                       0  /* LDO4_VSEL - [4:0] */
+#define WM8400_LDO4_VSEL_WIDTH                       5  /* LDO4_VSEL - [4:0] */
+
+/*
+ * R70 (0x46) - DCDC1 Control 1
+ */
+#define WM8400_DC1_ENA                          0x8000  /* DC1_ENA */
+#define WM8400_DC1_ENA_MASK                     0x8000  /* DC1_ENA */
+#define WM8400_DC1_ENA_SHIFT                        15  /* DC1_ENA */
+#define WM8400_DC1_ENA_WIDTH                         1  /* DC1_ENA */
+#define WM8400_DC1_ACTIVE                       0x4000  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_MASK                  0x4000  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_SHIFT                     14  /* DC1_ACTIVE */
+#define WM8400_DC1_ACTIVE_WIDTH                      1  /* DC1_ACTIVE */
+#define WM8400_DC1_SLEEP                        0x2000  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_MASK                   0x2000  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_SHIFT                      13  /* DC1_SLEEP */
+#define WM8400_DC1_SLEEP_WIDTH                       1  /* DC1_SLEEP */
+#define WM8400_DC1_OPFLT                        0x1000  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_MASK                   0x1000  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_SHIFT                      12  /* DC1_OPFLT */
+#define WM8400_DC1_OPFLT_WIDTH                       1  /* DC1_OPFLT */
+#define WM8400_DC1_ERRACT                       0x0800  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_MASK                  0x0800  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_SHIFT                     11  /* DC1_ERRACT */
+#define WM8400_DC1_ERRACT_WIDTH                      1  /* DC1_ERRACT */
+#define WM8400_DC1_HIB_MODE                     0x0400  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_MASK                0x0400  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_SHIFT                   10  /* DC1_HIB_MODE */
+#define WM8400_DC1_HIB_MODE_WIDTH                    1  /* DC1_HIB_MODE */
+#define WM8400_DC1_SOFTST_MASK                  0x0300  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_SOFTST_SHIFT                      8  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_SOFTST_WIDTH                      2  /* DC1_SOFTST - [9:8] */
+#define WM8400_DC1_OV_PROT                      0x0080  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_MASK                 0x0080  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_SHIFT                     7  /* DC1_OV_PROT */
+#define WM8400_DC1_OV_PROT_WIDTH                     1  /* DC1_OV_PROT */
+#define WM8400_DC1_VSEL_MASK                    0x007F  /* DC1_VSEL - [6:0] */
+#define WM8400_DC1_VSEL_SHIFT                        0  /* DC1_VSEL - [6:0] */
+#define WM8400_DC1_VSEL_WIDTH                        7  /* DC1_VSEL - [6:0] */
+
+/*
+ * R71 (0x47) - DCDC1 Control 2
+ */
+#define WM8400_DC1_FRC_PWM                      0x2000  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_MASK                 0x2000  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_SHIFT                    13  /* DC1_FRC_PWM */
+#define WM8400_DC1_FRC_PWM_WIDTH                     1  /* DC1_FRC_PWM */
+#define WM8400_DC1_STBY_LIM_MASK                0x0300  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_STBY_LIM_SHIFT                    8  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_STBY_LIM_WIDTH                    2  /* DC1_STBY_LIM - [9:8] */
+#define WM8400_DC1_ACT_LIM                      0x0080  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_MASK                 0x0080  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_SHIFT                     7  /* DC1_ACT_LIM */
+#define WM8400_DC1_ACT_LIM_WIDTH                     1  /* DC1_ACT_LIM */
+#define WM8400_DC1_VIMG_MASK                    0x007F  /* DC1_VIMG - [6:0] */
+#define WM8400_DC1_VIMG_SHIFT                        0  /* DC1_VIMG - [6:0] */
+#define WM8400_DC1_VIMG_WIDTH                        7  /* DC1_VIMG - [6:0] */
+
+/*
+ * R72 (0x48) - DCDC2 Control 1
+ */
+#define WM8400_DC2_ENA                          0x8000  /* DC2_ENA */
+#define WM8400_DC2_ENA_MASK                     0x8000  /* DC2_ENA */
+#define WM8400_DC2_ENA_SHIFT                        15  /* DC2_ENA */
+#define WM8400_DC2_ENA_WIDTH                         1  /* DC2_ENA */
+#define WM8400_DC2_ACTIVE                       0x4000  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_MASK                  0x4000  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_SHIFT                     14  /* DC2_ACTIVE */
+#define WM8400_DC2_ACTIVE_WIDTH                      1  /* DC2_ACTIVE */
+#define WM8400_DC2_SLEEP                        0x2000  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_MASK                   0x2000  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_SHIFT                      13  /* DC2_SLEEP */
+#define WM8400_DC2_SLEEP_WIDTH                       1  /* DC2_SLEEP */
+#define WM8400_DC2_OPFLT                        0x1000  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_MASK                   0x1000  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_SHIFT                      12  /* DC2_OPFLT */
+#define WM8400_DC2_OPFLT_WIDTH                       1  /* DC2_OPFLT */
+#define WM8400_DC2_ERRACT                       0x0800  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_MASK                  0x0800  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_SHIFT                     11  /* DC2_ERRACT */
+#define WM8400_DC2_ERRACT_WIDTH                      1  /* DC2_ERRACT */
+#define WM8400_DC2_HIB_MODE                     0x0400  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_MASK                0x0400  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_SHIFT                   10  /* DC2_HIB_MODE */
+#define WM8400_DC2_HIB_MODE_WIDTH                    1  /* DC2_HIB_MODE */
+#define WM8400_DC2_SOFTST_MASK                  0x0300  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_SOFTST_SHIFT                      8  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_SOFTST_WIDTH                      2  /* DC2_SOFTST - [9:8] */
+#define WM8400_DC2_OV_PROT                      0x0080  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_MASK                 0x0080  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_SHIFT                     7  /* DC2_OV_PROT */
+#define WM8400_DC2_OV_PROT_WIDTH                     1  /* DC2_OV_PROT */
+#define WM8400_DC2_VSEL_MASK                    0x007F  /* DC2_VSEL - [6:0] */
+#define WM8400_DC2_VSEL_SHIFT                        0  /* DC2_VSEL - [6:0] */
+#define WM8400_DC2_VSEL_WIDTH                        7  /* DC2_VSEL - [6:0] */
+
+/*
+ * R73 (0x49) - DCDC2 Control 2
+ */
+#define WM8400_DC2_FRC_PWM                      0x2000  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_MASK                 0x2000  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_SHIFT                    13  /* DC2_FRC_PWM */
+#define WM8400_DC2_FRC_PWM_WIDTH                     1  /* DC2_FRC_PWM */
+#define WM8400_DC2_STBY_LIM_MASK                0x0300  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_STBY_LIM_SHIFT                    8  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_STBY_LIM_WIDTH                    2  /* DC2_STBY_LIM - [9:8] */
+#define WM8400_DC2_ACT_LIM                      0x0080  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_MASK                 0x0080  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_SHIFT                     7  /* DC2_ACT_LIM */
+#define WM8400_DC2_ACT_LIM_WIDTH                     1  /* DC2_ACT_LIM */
+#define WM8400_DC2_VIMG_MASK                    0x007F  /* DC2_VIMG - [6:0] */
+#define WM8400_DC2_VIMG_SHIFT                        0  /* DC2_VIMG - [6:0] */
+#define WM8400_DC2_VIMG_WIDTH                        7  /* DC2_VIMG - [6:0] */
+
+/*
+ * R75 (0x4B) - Interface
+ */
+#define WM8400_AUTOINC                          0x0008  /* AUTOINC */
+#define WM8400_AUTOINC_MASK                     0x0008  /* AUTOINC */
+#define WM8400_AUTOINC_SHIFT                         3  /* AUTOINC */
+#define WM8400_AUTOINC_WIDTH                         1  /* AUTOINC */
+#define WM8400_ARA_ENA                          0x0004  /* ARA_ENA */
+#define WM8400_ARA_ENA_MASK                     0x0004  /* ARA_ENA */
+#define WM8400_ARA_ENA_SHIFT                         2  /* ARA_ENA */
+#define WM8400_ARA_ENA_WIDTH                         1  /* ARA_ENA */
+#define WM8400_SPI_CFG                          0x0002  /* SPI_CFG */
+#define WM8400_SPI_CFG_MASK                     0x0002  /* SPI_CFG */
+#define WM8400_SPI_CFG_SHIFT                         1  /* SPI_CFG */
+#define WM8400_SPI_CFG_WIDTH                         1  /* SPI_CFG */
+
+/*
+ * R76 (0x4C) - PM GENERAL
+ */
+#define WM8400_CODEC_SOFTST                     0x8000  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_MASK                0x8000  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_SHIFT                   15  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTST_WIDTH                    1  /* CODEC_SOFTST */
+#define WM8400_CODEC_SOFTSD                     0x4000  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_MASK                0x4000  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_SHIFT                   14  /* CODEC_SOFTSD */
+#define WM8400_CODEC_SOFTSD_WIDTH                    1  /* CODEC_SOFTSD */
+#define WM8400_CHIP_SOFTSD                      0x2000  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_MASK                 0x2000  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_SHIFT                    13  /* CHIP_SOFTSD */
+#define WM8400_CHIP_SOFTSD_WIDTH                     1  /* CHIP_SOFTSD */
+#define WM8400_DSLEEP1_POL                      0x0008  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_MASK                 0x0008  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_SHIFT                     3  /* DSLEEP1_POL */
+#define WM8400_DSLEEP1_POL_WIDTH                     1  /* DSLEEP1_POL */
+#define WM8400_DSLEEP2_POL                      0x0004  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_MASK                 0x0004  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_SHIFT                     2  /* DSLEEP2_POL */
+#define WM8400_DSLEEP2_POL_WIDTH                     1  /* DSLEEP2_POL */
+#define WM8400_PWR_STATE_MASK                   0x0003  /* PWR_STATE - [1:0] */
+#define WM8400_PWR_STATE_SHIFT                       0  /* PWR_STATE - [1:0] */
+#define WM8400_PWR_STATE_WIDTH                       2  /* PWR_STATE - [1:0] */
+
+/*
+ * R78 (0x4E) - PM Shutdown Control
+ */
+#define WM8400_CHIP_GT150_ERRACT                0x0200  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_MASK           0x0200  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_SHIFT               9  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT150_ERRACT_WIDTH               1  /* CHIP_GT150_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT                0x0100  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_MASK           0x0100  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_SHIFT               8  /* CHIP_GT115_ERRACT */
+#define WM8400_CHIP_GT115_ERRACT_WIDTH               1  /* CHIP_GT115_ERRACT */
+#define WM8400_LINE_CMP_ERRACT                  0x0080  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_MASK             0x0080  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_SHIFT                 7  /* LINE_CMP_ERRACT */
+#define WM8400_LINE_CMP_ERRACT_WIDTH                 1  /* LINE_CMP_ERRACT */
+#define WM8400_UVLO_ERRACT                      0x0040  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_MASK                 0x0040  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_SHIFT                     6  /* UVLO_ERRACT */
+#define WM8400_UVLO_ERRACT_WIDTH                     1  /* UVLO_ERRACT */
+
+/*
+ * R79 (0x4F) - Interrupt Status 1
+ */
+#define WM8400_MICD_CINT                        0x8000  /* MICD_CINT */
+#define WM8400_MICD_CINT_MASK                   0x8000  /* MICD_CINT */
+#define WM8400_MICD_CINT_SHIFT                      15  /* MICD_CINT */
+#define WM8400_MICD_CINT_WIDTH                       1  /* MICD_CINT */
+#define WM8400_MICSCD_CINT                      0x4000  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_MASK                 0x4000  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_SHIFT                    14  /* MICSCD_CINT */
+#define WM8400_MICSCD_CINT_WIDTH                     1  /* MICSCD_CINT */
+#define WM8400_JDL_CINT                         0x2000  /* JDL_CINT */
+#define WM8400_JDL_CINT_MASK                    0x2000  /* JDL_CINT */
+#define WM8400_JDL_CINT_SHIFT                       13  /* JDL_CINT */
+#define WM8400_JDL_CINT_WIDTH                        1  /* JDL_CINT */
+#define WM8400_JDR_CINT                         0x1000  /* JDR_CINT */
+#define WM8400_JDR_CINT_MASK                    0x1000  /* JDR_CINT */
+#define WM8400_JDR_CINT_SHIFT                       12  /* JDR_CINT */
+#define WM8400_JDR_CINT_WIDTH                        1  /* JDR_CINT */
+#define WM8400_CODEC_SEQ_END_EINT               0x0800  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_MASK          0x0800  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_SHIFT             11  /* CODEC_SEQ_END_EINT */
+#define WM8400_CODEC_SEQ_END_EINT_WIDTH              1  /* CODEC_SEQ_END_EINT */
+#define WM8400_CDEL_TO_EINT                     0x0400  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_MASK                0x0400  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_SHIFT                   10  /* CDEL_TO_EINT */
+#define WM8400_CDEL_TO_EINT_WIDTH                    1  /* CDEL_TO_EINT */
+#define WM8400_CHIP_GT150_EINT                  0x0200  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_MASK             0x0200  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_SHIFT                 9  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT150_EINT_WIDTH                 1  /* CHIP_GT150_EINT */
+#define WM8400_CHIP_GT115_EINT                  0x0100  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_MASK             0x0100  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_SHIFT                 8  /* CHIP_GT115_EINT */
+#define WM8400_CHIP_GT115_EINT_WIDTH                 1  /* CHIP_GT115_EINT */
+#define WM8400_LINE_CMP_EINT                    0x0080  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_MASK               0x0080  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_SHIFT                   7  /* LINE_CMP_EINT */
+#define WM8400_LINE_CMP_EINT_WIDTH                   1  /* LINE_CMP_EINT */
+#define WM8400_UVLO_EINT                        0x0040  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_MASK                   0x0040  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_SHIFT                       6  /* UVLO_EINT */
+#define WM8400_UVLO_EINT_WIDTH                       1  /* UVLO_EINT */
+#define WM8400_DC2_UV_EINT                      0x0020  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_MASK                 0x0020  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_SHIFT                     5  /* DC2_UV_EINT */
+#define WM8400_DC2_UV_EINT_WIDTH                     1  /* DC2_UV_EINT */
+#define WM8400_DC1_UV_EINT                      0x0010  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_MASK                 0x0010  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_SHIFT                     4  /* DC1_UV_EINT */
+#define WM8400_DC1_UV_EINT_WIDTH                     1  /* DC1_UV_EINT */
+#define WM8400_LDO4_UV_EINT                     0x0008  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_MASK                0x0008  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_SHIFT                    3  /* LDO4_UV_EINT */
+#define WM8400_LDO4_UV_EINT_WIDTH                    1  /* LDO4_UV_EINT */
+#define WM8400_LDO3_UV_EINT                     0x0004  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_MASK                0x0004  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_SHIFT                    2  /* LDO3_UV_EINT */
+#define WM8400_LDO3_UV_EINT_WIDTH                    1  /* LDO3_UV_EINT */
+#define WM8400_LDO2_UV_EINT                     0x0002  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_MASK                0x0002  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_SHIFT                    1  /* LDO2_UV_EINT */
+#define WM8400_LDO2_UV_EINT_WIDTH                    1  /* LDO2_UV_EINT */
+#define WM8400_LDO1_UV_EINT                     0x0001  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_MASK                0x0001  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_SHIFT                    0  /* LDO1_UV_EINT */
+#define WM8400_LDO1_UV_EINT_WIDTH                    1  /* LDO1_UV_EINT */
+
+/*
+ * R80 (0x50) - Interrupt Status 1 Mask
+ */
+#define WM8400_IM_MICD_CINT                     0x8000  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_MASK                0x8000  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_SHIFT                   15  /* IM_MICD_CINT */
+#define WM8400_IM_MICD_CINT_WIDTH                    1  /* IM_MICD_CINT */
+#define WM8400_IM_MICSCD_CINT                   0x4000  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_MASK              0x4000  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_SHIFT                 14  /* IM_MICSCD_CINT */
+#define WM8400_IM_MICSCD_CINT_WIDTH                  1  /* IM_MICSCD_CINT */
+#define WM8400_IM_JDL_CINT                      0x2000  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_MASK                 0x2000  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_SHIFT                    13  /* IM_JDL_CINT */
+#define WM8400_IM_JDL_CINT_WIDTH                     1  /* IM_JDL_CINT */
+#define WM8400_IM_JDR_CINT                      0x1000  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_MASK                 0x1000  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_SHIFT                    12  /* IM_JDR_CINT */
+#define WM8400_IM_JDR_CINT_WIDTH                     1  /* IM_JDR_CINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT            0x0800  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_MASK       0x0800  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_SHIFT          11  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CODEC_SEQ_END_EINT_WIDTH           1  /* IM_CODEC_SEQ_END_EINT */
+#define WM8400_IM_CDEL_TO_EINT                  0x0400  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_MASK             0x0400  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_SHIFT                10  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CDEL_TO_EINT_WIDTH                 1  /* IM_CDEL_TO_EINT */
+#define WM8400_IM_CHIP_GT150_EINT               0x0200  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_MASK          0x0200  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_SHIFT              9  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT150_EINT_WIDTH              1  /* IM_CHIP_GT150_EINT */
+#define WM8400_IM_CHIP_GT115_EINT               0x0100  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_MASK          0x0100  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_SHIFT              8  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_CHIP_GT115_EINT_WIDTH              1  /* IM_CHIP_GT115_EINT */
+#define WM8400_IM_LINE_CMP_EINT                 0x0080  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_MASK            0x0080  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_SHIFT                7  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_LINE_CMP_EINT_WIDTH                1  /* IM_LINE_CMP_EINT */
+#define WM8400_IM_UVLO_EINT                     0x0040  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_MASK                0x0040  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_SHIFT                    6  /* IM_UVLO_EINT */
+#define WM8400_IM_UVLO_EINT_WIDTH                    1  /* IM_UVLO_EINT */
+#define WM8400_IM_DC2_UV_EINT                   0x0020  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_MASK              0x0020  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_SHIFT                  5  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC2_UV_EINT_WIDTH                  1  /* IM_DC2_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT                   0x0010  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_MASK              0x0010  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_SHIFT                  4  /* IM_DC1_UV_EINT */
+#define WM8400_IM_DC1_UV_EINT_WIDTH                  1  /* IM_DC1_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT                  0x0008  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_MASK             0x0008  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_SHIFT                 3  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO4_UV_EINT_WIDTH                 1  /* IM_LDO4_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT                  0x0004  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_MASK             0x0004  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_SHIFT                 2  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO3_UV_EINT_WIDTH                 1  /* IM_LDO3_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT                  0x0002  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_MASK             0x0002  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_SHIFT                 1  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO2_UV_EINT_WIDTH                 1  /* IM_LDO2_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT                  0x0001  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_MASK             0x0001  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_SHIFT                 0  /* IM_LDO1_UV_EINT */
+#define WM8400_IM_LDO1_UV_EINT_WIDTH                 1  /* IM_LDO1_UV_EINT */
+
+/*
+ * R81 (0x51) - Interrupt Levels
+ */
+#define WM8400_MICD_LVL                         0x8000  /* MICD_LVL */
+#define WM8400_MICD_LVL_MASK                    0x8000  /* MICD_LVL */
+#define WM8400_MICD_LVL_SHIFT                       15  /* MICD_LVL */
+#define WM8400_MICD_LVL_WIDTH                        1  /* MICD_LVL */
+#define WM8400_MICSCD_LVL                       0x4000  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_MASK                  0x4000  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_SHIFT                     14  /* MICSCD_LVL */
+#define WM8400_MICSCD_LVL_WIDTH                      1  /* MICSCD_LVL */
+#define WM8400_JDL_LVL                          0x2000  /* JDL_LVL */
+#define WM8400_JDL_LVL_MASK                     0x2000  /* JDL_LVL */
+#define WM8400_JDL_LVL_SHIFT                        13  /* JDL_LVL */
+#define WM8400_JDL_LVL_WIDTH                         1  /* JDL_LVL */
+#define WM8400_JDR_LVL                          0x1000  /* JDR_LVL */
+#define WM8400_JDR_LVL_MASK                     0x1000  /* JDR_LVL */
+#define WM8400_JDR_LVL_SHIFT                        12  /* JDR_LVL */
+#define WM8400_JDR_LVL_WIDTH                         1  /* JDR_LVL */
+#define WM8400_CODEC_SEQ_END_LVL                0x0800  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_MASK           0x0800  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_SHIFT              11  /* CODEC_SEQ_END_LVL */
+#define WM8400_CODEC_SEQ_END_LVL_WIDTH               1  /* CODEC_SEQ_END_LVL */
+#define WM8400_CDEL_TO_LVL                      0x0400  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_MASK                 0x0400  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_SHIFT                    10  /* CDEL_TO_LVL */
+#define WM8400_CDEL_TO_LVL_WIDTH                     1  /* CDEL_TO_LVL */
+#define WM8400_CHIP_GT150_LVL                   0x0200  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_MASK              0x0200  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_SHIFT                  9  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT150_LVL_WIDTH                  1  /* CHIP_GT150_LVL */
+#define WM8400_CHIP_GT115_LVL                   0x0100  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_MASK              0x0100  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_SHIFT                  8  /* CHIP_GT115_LVL */
+#define WM8400_CHIP_GT115_LVL_WIDTH                  1  /* CHIP_GT115_LVL */
+#define WM8400_LINE_CMP_LVL                     0x0080  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_MASK                0x0080  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_SHIFT                    7  /* LINE_CMP_LVL */
+#define WM8400_LINE_CMP_LVL_WIDTH                    1  /* LINE_CMP_LVL */
+#define WM8400_UVLO_LVL                         0x0040  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_MASK                    0x0040  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_SHIFT                        6  /* UVLO_LVL */
+#define WM8400_UVLO_LVL_WIDTH                        1  /* UVLO_LVL */
+#define WM8400_DC2_UV_LVL                       0x0020  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_MASK                  0x0020  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_SHIFT                      5  /* DC2_UV_LVL */
+#define WM8400_DC2_UV_LVL_WIDTH                      1  /* DC2_UV_LVL */
+#define WM8400_DC1_UV_LVL                       0x0010  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_MASK                  0x0010  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_SHIFT                      4  /* DC1_UV_LVL */
+#define WM8400_DC1_UV_LVL_WIDTH                      1  /* DC1_UV_LVL */
+#define WM8400_LDO4_UV_LVL                      0x0008  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_MASK                 0x0008  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_SHIFT                     3  /* LDO4_UV_LVL */
+#define WM8400_LDO4_UV_LVL_WIDTH                     1  /* LDO4_UV_LVL */
+#define WM8400_LDO3_UV_LVL                      0x0004  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_MASK                 0x0004  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_SHIFT                     2  /* LDO3_UV_LVL */
+#define WM8400_LDO3_UV_LVL_WIDTH                     1  /* LDO3_UV_LVL */
+#define WM8400_LDO2_UV_LVL                      0x0002  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_MASK                 0x0002  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_SHIFT                     1  /* LDO2_UV_LVL */
+#define WM8400_LDO2_UV_LVL_WIDTH                     1  /* LDO2_UV_LVL */
+#define WM8400_LDO1_UV_LVL                      0x0001  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_MASK                 0x0001  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_SHIFT                     0  /* LDO1_UV_LVL */
+#define WM8400_LDO1_UV_LVL_WIDTH                     1  /* LDO1_UV_LVL */
+
+/*
+ * R82 (0x52) - Shutdown Reason
+ */
+#define WM8400_SDR_CHIP_SOFTSD                  0x2000  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_MASK             0x2000  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_SHIFT                13  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_CHIP_SOFTSD_WIDTH                 1  /* SDR_CHIP_SOFTSD */
+#define WM8400_SDR_NPDN                         0x0800  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_MASK                    0x0800  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_SHIFT                       11  /* SDR_NPDN */
+#define WM8400_SDR_NPDN_WIDTH                        1  /* SDR_NPDN */
+#define WM8400_SDR_CHIP_GT150                   0x0200  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_MASK              0x0200  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_SHIFT                  9  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT150_WIDTH                  1  /* SDR_CHIP_GT150 */
+#define WM8400_SDR_CHIP_GT115                   0x0100  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_MASK              0x0100  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_SHIFT                  8  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_CHIP_GT115_WIDTH                  1  /* SDR_CHIP_GT115 */
+#define WM8400_SDR_LINE_CMP                     0x0080  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_MASK                0x0080  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_SHIFT                    7  /* SDR_LINE_CMP */
+#define WM8400_SDR_LINE_CMP_WIDTH                    1  /* SDR_LINE_CMP */
+#define WM8400_SDR_UVLO                         0x0040  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_MASK                    0x0040  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_SHIFT                        6  /* SDR_UVLO */
+#define WM8400_SDR_UVLO_WIDTH                        1  /* SDR_UVLO */
+#define WM8400_SDR_DC2_UV                       0x0020  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_MASK                  0x0020  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_SHIFT                      5  /* SDR_DC2_UV */
+#define WM8400_SDR_DC2_UV_WIDTH                      1  /* SDR_DC2_UV */
+#define WM8400_SDR_DC1_UV                       0x0010  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_MASK                  0x0010  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_SHIFT                      4  /* SDR_DC1_UV */
+#define WM8400_SDR_DC1_UV_WIDTH                      1  /* SDR_DC1_UV */
+#define WM8400_SDR_LDO4_UV                      0x0008  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_MASK                 0x0008  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_SHIFT                     3  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO4_UV_WIDTH                     1  /* SDR_LDO4_UV */
+#define WM8400_SDR_LDO3_UV                      0x0004  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_MASK                 0x0004  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_SHIFT                     2  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO3_UV_WIDTH                     1  /* SDR_LDO3_UV */
+#define WM8400_SDR_LDO2_UV                      0x0002  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_MASK                 0x0002  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_SHIFT                     1  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO2_UV_WIDTH                     1  /* SDR_LDO2_UV */
+#define WM8400_SDR_LDO1_UV                      0x0001  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_MASK                 0x0001  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_SHIFT                     0  /* SDR_LDO1_UV */
+#define WM8400_SDR_LDO1_UV_WIDTH                     1  /* SDR_LDO1_UV */
+
+/*
+ * R84 (0x54) - Line Circuits
+ */
+#define WM8400_BG_LINE_COMP                     0x8000  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_MASK                0x8000  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_SHIFT                   15  /* BG_LINE_COMP */
+#define WM8400_BG_LINE_COMP_WIDTH                    1  /* BG_LINE_COMP */
+#define WM8400_LINE_CMP_VTHI_MASK               0x00F0  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHI_SHIFT                   4  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHI_WIDTH                   4  /* LINE_CMP_VTHI - [7:4] */
+#define WM8400_LINE_CMP_VTHD_MASK               0x000F  /* LINE_CMP_VTHD - [3:0] */
+#define WM8400_LINE_CMP_VTHD_SHIFT                   0  /* LINE_CMP_VTHD - [3:0] */
+#define WM8400_LINE_CMP_VTHD_WIDTH                   4  /* LINE_CMP_VTHD - [3:0] */
+
+u16 wm8400_reg_read(struct wm8400 *wm8400, u8 reg);
+int wm8400_block_read(struct wm8400 *wm8400, u8 reg, int count, u16 *data);
+int wm8400_set_bits(struct wm8400 *wm8400, u8 reg, u16 mask, u16 val);
+
+#endif
diff --git a/include/linux/mfd/wm8400.h b/include/linux/mfd/wm8400.h
new file mode 100644 (file)
index 0000000..b46b566
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * wm8400 client interface
+ *
+ * Copyright 2008 Wolfson Microelectronics plc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __LINUX_MFD_WM8400_H
+#define __LINUX_MFD_WM8400_H
+
+#include <linux/regulator/machine.h>
+
+#define WM8400_LDO1  0
+#define WM8400_LDO2  1
+#define WM8400_LDO3  2
+#define WM8400_LDO4  3
+#define WM8400_DCDC1 4
+#define WM8400_DCDC2 5
+
+struct wm8400_platform_data {
+       int (*platform_init)(struct device *dev);
+};
+
+int wm8400_register_regulator(struct device *dev, int reg,
+                             struct regulator_init_data *initdata);
+
+#endif
index c4db5827963d98a5624ec1c8fb637ad959903a75..eb71b45fdf5af411b42aad9b89ae808c1b19d8e8 100644 (file)
@@ -131,6 +131,16 @@ struct usb_device_id {
 #define USB_DEVICE_ID_MATCH_INT_SUBCLASS       0x0100
 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL       0x0200
 
+#define HID_ANY_ID                             (~0)
+
+struct hid_device_id {
+       __u16 bus;
+       __u32 vendor;
+       __u32 product;
+       kernel_ulong_t driver_data
+               __attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
 /* s390 CCW devices */
 struct ccw_device_id {
        __u16   match_flags;    /* which fields to match against */
@@ -274,7 +284,7 @@ struct pcmcia_device_id {
 /* Input */
 #define INPUT_DEVICE_ID_EV_MAX         0x1f
 #define INPUT_DEVICE_ID_KEY_MIN_INTERESTING    0x71
-#define INPUT_DEVICE_ID_KEY_MAX                0x1ff
+#define INPUT_DEVICE_ID_KEY_MAX                0x2ff
 #define INPUT_DEVICE_ID_REL_MAX                0x0f
 #define INPUT_DEVICE_ID_ABS_MAX                0x3f
 #define INPUT_DEVICE_ID_MSC_MAX                0x07
@@ -388,5 +398,52 @@ struct i2c_device_id {
                        __attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
+/* dmi */
+enum dmi_field {
+       DMI_NONE,
+       DMI_BIOS_VENDOR,
+       DMI_BIOS_VERSION,
+       DMI_BIOS_DATE,
+       DMI_SYS_VENDOR,
+       DMI_PRODUCT_NAME,
+       DMI_PRODUCT_VERSION,
+       DMI_PRODUCT_SERIAL,
+       DMI_PRODUCT_UUID,
+       DMI_BOARD_VENDOR,
+       DMI_BOARD_NAME,
+       DMI_BOARD_VERSION,
+       DMI_BOARD_SERIAL,
+       DMI_BOARD_ASSET_TAG,
+       DMI_CHASSIS_VENDOR,
+       DMI_CHASSIS_TYPE,
+       DMI_CHASSIS_VERSION,
+       DMI_CHASSIS_SERIAL,
+       DMI_CHASSIS_ASSET_TAG,
+       DMI_STRING_MAX,
+};
+
+struct dmi_strmatch {
+       unsigned char slot;
+       char substr[79];
+};
+
+#ifndef __KERNEL__
+struct dmi_system_id {
+       kernel_ulong_t callback;
+       kernel_ulong_t ident;
+       struct dmi_strmatch matches[4];
+       kernel_ulong_t driver_data
+                       __attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+#else
+struct dmi_system_id {
+       int (*callback)(const struct dmi_system_id *);
+       const char *ident;
+       struct dmi_strmatch matches[4];
+       void *driver_data;
+};
+#endif
+
+#define DMI_MATCH(a, b)        { a, b }
 
 #endif /* LINUX_MOD_DEVICETABLE_H */
index 68e09557c9511ab31da394afd80a58decad3ee71..a41555cbe00ae071a02dab3c88b3c57bf6c38d4b 100644 (file)
@@ -345,7 +345,6 @@ struct module
        /* Reference counts */
        struct module_ref ref[NR_CPUS];
 #endif
-
 };
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
index 30a1d63b6fb5cb37574935ff33c121c6526d111d..cab2a85e2ee82f556cf1515eb14bd6d88ad344b0 100644 (file)
@@ -5,8 +5,6 @@
  *
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
- * Version: $Id: mount.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
- *
  */
 #ifndef _LINUX_MOUNT_H
 #define _LINUX_MOUNT_H
index d3ea3de70a8a54afde98014602504ebd48437624..64875859d6542ffc0a40b23f371a586074d5292e 100644 (file)
@@ -11,7 +11,7 @@
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Corey Minyard <wf-rch!minyard@relay.EU.net>
  *             Donald J. Becker, <becker@cesdis.gsfc.nasa.gov>
- *             Alan Cox, <Alan.Cox@linux.org>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *             Bjorn Ekwall. <bj0rn@blox.se>
  *              Pekka Riikonen <priikone@poseidon.pspt.fi>
  *
index 0d8424f76899f11d5c96dce8d525c1f54fbe4b1a..7d8e0455ccacb101e79cb9e6a940ccf7f5c41615 100644 (file)
@@ -78,6 +78,9 @@ extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group,
                          int echo);
 extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags);
 
+extern void nfnl_lock(void);
+extern void nfnl_unlock(void);
+
 #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \
        MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys))
 
index 78a5922a2f111dc7d08b8d7d5bef59c2511cef15..ac8d0233b05c00650498f92750a1b0b8db994239 100644 (file)
@@ -137,7 +137,7 @@ struct nfs_inode {
        unsigned long           attrtimeo_timestamp;
        __u64                   change_attr;            /* v4 only */
 
-       unsigned long           last_updated;
+       unsigned long           attr_gencount;
        /* "Generation counter" for the attribute cache. This is
         * bumped whenever we update the metadata on the
         * server.
@@ -200,11 +200,10 @@ struct nfs_inode {
 /*
  * Bit offsets in flags field
  */
-#define NFS_INO_REVALIDATING   (0)             /* revalidating attrs */
-#define NFS_INO_ADVISE_RDPLUS  (1)             /* advise readdirplus */
-#define NFS_INO_STALE          (2)             /* possible stale inode */
-#define NFS_INO_ACL_LRU_SET    (3)             /* Inode is on the LRU list */
-#define NFS_INO_MOUNTPOINT     (4)             /* inode is remote mountpoint */
+#define NFS_INO_ADVISE_RDPLUS  (0)             /* advise readdirplus */
+#define NFS_INO_STALE          (1)             /* possible stale inode */
+#define NFS_INO_ACL_LRU_SET    (2)             /* Inode is on the LRU list */
+#define NFS_INO_MOUNTPOINT     (3)             /* inode is remote mountpoint */
 
 static inline struct nfs_inode *NFS_I(const struct inode *inode)
 {
@@ -345,15 +344,11 @@ extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ct
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
 extern u64 nfs_compat_user_ino64(u64 fileid);
+extern void nfs_fattr_init(struct nfs_fattr *fattr);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-
-static inline void nfs_fattr_init(struct nfs_fattr *fattr)
-{
-       fattr->valid = 0;
-       fattr->time_start = jiffies;
-}
+extern unsigned long nfs_inc_attr_generation_counter(void);
 
 /*
  * linux/fs/nfs/file.c
index c9beacd16c0073545a3518bb3f1ccabacbf5d6cf..4e477ae58699b59a3e4a011bb5447ccce1d5bc4b 100644 (file)
@@ -119,7 +119,6 @@ struct nfs_server {
        void (*destroy)(struct nfs_server *);
 
        atomic_t active; /* Keep trace of any activity to this server */
-       wait_queue_head_t active_wq;  /* Wait for any activity to stop  */
 
        /* mountd-related mount options */
        struct sockaddr_storage mountd_address;
index df7c6b7a7ebb1bfbe84e33bb85fb2f045492e10a..6549a06ac16e352c4333509fd1531f1135c122ec 100644 (file)
@@ -65,4 +65,8 @@ struct nfs_mount_data {
 #define NFS_MOUNT_UNSHARED     0x8000  /* 5 */
 #define NFS_MOUNT_FLAGMASK     0xFFFF
 
+/* The following are for internal use only */
+#define NFS_MOUNT_LOOKUP_CACHE_NONEG   0x10000
+#define NFS_MOUNT_LOOKUP_CACHE_NONE    0x20000
+
 #endif
index 8c77c11224d1e0b009d6250b8789287d5a628b35..c1c31acb8a2b97608f55902de126fbdf0b0ddd64 100644 (file)
@@ -36,6 +36,7 @@ struct nfs_fattr {
        __u32                   nlink;
        __u32                   uid;
        __u32                   gid;
+       dev_t                   rdev;
        __u64                   size;
        union {
                struct {
@@ -46,7 +47,6 @@ struct nfs_fattr {
                        __u64   used;
                } nfs3;
        } du;
-       dev_t                   rdev;
        struct nfs_fsid         fsid;
        __u64                   fileid;
        struct timespec         atime;
@@ -56,6 +56,7 @@ struct nfs_fattr {
        __u64                   change_attr;    /* NFSv4 change attribute */
        __u64                   pre_change_attr;/* pre-op NFSv4 change attribute */
        unsigned long           time_start;
+       unsigned long           gencount;
 };
 
 #define NFS_ATTR_WCC           0x0001          /* pre-op WCC data    */
@@ -672,16 +673,16 @@ struct nfs4_rename_res {
        struct nfs_fattr *              new_fattr;
 };
 
-#define NFS4_SETCLIENTID_NAMELEN       (56)
+#define NFS4_SETCLIENTID_NAMELEN       (127)
 struct nfs4_setclientid {
        const nfs4_verifier *           sc_verifier;
        unsigned int                    sc_name_len;
-       char                            sc_name[NFS4_SETCLIENTID_NAMELEN];
+       char                            sc_name[NFS4_SETCLIENTID_NAMELEN + 1];
        u32                             sc_prog;
        unsigned int                    sc_netid_len;
-       char                            sc_netid[RPCBIND_MAXNETIDLEN];
+       char                            sc_netid[RPCBIND_MAXNETIDLEN + 1];
        unsigned int                    sc_uaddr_len;
-       char                            sc_uaddr[RPCBIND_MAXUADDRLEN];
+       char                            sc_uaddr[RPCBIND_MAXUADDRLEN + 1];
        u32                             sc_cb_ident;
 };
 
index 108f47e5fd9511796516d758dca90b1232321bea..21269405ffe27a503209dbb096293221dee65231 100644 (file)
@@ -38,6 +38,7 @@
 #define NFSD_MAY_LOCK          32
 #define NFSD_MAY_OWNER_OVERRIDE        64
 #define NFSD_MAY_LOCAL_ACCESS  128 /* IRIX doing local access check on device special file*/
+#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
 
 #define NFSD_MAY_CREATE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
 #define NFSD_MAY_REMOVE                (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
@@ -125,7 +126,7 @@ int         nfsd_truncate(struct svc_rqst *, struct svc_fh *,
 __be32         nfsd_readdir(struct svc_rqst *, struct svc_fh *,
                             loff_t *, struct readdir_cd *, filldir_t);
 __be32         nfsd_statfs(struct svc_rqst *, struct svc_fh *,
-                               struct kstatfs *);
+                               struct kstatfs *, int access);
 
 int            nfsd_notify_change(struct inode *, struct iattr *);
 __be32         nfsd_permission(struct svc_rqst *, struct svc_export *,
index 79886ade070f2e791274c92814bc04bfbcff4947..e2488f5e7cb2bfc4ab275b1a2685bba103713205 100644 (file)
@@ -71,5 +71,8 @@ extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
        const struct of_device_id *matches, const struct device_node *node);
 extern int of_modalias_node(struct device_node *node, char *modalias, int len);
+extern int of_parse_phandles_with_args(struct device_node *np,
+       const char *list_name, const char *cells_name, int index,
+       struct device_node **out_node, const void **out_args);
 
 #endif /* _LINUX_OF_H */
index 041bb31100f48fd780b9505cf21842be36cdb68f..bcb8f725427c4868a6f4e6461a1ee720ed8b793c 100644 (file)
@@ -36,6 +36,8 @@
 #define XEN_ENTER_SWITCH_CODE          10
 #define SPU_PROFILING_CODE             11
 #define SPU_CTX_SWITCH_CODE            12
+#define IBS_FETCH_CODE                 13
+#define IBS_OP_CODE                    14
 
 struct super_block;
 struct dentry;
index 6a0d7cdb577465a84bf5ccf3ef8ff0b86edc4002..e1f83c5065c5e2ad4e4a92f4fa9908939c6f7e0c 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: parport.h,v 1.1 1998/05/17 10:57:52 andrea Exp andrea $ */
-
 /*
  * Any part of this program may be used in documents licensed under
  * the GNU Free Documentation License, Version 1.1 or any later version
index 7dcd050757567eb94265fb12b29d6f79e5cbcb3f..ea2281e726f65f5f2968eb571adc874843530959 100644 (file)
@@ -25,7 +25,7 @@ typedef struct {
        char *to;
 } substring_t;
 
-int match_token(char *, match_table_t table, substring_t args[]);
+int match_token(char *, const match_table_t table, substring_t args[]);
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
index f63b5455801caca2a66fa4d9b2618a74f66a6859..8edddc240e4f61c133308d9af0af7da179b9c56b 100644 (file)
 #define PCI_DEVICE_ID_MATROX_G200_PCI  0x0520
 #define PCI_DEVICE_ID_MATROX_G200_AGP  0x0521
 #define        PCI_DEVICE_ID_MATROX_G400       0x0525
+#define        PCI_DEVICE_ID_MATROX_G200EV_PCI 0x0530
 #define PCI_DEVICE_ID_MATROX_G550      0x2527
 #define PCI_DEVICE_ID_MATROX_VIA       0x4536
 
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
-#define PCI_DEVICE_ID_MARVELL_CAFE_SD  0x4101
+#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND     0x4100
+#define PCI_DEVICE_ID_MARVELL_88ALP01_SD       0x4101
+#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC     0x4102
 
 #define PCI_VENDOR_ID_V3               0x11b0
 #define PCI_DEVICE_ID_V3_V960          0x0001
index bb01f8b92b56208bf7b433d842f7d0821647e691..7646637221f3ac45b0e2f9381fd733950b6ff492 100644 (file)
@@ -1,9 +1,13 @@
 #ifndef _LINUX_PFN_H_
 #define _LINUX_PFN_H_
 
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#endif
+
 #define PFN_ALIGN(x)   (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
 #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
+#define PFN_PHYS(x)    ((phys_addr_t)(x) << PAGE_SHIFT)
 
 #endif
index 1af82c4e17d4e79a14d1854b35fd39ef93bdb649..d82fe825d62f9571fe6412700d854a326f5d8c4c 100644 (file)
@@ -84,12 +84,6 @@ static inline struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
        return tsk->nsproxy->pid_ns;
 }
 
-static inline struct task_struct *task_child_reaper(struct task_struct *tsk)
-{
-       BUG_ON(tsk != current);
-       return tsk->nsproxy->pid_ns->child_reaper;
-}
-
 void pidhash_init(void);
 void pidmap_init(void);
 
index 95ac21ab3a092369f5f41537614eb9890161d70e..4b8cc6a324797682d08e487d314cb4ce647e2d7c 100644 (file)
@@ -37,6 +37,8 @@ extern int platform_add_devices(struct platform_device **, int);
 
 extern struct platform_device *platform_device_register_simple(const char *, int id,
                                        struct resource *, unsigned int);
+extern struct platform_device *platform_device_register_data(struct device *,
+               const char *, int, const void *, size_t);
 
 extern struct platform_device *platform_device_alloc(const char *name, int id);
 extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
index 4dcce54b6d76f798e11f3e3ae08032ee0fbac592..42de4003c4ee10a52599ea95d7ae9d53964a0bf9 100644 (file)
@@ -419,7 +419,7 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
 
 #define suspend_report_result(fn, ret)                                 \
        do {                                                            \
-               __suspend_report_result(__FUNCTION__, fn, ret);         \
+               __suspend_report_result(__func__, fn, ret);             \
        } while (0)
 
 #else /* !CONFIG_PM_SLEEP */
index be764e514e35946eeced5615440769912da9e0fa..53b70fd1d9a535d92639a66757646ce5620e21f9 100644 (file)
@@ -22,9 +22,11 @@ struct pnp_dev;
  * Resource Management
  */
 #ifdef CONFIG_PNP
-struct resource *pnp_get_resource(struct pnp_dev *, unsigned int, unsigned int);
+struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned long type,
+                               unsigned int num);
 #else
-static inline struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned int type, unsigned int num)
+static inline struct resource *pnp_get_resource(struct pnp_dev *dev,
+                       unsigned long type, unsigned int num)
 {
        return NULL;
 }
index fb61850d1cfcf7b04352c6fa2a9d12c6c91e77f0..27d534f4470d2350cc7cd563e813e5b88ba25c37 100644 (file)
@@ -139,7 +139,6 @@ extern int proc_readdir(struct file *, void *, filldir_t);
 extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 extern const struct file_operations proc_kcore_operations;
-extern const struct file_operations ppc_htab_operations;
 
 extern int pid_ns_prepare_proc(struct pid_namespace *ns);
 extern void pid_ns_release_proc(struct pid_namespace *ns);
index 7e7087239af5fc0497ebf40bf92d65cb99b5749f..570045053ce9bf04bbda46d21a97feb3b76dadb2 100644 (file)
@@ -35,7 +35,9 @@ enum profile_type {
 extern int prof_on __read_mostly;
 
 /* init basic kernel profiler */
-void __init profile_init(void);
+int profile_init(void);
+int profile_setup(char *str);
+int create_proc_profile(void);
 void profile_tick(int type);
 
 /*
@@ -84,9 +86,9 @@ struct pt_regs;
 
 #define prof_on 0
 
-static inline void profile_init(void)
+static inline int profile_init(void)
 {
-       return;
+       return 0;
 }
 
 static inline void profile_tick(int type)
index 376a05048bc580650bd1923c9f21c6e3852cea11..40401b554484ceeafec0ca395097424f99acc2e9 100644 (file)
@@ -28,8 +28,6 @@
  * 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.
- *
- * Version: $Id: quota.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
  */
 
 #ifndef _LINUX_QUOTA_
index ca6b9b5c8d5271b430a534fe59969a09af85c997..a558a4c1d35a2a10eea7d0017fc5326133b8faf4 100644 (file)
@@ -3,9 +3,6 @@
  * macros expand to the right source-code.
  *
  * Author:  Marco van Wieringen <mvw@planets.elm.net>
- *
- * Version: $Id: quotaops.h,v 1.2 1998/01/15 16:22:26 ecd Exp $
- *
  */
 #ifndef _LINUX_QUOTAOPS_
 #define _LINUX_QUOTAOPS_
index 7e375111d0074b390136c56cdca76a1ce6bb5d3c..f38b9c586afbc38c2a3187ac479735b14ad5fffb 100644 (file)
@@ -5,8 +5,8 @@
 
 struct dev_info {
        mdk_rdev_t      *rdev;
-       sector_t        size;
-       sector_t        offset;
+       sector_t        num_sectors;
+       sector_t        start_sector;
 };
 
 typedef struct dev_info dev_info_t;
@@ -15,9 +15,11 @@ struct linear_private_data
 {
        struct linear_private_data *prev;       /* earlier version */
        dev_info_t              **hash_table;
-       sector_t                hash_spacing;
+       sector_t                spacing;
        sector_t                array_sectors;
-       int                     preshift; /* shift before dividing by hash_spacing */
+       int                     sector_shift;   /* shift before dividing
+                                                * by spacing
+                                                */
        dev_info_t              disks[0];
 };
 
index dc0e3fcb9f281b15bc9d0f040ce38a42191a4ea5..82bea14cae1a7a948aafe1a1a1329aa1a9e6037d 100644 (file)
 #define _MD_H
 
 #include <linux/blkdev.h>
-#include <linux/major.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/module.h>
-#include <linux/hdreg.h>
-#include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
-#include <linux/delay.h>
-#include <net/checksum.h>
-#include <linux/random.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <linux/completion.h>
-#include <linux/mempool.h>
-#include <linux/list.h>
-#include <linux/reboot.h>
-#include <linux/vmalloc.h>
-#include <linux/blkpg.h>
-#include <linux/bio.h>
 
 /*
  * 'md_p.h' holds the 'physical' layout of RAID devices
 
 extern int mdp_major;
 
-extern int register_md_personality (struct mdk_personality *p);
-extern int unregister_md_personality (struct mdk_personality *p);
-extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
+extern int register_md_personality(struct mdk_personality *p);
+extern int unregister_md_personality(struct mdk_personality *p);
+extern mdk_thread_t * md_register_thread(void (*run) (mddev_t *mddev),
                                mddev_t *mddev, const char *name);
-extern void md_unregister_thread (mdk_thread_t *thread);
+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_write_start(mddev_t *mddev, struct bio *bi);
 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_error (mddev_t *mddev, mdk_rdev_t *rdev);
-extern void md_unplug_mddev(mddev_t *mddev);
+extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
 
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
                           sector_t sector, int size, struct page *page);
index 1d712c7172a234094b95a24923e7706672ae591a..e37d80561985df64f9497e0aa26a4718e5c24ab5 100644 (file)
@@ -18,8 +18,8 @@
 #include <linux/device.h>
 #include <linux/regulator/consumer.h>
 
-struct regulator_constraints;
 struct regulator_dev;
+struct regulator_init_data;
 
 /**
  * struct regulator_ops - regulator operations.
@@ -51,7 +51,7 @@ struct regulator_ops {
                                          int output_uV, int load_uA);
 
        /* the operations below are for configuration of regulator state when
-        * it's parent PMIC enters a global STANBY/HIBERNATE state */
+        * its parent PMIC enters a global STANDBY/HIBERNATE state */
 
        /* set regulator suspend voltage */
        int (*set_suspend_voltage) (struct regulator_dev *, int uV);
@@ -85,15 +85,17 @@ struct regulator_desc {
        struct module *owner;
 };
 
-
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-                                         void *reg_data);
+       struct device *dev, void *driver_data);
 void regulator_unregister(struct regulator_dev *rdev);
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
 
 void *rdev_get_drvdata(struct regulator_dev *rdev);
+struct device *rdev_get_dev(struct regulator_dev *rdev);
 int rdev_get_id(struct regulator_dev *rdev);
 
+void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
+
 #endif
index 11e737dbfcf21d32fd29cd1c561e03be2c1c373f..c6d69331a81ef4c78fd6dd6797307d3388cb0a41 100644 (file)
@@ -89,15 +89,33 @@ struct regulation_constraints {
        unsigned apply_uV:1;    /* apply uV constraint iff min == max */
 };
 
-int regulator_set_supply(const char *regulator, const char *regulator_supply);
+/**
+ * struct regulator_consumer_supply - supply -> device mapping
+ *
+ * This maps a supply name to a device.
+ */
+struct regulator_consumer_supply {
+       struct device *dev;     /* consumer */
+       const char *supply;     /* consumer supply - e.g. "vcc" */
+};
 
-const char *regulator_get_supply(const char *regulator);
+/**
+ * struct regulator_init_data - regulator platform initialisation data.
+ *
+ * Initialisation constraints, our supply and consumers supplies.
+ */
+struct regulator_init_data {
+       struct device *supply_regulator_dev; /* or NULL for LINE */
 
-int regulator_set_machine_constraints(const char *regulator,
-       struct regulation_constraints *constraints);
+       struct regulation_constraints constraints;
 
-int regulator_set_device_supply(const char *regulator, struct device *dev,
-                               const char *supply);
+       int num_consumer_supplies;
+       struct regulator_consumer_supply *consumer_supplies;
+
+       /* optional regulator machine specific init */
+       int (*regulator_init)(void *driver_data);
+       void *driver_data;      /* core does not touch this */
+};
 
 int regulator_suspend_prepare(suspend_state_t state);
 
index e9963af16cda6ade6ede6dded784c2624f4bc449..bc5114d35e99b65db4e11acefe3bae623a7c9db9 100644 (file)
@@ -87,7 +87,7 @@ void reiserfs_warning(struct super_block *s, const char *fmt, ...);
 if( !( cond ) )                                                                \
   reiserfs_panic( NULL, "reiserfs[%i]: assertion " scond " failed at " \
                  __FILE__ ":%i:%s: " format "\n",              \
-                 in_interrupt() ? -1 : task_pid_nr(current), __LINE__ , __FUNCTION__ , ##args )
+                 in_interrupt() ? -1 : task_pid_nr(current), __LINE__ , __func__ , ##args )
 
 #define RASSERT(cond, format, args...) __RASSERT(cond, #cond, format, ##args)
 
index 382bb7951166ec649e7113c4d2eac86194e7ad78..f19b00b7d530a8e60f67e77c5f1c5ac5270e8d9b 100644 (file)
@@ -54,7 +54,7 @@ struct hrtimer_sleeper;
 #ifdef CONFIG_DEBUG_RT_MUTEXES
 # define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
        , .name = #mutexname, .file = __FILE__, .line = __LINE__
-# define rt_mutex_init(mutex)                  __rt_mutex_init(mutex, __FUNCTION__)
+# define rt_mutex_init(mutex)                  __rt_mutex_init(mutex, __func__)
  extern void rt_mutex_debug_task_free(struct task_struct *tsk);
 #else
 # define __DEBUG_RT_MUTEX_INITIALIZER(mutexname)
index deb714314fb169de39bf195921c01b2a7e8085a6..1ea8d9265bf67c5bc52d1a43b2557d9ae661c2df 100644 (file)
@@ -173,6 +173,22 @@ struct serial_icounter_struct {
        int reserved[9];
 };
 
+/*
+ * Serial interface for controlling RS485 settings on chips with suitable
+ * support. Set with TIOCSRS485 and get with TIOCGRS485 if supported by your
+ * platform. The set function returns the new state, with any unsupported bits
+ * reverted appropriately.
+ */
+
+struct serial_rs485 {
+       __u32   flags;                  /* RS485 feature flags */
+#define SER_RS485_ENABLED              (1 << 0)
+#define SER_RS485_RTS_ON_SEND          (1 << 1)
+#define SER_RS485_RTS_AFTER_SEND       (1 << 2)
+       __u32   delay_rts_before_send;  /* Milliseconds */
+       __u32   padding[6];             /* Memory is cheap, new structs
+                                          are a royal PITA .. */
+};
 
 #ifdef __KERNEL__
 #include <linux/compiler.h>
index 3b2f6c04855e73d0ea300803c13970729e9b2989..e27f216361fc1511f6fc6b52d7570536af95a9e6 100644 (file)
@@ -241,7 +241,7 @@ typedef unsigned int __bitwise__ upf_t;
 
 struct uart_port {
        spinlock_t              lock;                   /* port lock */
-       unsigned int            iobase;                 /* in/out[bwl] */
+       unsigned long           iobase;                 /* in/out[bwl] */
        unsigned char __iomem   *membase;               /* read/write[bwl] */
        unsigned int            irq;                    /* irq number */
        unsigned int            uartclk;                /* base uart clock */
index b4d9fa6f797cdd4653334315664a86a27ec081f1..decf6d8c77b7fa7d3a297653708566bb0bdf9d95 100644 (file)
@@ -11,6 +11,7 @@
 
 struct orion_spi_info {
        u32     tclk;           /* no <linux/clk.h> support yet */
+       u32     enable_clock_fix;
 };
 
 
index e5bfe01ee305feb20e70845fb7e7f14e108bd345..6f0ee1b84a4f5f64903f4c74af1004381c3d9dd1 100644 (file)
@@ -104,6 +104,7 @@ struct rpc_create_args {
        const struct rpc_timeout *timeout;
        char                    *servername;
        struct rpc_program      *program;
+       u32                     prognumber;     /* overrides program->number */
        u32                     version;
        rpc_authflavor_t        authflavor;
        unsigned long           flags;
@@ -124,10 +125,10 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 void           rpc_shutdown_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
 
-int            rpcb_register(u32, u32, int, unsigned short, int *);
+int            rpcb_register(u32, u32, int, unsigned short);
 int            rpcb_v4_register(const u32 program, const u32 version,
                                 const struct sockaddr *address,
-                                const char *netid, int *result);
+                                const char *netid);
 int            rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
 void           rpcb_getport_async(struct rpc_task *);
 
index dc69068d94c7e070c9c9758c17efd8eb7d0ccb5f..3afe7fb403b2733877a199485e4c804a8fc116ef 100644 (file)
@@ -66,6 +66,7 @@ struct svc_serv {
        struct list_head        sv_tempsocks;   /* all temporary sockets */
        int                     sv_tmpcnt;      /* count of temporary sockets */
        struct timer_list       sv_temptimer;   /* timer for aging temporary sockets */
+       sa_family_t             sv_family;      /* listener's address family */
 
        char *                  sv_name;        /* service name */
 
@@ -265,17 +266,17 @@ struct svc_rqst {
 /*
  * Rigorous type checking on sockaddr type conversions
  */
-static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
+static inline struct sockaddr_in *svc_addr_in(const struct svc_rqst *rqst)
 {
        return (struct sockaddr_in *) &rqst->rq_addr;
 }
 
-static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst)
+static inline struct sockaddr_in6 *svc_addr_in6(const struct svc_rqst *rqst)
 {
        return (struct sockaddr_in6 *) &rqst->rq_addr;
 }
 
-static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
+static inline struct sockaddr *svc_addr(const struct svc_rqst *rqst)
 {
        return (struct sockaddr *) &rqst->rq_addr;
 }
@@ -381,18 +382,20 @@ struct svc_procedure {
 /*
  * Function prototypes.
  */
-struct svc_serv *  svc_create(struct svc_program *, unsigned int,
-                             void (*shutdown)(struct svc_serv*));
+struct svc_serv *svc_create(struct svc_program *, unsigned int, sa_family_t,
+                           void (*shutdown)(struct svc_serv *));
 struct svc_rqst *svc_prepare_thread(struct svc_serv *serv,
                                        struct svc_pool *pool);
 void              svc_exit_thread(struct svc_rqst *);
 struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
-                       void (*shutdown)(struct svc_serv*), svc_thread_fn,
-                       struct module *);
+                       sa_family_t, void (*shutdown)(struct svc_serv *),
+                       svc_thread_fn, struct module *);
 int               svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
 void              svc_destroy(struct svc_serv *);
 int               svc_process(struct svc_rqst *);
-int               svc_register(struct svc_serv *, int, unsigned short);
+int               svc_register(const struct svc_serv *, const unsigned short,
+                               const unsigned short);
+
 void              svc_wake_up(struct svc_serv *);
 void              svc_reserve(struct svc_rqst *rqstp, int space);
 struct svc_pool *  svc_pool_for_cpu(struct svc_serv *serv, int cpu);
index dc05b54bd3a3c4f7d7b0e167e219844c0f163f73..c14fe86dac594f069a08342f1790c03909586c41 100644 (file)
@@ -72,6 +72,7 @@ extern atomic_t rdma_stat_sq_prod;
  */
 struct svc_rdma_op_ctxt {
        struct svc_rdma_op_ctxt *read_hdr;
+       struct svc_rdma_fastreg_mr *frmr;
        int hdr_count;
        struct xdr_buf arg;
        struct list_head dto_q;
@@ -103,16 +104,30 @@ struct svc_rdma_chunk_sge {
        int start;              /* sge no for this chunk */
        int count;              /* sge count for this chunk */
 };
+struct svc_rdma_fastreg_mr {
+       struct ib_mr *mr;
+       void *kva;
+       struct ib_fast_reg_page_list *page_list;
+       int page_list_len;
+       unsigned long access_flags;
+       unsigned long map_len;
+       enum dma_data_direction direction;
+       struct list_head frmr_list;
+};
 struct svc_rdma_req_map {
+       struct svc_rdma_fastreg_mr *frmr;
        unsigned long count;
        union {
                struct kvec sge[RPCSVC_MAXPAGES];
                struct svc_rdma_chunk_sge ch[RPCSVC_MAXPAGES];
        };
 };
-
+#define RDMACTXT_F_FAST_UNREG  1
 #define RDMACTXT_F_LAST_CTXT   2
 
+#define        SVCRDMA_DEVCAP_FAST_REG         1       /* fast mr registration */
+#define        SVCRDMA_DEVCAP_READ_W_INV       2       /* read w/ invalidate */
+
 struct svcxprt_rdma {
        struct svc_xprt      sc_xprt;           /* SVC transport structure */
        struct rdma_cm_id    *sc_cm_id;         /* RDMA connection id */
@@ -136,6 +151,11 @@ struct svcxprt_rdma {
        struct ib_cq         *sc_rq_cq;
        struct ib_cq         *sc_sq_cq;
        struct ib_mr         *sc_phys_mr;       /* MR for server memory */
+       u32                  sc_dev_caps;       /* distilled device caps */
+       u32                  sc_dma_lkey;       /* local dma key */
+       unsigned int         sc_frmr_pg_list_len;
+       struct list_head     sc_frmr_q;
+       spinlock_t           sc_frmr_q_lock;
 
        spinlock_t           sc_lock;           /* transport lock */
 
@@ -192,8 +212,13 @@ extern int svc_rdma_post_recv(struct svcxprt_rdma *);
 extern int svc_rdma_create_listen(struct svc_serv *, int, struct sockaddr *);
 extern struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *);
 extern void svc_rdma_put_context(struct svc_rdma_op_ctxt *, int);
+extern void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt);
 extern struct svc_rdma_req_map *svc_rdma_get_req_map(void);
 extern void svc_rdma_put_req_map(struct svc_rdma_req_map *);
+extern int svc_rdma_fastreg(struct svcxprt_rdma *, struct svc_rdma_fastreg_mr *);
+extern struct svc_rdma_fastreg_mr *svc_rdma_get_frmr(struct svcxprt_rdma *);
+extern void svc_rdma_put_frmr(struct svcxprt_rdma *,
+                             struct svc_rdma_fastreg_mr *);
 extern void svc_sq_reap(struct svcxprt_rdma *);
 extern void svc_rq_reap(struct svcxprt_rdma *);
 extern struct svc_xprt_class svc_rdma_class;
index 8cff696dedf58413dac70ab00294c19ba898bcba..483e10380aae45429b8ad7aba5a930aa8e4f3695 100644 (file)
@@ -39,10 +39,7 @@ int          svc_send(struct svc_rqst *);
 void           svc_drop(struct svc_rqst *);
 void           svc_sock_update_bufs(struct svc_serv *serv);
 int            svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
-int            svc_addsock(struct svc_serv *serv,
-                           int fd,
-                           char *name_return,
-                           int *proto);
+int            svc_addsock(struct svc_serv *serv, int fd, char *name_return);
 void           svc_init_xprt_sock(void);
 void           svc_cleanup_xprt_sock(void);
 
index 4de56b1d372bf2b6203c500c618ff07e2e2baad6..54a379c9e8ebd3709ed684d05f871322c12648a4 100644 (file)
@@ -66,9 +66,6 @@
 
 #define RPCRDMA_INLINE_PAD_THRESH  (512)/* payload threshold to pad (bytes) */
 
-#define RDMA_RESOLVE_TIMEOUT   (5*HZ)  /* TBD 5 seconds */
-#define RDMA_CONNECT_RETRY_MAX (2)     /* retries if no listener backlog */
-
 /* memory registration strategies */
 #define RPCRDMA_PERSISTENT_REGISTRATION (1)
 
@@ -78,6 +75,7 @@ enum rpcrdma_memreg {
        RPCRDMA_MEMWINDOWS,
        RPCRDMA_MEMWINDOWS_ASYNC,
        RPCRDMA_MTHCAFMR,
+       RPCRDMA_FRMR,
        RPCRDMA_ALLPHYSICAL,
        RPCRDMA_LAST
 };
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
new file mode 100644 (file)
index 0000000..b18ec55
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __LINUX_SWIOTLB_H
+#define __LINUX_SWIOTLB_H
+
+#include <linux/types.h>
+
+struct device;
+struct dma_attrs;
+struct scatterlist;
+
+extern void
+swiotlb_init(void);
+
+extern void
+*swiotlb_alloc_coherent(struct device *hwdev, size_t size,
+                       dma_addr_t *dma_handle, gfp_t flags);
+
+extern void
+swiotlb_free_coherent(struct device *hwdev, size_t size,
+                     void *vaddr, dma_addr_t dma_handle);
+
+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 dma_addr_t
+swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
+                        int dir, struct dma_attrs *attrs);
+
+extern void
+swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
+                          size_t size, int dir, struct dma_attrs *attrs);
+
+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_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
+                    int dir, struct dma_attrs *attrs);
+
+extern void
+swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
+                      int nelems, int dir, struct dma_attrs *attrs);
+
+extern void
+swiotlb_sync_single_for_cpu(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_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+                              size_t size, int dir);
+
+extern void
+swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
+                          int nelems, int dir);
+
+extern void
+swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+                                 unsigned long offset, size_t size, int dir);
+
+extern void
+swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+                                    unsigned long offset, size_t size,
+                                    int dir);
+
+extern int
+swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
+
+extern int
+swiotlb_dma_supported(struct device *hwdev, u64 mask);
+
+#endif /* __LINUX_SWIOTLB_H */
index d0437f36921f803e1bd8be49d1066a7ad1796928..39d471d1163b4e8a54a95f56584f04e8a65a2d61 100644 (file)
@@ -972,7 +972,7 @@ extern int sysctl_perm(struct ctl_table_root *root,
 
 typedef struct ctl_table ctl_table;
 
-typedef int ctl_handler (struct ctl_table *table, int __user *name, int nlen,
+typedef int ctl_handler (struct ctl_table *table,
                         void __user *oldval, size_t __user *oldlenp,
                         void __user *newval, size_t newlen);
 
index 37fa24152bd810f7d9dd67b685e738179b5bfdf9..b330e289d71f280f7bb6ca3af431a733039ac420 100644 (file)
@@ -78,6 +78,8 @@ struct sysfs_ops {
        ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
 };
 
+struct sysfs_dirent;
+
 #ifdef CONFIG_SYSFS
 
 int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
@@ -117,9 +119,14 @@ int sysfs_add_file_to_group(struct kobject *kobj,
 void sysfs_remove_file_from_group(struct kobject *kobj,
                        const struct attribute *attr, const char *group);
 
-void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
-
-extern int __must_check sysfs_init(void);
+void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
+void sysfs_notify_dirent(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+                                     const unsigned char *name);
+struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
+void sysfs_put(struct sysfs_dirent *sd);
+void sysfs_printk_last_file(void);
+int __must_check sysfs_init(void);
 
 #else /* CONFIG_SYSFS */
 
@@ -222,7 +229,24 @@ static inline void sysfs_remove_file_from_group(struct kobject *kobj,
 {
 }
 
-static inline void sysfs_notify(struct kobject *kobj, char *dir, char *attr)
+static inline void sysfs_notify(struct kobject *kobj, const char *dir,
+                               const char *attr)
+{
+}
+static inline void sysfs_notify_dirent(struct sysfs_dirent *sd)
+{
+}
+static inline
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+                                     const unsigned char *name)
+{
+       return NULL;
+}
+static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
+{
+       return NULL;
+}
+static inline void sysfs_put(struct sysfs_dirent *sd)
 {
 }
 
@@ -231,6 +255,10 @@ static inline int __must_check sysfs_init(void)
        return 0;
 }
 
+static inline void sysfs_printk_last_file(void)
+{
+}
+
 #endif /* CONFIG_SYSFS */
 
 #endif /* _SYSFS_H_ */
index 5e88afc9a2fbd5b5e82bc9486087d9f9017cadcd..bdf855c2856fb2905837d72296394e30d6354ad4 100644 (file)
@@ -5,7 +5,7 @@
  * Don't include this header file directly - it is designed to be dragged in via
  * sched.h.
  *
- * Blame akpm@osdl.org for all this.
+ * Blame Andrew Morton for all this.
  */
 
 struct task_io_accounting {
index 0d0cf2a1e7bcfa75cd93bdd8ba355582b14e4619..5b2b6261f193c872631cfeea9c8990e3127d4a8c 100644 (file)
  * ON AN "AS IS" BASIS, AND QUICKNET TECHNOLOGIES, INC. HAS NO OBLIGATION
  * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
- * Version:       $Revision: 4.2 $
- *
- * $Id: telephony.h,v 4.2 2001/08/06 07:09:43 craigs Exp $
- *
  *****************************************************************************/
 
 #ifndef TELEPHONY_H
index 478662889f487db6fb1b8f6abba1bd781831a445..2acd0c1f8a2a305c8c7fc23895a6cba3cdd35ea8 100644 (file)
@@ -4,4 +4,19 @@
 #include <linux/types.h>
 #include <asm/termios.h>
 
+#define NFF    5
+
+struct termiox
+{
+       __u16   x_hflag;
+       __u16   x_cflag;
+       __u16   x_rflag[NFF];
+       __u16   x_sflag;
+};
+
+#define        RTSXOFF         0x0001          /* RTS flow control on input */
+#define        CTSXON          0x0002          /* CTS flow control on output */
+#define        DTRXOFF         0x0004          /* DTR flow control on input */
+#define DSRXON         0x0008          /* DCD flow control on output */
+
 #endif
index e15206a7e82ec9278b25fc062585302f9ed71687..51e883df0fa51fe598832747477533fc4303e30a 100644 (file)
@@ -29,6 +29,8 @@ struct timezone {
 
 #ifdef __KERNEL__
 
+extern struct timezone sys_tz;
+
 /* Parameters used to convert the timespec values: */
 #define MSEC_PER_SEC   1000L
 #define USEC_PER_MSEC  1000L
index 0cbec74ec0865af37673d58cbd435d7c39475279..3b8121d4e36ff90aff5c8f7fa9fe3865be0baacc 100644 (file)
@@ -23,7 +23,7 @@
  */
 #define NR_UNIX98_PTY_DEFAULT  4096      /* Default maximum for Unix98 ptys */
 #define NR_UNIX98_PTY_MAX      (1 << MINORBITS) /* Absolute limit */
-#define NR_LDISCS              18
+#define NR_LDISCS              19
 
 /* line disciplines */
 #define N_TTY          0
@@ -45,6 +45,7 @@
 #define N_HCI          15      /* Bluetooth HCI UART */
 #define N_GIGASET_M101 16      /* Siemens Gigaset M101 serial DECT adapter */
 #define N_SLCAN                17      /* Serial / USB serial CAN Adaptors */
+#define N_PPS          18      /* Pulse per Second */
 
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
@@ -181,6 +182,7 @@ struct signal_struct;
 
 struct tty_port {
        struct tty_struct       *tty;           /* Back pointer */
+       spinlock_t              lock;           /* Lock protecting tty field */
        int                     blocked_open;   /* Waiting to open */
        int                     count;          /* Usage count */
        wait_queue_head_t       open_wait;      /* Open waiters */
@@ -208,6 +210,7 @@ struct tty_operations;
 
 struct tty_struct {
        int     magic;
+       struct kref kref;
        struct tty_driver *driver;
        const struct tty_operations *ops;
        int index;
@@ -217,6 +220,7 @@ struct tty_struct {
        spinlock_t ctrl_lock;
        /* Termios values are protected by the termios mutex */
        struct ktermios *termios, *termios_locked;
+       struct termiox *termiox;        /* May be NULL for unsupported */
        char name[64];
        struct pid *pgrp;               /* Protected by ctrl lock */
        struct pid *session;
@@ -310,6 +314,25 @@ extern int kmsg_redirect;
 extern void console_init(void);
 extern int vcs_init(void);
 
+extern struct class *tty_class;
+
+/**
+ *     tty_kref_get            -       get a tty reference
+ *     @tty: tty device
+ *
+ *     Return a new reference to a tty object. The caller must hold
+ *     sufficient locks/counts to ensure that their existing reference cannot
+ *     go away
+ */
+
+extern inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
+{
+       if (tty)
+               kref_get(&tty->kref);
+       return tty;
+}
+extern void tty_kref_put(struct tty_struct *tty);
+
 extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode,
                              const char *routine);
 extern char *tty_name(struct tty_struct *tty, char *buf);
@@ -333,13 +356,15 @@ extern void tty_throttle(struct tty_struct *tty);
 extern void tty_unthrottle(struct tty_struct *tty);
 extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
                                                struct winsize *ws);
-
+extern void tty_shutdown(struct tty_struct *tty);
+extern void tty_free_termios(struct tty_struct *tty);
 extern int is_current_pgrp_orphaned(void);
 extern struct pid *tty_get_pgrp(struct tty_struct *tty);
 extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern void tty_hangup(struct tty_struct *tty);
 extern void tty_vhangup(struct tty_struct *tty);
+extern void tty_vhangup_self(void);
 extern void tty_unhangup(struct file *filp);
 extern int tty_hung_up_p(struct file *filp);
 extern void do_SAK(struct tty_struct *tty);
@@ -347,6 +372,9 @@ extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
 extern void no_tty(void);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
+extern void tty_buffer_free_all(struct tty_struct *tty);
+extern void tty_buffer_flush(struct tty_struct *tty);
+extern void tty_buffer_init(struct tty_struct *tty);
 extern speed_t tty_get_baud_rate(struct tty_struct *tty);
 extern speed_t tty_termios_baud_rate(struct ktermios *termios);
 extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
@@ -372,6 +400,15 @@ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
 extern dev_t tty_devnum(struct tty_struct *tty);
 extern void proc_clear_tty(struct task_struct *p);
 extern struct tty_struct *get_current_tty(void);
+extern void tty_default_fops(struct file_operations *fops);
+extern struct tty_struct *alloc_tty_struct(void);
+extern void free_tty_struct(struct tty_struct *tty);
+extern void initialize_tty_struct(struct tty_struct *tty,
+               struct tty_driver *driver, int idx);
+extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
+                                                               int first_ok);
+extern void tty_release_dev(struct file *filp);
+extern int tty_init_termios(struct tty_struct *tty);
 
 extern struct mutex tty_mutex;
 
@@ -382,6 +419,8 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
 extern void tty_port_init(struct tty_port *port);
 extern int tty_port_alloc_xmit_buf(struct tty_port *port);
 extern void tty_port_free_xmit_buf(struct tty_port *port);
+extern struct tty_struct *tty_port_tty_get(struct tty_port *port);
+extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty);
 
 extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
 extern int tty_unregister_ldisc(int disc);
@@ -427,7 +466,7 @@ static inline void tty_audit_push_task(struct task_struct *tsk,
 #endif
 
 /* tty_ioctl.c */
-extern int n_tty_ioctl(struct tty_struct *tty, struct file *file,
+extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                       unsigned int cmd, unsigned long arg);
 
 /* serial.c */
index 16d27944c3211af2f954fa6fff4950d3c3591812..78416b901589cd08cb1ea1410e1ac61986c2f4e0 100644 (file)
@@ -7,6 +7,28 @@
  * defined; unless noted otherwise, they are optional, and can be
  * filled in with a null pointer.
  *
+ * struct tty_struct * (*lookup)(struct tty_driver *self, int idx)
+ *
+ *     Return the tty device corresponding to idx, NULL if there is not
+ *     one currently in use and an ERR_PTR value on error. Called under
+ *     tty_mutex (for now!)
+ *
+ *     Optional method. Default behaviour is to use the ttys array
+ *
+ * int (*install)(struct tty_driver *self, struct tty_struct *tty)
+ *
+ *     Install a new tty into the tty driver internal tables. Used in
+ *     conjunction with lookup and remove methods.
+ *
+ *     Optional method. Default behaviour is to use the ttys array
+ *
+ * void (*remove)(struct tty_driver *self, struct tty_struct *tty)
+ *
+ *     Remove a closed tty from the tty driver internal tables. Used in
+ *     conjunction with lookup and remove methods.
+ *
+ *     Optional method. Default behaviour is to use the ttys array
+ *
  * int  (*open)(struct tty_struct * tty, struct file * filp);
  *
  *     This routine is called when a particular tty device is opened.
  *
  *     Required method.
  *
+ * void (*shutdown)(struct tty_struct * tty);
+ *
+ *     This routine is called when a particular tty device is closed for
+ *     the last time freeing up the resources.
+ *
  * int (*write)(struct tty_struct * tty,
  *              const unsigned char *buf, int count);
  *
  *     not force errors here if they are not resizable objects (eg a serial
  *     line). See tty_do_resize() if you need to wrap the standard method
  *     in your own logic - the usual case.
+ *
+ * void (*set_termiox)(struct tty_struct *tty, struct termiox *new);
+ *
+ *     Called when the device receives a termiox based ioctl. Passes down
+ *     the requested data from user space. This method will not be invoked
+ *     unless the tty also has a valid tty->termiox pointer.
+ *
+ *     Optional: Called under the termios lock
  */
 
 #include <linux/fs.h>
@@ -190,8 +225,13 @@ struct tty_struct;
 struct tty_driver;
 
 struct tty_operations {
+       struct tty_struct * (*lookup)(struct tty_driver *driver,
+                       struct inode *inode, int idx);
+       int  (*install)(struct tty_driver *driver, struct tty_struct *tty);
+       void (*remove)(struct tty_driver *driver, struct tty_struct *tty);
        int  (*open)(struct tty_struct * tty, struct file * filp);
        void (*close)(struct tty_struct * tty, struct file * filp);
+       void (*shutdown)(struct tty_struct *tty);
        int  (*write)(struct tty_struct * tty,
                      const unsigned char *buf, int count);
        int  (*put_char)(struct tty_struct *tty, unsigned char ch);
@@ -220,6 +260,7 @@ struct tty_operations {
                        unsigned int set, unsigned int clear);
        int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty,
                                struct winsize *ws);
+       int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
 #ifdef CONFIG_CONSOLE_POLL
        int (*poll_init)(struct tty_driver *driver, int line, char *options);
        int (*poll_get_char)(struct tty_driver *driver, int line);
@@ -229,6 +270,7 @@ struct tty_operations {
 
 struct tty_driver {
        int     magic;          /* magic number for this structure */
+       struct kref kref;       /* Reference management */
        struct cdev cdev;
        struct module   *owner;
        const char      *driver_name;
@@ -242,7 +284,6 @@ struct tty_driver {
        short   subtype;        /* subtype of tty driver */
        struct ktermios init_termios; /* Initial termios */
        int     flags;          /* tty driver flags */
-       int     refcount;       /* for loadable tty drivers */
        struct proc_dir_entry *proc_entry; /* /proc fs entry */
        struct tty_driver *other; /* only used for the PTY driver */
 
@@ -264,12 +305,19 @@ struct tty_driver {
 
 extern struct list_head tty_drivers;
 
-struct tty_driver *alloc_tty_driver(int lines);
-void put_tty_driver(struct tty_driver *driver);
-void tty_set_operations(struct tty_driver *driver,
+extern struct tty_driver *alloc_tty_driver(int lines);
+extern void put_tty_driver(struct tty_driver *driver);
+extern void tty_set_operations(struct tty_driver *driver,
                        const struct tty_operations *op);
 extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
 
+extern void tty_driver_kref_put(struct tty_driver *driver);
+extern inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
+{
+       kref_get(&d->kref);
+       return d;
+}
+
 /* tty driver magic number */
 #define TTY_DRIVER_MAGIC               0x5402
 
index d4a9ce6e2760394a7fb29d4812e03a4728a9a555..f24f7beb47df0bcad9a481f6b14b83df34d12a1a 100644 (file)
@@ -191,12 +191,14 @@ typedef __u32 __bitwise __wsum;
 #ifdef __KERNEL__
 typedef unsigned __bitwise__ gfp_t;
 
-#ifdef CONFIG_RESOURCES_64BIT
-typedef u64 resource_size_t;
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+typedef u64 phys_addr_t;
 #else
-typedef u32 resource_size_t;
+typedef u32 phys_addr_t;
 #endif
 
+typedef phys_addr_t resource_size_t;
+
 struct ustat {
        __kernel_daddr_t        f_tfree;
        __kernel_ino_t          f_tinode;
index 303d93ffd6b23c2ccdf42bb676799f8ee295ef23..d4b03034ee73af53507e2ec15bb68235139b029d 100644 (file)
@@ -910,6 +910,8 @@ enum v4l2_mpeg_audio_encoding {
        V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
        V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
        V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
+       V4L2_MPEG_AUDIO_ENCODING_AAC     = 3,
+       V4L2_MPEG_AUDIO_ENCODING_AC3     = 4,
 };
 #define V4L2_CID_MPEG_AUDIO_L1_BITRATE                 (V4L2_CID_MPEG_BASE+102)
 enum v4l2_mpeg_audio_l1_bitrate {
@@ -988,12 +990,36 @@ enum v4l2_mpeg_audio_crc {
        V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
 };
 #define V4L2_CID_MPEG_AUDIO_MUTE               (V4L2_CID_MPEG_BASE+109)
+#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE                (V4L2_CID_MPEG_BASE+110)
+#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE                (V4L2_CID_MPEG_BASE+111)
+enum v4l2_mpeg_audio_ac3_bitrate {
+       V4L2_MPEG_AUDIO_AC3_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_40K  = 1,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_48K  = 2,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_56K  = 3,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_64K  = 4,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_80K  = 5,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_96K  = 6,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
+};
 
 /*  MPEG video */
 #define V4L2_CID_MPEG_VIDEO_ENCODING           (V4L2_CID_MPEG_BASE+200)
 enum v4l2_mpeg_video_encoding {
-       V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0,
-       V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_2     = 1,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2,
 };
 #define V4L2_CID_MPEG_VIDEO_ASPECT             (V4L2_CID_MPEG_BASE+201)
 enum v4l2_mpeg_video_aspect {
index 1cbd0a7db4e6b73c72084c346451573b0ea2e1a8..2f1113467f707b5b9e03a3d6243eb2beda5f1abc 100644 (file)
@@ -96,7 +96,7 @@ void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
 extern int unbind_con_driver(const struct consw *csw, int first, int last,
                             int deflt);
-int vty_init(void);
+int vty_init(const struct file_operations *console_fops);
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
index 0081147a9fe8cf23578a40bc6392cd8961e98b90..ef609f842faca33c6e9dded2db7bbd09d7adc8d1 100644 (file)
@@ -108,15 +108,6 @@ static inline int waitqueue_active(wait_queue_head_t *q)
        return !list_empty(&q->task_list);
 }
 
-/*
- * Used to distinguish between sync and async io wait context:
- * sync i/o typically specifies a NULL wait queue entry or a wait
- * queue entry bound to a task (current task) to wake up.
- * aio specifies a wait queue entry with an async notification
- * callback routine, not associated with any task.
- */
-#define is_sync_wait(wait)     (!(wait) || ((wait)->private))
-
 extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
 extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
 extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
index e193fb08fd553eb41f782e244b7982e1075c5159..4f26ecc1411b836bcf30dd26320e2304395d7044 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef __MATH_EMU_OP_2_H__
 #define __MATH_EMU_OP_2_H__
 
-#define _FP_FRAC_DECL_2(X)     _FP_W_TYPE X##_f0, X##_f1
+#define _FP_FRAC_DECL_2(X)     _FP_W_TYPE X##_f0 = 0, X##_f1 = 0
 #define _FP_FRAC_COPY_2(D,S)   (D##_f0 = S##_f0, D##_f1 = S##_f1)
 #define _FP_FRAC_SET_2(X,I)    __FP_FRAC_SET_2(X, I)
 #define _FP_FRAC_HIGH_2(X)     (X##_f1)
index bb46e7645d537234bdc44221bccfa8e0e332e4c5..cc1ec396f8d61bcc6e82e851845184011d467eb6 100644 (file)
@@ -73,7 +73,7 @@ do {                                                                  \
        X##_c = FP_CLS_NAN;                                             \
        /* Check for signaling NaN */                                   \
        if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))            \
-         FP_SET_EXCEPTION(FP_EX_INVALID);                              \
+         FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN);         \
       }                                                                        \
     break;                                                             \
   }                                                                    \
@@ -324,7 +324,7 @@ do {                                                                             \
        _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                              \
        R##_s = _FP_NANSIGN_##fs;                                            \
        R##_c = FP_CLS_NAN;                                                  \
-       FP_SET_EXCEPTION(FP_EX_INVALID);                                     \
+       FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI);                 \
        break;                                                               \
       }                                                                             \
     /* FALLTHRU */                                                          \
@@ -431,7 +431,7 @@ do {                                                        \
     R##_s = _FP_NANSIGN_##fs;                          \
     R##_c = FP_CLS_NAN;                                        \
     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
-    FP_SET_EXCEPTION(FP_EX_INVALID);                   \
+    FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
     break;                                             \
                                                        \
   default:                                             \
@@ -490,11 +490,15 @@ do {                                                      \
     break;                                             \
                                                        \
   case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):         \
+    R##_s = _FP_NANSIGN_##fs;                          \
+    R##_c = FP_CLS_NAN;                                        \
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
+    FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
   case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):       \
     R##_s = _FP_NANSIGN_##fs;                          \
     R##_c = FP_CLS_NAN;                                        \
     _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);            \
-    FP_SET_EXCEPTION(FP_EX_INVALID);                   \
+    FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
     break;                                             \
                                                        \
   default:                                             \
index a6f873b45f98aa04466fcea158c13711157b0edb..3f284bc031809f6cef05a36360f2c54ca2879ad9 100644 (file)
 #ifndef FP_EX_INVALID
 #define FP_EX_INVALID          0
 #endif
+#ifndef FP_EX_INVALID_SNAN
+#define FP_EX_INVALID_SNAN     0
+#endif
+/* inf - inf */
+#ifndef FP_EX_INVALID_ISI
+#define FP_EX_INVALID_ISI      0
+#endif
+/* inf / inf */
+#ifndef FP_EX_INVALID_IDI
+#define FP_EX_INVALID_IDI      0
+#endif
+/* 0 / 0 */
+#ifndef FP_EX_INVALID_ZDZ
+#define FP_EX_INVALID_ZDZ      0
+#endif
+/* inf * 0 */
+#ifndef FP_EX_INVALID_IMZ
+#define FP_EX_INVALID_IMZ      0
+#endif
 #ifndef FP_EX_OVERFLOW
 #define FP_EX_OVERFLOW         0
 #endif
index b8e8aa91905a4450bf3ff9c431e2ba7168092f1a..38f2d93c3957014ed5431b61caae60bc3ab4c50d 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/input.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
 
 #define IR_TYPE_RC5     1
 #define IR_TYPE_PD      2 /* Pulse distance encoded IR */
@@ -85,6 +86,10 @@ struct card_ir {
        u32 code;                       /* raw code under construction */
        struct timeval base_time;       /* time of last seen code */
        int active;                     /* building raw code */
+
+       /* NEC decoding */
+       u32                     nec_gpio;
+       struct tasklet_struct   tlet;
 };
 
 void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
@@ -105,6 +110,7 @@ void ir_rc5_timer_keyup(unsigned long data);
 extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pixelview_new[IR_KEYTAB_SIZE];
@@ -139,6 +145,7 @@ extern IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_asus_pc39[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_encore_enltv2[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE];
@@ -147,7 +154,9 @@ extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE];
-
+extern IR_KEYTAB_TYPE ir_codes_encore_enltv_fm53[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE];
 #endif
 
 /*
index f677dfb9d373d7f87364ae8fd0b6d881c78bc8d3..bab2127195911254fb3ae6087d2106921afb5b90 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    saa7115.h - definition for saa7113/4/5 inputs and frequency flags
+    saa7115.h - definition for saa7111/3/4/5 inputs and frequency flags
 
     Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
 
 #ifndef _SAA7115_H_
 #define _SAA7115_H_
 
-/* SAA7113/4/5 HW inputs */
+/* SAA7111/3/4/5 HW inputs */
 #define SAA7115_COMPOSITE0 0
 #define SAA7115_COMPOSITE1 1
 #define SAA7115_COMPOSITE2 2
 #define SAA7115_COMPOSITE3 3
-#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */
-#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */
+#define SAA7115_COMPOSITE4 4 /* not available for the saa7111/3 */
+#define SAA7115_COMPOSITE5 5 /* not available for the saa7111/3 */
 #define SAA7115_SVIDEO0    6
 #define SAA7115_SVIDEO1    7
 #define SAA7115_SVIDEO2    8
 #define SAA7115_FREQ_FL_CGCDIV (1 << 1)           /* SA 3A[6], CGCDIV, SAA7115 only */
 #define SAA7115_FREQ_FL_APLL   (1 << 2)           /* SA 3A[3], APLL, SAA7114/5 only */
 
-#define SAA7115_IPORT_ON    1
-#define SAA7115_IPORT_OFF   0
+#define SAA7115_IPORT_ON       1
+#define SAA7115_IPORT_OFF      0
+
+/* SAA7111 specific output flags */
+#define SAA7111_VBI_BYPASS     2
+#define SAA7111_FMT_YUV422      0x00
+#define SAA7111_FMT_RGB        0x40
+#define SAA7111_FMT_CCIR       0x80
+#define SAA7111_FMT_YUV411     0xc0
 
 #endif
 
index 2f68f4cd00377ac06b7543f084d93f99219b7f49..c5a6e22a4b37d626d90370b3becb212105534478 100644 (file)
 
 extern unsigned int saa7146_debug;
 
-//#define DEBUG_PROLOG printk("(0x%08x)(0x%08x) %s: %s(): ",(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,RPS_ADDR0))),(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,IER))),KBUILD_MODNAME,__FUNCTION__)
+//#define DEBUG_PROLOG printk("(0x%08x)(0x%08x) %s: %s(): ",(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,RPS_ADDR0))),(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,IER))),KBUILD_MODNAME,__func__)
 
 #ifndef DEBUG_VARIABLE
        #define DEBUG_VARIABLE saa7146_debug
 #endif
 
-#define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME,__FUNCTION__)
+#define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME, __func__)
 #define INFO(x) { printk("%s: ",KBUILD_MODNAME); printk x; }
 
 #define ERR(x) { DEBUG_PROLOG; printk x; }
index 234a4711d2ec9026d010a434d7fab11c992a3127..b5dbefea3740c65b7ae87e8f7964e6c8764e3c83 100644 (file)
@@ -5,8 +5,6 @@
 
 struct sh_mobile_ceu_info {
        unsigned long flags; /* SOCAM_... */
-       void (*enable_camera)(void);
-       void (*disable_camera)(void);
 };
 
 #endif /* __ASM_SH_MOBILE_CEU_H__ */
index d548de326722a657ae8a257fe35e214f6585f432..c5de7bb19fda759febc5a35aca76cf738a7afcc8 100644 (file)
@@ -83,6 +83,9 @@ struct soc_camera_link {
        int bus_id;
        /* GPIO number to switch between 8 and 10 bit modes */
        unsigned int gpio;
+       /* Optional callbacks to power on or off and reset the sensor */
+       int (*power)(struct device *, int);
+       int (*reset)(struct device *);
 };
 
 static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
index 77068fcc86bd9cb60a801732b24b67e28fc75103..67c1f514d0e297884a914b2c5c065f5996deea78 100644 (file)
 #define TUNER_TDA9887                   74      /* This tuner should be used only internally */
 #define TUNER_TEA5761                  75      /* Only FM Radio Tuner */
 #define TUNER_XC5000                   76      /* Xceive Silicon Tuner */
+#define TUNER_TCL_MF02GIP_5N           77      /* TCL MF02GIP_5N */
 
 /* tv card specific */
 #define TDA9887_PRESENT                (1<<0)
@@ -178,7 +179,7 @@ struct tuner_setup {
        unsigned int    type;   /* Tuner type */
        unsigned int    mode_mask;  /* Allowed tuner modes */
        unsigned int    config; /* configuraion for more complex tuners */
-       int (*tuner_callback) (void *dev, int command,int arg);
+       int (*tuner_callback) (void *dev, int component, int cmd, int arg);
 };
 
 #endif /* __KERNEL__ */
index 41b509babf3f4e895878118fd799b1b4d8e664cd..d73a8e9028a56f425e60eb1ecaddf642e5d34e66 100644 (file)
@@ -72,6 +72,10 @@ enum {
        /* module cs5345: just ident 5345 */
        V4L2_IDENT_CS5345 = 5345,
 
+       /* module saa6752hs: reserved range 6750-6759 */
+       V4L2_IDENT_SAA6752HS = 6752,
+       V4L2_IDENT_SAA6752HS_AC3 = 6753,
+
        /* module wm8739: just ident 8739 */
        V4L2_IDENT_WM8739 = 8739,
 
@@ -161,6 +165,7 @@ enum {
        /* Micron CMOS sensor chips: 45000-45099 */
        V4L2_IDENT_MT9M001C12ST         = 45000,
        V4L2_IDENT_MT9M001C12STM        = 45005,
+       V4L2_IDENT_MT9M111              = 45007,
        V4L2_IDENT_MT9V022IX7ATC        = 45010, /* No way to detect "normal" I77ATx */
        V4L2_IDENT_MT9V022IX7ATM        = 45015, /* and "lead free" IA7ATx chips */
 };
index 07d3a9a575d1422c1d1b1cb16b7cf58e137111f2..2f8719abf5cb84fa363ce22fcb33309cb69897ed 100644 (file)
@@ -76,11 +76,14 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
 
 int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
                const char **menu_items);
+const char *v4l2_ctrl_get_name(u32 id);
 const char **v4l2_ctrl_get_menu(u32 id);
 int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
 int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl);
 int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
                struct v4l2_queryctrl *qctrl, const char **menu_items);
+#define V4L2_CTRL_MENU_IDS_END (0xffffffff)
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
 u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
 
 /* ------------------------------------------------------------------------- */
@@ -222,18 +225,22 @@ struct v4l2_crystal_freq {
    An extra flags field allows device specific configuration regarding
    clock frequency dividers, etc. If not used, then set flags to 0.
    If the frequency is not supported, then -EINVAL is returned. */
-#define VIDIOC_INT_S_CRYSTAL_FREQ      _IOW ('d', 113, struct v4l2_crystal_freq)
+#define VIDIOC_INT_S_CRYSTAL_FREQ      _IOW('d', 113, struct v4l2_crystal_freq)
 
 /* Initialize the sensor registors to some sort of reasonable
    default values. */
-#define VIDIOC_INT_INIT                        _IOW ('d', 114, u32)
+#define VIDIOC_INT_INIT                        _IOW('d', 114, u32)
 
 /* Set v4l2_std_id for video OUTPUT devices. This is ignored by
    video input devices. */
-#define VIDIOC_INT_S_STD_OUTPUT                _IOW  ('d', 115, v4l2_std_id)
+#define VIDIOC_INT_S_STD_OUTPUT                _IOW('d', 115, v4l2_std_id)
 
 /* Get v4l2_std_id for video OUTPUT devices. This is ignored by
    video input devices. */
-#define VIDIOC_INT_G_STD_OUTPUT                _IOW  ('d', 116, v4l2_std_id)
+#define VIDIOC_INT_G_STD_OUTPUT                _IOW('d', 116, v4l2_std_id)
+
+/* Set GPIO pins. Very simple right now, might need to be extended with
+   a v4l2_gpio struct if a direction is also needed. */
+#define VIDIOC_INT_S_GPIO              _IOW('d', 117, u32)
 
 #endif /* V4L2_COMMON_H_ */
index 2745e1afc72267f7be541e7c52ea05371d33d451..a0a6b41c5e0944e3e655e51151e5a60e3abf2db4 100644 (file)
@@ -9,30 +9,20 @@
 #ifndef _V4L2_DEV_H
 #define _V4L2_DEV_H
 
-#define OBSOLETE_DEVDATA 1 /* to be removed soon */
-
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/device.h>
+#include <linux/cdev.h>
 #include <linux/mutex.h>
-#include <linux/compiler.h> /* need __user */
 #include <linux/videodev2.h>
 
 #define VIDEO_MAJOR    81
-/* Minor device allocation */
-#define MINOR_VFL_TYPE_GRABBER_MIN   0
-#define MINOR_VFL_TYPE_GRABBER_MAX  63
-#define MINOR_VFL_TYPE_RADIO_MIN    64
-#define MINOR_VFL_TYPE_RADIO_MAX   127
-#define MINOR_VFL_TYPE_VTX_MIN     192
-#define MINOR_VFL_TYPE_VTX_MAX     223
-#define MINOR_VFL_TYPE_VBI_MIN     224
-#define MINOR_VFL_TYPE_VBI_MAX     255
 
 #define VFL_TYPE_GRABBER       0
 #define VFL_TYPE_VBI           1
 #define VFL_TYPE_RADIO         2
 #define VFL_TYPE_VTX           3
+#define VFL_TYPE_MAX           4
 
 struct v4l2_ioctl_callbacks;
 
@@ -49,12 +39,15 @@ struct video_device
 
        /* sysfs */
        struct device dev;              /* v4l device */
+       struct cdev cdev;               /* character device */
+       void (*cdev_release)(struct kobject *kobj);
        struct device *parent;          /* device parent */
 
        /* device info */
        char name[32];
        int vfl_type;
        int minor;
+       u16 num;
        /* attribute to differentiate multiple indices on one physical device */
        int index;
 
@@ -69,50 +62,50 @@ struct video_device
 
        /* ioctl callbacks */
        const struct v4l2_ioctl_ops *ioctl_ops;
-
-#ifdef OBSOLETE_DEVDATA /* to be removed soon */
-       /* dev->driver_data will be used instead some day.
-        * Use the video_{get|set}_drvdata() helper functions,
-        * so the switch over will be transparent for you.
-        * Or use {pci|usb}_{get|set}_drvdata() directly. */
-       void *priv;
-#endif
-
-       /* for videodev.c internal usage -- please don't touch */
-       int users;                     /* video_exclusive_{open|close} ... */
-       struct mutex lock;             /* ... helper function uses these   */
 };
 
-/* Class-dev to video-device */
+/* dev to video-device */
 #define to_video_device(cd) container_of(cd, struct video_device, dev)
 
-/* Version 2 functions */
-extern int video_register_device(struct video_device *vfd, int type, int nr);
-int video_register_device_index(struct video_device *vfd, int type, int nr,
-                                       int index);
-void video_unregister_device(struct video_device *);
+/* Register and unregister devices. Note that if video_register_device fails,
+   the release() callback of the video_device structure is *not* called, so
+   the caller is responsible for freeing any data. Usually that means that
+   you call video_device_release() on failure. */
+int __must_check video_register_device(struct video_device *vfd, int type, int nr);
+int __must_check video_register_device_index(struct video_device *vfd,
+                                               int type, int nr, int index);
+void video_unregister_device(struct video_device *vfd);
 
-/* helper functions to alloc / release struct video_device, the
-   later can be used for video_device->release() */
-struct video_device *video_device_alloc(void);
+/* helper functions to alloc/release struct video_device, the
+   latter can also be used for video_device->release(). */
+struct video_device * __must_check video_device_alloc(void);
+
+/* this release function frees the vfd pointer */
 void video_device_release(struct video_device *vfd);
 
-#ifdef OBSOLETE_DEVDATA /* to be removed soon */
+/* this release function does nothing, use when the video_device is a
+   static global struct. Note that having a static video_device is
+   a dubious construction at best. */
+void video_device_release_empty(struct video_device *vfd);
+
 /* helper functions to access driver private data. */
 static inline void *video_get_drvdata(struct video_device *dev)
 {
-       return dev->priv;
+       return dev_get_drvdata(&dev->dev);
 }
 
 static inline void video_set_drvdata(struct video_device *dev, void *data)
 {
-       dev->priv = data;
+       dev_set_drvdata(&dev->dev, data);
 }
 
-/* Obsolete stuff - Still needed for radio devices and obsolete drivers */
-extern struct video_device* video_devdata(struct file*);
-extern int video_exclusive_open(struct inode *inode, struct file *file);
-extern int video_exclusive_release(struct inode *inode, struct file *file);
-#endif
+struct video_device *video_devdata(struct file *file);
+
+/* Combine video_get_drvdata and video_devdata as this is
+   used very often. */
+static inline void *video_drvdata(struct file *file)
+{
+       return video_get_drvdata(video_devdata(file));
+}
 
 #endif /* _V4L2_DEV_H */
index dc6404618555a7250b79810519ce34d4b6e92b69..0bef03add7968c1b26053be42b52ffbc5da132d3 100644 (file)
@@ -39,11 +39,6 @@ struct v4l2_ioctl_ops {
                                            struct v4l2_fmtdesc *f);
        int (*vidioc_enum_fmt_vid_out)     (struct file *file, void *fh,
                                            struct v4l2_fmtdesc *f);
-#if 1
-       /* deprecated, will be removed in 2.6.28 */
-       int (*vidioc_enum_fmt_vbi_cap)     (struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
-#endif
        int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
                                            struct v4l2_fmtdesc *f);
 
index c3626c0ba9d39a4358e028c328dfe534c5393b18..fb163e2e0de60c2c9df90b0980c4f84aadf6b9a1 100644 (file)
@@ -61,7 +61,7 @@ extern unsigned int p9_debug_level;
 do {  \
        if ((p9_debug_level & level) == level) \
                printk(KERN_NOTICE "-- %s (%d): " \
-               format , __FUNCTION__, task_pid_nr(current) , ## arg); \
+               format , __func__, task_pid_nr(current) , ## arg); \
 } while (0)
 
 #define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR,   \
@@ -76,7 +76,7 @@ do {  \
 #define P9_EPRINTK(level, format, arg...) \
 do { \
        printk(level "9p: %s (%d): " \
-               format , __FUNCTION__, task_pid_nr(current), ## arg); \
+               format , __func__, task_pid_nr(current), ## arg); \
 } while (0)
 
 /**
index 6f8418bf42417c218b112a4ae46b5b942c7863ee..996d12df75940f1ac722b52d764e5cd6c6d9a4c5 100644 (file)
@@ -54,8 +54,8 @@
 #define SOL_RFCOMM     18
 
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
-#define BT_DBG(fmt, arg...)  printk(KERN_INFO "%s: " fmt "\n" , __FUNCTION__ , ## arg)
-#define BT_ERR(fmt, arg...)  printk(KERN_ERR  "%s: " fmt "\n" , __FUNCTION__ , ## arg)
+#define BT_DBG(fmt, arg...)  printk(KERN_INFO "%s: " fmt "\n" , __func__ , ## arg)
+#define BT_ERR(fmt, arg...)  printk(KERN_ERR  "%s: " fmt "\n" , __func__ , ## arg)
 
 /* Connection and socket states */
 enum {
index a6bb94530cfddfbd0e8d3bd10880fdfcd8c996b5..9909774eb998d973532d629a90d9017f11eacd90 100644 (file)
 #include <linux/net.h>
 #include <linux/skbuff.h>
 #include <net/netlabel.h>
+#include <asm/atomic.h>
 
 /* known doi values */
 #define CIPSO_V4_DOI_UNKNOWN          0x00000000
 
-/* tag types */
+/* standard tag types */
 #define CIPSO_V4_TAG_INVALID          0
 #define CIPSO_V4_TAG_RBITMAP          1
 #define CIPSO_V4_TAG_ENUM             2
 #define CIPSO_V4_TAG_PBITMAP          6
 #define CIPSO_V4_TAG_FREEFORM         7
 
+/* non-standard tag types (tags > 127) */
+#define CIPSO_V4_TAG_LOCAL            128
+
 /* doi mapping types */
 #define CIPSO_V4_MAP_UNKNOWN          0
-#define CIPSO_V4_MAP_STD              1
+#define CIPSO_V4_MAP_TRANS            1
 #define CIPSO_V4_MAP_PASS             2
+#define CIPSO_V4_MAP_LOCAL            3
 
 /* limits */
 #define CIPSO_V4_MAX_REM_LVLS         255
@@ -79,10 +84,9 @@ struct cipso_v4_doi {
        } map;
        u8 tags[CIPSO_V4_TAG_MAXCNT];
 
-       u32 valid;
+       atomic_t refcount;
        struct list_head list;
        struct rcu_head rcu;
-       struct list_head dom_list;
 };
 
 /* Standard CIPSO mapping table */
@@ -128,25 +132,26 @@ extern int cipso_v4_rbm_strictvalid;
 
 #ifdef CONFIG_NETLABEL
 int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
-int cipso_v4_doi_remove(u32 doi,
-                       struct netlbl_audit *audit_info,
-                       void (*callback) (struct rcu_head * head));
+void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
+int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
+void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
 int cipso_v4_doi_walk(u32 *skip_cnt,
                     int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
                     void *cb_arg);
-int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain);
-int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
-                              const char *domain);
 #else
 static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
 {
        return -ENOSYS;
 }
 
+static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
+{
+       return;
+}
+
 static inline int cipso_v4_doi_remove(u32 doi,
-                                   struct netlbl_audit *audit_info,
-                                   void (*callback) (struct rcu_head * head))
+                                     struct netlbl_audit *audit_info)
 {
        return 0;
 }
@@ -206,10 +211,15 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
 int cipso_v4_sock_setattr(struct sock *sk,
                          const struct cipso_v4_doi *doi_def,
                          const struct netlbl_lsm_secattr *secattr);
+void cipso_v4_sock_delattr(struct sock *sk);
 int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
+int cipso_v4_skbuff_setattr(struct sk_buff *skb,
+                           const struct cipso_v4_doi *doi_def,
+                           const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_skbuff_delattr(struct sk_buff *skb);
 int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
                            struct netlbl_lsm_secattr *secattr);
-int cipso_v4_validate(unsigned char **option);
+int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
 #else
 static inline void cipso_v4_error(struct sk_buff *skb,
                                  int error,
@@ -225,19 +235,36 @@ static inline int cipso_v4_sock_setattr(struct sock *sk,
        return -ENOSYS;
 }
 
+static inline void cipso_v4_sock_delattr(struct sock *sk)
+{
+}
+
 static inline int cipso_v4_sock_getattr(struct sock *sk,
                                        struct netlbl_lsm_secattr *secattr)
 {
        return -ENOSYS;
 }
 
+static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
+                                     const struct cipso_v4_doi *doi_def,
+                                     const struct netlbl_lsm_secattr *secattr)
+{
+       return -ENOSYS;
+}
+
+static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
+{
+       return -ENOSYS;
+}
+
 static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
                                          struct netlbl_lsm_secattr *secattr)
 {
        return -ENOSYS;
 }
 
-static inline int cipso_v4_validate(unsigned char **option)
+static inline int cipso_v4_validate(const struct sk_buff *skb,
+                                   unsigned char **option)
 {
        return -ENOSYS;
 }
index 6048579d0b2433edf27132f086cfcc7509dd752d..93a56de3594be63de5c2a2847ea78fbb68db940b 100644 (file)
@@ -114,7 +114,7 @@ extern u32 ieee80211_debug_level;
 #define IEEE80211_DEBUG(level, fmt, args...) \
 do { if (ieee80211_debug_level & (level)) \
   printk(KERN_DEBUG "ieee80211: %c %s " fmt, \
-         in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+         in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
 static inline bool ieee80211_ratelimit_debug(u32 level)
 {
        return (ieee80211_debug_level & level) && net_ratelimit();
index 1cbccaf0de3f30f161b01965e0b70331490cb1da..bc026ecb513f7c57f1d836017f4a02b6d8e72a57 100644 (file)
@@ -396,7 +396,7 @@ extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
 int ipv4_doint_and_flush(ctl_table *ctl, int write,
                         struct file* filp, void __user *buffer,
                         size_t *lenp, loff_t *ppos);
-int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
+int ipv4_doint_and_flush_strategy(ctl_table *table,
                                  void __user *oldval, size_t __user *oldlenp,
                                  void __user *newval, size_t newlen);
 #ifdef CONFIG_PROC_FS
index 0b2071d9326de8c059ed814848247c50d24535cb..fe9fcf73c85ed26135b802a959382a85e5d64e43 100644 (file)
@@ -165,13 +165,13 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
     do {                                                               \
            if (level <= ip_vs_get_debug_level())                       \
                    printk(KERN_DEBUG "Enter: %s, %s line %i\n",        \
-                          __FUNCTION__, __FILE__, __LINE__);           \
+                          __func__, __FILE__, __LINE__);               \
     } while (0)
 #define LeaveFunction(level)                                            \
     do {                                                                \
            if (level <= ip_vs_get_debug_level())                       \
                        printk(KERN_DEBUG "Leave: %s, %s line %i\n",    \
-                              __FUNCTION__, __FILE__, __LINE__);       \
+                              __func__, __FILE__, __LINE__);       \
     } while (0)
 #else
 #define EnterFunction(level)   do {} while (0)
index 08387553b57e5ee18aeb9f3c8890cdd3d5f54a20..7e582061b230dd9dce935059d959572cbba7cc9a 100644 (file)
@@ -72,7 +72,7 @@ do {  if (irda_debug >= (n)) \
 #define IRDA_ASSERT(expr, func) \
 do { if(!(expr)) { \
        printk( "Assertion failed! %s:%s:%d %s\n", \
-               __FILE__,__FUNCTION__,__LINE__,(#expr) ); \
+               __FILE__,__func__,__LINE__,(#expr) ); \
        func } } while (0)
 #define IRDA_ASSERT_LABEL(label)       label
 #else
index 5617a1613c917b84c43758fd30400fd816b1a618..d861197f83c76aefdd1ec6dd1854057c6b27f177 100644 (file)
@@ -645,7 +645,8 @@ enum ieee80211_key_flags {
  *     - Temporal Encryption Key (128 bits)
  *     - Temporal Authenticator Tx MIC Key (64 bits)
  *     - Temporal Authenticator Rx MIC Key (64 bits)
- *
+ * @icv_len: FIXME
+ * @iv_len: FIXME
  */
 struct ieee80211_key_conf {
        enum ieee80211_key_alg alg;
index a01b7c4dc76371dba52e2aebac23ae254238b6e5..11dd0137c6a5b34ee1434c4b699b68d304ce5d46 100644 (file)
@@ -129,9 +129,8 @@ extern int                  ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
                                                           void __user *buffer,
                                                           size_t *lenp,
                                                           loff_t *ppos);
-int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
-                                int nlen, void __user *oldval,
-                                size_t __user *oldlenp,
+int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
+                                void __user *oldval, size_t __user *oldlenp,
                                 void __user *newval, size_t newlen);
 #endif
 
index f29eeb9777e0d8282c174c1f00c9a4e9423ce55e..58684066388c45750e1f5a21199ccc8a2557670b 100644 (file)
@@ -25,4 +25,12 @@ static inline int nf_nat_initialized(struct nf_conn *ct,
        else
                return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
 }
+
+struct nlattr;
+
+extern int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+                                 enum nf_nat_manip_type manip,
+                                 struct nlattr *attr);
+
 #endif /* _NF_NAT_CORE_H */
index e4d2d6baa98388e4d673f5f57ddc20405a3fdb69..17c442a4514e10faf20d9c12af3af5f9b75cef76 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This 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 +72,10 @@ struct cipso_v4_doi;
 /* NetLabel NETLINK protocol version
  *  1: initial version
  *  2: added static labels for unlabeled connections
+ *  3: network selectors added to the NetLabel/LSM domain mapping and the
+ *     CIPSO_V4_MAP_LOCAL CIPSO mapping was added
  */
-#define NETLBL_PROTO_VERSION            2
+#define NETLBL_PROTO_VERSION            3
 
 /* NetLabel NETLINK types/families */
 #define NETLBL_NLTYPE_NONE              0
@@ -87,6 +89,8 @@ struct cipso_v4_doi;
 #define NETLBL_NLTYPE_CIPSOV6_NAME      "NLBL_CIPSOv6"
 #define NETLBL_NLTYPE_UNLABELED         5
 #define NETLBL_NLTYPE_UNLABELED_NAME    "NLBL_UNLBL"
+#define NETLBL_NLTYPE_ADDRSELECT        6
+#define NETLBL_NLTYPE_ADDRSELECT_NAME   "NLBL_ADRSEL"
 
 /*
  * NetLabel - Kernel API for accessing the network packet label mappings.
@@ -200,7 +204,7 @@ struct netlbl_lsm_secattr {
        u32 type;
        char *domain;
        struct netlbl_lsm_cache *cache;
-       union {
+       struct {
                struct {
                        struct netlbl_lsm_secattr_catmap *cat;
                        u32 lvl;
@@ -352,12 +356,9 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
 int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info);
 int netlbl_cfg_unlbl_add_map(const char *domain,
                             struct netlbl_audit *audit_info);
-int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
-                          struct netlbl_audit *audit_info);
 int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
                               const char *domain,
                               struct netlbl_audit *audit_info);
-int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info);
 
 /*
  * LSM security attribute operations
@@ -380,12 +381,19 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
 int netlbl_enabled(void);
 int netlbl_sock_setattr(struct sock *sk,
                        const struct netlbl_lsm_secattr *secattr);
+void netlbl_sock_delattr(struct sock *sk);
 int netlbl_sock_getattr(struct sock *sk,
                        struct netlbl_lsm_secattr *secattr);
+int netlbl_conn_setattr(struct sock *sk,
+                       struct sockaddr *addr,
+                       const struct netlbl_lsm_secattr *secattr);
+int netlbl_skbuff_setattr(struct sk_buff *skb,
+                         u16 family,
+                         const struct netlbl_lsm_secattr *secattr);
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
                          u16 family,
                          struct netlbl_lsm_secattr *secattr);
-void netlbl_skbuff_err(struct sk_buff *skb, int error);
+void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway);
 
 /*
  * LSM label mapping cache operations
@@ -404,22 +412,12 @@ static inline int netlbl_cfg_unlbl_add_map(const char *domain,
 {
        return -ENOSYS;
 }
-static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
-                                        struct netlbl_audit *audit_info)
-{
-       return -ENOSYS;
-}
 static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
                                             const char *domain,
                                             struct netlbl_audit *audit_info)
 {
        return -ENOSYS;
 }
-static inline int netlbl_cfg_cipsov4_del(u32 doi,
-                                        struct netlbl_audit *audit_info)
-{
-       return -ENOSYS;
-}
 static inline int netlbl_secattr_catmap_walk(
                                      struct netlbl_lsm_secattr_catmap *catmap,
                                      u32 offset)
@@ -456,18 +454,35 @@ static inline int netlbl_sock_setattr(struct sock *sk,
 {
        return -ENOSYS;
 }
+static inline void netlbl_sock_delattr(struct sock *sk)
+{
+}
 static inline int netlbl_sock_getattr(struct sock *sk,
                                      struct netlbl_lsm_secattr *secattr)
 {
        return -ENOSYS;
 }
+static inline int netlbl_conn_setattr(struct sock *sk,
+                                     struct sockaddr *addr,
+                                     const struct netlbl_lsm_secattr *secattr)
+{
+       return -ENOSYS;
+}
+static inline int netlbl_skbuff_setattr(struct sk_buff *skb,
+                                     u16 family,
+                                     const struct netlbl_lsm_secattr *secattr)
+{
+       return -ENOSYS;
+}
 static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
                                        u16 family,
                                        struct netlbl_lsm_secattr *secattr)
 {
        return -ENOSYS;
 }
-static inline void netlbl_skbuff_err(struct sk_buff *skb, int error)
+static inline void netlbl_skbuff_err(struct sk_buff *skb,
+                                    int error,
+                                    int gateway)
 {
        return;
 }
index 703305d00365ff86460315c5490b3417b36ce2f1..ed71b110edf795094336e436816d9bdd5e6a1aab 100644 (file)
@@ -303,7 +303,7 @@ extern int sctp_debug_flag;
 #define SCTP_ASSERT(expr, str, func) \
        if (!(expr)) { \
                SCTP_DEBUG_PRINTK("Assertion Failed: %s(%s) at %s:%s:%d\n", \
-                       str, (#expr), __FILE__, __FUNCTION__, __LINE__); \
+                       str, (#expr), __FILE__, __func__, __LINE__); \
                func; \
        }
 
index ad6e278ba7f2df6e11c347840a8175ea2dc25930..b417985708f238dc0dff70c7700da1408dbdd9d4 100644 (file)
 
 #define MANFID_TOSHIBA                 0x0098
 
-#define MANFID_UNGERMANN 0x02c0
+#define MANFID_UNGERMANN               0x02c0
 
 #define MANFID_XIRCOM                  0x0105
 
index e2e10c1e9a0615fc9844419ed9995f40f2d9f732..cfdd5af77dcc92d49eaada6ad6726c24e52cc81a 100644 (file)
@@ -573,44 +573,6 @@ typedef struct tuple_t {
 #define TUPLE_RETURN_LINK      0x01
 #define TUPLE_RETURN_COMMON    0x02
 
-/* For ValidateCIS */
-typedef struct cisinfo_t {
-    u_int      Chains;
-} cisinfo_t;
-
 #define CISTPL_MAX_CIS_SIZE    0x200
 
-/* For ReplaceCIS */
-typedef struct cisdump_t {
-    u_int      Length;
-    cisdata_t  Data[CISTPL_MAX_CIS_SIZE];
-} cisdump_t;
-
-
-int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis);
-
-/* don't use outside of PCMCIA core yet */
-int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple);
-int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple);
-int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple);
-int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
-
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *count);
-
-/* ... but use these wrappers instead */
-#define pcmcia_get_first_tuple(p_dev, tuple) \
-               pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
-
-#define pcmcia_get_next_tuple(p_dev, tuple) \
-               pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
-
-#define pcmcia_get_tuple_data(p_dev, tuple) \
-               pccard_get_tuple_data(p_dev->socket, tuple)
-
-#define pcmcia_parse_tuple(p_dev, tuple, parse) \
-               pccard_parse_tuple(tuple, parse)
-
-#define pcmcia_validate_cis(p_dev, info) \
-               pccard_validate_cis(p_dev->socket, p_dev->func, info)
-
 #endif /* LINUX_CISTPL_H */
index 45d84b275789e3e138536bcac9ffff52e81a0df9..904468a191ef43c46c8a7fa091967a4f9f09e1c5 100644 (file)
@@ -28,72 +28,16 @@ typedef struct conf_reg_t {
 #define CS_WRITE       2
 
 /* for AdjustResourceInfo */
-typedef struct adjust_t {
-    u_int      Action;
-    u_int      Resource;
-    u_int      Attributes;
-    union {
-       struct memory {
-           u_long      Base;
-           u_long      Size;
-       } memory;
-       struct io {
-           ioaddr_t    BasePort;
-           ioaddr_t    NumPorts;
-           u_int       IOAddrLines;
-       } io;
-       struct irq {
-           u_int       IRQ;
-       } irq;
-    } resource;
-} adjust_t;
-
 /* Action field */
 #define REMOVE_MANAGED_RESOURCE                1
 #define ADD_MANAGED_RESOURCE           2
-#define GET_FIRST_MANAGED_RESOURCE     3
-#define GET_NEXT_MANAGED_RESOURCE      4
-/* Resource field */
-#define RES_MEMORY_RANGE               1
-#define RES_IO_RANGE                   2
-#define RES_IRQ                                3
-/* Attribute field */
-#define RES_IRQ_TYPE                   0x03
-#define RES_IRQ_TYPE_EXCLUSIVE         0
-#define RES_IRQ_TYPE_TIME              1
-#define RES_IRQ_TYPE_DYNAMIC           2
-#define RES_IRQ_CSC                    0x04
-#define RES_SHARED                     0x08
-#define RES_RESERVED                   0x10
-#define RES_ALLOCATED                  0x20
-#define RES_REMOVED                    0x40
+
 
 typedef struct event_callback_args_t {
        struct pcmcia_device    *client_handle;
        void                    *client_data;
 } event_callback_args_t;
 
-/* for GetConfigurationInfo */
-typedef struct config_info_t {
-    u_char     Function;
-    u_int      Attributes;
-    u_int      Vcc, Vpp1, Vpp2;
-    u_int      IntType;
-    u_int      ConfigBase;
-    u_char     Status, Pin, Copy, Option, ExtStatus;
-    u_int      Present;
-    u_int      CardValues;
-    u_int      AssignedIRQ;
-    u_int      IRQAttributes;
-    ioaddr_t   BasePort1;
-    ioaddr_t   NumPorts1;
-    u_int      Attributes1;
-    ioaddr_t   BasePort2;
-    ioaddr_t   NumPorts2;
-    u_int      Attributes2;
-    u_int      IOAddrLines;
-} config_info_t;
-
 /* For CardValues field */
 #define CV_OPTION_VALUE                0x01
 #define CV_STATUS_VALUE                0x02
@@ -257,22 +201,6 @@ typedef struct win_req_t {
 #define WIN_BAR_MASK           0xe000
 #define WIN_BAR_SHIFT          13
 
-/* Attributes for RegisterClient -- UNUSED -- */
-#define INFO_MASTER_CLIENT     0x01
-#define INFO_IO_CLIENT         0x02
-#define INFO_MTD_CLIENT                0x04
-#define INFO_MEM_CLIENT                0x08
-#define MAX_NUM_CLIENTS                3
-
-#define INFO_CARD_SHARE                0x10
-#define INFO_CARD_EXCL         0x20
-
-typedef struct cs_status_t {
-    u_char     Function;
-    event_t    CardState;
-    event_t    SocketState;
-} cs_status_t;
-
 typedef struct error_info_t {
     int                func;
     int                retcode;
@@ -308,95 +236,4 @@ typedef struct error_info_t {
 #define CS_EVENT_3VCARD                        0x200000
 #define CS_EVENT_XVCARD                        0x400000
 
-/* Return codes */
-#define CS_SUCCESS             0x00
-#define CS_BAD_ADAPTER         0x01
-#define CS_BAD_ATTRIBUTE       0x02
-#define CS_BAD_BASE            0x03
-#define CS_BAD_EDC             0x04
-#define CS_BAD_IRQ             0x06
-#define CS_BAD_OFFSET          0x07
-#define CS_BAD_PAGE            0x08
-#define CS_READ_FAILURE                0x09
-#define CS_BAD_SIZE            0x0a
-#define CS_BAD_SOCKET          0x0b
-#define CS_BAD_TYPE            0x0d
-#define CS_BAD_VCC             0x0e
-#define CS_BAD_VPP             0x0f
-#define CS_BAD_WINDOW          0x11
-#define CS_WRITE_FAILURE       0x12
-#define CS_NO_CARD             0x14
-#define CS_UNSUPPORTED_FUNCTION        0x15
-#define CS_UNSUPPORTED_MODE    0x16
-#define CS_BAD_SPEED           0x17
-#define CS_BUSY                        0x18
-#define CS_GENERAL_FAILURE     0x19
-#define CS_WRITE_PROTECTED     0x1a
-#define CS_BAD_ARG_LENGTH      0x1b
-#define CS_BAD_ARGS            0x1c
-#define CS_CONFIGURATION_LOCKED        0x1d
-#define CS_IN_USE              0x1e
-#define CS_NO_MORE_ITEMS       0x1f
-#define CS_OUT_OF_RESOURCE     0x20
-#define CS_BAD_HANDLE          0x21
-
-#define CS_BAD_TUPLE           0x40
-
-#ifdef __KERNEL__
-
-/*
- *  The main Card Services entry point
- */
-
-enum service {
-    AccessConfigurationRegister, AddSocketServices,
-    AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory,
-    DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo,
-    GetClientInfo, GetConfigurationInfo, GetEventMask,
-    GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple,
-    GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple,
-    GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage,
-    MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow,
-    OpenMemory, ParseTuple, ReadMemory, RegisterClient,
-    RegisterEraseQueue, RegisterMTD, RegisterTimer,
-    ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ,
-    ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices,
-    RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ,
-    RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry,
-    SetEventMask, SetRegion, ValidateCIS, VendorSpecific,
-    WriteMemory, BindDevice, BindMTD, ReportError,
-    SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS,
-    GetFirstWindow, GetNextWindow, GetMemPage
-};
-
-struct pcmcia_socket;
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg);
-int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config);
-int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
-int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_release_window(window_handle_t win);
-int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
-int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
-int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
-int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
-int pcmcia_suspend_card(struct pcmcia_socket *skt);
-int pcmcia_resume_card(struct pcmcia_socket *skt);
-int pcmcia_eject_card(struct pcmcia_socket *skt);
-int pcmcia_insert_card(struct pcmcia_socket *skt);
-int pccard_reset_card(struct pcmcia_socket *skt);
-
-struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *p_dev);
-void pcmcia_disable_device(struct pcmcia_device *p_dev);
-
-struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt);
-void pcmcia_put_socket(struct pcmcia_socket *skt);
-
-/* compatibility functions */
-#define pcmcia_reset_card(p_dev, req) \
-               pccard_reset_card(p_dev->socket)
-
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_CS_H */
index f402a0f435b451ce6843a4e9fa7faaf4620ede61..315965a37930099f6ffed2a672b303ba694b9bc6 100644 (file)
 #include <sys/types.h>
 #endif
 
-#if defined(__arm__) || defined(__mips__) || defined(__avr32__) || \
-       defined(__bfin__)
-/* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
-typedef u_int   ioaddr_t;
-#else
-typedef u_short        ioaddr_t;
-#endif
-
 typedef u_short        socket_t;
 typedef u_int  event_t;
 typedef u_char cisdata_t;
index e04e0b0d9a25a5b0c4903f3a51cab2af33de6d90..c33ea08352b8a5447ce37ed89f49cfb1d1efd265 100644 (file)
@@ -1,10 +1,19 @@
 /*
- * Copyright (2003-2004)       Dominik Brodowski <linux@brodo.de>
- *                             David Woodhouse
+ * device_id.h -- PCMCIA driver matching helpers
  *
- * License: GPL v2
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * (C) 2003 - 2004     David Woodhouse
+ * (C) 2003 - 2004     Dominik Brodowski
  */
 
+#ifndef _LINUX_PCMCIA_DEVICE_ID_H
+#define _LINUX_PCMCIA_DEVICE_ID_H
+
+#ifdef __KERNEL__
+
 #define PCMCIA_DEVICE_MANF_CARD(manf, card) { \
        .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
                        PCMCIA_DEV_ID_MATCH_CARD_ID, \
 
 
 #define PCMCIA_DEVICE_NULL { .match_flags = 0, }
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_PCMCIA_DEVICE_ID_H */
index b316027c853d7845dc374591b5a3f4c155f8f03d..a2be80b9a095fcd1bb955af8d2eacd75eafdddec 100644 (file)
@@ -10,7 +10,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * (C) 1999            David A. Hinds
- * (C) 2003 - 2004     Dominik Brodowski
+ * (C) 2003 - 2008     Dominik Brodowski
  */
 
 #ifndef _LINUX_DS_H
 #include <pcmcia/cs_types.h>
 #include <pcmcia/device_id.h>
 
-typedef struct tuple_parse_t {
-    tuple_t            tuple;
-    cisdata_t          data[255];
-    cisparse_t         parse;
-} tuple_parse_t;
-
-typedef struct win_info_t {
-    window_handle_t    handle;
-    win_req_t          window;
-    memreq_t           map;
-} win_info_t;
-    
-typedef struct bind_info_t {
-    dev_info_t         dev_info;
-    u_char             function;
-    struct pcmcia_device *instance;
-    char               name[DEV_NAME_LEN];
-    u_short            major, minor;
-    void               *next;
-} bind_info_t;
-
-typedef struct mtd_info_t {
-    dev_info_t         dev_info;
-    u_int              Attributes;
-    u_int              CardOffset;
-} mtd_info_t;
-
-typedef struct region_info_t {
-    u_int              Attributes;
-    u_int              CardOffset;
-    u_int              RegionSize;
-    u_int              AccessSpeed;
-    u_int              BlockSize;
-    u_int              PartMultiple;
-    u_char             JedecMfr, JedecInfo;
-    memory_handle_t    next;
-} region_info_t;
-#define REGION_TYPE            0x0001
-#define REGION_TYPE_CM         0x0000
-#define REGION_TYPE_AM         0x0001
-#define REGION_PREFETCH                0x0008
-#define REGION_CACHEABLE       0x0010
-#define REGION_BAR_MASK                0xe000
-#define REGION_BAR_SHIFT       13
-
-typedef union ds_ioctl_arg_t {
-    adjust_t           adjust;
-    config_info_t      config;
-    tuple_t            tuple;
-    tuple_parse_t      tuple_parse;
-    client_req_t       client_req;
-    cs_status_t                status;
-    conf_reg_t         conf_reg;
-    cisinfo_t          cisinfo;
-    region_info_t      region;
-    bind_info_t                bind_info;
-    mtd_info_t         mtd_info;
-    win_info_t         win_info;
-    cisdump_t          cisdump;
-} ds_ioctl_arg_t;
-
-#define DS_ADJUST_RESOURCE_INFO                _IOWR('d', 2, adjust_t)
-#define DS_GET_CONFIGURATION_INFO      _IOWR('d', 3, config_info_t)
-#define DS_GET_FIRST_TUPLE             _IOWR('d', 4, tuple_t)
-#define DS_GET_NEXT_TUPLE              _IOWR('d', 5, tuple_t)
-#define DS_GET_TUPLE_DATA              _IOWR('d', 6, tuple_parse_t)
-#define DS_PARSE_TUPLE                 _IOWR('d', 7, tuple_parse_t)
-#define DS_RESET_CARD                  _IO  ('d', 8)
-#define DS_GET_STATUS                  _IOWR('d', 9, cs_status_t)
-#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t)
-#define DS_VALIDATE_CIS                        _IOR ('d', 11, cisinfo_t)
-#define DS_SUSPEND_CARD                        _IO  ('d', 12)
-#define DS_RESUME_CARD                 _IO  ('d', 13)
-#define DS_EJECT_CARD                  _IO  ('d', 14)
-#define DS_INSERT_CARD                 _IO  ('d', 15)
-#define DS_GET_FIRST_REGION            _IOWR('d', 16, region_info_t)
-#define DS_GET_NEXT_REGION             _IOWR('d', 17, region_info_t)
-#define DS_REPLACE_CIS                 _IOWR('d', 18, cisdump_t)
-#define DS_GET_FIRST_WINDOW            _IOR ('d', 19, win_info_t)
-#define DS_GET_NEXT_WINDOW             _IOWR('d', 20, win_info_t)
-#define DS_GET_MEM_PAGE                        _IOWR('d', 21, win_info_t)
-
-#define DS_BIND_REQUEST                        _IOWR('d', 60, bind_info_t)
-#define DS_GET_DEVICE_INFO             _IOWR('d', 61, bind_info_t) 
-#define DS_GET_NEXT_DEVICE             _IOWR('d', 62, bind_info_t) 
-#define DS_UNBIND_REQUEST              _IOW ('d', 63, bind_info_t)
-#define DS_BIND_MTD                    _IOWR('d', 64, mtd_info_t)
-
 #ifdef __KERNEL__
 #include <linux/device.h>
 #include <pcmcia/ss.h>
 
-typedef struct dev_node_t {
-    char               dev_name[DEV_NAME_LEN];
-    u_short            major, minor;
-    struct dev_node_t  *next;
-} dev_node_t;
-
-
+/*
+ * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
+ * a.k.a. PCI drivers
+ */
 struct pcmcia_socket;
+struct pcmcia_device;
 struct config_t;
 
+/* dynamic device IDs for PCMCIA device drivers. See
+ * Documentation/pcmcia/driver.txt for details.
+*/
 struct pcmcia_dynids {
        spinlock_t              lock;
        struct list_head        list;
@@ -147,6 +60,14 @@ struct pcmcia_driver {
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
+/* Some drivers use dev_node_t to store char or block device information.
+ * Don't use this in new drivers, though.
+ */
+typedef struct dev_node_t {
+       char                    dev_name[DEV_NAME_LEN];
+       u_short                 major, minor;
+       struct dev_node_t       *next;
+} dev_node_t;
 
 struct pcmcia_device {
        /* the socket and the device_no [for multifunction devices]
@@ -216,10 +137,304 @@ struct pcmcia_device {
 #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
 #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
 
+/* deprecated -- don't use! */
 #define handle_to_dev(handle) (handle->dev)
 
-/* error reporting */
-void cs_error(struct pcmcia_device *handle, int func, int ret);
+
+/* (deprecated) error reporting by PCMCIA devices. Use dev_printk()
+ * or dev_dbg() directly in the driver, without referring to pcmcia_error_func()
+ * and/or pcmcia_error_ret() for those functions will go away soon.
+ */
+enum service {
+    AccessConfigurationRegister, AddSocketServices,
+    AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory,
+    DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo,
+    GetClientInfo, GetConfigurationInfo, GetEventMask,
+    GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple,
+    GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple,
+    GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage,
+    MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow,
+    OpenMemory, ParseTuple, ReadMemory, RegisterClient,
+    RegisterEraseQueue, RegisterMTD, RegisterTimer,
+    ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ,
+    ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices,
+    RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ,
+    RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry,
+    SetEventMask, SetRegion, ValidateCIS, VendorSpecific,
+    WriteMemory, BindDevice, BindMTD, ReportError,
+    SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS,
+    GetFirstWindow, GetNextWindow, GetMemPage
+};
+const char *pcmcia_error_func(int func);
+const char *pcmcia_error_ret(int ret);
+
+#define cs_error(p_dev, func, ret)                     \
+       {                                               \
+               dev_printk(KERN_NOTICE, &p_dev->dev,    \
+                          "%s : %s\n",                 \
+                          pcmcia_error_func(func),     \
+                          pcmcia_error_ret(ret));      \
+       }
+
+/* CIS access.
+ * Use the pcmcia_* versions in PCMCIA drivers
+ */
+int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse);
+
+int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function,
+                          tuple_t *tuple);
+#define pcmcia_get_first_tuple(p_dev, tuple) \
+               pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple)
+
+int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
+                         tuple_t *tuple);
+#define pcmcia_get_next_tuple(p_dev, tuple) \
+               pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple)
+
+int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple);
+#define pcmcia_get_tuple_data(p_dev, tuple) \
+               pccard_get_tuple_data(p_dev->socket, tuple)
+
+
+/* loop CIS entries for valid configuration */
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+                      int      (*conf_check)   (struct pcmcia_device *p_dev,
+                                                cistpl_cftable_entry_t *cf,
+                                                cistpl_cftable_entry_t *dflt,
+                                                unsigned int vcc,
+                                                void *priv_data),
+                      void *priv_data);
+
+/* is the device still there? */
+struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *p_dev);
+
+/* low-level interface reset */
+int pcmcia_reset_card(struct pcmcia_socket *skt);
+
+/* CIS config */
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
+                                        conf_reg_t *reg);
+
+/* device configuration */
+int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
+int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
+int pcmcia_request_configuration(struct pcmcia_device *p_dev,
+                                config_req_t *req);
+
+int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req,
+                         window_handle_t *wh);
+int pcmcia_release_window(window_handle_t win);
+
+int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
+int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
+
+int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
+void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 #endif /* __KERNEL__ */
+
+
+
+/* Below, there are only definitions which are used by
+ * - the PCMCIA ioctl
+ * - deprecated PCMCIA userspace tools only
+ *
+ * here be dragons ... here be dragons ... here be dragons ... here be drag
+ */
+
+#if defined(CONFIG_PCMCIA_IOCTL) || !defined(__KERNEL__)
+
+#if defined(__arm__) || defined(__mips__) || defined(__avr32__) || \
+       defined(__bfin__)
+/* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
+typedef u_int   ioaddr_t;
+#else
+typedef u_short        ioaddr_t;
+#endif
+
+/* for AdjustResourceInfo */
+typedef struct adjust_t {
+       u_int                   Action;
+       u_int                   Resource;
+       u_int                   Attributes;
+       union {
+               struct memory {
+                       u_long          Base;
+                       u_long          Size;
+               } memory;
+               struct io {
+                       ioaddr_t        BasePort;
+                       ioaddr_t        NumPorts;
+                       u_int           IOAddrLines;
+               } io;
+               struct irq {
+                       u_int           IRQ;
+               } irq;
+       } resource;
+} adjust_t;
+
+/* Action field */
+#define REMOVE_MANAGED_RESOURCE                1
+#define ADD_MANAGED_RESOURCE           2
+#define GET_FIRST_MANAGED_RESOURCE     3
+#define GET_NEXT_MANAGED_RESOURCE      4
+/* Resource field */
+#define RES_MEMORY_RANGE               1
+#define RES_IO_RANGE                   2
+#define RES_IRQ                                3
+/* Attribute field */
+#define RES_IRQ_TYPE                   0x03
+#define RES_IRQ_TYPE_EXCLUSIVE         0
+#define RES_IRQ_TYPE_TIME              1
+#define RES_IRQ_TYPE_DYNAMIC           2
+#define RES_IRQ_CSC                    0x04
+#define RES_SHARED                     0x08
+#define RES_RESERVED                   0x10
+#define RES_ALLOCATED                  0x20
+#define RES_REMOVED                    0x40
+
+
+typedef struct tuple_parse_t {
+       tuple_t                 tuple;
+       cisdata_t               data[255];
+       cisparse_t              parse;
+} tuple_parse_t;
+
+typedef struct win_info_t {
+       window_handle_t         handle;
+       win_req_t               window;
+       memreq_t                map;
+} win_info_t;
+
+typedef struct bind_info_t {
+       dev_info_t              dev_info;
+       u_char                  function;
+       struct pcmcia_device    *instance;
+       char                    name[DEV_NAME_LEN];
+       u_short                 major, minor;
+       void                    *next;
+} bind_info_t;
+
+typedef struct mtd_info_t {
+       dev_info_t              dev_info;
+       u_int                   Attributes;
+       u_int                   CardOffset;
+} mtd_info_t;
+
+typedef struct region_info_t {
+       u_int                   Attributes;
+       u_int                   CardOffset;
+       u_int                   RegionSize;
+       u_int                   AccessSpeed;
+       u_int                   BlockSize;
+       u_int                   PartMultiple;
+       u_char                  JedecMfr, JedecInfo;
+       memory_handle_t         next;
+} region_info_t;
+
+#define REGION_TYPE            0x0001
+#define REGION_TYPE_CM         0x0000
+#define REGION_TYPE_AM         0x0001
+#define REGION_PREFETCH                0x0008
+#define REGION_CACHEABLE       0x0010
+#define REGION_BAR_MASK                0xe000
+#define REGION_BAR_SHIFT       13
+
+/* For ReplaceCIS */
+typedef struct cisdump_t {
+       u_int                   Length;
+       cisdata_t               Data[CISTPL_MAX_CIS_SIZE];
+} cisdump_t;
+
+/* for GetConfigurationInfo */
+typedef struct config_info_t {
+       u_char                  Function;
+       u_int                   Attributes;
+       u_int                   Vcc, Vpp1, Vpp2;
+       u_int                   IntType;
+       u_int                   ConfigBase;
+       u_char                  Status, Pin, Copy, Option, ExtStatus;
+       u_int                   Present;
+       u_int                   CardValues;
+       u_int                   AssignedIRQ;
+       u_int                   IRQAttributes;
+       ioaddr_t                BasePort1;
+       ioaddr_t                NumPorts1;
+       u_int                   Attributes1;
+       ioaddr_t                BasePort2;
+       ioaddr_t                NumPorts2;
+       u_int                   Attributes2;
+       u_int                   IOAddrLines;
+} config_info_t;
+
+/* For ValidateCIS */
+typedef struct cisinfo_t {
+       u_int                   Chains;
+} cisinfo_t;
+
+typedef struct cs_status_t {
+       u_char                  Function;
+       event_t                 CardState;
+       event_t                 SocketState;
+} cs_status_t;
+
+typedef union ds_ioctl_arg_t {
+       adjust_t                adjust;
+       config_info_t           config;
+       tuple_t                 tuple;
+       tuple_parse_t           tuple_parse;
+       client_req_t            client_req;
+       cs_status_t             status;
+       conf_reg_t              conf_reg;
+       cisinfo_t               cisinfo;
+       region_info_t           region;
+       bind_info_t             bind_info;
+       mtd_info_t              mtd_info;
+       win_info_t              win_info;
+       cisdump_t               cisdump;
+} ds_ioctl_arg_t;
+
+#define DS_ADJUST_RESOURCE_INFO                        _IOWR('d',  2, adjust_t)
+#define DS_GET_CONFIGURATION_INFO              _IOWR('d',  3, config_info_t)
+#define DS_GET_FIRST_TUPLE                     _IOWR('d',  4, tuple_t)
+#define DS_GET_NEXT_TUPLE                      _IOWR('d',  5, tuple_t)
+#define DS_GET_TUPLE_DATA                      _IOWR('d',  6, tuple_parse_t)
+#define DS_PARSE_TUPLE                         _IOWR('d',  7, tuple_parse_t)
+#define DS_RESET_CARD                          _IO  ('d',  8)
+#define DS_GET_STATUS                          _IOWR('d',  9, cs_status_t)
+#define DS_ACCESS_CONFIGURATION_REGISTER       _IOWR('d', 10, conf_reg_t)
+#define DS_VALIDATE_CIS                                _IOR ('d', 11, cisinfo_t)
+#define DS_SUSPEND_CARD                                _IO  ('d', 12)
+#define DS_RESUME_CARD                         _IO  ('d', 13)
+#define DS_EJECT_CARD                          _IO  ('d', 14)
+#define DS_INSERT_CARD                         _IO  ('d', 15)
+#define DS_GET_FIRST_REGION                    _IOWR('d', 16, region_info_t)
+#define DS_GET_NEXT_REGION                     _IOWR('d', 17, region_info_t)
+#define DS_REPLACE_CIS                         _IOWR('d', 18, cisdump_t)
+#define DS_GET_FIRST_WINDOW                    _IOR ('d', 19, win_info_t)
+#define DS_GET_NEXT_WINDOW                     _IOWR('d', 20, win_info_t)
+#define DS_GET_MEM_PAGE                                _IOWR('d', 21, win_info_t)
+
+#define DS_BIND_REQUEST                                _IOWR('d', 60, bind_info_t)
+#define DS_GET_DEVICE_INFO                     _IOWR('d', 61, bind_info_t)
+#define DS_GET_NEXT_DEVICE                     _IOWR('d', 62, bind_info_t)
+#define DS_UNBIND_REQUEST                      _IOW ('d', 63, bind_info_t)
+#define DS_BIND_MTD                            _IOWR('d', 64, mtd_info_t)
+
+
+/* used in userspace only */
+#define CS_IN_USE                      0x1e
+
+#define INFO_MASTER_CLIENT     0x01
+#define INFO_IO_CLIENT         0x02
+#define INFO_MTD_CLIENT                0x04
+#define INFO_MEM_CLIENT                0x08
+#define MAX_NUM_CLIENTS                3
+
+#define INFO_CARD_SHARE                0x10
+#define INFO_CARD_EXCL         0x20
+
+
+#endif /* !defined(__KERNEL__) || defined(CONFIG_PCMCIA_IOCTL) */
+
 #endif /* _LINUX_DS_H */
index ed919dd9bb5c29debac61ce496baa06ae6408c4f..9b4ac9385f5d094a07dcaae9daad1c04b6bfb2bd 100644 (file)
 
 /* for GetSocket, SetSocket */
 typedef struct socket_state_t {
-    u_int      flags;
-    u_int      csc_mask;
-    u_char     Vcc, Vpp;
-    u_char     io_irq;
+       u_int   flags;
+       u_int   csc_mask;
+       u_char  Vcc, Vpp;
+       u_char  io_irq;
 } socket_state_t;
 
 extern socket_state_t dead_socket;
@@ -86,79 +86,22 @@ extern socket_state_t dead_socket;
 #define HOOK_POWER_PRE 0x01
 #define HOOK_POWER_POST        0x02
 
-
 typedef struct pccard_io_map {
-    u_char     map;
-    u_char     flags;
-    u_short    speed;
-    u_int      start, stop;
+       u_char  map;
+       u_char  flags;
+       u_short speed;
+       u_int   start, stop;
 } pccard_io_map;
 
 typedef struct pccard_mem_map {
-    u_char     map;
-    u_char     flags;
-    u_short    speed;
-    u_long     static_start;
-    u_int      card_start;
-    struct resource *res;
+       u_char          map;
+       u_char          flags;
+       u_short         speed;
+       u_long          static_start;
+       u_int           card_start;
+       struct resource *res;
 } pccard_mem_map;
 
-typedef struct cb_bridge_map {
-    u_char     map;
-    u_char     flags;
-    u_int      start, stop;
-} cb_bridge_map;
-
-/*
- * Socket operations.
- */
-struct pcmcia_socket;
-
-struct pccard_operations {
-       int (*init)(struct pcmcia_socket *sock);
-       int (*suspend)(struct pcmcia_socket *sock);
-       int (*get_status)(struct pcmcia_socket *sock, u_int *value);
-       int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
-       int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
-       int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
-};
-
-struct pccard_resource_ops {
-       int     (*validate_mem)         (struct pcmcia_socket *s);
-       int     (*adjust_io_region)     (struct resource *res,
-                                        unsigned long r_start,
-                                        unsigned long r_end,
-                                        struct pcmcia_socket *s);
-       struct resource* (*find_io)     (unsigned long base, int num,
-                                        unsigned long align,
-                                        struct pcmcia_socket *s);
-       struct resource* (*find_mem)    (unsigned long base, unsigned long num,
-                                        unsigned long align, int low,
-                                        struct pcmcia_socket *s);
-       int     (*add_io)               (struct pcmcia_socket *s,
-                                        unsigned int action,
-                                        unsigned long r_start,
-                                        unsigned long r_end);
-       int     (*add_mem)              (struct pcmcia_socket *s,
-                                        unsigned int action,
-                                        unsigned long r_start,
-                                        unsigned long r_end);
-       int     (*init)                 (struct pcmcia_socket *s);
-       void    (*exit)                 (struct pcmcia_socket *s);
-};
-/* SS_CAP_STATIC_MAP */
-extern struct pccard_resource_ops pccard_static_ops;
-/* !SS_CAP_STATIC_MAP */
-extern struct pccard_resource_ops pccard_nonstatic_ops;
-
-/* static mem, dynamic IO sockets */
-extern struct pccard_resource_ops pccard_iodyn_ops;
-
-/*
- *  Calls to set up low-level "Socket Services" drivers
- */
-struct pcmcia_socket;
-
 typedef struct io_window_t {
        u_int                   InUse, Config;
        struct resource         *res;
@@ -179,10 +122,25 @@ typedef struct window_t {
 /* Maximum number of memory windows per socket */
 #define MAX_WIN 4
 
+
+/*
+ * Socket operations.
+ */
+struct pcmcia_socket;
+struct pccard_resource_ops;
 struct config_t;
 struct pcmcia_callback;
 struct user_info_t;
 
+struct pccard_operations {
+       int (*init)(struct pcmcia_socket *s);
+       int (*suspend)(struct pcmcia_socket *s);
+       int (*get_status)(struct pcmcia_socket *s, u_int *value);
+       int (*set_socket)(struct pcmcia_socket *s, socket_state_t *state);
+       int (*set_io_map)(struct pcmcia_socket *s, struct pccard_io_map *io);
+       int (*set_mem_map)(struct pcmcia_socket *s, struct pccard_mem_map *mem);
+};
+
 struct pcmcia_socket {
        struct module                   *owner;
        spinlock_t                      lock;
@@ -199,8 +157,8 @@ struct pcmcia_socket {
        io_window_t                     io[MAX_IO_WIN];
        window_t                        win[MAX_WIN];
        struct list_head                cis_cache;
-       u_int                           fake_cis_len;
-       char                            *fake_cis;
+       size_t                          fake_cis_len;
+       u8                              *fake_cis;
 
        struct list_head                socket_list;
        struct completion               socket_released;
@@ -218,12 +176,12 @@ struct pcmcia_socket {
        struct pci_dev *                cb_dev;
 
 
-       /* socket setup is done so resources should be able to be allocated. Only
-        * if set to 1, calls to find_{io,mem}_region are handled, and insertion
-        * events are actually managed by the PCMCIA layer.*/
+       /* socket setup is done so resources should be able to be allocated.
+        * Only if set to 1, calls to find_{io,mem}_region are handled, and
+        * insertio events are actually managed by the PCMCIA layer.*/
        u8                              resource_setup_done:1;
 
-       /* is set to one if resource setup is done using adjust_resource_info() */
+       /* It's old if resource setup is done using adjust_resource_info() */
        u8                              resource_setup_old:1;
        u8                              resource_setup_new:1;
 
@@ -236,75 +194,101 @@ struct pcmcia_socket {
 
        /* Zoom video behaviour is so chip specific its not worth adding
           this to _ops */
-       void                            (*zoom_video)(struct pcmcia_socket *, int);
+       void                            (*zoom_video)(struct pcmcia_socket *,
+                                                     int);
 
        /* so is power hook */
        int (*power_hook)(struct pcmcia_socket *sock, int operation);
-#ifdef CONFIG_CARDBUS
+
        /* allows tuning the CB bridge before loading driver for the CB card */
+#ifdef CONFIG_CARDBUS
        void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus);
 #endif
 
        /* state thread */
-       struct mutex                    skt_mutex;      /* protects socket h/w state */
-
        struct task_struct              *thread;
        struct completion               thread_done;
-       spinlock_t                      thread_lock;    /* protects thread_events */
        unsigned int                    thread_events;
+       /* protects socket h/w state */
+       struct mutex                    skt_mutex;
+       /* protects thread_events */
+       spinlock_t                      thread_lock;
 
        /* pcmcia (16-bit) */
        struct pcmcia_callback          *callback;
 
 #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
-       struct list_head                devices_list;   /*  PCMCIA devices */
-       u8                              device_count;   /* the number of devices, used
-                                                        * only internally and subject
-                                                        * to incorrectness and change */
+       /* The following elements refer to 16-bit PCMCIA devices inserted
+        * into the socket */
+       struct list_head                devices_list;
+
+       /* the number of devices, used only internally and subject to
+        * incorrectness and change */
+       u8                              device_count;
 
+       /* 16-bit state: */
        struct {
-               u8                      present:1,      /* PCMCIA card is present in socket */
-                                       busy:1,         /* "master" ioctl is used */
-                                       dead:1,         /* pcmcia module is being unloaded */
-                                       device_add_pending:1, /* a multifunction-device
-                                                              * add event is pending */
-                                       mfc_pfc:1,      /* the pending event adds a mfc (1) or pfc (0) */
-                                       reserved:3;
-       }                               pcmcia_state;
-
-       struct work_struct              device_add;     /* for adding further pseudo-multifunction
-                                                        * devices */
+               /* PCMCIA card is present in socket */
+               u8                      present:1;
+               /* "master" ioctl is used */
+               u8                      busy:1;
+               /* pcmcia module is being unloaded */
+               u8                      dead:1;
+               /* a multifunction-device add event is pending */
+               u8                      device_add_pending:1;
+               /* the pending event adds a mfc (1) or pfc (0) */
+               u8                      mfc_pfc:1;
+
+               u8                      reserved:3;
+       } pcmcia_state;
+
+
+       /* for adding further pseudo-multifunction devices */
+       struct work_struct              device_add;
 
 #ifdef CONFIG_PCMCIA_IOCTL
        struct user_info_t              *user;
        wait_queue_head_t               queue;
-#endif
-#endif
+#endif /* CONFIG_PCMCIA_IOCTL */
+#endif /* CONFIG_PCMCIA */
 
        /* cardbus (32-bit) */
 #ifdef CONFIG_CARDBUS
        struct resource *               cb_cis_res;
        void __iomem                    *cb_cis_virt;
-#endif
+#endif /* CONFIG_CARDBUS */
 
        /* socket device */
        struct device                   dev;
-       void                            *driver_data;   /* data internal to the socket driver */
-
+       /* data internal to the socket driver */
+       void                            *driver_data;
 };
 
-struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr);
 
+/* socket drivers must define the resource operations type they use. There
+ * are three options:
+ * - pccard_static_ops         iomem and ioport areas are assigned statically
+ * - pccard_iodyn_ops          iomem areas is assigned statically, ioport
+ *                             areas dynamically
+ * - pccard_nonstatic_ops      iomem and ioport areas are assigned dynamically.
+ *                             If this option is selected, use
+ *                             "select PCCARD_NONSTATIC" in Kconfig.
+ */
+extern struct pccard_resource_ops pccard_static_ops;
+extern struct pccard_resource_ops pccard_iodyn_ops;
+extern struct pccard_resource_ops pccard_nonstatic_ops;
 
+/* socket drivers are expected to use these callbacks in their .drv struct */
+extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
+extern int pcmcia_socket_dev_resume(struct device *dev);
+
+/* socket drivers use this callback in their IRQ handler */
+extern void pcmcia_parse_events(struct pcmcia_socket *socket,
+                               unsigned int events);
 
-extern void pcmcia_parse_events(struct pcmcia_socket *socket, unsigned int events);
+/* to register and unregister a socket */
 extern int pcmcia_register_socket(struct pcmcia_socket *socket);
 extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
 
-extern struct class pcmcia_socket_class;
-
-/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
-extern int pcmcia_socket_dev_resume(struct device *dev);
 
 #endif /* _LINUX_SS_H */
index c1b26fcc0b5c81e8950c77230675bf9314b2c2a8..ca699a3017f39563fc8f6b1d4dc36841e724f125 100644 (file)
@@ -240,6 +240,7 @@ int snd_soc_dapm_sys_add(struct device *dev);
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 
index b62ce3e077f9176274b80156afdafcd027edfe0c..b6870cbaf2b38812e6bc77c24ce7a7e416eadd3f 100644 (file)
@@ -43,6 +43,7 @@ struct snd_tea575x {
        unsigned int freq_fixup;        /* crystal onboard */
        unsigned int val;               /* hw value */
        unsigned long freq;             /* frequency */
+       unsigned long in_use;           /* set if the device is in use */
        struct snd_tea575x_ops *ops;
        void *private_data;
 };
index 717440575380e3a0af91b230eac8f33bad15893a..d3c1d4e2c8e3a7f1f62d60d3d678e270fd374567 100644 (file)
@@ -4,7 +4,7 @@
 #endif
 
 #if CYBLAFB_DEBUG
-#define debug(f,a...)  printk("%s:" f,  __FUNCTION__ , ## a);
+#define debug(f,a...)  printk("%s:" f,  __func__ , ## a);
 #else
 #define debug(f,a...)
 #endif
index 38910da0ae59f083c27312674413c73e4a32034b..08b663782956a3aa3f295acc17c7bf581173ca83 100644 (file)
@@ -123,7 +123,6 @@ typedef volatile struct {
 
 struct neofb_par {
        struct vgastate state;
-       struct mutex open_lock;
        unsigned int ref_count;
 
        unsigned char MiscOutReg;       /* Misc */
index 099ffa5e5bee9b75195850977b5b6e4ef2240014..d5dcaf154ba4092412cb45e59bebebe5c6d23c5f 100644 (file)
 #define SC_BOTTOM_RIGHT                        0x16F0  
 #define SRC_SC_BOTTOM_RIGHT                    0x16F4  
 #define RB2D_DSTCACHE_MODE                    0x3428
-#define RB2D_DSTCACHE_CTLSTAT                 0x342C
+#define RB2D_DSTCACHE_CTLSTAT_broken          0x342C /* do not use */
 #define LVDS_GEN_CNTL                         0x02d0
 #define LVDS_PLL_CNTL                         0x02d4
 #define FP2_GEN_CNTL                           0x0288
 #define CRTC_DISPLAY_DIS                          (1 << 10)
 #define CRTC_CRT_ON                               (1 << 15)
 
+/* DSTCACHE_MODE bits constants */
+#define RB2D_DC_AUTOFLUSH_ENABLE                   (1 << 8)
+#define RB2D_DC_DC_DISABLE_IGNORE_PE               (1 << 17)
 
 /* DSTCACHE_CTLSTAT bit constants */
 #define RB2D_DC_FLUSH_2D                          (1 << 0)
 #define RB2D_DC_FLUSH_ALL                         (RB2D_DC_FLUSH_2D | RB2D_DC_FREE_2D)
 #define RB2D_DC_BUSY                              (1 << 31)
 
+/* DSTCACHE_MODE bits constants */
+#define RB2D_DC_AUTOFLUSH_ENABLE                   (1 << 8)
+#define RB2D_DC_DC_DISABLE_IGNORE_PE               (1 << 17)
 
 /* CRTC_GEN_CNTL bit constants */
 #define CRTC_DBL_SCAN_EN                           0x00000001
 #define GMC_DST_16BPP_YVYU422                      0x00000c00
 #define GMC_DST_32BPP_AYUV444                      0x00000e00
 #define GMC_DST_16BPP_ARGB4444                     0x00000f00
-#define GMC_SRC_MONO                               0x00000000
-#define GMC_SRC_MONO_LBKGD                         0x00001000
-#define GMC_SRC_DSTCOLOR                           0x00003000
 #define GMC_BYTE_ORDER_MSB_TO_LSB                  0x00000000
 #define GMC_BYTE_ORDER_LSB_TO_MSB                  0x00004000
 #define GMC_DP_CONVERSION_TEMP_9300                0x00008000
 #define GMC_DP_CONVERSION_TEMP_6500                0x00000000
-#define GMC_DP_SRC_RECT                            0x02000000
-#define GMC_DP_SRC_HOST                            0x03000000
 #define GMC_DP_SRC_HOST_BYTEALIGN                  0x04000000
 #define GMC_3D_FCN_EN_CLR                          0x00000000
 #define GMC_3D_FCN_EN_SET                          0x08000000
 #define GMC_WRITE_MASK_LEAVE                       0x00000000
 #define GMC_WRITE_MASK_SET                         0x40000000
 #define GMC_CLR_CMP_CNTL_DIS                      (1 << 28)
+#define GMC_SRC_DATATYPE_MASK                     (3 << 12)
+#define GMC_SRC_DATATYPE_MONO_FG_BG               (0 << 12)
+#define GMC_SRC_DATATYPE_MONO_FG_LA               (1 << 12)
 #define GMC_SRC_DATATYPE_COLOR                    (3 << 12)
 #define ROP3_S                                    0x00cc0000
 #define ROP3_SRCCOPY                              0x00cc0000
 #define DP_SRC_SOURCE_MASK                        (7    << 24)
 #define GMC_BRUSH_NONE                            (15   <<  4)
 #define DP_SRC_SOURCE_MEMORY                      (2    << 24)
+#define DP_SRC_SOURCE_HOST_DATA                           (3    << 24)
 #define GMC_BRUSH_SOLIDCOLOR                      0x000000d0
 
 /* DP_MIX bit constants */
 #define DISP_PWR_MAN_TV_ENABLE_RST                 (1 << 25)
 #define DISP_PWR_MAN_AUTO_PWRUP_EN                 (1 << 26)
 
+/* RBBM_GUICNTL constants */
+#define RBBM_GUICNTL_HOST_DATA_SWAP_NONE          (0 << 0)
+#define RBBM_GUICNTL_HOST_DATA_SWAP_16BIT          (1 << 0)
+#define RBBM_GUICNTL_HOST_DATA_SWAP_32BIT         (2 << 0)
+#define RBBM_GUICNTL_HOST_DATA_SWAP_HDW                   (3 << 0)
+
 /* masks */
 
 #define CONFIG_MEMSIZE_MASK            0x1f000000
index c99d261df8f72adbb034fec1970ee5ff2b2c9ded..fe41b84079460033618a0598fa424aefc6c55576 100644 (file)
@@ -14,7 +14,8 @@
 #define        S1D13XXXFB_H
 
 #define S1D_PALETTE_SIZE               256
-#define S1D_CHIP_REV                   7       /* expected chip revision number for s1d13806 */
+#define S1D13506_CHIP_REV              4       /* expected chip revision number for s1d13506 */
+#define S1D13806_CHIP_REV              7       /* expected chip revision number for s1d13806 */
 #define S1D_FBID                       "S1D13806"
 #define S1D_DEVICENAME                 "s1d13806fb"
 
index c11da38837e5b7bef935297d3ec0da85c90e1fd7..5ceff3249a2d84cd23110b99fb3f8a076e8cf56c 100644 (file)
@@ -713,6 +713,14 @@ config SHMEM
          option replaces shmem and tmpfs with the much simpler ramfs code,
          which may be appropriate on small systems without swap.
 
+config AIO
+       bool "Enable AIO support" if EMBEDDED
+       default y
+       help
+         This option enables POSIX asynchronous I/O which may by used
+          by some high performance threaded applications. Disabling
+          this option saves about 7k.
+
 config VM_EVENT_COUNTERS
        default y
        bool "Enable VM event counters for /proc/vmstat" if EMBEDDED
@@ -779,16 +787,6 @@ config MARKERS
 
 source "arch/Kconfig"
 
-config PROC_PAGE_MONITOR
-       default y
-       depends on PROC_FS && MMU
-       bool "Enable /proc page monitoring" if EMBEDDED
-       help
-         Various /proc files exist to monitor process memory utilization:
-         /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
-         /proc/kpagecount, and /proc/kpageflags. Disabling these
-          interfaces will reduce the size of the kernel by approximately 4kb.
-
 endmenu                # General setup
 
 config HAVE_GENERIC_DMA_COHERENT
index 693d24694a6c9f1839a4f7f2f7828f4671d16459..4c87ee1fe5d30fe1783f0800fde7e3888aad298e 100644 (file)
@@ -1,5 +1,6 @@
 
 #include <linux/raid/md.h>
+#include <linux/delay.h>
 
 #include "do_mounts.h"
 
  * The code for that is here.
  */
 
-static int __initdata raid_noautodetect, raid_autopart;
+#ifdef CONFIG_MD_AUTODETECT
+static int __initdata raid_noautodetect;
+#else
+static int __initdata raid_noautodetect=1;
+#endif
+static int __initdata raid_autopart;
 
 static struct {
        int minor;
@@ -252,6 +258,8 @@ static int __init raid_setup(char *str)
 
                if (!strncmp(str, "noautodetect", wlen))
                        raid_noautodetect = 1;
+               if (!strncmp(str, "autodetect", wlen))
+                       raid_noautodetect = 0;
                if (strncmp(str, "partitionable", wlen)==0)
                        raid_autopart = 1;
                if (strncmp(str, "part", wlen)==0)
@@ -264,17 +272,32 @@ static int __init raid_setup(char *str)
 __setup("raid=", raid_setup);
 __setup("md=", md_setup);
 
+static void autodetect_raid(void)
+{
+       int fd;
+
+       /*
+        * Since we don't want to detect and use half a raid array, we need to
+        * wait for the known devices to complete their probing
+        */
+       printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
+       printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
+       while (driver_probe_done() < 0)
+               msleep(100);
+       fd = sys_open("/dev/md0", 0, 0);
+       if (fd >= 0) {
+               sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
+               sys_close(fd);
+       }
+}
+
 void __init md_run_setup(void)
 {
        create_dev("/dev/md0", MKDEV(MD_MAJOR, 0));
+
        if (raid_noautodetect)
-               printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n");
-       else {
-               int fd = sys_open("/dev/md0", 0, 0);
-               if (fd >= 0) {
-                       sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
-                       sys_close(fd);
-               }
-       }
+               printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=autodetect will force)\n");
+       else
+               autodetect_raid();
        md_setup_drive();
 }
index fedef93b586fad4146bf1f1cfd04dffbb012c0e1..a7c748fa977a44c2887ad9fcaee3beddf8d4f45e 100644 (file)
@@ -71,7 +71,7 @@ identify_ramdisk_image(int fd, int start_block)
        sys_read(fd, buf, size);
 
        /*
-        * If it matches the gzip magic numbers, return -1
+        * If it matches the gzip magic numbers, return 0
         */
        if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
                printk(KERN_NOTICE
index 644fc01ad5f05244f3f3012becffda2326b2b65d..4f5ba75aaa7c67d1d80754e6b0be67f68151dfda 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/syscalls.h>
+#include <linux/utime.h>
 
 static __initdata char *message;
 static void __init error(char *x)
@@ -72,6 +73,49 @@ static void __init free_hash(void)
        }
 }
 
+static long __init do_utime(char __user *filename, time_t mtime)
+{
+       struct timespec t[2];
+
+       t[0].tv_sec = mtime;
+       t[0].tv_nsec = 0;
+       t[1].tv_sec = mtime;
+       t[1].tv_nsec = 0;
+
+       return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW);
+}
+
+static __initdata LIST_HEAD(dir_list);
+struct dir_entry {
+       struct list_head list;
+       char *name;
+       time_t mtime;
+};
+
+static void __init dir_add(const char *name, time_t mtime)
+{
+       struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
+       if (!de)
+               panic("can't allocate dir_entry buffer");
+       INIT_LIST_HEAD(&de->list);
+       de->name = kstrdup(name, GFP_KERNEL);
+       de->mtime = mtime;
+       list_add(&de->list, &dir_list);
+}
+
+static void __init dir_utime(void)
+{
+       struct dir_entry *de, *tmp;
+       list_for_each_entry_safe(de, tmp, &dir_list, list) {
+               list_del(&de->list);
+               do_utime(de->name, de->mtime);
+               kfree(de->name);
+               kfree(de);
+       }
+}
+
+static __initdata time_t mtime;
+
 /* cpio header parsing */
 
 static __initdata unsigned long ino, major, minor, nlink;
@@ -97,6 +141,7 @@ static void __init parse_header(char *s)
        uid = parsed[2];
        gid = parsed[3];
        nlink = parsed[4];
+       mtime = parsed[5];
        body_len = parsed[6];
        major = parsed[7];
        minor = parsed[8];
@@ -130,6 +175,7 @@ static inline void __init eat(unsigned n)
        count -= n;
 }
 
+static __initdata char *vcollected;
 static __initdata char *collected;
 static __initdata int remains;
 static __initdata char *collect;
@@ -271,6 +317,7 @@ static int __init do_name(void)
                        if (wfd >= 0) {
                                sys_fchown(wfd, uid, gid);
                                sys_fchmod(wfd, mode);
+                               vcollected = kstrdup(collected, GFP_KERNEL);
                                state = CopyFile;
                        }
                }
@@ -278,12 +325,14 @@ static int __init do_name(void)
                sys_mkdir(collected, mode);
                sys_chown(collected, uid, gid);
                sys_chmod(collected, mode);
+               dir_add(collected, mtime);
        } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
                if (maybe_link() == 0) {
                        sys_mknod(collected, mode, rdev);
                        sys_chown(collected, uid, gid);
                        sys_chmod(collected, mode);
+                       do_utime(collected, mtime);
                }
        }
        return 0;
@@ -294,6 +343,8 @@ static int __init do_copy(void)
        if (count >= body_len) {
                sys_write(wfd, victim, body_len);
                sys_close(wfd);
+               do_utime(vcollected, mtime);
+               kfree(vcollected);
                eat(body_len);
                state = SkipIt;
                return 0;
@@ -311,6 +362,7 @@ static int __init do_symlink(void)
        clean_path(collected, 0);
        sys_symlink(collected + N_ALIGN(name_len), collected);
        sys_lchown(collected, uid, gid);
+       do_utime(collected, mtime);
        state = SkipIt;
        next_state = Reset;
        return 0;
@@ -466,6 +518,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
                buf += inptr;
                len -= inptr;
        }
+       dir_utime();
        kfree(window);
        kfree(name_buf);
        kfree(symlink_buf);
index 3820323c4c8467c07831a8844532fb85976e9a9f..27f6bf6108e96908b10df5b20e0011aaebb3266c 100644 (file)
@@ -708,7 +708,7 @@ int do_one_initcall(initcall_t fn)
        int result;
 
        if (initcall_debug) {
-               printk("calling  %pF\n", fn);
+               printk("calling  %pF @ %i\n", fn, task_pid_nr(current));
                t0 = ktime_get();
        }
 
index 69bc85978ba0bb04f0f77745cfa842aea69b7c76..0dfebc5094264fce2c95d62dfc5ff432eee5db58 100644 (file)
@@ -131,7 +131,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 /* The generic sysctl ipc data routine. */
-static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
+static int sysctl_ipc_data(ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
@@ -169,14 +169,13 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
        return 1;
 }
 
-static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
-               int nlen, void __user *oldval, size_t __user *oldlenp,
+static int sysctl_ipc_registered_data(ctl_table *table,
+               void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
        int rc;
 
-       rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval,
-               newlen);
+       rc = sysctl_ipc_data(table, oldval, oldlenp, newval, newlen);
 
        if (newval && newlen && rc > 0)
                /*
index bf1bc36cb7ee62bc95021ba62253d5b667802952..082122469b17490c1d0a1b634055efc079be81c1 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -504,7 +504,7 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
        return semzcnt;
 }
 
-void free_un(struct rcu_head *head)
+static void free_un(struct rcu_head *head)
 {
        struct sem_undo *un = container_of(head, struct sem_undo, rcu);
        kfree(un);
index dd68b905941818df3253e6f60558a49b9fbf2ef4..f6006a60df5ddff73990656f73ea7fff55dcf9b8 100644 (file)
@@ -548,7 +548,7 @@ static void do_acct_process(struct bsd_acct_struct *acct,
 #endif
 
        spin_lock_irq(&current->sighand->siglock);
-       tty = current->signal->tty;
+       tty = current->signal->tty;     /* Safe as we hold the siglock */
        ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0;
        ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
        ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime)));
index 59cedfb040e7864cdfa3199ae2557f236cdd1122..cf5bc2f5f9c3e527ac2ea72ec019d156be72ecb6 100644 (file)
@@ -246,8 +246,8 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
        unsigned n;
        if (unlikely(!ctx))
                return 0;
-
        n = ctx->major;
+
        switch (audit_classify_syscall(ctx->arch, n)) {
        case 0: /* native */
                if ((mask & AUDIT_PERM_WRITE) &&
@@ -1204,13 +1204,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
 
-       mutex_lock(&tty_mutex);
-       read_lock(&tasklist_lock);
+       spin_lock_irq(&tsk->sighand->siglock);
        if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
                tty = tsk->signal->tty->name;
        else
                tty = "(none)";
-       read_unlock(&tasklist_lock);
+       spin_unlock_irq(&tsk->sighand->siglock);
+
        audit_log_format(ab,
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
                  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
@@ -1230,7 +1230,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->egid, context->sgid, context->fsgid, tty,
                  tsk->sessionid);
 
-       mutex_unlock(&tty_mutex);
 
        audit_log_task_info(ab, tsk);
        if (context->filterkey) {
index a0123d75ec9a7624f897bc2984ca4009b61abfbc..8c6e1c17e6d37faae0870c2d9ff5635c1e192037 100644 (file)
@@ -2735,6 +2735,8 @@ void cgroup_fork_callbacks(struct task_struct *child)
  * Called on every change to mm->owner. mm_init_owner() does not
  * invoke this routine, since it assigns the mm->owner the first time
  * and does not change it.
+ *
+ * The callbacks are invoked with mmap_sem held in read mode.
  */
 void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
 {
@@ -2750,7 +2752,7 @@ void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
                        if (oldcgrp == newcgrp)
                                continue;
                        if (ss->mm_owner_changed)
-                               ss->mm_owner_changed(ss, oldcgrp, newcgrp);
+                               ss->mm_owner_changed(ss, oldcgrp, newcgrp, new);
                }
        }
 }
index 32c254a8ab9af07ae3ac102972063956592e0b3b..143990e48cb9aab2af2f04d93a372d63dc570882 100644 (file)
 
 #include <asm/uaccess.h>
 
+/*
+ * Note that the native side is already converted to a timespec, because
+ * that's what we want anyway.
+ */
+static int compat_get_timeval(struct timespec *o,
+               struct compat_timeval __user *i)
+{
+       long usec;
+
+       if (get_user(o->tv_sec, &i->tv_sec) ||
+           get_user(usec, &i->tv_usec))
+               return -EFAULT;
+       o->tv_nsec = usec * 1000;
+       return 0;
+}
+
+static int compat_put_timeval(struct compat_timeval __user *o,
+               struct timeval *i)
+{
+       return (put_user(i->tv_sec, &o->tv_sec) ||
+               put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
+}
+
+asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
+               struct timezone __user *tz)
+{
+       if (tv) {
+               struct timeval ktv;
+               do_gettimeofday(&ktv);
+               if (compat_put_timeval(tv, &ktv))
+                       return -EFAULT;
+       }
+       if (tz) {
+               if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+                       return -EFAULT;
+       }
+
+       return 0;
+}
+
+asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
+               struct timezone __user *tz)
+{
+       struct timespec kts;
+       struct timezone ktz;
+
+       if (tv) {
+               if (compat_get_timeval(&kts, tv))
+                       return -EFAULT;
+       }
+       if (tz) {
+               if (copy_from_user(&ktz, tz, sizeof(ktz)))
+                       return -EFAULT;
+       }
+
+       return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+}
+
 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
        return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
index d2c60a82279085e80d0a46edbc0a3557e9b87f83..f903189c530440395417f7b873aff50e9936dc47 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: dma.c,v 1.7 1994/12/28 03:35:33 root Exp root $
+/*
  * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
  *
  * Written by Hennus Bergman, 1992.
index 85a83c831856c193570e40a3b7d3e03ef8862d1c..0ef4673e351bddd4e738f88941511efa02f062fa 100644 (file)
@@ -640,24 +640,23 @@ retry:
 assign_new_owner:
        BUG_ON(c == p);
        get_task_struct(c);
+       read_unlock(&tasklist_lock);
+       down_write(&mm->mmap_sem);
        /*
         * The task_lock protects c->mm from changing.
         * We always want mm->owner->mm == mm
         */
        task_lock(c);
-       /*
-        * Delay read_unlock() till we have the task_lock()
-        * to ensure that c does not slip away underneath us
-        */
-       read_unlock(&tasklist_lock);
        if (c->mm != mm) {
                task_unlock(c);
+               up_write(&mm->mmap_sem);
                put_task_struct(c);
                goto retry;
        }
        cgroup_mm_owner_callbacks(mm->owner, c);
        mm->owner = c;
        task_unlock(c);
+       up_write(&mm->mmap_sem);
        put_task_struct(c);
 }
 #endif /* CONFIG_MM_OWNER */
index 7ce2ebe847964ecd0701c3c74c18994e3eebcf26..30de644a40c4d4d9617d650589f4c90da1e977a2 100644 (file)
@@ -802,6 +802,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 
        sig->leader = 0;        /* session leadership doesn't inherit */
        sig->tty_old_pgrp = NULL;
+       sig->tty = NULL;
 
        sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
        sig->gtime = cputime_zero;
@@ -838,6 +839,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 void __cleanup_signal(struct signal_struct *sig)
 {
        exit_thread_group_keys(sig);
+       tty_kref_put(sig->tty);
        kmem_cache_free(signal_cachep, sig);
 }
 
@@ -1227,7 +1229,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                                p->nsproxy->pid_ns->child_reaper = p;
 
                        p->signal->leader_pid = pid;
-                       p->signal->tty = current->signal->tty;
+                       tty_kref_put(p->signal->tty);
+                       p->signal->tty = tty_kref_get(current->signal->tty);
                        set_task_pgrp(p, task_pgrp_nr(current));
                        set_task_session(p, task_session_nr(current));
                        attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
index 38fc10ac75415a8ff4da69b68d90facf61eb5e41..5072cf1685a27ca9fc78986e3438ab53baa882a4 100644 (file)
@@ -260,7 +260,6 @@ const char *kallsyms_lookup(unsigned long addr,
        /* see if it's in a module */
        return module_address_lookup(addr, symbolsize, offset, modname,
                                     namebuf);
-       return NULL;
 }
 
 int lookup_symbol_name(unsigned long addr, char *symname)
index 2456d1a0befbd45b91cd7cb7a97ae6d2fb270c4c..3d3c3ea3a023376f2ecf8c16b6c89aed39da67f4 100644 (file)
@@ -113,7 +113,7 @@ int request_module(const char *fmt, ...)
        return ret;
 }
 EXPORT_SYMBOL(request_module);
-#endif /* CONFIG_KMOD */
+#endif /* CONFIG_MODULES */
 
 struct subprocess_info {
        struct work_struct work;
@@ -265,7 +265,7 @@ static void __call_usermodehelper(struct work_struct *work)
        }
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 /*
  * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
  * (used for preventing user land processes from being created after the user
@@ -288,39 +288,37 @@ static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
  */
 #define RUNNING_HELPERS_TIMEOUT        (5 * HZ)
 
-static int usermodehelper_pm_callback(struct notifier_block *nfb,
-                                       unsigned long action,
-                                       void *ignored)
+/**
+ * usermodehelper_disable - prevent new helpers from being started
+ */
+int usermodehelper_disable(void)
 {
        long retval;
 
-       switch (action) {
-       case PM_HIBERNATION_PREPARE:
-       case PM_SUSPEND_PREPARE:
-               usermodehelper_disabled = 1;
-               smp_mb();
-               /*
-                * From now on call_usermodehelper_exec() won't start any new
-                * helpers, so it is sufficient if running_helpers turns out to
-                * be zero at one point (it may be increased later, but that
-                * doesn't matter).
-                */
-               retval = wait_event_timeout(running_helpers_waitq,
+       usermodehelper_disabled = 1;
+       smp_mb();
+       /*
+        * From now on call_usermodehelper_exec() won't start any new
+        * helpers, so it is sufficient if running_helpers turns out to
+        * be zero at one point (it may be increased later, but that
+        * doesn't matter).
+        */
+       retval = wait_event_timeout(running_helpers_waitq,
                                        atomic_read(&running_helpers) == 0,
                                        RUNNING_HELPERS_TIMEOUT);
-               if (retval) {
-                       return NOTIFY_OK;
-               } else {
-                       usermodehelper_disabled = 0;
-                       return NOTIFY_BAD;
-               }
-       case PM_POST_HIBERNATION:
-       case PM_POST_SUSPEND:
-               usermodehelper_disabled = 0;
-               return NOTIFY_OK;
-       }
+       if (retval)
+               return 0;
 
-       return NOTIFY_DONE;
+       usermodehelper_disabled = 0;
+       return -EAGAIN;
+}
+
+/**
+ * usermodehelper_enable - allow new helpers to be started again
+ */
+void usermodehelper_enable(void)
+{
+       usermodehelper_disabled = 0;
 }
 
 static void helper_lock(void)
@@ -334,18 +332,12 @@ static void helper_unlock(void)
        if (atomic_dec_and_test(&running_helpers))
                wake_up(&running_helpers_waitq);
 }
-
-static void register_pm_notifier_callback(void)
-{
-       pm_notifier(usermodehelper_pm_callback, 0);
-}
-#else /* CONFIG_PM */
+#else /* CONFIG_PM_SLEEP */
 #define usermodehelper_disabled        0
 
 static inline void helper_lock(void) {}
 static inline void helper_unlock(void) {}
-static inline void register_pm_notifier_callback(void) {}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 /**
  * call_usermodehelper_setup - prepare to call a usermode helper
@@ -515,5 +507,4 @@ void __init usermodehelper_init(void)
 {
        khelper_wq = create_singlethread_workqueue("khelper");
        BUG_ON(!khelper_wq);
-       register_pm_notifier_callback();
 }
index 75bc2cd9ebc6a7307aa15c404a914559bcab917b..8b57a2597f21fda9c9602e27028753f1f7325234 100644 (file)
@@ -404,7 +404,7 @@ void kretprobe_hash_lock(struct task_struct *tsk,
        spin_lock_irqsave(hlist_lock, *flags);
 }
 
-void kretprobe_table_lock(unsigned long hash, unsigned long *flags)
+static void kretprobe_table_lock(unsigned long hash, unsigned long *flags)
 {
        spinlock_t *hlist_lock = kretprobe_table_lock_ptr(hash);
        spin_lock_irqsave(hlist_lock, *flags);
index e53bc30e9ba5aa8b55311fd6700191b0f21a9597..08dd8ed86c77a7f7d05316a794f2eaf2f378c058 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
+#include <linux/profile.h>
 #include <linux/sched.h>
 
 #define KERNEL_ATTR_RO(_name) \
@@ -53,6 +54,37 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
 KERNEL_ATTR_RW(uevent_helper);
 #endif
 
+#ifdef CONFIG_PROFILING
+static ssize_t profiling_show(struct kobject *kobj,
+                                 struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", prof_on);
+}
+static ssize_t profiling_store(struct kobject *kobj,
+                                  struct kobj_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       int ret;
+
+       if (prof_on)
+               return -EEXIST;
+       /*
+        * This eventually calls into get_option() which
+        * has a ton of callers and is not const.  It is
+        * easiest to cast it away here.
+        */
+       profile_setup((char *)buf);
+       ret = profile_init();
+       if (ret)
+               return ret;
+       ret = create_proc_profile();
+       if (ret)
+               return ret;
+       return count;
+}
+KERNEL_ATTR_RW(profiling);
+#endif
+
 #ifdef CONFIG_KEXEC
 static ssize_t kexec_loaded_show(struct kobject *kobj,
                                 struct kobj_attribute *attr, char *buf)
@@ -109,6 +141,9 @@ static struct attribute * kernel_attrs[] = {
        &uevent_seqnum_attr.attr,
        &uevent_helper_attr.attr,
 #endif
+#ifdef CONFIG_PROFILING
+       &profiling_attr.attr,
+#endif
 #ifdef CONFIG_KEXEC
        &kexec_loaded_attr.attr,
        &kexec_crash_loaded_attr.attr,
index 9db11911e04b7b55df05fd9f928f5629fe46430d..b7205f67cfaf570aa4aee965cae7e953fec65a2f 100644 (file)
@@ -100,7 +100,7 @@ static inline int strong_try_module_get(struct module *mod)
 static inline void add_taint_module(struct module *mod, unsigned flag)
 {
        add_taint(flag);
-       mod->taints |= flag;
+       mod->taints |= (1U << flag);
 }
 
 /*
@@ -784,6 +784,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
        mutex_lock(&module_mutex);
        /* Store the name of the last unloaded module for diagnostic purposes */
        strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
+       unregister_dynamic_debug_module(mod->name);
        free_module(mod);
 
  out:
@@ -923,7 +924,7 @@ static const char vermagic[] = VERMAGIC_STRING;
 static int try_to_force_load(struct module *mod, const char *symname)
 {
 #ifdef CONFIG_MODULE_FORCE_LOAD
-       if (!(tainted & TAINT_FORCED_MODULE))
+       if (!test_taint(TAINT_FORCED_MODULE))
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
        add_taint_module(mod, TAINT_FORCED_MODULE);
@@ -1033,7 +1034,7 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
        const unsigned long *crc;
 
        ret = find_symbol(name, &owner, &crc,
-                         !(mod->taints & TAINT_PROPRIETARY_MODULE), true);
+                         !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
        if (!IS_ERR_VALUE(ret)) {
                /* use_module can fail due to OOM,
                   or module initialization or unloading */
@@ -1173,7 +1174,7 @@ static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
                while (i-- > 0)
                        sysfs_remove_bin_file(notes_attrs->dir,
                                              &notes_attrs->attrs[i]);
-               kobject_del(notes_attrs->dir);
+               kobject_put(notes_attrs->dir);
        }
        kfree(notes_attrs);
 }
@@ -1634,7 +1635,7 @@ static void set_license(struct module *mod, const char *license)
                license = "unspecified";
 
        if (!license_is_gpl_compatible(license)) {
-               if (!(tainted & TAINT_PROPRIETARY_MODULE))
+               if (!test_taint(TAINT_PROPRIETARY_MODULE))
                        printk(KERN_WARNING "%s: module license '%s' taints "
                                "kernel.\n", mod->name, license);
                add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
@@ -1783,6 +1784,33 @@ static inline void add_kallsyms(struct module *mod,
 }
 #endif /* CONFIG_KALLSYMS */
 
+#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
+{
+       struct mod_debug *debug_info;
+       unsigned long pos, end;
+       unsigned int num_verbose;
+
+       pos = sechdrs[verboseindex].sh_addr;
+       num_verbose = sechdrs[verboseindex].sh_size /
+                               sizeof(struct mod_debug);
+       end = pos + (num_verbose * sizeof(struct mod_debug));
+
+       for (; pos < end; pos += sizeof(struct mod_debug)) {
+               debug_info = (struct mod_debug *)pos;
+               register_dynamic_debug_module(debug_info->modname,
+                       debug_info->type, debug_info->logical_modname,
+                       debug_info->flag_names, debug_info->hash,
+                       debug_info->hash2);
+       }
+}
+#else
+static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
+                                       unsigned int verboseindex)
+{
+}
+#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
+
 static void *module_alloc_update_bounds(unsigned long size)
 {
        void *ret = module_alloc(size);
@@ -1831,6 +1859,7 @@ static noinline struct module *load_module(void __user *umod,
 #endif
        unsigned int markersindex;
        unsigned int markersstringsindex;
+       unsigned int verboseindex;
        struct module *mod;
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -2117,6 +2146,7 @@ static noinline struct module *load_module(void __user *umod,
        markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
        markersstringsindex = find_sec(hdr, sechdrs, secstrings,
                                        "__markers_strings");
+       verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
 
        /* Now do relocations. */
        for (i = 1; i < hdr->e_shnum; i++) {
@@ -2167,6 +2197,7 @@ static noinline struct module *load_module(void __user *umod,
                marker_update_probe_range(mod->markers,
                        mod->markers + mod->num_markers);
 #endif
+       dynamic_printk_setup(sechdrs, verboseindex);
        err = module_finalize(hdr, sechdrs, mod);
        if (err < 0)
                goto cleanup;
@@ -2552,9 +2583,9 @@ static char *module_flags(struct module *mod, char *buf)
            mod->state == MODULE_STATE_GOING ||
            mod->state == MODULE_STATE_COMING) {
                buf[bx++] = '(';
-               if (mod->taints & TAINT_PROPRIETARY_MODULE)
+               if (mod->taints & (1 << TAINT_PROPRIETARY_MODULE))
                        buf[bx++] = 'P';
-               if (mod->taints & TAINT_FORCED_MODULE)
+               if (mod->taints & (1 << TAINT_FORCED_MODULE))
                        buf[bx++] = 'F';
                /*
                 * TAINT_FORCED_RMMOD: could be added.
index 12c5a0a6c89bee42e44c65ee41eb4695ae180983..f290e8e866f65a636c324acfccc69954c2968bd1 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/kallsyms.h>
 
 int panic_on_oops;
-int tainted;
+static unsigned long tainted_mask;
 static int pause_on_oops;
 static int pause_on_oops_flag;
 static DEFINE_SPINLOCK(pause_on_oops_lock);
@@ -143,6 +143,26 @@ NORET_TYPE void panic(const char * fmt, ...)
 
 EXPORT_SYMBOL(panic);
 
+
+struct tnt {
+       u8 bit;
+       char true;
+       char false;
+};
+
+static const struct tnt tnts[] = {
+       { TAINT_PROPRIETARY_MODULE, 'P', 'G' },
+       { TAINT_FORCED_MODULE, 'F', ' ' },
+       { TAINT_UNSAFE_SMP, 'S', ' ' },
+       { TAINT_FORCED_RMMOD, 'R', ' ' },
+       { TAINT_MACHINE_CHECK, 'M', ' ' },
+       { TAINT_BAD_PAGE, 'B', ' ' },
+       { TAINT_USER, 'U', ' ' },
+       { TAINT_DIE, 'D', ' ' },
+       { TAINT_OVERRIDDEN_ACPI_TABLE, 'A', ' ' },
+       { TAINT_WARN, 'W', ' ' },
+};
+
 /**
  *     print_tainted - return a string to represent the kernel taint state.
  *
@@ -158,32 +178,41 @@ EXPORT_SYMBOL(panic);
  *
  *     The string is overwritten by the next call to print_taint().
  */
-
 const char *print_tainted(void)
 {
-       static char buf[20];
-       if (tainted) {
-               snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c%c",
-                       tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
-                       tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
-                       tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
-                       tainted & TAINT_FORCED_RMMOD ? 'R' : ' ',
-                       tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
-                       tainted & TAINT_BAD_PAGE ? 'B' : ' ',
-                       tainted & TAINT_USER ? 'U' : ' ',
-                       tainted & TAINT_DIE ? 'D' : ' ',
-                       tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ',
-                       tainted & TAINT_WARN ? 'W' : ' ');
-       }
-       else
+       static char buf[ARRAY_SIZE(tnts) + sizeof("Tainted: ") + 1];
+
+       if (tainted_mask) {
+               char *s;
+               int i;
+
+               s = buf + sprintf(buf, "Tainted: ");
+               for (i = 0; i < ARRAY_SIZE(tnts); i++) {
+                       const struct tnt *t = &tnts[i];
+                       *s++ = test_bit(t->bit, &tainted_mask) ?
+                                       t->true : t->false;
+               }
+               *s = 0;
+       } else
                snprintf(buf, sizeof(buf), "Not tainted");
        return(buf);
 }
 
+int test_taint(unsigned flag)
+{
+       return test_bit(flag, &tainted_mask);
+}
+EXPORT_SYMBOL(test_taint);
+
+unsigned long get_taint(void)
+{
+       return tainted_mask;
+}
+
 void add_taint(unsigned flag)
 {
        debug_locks = 0; /* can't trust the integrity of the kernel anymore */
-       tainted |= flag;
+       set_bit(flag, &tainted_mask);
 }
 EXPORT_SYMBOL(add_taint);
 
index bbd85c60f7419f5fca1cbf1d0b5d6e6aad37f625..331f9836383feaba687c89c3e4596edff76fb2fe 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/reboot.h>
 #include <linux/string.h>
 #include <linux/device.h>
+#include <linux/kmod.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -520,6 +521,10 @@ int hibernate(void)
        if (error)
                goto Exit;
 
+       error = usermodehelper_disable();
+       if (error)
+               goto Exit;
+
        /* Allocate memory management structures */
        error = create_basic_memory_bitmaps();
        if (error)
@@ -558,6 +563,7 @@ int hibernate(void)
        thaw_processes();
  Finish:
        free_basic_memory_bitmaps();
+       usermodehelper_enable();
  Exit:
        pm_notifier_call_chain(PM_POST_HIBERNATION);
        pm_restore_console();
@@ -634,6 +640,10 @@ static int software_resume(void)
        if (error)
                goto Finish;
 
+       error = usermodehelper_disable();
+       if (error)
+               goto Finish;
+
        error = create_basic_memory_bitmaps();
        if (error)
                goto Finish;
@@ -656,6 +666,7 @@ static int software_resume(void)
        thaw_processes();
  Done:
        free_basic_memory_bitmaps();
+       usermodehelper_enable();
  Finish:
        pm_notifier_call_chain(PM_POST_RESTORE);
        pm_restore_console();
index 540b16b68565e74fb9f51f68134f68cc3011b0a0..19122cf6d827d13d03e8a7520d0120d5adf92bbc 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/cpu.h>
@@ -237,6 +238,10 @@ static int suspend_prepare(void)
        if (error)
                goto Finish;
 
+       error = usermodehelper_disable();
+       if (error)
+               goto Finish;
+
        if (suspend_freeze_processes()) {
                error = -EAGAIN;
                goto Thaw;
@@ -256,6 +261,7 @@ static int suspend_prepare(void)
 
  Thaw:
        suspend_thaw_processes();
+       usermodehelper_enable();
  Finish:
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
@@ -376,6 +382,7 @@ int suspend_devices_and_enter(suspend_state_t state)
 static void suspend_finish(void)
 {
        suspend_thaw_processes();
+       usermodehelper_enable();
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
 }
index a6332a3132620b4563e3be8a0fbfb9639b1e5405..005b93d839ba1268da0c80c3106739ee388d996a 100644 (file)
@@ -212,13 +212,20 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
        case SNAPSHOT_FREEZE:
                if (data->frozen)
                        break;
+
                printk("Syncing filesystems ... ");
                sys_sync();
                printk("done.\n");
 
-               error = freeze_processes();
+               error = usermodehelper_disable();
                if (error)
+                       break;
+
+               error = freeze_processes();
+               if (error) {
                        thaw_processes();
+                       usermodehelper_enable();
+               }
                if (!error)
                        data->frozen = 1;
                break;
@@ -227,6 +234,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                if (!data->frozen || data->ready)
                        break;
                thaw_processes();
+               usermodehelper_enable();
                data->frozen = 0;
                break;
 
index b51b1567bb5570dfc5b4a19bffd5af865d254e77..6341af77eb65b559c1bf66e5cc7664b06779a694 100644 (file)
@@ -13,7 +13,7 @@
  * Fixed SMP synchronization, 08/08/99, Manfred Spraul
  *     manfred@colorfullife.com
  * Rewrote bits to get rid of console_lock
- *     01Mar01 Andrew Morton <andrewm@uow.edu.au>
+ *     01Mar01 Andrew Morton
  */
 
 #include <linux/kernel.h>
@@ -577,9 +577,6 @@ static int have_callable_console(void)
  * @fmt: format string
  *
  * This is printk().  It can be called from any context.  We want it to work.
- * Be aware of the fact that if oops_in_progress is not set, we might try to
- * wake klogd up which could deadlock on runqueue lock if printk() is called
- * from scheduler code.
  *
  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  * call the console drivers.  If we fail to get the semaphore we place the output
@@ -593,6 +590,8 @@ static int have_callable_console(void)
  *
  * See also:
  * printf(3)
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
  */
 
 asmlinkage int printk(const char *fmt, ...)
@@ -982,10 +981,25 @@ int is_console_locked(void)
        return console_locked;
 }
 
-void wake_up_klogd(void)
+static DEFINE_PER_CPU(int, printk_pending);
+
+void printk_tick(void)
 {
-       if (!oops_in_progress && waitqueue_active(&log_wait))
+       if (__get_cpu_var(printk_pending)) {
+               __get_cpu_var(printk_pending) = 0;
                wake_up_interruptible(&log_wait);
+       }
+}
+
+int printk_needs_cpu(int cpu)
+{
+       return per_cpu(printk_pending, cpu);
+}
+
+void wake_up_klogd(void)
+{
+       if (waitqueue_active(&log_wait))
+               __raw_get_cpu_var(printk_pending) = 1;
 }
 
 /**
@@ -1291,22 +1305,6 @@ static int __init disable_boot_consoles(void)
 }
 late_initcall(disable_boot_consoles);
 
-/**
- * tty_write_message - write a message to a certain tty, not just the console.
- * @tty: the destination tty_struct
- * @msg: the message to write
- *
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
- */
-void tty_write_message(struct tty_struct *tty, char *msg)
-{
-       if (tty && tty->ops->write)
-               tty->ops->write(tty, msg, strlen(msg));
-       return;
-}
-
 #if defined CONFIG_PRINTK
 
 /*
index cd26bed4cc26535ca7398eae07fb9b800b762f2e..a9e422df6bf63e28648432efa7f0503aa09ffe8f 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/cpu.h>
 #include <linux/highmem.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <asm/sections.h>
 #include <asm/irq_regs.h>
 #include <asm/ptrace.h>
@@ -50,11 +52,11 @@ static DEFINE_PER_CPU(int, cpu_profile_flip);
 static DEFINE_MUTEX(profile_flip_mutex);
 #endif /* CONFIG_SMP */
 
-static int __init profile_setup(char *str)
+int profile_setup(char *str)
 {
-       static char __initdata schedstr[] = "schedule";
-       static char __initdata sleepstr[] = "sleep";
-       static char __initdata kvmstr[] = "kvm";
+       static char schedstr[] = "schedule";
+       static char sleepstr[] = "sleep";
+       static char kvmstr[] = "kvm";
        int par;
 
        if (!strncmp(str, sleepstr, strlen(sleepstr))) {
@@ -100,14 +102,33 @@ static int __init profile_setup(char *str)
 __setup("profile=", profile_setup);
 
 
-void __init profile_init(void)
+int profile_init(void)
 {
+       int buffer_bytes;
        if (!prof_on)
-               return;
+               return 0;
 
        /* only text is profiled */
        prof_len = (_etext - _stext) >> prof_shift;
-       prof_buffer = alloc_bootmem(prof_len*sizeof(atomic_t));
+       buffer_bytes = prof_len*sizeof(atomic_t);
+       if (!slab_is_available()) {
+               prof_buffer = alloc_bootmem(buffer_bytes);
+               return 0;
+       }
+
+       prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL);
+       if (prof_buffer)
+               return 0;
+
+       prof_buffer = alloc_pages_exact(buffer_bytes, GFP_KERNEL|__GFP_ZERO);
+       if (prof_buffer)
+               return 0;
+
+       prof_buffer = vmalloc(buffer_bytes);
+       if (prof_buffer)
+               return 0;
+
+       return -ENOMEM;
 }
 
 /* Profile event notifications */
@@ -527,7 +548,7 @@ static void __init profile_nop(void *unused)
 {
 }
 
-static int __init create_hash_tables(void)
+static int create_hash_tables(void)
 {
        int cpu;
 
@@ -575,14 +596,14 @@ out_cleanup:
 #define create_hash_tables()                   ({ 0; })
 #endif
 
-static int __init create_proc_profile(void)
+int create_proc_profile(void)
 {
        struct proc_dir_entry *entry;
 
        if (!prof_on)
                return 0;
        if (create_hash_tables())
-               return -1;
+               return -ENOMEM;
        entry = proc_create("profile", S_IWUSR | S_IRUGO,
                            NULL, &proc_profile_operations);
        if (!entry)
index 414d6fc9131ea3dde1c98087d9cd4ede65cf19f1..4089d12af6e0eda2aa15cc8c145940f1bd12056c 100644 (file)
@@ -38,10 +38,6 @@ EXPORT_SYMBOL(iomem_resource);
 
 static DEFINE_RWLOCK(resource_lock);
 
-#ifdef CONFIG_PROC_FS
-
-enum { MAX_IORES_LEVEL = 5 };
-
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct resource *p = v;
@@ -53,6 +49,10 @@ static void *r_next(struct seq_file *m, void *v, loff_t *pos)
        return p->sibling;
 }
 
+#ifdef CONFIG_PROC_FS
+
+enum { MAX_IORES_LEVEL = 5 };
+
 static void *r_start(struct seq_file *m, loff_t *pos)
        __acquires(resource_lock)
 {
@@ -549,13 +549,9 @@ static void __init __reserve_region_with_split(struct resource *root,
        }
 
        if (!res) {
-               printk(KERN_DEBUG "    __reserve_region_with_split: (%s) [%llx, %llx], res: (%s) [%llx, %llx]\n",
-                        conflict->name, conflict->start, conflict->end,
-                        name, start, end);
-
                /* failed, split and try again */
 
-               /* conflict coverred whole area */
+               /* conflict covered whole area */
                if (conflict->start <= start && conflict->end >= end)
                        return;
 
@@ -630,33 +626,34 @@ struct resource * __request_region(struct resource *parent,
 {
        struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 
-       if (res) {
-               res->name = name;
-               res->start = start;
-               res->end = start + n - 1;
-               res->flags = IORESOURCE_BUSY;
+       if (!res)
+               return NULL;
 
-               write_lock(&resource_lock);
+       res->name = name;
+       res->start = start;
+       res->end = start + n - 1;
+       res->flags = IORESOURCE_BUSY;
 
-               for (;;) {
-                       struct resource *conflict;
+       write_lock(&resource_lock);
 
-                       conflict = __request_resource(parent, res);
-                       if (!conflict)
-                               break;
-                       if (conflict != parent) {
-                               parent = conflict;
-                               if (!(conflict->flags & IORESOURCE_BUSY))
-                                       continue;
-                       }
+       for (;;) {
+               struct resource *conflict;
 
-                       /* Uhhuh, that didn't work out.. */
-                       kfree(res);
-                       res = NULL;
+               conflict = __request_resource(parent, res);
+               if (!conflict)
                        break;
+               if (conflict != parent) {
+                       parent = conflict;
+                       if (!(conflict->flags & IORESOURCE_BUSY))
+                               continue;
                }
-               write_unlock(&resource_lock);
+
+               /* Uhhuh, that didn't work out.. */
+               kfree(res);
+               res = NULL;
+               break;
        }
+       write_unlock(&resource_lock);
        return res;
 }
 EXPORT_SYMBOL(__request_region);
@@ -831,3 +828,40 @@ static int __init reserve_setup(char *str)
 }
 
 __setup("reserve=", reserve_setup);
+
+/*
+ * Check if the requested addr and size spans more than any slot in the
+ * iomem resource tree.
+ */
+int iomem_map_sanity_check(resource_size_t addr, unsigned long size)
+{
+       struct resource *p = &iomem_resource;
+       int err = 0;
+       loff_t l;
+
+       read_lock(&resource_lock);
+       for (p = p->child; p ; p = r_next(NULL, p, &l)) {
+               /*
+                * We can probably skip the resources without
+                * IORESOURCE_IO attribute?
+                */
+               if (p->start >= addr + size)
+                       continue;
+               if (p->end < addr)
+                       continue;
+               if (p->start <= addr && (p->end >= addr + size - 1))
+                       continue;
+               printk(KERN_WARNING "resource map sanity check conflict: "
+                      "0x%llx 0x%llx 0x%llx 0x%llx %s\n",
+                      (unsigned long long)addr,
+                      (unsigned long long)(addr + size - 1),
+                      (unsigned long long)p->start,
+                      (unsigned long long)p->end,
+                      p->name);
+               err = -1;
+               break;
+       }
+       read_unlock(&resource_lock);
+
+       return err;
+}
index e8ab096ddfe399dc3007e32b169b46d02ed9cb48..81787248b60fda5bc58b6231be84a6a54a763cb0 100644 (file)
@@ -118,13 +118,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now)
 
        /*
         * scd->clock = clamp(scd->tick_gtod + delta,
-        *                    max(scd->tick_gtod, scd->clock),
-        *                    scd->tick_gtod + TICK_NSEC);
+        *                    max(scd->tick_gtod, scd->clock),
+        *                    max(scd->clock, scd->tick_gtod + TICK_NSEC));
         */
 
        clock = scd->tick_gtod + delta;
        min_clock = wrap_max(scd->tick_gtod, scd->clock);
-       max_clock = scd->tick_gtod + TICK_NSEC;
+       max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC);
 
        clock = wrap_max(clock, min_clock);
        clock = wrap_min(clock, max_clock);
index bbe6b31c3c560d864285ad696d0e885f0ee3e5d6..ad958c1ec70859704afc3ae3d444c03914b37a6b 100644 (file)
@@ -333,12 +333,10 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
        unsigned long flags;
        int num_threads = 1;
 
-       rcu_read_lock();
        if (lock_task_sighand(p, &flags)) {
                num_threads = atomic_read(&p->signal->count);
                unlock_task_sighand(p, &flags);
        }
-       rcu_read_unlock();
 
        SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
        SEQ_printf(m,
index c506f266a6b90ee9d887b9eeecdd45061e74ef1f..37d67aa2d56fb18cb189f13e6a727ae3570c546e 100644 (file)
@@ -46,7 +46,7 @@ irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
 EXPORT_SYMBOL(irq_stat);
 #endif
 
-static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
+static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
 
 static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
@@ -205,7 +205,18 @@ restart:
 
        do {
                if (pending & 1) {
+                       int prev_count = preempt_count();
+
                        h->action(h);
+
+                       if (unlikely(prev_count != preempt_count())) {
+                               printk(KERN_ERR "huh, entered softirq %td %p"
+                                      "with preempt_count %08x,"
+                                      " exited with %08x?\n", h - softirq_vec,
+                                      h->action, prev_count, preempt_count());
+                               preempt_count() = prev_count;
+                       }
+
                        rcu_bh_qsctr_inc(cpu);
                }
                h++;
index cb838ee93a82000bc5b313271487836e9fb5804e..3953e4aed733d32284f48ecfffa1fbff05e234c6 100644 (file)
@@ -226,7 +226,7 @@ static void check_hung_uninterruptible_tasks(int this_cpu)
         * If the system crashed already then all bets are off,
         * do not report extra hung tasks:
         */
-       if ((tainted & TAINT_DIE) || did_panic)
+       if (test_taint(TAINT_DIE) || did_panic)
                return;
 
        read_lock(&tasklist_lock);
index 038a7bc0901d20f90f841c5e4326fc1f2f2b963f..0bc8fa3c2288110b49fad4e9eaab2326f52c69f7 100644 (file)
@@ -1060,9 +1060,7 @@ asmlinkage long sys_setsid(void)
        group_leader->signal->leader = 1;
        __set_special_pids(sid);
 
-       spin_lock(&group_leader->sighand->siglock);
-       group_leader->signal->tty = NULL;
-       spin_unlock(&group_leader->sighand->siglock);
+       proc_clear_tty(group_leader);
 
        err = session;
 out:
@@ -1351,8 +1349,10 @@ asmlinkage long sys_sethostname(char __user *name, int len)
        down_write(&uts_sem);
        errno = -EFAULT;
        if (!copy_from_user(tmp, name, len)) {
-               memcpy(utsname()->nodename, tmp, len);
-               utsname()->nodename[len] = 0;
+               struct new_utsname *u = utsname();
+
+               memcpy(u->nodename, tmp, len);
+               memset(u->nodename + len, 0, sizeof(u->nodename) - len);
                errno = 0;
        }
        up_write(&uts_sem);
@@ -1364,15 +1364,17 @@ asmlinkage long sys_sethostname(char __user *name, int len)
 asmlinkage long sys_gethostname(char __user *name, int len)
 {
        int i, errno;
+       struct new_utsname *u;
 
        if (len < 0)
                return -EINVAL;
        down_read(&uts_sem);
-       i = 1 + strlen(utsname()->nodename);
+       u = utsname();
+       i = 1 + strlen(u->nodename);
        if (i > len)
                i = len;
        errno = 0;
-       if (copy_to_user(name, utsname()->nodename, i))
+       if (copy_to_user(name, u->nodename, i))
                errno = -EFAULT;
        up_read(&uts_sem);
        return errno;
@@ -1397,8 +1399,10 @@ asmlinkage long sys_setdomainname(char __user *name, int len)
        down_write(&uts_sem);
        errno = -EFAULT;
        if (!copy_from_user(tmp, name, len)) {
-               memcpy(utsname()->domainname, tmp, len);
-               utsname()->domainname[len] = 0;
+               struct new_utsname *u = utsname();
+
+               memcpy(u->domainname, tmp, len);
+               memset(u->domainname + len, 0, sizeof(u->domainname) - len);
                errno = 0;
        }
        up_write(&uts_sem);
@@ -1452,14 +1456,22 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
                return -EINVAL;
        if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
                return -EFAULT;
-       if (new_rlim.rlim_cur > new_rlim.rlim_max)
-               return -EINVAL;
        old_rlim = current->signal->rlim + resource;
        if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
            !capable(CAP_SYS_RESOURCE))
                return -EPERM;
-       if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
-               return -EPERM;
+
+       if (resource == RLIMIT_NOFILE) {
+               if (new_rlim.rlim_max == RLIM_INFINITY)
+                       new_rlim.rlim_max = sysctl_nr_open;
+               if (new_rlim.rlim_cur == RLIM_INFINITY)
+                       new_rlim.rlim_cur = sysctl_nr_open;
+               if (new_rlim.rlim_max > sysctl_nr_open)
+                       return -EPERM;
+       }
+
+       if (new_rlim.rlim_cur > new_rlim.rlim_max)
+               return -EINVAL;
 
        retval = security_task_setrlimit(resource, &new_rlim);
        if (retval)
index 08d6e1bb99ac351f28bfe768acf49c17e04b0593..a77b27b11b048fee528e0628798f9fe8774ebbf9 100644 (file)
@@ -125,6 +125,12 @@ cond_syscall(sys_vm86old);
 cond_syscall(sys_vm86);
 cond_syscall(compat_sys_ipc);
 cond_syscall(compat_sys_sysctl);
+cond_syscall(sys_flock);
+cond_syscall(sys_io_setup);
+cond_syscall(sys_io_destroy);
+cond_syscall(sys_io_submit);
+cond_syscall(sys_io_cancel);
+cond_syscall(sys_io_getevents);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);
index 1bf369bd44234e829905d9a565577537c040c846..617d41e4d6a08eae69152515e1ac47a9c8a3fc85 100644 (file)
@@ -80,7 +80,6 @@ extern int pid_max_min, pid_max_max;
 extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
 extern int compat_log;
-extern int maps_protect;
 extern int latencytop_enabled;
 extern int sysctl_nr_open_min, sysctl_nr_open_max;
 #ifdef CONFIG_RCU_TORTURE_TEST
@@ -97,7 +96,7 @@ static int sixty = 60;
 static int neg_one = -1;
 #endif
 
-#ifdef CONFIG_MMU
+#if defined(CONFIG_MMU) && defined(CONFIG_FILE_LOCKING)
 static int two = 2;
 #endif
 
@@ -150,7 +149,7 @@ extern int max_lock_depth;
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
-static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
+static int proc_taint(struct ctl_table *table, int write, struct file *filp,
                               void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
@@ -380,10 +379,9 @@ static struct ctl_table kern_table[] = {
 #ifdef CONFIG_PROC_SYSCTL
        {
                .procname       = "tainted",
-               .data           = &tainted,
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_taint,
+               .proc_handler   = &proc_taint,
        },
 #endif
 #ifdef CONFIG_LATENCYTOP
@@ -807,16 +805,6 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
-#endif
-#ifdef CONFIG_PROC_FS
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "maps_protect",
-               .data           = &maps_protect,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
 #endif
        {
                .ctl_name       = CTL_UNNUMBERED,
@@ -1259,6 +1247,7 @@ static struct ctl_table fs_table[] = {
                .extra1         = &minolduid,
                .extra2         = &maxolduid,
        },
+#ifdef CONFIG_FILE_LOCKING
        {
                .ctl_name       = FS_LEASES,
                .procname       = "leases-enable",
@@ -1267,6 +1256,7 @@ static struct ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#endif
 #ifdef CONFIG_DNOTIFY
        {
                .ctl_name       = FS_DIR_NOTIFY,
@@ -1278,6 +1268,7 @@ static struct ctl_table fs_table[] = {
        },
 #endif
 #ifdef CONFIG_MMU
+#ifdef CONFIG_FILE_LOCKING
        {
                .ctl_name       = FS_LEASE_TIME,
                .procname       = "lease-break-time",
@@ -1289,6 +1280,8 @@ static struct ctl_table fs_table[] = {
                .extra1         = &zero,
                .extra2         = &two,
        },
+#endif
+#ifdef CONFIG_AIO
        {
                .procname       = "aio-nr",
                .data           = &aio_nr,
@@ -1303,6 +1296,7 @@ static struct ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_doulongvec_minmax,
        },
+#endif /* CONFIG_AIO */
 #ifdef CONFIG_INOTIFY_USER
        {
                .ctl_name       = FS_INOTIFY,
@@ -1508,7 +1502,6 @@ void register_sysctl_root(struct ctl_table_root *root)
 /* Perform the actual read/write of a sysctl table entry. */
 static int do_sysctl_strategy(struct ctl_table_root *root,
                        struct ctl_table *table,
-                       int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
                        void __user *newval, size_t newlen)
 {
@@ -1522,8 +1515,7 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
                return -EPERM;
 
        if (table->strategy) {
-               rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                                    newval, newlen);
+               rc = table->strategy(table, oldval, oldlenp, newval, newlen);
                if (rc < 0)
                        return rc;
                if (rc > 0)
@@ -1533,8 +1525,7 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
        /* If there is no strategy routine, or if the strategy returns
         * zero, proceed with automatic r/w */
        if (table->data && table->maxlen) {
-               rc = sysctl_data(table, name, nlen, oldval, oldlenp,
-                                newval, newlen);
+               rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
                if (rc < 0)
                        return rc;
        }
@@ -1566,7 +1557,7 @@ repeat:
                                table = table->child;
                                goto repeat;
                        }
-                       error = do_sysctl_strategy(root, table, name, nlen,
+                       error = do_sysctl_strategy(root, table,
                                                   oldval, oldlenp,
                                                   newval, newlen);
                        return error;
@@ -2235,49 +2226,39 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
                            NULL,NULL);
 }
 
-#define OP_SET 0
-#define OP_AND 1
-#define OP_OR  2
-
-static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
-                                     int *valp,
-                                     int write, void *data)
-{
-       int op = *(int *)data;
-       if (write) {
-               int val = *negp ? -*lvalp : *lvalp;
-               switch(op) {
-               case OP_SET:    *valp = val; break;
-               case OP_AND:    *valp &= val; break;
-               case OP_OR:     *valp |= val; break;
-               }
-       } else {
-               int val = *valp;
-               if (val < 0) {
-                       *negp = -1;
-                       *lvalp = (unsigned long)-val;
-               } else {
-                       *negp = 0;
-                       *lvalp = (unsigned long)val;
-               }
-       }
-       return 0;
-}
-
 /*
- *     Taint values can only be increased
+ * Taint values can only be increased
+ * This means we can safely use a temporary.
  */
-static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
+static int proc_taint(struct ctl_table *table, int write, struct file *filp,
                               void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int op;
+       struct ctl_table t;
+       unsigned long tmptaint = get_taint();
+       int err;
 
        if (write && !capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       op = OP_OR;
-       return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
-                               do_proc_dointvec_bset_conv,&op);
+       t = *table;
+       t.data = &tmptaint;
+       err = proc_doulongvec_minmax(&t, write, filp, buffer, lenp, ppos);
+       if (err < 0)
+               return err;
+
+       if (write) {
+               /*
+                * Poor man's atomic or. Not worth adding a primitive
+                * to everyone's atomic.h for this
+                */
+               int i;
+               for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
+                       if ((tmptaint >> i) & 1)
+                               add_taint(i);
+               }
+       }
+
+       return err;
 }
 
 struct do_proc_dointvec_minmax_conv_param {
@@ -2725,7 +2706,7 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
  */
 
 /* The generic sysctl data routine (used if no strategy routine supplied) */
-int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_data(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
@@ -2759,7 +2740,7 @@ int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
 }
 
 /* The generic string strategy routine: */
-int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_string(struct ctl_table *table,
                  void __user *oldval, size_t __user *oldlenp,
                  void __user *newval, size_t newlen)
 {
@@ -2805,7 +2786,7 @@ int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
  * are between the minimum and maximum values given in the arrays
  * table->extra1 and table->extra2, respectively.
  */
-int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_intvec(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
@@ -2841,7 +2822,7 @@ int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
 }
 
 /* Strategy function to convert jiffies to seconds */ 
-int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_jiffies(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
@@ -2875,7 +2856,7 @@ int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
 }
 
 /* Strategy function to convert jiffies to seconds */ 
-int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_ms_jiffies(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
@@ -2930,35 +2911,35 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
        return error;
 }
 
-int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_data(struct ctl_table *table,
                  void __user *oldval, size_t __user *oldlenp,
                  void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
-int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_string(struct ctl_table *table,
                  void __user *oldval, size_t __user *oldlenp,
                  void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
-int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_intvec(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
-int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_jiffies(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
-int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
+int sysctl_ms_jiffies(struct ctl_table *table,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen)
 {
index 8d53106a0a92c1dd619b6dc0f5e7841fc10824b4..95ed42951e0adb536db3783b5d026914ddfdbc73 100644 (file)
@@ -3,7 +3,6 @@
 #
 config TICK_ONESHOT
        bool
-       default n
 
 config NO_HZ
        bool "Tickless System (Dynamic Ticks)"
index a4d2193981675aa7b5e2048bf229d5dbdbeccdcd..b711ffcb106c906be19eab01140ec1e8cafd0063 100644 (file)
@@ -270,7 +270,7 @@ void tick_nohz_stop_sched_tick(int inidle)
        next_jiffies = get_next_timer_interrupt(last_jiffies);
        delta_jiffies = next_jiffies - last_jiffies;
 
-       if (rcu_needs_cpu(cpu))
+       if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
                delta_jiffies = 1;
        /*
         * Do not stop the tick, if we are only one off
index 03bc7f1f159350d2ad29ca45d3b3a28fc275f296..510fe69351ca2ec19700802b59ac3dbe9d142019 100644 (file)
@@ -978,6 +978,7 @@ void update_process_times(int user_tick)
        run_local_timers();
        if (rcu_pending(cpu))
                rcu_check_callbacks(cpu, user_tick);
+       printk_tick();
        scheduler_tick();
        run_posix_cpu_timers(p);
 }
index 4ab9659d269e23bc315729f840b8742b5876e1ff..3b34b3545936dfcd179eca7f9fd2aebf4a2abfa0 100644 (file)
@@ -60,7 +60,7 @@ static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 /* The generic string strategy routine: */
-static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
+static int sysctl_uts_string(ctl_table *table,
                  void __user *oldval, size_t __user *oldlenp,
                  void __user *newval, size_t newlen)
 {
@@ -69,8 +69,7 @@ static int sysctl_uts_string(ctl_table *table, int __user *name, int nlen,
        write = newval && newlen;
        memcpy(&uts_table, table, sizeof(uts_table));
        uts_table.data = get_uts(table, write);
-       r = sysctl_string(&uts_table, name, nlen,
-               oldval, oldlenp, newval, newlen);
+       r = sysctl_string(&uts_table, oldval, oldlenp, newval, newlen);
        put_uts(table, write, uts_table.data);
        return r;
 }
index c275c56cf2d313e509a2aac411d3bcebf4278ca1..cd87131f2fc2aa138aa1bc818f5efab612c3085c 100644 (file)
@@ -72,12 +72,7 @@ prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
        spin_lock_irqsave(&q->lock, flags);
        if (list_empty(&wait->task_list))
                __add_wait_queue(q, wait);
-       /*
-        * don't alter the task state if this is just going to
-        * queue an async wait queue callback
-        */
-       if (is_sync_wait(wait))
-               set_current_state(state);
+       set_current_state(state);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 EXPORT_SYMBOL(prepare_to_wait);
@@ -91,12 +86,7 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
        spin_lock_irqsave(&q->lock, flags);
        if (list_empty(&wait->task_list))
                __add_wait_queue_tail(q, wait);
-       /*
-        * don't alter the task state if this is just going to
-        * queue an async wait queue callback
-        */
-       if (is_sync_wait(wait))
-               set_current_state(state);
+       set_current_state(state);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 EXPORT_SYMBOL(prepare_to_wait_exclusive);
index 4048e92aa04f21e7e105563fac7bf24e1be5411f..714afad46539616e4bbcab15240160ca4d188226 100644 (file)
@@ -9,7 +9,7 @@
  * Derived from the taskqueue/keventd code by:
  *
  *   David Woodhouse <dwmw2@infradead.org>
- *   Andrew Morton <andrewm@uow.edu.au>
+ *   Andrew Morton
  *   Kai Petzke <wpp@marie.physik.tu-berlin.de>
  *   Theodore Ts'o <tytso@mit.edu>
  *
index c7ad7a5b3535210df1dabe86fd1c63b888e0a7ae..85cf7ea978aafe6606e6e44cc634a82e6cf29477 100644 (file)
@@ -8,10 +8,10 @@ config BITREVERSE
        tristate
 
 config GENERIC_FIND_FIRST_BIT
-       def_bool n
+       bool
 
 config GENERIC_FIND_NEXT_BIT
-       def_bool n
+       bool
 
 config CRC_CCITT
        tristate "CRC-CCITT functions"
index aa81d2848448db8f007194cc086804dcffe2623e..31d784dd80d022cdb112fc56863eebe0cf6c5d7d 100644 (file)
@@ -807,6 +807,61 @@ menuconfig BUILD_DOCSRC
 
          Say N if you are unsure.
 
+config DYNAMIC_PRINTK_DEBUG
+       bool "Enable dynamic printk() call support"
+       default n
+       depends on PRINTK
+       select PRINTK_DEBUG
+       help
+
+         Compiles debug level messages into the kernel, which would not
+         otherwise be available at runtime. These messages can then be
+         enabled/disabled on a per module basis. This mechanism implicitly
+         enables all pr_debug() and dev_dbg() calls. The impact of this
+         compile option is a larger kernel text size of about 2%.
+
+         Usage:
+
+         Dynamic debugging is controlled by the debugfs file,
+         dynamic_printk/modules. This file contains a list of the modules that
+         can be enabled. The format of the file is the module name, followed
+         by a set of flags that can be enabled. The first flag is always the
+         'enabled' flag. For example:
+
+               <module_name> <enabled=0/1>
+                               .
+                               .
+                               .
+
+         <module_name> : Name of the module in which the debug call resides
+         <enabled=0/1> : whether the messages are enabled or not
+
+         From a live system:
+
+               snd_hda_intel enabled=0
+               fixup enabled=0
+               driver enabled=0
+
+         Enable a module:
+
+               $echo "set enabled=1 <module_name>" > dynamic_printk/modules
+
+         Disable a module:
+
+               $echo "set enabled=0 <module_name>" > dynamic_printk/modules
+
+         Enable all modules:
+
+               $echo "set enabled=1 all" > dynamic_printk/modules
+
+         Disable all modules:
+
+               $echo "set enabled=0 all" > dynamic_printk/modules
+
+         Finally, passing "dynamic_printk" at the command line enables
+         debugging for all modules. This mode can be turned off via the above
+         disable command.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
index 44001af76a7dfc4f44216fa25959291633df36e7..16feaab057b2d5fdda220ae350a09f765c7f24be 100644 (file)
@@ -81,6 +81,8 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o
 
 obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
 
+obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
+
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
 
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
new file mode 100644 (file)
index 0000000..d640f87
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * lib/dynamic_printk.c
+ *
+ * make pr_debug()/dev_dbg() calls runtime configurable based upon their
+ * their source module.
+ *
+ * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+
+extern struct mod_debug __start___verbose[];
+extern struct mod_debug __stop___verbose[];
+
+struct debug_name {
+       struct hlist_node hlist;
+       struct hlist_node hlist2;
+       int hash1;
+       int hash2;
+       char *name;
+       int enable;
+       int type;
+};
+
+static int nr_entries;
+static int num_enabled;
+int dynamic_enabled = DYNAMIC_ENABLED_NONE;
+static struct hlist_head module_table[DEBUG_HASH_TABLE_SIZE] =
+       { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
+static struct hlist_head module_table2[DEBUG_HASH_TABLE_SIZE] =
+       { [0 ... DEBUG_HASH_TABLE_SIZE-1] = HLIST_HEAD_INIT };
+static DECLARE_MUTEX(debug_list_mutex);
+
+/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
+ * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
+ * use independent hash functions, to reduce the chance of false positives.
+ */
+long long dynamic_printk_enabled;
+EXPORT_SYMBOL_GPL(dynamic_printk_enabled);
+long long dynamic_printk_enabled2;
+EXPORT_SYMBOL_GPL(dynamic_printk_enabled2);
+
+/* returns the debug module pointer. */
+static struct debug_name *find_debug_module(char *module_name)
+{
+       int i;
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct debug_name *element;
+
+       element = NULL;
+       for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
+               head = &module_table[i];
+               hlist_for_each_entry_rcu(element, node, head, hlist)
+                       if (!strcmp(element->name, module_name))
+                               return element;
+       }
+       return NULL;
+}
+
+/* returns the debug module pointer. */
+static struct debug_name *find_debug_module_hash(char *module_name, int hash)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct debug_name *element;
+
+       element = NULL;
+       head = &module_table[hash];
+       hlist_for_each_entry_rcu(element, node, head, hlist)
+               if (!strcmp(element->name, module_name))
+                       return element;
+       return NULL;
+}
+
+/* caller must hold mutex*/
+static int __add_debug_module(char *mod_name, int hash, int hash2)
+{
+       struct debug_name *new;
+       char *module_name;
+       int ret = 0;
+
+       if (find_debug_module(mod_name)) {
+               ret = -EINVAL;
+               goto out;
+       }
+       module_name = kmalloc(strlen(mod_name) + 1, GFP_KERNEL);
+       if (!module_name) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       module_name = strcpy(module_name, mod_name);
+       module_name[strlen(mod_name)] = '\0';
+       new = kzalloc(sizeof(struct debug_name), GFP_KERNEL);
+       if (!new) {
+               kfree(module_name);
+               ret = -ENOMEM;
+               goto out;
+       }
+       INIT_HLIST_NODE(&new->hlist);
+       INIT_HLIST_NODE(&new->hlist2);
+       new->name = module_name;
+       new->hash1 = hash;
+       new->hash2 = hash2;
+       hlist_add_head_rcu(&new->hlist, &module_table[hash]);
+       hlist_add_head_rcu(&new->hlist2, &module_table2[hash2]);
+       nr_entries++;
+out:
+       return ret;
+}
+
+int unregister_dynamic_debug_module(char *mod_name)
+{
+       struct debug_name *element;
+       int ret = 0;
+
+       down(&debug_list_mutex);
+       element = find_debug_module(mod_name);
+       if (!element) {
+               ret = -EINVAL;
+               goto out;
+       }
+       hlist_del_rcu(&element->hlist);
+       hlist_del_rcu(&element->hlist2);
+       synchronize_rcu();
+       kfree(element->name);
+       if (element->enable)
+               num_enabled--;
+       kfree(element);
+       nr_entries--;
+out:
+       up(&debug_list_mutex);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module);
+
+int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
+                                       char *flags, int hash, int hash2)
+{
+       struct debug_name *elem;
+       int ret = 0;
+
+       down(&debug_list_mutex);
+       elem = find_debug_module(mod_name);
+       if (!elem) {
+               if (__add_debug_module(mod_name, hash, hash2))
+                       goto out;
+               elem = find_debug_module(mod_name);
+               if (dynamic_enabled == DYNAMIC_ENABLED_ALL &&
+                               !strcmp(mod_name, share_name)) {
+                       elem->enable = true;
+                       num_enabled++;
+               }
+       }
+       elem->type |= type;
+out:
+       up(&debug_list_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(register_dynamic_debug_module);
+
+int __dynamic_dbg_enabled_helper(char *mod_name, int type, int value, int hash)
+{
+       struct debug_name *elem;
+       int ret = 0;
+
+       if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
+               return 1;
+       rcu_read_lock();
+       elem = find_debug_module_hash(mod_name, hash);
+       if (elem && elem->enable)
+               ret = 1;
+       rcu_read_unlock();
+       return ret;
+}
+EXPORT_SYMBOL_GPL(__dynamic_dbg_enabled_helper);
+
+static void set_all(bool enable)
+{
+       struct debug_name *e;
+       struct hlist_node *node;
+       int i;
+       long long enable_mask;
+
+       for (i = 0; i < DEBUG_HASH_TABLE_SIZE; i++) {
+               if (module_table[i].first != NULL) {
+                       hlist_for_each_entry(e, node, &module_table[i], hlist) {
+                               e->enable = enable;
+                       }
+               }
+       }
+       if (enable)
+               enable_mask = ULLONG_MAX;
+       else
+               enable_mask = 0;
+       dynamic_printk_enabled = enable_mask;
+       dynamic_printk_enabled2 = enable_mask;
+}
+
+static int disabled_hash(int i, bool first_table)
+{
+       struct debug_name *e;
+       struct hlist_node *node;
+
+       if (first_table) {
+               hlist_for_each_entry(e, node, &module_table[i], hlist) {
+                       if (e->enable)
+                               return 0;
+               }
+       } else {
+               hlist_for_each_entry(e, node, &module_table2[i], hlist2) {
+                       if (e->enable)
+                               return 0;
+               }
+       }
+       return 1;
+}
+
+static ssize_t pr_debug_write(struct file *file, const char __user *buf,
+                               size_t length, loff_t *ppos)
+{
+       char *buffer, *s, *value_str, *setting_str;
+       int err, value;
+       struct debug_name *elem = NULL;
+       int all = 0;
+
+       if (length > PAGE_SIZE || length < 0)
+               return -EINVAL;
+
+       buffer = (char *)__get_free_page(GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       err = -EFAULT;
+       if (copy_from_user(buffer, buf, length))
+               goto out;
+
+       err = -EINVAL;
+       if (length < PAGE_SIZE)
+               buffer[length] = '\0';
+       else if (buffer[PAGE_SIZE-1])
+               goto out;
+
+       err = -EINVAL;
+       down(&debug_list_mutex);
+
+       if (strncmp("set", buffer, 3))
+               goto out_up;
+       s = buffer + 3;
+       setting_str = strsep(&s, "=");
+       if (s == NULL)
+               goto out_up;
+       setting_str = strstrip(setting_str);
+       value_str = strsep(&s, " ");
+       if (s == NULL)
+               goto out_up;
+       s = strstrip(s);
+       if (!strncmp(s, "all", 3))
+               all = 1;
+       else
+               elem = find_debug_module(s);
+       if (!strncmp(setting_str, "enable", 6)) {
+               value = !!simple_strtol(value_str, NULL, 10);
+               if (all) {
+                       if (value) {
+                               set_all(true);
+                               num_enabled = nr_entries;
+                               dynamic_enabled = DYNAMIC_ENABLED_ALL;
+                       } else {
+                               set_all(false);
+                               num_enabled = 0;
+                               dynamic_enabled = DYNAMIC_ENABLED_NONE;
+                       }
+                       err = 0;
+               } else {
+                       if (elem) {
+                               if (value && (elem->enable == 0)) {
+                                       dynamic_printk_enabled |=
+                                                       (1LL << elem->hash1);
+                                       dynamic_printk_enabled2 |=
+                                                       (1LL << elem->hash2);
+                                       elem->enable = 1;
+                                       num_enabled++;
+                                       dynamic_enabled = DYNAMIC_ENABLED_SOME;
+                                       err = 0;
+                                       printk(KERN_DEBUG
+                                              "debugging enabled for module %s",
+                                              elem->name);
+                               } else if (!value && (elem->enable == 1)) {
+                                       elem->enable = 0;
+                                       num_enabled--;
+                                       if (disabled_hash(elem->hash1, true))
+                                               dynamic_printk_enabled &=
+                                                       ~(1LL << elem->hash1);
+                                       if (disabled_hash(elem->hash2, false))
+                                               dynamic_printk_enabled2 &=
+                                                       ~(1LL << elem->hash2);
+                                       if (num_enabled)
+                                               dynamic_enabled =
+                                                       DYNAMIC_ENABLED_SOME;
+                                       else
+                                               dynamic_enabled =
+                                                       DYNAMIC_ENABLED_NONE;
+                                       err = 0;
+                                       printk(KERN_DEBUG
+                                              "debugging disabled for module "
+                                              "%s", elem->name);
+                               }
+                       }
+               }
+       }
+       if (!err)
+               err = length;
+out_up:
+       up(&debug_list_mutex);
+out:
+       free_page((unsigned long)buffer);
+       return err;
+}
+
+static void *pr_debug_seq_start(struct seq_file *f, loff_t *pos)
+{
+       return (*pos < DEBUG_HASH_TABLE_SIZE) ? pos : NULL;
+}
+
+static void *pr_debug_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       (*pos)++;
+       if (*pos >= DEBUG_HASH_TABLE_SIZE)
+               return NULL;
+       return pos;
+}
+
+static void pr_debug_seq_stop(struct seq_file *s, void *v)
+{
+       /* Nothing to do */
+}
+
+static int pr_debug_seq_show(struct seq_file *s, void *v)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct debug_name *elem;
+       unsigned int i = *(loff_t *) v;
+
+       rcu_read_lock();
+       head = &module_table[i];
+       hlist_for_each_entry_rcu(elem, node, head, hlist) {
+               seq_printf(s, "%s enabled=%d", elem->name, elem->enable);
+               seq_printf(s, "\n");
+       }
+       rcu_read_unlock();
+       return 0;
+}
+
+static struct seq_operations pr_debug_seq_ops = {
+       .start = pr_debug_seq_start,
+       .next  = pr_debug_seq_next,
+       .stop  = pr_debug_seq_stop,
+       .show  = pr_debug_seq_show
+};
+
+static int pr_debug_open(struct inode *inode, struct file *filp)
+{
+       return seq_open(filp, &pr_debug_seq_ops);
+}
+
+static const struct file_operations pr_debug_operations = {
+       .open           = pr_debug_open,
+       .read           = seq_read,
+       .write          = pr_debug_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init dynamic_printk_init(void)
+{
+       struct dentry *dir, *file;
+       struct mod_debug *iter;
+       unsigned long value;
+
+       dir = debugfs_create_dir("dynamic_printk", NULL);
+       if (!dir)
+               return -ENOMEM;
+       file = debugfs_create_file("modules", 0644, dir, NULL,
+                                       &pr_debug_operations);
+       if (!file) {
+               debugfs_remove(dir);
+               return -ENOMEM;
+       }
+       for (value = (unsigned long)__start___verbose;
+               value < (unsigned long)__stop___verbose;
+               value += sizeof(struct mod_debug)) {
+                       iter = (struct mod_debug *)value;
+                       register_dynamic_debug_module(iter->modname,
+                               iter->type,
+                               iter->logical_modname,
+                               iter->flag_names, iter->hash, iter->hash2);
+       }
+       return 0;
+}
+module_init(dynamic_printk_init);
+/* may want to move this earlier so we can get traces as early as possible */
+
+static int __init dynamic_printk_setup(char *str)
+{
+       if (str)
+               return -ENOENT;
+       set_all(true);
+       return 0;
+}
+/* Use early_param(), so we can get debug output as early as possible */
+early_param("dynamic_printk", dynamic_printk_setup);
index 5d90074dca7550f4935e71127911441c9bc617e2..75dbda03f4fb99a92ef8cc3ead817afefd707702 100644 (file)
@@ -79,3 +79,12 @@ void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
        }
 }
 EXPORT_SYMBOL(iommu_area_free);
+
+unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
+                             unsigned long io_page_size)
+{
+       unsigned long size = (addr & (io_page_size - 1)) + len;
+
+       return DIV_ROUND_UP(size, io_page_size);
+}
+EXPORT_SYMBOL(iommu_num_pages);
index fbf0ae28237672a6fafdbbf29e481d76c45ddd11..0487d1f64806c645927fdc22ea4a5848f3d9ea5f 100644 (file)
@@ -387,11 +387,17 @@ EXPORT_SYMBOL_GPL(kobject_init_and_add);
  * kobject_rename - change the name of an object
  * @kobj: object in question.
  * @new_name: object's new name
+ *
+ * It is the responsibility of the caller to provide mutual
+ * exclusion between two different calls of kobject_rename
+ * on the same kobject and to ensure that new_name is valid and
+ * won't conflict with other kobjects.
  */
 int kobject_rename(struct kobject *kobj, const char *new_name)
 {
        int error = 0;
        const char *devpath = NULL;
+       const char *dup_name = NULL, *name;
        char *devpath_string = NULL;
        char *envp[2];
 
@@ -401,19 +407,6 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
        if (!kobj->parent)
                return -EINVAL;
 
-       /* see if this name is already in use */
-       if (kobj->kset) {
-               struct kobject *temp_kobj;
-               temp_kobj = kset_find_obj(kobj->kset, new_name);
-               if (temp_kobj) {
-                       printk(KERN_WARNING "kobject '%s' cannot be renamed "
-                              "to '%s' as '%s' is already in existence.\n",
-                              kobject_name(kobj), new_name, new_name);
-                       kobject_put(temp_kobj);
-                       return -EINVAL;
-               }
-       }
-
        devpath = kobject_get_path(kobj, GFP_KERNEL);
        if (!devpath) {
                error = -ENOMEM;
@@ -428,15 +421,27 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
        envp[0] = devpath_string;
        envp[1] = NULL;
 
+       name = dup_name = kstrdup(new_name, GFP_KERNEL);
+       if (!name) {
+               error = -ENOMEM;
+               goto out;
+       }
+
        error = sysfs_rename_dir(kobj, new_name);
+       if (error)
+               goto out;
+
+       /* Install the new kobject name */
+       dup_name = kobj->name;
+       kobj->name = name;
 
        /* This function is mostly/only used for network interface.
         * Some hotplug package track interfaces by their name and
         * therefore want to know when the name is changed by the user. */
-       if (!error)
-               kobject_uevent_env(kobj, KOBJ_MOVE, envp);
+       kobject_uevent_env(kobj, KOBJ_MOVE, envp);
 
 out:
+       kfree(dup_name);
        kfree(devpath_string);
        kfree(devpath);
        kobject_put(kobj);
index 4f0cbc03e0e86844840c28b08a279394215b4e31..b00d02059a5f8acc3a58a6290251aa487f2cca2e 100644 (file)
@@ -100,7 +100,7 @@ static int match_one(char *s, const char *p, substring_t args[])
  * format identifiers which will be taken into account when matching the
  * tokens, and whose locations will be returned in the @args array.
  */
-int match_token(char *s, match_table_t table, substring_t args[])
+int match_token(char *s, const match_table_t table, substring_t args[])
 {
        const struct match_token *p;
 
index c399bc1093cbedb276f3e974353534560197e940..cceecb6a963d1638bd420a82f7a3b85014cea379 100644 (file)
 /* Works only for digits and letters, but small and fast */
 #define TOLOWER(x) ((x) | 0x20)
 
+static unsigned int simple_guess_base(const char *cp)
+{
+       if (cp[0] == '0') {
+               if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
+                       return 16;
+               else
+                       return 8;
+       } else {
+               return 10;
+       }
+}
+
 /**
  * simple_strtoul - convert a string to an unsigned 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 simple_strtoul(const char *cp,char **endp,unsigned int base)
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
 {
-       unsigned long result = 0,value;
+       unsigned long result = 0;
 
-       if (!base) {
-               base = 10;
-               if (*cp == '0') {
-                       base = 8;
-                       cp++;
-                       if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
-                               cp++;
-                               base = 16;
-                       }
-               }
-       } else if (base == 16) {
-               if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
-                       cp += 2;
-       }
-       while (isxdigit(*cp) &&
-              (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
-               result = result*base + value;
+       if (!base)
+               base = simple_guess_base(cp);
+
+       if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+               cp += 2;
+
+       while (isxdigit(*cp)) {
+               unsigned int value;
+
+               value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
+               if (value >= base)
+                       break;
+               result = result * base + value;
                cp++;
        }
+
        if (endp)
                *endp = (char *)cp;
        return result;
 }
-
 EXPORT_SYMBOL(simple_strtoul);
 
 /**
@@ -74,13 +82,12 @@ EXPORT_SYMBOL(simple_strtoul);
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  */
-long simple_strtol(const char *cp,char **endp,unsigned int base)
+long simple_strtol(const char *cp, char **endp, unsigned int base)
 {
-       if(*cp=='-')
-               return -simple_strtoul(cp+1,endp,base);
-       return simple_strtoul(cp,endp,base);
+       if(*cp == '-')
+               return -simple_strtoul(cp + 1, endp, base);
+       return simple_strtoul(cp, endp, base);
 }
-
 EXPORT_SYMBOL(simple_strtol);
 
 /**
@@ -89,34 +96,30 @@ EXPORT_SYMBOL(simple_strtol);
  * @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 simple_strtoull(const char *cp, char **endp, unsigned int base)
 {
-       unsigned long long result = 0,value;
+       unsigned long long result = 0;
 
-       if (!base) {
-               base = 10;
-               if (*cp == '0') {
-                       base = 8;
-                       cp++;
-                       if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
-                               cp++;
-                               base = 16;
-                       }
-               }
-       } else if (base == 16) {
-               if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
-                       cp += 2;
-       }
-       while (isxdigit(*cp)
-        && (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
-               result = result*base + value;
+       if (!base)
+               base = simple_guess_base(cp);
+
+       if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+               cp += 2;
+
+       while (isxdigit(*cp)) {
+               unsigned int value;
+
+               value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
+               if (value >= base)
+                       break;
+               result = result * base + value;
                cp++;
        }
+
        if (endp)
                *endp = (char *)cp;
        return result;
 }
-
 EXPORT_SYMBOL(simple_strtoull);
 
 /**
@@ -125,14 +128,13 @@ EXPORT_SYMBOL(simple_strtoull);
  * @endp: A pointer to the end of the parsed string will be placed here
  * @base: The number base to use
  */
-long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 {
        if(*cp=='-')
-               return -simple_strtoull(cp+1,endp,base);
-       return simple_strtoull(cp,endp,base);
+               return -simple_strtoull(cp + 1, endp, base);
+       return simple_strtoull(cp, endp, base);
 }
 
-
 /**
  * strict_strtoul - convert a string to an unsigned long strictly
  * @cp: The string to be converted
@@ -155,7 +157,27 @@ long long simple_strtoll(const char *cp,char **endp,unsigned int base)
  * simple_strtoul just ignores the successive invalid characters and
  * return the converted value of prefix part of the string.
  */
-int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
+int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
+{
+       char *tail;
+       unsigned long val;
+       size_t len;
+
+       *res = 0;
+       len = strlen(cp);
+       if (len == 0)
+               return -EINVAL;
+
+       val = simple_strtoul(cp, &tail, base);
+       if ((*tail == '\0') ||
+               ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
+               *res = val;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(strict_strtoul);
 
 /**
  * strict_strtol - convert a string to a long strictly
@@ -169,7 +191,20 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
  * It returns 0 if conversion is successful and *res is set to the converted
  * value, otherwise it returns -EINVAL and *res is set to 0.
  */
-int strict_strtol(const char *cp, unsigned int base, long *res);
+int strict_strtol(const char *cp, unsigned int base, long *res)
+{
+       int ret;
+       if (*cp == '-') {
+               ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
+               if (!ret)
+                       *res = -(*res);
+       } else {
+               ret = strict_strtoul(cp, base, (unsigned long *)res);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(strict_strtol);
 
 /**
  * strict_strtoull - convert a string to an unsigned long long strictly
@@ -193,7 +228,27 @@ int strict_strtol(const char *cp, unsigned int base, long *res);
  * simple_strtoull just ignores the successive invalid characters and
  * return the converted value of prefix part of the string.
  */
-int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res);
+int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
+{
+       char *tail;
+       unsigned long long val;
+       size_t len;
+
+       *res = 0;
+       len = strlen(cp);
+       if (len == 0)
+               return -EINVAL;
+
+       val = simple_strtoull(cp, &tail, base);
+       if ((*tail == '\0') ||
+               ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
+               *res = val;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(strict_strtoull);
 
 /**
  * strict_strtoll - convert a string to a long long strictly
@@ -207,53 +262,20 @@ int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res);
  * It returns 0 if conversion is successful and *res is set to the converted
  * value, otherwise it returns -EINVAL and *res is set to 0.
  */
-int strict_strtoll(const char *cp, unsigned int base, long long *res);
-
-#define define_strict_strtoux(type, valtype)                           \
-int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\
-{                                                                      \
-       char *tail;                                                     \
-       valtype val;                                                    \
-       size_t len;                                                     \
-                                                                       \
-       *res = 0;                                                       \
-       len = strlen(cp);                                               \
-       if (len == 0)                                                   \
-               return -EINVAL;                                         \
-                                                                       \
-       val = simple_strtou##type(cp, &tail, base);                     \
-       if ((*tail == '\0') ||                                          \
-               ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\
-               *res = val;                                             \
-               return 0;                                               \
-       }                                                               \
-                                                                       \
-       return -EINVAL;                                                 \
-}                                                                      \
-
-#define define_strict_strtox(type, valtype)                            \
-int strict_strto##type(const char *cp, unsigned int base, valtype *res)        \
-{                                                                      \
-       int ret;                                                        \
-       if (*cp == '-') {                                               \
-               ret = strict_strtou##type(cp+1, base, res);             \
-               if (!ret)                                               \
-                       *res = -(*res);                                 \
-       } else                                                          \
-               ret = strict_strtou##type(cp, base, res);               \
-                                                                       \
-       return ret;                                                     \
-}                                                                      \
-
-define_strict_strtoux(l, unsigned long)
-define_strict_strtox(l, long)
-define_strict_strtoux(ll, unsigned long long)
-define_strict_strtox(ll, long long)
+int strict_strtoll(const char *cp, unsigned int base, long long *res)
+{
+       int ret;
+       if (*cp == '-') {
+               ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
+               if (!ret)
+                       *res = -(*res);
+       } else {
+               ret = strict_strtoull(cp, base, (unsigned long long *)res);
+       }
 
-EXPORT_SYMBOL(strict_strtoul);
-EXPORT_SYMBOL(strict_strtol);
+       return ret;
+}
 EXPORT_SYMBOL(strict_strtoll);
-EXPORT_SYMBOL(strict_strtoull);
 
 static int skip_atoi(const char **s)
 {
@@ -565,6 +587,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
  * @fmt: The format string to use
  * @args: Arguments for the format string
  *
+ * This function follows C99 vsnprintf, but has some extensions:
+ * %pS output the name of a text symbol
+ * %pF output the name of a function pointer
+ *
  * The return value is the number of characters which would
  * be generated for the given input, excluding the trailing
  * '\0', as per ISO C99. If you want to have the exact
@@ -790,7 +816,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
        /* the trailing null byte doesn't count towards the total */
        return str-buf;
 }
-
 EXPORT_SYMBOL(vsnprintf);
 
 /**
@@ -806,6 +831,8 @@ EXPORT_SYMBOL(vsnprintf);
  *
  * Call this function if you are already dealing with a va_list.
  * You probably want scnprintf() instead.
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
  */
 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
 {
@@ -814,7 +841,6 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
        i=vsnprintf(buf,size,fmt,args);
        return (i >= size) ? (size - 1) : i;
 }
-
 EXPORT_SYMBOL(vscnprintf);
 
 /**
@@ -828,6 +854,8 @@ EXPORT_SYMBOL(vscnprintf);
  * generated for the given input, excluding the trailing null,
  * as per ISO C99.  If the return is greater than or equal to
  * @size, the resulting string is truncated.
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
  */
 int snprintf(char * buf, size_t size, const char *fmt, ...)
 {
@@ -839,7 +867,6 @@ int snprintf(char * buf, size_t size, const char *fmt, ...)
        va_end(args);
        return i;
 }
-
 EXPORT_SYMBOL(snprintf);
 
 /**
@@ -877,12 +904,13 @@ EXPORT_SYMBOL(scnprintf);
  *
  * Call this function if you are already dealing with a va_list.
  * You probably want sprintf() instead.
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
  */
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
        return vsnprintf(buf, INT_MAX, fmt, args);
 }
-
 EXPORT_SYMBOL(vsprintf);
 
 /**
@@ -894,6 +922,8 @@ EXPORT_SYMBOL(vsprintf);
  * The function returns the number of characters written
  * into @buf. Use snprintf() or scnprintf() in order to avoid
  * buffer overflows.
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
  */
 int sprintf(char * buf, const char *fmt, ...)
 {
@@ -905,7 +935,6 @@ int sprintf(char * buf, const char *fmt, ...)
        va_end(args);
        return i;
 }
-
 EXPORT_SYMBOL(sprintf);
 
 /**
@@ -1134,7 +1163,6 @@ int vsscanf(const char * buf, const char * fmt, va_list args)
 
        return num;
 }
-
 EXPORT_SYMBOL(vsscanf);
 
 /**
@@ -1153,5 +1181,4 @@ int sscanf(const char * buf, const char * fmt, ...)
        va_end(args);
        return i;
 }
-
 EXPORT_SYMBOL(sscanf);
index 0bd9c2dbb2a0be8d184b4b9f1d75dc03ec2a14ba..1a501a4de95cba98543bf706d8c8078ce598d3cd 100644 (file)
@@ -101,7 +101,7 @@ config HAVE_MEMORY_PRESENT
 # with gcc 3.4 and later.
 #
 config SPARSEMEM_STATIC
-       def_bool n
+       bool
 
 #
 # Architecture platforms which require a two level mem_section in SPARSEMEM
@@ -113,7 +113,7 @@ config SPARSEMEM_EXTREME
        depends on SPARSEMEM && !SPARSEMEM_STATIC
 
 config SPARSEMEM_VMEMMAP_ENABLE
-       def_bool n
+       bool
 
 config SPARSEMEM_VMEMMAP
        bool "Sparse Memory virtual memmap"
@@ -187,6 +187,9 @@ config RESOURCES_64BIT
        help
          This option allows memory and IO resources to be 64 bit.
 
+config PHYS_ADDR_T_64BIT
+       def_bool 64BIT || ARCH_PHYS_ADDR_T_64BIT
+
 config ZONE_DMA_FLAG
        int
        default "0" if !ZONE_DMA
index ad8eec6e44a85a9593c781ce252b127cb96992cd..ac5a891f142a8176dc7c3fdd2592ef6c89511dec 100644 (file)
@@ -48,7 +48,7 @@ early_param("bootmem_debug", bootmem_debug_setup);
        if (unlikely(bootmem_debug))                    \
                printk(KERN_INFO                        \
                        "bootmem::%s " fmt,             \
-                       __FUNCTION__, ## args);         \
+                       __func__, ## args);             \
 })
 
 static unsigned long __init bootmap_bytes(unsigned long pages)
index 343cfdfebd9ea0931b9ac6c4e91ed61ba0262730..a1da969bd9803cf334c3c5c1e9746e96eba1f377 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2002, Linus Torvalds
  *
- * 11Jan2003   akpm@digeo.com
+ * 11Jan2003   Andrew Morton
  *             Initial version.
  */
 
index 876bc595d0f8b3b3e4f626bf1ad7acbb657bdc66..903bf316912a68882dadfb0144aef035a6bd5fda 100644 (file)
@@ -1100,8 +1100,9 @@ page_ok:
 
 page_not_up_to_date:
                /* Get exclusive access to the page ... */
-               if (lock_page_killable(page))
-                       goto readpage_eio;
+               error = lock_page_killable(page);
+               if (unlikely(error))
+                       goto readpage_error;
 
 page_not_up_to_date_locked:
                /* Did it get truncated before we got the lock? */
@@ -1130,8 +1131,9 @@ readpage:
                }
 
                if (!PageUptodate(page)) {
-                       if (lock_page_killable(page))
-                               goto readpage_eio;
+                       error = lock_page_killable(page);
+                       if (unlikely(error))
+                               goto readpage_error;
                        if (!PageUptodate(page)) {
                                if (page->mapping == NULL) {
                                        /*
@@ -1143,15 +1145,14 @@ readpage:
                                }
                                unlock_page(page);
                                shrink_readahead_size_eio(filp, ra);
-                               goto readpage_eio;
+                               error = -EIO;
+                               goto readpage_error;
                        }
                        unlock_page(page);
                }
 
                goto page_ok;
 
-readpage_eio:
-               error = -EIO;
 readpage_error:
                /* UHHUH! A synchronous read error occurred. Report it */
                desc->error = error;
@@ -1186,8 +1187,7 @@ out:
        ra->prev_pos |= prev_offset;
 
        *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
-       if (filp)
-               file_accessed(filp);
+       file_accessed(filp);
 }
 
 int file_read_actor(read_descriptor_t *desc, struct page *page,
index 67a71191136ed8f6ad9dad03b472440baa322210..38633864a93e874009d9e6aa00619cf7471b0d9e 100644 (file)
@@ -2008,7 +2008,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        entry = huge_ptep_get(ptep);
        if (huge_pte_none(entry)) {
                ret = hugetlb_no_page(mm, vma, address, ptep, write_access);
-               goto out_unlock;
+               goto out_mutex;
        }
 
        ret = 0;
@@ -2024,7 +2024,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (write_access && !pte_write(entry)) {
                if (vma_needs_reservation(h, vma, address) < 0) {
                        ret = VM_FAULT_OOM;
-                       goto out_unlock;
+                       goto out_mutex;
                }
 
                if (!(vma->vm_flags & VM_SHARED))
@@ -2034,10 +2034,23 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        spin_lock(&mm->page_table_lock);
        /* Check for a racing update before calling hugetlb_cow */
-       if (likely(pte_same(entry, huge_ptep_get(ptep))))
-               if (write_access && !pte_write(entry))
+       if (unlikely(!pte_same(entry, huge_ptep_get(ptep))))
+               goto out_page_table_lock;
+
+
+       if (write_access) {
+               if (!pte_write(entry)) {
                        ret = hugetlb_cow(mm, vma, address, ptep, entry,
                                                        pagecache_page);
+                       goto out_page_table_lock;
+               }
+               entry = pte_mkdirty(entry);
+       }
+       entry = pte_mkyoung(entry);
+       if (huge_ptep_set_access_flags(vma, address, ptep, entry, write_access))
+               update_mmu_cache(vma, address, entry);
+
+out_page_table_lock:
        spin_unlock(&mm->page_table_lock);
 
        if (pagecache_page) {
@@ -2045,7 +2058,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                put_page(pagecache_page);
        }
 
-out_unlock:
+out_mutex:
        mutex_unlock(&hugetlb_instantiation_mutex);
 
        return ret;
index 24de8b65fdbd1f3cd26fafe888277401125c7bc9..c130a137c12938cb0d7baa3ac6a9b8f333beb53c 100644 (file)
@@ -7,7 +7,7 @@
  * Contains functions related to writing back dirty pages at the
  * address_space level.
  *
- * 10Apr2002   akpm@zip.com.au
+ * 10Apr2002   Andrew Morton
  *             Initial version
  */
 
index 27b8681139fdb71e4d0da204ecc4a65fc3f7a1b5..9eb9eb92828510efbc7100addea5fa766c8f48ea 100644 (file)
@@ -3952,7 +3952,7 @@ static void check_for_regular_memory(pg_data_t *pgdat)
 void __init free_area_init_nodes(unsigned long *max_zone_pfn)
 {
        unsigned long nid;
-       enum zone_type i;
+       int i;
 
        /* Sort early_node_map as initialisation assumes it is sorted */
        sort_node_map();
index 0cbe0c60c6bff39d60f0f3994258de7931d6dd4d..a0a14c4d5072dbeef4f68c9ba37ea771e4f38577 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2002, Linus Torvalds.
  *
- * 09Apr2002   akpm@zip.com.au
+ * 09Apr2002   Andrew Morton
  *             Initial version
  * 29Feb2004   kaos@sgi.com
  *             Move worker thread creation to kthread to avoid chewing
index 77e8ddf945e9a725d4b675923124f4eafd0924e2..6cbd9a72fde2c8c1e20bd1c3da9144fa0d13d65c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2002, Linus Torvalds
  *
- * 09Apr2002   akpm@zip.com.au
+ * 09Apr2002   Andrew Morton
  *             Initial version.
  */
 
index 04fb4f1ab88e7e0c87e646afded96e962251fb61..bf66d0191baf57e36a72143335f0d3d93e24d548 100644 (file)
 #include <linux/migrate.h>
 #include <linux/highmem.h>
 #include <linux/seq_file.h>
+#include <linux/magic.h>
 
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <asm/pgtable.h>
 
-/* This magic number is used in glibc for posix shared memory */
-#define TMPFS_MAGIC    0x01021994
-
 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
 #define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
 #define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
index 6650c1d878b463a114e0e024688ecdc1d0fa6b74..e83e4b114ef12b78c74480cd0ddaa6b4369d3b4c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2002, Linus Torvalds
  *
- * 10Sep2002   akpm@zip.com.au
+ * 10Sep2002   Andrew Morton
  *             Initial version.
  */
 
index cb3475ea6fdada58337e7bf6e39773478afb0b7b..34cf1ee014b8a10e668408052ff916916630906c 100644 (file)
@@ -82,13 +82,13 @@ static int fc_header(struct sk_buff *skb, struct net_device *dev,
 
 static int fc_rebuild_header(struct sk_buff *skb)
 {
+#ifdef CONFIG_INET
        struct fch_hdr *fch=(struct fch_hdr *)skb->data;
        struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
        if(fcllc->ethertype != htons(ETH_P_IP)) {
                printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype));
                return 0;
        }
-#ifdef CONFIG_INET
        return arp_find(fch->daddr, skb);
 #else
        return 0;
index b3cfe5a14fcaee0cfb56401286574d1a2e94a74b..70980baeb68297bdc629b27f8ea63f68b0a9e04a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     SNAP data link layer. Derived from 802.2
  *
- *             Alan Cox <Alan.Cox@linux.org>,
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>,
  *             from the 802.2 layer by Greg Page.
  *             Merged in additions from Greg Page's psnap.c.
  *
index 10e320307ec015dad7e2a7db8b753f4a1886f645..e053e06028a551fc38c43b438c49d6870767d408 100644 (file)
@@ -52,7 +52,7 @@ enum {
        Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_msize, "msize=%u"},
        {Opt_legacy, "noextend"},
        {Opt_trans, "trans=%s"},
index d652baf5ff919c422664ed8890996d9f71beadc1..6dabbdb666510fcfc570a67e3f24cf598429e080 100644 (file)
@@ -86,7 +86,7 @@ enum {
        Opt_port, Opt_rfdno, Opt_wfdno, Opt_err,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_port, "port=%u"},
        {Opt_rfdno, "rfdno=%u"},
        {Opt_wfdno, "wfdno=%u"},
index 0c850427a85b437e4e82e80b6c5f7f5bc52e06d0..d3134e7e6ee8e3a6960806259ce4266fabdb6a82 100644 (file)
@@ -2,7 +2,7 @@
  *     DDP:    An implementation of the AppleTalk DDP protocol for
  *             Ethernet 'ELAP'.
  *
- *             Alan Cox  <Alan.Cox@linux.org>
+ *             Alan Cox  <alan@lxorguk.ukuu.org.uk>
  *
  *             With more than a little assistance from
  *
@@ -1934,6 +1934,6 @@ static void __exit atalk_exit(void)
 module_exit(atalk_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alan Cox <Alan.Cox@linux.org>");
+MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
 MODULE_DESCRIPTION("AppleTalk 0.20\n");
 MODULE_ALIAS_NETPROTO(PF_APPLETALK);
index f6348e078aa434077bf26c57ffb8f0eabf4ecbe3..8f9431a12c6f36ed5f8d3ad2b28f765120824d7b 100644 (file)
 #include <linux/poll.h>
 #include <net/sock.h>
 #include <asm/ioctls.h>
-
-#if defined(CONFIG_KMOD)
 #include <linux/kmod.h>
-#endif
 
 #include <net/bluetooth/bluetooth.h>
 
@@ -145,11 +142,8 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto)
        if (proto < 0 || proto >= BT_MAX_PROTO)
                return -EINVAL;
 
-#if defined(CONFIG_KMOD)
-       if (!bt_proto[proto]) {
+       if (!bt_proto[proto])
                request_module("bt-proto-%d", proto);
-       }
-#endif
 
        err = -EPROTONOSUPPORT;
 
index 96434d774c842ff79b84e2d171cdd1e01dd03aaa..acdeab3d980707fbd7740344abd4f7ffe335c75d 100644 (file)
@@ -578,7 +578,7 @@ static int hidp_session(void *arg)
        if (session->hid) {
                if (session->hid->claimed & HID_CLAIMED_INPUT)
                        hidinput_disconnect(session->hid);
-               hid_free_device(session->hid);
+               hid_destroy_device(session->hid);
        }
 
        /* Wakeup user-space polling for socket errors */
@@ -623,9 +623,15 @@ static struct device *hidp_get_device(struct hidp_session *session)
 static int hidp_setup_input(struct hidp_session *session,
                                struct hidp_connadd_req *req)
 {
-       struct input_dev *input = session->input;
+       struct input_dev *input;
        int i;
 
+       input = input_allocate_device();
+       if (!input)
+               return -ENOMEM;
+
+       session->input = input;
+
        input_set_drvdata(input, session);
 
        input->name = "Bluetooth HID Boot Protocol Device";
@@ -677,67 +683,114 @@ static void hidp_close(struct hid_device *hid)
 {
 }
 
-static const struct {
-       __u16 idVendor;
-       __u16 idProduct;
-       unsigned quirks;
-} hidp_blacklist[] = {
-       /* Apple wireless Mighty Mouse */
-       { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
+static int hidp_parse(struct hid_device *hid)
+{
+       struct hidp_session *session = hid->driver_data;
+       struct hidp_connadd_req *req = session->req;
+       unsigned char *buf;
+       int ret;
 
-       { }     /* Terminating entry */
-};
+       buf = kmalloc(req->rd_size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, req->rd_data, req->rd_size)) {
+               kfree(buf);
+               return -EFAULT;
+       }
+
+       ret = hid_parse_report(session->hid, buf, req->rd_size);
+
+       kfree(buf);
+
+       if (ret)
+               return ret;
+
+       session->req = NULL;
+
+       return 0;
+}
+
+static int hidp_start(struct hid_device *hid)
+{
+       struct hidp_session *session = hid->driver_data;
+       struct hid_report *report;
 
-static void hidp_setup_quirks(struct hid_device *hid)
+       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
+                       report_list, list)
+               hidp_send_report(session, report);
+
+       list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
+                       report_list, list)
+               hidp_send_report(session, report);
+
+       return 0;
+}
+
+static void hidp_stop(struct hid_device *hid)
 {
-       unsigned int n;
+       struct hidp_session *session = hid->driver_data;
+
+       skb_queue_purge(&session->ctrl_transmit);
+       skb_queue_purge(&session->intr_transmit);
 
-       for (n = 0; hidp_blacklist[n].idVendor; n++)
-               if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) &&
-                               hidp_blacklist[n].idProduct == le16_to_cpu(hid->product))
-                       hid->quirks = hidp_blacklist[n].quirks;
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_disconnect(hid);
+       hid->claimed = 0;
 }
 
-static void hidp_setup_hid(struct hidp_session *session,
+static struct hid_ll_driver hidp_hid_driver = {
+       .parse = hidp_parse,
+       .start = hidp_start,
+       .stop = hidp_stop,
+       .open  = hidp_open,
+       .close = hidp_close,
+       .hidinput_input_event = hidp_hidinput_event,
+};
+
+static int hidp_setup_hid(struct hidp_session *session,
                                struct hidp_connadd_req *req)
 {
-       struct hid_device *hid = session->hid;
-       struct hid_report *report;
+       struct hid_device *hid;
        bdaddr_t src, dst;
+       int ret;
 
-       baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
-       baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
+       hid = hid_allocate_device();
+       if (IS_ERR(hid)) {
+               ret = PTR_ERR(session->hid);
+               goto err;
+       }
 
+       session->hid = hid;
+       session->req = req;
        hid->driver_data = session;
 
-       hid->country = req->country;
+       baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
+       baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
 
        hid->bus     = BUS_BLUETOOTH;
        hid->vendor  = req->vendor;
        hid->product = req->product;
        hid->version = req->version;
+       hid->country = req->country;
 
        strncpy(hid->name, req->name, 128);
        strncpy(hid->phys, batostr(&src), 64);
        strncpy(hid->uniq, batostr(&dst), 64);
 
-       hid->dev = hidp_get_device(session);
-
-       hid->hid_open  = hidp_open;
-       hid->hid_close = hidp_close;
-
-       hid->hidinput_input_event = hidp_hidinput_event;
+       hid->dev.parent = hidp_get_device(session);
+       hid->ll_driver = &hidp_hid_driver;
 
-       hidp_setup_quirks(hid);
+       ret = hid_add_device(hid);
+       if (ret)
+               goto err_hid;
 
-       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
-               hidp_send_report(session, report);
-
-       list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
-               hidp_send_report(session, report);
-
-       if (hidinput_connect(hid) == 0)
-               hid->claimed |= HID_CLAIMED_INPUT;
+       return 0;
+err_hid:
+       hid_destroy_device(hid);
+       session->hid = NULL;
+err:
+       return ret;
 }
 
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -757,38 +810,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 
        BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
 
-       if (req->rd_size > 0) {
-               unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
-
-               if (!buf) {
-                       kfree(session);
-                       return -ENOMEM;
-               }
-
-               if (copy_from_user(buf, req->rd_data, req->rd_size)) {
-                       kfree(buf);
-                       kfree(session);
-                       return -EFAULT;
-               }
-
-               session->hid = hid_parse_report(buf, req->rd_size);
-
-               kfree(buf);
-
-               if (!session->hid) {
-                       kfree(session);
-                       return -EINVAL;
-               }
-       }
-
-       if (!session->hid) {
-               session->input = input_allocate_device();
-               if (!session->input) {
-                       kfree(session);
-                       return -ENOMEM;
-               }
-       }
-
        down_write(&hidp_session_sem);
 
        s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
@@ -816,15 +837,18 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
        session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
        session->idle_to = req->idle_to;
 
-       if (session->input) {
+       if (req->rd_size > 0) {
+               err = hidp_setup_hid(session, req);
+               if (err && err != -ENODEV)
+                       goto err_skb;
+       }
+
+       if (!session->hid) {
                err = hidp_setup_input(session, req);
                if (err < 0)
-                       goto failed;
+                       goto err_skb;
        }
 
-       if (session->hid)
-               hidp_setup_hid(session, req);
-
        __hidp_link_session(session);
 
        hidp_set_timer(session);
@@ -850,17 +874,16 @@ unlink:
 
        __hidp_unlink_session(session);
 
-       if (session->input) {
+       if (session->input)
                input_unregister_device(session->input);
-               session->input = NULL; /* don't try to free it here */
-       }
-
+       if (session->hid)
+               hid_destroy_device(session->hid);
+err_skb:
+       skb_queue_purge(&session->ctrl_transmit);
+       skb_queue_purge(&session->intr_transmit);
 failed:
        up_write(&hidp_session_sem);
 
-       if (session->hid)
-               hid_free_device(session->hid);
-
        input_free_device(session->input);
        kfree(session);
        return err;
@@ -950,18 +973,43 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
        return err;
 }
 
+static const struct hid_device_id hidp_table[] = {
+       { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
+       { }
+};
+
+static struct hid_driver hidp_driver = {
+       .name = "generic-bluetooth",
+       .id_table = hidp_table,
+};
+
 static int __init hidp_init(void)
 {
+       int ret;
+
        l2cap_load();
 
        BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
 
-       return hidp_init_sockets();
+       ret = hid_register_driver(&hidp_driver);
+       if (ret)
+               goto err;
+
+       ret = hidp_init_sockets();
+       if (ret)
+               goto err_drv;
+
+       return 0;
+err_drv:
+       hid_unregister_driver(&hidp_driver);
+err:
+       return ret;
 }
 
 static void __exit hidp_exit(void)
 {
        hidp_cleanup_sockets();
+       hid_unregister_driver(&hidp_driver);
 }
 
 module_init(hidp_init);
index 343fb0566b3ee73a244a9ce269e482c8578603fe..e503c89057ad4d2bf4e1a3449a63663553c4393e 100644 (file)
@@ -151,6 +151,8 @@ struct hidp_session {
 
        struct sk_buff_head ctrl_transmit;
        struct sk_buff_head intr_transmit;
+
+       struct hidp_connadd_req *req;
 };
 
 static inline void hidp_schedule(struct hidp_session *session)
index 366d3e9d51f8ed49dbac3708c90c2de28d5c9f3a..ba6f73eb06c60c1a7f44e90eacfe5c130819ddd8 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig BRIDGE_NF_EBTABLES
        tristate "Ethernet Bridge tables (ebtables) support"
+       depends on BRIDGE && BRIDGE_NETFILTER
        select NETFILTER_XTABLES
        help
          ebtables is a general, extensible frame/packet identification
index 5bb88eb0aad43c928c5d43877a2497121dec832d..0fa208e86405ceab189042dd36e03fd3e6b893fd 100644 (file)
@@ -305,23 +305,14 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
        return NULL;
 }
 
-#ifndef CONFIG_KMOD
-#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
-#else
 static void *
 find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
    int *error, struct mutex *mutex)
 {
-       void *ret;
-
-       ret = find_inlist_lock_noload(head, name, error, mutex);
-       if (!ret) {
-               request_module("%s%s", prefix, name);
-               ret = find_inlist_lock_noload(head, name, error, mutex);
-       }
-       return ret;
+       return try_then_request_module(
+                       find_inlist_lock_noload(head, name, error, mutex),
+                       "%s%s", prefix, name);
 }
-#endif
 
 static inline struct ebt_table *
 find_table_lock(const char *name, int *error, struct mutex *mutex)
index 8035fbf526ae24e5fabff5b1c588abb8769e3c67..7d4d2b3c137ef6b84598d9bebd50b1a69dfaf707 100644 (file)
@@ -128,8 +128,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
        if (net != &init_net)
                return -EAFNOSUPPORT;
 
-#ifdef CONFIG_KMOD
-       /* try to load protocol module, when CONFIG_KMOD is defined */
+#ifdef CONFIG_MODULES
+       /* try to load protocol module kernel is modular */
        if (!proto_tab[protocol]) {
                err = request_module("can-proto-%d", protocol);
 
index 52f577a0f5440c32b17488c630cfc619ede5c49a..ee631843c2f533de37101e92d05d447f85cf4d1f 100644 (file)
@@ -9,7 +9,7 @@
  *     identical recvmsg() code. So we share it here. The poll was
  *     shared before but buried in udp.c so I moved it.
  *
- *     Authors:        Alan Cox <alan@redhat.com>. (datagram_poll() from old
+ *     Authors:        Alan Cox <alan@lxorguk.ukuu.org.uk>. (datagram_poll() from old
  *                                                  udp.c code)
  *
  *     Fixes:
index 1408a083fe4e28c790f5f1184544993fed6642f2..868ec0ba8b77dc7088c28816238b2ee557316e01 100644 (file)
@@ -4956,8 +4956,6 @@ EXPORT_SYMBOL(br_fdb_get_hook);
 EXPORT_SYMBOL(br_fdb_put_hook);
 #endif
 
-#ifdef CONFIG_KMOD
 EXPORT_SYMBOL(dev_load);
-#endif
 
 EXPORT_PER_CPU_SYMBOL(softnet_data);
index 5402b3b38e0d230f9858adb0889b11746d90e2f5..9e2fa39f22a300e1fc46502aac39f305751e69c5 100644 (file)
@@ -6,7 +6,7 @@
  *             Richard Underwood <richard@wuzz.demon.co.uk>
  *
  *     Stir fried together from the IP multicast and CAP patches above
- *             Alan Cox <Alan.Cox@linux.org>
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  *     Fixes:
  *             Alan Cox        :       Update the device on a real delete
index b0dc818a91d7fadafb9ea7308fa66f1140ca45a4..f1d07b5c1e17257c21f6669588946a0df08b77a4 100644 (file)
@@ -96,7 +96,7 @@ static void net_free(struct net *net)
                return;
        }
 #endif
-
+       kfree(net->gen);
        kmem_cache_free(net_cachep, net);
 }
 
index a756847e3814e5fc9e425f105acfd2984eccb33a..99f656d35b4f5556be314cbb3ec4c732228f5709 100644 (file)
@@ -2474,7 +2474,7 @@ static inline int process_ipsec(struct pktgen_dev *pkt_dev,
                                if (ret < 0) {
                                        printk(KERN_ERR "Error expanding "
                                               "ipsec packet %d\n",ret);
-                                       return 0;
+                                       goto err;
                                }
                        }
 
@@ -2484,8 +2484,7 @@ static inline int process_ipsec(struct pktgen_dev *pkt_dev,
                        if (ret) {
                                printk(KERN_ERR "Error creating ipsec "
                                       "packet %d\n",ret);
-                               kfree_skb(skb);
-                               return 0;
+                               goto err;
                        }
                        /* restore ll */
                        eth = (__u8 *) skb_push(skb, ETH_HLEN);
@@ -2494,6 +2493,9 @@ static inline int process_ipsec(struct pktgen_dev *pkt_dev,
                }
        }
        return 1;
+err:
+       kfree_skb(skb);
+       return 0;
 }
 #endif
 
index 3630131fa1fa37e3245301e719db583d0d63db59..31f29d2989fd207b65229cb562bc6105b79a6ca1 100644 (file)
@@ -1040,7 +1040,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        struct nlattr *linkinfo[IFLA_INFO_MAX+1];
        int err;
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 replay:
 #endif
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
@@ -1129,7 +1129,7 @@ replay:
                        return -EOPNOTSUPP;
 
                if (!ops) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                        if (kind[0]) {
                                __rtnl_unlock();
                                request_module("rtnl-link-%s", kind);
index 1f49afcd8e8688c427508903b96f6e83a856fa4a..86234923a3b7600571d434e884fed063a318c718 100644 (file)
@@ -35,7 +35,7 @@ int skb_dma_map(struct device *dev, struct sk_buff *skb,
        return 0;
 
 unwind:
-       while (i-- >= 0) {
+       while (--i >= 0) {
                skb_frag_t *fp = &sp->frags[i];
 
                dma_unmap_page(dev, sp->dma_maps[i + 1],
index 7f7bb1a636d935eb4a825d440605e1d35fde3994..4e22e3a35359169f172320337b91bf25ee7e3da7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     Routines having to do with the 'struct sk_buff' memory handlers.
  *
- *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
+ *     Authors:        Alan Cox <alan@lxorguk.ukuu.org.uk>
  *                     Florian La Roche <rzsfl@rz.uni-sb.de>
  *
  *     Fixes:
index a6b3437ff082d9cf98b59bb754b409817f3b4597..8727cead64ad5f55bd4980d4964ede930d3242a9 100644 (file)
@@ -9,7 +9,7 @@
  *
  *     Authors:        Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *                     (from old tcp.c code)
- *                     Alan Cox <alan@redhat.com> (Borrowed comments 8-))
+ *                     Alan Cox <alan@lxorguk.ukuu.org.uk> (Borrowed comments 8-))
  */
 
 #include <linux/module.h>
index 4809753d12aed1c4e6304f02d97e7a301fc44680..8fe931a3d7a1b1b7240a3421b7af0c404afae375 100644 (file)
@@ -154,7 +154,7 @@ struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
        struct ccid *ccid = NULL;
 
        ccids_read_lock();
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        if (ccids[id] == NULL) {
                /* We only try to load if in process context */
                ccids_read_unlock();
index 2f0ac3c3eb710e409ee41323b22f6f64fa2a5342..28e26bd08e24c2422e31ad52cd3f646c97d5843d 100644 (file)
@@ -152,7 +152,7 @@ static struct dn_dev_parms dn_dev_list[] =  {
 
 #define DN_DEV_LIST_SIZE ARRAY_SIZE(dn_dev_list)
 
-#define DN_DEV_PARMS_OFFSET(x) ((int) ((char *) &((struct dn_dev_parms *)0)->x))
+#define DN_DEV_PARMS_OFFSET(x) offsetof(struct dn_dev_parms, x)
 
 #ifdef CONFIG_SYSCTL
 
@@ -166,7 +166,7 @@ static int max_priority[] = { 127 }; /* From DECnet spec */
 
 static int dn_forwarding_proc(ctl_table *, int, struct file *,
                        void __user *, size_t *, loff_t *);
-static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
+static int dn_forwarding_sysctl(ctl_table *table,
                        void __user *oldval, size_t __user *oldlenp,
                        void __user *newval, size_t newlen);
 
@@ -318,7 +318,7 @@ static int dn_forwarding_proc(ctl_table *table, int write,
 #endif
 }
 
-static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
+static int dn_forwarding_sysctl(ctl_table *table,
                        void __user *oldval, size_t __user *oldlenp,
                        void __user *newval, size_t newlen)
 {
@@ -490,9 +490,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg)
                return -EFAULT;
        ifr->ifr_name[IFNAMSIZ-1] = 0;
 
-#ifdef CONFIG_KMOD
        dev_load(&init_net, ifr->ifr_name);
-#endif
 
        switch(cmd) {
                case SIOCGIFADDR:
index 228067c571ba2aaf379463a609c822a2f6797861..36400b2668967c1bb5e4eab723837f78566641f8 100644 (file)
@@ -132,7 +132,7 @@ static int parse_addr(__le16 *addr, char *str)
 }
 
 
-static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen,
+static int dn_node_address_strategy(ctl_table *table,
                                void __user *oldval, size_t __user *oldlenp,
                                void __user *newval, size_t newlen)
 {
@@ -217,7 +217,7 @@ static int dn_node_address_handler(ctl_table *table, int write,
 }
 
 
-static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen,
+static int dn_def_dev_strategy(ctl_table *table,
                                void __user *oldval, size_t __user *oldlenp,
                                void __user *newval, size_t newlen)
 {
index cdce4c6c672a03d884ad597fb3b20a4b0af17eb5..49211b35725ba74c5661717522075e7b968f303f 100644 (file)
@@ -1,7 +1,7 @@
 menuconfig NET_DSA
        bool "Distributed Switch Architecture support"
        default n
-       depends on EXPERIMENTAL
+       depends on EXPERIMENTAL && !S390
        select PHYLIB
        ---help---
          This allows you to use hardware switch chips that use
index 2c0e4572cc9042e76fca92f5c08303d1489f513c..490e035c6d90d231aee5514ac8d4a3f262ef0a4d 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <asm/bug.h>
 #include <asm/unaligned.h>
 
-struct cipso_v4_domhsh_entry {
-       char *domain;
-       u32 valid;
-       struct list_head list;
-       struct rcu_head rcu;
-};
-
 /* List of available DOI definitions */
-/* XXX - Updates should be minimal so having a single lock for the
- * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
- * okay. */
 /* XXX - This currently assumes a minimal number of different DOIs in use,
  * if in practice there are a lot of different DOIs this list should
  * probably be turned into a hash table or something similar so we
@@ -119,6 +109,19 @@ int cipso_v4_rbm_strictvalid = 1;
  * be omitted. */
 #define CIPSO_V4_TAG_RNG_CAT_MAX      8
 
+/* Base length of the local tag (non-standard tag).
+ *  Tag definition (may change between kernel versions)
+ *
+ * 0          8          16         24         32
+ * +----------+----------+----------+----------+
+ * | 10000000 | 00000110 | 32-bit secid value  |
+ * +----------+----------+----------+----------+
+ * | in (host byte order)|
+ * +----------+----------+
+ *
+ */
+#define CIPSO_V4_TAG_LOC_BLEN         6
+
 /*
  * Helper Functions
  */
@@ -193,25 +196,6 @@ static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
                bitmap[byte_spot] &= ~bitmask;
 }
 
-/**
- * cipso_v4_doi_domhsh_free - Frees a domain list entry
- * @entry: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that the memory allocated to a domain list entry can be released
- * safely.
- *
- */
-static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
-{
-       struct cipso_v4_domhsh_entry *ptr;
-
-       ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
-       kfree(ptr->domain);
-       kfree(ptr);
-}
-
 /**
  * cipso_v4_cache_entry_free - Frees a cache entry
  * @entry: the entry to free
@@ -457,7 +441,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
        struct cipso_v4_doi *iter;
 
        list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
-               if (iter->doi == doi && iter->valid)
+               if (iter->doi == doi && atomic_read(&iter->refcount))
                        return iter;
        return NULL;
 }
@@ -496,14 +480,17 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
                        if (doi_def->type != CIPSO_V4_MAP_PASS)
                                return -EINVAL;
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       if (doi_def->type != CIPSO_V4_MAP_LOCAL)
+                               return -EINVAL;
+                       break;
                default:
                        return -EINVAL;
                }
        }
 
-       doi_def->valid = 1;
+       atomic_set(&doi_def->refcount, 1);
        INIT_RCU_HEAD(&doi_def->rcu);
-       INIT_LIST_HEAD(&doi_def->dom_list);
 
        spin_lock(&cipso_v4_doi_list_lock);
        if (cipso_v4_doi_search(doi_def->doi) != NULL)
@@ -518,60 +505,130 @@ doi_add_failure:
        return -EEXIST;
 }
 
+/**
+ * cipso_v4_doi_free - Frees a DOI definition
+ * @entry: the entry's RCU field
+ *
+ * Description:
+ * This function frees all of the memory associated with a DOI definition.
+ *
+ */
+void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
+{
+       if (doi_def == NULL)
+               return;
+
+       switch (doi_def->type) {
+       case CIPSO_V4_MAP_TRANS:
+               kfree(doi_def->map.std->lvl.cipso);
+               kfree(doi_def->map.std->lvl.local);
+               kfree(doi_def->map.std->cat.cipso);
+               kfree(doi_def->map.std->cat.local);
+               break;
+       }
+       kfree(doi_def);
+}
+
+/**
+ * cipso_v4_doi_free_rcu - Frees a DOI definition via the RCU pointer
+ * @entry: the entry's RCU field
+ *
+ * Description:
+ * This function is designed to be used as a callback to the call_rcu()
+ * function so that the memory allocated to the DOI definition can be released
+ * safely.
+ *
+ */
+static void cipso_v4_doi_free_rcu(struct rcu_head *entry)
+{
+       struct cipso_v4_doi *doi_def;
+
+       doi_def = container_of(entry, struct cipso_v4_doi, rcu);
+       cipso_v4_doi_free(doi_def);
+}
+
 /**
  * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
  * @doi: the DOI value
  * @audit_secid: the LSM secid to use in the audit message
- * @callback: the DOI cleanup/free callback
  *
  * Description:
- * Removes a DOI definition from the CIPSO engine, @callback is called to
- * free any memory.  The NetLabel routines will be called to release their own
- * LSM domain mappings as well as our own domain list.  Returns zero on
- * success and negative values on failure.
+ * Removes a DOI definition from the CIPSO engine.  The NetLabel routines will
+ * be called to release their own LSM domain mappings as well as our own
+ * domain list.  Returns zero on success and negative values on failure.
  *
  */
-int cipso_v4_doi_remove(u32 doi,
-                       struct netlbl_audit *audit_info,
-                       void (*callback) (struct rcu_head * head))
+int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
 {
        struct cipso_v4_doi *doi_def;
-       struct cipso_v4_domhsh_entry *dom_iter;
 
        spin_lock(&cipso_v4_doi_list_lock);
        doi_def = cipso_v4_doi_search(doi);
-       if (doi_def != NULL) {
-               doi_def->valid = 0;
-               list_del_rcu(&doi_def->list);
+       if (doi_def == NULL) {
                spin_unlock(&cipso_v4_doi_list_lock);
-               rcu_read_lock();
-               list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
-                       if (dom_iter->valid)
-                               netlbl_cfg_map_del(dom_iter->domain,
-                                                  audit_info);
-               rcu_read_unlock();
-               cipso_v4_cache_invalidate();
-               call_rcu(&doi_def->rcu, callback);
-               return 0;
+               return -ENOENT;
+       }
+       if (!atomic_dec_and_test(&doi_def->refcount)) {
+               spin_unlock(&cipso_v4_doi_list_lock);
+               return -EBUSY;
        }
+       list_del_rcu(&doi_def->list);
        spin_unlock(&cipso_v4_doi_list_lock);
 
-       return -ENOENT;
+       cipso_v4_cache_invalidate();
+       call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
+
+       return 0;
 }
 
 /**
- * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
+ * cipso_v4_doi_getdef - Returns a reference to a valid DOI definition
  * @doi: the DOI value
  *
  * Description:
  * Searches for a valid DOI definition and if one is found it is returned to
  * the caller.  Otherwise NULL is returned.  The caller must ensure that
- * rcu_read_lock() is held while accessing the returned definition.
+ * rcu_read_lock() is held while accessing the returned definition and the DOI
+ * definition reference count is decremented when the caller is done.
  *
  */
 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
 {
-       return cipso_v4_doi_search(doi);
+       struct cipso_v4_doi *doi_def;
+
+       rcu_read_lock();
+       doi_def = cipso_v4_doi_search(doi);
+       if (doi_def == NULL)
+               goto doi_getdef_return;
+       if (!atomic_inc_not_zero(&doi_def->refcount))
+               doi_def = NULL;
+
+doi_getdef_return:
+       rcu_read_unlock();
+       return doi_def;
+}
+
+/**
+ * cipso_v4_doi_putdef - Releases a reference for the given DOI definition
+ * @doi_def: the DOI definition
+ *
+ * Description:
+ * Releases a DOI definition reference obtained from cipso_v4_doi_getdef().
+ *
+ */
+void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def)
+{
+       if (doi_def == NULL)
+               return;
+
+       if (!atomic_dec_and_test(&doi_def->refcount))
+               return;
+       spin_lock(&cipso_v4_doi_list_lock);
+       list_del_rcu(&doi_def->list);
+       spin_unlock(&cipso_v4_doi_list_lock);
+
+       cipso_v4_cache_invalidate();
+       call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
 }
 
 /**
@@ -597,7 +654,7 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
 
        rcu_read_lock();
        list_for_each_entry_rcu(iter_doi, &cipso_v4_doi_list, list)
-               if (iter_doi->valid) {
+               if (atomic_read(&iter_doi->refcount) > 0) {
                        if (doi_cnt++ < *skip_cnt)
                                continue;
                        ret_val = callback(iter_doi, cb_arg);
@@ -613,85 +670,6 @@ doi_walk_return:
        return ret_val;
 }
 
-/**
- * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
- * @doi_def: the DOI definition
- * @domain: the domain to add
- *
- * Description:
- * Adds the @domain to the DOI specified by @doi_def, this function
- * should only be called by external functions (i.e. NetLabel).  This function
- * does allocate memory.  Returns zero on success, negative values on failure.
- *
- */
-int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
-{
-       struct cipso_v4_domhsh_entry *iter;
-       struct cipso_v4_domhsh_entry *new_dom;
-
-       new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
-       if (new_dom == NULL)
-               return -ENOMEM;
-       if (domain) {
-               new_dom->domain = kstrdup(domain, GFP_KERNEL);
-               if (new_dom->domain == NULL) {
-                       kfree(new_dom);
-                       return -ENOMEM;
-               }
-       }
-       new_dom->valid = 1;
-       INIT_RCU_HEAD(&new_dom->rcu);
-
-       spin_lock(&cipso_v4_doi_list_lock);
-       list_for_each_entry(iter, &doi_def->dom_list, list)
-               if (iter->valid &&
-                   ((domain != NULL && iter->domain != NULL &&
-                     strcmp(iter->domain, domain) == 0) ||
-                    (domain == NULL && iter->domain == NULL))) {
-                       spin_unlock(&cipso_v4_doi_list_lock);
-                       kfree(new_dom->domain);
-                       kfree(new_dom);
-                       return -EEXIST;
-               }
-       list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
-       spin_unlock(&cipso_v4_doi_list_lock);
-
-       return 0;
-}
-
-/**
- * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
- * @doi_def: the DOI definition
- * @domain: the domain to remove
- *
- * Description:
- * Removes the @domain from the DOI specified by @doi_def, this function
- * should only be called by external functions (i.e. NetLabel).   Returns zero
- * on success and negative values on error.
- *
- */
-int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
-                              const char *domain)
-{
-       struct cipso_v4_domhsh_entry *iter;
-
-       spin_lock(&cipso_v4_doi_list_lock);
-       list_for_each_entry(iter, &doi_def->dom_list, list)
-               if (iter->valid &&
-                   ((domain != NULL && iter->domain != NULL &&
-                     strcmp(iter->domain, domain) == 0) ||
-                    (domain == NULL && iter->domain == NULL))) {
-                       iter->valid = 0;
-                       list_del_rcu(&iter->list);
-                       spin_unlock(&cipso_v4_doi_list_lock);
-                       call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
-                       return 0;
-               }
-       spin_unlock(&cipso_v4_doi_list_lock);
-
-       return -ENOENT;
-}
-
 /*
  * Label Mapping Functions
  */
@@ -712,7 +690,7 @@ static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level)
        switch (doi_def->type) {
        case CIPSO_V4_MAP_PASS:
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
                        return 0;
                break;
@@ -741,7 +719,7 @@ static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
        case CIPSO_V4_MAP_PASS:
                *net_lvl = host_lvl;
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                if (host_lvl < doi_def->map.std->lvl.local_size &&
                    doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) {
                        *net_lvl = doi_def->map.std->lvl.local[host_lvl];
@@ -775,7 +753,7 @@ static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
        case CIPSO_V4_MAP_PASS:
                *host_lvl = net_lvl;
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                map_tbl = doi_def->map.std;
                if (net_lvl < map_tbl->lvl.cipso_size &&
                    map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
@@ -812,7 +790,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
        switch (doi_def->type) {
        case CIPSO_V4_MAP_PASS:
                return 0;
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                cipso_cat_size = doi_def->map.std->cat.cipso_size;
                cipso_array = doi_def->map.std->cat.cipso;
                for (;;) {
@@ -860,7 +838,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
        u32 host_cat_size = 0;
        u32 *host_cat_array = NULL;
 
-       if (doi_def->type == CIPSO_V4_MAP_STD) {
+       if (doi_def->type == CIPSO_V4_MAP_TRANS) {
                host_cat_size = doi_def->map.std->cat.local_size;
                host_cat_array = doi_def->map.std->cat.local;
        }
@@ -875,7 +853,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
                case CIPSO_V4_MAP_PASS:
                        net_spot = host_spot;
                        break;
-               case CIPSO_V4_MAP_STD:
+               case CIPSO_V4_MAP_TRANS:
                        if (host_spot >= host_cat_size)
                                return -EPERM;
                        net_spot = host_cat_array[host_spot];
@@ -921,7 +899,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
        u32 net_cat_size = 0;
        u32 *net_cat_array = NULL;
 
-       if (doi_def->type == CIPSO_V4_MAP_STD) {
+       if (doi_def->type == CIPSO_V4_MAP_TRANS) {
                net_cat_size = doi_def->map.std->cat.cipso_size;
                net_cat_array = doi_def->map.std->cat.cipso;
        }
@@ -941,7 +919,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
                case CIPSO_V4_MAP_PASS:
                        host_spot = net_spot;
                        break;
-               case CIPSO_V4_MAP_STD:
+               case CIPSO_V4_MAP_TRANS:
                        if (net_spot >= net_cat_size)
                                return -EPERM;
                        host_spot = net_cat_array[net_spot];
@@ -1277,7 +1255,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x01;
+       buffer[0] = CIPSO_V4_TAG_RBITMAP;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1373,7 +1351,7 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x02;
+       buffer[0] = CIPSO_V4_TAG_ENUM;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1469,7 +1447,7 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
        } else
                tag_len = 4;
 
-       buffer[0] = 0x05;
+       buffer[0] = CIPSO_V4_TAG_RANGE;
        buffer[1] = tag_len;
        buffer[3] = level;
 
@@ -1522,6 +1500,54 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
        return 0;
 }
 
+/**
+ * cipso_v4_gentag_loc - Generate a CIPSO local tag (non-standard)
+ * @doi_def: the DOI definition
+ * @secattr: the security attributes
+ * @buffer: the option buffer
+ * @buffer_len: length of buffer in bytes
+ *
+ * Description:
+ * Generate a CIPSO option using the local tag.  Returns the size of the tag
+ * on success, negative values on failure.
+ *
+ */
+static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def,
+                              const struct netlbl_lsm_secattr *secattr,
+                              unsigned char *buffer,
+                              u32 buffer_len)
+{
+       if (!(secattr->flags & NETLBL_SECATTR_SECID))
+               return -EPERM;
+
+       buffer[0] = CIPSO_V4_TAG_LOCAL;
+       buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
+       *(u32 *)&buffer[2] = secattr->attr.secid;
+
+       return CIPSO_V4_TAG_LOC_BLEN;
+}
+
+/**
+ * cipso_v4_parsetag_loc - Parse a CIPSO local tag
+ * @doi_def: the DOI definition
+ * @tag: the CIPSO tag
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Parse a CIPSO local tag and return the security attributes in @secattr.
+ * Return zero on success, negatives values on failure.
+ *
+ */
+static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
+                                const unsigned char *tag,
+                                struct netlbl_lsm_secattr *secattr)
+{
+       secattr->attr.secid = *(u32 *)&tag[2];
+       secattr->flags |= NETLBL_SECATTR_SECID;
+
+       return 0;
+}
+
 /**
  * cipso_v4_validate - Validate a CIPSO option
  * @option: the start of the option, on error it is set to point to the error
@@ -1541,7 +1567,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
  *   that is unrecognized."
  *
  */
-int cipso_v4_validate(unsigned char **option)
+int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
 {
        unsigned char *opt = *option;
        unsigned char *tag;
@@ -1566,7 +1592,7 @@ int cipso_v4_validate(unsigned char **option)
                goto validate_return_locked;
        }
 
-       opt_iter = 6;
+       opt_iter = CIPSO_V4_HDR_LEN;
        tag = opt + opt_iter;
        while (opt_iter < opt_len) {
                for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
@@ -1584,7 +1610,7 @@ int cipso_v4_validate(unsigned char **option)
 
                switch (tag[0]) {
                case CIPSO_V4_TAG_RBITMAP:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_RBM_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1602,7 +1628,7 @@ int cipso_v4_validate(unsigned char **option)
                                        err_offset = opt_iter + 3;
                                        goto validate_return_locked;
                                }
-                               if (tag_len > 4 &&
+                               if (tag_len > CIPSO_V4_TAG_RBM_BLEN &&
                                    cipso_v4_map_cat_rbm_valid(doi_def,
                                                            &tag[4],
                                                            tag_len - 4) < 0) {
@@ -1612,7 +1638,7 @@ int cipso_v4_validate(unsigned char **option)
                        }
                        break;
                case CIPSO_V4_TAG_ENUM:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_ENUM_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1622,7 +1648,7 @@ int cipso_v4_validate(unsigned char **option)
                                err_offset = opt_iter + 3;
                                goto validate_return_locked;
                        }
-                       if (tag_len > 4 &&
+                       if (tag_len > CIPSO_V4_TAG_ENUM_BLEN &&
                            cipso_v4_map_cat_enum_valid(doi_def,
                                                        &tag[4],
                                                        tag_len - 4) < 0) {
@@ -1631,7 +1657,7 @@ int cipso_v4_validate(unsigned char **option)
                        }
                        break;
                case CIPSO_V4_TAG_RANGE:
-                       if (tag_len < 4) {
+                       if (tag_len < CIPSO_V4_TAG_RNG_BLEN) {
                                err_offset = opt_iter + 1;
                                goto validate_return_locked;
                        }
@@ -1641,7 +1667,7 @@ int cipso_v4_validate(unsigned char **option)
                                err_offset = opt_iter + 3;
                                goto validate_return_locked;
                        }
-                       if (tag_len > 4 &&
+                       if (tag_len > CIPSO_V4_TAG_RNG_BLEN &&
                            cipso_v4_map_cat_rng_valid(doi_def,
                                                       &tag[4],
                                                       tag_len - 4) < 0) {
@@ -1649,6 +1675,19 @@ int cipso_v4_validate(unsigned char **option)
                                goto validate_return_locked;
                        }
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       /* This is a non-standard tag that we only allow for
+                        * local connections, so if the incoming interface is
+                        * not the loopback device drop the packet. */
+                       if (!(skb->dev->flags & IFF_LOOPBACK)) {
+                               err_offset = opt_iter;
+                               goto validate_return_locked;
+                       }
+                       if (tag_len != CIPSO_V4_TAG_LOC_BLEN) {
+                               err_offset = opt_iter + 1;
+                               goto validate_return_locked;
+                       }
+                       break;
                default:
                        err_offset = opt_iter;
                        goto validate_return_locked;
@@ -1704,48 +1743,27 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 }
 
 /**
- * cipso_v4_sock_setattr - Add a CIPSO option to a socket
- * @sk: the socket
+ * cipso_v4_genopt - Generate a CIPSO option
+ * @buf: the option buffer
+ * @buf_len: the size of opt_buf
  * @doi_def: the CIPSO DOI to use
- * @secattr: the specific security attributes of the socket
+ * @secattr: the security attributes
  *
  * Description:
- * Set the CIPSO option on the given socket using the DOI definition and
- * security attributes passed to the function.  This function requires
- * exclusive access to @sk, which means it either needs to be in the
- * process of being created or locked.  Returns zero on success and negative
- * values on failure.
+ * Generate a CIPSO option using the DOI definition and security attributes
+ * passed to the function.  Returns the length of the option on success and
+ * negative values on failure.
  *
  */
-int cipso_v4_sock_setattr(struct sock *sk,
-                         const struct cipso_v4_doi *doi_def,
-                         const struct netlbl_lsm_secattr *secattr)
+static int cipso_v4_genopt(unsigned char *buf, u32 buf_len,
+                          const struct cipso_v4_doi *doi_def,
+                          const struct netlbl_lsm_secattr *secattr)
 {
-       int ret_val = -EPERM;
+       int ret_val;
        u32 iter;
-       unsigned char *buf;
-       u32 buf_len = 0;
-       u32 opt_len;
-       struct ip_options *opt = NULL;
-       struct inet_sock *sk_inet;
-       struct inet_connection_sock *sk_conn;
 
-       /* In the case of sock_create_lite(), the sock->sk field is not
-        * defined yet but it is not a problem as the only users of these
-        * "lite" PF_INET sockets are functions which do an accept() call
-        * afterwards so we will label the socket as part of the accept(). */
-       if (sk == NULL)
-               return 0;
-
-       /* We allocate the maximum CIPSO option size here so we are probably
-        * being a little wasteful, but it makes our life _much_ easier later
-        * on and after all we are only talking about 40 bytes. */
-       buf_len = CIPSO_V4_OPT_LEN_MAX;
-       buf = kmalloc(buf_len, GFP_ATOMIC);
-       if (buf == NULL) {
-               ret_val = -ENOMEM;
-               goto socket_setattr_failure;
-       }
+       if (buf_len <= CIPSO_V4_HDR_LEN)
+               return -ENOSPC;
 
        /* XXX - This code assumes only one tag per CIPSO option which isn't
         * really a good assumption to make but since we only support the MAC
@@ -1772,9 +1790,14 @@ int cipso_v4_sock_setattr(struct sock *sk,
                                                   &buf[CIPSO_V4_HDR_LEN],
                                                   buf_len - CIPSO_V4_HDR_LEN);
                        break;
+               case CIPSO_V4_TAG_LOCAL:
+                       ret_val = cipso_v4_gentag_loc(doi_def,
+                                                  secattr,
+                                                  &buf[CIPSO_V4_HDR_LEN],
+                                                  buf_len - CIPSO_V4_HDR_LEN);
+                       break;
                default:
-                       ret_val = -EPERM;
-                       goto socket_setattr_failure;
+                       return -EPERM;
                }
 
                iter++;
@@ -1782,9 +1805,58 @@ int cipso_v4_sock_setattr(struct sock *sk,
                 iter < CIPSO_V4_TAG_MAXCNT &&
                 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
        if (ret_val < 0)
-               goto socket_setattr_failure;
+               return ret_val;
        cipso_v4_gentag_hdr(doi_def, buf, ret_val);
-       buf_len = CIPSO_V4_HDR_LEN + ret_val;
+       return CIPSO_V4_HDR_LEN + ret_val;
+}
+
+/**
+ * cipso_v4_sock_setattr - Add a CIPSO option to a socket
+ * @sk: the socket
+ * @doi_def: the CIPSO DOI to use
+ * @secattr: the specific security attributes of the socket
+ *
+ * Description:
+ * Set the CIPSO option on the given socket using the DOI definition and
+ * security attributes passed to the function.  This function requires
+ * exclusive access to @sk, which means it either needs to be in the
+ * process of being created or locked.  Returns zero on success and negative
+ * values on failure.
+ *
+ */
+int cipso_v4_sock_setattr(struct sock *sk,
+                         const struct cipso_v4_doi *doi_def,
+                         const struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val = -EPERM;
+       unsigned char *buf = NULL;
+       u32 buf_len;
+       u32 opt_len;
+       struct ip_options *opt = NULL;
+       struct inet_sock *sk_inet;
+       struct inet_connection_sock *sk_conn;
+
+       /* In the case of sock_create_lite(), the sock->sk field is not
+        * defined yet but it is not a problem as the only users of these
+        * "lite" PF_INET sockets are functions which do an accept() call
+        * afterwards so we will label the socket as part of the accept(). */
+       if (sk == NULL)
+               return 0;
+
+       /* We allocate the maximum CIPSO option size here so we are probably
+        * being a little wasteful, but it makes our life _much_ easier later
+        * on and after all we are only talking about 40 bytes. */
+       buf_len = CIPSO_V4_OPT_LEN_MAX;
+       buf = kmalloc(buf_len, GFP_ATOMIC);
+       if (buf == NULL) {
+               ret_val = -ENOMEM;
+               goto socket_setattr_failure;
+       }
+
+       ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
+       if (ret_val < 0)
+               goto socket_setattr_failure;
+       buf_len = ret_val;
 
        /* We can't use ip_options_get() directly because it makes a call to
         * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1821,6 +1893,80 @@ socket_setattr_failure:
        return ret_val;
 }
 
+/**
+ * cipso_v4_sock_delattr - Delete the CIPSO option from a socket
+ * @sk: the socket
+ *
+ * Description:
+ * Removes the CIPSO option from a socket, if present.
+ *
+ */
+void cipso_v4_sock_delattr(struct sock *sk)
+{
+       u8 hdr_delta;
+       struct ip_options *opt;
+       struct inet_sock *sk_inet;
+
+       sk_inet = inet_sk(sk);
+       opt = sk_inet->opt;
+       if (opt == NULL || opt->cipso == 0)
+               return;
+
+       if (opt->srr || opt->rr || opt->ts || opt->router_alert) {
+               u8 cipso_len;
+               u8 cipso_off;
+               unsigned char *cipso_ptr;
+               int iter;
+               int optlen_new;
+
+               cipso_off = opt->cipso - sizeof(struct iphdr);
+               cipso_ptr = &opt->__data[cipso_off];
+               cipso_len = cipso_ptr[1];
+
+               if (opt->srr > opt->cipso)
+                       opt->srr -= cipso_len;
+               if (opt->rr > opt->cipso)
+                       opt->rr -= cipso_len;
+               if (opt->ts > opt->cipso)
+                       opt->ts -= cipso_len;
+               if (opt->router_alert > opt->cipso)
+                       opt->router_alert -= cipso_len;
+               opt->cipso = 0;
+
+               memmove(cipso_ptr, cipso_ptr + cipso_len,
+                       opt->optlen - cipso_off - cipso_len);
+
+               /* determining the new total option length is tricky because of
+                * the padding necessary, the only thing i can think to do at
+                * this point is walk the options one-by-one, skipping the
+                * padding at the end to determine the actual option size and
+                * from there we can determine the new total option length */
+               iter = 0;
+               optlen_new = 0;
+               while (iter < opt->optlen)
+                       if (opt->__data[iter] != IPOPT_NOP) {
+                               iter += opt->__data[iter + 1];
+                               optlen_new = iter;
+                       } else
+                               iter++;
+               hdr_delta = opt->optlen;
+               opt->optlen = (optlen_new + 3) & ~3;
+               hdr_delta -= opt->optlen;
+       } else {
+               /* only the cipso option was present on the socket so we can
+                * remove the entire option struct */
+               sk_inet->opt = NULL;
+               hdr_delta = opt->optlen;
+               kfree(opt);
+       }
+
+       if (sk_inet->is_icsk && hdr_delta > 0) {
+               struct inet_connection_sock *sk_conn = inet_csk(sk);
+               sk_conn->icsk_ext_hdr_len -= hdr_delta;
+               sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
+       }
+}
+
 /**
  * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions
  * @cipso: the CIPSO v4 option
@@ -1859,6 +2005,9 @@ static int cipso_v4_getattr(const unsigned char *cipso,
        case CIPSO_V4_TAG_RANGE:
                ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr);
                break;
+       case CIPSO_V4_TAG_LOCAL:
+               ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr);
+               break;
        }
        if (ret_val == 0)
                secattr->type = NETLBL_NLTYPE_CIPSOV4;
@@ -1892,6 +2041,123 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
                                secattr);
 }
 
+/**
+ * cipso_v4_skbuff_setattr - Set the CIPSO option on a packet
+ * @skb: the packet
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Set the CIPSO option on the given packet based on the security attributes.
+ * Returns a pointer to the IP header on success and NULL on failure.
+ *
+ */
+int cipso_v4_skbuff_setattr(struct sk_buff *skb,
+                           const struct cipso_v4_doi *doi_def,
+                           const struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val;
+       struct iphdr *iph;
+       struct ip_options *opt = &IPCB(skb)->opt;
+       unsigned char buf[CIPSO_V4_OPT_LEN_MAX];
+       u32 buf_len = CIPSO_V4_OPT_LEN_MAX;
+       u32 opt_len;
+       int len_delta;
+
+       buf_len = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
+       if (buf_len < 0)
+               return buf_len;
+       opt_len = (buf_len + 3) & ~3;
+
+       /* we overwrite any existing options to ensure that we have enough
+        * room for the CIPSO option, the reason is that we _need_ to guarantee
+        * that the security label is applied to the packet - we do the same
+        * thing when using the socket options and it hasn't caused a problem,
+        * if we need to we can always revisit this choice later */
+
+       len_delta = opt_len - opt->optlen;
+       /* if we don't ensure enough headroom we could panic on the skb_push()
+        * call below so make sure we have enough, we are also "mangling" the
+        * packet so we should probably do a copy-on-write call anyway */
+       ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
+       if (ret_val < 0)
+               return ret_val;
+
+       if (len_delta > 0) {
+               /* we assume that the header + opt->optlen have already been
+                * "pushed" in ip_options_build() or similar */
+               iph = ip_hdr(skb);
+               skb_push(skb, len_delta);
+               memmove((char *)iph - len_delta, iph, iph->ihl << 2);
+               skb_reset_network_header(skb);
+               iph = ip_hdr(skb);
+       } else if (len_delta < 0) {
+               iph = ip_hdr(skb);
+               memset(iph + 1, IPOPT_NOP, opt->optlen);
+       } else
+               iph = ip_hdr(skb);
+
+       if (opt->optlen > 0)
+               memset(opt, 0, sizeof(*opt));
+       opt->optlen = opt_len;
+       opt->cipso = sizeof(struct iphdr);
+       opt->is_changed = 1;
+
+       /* we have to do the following because we are being called from a
+        * netfilter hook which means the packet already has had the header
+        * fields populated and the checksum calculated - yes this means we
+        * are doing more work than needed but we do it to keep the core
+        * stack clean and tidy */
+       memcpy(iph + 1, buf, buf_len);
+       if (opt_len > buf_len)
+               memset((char *)(iph + 1) + buf_len, 0, opt_len - buf_len);
+       if (len_delta != 0) {
+               iph->ihl = 5 + (opt_len >> 2);
+               iph->tot_len = htons(skb->len);
+       }
+       ip_send_check(iph);
+
+       return 0;
+}
+
+/**
+ * cipso_v4_skbuff_delattr - Delete any CIPSO options from a packet
+ * @skb: the packet
+ *
+ * Description:
+ * Removes any and all CIPSO options from the given packet.  Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int cipso_v4_skbuff_delattr(struct sk_buff *skb)
+{
+       int ret_val;
+       struct iphdr *iph;
+       struct ip_options *opt = &IPCB(skb)->opt;
+       unsigned char *cipso_ptr;
+
+       if (opt->cipso == 0)
+               return 0;
+
+       /* since we are changing the packet we should make a copy */
+       ret_val = skb_cow(skb, skb_headroom(skb));
+       if (ret_val < 0)
+               return ret_val;
+
+       /* the easiest thing to do is just replace the cipso option with noop
+        * options since we don't change the size of the packet, although we
+        * still need to recalculate the checksum */
+
+       iph = ip_hdr(skb);
+       cipso_ptr = (unsigned char *)iph + opt->cipso;
+       memset(cipso_ptr, IPOPT_NOOP, cipso_ptr[1]);
+       opt->cipso = 0;
+       opt->is_changed = 1;
+
+       ip_send_check(iph);
+
+       return 0;
+}
+
 /**
  * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
  * @skb: the packet
index b12dae2b0b2dbcc527eee09a5d7309ffd4852ebc..56fce3ab6c55263c727357ee54c18bf70221451a 100644 (file)
@@ -613,9 +613,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        if (colon)
                *colon = 0;
 
-#ifdef CONFIG_KMOD
        dev_load(net, ifr.ifr_name);
-#endif
 
        switch (cmd) {
        case SIOCGIFADDR:       /* Get interface address */
@@ -1283,7 +1281,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
        return ret;
 }
 
-static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
+static int devinet_conf_sysctl(ctl_table *table,
                               void __user *oldval, size_t __user *oldlenp,
                               void __user *newval, size_t newlen)
 {
@@ -1379,12 +1377,11 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write,
        return ret;
 }
 
-int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
+int ipv4_doint_and_flush_strategy(ctl_table *table,
                                  void __user *oldval, size_t __user *oldlenp,
                                  void __user *newval, size_t newlen)
 {
-       int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
-                                     newval, newlen);
+       int ret = devinet_conf_sysctl(table, oldval, oldlenp, newval, newlen);
        struct net *net = table->extra2;
 
        if (ret == 1)
index 55c355e632345c9d3b07b263beea4332e2d36904..72b2de76f1cd1683b9dc33c957597a4556d9b36b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     NET3:   Implementation of the ICMP protocol layer.
  *
- *             Alan Cox, <alan@redhat.com>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
index 7f9e337e3908c9f643d00f020484f142f52bb6ef..a0d86455c53e3a69fc24adc90fcfcc2e1d293571 100644 (file)
@@ -9,7 +9,7 @@
  *     seems to fall out with gcc 2.6.2.
  *
  *     Authors:
- *             Alan Cox <Alan.Cox@linux.org>
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
index 89cb047ab31436d42a6f2dd8cf0e0c7a70c438f1..564230dabcb8a7ff172bed468a4257dd0a11616f 100644 (file)
@@ -53,11 +53,9 @@ static DEFINE_MUTEX(inet_diag_table_mutex);
 
 static const struct inet_diag_handler *inet_diag_lock_handler(int type)
 {
-#ifdef CONFIG_KMOD
        if (!inet_diag_table[type])
                request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
                               NETLINK_INET_DIAG, type);
-#endif
 
        mutex_lock(&inet_diag_table_mutex);
        if (!inet_diag_table[type])
index 2152d222b954b3eca22bba260e30a5a551316da0..e4f81f54befee04ad398f6e5a6e3877d388d65bf 100644 (file)
@@ -6,7 +6,7 @@
  *             The IP fragmentation functionality.
  *
  * Authors:    Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
- *             Alan Cox <Alan.Cox@linux.org>
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  * Fixes:
  *             Alan Cox        :       Split from ip.c , see ip_input.c for history.
index e0bed56c51f1952d9d20d75729f01e83e31e2eed..861978a4f1a8b2f92a79baf34318beb808589a64 100644 (file)
@@ -8,7 +8,7 @@
  * Authors:    Ross Biro
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Donald Becker, <becker@super.org>
- *             Alan Cox, <Alan.Cox@linux.org>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *             Richard Underwood
  *             Stefan Becker, <stefanb@yello.ping.de>
  *             Jorge Cwik, <jorge@laser.satlink.net>
index be3f18a7a40ebbbf4f40ef90bfea8702fd4f1fae..2c88da6e7862f2b49d4d9ba17197eb9d10205fe8 100644 (file)
@@ -438,7 +438,7 @@ int ip_options_compile(struct net *net,
                                goto error;
                        }
                        opt->cipso = optptr - iph;
-                       if (cipso_v4_validate(&optptr)) {
+                       if (cipso_v4_validate(skb, &optptr)) {
                                pp_ptr = optptr;
                                goto error;
                        }
index 4c6d2caf92032c4fef47b2cb042e531eae0aa193..29609d29df769350e9d1683209b372a422e9cd3d 100644 (file)
@@ -41,7 +41,7 @@
                Made the tunnels use dev->name not tunnel: when error reporting.
                Added tx_dropped stat
 
-               -Alan Cox       (Alan.Cox@linux.org) 21 March 95
+               -Alan Cox       (alan@lxorguk.ukuu.org.uk) 21 March 95
 
        Reworked:
                Changed to tunnel to destination gateway in addition to the
index c519b8d30eee5c46f4547c3a014b3832d5a090ab..b42e082cc17048ddcdee7103f933c6123c663111 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     IP multicast routing support for mrouted 3.6/3.8
  *
- *             (c) 1995 Alan Cox, <alan@redhat.com>
+ *             (c) 1995 Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *       Linux Consultancy and Custom Driver Development
  *
  *     This program is free software; you can redistribute it and/or
index aa2c50a180f7ea0d194992321dd60797e7859812..fa2d6b6fc3e581524181d88a1402df6289eb42c8 100644 (file)
@@ -41,12 +41,13 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
                                          int (*okfn)(struct sk_buff *))
 {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
        /* Previously seen (loopback)?  Ignore.  Do this before
           fragment check. */
        if (skb->nfct)
                return NF_ACCEPT;
 #endif
-
+#endif
        /* Gather fragments. */
        if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                if (nf_ct_ipv4_gather_frags(skb,
index 2ac9eaf1a8c92bfbcf546ae26c81a09aeb899551..a65cf692359fbc803032a2d9a18dead804747bc0 100644 (file)
@@ -584,6 +584,98 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {
        .flags          = NF_CT_EXT_F_PREALLOC,
 };
 
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
+       [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
+       [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
+};
+
+static int nfnetlink_parse_nat_proto(struct nlattr *attr,
+                                    const struct nf_conn *ct,
+                                    struct nf_nat_range *range)
+{
+       struct nlattr *tb[CTA_PROTONAT_MAX+1];
+       const struct nf_nat_protocol *npt;
+       int err;
+
+       err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
+       if (err < 0)
+               return err;
+
+       npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
+       if (npt->nlattr_to_range)
+               err = npt->nlattr_to_range(tb, range);
+       nf_nat_proto_put(npt);
+       return err;
+}
+
+static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
+       [CTA_NAT_MINIP]         = { .type = NLA_U32 },
+       [CTA_NAT_MAXIP]         = { .type = NLA_U32 },
+};
+
+static int
+nfnetlink_parse_nat(struct nlattr *nat,
+                   const struct nf_conn *ct, struct nf_nat_range *range)
+{
+       struct nlattr *tb[CTA_NAT_MAX+1];
+       int err;
+
+       memset(range, 0, sizeof(*range));
+
+       err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
+       if (err < 0)
+               return err;
+
+       if (tb[CTA_NAT_MINIP])
+               range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]);
+
+       if (!tb[CTA_NAT_MAXIP])
+               range->max_ip = range->min_ip;
+       else
+               range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
+
+       if (range->min_ip)
+               range->flags |= IP_NAT_RANGE_MAP_IPS;
+
+       if (!tb[CTA_NAT_PROTO])
+               return 0;
+
+       err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int
+nfnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       struct nf_nat_range range;
+
+       if (nfnetlink_parse_nat(attr, ct, &range) < 0)
+               return -EINVAL;
+       if (nf_nat_initialized(ct, manip))
+               return -EEXIST;
+
+       return nf_nat_setup_info(ct, &range, manip);
+}
+#else
+static int
+nfnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       return -EOPNOTSUPP;
+}
+#endif
+
 static int __net_init nf_nat_net_init(struct net *net)
 {
        net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
@@ -654,6 +746,9 @@ static int __init nf_nat_init(void)
 
        BUG_ON(nf_nat_seq_adjust_hook != NULL);
        rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
+       BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
+       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook,
+                          nfnetlink_parse_nat_setup);
        return 0;
 
  cleanup_extend:
@@ -667,10 +762,12 @@ static void __exit nf_nat_cleanup(void)
        nf_ct_l3proto_put(l3proto);
        nf_ct_extend_unregister(&nat_extend);
        rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
+       rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL);
        synchronize_net();
 }
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("nf-nat-ipv4");
 
 module_init(nf_nat_init);
 module_exit(nf_nat_cleanup);
index a6d7c584f53b9a4f7493ac3b73b2e4b2602f66bf..2ea6dcc3e2ccd62b6faedb97b31e2206f121764a 100644 (file)
@@ -1109,7 +1109,12 @@ restart:
                printk("\n");
        }
 #endif
-       rt_hash_table[hash].chain = rt;
+       /*
+        * Since lookup is lockfree, we must make sure
+        * previous writes to rt are comitted to memory
+        * before making rt visible to other CPUS.
+        */
+       rcu_assign_pointer(rt_hash_table[hash].chain, rt);
        spin_unlock_bh(rt_hash_lock_addr(hash));
        *rp = rt;
        return 0;
@@ -2908,8 +2913,6 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
 }
 
 static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table,
-                                               int __user *name,
-                                               int nlen,
                                                void __user *oldval,
                                                size_t __user *oldlenp,
                                                void __user *newval,
@@ -2972,16 +2975,13 @@ static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write,
 }
 
 static int ipv4_sysctl_rt_secret_interval_strategy(ctl_table *table,
-                                                  int __user *name,
-                                                  int nlen,
                                                   void __user *oldval,
                                                   size_t __user *oldlenp,
                                                   void __user *newval,
                                                   size_t newlen)
 {
        int old = ip_rt_secret_interval;
-       int ret = sysctl_jiffies(table, name, nlen, oldval, oldlenp, newval,
-                                newlen);
+       int ret = sysctl_jiffies(table, oldval, oldlenp, newval, newlen);
 
        rt_secret_reschedule(old);
 
index 276d047fb85a94eccf402ab17dc043809884f790..1bb10df8ce7dd94b89a0b43b170307557cf521f0 100644 (file)
@@ -64,8 +64,8 @@ static int ipv4_local_port_range(ctl_table *table, int write, struct file *filp,
 }
 
 /* Validate changes from sysctl interface. */
-static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
-                                        int nlen, void __user *oldval,
+static int ipv4_sysctl_local_port_range(ctl_table *table,
+                                        void __user *oldval,
                                         size_t __user *oldlenp,
                                        void __user *newval, size_t newlen)
 {
@@ -80,7 +80,7 @@ static int ipv4_sysctl_local_port_range(ctl_table *table, int __user *name,
        };
 
        inet_get_local_port_range(range, range + 1);
-       ret = sysctl_intvec(&tmp, name, nlen, oldval, oldlenp, newval, newlen);
+       ret = sysctl_intvec(&tmp, oldval, oldlenp, newval, newlen);
        if (ret == 0 && newval && newlen) {
                if (range[1] < range[0])
                        ret = -EINVAL;
@@ -109,8 +109,8 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file *
        return ret;
 }
 
-static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
-                                        int nlen, void __user *oldval,
+static int sysctl_tcp_congestion_control(ctl_table *table,
+                                        void __user *oldval,
                                         size_t __user *oldlenp,
                                         void __user *newval, size_t newlen)
 {
@@ -122,7 +122,7 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
        int ret;
 
        tcp_get_default_congestion_control(val);
-       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
+       ret = sysctl_string(&tbl, oldval, oldlenp, newval, newlen);
        if (ret == 1 && newval && newlen)
                ret = tcp_set_default_congestion_control(val);
        return ret;
@@ -165,8 +165,8 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
        return ret;
 }
 
-static int strategy_allowed_congestion_control(ctl_table *table, int __user *name,
-                                              int nlen, void __user *oldval,
+static int strategy_allowed_congestion_control(ctl_table *table,
+                                              void __user *oldval,
                                               size_t __user *oldlenp,
                                               void __user *newval,
                                               size_t newlen)
@@ -179,7 +179,7 @@ static int strategy_allowed_congestion_control(ctl_table *table, int __user *nam
                return -ENOMEM;
 
        tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
-       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
+       ret = sysctl_string(&tbl, oldval, oldlenp, newval, newlen);
        if (ret == 1 && newval && newlen)
                ret = tcp_set_allowed_congestion_control(tbl.data);
        kfree(tbl.data);
index 6a250828b767aef7f037a3cf10d10b1dd74625cb..4ec5b4e97c4e2bc97a07e5887167e26b265b9e72 100644 (file)
@@ -115,7 +115,7 @@ int tcp_set_default_congestion_control(const char *name)
 
        spin_lock(&tcp_cong_list_lock);
        ca = tcp_ca_find(name);
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        if (!ca && capable(CAP_SYS_MODULE)) {
                spin_unlock(&tcp_cong_list_lock);
 
@@ -244,7 +244,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
        if (ca == icsk->icsk_ca_ops)
                goto out;
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        /* not found attempt to autoload module */
        if (!ca && capable(CAP_SYS_MODULE)) {
                rcu_read_unlock();
index eacf4cfef146dc445eef300b852c70545c584574..2095abc3caba90e2883febab41a9b792d405ba5f 100644 (file)
@@ -8,7 +8,7 @@
  * Authors:    Ross Biro
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *             Alan Cox, <Alan.Cox@linux.org>
+ *             Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *             Hirokazu Takahashi, <taka@valinux.co.jp>
  *
  * Fixes:
index 7b6a584b62ddbcbac75ba193fe04cfebc26357da..eea9542728ca79b76b3c20427f74f9a5cad95079 100644 (file)
@@ -3982,7 +3982,6 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
 }
 
 static int addrconf_sysctl_forward_strategy(ctl_table *table,
-                                           int __user *name, int nlen,
                                            void __user *oldval,
                                            size_t __user *oldlenp,
                                            void __user *newval, size_t newlen)
index 050e14b7f7014a2f61854af31defd1483a7eb234..01edac888510cb7f4efb0c1ff994c4978a11bfaf 100644 (file)
@@ -834,7 +834,7 @@ static void __net_exit ipv6_cleanup_mibs(struct net *net)
        snmp_mib_free((void **)net->mib.icmpv6msg_statistics);
 }
 
-static int inet6_net_init(struct net *net)
+static int __net_init inet6_net_init(struct net *net)
 {
        int err = 0;
 
index 840b15780a366a7d09e8df994eabc0ddb9752f13..172438320eec74287b045cd6b784bb3de0b38b0f 100644 (file)
@@ -1199,7 +1199,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                }
                neigh->flags |= NTF_ROUTER;
        } else if (rt) {
-               rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
+               rt->rt6i_flags = (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
        }
 
        if (rt)
@@ -1730,9 +1730,8 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
        return ret;
 }
 
-int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
-                                int nlen, void __user *oldval,
-                                size_t __user *oldlenp,
+int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
+                                void __user *oldval, size_t __user *oldlenp,
                                 void __user *newval, size_t newlen)
 {
        struct net_device *dev = ctl->extra1;
@@ -1745,13 +1744,11 @@ int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
 
        switch (ctl->ctl_name) {
        case NET_NEIGH_REACHABLE_TIME:
-               ret = sysctl_jiffies(ctl, name, nlen,
-                                    oldval, oldlenp, newval, newlen);
+               ret = sysctl_jiffies(ctl, oldval, oldlenp, newval, newlen);
                break;
        case NET_NEIGH_RETRANS_TIME_MS:
        case NET_NEIGH_REACHABLE_TIME_MS:
-                ret = sysctl_ms_jiffies(ctl, name, nlen,
-                                        oldval, oldlenp, newval, newlen);
+                ret = sysctl_ms_jiffies(ctl, oldval, oldlenp, newval, newlen);
                 break;
        default:
                ret = 0;
index 6b29b03925f1f08ec7013a969c64511a8c228f13..fd5b3a4e332988056119748ae1c636dff72b53b9 100644 (file)
@@ -12,6 +12,7 @@
 
 int ip6_route_me_harder(struct sk_buff *skb)
 {
+       struct net *net = dev_net(skb->dst->dev);
        struct ipv6hdr *iph = ipv6_hdr(skb);
        struct dst_entry *dst;
        struct flowi fl = {
@@ -23,7 +24,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
                    .saddr = iph->saddr, } },
        };
 
-       dst = ip6_route_output(dev_net(skb->dst->dev), skb->sk, &fl);
+       dst = ip6_route_output(net, skb->sk, &fl);
 
 #ifdef CONFIG_XFRM
        if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@@ -33,8 +34,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
 #endif
 
        if (dst->error) {
-               IP6_INC_STATS(&init_net, ip6_dst_idev(dst),
-                             IPSTATS_MIB_OUTNOROUTES);
+               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
                LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
                dst_release(dst);
                return -EINVAL;
index 2a451562377608788b5e7ece2beac917320dca43..2ad504fc3414e19eb1b43cef909af2a68214de4b 100644 (file)
@@ -545,8 +545,12 @@ static int netdev_notify(struct notifier_block *nb,
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       sprintf(buf, "netdev:%s", dev->name);
        dir = sdata->debugfsdir;
+
+       if (!dir)
+               return 0;
+
+       sprintf(buf, "netdev:%s", dev->name);
        if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
                printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
                       "dir to %s\n", buf);
index b9902e425f096f336f93c97aa2a4494508de4272..189d0bafa91ae0f274c2813f912012679f53903d 100644 (file)
@@ -249,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
        DECLARE_MAC_BUF(mbuf);
        u8 *mac;
 
+       sta->debugfs.add_has_run = true;
+
        if (!stations_dir)
                return;
 
        mac = print_mac(mbuf, sta->sta.addr);
 
+       /*
+        * This might fail due to a race condition:
+        * When mac80211 unlinks a station, the debugfs entries
+        * remain, but it is already possible to link a new
+        * station with the same address which triggers adding
+        * it to debugfs; therefore, if the old station isn't
+        * destroyed quickly enough the old station's debugfs
+        * dir might still be around.
+        */
        sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
        if (!sta->debugfs.dir)
                return;
index 8025b294588bc0e1c44b61bfb465085cb0184c84..156e42a003ae77ac38e77aa1e047d58575e87eec 100644 (file)
@@ -816,8 +816,8 @@ struct ieee802_11_elems {
        u8 *ext_supp_rates;
        u8 *wmm_info;
        u8 *wmm_param;
-       u8 *ht_cap_elem;
-       u8 *ht_info_elem;
+       struct ieee80211_ht_cap *ht_cap_elem;
+       struct ieee80211_ht_addt_info *ht_info_elem;
        u8 *mesh_config;
        u8 *mesh_id;
        u8 *peer_link;
@@ -844,8 +844,6 @@ struct ieee802_11_elems {
        u8 ext_supp_rates_len;
        u8 wmm_info_len;
        u8 wmm_param_len;
-       u8 ht_cap_elem_len;
-       u8 ht_info_elem_len;
        u8 mesh_config_len;
        u8 mesh_id_len;
        u8 peer_link_len;
index 49f86fa56bff396adfc99daf8c921be3517a8cfb..87665d7bb4f9aa0bad666295914edca3dfefa701 100644 (file)
@@ -1348,10 +1348,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
            (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
                struct ieee80211_ht_bss_info bss_info;
                ieee80211_ht_cap_ie_to_ht_info(
-                               (struct ieee80211_ht_cap *)
                                elems.ht_cap_elem, &sta->sta.ht_info);
                ieee80211_ht_addt_info_ie_to_ht_bss_info(
-                               (struct ieee80211_ht_addt_info *)
                                elems.ht_info_elem, &bss_info);
                ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info);
        }
@@ -1709,7 +1707,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_ht_bss_info bss_info;
 
                ieee80211_ht_addt_info_ie_to_ht_bss_info(
-                               (struct ieee80211_ht_addt_info *)
                                elems.ht_info_elem, &bss_info);
                changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
                                               &bss_info);
index 77e7b014872b0bd8b2618ff7bfb65c22c56a97dc..cf6b121e1bbf58407608132c24b613c2cbd34129 100644 (file)
@@ -1379,6 +1379,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
+#ifdef CONFIG_MAC80211_MESH
 static ieee80211_rx_result
 ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 {
@@ -1453,7 +1454,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        else
                return RX_DROP_MONITOR;
 }
-
+#endif
 
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
@@ -1780,8 +1781,10 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
        /* must be after MMIC verify so header is counted in MPDU mic */
        CALL_RXH(ieee80211_rx_h_remove_qos_control)
        CALL_RXH(ieee80211_rx_h_amsdu)
+#ifdef CONFIG_MAC80211_MESH
        if (ieee80211_vif_is_mesh(&sdata->vif))
                CALL_RXH(ieee80211_rx_h_mesh_fwding);
+#endif
        CALL_RXH(ieee80211_rx_h_data)
        CALL_RXH(ieee80211_rx_h_ctrl)
        CALL_RXH(ieee80211_rx_h_action)
index 8e6685e7ae8595569582ecdf7ea67340da79f2fa..416bb41099f361159d0bc578533d08a371a7de03 100644 (file)
@@ -388,7 +388,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
        bss = ieee80211_bss_info_update(sdata->local, rx_status,
                                        mgmt, skb->len, &elems,
                                        freq, beacon);
-       ieee80211_rx_bss_put(sdata->local, bss);
+       if (bss)
+               ieee80211_rx_bss_put(sdata->local, bss);
 
        dev_kfree_skb(skb);
        return RX_QUEUED;
index 9b72d15bc8dcb7c12978c607e057a67626c482c1..7fef8ea1f5ecf53eaf5b1596479ef1d8a834b348 100644 (file)
@@ -635,7 +635,12 @@ static void sta_info_debugfs_add_work(struct work_struct *work)
 
                spin_lock_irqsave(&local->sta_lock, flags);
                list_for_each_entry(tmp, &local->sta_list, list) {
-                       if (!tmp->debugfs.dir) {
+                       /*
+                        * debugfs.add_has_run will be set by
+                        * ieee80211_sta_debugfs_add regardless
+                        * of what else it does.
+                        */
+                       if (!tmp->debugfs.add_has_run) {
                                sta = tmp;
                                __sta_info_pin(sta);
                                break;
index a6b51862a89d2b8fc46ab9bdf7ff8fc2e27d89df..168a39a298bdc1f754de9ad1d0ac04f311466d33 100644 (file)
@@ -300,6 +300,7 @@ struct sta_info {
                struct dentry *inactive_ms;
                struct dentry *last_seq_ctrl;
                struct dentry *agg_status;
+               bool add_has_run;
        } debugfs;
 #endif
 
index f32561ec224ca4fb1ec6a83a53d0b59dc7d63451..cee4884b9d06215f86b73630362fae1f9ab87168 100644 (file)
@@ -529,12 +529,12 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
                        elems->ext_supp_rates_len = elen;
                        break;
                case WLAN_EID_HT_CAPABILITY:
-                       elems->ht_cap_elem = pos;
-                       elems->ht_cap_elem_len = elen;
+                       if (elen >= sizeof(struct ieee80211_ht_cap))
+                               elems->ht_cap_elem = (void *)pos;
                        break;
                case WLAN_EID_HT_EXTRA_INFO:
-                       elems->ht_info_elem = pos;
-                       elems->ht_info_elem_len = elen;
+                       if (elen >= sizeof(struct ieee80211_ht_addt_info))
+                               elems->ht_info_elem = (void *)pos;
                        break;
                case WLAN_EID_MESH_ID:
                        elems->mesh_id = pos;
index 7e0d53abde24bb9e10b86e55d1112b76eaa63331..742f811ca416e5b16701ce2ae49f582ed32317a6 100644 (file)
@@ -775,7 +775,7 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev,
         * configure it here */
 
        if (local->ops->set_frag_threshold)
-               local->ops->set_frag_threshold(
+               return local->ops->set_frag_threshold(
                        local_to_hw(local),
                        local->fragmentation_threshold);
 
index 03591d37b9cc661f2b28b8d26b23aade24482781..b92df5c1dfcf395078ca2f766f57206f2ffad047 100644 (file)
@@ -115,7 +115,7 @@ int nf_conntrack_acct_init(struct net *net)
 
        if (net_eq(net, &init_net)) {
 #ifdef CONFIG_NF_CT_ACCT
-               printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
+       printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Please use\n");
                printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
                printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
 #endif
index 27de3c7b006e6fe5bc72e775b62b6a78db886bc3..622d7c671cb78533082f9bf0b655a3bbffcd2f92 100644 (file)
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_conntrack_acct.h>
+#include <net/netfilter/nf_nat.h>
 
 #define NF_CONNTRACK_VERSION   "0.5.0"
 
+unsigned int
+(*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
+                                 enum nf_nat_manip_type manip,
+                                 struct nlattr *attr) __read_mostly;
+EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook);
+
 DEFINE_SPINLOCK(nf_conntrack_lock);
 EXPORT_SYMBOL_GPL(nf_conntrack_lock);
 
index cadfd15b44f61457b54ea0291cd7c44e0b405df3..2e4ad9671e19c0203915a13e7b7108aa65f34a54 100644 (file)
@@ -689,71 +689,6 @@ ctnetlink_parse_tuple(struct nlattr *cda[], struct nf_conntrack_tuple *tuple,
        return 0;
 }
 
-#ifdef CONFIG_NF_NAT_NEEDED
-static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
-       [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
-       [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
-};
-
-static int nfnetlink_parse_nat_proto(struct nlattr *attr,
-                                    const struct nf_conn *ct,
-                                    struct nf_nat_range *range)
-{
-       struct nlattr *tb[CTA_PROTONAT_MAX+1];
-       const struct nf_nat_protocol *npt;
-       int err;
-
-       err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy);
-       if (err < 0)
-               return err;
-
-       npt = nf_nat_proto_find_get(nf_ct_protonum(ct));
-       if (npt->nlattr_to_range)
-               err = npt->nlattr_to_range(tb, range);
-       nf_nat_proto_put(npt);
-       return err;
-}
-
-static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
-       [CTA_NAT_MINIP]         = { .type = NLA_U32 },
-       [CTA_NAT_MAXIP]         = { .type = NLA_U32 },
-};
-
-static inline int
-nfnetlink_parse_nat(struct nlattr *nat,
-                   const struct nf_conn *ct, struct nf_nat_range *range)
-{
-       struct nlattr *tb[CTA_NAT_MAX+1];
-       int err;
-
-       memset(range, 0, sizeof(*range));
-
-       err = nla_parse_nested(tb, CTA_NAT_MAX, nat, nat_nla_policy);
-       if (err < 0)
-               return err;
-
-       if (tb[CTA_NAT_MINIP])
-               range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]);
-
-       if (!tb[CTA_NAT_MAXIP])
-               range->max_ip = range->min_ip;
-       else
-               range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
-
-       if (range->min_ip)
-               range->flags |= IP_NAT_RANGE_MAP_IPS;
-
-       if (!tb[CTA_NAT_PROTO])
-               return 0;
-
-       err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range);
-       if (err < 0)
-               return err;
-
-       return 0;
-}
-#endif
-
 static inline int
 ctnetlink_parse_help(struct nlattr *attr, char **helper_name)
 {
@@ -878,6 +813,34 @@ out:
        return err;
 }
 
+static int
+ctnetlink_parse_nat_setup(struct nf_conn *ct,
+                         enum nf_nat_manip_type manip,
+                         struct nlattr *attr)
+{
+       typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
+
+       parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook);
+       if (!parse_nat_setup) {
+#ifdef CONFIG_MODULES
+               rcu_read_unlock();
+               nfnl_unlock();
+               if (request_module("nf-nat-ipv4") < 0) {
+                       nfnl_lock();
+                       rcu_read_lock();
+                       return -EOPNOTSUPP;
+               }
+               nfnl_lock();
+               rcu_read_lock();
+               if (nfnetlink_parse_nat_setup_hook)
+                       return -EAGAIN;
+#endif
+               return -EOPNOTSUPP;
+       }
+
+       return parse_nat_setup(ct, manip, attr);
+}
+
 static int
 ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
 {
@@ -897,31 +860,6 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
                /* ASSURED bit can only be set */
                return -EBUSY;
 
-       if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
-#ifndef CONFIG_NF_NAT_NEEDED
-               return -EOPNOTSUPP;
-#else
-               struct nf_nat_range range;
-
-               if (cda[CTA_NAT_DST]) {
-                       if (nfnetlink_parse_nat(cda[CTA_NAT_DST], ct,
-                                               &range) < 0)
-                               return -EINVAL;
-                       if (nf_nat_initialized(ct, IP_NAT_MANIP_DST))
-                               return -EEXIST;
-                       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST);
-               }
-               if (cda[CTA_NAT_SRC]) {
-                       if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
-                                               &range) < 0)
-                               return -EINVAL;
-                       if (nf_nat_initialized(ct, IP_NAT_MANIP_SRC))
-                               return -EEXIST;
-                       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC);
-               }
-#endif
-       }
-
        /* Be careful here, modifying NAT bits can screw up things,
         * so don't let users modify them directly if they don't pass
         * nf_nat_range. */
@@ -929,6 +867,31 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
        return 0;
 }
 
+static int
+ctnetlink_change_nat(struct nf_conn *ct, struct nlattr *cda[])
+{
+#ifdef CONFIG_NF_NAT_NEEDED
+       int ret;
+
+       if (cda[CTA_NAT_DST]) {
+               ret = ctnetlink_parse_nat_setup(ct,
+                                               IP_NAT_MANIP_DST,
+                                               cda[CTA_NAT_DST]);
+               if (ret < 0)
+                       return ret;
+       }
+       if (cda[CTA_NAT_SRC]) {
+               ret = ctnetlink_parse_nat_setup(ct,
+                                               IP_NAT_MANIP_SRC,
+                                               cda[CTA_NAT_SRC]);
+               if (ret < 0)
+                       return ret;
+       }
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
+}
 
 static inline int
 ctnetlink_change_helper(struct nf_conn *ct, struct nlattr *cda[])
@@ -1157,6 +1120,14 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
                }
        }
 
+       if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) {
+               err = ctnetlink_change_nat(ct, cda);
+               if (err < 0) {
+                       rcu_read_unlock();
+                       goto err;
+               }
+       }
+
        if (cda[CTA_PROTOINFO]) {
                err = ctnetlink_change_protoinfo(ct, cda);
                if (err < 0) {
index 373e51e91ce5bb07176ff87cf883309c616aa880..1bc3001d182773e33872081d4b40fc7bf6f4e95d 100644 (file)
@@ -65,7 +65,7 @@ void
                             struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#ifdef DEBUG
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
 /* PptpControlMessageType names */
 const char *const pptp_msg_name[] = {
        "UNKNOWN_MESSAGE",
index fe34f4bf74ccd43942898b528db25c5e49b48c64..cdc97f3105a3153e4c55cfb57f5eb4994d393922 100644 (file)
@@ -10,7 +10,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/net.h>
index b75c9c4a995d885c1ac12339b0afff9d1d24db31..9c0ba17a1ddb771ea8fc58b3bfd7ae55b245cceb 100644 (file)
@@ -44,15 +44,17 @@ static struct sock *nfnl = NULL;
 static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
 static DEFINE_MUTEX(nfnl_mutex);
 
-static inline void nfnl_lock(void)
+void nfnl_lock(void)
 {
        mutex_lock(&nfnl_mutex);
 }
+EXPORT_SYMBOL_GPL(nfnl_lock);
 
-static inline void nfnl_unlock(void)
+void nfnl_unlock(void)
 {
        mutex_unlock(&nfnl_mutex);
 }
+EXPORT_SYMBOL_GPL(nfnl_unlock);
 
 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
 {
@@ -132,9 +134,10 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                return 0;
 
        type = nlh->nlmsg_type;
+replay:
        ss = nfnetlink_get_subsys(type);
        if (!ss) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                nfnl_unlock();
                request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
                nfnl_lock();
@@ -165,7 +168,10 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                } else
                        return -EINVAL;
 
-               return nc->call(nfnl, skb, nlh, cda);
+               err = nc->call(nfnl, skb, nlh, cda);
+               if (err == -EAGAIN)
+                       goto replay;
+               return err;
        }
 }
 
index 8af18c0a47d90b778c7f79cbfe57ac6bc5b684c9..ea750e9df65f7bdbfafcd6ae4246d6d9520707ee 100644 (file)
@@ -5,7 +5,8 @@
 #
 
 # base objects
-obj-y  := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o
+obj-y  := netlabel_user.o netlabel_kapi.o
+obj-y  += netlabel_domainhash.o netlabel_addrlist.o
 
 # management objects
 obj-y  += netlabel_mgmt.o
diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c
new file mode 100644 (file)
index 0000000..b0925a3
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * NetLabel Network Address Lists
+ *
+ * This file contains network address list functions used to manage ordered
+ * lists of network addresses for use by the NetLabel subsystem.  The NetLabel
+ * system manages static and dynamic label mappings for network protocols such
+ * as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <linux/audit.h>
+
+#include "netlabel_addrlist.h"
+
+/*
+ * Address List Functions
+ */
+
+/**
+ * netlbl_af4list_search - Search for a matching IPv4 address entry
+ * @addr: IPv4 address
+ * @head: the list head
+ *
+ * Description:
+ * Searches the IPv4 address list given by @head.  If a matching address entry
+ * is found it is returned, otherwise NULL is returned.  The caller is
+ * responsible for calling the rcu_read_[un]lock() functions.
+ *
+ */
+struct netlbl_af4list *netlbl_af4list_search(__be32 addr,
+                                            struct list_head *head)
+{
+       struct netlbl_af4list *iter;
+
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid && (addr & iter->mask) == iter->addr)
+                       return iter;
+
+       return NULL;
+}
+
+/**
+ * netlbl_af4list_search_exact - Search for an exact IPv4 address entry
+ * @addr: IPv4 address
+ * @mask: IPv4 address mask
+ * @head: the list head
+ *
+ * Description:
+ * Searches the IPv4 address list given by @head.  If an exact match if found
+ * it is returned, otherwise NULL is returned.  The caller is responsible for
+ * calling the rcu_read_[un]lock() functions.
+ *
+ */
+struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr,
+                                                  __be32 mask,
+                                                  struct list_head *head)
+{
+       struct netlbl_af4list *iter;
+
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid && iter->addr == addr && iter->mask == mask)
+                       return iter;
+
+       return NULL;
+}
+
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * netlbl_af6list_search - Search for a matching IPv6 address entry
+ * @addr: IPv6 address
+ * @head: the list head
+ *
+ * Description:
+ * Searches the IPv6 address list given by @head.  If a matching address entry
+ * is found it is returned, otherwise NULL is returned.  The caller is
+ * responsible for calling the rcu_read_[un]lock() functions.
+ *
+ */
+struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
+                                            struct list_head *head)
+{
+       struct netlbl_af6list *iter;
+
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid &&
+                   ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
+                       return iter;
+
+       return NULL;
+}
+
+/**
+ * netlbl_af6list_search_exact - Search for an exact IPv6 address entry
+ * @addr: IPv6 address
+ * @mask: IPv6 address mask
+ * @head: the list head
+ *
+ * Description:
+ * Searches the IPv6 address list given by @head.  If an exact match if found
+ * it is returned, otherwise NULL is returned.  The caller is responsible for
+ * calling the rcu_read_[un]lock() functions.
+ *
+ */
+struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr,
+                                                  const struct in6_addr *mask,
+                                                  struct list_head *head)
+{
+       struct netlbl_af6list *iter;
+
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid &&
+                   ipv6_addr_equal(&iter->addr, addr) &&
+                   ipv6_addr_equal(&iter->mask, mask))
+                       return iter;
+
+       return NULL;
+}
+#endif /* IPv6 */
+
+/**
+ * netlbl_af4list_add - Add a new IPv4 address entry to a list
+ * @entry: address entry
+ * @head: the list head
+ *
+ * Description:
+ * Add a new address entry to the list pointed to by @head.  On success zero is
+ * returned, otherwise a negative value is returned.  The caller is responsible
+ * for calling the necessary locking functions.
+ *
+ */
+int netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head)
+{
+       struct netlbl_af4list *iter;
+
+       iter = netlbl_af4list_search(entry->addr, head);
+       if (iter != NULL &&
+           iter->addr == entry->addr && iter->mask == entry->mask)
+               return -EEXIST;
+
+       /* in order to speed up address searches through the list (the common
+        * case) we need to keep the list in order based on the size of the
+        * address mask such that the entry with the widest mask (smallest
+        * numerical value) appears first in the list */
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid &&
+                   ntohl(entry->mask) > ntohl(iter->mask)) {
+                       __list_add_rcu(&entry->list,
+                                      iter->list.prev,
+                                      &iter->list);
+                       return 0;
+               }
+       list_add_tail_rcu(&entry->list, head);
+       return 0;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * netlbl_af6list_add - Add a new IPv6 address entry to a list
+ * @entry: address entry
+ * @head: the list head
+ *
+ * Description:
+ * Add a new address entry to the list pointed to by @head.  On success zero is
+ * returned, otherwise a negative value is returned.  The caller is responsible
+ * for calling the necessary locking functions.
+ *
+ */
+int netlbl_af6list_add(struct netlbl_af6list *entry, struct list_head *head)
+{
+       struct netlbl_af6list *iter;
+
+       iter = netlbl_af6list_search(&entry->addr, head);
+       if (iter != NULL &&
+           ipv6_addr_equal(&iter->addr, &entry->addr) &&
+           ipv6_addr_equal(&iter->mask, &entry->mask))
+               return -EEXIST;
+
+       /* in order to speed up address searches through the list (the common
+        * case) we need to keep the list in order based on the size of the
+        * address mask such that the entry with the widest mask (smallest
+        * numerical value) appears first in the list */
+       list_for_each_entry_rcu(iter, head, list)
+               if (iter->valid &&
+                   ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
+                       __list_add_rcu(&entry->list,
+                                      iter->list.prev,
+                                      &iter->list);
+                       return 0;
+               }
+       list_add_tail_rcu(&entry->list, head);
+       return 0;
+}
+#endif /* IPv6 */
+
+/**
+ * netlbl_af4list_remove_entry - Remove an IPv4 address entry
+ * @entry: address entry
+ *
+ * Description:
+ * Remove the specified IP address entry.  The caller is responsible for
+ * calling the necessary locking functions.
+ *
+ */
+void netlbl_af4list_remove_entry(struct netlbl_af4list *entry)
+{
+       entry->valid = 0;
+       list_del_rcu(&entry->list);
+}
+
+/**
+ * netlbl_af4list_remove - Remove an IPv4 address entry
+ * @addr: IP address
+ * @mask: IP address mask
+ * @head: the list head
+ *
+ * Description:
+ * Remove an IP address entry from the list pointed to by @head.  Returns the
+ * entry on success, NULL on failure.  The caller is responsible for calling
+ * the necessary locking functions.
+ *
+ */
+struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
+                                            struct list_head *head)
+{
+       struct netlbl_af4list *entry;
+
+       entry = netlbl_af4list_search(addr, head);
+       if (entry != NULL && entry->addr == addr && entry->mask == mask) {
+               netlbl_af4list_remove_entry(entry);
+               return entry;
+       }
+
+       return NULL;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * netlbl_af6list_remove_entry - Remove an IPv6 address entry
+ * @entry: address entry
+ *
+ * Description:
+ * Remove the specified IP address entry.  The caller is responsible for
+ * calling the necessary locking functions.
+ *
+ */
+void netlbl_af6list_remove_entry(struct netlbl_af6list *entry)
+{
+       entry->valid = 0;
+       list_del_rcu(&entry->list);
+}
+
+/**
+ * netlbl_af6list_remove - Remove an IPv6 address entry
+ * @addr: IP address
+ * @mask: IP address mask
+ * @head: the list head
+ *
+ * Description:
+ * Remove an IP address entry from the list pointed to by @head.  Returns the
+ * entry on success, NULL on failure.  The caller is responsible for calling
+ * the necessary locking functions.
+ *
+ */
+struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
+                                            const struct in6_addr *mask,
+                                            struct list_head *head)
+{
+       struct netlbl_af6list *entry;
+
+       entry = netlbl_af6list_search(addr, head);
+       if (entry != NULL &&
+           ipv6_addr_equal(&entry->addr, addr) &&
+           ipv6_addr_equal(&entry->mask, mask)) {
+               netlbl_af6list_remove_entry(entry);
+               return entry;
+       }
+
+       return NULL;
+}
+#endif /* IPv6 */
+
+/*
+ * Audit Helper Functions
+ */
+
+/**
+ * netlbl_af4list_audit_addr - Audit an IPv4 address
+ * @audit_buf: audit buffer
+ * @src: true if source address, false if destination
+ * @dev: network interface
+ * @addr: IP address
+ * @mask: IP address mask
+ *
+ * Description:
+ * Write the IPv4 address and address mask, if necessary, to @audit_buf.
+ *
+ */
+void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
+                                       int src, const char *dev,
+                                       __be32 addr, __be32 mask)
+{
+       u32 mask_val = ntohl(mask);
+       char *dir = (src ? "src" : "dst");
+
+       if (dev != NULL)
+               audit_log_format(audit_buf, " netif=%s", dev);
+       audit_log_format(audit_buf, " %s=" NIPQUAD_FMT, dir, NIPQUAD(addr));
+       if (mask_val != 0xffffffff) {
+               u32 mask_len = 0;
+               while (mask_val > 0) {
+                       mask_val <<= 1;
+                       mask_len++;
+               }
+               audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
+       }
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * netlbl_af6list_audit_addr - Audit an IPv6 address
+ * @audit_buf: audit buffer
+ * @src: true if source address, false if destination
+ * @dev: network interface
+ * @addr: IP address
+ * @mask: IP address mask
+ *
+ * Description:
+ * Write the IPv6 address and address mask, if necessary, to @audit_buf.
+ *
+ */
+void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
+                                int src,
+                                const char *dev,
+                                const struct in6_addr *addr,
+                                const struct in6_addr *mask)
+{
+       char *dir = (src ? "src" : "dst");
+
+       if (dev != NULL)
+               audit_log_format(audit_buf, " netif=%s", dev);
+       audit_log_format(audit_buf, " %s=" NIP6_FMT, dir, NIP6(*addr));
+       if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
+               u32 mask_len = 0;
+               u32 mask_val;
+               int iter = -1;
+               while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
+                       mask_len += 32;
+               mask_val = ntohl(mask->s6_addr32[iter]);
+               while (mask_val > 0) {
+                       mask_val <<= 1;
+                       mask_len++;
+               }
+               audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len);
+       }
+}
+#endif /* IPv6 */
diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h
new file mode 100644 (file)
index 0000000..0242bea
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * NetLabel Network Address Lists
+ *
+ * This file contains network address list functions used to manage ordered
+ * lists of network addresses for use by the NetLabel subsystem.  The NetLabel
+ * system manages static and dynamic label mappings for network protocols such
+ * as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2008
+ *
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the 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 _NETLABEL_ADDRLIST_H
+#define _NETLABEL_ADDRLIST_H
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/in6.h>
+#include <linux/audit.h>
+
+/**
+ * struct netlbl_af4list - NetLabel IPv4 address list
+ * @addr: IPv4 address
+ * @mask: IPv4 address mask
+ * @valid: valid flag
+ * @list: list structure, used internally
+ */
+struct netlbl_af4list {
+       __be32 addr;
+       __be32 mask;
+
+       u32 valid;
+       struct list_head list;
+};
+
+/**
+ * struct netlbl_af6list - NetLabel IPv6 address list
+ * @addr: IPv6 address
+ * @mask: IPv6 address mask
+ * @valid: valid flag
+ * @list: list structure, used internally
+ */
+struct netlbl_af6list {
+       struct in6_addr addr;
+       struct in6_addr mask;
+
+       u32 valid;
+       struct list_head list;
+};
+
+#define __af4list_entry(ptr) container_of(ptr, struct netlbl_af4list, list)
+
+static inline struct netlbl_af4list *__af4list_valid(struct list_head *s,
+                                                    struct list_head *h)
+{
+       struct list_head *i = s;
+       struct netlbl_af4list *n = __af4list_entry(s);
+       while (i != h && !n->valid) {
+               i = i->next;
+               n = __af4list_entry(i);
+       }
+       return n;
+}
+
+static inline struct netlbl_af4list *__af4list_valid_rcu(struct list_head *s,
+                                                        struct list_head *h)
+{
+       struct list_head *i = s;
+       struct netlbl_af4list *n = __af4list_entry(s);
+       while (i != h && !n->valid) {
+               i = rcu_dereference(i->next);
+               n = __af4list_entry(i);
+       }
+       return n;
+}
+
+#define netlbl_af4list_foreach(iter, head)                             \
+       for (iter = __af4list_valid((head)->next, head);                \
+            prefetch(iter->list.next), &iter->list != (head);          \
+            iter = __af4list_valid(iter->list.next, head))
+
+#define netlbl_af4list_foreach_rcu(iter, head)                         \
+       for (iter = __af4list_valid_rcu((head)->next, head);            \
+            prefetch(iter->list.next), &iter->list != (head);          \
+            iter = __af4list_valid_rcu(iter->list.next, head))
+
+#define netlbl_af4list_foreach_safe(iter, tmp, head)                   \
+       for (iter = __af4list_valid((head)->next, head),                \
+                    tmp = __af4list_valid(iter->list.next, head);      \
+            &iter->list != (head);                                     \
+            iter = tmp, tmp = __af4list_valid(iter->list.next, head))
+
+int netlbl_af4list_add(struct netlbl_af4list *entry,
+                      struct list_head *head);
+struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask,
+                                            struct list_head *head);
+void netlbl_af4list_remove_entry(struct netlbl_af4list *entry);
+struct netlbl_af4list *netlbl_af4list_search(__be32 addr,
+                                            struct list_head *head);
+struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr,
+                                                  __be32 mask,
+                                                  struct list_head *head);
+void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf,
+                              int src, const char *dev,
+                              __be32 addr, __be32 mask);
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+#define __af6list_entry(ptr) container_of(ptr, struct netlbl_af6list, list)
+
+static inline struct netlbl_af6list *__af6list_valid(struct list_head *s,
+                                                    struct list_head *h)
+{
+       struct list_head *i = s;
+       struct netlbl_af6list *n = __af6list_entry(s);
+       while (i != h && !n->valid) {
+               i = i->next;
+               n = __af6list_entry(i);
+       }
+       return n;
+}
+
+static inline struct netlbl_af6list *__af6list_valid_rcu(struct list_head *s,
+                                                        struct list_head *h)
+{
+       struct list_head *i = s;
+       struct netlbl_af6list *n = __af6list_entry(s);
+       while (i != h && !n->valid) {
+               i = rcu_dereference(i->next);
+               n = __af6list_entry(i);
+       }
+       return n;
+}
+
+#define netlbl_af6list_foreach(iter, head)                             \
+       for (iter = __af6list_valid((head)->next, head);                \
+            prefetch(iter->list.next), &iter->list != (head);          \
+            iter = __af6list_valid(iter->list.next, head))
+
+#define netlbl_af6list_foreach_rcu(iter, head)                         \
+       for (iter = __af6list_valid_rcu((head)->next, head);            \
+            prefetch(iter->list.next), &iter->list != (head);          \
+            iter = __af6list_valid_rcu(iter->list.next, head))
+
+#define netlbl_af6list_foreach_safe(iter, tmp, head)                   \
+       for (iter = __af6list_valid((head)->next, head),                \
+                    tmp = __af6list_valid(iter->list.next, head);      \
+            &iter->list != (head);                                     \
+            iter = tmp, tmp = __af6list_valid(iter->list.next, head))
+
+int netlbl_af6list_add(struct netlbl_af6list *entry,
+                      struct list_head *head);
+struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr,
+                                            const struct in6_addr *mask,
+                                            struct list_head *head);
+void netlbl_af6list_remove_entry(struct netlbl_af6list *entry);
+struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr,
+                                            struct list_head *head);
+struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr,
+                                                  const struct in6_addr *mask,
+                                                  struct list_head *head);
+void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf,
+                              int src,
+                              const char *dev,
+                              const struct in6_addr *addr,
+                              const struct in6_addr *mask);
+#endif /* IPV6 */
+
+#endif
index 0aec318bf0ef17aed66c4ec10881846403f0d9b4..fff32b70efa9d9d0e1b71e7ef56dce87ee83736a 100644 (file)
@@ -43,6 +43,7 @@
 #include "netlabel_user.h"
 #include "netlabel_cipso_v4.h"
 #include "netlabel_mgmt.h"
+#include "netlabel_domainhash.h"
 
 /* Argument struct for cipso_v4_doi_walk() */
 struct netlbl_cipsov4_doiwalk_arg {
@@ -51,6 +52,12 @@ struct netlbl_cipsov4_doiwalk_arg {
        u32 seq;
 };
 
+/* Argument struct for netlbl_domhsh_walk() */
+struct netlbl_domhsh_walk_arg {
+       struct netlbl_audit *audit_info;
+       u32 doi;
+};
+
 /* NetLabel Generic NETLINK CIPSOv4 family */
 static struct genl_family netlbl_cipsov4_gnl_family = {
        .id = GENL_ID_GENERATE,
@@ -80,32 +87,6 @@ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1
  * Helper Functions
  */
 
-/**
- * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition
- * @entry: the entry's RCU field
- *
- * Description:
- * This function is designed to be used as a callback to the call_rcu()
- * function so that the memory allocated to the DOI definition can be released
- * safely.
- *
- */
-void netlbl_cipsov4_doi_free(struct rcu_head *entry)
-{
-       struct cipso_v4_doi *ptr;
-
-       ptr = container_of(entry, struct cipso_v4_doi, rcu);
-       switch (ptr->type) {
-       case CIPSO_V4_MAP_STD:
-               kfree(ptr->map.std->lvl.cipso);
-               kfree(ptr->map.std->lvl.local);
-               kfree(ptr->map.std->cat.cipso);
-               kfree(ptr->map.std->cat.local);
-               break;
-       }
-       kfree(ptr);
-}
-
 /**
  * netlbl_cipsov4_add_common - Parse the common sections of a ADD message
  * @info: the Generic NETLINK info block
@@ -151,9 +132,9 @@ static int netlbl_cipsov4_add_common(struct genl_info *info,
  * @info: the Generic NETLINK info block
  *
  * Description:
- * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
- * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
- * error.
+ * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
+ * message and add it to the CIPSO V4 engine.  Return zero on success and
+ * non-zero on error.
  *
  */
 static int netlbl_cipsov4_add_std(struct genl_info *info)
@@ -183,7 +164,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
                ret_val = -ENOMEM;
                goto add_std_failure;
        }
-       doi_def->type = CIPSO_V4_MAP_STD;
+       doi_def->type = CIPSO_V4_MAP_TRANS;
 
        ret_val = netlbl_cipsov4_add_common(info, doi_def);
        if (ret_val != 0)
@@ -342,7 +323,7 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
 
 add_std_failure:
        if (doi_def)
-               netlbl_cipsov4_doi_free(&doi_def->rcu);
+               cipso_v4_doi_free(doi_def);
        return ret_val;
 }
 
@@ -379,7 +360,44 @@ static int netlbl_cipsov4_add_pass(struct genl_info *info)
        return 0;
 
 add_pass_failure:
-       netlbl_cipsov4_doi_free(&doi_def->rcu);
+       cipso_v4_doi_free(doi_def);
+       return ret_val;
+}
+
+/**
+ * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
+ * @info: the Generic NETLINK info block
+ *
+ * Description:
+ * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
+ * message and add it to the CIPSO V4 engine.  Return zero on success and
+ * non-zero on error.
+ *
+ */
+static int netlbl_cipsov4_add_local(struct genl_info *info)
+{
+       int ret_val;
+       struct cipso_v4_doi *doi_def = NULL;
+
+       if (!info->attrs[NLBL_CIPSOV4_A_TAGLST])
+               return -EINVAL;
+
+       doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
+       if (doi_def == NULL)
+               return -ENOMEM;
+       doi_def->type = CIPSO_V4_MAP_LOCAL;
+
+       ret_val = netlbl_cipsov4_add_common(info, doi_def);
+       if (ret_val != 0)
+               goto add_local_failure;
+
+       ret_val = cipso_v4_doi_add(doi_def);
+       if (ret_val != 0)
+               goto add_local_failure;
+       return 0;
+
+add_local_failure:
+       cipso_v4_doi_free(doi_def);
        return ret_val;
 }
 
@@ -412,14 +430,18 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
 
        type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
        switch (type) {
-       case CIPSO_V4_MAP_STD:
-               type_str = "std";
+       case CIPSO_V4_MAP_TRANS:
+               type_str = "trans";
                ret_val = netlbl_cipsov4_add_std(info);
                break;
        case CIPSO_V4_MAP_PASS:
                type_str = "pass";
                ret_val = netlbl_cipsov4_add_pass(info);
                break;
+       case CIPSO_V4_MAP_LOCAL:
+               type_str = "local";
+               ret_val = netlbl_cipsov4_add_local(info);
+               break;
        }
        if (ret_val == 0)
                atomic_inc(&netlabel_mgmt_protocount);
@@ -491,7 +513,7 @@ list_start:
        doi_def = cipso_v4_doi_getdef(doi);
        if (doi_def == NULL) {
                ret_val = -EINVAL;
-               goto list_failure;
+               goto list_failure_lock;
        }
 
        ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
@@ -516,7 +538,7 @@ list_start:
        nla_nest_end(ans_skb, nla_a);
 
        switch (doi_def->type) {
-       case CIPSO_V4_MAP_STD:
+       case CIPSO_V4_MAP_TRANS:
                nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
                if (nla_a == NULL) {
                        ret_val = -ENOMEM;
@@ -655,7 +677,7 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb,
                                  struct netlink_callback *cb)
 {
        struct netlbl_cipsov4_doiwalk_arg cb_arg;
-       int doi_skip = cb->args[0];
+       u32 doi_skip = cb->args[0];
 
        cb_arg.nl_cb = cb;
        cb_arg.skb = skb;
@@ -667,6 +689,29 @@ static int netlbl_cipsov4_listall(struct sk_buff *skb,
        return skb->len;
 }
 
+/**
+ * netlbl_cipsov4_remove_cb - netlbl_cipsov4_remove() callback for REMOVE
+ * @entry: LSM domain mapping entry
+ * @arg: the netlbl_domhsh_walk_arg structure
+ *
+ * Description:
+ * This function is intended for use by netlbl_cipsov4_remove() as the callback
+ * for the netlbl_domhsh_walk() function; it removes LSM domain map entries
+ * which are associated with the CIPSO DOI specified in @arg.  Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int netlbl_cipsov4_remove_cb(struct netlbl_dom_map *entry, void *arg)
+{
+       struct netlbl_domhsh_walk_arg *cb_arg = arg;
+
+       if (entry->type == NETLBL_NLTYPE_CIPSOV4 &&
+           entry->type_def.cipsov4->doi == cb_arg->doi)
+               return netlbl_domhsh_remove_entry(entry, cb_arg->audit_info);
+
+       return 0;
+}
+
 /**
  * netlbl_cipsov4_remove - Handle a REMOVE message
  * @skb: the NETLINK buffer
@@ -681,8 +726,11 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
 {
        int ret_val = -EINVAL;
        u32 doi = 0;
+       struct netlbl_domhsh_walk_arg cb_arg;
        struct audit_buffer *audit_buf;
        struct netlbl_audit audit_info;
+       u32 skip_bkt = 0;
+       u32 skip_chain = 0;
 
        if (!info->attrs[NLBL_CIPSOV4_A_DOI])
                return -EINVAL;
@@ -690,11 +738,15 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
        doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
        netlbl_netlink_auditinfo(skb, &audit_info);
 
-       ret_val = cipso_v4_doi_remove(doi,
-                                     &audit_info,
-                                     netlbl_cipsov4_doi_free);
-       if (ret_val == 0)
-               atomic_dec(&netlabel_mgmt_protocount);
+       cb_arg.doi = doi;
+       cb_arg.audit_info = &audit_info;
+       ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
+                                    netlbl_cipsov4_remove_cb, &cb_arg);
+       if (ret_val == 0 || ret_val == -ENOENT) {
+               ret_val = cipso_v4_doi_remove(doi, &audit_info);
+               if (ret_val == 0)
+                       atomic_dec(&netlabel_mgmt_protocount);
+       }
 
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
                                              &audit_info);
index 220cb9d06b496d315d30c1041a03525421b4a9e2..c8a4079261f04a88147695554865bab3765ce3bd 100644 (file)
  *     NLBL_CIPSOV4_A_MTYPE
  *     NLBL_CIPSOV4_A_TAGLST
  *
- *   If using CIPSO_V4_MAP_STD the following attributes are required:
+ *   If using CIPSO_V4_MAP_TRANS the following attributes are required:
  *
  *     NLBL_CIPSOV4_A_MLSLVLLST
  *     NLBL_CIPSOV4_A_MLSCATLST
  *
- *   If using CIPSO_V4_MAP_PASS no additional attributes are required.
+ *   If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes
+ *   are required.
  *
  * o REMOVE:
  *   Sent by an application to remove a specific DOI mapping table from the
  *     NLBL_CIPSOV4_A_MTYPE
  *     NLBL_CIPSOV4_A_TAGLST
  *
- *   If using CIPSO_V4_MAP_STD the following attributes are required:
+ *   If using CIPSO_V4_MAP_TRANS the following attributes are required:
  *
  *     NLBL_CIPSOV4_A_MLSLVLLST
  *     NLBL_CIPSOV4_A_MLSCATLST
  *
- *   If using CIPSO_V4_MAP_PASS no additional attributes are required.
+ *   If using CIPSO_V4_MAP_PASS or CIPSO_V4_MAP_LOCAL no additional attributes
+ *   are required.
  *
  * o LISTALL:
  *   This message is sent by an application to list the valid DOIs on the
index 643c032a3a57dd50a89a92d3536e52ad03c5d01a..5fadf10e5ddfe39cf19eb760f2b404d93d8c53b3 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@
 #include <asm/bug.h>
 
 #include "netlabel_mgmt.h"
+#include "netlabel_addrlist.h"
 #include "netlabel_domainhash.h"
 #include "netlabel_user.h"
 
@@ -72,8 +73,28 @@ static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
 static void netlbl_domhsh_free_entry(struct rcu_head *entry)
 {
        struct netlbl_dom_map *ptr;
+       struct netlbl_af4list *iter4;
+       struct netlbl_af4list *tmp4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *iter6;
+       struct netlbl_af6list *tmp6;
+#endif /* IPv6 */
 
        ptr = container_of(entry, struct netlbl_dom_map, rcu);
+       if (ptr->type == NETLBL_NLTYPE_ADDRSELECT) {
+               netlbl_af4list_foreach_safe(iter4, tmp4,
+                                           &ptr->type_def.addrsel->list4) {
+                       netlbl_af4list_remove_entry(iter4);
+                       kfree(netlbl_domhsh_addr4_entry(iter4));
+               }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               netlbl_af6list_foreach_safe(iter6, tmp6,
+                                           &ptr->type_def.addrsel->list6) {
+                       netlbl_af6list_remove_entry(iter6);
+                       kfree(netlbl_domhsh_addr6_entry(iter6));
+               }
+#endif /* IPv6 */
+       }
        kfree(ptr->domain);
        kfree(ptr);
 }
@@ -115,13 +136,13 @@ static u32 netlbl_domhsh_hash(const char *key)
 static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
 {
        u32 bkt;
+       struct list_head *bkt_list;
        struct netlbl_dom_map *iter;
 
        if (domain != NULL) {
                bkt = netlbl_domhsh_hash(domain);
-               list_for_each_entry_rcu(iter,
-                                    &rcu_dereference(netlbl_domhsh)->tbl[bkt],
-                                    list)
+               bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt];
+               list_for_each_entry_rcu(iter, bkt_list, list)
                        if (iter->valid && strcmp(iter->domain, domain) == 0)
                                return iter;
        }
@@ -156,6 +177,69 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
        return entry;
 }
 
+/**
+ * netlbl_domhsh_audit_add - Generate an audit entry for an add event
+ * @entry: the entry being added
+ * @addr4: the IPv4 address information
+ * @addr6: the IPv6 address information
+ * @result: the result code
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Generate an audit record for adding a new NetLabel/LSM mapping entry with
+ * the given information.  Caller is responsibile for holding the necessary
+ * locks.
+ *
+ */
+static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry,
+                                   struct netlbl_af4list *addr4,
+                                   struct netlbl_af6list *addr6,
+                                   int result,
+                                   struct netlbl_audit *audit_info)
+{
+       struct audit_buffer *audit_buf;
+       struct cipso_v4_doi *cipsov4 = NULL;
+       u32 type;
+
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
+       if (audit_buf != NULL) {
+               audit_log_format(audit_buf, " nlbl_domain=%s",
+                                entry->domain ? entry->domain : "(default)");
+               if (addr4 != NULL) {
+                       struct netlbl_domaddr4_map *map4;
+                       map4 = netlbl_domhsh_addr4_entry(addr4);
+                       type = map4->type;
+                       cipsov4 = map4->type_def.cipsov4;
+                       netlbl_af4list_audit_addr(audit_buf, 0, NULL,
+                                                 addr4->addr, addr4->mask);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               } else if (addr6 != NULL) {
+                       struct netlbl_domaddr6_map *map6;
+                       map6 = netlbl_domhsh_addr6_entry(addr6);
+                       type = map6->type;
+                       netlbl_af6list_audit_addr(audit_buf, 0, NULL,
+                                                 &addr6->addr, &addr6->mask);
+#endif /* IPv6 */
+               } else {
+                       type = entry->type;
+                       cipsov4 = entry->type_def.cipsov4;
+               }
+               switch (type) {
+               case NETLBL_NLTYPE_UNLABELED:
+                       audit_log_format(audit_buf, " nlbl_protocol=unlbl");
+                       break;
+               case NETLBL_NLTYPE_CIPSOV4:
+                       BUG_ON(cipsov4 == NULL);
+                       audit_log_format(audit_buf,
+                                        " nlbl_protocol=cipsov4 cipso_doi=%u",
+                                        cipsov4->doi);
+                       break;
+               }
+               audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0);
+               audit_log_end(audit_buf);
+       }
+}
+
 /*
  * Domain Hash Table Functions
  */
@@ -213,74 +297,106 @@ int __init netlbl_domhsh_init(u32 size)
 int netlbl_domhsh_add(struct netlbl_dom_map *entry,
                      struct netlbl_audit *audit_info)
 {
-       int ret_val;
-       u32 bkt;
-       struct audit_buffer *audit_buf;
-
-       switch (entry->type) {
-       case NETLBL_NLTYPE_UNLABELED:
-               ret_val = 0;
-               break;
-       case NETLBL_NLTYPE_CIPSOV4:
-               ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4,
-                                                 entry->domain);
-               break;
-       default:
-               return -EINVAL;
-       }
-       if (ret_val != 0)
-               return ret_val;
-
-       entry->valid = 1;
-       INIT_RCU_HEAD(&entry->rcu);
+       int ret_val = 0;
+       struct netlbl_dom_map *entry_old;
+       struct netlbl_af4list *iter4;
+       struct netlbl_af4list *tmp4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *iter6;
+       struct netlbl_af6list *tmp6;
+#endif /* IPv6 */
 
        rcu_read_lock();
+
        spin_lock(&netlbl_domhsh_lock);
-       if (entry->domain != NULL) {
-               bkt = netlbl_domhsh_hash(entry->domain);
-               if (netlbl_domhsh_search(entry->domain) == NULL)
+       if (entry->domain != NULL)
+               entry_old = netlbl_domhsh_search(entry->domain);
+       else
+               entry_old = netlbl_domhsh_search_def(entry->domain);
+       if (entry_old == NULL) {
+               entry->valid = 1;
+               INIT_RCU_HEAD(&entry->rcu);
+
+               if (entry->domain != NULL) {
+                       u32 bkt = netlbl_domhsh_hash(entry->domain);
                        list_add_tail_rcu(&entry->list,
                                    &rcu_dereference(netlbl_domhsh)->tbl[bkt]);
-               else
-                       ret_val = -EEXIST;
-       } else {
-               INIT_LIST_HEAD(&entry->list);
-               if (rcu_dereference(netlbl_domhsh_def) == NULL)
+               } else {
+                       INIT_LIST_HEAD(&entry->list);
                        rcu_assign_pointer(netlbl_domhsh_def, entry);
-               else
-                       ret_val = -EEXIST;
-       }
-       spin_unlock(&netlbl_domhsh_lock);
-       audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
-       if (audit_buf != NULL) {
-               audit_log_format(audit_buf,
-                                " nlbl_domain=%s",
-                                entry->domain ? entry->domain : "(default)");
-               switch (entry->type) {
-               case NETLBL_NLTYPE_UNLABELED:
-                       audit_log_format(audit_buf, " nlbl_protocol=unlbl");
-                       break;
-               case NETLBL_NLTYPE_CIPSOV4:
-                       audit_log_format(audit_buf,
-                                        " nlbl_protocol=cipsov4 cipso_doi=%u",
-                                        entry->type_def.cipsov4->doi);
-                       break;
                }
-               audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
-               audit_log_end(audit_buf);
-       }
-       rcu_read_unlock();
 
-       if (ret_val != 0) {
-               switch (entry->type) {
-               case NETLBL_NLTYPE_CIPSOV4:
-                       if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
-                                                      entry->domain) != 0)
-                               BUG();
-                       break;
+               if (entry->type == NETLBL_NLTYPE_ADDRSELECT) {
+                       netlbl_af4list_foreach_rcu(iter4,
+                                              &entry->type_def.addrsel->list4)
+                               netlbl_domhsh_audit_add(entry, iter4, NULL,
+                                                       ret_val, audit_info);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+                       netlbl_af6list_foreach_rcu(iter6,
+                                              &entry->type_def.addrsel->list6)
+                               netlbl_domhsh_audit_add(entry, NULL, iter6,
+                                                       ret_val, audit_info);
+#endif /* IPv6 */
+               } else
+                       netlbl_domhsh_audit_add(entry, NULL, NULL,
+                                               ret_val, audit_info);
+       } else if (entry_old->type == NETLBL_NLTYPE_ADDRSELECT &&
+                  entry->type == NETLBL_NLTYPE_ADDRSELECT) {
+               struct list_head *old_list4;
+               struct list_head *old_list6;
+
+               old_list4 = &entry_old->type_def.addrsel->list4;
+               old_list6 = &entry_old->type_def.addrsel->list6;
+
+               /* we only allow the addition of address selectors if all of
+                * the selectors do not exist in the existing domain map */
+               netlbl_af4list_foreach_rcu(iter4,
+                                          &entry->type_def.addrsel->list4)
+                       if (netlbl_af4list_search_exact(iter4->addr,
+                                                       iter4->mask,
+                                                       old_list4)) {
+                               ret_val = -EEXIST;
+                               goto add_return;
+                       }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               netlbl_af6list_foreach_rcu(iter6,
+                                          &entry->type_def.addrsel->list6)
+                       if (netlbl_af6list_search_exact(&iter6->addr,
+                                                       &iter6->mask,
+                                                       old_list6)) {
+                               ret_val = -EEXIST;
+                               goto add_return;
+                       }
+#endif /* IPv6 */
+
+               netlbl_af4list_foreach_safe(iter4, tmp4,
+                                           &entry->type_def.addrsel->list4) {
+                       netlbl_af4list_remove_entry(iter4);
+                       iter4->valid = 1;
+                       ret_val = netlbl_af4list_add(iter4, old_list4);
+                       netlbl_domhsh_audit_add(entry_old, iter4, NULL,
+                                               ret_val, audit_info);
+                       if (ret_val != 0)
+                               goto add_return;
                }
-       }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               netlbl_af6list_foreach_safe(iter6, tmp6,
+                                           &entry->type_def.addrsel->list6) {
+                       netlbl_af6list_remove_entry(iter6);
+                       iter6->valid = 1;
+                       ret_val = netlbl_af6list_add(iter6, old_list6);
+                       netlbl_domhsh_audit_add(entry_old, NULL, iter6,
+                                               ret_val, audit_info);
+                       if (ret_val != 0)
+                               goto add_return;
+               }
+#endif /* IPv6 */
+       } else
+               ret_val = -EINVAL;
 
+add_return:
+       spin_unlock(&netlbl_domhsh_lock);
+       rcu_read_unlock();
        return ret_val;
 }
 
@@ -302,35 +418,26 @@ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
 }
 
 /**
- * netlbl_domhsh_remove - Removes an entry from the domain hash table
- * @domain: the domain to remove
+ * netlbl_domhsh_remove_entry - Removes a given entry from the domain table
+ * @entry: the entry to remove
  * @audit_info: NetLabel audit information
  *
  * Description:
  * Removes an entry from the domain hash table and handles any updates to the
- * lower level protocol handler (i.e. CIPSO).  Returns zero on success,
- * negative on failure.
+ * lower level protocol handler (i.e. CIPSO).  Caller is responsible for
+ * ensuring that the RCU read lock is held.  Returns zero on success, negative
+ * on failure.
  *
  */
-int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
+int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
+                              struct netlbl_audit *audit_info)
 {
-       int ret_val = -ENOENT;
-       struct netlbl_dom_map *entry;
+       int ret_val = 0;
        struct audit_buffer *audit_buf;
 
-       rcu_read_lock();
-       if (domain)
-               entry = netlbl_domhsh_search(domain);
-       else
-               entry = netlbl_domhsh_search_def(domain);
        if (entry == NULL)
-               goto remove_return;
-       switch (entry->type) {
-       case NETLBL_NLTYPE_CIPSOV4:
-               cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
-                                          entry->domain);
-               break;
-       }
+               return -ENOENT;
+
        spin_lock(&netlbl_domhsh_lock);
        if (entry->valid) {
                entry->valid = 0;
@@ -338,8 +445,8 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
                        list_del_rcu(&entry->list);
                else
                        rcu_assign_pointer(netlbl_domhsh_def, NULL);
-               ret_val = 0;
-       }
+       } else
+               ret_val = -ENOENT;
        spin_unlock(&netlbl_domhsh_lock);
 
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info);
@@ -351,10 +458,54 @@ int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
                audit_log_end(audit_buf);
        }
 
-remove_return:
-       rcu_read_unlock();
-       if (ret_val == 0)
+       if (ret_val == 0) {
+               struct netlbl_af4list *iter4;
+               struct netlbl_domaddr4_map *map4;
+
+               switch (entry->type) {
+               case NETLBL_NLTYPE_ADDRSELECT:
+                       netlbl_af4list_foreach_rcu(iter4,
+                                            &entry->type_def.addrsel->list4) {
+                               map4 = netlbl_domhsh_addr4_entry(iter4);
+                               cipso_v4_doi_putdef(map4->type_def.cipsov4);
+                       }
+                       /* no need to check the IPv6 list since we currently
+                        * support only unlabeled protocols for IPv6 */
+                       break;
+               case NETLBL_NLTYPE_CIPSOV4:
+                       cipso_v4_doi_putdef(entry->type_def.cipsov4);
+                       break;
+               }
                call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
+       }
+
+       return ret_val;
+}
+
+/**
+ * netlbl_domhsh_remove - Removes an entry from the domain hash table
+ * @domain: the domain to remove
+ * @audit_info: NetLabel audit information
+ *
+ * Description:
+ * Removes an entry from the domain hash table and handles any updates to the
+ * lower level protocol handler (i.e. CIPSO).  Returns zero on success,
+ * negative on failure.
+ *
+ */
+int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info)
+{
+       int ret_val;
+       struct netlbl_dom_map *entry;
+
+       rcu_read_lock();
+       if (domain)
+               entry = netlbl_domhsh_search(domain);
+       else
+               entry = netlbl_domhsh_search_def(domain);
+       ret_val = netlbl_domhsh_remove_entry(entry, audit_info);
+       rcu_read_unlock();
+
        return ret_val;
 }
 
@@ -388,6 +539,70 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
        return netlbl_domhsh_search_def(domain);
 }
 
+/**
+ * netlbl_domhsh_getentry_af4 - Get an entry from the domain hash table
+ * @domain: the domain name to search for
+ * @addr: the IP address to search for
+ *
+ * Description:
+ * Look through the domain hash table searching for an entry to match @domain
+ * and @addr, return a pointer to a copy of the entry or NULL.  The caller is
+ * responsible for ensuring that rcu_read_[un]lock() is called.
+ *
+ */
+struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain,
+                                                      __be32 addr)
+{
+       struct netlbl_dom_map *dom_iter;
+       struct netlbl_af4list *addr_iter;
+
+       dom_iter = netlbl_domhsh_search_def(domain);
+       if (dom_iter == NULL)
+               return NULL;
+       if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT)
+               return NULL;
+
+       addr_iter = netlbl_af4list_search(addr,
+                                         &dom_iter->type_def.addrsel->list4);
+       if (addr_iter == NULL)
+               return NULL;
+
+       return netlbl_domhsh_addr4_entry(addr_iter);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+/**
+ * netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table
+ * @domain: the domain name to search for
+ * @addr: the IP address to search for
+ *
+ * Description:
+ * Look through the domain hash table searching for an entry to match @domain
+ * and @addr, return a pointer to a copy of the entry or NULL.  The caller is
+ * responsible for ensuring that rcu_read_[un]lock() is called.
+ *
+ */
+struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain,
+                                                  const struct in6_addr *addr)
+{
+       struct netlbl_dom_map *dom_iter;
+       struct netlbl_af6list *addr_iter;
+
+       dom_iter = netlbl_domhsh_search_def(domain);
+       if (dom_iter == NULL)
+               return NULL;
+       if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT)
+               return NULL;
+
+       addr_iter = netlbl_af6list_search(addr,
+                                         &dom_iter->type_def.addrsel->list6);
+       if (addr_iter == NULL)
+               return NULL;
+
+       return netlbl_domhsh_addr6_entry(addr_iter);
+}
+#endif /* IPv6 */
+
 /**
  * netlbl_domhsh_walk - Iterate through the domain mapping hash table
  * @skip_bkt: the number of buckets to skip at the start
@@ -410,6 +625,7 @@ int netlbl_domhsh_walk(u32 *skip_bkt,
 {
        int ret_val = -ENOENT;
        u32 iter_bkt;
+       struct list_head *iter_list;
        struct netlbl_dom_map *iter_entry;
        u32 chain_cnt = 0;
 
@@ -417,9 +633,8 @@ int netlbl_domhsh_walk(u32 *skip_bkt,
        for (iter_bkt = *skip_bkt;
             iter_bkt < rcu_dereference(netlbl_domhsh)->size;
             iter_bkt++, chain_cnt = 0) {
-               list_for_each_entry_rcu(iter_entry,
-                               &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt],
-                               list)
+               iter_list = &rcu_dereference(netlbl_domhsh)->tbl[iter_bkt];
+               list_for_each_entry_rcu(iter_entry, iter_list, list)
                        if (iter_entry->valid) {
                                if (chain_cnt++ < *skip_chain)
                                        continue;
index 8220990ceb967a0480421e82c465490fab3983b8..bfcb6763a1a15fac8edbcfe51045e706a9b00149 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <linux/rcupdate.h>
 #include <linux/list.h>
 
+#include "netlabel_addrlist.h"
+
 /* Domain hash table size */
 /* XXX - currently this number is an uneducated guess */
 #define NETLBL_DOMHSH_BITSIZE       7
 
-/* Domain mapping definition struct */
+/* Domain mapping definition structures */
+#define netlbl_domhsh_addr4_entry(iter) \
+       container_of(iter, struct netlbl_domaddr4_map, list)
+struct netlbl_domaddr4_map {
+       u32 type;
+       union {
+               struct cipso_v4_doi *cipsov4;
+       } type_def;
+
+       struct netlbl_af4list list;
+};
+#define netlbl_domhsh_addr6_entry(iter) \
+       container_of(iter, struct netlbl_domaddr6_map, list)
+struct netlbl_domaddr6_map {
+       u32 type;
+
+       /* NOTE: no 'type_def' union needed at present since we don't currently
+        *       support any IPv6 labeling protocols */
+
+       struct netlbl_af6list list;
+};
+struct netlbl_domaddr_map {
+       struct list_head list4;
+       struct list_head list6;
+};
 struct netlbl_dom_map {
        char *domain;
        u32 type;
        union {
                struct cipso_v4_doi *cipsov4;
+               struct netlbl_domaddr_map *addrsel;
        } type_def;
 
        u32 valid;
@@ -61,12 +88,21 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
                      struct netlbl_audit *audit_info);
 int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
                              struct netlbl_audit *audit_info);
+int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
+                              struct netlbl_audit *audit_info);
 int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
 int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info);
 struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
+struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain,
+                                                      __be32 addr);
 int netlbl_domhsh_walk(u32 *skip_bkt,
                     u32 *skip_chain,
                     int (*callback) (struct netlbl_dom_map *entry, void *arg),
                     void *cb_arg);
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain,
+                                                 const struct in6_addr *addr);
+#endif /* IPv6 */
+
 #endif
index 39793a1a93aaba375a6bf7382081c245b197e38b..b32eceb3ab0d526ad0c021e4e1feeaebdf3293e6 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -82,7 +82,7 @@ int netlbl_cfg_unlbl_add_map(const char *domain,
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
-               goto cfg_unlbl_add_map_failure;
+               return -ENOMEM;
        if (domain != NULL) {
                entry->domain = kstrdup(domain, GFP_ATOMIC);
                if (entry->domain == NULL)
@@ -103,49 +103,6 @@ cfg_unlbl_add_map_failure:
        return ret_val;
 }
 
-/**
- * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
- * @doi_def: the DOI definition
- * @audit_info: NetLabel audit information
- *
- * Description:
- * Add a new CIPSOv4 DOI definition to the NetLabel subsystem.  Returns zero on
- * success, negative values on failure.
- *
- */
-int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
-                          struct netlbl_audit *audit_info)
-{
-       int ret_val;
-       const char *type_str;
-       struct audit_buffer *audit_buf;
-
-       ret_val = cipso_v4_doi_add(doi_def);
-
-       audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
-                                             audit_info);
-       if (audit_buf != NULL) {
-               switch (doi_def->type) {
-               case CIPSO_V4_MAP_STD:
-                       type_str = "std";
-                       break;
-               case CIPSO_V4_MAP_PASS:
-                       type_str = "pass";
-                       break;
-               default:
-                       type_str = "(unknown)";
-               }
-               audit_log_format(audit_buf,
-                                " cipso_doi=%u cipso_type=%s res=%u",
-                                doi_def->doi,
-                                type_str,
-                                ret_val == 0 ? 1 : 0);
-               audit_log_end(audit_buf);
-       }
-
-       return ret_val;
-}
-
 /**
  * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
  * @doi_def: the DOI definition
@@ -164,58 +121,71 @@ int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
                               struct netlbl_audit *audit_info)
 {
        int ret_val = -ENOMEM;
+       u32 doi;
+       u32 doi_type;
        struct netlbl_dom_map *entry;
+       const char *type_str;
+       struct audit_buffer *audit_buf;
+
+       doi = doi_def->doi;
+       doi_type = doi_def->type;
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
-               goto cfg_cipsov4_add_map_failure;
+               return -ENOMEM;
        if (domain != NULL) {
                entry->domain = kstrdup(domain, GFP_ATOMIC);
                if (entry->domain == NULL)
                        goto cfg_cipsov4_add_map_failure;
        }
-       entry->type = NETLBL_NLTYPE_CIPSOV4;
-       entry->type_def.cipsov4 = doi_def;
-
-       /* Grab a RCU read lock here so nothing happens to the doi_def variable
-        * between adding it to the CIPSOv4 protocol engine and adding a
-        * domain mapping for it. */
 
-       rcu_read_lock();
-       ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info);
+       ret_val = cipso_v4_doi_add(doi_def);
        if (ret_val != 0)
-               goto cfg_cipsov4_add_map_failure_unlock;
+               goto cfg_cipsov4_add_map_failure_remove_doi;
+       entry->type = NETLBL_NLTYPE_CIPSOV4;
+       entry->type_def.cipsov4 = cipso_v4_doi_getdef(doi);
+       if (entry->type_def.cipsov4 == NULL) {
+               ret_val = -ENOENT;
+               goto cfg_cipsov4_add_map_failure_remove_doi;
+       }
        ret_val = netlbl_domhsh_add(entry, audit_info);
        if (ret_val != 0)
-               goto cfg_cipsov4_add_map_failure_remove_doi;
-       rcu_read_unlock();
+               goto cfg_cipsov4_add_map_failure_release_doi;
 
-       return 0;
+cfg_cipsov4_add_map_return:
+       audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
+                                             audit_info);
+       if (audit_buf != NULL) {
+               switch (doi_type) {
+               case CIPSO_V4_MAP_TRANS:
+                       type_str = "trans";
+                       break;
+               case CIPSO_V4_MAP_PASS:
+                       type_str = "pass";
+                       break;
+               case CIPSO_V4_MAP_LOCAL:
+                       type_str = "local";
+                       break;
+               default:
+                       type_str = "(unknown)";
+               }
+               audit_log_format(audit_buf,
+                                " cipso_doi=%u cipso_type=%s res=%u",
+                                doi, type_str, ret_val == 0 ? 1 : 0);
+               audit_log_end(audit_buf);
+       }
 
+       return ret_val;
+
+cfg_cipsov4_add_map_failure_release_doi:
+       cipso_v4_doi_putdef(doi_def);
 cfg_cipsov4_add_map_failure_remove_doi:
-       cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free);
-cfg_cipsov4_add_map_failure_unlock:
-       rcu_read_unlock();
+       cipso_v4_doi_remove(doi, audit_info);
 cfg_cipsov4_add_map_failure:
        if (entry != NULL)
                kfree(entry->domain);
        kfree(entry);
-       return ret_val;
-}
-
-/**
- * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition
- * @doi: the CIPSO DOI value
- * @audit_info: NetLabel audit information
- *
- * Description:
- * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem.
- * Returns zero on success, negative values on failure.
- *
- */
-int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
-{
-       return cipso_v4_doi_remove(doi, audit_info, netlbl_cipsov4_doi_free);
+       goto cfg_cipsov4_add_map_return;
 }
 
 /*
@@ -452,7 +422,9 @@ int netlbl_enabled(void)
  * Attach the correct label to the given socket using the security attributes
  * specified in @secattr.  This function requires exclusive access to @sk,
  * which means it either needs to be in the process of being created or locked.
- * Returns zero on success, negative values on failure.
+ * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
+ * network address selectors (can't blindly label the socket), and negative
+ * values on all other failures.
  *
  */
 int netlbl_sock_setattr(struct sock *sk,
@@ -466,6 +438,9 @@ int netlbl_sock_setattr(struct sock *sk,
        if (dom_entry == NULL)
                goto socket_setattr_return;
        switch (dom_entry->type) {
+       case NETLBL_NLTYPE_ADDRSELECT:
+               ret_val = -EDESTADDRREQ;
+               break;
        case NETLBL_NLTYPE_CIPSOV4:
                ret_val = cipso_v4_sock_setattr(sk,
                                                dom_entry->type_def.cipsov4,
@@ -483,6 +458,20 @@ socket_setattr_return:
        return ret_val;
 }
 
+/**
+ * netlbl_sock_delattr - Delete all the NetLabel labels on a socket
+ * @sk: the socket
+ *
+ * Description:
+ * Remove all the NetLabel labeling from @sk.  The caller is responsible for
+ * ensuring that @sk is locked.
+ *
+ */
+void netlbl_sock_delattr(struct sock *sk)
+{
+       cipso_v4_sock_delattr(sk);
+}
+
 /**
  * netlbl_sock_getattr - Determine the security attributes of a sock
  * @sk: the sock
@@ -500,6 +489,128 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
        return cipso_v4_sock_getattr(sk, secattr);
 }
 
+/**
+ * netlbl_conn_setattr - Label a connected socket using the correct protocol
+ * @sk: the socket to label
+ * @addr: the destination address
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Attach the correct label to the given connected socket using the security
+ * attributes specified in @secattr.  The caller is responsible for ensuring
+ * that @sk is locked.  Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_conn_setattr(struct sock *sk,
+                       struct sockaddr *addr,
+                       const struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val;
+       struct sockaddr_in *addr4;
+       struct netlbl_domaddr4_map *af4_entry;
+
+       rcu_read_lock();
+       switch (addr->sa_family) {
+       case AF_INET:
+               addr4 = (struct sockaddr_in *)addr;
+               af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
+                                                      addr4->sin_addr.s_addr);
+               if (af4_entry == NULL) {
+                       ret_val = -ENOENT;
+                       goto conn_setattr_return;
+               }
+               switch (af4_entry->type) {
+               case NETLBL_NLTYPE_CIPSOV4:
+                       ret_val = cipso_v4_sock_setattr(sk,
+                                                  af4_entry->type_def.cipsov4,
+                                                  secattr);
+                       break;
+               case NETLBL_NLTYPE_UNLABELED:
+                       /* just delete the protocols we support for right now
+                        * but we could remove other protocols if needed */
+                       cipso_v4_sock_delattr(sk);
+                       ret_val = 0;
+                       break;
+               default:
+                       ret_val = -ENOENT;
+               }
+               break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       case AF_INET6:
+               /* since we don't support any IPv6 labeling protocols right
+                * now we can optimize everything away until we do */
+               ret_val = 0;
+               break;
+#endif /* IPv6 */
+       default:
+               ret_val = 0;
+       }
+
+conn_setattr_return:
+       rcu_read_unlock();
+       return ret_val;
+}
+
+/**
+ * netlbl_skbuff_setattr - Label a packet using the correct protocol
+ * @skb: the packet
+ * @family: protocol family
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Attach the correct label to the given packet using the security attributes
+ * specified in @secattr.  Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_skbuff_setattr(struct sk_buff *skb,
+                         u16 family,
+                         const struct netlbl_lsm_secattr *secattr)
+{
+       int ret_val;
+       struct iphdr *hdr4;
+       struct netlbl_domaddr4_map *af4_entry;
+
+       rcu_read_lock();
+       switch (family) {
+       case AF_INET:
+               hdr4 = ip_hdr(skb);
+               af4_entry = netlbl_domhsh_getentry_af4(secattr->domain,
+                                                      hdr4->daddr);
+               if (af4_entry == NULL) {
+                       ret_val = -ENOENT;
+                       goto skbuff_setattr_return;
+               }
+               switch (af4_entry->type) {
+               case NETLBL_NLTYPE_CIPSOV4:
+                       ret_val = cipso_v4_skbuff_setattr(skb,
+                                                  af4_entry->type_def.cipsov4,
+                                                  secattr);
+                       break;
+               case NETLBL_NLTYPE_UNLABELED:
+                       /* just delete the protocols we support for right now
+                        * but we could remove other protocols if needed */
+                       ret_val = cipso_v4_skbuff_delattr(skb);
+                       break;
+               default:
+                       ret_val = -ENOENT;
+               }
+               break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       case AF_INET6:
+               /* since we don't support any IPv6 labeling protocols right
+                * now we can optimize everything away until we do */
+               ret_val = 0;
+               break;
+#endif /* IPv6 */
+       default:
+               ret_val = 0;
+       }
+
+skbuff_setattr_return:
+       rcu_read_unlock();
+       return ret_val;
+}
+
 /**
  * netlbl_skbuff_getattr - Determine the security attributes of a packet
  * @skb: the packet
@@ -528,6 +639,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
  * netlbl_skbuff_err - Handle a LSM error on a sk_buff
  * @skb: the packet
  * @error: the error code
+ * @gateway: true if host is acting as a gateway, false otherwise
  *
  * Description:
  * Deal with a LSM problem when handling the packet in @skb, typically this is
@@ -535,10 +647,10 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
  * according to the packet's labeling protocol.
  *
  */
-void netlbl_skbuff_err(struct sk_buff *skb, int error)
+void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway)
 {
        if (CIPSO_V4_OPTEXIST(skb))
-               cipso_v4_error(skb, error, 0);
+               cipso_v4_error(skb, error, gateway);
 }
 
 /**
index 44be5d5261f4670005f44276f5fb5a257fe97538..ee769ecaa13cf149f137a8a88b3606673b325cee 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <linux/socket.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/in6.h>
 #include <net/sock.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
 #include <asm/atomic.h>
@@ -71,85 +75,336 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
 };
 
 /*
- * NetLabel Command Handlers
+ * Helper Functions
  */
 
 /**
  * netlbl_mgmt_add - Handle an ADD message
- * @skb: the NETLINK buffer
  * @info: the Generic NETLINK info block
+ * @audit_info: NetLabel audit information
  *
  * Description:
- * Process a user generated ADD message and add the domains from the message
- * to the hash table.  See netlabel.h for a description of the message format.
- * Returns zero on success, negative values on failure.
+ * Helper function for the ADD and ADDDEF messages to add the domain mappings
+ * from the message to the hash table.  See netlabel.h for a description of the
+ * message format.  Returns zero on success, negative values on failure.
  *
  */
-static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
+static int netlbl_mgmt_add_common(struct genl_info *info,
+                                 struct netlbl_audit *audit_info)
 {
        int ret_val = -EINVAL;
        struct netlbl_dom_map *entry = NULL;
-       size_t tmp_size;
+       struct netlbl_domaddr_map *addrmap = NULL;
+       struct cipso_v4_doi *cipsov4 = NULL;
        u32 tmp_val;
-       struct netlbl_audit audit_info;
-
-       if (!info->attrs[NLBL_MGMT_A_DOMAIN] ||
-           !info->attrs[NLBL_MGMT_A_PROTOCOL])
-               goto add_failure;
-
-       netlbl_netlink_auditinfo(skb, &audit_info);
 
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (entry == NULL) {
                ret_val = -ENOMEM;
                goto add_failure;
        }
-       tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
-       entry->domain = kmalloc(tmp_size, GFP_KERNEL);
-       if (entry->domain == NULL) {
-               ret_val = -ENOMEM;
-               goto add_failure;
-       }
        entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
-       nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
+       if (info->attrs[NLBL_MGMT_A_DOMAIN]) {
+               size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]);
+               entry->domain = kmalloc(tmp_size, GFP_KERNEL);
+               if (entry->domain == NULL) {
+                       ret_val = -ENOMEM;
+                       goto add_failure;
+               }
+               nla_strlcpy(entry->domain,
+                           info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size);
+       }
+
+       /* NOTE: internally we allow/use a entry->type value of
+        *       NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users
+        *       to pass that as a protocol value because we need to know the
+        *       "real" protocol */
 
        switch (entry->type) {
        case NETLBL_NLTYPE_UNLABELED:
-               ret_val = netlbl_domhsh_add(entry, &audit_info);
                break;
        case NETLBL_NLTYPE_CIPSOV4:
                if (!info->attrs[NLBL_MGMT_A_CV4DOI])
                        goto add_failure;
 
                tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
-               /* We should be holding a rcu_read_lock() here while we hold
-                * the result but since the entry will always be deleted when
-                * the CIPSO DOI is deleted we aren't going to keep the
-                * lock. */
-               rcu_read_lock();
-               entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
-               if (entry->type_def.cipsov4 == NULL) {
-                       rcu_read_unlock();
+               cipsov4 = cipso_v4_doi_getdef(tmp_val);
+               if (cipsov4 == NULL)
                        goto add_failure;
-               }
-               ret_val = netlbl_domhsh_add(entry, &audit_info);
-               rcu_read_unlock();
+               entry->type_def.cipsov4 = cipsov4;
                break;
        default:
                goto add_failure;
        }
+
+       if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) {
+               struct in_addr *addr;
+               struct in_addr *mask;
+               struct netlbl_domaddr4_map *map;
+
+               addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
+               if (addrmap == NULL) {
+                       ret_val = -ENOMEM;
+                       goto add_failure;
+               }
+               INIT_LIST_HEAD(&addrmap->list4);
+               INIT_LIST_HEAD(&addrmap->list6);
+
+               if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) !=
+                   sizeof(struct in_addr)) {
+                       ret_val = -EINVAL;
+                       goto add_failure;
+               }
+               if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) !=
+                   sizeof(struct in_addr)) {
+                       ret_val = -EINVAL;
+                       goto add_failure;
+               }
+               addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]);
+               mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]);
+
+               map = kzalloc(sizeof(*map), GFP_KERNEL);
+               if (map == NULL) {
+                       ret_val = -ENOMEM;
+                       goto add_failure;
+               }
+               map->list.addr = addr->s_addr & mask->s_addr;
+               map->list.mask = mask->s_addr;
+               map->list.valid = 1;
+               map->type = entry->type;
+               if (cipsov4)
+                       map->type_def.cipsov4 = cipsov4;
+
+               ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
+               if (ret_val != 0) {
+                       kfree(map);
+                       goto add_failure;
+               }
+
+               entry->type = NETLBL_NLTYPE_ADDRSELECT;
+               entry->type_def.addrsel = addrmap;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) {
+               struct in6_addr *addr;
+               struct in6_addr *mask;
+               struct netlbl_domaddr6_map *map;
+
+               addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL);
+               if (addrmap == NULL) {
+                       ret_val = -ENOMEM;
+                       goto add_failure;
+               }
+               INIT_LIST_HEAD(&addrmap->list4);
+               INIT_LIST_HEAD(&addrmap->list6);
+
+               if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) !=
+                   sizeof(struct in6_addr)) {
+                       ret_val = -EINVAL;
+                       goto add_failure;
+               }
+               if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) !=
+                   sizeof(struct in6_addr)) {
+                       ret_val = -EINVAL;
+                       goto add_failure;
+               }
+               addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]);
+               mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]);
+
+               map = kzalloc(sizeof(*map), GFP_KERNEL);
+               if (map == NULL) {
+                       ret_val = -ENOMEM;
+                       goto add_failure;
+               }
+               ipv6_addr_copy(&map->list.addr, addr);
+               map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
+               map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
+               map->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
+               map->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
+               ipv6_addr_copy(&map->list.mask, mask);
+               map->list.valid = 1;
+               map->type = entry->type;
+
+               ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
+               if (ret_val != 0) {
+                       kfree(map);
+                       goto add_failure;
+               }
+
+               entry->type = NETLBL_NLTYPE_ADDRSELECT;
+               entry->type_def.addrsel = addrmap;
+#endif /* IPv6 */
+       }
+
+       ret_val = netlbl_domhsh_add(entry, audit_info);
        if (ret_val != 0)
                goto add_failure;
 
        return 0;
 
 add_failure:
+       if (cipsov4)
+               cipso_v4_doi_putdef(cipsov4);
        if (entry)
                kfree(entry->domain);
+       kfree(addrmap);
        kfree(entry);
        return ret_val;
 }
 
+/**
+ * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry
+ * @skb: the NETLINK buffer
+ * @entry: the map entry
+ *
+ * Description:
+ * This function is a helper function used by the LISTALL and LISTDEF command
+ * handlers.  The caller is responsibile for ensuring that the RCU read lock
+ * is held.  Returns zero on success, negative values on failure.
+ *
+ */
+static int netlbl_mgmt_listentry(struct sk_buff *skb,
+                                struct netlbl_dom_map *entry)
+{
+       int ret_val;
+       struct nlattr *nla_a;
+       struct nlattr *nla_b;
+       struct netlbl_af4list *iter4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *iter6;
+#endif
+
+       if (entry->domain != NULL) {
+               ret_val = nla_put_string(skb,
+                                        NLBL_MGMT_A_DOMAIN, entry->domain);
+               if (ret_val != 0)
+                       return ret_val;
+       }
+
+       switch (entry->type) {
+       case NETLBL_NLTYPE_ADDRSELECT:
+               nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST);
+               if (nla_a == NULL)
+                       return -ENOMEM;
+
+               netlbl_af4list_foreach_rcu(iter4,
+                                          &entry->type_def.addrsel->list4) {
+                       struct netlbl_domaddr4_map *map4;
+                       struct in_addr addr_struct;
+
+                       nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
+                       if (nla_b == NULL)
+                               return -ENOMEM;
+
+                       addr_struct.s_addr = iter4->addr;
+                       ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR,
+                                         sizeof(struct in_addr),
+                                         &addr_struct);
+                       if (ret_val != 0)
+                               return ret_val;
+                       addr_struct.s_addr = iter4->mask;
+                       ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK,
+                                         sizeof(struct in_addr),
+                                         &addr_struct);
+                       if (ret_val != 0)
+                               return ret_val;
+                       map4 = netlbl_domhsh_addr4_entry(iter4);
+                       ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
+                                             map4->type);
+                       if (ret_val != 0)
+                               return ret_val;
+                       switch (map4->type) {
+                       case NETLBL_NLTYPE_CIPSOV4:
+                               ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
+                                                 map4->type_def.cipsov4->doi);
+                               if (ret_val != 0)
+                                       return ret_val;
+                               break;
+                       }
+
+                       nla_nest_end(skb, nla_b);
+               }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               netlbl_af6list_foreach_rcu(iter6,
+                                          &entry->type_def.addrsel->list6) {
+                       struct netlbl_domaddr6_map *map6;
+
+                       nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR);
+                       if (nla_b == NULL)
+                               return -ENOMEM;
+
+                       ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR,
+                                         sizeof(struct in6_addr),
+                                         &iter6->addr);
+                       if (ret_val != 0)
+                               return ret_val;
+                       ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK,
+                                         sizeof(struct in6_addr),
+                                         &iter6->mask);
+                       if (ret_val != 0)
+                               return ret_val;
+                       map6 = netlbl_domhsh_addr6_entry(iter6);
+                       ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL,
+                                             map6->type);
+                       if (ret_val != 0)
+                               return ret_val;
+
+                       nla_nest_end(skb, nla_b);
+               }
+#endif /* IPv6 */
+
+               nla_nest_end(skb, nla_a);
+               break;
+       case NETLBL_NLTYPE_UNLABELED:
+               ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
+               break;
+       case NETLBL_NLTYPE_CIPSOV4:
+               ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type);
+               if (ret_val != 0)
+                       return ret_val;
+               ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI,
+                                     entry->type_def.cipsov4->doi);
+               break;
+       }
+
+       return ret_val;
+}
+
+/*
+ * NetLabel Command Handlers
+ */
+
+/**
+ * netlbl_mgmt_add - Handle an ADD message
+ * @skb: the NETLINK buffer
+ * @info: the Generic NETLINK info block
+ *
+ * Description:
+ * Process a user generated ADD message and add the domains from the message
+ * to the hash table.  See netlabel.h for a description of the message format.
+ * Returns zero on success, negative values on failure.
+ *
+ */
+static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info)
+{
+       struct netlbl_audit audit_info;
+
+       if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) ||
+           (!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
+           (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
+            info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
+           (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
+            info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
+           ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
+            (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
+           ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
+            (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
+               return -EINVAL;
+
+       netlbl_netlink_auditinfo(skb, &audit_info);
+
+       return netlbl_mgmt_add_common(info, &audit_info);
+}
+
 /**
  * netlbl_mgmt_remove - Handle a REMOVE message
  * @skb: the NETLINK buffer
@@ -198,23 +453,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg)
        if (data == NULL)
                goto listall_cb_failure;
 
-       ret_val = nla_put_string(cb_arg->skb,
-                                NLBL_MGMT_A_DOMAIN,
-                                entry->domain);
+       ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry);
        if (ret_val != 0)
                goto listall_cb_failure;
-       ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type);
-       if (ret_val != 0)
-               goto listall_cb_failure;
-       switch (entry->type) {
-       case NETLBL_NLTYPE_CIPSOV4:
-               ret_val = nla_put_u32(cb_arg->skb,
-                                     NLBL_MGMT_A_CV4DOI,
-                                     entry->type_def.cipsov4->doi);
-               if (ret_val != 0)
-                       goto listall_cb_failure;
-               break;
-       }
 
        cb_arg->seq++;
        return genlmsg_end(cb_arg->skb, data);
@@ -268,56 +509,22 @@ static int netlbl_mgmt_listall(struct sk_buff *skb,
  */
 static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info)
 {
-       int ret_val = -EINVAL;
-       struct netlbl_dom_map *entry = NULL;
-       u32 tmp_val;
        struct netlbl_audit audit_info;
 
-       if (!info->attrs[NLBL_MGMT_A_PROTOCOL])
-               goto adddef_failure;
+       if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) ||
+           (info->attrs[NLBL_MGMT_A_IPV4ADDR] &&
+            info->attrs[NLBL_MGMT_A_IPV6ADDR]) ||
+           (info->attrs[NLBL_MGMT_A_IPV4MASK] &&
+            info->attrs[NLBL_MGMT_A_IPV6MASK]) ||
+           ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^
+            (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) ||
+           ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^
+            (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL)))
+               return -EINVAL;
 
        netlbl_netlink_auditinfo(skb, &audit_info);
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (entry == NULL) {
-               ret_val = -ENOMEM;
-               goto adddef_failure;
-       }
-       entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]);
-
-       switch (entry->type) {
-       case NETLBL_NLTYPE_UNLABELED:
-               ret_val = netlbl_domhsh_add_default(entry, &audit_info);
-               break;
-       case NETLBL_NLTYPE_CIPSOV4:
-               if (!info->attrs[NLBL_MGMT_A_CV4DOI])
-                       goto adddef_failure;
-
-               tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]);
-               /* We should be holding a rcu_read_lock() here while we hold
-                * the result but since the entry will always be deleted when
-                * the CIPSO DOI is deleted we aren't going to keep the
-                * lock. */
-               rcu_read_lock();
-               entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
-               if (entry->type_def.cipsov4 == NULL) {
-                       rcu_read_unlock();
-                       goto adddef_failure;
-               }
-               ret_val = netlbl_domhsh_add_default(entry, &audit_info);
-               rcu_read_unlock();
-               break;
-       default:
-               goto adddef_failure;
-       }
-       if (ret_val != 0)
-               goto adddef_failure;
-
-       return 0;
-
-adddef_failure:
-       kfree(entry);
-       return ret_val;
+       return netlbl_mgmt_add_common(info, &audit_info);
 }
 
 /**
@@ -371,19 +578,10 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
                ret_val = -ENOENT;
                goto listdef_failure_lock;
        }
-       ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type);
-       if (ret_val != 0)
-               goto listdef_failure_lock;
-       switch (entry->type) {
-       case NETLBL_NLTYPE_CIPSOV4:
-               ret_val = nla_put_u32(ans_skb,
-                                     NLBL_MGMT_A_CV4DOI,
-                                     entry->type_def.cipsov4->doi);
-               if (ret_val != 0)
-                       goto listdef_failure_lock;
-               break;
-       }
+       ret_val = netlbl_mgmt_listentry(ans_skb, entry);
        rcu_read_unlock();
+       if (ret_val != 0)
+               goto listdef_failure;
 
        genlmsg_end(ans_skb, data);
        return genlmsg_reply(ans_skb, info);
index a43bff169d6b5f793b0550b6b4fa65b5a53b37c5..05d96431f81984061b575fd6adbad5c5de2ced19 100644 (file)
  *     NLBL_MGMT_A_DOMAIN
  *     NLBL_MGMT_A_PROTOCOL
  *
+ *   If IPv4 is specified the following attributes are required:
+ *
+ *     NLBL_MGMT_A_IPV4ADDR
+ *     NLBL_MGMT_A_IPV4MASK
+ *
+ *   If IPv6 is specified the following attributes are required:
+ *
+ *     NLBL_MGMT_A_IPV6ADDR
+ *     NLBL_MGMT_A_IPV6MASK
+ *
  *   If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
  *
  *     NLBL_MGMT_A_CV4DOI
  *   Required attributes:
  *
  *     NLBL_MGMT_A_DOMAIN
+ *
+ *   If the IP address selectors are not used the following attribute is
+ *   required:
+ *
  *     NLBL_MGMT_A_PROTOCOL
  *
- *   If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
+ *   If the IP address selectors are used then the following attritbute is
+ *   required:
+ *
+ *     NLBL_MGMT_A_SELECTORLIST
+ *
+ *   If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following
+ *   attributes are required:
  *
  *     NLBL_MGMT_A_CV4DOI
  *
- *   If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
+ *   If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other
+ *   attributes are required.
  *
  * o ADDDEF:
  *   Sent by an application to set the default domain mapping for the NetLabel
  *   application there is no payload.  On success the kernel should send a
  *   response using the following format.
  *
- *   Required attributes:
+ *   If the IP address selectors are not used the following attribute is
+ *   required:
  *
  *     NLBL_MGMT_A_PROTOCOL
  *
- *   If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required:
+ *   If the IP address selectors are used then the following attritbute is
+ *   required:
+ *
+ *     NLBL_MGMT_A_SELECTORLIST
+ *
+ *   If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following
+ *   attributes are required:
  *
  *     NLBL_MGMT_A_CV4DOI
  *
- *   If using NETLBL_NLTYPE_UNLABELED no other attributes are required.
+ *   If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other
+ *   attributes are required.
  *
  * o PROTOCOLS:
  *   Sent by an application to request a list of configured NetLabel protocols
@@ -162,6 +191,26 @@ enum {
        NLBL_MGMT_A_CV4DOI,
        /* (NLA_U32)
         * the CIPSOv4 DOI value */
+       NLBL_MGMT_A_IPV6ADDR,
+       /* (NLA_BINARY, struct in6_addr)
+        * an IPv6 address */
+       NLBL_MGMT_A_IPV6MASK,
+       /* (NLA_BINARY, struct in6_addr)
+        * an IPv6 address mask */
+       NLBL_MGMT_A_IPV4ADDR,
+       /* (NLA_BINARY, struct in_addr)
+        * an IPv4 address */
+       NLBL_MGMT_A_IPV4MASK,
+       /* (NLA_BINARY, struct in_addr)
+        * and IPv4 address mask */
+       NLBL_MGMT_A_ADDRSELECTOR,
+       /* (NLA_NESTED)
+        * an IP address selector, must contain an address, mask, and protocol
+        * attribute plus any protocol specific attributes */
+       NLBL_MGMT_A_SELECTORLIST,
+       /* (NLA_NESTED)
+        * the selector list, there must be at least one
+        * NLBL_MGMT_A_ADDRSELECTOR attribute */
        __NLBL_MGMT_A_MAX,
 };
 #define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1)
index 921c118ead891991f0337d4bb29689adabe586c6..e8a5c32b0f106042c82790c2e1c924837bfe0b64 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
 #include <asm/atomic.h>
 
 #include "netlabel_user.h"
+#include "netlabel_addrlist.h"
 #include "netlabel_domainhash.h"
 #include "netlabel_unlabeled.h"
 #include "netlabel_mgmt.h"
@@ -76,22 +77,20 @@ struct netlbl_unlhsh_tbl {
        struct list_head *tbl;
        u32 size;
 };
+#define netlbl_unlhsh_addr4_entry(iter) \
+       container_of(iter, struct netlbl_unlhsh_addr4, list)
 struct netlbl_unlhsh_addr4 {
-       __be32 addr;
-       __be32 mask;
        u32 secid;
 
-       u32 valid;
-       struct list_head list;
+       struct netlbl_af4list list;
        struct rcu_head rcu;
 };
+#define netlbl_unlhsh_addr6_entry(iter) \
+       container_of(iter, struct netlbl_unlhsh_addr6, list)
 struct netlbl_unlhsh_addr6 {
-       struct in6_addr addr;
-       struct in6_addr mask;
        u32 secid;
 
-       u32 valid;
-       struct list_head list;
+       struct netlbl_af6list list;
        struct rcu_head rcu;
 };
 struct netlbl_unlhsh_iface {
@@ -146,76 +145,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1
        [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY }
 };
 
-/*
- * Audit Helper Functions
- */
-
-/**
- * netlbl_unlabel_audit_addr4 - Audit an IPv4 address
- * @audit_buf: audit buffer
- * @dev: network interface
- * @addr: IP address
- * @mask: IP address mask
- *
- * Description:
- * Write the IPv4 address and address mask, if necessary, to @audit_buf.
- *
- */
-static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf,
-                                    const char *dev,
-                                    __be32 addr, __be32 mask)
-{
-       u32 mask_val = ntohl(mask);
-
-       if (dev != NULL)
-               audit_log_format(audit_buf, " netif=%s", dev);
-       audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr));
-       if (mask_val != 0xffffffff) {
-               u32 mask_len = 0;
-               while (mask_val > 0) {
-                       mask_val <<= 1;
-                       mask_len++;
-               }
-               audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
-       }
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-/**
- * netlbl_unlabel_audit_addr6 - Audit an IPv6 address
- * @audit_buf: audit buffer
- * @dev: network interface
- * @addr: IP address
- * @mask: IP address mask
- *
- * Description:
- * Write the IPv6 address and address mask, if necessary, to @audit_buf.
- *
- */
-static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf,
-                                    const char *dev,
-                                    const struct in6_addr *addr,
-                                    const struct in6_addr *mask)
-{
-       if (dev != NULL)
-               audit_log_format(audit_buf, " netif=%s", dev);
-       audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr));
-       if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
-               u32 mask_len = 0;
-               u32 mask_val;
-               int iter = -1;
-               while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
-                       mask_len += 32;
-               mask_val = ntohl(mask->s6_addr32[iter]);
-               while (mask_val > 0) {
-                       mask_val <<= 1;
-                       mask_len++;
-               }
-               audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
-       }
-}
-#endif /* IPv6 */
-
 /*
  * Unlabeled Connection Hash Table Functions
  */
@@ -274,26 +203,28 @@ static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
 static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
 {
        struct netlbl_unlhsh_iface *iface;
-       struct netlbl_unlhsh_addr4 *iter4;
-       struct netlbl_unlhsh_addr4 *tmp4;
-       struct netlbl_unlhsh_addr6 *iter6;
-       struct netlbl_unlhsh_addr6 *tmp6;
+       struct netlbl_af4list *iter4;
+       struct netlbl_af4list *tmp4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *iter6;
+       struct netlbl_af6list *tmp6;
+#endif /* IPv6 */
 
        iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
 
        /* no need for locks here since we are the only one with access to this
         * structure */
 
-       list_for_each_entry_safe(iter4, tmp4, &iface->addr4_list, list)
-               if (iter4->valid) {
-                       list_del_rcu(&iter4->list);
-                       kfree(iter4);
-               }
-       list_for_each_entry_safe(iter6, tmp6, &iface->addr6_list, list)
-               if (iter6->valid) {
-                       list_del_rcu(&iter6->list);
-                       kfree(iter6);
-               }
+       netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) {
+               netlbl_af4list_remove_entry(iter4);
+               kfree(netlbl_unlhsh_addr4_entry(iter4));
+       }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) {
+               netlbl_af6list_remove_entry(iter6);
+               kfree(netlbl_unlhsh_addr6_entry(iter6));
+       }
+#endif /* IPv6 */
        kfree(iface);
 }
 
@@ -315,59 +246,6 @@ static u32 netlbl_unlhsh_hash(int ifindex)
        return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1);
 }
 
-/**
- * netlbl_unlhsh_search_addr4 - Search for a matching IPv4 address entry
- * @addr: IPv4 address
- * @iface: the network interface entry
- *
- * Description:
- * Searches the IPv4 address list of the network interface specified by @iface.
- * If a matching address entry is found it is returned, otherwise NULL is
- * returned.  The caller is responsible for calling the rcu_read_[un]lock()
- * functions.
- *
- */
-static struct netlbl_unlhsh_addr4 *netlbl_unlhsh_search_addr4(
-                                      __be32 addr,
-                                      const struct netlbl_unlhsh_iface *iface)
-{
-       struct netlbl_unlhsh_addr4 *iter;
-
-       list_for_each_entry_rcu(iter, &iface->addr4_list, list)
-               if (iter->valid && (addr & iter->mask) == iter->addr)
-                       return iter;
-
-       return NULL;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-/**
- * netlbl_unlhsh_search_addr6 - Search for a matching IPv6 address entry
- * @addr: IPv6 address
- * @iface: the network interface entry
- *
- * Description:
- * Searches the IPv6 address list of the network interface specified by @iface.
- * If a matching address entry is found it is returned, otherwise NULL is
- * returned.  The caller is responsible for calling the rcu_read_[un]lock()
- * functions.
- *
- */
-static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
-                                      const struct in6_addr *addr,
-                                      const struct netlbl_unlhsh_iface *iface)
-{
-       struct netlbl_unlhsh_addr6 *iter;
-
-       list_for_each_entry_rcu(iter, &iface->addr6_list, list)
-               if (iter->valid &&
-                   ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
-               return iter;
-
-       return NULL;
-}
-#endif /* IPv6 */
-
 /**
  * netlbl_unlhsh_search_iface - Search for a matching interface entry
  * @ifindex: the network interface
@@ -381,12 +259,12 @@ static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
 static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
 {
        u32 bkt;
+       struct list_head *bkt_list;
        struct netlbl_unlhsh_iface *iter;
 
        bkt = netlbl_unlhsh_hash(ifindex);
-       list_for_each_entry_rcu(iter,
-                               &rcu_dereference(netlbl_unlhsh)->tbl[bkt],
-                               list)
+       bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt];
+       list_for_each_entry_rcu(iter, bkt_list, list)
                if (iter->valid && iter->ifindex == ifindex)
                        return iter;
 
@@ -439,43 +317,26 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
                                   const struct in_addr *mask,
                                   u32 secid)
 {
+       int ret_val;
        struct netlbl_unlhsh_addr4 *entry;
-       struct netlbl_unlhsh_addr4 *iter;
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
                return -ENOMEM;
 
-       entry->addr = addr->s_addr & mask->s_addr;
-       entry->mask = mask->s_addr;
-       entry->secid = secid;
-       entry->valid = 1;
+       entry->list.addr = addr->s_addr & mask->s_addr;
+       entry->list.mask = mask->s_addr;
+       entry->list.valid = 1;
        INIT_RCU_HEAD(&entry->rcu);
+       entry->secid = secid;
 
        spin_lock(&netlbl_unlhsh_lock);
-       iter = netlbl_unlhsh_search_addr4(entry->addr, iface);
-       if (iter != NULL &&
-           iter->addr == addr->s_addr && iter->mask == mask->s_addr) {
-               spin_unlock(&netlbl_unlhsh_lock);
-               kfree(entry);
-               return -EEXIST;
-       }
-       /* in order to speed up address searches through the list (the common
-        * case) we need to keep the list in order based on the size of the
-        * address mask such that the entry with the widest mask (smallest
-        * numerical value) appears first in the list */
-       list_for_each_entry_rcu(iter, &iface->addr4_list, list)
-               if (iter->valid &&
-                   ntohl(entry->mask) > ntohl(iter->mask)) {
-                       __list_add_rcu(&entry->list,
-                                      iter->list.prev,
-                                      &iter->list);
-                       spin_unlock(&netlbl_unlhsh_lock);
-                       return 0;
-               }
-       list_add_tail_rcu(&entry->list, &iface->addr4_list);
+       ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
        spin_unlock(&netlbl_unlhsh_lock);
-       return 0;
+
+       if (ret_val != 0)
+               kfree(entry);
+       return ret_val;
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -498,47 +359,29 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
                                   const struct in6_addr *mask,
                                   u32 secid)
 {
+       int ret_val;
        struct netlbl_unlhsh_addr6 *entry;
-       struct netlbl_unlhsh_addr6 *iter;
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
                return -ENOMEM;
 
-       ipv6_addr_copy(&entry->addr, addr);
-       entry->addr.s6_addr32[0] &= mask->s6_addr32[0];
-       entry->addr.s6_addr32[1] &= mask->s6_addr32[1];
-       entry->addr.s6_addr32[2] &= mask->s6_addr32[2];
-       entry->addr.s6_addr32[3] &= mask->s6_addr32[3];
-       ipv6_addr_copy(&entry->mask, mask);
-       entry->secid = secid;
-       entry->valid = 1;
+       ipv6_addr_copy(&entry->list.addr, addr);
+       entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
+       entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
+       entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
+       entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
+       ipv6_addr_copy(&entry->list.mask, mask);
+       entry->list.valid = 1;
        INIT_RCU_HEAD(&entry->rcu);
+       entry->secid = secid;
 
        spin_lock(&netlbl_unlhsh_lock);
-       iter = netlbl_unlhsh_search_addr6(&entry->addr, iface);
-       if (iter != NULL &&
-           (ipv6_addr_equal(&iter->addr, addr) &&
-            ipv6_addr_equal(&iter->mask, mask))) {
-               spin_unlock(&netlbl_unlhsh_lock);
-               kfree(entry);
-               return -EEXIST;
-       }
-       /* in order to speed up address searches through the list (the common
-        * case) we need to keep the list in order based on the size of the
-        * address mask such that the entry with the widest mask (smallest
-        * numerical value) appears first in the list */
-       list_for_each_entry_rcu(iter, &iface->addr6_list, list)
-               if (iter->valid &&
-                   ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
-                       __list_add_rcu(&entry->list,
-                                      iter->list.prev,
-                                      &iter->list);
-                       spin_unlock(&netlbl_unlhsh_lock);
-                       return 0;
-               }
-       list_add_tail_rcu(&entry->list, &iface->addr6_list);
+       ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
        spin_unlock(&netlbl_unlhsh_lock);
+
+       if (ret_val != 0)
+               kfree(entry);
        return 0;
 }
 #endif /* IPv6 */
@@ -658,10 +501,10 @@ static int netlbl_unlhsh_add(struct net *net,
                mask4 = (struct in_addr *)mask;
                ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
                if (audit_buf != NULL)
-                       netlbl_unlabel_audit_addr4(audit_buf,
-                                                  dev_name,
-                                                  addr4->s_addr,
-                                                  mask4->s_addr);
+                       netlbl_af4list_audit_addr(audit_buf, 1,
+                                                 dev_name,
+                                                 addr4->s_addr,
+                                                 mask4->s_addr);
                break;
        }
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -672,9 +515,9 @@ static int netlbl_unlhsh_add(struct net *net,
                mask6 = (struct in6_addr *)mask;
                ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
                if (audit_buf != NULL)
-                       netlbl_unlabel_audit_addr6(audit_buf,
-                                                  dev_name,
-                                                  addr6, mask6);
+                       netlbl_af6list_audit_addr(audit_buf, 1,
+                                                 dev_name,
+                                                 addr6, mask6);
                break;
        }
 #endif /* IPv6 */
@@ -719,35 +562,34 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
                                      const struct in_addr *mask,
                                      struct netlbl_audit *audit_info)
 {
-       int ret_val = -ENOENT;
+       int ret_val = 0;
+       struct netlbl_af4list *list_entry;
        struct netlbl_unlhsh_addr4 *entry;
-       struct audit_buffer *audit_buf = NULL;
+       struct audit_buffer *audit_buf;
        struct net_device *dev;
-       char *secctx = NULL;
+       char *secctx;
        u32 secctx_len;
 
        spin_lock(&netlbl_unlhsh_lock);
-       entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface);
-       if (entry != NULL &&
-           entry->addr == addr->s_addr && entry->mask == mask->s_addr) {
-               entry->valid = 0;
-               list_del_rcu(&entry->list);
-               ret_val = 0;
-       }
+       list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
+                                          &iface->addr4_list);
        spin_unlock(&netlbl_unlhsh_lock);
+       if (list_entry == NULL)
+               ret_val = -ENOENT;
+       entry = netlbl_unlhsh_addr4_entry(list_entry);
 
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
                                              audit_info);
        if (audit_buf != NULL) {
                dev = dev_get_by_index(net, iface->ifindex);
-               netlbl_unlabel_audit_addr4(audit_buf,
-                                          (dev != NULL ? dev->name : NULL),
-                                          entry->addr, entry->mask);
+               netlbl_af4list_audit_addr(audit_buf, 1,
+                                         (dev != NULL ? dev->name : NULL),
+                                         addr->s_addr, mask->s_addr);
                if (dev != NULL)
                        dev_put(dev);
-               if (security_secid_to_secctx(entry->secid,
-                                            &secctx,
-                                            &secctx_len) == 0) {
+               if (entry && security_secid_to_secctx(entry->secid,
+                                                     &secctx,
+                                                     &secctx_len) == 0) {
                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
                        security_release_secctx(secctx, secctx_len);
                }
@@ -781,36 +623,33 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
                                      const struct in6_addr *mask,
                                      struct netlbl_audit *audit_info)
 {
-       int ret_val = -ENOENT;
+       int ret_val = 0;
+       struct netlbl_af6list *list_entry;
        struct netlbl_unlhsh_addr6 *entry;
-       struct audit_buffer *audit_buf = NULL;
+       struct audit_buffer *audit_buf;
        struct net_device *dev;
-       char *secctx = NULL;
+       char *secctx;
        u32 secctx_len;
 
        spin_lock(&netlbl_unlhsh_lock);
-       entry = netlbl_unlhsh_search_addr6(addr, iface);
-       if (entry != NULL &&
-           (ipv6_addr_equal(&entry->addr, addr) &&
-            ipv6_addr_equal(&entry->mask, mask))) {
-               entry->valid = 0;
-               list_del_rcu(&entry->list);
-               ret_val = 0;
-       }
+       list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
        spin_unlock(&netlbl_unlhsh_lock);
+       if (list_entry == NULL)
+               ret_val = -ENOENT;
+       entry = netlbl_unlhsh_addr6_entry(list_entry);
 
        audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
                                              audit_info);
        if (audit_buf != NULL) {
                dev = dev_get_by_index(net, iface->ifindex);
-               netlbl_unlabel_audit_addr6(audit_buf,
-                                          (dev != NULL ? dev->name : NULL),
-                                          addr, mask);
+               netlbl_af6list_audit_addr(audit_buf, 1,
+                                         (dev != NULL ? dev->name : NULL),
+                                         addr, mask);
                if (dev != NULL)
                        dev_put(dev);
-               if (security_secid_to_secctx(entry->secid,
-                                            &secctx,
-                                            &secctx_len) == 0) {
+               if (entry && security_secid_to_secctx(entry->secid,
+                                                     &secctx,
+                                                     &secctx_len) == 0) {
                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
                        security_release_secctx(secctx, secctx_len);
                }
@@ -836,16 +675,18 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
  */
 static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
 {
-       struct netlbl_unlhsh_addr4 *iter4;
-       struct netlbl_unlhsh_addr6 *iter6;
+       struct netlbl_af4list *iter4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *iter6;
+#endif /* IPv6 */
 
        spin_lock(&netlbl_unlhsh_lock);
-       list_for_each_entry_rcu(iter4, &iface->addr4_list, list)
-               if (iter4->valid)
-                       goto unlhsh_condremove_failure;
-       list_for_each_entry_rcu(iter6, &iface->addr6_list, list)
-               if (iter6->valid)
-                       goto unlhsh_condremove_failure;
+       netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
+               goto unlhsh_condremove_failure;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
+               goto unlhsh_condremove_failure;
+#endif /* IPv6 */
        iface->valid = 0;
        if (iface->ifindex > 0)
                list_del_rcu(&iface->list);
@@ -1349,7 +1190,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
        if (addr4) {
                struct in_addr addr_struct;
 
-               addr_struct.s_addr = addr4->addr;
+               addr_struct.s_addr = addr4->list.addr;
                ret_val = nla_put(cb_arg->skb,
                                  NLBL_UNLABEL_A_IPV4ADDR,
                                  sizeof(struct in_addr),
@@ -1357,7 +1198,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
                if (ret_val != 0)
                        goto list_cb_failure;
 
-               addr_struct.s_addr = addr4->mask;
+               addr_struct.s_addr = addr4->list.mask;
                ret_val = nla_put(cb_arg->skb,
                                  NLBL_UNLABEL_A_IPV4MASK,
                                  sizeof(struct in_addr),
@@ -1370,14 +1211,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
                ret_val = nla_put(cb_arg->skb,
                                  NLBL_UNLABEL_A_IPV6ADDR,
                                  sizeof(struct in6_addr),
-                                 &addr6->addr);
+                                 &addr6->list.addr);
                if (ret_val != 0)
                        goto list_cb_failure;
 
                ret_val = nla_put(cb_arg->skb,
                                  NLBL_UNLABEL_A_IPV6MASK,
                                  sizeof(struct in6_addr),
-                                 &addr6->mask);
+                                 &addr6->list.mask);
                if (ret_val != 0)
                        goto list_cb_failure;
 
@@ -1425,8 +1266,11 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        u32 iter_bkt;
        u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_unlhsh_iface *iface;
-       struct netlbl_unlhsh_addr4 *addr4;
-       struct netlbl_unlhsh_addr6 *addr6;
+       struct list_head *iter_list;
+       struct netlbl_af4list *addr4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       struct netlbl_af6list *addr6;
+#endif
 
        cb_arg.nl_cb = cb;
        cb_arg.skb = skb;
@@ -1436,44 +1280,43 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        for (iter_bkt = skip_bkt;
             iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
             iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
-               list_for_each_entry_rcu(iface,
-                               &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt],
-                               list) {
+               iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
+               list_for_each_entry_rcu(iface, iter_list, list) {
                        if (!iface->valid ||
                            iter_chain++ < skip_chain)
                                continue;
-                       list_for_each_entry_rcu(addr4,
-                                               &iface->addr4_list,
-                                               list) {
-                               if (!addr4->valid || iter_addr4++ < skip_addr4)
+                       netlbl_af4list_foreach_rcu(addr4,
+                                                  &iface->addr4_list) {
+                               if (iter_addr4++ < skip_addr4)
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
-                                                    NLBL_UNLABEL_C_STATICLIST,
-                                                    iface,
-                                                    addr4,
-                                                    NULL,
-                                                    &cb_arg) < 0) {
+                                             NLBL_UNLABEL_C_STATICLIST,
+                                             iface,
+                                             netlbl_unlhsh_addr4_entry(addr4),
+                                             NULL,
+                                             &cb_arg) < 0) {
                                        iter_addr4--;
                                        iter_chain--;
                                        goto unlabel_staticlist_return;
                                }
                        }
-                       list_for_each_entry_rcu(addr6,
-                                               &iface->addr6_list,
-                                               list) {
-                               if (!addr6->valid || iter_addr6++ < skip_addr6)
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+                       netlbl_af6list_foreach_rcu(addr6,
+                                                  &iface->addr6_list) {
+                               if (iter_addr6++ < skip_addr6)
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
-                                                    NLBL_UNLABEL_C_STATICLIST,
-                                                    iface,
-                                                    NULL,
-                                                    addr6,
-                                                    &cb_arg) < 0) {
+                                             NLBL_UNLABEL_C_STATICLIST,
+                                             iface,
+                                             NULL,
+                                             netlbl_unlhsh_addr6_entry(addr6),
+                                             &cb_arg) < 0) {
                                        iter_addr6--;
                                        iter_chain--;
                                        goto unlabel_staticlist_return;
                                }
                        }
+#endif /* IPv6 */
                }
        }
 
@@ -1504,9 +1347,12 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
        struct netlbl_unlhsh_iface *iface;
        u32 skip_addr4 = cb->args[0];
        u32 skip_addr6 = cb->args[1];
-       u32 iter_addr4 = 0, iter_addr6 = 0;
-       struct netlbl_unlhsh_addr4 *addr4;
-       struct netlbl_unlhsh_addr6 *addr6;
+       u32 iter_addr4 = 0;
+       struct netlbl_af4list *addr4;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       u32 iter_addr6 = 0;
+       struct netlbl_af6list *addr6;
+#endif
 
        cb_arg.nl_cb = cb;
        cb_arg.skb = skb;
@@ -1517,30 +1363,32 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
        if (iface == NULL || !iface->valid)
                goto unlabel_staticlistdef_return;
 
-       list_for_each_entry_rcu(addr4, &iface->addr4_list, list) {
-               if (!addr4->valid || iter_addr4++ < skip_addr4)
+       netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
+               if (iter_addr4++ < skip_addr4)
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
-                                          iface,
-                                          addr4,
-                                          NULL,
-                                          &cb_arg) < 0) {
+                                             iface,
+                                             netlbl_unlhsh_addr4_entry(addr4),
+                                             NULL,
+                                             &cb_arg) < 0) {
                        iter_addr4--;
                        goto unlabel_staticlistdef_return;
                }
        }
-       list_for_each_entry_rcu(addr6, &iface->addr6_list, list) {
-               if (!addr6->valid || iter_addr6++ < skip_addr6)
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+       netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
+               if (iter_addr6++ < skip_addr6)
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
-                                          iface,
-                                          NULL,
-                                          addr6,
-                                          &cb_arg) < 0) {
+                                             iface,
+                                             NULL,
+                                             netlbl_unlhsh_addr6_entry(addr6),
+                                             &cb_arg) < 0) {
                        iter_addr6--;
                        goto unlabel_staticlistdef_return;
                }
        }
+#endif /* IPv6 */
 
 unlabel_staticlistdef_return:
        rcu_read_unlock();
@@ -1718,25 +1566,27 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
        switch (family) {
        case PF_INET: {
                struct iphdr *hdr4;
-               struct netlbl_unlhsh_addr4 *addr4;
+               struct netlbl_af4list *addr4;
 
                hdr4 = ip_hdr(skb);
-               addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface);
+               addr4 = netlbl_af4list_search(hdr4->saddr,
+                                             &iface->addr4_list);
                if (addr4 == NULL)
                        goto unlabel_getattr_nolabel;
-               secattr->attr.secid = addr4->secid;
+               secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
                break;
        }
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case PF_INET6: {
                struct ipv6hdr *hdr6;
-               struct netlbl_unlhsh_addr6 *addr6;
+               struct netlbl_af6list *addr6;
 
                hdr6 = ipv6_hdr(skb);
-               addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface);
+               addr6 = netlbl_af6list_search(&hdr6->saddr,
+                                             &iface->addr6_list);
                if (addr6 == NULL)
                        goto unlabel_getattr_nolabel;
-               secattr->attr.secid = addr6->secid;
+               secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
                break;
        }
 #endif /* IPv6 */
index b0eacc0007cc39b1c19ccf0c38800e0e50a8d608..480184a857d21abdf72886d795679b64996399b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * NETLINK      Kernel-user communication protocol.
  *
- *             Authors:        Alan Cox <alan@redhat.com>
+ *             Authors:        Alan Cox <alan@lxorguk.ukuu.org.uk>
  *                             Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
  *
  *             This program is free software; you can redistribute it and/or
@@ -435,7 +435,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol)
                return -EPROTONOSUPPORT;
 
        netlink_lock_table();
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        if (!nl_table[protocol].registered) {
                netlink_unlock_table();
                request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
index 9e9c6fce11aad1ff98a79675c1c840aa79dec4de..b9d97effebe32ac3c276bf4dee94cda5da4fb7cf 100644 (file)
@@ -67,11 +67,10 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
        }
 
        pnp = phonet_proto_get(protocol);
-#ifdef CONFIG_KMOD
        if (pnp == NULL &&
            request_module("net-pf-%d-proto-%d", PF_PHONET, protocol) == 0)
                pnp = phonet_proto_get(protocol);
-#endif
+
        if (pnp == NULL)
                return -EPROTONOSUPPORT;
        if (sock->type != pnp->sock_type) {
index e5b69556bb5b270f5d0b1250d5c01825ba27ea43..21124ec0a73d64d8b4f937b6a7d93d37a6f81a69 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/workqueue.h>
 #include <linux/init.h>
 #include <linux/rfkill.h>
+#include <linux/sched.h>
 
 #include "rfkill-input.h"
 
index 9974b3f04f05cfe54142d7d55cd762021509c8e5..8f457f1e0acf86b16911688b938b262f566669fb 100644 (file)
@@ -494,7 +494,7 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
 
        a_o = tc_lookup_action_n(act_name);
        if (a_o == NULL) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                rtnl_unlock();
                request_module("act_%s", act_name);
                rtnl_lock();
index 8eb79e92e94cb82348a7cf76e8399f46f86426a7..16e7ac9774e5aeab547d6aee1fabcab56efc7480 100644 (file)
@@ -227,7 +227,7 @@ replay:
                err = -ENOENT;
                tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
                if (tp_ops == NULL) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                        struct nlattr *kind = tca[TCA_KIND];
                        char name[IFNAMSIZ];
 
index 5e6f82e0e6f3ca7c092e3a1628d69b416604d0f5..e82519e548d70c747f602bc179ca487f120ef5af 100644 (file)
@@ -224,7 +224,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
 
                if (em->ops == NULL) {
                        err = -ENOENT;
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                        __rtnl_unlock();
                        request_module("ematch-kind-%u", em_hdr->kind);
                        rtnl_lock();
index 1122c952aa99bd17f78f3de3d6c6d6600c3d81b5..b16ad2972c6b527dc2013a5dfb4108ad35ef8197 100644 (file)
@@ -764,7 +764,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
        struct qdisc_size_table *stab;
 
        ops = qdisc_lookup_ops(kind);
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        if (ops == NULL && kind != NULL) {
                char name[IFNAMSIZ];
                if (nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
index 3e8d4e35c08f3892e615959f60b0855e72f348a1..2b7a4b5c9b7254c2ca0534cd174de5bb004a7659 100644 (file)
@@ -1142,7 +1142,7 @@ static int __sock_create(struct net *net, int family, int type, int protocol,
 
        sock->type = type;
 
-#if defined(CONFIG_KMOD)
+#ifdef CONFIG_MODULES
        /* Attempt to load a protocol module if the find failed.
         *
         * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
index 6bfea9ed6869f4142d356b468a70493817b233b7..436bf1b4b76c4fb428df75b948b82df4ff566629 100644 (file)
@@ -83,10 +83,8 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
        if (flavor >= RPC_AUTH_MAXFLAVOR)
                goto out;
 
-#ifdef CONFIG_KMOD
        if ((ops = auth_flavors[flavor]) == NULL)
                request_module("rpc-auth-%u", flavor);
-#endif
        spin_lock(&rpc_authflavor_lock);
        ops = auth_flavors[flavor];
        if (ops == NULL || !try_module_get(ops->owner)) {
index 76739e928d0da5ff99b748ac61538e2bfc03fbf4..4895c341e46d03b2ad31b23c229e58876dce1c68 100644 (file)
@@ -174,7 +174,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        clnt->cl_procinfo = version->procs;
        clnt->cl_maxproc  = version->nrprocs;
        clnt->cl_protname = program->name;
-       clnt->cl_prog     = program->number;
+       clnt->cl_prog     = args->prognumber ? : program->number;
        clnt->cl_vers     = version->number;
        clnt->cl_stats    = program->stats;
        clnt->cl_metrics  = rpc_alloc_iostats(clnt);
@@ -213,10 +213,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
        }
 
        /* save the nodename */
-       clnt->cl_nodelen = strlen(utsname()->nodename);
+       clnt->cl_nodelen = strlen(init_utsname()->nodename);
        if (clnt->cl_nodelen > UNX_MAXNODENAME)
                clnt->cl_nodelen = UNX_MAXNODENAME;
-       memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
+       memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen);
        rpc_register_client(clnt);
        return clnt;
 
index 24db2b4d12d3e43b3faf944262a10105ecaca898..41013dd66ac3f3e61e4823ef853911e179efc46b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/in6.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <net/ipv6.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/sched.h>
@@ -176,13 +177,12 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
 }
 
 static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
-                             u32 version, struct rpc_message *msg,
-                             int *result)
+                             u32 version, struct rpc_message *msg)
 {
        struct rpc_clnt *rpcb_clnt;
-       int error = 0;
+       int result, error = 0;
 
-       *result = 0;
+       msg->rpc_resp = &result;
 
        rpcb_clnt = rpcb_create_local(addr, addrlen, version);
        if (!IS_ERR(rpcb_clnt)) {
@@ -191,12 +191,15 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
        } else
                error = PTR_ERR(rpcb_clnt);
 
-       if (error < 0)
+       if (error < 0) {
                printk(KERN_WARNING "RPC: failed to contact local rpcbind "
                                "server (errno %d).\n", -error);
-       dprintk("RPC:       registration status %d/%d\n", error, *result);
+               return error;
+       }
 
-       return error;
+       if (!result)
+               return -EACCES;
+       return 0;
 }
 
 /**
@@ -205,7 +208,11 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
  * @vers: RPC version number to bind
  * @prot: transport protocol to register
  * @port: port value to register
- * @okay: OUT: result code
+ *
+ * Returns zero if the registration request was dispatched successfully
+ * and the rpcbind daemon returned success.  Otherwise, returns an errno
+ * value that reflects the nature of the error (request could not be
+ * dispatched, timed out, or rpcbind returned an error).
  *
  * RPC services invoke this function to advertise their contact
  * information via the system's rpcbind daemon.  RPC services
@@ -217,15 +224,6 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
  * all registered transports for [program, version] from the local
  * rpcbind database.
  *
- * Returns zero if the registration request was dispatched
- * successfully and a reply was received.  The rpcbind daemon's
- * boolean result code is stored in *okay.
- *
- * Returns an errno value and sets *result to zero if there was
- * some problem that prevented the rpcbind request from being
- * dispatched, or if the rpcbind daemon did not respond within
- * the timeout.
- *
  * This function uses rpcbind protocol version 2 to contact the
  * local rpcbind daemon.
  *
@@ -236,7 +234,7 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
  * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6
  * addresses).
  */
-int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
+int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port)
 {
        struct rpcbind_args map = {
                .r_prog         = prog,
@@ -246,7 +244,6 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
        };
        struct rpc_message msg = {
                .rpc_argp       = &map,
-               .rpc_resp       = okay,
        };
 
        dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
@@ -259,7 +256,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
 
        return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
                                        sizeof(rpcb_inaddr_loopback),
-                                       RPCBVERS_2, &msg, okay);
+                                       RPCBVERS_2, &msg);
 }
 
 /*
@@ -290,7 +287,7 @@ static int rpcb_register_netid4(struct sockaddr_in *address_to_register,
 
        return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback,
                                        sizeof(rpcb_inaddr_loopback),
-                                       RPCBVERS_4, msg, msg->rpc_resp);
+                                       RPCBVERS_4, msg);
 }
 
 /*
@@ -304,10 +301,13 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
        char buf[64];
 
        /* Construct AF_INET6 universal address */
-       snprintf(buf, sizeof(buf),
-                       NIP6_FMT".%u.%u",
-                       NIP6(address_to_register->sin6_addr),
-                       port >> 8, port & 0xff);
+       if (ipv6_addr_any(&address_to_register->sin6_addr))
+               snprintf(buf, sizeof(buf), "::.%u.%u",
+                               port >> 8, port & 0xff);
+       else
+               snprintf(buf, sizeof(buf), NIP6_FMT".%u.%u",
+                               NIP6(address_to_register->sin6_addr),
+                               port >> 8, port & 0xff);
        map->r_addr = buf;
 
        dprintk("RPC:       %sregistering [%u, %u, %s, '%s'] with "
@@ -321,7 +321,7 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
 
        return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback,
                                        sizeof(rpcb_in6addr_loopback),
-                                       RPCBVERS_4, msg, msg->rpc_resp);
+                                       RPCBVERS_4, msg);
 }
 
 /**
@@ -330,7 +330,11 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
  * @version: RPC version number of service to (un)register
  * @address: address family, IP address, and port to (un)register
  * @netid: netid of transport protocol to (un)register
- * @result: result code from rpcbind RPC call
+ *
+ * Returns zero if the registration request was dispatched successfully
+ * and the rpcbind daemon returned success.  Otherwise, returns an errno
+ * value that reflects the nature of the error (request could not be
+ * dispatched, timed out, or rpcbind returned an error).
  *
  * RPC services invoke this function to advertise their contact
  * information via the system's rpcbind daemon.  RPC services
@@ -342,15 +346,6 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
  * to zero.  Callers pass a netid of "" to unregister all
  * transport netids associated with [program, version, address].
  *
- * Returns zero if the registration request was dispatched
- * successfully and a reply was received.  The rpcbind daemon's
- * result code is stored in *result.
- *
- * Returns an errno value and sets *result to zero if there was
- * some problem that prevented the rpcbind request from being
- * dispatched, or if the rpcbind daemon did not respond within
- * the timeout.
- *
  * This function uses rpcbind protocol version 4 to contact the
  * local rpcbind daemon.  The local rpcbind daemon must support
  * version 4 of the rpcbind protocol in order for these functions
@@ -372,8 +367,7 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register,
  * advertises the service on all IPv4 and IPv6 addresses.
  */
 int rpcb_v4_register(const u32 program, const u32 version,
-                    const struct sockaddr *address, const char *netid,
-                    int *result)
+                    const struct sockaddr *address, const char *netid)
 {
        struct rpcbind_args map = {
                .r_prog         = program,
@@ -383,11 +377,8 @@ int rpcb_v4_register(const u32 program, const u32 version,
        };
        struct rpc_message msg = {
                .rpc_argp       = &map,
-               .rpc_resp       = result,
        };
 
-       *result = 0;
-
        switch (address->sa_family) {
        case AF_INET:
                return rpcb_register_netid4((struct sockaddr_in *)address,
@@ -469,6 +460,28 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
        return rpc_run_task(&task_setup_data);
 }
 
+/*
+ * In the case where rpc clients have been cloned, we want to make
+ * sure that we use the program number/version etc of the actual
+ * owner of the xprt. To do so, we walk back up the tree of parents
+ * to find whoever created the transport and/or whoever has the
+ * autobind flag set.
+ */
+static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
+{
+       struct rpc_clnt *parent = clnt->cl_parent;
+
+       while (parent != clnt) {
+               if (parent->cl_xprt != clnt->cl_xprt)
+                       break;
+               if (clnt->cl_autobind)
+                       break;
+               clnt = parent;
+               parent = parent->cl_parent;
+       }
+       return clnt;
+}
+
 /**
  * rpcb_getport_async - obtain the port for a given RPC service on a given host
  * @task: task that is waiting for portmapper request
@@ -478,10 +491,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
  */
 void rpcb_getport_async(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
+       struct rpc_clnt *clnt;
        struct rpc_procinfo *proc;
        u32 bind_version;
-       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_xprt *xprt;
        struct rpc_clnt *rpcb_clnt;
        static struct rpcbind_args *map;
        struct rpc_task *child;
@@ -490,13 +503,13 @@ void rpcb_getport_async(struct rpc_task *task)
        size_t salen;
        int status;
 
+       clnt = rpcb_find_transport_owner(task->tk_client);
+       xprt = clnt->cl_xprt;
+
        dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
                task->tk_pid, __func__,
                clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
 
-       /* Autobind on cloned rpc clients is discouraged */
-       BUG_ON(clnt->cl_parent != clnt);
-
        /* Put self on the wait queue to ensure we get notified if
         * some other task is already attempting to bind the port */
        rpc_sleep_on(&xprt->binding, task, NULL);
@@ -558,7 +571,7 @@ void rpcb_getport_async(struct rpc_task *task)
                status = -ENOMEM;
                dprintk("RPC: %5u %s: no memory available\n",
                        task->tk_pid, __func__);
-               goto bailout_nofree;
+               goto bailout_release_client;
        }
        map->r_prog = clnt->cl_prog;
        map->r_vers = clnt->cl_vers;
@@ -578,11 +591,13 @@ void rpcb_getport_async(struct rpc_task *task)
                        task->tk_pid, __func__);
                return;
        }
-       rpc_put_task(child);
 
-       task->tk_xprt->stat.bind_count++;
+       xprt->stat.bind_count++;
+       rpc_put_task(child);
        return;
 
+bailout_release_client:
+       rpc_release_client(rpcb_clnt);
 bailout_nofree:
        rpcb_wake_rpcbind_waiters(xprt, status);
        task->tk_status = status;
@@ -633,7 +648,7 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
 static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
                               struct rpcbind_args *rpcb)
 {
-       dprintk("RPC:       rpcb_encode_mapping(%u, %u, %d, %u)\n",
+       dprintk("RPC:       encoding rpcb request (%u, %u, %d, %u)\n",
                        rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
        *p++ = htonl(rpcb->r_prog);
        *p++ = htonl(rpcb->r_vers);
@@ -648,7 +663,7 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
                               unsigned short *portp)
 {
        *portp = (unsigned short) ntohl(*p++);
-       dprintk("RPC:       rpcb_decode_getport result %u\n",
+       dprintk("RPC:       rpcb getport result: %u\n",
                        *portp);
        return 0;
 }
@@ -657,7 +672,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
                           unsigned int *boolp)
 {
        *boolp = (unsigned int) ntohl(*p++);
-       dprintk("RPC:       rpcb_decode_set: call %s\n",
+       dprintk("RPC:       rpcb set/unset call %s\n",
                        (*boolp ? "succeeded" : "failed"));
        return 0;
 }
@@ -665,7 +680,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
 static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
                               struct rpcbind_args *rpcb)
 {
-       dprintk("RPC:       rpcb_encode_getaddr(%u, %u, %s)\n",
+       dprintk("RPC:       encoding rpcb request (%u, %u, %s)\n",
                        rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
        *p++ = htonl(rpcb->r_prog);
        *p++ = htonl(rpcb->r_vers);
index 5a32cb7c4bb486267a03d15892adc7ce5db93c93..54c98d8768472f8a8442b024d5ef47c913c99511 100644 (file)
@@ -28,6 +28,8 @@
 
 #define RPCDBG_FACILITY        RPCDBG_SVCDSP
 
+static void svc_unregister(const struct svc_serv *serv);
+
 #define svc_serv_is_pooled(serv)    ((serv)->sv_function)
 
 /*
@@ -357,7 +359,7 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu)
  */
 static struct svc_serv *
 __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
-          void (*shutdown)(struct svc_serv *serv))
+          sa_family_t family, void (*shutdown)(struct svc_serv *serv))
 {
        struct svc_serv *serv;
        unsigned int vers;
@@ -366,6 +368,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
 
        if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL)))
                return NULL;
+       serv->sv_family    = family;
        serv->sv_name      = prog->pg_name;
        serv->sv_program   = prog;
        serv->sv_nrthreads = 1;
@@ -416,30 +419,29 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,
                spin_lock_init(&pool->sp_lock);
        }
 
-
        /* Remove any stale portmap registrations */
-       svc_register(serv, 0, 0);
+       svc_unregister(serv);
 
        return serv;
 }
 
 struct svc_serv *
 svc_create(struct svc_program *prog, unsigned int bufsize,
-               void (*shutdown)(struct svc_serv *serv))
+               sa_family_t family, void (*shutdown)(struct svc_serv *serv))
 {
-       return __svc_create(prog, bufsize, /*npools*/1, shutdown);
+       return __svc_create(prog, bufsize, /*npools*/1, family, shutdown);
 }
 EXPORT_SYMBOL(svc_create);
 
 struct svc_serv *
 svc_create_pooled(struct svc_program *prog, unsigned int bufsize,
-               void (*shutdown)(struct svc_serv *serv),
+                 sa_family_t family, void (*shutdown)(struct svc_serv *serv),
                  svc_thread_fn func, struct module *mod)
 {
        struct svc_serv *serv;
        unsigned int npools = svc_pool_map_get();
 
-       serv = __svc_create(prog, bufsize, npools, shutdown);
+       serv = __svc_create(prog, bufsize, npools, family, shutdown);
 
        if (serv != NULL) {
                serv->sv_function = func;
@@ -486,8 +488,7 @@ svc_destroy(struct svc_serv *serv)
        if (svc_serv_is_pooled(serv))
                svc_pool_map_put();
 
-       /* Unregister service with the portmapper */
-       svc_register(serv, 0, 0);
+       svc_unregister(serv);
        kfree(serv->sv_pools);
        kfree(serv);
 }
@@ -718,55 +719,245 @@ svc_exit_thread(struct svc_rqst *rqstp)
 }
 EXPORT_SYMBOL(svc_exit_thread);
 
+#ifdef CONFIG_SUNRPC_REGISTER_V4
+
 /*
- * Register an RPC service with the local portmapper.
- * To unregister a service, call this routine with
- * proto and port == 0.
+ * Register an "inet" protocol family netid with the local
+ * rpcbind daemon via an rpcbind v4 SET request.
+ *
+ * No netconfig infrastructure is available in the kernel, so
+ * we map IP_ protocol numbers to netids by hand.
+ *
+ * Returns zero on success; a negative errno value is returned
+ * if any error occurs.
  */
-int
-svc_register(struct svc_serv *serv, int proto, unsigned short port)
+static int __svc_rpcb_register4(const u32 program, const u32 version,
+                               const unsigned short protocol,
+                               const unsigned short port)
+{
+       struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+               .sin_addr.s_addr        = htonl(INADDR_ANY),
+               .sin_port               = htons(port),
+       };
+       char *netid;
+
+       switch (protocol) {
+       case IPPROTO_UDP:
+               netid = RPCBIND_NETID_UDP;
+               break;
+       case IPPROTO_TCP:
+               netid = RPCBIND_NETID_TCP;
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       return rpcb_v4_register(program, version,
+                               (struct sockaddr *)&sin, netid);
+}
+
+/*
+ * Register an "inet6" protocol family netid with the local
+ * rpcbind daemon via an rpcbind v4 SET request.
+ *
+ * No netconfig infrastructure is available in the kernel, so
+ * we map IP_ protocol numbers to netids by hand.
+ *
+ * Returns zero on success; a negative errno value is returned
+ * if any error occurs.
+ */
+static int __svc_rpcb_register6(const u32 program, const u32 version,
+                               const unsigned short protocol,
+                               const unsigned short port)
+{
+       struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+               .sin6_port              = htons(port),
+       };
+       char *netid;
+
+       switch (protocol) {
+       case IPPROTO_UDP:
+               netid = RPCBIND_NETID_UDP6;
+               break;
+       case IPPROTO_TCP:
+               netid = RPCBIND_NETID_TCP6;
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       return rpcb_v4_register(program, version,
+                               (struct sockaddr *)&sin6, netid);
+}
+
+/*
+ * Register a kernel RPC service via rpcbind version 4.
+ *
+ * Returns zero on success; a negative errno value is returned
+ * if any error occurs.
+ */
+static int __svc_register(const u32 program, const u32 version,
+                         const sa_family_t family,
+                         const unsigned short protocol,
+                         const unsigned short port)
+{
+       int error;
+
+       switch (family) {
+       case AF_INET:
+               return __svc_rpcb_register4(program, version,
+                                               protocol, port);
+       case AF_INET6:
+               error = __svc_rpcb_register6(program, version,
+                                               protocol, port);
+               if (error < 0)
+                       return error;
+
+               /*
+                * Work around bug in some versions of Linux rpcbind
+                * which don't allow registration of both inet and
+                * inet6 netids.
+                *
+                * Error return ignored for now.
+                */
+               __svc_rpcb_register4(program, version,
+                                               protocol, port);
+               return 0;
+       }
+
+       return -EAFNOSUPPORT;
+}
+
+#else  /* CONFIG_SUNRPC_REGISTER_V4 */
+
+/*
+ * Register a kernel RPC service via rpcbind version 2.
+ *
+ * Returns zero on success; a negative errno value is returned
+ * if any error occurs.
+ */
+static int __svc_register(const u32 program, const u32 version,
+                         sa_family_t family,
+                         const unsigned short protocol,
+                         const unsigned short port)
+{
+       if (family != AF_INET)
+               return -EAFNOSUPPORT;
+
+       return rpcb_register(program, version, protocol, port);
+}
+
+#endif /* CONFIG_SUNRPC_REGISTER_V4 */
+
+/**
+ * svc_register - register an RPC service with the local portmapper
+ * @serv: svc_serv struct for the service to register
+ * @proto: transport protocol number to advertise
+ * @port: port to advertise
+ *
+ * Service is registered for any address in serv's address family
+ */
+int svc_register(const struct svc_serv *serv, const unsigned short proto,
+                const unsigned short port)
 {
        struct svc_program      *progp;
-       unsigned long           flags;
        unsigned int            i;
-       int                     error = 0, dummy;
+       int                     error = 0;
 
-       if (!port)
-               clear_thread_flag(TIF_SIGPENDING);
+       BUG_ON(proto == 0 && port == 0);
 
        for (progp = serv->sv_program; progp; progp = progp->pg_next) {
                for (i = 0; i < progp->pg_nvers; i++) {
                        if (progp->pg_vers[i] == NULL)
                                continue;
 
-                       dprintk("svc: svc_register(%s, %s, %d, %d)%s\n",
+                       dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
                                        progp->pg_name,
+                                       i,
                                        proto == IPPROTO_UDP?  "udp" : "tcp",
                                        port,
-                                       i,
+                                       serv->sv_family,
                                        progp->pg_vers[i]->vs_hidden?
                                                " (but not telling portmap)" : "");
 
                        if (progp->pg_vers[i]->vs_hidden)
                                continue;
 
-                       error = rpcb_register(progp->pg_prog, i, proto, port, &dummy);
+                       error = __svc_register(progp->pg_prog, i,
+                                               serv->sv_family, proto, port);
                        if (error < 0)
                                break;
-                       if (port && !dummy) {
-                               error = -EACCES;
-                               break;
-                       }
                }
        }
 
-       if (!port) {
-               spin_lock_irqsave(&current->sighand->siglock, flags);
-               recalc_sigpending();
-               spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       return error;
+}
+
+#ifdef CONFIG_SUNRPC_REGISTER_V4
+
+static void __svc_unregister(const u32 program, const u32 version,
+                            const char *progname)
+{
+       struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+               .sin6_port              = 0,
+       };
+       int error;
+
+       error = rpcb_v4_register(program, version,
+                               (struct sockaddr *)&sin6, "");
+       dprintk("svc: %s(%sv%u), error %d\n",
+                       __func__, progname, version, error);
+}
+
+#else  /* CONFIG_SUNRPC_REGISTER_V4 */
+
+static void __svc_unregister(const u32 program, const u32 version,
+                            const char *progname)
+{
+       int error;
+
+       error = rpcb_register(program, version, 0, 0);
+       dprintk("svc: %s(%sv%u), error %d\n",
+                       __func__, progname, version, error);
+}
+
+#endif /* CONFIG_SUNRPC_REGISTER_V4 */
+
+/*
+ * All netids, bind addresses and ports registered for [program, version]
+ * are removed from the local rpcbind database (if the service is not
+ * hidden) to make way for a new instance of the service.
+ *
+ * The result of unregistration is reported via dprintk for those who want
+ * verification of the result, but is otherwise not important.
+ */
+static void svc_unregister(const struct svc_serv *serv)
+{
+       struct svc_program *progp;
+       unsigned long flags;
+       unsigned int i;
+
+       clear_thread_flag(TIF_SIGPENDING);
+
+       for (progp = serv->sv_program; progp; progp = progp->pg_next) {
+               for (i = 0; i < progp->pg_nvers; i++) {
+                       if (progp->pg_vers[i] == NULL)
+                               continue;
+                       if (progp->pg_vers[i]->vs_hidden)
+                               continue;
+
+                       __svc_unregister(progp->pg_prog, i, progp->pg_name);
+               }
        }
 
-       return error;
+       spin_lock_irqsave(&current->sighand->siglock, flags);
+       recalc_sigpending();
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
 }
 
 /*
index e46c825f49548923f79f1363d4a7712ef4ead513..bf5b5cdafebfcc82866369bdb3d895c83379a4e3 100644 (file)
@@ -159,15 +159,44 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
 }
 EXPORT_SYMBOL_GPL(svc_xprt_init);
 
-int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
-                   int flags)
+static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
+                                        struct svc_serv *serv,
+                                        unsigned short port, int flags)
 {
-       struct svc_xprt_class *xcl;
        struct sockaddr_in sin = {
                .sin_family             = AF_INET,
                .sin_addr.s_addr        = htonl(INADDR_ANY),
                .sin_port               = htons(port),
        };
+       struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+               .sin6_port              = htons(port),
+       };
+       struct sockaddr *sap;
+       size_t len;
+
+       switch (serv->sv_family) {
+       case AF_INET:
+               sap = (struct sockaddr *)&sin;
+               len = sizeof(sin);
+               break;
+       case AF_INET6:
+               sap = (struct sockaddr *)&sin6;
+               len = sizeof(sin6);
+               break;
+       default:
+               return ERR_PTR(-EAFNOSUPPORT);
+       }
+
+       return xcl->xcl_ops->xpo_create(serv, sap, len, flags);
+}
+
+int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
+                   int flags)
+{
+       struct svc_xprt_class *xcl;
+
        dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
        spin_lock(&svc_xprt_class_lock);
        list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
@@ -180,9 +209,7 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
                        goto err;
 
                spin_unlock(&svc_xprt_class_lock);
-               newxprt = xcl->xcl_ops->
-                       xpo_create(serv, (struct sockaddr *)&sin, sizeof(sin),
-                                  flags);
+               newxprt = __svc_xpo_create(xcl, serv, port, flags);
                if (IS_ERR(newxprt)) {
                        module_put(xcl->xcl_owner);
                        return PTR_ERR(newxprt);
index 3e65719f1ef698891d8e81ebea6c57e72b212717..95293f549e9c2b371b82ce32af4ca43be00b5ada 100644 (file)
@@ -1114,6 +1114,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        struct svc_sock *svsk;
        struct sock     *inet;
        int             pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
+       int             val;
 
        dprintk("svc: svc_setup_socket %p\n", sock);
        if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1146,6 +1147,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        else
                svc_tcp_init(svsk, serv);
 
+       /*
+        * We start one listener per sv_serv.  We want AF_INET
+        * requests to be automatically shunted to our AF_INET6
+        * listener using a mapped IPv4 address.  Make sure
+        * no-one starts an equivalent IPv4 listener, which
+        * would steal our incoming connections.
+        */
+       val = 0;
+       if (serv->sv_family == AF_INET6)
+               kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
+                                       (char *)&val, sizeof(val));
+
        dprintk("svc: svc_setup_socket created %p (inet %p)\n",
                                svsk, svsk->sk_sk);
 
@@ -1154,8 +1167,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
 
 int svc_addsock(struct svc_serv *serv,
                int fd,
-               char *name_return,
-               int *proto)
+               char *name_return)
 {
        int err = 0;
        struct socket *so = sockfd_lookup(fd, &err);
@@ -1190,7 +1202,6 @@ int svc_addsock(struct svc_serv *serv,
                sockfd_put(so);
                return err;
        }
-       if (proto) *proto = so->sk->sk_protocol;
        return one_sock_name(name_return, svsk);
 }
 EXPORT_SYMBOL_GPL(svc_addsock);
index 99a52aabe332a70d881a427dd1beba36e9d1d87a..29e401bb612ecf62edfa8f71a3e44f2583837b5c 100644 (file)
@@ -108,13 +108,10 @@ int xprt_register_transport(struct xprt_class *transport)
                        goto out;
        }
 
-       result = -EINVAL;
-       if (try_module_get(THIS_MODULE)) {
-               list_add_tail(&transport->list, &xprt_list);
-               printk(KERN_INFO "RPC: Registered %s transport module.\n",
-                       transport->name);
-               result = 0;
-       }
+       list_add_tail(&transport->list, &xprt_list);
+       printk(KERN_INFO "RPC: Registered %s transport module.\n",
+              transport->name);
+       result = 0;
 
 out:
        spin_unlock(&xprt_list_lock);
@@ -143,7 +140,6 @@ int xprt_unregister_transport(struct xprt_class *transport)
                                "RPC: Unregistered %s transport module.\n",
                                transport->name);
                        list_del_init(&transport->list);
-                       module_put(THIS_MODULE);
                        goto out;
                }
        }
index 5c1954d28d0914578d744f94eddbd157f7da2e3a..14106d26bb95881b2f7e3c5496aa8b10625a298f 100644 (file)
@@ -118,6 +118,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
        }
 
        if (xdrbuf->tail[0].iov_len) {
+               /* the rpcrdma protocol allows us to omit any trailing
+                * xdr pad bytes, saving the server an RDMA operation. */
+               if (xdrbuf->tail[0].iov_len < 4 && xprt_rdma_pad_optimize)
+                       return n;
                if (n == nsegs)
                        return 0;
                seg[n].mr_page = NULL;
@@ -508,8 +512,8 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
        if (hdrlen == 0)
                return -1;
 
-       dprintk("RPC:       %s: %s: hdrlen %zd rpclen %zd padlen %zd\n"
-               "                   headerp 0x%p base 0x%p lkey 0x%x\n",
+       dprintk("RPC:       %s: %s: hdrlen %zd rpclen %zd padlen %zd"
+               " headerp 0x%p base 0x%p lkey 0x%x\n",
                __func__, transfertypes[wtype], hdrlen, rpclen, padlen,
                headerp, base, req->rl_iov.lkey);
 
@@ -594,7 +598,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b
  * Scatter inline received data back into provided iov's.
  */
 static void
-rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len)
+rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
 {
        int i, npages, curlen, olen;
        char *destp;
@@ -660,6 +664,13 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len)
        } else
                rqst->rq_rcv_buf.tail[0].iov_len = 0;
 
+       if (pad) {
+               /* implicit padding on terminal chunk */
+               unsigned char *p = rqst->rq_rcv_buf.tail[0].iov_base;
+               while (pad--)
+                       p[rqst->rq_rcv_buf.tail[0].iov_len++] = 0;
+       }
+
        if (copy_len)
                dprintk("RPC:       %s: %d bytes in"
                        " %d extra segments (%d lost)\n",
@@ -681,12 +692,14 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep)
        struct rpc_xprt *xprt = ep->rep_xprt;
 
        spin_lock_bh(&xprt->transport_lock);
+       if (++xprt->connect_cookie == 0)        /* maintain a reserved value */
+               ++xprt->connect_cookie;
        if (ep->rep_connected > 0) {
                if (!xprt_test_and_set_connected(xprt))
                        xprt_wake_pending_tasks(xprt, 0);
        } else {
                if (xprt_test_and_clear_connected(xprt))
-                       xprt_wake_pending_tasks(xprt, ep->rep_connected);
+                       xprt_wake_pending_tasks(xprt, -ENOTCONN);
        }
        spin_unlock_bh(&xprt->transport_lock);
 }
@@ -792,14 +805,20 @@ repost:
                            ((unsigned char *)iptr - (unsigned char *)headerp);
                        status = rep->rr_len + rdmalen;
                        r_xprt->rx_stats.total_rdma_reply += rdmalen;
+                       /* special case - last chunk may omit padding */
+                       if (rdmalen &= 3) {
+                               rdmalen = 4 - rdmalen;
+                               status += rdmalen;
+                       }
                } else {
                        /* else ordinary inline */
+                       rdmalen = 0;
                        iptr = (__be32 *)((unsigned char *)headerp + 28);
                        rep->rr_len -= 28; /*sizeof *headerp;*/
                        status = rep->rr_len;
                }
                /* Fix up the rpc results for upper layer */
-               rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len);
+               rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len, rdmalen);
                break;
 
        case htonl(RDMA_NOMSG):
index 74de31a066168509db7dba7ab559b29d17dae413..a4756576d68794a1106c4404b39ad9adf510a906 100644 (file)
@@ -116,7 +116,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp,
  *
  * Assumptions:
  * - chunk[0]->position points to pages[0] at an offset of 0
- * - pages[] is not physically or virtually contigous and consists of
+ * - pages[] is not physically or virtually contiguous and consists of
  *   PAGE_SIZE elements.
  *
  * Output:
@@ -125,7 +125,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp,
  *   chunk in the read list
  *
  */
-static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt,
+static int map_read_chunks(struct svcxprt_rdma *xprt,
                           struct svc_rqst *rqstp,
                           struct svc_rdma_op_ctxt *head,
                           struct rpcrdma_msg *rmsgp,
@@ -211,26 +211,128 @@ static int rdma_rcl_to_sge(struct svcxprt_rdma *xprt,
        return sge_no;
 }
 
-static void rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
-                             struct svc_rdma_op_ctxt *ctxt,
-                             struct kvec *vec,
-                             u64 *sgl_offset,
-                             int count)
+/* Map a read-chunk-list to an XDR and fast register the page-list.
+ *
+ * Assumptions:
+ * - chunk[0]  position points to pages[0] at an offset of 0
+ * - pages[]   will be made physically contiguous by creating a one-off memory
+ *             region using the fastreg verb.
+ * - byte_count is # of bytes in read-chunk-list
+ * - ch_count  is # of chunks in read-chunk-list
+ *
+ * Output:
+ * - sge array pointing into pages[] array.
+ * - chunk_sge array specifying sge index and count for each
+ *   chunk in the read list
+ */
+static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
+                               struct svc_rqst *rqstp,
+                               struct svc_rdma_op_ctxt *head,
+                               struct rpcrdma_msg *rmsgp,
+                               struct svc_rdma_req_map *rpl_map,
+                               struct svc_rdma_req_map *chl_map,
+                               int ch_count,
+                               int byte_count)
+{
+       int page_no;
+       int ch_no;
+       u32 offset;
+       struct rpcrdma_read_chunk *ch;
+       struct svc_rdma_fastreg_mr *frmr;
+       int ret = 0;
+
+       frmr = svc_rdma_get_frmr(xprt);
+       if (IS_ERR(frmr))
+               return -ENOMEM;
+
+       head->frmr = frmr;
+       head->arg.head[0] = rqstp->rq_arg.head[0];
+       head->arg.tail[0] = rqstp->rq_arg.tail[0];
+       head->arg.pages = &head->pages[head->count];
+       head->hdr_count = head->count; /* save count of hdr pages */
+       head->arg.page_base = 0;
+       head->arg.page_len = byte_count;
+       head->arg.len = rqstp->rq_arg.len + byte_count;
+       head->arg.buflen = rqstp->rq_arg.buflen + byte_count;
+
+       /* Fast register the page list */
+       frmr->kva = page_address(rqstp->rq_arg.pages[0]);
+       frmr->direction = DMA_FROM_DEVICE;
+       frmr->access_flags = (IB_ACCESS_LOCAL_WRITE|IB_ACCESS_REMOTE_WRITE);
+       frmr->map_len = byte_count;
+       frmr->page_list_len = PAGE_ALIGN(byte_count) >> PAGE_SHIFT;
+       for (page_no = 0; page_no < frmr->page_list_len; page_no++) {
+               frmr->page_list->page_list[page_no] =
+                       ib_dma_map_single(xprt->sc_cm_id->device,
+                                         page_address(rqstp->rq_arg.pages[page_no]),
+                                         PAGE_SIZE, DMA_TO_DEVICE);
+               if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                        frmr->page_list->page_list[page_no]))
+                       goto fatal_err;
+               atomic_inc(&xprt->sc_dma_used);
+               head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no];
+       }
+       head->count += page_no;
+
+       /* rq_respages points one past arg pages */
+       rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
+
+       /* Create the reply and chunk maps */
+       offset = 0;
+       ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
+       for (ch_no = 0; ch_no < ch_count; ch_no++) {
+               rpl_map->sge[ch_no].iov_base = frmr->kva + offset;
+               rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length;
+               chl_map->ch[ch_no].count = 1;
+               chl_map->ch[ch_no].start = ch_no;
+               offset += ch->rc_target.rs_length;
+               ch++;
+       }
+
+       ret = svc_rdma_fastreg(xprt, frmr);
+       if (ret)
+               goto fatal_err;
+
+       return ch_no;
+
+ fatal_err:
+       printk("svcrdma: error fast registering xdr for xprt %p", xprt);
+       svc_rdma_put_frmr(xprt, frmr);
+       return -EIO;
+}
+
+static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
+                            struct svc_rdma_op_ctxt *ctxt,
+                            struct svc_rdma_fastreg_mr *frmr,
+                            struct kvec *vec,
+                            u64 *sgl_offset,
+                            int count)
 {
        int i;
 
        ctxt->count = count;
        ctxt->direction = DMA_FROM_DEVICE;
        for (i = 0; i < count; i++) {
-               atomic_inc(&xprt->sc_dma_used);
-               ctxt->sge[i].addr =
-                       ib_dma_map_single(xprt->sc_cm_id->device,
-                                         vec[i].iov_base, vec[i].iov_len,
-                                         DMA_FROM_DEVICE);
+               ctxt->sge[i].length = 0; /* in case map fails */
+               if (!frmr) {
+                       ctxt->sge[i].addr =
+                               ib_dma_map_single(xprt->sc_cm_id->device,
+                                                 vec[i].iov_base,
+                                                 vec[i].iov_len,
+                                                 DMA_FROM_DEVICE);
+                       if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                                ctxt->sge[i].addr))
+                               return -EINVAL;
+                       ctxt->sge[i].lkey = xprt->sc_dma_lkey;
+                       atomic_inc(&xprt->sc_dma_used);
+               } else {
+                       ctxt->sge[i].addr = (unsigned long)vec[i].iov_base;
+                       ctxt->sge[i].lkey = frmr->mr->lkey;
+               }
                ctxt->sge[i].length = vec[i].iov_len;
-               ctxt->sge[i].lkey = xprt->sc_phys_mr->lkey;
                *sgl_offset = *sgl_offset + vec[i].iov_len;
        }
+       return 0;
 }
 
 static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count)
@@ -278,6 +380,7 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
                         struct svc_rdma_op_ctxt *hdr_ctxt)
 {
        struct ib_send_wr read_wr;
+       struct ib_send_wr inv_wr;
        int err = 0;
        int ch_no;
        int ch_count;
@@ -301,9 +404,20 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
        svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count);
        if (ch_count > RPCSVC_MAXPAGES)
                return -EINVAL;
-       sge_count = rdma_rcl_to_sge(xprt, rqstp, hdr_ctxt, rmsgp,
-                                   rpl_map, chl_map,
-                                   ch_count, byte_count);
+
+       if (!xprt->sc_frmr_pg_list_len)
+               sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp,
+                                           rpl_map, chl_map, ch_count,
+                                           byte_count);
+       else
+               sge_count = fast_reg_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp,
+                                                rpl_map, chl_map, ch_count,
+                                                byte_count);
+       if (sge_count < 0) {
+               err = -EIO;
+               goto out;
+       }
+
        sgl_offset = 0;
        ch_no = 0;
 
@@ -312,13 +426,16 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt,
 next_sge:
                ctxt = svc_rdma_get_context(xprt);
                ctxt->direction = DMA_FROM_DEVICE;
+               ctxt->frmr = hdr_ctxt->frmr;
+               ctxt->read_hdr = NULL;
                clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
+               clear_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags);
 
                /* Prepare READ WR */
                memset(&read_wr, 0, sizeof read_wr);
-               ctxt->wr_op = IB_WR_RDMA_READ;
                read_wr.wr_id = (unsigned long)ctxt;
                read_wr.opcode = IB_WR_RDMA_READ;
+               ctxt->wr_op = read_wr.opcode;
                read_wr.send_flags = IB_SEND_SIGNALED;
                read_wr.wr.rdma.rkey = ch->rc_target.rs_handle;
                read_wr.wr.rdma.remote_addr =
@@ -327,10 +444,15 @@ next_sge:
                read_wr.sg_list = ctxt->sge;
                read_wr.num_sge =
                        rdma_read_max_sge(xprt, chl_map->ch[ch_no].count);
-               rdma_set_ctxt_sge(xprt, ctxt,
-                                 &rpl_map->sge[chl_map->ch[ch_no].start],
-                                 &sgl_offset,
-                                 read_wr.num_sge);
+               err = rdma_set_ctxt_sge(xprt, ctxt, hdr_ctxt->frmr,
+                                       &rpl_map->sge[chl_map->ch[ch_no].start],
+                                       &sgl_offset,
+                                       read_wr.num_sge);
+               if (err) {
+                       svc_rdma_unmap_dma(ctxt);
+                       svc_rdma_put_context(ctxt, 0);
+                       goto out;
+               }
                if (((ch+1)->rc_discrim == 0) &&
                    (read_wr.num_sge == chl_map->ch[ch_no].count)) {
                        /*
@@ -339,6 +461,29 @@ next_sge:
                         * the client and the RPC needs to be enqueued.
                         */
                        set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
+                       if (hdr_ctxt->frmr) {
+                               set_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags);
+                               /*
+                                * Invalidate the local MR used to map the data
+                                * sink.
+                                */
+                               if (xprt->sc_dev_caps &
+                                   SVCRDMA_DEVCAP_READ_W_INV) {
+                                       read_wr.opcode =
+                                               IB_WR_RDMA_READ_WITH_INV;
+                                       ctxt->wr_op = read_wr.opcode;
+                                       read_wr.ex.invalidate_rkey =
+                                               ctxt->frmr->mr->lkey;
+                               } else {
+                                       /* Prepare INVALIDATE WR */
+                                       memset(&inv_wr, 0, sizeof inv_wr);
+                                       inv_wr.opcode = IB_WR_LOCAL_INV;
+                                       inv_wr.send_flags = IB_SEND_SIGNALED;
+                                       inv_wr.ex.invalidate_rkey =
+                                               hdr_ctxt->frmr->mr->lkey;
+                                       read_wr.next = &inv_wr;
+                               }
+                       }
                        ctxt->read_hdr = hdr_ctxt;
                }
                /* Post the read */
index 84d328329d98575d624557fa75a7e159436ece85..9a7a8e7ae038fbb255dd34880e7882feb8eff322 100644 (file)
  * array is only concerned with the reply we are assured that we have
  * on extra page for the RPCRMDA header.
  */
-static void xdr_to_sge(struct svcxprt_rdma *xprt,
-                      struct xdr_buf *xdr,
-                      struct svc_rdma_req_map *vec)
+int fast_reg_xdr(struct svcxprt_rdma *xprt,
+                struct xdr_buf *xdr,
+                struct svc_rdma_req_map *vec)
+{
+       int sge_no;
+       u32 sge_bytes;
+       u32 page_bytes;
+       u32 page_off;
+       int page_no = 0;
+       u8 *frva;
+       struct svc_rdma_fastreg_mr *frmr;
+
+       frmr = svc_rdma_get_frmr(xprt);
+       if (IS_ERR(frmr))
+               return -ENOMEM;
+       vec->frmr = frmr;
+
+       /* Skip the RPCRDMA header */
+       sge_no = 1;
+
+       /* Map the head. */
+       frva = (void *)((unsigned long)(xdr->head[0].iov_base) & PAGE_MASK);
+       vec->sge[sge_no].iov_base = xdr->head[0].iov_base;
+       vec->sge[sge_no].iov_len = xdr->head[0].iov_len;
+       vec->count = 2;
+       sge_no++;
+
+       /* Build the FRMR */
+       frmr->kva = frva;
+       frmr->direction = DMA_TO_DEVICE;
+       frmr->access_flags = 0;
+       frmr->map_len = PAGE_SIZE;
+       frmr->page_list_len = 1;
+       frmr->page_list->page_list[page_no] =
+               ib_dma_map_single(xprt->sc_cm_id->device,
+                                 (void *)xdr->head[0].iov_base,
+                                 PAGE_SIZE, DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                frmr->page_list->page_list[page_no]))
+               goto fatal_err;
+       atomic_inc(&xprt->sc_dma_used);
+
+       page_off = xdr->page_base;
+       page_bytes = xdr->page_len + page_off;
+       if (!page_bytes)
+               goto encode_tail;
+
+       /* Map the pages */
+       vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off;
+       vec->sge[sge_no].iov_len = page_bytes;
+       sge_no++;
+       while (page_bytes) {
+               struct page *page;
+
+               page = xdr->pages[page_no++];
+               sge_bytes = min_t(u32, page_bytes, (PAGE_SIZE - page_off));
+               page_bytes -= sge_bytes;
+
+               frmr->page_list->page_list[page_no] =
+                       ib_dma_map_page(xprt->sc_cm_id->device, page, 0,
+                                         PAGE_SIZE, DMA_TO_DEVICE);
+               if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                        frmr->page_list->page_list[page_no]))
+                       goto fatal_err;
+
+               atomic_inc(&xprt->sc_dma_used);
+               page_off = 0; /* reset for next time through loop */
+               frmr->map_len += PAGE_SIZE;
+               frmr->page_list_len++;
+       }
+       vec->count++;
+
+ encode_tail:
+       /* Map tail */
+       if (0 == xdr->tail[0].iov_len)
+               goto done;
+
+       vec->count++;
+       vec->sge[sge_no].iov_len = xdr->tail[0].iov_len;
+
+       if (((unsigned long)xdr->tail[0].iov_base & PAGE_MASK) ==
+           ((unsigned long)xdr->head[0].iov_base & PAGE_MASK)) {
+               /*
+                * If head and tail use the same page, we don't need
+                * to map it again.
+                */
+               vec->sge[sge_no].iov_base = xdr->tail[0].iov_base;
+       } else {
+               void *va;
+
+               /* Map another page for the tail */
+               page_off = (unsigned long)xdr->tail[0].iov_base & ~PAGE_MASK;
+               va = (void *)((unsigned long)xdr->tail[0].iov_base & PAGE_MASK);
+               vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off;
+
+               frmr->page_list->page_list[page_no] =
+                       ib_dma_map_single(xprt->sc_cm_id->device, va, PAGE_SIZE,
+                                         DMA_TO_DEVICE);
+               if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                        frmr->page_list->page_list[page_no]))
+                       goto fatal_err;
+               atomic_inc(&xprt->sc_dma_used);
+               frmr->map_len += PAGE_SIZE;
+               frmr->page_list_len++;
+       }
+
+ done:
+       if (svc_rdma_fastreg(xprt, frmr))
+               goto fatal_err;
+
+       return 0;
+
+ fatal_err:
+       printk("svcrdma: Error fast registering memory for xprt %p\n", xprt);
+       svc_rdma_put_frmr(xprt, frmr);
+       return -EIO;
+}
+
+static int map_xdr(struct svcxprt_rdma *xprt,
+                  struct xdr_buf *xdr,
+                  struct svc_rdma_req_map *vec)
 {
        int sge_max = (xdr->len+PAGE_SIZE-1) / PAGE_SIZE + 3;
        int sge_no;
@@ -83,6 +201,9 @@ static void xdr_to_sge(struct svcxprt_rdma *xprt,
        BUG_ON(xdr->len !=
               (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len));
 
+       if (xprt->sc_frmr_pg_list_len)
+               return fast_reg_xdr(xprt, xdr, vec);
+
        /* Skip the first sge, this is for the RPCRDMA header */
        sge_no = 1;
 
@@ -116,9 +237,12 @@ static void xdr_to_sge(struct svcxprt_rdma *xprt,
 
        BUG_ON(sge_no > sge_max);
        vec->count = sge_no;
+       return 0;
 }
 
 /* Assumptions:
+ * - We are using FRMR
+ *     - or -
  * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE
  */
 static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
@@ -158,30 +282,35 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
        sge_no = 0;
 
        /* Copy the remaining SGE */
-       while (bc != 0 && xdr_sge_no < vec->count) {
-               sge[sge_no].lkey = xprt->sc_phys_mr->lkey;
-               sge_bytes = min((size_t)bc,
-                               (size_t)(vec->sge[xdr_sge_no].iov_len-sge_off));
+       while (bc != 0) {
+               sge_bytes = min_t(size_t,
+                         bc, vec->sge[xdr_sge_no].iov_len-sge_off);
                sge[sge_no].length = sge_bytes;
-               atomic_inc(&xprt->sc_dma_used);
-               sge[sge_no].addr =
-                       ib_dma_map_single(xprt->sc_cm_id->device,
-                                         (void *)
-                                         vec->sge[xdr_sge_no].iov_base + sge_off,
-                                         sge_bytes, DMA_TO_DEVICE);
-               if (dma_mapping_error(xprt->sc_cm_id->device->dma_device,
-                                       sge[sge_no].addr))
-                       goto err;
+               if (!vec->frmr) {
+                       sge[sge_no].addr =
+                               ib_dma_map_single(xprt->sc_cm_id->device,
+                                                 (void *)
+                                                 vec->sge[xdr_sge_no].iov_base + sge_off,
+                                                 sge_bytes, DMA_TO_DEVICE);
+                       if (ib_dma_mapping_error(xprt->sc_cm_id->device,
+                                                sge[sge_no].addr))
+                               goto err;
+                       atomic_inc(&xprt->sc_dma_used);
+                       sge[sge_no].lkey = xprt->sc_dma_lkey;
+               } else {
+                       sge[sge_no].addr = (unsigned long)
+                               vec->sge[xdr_sge_no].iov_base + sge_off;
+                       sge[sge_no].lkey = vec->frmr->mr->lkey;
+               }
+               ctxt->count++;
+               ctxt->frmr = vec->frmr;
                sge_off = 0;
                sge_no++;
-               ctxt->count++;
                xdr_sge_no++;
+               BUG_ON(xdr_sge_no > vec->count);
                bc -= sge_bytes;
        }
 
-       BUG_ON(bc != 0);
-       BUG_ON(xdr_sge_no > vec->count);
-
        /* Prepare WRITE WR */
        memset(&write_wr, 0, sizeof write_wr);
        ctxt->wr_op = IB_WR_RDMA_WRITE;
@@ -226,7 +355,10 @@ static int send_write_chunks(struct svcxprt_rdma *xprt,
        res_ary = (struct rpcrdma_write_array *)
                &rdma_resp->rm_body.rm_chunks[1];
 
-       max_write = xprt->sc_max_sge * PAGE_SIZE;
+       if (vec->frmr)
+               max_write = vec->frmr->map_len;
+       else
+               max_write = xprt->sc_max_sge * PAGE_SIZE;
 
        /* Write chunks start at the pagelist */
        for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0;
@@ -297,7 +429,10 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
        res_ary = (struct rpcrdma_write_array *)
                &rdma_resp->rm_body.rm_chunks[2];
 
-       max_write = xprt->sc_max_sge * PAGE_SIZE;
+       if (vec->frmr)
+               max_write = vec->frmr->map_len;
+       else
+               max_write = xprt->sc_max_sge * PAGE_SIZE;
 
        /* xdr offset starts at RPC message */
        for (xdr_off = 0, chunk_no = 0;
@@ -307,7 +442,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
                ch = &arg_ary->wc_array[chunk_no].wc_target;
                write_len = min(xfer_len, ch->rs_length);
 
-
                /* Prepare the reply chunk given the length actually
                 * written */
                rs_offset = get_unaligned(&(ch->rs_offset));
@@ -366,6 +500,7 @@ static int send_reply(struct svcxprt_rdma *rdma,
                      int byte_count)
 {
        struct ib_send_wr send_wr;
+       struct ib_send_wr inv_wr;
        int sge_no;
        int sge_bytes;
        int page_no;
@@ -385,27 +520,45 @@ static int send_reply(struct svcxprt_rdma *rdma,
        /* Prepare the context */
        ctxt->pages[0] = page;
        ctxt->count = 1;
+       ctxt->frmr = vec->frmr;
+       if (vec->frmr)
+               set_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags);
+       else
+               clear_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags);
 
        /* Prepare the SGE for the RPCRDMA Header */
-       atomic_inc(&rdma->sc_dma_used);
        ctxt->sge[0].addr =
                ib_dma_map_page(rdma->sc_cm_id->device,
                                page, 0, PAGE_SIZE, DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr))
+               goto err;
+       atomic_inc(&rdma->sc_dma_used);
+
        ctxt->direction = DMA_TO_DEVICE;
+
        ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp);
-       ctxt->sge[0].lkey = rdma->sc_phys_mr->lkey;
+       ctxt->sge[0].lkey = rdma->sc_dma_lkey;
 
        /* Determine how many of our SGE are to be transmitted */
        for (sge_no = 1; byte_count && sge_no < vec->count; sge_no++) {
                sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count);
                byte_count -= sge_bytes;
-               atomic_inc(&rdma->sc_dma_used);
-               ctxt->sge[sge_no].addr =
-                       ib_dma_map_single(rdma->sc_cm_id->device,
-                                         vec->sge[sge_no].iov_base,
-                                         sge_bytes, DMA_TO_DEVICE);
+               if (!vec->frmr) {
+                       ctxt->sge[sge_no].addr =
+                               ib_dma_map_single(rdma->sc_cm_id->device,
+                                                 vec->sge[sge_no].iov_base,
+                                                 sge_bytes, DMA_TO_DEVICE);
+                       if (ib_dma_mapping_error(rdma->sc_cm_id->device,
+                                                ctxt->sge[sge_no].addr))
+                               goto err;
+                       atomic_inc(&rdma->sc_dma_used);
+                       ctxt->sge[sge_no].lkey = rdma->sc_dma_lkey;
+               } else {
+                       ctxt->sge[sge_no].addr = (unsigned long)
+                               vec->sge[sge_no].iov_base;
+                       ctxt->sge[sge_no].lkey = vec->frmr->mr->lkey;
+               }
                ctxt->sge[sge_no].length = sge_bytes;
-               ctxt->sge[sge_no].lkey = rdma->sc_phys_mr->lkey;
        }
        BUG_ON(byte_count != 0);
 
@@ -417,11 +570,16 @@ static int send_reply(struct svcxprt_rdma *rdma,
                ctxt->pages[page_no+1] = rqstp->rq_respages[page_no];
                ctxt->count++;
                rqstp->rq_respages[page_no] = NULL;
-               /* If there are more pages than SGE, terminate SGE list */
+               /*
+                * If there are more pages than SGE, terminate SGE
+                * list so that svc_rdma_unmap_dma doesn't attempt to
+                * unmap garbage.
+                */
                if (page_no+1 >= sge_no)
                        ctxt->sge[page_no+1].length = 0;
        }
        BUG_ON(sge_no > rdma->sc_max_sge);
+       BUG_ON(sge_no > ctxt->count);
        memset(&send_wr, 0, sizeof send_wr);
        ctxt->wr_op = IB_WR_SEND;
        send_wr.wr_id = (unsigned long)ctxt;
@@ -429,12 +587,26 @@ static int send_reply(struct svcxprt_rdma *rdma,
        send_wr.num_sge = sge_no;
        send_wr.opcode = IB_WR_SEND;
        send_wr.send_flags =  IB_SEND_SIGNALED;
+       if (vec->frmr) {
+               /* Prepare INVALIDATE WR */
+               memset(&inv_wr, 0, sizeof inv_wr);
+               inv_wr.opcode = IB_WR_LOCAL_INV;
+               inv_wr.send_flags = IB_SEND_SIGNALED;
+               inv_wr.ex.invalidate_rkey =
+                       vec->frmr->mr->lkey;
+               send_wr.next = &inv_wr;
+       }
 
        ret = svc_rdma_send(rdma, &send_wr);
        if (ret)
-               svc_rdma_put_context(ctxt, 1);
+               goto err;
 
-       return ret;
+       return 0;
+
+ err:
+       svc_rdma_put_frmr(rdma, vec->frmr);
+       svc_rdma_put_context(ctxt, 1);
+       return -EIO;
 }
 
 void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp)
@@ -477,8 +649,9 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        ctxt = svc_rdma_get_context(rdma);
        ctxt->direction = DMA_TO_DEVICE;
        vec = svc_rdma_get_req_map();
-       xdr_to_sge(rdma, &rqstp->rq_res, vec);
-
+       ret = map_xdr(rdma, &rqstp->rq_res, vec);
+       if (ret)
+               goto err0;
        inline_bytes = rqstp->rq_res.len;
 
        /* Create the RDMA response header */
@@ -498,7 +671,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        if (ret < 0) {
                printk(KERN_ERR "svcrdma: failed to send write chunks, rc=%d\n",
                       ret);
-               goto error;
+               goto err1;
        }
        inline_bytes -= ret;
 
@@ -508,7 +681,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        if (ret < 0) {
                printk(KERN_ERR "svcrdma: failed to send reply chunks, rc=%d\n",
                       ret);
-               goto error;
+               goto err1;
        }
        inline_bytes -= ret;
 
@@ -517,9 +690,11 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
        svc_rdma_put_req_map(vec);
        dprintk("svcrdma: send_reply returns %d\n", ret);
        return ret;
- error:
+
+ err1:
+       put_page(res_page);
+ err0:
        svc_rdma_put_req_map(vec);
        svc_rdma_put_context(ctxt, 0);
-       put_page(res_page);
        return ret;
 }
index 900cb69728c691537e14e85e6f4618c0b0f79cfe..6fb493cbd29fcd2786479965bb526ba343e1b70f 100644 (file)
@@ -100,20 +100,29 @@ struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
        ctxt->xprt = xprt;
        INIT_LIST_HEAD(&ctxt->dto_q);
        ctxt->count = 0;
+       ctxt->frmr = NULL;
        atomic_inc(&xprt->sc_ctxt_used);
        return ctxt;
 }
 
-static void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
+void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
 {
        struct svcxprt_rdma *xprt = ctxt->xprt;
        int i;
        for (i = 0; i < ctxt->count && ctxt->sge[i].length; i++) {
-               atomic_dec(&xprt->sc_dma_used);
-               ib_dma_unmap_single(xprt->sc_cm_id->device,
-                                   ctxt->sge[i].addr,
-                                   ctxt->sge[i].length,
-                                   ctxt->direction);
+               /*
+                * Unmap the DMA addr in the SGE if the lkey matches
+                * the sc_dma_lkey, otherwise, ignore it since it is
+                * an FRMR lkey and will be unmapped later when the
+                * last WR that uses it completes.
+                */
+               if (ctxt->sge[i].lkey == xprt->sc_dma_lkey) {
+                       atomic_dec(&xprt->sc_dma_used);
+                       ib_dma_unmap_single(xprt->sc_cm_id->device,
+                                           ctxt->sge[i].addr,
+                                           ctxt->sge[i].length,
+                                           ctxt->direction);
+               }
        }
 }
 
@@ -150,6 +159,7 @@ struct svc_rdma_req_map *svc_rdma_get_req_map(void)
                schedule_timeout_uninterruptible(msecs_to_jiffies(500));
        }
        map->count = 0;
+       map->frmr = NULL;
        return map;
 }
 
@@ -315,6 +325,50 @@ static void rq_cq_reap(struct svcxprt_rdma *xprt)
                svc_xprt_enqueue(&xprt->sc_xprt);
 }
 
+/*
+ * Processs a completion context
+ */
+static void process_context(struct svcxprt_rdma *xprt,
+                           struct svc_rdma_op_ctxt *ctxt)
+{
+       svc_rdma_unmap_dma(ctxt);
+
+       switch (ctxt->wr_op) {
+       case IB_WR_SEND:
+               if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags))
+                       svc_rdma_put_frmr(xprt, ctxt->frmr);
+               svc_rdma_put_context(ctxt, 1);
+               break;
+
+       case IB_WR_RDMA_WRITE:
+               svc_rdma_put_context(ctxt, 0);
+               break;
+
+       case IB_WR_RDMA_READ:
+       case IB_WR_RDMA_READ_WITH_INV:
+               if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) {
+                       struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr;
+                       BUG_ON(!read_hdr);
+                       if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags))
+                               svc_rdma_put_frmr(xprt, ctxt->frmr);
+                       spin_lock_bh(&xprt->sc_rq_dto_lock);
+                       set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
+                       list_add_tail(&read_hdr->dto_q,
+                                     &xprt->sc_read_complete_q);
+                       spin_unlock_bh(&xprt->sc_rq_dto_lock);
+                       svc_xprt_enqueue(&xprt->sc_xprt);
+               }
+               svc_rdma_put_context(ctxt, 0);
+               break;
+
+       default:
+               printk(KERN_ERR "svcrdma: unexpected completion type, "
+                      "opcode=%d\n",
+                      ctxt->wr_op);
+               break;
+       }
+}
+
 /*
  * Send Queue Completion Handler - potentially called on interrupt context.
  *
@@ -327,17 +381,12 @@ static void sq_cq_reap(struct svcxprt_rdma *xprt)
        struct ib_cq *cq = xprt->sc_sq_cq;
        int ret;
 
-
        if (!test_and_clear_bit(RDMAXPRT_SQ_PENDING, &xprt->sc_flags))
                return;
 
        ib_req_notify_cq(xprt->sc_sq_cq, IB_CQ_NEXT_COMP);
        atomic_inc(&rdma_stat_sq_poll);
        while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) {
-               ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
-               xprt = ctxt->xprt;
-
-               svc_rdma_unmap_dma(ctxt);
                if (wc.status != IB_WC_SUCCESS)
                        /* Close the transport */
                        set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
@@ -346,35 +395,10 @@ static void sq_cq_reap(struct svcxprt_rdma *xprt)
                atomic_dec(&xprt->sc_sq_count);
                wake_up(&xprt->sc_send_wait);
 
-               switch (ctxt->wr_op) {
-               case IB_WR_SEND:
-                       svc_rdma_put_context(ctxt, 1);
-                       break;
-
-               case IB_WR_RDMA_WRITE:
-                       svc_rdma_put_context(ctxt, 0);
-                       break;
-
-               case IB_WR_RDMA_READ:
-                       if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) {
-                               struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr;
-                               BUG_ON(!read_hdr);
-                               spin_lock_bh(&xprt->sc_rq_dto_lock);
-                               set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
-                               list_add_tail(&read_hdr->dto_q,
-                                             &xprt->sc_read_complete_q);
-                               spin_unlock_bh(&xprt->sc_rq_dto_lock);
-                               svc_xprt_enqueue(&xprt->sc_xprt);
-                       }
-                       svc_rdma_put_context(ctxt, 0);
-                       break;
+               ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
+               if (ctxt)
+                       process_context(xprt, ctxt);
 
-               default:
-                       printk(KERN_ERR "svcrdma: unexpected completion type, "
-                              "opcode=%d, status=%d\n",
-                              wc.opcode, wc.status);
-                       break;
-               }
                svc_xprt_put(&xprt->sc_xprt);
        }
 
@@ -425,10 +449,12 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
        INIT_LIST_HEAD(&cma_xprt->sc_dto_q);
        INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q);
        INIT_LIST_HEAD(&cma_xprt->sc_read_complete_q);
+       INIT_LIST_HEAD(&cma_xprt->sc_frmr_q);
        init_waitqueue_head(&cma_xprt->sc_send_wait);
 
        spin_lock_init(&cma_xprt->sc_lock);
        spin_lock_init(&cma_xprt->sc_rq_dto_lock);
+       spin_lock_init(&cma_xprt->sc_frmr_q_lock);
 
        cma_xprt->sc_ord = svcrdma_ord;
 
@@ -462,7 +488,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
        struct ib_recv_wr recv_wr, *bad_recv_wr;
        struct svc_rdma_op_ctxt *ctxt;
        struct page *page;
-       unsigned long pa;
+       dma_addr_t pa;
        int sge_no;
        int buflen;
        int ret;
@@ -474,13 +500,15 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
                BUG_ON(sge_no >= xprt->sc_max_sge);
                page = svc_rdma_get_page();
                ctxt->pages[sge_no] = page;
-               atomic_inc(&xprt->sc_dma_used);
                pa = ib_dma_map_page(xprt->sc_cm_id->device,
                                     page, 0, PAGE_SIZE,
                                     DMA_FROM_DEVICE);
+               if (ib_dma_mapping_error(xprt->sc_cm_id->device, pa))
+                       goto err_put_ctxt;
+               atomic_inc(&xprt->sc_dma_used);
                ctxt->sge[sge_no].addr = pa;
                ctxt->sge[sge_no].length = PAGE_SIZE;
-               ctxt->sge[sge_no].lkey = xprt->sc_phys_mr->lkey;
+               ctxt->sge[sge_no].lkey = xprt->sc_dma_lkey;
                buflen += PAGE_SIZE;
        }
        ctxt->count = sge_no;
@@ -496,6 +524,10 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
                svc_rdma_put_context(ctxt, 1);
        }
        return ret;
+
+ err_put_ctxt:
+       svc_rdma_put_context(ctxt, 1);
+       return -ENOMEM;
 }
 
 /*
@@ -566,7 +598,7 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
                dprintk("svcrdma: Connect request on cma_id=%p, xprt = %p, "
                        "event=%d\n", cma_id, cma_id->context, event->event);
                handle_connect_req(cma_id,
-                                  event->param.conn.responder_resources);
+                                  event->param.conn.initiator_depth);
                break;
 
        case RDMA_CM_EVENT_ESTABLISHED:
@@ -686,6 +718,97 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
        return ERR_PTR(ret);
 }
 
+static struct svc_rdma_fastreg_mr *rdma_alloc_frmr(struct svcxprt_rdma *xprt)
+{
+       struct ib_mr *mr;
+       struct ib_fast_reg_page_list *pl;
+       struct svc_rdma_fastreg_mr *frmr;
+
+       frmr = kmalloc(sizeof(*frmr), GFP_KERNEL);
+       if (!frmr)
+               goto err;
+
+       mr = ib_alloc_fast_reg_mr(xprt->sc_pd, RPCSVC_MAXPAGES);
+       if (!mr)
+               goto err_free_frmr;
+
+       pl = ib_alloc_fast_reg_page_list(xprt->sc_cm_id->device,
+                                        RPCSVC_MAXPAGES);
+       if (!pl)
+               goto err_free_mr;
+
+       frmr->mr = mr;
+       frmr->page_list = pl;
+       INIT_LIST_HEAD(&frmr->frmr_list);
+       return frmr;
+
+ err_free_mr:
+       ib_dereg_mr(mr);
+ err_free_frmr:
+       kfree(frmr);
+ err:
+       return ERR_PTR(-ENOMEM);
+}
+
+static void rdma_dealloc_frmr_q(struct svcxprt_rdma *xprt)
+{
+       struct svc_rdma_fastreg_mr *frmr;
+
+       while (!list_empty(&xprt->sc_frmr_q)) {
+               frmr = list_entry(xprt->sc_frmr_q.next,
+                                 struct svc_rdma_fastreg_mr, frmr_list);
+               list_del_init(&frmr->frmr_list);
+               ib_dereg_mr(frmr->mr);
+               ib_free_fast_reg_page_list(frmr->page_list);
+               kfree(frmr);
+       }
+}
+
+struct svc_rdma_fastreg_mr *svc_rdma_get_frmr(struct svcxprt_rdma *rdma)
+{
+       struct svc_rdma_fastreg_mr *frmr = NULL;
+
+       spin_lock_bh(&rdma->sc_frmr_q_lock);
+       if (!list_empty(&rdma->sc_frmr_q)) {
+               frmr = list_entry(rdma->sc_frmr_q.next,
+                                 struct svc_rdma_fastreg_mr, frmr_list);
+               list_del_init(&frmr->frmr_list);
+               frmr->map_len = 0;
+               frmr->page_list_len = 0;
+       }
+       spin_unlock_bh(&rdma->sc_frmr_q_lock);
+       if (frmr)
+               return frmr;
+
+       return rdma_alloc_frmr(rdma);
+}
+
+static void frmr_unmap_dma(struct svcxprt_rdma *xprt,
+                          struct svc_rdma_fastreg_mr *frmr)
+{
+       int page_no;
+       for (page_no = 0; page_no < frmr->page_list_len; page_no++) {
+               dma_addr_t addr = frmr->page_list->page_list[page_no];
+               if (ib_dma_mapping_error(frmr->mr->device, addr))
+                       continue;
+               atomic_dec(&xprt->sc_dma_used);
+               ib_dma_unmap_single(frmr->mr->device, addr, PAGE_SIZE,
+                                   frmr->direction);
+       }
+}
+
+void svc_rdma_put_frmr(struct svcxprt_rdma *rdma,
+                      struct svc_rdma_fastreg_mr *frmr)
+{
+       if (frmr) {
+               frmr_unmap_dma(rdma, frmr);
+               spin_lock_bh(&rdma->sc_frmr_q_lock);
+               BUG_ON(!list_empty(&frmr->frmr_list));
+               list_add(&frmr->frmr_list, &rdma->sc_frmr_q);
+               spin_unlock_bh(&rdma->sc_frmr_q_lock);
+       }
+}
+
 /*
  * This is the xpo_recvfrom function for listening endpoints. Its
  * purpose is to accept incoming connections. The CMA callback handler
@@ -704,6 +827,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        struct rdma_conn_param conn_param;
        struct ib_qp_init_attr qp_attr;
        struct ib_device_attr devattr;
+       int dma_mr_acc;
+       int need_dma_mr;
        int ret;
        int i;
 
@@ -819,15 +944,77 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        }
        newxprt->sc_qp = newxprt->sc_cm_id->qp;
 
-       /* Register all of physical memory */
-       newxprt->sc_phys_mr = ib_get_dma_mr(newxprt->sc_pd,
-                                           IB_ACCESS_LOCAL_WRITE |
-                                           IB_ACCESS_REMOTE_WRITE);
-       if (IS_ERR(newxprt->sc_phys_mr)) {
-               dprintk("svcrdma: Failed to create DMA MR ret=%d\n", ret);
+       /*
+        * Use the most secure set of MR resources based on the
+        * transport type and available memory management features in
+        * the device. Here's the table implemented below:
+        *
+        *              Fast    Global  DMA     Remote WR
+        *              Reg     LKEY    MR      Access
+        *              Sup'd   Sup'd   Needed  Needed
+        *
+        * IWARP        N       N       Y       Y
+        *              N       Y       Y       Y
+        *              Y       N       Y       N
+        *              Y       Y       N       -
+        *
+        * IB           N       N       Y       N
+        *              N       Y       N       -
+        *              Y       N       Y       N
+        *              Y       Y       N       -
+        *
+        * NB:  iWARP requires remote write access for the data sink
+        *      of an RDMA_READ. IB does not.
+        */
+       if (devattr.device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) {
+               newxprt->sc_frmr_pg_list_len =
+                       devattr.max_fast_reg_page_list_len;
+               newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_FAST_REG;
+       }
+
+       /*
+        * Determine if a DMA MR is required and if so, what privs are required
+        */
+       switch (rdma_node_get_transport(newxprt->sc_cm_id->device->node_type)) {
+       case RDMA_TRANSPORT_IWARP:
+               newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_READ_W_INV;
+               if (!(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG)) {
+                       need_dma_mr = 1;
+                       dma_mr_acc =
+                               (IB_ACCESS_LOCAL_WRITE |
+                                IB_ACCESS_REMOTE_WRITE);
+               } else if (!(devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)) {
+                       need_dma_mr = 1;
+                       dma_mr_acc = IB_ACCESS_LOCAL_WRITE;
+               } else
+                       need_dma_mr = 0;
+               break;
+       case RDMA_TRANSPORT_IB:
+               if (!(devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)) {
+                       need_dma_mr = 1;
+                       dma_mr_acc = IB_ACCESS_LOCAL_WRITE;
+               } else
+                       need_dma_mr = 0;
+               break;
+       default:
                goto errout;
        }
 
+       /* Create the DMA MR if needed, otherwise, use the DMA LKEY */
+       if (need_dma_mr) {
+               /* Register all of physical memory */
+               newxprt->sc_phys_mr =
+                       ib_get_dma_mr(newxprt->sc_pd, dma_mr_acc);
+               if (IS_ERR(newxprt->sc_phys_mr)) {
+                       dprintk("svcrdma: Failed to create DMA MR ret=%d\n",
+                               ret);
+                       goto errout;
+               }
+               newxprt->sc_dma_lkey = newxprt->sc_phys_mr->lkey;
+       } else
+               newxprt->sc_dma_lkey =
+                       newxprt->sc_cm_id->device->local_dma_lkey;
+
        /* Post receive buffers */
        for (i = 0; i < newxprt->sc_max_requests; i++) {
                ret = svc_rdma_post_recv(newxprt);
@@ -961,6 +1148,9 @@ static void __svc_rdma_free(struct work_struct *work)
        WARN_ON(atomic_read(&rdma->sc_ctxt_used) != 0);
        WARN_ON(atomic_read(&rdma->sc_dma_used) != 0);
 
+       /* De-allocate fastreg mr */
+       rdma_dealloc_frmr_q(rdma);
+
        /* Destroy the QP if present (not a listener) */
        if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
                ib_destroy_qp(rdma->sc_qp);
@@ -1014,21 +1204,59 @@ static int svc_rdma_has_wspace(struct svc_xprt *xprt)
        return 1;
 }
 
+/*
+ * Attempt to register the kvec representing the RPC memory with the
+ * device.
+ *
+ * Returns:
+ *  NULL : The device does not support fastreg or there were no more
+ *         fastreg mr.
+ *  frmr : The kvec register request was successfully posted.
+ *    <0 : An error was encountered attempting to register the kvec.
+ */
+int svc_rdma_fastreg(struct svcxprt_rdma *xprt,
+                    struct svc_rdma_fastreg_mr *frmr)
+{
+       struct ib_send_wr fastreg_wr;
+       u8 key;
+
+       /* Bump the key */
+       key = (u8)(frmr->mr->lkey & 0x000000FF);
+       ib_update_fast_reg_key(frmr->mr, ++key);
+
+       /* Prepare FASTREG WR */
+       memset(&fastreg_wr, 0, sizeof fastreg_wr);
+       fastreg_wr.opcode = IB_WR_FAST_REG_MR;
+       fastreg_wr.send_flags = IB_SEND_SIGNALED;
+       fastreg_wr.wr.fast_reg.iova_start = (unsigned long)frmr->kva;
+       fastreg_wr.wr.fast_reg.page_list = frmr->page_list;
+       fastreg_wr.wr.fast_reg.page_list_len = frmr->page_list_len;
+       fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
+       fastreg_wr.wr.fast_reg.length = frmr->map_len;
+       fastreg_wr.wr.fast_reg.access_flags = frmr->access_flags;
+       fastreg_wr.wr.fast_reg.rkey = frmr->mr->lkey;
+       return svc_rdma_send(xprt, &fastreg_wr);
+}
+
 int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
 {
-       struct ib_send_wr *bad_wr;
+       struct ib_send_wr *bad_wr, *n_wr;
+       int wr_count;
+       int i;
        int ret;
 
        if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
                return -ENOTCONN;
 
        BUG_ON(wr->send_flags != IB_SEND_SIGNALED);
-       BUG_ON(((struct svc_rdma_op_ctxt *)(unsigned long)wr->wr_id)->wr_op !=
-               wr->opcode);
+       wr_count = 1;
+       for (n_wr = wr->next; n_wr; n_wr = n_wr->next)
+               wr_count++;
+
        /* If the SQ is full, wait until an SQ entry is available */
        while (1) {
                spin_lock_bh(&xprt->sc_lock);
-               if (xprt->sc_sq_depth == atomic_read(&xprt->sc_sq_count)) {
+               if (xprt->sc_sq_depth < atomic_read(&xprt->sc_sq_count) + wr_count) {
                        spin_unlock_bh(&xprt->sc_lock);
                        atomic_inc(&rdma_stat_sq_starve);
 
@@ -1043,19 +1271,26 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
                                return 0;
                        continue;
                }
-               /* Bumped used SQ WR count and post */
-               svc_xprt_get(&xprt->sc_xprt);
+               /* Take a transport ref for each WR posted */
+               for (i = 0; i < wr_count; i++)
+                       svc_xprt_get(&xprt->sc_xprt);
+
+               /* Bump used SQ WR count and post */
+               atomic_add(wr_count, &xprt->sc_sq_count);
                ret = ib_post_send(xprt->sc_qp, wr, &bad_wr);
-               if (!ret)
-                       atomic_inc(&xprt->sc_sq_count);
-               else {
-                       svc_xprt_put(&xprt->sc_xprt);
+               if (ret) {
+                       set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
+                       atomic_sub(wr_count, &xprt->sc_sq_count);
+                       for (i = 0; i < wr_count; i ++)
+                               svc_xprt_put(&xprt->sc_xprt);
                        dprintk("svcrdma: failed to post SQ WR rc=%d, "
                               "sc_sq_count=%d, sc_sq_depth=%d\n",
                               ret, atomic_read(&xprt->sc_sq_count),
                               xprt->sc_sq_depth);
                }
                spin_unlock_bh(&xprt->sc_lock);
+               if (ret)
+                       wake_up(&xprt->sc_send_wait);
                break;
        }
        return ret;
@@ -1079,10 +1314,14 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
        length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
 
        /* Prepare SGE for local address */
-       atomic_inc(&xprt->sc_dma_used);
        sge.addr = ib_dma_map_page(xprt->sc_cm_id->device,
                                   p, 0, PAGE_SIZE, DMA_FROM_DEVICE);
-       sge.lkey = xprt->sc_phys_mr->lkey;
+       if (ib_dma_mapping_error(xprt->sc_cm_id->device, sge.addr)) {
+               put_page(p);
+               return;
+       }
+       atomic_inc(&xprt->sc_dma_used);
+       sge.lkey = xprt->sc_dma_lkey;
        sge.length = length;
 
        ctxt = svc_rdma_get_context(xprt);
@@ -1103,6 +1342,9 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
        if (ret) {
                dprintk("svcrdma: Error %d posting send for protocol error\n",
                        ret);
+               ib_dma_unmap_page(xprt->sc_cm_id->device,
+                                 sge.addr, PAGE_SIZE,
+                                 DMA_FROM_DEVICE);
                svc_rdma_put_context(ctxt, 1);
        }
 }
index a564c1a39ec5f833b3a5dd9f369269615a047940..9839c3d94145d4b154c71ac754f65f9a52239f63 100644 (file)
@@ -70,11 +70,8 @@ static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE;
 static unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE;
 static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE;
 static unsigned int xprt_rdma_inline_write_padding;
-#if !RPCRDMA_PERSISTENT_REGISTRATION
-static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_REGISTER; /* FMR? */
-#else
-static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_ALLPHYSICAL;
-#endif
+static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR;
+                int xprt_rdma_pad_optimize = 0;
 
 #ifdef RPC_DEBUG
 
@@ -139,6 +136,14 @@ static ctl_table xr_tunables_table[] = {
                .extra1         = &min_memreg,
                .extra2         = &max_memreg,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "rdma_pad_optimize",
+               .data           = &xprt_rdma_pad_optimize,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name = 0,
        },
@@ -458,6 +463,8 @@ xprt_rdma_close(struct rpc_xprt *xprt)
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
 
        dprintk("RPC:       %s: closing\n", __func__);
+       if (r_xprt->rx_ep.rep_connected > 0)
+               xprt->reestablish_timeout = 0;
        xprt_disconnect_done(xprt);
        (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia);
 }
@@ -485,6 +492,11 @@ xprt_rdma_connect(struct rpc_task *task)
                        /* Reconnect */
                        schedule_delayed_work(&r_xprt->rdma_connect,
                                xprt->reestablish_timeout);
+                       xprt->reestablish_timeout <<= 1;
+                       if (xprt->reestablish_timeout > (30 * HZ))
+                               xprt->reestablish_timeout = (30 * HZ);
+                       else if (xprt->reestablish_timeout < (5 * HZ))
+                               xprt->reestablish_timeout = (5 * HZ);
                } else {
                        schedule_delayed_work(&r_xprt->rdma_connect, 0);
                        if (!RPC_IS_ASYNC(task))
@@ -591,6 +603,7 @@ xprt_rdma_allocate(struct rpc_task *task, size_t size)
        }
        dprintk("RPC:       %s: size %zd, request 0x%p\n", __func__, size, req);
 out:
+       req->rl_connect_cookie = 0;     /* our reserved value */
        return req->rl_xdr_buf;
 
 outfail:
@@ -694,13 +707,21 @@ xprt_rdma_send_request(struct rpc_task *task)
                req->rl_reply->rr_xprt = xprt;
        }
 
-       if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req)) {
-               xprt_disconnect_done(xprt);
-               return -ENOTCONN;       /* implies disconnect */
-       }
+       /* Must suppress retransmit to maintain credits */
+       if (req->rl_connect_cookie == xprt->connect_cookie)
+               goto drop_connection;
+       req->rl_connect_cookie = xprt->connect_cookie;
+
+       if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req))
+               goto drop_connection;
 
+       task->tk_bytes_sent += rqst->rq_snd_buf.len;
        rqst->rq_bytes_sent = 0;
        return 0;
+
+drop_connection:
+       xprt_disconnect_done(xprt);
+       return -ENOTCONN;       /* implies disconnect */
 }
 
 static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
@@ -770,7 +791,7 @@ static void __exit xprt_rdma_cleanup(void)
 {
        int rc;
 
-       dprintk("RPCRDMA Module Removed, deregister RPC RDMA transport\n");
+       dprintk(KERN_INFO "RPCRDMA Module Removed, deregister RPC RDMA transport\n");
 #ifdef RPC_DEBUG
        if (sunrpc_table_header) {
                unregister_sysctl_table(sunrpc_table_header);
index 8ea283ecc522a8a5e8e033b12f6485fc5ef456c4..a5fef5e6c32314b7098fe59756ddb5280681e5df 100644 (file)
@@ -284,6 +284,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
        switch (event->event) {
        case RDMA_CM_EVENT_ADDR_RESOLVED:
        case RDMA_CM_EVENT_ROUTE_RESOLVED:
+               ia->ri_async_rc = 0;
                complete(&ia->ri_done);
                break;
        case RDMA_CM_EVENT_ADDR_ERROR:
@@ -338,13 +339,32 @@ connected:
                wake_up_all(&ep->rep_connect_wait);
                break;
        default:
-               ia->ri_async_rc = -EINVAL;
-               dprintk("RPC:       %s: unexpected CM event %X\n",
+               dprintk("RPC:       %s: unexpected CM event %d\n",
                        __func__, event->event);
-               complete(&ia->ri_done);
                break;
        }
 
+#ifdef RPC_DEBUG
+       if (connstate == 1) {
+               int ird = attr.max_dest_rd_atomic;
+               int tird = ep->rep_remote_cma.responder_resources;
+               printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u "
+                       "on %s, memreg %d slots %d ird %d%s\n",
+                       NIPQUAD(addr->sin_addr.s_addr),
+                       ntohs(addr->sin_port),
+                       ia->ri_id->device->name,
+                       ia->ri_memreg_strategy,
+                       xprt->rx_buf.rb_max_requests,
+                       ird, ird < 4 && ird < tird / 2 ? " (low!)" : "");
+       } else if (connstate < 0) {
+               printk(KERN_INFO "rpcrdma: connection to %u.%u.%u.%u:%u "
+                       "closed (%d)\n",
+                       NIPQUAD(addr->sin_addr.s_addr),
+                       ntohs(addr->sin_port),
+                       connstate);
+       }
+#endif
+
        return 0;
 }
 
@@ -355,6 +375,8 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt,
        struct rdma_cm_id *id;
        int rc;
 
+       init_completion(&ia->ri_done);
+
        id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP);
        if (IS_ERR(id)) {
                rc = PTR_ERR(id);
@@ -363,26 +385,28 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt,
                return id;
        }
 
-       ia->ri_async_rc = 0;
+       ia->ri_async_rc = -ETIMEDOUT;
        rc = rdma_resolve_addr(id, NULL, addr, RDMA_RESOLVE_TIMEOUT);
        if (rc) {
                dprintk("RPC:       %s: rdma_resolve_addr() failed %i\n",
                        __func__, rc);
                goto out;
        }
-       wait_for_completion(&ia->ri_done);
+       wait_for_completion_interruptible_timeout(&ia->ri_done,
+                               msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT) + 1);
        rc = ia->ri_async_rc;
        if (rc)
                goto out;
 
-       ia->ri_async_rc = 0;
+       ia->ri_async_rc = -ETIMEDOUT;
        rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT);
        if (rc) {
                dprintk("RPC:       %s: rdma_resolve_route() failed %i\n",
                        __func__, rc);
                goto out;
        }
-       wait_for_completion(&ia->ri_done);
+       wait_for_completion_interruptible_timeout(&ia->ri_done,
+                               msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT) + 1);
        rc = ia->ri_async_rc;
        if (rc)
                goto out;
@@ -423,11 +447,10 @@ rpcrdma_clean_cq(struct ib_cq *cq)
 int
 rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
 {
-       int rc;
+       int rc, mem_priv;
+       struct ib_device_attr devattr;
        struct rpcrdma_ia *ia = &xprt->rx_ia;
 
-       init_completion(&ia->ri_done);
-
        ia->ri_id = rpcrdma_create_id(xprt, ia, addr);
        if (IS_ERR(ia->ri_id)) {
                rc = PTR_ERR(ia->ri_id);
@@ -442,6 +465,73 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
                goto out2;
        }
 
+       /*
+        * Query the device to determine if the requested memory
+        * registration strategy is supported. If it isn't, set the
+        * strategy to a globally supported model.
+        */
+       rc = ib_query_device(ia->ri_id->device, &devattr);
+       if (rc) {
+               dprintk("RPC:       %s: ib_query_device failed %d\n",
+                       __func__, rc);
+               goto out2;
+       }
+
+       if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) {
+               ia->ri_have_dma_lkey = 1;
+               ia->ri_dma_lkey = ia->ri_id->device->local_dma_lkey;
+       }
+
+       switch (memreg) {
+       case RPCRDMA_MEMWINDOWS:
+       case RPCRDMA_MEMWINDOWS_ASYNC:
+               if (!(devattr.device_cap_flags & IB_DEVICE_MEM_WINDOW)) {
+                       dprintk("RPC:       %s: MEMWINDOWS registration "
+                               "specified but not supported by adapter, "
+                               "using slower RPCRDMA_REGISTER\n",
+                               __func__);
+                       memreg = RPCRDMA_REGISTER;
+               }
+               break;
+       case RPCRDMA_MTHCAFMR:
+               if (!ia->ri_id->device->alloc_fmr) {
+#if RPCRDMA_PERSISTENT_REGISTRATION
+                       dprintk("RPC:       %s: MTHCAFMR registration "
+                               "specified but not supported by adapter, "
+                               "using riskier RPCRDMA_ALLPHYSICAL\n",
+                               __func__);
+                       memreg = RPCRDMA_ALLPHYSICAL;
+#else
+                       dprintk("RPC:       %s: MTHCAFMR registration "
+                               "specified but not supported by adapter, "
+                               "using slower RPCRDMA_REGISTER\n",
+                               __func__);
+                       memreg = RPCRDMA_REGISTER;
+#endif
+               }
+               break;
+       case RPCRDMA_FRMR:
+               /* Requires both frmr reg and local dma lkey */
+               if ((devattr.device_cap_flags &
+                    (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) !=
+                   (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) {
+#if RPCRDMA_PERSISTENT_REGISTRATION
+                       dprintk("RPC:       %s: FRMR registration "
+                               "specified but not supported by adapter, "
+                               "using riskier RPCRDMA_ALLPHYSICAL\n",
+                               __func__);
+                       memreg = RPCRDMA_ALLPHYSICAL;
+#else
+                       dprintk("RPC:       %s: FRMR registration "
+                               "specified but not supported by adapter, "
+                               "using slower RPCRDMA_REGISTER\n",
+                               __func__);
+                       memreg = RPCRDMA_REGISTER;
+#endif
+               }
+               break;
+       }
+
        /*
         * Optionally obtain an underlying physical identity mapping in
         * order to do a memory window-based bind. This base registration
@@ -450,22 +540,28 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
         * revoked after the corresponding completion similar to a storage
         * adapter.
         */
-       if (memreg > RPCRDMA_REGISTER) {
-               int mem_priv = IB_ACCESS_LOCAL_WRITE;
-               switch (memreg) {
+       switch (memreg) {
+       case RPCRDMA_BOUNCEBUFFERS:
+       case RPCRDMA_REGISTER:
+       case RPCRDMA_FRMR:
+               break;
 #if RPCRDMA_PERSISTENT_REGISTRATION
-               case RPCRDMA_ALLPHYSICAL:
-                       mem_priv |= IB_ACCESS_REMOTE_WRITE;
-                       mem_priv |= IB_ACCESS_REMOTE_READ;
-                       break;
+       case RPCRDMA_ALLPHYSICAL:
+               mem_priv = IB_ACCESS_LOCAL_WRITE |
+                               IB_ACCESS_REMOTE_WRITE |
+                               IB_ACCESS_REMOTE_READ;
+               goto register_setup;
 #endif
-               case RPCRDMA_MEMWINDOWS_ASYNC:
-               case RPCRDMA_MEMWINDOWS:
-                       mem_priv |= IB_ACCESS_MW_BIND;
-                       break;
-               default:
+       case RPCRDMA_MEMWINDOWS_ASYNC:
+       case RPCRDMA_MEMWINDOWS:
+               mem_priv = IB_ACCESS_LOCAL_WRITE |
+                               IB_ACCESS_MW_BIND;
+               goto register_setup;
+       case RPCRDMA_MTHCAFMR:
+               if (ia->ri_have_dma_lkey)
                        break;
-               }
+               mem_priv = IB_ACCESS_LOCAL_WRITE;
+       register_setup:
                ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv);
                if (IS_ERR(ia->ri_bind_mem)) {
                        printk(KERN_ALERT "%s: ib_get_dma_mr for "
@@ -475,7 +571,15 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
                        memreg = RPCRDMA_REGISTER;
                        ia->ri_bind_mem = NULL;
                }
+               break;
+       default:
+               printk(KERN_ERR "%s: invalid memory registration mode %d\n",
+                               __func__, memreg);
+               rc = -EINVAL;
+               goto out2;
        }
+       dprintk("RPC:       %s: memory registration strategy is %d\n",
+               __func__, memreg);
 
        /* Else will do memory reg/dereg for each chunk */
        ia->ri_memreg_strategy = memreg;
@@ -483,6 +587,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
        return 0;
 out2:
        rdma_destroy_id(ia->ri_id);
+       ia->ri_id = NULL;
 out1:
        return rc;
 }
@@ -503,15 +608,17 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
                dprintk("RPC:       %s: ib_dereg_mr returned %i\n",
                        __func__, rc);
        }
-       if (ia->ri_id != NULL && !IS_ERR(ia->ri_id) && ia->ri_id->qp)
-               rdma_destroy_qp(ia->ri_id);
+       if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) {
+               if (ia->ri_id->qp)
+                       rdma_destroy_qp(ia->ri_id);
+               rdma_destroy_id(ia->ri_id);
+               ia->ri_id = NULL;
+       }
        if (ia->ri_pd != NULL && !IS_ERR(ia->ri_pd)) {
                rc = ib_dealloc_pd(ia->ri_pd);
                dprintk("RPC:       %s: ib_dealloc_pd returned %i\n",
                        __func__, rc);
        }
-       if (ia->ri_id != NULL && !IS_ERR(ia->ri_id))
-               rdma_destroy_id(ia->ri_id);
 }
 
 /*
@@ -541,6 +648,12 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
        ep->rep_attr.srq = NULL;
        ep->rep_attr.cap.max_send_wr = cdata->max_requests;
        switch (ia->ri_memreg_strategy) {
+       case RPCRDMA_FRMR:
+               /* Add room for frmr register and invalidate WRs */
+               ep->rep_attr.cap.max_send_wr *= 3;
+               if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr)
+                       return -EINVAL;
+               break;
        case RPCRDMA_MEMWINDOWS_ASYNC:
        case RPCRDMA_MEMWINDOWS:
                /* Add room for mw_binds+unbinds - overkill! */
@@ -617,29 +730,13 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
        ep->rep_remote_cma.private_data_len = 0;
 
        /* Client offers RDMA Read but does not initiate */
-       switch (ia->ri_memreg_strategy) {
-       case RPCRDMA_BOUNCEBUFFERS:
+       ep->rep_remote_cma.initiator_depth = 0;
+       if (ia->ri_memreg_strategy == RPCRDMA_BOUNCEBUFFERS)
                ep->rep_remote_cma.responder_resources = 0;
-               break;
-       case RPCRDMA_MTHCAFMR:
-       case RPCRDMA_REGISTER:
-               ep->rep_remote_cma.responder_resources = cdata->max_requests *
-                               (RPCRDMA_MAX_DATA_SEGS / 8);
-               break;
-       case RPCRDMA_MEMWINDOWS:
-       case RPCRDMA_MEMWINDOWS_ASYNC:
-#if RPCRDMA_PERSISTENT_REGISTRATION
-       case RPCRDMA_ALLPHYSICAL:
-#endif
-               ep->rep_remote_cma.responder_resources = cdata->max_requests *
-                               (RPCRDMA_MAX_DATA_SEGS / 2);
-               break;
-       default:
-               break;
-       }
-       if (ep->rep_remote_cma.responder_resources > devattr.max_qp_rd_atom)
+       else if (devattr.max_qp_rd_atom > 32)   /* arbitrary but <= 255 */
+               ep->rep_remote_cma.responder_resources = 32;
+       else
                ep->rep_remote_cma.responder_resources = devattr.max_qp_rd_atom;
-       ep->rep_remote_cma.initiator_depth = 0;
 
        ep->rep_remote_cma.retry_count = 7;
        ep->rep_remote_cma.flow_control = 0;
@@ -679,21 +776,16 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
                if (rc)
                        dprintk("RPC:       %s: rpcrdma_ep_disconnect"
                                " returned %i\n", __func__, rc);
+               rdma_destroy_qp(ia->ri_id);
+               ia->ri_id->qp = NULL;
        }
 
-       ep->rep_func = NULL;
-
        /* padding - could be done in rpcrdma_buffer_destroy... */
        if (ep->rep_pad_mr) {
                rpcrdma_deregister_internal(ia, ep->rep_pad_mr, &ep->rep_pad);
                ep->rep_pad_mr = NULL;
        }
 
-       if (ia->ri_id->qp) {
-               rdma_destroy_qp(ia->ri_id);
-               ia->ri_id->qp = NULL;
-       }
-
        rpcrdma_clean_cq(ep->rep_cq);
        rc = ib_destroy_cq(ep->rep_cq);
        if (rc)
@@ -712,9 +804,8 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
        struct rdma_cm_id *id;
        int rc = 0;
        int retry_count = 0;
-       int reconnect = (ep->rep_connected != 0);
 
-       if (reconnect) {
+       if (ep->rep_connected != 0) {
                struct rpcrdma_xprt *xprt;
 retry:
                rc = rpcrdma_ep_disconnect(ep, ia);
@@ -745,6 +836,7 @@ retry:
                        goto out;
                }
                /* END TEMP */
+               rdma_destroy_qp(ia->ri_id);
                rdma_destroy_id(ia->ri_id);
                ia->ri_id = id;
        }
@@ -769,14 +861,6 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) {
        }
 }
 
-       /* Theoretically a client initiator_depth > 0 is not needed,
-        * but many peers fail to complete the connection unless they
-        * == responder_resources! */
-       if (ep->rep_remote_cma.initiator_depth !=
-                               ep->rep_remote_cma.responder_resources)
-               ep->rep_remote_cma.initiator_depth =
-                       ep->rep_remote_cma.responder_resources;
-
        ep->rep_connected = 0;
 
        rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma);
@@ -786,9 +870,6 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) {
                goto out;
        }
 
-       if (reconnect)
-               return 0;
-
        wait_event_interruptible(ep->rep_connect_wait, ep->rep_connected != 0);
 
        /*
@@ -805,14 +886,16 @@ if (strnicmp(ia->ri_id->device->dma_device->bus->name, "pci", 3) == 0) {
        if (ep->rep_connected <= 0) {
                /* Sometimes, the only way to reliably connect to remote
                 * CMs is to use same nonzero values for ORD and IRD. */
-               ep->rep_remote_cma.initiator_depth =
-                                       ep->rep_remote_cma.responder_resources;
-               if (ep->rep_remote_cma.initiator_depth == 0)
-                       ++ep->rep_remote_cma.initiator_depth;
-               if (ep->rep_remote_cma.responder_resources == 0)
-                       ++ep->rep_remote_cma.responder_resources;
-               if (retry_count++ == 0)
+               if (retry_count++ <= RDMA_CONNECT_RETRY_MAX + 1 &&
+                   (ep->rep_remote_cma.responder_resources == 0 ||
+                    ep->rep_remote_cma.initiator_depth !=
+                               ep->rep_remote_cma.responder_resources)) {
+                       if (ep->rep_remote_cma.responder_resources == 0)
+                               ep->rep_remote_cma.responder_resources = 1;
+                       ep->rep_remote_cma.initiator_depth =
+                               ep->rep_remote_cma.responder_resources;
                        goto retry;
+               }
                rc = ep->rep_connected;
        } else {
                dprintk("RPC:       %s: connected\n", __func__);
@@ -863,6 +946,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
        char *p;
        size_t len;
        int i, rc;
+       struct rpcrdma_mw *r;
 
        buf->rb_max_requests = cdata->max_requests;
        spin_lock_init(&buf->rb_lock);
@@ -873,7 +957,7 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
         *   2.  arrays of struct rpcrdma_req to fill in pointers
         *   3.  array of struct rpcrdma_rep for replies
         *   4.  padding, if any
-        *   5.  mw's, if any
+        *   5.  mw's, fmr's or frmr's, if any
         * Send/recv buffers in req/rep need to be registered
         */
 
@@ -881,6 +965,10 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
                (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *));
        len += cdata->padding;
        switch (ia->ri_memreg_strategy) {
+       case RPCRDMA_FRMR:
+               len += buf->rb_max_requests * RPCRDMA_MAX_SEGS *
+                               sizeof(struct rpcrdma_mw);
+               break;
        case RPCRDMA_MTHCAFMR:
                /* TBD we are perhaps overallocating here */
                len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS *
@@ -927,15 +1015,37 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
         * and also reduce unbind-to-bind collision.
         */
        INIT_LIST_HEAD(&buf->rb_mws);
+       r = (struct rpcrdma_mw *)p;
        switch (ia->ri_memreg_strategy) {
+       case RPCRDMA_FRMR:
+               for (i = buf->rb_max_requests * RPCRDMA_MAX_SEGS; i; i--) {
+                       r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd,
+                                                        RPCRDMA_MAX_SEGS);
+                       if (IS_ERR(r->r.frmr.fr_mr)) {
+                               rc = PTR_ERR(r->r.frmr.fr_mr);
+                               dprintk("RPC:       %s: ib_alloc_fast_reg_mr"
+                                       " failed %i\n", __func__, rc);
+                               goto out;
+                       }
+                       r->r.frmr.fr_pgl =
+                               ib_alloc_fast_reg_page_list(ia->ri_id->device,
+                                                           RPCRDMA_MAX_SEGS);
+                       if (IS_ERR(r->r.frmr.fr_pgl)) {
+                               rc = PTR_ERR(r->r.frmr.fr_pgl);
+                               dprintk("RPC:       %s: "
+                                       "ib_alloc_fast_reg_page_list "
+                                       "failed %i\n", __func__, rc);
+                               goto out;
+                       }
+                       list_add(&r->mw_list, &buf->rb_mws);
+                       ++r;
+               }
+               break;
        case RPCRDMA_MTHCAFMR:
-               {
-               struct rpcrdma_mw *r = (struct rpcrdma_mw *)p;
-               struct ib_fmr_attr fa = {
-                       RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT
-               };
                /* TBD we are perhaps overallocating here */
                for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) {
+                       static struct ib_fmr_attr fa =
+                               { RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT };
                        r->r.fmr = ib_alloc_fmr(ia->ri_pd,
                                IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ,
                                &fa);
@@ -948,12 +1058,9 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
                        list_add(&r->mw_list, &buf->rb_mws);
                        ++r;
                }
-               }
                break;
        case RPCRDMA_MEMWINDOWS_ASYNC:
        case RPCRDMA_MEMWINDOWS:
-               {
-               struct rpcrdma_mw *r = (struct rpcrdma_mw *)p;
                /* Allocate one extra request's worth, for full cycling */
                for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) {
                        r->r.mw = ib_alloc_mw(ia->ri_pd);
@@ -966,7 +1073,6 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep,
                        list_add(&r->mw_list, &buf->rb_mws);
                        ++r;
                }
-               }
                break;
        default:
                break;
@@ -1046,6 +1152,7 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
 {
        int rc, i;
        struct rpcrdma_ia *ia = rdmab_to_ia(buf);
+       struct rpcrdma_mw *r;
 
        /* clean up in reverse order from create
         *   1.  recv mr memory (mr free, then kfree)
@@ -1065,11 +1172,19 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
                }
                if (buf->rb_send_bufs && buf->rb_send_bufs[i]) {
                        while (!list_empty(&buf->rb_mws)) {
-                               struct rpcrdma_mw *r;
                                r = list_entry(buf->rb_mws.next,
                                        struct rpcrdma_mw, mw_list);
                                list_del(&r->mw_list);
                                switch (ia->ri_memreg_strategy) {
+                               case RPCRDMA_FRMR:
+                                       rc = ib_dereg_mr(r->r.frmr.fr_mr);
+                                       if (rc)
+                                               dprintk("RPC:       %s:"
+                                                       " ib_dereg_mr"
+                                                       " failed %i\n",
+                                                       __func__, rc);
+                                       ib_free_fast_reg_page_list(r->r.frmr.fr_pgl);
+                                       break;
                                case RPCRDMA_MTHCAFMR:
                                        rc = ib_dealloc_fmr(r->r.fmr);
                                        if (rc)
@@ -1115,6 +1230,8 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
 {
        struct rpcrdma_req *req;
        unsigned long flags;
+       int i;
+       struct rpcrdma_mw *r;
 
        spin_lock_irqsave(&buffers->rb_lock, flags);
        if (buffers->rb_send_index == buffers->rb_max_requests) {
@@ -1135,9 +1252,8 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
        }
        buffers->rb_send_bufs[buffers->rb_send_index++] = NULL;
        if (!list_empty(&buffers->rb_mws)) {
-               int i = RPCRDMA_MAX_SEGS - 1;
+               i = RPCRDMA_MAX_SEGS - 1;
                do {
-                       struct rpcrdma_mw *r;
                        r = list_entry(buffers->rb_mws.next,
                                        struct rpcrdma_mw, mw_list);
                        list_del(&r->mw_list);
@@ -1171,6 +1287,7 @@ rpcrdma_buffer_put(struct rpcrdma_req *req)
                req->rl_reply = NULL;
        }
        switch (ia->ri_memreg_strategy) {
+       case RPCRDMA_FRMR:
        case RPCRDMA_MTHCAFMR:
        case RPCRDMA_MEMWINDOWS_ASYNC:
        case RPCRDMA_MEMWINDOWS:
@@ -1252,7 +1369,11 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len,
                        va, len, DMA_BIDIRECTIONAL);
        iov->length = len;
 
-       if (ia->ri_bind_mem != NULL) {
+       if (ia->ri_have_dma_lkey) {
+               *mrp = NULL;
+               iov->lkey = ia->ri_dma_lkey;
+               return 0;
+       } else if (ia->ri_bind_mem != NULL) {
                *mrp = NULL;
                iov->lkey = ia->ri_bind_mem->lkey;
                return 0;
@@ -1329,15 +1450,292 @@ rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg)
                                seg->mr_dma, seg->mr_dmalen, seg->mr_dir);
 }
 
+static int
+rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
+                       int *nsegs, int writing, struct rpcrdma_ia *ia,
+                       struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct ib_send_wr frmr_wr, *bad_wr;
+       u8 key;
+       int len, pageoff;
+       int i, rc;
+
+       pageoff = offset_in_page(seg1->mr_offset);
+       seg1->mr_offset -= pageoff;     /* start of page */
+       seg1->mr_len += pageoff;
+       len = -pageoff;
+       if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
+               *nsegs = RPCRDMA_MAX_DATA_SEGS;
+       for (i = 0; i < *nsegs;) {
+               rpcrdma_map_one(ia, seg, writing);
+               seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma;
+               len += seg->mr_len;
+               ++seg;
+               ++i;
+               /* Check for holes */
+               if ((i < *nsegs && offset_in_page(seg->mr_offset)) ||
+                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
+                       break;
+       }
+       dprintk("RPC:       %s: Using frmr %p to map %d segments\n",
+               __func__, seg1->mr_chunk.rl_mw, i);
+
+       /* Bump the key */
+       key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF);
+       ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key);
+
+       /* Prepare FRMR WR */
+       memset(&frmr_wr, 0, sizeof frmr_wr);
+       frmr_wr.opcode = IB_WR_FAST_REG_MR;
+       frmr_wr.send_flags = 0;                 /* unsignaled */
+       frmr_wr.wr.fast_reg.iova_start = (unsigned long)seg1->mr_dma;
+       frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl;
+       frmr_wr.wr.fast_reg.page_list_len = i;
+       frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
+       frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT;
+       frmr_wr.wr.fast_reg.access_flags = (writing ?
+                               IB_ACCESS_REMOTE_WRITE : IB_ACCESS_REMOTE_READ);
+       frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
+       DECR_CQCOUNT(&r_xprt->rx_ep);
+
+       rc = ib_post_send(ia->ri_id->qp, &frmr_wr, &bad_wr);
+
+       if (rc) {
+               dprintk("RPC:       %s: failed ib_post_send for register,"
+                       " status %i\n", __func__, rc);
+               while (i--)
+                       rpcrdma_unmap_one(ia, --seg);
+       } else {
+               seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
+               seg1->mr_base = seg1->mr_dma + pageoff;
+               seg1->mr_nsegs = i;
+               seg1->mr_len = len;
+       }
+       *nsegs = i;
+       return rc;
+}
+
+static int
+rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg,
+                       struct rpcrdma_ia *ia, struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct ib_send_wr invalidate_wr, *bad_wr;
+       int rc;
+
+       while (seg1->mr_nsegs--)
+               rpcrdma_unmap_one(ia, seg++);
+
+       memset(&invalidate_wr, 0, sizeof invalidate_wr);
+       invalidate_wr.opcode = IB_WR_LOCAL_INV;
+       invalidate_wr.send_flags = 0;                   /* unsignaled */
+       invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
+       DECR_CQCOUNT(&r_xprt->rx_ep);
+
+       rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr);
+       if (rc)
+               dprintk("RPC:       %s: failed ib_post_send for invalidate,"
+                       " status %i\n", __func__, rc);
+       return rc;
+}
+
+static int
+rpcrdma_register_fmr_external(struct rpcrdma_mr_seg *seg,
+                       int *nsegs, int writing, struct rpcrdma_ia *ia)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       u64 physaddrs[RPCRDMA_MAX_DATA_SEGS];
+       int len, pageoff, i, rc;
+
+       pageoff = offset_in_page(seg1->mr_offset);
+       seg1->mr_offset -= pageoff;     /* start of page */
+       seg1->mr_len += pageoff;
+       len = -pageoff;
+       if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
+               *nsegs = RPCRDMA_MAX_DATA_SEGS;
+       for (i = 0; i < *nsegs;) {
+               rpcrdma_map_one(ia, seg, writing);
+               physaddrs[i] = seg->mr_dma;
+               len += seg->mr_len;
+               ++seg;
+               ++i;
+               /* Check for holes */
+               if ((i < *nsegs && offset_in_page(seg->mr_offset)) ||
+                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
+                       break;
+       }
+       rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr,
+                               physaddrs, i, seg1->mr_dma);
+       if (rc) {
+               dprintk("RPC:       %s: failed ib_map_phys_fmr "
+                       "%u@0x%llx+%i (%d)... status %i\n", __func__,
+                       len, (unsigned long long)seg1->mr_dma,
+                       pageoff, i, rc);
+               while (i--)
+                       rpcrdma_unmap_one(ia, --seg);
+       } else {
+               seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey;
+               seg1->mr_base = seg1->mr_dma + pageoff;
+               seg1->mr_nsegs = i;
+               seg1->mr_len = len;
+       }
+       *nsegs = i;
+       return rc;
+}
+
+static int
+rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg,
+                       struct rpcrdma_ia *ia)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       LIST_HEAD(l);
+       int rc;
+
+       list_add(&seg1->mr_chunk.rl_mw->r.fmr->list, &l);
+       rc = ib_unmap_fmr(&l);
+       while (seg1->mr_nsegs--)
+               rpcrdma_unmap_one(ia, seg++);
+       if (rc)
+               dprintk("RPC:       %s: failed ib_unmap_fmr,"
+                       " status %i\n", __func__, rc);
+       return rc;
+}
+
+static int
+rpcrdma_register_memwin_external(struct rpcrdma_mr_seg *seg,
+                       int *nsegs, int writing, struct rpcrdma_ia *ia,
+                       struct rpcrdma_xprt *r_xprt)
+{
+       int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE :
+                                 IB_ACCESS_REMOTE_READ);
+       struct ib_mw_bind param;
+       int rc;
+
+       *nsegs = 1;
+       rpcrdma_map_one(ia, seg, writing);
+       param.mr = ia->ri_bind_mem;
+       param.wr_id = 0ULL;     /* no send cookie */
+       param.addr = seg->mr_dma;
+       param.length = seg->mr_len;
+       param.send_flags = 0;
+       param.mw_access_flags = mem_priv;
+
+       DECR_CQCOUNT(&r_xprt->rx_ep);
+       rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, &param);
+       if (rc) {
+               dprintk("RPC:       %s: failed ib_bind_mw "
+                       "%u@0x%llx status %i\n",
+                       __func__, seg->mr_len,
+                       (unsigned long long)seg->mr_dma, rc);
+               rpcrdma_unmap_one(ia, seg);
+       } else {
+               seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey;
+               seg->mr_base = param.addr;
+               seg->mr_nsegs = 1;
+       }
+       return rc;
+}
+
+static int
+rpcrdma_deregister_memwin_external(struct rpcrdma_mr_seg *seg,
+                       struct rpcrdma_ia *ia,
+                       struct rpcrdma_xprt *r_xprt, void **r)
+{
+       struct ib_mw_bind param;
+       LIST_HEAD(l);
+       int rc;
+
+       BUG_ON(seg->mr_nsegs != 1);
+       param.mr = ia->ri_bind_mem;
+       param.addr = 0ULL;      /* unbind */
+       param.length = 0;
+       param.mw_access_flags = 0;
+       if (*r) {
+               param.wr_id = (u64) (unsigned long) *r;
+               param.send_flags = IB_SEND_SIGNALED;
+               INIT_CQCOUNT(&r_xprt->rx_ep);
+       } else {
+               param.wr_id = 0ULL;
+               param.send_flags = 0;
+               DECR_CQCOUNT(&r_xprt->rx_ep);
+       }
+       rc = ib_bind_mw(ia->ri_id->qp, seg->mr_chunk.rl_mw->r.mw, &param);
+       rpcrdma_unmap_one(ia, seg);
+       if (rc)
+               dprintk("RPC:       %s: failed ib_(un)bind_mw,"
+                       " status %i\n", __func__, rc);
+       else
+               *r = NULL;      /* will upcall on completion */
+       return rc;
+}
+
+static int
+rpcrdma_register_default_external(struct rpcrdma_mr_seg *seg,
+                       int *nsegs, int writing, struct rpcrdma_ia *ia)
+{
+       int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE :
+                                 IB_ACCESS_REMOTE_READ);
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS];
+       int len, i, rc = 0;
+
+       if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
+               *nsegs = RPCRDMA_MAX_DATA_SEGS;
+       for (len = 0, i = 0; i < *nsegs;) {
+               rpcrdma_map_one(ia, seg, writing);
+               ipb[i].addr = seg->mr_dma;
+               ipb[i].size = seg->mr_len;
+               len += seg->mr_len;
+               ++seg;
+               ++i;
+               /* Check for holes */
+               if ((i < *nsegs && offset_in_page(seg->mr_offset)) ||
+                   offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len))
+                       break;
+       }
+       seg1->mr_base = seg1->mr_dma;
+       seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd,
+                               ipb, i, mem_priv, &seg1->mr_base);
+       if (IS_ERR(seg1->mr_chunk.rl_mr)) {
+               rc = PTR_ERR(seg1->mr_chunk.rl_mr);
+               dprintk("RPC:       %s: failed ib_reg_phys_mr "
+                       "%u@0x%llx (%d)... status %i\n",
+                       __func__, len,
+                       (unsigned long long)seg1->mr_dma, i, rc);
+               while (i--)
+                       rpcrdma_unmap_one(ia, --seg);
+       } else {
+               seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey;
+               seg1->mr_nsegs = i;
+               seg1->mr_len = len;
+       }
+       *nsegs = i;
+       return rc;
+}
+
+static int
+rpcrdma_deregister_default_external(struct rpcrdma_mr_seg *seg,
+                       struct rpcrdma_ia *ia)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       int rc;
+
+       rc = ib_dereg_mr(seg1->mr_chunk.rl_mr);
+       seg1->mr_chunk.rl_mr = NULL;
+       while (seg1->mr_nsegs--)
+               rpcrdma_unmap_one(ia, seg++);
+       if (rc)
+               dprintk("RPC:       %s: failed ib_dereg_mr,"
+                       " status %i\n", __func__, rc);
+       return rc;
+}
+
 int
 rpcrdma_register_external(struct rpcrdma_mr_seg *seg,
                        int nsegs, int writing, struct rpcrdma_xprt *r_xprt)
 {
        struct rpcrdma_ia *ia = &r_xprt->rx_ia;
-       int mem_priv = (writing ? IB_ACCESS_REMOTE_WRITE :
-                                 IB_ACCESS_REMOTE_READ);
-       struct rpcrdma_mr_seg *seg1 = seg;
-       int i;
        int rc = 0;
 
        switch (ia->ri_memreg_strategy) {
@@ -1352,114 +1750,25 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg,
                break;
 #endif
 
-       /* Registration using fast memory registration */
+       /* Registration using frmr registration */
+       case RPCRDMA_FRMR:
+               rc = rpcrdma_register_frmr_external(seg, &nsegs, writing, ia, r_xprt);
+               break;
+
+       /* Registration using fmr memory registration */
        case RPCRDMA_MTHCAFMR:
-               {
-               u64 physaddrs[RPCRDMA_MAX_DATA_SEGS];
-               int len, pageoff = offset_in_page(seg->mr_offset);
-               seg1->mr_offset -= pageoff;     /* start of page */
-               seg1->mr_len += pageoff;
-               len = -pageoff;
-               if (nsegs > RPCRDMA_MAX_DATA_SEGS)
-                       nsegs = RPCRDMA_MAX_DATA_SEGS;
-               for (i = 0; i < nsegs;) {
-                       rpcrdma_map_one(ia, seg, writing);
-                       physaddrs[i] = seg->mr_dma;
-                       len += seg->mr_len;
-                       ++seg;
-                       ++i;
-                       /* Check for holes */
-                       if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
-                           offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len))
-                               break;
-               }
-               nsegs = i;
-               rc = ib_map_phys_fmr(seg1->mr_chunk.rl_mw->r.fmr,
-                                       physaddrs, nsegs, seg1->mr_dma);
-               if (rc) {
-                       dprintk("RPC:       %s: failed ib_map_phys_fmr "
-                               "%u@0x%llx+%i (%d)... status %i\n", __func__,
-                               len, (unsigned long long)seg1->mr_dma,
-                               pageoff, nsegs, rc);
-                       while (nsegs--)
-                               rpcrdma_unmap_one(ia, --seg);
-               } else {
-                       seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.fmr->rkey;
-                       seg1->mr_base = seg1->mr_dma + pageoff;
-                       seg1->mr_nsegs = nsegs;
-                       seg1->mr_len = len;
-               }
-               }
+               rc = rpcrdma_register_fmr_external(seg, &nsegs, writing, ia);
                break;
 
        /* Registration using memory windows */
        case RPCRDMA_MEMWINDOWS_ASYNC:
        case RPCRDMA_MEMWINDOWS:
-               {
-               struct ib_mw_bind param;
-               rpcrdma_map_one(ia, seg, writing);
-               param.mr = ia->ri_bind_mem;
-               param.wr_id = 0ULL;     /* no send cookie */
-               param.addr = seg->mr_dma;
-               param.length = seg->mr_len;
-               param.send_flags = 0;
-               param.mw_access_flags = mem_priv;
-
-               DECR_CQCOUNT(&r_xprt->rx_ep);
-               rc = ib_bind_mw(ia->ri_id->qp,
-                                       seg->mr_chunk.rl_mw->r.mw, &param);
-               if (rc) {
-                       dprintk("RPC:       %s: failed ib_bind_mw "
-                               "%u@0x%llx status %i\n",
-                               __func__, seg->mr_len,
-                               (unsigned long long)seg->mr_dma, rc);
-                       rpcrdma_unmap_one(ia, seg);
-               } else {
-                       seg->mr_rkey = seg->mr_chunk.rl_mw->r.mw->rkey;
-                       seg->mr_base = param.addr;
-                       seg->mr_nsegs = 1;
-                       nsegs = 1;
-               }
-               }
+               rc = rpcrdma_register_memwin_external(seg, &nsegs, writing, ia, r_xprt);
                break;
 
        /* Default registration each time */
        default:
-               {
-               struct ib_phys_buf ipb[RPCRDMA_MAX_DATA_SEGS];
-               int len = 0;
-               if (nsegs > RPCRDMA_MAX_DATA_SEGS)
-                       nsegs = RPCRDMA_MAX_DATA_SEGS;
-               for (i = 0; i < nsegs;) {
-                       rpcrdma_map_one(ia, seg, writing);
-                       ipb[i].addr = seg->mr_dma;
-                       ipb[i].size = seg->mr_len;
-                       len += seg->mr_len;
-                       ++seg;
-                       ++i;
-                       /* Check for holes */
-                       if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
-                           offset_in_page((seg-1)->mr_offset+(seg-1)->mr_len))
-                               break;
-               }
-               nsegs = i;
-               seg1->mr_base = seg1->mr_dma;
-               seg1->mr_chunk.rl_mr = ib_reg_phys_mr(ia->ri_pd,
-                                       ipb, nsegs, mem_priv, &seg1->mr_base);
-               if (IS_ERR(seg1->mr_chunk.rl_mr)) {
-                       rc = PTR_ERR(seg1->mr_chunk.rl_mr);
-                       dprintk("RPC:       %s: failed ib_reg_phys_mr "
-                               "%u@0x%llx (%d)... status %i\n",
-                               __func__, len,
-                               (unsigned long long)seg1->mr_dma, nsegs, rc);
-                       while (nsegs--)
-                               rpcrdma_unmap_one(ia, --seg);
-               } else {
-                       seg1->mr_rkey = seg1->mr_chunk.rl_mr->rkey;
-                       seg1->mr_nsegs = nsegs;
-                       seg1->mr_len = len;
-               }
-               }
+               rc = rpcrdma_register_default_external(seg, &nsegs, writing, ia);
                break;
        }
        if (rc)
@@ -1473,7 +1782,6 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg,
                struct rpcrdma_xprt *r_xprt, void *r)
 {
        struct rpcrdma_ia *ia = &r_xprt->rx_ia;
-       struct rpcrdma_mr_seg *seg1 = seg;
        int nsegs = seg->mr_nsegs, rc;
 
        switch (ia->ri_memreg_strategy) {
@@ -1486,56 +1794,21 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg,
                break;
 #endif
 
+       case RPCRDMA_FRMR:
+               rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt);
+               break;
+
        case RPCRDMA_MTHCAFMR:
-               {
-               LIST_HEAD(l);
-               list_add(&seg->mr_chunk.rl_mw->r.fmr->list, &l);
-               rc = ib_unmap_fmr(&l);
-               while (seg1->mr_nsegs--)
-                       rpcrdma_unmap_one(ia, seg++);
-               }
-               if (rc)
-                       dprintk("RPC:       %s: failed ib_unmap_fmr,"
-                               " status %i\n", __func__, rc);
+               rc = rpcrdma_deregister_fmr_external(seg, ia);
                break;
 
        case RPCRDMA_MEMWINDOWS_ASYNC:
        case RPCRDMA_MEMWINDOWS:
-               {
-               struct ib_mw_bind param;
-               BUG_ON(nsegs != 1);
-               param.mr = ia->ri_bind_mem;
-               param.addr = 0ULL;      /* unbind */
-               param.length = 0;
-               param.mw_access_flags = 0;
-               if (r) {
-                       param.wr_id = (u64) (unsigned long) r;
-                       param.send_flags = IB_SEND_SIGNALED;
-                       INIT_CQCOUNT(&r_xprt->rx_ep);
-               } else {
-                       param.wr_id = 0ULL;
-                       param.send_flags = 0;
-                       DECR_CQCOUNT(&r_xprt->rx_ep);
-               }
-               rc = ib_bind_mw(ia->ri_id->qp,
-                               seg->mr_chunk.rl_mw->r.mw, &param);
-               rpcrdma_unmap_one(ia, seg);
-               }
-               if (rc)
-                       dprintk("RPC:       %s: failed ib_(un)bind_mw,"
-                               " status %i\n", __func__, rc);
-               else
-                       r = NULL;       /* will upcall on completion */
+               rc = rpcrdma_deregister_memwin_external(seg, ia, r_xprt, &r);
                break;
 
        default:
-               rc = ib_dereg_mr(seg1->mr_chunk.rl_mr);
-               seg1->mr_chunk.rl_mr = NULL;
-               while (seg1->mr_nsegs--)
-                       rpcrdma_unmap_one(ia, seg++);
-               if (rc)
-                       dprintk("RPC:       %s: failed ib_dereg_mr,"
-                               " status %i\n", __func__, rc);
+               rc = rpcrdma_deregister_default_external(seg, ia);
                break;
        }
        if (r) {
index 2427822f8bd49edef84e50666a93694246bbdec4..c7a7eba991bc11e592aa541ba39c29fe22eaa9f2 100644 (file)
@@ -51,6 +51,9 @@
 #include <linux/sunrpc/rpc_rdma.h>     /* RPC/RDMA protocol */
 #include <linux/sunrpc/xprtrdma.h>     /* xprt parameters */
 
+#define RDMA_RESOLVE_TIMEOUT   (5000)  /* 5 seconds */
+#define RDMA_CONNECT_RETRY_MAX (2)     /* retries if no listener backlog */
+
 /*
  * Interface Adapter -- one per transport instance
  */
@@ -58,6 +61,8 @@ struct rpcrdma_ia {
        struct rdma_cm_id       *ri_id;
        struct ib_pd            *ri_pd;
        struct ib_mr            *ri_bind_mem;
+       u32                     ri_dma_lkey;
+       int                     ri_have_dma_lkey;
        struct completion       ri_done;
        int                     ri_async_rc;
        enum rpcrdma_memreg     ri_memreg_strategy;
@@ -156,6 +161,10 @@ struct rpcrdma_mr_seg {            /* chunk descriptors */
                        union {
                                struct ib_mw    *mw;
                                struct ib_fmr   *fmr;
+                               struct {
+                                       struct ib_fast_reg_page_list *fr_pgl;
+                                       struct ib_mr *fr_mr;
+                               } frmr;
                        } r;
                        struct list_head mw_list;
                } *rl_mw;
@@ -175,6 +184,7 @@ struct rpcrdma_req {
        size_t          rl_size;        /* actual length of buffer */
        unsigned int    rl_niovs;       /* 0, 2 or 4 */
        unsigned int    rl_nchunks;     /* non-zero if chunks */
+       unsigned int    rl_connect_cookie;      /* retry detection */
        struct rpcrdma_buffer *rl_buffer; /* home base for this structure */
        struct rpcrdma_rep      *rl_reply;/* holder for reply buffer */
        struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */
@@ -198,7 +208,7 @@ struct rpcrdma_buffer {
        atomic_t        rb_credits;     /* most recent server credits */
        unsigned long   rb_cwndscale;   /* cached framework rpc_cwndscale */
        int             rb_max_requests;/* client max requests */
-       struct list_head rb_mws;        /* optional memory windows/fmrs */
+       struct list_head rb_mws;        /* optional memory windows/fmrs/frmrs */
        int             rb_send_index;
        struct rpcrdma_req      **rb_send_bufs;
        int             rb_recv_index;
@@ -273,6 +283,11 @@ struct rpcrdma_xprt {
 #define rpcx_to_rdmax(x) container_of(x, struct rpcrdma_xprt, xprt)
 #define rpcx_to_rdmad(x) (rpcx_to_rdmax(x)->rx_data)
 
+/* Setting this to 0 ensures interoperability with early servers.
+ * Setting this to 1 enhances certain unaligned read/write performance.
+ * Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */
+extern int xprt_rdma_pad_optimize;
+
 /*
  * Interface Adapter calls - xprtrdma/verbs.c
  */
index 4486c59c3aca87d6102a372255246a326b9efdc6..9a288d5eea646e65953bf92b015f2e557d15239e 100644 (file)
@@ -3,8 +3,8 @@
  *
  * Client-side transport implementation for sockets.
  *
- * TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
- * TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ * TCP callback races fixes (C) 1998 Red Hat
+ * TCP send fixes (C) 1998 Red Hat
  * TCP NFS related read + write fixes
  *  (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
  *
index 015606b54d9b28325aad62a71ea4fc160b686cd8..c647aab8d418c508c9088789c847fae59745c049 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * NET4:       Implementation of BSD Unix domain sockets.
  *
- * Authors:    Alan Cox, <alan.cox@linux.org>
+ * Authors:    Alan Cox, <alan@lxorguk.ukuu.org.uk>
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
index 5cadbeb76a1430ca30d0b1faff578f83807057e5..5031db7b275b734b46870089765420c75c136d10 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/debugfs.h>
 #include <linux/notifier.h>
 #include <linux/device.h>
-#include <linux/list.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include <net/wireless.h>
@@ -185,7 +184,8 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
        if (result)
                goto out_unlock;
 
-       if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
+       if (rdev->wiphy.debugfsdir &&
+           !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
                            rdev->wiphy.debugfsdir,
                            rdev->wiphy.debugfsdir->d_parent,
                            newname))
@@ -318,6 +318,8 @@ int wiphy_register(struct wiphy *wiphy)
        drv->wiphy.debugfsdir =
                debugfs_create_dir(wiphy_name(&drv->wiphy),
                                   ieee80211_debugfs_dir);
+       if (IS_ERR(drv->wiphy.debugfsdir))
+               drv->wiphy.debugfsdir = NULL;
 
        res = 0;
 out_unlock:
index ea48b82a37076123c09c04346f796bc8e68da5db..b4ca38a2115883294c49255769953519fb1c1ca4 100644 (file)
@@ -96,6 +96,14 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
 modname_flags  = $(if $(filter 1,$(words $(modname))),\
                  -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
 
+#hash values
+ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
+debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
+              -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
+else
+debug_flags =
+endif
+
 orig_c_flags   = $(KBUILD_CFLAGS) $(ccflags-y) $(CFLAGS_$(basetarget).o)
 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
 _a_flags       = $(KBUILD_AFLAGS) $(asflags-y) $(AFLAGS_$(basetarget).o)
@@ -121,7 +129,8 @@ endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
                 $(__c_flags) $(modkern_cflags) \
-                -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
+                -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
+                 $(debug_flags)
 
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) \
                 $(__a_flags) $(modkern_aflags)
index 4c324a1f1e0efb8668b4d64e05b56e8e0f64f25b..09559951df1208e00f5a51efa1208145a87efe14 100644 (file)
@@ -9,7 +9,7 @@
 # fixdep:       Used to generate dependency information during build process
 # docproc:      Used in Documentation/DocBook
 
-hostprogs-y    := fixdep docproc
+hostprogs-y    := fixdep docproc hash
 always         := $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
new file mode 100644 (file)
index 0000000..3299ad7
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DYNAMIC_DEBUG_HASH_BITS 6
+
+static const char *program;
+
+static void usage(void)
+{
+       printf("Usage: %s <djb2|r5> <modname>\n", program);
+       exit(1);
+}
+
+/* djb2 hashing algorithm by Dan Bernstein. From:
+ * http://www.cse.yorku.ca/~oz/hash.html
+ */
+
+unsigned int djb2_hash(char *str)
+{
+       unsigned long hash = 5381;
+       int c;
+
+       c = *str;
+       while (c) {
+               hash = ((hash << 5) + hash) + c;
+               c = *++str;
+       }
+       return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
+}
+
+unsigned int r5_hash(char *str)
+{
+       unsigned long hash = 0;
+       int c;
+
+       c = *str;
+       while (c) {
+               hash = (hash + (c << 4) + (c >> 4)) * 11;
+               c = *++str;
+       }
+       return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
+}
+
+int main(int argc, char *argv[])
+{
+       program = argv[0];
+
+       if (argc != 3)
+               usage();
+       if (!strcmp(argv[1], "djb2"))
+               printf("%d\n", djb2_hash(argv[2]));
+       else if (!strcmp(argv[1], "r5"))
+               printf("%d\n", r5_hash(argv[2]));
+       else
+               usage();
+       exit(0);
+}
+
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
new file mode 100644 (file)
index 0000000..2243353
--- /dev/null
@@ -0,0 +1,147 @@
+#!/usr/bin/perl
+
+# Copyright 2008, Intel Corporation
+#
+# This file is part of the Linux kernel
+#
+# This program 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; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program in a file named COPYING; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Authors:
+#      Arjan van de Ven <arjan@linux.intel.com>
+
+
+#
+# This script turns a dmesg output into a SVG graphic that shows which
+# functions take how much time. You can view SVG graphics with various
+# programs, including Inkscape, The Gimp and Firefox.
+#
+#
+# For this script to work, the kernel needs to be compiled with the
+# CONFIG_PRINTK_TIME configuration option enabled, and with
+# "initcall_debug" passed on the kernel command line.
+#
+# usage:
+#      dmesg | perl scripts/bootgraph.pl > output.svg
+#
+
+my @rows;
+my %start, %end, %row;
+my $done = 0;
+my $rowcount = 0;
+my $maxtime = 0;
+my $firsttime = 100;
+my $count = 0;
+while (<>) {
+       my $line = $_;
+       if ($line =~ /([0-9\.]+)\] calling  ([a-zA-Z0-9\_]+)\+/) {
+               my $func = $2;
+               if ($done == 0) {
+                       $start{$func} = $1;
+                       if ($1 < $firsttime) {
+                               $firsttime = $1;
+                       }
+               }
+               $row{$func} = 1;
+               if ($line =~ /\@ ([0-9]+)/) {
+                       my $pid = $1;
+                       if (!defined($rows[$pid])) {
+                               $rowcount = $rowcount + 1;
+                               $rows[$pid] = $rowcount;
+                       }
+                       $row{$func} = $rows[$pid];
+               }
+               $count = $count + 1;
+       }
+
+       if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_]+)\+.*returned/) {
+               if ($done == 0) {
+                       $end{$2} = $1;
+                       $maxtime = $1;
+               }
+       }
+       if ($line =~ /Write protecting the/) {
+               $done = 1;
+       }
+       if ($line =~ /Freeing unused kernel memory/) {
+               $done = 1;
+       }
+}
+
+if ($count == 0) {
+       print "No data found in the dmesg. Make sure that 'printk.time=1' and\n";
+       print "'initcall_debug' are passed on the kernel command line.\n\n";
+       print "Usage: \n";
+       print "      dmesg | perl scripts/bootgraph.pl > output.svg\n\n";
+       exit;
+}
+
+print "<?xml version=\"1.0\" standalone=\"no\"?> \n";
+print "<svg width=\"1000\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n";
+
+my @styles;
+
+$styles[0] = "fill:rgb(0,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[1] = "fill:rgb(0,255,0);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[2] = "fill:rgb(255,0,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[3] = "fill:rgb(255,255,20);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[4] = "fill:rgb(255,0,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[5] = "fill:rgb(0,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[6] = "fill:rgb(0,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[7] = "fill:rgb(0,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[8] = "fill:rgb(255,0,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[9] = "fill:rgb(255,255,128);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[10] = "fill:rgb(255,128,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+$styles[11] = "fill:rgb(128,255,255);fill-opacity:0.5;stroke-width:1;stroke:rgb(0,0,0)";
+
+my $mult = 950.0 / ($maxtime - $firsttime);
+my $threshold = ($maxtime - $firsttime) / 60.0;
+my $stylecounter = 0;
+while (($key,$value) = each %start) {
+       my $duration = $end{$key} - $start{$key};
+
+       if ($duration >= $threshold) {
+               my $s, $s2, $e, $y;
+               $s = ($value - $firsttime) * $mult;
+               $s2 = $s + 6;
+               $e = ($end{$key} - $firsttime) * $mult;
+               $w = $e - $s;
+
+               $y = $row{$key} * 150;
+               $y2 = $y + 4;
+
+               $style = $styles[$stylecounter];
+               $stylecounter = $stylecounter + 1;
+               if ($stylecounter > 11) {
+                       $stylecounter = 0;
+               };
+
+               print "<rect x=\"$s\" width=\"$w\" y=\"$y\" height=\"145\" style=\"$style\"/>\n";
+               print "<text transform=\"translate($s2,$y2) rotate(90)\">$key</text>\n";
+       }
+}
+
+
+# print the time line on top
+my $time = $firsttime;
+my $step = ($maxtime - $firsttime) / 15;
+while ($time < $maxtime) {
+       my $s2 = ($time - $firsttime) * $mult;
+       my $tm = int($time * 100) / 100.0;
+       print "<text transform=\"translate($s2,89) rotate(90)\">$tm</text>\n";
+       $time = $time + $step;
+}
+
+print "</svg>\n";
index bc6779398229757a94a44a4d3ef4a70dbf618a49..e30bac141b21ee1894f62135b8727efa276fe38e 100755 (executable)
@@ -9,7 +9,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.21';
+my $V = '0.24';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -66,6 +66,7 @@ if ($#ARGV < 0) {
 my $dbg_values = 0;
 my $dbg_possible = 0;
 my $dbg_type = 0;
+my $dbg_attr = 0;
 for my $key (keys %debug) {
        eval "\${dbg_$key} = '$debug{$key}';"
 }
@@ -112,7 +113,10 @@ our $Attribute     = qr{
                        const|
                        __read_mostly|
                        __kprobes|
-                       __(?:mem|cpu|dev|)(?:initdata|init)
+                       __(?:mem|cpu|dev|)(?:initdata|init)|
+                       ____cacheline_aligned|
+                       ____cacheline_aligned_in_smp|
+                       ____cacheline_internodealigned_in_smp
                  }x;
 our $Modifier;
 our $Inline    = qr{inline|__always_inline|noinline};
@@ -142,6 +146,11 @@ our $UTF8  = qr {
        |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
 }x;
 
+our $typeTypedefs = qr{(?x:
+       (?:__)?(?:u|s|be|le)(?:\d|\d\d)|
+       atomic_t
+)};
+
 our @typeList = (
        qr{void},
        qr{(?:unsigned\s+)?char},
@@ -155,7 +164,6 @@ our @typeList = (
        qr{float},
        qr{double},
        qr{bool},
-       qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)},
        qr{struct\s+$Ident},
        qr{union\s+$Ident},
        qr{enum\s+$Ident},
@@ -175,6 +183,7 @@ sub build_types {
                        (?:$Modifier\s+|const\s+)*
                        (?:
                                (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
+                               (?:$typeTypedefs\b)|
                                (?:${all}\b)
                        )
                        (?:\s+$Modifier|\s+const)*
@@ -331,7 +340,7 @@ sub sanitise_line {
                        $off++;
                        next;
                }
-               if (substr($line, $off, 2) eq '*/') {
+               if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
                        $sanitise_quote = '';
                        substr($res, $off, 2, "$;$;");
                        $off++;
@@ -404,6 +413,7 @@ sub ctx_statement_block {
                # context.
                if ($off >= $len) {
                        for (; $remain > 0; $line++) {
+                               last if (!defined $lines[$line]);
                                next if ($lines[$line] =~ /^-/);
                                $remain--;
                                $loff = $len;
@@ -669,6 +679,22 @@ sub ctx_has_comment {
        return ($cmt ne '');
 }
 
+sub raw_line {
+       my ($linenr, $cnt) = @_;
+
+       my $offset = $linenr - 1;
+       $cnt++;
+
+       my $line;
+       while ($cnt) {
+               $line = $rawlines[$offset++];
+               next if (defined($line) && $line =~ /^-/);
+               $cnt--;
+       }
+
+       return $line;
+}
+
 sub cat_vet {
        my ($vet) = @_;
        my ($res, $coded);
@@ -782,9 +808,9 @@ sub annotate_values {
                        }
                        $type = 'N';
 
-               } elsif ($cur =~ /^(if|while|typeof|__typeof__|for)\b/o) {
+               } elsif ($cur =~ /^(if|while|for)\b/o) {
                        print "COND($1)\n" if ($dbg_values > 1);
-                       $av_pending = 'N';
+                       $av_pending = 'E';
                        $type = 'N';
 
                } elsif ($cur =~/^(case)/o) {
@@ -792,7 +818,7 @@ sub annotate_values {
                        $av_pend_colon = 'C';
                        $type = 'N';
 
-               } elsif ($cur =~/^(return|else|goto)/o) {
+               } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
                        print "KEYWORD($1)\n" if ($dbg_values > 1);
                        $type = 'N';
 
@@ -858,7 +884,7 @@ sub annotate_values {
                        print "CLOSE($1)\n" if ($dbg_values > 1);
                        $type = 'N';
 
-               } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&(?!\&))/o) {
+               } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
                        my $variant;
 
                        print "OPV($1)\n" if ($dbg_values > 1);
@@ -892,12 +918,22 @@ sub annotate_values {
 sub possible {
        my ($possible, $line) = @_;
 
-       print "CHECK<$possible> ($line)\n" if ($dbg_possible > 1);
-       if ($possible !~ /^(?:$Modifier|$Storage|$Type|DEFINE_\S+)$/ &&
-           $possible ne 'goto' && $possible ne 'return' &&
-           $possible ne 'case' && $possible ne 'else' &&
-           $possible ne 'asm' && $possible ne '__asm__' &&
-           $possible !~ /^(typedef|struct|enum)\b/) {
+       print "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
+       if ($possible !~ /(?:
+               ^(?:
+                       $Modifier|
+                       $Storage|
+                       $Type|
+                       DEFINE_\S+|
+                       goto|
+                       return|
+                       case|
+                       else|
+                       asm|__asm__|
+                       do
+               )$|
+               ^(?:typedef|struct|enum)\b
+           )/x) {
                # Check for modifiers.
                $possible =~ s/\s*$Storage\s*//g;
                $possible =~ s/\s*$Sparse\s*//g;
@@ -915,6 +951,8 @@ sub possible {
                        push(@typeList, $possible);
                }
                build_types();
+       } else {
+               warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
        }
 }
 
@@ -954,6 +992,33 @@ sub CHK {
        }
 }
 
+sub check_absolute_file {
+       my ($absolute, $herecurr) = @_;
+       my $file = $absolute;
+
+       ##print "absolute<$absolute>\n";
+
+       # See if any suffix of this path is a path within the tree.
+       while ($file =~ s@^[^/]*/@@) {
+               if (-f "$root/$file") {
+                       ##print "file<$file>\n";
+                       last;
+               }
+       }
+       if (! -f _)  {
+               return 0;
+       }
+
+       # It is, so see if the prefix is acceptable.
+       my $prefix = $absolute;
+       substr($prefix, -length($file)) = '';
+
+       ##print "prefix<$prefix>\n";
+       if ($prefix ne ".../") {
+               WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr);
+       }
+}
+
 sub process {
        my $filename = shift;
 
@@ -991,6 +1056,7 @@ sub process {
 
        # suppression flags
        my %suppress_ifbraces;
+       my %suppress_whiletrailers;
 
        # Pre-scan the patch sanitizing the lines.
        # Pre-scan the patch looking for any __setup documentation.
@@ -1025,9 +1091,14 @@ sub process {
                        # edge is a close comment then we must be in a comment
                        # at context start.
                        my $edge;
-                       for (my $ln = $linenr + 1; $ln < ($linenr + $realcnt); $ln++) {
-                               next if ($line =~ /^-/);
-                               ($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
+                       my $cnt = $realcnt;
+                       for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
+                               next if (defined $rawlines[$ln - 1] &&
+                                        $rawlines[$ln - 1] =~ /^-/);
+                               $cnt--;
+                               #print "RAW<$rawlines[$ln - 1]>\n";
+                               ($edge) = (defined $rawlines[$ln - 1] &&
+                                       $rawlines[$ln - 1] =~ m@(/\*|\*/)@);
                                last if (defined $edge);
                        }
                        if (defined $edge && $edge eq '*/') {
@@ -1075,6 +1146,7 @@ sub process {
                $linenr++;
 
                my $rawline = $rawlines[$linenr - 1];
+               my $hunk_line = ($realcnt != 0);
 
 #extract the line range in the file after the patch is applied
                if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
@@ -1090,6 +1162,7 @@ sub process {
                        $prev_values = 'E';
 
                        %suppress_ifbraces = ();
+                       %suppress_whiletrailers = ();
                        next;
 
 # track the line number as we move through the hunk, note that
@@ -1125,7 +1198,7 @@ sub process {
                        $realfile = $1;
                        $realfile =~ s@^[^/]*/@@;
 
-                       if ($realfile =~ m@include/asm/@) {
+                       if ($realfile =~ m@^include/asm/@) {
                                ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
                        }
                        next;
@@ -1159,6 +1232,20 @@ sub process {
                                $herecurr) if (!$emitted_corrupt++);
                }
 
+# Check for absolute kernel paths.
+               if ($tree) {
+                       while ($line =~ m{(?:^|\s)(/\S*)}g) {
+                               my $file = $1;
+
+                               if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
+                                   check_absolute_file($1, $herecurr)) {
+                                       #
+                               } else {
+                                       check_absolute_file($file, $herecurr);
+                               }
+                       }
+               }
+
 # UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
                if (($realfile =~ /^$/ || $line =~ /^\+/) &&
                    $rawline !~ m/^$UTF8*$/) {
@@ -1171,11 +1258,8 @@ sub process {
                        ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
                }
 
-#ignore lines being removed
-               if ($line=~/^-/) {next;}
-
-# check we are in a valid source file if not then ignore this hunk
-               next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+# ignore non-hunk lines and lines being removed
+               next if (!$hunk_line || $line =~ /^-/);
 
 #trailing whitespace
                if ($line =~ /^\+.*\015/) {
@@ -1186,6 +1270,10 @@ sub process {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        ERROR("trailing whitespace\n" . $herevet);
                }
+
+# check we are in a valid source file if not then ignore this hunk
+               next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+
 #80 column limit
                if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
                    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
@@ -1200,8 +1288,8 @@ sub process {
                        WARN("adding a line without newline at end of file\n" . $herecurr);
                }
 
-# check we are in a valid source file *.[hc] if not then ignore this hunk
-               next if ($realfile !~ /\.[hc]$/);
+# check we are in a valid source file C or perl if not then ignore this hunk
+               next if ($realfile !~ /\.(h|c|pl)$/);
 
 # at the beginning of a line any tabs must come first and anything
 # more than 8 must use tabs.
@@ -1211,15 +1299,18 @@ sub process {
                        ERROR("code indent should use tabs where possible\n" . $herevet);
                }
 
+# check we are in a valid C source file if not then ignore this hunk
+               next if ($realfile !~ /\.(h|c)$/);
+
 # check for RCS/CVS revision markers
                if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
                        WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
                }
 
 # Check for potential 'bare' types
-               my ($stat, $cond, $line_nr_next, $remain_next);
+               my ($stat, $cond, $line_nr_next, $remain_next, $off_next);
                if ($realcnt && $line =~ /.\s*\S/) {
-                       ($stat, $cond, $line_nr_next, $remain_next) =
+                       ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0);
                        $stat =~ s/\n./\n /g;
                        $cond =~ s/\n./\n /g;
@@ -1240,7 +1331,7 @@ sub process {
                                possible($type, "A:" . $s);
 
                        # definitions in global scope can only start with types
-                       } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/s) {
+                       } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
                                possible($1, "B:" . $s);
                        }
 
@@ -1294,10 +1385,6 @@ sub process {
                                ERROR("switch and case should be at the same indent\n$hereline$err");
                        }
                }
-               if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
-                   $line !~ /\G(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$/g) {
-                       ERROR("trailing statements should be on next line\n" . $herecurr);
-               }
 
 # if/while/etc brace do not go on next line, unless defining a do while loop,
 # or if that brace on the next line is for something else
@@ -1338,6 +1425,91 @@ sub process {
                        }
                }
 
+# Check relative indent for conditionals and blocks.
+               if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+                       my ($s, $c) = ($stat, $cond);
+
+                       substr($s, 0, length($c), '');
+
+                       # Make sure we remove the line prefixes as we have
+                       # none on the first line, and are going to readd them
+                       # where necessary.
+                       $s =~ s/\n./\n/gs;
+
+                       # Find out how long the conditional actually is.
+                       my @newlines = ($c =~ /\n/gs);
+                       my $cond_lines = 1 + $#newlines;
+
+                       # We want to check the first line inside the block
+                       # starting at the end of the conditional, so remove:
+                       #  1) any blank line termination
+                       #  2) any opening brace { on end of the line
+                       #  3) any do (...) {
+                       my $continuation = 0;
+                       my $check = 0;
+                       $s =~ s/^.*\bdo\b//;
+                       $s =~ s/^\s*{//;
+                       if ($s =~ s/^\s*\\//) {
+                               $continuation = 1;
+                       }
+                       if ($s =~ s/^\s*?\n//) {
+                               $check = 1;
+                               $cond_lines++;
+                       }
+
+                       # Also ignore a loop construct at the end of a
+                       # preprocessor statement.
+                       if (($prevline =~ /^.\s*#\s*define\s/ ||
+                           $prevline =~ /\\\s*$/) && $continuation == 0) {
+                               $check = 0;
+                       }
+
+                       my $cond_ptr = -1;
+                       $continuation = 0;
+                       while ($cond_ptr != $cond_lines) {
+                               $cond_ptr = $cond_lines;
+
+                               # If we see an #else/#elif then the code
+                               # is not linear.
+                               if ($s =~ /^\s*\#\s*(?:else|elif)/) {
+                                       $check = 0;
+                               }
+
+                               # Ignore:
+                               #  1) blank lines, they should be at 0,
+                               #  2) preprocessor lines, and
+                               #  3) labels.
+                               if ($continuation ||
+                                   $s =~ /^\s*?\n/ ||
+                                   $s =~ /^\s*#\s*?/ ||
+                                   $s =~ /^\s*$Ident\s*:/) {
+                                       $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
+                                       $s =~ s/^.*?\n//;
+                                       $cond_lines++;
+                               }
+                       }
+
+                       my (undef, $sindent) = line_stats("+" . $s);
+                       my $stat_real = raw_line($linenr, $cond_lines);
+
+                       # Check if either of these lines are modified, else
+                       # this is not this patch's fault.
+                       if (!defined($stat_real) ||
+                           $stat !~ /^\+/ && $stat_real !~ /^\+/) {
+                               $check = 0;
+                       }
+                       if (defined($stat_real) && $cond_lines > 1) {
+                               $stat_real = "[...]\n$stat_real";
+                       }
+
+                       #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
+
+                       if ($check && (($sindent % 8) != 0 ||
+                           ($sindent <= $indent && $s ne ''))) {
+                               WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
+                       }
+               }
+
                # Track the 'values' across context and added lines.
                my $opline = $line; $opline =~ s/^./ /;
                my ($curr_values, $curr_vars) =
@@ -1363,6 +1535,15 @@ sub process {
                        }
                        next;
                }
+# TEST: allow direct testing of the attribute matcher.
+               if ($dbg_attr) {
+                       if ($line =~ /^.\s*$Attribute\s*$/) {
+                               ERROR("TEST: is attr\n" . $herecurr);
+                       } elsif ($dbg_attr > 1 && $line =~ /^.+($Attribute)/) {
+                               ERROR("TEST: is not attr ($1 is)\n". $herecurr);
+                       }
+                       next;
+               }
 
 # check for initialisation to aggregates open brace on the next line
                if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
@@ -1395,13 +1576,14 @@ sub process {
                if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
                    ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
                        my $name = $1;
-                       if (($prevline !~ /^}/) &&
-                          ($prevline !~ /^\+}/) &&
-                          ($prevline !~ /^ }/) &&
-                          ($prevline !~ /^.DECLARE_$Ident\(\Q$name\E\)/) &&
-                          ($prevline !~ /^.LIST_HEAD\(\Q$name\E\)/) &&
-                          ($prevline !~ /^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(/) &&
-                          ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)/)) {
+                       if ($prevline !~ /(?:
+                               ^.}|
+                               ^.DEFINE_$Ident\(\Q$name\E\)|
+                               ^.DECLARE_$Ident\(\Q$name\E\)|
+                               ^.LIST_HEAD\(\Q$name\E\)|
+                               ^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
+                               \b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)
+                           )/x) {
                                WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
                        }
                }
@@ -1422,6 +1604,7 @@ sub process {
                if ($line =~ /\btypedef\s/ &&
                    $line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ &&
                    $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
+                   $line !~ /\b$typeTypedefs\b/ &&
                    $line !~ /\b__bitwise(?:__|)\b/) {
                        WARN("do not add new typedefs\n" . $herecurr);
                }
@@ -1493,11 +1676,13 @@ sub process {
 
 # check for spacing round square brackets; allowed:
 #  1. with a type on the left -- int [] a;
-#  2. at the beginning of a line for slice initialisers -- [0..10] = 5,
+#  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
+#  3. inside a curly brace -- = { [0...10] = 5 }
                while ($line =~ /(.*?\s)\[/g) {
                        my ($where, $prefix) = ($-[1], $1);
                        if ($prefix !~ /$Type\s+$/ &&
-                           ($where != 0 || $prefix !~ /^.\s+$/)) {
+                           ($where != 0 || $prefix !~ /^.\s+$/) &&
+                           $prefix !~ /{\s+$/) {
                                ERROR("space prohibited before open square bracket '['\n" . $herecurr);
                        }
                }
@@ -1632,7 +1817,7 @@ sub process {
                                # unary operator, or a cast
                                } elsif ($op eq '!' || $op eq '~' ||
                                         $opv eq '*U' || $opv eq '-U' ||
-                                        $opv eq '&U') {
+                                        $opv eq '&U' || $opv eq '&&U') {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                ERROR("space required before that '$op' $at\n" . $hereptr);
                                        }
@@ -1785,7 +1970,26 @@ sub process {
 
 # Check for illegal assignment in if conditional -- and check for trailing
 # statements after the conditional.
-               if ($line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
+               if ($line =~ /do\s*(?!{)/) {
+                       my ($stat_next) = ctx_statement_block($line_nr_next,
+                                               $remain_next, $off_next);
+                       $stat_next =~ s/\n./\n /g;
+                       ##print "stat<$stat> stat_next<$stat_next>\n";
+
+                       if ($stat_next =~ /^\s*while\b/) {
+                               # If the statement carries leading newlines,
+                               # then count those as offsets.
+                               my ($whitespace) =
+                                       ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
+                               my $offset =
+                                       statement_rawlines($whitespace) - 1;
+
+                               $suppress_whiletrailers{$line_nr_next +
+                                                               $offset} = 1;
+                       }
+               }
+               if (!defined $suppress_whiletrailers{$linenr} &&
+                   $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
                        my ($s, $c) = ($stat, $cond);
 
                        if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
@@ -1800,57 +2004,16 @@ sub process {
                        if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
                            $c !~ /}\s*while\s*/)
                        {
-                               ERROR("trailing statements should be on next line\n" . $herecurr);
-                       }
-               }
-
-# Check relative indent for conditionals and blocks.
-               if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
-                       my ($s, $c) = ($stat, $cond);
-
-                       substr($s, 0, length($c), '');
+                               # Find out how long the conditional actually is.
+                               my @newlines = ($c =~ /\n/gs);
+                               my $cond_lines = 1 + $#newlines;
 
-                       # Make sure we remove the line prefixes as we have
-                       # none on the first line, and are going to readd them
-                       # where necessary.
-                       $s =~ s/\n./\n/gs;
-
-                       # We want to check the first line inside the block
-                       # starting at the end of the conditional, so remove:
-                       #  1) any blank line termination
-                       #  2) any opening brace { on end of the line
-                       #  3) any do (...) {
-                       my $continuation = 0;
-                       my $check = 0;
-                       $s =~ s/^.*\bdo\b//;
-                       $s =~ s/^\s*{//;
-                       if ($s =~ s/^\s*\\//) {
-                               $continuation = 1;
-                       }
-                       if ($s =~ s/^\s*\n//) {
-                               $check = 1;
-                       }
-
-                       # Also ignore a loop construct at the end of a
-                       # preprocessor statement.
-                       if (($prevline =~ /^.\s*#\s*define\s/ ||
-                           $prevline =~ /\\\s*$/) && $continuation == 0) {
-                               $check = 0;
-                       }
-
-                       # Ignore the current line if its is a preprocessor
-                       # line.
-                       if ($s =~ /^\s*#\s*/) {
-                               $check = 0;
-                       }
-
-                       my (undef, $sindent) = line_stats("+" . $s);
-
-                       ##print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s>\n";
+                               my $stat_real = raw_line($linenr, $cond_lines);
+                               if (defined($stat_real) && $cond_lines > 1) {
+                                       $stat_real = "[...]\n$stat_real";
+                               }
 
-                       if ($check && (($sindent % 8) != 0 ||
-                           ($sindent <= $indent && $s ne ''))) {
-                               WARN("suspect code indent for conditional statements\n" . $herecurr);
+                               ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real);
                        }
                }
 
@@ -1877,6 +2040,15 @@ sub process {
                                ERROR("trailing statements should be on next line\n" . $herecurr);
                        }
                }
+# case and default should not have general statements after them
+               if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
+                   $line !~ /\G(?:
+                       (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
+                       \s*return\s+
+                   )/xg)
+               {
+                       ERROR("trailing statements should be on next line\n" . $herecurr);
+               }
 
                # Check for }<nl>else {, these must be at the same
                # indent level to be relevant to each other.
@@ -1913,12 +2085,17 @@ sub process {
 
 #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
                if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
-                       my $checkfile = "include/linux/$1.h";
-                       if (-f "$root/$checkfile" && $realfile ne $checkfile &&
+                       my $file = "$1.h";
+                       my $checkfile = "include/linux/$file";
+                       if (-f "$root/$checkfile" &&
+                           $realfile ne $checkfile &&
                            $1 ne 'irq')
                        {
-                               WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
-                                       $herecurr);
+                               if ($realfile =~ m{^arch/}) {
+                                       CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+                               } else {
+                                       WARN("Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+                               }
                        }
                }
 
@@ -1953,8 +2130,8 @@ sub process {
                        # Extract the remainder of the define (if any) and
                        # rip off surrounding spaces, and trailing \'s.
                        $rest = '';
-                       while ($off != 0 || ($cnt > 0 && $rest =~ /(?:^|\\)\s*$/)) {
-                               #print "ADDING $off <" . substr($lines[$ln - 1], $off) . ">\n";
+                       while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) {
+                               #print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
                                if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
                                        $rest .= substr($lines[$ln - 1], $off) . "\n";
                                        $cnt--;
@@ -1978,9 +2155,10 @@ sub process {
                        $dstat =~ s/\s*$//s;
 
                        # Flatten any parentheses and braces
-                       while ($dstat =~ s/\([^\(\)]*\)/1/) {
-                       }
-                       while ($dstat =~ s/\{[^\{\}]*\}/1/) {
+                       while ($dstat =~ s/\([^\(\)]*\)/1/ ||
+                              $dstat =~ s/\{[^\{\}]*\}/1/ ||
+                              $dstat =~ s/\[[^\{\}]*\]/1/)
+                       {
                        }
 
                        my $exceptions = qr{
@@ -2003,6 +2181,7 @@ sub process {
                                if ($dstat ne '' &&
                                    $dstat !~ /^(?:$Ident|-?$Constant)$/ &&
                                    $dstat !~ /$exceptions/ &&
+                                   $dstat !~ /^\.$Ident\s*=/ &&
                                    $dstat =~ /$Operators/)
                                {
                                        ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
@@ -2103,10 +2282,10 @@ sub process {
                        }
                        if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
                                my $herectx = $here . "\n";;
-                               my $end = $linenr + statement_rawlines($block) - 1;
+                               my $cnt = statement_rawlines($block);
 
-                               for (my $ln = $linenr - 1; $ln < $end; $ln++) {
-                                       $herectx .= $rawlines[$ln] . "\n";;
+                               for (my $n = 0; $n < $cnt; $n++) {
+                                       $herectx .= raw_line($linenr, $n) . "\n";;
                                }
 
                                WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
@@ -2281,6 +2460,7 @@ sub process {
                my $string;
                while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
                        $string = substr($rawline, $-[1], $+[1] - $-[1]);
+                       $string =~ s/%%/__/g;
                        if ($string =~ /(?<!%)%L[udi]/) {
                                WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
                                last;
index 4c9890ec252875500c6c35d388fdd44af9545f34..d4dc222a74f33c69fd17dbb7170c41731933aa2b 100644 (file)
@@ -206,6 +206,20 @@ static void do_usb_table(void *symval, unsigned long size,
                do_usb_entry_multi(symval + i, mod);
 }
 
+/* Looks like: hid:bNvNpN */
+static int do_hid_entry(const char *filename,
+                            struct hid_device_id *id, char *alias)
+{
+       id->vendor = TO_NATIVE(id->vendor);
+       id->product = TO_NATIVE(id->product);
+
+       sprintf(alias, "hid:b%04X", id->bus);
+       ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
+       ADD(alias, "p", id->product != HID_ANY_ID, id->product);
+
+       return 1;
+}
+
 /* Looks like: ieee1394:venNmoNspNverN */
 static int do_ieee1394_entry(const char *filename,
                             struct ieee1394_device_id *id, char *alias)
@@ -629,6 +643,59 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
        return 1;
 }
 
+static const struct dmifield {
+       const char *prefix;
+       int field;
+} dmi_fields[] = {
+       { "bvn", DMI_BIOS_VENDOR },
+       { "bvr", DMI_BIOS_VERSION },
+       { "bd",  DMI_BIOS_DATE },
+       { "svn", DMI_SYS_VENDOR },
+       { "pn",  DMI_PRODUCT_NAME },
+       { "pvr", DMI_PRODUCT_VERSION },
+       { "rvn", DMI_BOARD_VENDOR },
+       { "rn",  DMI_BOARD_NAME },
+       { "rvr", DMI_BOARD_VERSION },
+       { "cvn", DMI_CHASSIS_VENDOR },
+       { "ct",  DMI_CHASSIS_TYPE },
+       { "cvr", DMI_CHASSIS_VERSION },
+       { NULL,  DMI_NONE }
+};
+
+static void dmi_ascii_filter(char *d, const char *s)
+{
+       /* Filter out characters we don't want to see in the modalias string */
+       for (; *s; s++)
+               if (*s > ' ' && *s < 127 && *s != ':')
+                       *(d++) = *s;
+
+       *d = 0;
+}
+
+
+static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
+                       char *alias)
+{
+       int i, j;
+
+       sprintf(alias, "dmi*");
+
+       for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
+               for (j = 0; j < 4; j++) {
+                       if (id->matches[j].slot &&
+                           id->matches[j].slot == dmi_fields[i].field) {
+                               sprintf(alias + strlen(alias), ":%s*",
+                                       dmi_fields[i].prefix);
+                               dmi_ascii_filter(alias + strlen(alias),
+                                                id->matches[j].substr);
+                               strcat(alias, "*");
+                       }
+               }
+       }
+
+       strcat(alias, ":");
+       return 1;
+}
 /* Ignore any prefix, eg. some architectures prepend _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -692,6 +759,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
        else if (sym_is(symname, "__mod_usb_device_table"))
                /* special case to handle bcdDevice ranges */
                do_usb_table(symval, sym->st_size, mod);
+       else if (sym_is(symname, "__mod_hid_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct hid_device_id), "hid",
+                        do_hid_entry, mod);
        else if (sym_is(symname, "__mod_ieee1394_device_table"))
                do_table(symval, sym->st_size,
                         sizeof(struct ieee1394_device_id), "ieee1394",
@@ -760,6 +831,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct i2c_device_id), "i2c",
                         do_i2c_entry, mod);
+       else if (sym_is(symname, "__mod_dmi_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct dmi_system_id), "dmi",
+                        do_dmi_entry, mod);
        free(zeros);
 }
 
index ca4958ebad8d30c7c4f8ce4bdf1b98309fe2e13e..efea5a6054663f2d2aba78930bd3185986e14cdd 100644 (file)
@@ -20,8 +20,7 @@
 #include <linux/init.h>
 #include <linux/namei.h>
 #include <linux/security.h>
-
-#define SECURITYFS_MAGIC       0x73636673
+#include <linux/magic.h>
 
 static struct vfsmount *mount;
 static int mount_count;
index 4a7374c12d9ca5a2b9c76c1101ecb42ee44b48af..576e511990794eacfad7ad525722c4fa077ae852 100644 (file)
@@ -291,6 +291,7 @@ static void sk_free_security(struct sock *sk)
        struct sk_security_struct *ssec = sk->sk_security;
 
        sk->sk_security = NULL;
+       selinux_netlbl_sk_security_free(ssec);
        kfree(ssec);
 }
 
@@ -324,7 +325,7 @@ enum {
        Opt_rootcontext = 4,
 };
 
-static match_table_t tokens = {
+static const match_table_t tokens = {
        {Opt_context, CONTEXT_STR "%s"},
        {Opt_fscontext, FSCONTEXT_STR "%s"},
        {Opt_defcontext, DEFCONTEXT_STR "%s"},
@@ -2121,7 +2122,6 @@ static inline void flush_unauthorized_files(struct files_struct *files)
        long j = -1;
        int drop_tty = 0;
 
-       mutex_lock(&tty_mutex);
        tty = get_current_tty();
        if (tty) {
                file_list_lock();
@@ -2139,8 +2139,8 @@ static inline void flush_unauthorized_files(struct files_struct *files)
                        }
                }
                file_list_unlock();
+               tty_kref_put(tty);
        }
-       mutex_unlock(&tty_mutex);
        /* Reset controlling tty. */
        if (drop_tty)
                no_tty();
@@ -3801,6 +3801,7 @@ out:
 
 static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
 {
+       struct sock *sk = sock->sk;
        struct inode_security_struct *isec;
        int err;
 
@@ -3814,7 +3815,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
        isec = SOCK_INODE(sock)->i_security;
        if (isec->sclass == SECCLASS_TCP_SOCKET ||
            isec->sclass == SECCLASS_DCCP_SOCKET) {
-               struct sock *sk = sock->sk;
                struct avc_audit_data ad;
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
@@ -3848,6 +3848,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
                        goto out;
        }
 
+       err = selinux_netlbl_socket_connect(sk, address);
+
 out:
        return err;
 }
@@ -4077,20 +4079,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
 }
 
 static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
-                                      struct avc_audit_data *ad,
-                                      u16 family, char *addrp)
+                                      u16 family)
 {
        int err;
        struct sk_security_struct *sksec = sk->sk_security;
        u32 peer_sid;
        u32 sk_sid = sksec->sid;
+       struct avc_audit_data ad;
+       char *addrp;
+
+       AVC_AUDIT_DATA_INIT(&ad, NET);
+       ad.u.net.netif = skb->iif;
+       ad.u.net.family = family;
+       err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
+       if (err)
+               return err;
 
        if (selinux_compat_net)
-               err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
+               err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
                                                           family, addrp);
        else
                err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
-                                  PACKET__RECV, ad);
+                                  PACKET__RECV, &ad);
        if (err)
                return err;
 
@@ -4099,12 +4109,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
                if (err)
                        return err;
                err = avc_has_perm(sk_sid, peer_sid,
-                                  SECCLASS_PEER, PEER__RECV, ad);
+                                  SECCLASS_PEER, PEER__RECV, &ad);
+               if (err)
+                       selinux_netlbl_err(skb, err, 0);
        } else {
-               err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
+               err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
                if (err)
                        return err;
-               err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
+               err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
        }
 
        return err;
@@ -4118,6 +4130,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        u32 sk_sid = sksec->sid;
        struct avc_audit_data ad;
        char *addrp;
+       u8 secmark_active;
+       u8 peerlbl_active;
 
        if (family != PF_INET && family != PF_INET6)
                return 0;
@@ -4126,6 +4140,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
                family = PF_INET;
 
+       /* If any sort of compatibility mode is enabled then handoff processing
+        * to the selinux_sock_rcv_skb_compat() function to deal with the
+        * special handling.  We do this in an attempt to keep this function
+        * as fast and as clean as possible. */
+       if (selinux_compat_net || !selinux_policycap_netpeer)
+               return selinux_sock_rcv_skb_compat(sk, skb, family);
+
+       secmark_active = selinux_secmark_enabled();
+       peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+       if (!secmark_active && !peerlbl_active)
+               return 0;
+
        AVC_AUDIT_DATA_INIT(&ad, NET);
        ad.u.net.netif = skb->iif;
        ad.u.net.family = family;
@@ -4133,15 +4159,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        if (err)
                return err;
 
-       /* If any sort of compatibility mode is enabled then handoff processing
-        * to the selinux_sock_rcv_skb_compat() function to deal with the
-        * special handling.  We do this in an attempt to keep this function
-        * as fast and as clean as possible. */
-       if (selinux_compat_net || !selinux_policycap_netpeer)
-               return selinux_sock_rcv_skb_compat(sk, skb, &ad,
-                                                  family, addrp);
-
-       if (netlbl_enabled() || selinux_xfrm_enabled()) {
+       if (peerlbl_active) {
                u32 peer_sid;
 
                err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4149,13 +4167,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                        return err;
                err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
                                               peer_sid, &ad);
-               if (err)
+               if (err) {
+                       selinux_netlbl_err(skb, err, 0);
                        return err;
+               }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
+               if (err)
+                       selinux_netlbl_err(skb, err, 0);
        }
 
-       if (selinux_secmark_enabled()) {
+       if (secmark_active) {
                err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
                                   PACKET__RECV, &ad);
                if (err)
@@ -4214,10 +4236,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
        u32 peer_secid = SECSID_NULL;
        u16 family;
 
-       if (sock)
+       if (skb && skb->protocol == htons(ETH_P_IP))
+               family = PF_INET;
+       else if (skb && skb->protocol == htons(ETH_P_IPV6))
+               family = PF_INET6;
+       else if (sock)
                family = sock->sk->sk_family;
-       else if (skb && skb->sk)
-               family = skb->sk->sk_family;
        else
                goto out;
 
@@ -4275,8 +4299,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
            sk->sk_family == PF_UNIX)
                isec->sid = sksec->sid;
        sksec->sclass = isec->sclass;
-
-       selinux_netlbl_sock_graft(sk, parent);
 }
 
 static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
@@ -4284,10 +4306,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 {
        struct sk_security_struct *sksec = sk->sk_security;
        int err;
+       u16 family = sk->sk_family;
        u32 newsid;
        u32 peersid;
 
-       err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
+       /* handle mapped IPv4 packets arriving via IPv6 sockets */
+       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+               family = PF_INET;
+
+       err = selinux_skb_peerlbl_sid(skb, family, &peersid);
        if (err)
                return err;
        if (peersid == SECSID_NULL) {
@@ -4322,12 +4349,18 @@ static void selinux_inet_csk_clone(struct sock *newsk,
        selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
 }
 
-static void selinux_inet_conn_established(struct sock *sk,
-                               struct sk_buff *skb)
+static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
 {
+       u16 family = sk->sk_family;
        struct sk_security_struct *sksec = sk->sk_security;
 
-       selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
+       /* handle mapped IPv4 packets arriving via IPv6 sockets */
+       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
+               family = PF_INET;
+
+       selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
+
+       selinux_netlbl_inet_conn_established(sk, family);
 }
 
 static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4377,39 +4410,54 @@ out:
 static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
                                       u16 family)
 {
+       int err;
        char *addrp;
        u32 peer_sid;
        struct avc_audit_data ad;
        u8 secmark_active;
+       u8 netlbl_active;
        u8 peerlbl_active;
 
        if (!selinux_policycap_netpeer)
                return NF_ACCEPT;
 
        secmark_active = selinux_secmark_enabled();
-       peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+       netlbl_active = netlbl_enabled();
+       peerlbl_active = netlbl_active || selinux_xfrm_enabled();
        if (!secmark_active && !peerlbl_active)
                return NF_ACCEPT;
 
+       if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
+               return NF_DROP;
+
        AVC_AUDIT_DATA_INIT(&ad, NET);
        ad.u.net.netif = ifindex;
        ad.u.net.family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
                return NF_DROP;
 
-       if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
-               return NF_DROP;
-
-       if (peerlbl_active)
-               if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
-                                            peer_sid, &ad) != 0)
+       if (peerlbl_active) {
+               err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
+                                              peer_sid, &ad);
+               if (err) {
+                       selinux_netlbl_err(skb, err, 1);
                        return NF_DROP;
+               }
+       }
 
        if (secmark_active)
                if (avc_has_perm(peer_sid, skb->secmark,
                                 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
                        return NF_DROP;
 
+       if (netlbl_active)
+               /* we do this in the FORWARD path and not the POST_ROUTING
+                * path because we want to make sure we apply the necessary
+                * labeling before IPsec is applied so we can leverage AH
+                * protection */
+               if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
+                       return NF_DROP;
+
        return NF_ACCEPT;
 }
 
@@ -4433,6 +4481,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
 }
 #endif /* IPV6 */
 
+static unsigned int selinux_ip_output(struct sk_buff *skb,
+                                     u16 family)
+{
+       u32 sid;
+
+       if (!netlbl_enabled())
+               return NF_ACCEPT;
+
+       /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
+        * because we want to make sure we apply the necessary labeling
+        * before IPsec is applied so we can leverage AH protection */
+       if (skb->sk) {
+               struct sk_security_struct *sksec = skb->sk->sk_security;
+               sid = sksec->sid;
+       } else
+               sid = SECINITSID_KERNEL;
+       if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
+               return NF_DROP;
+
+       return NF_ACCEPT;
+}
+
+static unsigned int selinux_ipv4_output(unsigned int hooknum,
+                                       struct sk_buff *skb,
+                                       const struct net_device *in,
+                                       const struct net_device *out,
+                                       int (*okfn)(struct sk_buff *))
+{
+       return selinux_ip_output(skb, PF_INET);
+}
+
 static int selinux_ip_postroute_iptables_compat(struct sock *sk,
                                                int ifindex,
                                                struct avc_audit_data *ad,
@@ -4500,30 +4579,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
 
 static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
                                                int ifindex,
-                                               struct avc_audit_data *ad,
-                                               u16 family,
-                                               char *addrp,
-                                               u8 proto)
+                                               u16 family)
 {
        struct sock *sk = skb->sk;
        struct sk_security_struct *sksec;
+       struct avc_audit_data ad;
+       char *addrp;
+       u8 proto;
 
        if (sk == NULL)
                return NF_ACCEPT;
        sksec = sk->sk_security;
 
+       AVC_AUDIT_DATA_INIT(&ad, NET);
+       ad.u.net.netif = ifindex;
+       ad.u.net.family = family;
+       if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
+               return NF_DROP;
+
        if (selinux_compat_net) {
                if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
-                                                        ad, family, addrp))
+                                                        &ad, family, addrp))
                        return NF_DROP;
        } else {
                if (avc_has_perm(sksec->sid, skb->secmark,
-                                SECCLASS_PACKET, PACKET__SEND, ad))
+                                SECCLASS_PACKET, PACKET__SEND, &ad))
                        return NF_DROP;
        }
 
        if (selinux_policycap_netpeer)
-               if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
+               if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
                        return NF_DROP;
 
        return NF_ACCEPT;
@@ -4537,23 +4622,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        struct sock *sk;
        struct avc_audit_data ad;
        char *addrp;
-       u8 proto;
        u8 secmark_active;
        u8 peerlbl_active;
 
-       AVC_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
-       if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
-               return NF_DROP;
-
        /* If any sort of compatibility mode is enabled then handoff processing
         * to the selinux_ip_postroute_compat() function to deal with the
         * special handling.  We do this in an attempt to keep this function
         * as fast and as clean as possible. */
        if (selinux_compat_net || !selinux_policycap_netpeer)
-               return selinux_ip_postroute_compat(skb, ifindex, &ad,
-                                                  family, addrp, proto);
+               return selinux_ip_postroute_compat(skb, ifindex, family);
 
        /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
         * packet transformation so allow the packet to pass without any checks
@@ -4569,21 +4646,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        if (!secmark_active && !peerlbl_active)
                return NF_ACCEPT;
 
-       /* if the packet is locally generated (skb->sk != NULL) then use the
-        * socket's label as the peer label, otherwise the packet is being
-        * forwarded through this system and we need to fetch the peer label
-        * directly from the packet */
+       /* if the packet is being forwarded then get the peer label from the
+        * packet itself; otherwise check to see if it is from a local
+        * application or the kernel, if from an application get the peer label
+        * from the sending socket, otherwise use the kernel's sid */
        sk = skb->sk;
-       if (sk) {
+       if (sk == NULL) {
+               switch (family) {
+               case PF_INET:
+                       if (IPCB(skb)->flags & IPSKB_FORWARDED)
+                               secmark_perm = PACKET__FORWARD_OUT;
+                       else
+                               secmark_perm = PACKET__SEND;
+                       break;
+               case PF_INET6:
+                       if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
+                               secmark_perm = PACKET__FORWARD_OUT;
+                       else
+                               secmark_perm = PACKET__SEND;
+                       break;
+               default:
+                       return NF_DROP;
+               }
+               if (secmark_perm == PACKET__FORWARD_OUT) {
+                       if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
+                               return NF_DROP;
+               } else
+                       peer_sid = SECINITSID_KERNEL;
+       } else {
                struct sk_security_struct *sksec = sk->sk_security;
                peer_sid = sksec->sid;
                secmark_perm = PACKET__SEND;
-       } else {
-               if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
-                               return NF_DROP;
-               secmark_perm = PACKET__FORWARD_OUT;
        }
 
+       AVC_AUDIT_DATA_INIT(&ad, NET);
+       ad.u.net.netif = ifindex;
+       ad.u.net.family = family;
+       if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
+               return NF_DROP;
+
        if (secmark_active)
                if (avc_has_perm(peer_sid, skb->secmark,
                                 SECCLASS_PACKET, secmark_perm, &ad))
@@ -5657,6 +5758,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
                .pf =           PF_INET,
                .hooknum =      NF_INET_FORWARD,
                .priority =     NF_IP_PRI_SELINUX_FIRST,
+       },
+       {
+               .hook =         selinux_ipv4_output,
+               .owner =        THIS_MODULE,
+               .pf =           PF_INET,
+               .hooknum =      NF_INET_LOCAL_OUT,
+               .priority =     NF_IP_PRI_SELINUX_FIRST,
        }
 };
 
index 487a7d81fe204ae35df5d96d390b46e7652548fc..b913c8d060386728bfe0bc68441a56b4ad3f012f 100644 (file)
@@ -39,6 +39,9 @@
 #ifdef CONFIG_NETLABEL
 void selinux_netlbl_cache_invalidate(void);
 
+void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
+
+void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
 void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
                                      int family);
 
@@ -46,8 +49,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
                                 u16 family,
                                 u32 *type,
                                 u32 *sid);
+int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
+                                u16 family,
+                                u32 sid);
 
-void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
+void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family);
 int selinux_netlbl_socket_post_create(struct socket *sock);
 int selinux_netlbl_inode_permission(struct inode *inode, int mask);
 int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -57,12 +63,27 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
 int selinux_netlbl_socket_setsockopt(struct socket *sock,
                                     int level,
                                     int optname);
+int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr);
+
 #else
 static inline void selinux_netlbl_cache_invalidate(void)
 {
        return;
 }
 
+static inline void selinux_netlbl_err(struct sk_buff *skb,
+                                     int error,
+                                     int gateway)
+{
+       return;
+}
+
+static inline void selinux_netlbl_sk_security_free(
+                                              struct sk_security_struct *ssec)
+{
+       return;
+}
+
 static inline void selinux_netlbl_sk_security_reset(
                                               struct sk_security_struct *ssec,
                                               int family)
@@ -79,9 +100,21 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
        *sid = SECSID_NULL;
        return 0;
 }
+static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
+                                              u16 family,
+                                              u32 sid)
+{
+       return 0;
+}
 
-static inline void selinux_netlbl_sock_graft(struct sock *sk,
-                                            struct socket *sock)
+static inline int selinux_netlbl_conn_setsid(struct sock *sk,
+                                            struct sockaddr *addr)
+{
+       return 0;
+}
+
+static inline void selinux_netlbl_inet_conn_established(struct sock *sk,
+                                                       u16 family)
 {
        return;
 }
@@ -107,6 +140,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
 {
        return 0;
 }
+static inline int selinux_netlbl_socket_connect(struct sock *sk,
+                                               struct sockaddr *addr)
+{
+       return 0;
+}
 #endif /* CONFIG_NETLABEL */
 
 #endif
index 91070ab874ce8b1255fadfff9f99aac0ce5bcc60..f8be8d7fa26d7962f020e612254653d849f5b226 100644 (file)
@@ -109,16 +109,19 @@ struct netport_security_struct {
 };
 
 struct sk_security_struct {
-       u32 sid;                        /* SID of this object */
-       u32 peer_sid;                   /* SID of peer */
-       u16 sclass;                     /* sock security class */
 #ifdef CONFIG_NETLABEL
        enum {                          /* NetLabel state */
                NLBL_UNSET = 0,
                NLBL_REQUIRE,
                NLBL_LABELED,
+               NLBL_REQSKB,
+               NLBL_CONNLABELED,
        } nlbl_state;
+       struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
 #endif
+       u32 sid;                        /* SID of this object */
+       u32 peer_sid;                   /* SID of peer */
+       u16 sclass;                     /* sock security class */
 };
 
 struct key_security_struct {
index 89b418392f1179ca13e62d66bb779d6a3f04ccfa..f58701a7b728619a5a50e3bc74981baa23ab60cf 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2007
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
 #include <net/sock.h>
 #include <net/netlabel.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
 
 #include "objsec.h"
 #include "security.h"
@@ -63,33 +67,70 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
        return rc;
 }
 
+/**
+ * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
+ * @sk: the socket
+ *
+ * Description:
+ * Generate the NetLabel security attributes for a socket, making full use of
+ * the socket's attribute cache.  Returns a pointer to the security attributes
+ * on success, NULL on failure.
+ *
+ */
+static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
+{
+       int rc;
+       struct sk_security_struct *sksec = sk->sk_security;
+       struct netlbl_lsm_secattr *secattr;
+
+       if (sksec->nlbl_secattr != NULL)
+               return sksec->nlbl_secattr;
+
+       secattr = netlbl_secattr_alloc(GFP_ATOMIC);
+       if (secattr == NULL)
+               return NULL;
+       rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
+       if (rc != 0) {
+               netlbl_secattr_free(secattr);
+               return NULL;
+       }
+       sksec->nlbl_secattr = secattr;
+
+       return secattr;
+}
+
 /**
  * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
  * @sk: the socket to label
- * @sid: the SID to use
  *
  * Description:
- * Attempt to label a socket using the NetLabel mechanism using the given
- * SID.  Returns zero values on success, negative values on failure.
+ * Attempt to label a socket using the NetLabel mechanism.  Returns zero values
+ * on success, negative values on failure.
  *
  */
-static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
+static int selinux_netlbl_sock_setsid(struct sock *sk)
 {
        int rc;
        struct sk_security_struct *sksec = sk->sk_security;
-       struct netlbl_lsm_secattr secattr;
+       struct netlbl_lsm_secattr *secattr;
 
-       netlbl_secattr_init(&secattr);
+       if (sksec->nlbl_state != NLBL_REQUIRE)
+               return 0;
 
-       rc = security_netlbl_sid_to_secattr(sid, &secattr);
-       if (rc != 0)
-               goto sock_setsid_return;
-       rc = netlbl_sock_setattr(sk, &secattr);
-       if (rc == 0)
+       secattr = selinux_netlbl_sock_genattr(sk);
+       if (secattr == NULL)
+               return -ENOMEM;
+       rc = netlbl_sock_setattr(sk, secattr);
+       switch (rc) {
+       case 0:
                sksec->nlbl_state = NLBL_LABELED;
+               break;
+       case -EDESTADDRREQ:
+               sksec->nlbl_state = NLBL_REQSKB;
+               rc = 0;
+               break;
+       }
 
-sock_setsid_return:
-       netlbl_secattr_destroy(&secattr);
        return rc;
 }
 
@@ -105,6 +146,38 @@ void selinux_netlbl_cache_invalidate(void)
        netlbl_cache_invalidate();
 }
 
+/**
+ * selinux_netlbl_err - Handle a NetLabel packet error
+ * @skb: the packet
+ * @error: the error code
+ * @gateway: true if host is acting as a gateway, false otherwise
+ *
+ * Description:
+ * When a packet is dropped due to a call to avc_has_perm() pass the error
+ * code to the NetLabel subsystem so any protocol specific processing can be
+ * done.  This is safe to call even if you are unsure if NetLabel labeling is
+ * present on the packet, NetLabel is smart enough to only act when it should.
+ *
+ */
+void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
+{
+       netlbl_skbuff_err(skb, error, gateway);
+}
+
+/**
+ * selinux_netlbl_sk_security_free - Free the NetLabel fields
+ * @sssec: the sk_security_struct
+ *
+ * Description:
+ * Free all of the memory in the NetLabel fields of a sk_security_struct.
+ *
+ */
+void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
+{
+       if (ssec->nlbl_secattr != NULL)
+               netlbl_secattr_free(ssec->nlbl_secattr);
+}
+
 /**
  * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
  * @ssec: the sk_security_struct
@@ -163,35 +236,118 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
 }
 
 /**
- * selinux_netlbl_sock_graft - Netlabel the new socket
+ * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
+ * @skb: the packet
+ * @family: protocol family
+ * @sid: the SID
+ *
+ * Description
+ * Call the NetLabel mechanism to set the label of a packet using @sid.
+ * Returns zero on auccess, negative values on failure.
+ *
+ */
+int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
+                                u16 family,
+                                u32 sid)
+{
+       int rc;
+       struct netlbl_lsm_secattr secattr_storage;
+       struct netlbl_lsm_secattr *secattr = NULL;
+       struct sock *sk;
+
+       /* if this is a locally generated packet check to see if it is already
+        * being labeled by it's parent socket, if it is just exit */
+       sk = skb->sk;
+       if (sk != NULL) {
+               struct sk_security_struct *sksec = sk->sk_security;
+               if (sksec->nlbl_state != NLBL_REQSKB)
+                       return 0;
+               secattr = sksec->nlbl_secattr;
+       }
+       if (secattr == NULL) {
+               secattr = &secattr_storage;
+               netlbl_secattr_init(secattr);
+               rc = security_netlbl_sid_to_secattr(sid, secattr);
+               if (rc != 0)
+                       goto skbuff_setsid_return;
+       }
+
+       rc = netlbl_skbuff_setattr(skb, family, secattr);
+
+skbuff_setsid_return:
+       if (secattr == &secattr_storage)
+               netlbl_secattr_destroy(secattr);
+       return rc;
+}
+
+/**
+ * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
  * @sk: the new connection
- * @sock: the new socket
  *
  * Description:
- * The connection represented by @sk is being grafted onto @sock so set the
- * socket's NetLabel to match the SID of @sk.
+ * A new connection has been established on @sk so make sure it is labeled
+ * correctly with the NetLabel susbsystem.
  *
  */
-void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
+void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
 {
+       int rc;
        struct sk_security_struct *sksec = sk->sk_security;
-       struct netlbl_lsm_secattr secattr;
-       u32 nlbl_peer_sid;
+       struct netlbl_lsm_secattr *secattr;
+       struct inet_sock *sk_inet = inet_sk(sk);
+       struct sockaddr_in addr;
 
        if (sksec->nlbl_state != NLBL_REQUIRE)
                return;
 
-       netlbl_secattr_init(&secattr);
-       if (netlbl_sock_getattr(sk, &secattr) == 0 &&
-           secattr.flags != NETLBL_SECATTR_NONE &&
-           security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
-               sksec->peer_sid = nlbl_peer_sid;
-       netlbl_secattr_destroy(&secattr);
+       secattr = selinux_netlbl_sock_genattr(sk);
+       if (secattr == NULL)
+               return;
 
-       /* Try to set the NetLabel on the socket to save time later, if we fail
-        * here we will pick up the pieces in later calls to
-        * selinux_netlbl_inode_permission(). */
-       selinux_netlbl_sock_setsid(sk, sksec->sid);
+       rc = netlbl_sock_setattr(sk, secattr);
+       switch (rc) {
+       case 0:
+               sksec->nlbl_state = NLBL_LABELED;
+               break;
+       case -EDESTADDRREQ:
+               /* no PF_INET6 support yet because we don't support any IPv6
+                * labeling protocols */
+               if (family != PF_INET) {
+                       sksec->nlbl_state = NLBL_UNSET;
+                       return;
+               }
+
+               addr.sin_family = family;
+               addr.sin_addr.s_addr = sk_inet->daddr;
+               if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
+                                       secattr) != 0) {
+                       /* we failed to label the connected socket (could be
+                        * for a variety of reasons, the actual "why" isn't
+                        * important here) so we have to go to our backup plan,
+                        * labeling the packets individually in the netfilter
+                        * local output hook.  this is okay but we need to
+                        * adjust the MSS of the connection to take into
+                        * account any labeling overhead, since we don't know
+                        * the exact overhead at this point we'll use the worst
+                        * case value which is 40 bytes for IPv4 */
+                       struct inet_connection_sock *sk_conn = inet_csk(sk);
+                       sk_conn->icsk_ext_hdr_len += 40 -
+                                     (sk_inet->opt ? sk_inet->opt->optlen : 0);
+                       sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
+
+                       sksec->nlbl_state = NLBL_REQSKB;
+               } else
+                       sksec->nlbl_state = NLBL_CONNLABELED;
+               break;
+       default:
+               /* note that we are failing to label the socket which could be
+                * a bad thing since it means traffic could leave the system
+                * without the desired labeling, however, all is not lost as
+                * we have a check in selinux_netlbl_inode_permission() to
+                * pick up the pieces that we might drop here because we can't
+                * return an error code */
+               break;
+       }
 }
 
 /**
@@ -205,13 +361,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
  */
 int selinux_netlbl_socket_post_create(struct socket *sock)
 {
-       struct sock *sk = sock->sk;
-       struct sk_security_struct *sksec = sk->sk_security;
-
-       if (sksec->nlbl_state != NLBL_REQUIRE)
-               return 0;
-
-       return selinux_netlbl_sock_setsid(sk, sksec->sid);
+       return selinux_netlbl_sock_setsid(sock->sk);
 }
 
 /**
@@ -246,7 +396,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
        local_bh_disable();
        bh_lock_sock_nested(sk);
        if (likely(sksec->nlbl_state == NLBL_REQUIRE))
-               rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+               rc = selinux_netlbl_sock_setsid(sk);
        else
                rc = 0;
        bh_unlock_sock(sk);
@@ -307,7 +457,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
                return 0;
 
        if (nlbl_sid != SECINITSID_UNLABELED)
-               netlbl_skbuff_err(skb, rc);
+               netlbl_skbuff_err(skb, rc, 0);
        return rc;
 }
 
@@ -334,7 +484,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
        struct netlbl_lsm_secattr secattr;
 
        if (level == IPPROTO_IP && optname == IP_OPTIONS &&
-           sksec->nlbl_state == NLBL_LABELED) {
+           (sksec->nlbl_state == NLBL_LABELED ||
+            sksec->nlbl_state == NLBL_CONNLABELED)) {
                netlbl_secattr_init(&secattr);
                lock_sock(sk);
                rc = netlbl_sock_getattr(sk, &secattr);
@@ -346,3 +497,50 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
 
        return rc;
 }
+
+/**
+ * selinux_netlbl_socket_connect - Label a client-side socket on connect
+ * @sk: the socket to label
+ * @addr: the destination address
+ *
+ * Description:
+ * Attempt to label a connected socket with NetLabel using the given address.
+ * Returns zero values on success, negative values on failure.
+ *
+ */
+int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
+{
+       int rc;
+       struct sk_security_struct *sksec = sk->sk_security;
+       struct netlbl_lsm_secattr *secattr;
+
+       if (sksec->nlbl_state != NLBL_REQSKB &&
+           sksec->nlbl_state != NLBL_CONNLABELED)
+               return 0;
+
+       local_bh_disable();
+       bh_lock_sock_nested(sk);
+
+       /* connected sockets are allowed to disconnect when the address family
+        * is set to AF_UNSPEC, if that is what is happening we want to reset
+        * the socket */
+       if (addr->sa_family == AF_UNSPEC) {
+               netlbl_sock_delattr(sk);
+               sksec->nlbl_state = NLBL_REQSKB;
+               rc = 0;
+               goto socket_connect_return;
+       }
+       secattr = selinux_netlbl_sock_genattr(sk);
+       if (secattr == NULL) {
+               rc = -ENOMEM;
+               goto socket_connect_return;
+       }
+       rc = netlbl_conn_setattr(sk, addr, secattr);
+       if (rc == 0)
+               sksec->nlbl_state = NLBL_CONNLABELED;
+
+socket_connect_return:
+       bh_unlock_sock(sk);
+       local_bh_enable();
+       return rc;
+}
index ab0cc0c7b9444e60a8cf625c0edb1aaa479456ba..343c8ab14af0a71881336ac3c2461d3360839895 100644 (file)
@@ -2955,7 +2955,7 @@ netlbl_secattr_to_sid_return_cleanup:
  */
 int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 {
-       int rc = -ENOENT;
+       int rc;
        struct context *ctx;
 
        if (!ss_initialized)
@@ -2963,11 +2963,18 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
        read_lock(&policy_rwlock);
        ctx = sidtab_search(&sidtab, sid);
-       if (ctx == NULL)
+       if (ctx == NULL) {
+               rc = -ENOENT;
                goto netlbl_sid_to_secattr_failure;
+       }
        secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
                                  GFP_ATOMIC);
-       secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY;
+       if (secattr->domain == NULL) {
+               rc = -ENOMEM;
+               goto netlbl_sid_to_secattr_failure;
+       }
+       secattr->attr.secid = sid;
+       secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
        mls_export_netlbl_lvl(ctx, secattr);
        rc = mls_export_netlbl_cat(ctx, secattr);
        if (rc != 0)
index 87d75417ea937e7756678fd381c3cb96c9d1c7a5..6e2dc0bab70d837a57ac78a452603178761fbbb3 100644 (file)
@@ -2179,7 +2179,10 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
         * This is the simplist possible security model
         * for networking.
         */
-       return smk_access(smack, ssp->smk_in, MAY_WRITE);
+       rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
+       if (rc != 0)
+               netlbl_skbuff_err(skb, rc, 0);
+       return rc;
 }
 
 /**
index e7c642458ec9431b1639935880b6082f21492f6a..c21d8c8bf0c789f3af9693fac3cdbd226dd4b8cc 100644 (file)
@@ -354,9 +354,11 @@ static void smk_cipso_doi(void)
                doip->tags[rc] = CIPSO_V4_TAG_INVALID;
 
        rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
-       if (rc != 0)
+       if (rc != 0) {
                printk(KERN_WARNING "%s:%d add rc = %d\n",
                       __func__, __LINE__, rc);
+               kfree(doip);
+       }
 }
 
 /**
index 622cd37a011817f3a4edd94cca5bf12a78faa281..a0f223c13f663ac9f65c92b706aa44ecde4e55cf 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef __SOUNDBUS_H
 #define __SOUNDBUS_H
 
-#include <asm/of_device.h>
+#include <linux/of_device.h>
 #include <sound/pcm.h>
 #include <linux/list.h>
 
index 99026dfb81ea5c2220165f7e243f15b4ba891f6a..34c1d94f921e1285238cbcbfae13ab9eab10f04f 100644 (file)
@@ -50,7 +50,7 @@ unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        mutex_lock(&car_mutex);
 
        /* set up primary or secondary codec space */
-       if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+       if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
                reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
        else
                reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
@@ -90,7 +90,7 @@ void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        mutex_lock(&car_mutex);
 
        /* set up primary or secondary codec space */
-       if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
+       if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
                reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
        else
                reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
@@ -200,7 +200,7 @@ static inline void pxa_ac97_cold_pxa3xx(void)
 bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
 {
 #ifdef CONFIG_PXA25x
-       if (cpu_is_pxa21x() || cpu_is_pxa25x())
+       if (cpu_is_pxa25x())
                pxa_ac97_warm_pxa25x();
        else
 #endif
@@ -230,7 +230,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
 bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
 {
 #ifdef CONFIG_PXA25x
-       if (cpu_is_pxa21x() || cpu_is_pxa25x())
+       if (cpu_is_pxa25x())
                pxa_ac97_cold_pxa25x();
        else
 #endif
@@ -301,7 +301,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
 
 int pxa2xx_ac97_hw_resume(void)
 {
-       if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+       if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
                pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
                pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
                pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
@@ -325,7 +325,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
        if (ret < 0)
                goto err;
 
-       if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
+       if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
                pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
                pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
                pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
index 8af467df9245823a2ea5c96981e161d42ed63734..ef2352c2e45116a824f4e8275e590a2c7394594b 100644 (file)
@@ -549,9 +549,9 @@ int snd_card_register(struct snd_card *card)
                return -EINVAL;
 #ifndef CONFIG_SYSFS_DEPRECATED
        if (!card->card_dev) {
-               card->card_dev = device_create_drvdata(sound_class, card->dev,
-                                                      MKDEV(0, 0), NULL,
-                                                      "card%i", card->number);
+               card->card_dev = device_create(sound_class, card->dev,
+                                              MKDEV(0, 0), NULL,
+                                              "card%i", card->number);
                if (IS_ERR(card->card_dev))
                        card->card_dev = NULL;
        }
index c0685e2f0afa1fe39cab14cf86cb733cbaa761e7..44a69bb8d4f018e953cf0de692a9fb681a4a74b0 100644 (file)
@@ -274,9 +274,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
                return minor;
        }
        snd_minors[minor] = preg;
-       preg->dev = device_create_drvdata(sound_class, device,
-                                         MKDEV(major, minor),
-                                         private_data, "%s", name);
+       preg->dev = device_create(sound_class, device, MKDEV(major, minor),
+                                 private_data, "%s", name);
        if (IS_ERR(preg->dev)) {
                snd_minors[minor] = NULL;
                mutex_unlock(&sound_mutex);
index 83e90057270ead89f272ffe34fd6c3515a2b8a28..c13a178383ba0215e3edf14fca8d902973c88cc6 100644 (file)
@@ -87,8 +87,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
 static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
                             unsigned int cmd, unsigned long data)
 {
-       struct video_device *dev = video_devdata(file);
-       struct snd_tea575x *tea = video_get_drvdata(dev);
+       struct snd_tea575x *tea = video_drvdata(file);
        void __user *arg = (void __user *)data;
        
        switch(cmd) {
@@ -175,6 +174,21 @@ static void snd_tea575x_release(struct video_device *vfd)
 {
 }
 
+static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file)
+{
+       struct snd_tea575x *tea = video_drvdata(file);
+
+       return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0;
+}
+
+static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file)
+{
+       struct snd_tea575x *tea = video_drvdata(file);
+
+       clear_bit(0, &tea->in_use);
+       return 0;
+}
+
 /*
  * initialize all the tea575x chips
  */
@@ -193,9 +207,10 @@ void snd_tea575x_init(struct snd_tea575x *tea)
        tea->vd.release = snd_tea575x_release;
        video_set_drvdata(&tea->vd, tea);
        tea->vd.fops = &tea->fops;
+       tea->in_use = 0;
        tea->fops.owner = tea->card->module;
-       tea->fops.open = video_exclusive_open;
-       tea->fops.release = video_exclusive_release;
+       tea->fops.open = snd_tea575x_exclusive_open;
+       tea->fops.release = snd_tea575x_exclusive_release;
        tea->fops.ioctl = snd_tea575x_ioctl;
        if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) {
                snd_printk(KERN_ERR "unable to register tea575x tuner\n");
index b63839e8f9bd13c344c1efdcf6f45d7eff434b94..456a1b4d7832222b577d43e14dcde7b3baba2c9c 100644 (file)
@@ -30,7 +30,7 @@
  **************************************************************************
  *
  * History
- * May 02, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 02, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
  *     Removed non existant WM9700
  *     Added support for WM9705, WM9708, WM9709, WM9710, WM9711
  *     WM9712 and WM9717
index 7d89c081a0866bfe9b7ee22696ee286007cb0a2a..61aaedae6b7e084f8d7359d28fc88d9e4493e490 100644 (file)
@@ -560,19 +560,18 @@ static int __init oss_init(void)
        sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
        for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-               device_create_drvdata(sound_class, NULL,
-                                     MKDEV(SOUND_MAJOR, dev_list[i].minor),
-                                     NULL, "%s", dev_list[i].name);
+               device_create(sound_class, NULL,
+                             MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
+                             "%s", dev_list[i].name);
 
                if (!dev_list[i].num)
                        continue;
 
                for (j = 1; j < *dev_list[i].num; j++)
-                       device_create_drvdata(sound_class, NULL,
-                                             MKDEV(SOUND_MAJOR,
-                                                   dev_list[i].minor + (j*0x10)),
-                                             NULL,
-                                             "%s%d", dev_list[i].name, j);
+                       device_create(sound_class, NULL,
+                                     MKDEV(SOUND_MAJOR,
+                                           dev_list[i].minor + (j*0x10)),
+                                     NULL, "%s%d", dev_list[i].name, j);
        }
 
        if (sound_nblocks >= 1024)
index 6ce3cbe98a6a11d7212cfca404a01a73f6bf26bd..6e831aff1bd0e50ae3f38bc6484c0688b6084632 100644 (file)
@@ -476,7 +476,7 @@ static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
 }
 
 /*
- * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
  *  removed broken wolfson00 patch.
  *  added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
  */
index 0b6e682c46d06d64cc94011c93003c8519592ce5..e72707cb60a3394cd00334d94bb9a3c483f4bcea 100644 (file)
@@ -822,6 +822,27 @@ static void alc_sku_automute(struct hda_codec *codec)
                            spec->jack_present ? 0 : PIN_OUT);
 }
 
+static void alc_mic_automute(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int present;
+       unsigned int mic_nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
+       unsigned int fmic_nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
+       unsigned int mix_nid = spec->capsrc_nids[0];
+       unsigned int capsrc_idx_mic, capsrc_idx_fmic;
+
+       capsrc_idx_mic = mic_nid - 0x18;
+       capsrc_idx_fmic = fmic_nid - 0x18;
+       present = snd_hda_codec_read(codec, mic_nid, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+       snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                   0x7000 | (capsrc_idx_mic << 8) | (present ? 0 : 0x80));
+       snd_hda_codec_write(codec, mix_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                   0x7000 | (capsrc_idx_fmic << 8) | (present ? 0x80 : 0));
+       snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
+                        HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+}
+
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 {
@@ -829,10 +850,17 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
                res >>= 28;
        else
                res >>= 26;
-       if (res != ALC880_HP_EVENT)
-               return;
+       if (res == ALC880_HP_EVENT)
+               alc_sku_automute(codec);
+
+       if (res == ALC880_MIC_EVENT)
+               alc_mic_automute(codec);
+}
 
+static void alc_inithook(struct hda_codec *codec)
+{
        alc_sku_automute(codec);
+       alc_mic_automute(codec);
 }
 
 /* additional initialization for ALC888 variants */
@@ -1018,10 +1046,17 @@ do_sku:
                else
                        return;
        }
+       if (spec->autocfg.hp_pins[0])
+               snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
+                       AC_VERB_SET_UNSOLICITED_ENABLE,
+                       AC_USRSP_EN | ALC880_HP_EVENT);
 
-       snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0,
-                           AC_VERB_SET_UNSOLICITED_ENABLE,
-                           AC_USRSP_EN | ALC880_HP_EVENT);
+       if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
+               spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
+               snd_hda_codec_write(codec,
+                       spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
+                       AC_VERB_SET_UNSOLICITED_ENABLE,
+                       AC_USRSP_EN | ALC880_MIC_EVENT);
 
        spec->unsol_event = alc_sku_unsol_event;
 }
@@ -3808,7 +3843,7 @@ static void alc880_auto_init(struct hda_codec *codec)
        alc880_auto_init_extra_out(codec);
        alc880_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -5219,7 +5254,7 @@ static void alc260_auto_init(struct hda_codec *codec)
        alc260_auto_init_multi_out(codec);
        alc260_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -6629,7 +6664,7 @@ static void alc882_auto_init(struct hda_codec *codec)
        alc882_auto_init_analog_input(codec);
        alc882_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec); /* called in patch_alc882() */
@@ -8306,8 +8341,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
        SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
+       SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
        SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
-       SND_PCI_QUIRK(0x1043, 0x8317, "Asus M90V", ALC888_ASUS_M90V),
        SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
        SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
@@ -8758,7 +8793,7 @@ static void alc883_auto_init(struct hda_codec *codec)
        alc883_auto_init_analog_input(codec);
        alc883_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc883(struct hda_codec *codec)
@@ -8802,8 +8837,13 @@ static int patch_alc883(struct hda_codec *codec)
 
        switch (codec->vendor_id) {
        case 0x10ec0888:
-               spec->stream_name_analog = "ALC888 Analog";
-               spec->stream_name_digital = "ALC888 Digital";
+               if (codec->revision_id == 0x100101) {
+                       spec->stream_name_analog = "ALC1200 Analog";
+                       spec->stream_name_digital = "ALC1200 Digital";
+               } else {
+                       spec->stream_name_analog = "ALC888 Analog";
+                       spec->stream_name_digital = "ALC888 Digital";
+               }
                break;
        case 0x10ec0889:
                spec->stream_name_analog = "ALC889 Analog";
@@ -10285,7 +10325,7 @@ static void alc262_auto_init(struct hda_codec *codec)
        alc262_auto_init_analog_input(codec);
        alc262_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -10343,7 +10383,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
                      ALC262_TOSHIBA_RX1),
-       SND_PCI_QUIRK(0x1179, 0x0268, "Toshiba S06", ALC262_TOSHIBA_S06),
+       SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
        SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
@@ -11417,7 +11457,7 @@ static void alc268_auto_init(struct hda_codec *codec)
        alc268_auto_init_mono_speaker_out(codec);
        alc268_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -12200,7 +12240,7 @@ static void alc269_auto_init(struct hda_codec *codec)
        alc269_auto_init_hp_out(codec);
        alc269_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 /*
@@ -13281,7 +13321,7 @@ static void alc861_auto_init(struct hda_codec *codec)
        alc861_auto_init_hp_out(codec);
        alc861_auto_init_analog_input(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -14393,7 +14433,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
        alc861vd_auto_init_analog_input(codec);
        alc861vd_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc861vd(struct hda_codec *codec)
@@ -15667,7 +15707,7 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
 
 static struct snd_pci_quirk alc662_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
-       SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
+       SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
        SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
        SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
@@ -15680,6 +15720,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
+       SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
        SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
        SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
@@ -16223,7 +16264,7 @@ static void alc662_auto_init(struct hda_codec *codec)
        alc662_auto_init_analog_input(codec);
        alc662_auto_init_input_src(codec);
        if (spec->unsol_event)
-               alc_sku_automute(codec);
+               alc_inithook(codec);
 }
 
 static int patch_alc662(struct hda_codec *codec)
@@ -16268,6 +16309,9 @@ static int patch_alc662(struct hda_codec *codec)
        if (codec->vendor_id == 0x10ec0663) {
                spec->stream_name_analog = "ALC663 Analog";
                spec->stream_name_digital = "ALC663 Digital";
+       } else if (codec->vendor_id == 0x10ec0272) {
+               spec->stream_name_analog = "ALC272 Analog";
+               spec->stream_name_digital = "ALC272 Digital";
        } else {
                spec->stream_name_analog = "ALC662 Analog";
                spec->stream_name_digital = "ALC662 Digital";
@@ -16305,6 +16349,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
        { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
        { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
+       { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -16323,7 +16368,10 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
          .patch = patch_alc882 }, /* should be patch_alc883() in future */
        { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
+       { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc883 },
        { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
+       { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
+         .patch = patch_alc883 },
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
        {} /* terminator */
 };
index c461baa83c2a9ead2c669bc86460215340bbe4aa..a2ac7205d45de81706ef520e2c9dca69f5ce503d 100644 (file)
@@ -322,8 +322,8 @@ static hda_nid_t stac92hd71bxx_mux_nids[2] = {
        0x1a, 0x1b
 };
 
-static hda_nid_t stac92hd71bxx_dmux_nids[1] = {
-       0x1c,
+static hda_nid_t stac92hd71bxx_dmux_nids[2] = {
+       0x1c, 0x1d,
 };
 
 static hda_nid_t stac92hd71bxx_smux_nids[2] = {
@@ -861,20 +861,18 @@ static struct hda_verb stac92hd71bxx_core_init[] = {
        { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
        /* connect headphone jack to dac1 */
        { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
-       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
        /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
        { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 };
 
-#define HD_DISABLE_PORTF 3
+#define HD_DISABLE_PORTF 2
 static struct hda_verb stac92hd71bxx_analog_core_init[] = {
        /* start of config #1 */
 
        /* connect port 0f to audio mixer */
        { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
-       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
        /* unmute right and left channels for node 0x0f */
        { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        /* start of config #2 */
@@ -883,10 +881,6 @@ static struct hda_verb stac92hd71bxx_analog_core_init[] = {
        { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
        /* connect headphone jack to dac1 */
        { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
-       /* connect port 0d to audio mixer */
-       { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2},
-       /* unmute dac0 input in audio mixer */
-       { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
        /* unmute right and left channels for nodes 0x0a, 0xd */
        { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -1107,6 +1101,7 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = {
 
 static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
        STAC_INPUT_SOURCE(2),
+       STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2),
 
        HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT),
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT),
@@ -1119,8 +1114,17 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
        HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
        */
 
-       HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT),
-       HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT),
+       HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT),
+
+       HDA_CODEC_MUTE("Import1 Mux Capture Switch", 0x17, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Import1 Mux Capture Volume", 0x17, 0x1, HDA_INPUT),
+
+       HDA_CODEC_MUTE("DAC0 Capture Switch", 0x17, 0x3, HDA_INPUT),
+       HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x17, 0x3, HDA_INPUT),
+
+       HDA_CODEC_MUTE("DAC1 Capture Switch", 0x17, 0x4, HDA_INPUT),
+       HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x17, 0x4, HDA_INPUT),
        { } /* end */
 };
 
@@ -1649,7 +1653,7 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
 
 static unsigned int ref92hd71bxx_pin_configs[11] = {
        0x02214030, 0x02a19040, 0x01a19020, 0x01014010,
-       0x0181302e, 0x01114010, 0x01019020, 0x90a000f0,
+       0x0181302e, 0x01014010, 0x01019020, 0x90a000f0,
        0x90a000f0, 0x01452050, 0x01452050,
 };
 
@@ -2812,7 +2816,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
        static const char *chname[4] = {
                "Front", "Surround", NULL /*CLFE*/, "Side"
        };
-       hda_nid_t nid;
+       hda_nid_t nid = 0;
        int i, err;
 
        struct sigmatel_spec *spec = codec->spec;
@@ -3000,7 +3004,7 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
 
 /* labels for amp mux outputs */
 static const char *stac92xx_amp_labels[3] = {
-       "Front Microphone", "Microphone", "Line In"
+       "Front Microphone", "Microphone", "Line In",
 };
 
 /* create amp out controls mux on capable codecs */
@@ -4327,6 +4331,16 @@ static struct hda_codec_ops stac92hd71bxx_patch_ops = {
 #endif
 };
 
+static struct hda_input_mux stac92hd71bxx_dmux = {
+       .num_items = 4,
+       .items = {
+               { "Analog Inputs", 0x00 },
+               { "Mixer", 0x01 },
+               { "Digital Mic 1", 0x02 },
+               { "Digital Mic 2", 0x03 },
+       }
+};
+
 static int patch_stac92hd71bxx(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec;
@@ -4341,6 +4355,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
        spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
        spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
        spec->pin_nids = stac92hd71bxx_pin_nids;
+       memcpy(&spec->private_dimux, &stac92hd71bxx_dmux,
+                       sizeof(stac92hd71bxx_dmux));
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD71BXX_MODELS,
                                                        stac92hd71bxx_models,
@@ -4392,6 +4408,7 @@ again:
                /* no output amps */
                spec->num_pwrs = 0;
                spec->mixer = stac92hd71bxx_analog_mixer;
+               spec->dinput_mux = &spec->private_dimux;
 
                /* disable VSW */
                spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
@@ -4409,12 +4426,13 @@ again:
                spec->num_pwrs = 0;
                /* fallthru */
        default:
+               spec->dinput_mux = &spec->private_dimux;
                spec->mixer = stac92hd71bxx_analog_mixer;
                spec->init = stac92hd71bxx_analog_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
        }
 
-       spec->aloopback_mask = 0x20;
+       spec->aloopback_mask = 0x50;
        spec->aloopback_shift = 0;
 
        if (spec->board_config > STAC_92HD71BXX_REF) {
@@ -4456,6 +4474,10 @@ again:
        spec->multiout.num_dacs = 1;
        spec->multiout.hp_nid = 0x11;
        spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
+       if (spec->dinput_mux)
+               spec->private_dimux.num_items +=
+                       spec->num_dmics -
+                               (ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1);
 
        err = stac92xx_parse_auto_config(codec, 0x21, 0x23);
        if (!err) {
index 905186502e0009039efc81919022b9d4ffe44a54..85a883299c2e5dc10c72182f1e6a2d903c15d7dd 100644 (file)
@@ -8,20 +8,3 @@ config SND_AT91_SOC
 
 config SND_AT91_SOC_SSC
        tristate
-
-config SND_AT91_SOC_ETI_B1_WM8731
-       tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
-       depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
-       select SND_AT91_SOC_SSC
-       select SND_SOC_WM8731
-       help
-         Say Y if you want to add support for SoC audio on WM8731-based
-         Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
-
-config SND_AT91_SOC_ETI_SLAVE
-       bool "Run codec in slave Mode on Endrelia boards"
-       depends on SND_AT91_SOC_ETI_B1_WM8731
-       default n
-       help
-         Say Y if you want to run with the AT91 SSC generating the BCLK
-         and LRC signals on Endrelia boards.
index f23da17cc3288e0e11ac2e951ffcf2a14b3e87bd..b817f11df28669be198c3e3743a535b98e4a5aec 100644 (file)
@@ -4,8 +4,3 @@ snd-soc-at91-ssc-objs := at91-ssc.o
 
 obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
 obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
-
-# AT91 Machine Support
-snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
-
-obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
index a5b1a79ebffb5f72968ac949546bd59b1ae2dc5f..1b61cc4612618eedc61434fa23f559d54a0e4d3a 100644 (file)
@@ -5,7 +5,7 @@
  *         Endrelia Technologies Inc.
  *
  * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Liam Girdwood <lrg@slimlogic.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 the
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644 (file)
index 684781e..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * eti_b1_wm8731  --  SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
- *
- * Author:     Frank Mandarino <fmandarino@endrelia.com>
- *             Endrelia Technologies Inc.
- * Created:    Mar 29, 2006
- *
- * Based on corgi.c by:
- *
- * Copyright 2005 Wolfson Microelectronics PLC.
- * Copyright 2005 Openedhand Ltd.
- *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *          Richard Purdie <richard@openedhand.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-
-#include "../codecs/wm8731.h"
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define        DBG(x...)       printk(KERN_INFO "eti_b1_wm8731: " x)
-#else
-#define        DBG(x...)
-#endif
-
-static struct clk *pck1_clk;
-static struct clk *pllb_clk;
-
-
-static int eti_b1_startup(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       int ret;
-
-       /* cpu clock is the AT91 master clock sent to the SSC */
-       ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
-               60000000, SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       /* codec system clock is supplied by PCK1, set to 12MHz */
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
-               12000000, SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       /* Start PCK1 clock. */
-       clk_enable(pck1_clk);
-       DBG("pck1 started\n");
-
-       return 0;
-}
-
-static void eti_b1_shutdown(struct snd_pcm_substream *substream)
-{
-       /* Stop PCK1 clock. */
-       clk_disable(pck1_clk);
-       DBG("pck1 stopped\n");
-}
-
-static int eti_b1_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       int ret;
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-       unsigned int rate;
-       int cmr_div, period;
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-       if (ret < 0)
-               return ret;
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * The SSC clock dividers depend on the sample rate.  The CMR.DIV
-        * field divides the system master clock MCK to drive the SSC TK
-        * signal which provides the codec BCLK.  The TCMR.PERIOD and
-        * RCMR.PERIOD fields further divide the BCLK signal to drive
-        * the SSC TF and RF signals which provide the codec DACLRC and
-        * ADCLRC clocks.
-        *
-        * The dividers were determined through trial and error, where a
-        * CMR.DIV value is chosen such that the resulting BCLK value is
-        * divisible, or almost divisible, by (2 * sample rate), and then
-        * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
-        */
-       rate = params_rate(params);
-
-       switch (rate) {
-       case 8000:
-               cmr_div = 25;   /* BCLK = 60MHz/(2*25) = 1.2MHz */
-               period = 74;    /* LRC = BCLK/(2*(74+1)) = 8000Hz */
-               break;
-       case 32000:
-               cmr_div = 7;    /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
-               period = 66;    /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
-               break;
-       case 48000:
-               cmr_div = 13;   /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
-               period = 23;    /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
-               break;
-       default:
-               printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
-               return -EINVAL;
-       }
-
-       /* set the MCK divider for BCLK */
-       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
-       if (ret < 0)
-               return ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* set the BCLK divider for DACLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               AT91SSC_TCMR_PERIOD, period);
-       } else {
-               /* set the BCLK divider for ADCLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               AT91SSC_RCMR_PERIOD, period);
-       }
-       if (ret < 0)
-               return ret;
-
-#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-       /*
-        * Codec in Master Mode.
-        */
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-
-       return 0;
-}
-
-static struct snd_soc_ops eti_b1_ops = {
-       .startup = eti_b1_startup,
-       .hw_params = eti_b1_hw_params,
-       .shutdown = eti_b1_shutdown,
-};
-
-
-static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
-       SND_SOC_DAPM_MIC("Int Mic", NULL),
-       SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-
-       /* speaker connected to LHPOUT */
-       {"Ext Spk", NULL, "LHPOUT"},
-
-       /* mic is connected to Mic Jack, with WM8731 Mic Bias */
-       {"MICIN", NULL, "Mic Bias"},
-       {"Mic Bias", NULL, "Int Mic"},
-};
-
-/*
- * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
- */
-static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
-{
-       DBG("eti_b1_wm8731_init() called\n");
-
-       /* Add specific widgets */
-       snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
-                                 ARRAY_SIZE(eti_b1_dapm_widgets));
-
-       /* Set up specific audio path interconnects */
-       snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
-
-       /* not connected */
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-
-       /* always connected */
-       snd_soc_dapm_enable_pin(codec, "Int Mic");
-       snd_soc_dapm_enable_pin(codec, "Ext Spk");
-
-       snd_soc_dapm_sync(codec);
-
-       return 0;
-}
-
-static struct snd_soc_dai_link eti_b1_dai = {
-       .name = "WM8731",
-       .stream_name = "WM8731 PCM",
-       .cpu_dai = &at91_ssc_dai[1],
-       .codec_dai = &wm8731_dai,
-       .init = eti_b1_wm8731_init,
-       .ops = &eti_b1_ops,
-};
-
-static struct snd_soc_machine snd_soc_machine_eti_b1 = {
-       .name = "ETI_B1_WM8731",
-       .dai_link = &eti_b1_dai,
-       .num_links = 1,
-};
-
-static struct wm8731_setup_data eti_b1_wm8731_setup = {
-       .i2c_bus = 0,
-       .i2c_address = 0x1a,
-};
-
-static struct snd_soc_device eti_b1_snd_devdata = {
-       .machine = &snd_soc_machine_eti_b1,
-       .platform = &at91_soc_platform,
-       .codec_dev = &soc_codec_dev_wm8731,
-       .codec_data = &eti_b1_wm8731_setup,
-};
-
-static struct platform_device *eti_b1_snd_device;
-
-static int __init eti_b1_init(void)
-{
-       int ret;
-       struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
-       if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
-               DBG("SSC1 memory region is busy\n");
-               return -EBUSY;
-       }
-
-       ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
-       if (!ssc->base) {
-               DBG("SSC1 memory ioremap failed\n");
-               ret = -ENOMEM;
-               goto fail_release_mem;
-       }
-
-       ssc->pid = AT91RM9200_ID_SSC1;
-
-       eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!eti_b1_snd_device) {
-               DBG("platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto fail_io_unmap;
-       }
-
-       platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
-       eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
-
-       ret = platform_device_add(eti_b1_snd_device);
-       if (ret) {
-               DBG("platform device add failed\n");
-               platform_device_put(eti_b1_snd_device);
-               goto fail_io_unmap;
-       }
-
-       at91_set_A_periph(AT91_PIN_PB6, 0);     /* TF1 */
-       at91_set_A_periph(AT91_PIN_PB7, 0);     /* TK1 */
-       at91_set_A_periph(AT91_PIN_PB8, 0);     /* TD1 */
-       at91_set_A_periph(AT91_PIN_PB9, 0);     /* RD1 */
-/*     at91_set_A_periph(AT91_PIN_PB10, 0);*/  /* RK1 */
-       at91_set_A_periph(AT91_PIN_PB11, 0);    /* RF1 */
-
-       /*
-        * Set PCK1 parent to PLLB and its rate to 12 Mhz.
-        */
-       pllb_clk = clk_get(NULL, "pllb");
-       pck1_clk = clk_get(NULL, "pck1");
-
-       clk_set_parent(pck1_clk, pllb_clk);
-       clk_set_rate(pck1_clk, 12000000);
-
-       DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
-
-       /* assign the GPIO pin to PCK1 */
-       at91_set_B_periph(AT91_PIN_PA24, 0);
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-       printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
-#else
-       printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
-#endif
-       return ret;
-
-fail_io_unmap:
-       iounmap(ssc->base);
-fail_release_mem:
-       release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-       return ret;
-}
-
-static void __exit eti_b1_exit(void)
-{
-       struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
-       clk_put(pck1_clk);
-       clk_put(pllb_clk);
-
-       platform_device_unregister(eti_b1_snd_device);
-
-       iounmap(ssc->base);
-       release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-}
-
-module_init(eti_b1_init);
-module_exit(eti_b1_exit);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
-MODULE_LICENSE("GPL");
index f98331d099e7f05379b70dd1080f4477a4c7f39c..dc006206f622d043d4257162e71466f3b77bf0fb 100644 (file)
@@ -17,6 +17,22 @@ config SND_BF5XX_SOC_SSM2602
        help
          Say Y if you want to add support for SoC audio on BF527-EZKIT.
 
+config SND_BF5XX_SOC_AD73311
+       tristate "SoC AD73311 Audio support for Blackfin"
+       depends on SND_BF5XX_I2S
+       select SND_BF5XX_SOC_I2S
+       select SND_SOC_AD73311
+       help
+         Say Y if you want to add support for AD73311 codec on Blackfin.
+
+config SND_BFIN_AD73311_SE
+       int "PF pin for AD73311L Chip Select"
+       depends on SND_BF5XX_SOC_AD73311
+       default 4
+       help
+         Enter the GPIO used to control AD73311's SE pin. Acceptable
+         values are 0 to 7
+
 config SND_BF5XX_AC97
        tristate "SoC AC97 Audio for the ADI BF5xx chip"
        depends on BLACKFIN && SND_SOC
index 9ea8bd9e0ba3448471fdbfc3b52b7d76c27eb9b8..97bb37a6359c9b72816424658fdab4636c76fa36 100644 (file)
@@ -14,7 +14,8 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
 # Blackfin Machine Support
 snd-ad1980-objs := bf5xx-ad1980.o
 snd-ssm2602-objs := bf5xx-ssm2602.o
-
+snd-ad73311-objs := bf5xx-ad73311.o
 
 obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
 obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
+obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
index 51f4907c4831af2f86fb04aa4a3c7fa5b10e22d2..25e50d2ea1ec321d4140295f6d6ce587d79f0a9a 100644 (file)
@@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
                sport->tx_pos += runtime->period_size;
                if (sport->tx_pos >= runtime->buffer_size)
                        sport->tx_pos %= runtime->buffer_size;
+               sport->tx_delay_pos = sport->tx_pos;
        } else {
                bf5xx_ac97_to_pcm(
                        (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
@@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
        struct snd_pcm_substream *pcm = data;
 #if defined(CONFIG_SND_MMAP_SUPPORT)
        struct snd_pcm_runtime *runtime = pcm->runtime;
+       struct sport_device *sport = runtime->private_data;
        bf5xx_mmap_copy(pcm, runtime->period_size);
+       if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (sport->once == 0) {
+                       snd_pcm_period_elapsed(pcm);
+                       bf5xx_mmap_copy(pcm, runtime->period_size);
+                       sport->once = 1;
+               }
+       }
 #endif
        snd_pcm_period_elapsed(pcm);
 }
@@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
 
 static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       memset(runtime->dma_area, 0, runtime->buffer_size);
        snd_pcm_lib_free_pages(substream);
        return 0;
 }
@@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
         * SPORT working in TMD mode(include AC97).
         */
 #if defined(CONFIG_SND_MMAP_SUPPORT)
-       size_t size = bf5xx_pcm_hardware.buffer_bytes_max
-                       * sizeof(struct ac97_frame) / 4;
-       /*clean up intermediate buffer*/
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               memset(sport->tx_dma_buf, 0, size);
                sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
                sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
                        runtime->period_size * sizeof(struct ac97_frame));
        } else {
-               memset(sport->rx_dma_buf, 0, size);
                sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
                sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
                        runtime->period_size * sizeof(struct ac97_frame));
@@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        pr_debug("%s enter\n", __func__);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       bf5xx_mmap_copy(substream, runtime->period_size);
+                       snd_pcm_period_elapsed(substream);
+                       sport->tx_delay_pos = 0;
                        sport_tx_start(sport);
+               }
                else
                        sport_rx_start(sport);
                break;
@@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
 
 #if defined(CONFIG_SND_MMAP_SUPPORT)
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               curr = sport->tx_pos;
+               curr = sport->tx_delay_pos;
        else
                curr = sport->rx_pos;
 #else
@@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
        return ret;
 }
 
+static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sport_device *sport = runtime->private_data;
+
+       pr_debug("%s enter\n", __func__);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               sport->once = 0;
+               memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+       } else
+               memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+
+       return 0;
+}
+
 #ifdef CONFIG_SND_MMAP_SUPPORT
 static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
        struct vm_area_struct *vma)
@@ -272,6 +299,7 @@ static      int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
 
 struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
        .open           = bf5xx_pcm_open,
+       .close          = bf5xx_pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = bf5xx_pcm_hw_params,
        .hw_free        = bf5xx_pcm_hw_free,
index c782e311fd56a38d9c0ad04ccf11e82bd851c4f7..5e5aafb6485f0bce67bf211a24bc475db69f686b 100644 (file)
@@ -128,7 +128,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
        int nextfrag = sport_tx_curr_frag(sport);
        struct ac97_frame *nextwrite;
 
-       sport_incfrag(sport, &nextfrag, 1);
        sport_incfrag(sport, &nextfrag, 1);
 
        nextwrite = (struct ac97_frame *)(sport->tx_buf + \
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644 (file)
index 0000000..622c9b9
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-ad73311.c
+ * Author:       Cliff Cai <Cliff.Cai@analog.com>
+ *
+ * Created:      Thur Sep 25 2008
+ * Description:  Board driver for ad73311 sound chip
+ *
+ * Modified:
+ *               Copyright 2008 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include "../codecs/ad73311.h"
+#include "bf5xx-sport.h"
+#include "bf5xx-i2s-pcm.h"
+#include "bf5xx-i2s.h"
+
+#if CONFIG_SND_BF5XX_SPORT_NUM == 0
+#define bfin_write_SPORT_TCR1  bfin_write_SPORT0_TCR1
+#define bfin_read_SPORT_TCR1   bfin_read_SPORT0_TCR1
+#define bfin_write_SPORT_TCR2  bfin_write_SPORT0_TCR2
+#define bfin_write_SPORT_TX16  bfin_write_SPORT0_TX16
+#define bfin_read_SPORT_STAT   bfin_read_SPORT0_STAT
+#else
+#define bfin_write_SPORT_TCR1  bfin_write_SPORT1_TCR1
+#define bfin_read_SPORT_TCR1   bfin_read_SPORT1_TCR1
+#define bfin_write_SPORT_TCR2  bfin_write_SPORT1_TCR2
+#define bfin_write_SPORT_TX16  bfin_write_SPORT1_TX16
+#define bfin_read_SPORT_STAT   bfin_read_SPORT1_STAT
+#endif
+
+#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
+
+static struct snd_soc_machine bf5xx_ad73311;
+
+static int snd_ad73311_startup(void)
+{
+       pr_debug("%s enter\n", __func__);
+
+       /* Pull up SE pin on AD73311L */
+       gpio_set_value(GPIO_SE, 1);
+       return 0;
+}
+
+static int snd_ad73311_configure(void)
+{
+       unsigned short ctrl_regs[6];
+       unsigned short status = 0;
+       int count = 0;
+
+       /* DMCLK = MCLK = 16.384 MHz
+        * SCLK = DMCLK/8 = 2.048 MHz
+        * Sample Rate = DMCLK/2048  = 8 KHz
+        */
+       ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
+                       REGB_SCDIV(0) | REGB_DIRATE(0);
+       ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
+                       REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
+       ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
+                       REGD_IGS(2);
+       ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
+       ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
+       ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
+
+       local_irq_disable();
+       snd_ad73311_startup();
+       udelay(1);
+
+       bfin_write_SPORT_TCR1(TFSR);
+       bfin_write_SPORT_TCR2(0xF);
+       SSYNC();
+
+       /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
+        * FIFO before enable SPORT to transfer the data
+        */
+       for (count = 0; count < 6; count++)
+               bfin_write_SPORT_TX16(ctrl_regs[count]);
+       SSYNC();
+       bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
+       SSYNC();
+
+       /* When TUVF is set, the data is already send out */
+       while (!(status & TUVF) && count++ < 10000) {
+               udelay(1);
+               status = bfin_read_SPORT_STAT();
+               SSYNC();
+       }
+       bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
+       SSYNC();
+       local_irq_enable();
+
+       if (count == 10000) {
+               printk(KERN_ERR "ad73311: failed to configure codec\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int bf5xx_probe(struct platform_device *pdev)
+{
+       int err;
+       if (gpio_request(GPIO_SE, "AD73311_SE")) {
+               printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
+               return -EBUSY;
+       }
+
+       gpio_direction_output(GPIO_SE, 0);
+
+       err = snd_ad73311_configure();
+       if (err < 0)
+               return -EFAULT;
+
+       return 0;
+}
+
+static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       pr_debug("%s enter\n", __func__);
+       cpu_dai->private_data = sport_handle;
+       return 0;
+}
+
+static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret = 0;
+
+       pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
+               params_format(params));
+
+       /* set cpu DAI configuration */
+       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+
+static struct snd_soc_ops bf5xx_ad73311_ops = {
+       .startup = bf5xx_ad73311_startup,
+       .hw_params = bf5xx_ad73311_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_ad73311_dai = {
+       .name = "ad73311",
+       .stream_name = "AD73311",
+       .cpu_dai = &bf5xx_i2s_dai,
+       .codec_dai = &ad73311_dai,
+       .ops = &bf5xx_ad73311_ops,
+};
+
+static struct snd_soc_machine bf5xx_ad73311 = {
+       .name = "bf5xx_ad73311",
+       .probe = bf5xx_probe,
+       .dai_link = &bf5xx_ad73311_dai,
+       .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
+       .machine = &bf5xx_ad73311,
+       .platform = &bf5xx_i2s_soc_platform,
+       .codec_dev = &soc_codec_dev_ad73311,
+};
+
+static struct platform_device *bf52x_ad73311_snd_device;
+
+static int __init bf5xx_ad73311_init(void)
+{
+       int ret;
+
+       pr_debug("%s enter\n", __func__);
+       bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bf52x_ad73311_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
+       bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
+       ret = platform_device_add(bf52x_ad73311_snd_device);
+
+       if (ret)
+               platform_device_put(bf52x_ad73311_snd_device);
+
+       return ret;
+}
+
+static void __exit bf5xx_ad73311_exit(void)
+{
+       pr_debug("%s enter\n", __func__);
+       platform_device_unregister(bf52x_ad73311_snd_device);
+}
+
+module_init(bf5xx_ad73311_init);
+module_exit(bf5xx_ad73311_exit);
+
+/* Module information */
+MODULE_AUTHOR("Cliff Cai");
+MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
+MODULE_LICENSE("GPL");
+
index 43a4092eeb89f0d623df6b5fa0dda8b6a24d6bb8..827587f08180de31774c0fdc79817189d2bf605b 100644 (file)
@@ -70,6 +70,13 @@ static struct sport_param sport_params[2] = {
        }
 };
 
+static u16 sport_req[][7] = {
+               { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+                 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
+               { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+                 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
+};
+
 static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
@@ -78,6 +85,14 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        /* interface format:support I2S,slave mode */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
+               bf5xx_i2s.tcr1 |= TFSR | TCKFE;
+               bf5xx_i2s.rcr1 |= RFSR | RCKFE;
+               bf5xx_i2s.tcr2 |= TSFSE;
+               bf5xx_i2s.rcr2 |= RSFSE;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               bf5xx_i2s.tcr1 |= TFSR;
+               bf5xx_i2s.rcr1 |= RFSR;
                break;
        case SND_SOC_DAIFMT_LEFT_J:
                ret = -EINVAL;
@@ -127,14 +142,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S16_LE:
                bf5xx_i2s.tcr2 |= 15;
                bf5xx_i2s.rcr2 |= 15;
+               sport_handle->wdsize = 2;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
                bf5xx_i2s.tcr2 |= 23;
                bf5xx_i2s.rcr2 |= 23;
+               sport_handle->wdsize = 3;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                bf5xx_i2s.tcr2 |= 31;
                bf5xx_i2s.rcr2 |= 31;
+               sport_handle->wdsize = 4;
                break;
        }
 
@@ -145,17 +163,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
                 * need to configure both of them at the time when the first
                 * stream is opened.
                 *
-                * CPU DAI format:I2S, slave mode.
+                * CPU DAI:slave mode.
                 */
-               ret = sport_config_rx(sport_handle, RFSR | RCKFE,
-                                     RSFSE|bf5xx_i2s.rcr2, 0, 0);
+               ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
+                                     bf5xx_i2s.rcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
                }
 
-               ret = sport_config_tx(sport_handle, TFSR | TCKFE,
-                                     TSFSE|bf5xx_i2s.tcr2, 0, 0);
+               ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
+                                     bf5xx_i2s.tcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
@@ -174,13 +192,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
 static int bf5xx_i2s_probe(struct platform_device *pdev,
                           struct snd_soc_dai *dai)
 {
-       u16 sport_req[][7] = {
-               { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-                 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
-               { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-                 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
-       };
-
        pr_debug("%s enter\n", __func__);
        if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
                pr_err("Requesting Peripherals failed\n");
@@ -198,6 +209,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
        return 0;
 }
 
+static void bf5xx_i2s_remove(struct platform_device *pdev,
+                          struct snd_soc_dai *dai)
+{
+       pr_debug("%s enter\n", __func__);
+       peripheral_free_list(&sport_req[sport_num][0]);
+}
+
 #ifdef CONFIG_PM
 static int bf5xx_i2s_suspend(struct platform_device *dev,
                             struct snd_soc_dai *dai)
@@ -263,15 +281,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
        .id = 0,
        .type = SND_SOC_DAI_I2S,
        .probe = bf5xx_i2s_probe,
+       .remove = bf5xx_i2s_remove,
        .suspend = bf5xx_i2s_suspend,
        .resume = bf5xx_i2s_resume,
        .playback = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = BF5XX_I2S_RATES,
                .formats = BF5XX_I2S_FORMATS,},
        .capture = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = BF5XX_I2S_RATES,
                .formats = BF5XX_I2S_FORMATS,},
index 4c163454bbf8410570e2f8e43cf06da224cae66e..fcadcc081f7fe4994a2dc3dbc0514656c7c6cd06 100644 (file)
@@ -123,6 +123,8 @@ struct sport_device {
        int rx_pos;
        unsigned int tx_buffer_size;
        unsigned int rx_buffer_size;
+       int tx_delay_pos;
+       int once;
 #endif
        void *private_data;
 };
index e0b9869df0f107ed2876a2a8b9c8893ff8740cd5..38a0e3b620a750ad4845ee861f18b323b74cf0f4 100644 (file)
@@ -3,9 +3,11 @@ config SND_SOC_ALL_CODECS
        depends on I2C
        select SPI
        select SPI_MASTER
+       select SND_SOC_AD73311
        select SND_SOC_AK4535
        select SND_SOC_CS4270
        select SND_SOC_SSM2602
+       select SND_SOC_TLV320AIC23
        select SND_SOC_TLV320AIC26
        select SND_SOC_TLV320AIC3X
        select SND_SOC_UDA1380
@@ -34,6 +36,9 @@ config SND_SOC_AC97_CODEC
 config SND_SOC_AD1980
        tristate
 
+config SND_SOC_AD73311
+       tristate
+
 config SND_SOC_AK4535
        tristate
 
@@ -58,9 +63,13 @@ config SND_SOC_CS4270_VD33_ERRATA
 config SND_SOC_SSM2602
        tristate
 
+config SND_SOC_TLV320AIC23
+       tristate
+       depends on I2C
+
 config SND_SOC_TLV320AIC26
-       tristate "TI TLV320AIC26 Codec support"
-       depends on SND_SOC && SPI
+       tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
+       depends on SPI
 
 config SND_SOC_TLV320AIC3X
        tristate
index f977978a3409e2c19584f1819ddde1989bd9aeef..90f0a585fc70e1f5a4d9a9be1b8514a22100917a 100644 (file)
@@ -1,8 +1,10 @@
 snd-soc-ac97-objs := ac97.o
 snd-soc-ad1980-objs := ad1980.o
+snd-soc-ad73311-objs := ad73311.o
 snd-soc-ak4535-objs := ak4535.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-ssm2602-objs := ssm2602.o
+snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 snd-soc-uda1380-objs := uda1380.o
@@ -20,9 +22,11 @@ snd-soc-wm9713-objs := wm9713.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_AD1980)   += snd-soc-ad1980.o
+obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
 obj-$(CONFIG_SND_SOC_AK4535)   += snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23)      += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)      += snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)      += snd-soc-tlv320aic3x.o
 obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
index 61fd96ca7bc782588e17655ebd8dd12887837e75..bd1ebdc6c86ce0e6ef021139f5ac10b93831f4d4 100644 (file)
@@ -2,8 +2,7 @@
  * ac97.c  --  ALSA Soc AC97 codec support
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
index 4e09c1f2c063a3f335188d043314ff0dd525f8ac..1397b8e06c0b41eda7002815a276baba8f3ea035 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <sound/core.h>
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
new file mode 100644 (file)
index 0000000..37af860
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * ad73311.c  --  ALSA Soc AD73311 codec support
+ *
+ * Copyright:  Analog Device Inc.
+ * Author:     Cliff Cai <cliff.cai@analog.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.
+ *
+ *  Revision history
+ *    25th Sep 2008   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "ad73311.h"
+
+struct snd_soc_dai ad73311_dai = {
+       .name = "AD73311",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+};
+EXPORT_SYMBOL_GPL(ad73311_dai);
+
+static int ad73311_soc_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+       mutex_init(&codec->mutex);
+       codec->name = "AD73311";
+       codec->owner = THIS_MODULE;
+       codec->dai = &ad73311_dai;
+       codec->num_dai = 1;
+       socdev->codec = codec;
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "ad73311: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "ad73311: failed to register card\n");
+               goto register_err;
+       }
+
+       return ret;
+
+register_err:
+       snd_soc_free_pcms(socdev);
+pcm_err:
+       kfree(socdev->codec);
+       socdev->codec = NULL;
+       return ret;
+}
+
+static int ad73311_soc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec == NULL)
+               return 0;
+       snd_soc_free_pcms(socdev);
+       kfree(codec);
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ad73311 = {
+       .probe =        ad73311_soc_probe,
+       .remove =       ad73311_soc_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
+
+MODULE_DESCRIPTION("ASoC ad73311 driver");
+MODULE_AUTHOR("Cliff Cai ");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
new file mode 100644 (file)
index 0000000..507ce0c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * File:         sound/soc/codec/ad73311.h
+ * Based on:
+ * Author:       Cliff Cai <cliff.cai@analog.com>
+ *
+ * Created:      Thur Sep 25, 2008
+ * Description:  definitions for AD73311 registers
+ *
+ *
+ * Modified:
+ *               Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AD73311_H__
+#define __AD73311_H__
+
+#define AD_CONTROL     0x8000
+#define AD_DATA                0x0000
+#define AD_READ                0x4000
+#define AD_WRITE       0x0000
+
+/* Control register A */
+#define CTRL_REG_A     (0 << 8)
+
+#define REGA_MODE_PRO  0x00
+#define REGA_MODE_DATA 0x01
+#define REGA_MODE_MIXED        0x03
+#define REGA_DLB               0x04
+#define REGA_SLB               0x08
+#define REGA_DEVC(x)           ((x & 0x7) << 4)
+#define REGA_RESET             0x80
+
+/* Control register B */
+#define CTRL_REG_B     (1 << 8)
+
+#define REGB_DIRATE(x) (x & 0x3)
+#define REGB_SCDIV(x)  ((x & 0x3) << 2)
+#define REGB_MCDIV(x)  ((x & 0x7) << 4)
+#define REGB_CEE               (1 << 7)
+
+/* Control register C */
+#define CTRL_REG_C     (2 << 8)
+
+#define REGC_PUDEV             (1 << 0)
+#define REGC_PUADC             (1 << 3)
+#define REGC_PUDAC             (1 << 4)
+#define REGC_PUREF             (1 << 5)
+#define REGC_REFUSE            (1 << 6)
+
+/* Control register D */
+#define CTRL_REG_D     (3 << 8)
+
+#define REGD_IGS(x)            (x & 0x7)
+#define REGD_RMOD              (1 << 3)
+#define REGD_OGS(x)            ((x & 0x7) << 4)
+#define REGD_MUTE              (x << 7)
+
+/* Control register E */
+#define CTRL_REG_E     (4 << 8)
+
+#define REGE_DA(x)             (x & 0x1f)
+#define REGE_IBYP              (1 << 5)
+
+/* Control register F */
+#define CTRL_REG_F     (5 << 8)
+
+#define REGF_SEEN              (1 << 5)
+#define REGF_INV               (1 << 6)
+#define REGF_ALB               (1 << 7)
+
+extern struct snd_soc_dai ad73311_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ad73311;
+#endif
index 088cf99277203ff4d729d722629ed8cf222f2cb0..2a89b5888e11c33bdedf44b817e0c61282b95d0d 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "ak4535.h"
 
-#define AUDIO_NAME "ak4535"
 #define AK4535_VERSION "0.3"
 
 struct snd_soc_codec_device soc_codec_dev_ak4535;
index 940ce1c3522e007733c9bfc9066d822f21727077..44ef0dacd564701b3999316d9c2e21c5b41ec4a8 100644 (file)
@@ -42,7 +42,6 @@
 
 #include "ssm2602.h"
 
-#define AUDIO_NAME "ssm2602"
 #define SSM2602_VERSION "0.1"
 
 struct snd_soc_codec_device soc_codec_dev_ssm2602;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
new file mode 100644 (file)
index 0000000..44308da
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author:      Arun KS, <arunks@mistralsolutions.com>
+ * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Notes:
+ *  The AIC23 is a driver for a low power stereo audio
+ *  codec tlv320aic23
+ *
+ *  The machine layer should disable unsupported inputs/outputs by
+ *  snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+
+#include "tlv320aic23.h"
+
+#define AIC23_VERSION "0.1"
+
+struct tlv320aic23_srate_reg_info {
+       u32 sample_rate;
+       u8 control;             /* SR3, SR2, SR1, SR0 and BOSR */
+       u8 divider;             /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
+/*
+ * AIC23 register cache
+ */
+static const u16 tlv320aic23_reg[] = {
+       0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
+       0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
+       0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
+       0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
+};
+
+/*
+ * read tlv320aic23 register cache
+ */
+static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
+                                                     *codec, unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+               return -1;
+       return cache[reg];
+}
+
+/*
+ * write tlv320aic23 register cache
+ */
+static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
+                                              u8 reg, u16 value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+               return;
+       cache[reg] = value;
+}
+
+/*
+ * write to the tlv320aic23 register space
+ */
+static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
+                            unsigned int value)
+{
+
+       u8 data[2];
+
+       /* TLV320AIC23 has 7 bit address and 9 bits of data
+        * so we need to switch one data bit into reg and rest
+        * of data into val
+        */
+
+       if ((reg < 0 || reg > 9) && (reg != 15)) {
+               printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg);
+               return -1;
+       }
+
+       data[0] = (reg << 1) | (value >> 8 & 0x01);
+       data[1] = value & 0xff;
+
+       tlv320aic23_write_reg_cache(codec, reg, value);
+
+       if (codec->hw_write(codec->control_data, data, 2) == 2)
+               return 0;
+
+       printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
+              value, reg);
+
+       return -EIO;
+}
+
+static const char *rec_src_text[] = { "Line", "Mic" };
+static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+
+static const struct soc_enum rec_src_enum =
+       SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+
+static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
+SOC_DAPM_ENUM("Input Select", rec_src_enum);
+
+static const struct soc_enum tlv320aic23_rec_src =
+       SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+static const struct soc_enum tlv320aic23_deemph =
+       SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
+
+static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
+static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
+
+static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 val, reg;
+
+       val = (ucontrol->value.integer.value[0] & 0x07);
+
+       /* linear conversion to userspace
+       * 000   =       -6db
+       * 001   =       -9db
+       * 010   =       -12db
+       * 011   =       -18db (Min)
+       * 100   =       0db (Max)
+       */
+       val = (val >= 4) ? 4  : (3 - val);
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
+       tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+
+       return 0;
+}
+
+static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 val;
+
+       val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+       val = val >> 6;
+       val = (val >= 4) ? 4  : (3 -  val);
+       ucontrol->value.integer.value[0] = val;
+       return 0;
+
+}
+
+#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
+       .put = snd_soc_tlv320aic23_put_volsw, \
+       .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
+       SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
+                        TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
+       SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
+       SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
+                    TLV320AIC23_RINVOL, 7, 1, 0),
+       SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
+                        TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
+       SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
+       SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
+       SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
+                                 6, 4, 0, sidetone_vol_tlv),
+       SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
+};
+
+/* add non dapm controls */
+static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
+{
+
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                                 snd_soc_cnew(&tlv320aic23_snd_controls[i],
+                                              codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+
+}
+
+/* PGA Mixer controls for Line and Mic switch */
+static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
+       SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
+       SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+       SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
+       SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
+       SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
+                        &tlv320aic23_rec_src_mux_controls),
+       SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
+                          &tlv320aic23_output_mixer_controls[0],
+                          ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
+       SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
+
+       SND_SOC_DAPM_OUTPUT("LHPOUT"),
+       SND_SOC_DAPM_OUTPUT("RHPOUT"),
+       SND_SOC_DAPM_OUTPUT("LOUT"),
+       SND_SOC_DAPM_OUTPUT("ROUT"),
+
+       SND_SOC_DAPM_INPUT("LLINEIN"),
+       SND_SOC_DAPM_INPUT("RLINEIN"),
+
+       SND_SOC_DAPM_INPUT("MICIN"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+       /* Output Mixer */
+       {"Output Mixer", "Line Bypass Switch", "Line Input"},
+       {"Output Mixer", "Playback Switch", "DAC"},
+       {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
+
+       /* Outputs */
+       {"RHPOUT", NULL, "Output Mixer"},
+       {"LHPOUT", NULL, "Output Mixer"},
+       {"LOUT", NULL, "Output Mixer"},
+       {"ROUT", NULL, "Output Mixer"},
+
+       /* Inputs */
+       {"Line Input", "NULL", "LLINEIN"},
+       {"Line Input", "NULL", "RLINEIN"},
+
+       {"Mic Input", "NULL", "MICIN"},
+
+       /* input mux */
+       {"Capture Source", "Line", "Line Input"},
+       {"Capture Source", "Mic", "Mic Input"},
+       {"ADC", NULL, "Capture Source"},
+
+};
+
+/* tlv320aic23 related */
+static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
+       {4000, 0x06, 1},        /*  4000 */
+       {8000, 0x06, 0},        /*  8000 */
+       {16000, 0x0C, 1},       /* 16000 */
+       {22050, 0x11, 1},       /* 22050 */
+       {24000, 0x00, 1},       /* 24000 */
+       {32000, 0x0C, 0},       /* 32000 */
+       {44100, 0x11, 0},       /* 44100 */
+       {48000, 0x00, 0},       /* 48000 */
+       {88200, 0x1F, 0},       /* 88200 */
+       {96000, 0x0E, 0},       /* 96000 */
+};
+
+static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+       /* set up audio path interconnects */
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 iface_reg, data;
+       u8 count = 0;
+
+       iface_reg =
+           tlv320aic23_read_reg_cache(codec,
+                                      TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
+       /* Search for the right sample rate */
+       /* Verify what happens if the rate is not supported
+        * now it goes to 96Khz */
+       while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
+              (count < ARRAY_SIZE(srate_reg_info))) {
+               count++;
+       }
+
+       data =  (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
+               (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
+               TLV320AIC23_USB_CLK_ON;
+
+       tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface_reg |= (0x01 << 2);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface_reg |= (0x02 << 2);
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               iface_reg |= (0x03 << 2);
+               break;
+       }
+       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+       return 0;
+}
+
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+
+       /* set active */
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+
+       return 0;
+}
+
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+
+       /* deactivate */
+       if (!codec->active) {
+               udelay(50);
+               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+       }
+}
+
+static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 reg;
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+       if (mute)
+               reg |= TLV320AIC23_DACM_MUTE;
+
+       else
+               reg &= ~TLV320AIC23_DACM_MUTE;
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+
+       return 0;
+}
+
+static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                  unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface_reg;
+
+       iface_reg =
+           tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               iface_reg |= TLV320AIC23_MS_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+
+       }
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface_reg |= TLV320AIC23_FOR_I2S;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface_reg |= TLV320AIC23_FOR_DSP;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface_reg |= TLV320AIC23_FOR_LJUST;
+               break;
+       default:
+               return -EINVAL;
+
+       }
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+       return 0;
+}
+
+static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                     int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+
+       switch (freq) {
+       case 12000000:
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
+                                     enum snd_soc_bias_level level)
+{
+       u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               /* vref/mid, osc on, dac unmute */
+               tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               /* everything off except vref/vmid, */
+               tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040);
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* everything off, dac mute, inactive */
+               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+               tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define AIC23_RATES    SNDRV_PCM_RATE_8000_96000
+#define AIC23_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+                        SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai tlv320aic23_dai = {
+       .name = "tlv320aic23",
+       .playback = {
+                    .stream_name = "Playback",
+                    .channels_min = 2,
+                    .channels_max = 2,
+                    .rates = AIC23_RATES,
+                    .formats = AIC23_FORMATS,},
+       .capture = {
+                   .stream_name = "Capture",
+                   .channels_min = 2,
+                   .channels_max = 2,
+                   .rates = AIC23_RATES,
+                   .formats = AIC23_FORMATS,},
+       .ops = {
+               .prepare = tlv320aic23_pcm_prepare,
+               .hw_params = tlv320aic23_hw_params,
+               .shutdown = tlv320aic23_shutdown,
+               },
+       .dai_ops = {
+                   .digital_mute = tlv320aic23_mute,
+                   .set_fmt = tlv320aic23_set_dai_fmt,
+                   .set_sysclk = tlv320aic23_set_dai_sysclk,
+                   }
+};
+EXPORT_SYMBOL_GPL(tlv320aic23_dai);
+
+static int tlv320aic23_suspend(struct platform_device *pdev,
+                              pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int tlv320aic23_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       int i;
+       u16 reg;
+
+       /* Sync reg_cache with the hardware */
+       for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) {
+               u16 val = tlv320aic23_read_reg_cache(codec, reg);
+               tlv320aic23_write(codec, reg, val);
+       }
+
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
+
+       return 0;
+}
+
+/*
+ * initialise the AIC23 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int tlv320aic23_init(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret = 0;
+       u16 reg;
+
+       codec->name = "tlv320aic23";
+       codec->owner = THIS_MODULE;
+       codec->read = tlv320aic23_read_reg_cache;
+       codec->write = tlv320aic23_write;
+       codec->set_bias_level = tlv320aic23_set_bias_level;
+       codec->dai = &tlv320aic23_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
+       codec->reg_cache =
+           kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       /* Reset codec */
+       tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* power on device */
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+
+       /* Unmute input */
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
+       tlv320aic23_write(codec, TLV320AIC23_LINVOL,
+                         (reg & (~TLV320AIC23_LIM_MUTED)) |
+                         (TLV320AIC23_LRS_ENABLED));
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
+       tlv320aic23_write(codec, TLV320AIC23_RINVOL,
+                         (reg & (~TLV320AIC23_LIM_MUTED)) |
+                         TLV320AIC23_LRS_ENABLED);
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
+       tlv320aic23_write(codec, TLV320AIC23_ANLG,
+                        (reg) & (~TLV320AIC23_BYPASS_ON) &
+                        (~TLV320AIC23_MICM_MUTED));
+
+       /* Default output volume */
+       tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
+                         TLV320AIC23_DEFAULT_OUT_VOL &
+                         TLV320AIC23_OUT_VOL_MASK);
+       tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
+                         TLV320AIC23_DEFAULT_OUT_VOL &
+                         TLV320AIC23_OUT_VOL_MASK);
+
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+
+       tlv320aic23_add_controls(codec);
+       tlv320aic23_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+       return ret;
+}
+static struct snd_soc_device *tlv320aic23_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+/*
+ * If the i2c layer weren't so broken, we could pass this kind of data
+ * around
+ */
+static int tlv320aic23_codec_probe(struct i2c_client *i2c,
+                                  const struct i2c_device_id *i2c_id)
+{
+       struct snd_soc_device *socdev = tlv320aic23_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EINVAL;
+
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = tlv320aic23_init(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
+{
+       put_device(&i2c->dev);
+       return 0;
+}
+
+static const struct i2c_device_id tlv320aic23_id[] = {
+       {"tlv320aic23", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
+
+static struct i2c_driver tlv320aic23_i2c_driver = {
+       .driver = {
+                  .name = "tlv320aic23",
+                  },
+       .probe = tlv320aic23_codec_probe,
+       .remove = __exit_p(tlv320aic23_i2c_remove),
+       .id_table = tlv320aic23_id,
+};
+
+#endif
+
+static int tlv320aic23_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       tlv320aic23_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       codec->hw_write = (hw_write_t) i2c_master_send;
+       codec->hw_read = NULL;
+       ret = i2c_add_driver(&tlv320aic23_i2c_driver);
+       if (ret != 0)
+               printk(KERN_ERR "can't add i2c driver");
+#endif
+       return ret;
+}
+
+static int tlv320aic23_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&tlv320aic23_i2c_driver);
+#endif
+       kfree(codec->reg_cache);
+       kfree(codec);
+
+       return 0;
+}
+struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
+       .probe = tlv320aic23_probe,
+       .remove = tlv320aic23_remove,
+       .suspend = tlv320aic23_suspend,
+       .resume = tlv320aic23_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
new file mode 100644 (file)
index 0000000..79d1faf
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author:      Arun KS, <arunks@mistralsolutions.com>
+ * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd
+ *
+ * This program is free software; you can 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 _TLV320AIC23_H
+#define _TLV320AIC23_H
+
+/* Codec TLV320AIC23 */
+#define TLV320AIC23_LINVOL             0x00
+#define TLV320AIC23_RINVOL             0x01
+#define TLV320AIC23_LCHNVOL            0x02
+#define TLV320AIC23_RCHNVOL            0x03
+#define TLV320AIC23_ANLG               0x04
+#define TLV320AIC23_DIGT               0x05
+#define TLV320AIC23_PWR                        0x06
+#define TLV320AIC23_DIGT_FMT           0x07
+#define TLV320AIC23_SRATE              0x08
+#define TLV320AIC23_ACTIVE             0x09
+#define TLV320AIC23_RESET              0x0F
+
+/* Left (right) line input volume control register */
+#define TLV320AIC23_LRS_ENABLED                0x0100
+#define TLV320AIC23_LIM_MUTED          0x0080
+#define TLV320AIC23_LIV_DEFAULT                0x0017
+#define TLV320AIC23_LIV_MAX            0x001f
+#define TLV320AIC23_LIV_MIN            0x0000
+
+/* Left (right) channel headphone volume control register */
+#define TLV320AIC23_LZC_ON             0x0080
+#define TLV320AIC23_LHV_DEFAULT                0x0079
+#define TLV320AIC23_LHV_MAX            0x007f
+#define TLV320AIC23_LHV_MIN            0x0000
+
+/* Analog audio path control register */
+#define TLV320AIC23_STA_REG(x)         ((x)<<6)
+#define TLV320AIC23_STE_ENABLED                0x0020
+#define TLV320AIC23_DAC_SELECTED       0x0010
+#define TLV320AIC23_BYPASS_ON          0x0008
+#define TLV320AIC23_INSEL_MIC          0x0004
+#define TLV320AIC23_MICM_MUTED         0x0002
+#define TLV320AIC23_MICB_20DB          0x0001
+
+/* Digital audio path control register */
+#define TLV320AIC23_DACM_MUTE          0x0008
+#define TLV320AIC23_DEEMP_32K          0x0002
+#define TLV320AIC23_DEEMP_44K          0x0004
+#define TLV320AIC23_DEEMP_48K          0x0006
+#define TLV320AIC23_ADCHP_ON           0x0001
+
+/* Power control down register */
+#define TLV320AIC23_DEVICE_PWR_OFF     0x0080
+#define TLV320AIC23_CLK_OFF            0x0040
+#define TLV320AIC23_OSC_OFF            0x0020
+#define TLV320AIC23_OUT_OFF            0x0010
+#define TLV320AIC23_DAC_OFF            0x0008
+#define TLV320AIC23_ADC_OFF            0x0004
+#define TLV320AIC23_MIC_OFF            0x0002
+#define TLV320AIC23_LINE_OFF           0x0001
+
+/* Digital audio interface register */
+#define TLV320AIC23_MS_MASTER          0x0040
+#define TLV320AIC23_LRSWAP_ON          0x0020
+#define TLV320AIC23_LRP_ON             0x0010
+#define TLV320AIC23_IWL_16             0x0000
+#define TLV320AIC23_IWL_20             0x0004
+#define TLV320AIC23_IWL_24             0x0008
+#define TLV320AIC23_IWL_32             0x000C
+#define TLV320AIC23_FOR_I2S            0x0002
+#define TLV320AIC23_FOR_DSP            0x0003
+#define TLV320AIC23_FOR_LJUST          0x0001
+
+/* Sample rate control register */
+#define TLV320AIC23_CLKOUT_HALF                0x0080
+#define TLV320AIC23_CLKIN_HALF         0x0040
+#define TLV320AIC23_BOSR_384fs         0x0002  /* BOSR_272fs in USB mode */
+#define TLV320AIC23_USB_CLK_ON         0x0001
+#define TLV320AIC23_SR_MASK             0xf
+#define TLV320AIC23_CLKOUT_SHIFT        7
+#define TLV320AIC23_CLKIN_SHIFT         6
+#define TLV320AIC23_SR_SHIFT            2
+#define TLV320AIC23_BOSR_SHIFT          1
+
+/* Digital interface register */
+#define TLV320AIC23_ACT_ON             0x0001
+
+/*
+ * AUDIO related MACROS
+ */
+
+#define TLV320AIC23_DEFAULT_OUT_VOL    0x70
+#define TLV320AIC23_DEFAULT_IN_VOLUME  0x10
+
+#define TLV320AIC23_OUT_VOL_MIN                TLV320AIC23_LHV_MIN
+#define TLV320AIC23_OUT_VOL_MAX                TLV320AIC23_LHV_MAX
+#define TLV320AIC23_OUT_VO_RANGE       (TLV320AIC23_OUT_VOL_MAX - \
+                                       TLV320AIC23_OUT_VOL_MIN)
+#define TLV320AIC23_OUT_VOL_MASK       TLV320AIC23_OUT_VOL_MAX
+
+#define TLV320AIC23_IN_VOL_MIN         TLV320AIC23_LIV_MIN
+#define TLV320AIC23_IN_VOL_MAX         TLV320AIC23_LIV_MAX
+#define TLV320AIC23_IN_VOL_RANGE       (TLV320AIC23_IN_VOL_MAX - \
+                                       TLV320AIC23_IN_VOL_MIN)
+#define TLV320AIC23_IN_VOL_MASK                TLV320AIC23_IN_VOL_MAX
+
+#define TLV320AIC23_SIDETONE_MASK      0x1c0
+#define TLV320AIC23_SIDETONE_0         0x100
+#define TLV320AIC23_SIDETONE_6         0x000
+#define TLV320AIC23_SIDETONE_9         0x040
+#define TLV320AIC23_SIDETONE_12                0x080
+#define TLV320AIC23_SIDETONE_18                0x0c0
+
+extern struct snd_soc_dai tlv320aic23_dai;
+extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
+
+#endif /* _TLV320AIC23_H */
index 566a427c928f18085101add5e5990736101850dc..05336ed7e4935fdbd0d9f27a1f77e3b0c5c0bef2 100644 (file)
@@ -48,7 +48,6 @@
 
 #include "tlv320aic3x.h"
 
-#define AUDIO_NAME "aic3x"
 #define AIC3X_VERSION "0.2"
 
 /* codec private data */
@@ -991,7 +990,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
                         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 struct snd_soc_dai aic3x_dai = {
-       .name = "aic3x",
+       .name = "tlv320aic3x",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1055,7 +1054,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
        struct aic3x_setup_data *setup = socdev->codec_data;
        int reg, ret = 0;
 
-       codec->name = "aic3x";
+       codec->name = "tlv320aic3x";
        codec->owner = THIS_MODULE;
        codec->read = aic3x_read_reg_cache;
        codec->write = aic3x_write;
index d206d7f892b68b8c0103bc5337b27e5b460b62d2..a69ee72a7af553ca3f36d03d2c63288d97914232 100644 (file)
@@ -36,7 +36,6 @@
 #include "uda1380.h"
 
 #define UDA1380_VERSION "0.6"
-#define AUDIO_NAME "uda1380"
 
 /*
  * uda1380 register cache
index 9a37c8d95ed2475892f75cbef7a6ca43fc3e1533..d8ca2da8d634e5e2a827339f3f3939d196d89941 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
  *
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.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
@@ -18,6 +18,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -27,7 +28,6 @@
 
 #include "wm8510.h"
 
-#define AUDIO_NAME "wm8510"
 #define WM8510_VERSION "0.6"
 
 struct snd_soc_codec_device soc_codec_dev_wm8510;
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
        0x0001,
 };
 
+#define WM8510_POWER1_BIASEN  0x08
+#define WM8510_POWER1_BUFIOEN 0x10
+
 /*
  * read wm8510 register cache
  */
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
 SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
 
-SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0,
-                &wm8510_micpga_controls[0],
-                ARRAY_SIZE(wm8510_micpga_controls)),
+SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
+                  &wm8510_micpga_controls[0],
+                  ARRAY_SIZE(wm8510_micpga_controls)),
 SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
        &wm8510_boost_controls[0],
        ARRAY_SIZE(wm8510_boost_controls)),
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
 static int wm8510_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               wm8510_write(codec, WM8510_POWER1, 0x1ff);
-               wm8510_write(codec, WM8510_POWER2, 0x1ff);
-               wm8510_write(codec, WM8510_POWER3, 0x1ff);
-               break;
        case SND_SOC_BIAS_PREPARE:
+               power1 |= 0x1;  /* VMID 50k */
+               wm8510_write(codec, WM8510_POWER1, power1);
+               break;
+
        case SND_SOC_BIAS_STANDBY:
+               power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
+
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Initial cap charge at VMID 5k */
+                       wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
+                       mdelay(100);
+               }
+
+               power1 |= 0x2;  /* VMID 500k */
+               wm8510_write(codec, WM8510_POWER1, power1);
                break;
+
        case SND_SOC_BIAS_OFF:
-               /* everything off, dac mute, inactive */
-               wm8510_write(codec, WM8510_POWER1, 0x0);
-               wm8510_write(codec, WM8510_POWER2, 0x0);
-               wm8510_write(codec, WM8510_POWER3, 0x0);
+               wm8510_write(codec, WM8510_POWER1, 0);
+               wm8510_write(codec, WM8510_POWER2, 0);
+               wm8510_write(codec, WM8510_POWER3, 0);
                break;
        }
+
        codec->bias_level = level;
        return 0;
 }
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
        }
 
        /* power on device */
+       codec->bias_level = SND_SOC_BIAS_OFF;
        wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        wm8510_add_controls(codec);
        wm8510_add_widgets(codec);
@@ -747,6 +763,62 @@ err_driver:
 }
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8510_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_device *socdev = wm8510_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       codec->control_data = spi;
+
+       ret = wm8510_init(socdev);
+       if (ret < 0)
+               dev_err(&spi->dev, "failed to initialise WM8510\n");
+
+       return ret;
+}
+
+static int __devexit wm8510_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static struct spi_driver wm8510_spi_driver = {
+       .driver = {
+               .name   = "wm8510",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8510_spi_probe,
+       .remove         = __devexit_p(wm8510_spi_remove),
+};
+
+static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
+{
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#endif /* CONFIG_SPI_MASTER */
+
 static int wm8510_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -772,8 +844,14 @@ static int wm8510_probe(struct platform_device *pdev)
                codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8510_add_i2c_device(pdev, setup);
        }
-#else
-       /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       if (setup->spi) {
+               codec->hw_write = (hw_write_t)wm8510_spi_write;
+               ret = spi_register_driver(&wm8510_spi_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add spi driver");
+       }
 #endif
 
        if (ret != 0)
@@ -795,6 +873,9 @@ static int wm8510_remove(struct platform_device *pdev)
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_unregister_device(codec->control_data);
        i2c_del_driver(&wm8510_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8510_spi_driver);
 #endif
        kfree(codec);
 
index c53683960456ad2a568c3ae44eea7c9095e7723b..bdefcf5c69ff2a9ed57e160843710467d19d33d0 100644 (file)
@@ -94,6 +94,7 @@
 #define WM8510_MCLKDIV_12      (7 << 5)
 
 struct wm8510_setup_data {
+       int spi;
        int i2c_bus;
        unsigned short i2c_address;
 };
index df1ffbe305bf3875a4daa9f22c9ff709a6370bde..627ebfb4209b72b786ad66f992b0659491f8f74d 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -36,7 +35,6 @@
 
 #include "wm8580.h"
 
-#define AUDIO_NAME "wm8580"
 #define WM8580_VERSION "0.1"
 
 struct pll_state {
index 7b64d9a7ff76408092520d614c1601dbb901c7be..7f8a7e36b33e9124d0c3d924301d9cccb6cb9c5f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8731.h"
 
-#define AUDIO_NAME "wm8731"
 #define WM8731_VERSION "0.13"
 
 struct snd_soc_codec_device soc_codec_dev_wm8731;
index 4892e398a5982fa89b87ecbd1d2ceaa6fdc3af53..9b7296ee5b08fa541c6dfdbc44f9b5b8b31f92d6 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8750.h"
 
-#define AUDIO_NAME "WM8750"
 #define WM8750_VERSION "0.12"
 
 /* codec private data */
index 8c4df44f334582b2fa23a8be42a0ecdea472c1c0..d426eaa2218575b75004a48f86cfe9079d84fa21 100644 (file)
@@ -2,8 +2,7 @@
  * wm8753.c  --  WM8753 ALSA Soc Audio driver
  *
  * Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
@@ -40,6 +39,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -51,7 +51,6 @@
 
 #include "wm8753.h"
 
-#define AUDIO_NAME "wm8753"
 #define WM8753_VERSION "0.16"
 
 static int caps_charge = 2000;
@@ -1719,6 +1718,63 @@ err_driver:
 }
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_device *socdev = wm8753_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       codec->control_data = spi;
+
+       ret = wm8753_init(socdev);
+       if (ret < 0)
+               dev_err(&spi->dev, "failed to initialise WM8753\n");
+
+       return ret;
+}
+
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static struct spi_driver wm8753_spi_driver = {
+       .driver = {
+               .name   = "wm8753",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8753_spi_probe,
+       .remove         = __devexit_p(wm8753_spi_remove),
+};
+
+static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
+{
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#endif
+
+
 static int wm8753_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1753,8 +1809,14 @@ static int wm8753_probe(struct platform_device *pdev)
                codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8753_add_i2c_device(pdev, setup);
        }
-#else
-               /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       if (setup->spi) {
+               codec->hw_write = (hw_write_t)wm8753_spi_write;
+               ret = spi_register_driver(&wm8753_spi_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add spi driver");
+       }
 #endif
 
        if (ret != 0) {
@@ -1797,6 +1859,9 @@ static int wm8753_remove(struct platform_device *pdev)
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_unregister_device(codec->control_data);
        i2c_del_driver(&wm8753_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8753_spi_driver);
 #endif
        kfree(codec->private_data);
        kfree(codec);
index 7defde069f1df92793c254f49c305351db3d8b86..f55704ce931b44e135b8038967eaebf751dbf632 100644 (file)
@@ -2,8 +2,7 @@
  * wm8753.h  --  audio driver for WM8753
  *
  * Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
@@ -79,6 +78,7 @@
 #define WM8753_ADCTL2          0x3f
 
 struct wm8753_setup_data {
+       int spi;
        int i2c_bus;
        unsigned short i2c_address;
 };
index 0b8c6d38b48f4253db572b422bec4d04da9bedb5..3b326c9b55866bba7a81c1421329026bed290247 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index a3f54ec4226eb554248c75133508a5d7d21701f2..ce40d78776058456782f5d723152250bfc79e681 100644 (file)
@@ -653,14 +653,14 @@ static const struct snd_kcontrol_new wm8903_snd_controls[] = {
 
 /* Input PGAs - No TLV since the scale depends on PGA mode */
 SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0,
-          7, 1, 0),
+          7, 1, 1),
 SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0,
           0, 31, 0),
 SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1,
           6, 1, 0),
 
 SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0,
-          7, 1, 0),
+          7, 1, 1),
 SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0,
           0, 31, 0),
 SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1,
index 974a4cd0f3fdbd6ce0845e8ea7fcb954e345ecd9..f41a578ddd4fabe908053cee4b273a43155b0e77 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8971.h"
 
-#define AUDIO_NAME "wm8971"
 #define WM8971_VERSION "0.9"
 
 #define        WM8971_REG_COUNT                43
index 63410d7b5efb3623c8e92585ac51fb9ff8737606..572d22b0880b5b1f1033e244cee6269831cd9216 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "wm8990.h"
 
-#define AUDIO_NAME "wm8990"
 #define WM8990_VERSION "0.2"
 
 /* codec private data */
index 2f1c91b1d5567feb6fc3aea44eece7a3f00dd158..ffb471e420e2e76718f931420135c8b99cf21864 100644 (file)
@@ -2,8 +2,7 @@
  * wm9712.c  --  ALSA Soc WM9712 codec support
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
index 441d0580db1f75adf212ee40a882cd4ca47fb4c0..aba402b3c99994a95489bde9e526da23f7d4ea69 100644 (file)
@@ -2,8 +2,7 @@
  * wm9713.c  --  ALSA Soc WM9713 codec support
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
index aea27e70043cf8f687884227c117ceed224c98f4..8b7766b998d7de431bd30d18d32569019a116d28 100644 (file)
@@ -13,3 +13,11 @@ config SND_OMAP_SOC_N810
        select SND_SOC_TLV320AIC3X
        help
          Say Y if you want to add support for SoC audio on Nokia N810.
+
+config SND_OMAP_SOC_OSK5912
+       tristate "SoC Audio support for omap osk5912"
+       depends on SND_OMAP_SOC && MACH_OMAP_OSK
+       select SND_OMAP_SOC_MCBSP
+       select SND_SOC_TLV320AIC23
+       help
+         Say Y if you want to add support for SoC audio on osk5912.
index d8d8d58075e3ee4c0b362eadeee9fce1b43cc2d3..e09d1f297f644c856c16250dc7cdc407bd6f7e6f 100644 (file)
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 
 # OMAP Machine Support
 snd-soc-n810-objs := n810.o
+snd-soc-osk5912-objs := osk5912.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
index d166b6b2a60dd9b78ade26cb76532cbe1b3c30a8..fae3ad36e0bfc3e03606561c48c0c54bb7d192b6 100644 (file)
@@ -247,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* Not connected */
-       snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
-       snd_soc_dapm_disable_pin(codec, "HPLCOM");
-       snd_soc_dapm_disable_pin(codec, "HPRCOM");
+       snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
+       snd_soc_dapm_nc_pin(codec, "HPLCOM");
+       snd_soc_dapm_nc_pin(codec, "HPRCOM");
 
        /* Add N810 specific controls */
        for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
index 35310e16d7f3658623fdf9755ae6df7190688a1e..0a063a98a6613820295419a5cab10bd09a8dc338 100644 (file)
@@ -59,12 +59,7 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
  * Stream DMA parameters. DMA request line and port address are set runtime
  * since they are different between OMAP1 and later OMAPs
  */
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = {
-{
-       { .name         = "I2S PCM Stereo out", },
-       { .name         = "I2S PCM Stereo in", },
-},
-};
+static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
 
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
 static const int omap1_dma_reqs[][2] = {
@@ -84,11 +79,22 @@ static const unsigned long omap1_mcbsp_port[][2] = {
 static const int omap1_dma_reqs[][2] = {};
 static const unsigned long omap1_mcbsp_port[][2] = {};
 #endif
-#if defined(CONFIG_ARCH_OMAP2420)
-static const int omap2420_dma_reqs[][2] = {
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+static const int omap24xx_dma_reqs[][2] = {
        { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
        { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+       { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
+       { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
+       { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
+#endif
 };
+#else
+static const int omap24xx_dma_reqs[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
 static const unsigned long omap2420_mcbsp_port[][2] = {
        { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
          OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
@@ -96,10 +102,43 @@ static const unsigned long omap2420_mcbsp_port[][2] = {
          OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
 };
 #else
-static const int omap2420_dma_reqs[][2] = {};
 static const unsigned long omap2420_mcbsp_port[][2] = {};
 #endif
 
+#if defined(CONFIG_ARCH_OMAP2430)
+static const unsigned long omap2430_mcbsp_port[][2] = {
+       { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap2430_mcbsp_port[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP34XX)
+static const unsigned long omap34xx_mcbsp_port[][2] = {
+       { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap34xx_mcbsp_port[][2] = {};
+#endif
+
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -167,14 +206,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                dma = omap1_dma_reqs[bus_id][substream->stream];
                port = omap1_mcbsp_port[bus_id][substream->stream];
        } else if (cpu_is_omap2420()) {
-               dma = omap2420_dma_reqs[bus_id][substream->stream];
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
                port = omap2420_mcbsp_port[bus_id][substream->stream];
+       } else if (cpu_is_omap2430()) {
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
+               port = omap2430_mcbsp_port[bus_id][substream->stream];
+       } else if (cpu_is_omap343x()) {
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
+               port = omap34xx_mcbsp_port[bus_id][substream->stream];
        } else {
-               /*
-                * TODO: Add support for 2430 and 3430
-                */
                return -ENODEV;
        }
+       omap_mcbsp_dai_dma_params[id][substream->stream].name =
+               substream->stream ? "Audio Capture" : "Audio Playback";
        omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
        omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
        cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
@@ -245,6 +289,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               /* 0-bit data delay */
+               regs->rcr2      |= RDATDLY(0);
+               regs->xcr2      |= XDATDLY(0);
+               break;
        default:
                /* Unsupported data format */
                return -EINVAL;
@@ -310,7 +359,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                                       int clk_id)
 {
        int sel_bit;
-       u16 reg;
+       u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
 
        if (cpu_class_is_omap1()) {
                /* OMAP1's can use only external source clock */
@@ -320,6 +369,12 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                        return 0;
        }
 
+       if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
+               return -EINVAL;
+
+       if (cpu_is_omap343x())
+               reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
+
        switch (mcbsp_data->bus_id) {
        case 0:
                reg = OMAP2_CONTROL_DEVCONF0;
@@ -329,20 +384,26 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                reg = OMAP2_CONTROL_DEVCONF0;
                sel_bit = 6;
                break;
-       /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */
+       case 2:
+               reg = reg_devconf1;
+               sel_bit = 0;
+               break;
+       case 3:
+               reg = reg_devconf1;
+               sel_bit = 2;
+               break;
+       case 4:
+               reg = reg_devconf1;
+               sel_bit = 4;
+               break;
        default:
                return -EINVAL;
        }
 
-       if (cpu_class_is_omap2()) {
-               if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) {
-                       omap_ctrl_writel(omap_ctrl_readl(reg) &
-                                        ~(1 << sel_bit), reg);
-               } else {
-                       omap_ctrl_writel(omap_ctrl_readl(reg) |
-                                        (1 << sel_bit), reg);
-               }
-       }
+       if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
+               omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
+       else
+               omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
 
        return 0;
 }
@@ -376,37 +437,49 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        return err;
 }
 
-struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = {
-{
-       .name = "omap-mcbsp-dai",
-       .id = 0,
-       .type = SND_SOC_DAI_I2S,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = OMAP_MCBSP_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = OMAP_MCBSP_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .ops = {
-               .startup = omap_mcbsp_dai_startup,
-               .shutdown = omap_mcbsp_dai_shutdown,
-               .trigger = omap_mcbsp_dai_trigger,
-               .hw_params = omap_mcbsp_dai_hw_params,
-       },
-       .dai_ops = {
-               .set_fmt = omap_mcbsp_dai_set_dai_fmt,
-               .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
-               .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
-       },
-       .private_data = &mcbsp_data[0].bus_id,
-},
+#define OMAP_MCBSP_DAI_BUILDER(link_id)                                \
+{                                                              \
+       .name = "omap-mcbsp-dai-(link_id)",                     \
+       .id = (link_id),                                        \
+       .type = SND_SOC_DAI_I2S,                                \
+       .playback = {                                           \
+               .channels_min = 2,                              \
+               .channels_max = 2,                              \
+               .rates = OMAP_MCBSP_RATES,                      \
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
+       },                                                      \
+       .capture = {                                            \
+               .channels_min = 2,                              \
+               .channels_max = 2,                              \
+               .rates = OMAP_MCBSP_RATES,                      \
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
+       },                                                      \
+       .ops = {                                                \
+               .startup = omap_mcbsp_dai_startup,              \
+               .shutdown = omap_mcbsp_dai_shutdown,            \
+               .trigger = omap_mcbsp_dai_trigger,              \
+               .hw_params = omap_mcbsp_dai_hw_params,          \
+       },                                                      \
+       .dai_ops = {                                            \
+               .set_fmt = omap_mcbsp_dai_set_dai_fmt,          \
+               .set_clkdiv = omap_mcbsp_dai_set_clkdiv,        \
+               .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,    \
+       },                                                      \
+       .private_data = &mcbsp_data[(link_id)].bus_id,          \
+}
+
+struct snd_soc_dai omap_mcbsp_dai[] = {
+       OMAP_MCBSP_DAI_BUILDER(0),
+       OMAP_MCBSP_DAI_BUILDER(1),
+#if NUM_LINKS >= 3
+       OMAP_MCBSP_DAI_BUILDER(2),
+#endif
+#if NUM_LINKS == 5
+       OMAP_MCBSP_DAI_BUILDER(3),
+       OMAP_MCBSP_DAI_BUILDER(4),
+#endif
 };
+
 EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
index ed8afb55067173fc4969b2984ae20e10f5cabdea..df7ad13ba73d14711ca8aff42067e317b1639d1e 100644 (file)
@@ -38,11 +38,17 @@ enum omap_mcbsp_div {
        OMAP_MCBSP_CLKGDV,              /* Sample rate generator divider */
 };
 
-/*
- * REVISIT: Preparation for the ASoC v2. Let the number of available links to
- * be same than number of McBSP ports found in OMAP(s) we are compiling for.
- */
-#define NUM_LINKS      1
+#if defined(CONFIG_ARCH_OMAP2420)
+#define NUM_LINKS      2
+#endif
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+#undef  NUM_LINKS
+#define NUM_LINKS      3
+#endif
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#undef  NUM_LINKS
+#define NUM_LINKS      5
+#endif
 
 extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
 
index 690bfeaec4a0ee3b157b0ccb7a7ea1a1ea5e4189..e9084fdd2082efcbc14695e801ec6ad89ff66599 100644 (file)
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
        prtd->dma_data = dma_data;
        err = omap_request_dma(dma_data->dma_req, dma_data->name,
                               omap_pcm_dma_irq, substream, &prtd->dma_ch);
-       if (!cpu_is_omap1510()) {
+       if (!err & !cpu_is_omap1510()) {
                /*
                 * Link channel with itself so DMA doesn't need any
                 * reprogramming while looping the buffer
@@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
                dma_params.src_or_dst_synch     = OMAP_DMA_DST_SYNC;
                dma_params.src_start            = runtime->dma_addr;
                dma_params.dst_start            = dma_data->port_addr;
+               dma_params.dst_port             = OMAP_DMA_PORT_MPUI;
        } else {
                dma_params.src_amode            = OMAP_DMA_AMODE_CONSTANT;
                dma_params.dst_amode            = OMAP_DMA_AMODE_POST_INC;
                dma_params.src_or_dst_synch     = OMAP_DMA_SRC_SYNC;
                dma_params.src_start            = dma_data->port_addr;
                dma_params.dst_start            = runtime->dma_addr;
+               dma_params.src_port             = OMAP_DMA_PORT_MPUI;
        }
        /*
         * Set DMA transfer frame size equal to ALSA period size and frame
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
new file mode 100644 (file)
index 0000000..0fe7337
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * osk5912.c  --  SoC audio for OSK 5912
+ *
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * Contact: Arun KS  <arunks@mistralsolutions.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/tlv320aic23.h"
+
+#define CODEC_CLOCK    12000000
+
+static struct clk *tlv320aic23_mclk;
+
+static int osk_startup(struct snd_pcm_substream *substream)
+{
+       return clk_enable(tlv320aic23_mclk);
+}
+
+static void osk_shutdown(struct snd_pcm_substream *substream)
+{
+       clk_disable(tlv320aic23_mclk);
+}
+
+static int osk_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int err;
+
+       /* Set codec DAI configuration */
+       err = snd_soc_dai_set_fmt(codec_dai,
+                                 SND_SOC_DAIFMT_DSP_A |
+                                 SND_SOC_DAIFMT_NB_IF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0) {
+               printk(KERN_ERR "can't set codec DAI configuration\n");
+               return err;
+       }
+
+       /* Set cpu DAI configuration */
+       err = snd_soc_dai_set_fmt(cpu_dai,
+                                 SND_SOC_DAIFMT_DSP_A |
+                                 SND_SOC_DAIFMT_NB_IF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0) {
+               printk(KERN_ERR "can't set cpu DAI configuration\n");
+               return err;
+       }
+
+       /* Set the codec system clock for DAC and ADC */
+       err =
+           snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
+
+       if (err < 0) {
+               printk(KERN_ERR "can't set codec system clock\n");
+               return err;
+       }
+
+       return err;
+}
+
+static struct snd_soc_ops osk_ops = {
+       .startup = osk_startup,
+       .hw_params = osk_hw_params,
+       .shutdown = osk_shutdown,
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_LINE("Line In", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       {"Headphone Jack", NULL, "LHPOUT"},
+       {"Headphone Jack", NULL, "RHPOUT"},
+
+       {"LLINEIN", NULL, "Line In"},
+       {"RLINEIN", NULL, "Line In"},
+
+       {"MICIN", NULL, "Mic Jack"},
+};
+
+static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
+{
+
+       /* Add osk5912 specific widgets */
+       snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+       /* Set up osk5912 specific audio path audio_map */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Line In");
+       snd_soc_dapm_enable_pin(codec, "Mic Jack");
+
+       snd_soc_dapm_sync(codec);
+
+       return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link osk_dai = {
+       .name = "TLV320AIC23",
+       .stream_name = "AIC23",
+       .cpu_dai = &omap_mcbsp_dai[0],
+       .codec_dai = &tlv320aic23_dai,
+       .init = osk_tlv320aic23_init,
+       .ops = &osk_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_osk = {
+       .name = "OSK5912",
+       .dai_link = &osk_dai,
+       .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device osk_snd_devdata = {
+       .machine = &snd_soc_machine_osk,
+       .platform = &omap_soc_platform,
+       .codec_dev = &soc_codec_dev_tlv320aic23,
+};
+
+static struct platform_device *osk_snd_device;
+
+static int __init osk_soc_init(void)
+{
+       int err;
+       u32 curRate;
+       struct device *dev;
+
+       if (!(machine_is_omap_osk()))
+               return -ENODEV;
+
+       osk_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!osk_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
+       osk_snd_devdata.dev = &osk_snd_device->dev;
+       *(unsigned int *)osk_dai.cpu_dai->private_data = 0;     /* McBSP1 */
+       err = platform_device_add(osk_snd_device);
+       if (err)
+               goto err1;
+
+       dev = &osk_snd_device->dev;
+
+       tlv320aic23_mclk = clk_get(dev, "mclk");
+       if (IS_ERR(tlv320aic23_mclk)) {
+               printk(KERN_ERR "Could not get mclk clock\n");
+               return -ENODEV;
+       }
+
+       if (clk_get_usecount(tlv320aic23_mclk) > 0) {
+               /* MCLK is already in use */
+               printk(KERN_WARNING
+                      "MCLK in use at %d Hz. We change it to %d Hz\n",
+                      (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
+       }
+
+       /*
+        * Configure 12 MHz output on MCLK.
+        */
+       curRate = (uint) clk_get_rate(tlv320aic23_mclk);
+       if (curRate != CODEC_CLOCK) {
+               if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
+                       printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
+                       err = -ECANCELED;
+                       goto err1;
+               }
+       }
+
+       printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
+              (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
+              clk_get_usecount(tlv320aic23_mclk));
+
+       return 0;
+err1:
+       clk_put(tlv320aic23_mclk);
+       platform_device_del(osk_snd_device);
+       platform_device_put(osk_snd_device);
+
+       return err;
+
+}
+
+static void __exit osk_soc_exit(void)
+{
+       platform_device_unregister(osk_snd_device);
+}
+
+module_init(osk_soc_init);
+module_exit(osk_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC OSK 5912");
+MODULE_LICENSE("GPL");
index 1a8373de7f3a3badc8a58b5f3559186cff21c584..2718eaf7895f39d4db2e5d93e4227400b995b1a7 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -281,8 +281,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_nc_pin(codec, "LLINEIN");
+       snd_soc_dapm_nc_pin(codec, "RLINEIN");
 
        /* Add corgi specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
index d9c3f7b28be212ecdb7cc1bf62ce22d09f2808df..e6ff6929ab4b799f7b9875144681469c15e6d8fe 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
index f84f7d8db09a0f19d5eb75089203bd603f25708f..4d9930c52789989313a8a1189bbc99b26160d8b2 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_nc_pin(codec, "LLINEIN");
+       snd_soc_dapm_nc_pin(codec, "RLINEIN");
        snd_soc_dapm_enable_pin(codec, "MICIN");
 
        /* Add poodle specific controls */
index 2fb58298513b32c88e5cf2f74184db37a883d163..e758034db5c3ba38422e07592b2a933dc3e50b81 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *         lrg@slimlogic.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 the
@@ -405,6 +405,6 @@ module_init(pxa2xx_i2s_init);
 module_exit(pxa2xx_i2s_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
 MODULE_LICENSE("GPL");
index 9a70b00fc30e6d8100c2698b56adad67f2d08594..d307b6757e9550646b565a4cffaac5abc0a02007 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -281,13 +281,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* NC codec pins */
-       snd_soc_dapm_disable_pin(codec, "RINPUT1");
-       snd_soc_dapm_disable_pin(codec, "LINPUT2");
-       snd_soc_dapm_disable_pin(codec, "RINPUT2");
-       snd_soc_dapm_disable_pin(codec, "LINPUT3");
-       snd_soc_dapm_disable_pin(codec, "RINPUT3");
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "MONO1");
+       snd_soc_dapm_nc_pin(codec, "RINPUT1");
+       snd_soc_dapm_nc_pin(codec, "LINPUT2");
+       snd_soc_dapm_nc_pin(codec, "RINPUT2");
+       snd_soc_dapm_nc_pin(codec, "LINPUT3");
+       snd_soc_dapm_nc_pin(codec, "RINPUT3");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "MONO1");
 
        /* Add spitz specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
index 2baaa750f123013f566fb351e972651a967db382..afefe41b8c46c9f47ae255b14ec1ebed56e3522e 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "MONOOUT");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "MONOOUT");
 
        /* add tosa specific controls */
        for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
index 73a50e93a9a222e5296f9a0d5191f9756a275a64..87ddfefcc2fba18b821f3b154fbe03d86e1bf3e7 100644 (file)
@@ -511,21 +511,20 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
        DBG("Entered %s\n", __func__);
 
        /* set up NC codec pins */
-       snd_soc_dapm_disable_pin(codec, "LOUT2");
-       snd_soc_dapm_disable_pin(codec, "ROUT2");
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "OUT4");
-       snd_soc_dapm_disable_pin(codec, "LINE1");
-       snd_soc_dapm_disable_pin(codec, "LINE2");
-
-
-       /* set endpoints to default mode */
-       set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+       snd_soc_dapm_nc_pin(codec, "LOUT2");
+       snd_soc_dapm_nc_pin(codec, "ROUT2");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "OUT4");
+       snd_soc_dapm_nc_pin(codec, "LINE1");
+       snd_soc_dapm_nc_pin(codec, "LINE2");
 
        /* Add neo1973 specific widgets */
        snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
                                  ARRAY_SIZE(wm8753_dapm_widgets));
 
+       /* set endpoints to default mode */
+       set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+
        /* add neo1973 specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
                err = snd_ctl_add(codec->card,
@@ -603,6 +602,8 @@ static int lm4857_i2c_probe(struct i2c_client *client,
 {
        DBG("Entered %s\n", __func__);
 
+       i2c = client;
+
        lm4857_write_regs();
        return 0;
 }
@@ -611,6 +612,8 @@ static int lm4857_i2c_remove(struct i2c_client *client)
 {
        DBG("Entered %s\n", __func__);
 
+       i2c = NULL;
+
        return 0;
 }
 
@@ -650,7 +653,7 @@ static void lm4857_shutdown(struct i2c_client *dev)
 }
 
 static const struct i2c_device_id lm4857_i2c_id[] = {
-       { "neo1973_lm4857", 0 }
+       { "neo1973_lm4857", 0 },
        { }
 };
 
@@ -668,48 +671,6 @@ static struct i2c_driver lm4857_i2c_driver = {
 };
 
 static struct platform_device *neo1973_snd_device;
-static struct i2c_client *lm4857_client;
-
-static int __init neo1973_add_lm4857_device(struct platform_device *pdev,
-                                           int i2c_bus,
-                                           unsigned short i2c_address)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&lm4857_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add lm4857 driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = i2c_address;
-       strlcpy(info.type, "neo1973_lm4857", I2C_NAME_SIZE);
-
-       adapter = i2c_get_adapter(i2c_bus);
-       if (!adapter) {
-               dev_err(&pdev->dev, "can't get i2c adapter %d\n", i2c_bus);
-               goto err_driver;
-       }
-
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               dev_err(&pdev->dev, "can't add lm4857 device at 0x%x\n",
-                       (unsigned int)info.addr);
-               goto err_driver;
-       }
-
-       lm4857_client = client;
-       return 0;
-
-err_driver:
-       i2c_del_driver(&lm4857_i2c_driver);
-       return -ENODEV;
-}
 
 static int __init neo1973_init(void)
 {
@@ -736,8 +697,8 @@ static int __init neo1973_init(void)
                return ret;
        }
 
-       ret = neo1973_add_lm4857_device(neo1973_snd_device,
-                                       neo1973_wm8753_setup, 0x7C);
+       ret = i2c_add_driver(&lm4857_i2c_driver);
+
        if (ret != 0)
                platform_device_unregister(neo1973_snd_device);
 
@@ -748,7 +709,6 @@ static void __exit neo1973_exit(void)
 {
        DBG("Entered %s\n", __func__);
 
-       i2c_unregister_device(lm4857_client);
        i2c_del_driver(&lm4857_i2c_driver);
        platform_device_unregister(neo1973_snd_device);
 }
index ad381138fc2e482e0bf0110a96cf32c385ba8c04..462e635dfc74bc084f2c140480c4e6fe8e8cd7cc 100644 (file)
@@ -4,8 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *         with code, comments and ideas from :-
  *         Richard Purdie <richard@openedhand.com>
  *
@@ -1886,7 +1885,7 @@ module_init(snd_soc_init);
 module_exit(snd_soc_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("ALSA SoC Core");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:soc-audio");
index 9ca9c08610fa85bfd7fa7967555f07e1c6ac8082..efbd0b37810aba581672c1208bf82a99a2d1554a 100644 (file)
@@ -2,8 +2,7 @@
  * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.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 the
@@ -1483,6 +1482,26 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
 
+/**
+ * snd_soc_dapm_nc_pin - permanently disable pin.
+ * @codec: SoC codec
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets.  At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
+{
+       return snd_soc_dapm_set_pin(codec, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
+
 /**
  * snd_soc_dapm_get_pin_status - get audio pin status
  * @codec: audio codec
@@ -1521,6 +1540,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
 MODULE_LICENSE("GPL");
index 4ae07e236b36a81d87a51307a9272b50cef17528..faef87a9bc3fdbac4f5ed27040877de887db6783 100644 (file)
@@ -220,9 +220,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
        else
                sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 
-       device_create_drvdata(sound_class, dev,
-                             MKDEV(SOUND_MAJOR, s->unit_minor),
-                             NULL, s->name+6);
+       device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
+                     NULL, s->name+6);
        return r;
 
  fail:
index b441fe2cd190aa5b5b2b1072b750f28ee3045980..c2515b680f9fd8d5245fad46c79c378cd418ba82 100644 (file)
@@ -118,12 +118,11 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
        void *vaddr;
        struct us122l *us122l = area->vm_private_data;
        struct usb_stream *s;
-       int vm_f = VM_FAULT_SIGBUS;
 
        mutex_lock(&us122l->mutex);
        s = us122l->sk.s;
        if (!s)
-               goto out;
+               goto unlock;
 
        offset = vmf->pgoff << PAGE_SHIFT;
        if (offset < PAGE_ALIGN(s->read_size))
@@ -131,7 +130,7 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
        else {
                offset -= PAGE_ALIGN(s->read_size);
                if (offset >= PAGE_ALIGN(s->write_size))
-                       goto out;
+                       goto unlock;
 
                vaddr = us122l->sk.write_page + offset;
        }
@@ -141,9 +140,11 @@ static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area,
        mutex_unlock(&us122l->mutex);
 
        vmf->page = page;
-       vm_f = 0;
-out:
-       return vm_f;
+
+       return 0;
+unlock:
+       mutex_unlock(&us122l->mutex);
+       return VM_FAULT_SIGBUS;
 }
 
 static void usb_stream_hwdep_vm_close(struct vm_area_struct *area)
index c0d22870ee9c56137583c026b06dee47c66d58d8..53772bb46320ae9e1fbf84297a6a4707e5b3e0ed 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "ioapic.h"
 #include "lapic.h"
+#include "irq.h"
 
 #if 0
 #define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
@@ -285,26 +286,31 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
        }
 }
 
-static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi)
+static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
+                                   int trigger_mode)
 {
        union ioapic_redir_entry *ent;
 
        ent = &ioapic->redirtbl[gsi];
-       ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
 
-       ent->fields.remote_irr = 0;
-       if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
-               ioapic_service(ioapic, gsi);
+       kvm_notify_acked_irq(ioapic->kvm, gsi);
+
+       if (trigger_mode == IOAPIC_LEVEL_TRIG) {
+               ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
+               ent->fields.remote_irr = 0;
+               if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
+                       ioapic_service(ioapic, gsi);
+       }
 }
 
-void kvm_ioapic_update_eoi(struct kvm *kvm, int vector)
+void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode)
 {
        struct kvm_ioapic *ioapic = kvm->arch.vioapic;
        int i;
 
        for (i = 0; i < IOAPIC_NUM_PINS; i++)
                if (ioapic->redirtbl[i].fields.vector == vector)
-                       __kvm_ioapic_update_eoi(ioapic, i);
+                       __kvm_ioapic_update_eoi(ioapic, i, trigger_mode);
 }
 
 static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
@@ -380,7 +386,7 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
                break;
 #ifdef CONFIG_IA64
        case IOAPIC_REG_EOI:
-               kvm_ioapic_update_eoi(ioapic->kvm, data);
+               kvm_ioapic_update_eoi(ioapic->kvm, data, IOAPIC_LEVEL_TRIG);
                break;
 #endif
 
index 7f16675fe783a8e4d1a8e672a8a4c1c25a1f61a0..cd7ae7691c9d68eb3c066b6c47bbc4749c85e18d 100644 (file)
@@ -58,6 +58,7 @@ struct kvm_ioapic {
        } redirtbl[IOAPIC_NUM_PINS];
        struct kvm_io_device dev;
        struct kvm *kvm;
+       void (*ack_notifier)(void *opaque, int irq);
 };
 
 #ifdef DEBUG
@@ -78,16 +79,9 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
        return kvm->arch.vioapic;
 }
 
-#ifdef CONFIG_IA64
-static inline int irqchip_in_kernel(struct kvm *kvm)
-{
-       return 1;
-}
-#endif
-
 struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
                                       unsigned long bitmap);
-void kvm_ioapic_update_eoi(struct kvm *kvm, int vector);
+void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
 int kvm_ioapic_init(struct kvm *kvm);
 void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
 void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
new file mode 100644 (file)
index 0000000..d0169f5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * irq_comm.c: Common API for in kernel interrupt controller
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ * Authors:
+ *   Yaozu (Eddie) Dong <Eddie.dong@intel.com>
+ *
+ */
+
+#include <linux/kvm_host.h>
+#include "irq.h"
+
+#include "ioapic.h"
+
+/* This should be called with the kvm->lock mutex held */
+void kvm_set_irq(struct kvm *kvm, int irq, int level)
+{
+       /* Not possible to detect if the guest uses the PIC or the
+        * IOAPIC.  So set the bit in both. The guest will ignore
+        * writes to the unused one.
+        */
+       kvm_ioapic_set_irq(kvm->arch.vioapic, irq, level);
+#ifdef CONFIG_X86
+       kvm_pic_set_irq(pic_irqchip(kvm), irq, level);
+#endif
+}
+
+void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi)
+{
+       struct kvm_irq_ack_notifier *kian;
+       struct hlist_node *n;
+
+       hlist_for_each_entry(kian, n, &kvm->arch.irq_ack_notifier_list, link)
+               if (kian->gsi == gsi)
+                       kian->irq_acked(kian);
+}
+
+void kvm_register_irq_ack_notifier(struct kvm *kvm,
+                                  struct kvm_irq_ack_notifier *kian)
+{
+       hlist_add_head(&kian->link, &kvm->arch.irq_ack_notifier_list);
+}
+
+void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
+                                    struct kvm_irq_ack_notifier *kian)
+{
+       hlist_del(&kian->link);
+}
index 7dd9b0b85e4eea1aafaff116e993e6392c9cc173..cf0ab8ed3845c898e927d62608221512148bee4a 100644 (file)
 #include "coalesced_mmio.h"
 #endif
 
+#ifdef KVM_CAP_DEVICE_ASSIGNMENT
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include "irq.h"
+#endif
+
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
@@ -71,11 +77,253 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
 
 bool kvm_rebooting;
 
+#ifdef KVM_CAP_DEVICE_ASSIGNMENT
+static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
+                                                     int assigned_dev_id)
+{
+       struct list_head *ptr;
+       struct kvm_assigned_dev_kernel *match;
+
+       list_for_each(ptr, head) {
+               match = list_entry(ptr, struct kvm_assigned_dev_kernel, list);
+               if (match->assigned_dev_id == assigned_dev_id)
+                       return match;
+       }
+       return NULL;
+}
+
+static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev;
+
+       assigned_dev = container_of(work, struct kvm_assigned_dev_kernel,
+                                   interrupt_work);
+
+       /* This is taken to safely inject irq inside the guest. When
+        * the interrupt injection (or the ioapic code) uses a
+        * finer-grained lock, update this
+        */
+       mutex_lock(&assigned_dev->kvm->lock);
+       kvm_set_irq(assigned_dev->kvm,
+                   assigned_dev->guest_irq, 1);
+       mutex_unlock(&assigned_dev->kvm->lock);
+       kvm_put_kvm(assigned_dev->kvm);
+}
+
+/* FIXME: Implement the OR logic needed to make shared interrupts on
+ * this line behave properly
+ */
+static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev =
+               (struct kvm_assigned_dev_kernel *) dev_id;
+
+       kvm_get_kvm(assigned_dev->kvm);
+       schedule_work(&assigned_dev->interrupt_work);
+       disable_irq_nosync(irq);
+       return IRQ_HANDLED;
+}
+
+/* Ack the irq line for an assigned device */
+static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
+{
+       struct kvm_assigned_dev_kernel *dev;
+
+       if (kian->gsi == -1)
+               return;
+
+       dev = container_of(kian, struct kvm_assigned_dev_kernel,
+                          ack_notifier);
+       kvm_set_irq(dev->kvm, dev->guest_irq, 0);
+       enable_irq(dev->host_irq);
+}
+
+static void kvm_free_assigned_device(struct kvm *kvm,
+                                    struct kvm_assigned_dev_kernel
+                                    *assigned_dev)
+{
+       if (irqchip_in_kernel(kvm) && assigned_dev->irq_requested)
+               free_irq(assigned_dev->host_irq, (void *)assigned_dev);
+
+       kvm_unregister_irq_ack_notifier(kvm, &assigned_dev->ack_notifier);
+
+       if (cancel_work_sync(&assigned_dev->interrupt_work))
+               /* We had pending work. That means we will have to take
+                * care of kvm_put_kvm.
+                */
+               kvm_put_kvm(kvm);
+
+       pci_release_regions(assigned_dev->dev);
+       pci_disable_device(assigned_dev->dev);
+       pci_dev_put(assigned_dev->dev);
+
+       list_del(&assigned_dev->list);
+       kfree(assigned_dev);
+}
+
+void kvm_free_all_assigned_devices(struct kvm *kvm)
+{
+       struct list_head *ptr, *ptr2;
+       struct kvm_assigned_dev_kernel *assigned_dev;
+
+       list_for_each_safe(ptr, ptr2, &kvm->arch.assigned_dev_head) {
+               assigned_dev = list_entry(ptr,
+                                         struct kvm_assigned_dev_kernel,
+                                         list);
+
+               kvm_free_assigned_device(kvm, assigned_dev);
+       }
+}
+
+static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
+                                  struct kvm_assigned_irq
+                                  *assigned_irq)
+{
+       int r = 0;
+       struct kvm_assigned_dev_kernel *match;
+
+       mutex_lock(&kvm->lock);
+
+       match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+                                     assigned_irq->assigned_dev_id);
+       if (!match) {
+               mutex_unlock(&kvm->lock);
+               return -EINVAL;
+       }
+
+       if (match->irq_requested) {
+               match->guest_irq = assigned_irq->guest_irq;
+               match->ack_notifier.gsi = assigned_irq->guest_irq;
+               mutex_unlock(&kvm->lock);
+               return 0;
+       }
+
+       INIT_WORK(&match->interrupt_work,
+                 kvm_assigned_dev_interrupt_work_handler);
+
+       if (irqchip_in_kernel(kvm)) {
+               if (!capable(CAP_SYS_RAWIO)) {
+                       r = -EPERM;
+                       goto out_release;
+               }
+
+               if (assigned_irq->host_irq)
+                       match->host_irq = assigned_irq->host_irq;
+               else
+                       match->host_irq = match->dev->irq;
+               match->guest_irq = assigned_irq->guest_irq;
+               match->ack_notifier.gsi = assigned_irq->guest_irq;
+               match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
+               kvm_register_irq_ack_notifier(kvm, &match->ack_notifier);
+
+               /* Even though this is PCI, we don't want to use shared
+                * interrupts. Sharing host devices with guest-assigned devices
+                * on the same interrupt line is not a happy situation: there
+                * are going to be long delays in accepting, acking, etc.
+                */
+               if (request_irq(match->host_irq, kvm_assigned_dev_intr, 0,
+                               "kvm_assigned_device", (void *)match)) {
+                       r = -EIO;
+                       goto out_release;
+               }
+       }
+
+       match->irq_requested = true;
+       mutex_unlock(&kvm->lock);
+       return r;
+out_release:
+       mutex_unlock(&kvm->lock);
+       kvm_free_assigned_device(kvm, match);
+       return r;
+}
+
+static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+                                     struct kvm_assigned_pci_dev *assigned_dev)
+{
+       int r = 0;
+       struct kvm_assigned_dev_kernel *match;
+       struct pci_dev *dev;
+
+       mutex_lock(&kvm->lock);
+
+       match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
+                                     assigned_dev->assigned_dev_id);
+       if (match) {
+               /* device already assigned */
+               r = -EINVAL;
+               goto out;
+       }
+
+       match = kzalloc(sizeof(struct kvm_assigned_dev_kernel), GFP_KERNEL);
+       if (match == NULL) {
+               printk(KERN_INFO "%s: Couldn't allocate memory\n",
+                      __func__);
+               r = -ENOMEM;
+               goto out;
+       }
+       dev = pci_get_bus_and_slot(assigned_dev->busnr,
+                                  assigned_dev->devfn);
+       if (!dev) {
+               printk(KERN_INFO "%s: host device not found\n", __func__);
+               r = -EINVAL;
+               goto out_free;
+       }
+       if (pci_enable_device(dev)) {
+               printk(KERN_INFO "%s: Could not enable PCI device\n", __func__);
+               r = -EBUSY;
+               goto out_put;
+       }
+       r = pci_request_regions(dev, "kvm_assigned_device");
+       if (r) {
+               printk(KERN_INFO "%s: Could not get access to device regions\n",
+                      __func__);
+               goto out_disable;
+       }
+       match->assigned_dev_id = assigned_dev->assigned_dev_id;
+       match->host_busnr = assigned_dev->busnr;
+       match->host_devfn = assigned_dev->devfn;
+       match->dev = dev;
+
+       match->kvm = kvm;
+
+       list_add(&match->list, &kvm->arch.assigned_dev_head);
+
+       if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) {
+               r = kvm_iommu_map_guest(kvm, match);
+               if (r)
+                       goto out_list_del;
+       }
+
+out:
+       mutex_unlock(&kvm->lock);
+       return r;
+out_list_del:
+       list_del(&match->list);
+       pci_release_regions(dev);
+out_disable:
+       pci_disable_device(dev);
+out_put:
+       pci_dev_put(dev);
+out_free:
+       kfree(match);
+       mutex_unlock(&kvm->lock);
+       return r;
+}
+#endif
+
 static inline int valid_vcpu(int n)
 {
        return likely(n >= 0 && n < KVM_MAX_VCPUS);
 }
 
+inline int kvm_is_mmio_pfn(pfn_t pfn)
+{
+       if (pfn_valid(pfn))
+               return PageReserved(pfn_to_page(pfn));
+
+       return true;
+}
+
 /*
  * Switches to specified vcpu, until a matching vcpu_put()
  */
@@ -570,6 +818,12 @@ int __kvm_set_memory_region(struct kvm *kvm,
        }
 
        kvm_free_physmem_slot(&old, &new);
+#ifdef CONFIG_DMAR
+       /* map the pages in iommu page table */
+       r = kvm_iommu_map_pages(kvm, base_gfn, npages);
+       if (r)
+               goto out;
+#endif
        return 0;
 
 out_free:
@@ -708,9 +962,6 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(gfn_to_hva);
 
-/*
- * Requires current->mm->mmap_sem to be held
- */
 pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
 {
        struct page *page[1];
@@ -726,21 +977,24 @@ pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
                return page_to_pfn(bad_page);
        }
 
-       npages = get_user_pages(current, current->mm, addr, 1, 1, 1, page,
-                               NULL);
+       npages = get_user_pages_fast(addr, 1, 1, page);
 
        if (unlikely(npages != 1)) {
                struct vm_area_struct *vma;
 
+               down_read(&current->mm->mmap_sem);
                vma = find_vma(current->mm, addr);
+
                if (vma == NULL || addr < vma->vm_start ||
                    !(vma->vm_flags & VM_PFNMAP)) {
+                       up_read(&current->mm->mmap_sem);
                        get_page(bad_page);
                        return page_to_pfn(bad_page);
                }
 
                pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-               BUG_ON(pfn_valid(pfn));
+               up_read(&current->mm->mmap_sem);
+               BUG_ON(!kvm_is_mmio_pfn(pfn));
        } else
                pfn = page_to_pfn(page[0]);
 
@@ -754,10 +1008,10 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
        pfn_t pfn;
 
        pfn = gfn_to_pfn(kvm, gfn);
-       if (pfn_valid(pfn))
+       if (!kvm_is_mmio_pfn(pfn))
                return pfn_to_page(pfn);
 
-       WARN_ON(!pfn_valid(pfn));
+       WARN_ON(kvm_is_mmio_pfn(pfn));
 
        get_page(bad_page);
        return bad_page;
@@ -773,7 +1027,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       if (pfn_valid(pfn))
+       if (!kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
@@ -799,7 +1053,7 @@ EXPORT_SYMBOL_GPL(kvm_set_page_dirty);
 
 void kvm_set_pfn_dirty(pfn_t pfn)
 {
-       if (pfn_valid(pfn)) {
+       if (!kvm_is_mmio_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);
                if (!PageReserved(page))
                        SetPageDirty(page);
@@ -809,14 +1063,14 @@ EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
 
 void kvm_set_pfn_accessed(pfn_t pfn)
 {
-       if (pfn_valid(pfn))
+       if (!kvm_is_mmio_pfn(pfn))
                mark_page_accessed(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed);
 
 void kvm_get_pfn(pfn_t pfn)
 {
-       if (pfn_valid(pfn))
+       if (!kvm_is_mmio_pfn(pfn))
                get_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_get_pfn);
@@ -972,12 +1226,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
        for (;;) {
                prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
 
-               if (kvm_cpu_has_interrupt(vcpu))
-                       break;
-               if (kvm_cpu_has_pending_timer(vcpu))
-                       break;
-               if (kvm_arch_vcpu_runnable(vcpu))
+               if (kvm_cpu_has_interrupt(vcpu) ||
+                   kvm_cpu_has_pending_timer(vcpu) ||
+                   kvm_arch_vcpu_runnable(vcpu)) {
+                       set_bit(KVM_REQ_UNHALT, &vcpu->requests);
                        break;
+               }
                if (signal_pending(current))
                        break;
 
@@ -1074,12 +1328,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
 
        r = kvm_arch_vcpu_setup(vcpu);
        if (r)
-               goto vcpu_destroy;
+               return r;
 
        mutex_lock(&kvm->lock);
        if (kvm->vcpus[n]) {
                r = -EEXIST;
-               mutex_unlock(&kvm->lock);
                goto vcpu_destroy;
        }
        kvm->vcpus[n] = vcpu;
@@ -1095,8 +1348,8 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n)
 unlink:
        mutex_lock(&kvm->lock);
        kvm->vcpus[n] = NULL;
-       mutex_unlock(&kvm->lock);
 vcpu_destroy:
+       mutex_unlock(&kvm->lock);
        kvm_arch_vcpu_destroy(vcpu);
        return r;
 }
@@ -1118,6 +1371,8 @@ static long kvm_vcpu_ioctl(struct file *filp,
        struct kvm_vcpu *vcpu = filp->private_data;
        void __user *argp = (void __user *)arg;
        int r;
+       struct kvm_fpu *fpu = NULL;
+       struct kvm_sregs *kvm_sregs = NULL;
 
        if (vcpu->kvm->mm != current->mm)
                return -EIO;
@@ -1165,25 +1420,28 @@ out_free2:
                break;
        }
        case KVM_GET_SREGS: {
-               struct kvm_sregs kvm_sregs;
-
-               memset(&kvm_sregs, 0, sizeof kvm_sregs);
-               r = kvm_arch_vcpu_ioctl_get_sregs(vcpu, &kvm_sregs);
+               kvm_sregs = kzalloc(sizeof(struct kvm_sregs), GFP_KERNEL);
+               r = -ENOMEM;
+               if (!kvm_sregs)
+                       goto out;
+               r = kvm_arch_vcpu_ioctl_get_sregs(vcpu, kvm_sregs);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &kvm_sregs, sizeof kvm_sregs))
+               if (copy_to_user(argp, kvm_sregs, sizeof(struct kvm_sregs)))
                        goto out;
                r = 0;
                break;
        }
        case KVM_SET_SREGS: {
-               struct kvm_sregs kvm_sregs;
-
+               kvm_sregs = kmalloc(sizeof(struct kvm_sregs), GFP_KERNEL);
+               r = -ENOMEM;
+               if (!kvm_sregs)
+                       goto out;
                r = -EFAULT;
-               if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
+               if (copy_from_user(kvm_sregs, argp, sizeof(struct kvm_sregs)))
                        goto out;
-               r = kvm_arch_vcpu_ioctl_set_sregs(vcpu, &kvm_sregs);
+               r = kvm_arch_vcpu_ioctl_set_sregs(vcpu, kvm_sregs);
                if (r)
                        goto out;
                r = 0;
@@ -1264,25 +1522,28 @@ out_free2:
                break;
        }
        case KVM_GET_FPU: {
-               struct kvm_fpu fpu;
-
-               memset(&fpu, 0, sizeof fpu);
-               r = kvm_arch_vcpu_ioctl_get_fpu(vcpu, &fpu);
+               fpu = kzalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
+               r = -ENOMEM;
+               if (!fpu)
+                       goto out;
+               r = kvm_arch_vcpu_ioctl_get_fpu(vcpu, fpu);
                if (r)
                        goto out;
                r = -EFAULT;
-               if (copy_to_user(argp, &fpu, sizeof fpu))
+               if (copy_to_user(argp, fpu, sizeof(struct kvm_fpu)))
                        goto out;
                r = 0;
                break;
        }
        case KVM_SET_FPU: {
-               struct kvm_fpu fpu;
-
+               fpu = kmalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
+               r = -ENOMEM;
+               if (!fpu)
+                       goto out;
                r = -EFAULT;
-               if (copy_from_user(&fpu, argp, sizeof fpu))
+               if (copy_from_user(fpu, argp, sizeof(struct kvm_fpu)))
                        goto out;
-               r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, &fpu);
+               r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, fpu);
                if (r)
                        goto out;
                r = 0;
@@ -1292,6 +1553,8 @@ out_free2:
                r = kvm_arch_vcpu_ioctl(filp, ioctl, arg);
        }
 out:
+       kfree(fpu);
+       kfree(kvm_sregs);
        return r;
 }
 
@@ -1359,6 +1622,30 @@ static long kvm_vm_ioctl(struct file *filp,
                r = 0;
                break;
        }
+#endif
+#ifdef KVM_CAP_DEVICE_ASSIGNMENT
+       case KVM_ASSIGN_PCI_DEVICE: {
+               struct kvm_assigned_pci_dev assigned_dev;
+
+               r = -EFAULT;
+               if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
+                       goto out;
+               r = kvm_vm_ioctl_assign_device(kvm, &assigned_dev);
+               if (r)
+                       goto out;
+               break;
+       }
+       case KVM_ASSIGN_IRQ: {
+               struct kvm_assigned_irq assigned_irq;
+
+               r = -EFAULT;
+               if (copy_from_user(&assigned_irq, argp, sizeof assigned_irq))
+                       goto out;
+               r = kvm_vm_ioctl_assign_irq(kvm, &assigned_irq);
+               if (r)
+                       goto out;
+               break;
+       }
 #endif
        default:
                r = kvm_arch_vm_ioctl(filp, ioctl, arg);
@@ -1369,17 +1656,22 @@ out:
 
 static int kvm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
+       struct page *page[1];
+       unsigned long addr;
+       int npages;
+       gfn_t gfn = vmf->pgoff;
        struct kvm *kvm = vma->vm_file->private_data;
-       struct page *page;
 
-       if (!kvm_is_visible_gfn(kvm, vmf->pgoff))
+       addr = gfn_to_hva(kvm, gfn);
+       if (kvm_is_error_hva(addr))
                return VM_FAULT_SIGBUS;
-       page = gfn_to_page(kvm, vmf->pgoff);
-       if (is_error_page(page)) {
-               kvm_release_page_clean(page);
+
+       npages = get_user_pages(current, current->mm, addr, 1, 1, 0, page,
+                               NULL);
+       if (unlikely(npages != 1))
                return VM_FAULT_SIGBUS;
-       }
-       vmf->page = page;
+
+       vmf->page = page[0];
        return 0;
 }
 
index 58141f31ea8fb218f8091b16f192857615ad66b6..41dcc845f78c34d65a9d13e72cc7023a8a14f142 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/relay.h>
 #include <linux/debugfs.h>
+#include <linux/ktime.h>
 
 #include <linux/kvm_host.h>
 
@@ -35,16 +36,16 @@ static struct kvm_trace *kvm_trace;
 struct kvm_trace_probe {
        const char *name;
        const char *format;
-       u32 cycle_in;
+       u32 timestamp_in;
        marker_probe_func *probe_func;
 };
 
-static inline int calc_rec_size(int cycle, int extra)
+static inline int calc_rec_size(int timestamp, int extra)
 {
        int rec_size = KVM_TRC_HEAD_SIZE;
 
        rec_size += extra;
-       return cycle ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
+       return timestamp ? rec_size += KVM_TRC_CYCLE_SIZE : rec_size;
 }
 
 static void kvm_add_trace(void *probe_private, void *call_data,
@@ -54,12 +55,13 @@ static void kvm_add_trace(void *probe_private, void *call_data,
        struct kvm_trace *kt = kvm_trace;
        struct kvm_trace_rec rec;
        struct kvm_vcpu *vcpu;
-       int    i, extra, size;
+       int    i, size;
+       u32    extra;
 
        if (unlikely(kt->trace_state != KVM_TRACE_STATE_RUNNING))
                return;
 
-       rec.event       = va_arg(*args, u32);
+       rec.rec_val     = TRACE_REC_EVENT_ID(va_arg(*args, u32));
        vcpu            = va_arg(*args, struct kvm_vcpu *);
        rec.pid         = current->tgid;
        rec.vcpu_id     = vcpu->vcpu_id;
@@ -67,21 +69,21 @@ static void kvm_add_trace(void *probe_private, void *call_data,
        extra           = va_arg(*args, u32);
        WARN_ON(!(extra <= KVM_TRC_EXTRA_MAX));
        extra           = min_t(u32, extra, KVM_TRC_EXTRA_MAX);
-       rec.extra_u32   = extra;
 
-       rec.cycle_in    = p->cycle_in;
+       rec.rec_val |= TRACE_REC_TCS(p->timestamp_in)
+                       | TRACE_REC_NUM_DATA_ARGS(extra);
 
-       if (rec.cycle_in) {
-               rec.u.cycle.cycle_u64 = get_cycles();
+       if (p->timestamp_in) {
+               rec.u.timestamp.timestamp = ktime_to_ns(ktime_get());
 
-               for (i = 0; i < rec.extra_u32; i++)
-                       rec.u.cycle.extra_u32[i] = va_arg(*args, u32);
+               for (i = 0; i < extra; i++)
+                       rec.u.timestamp.extra_u32[i] = va_arg(*args, u32);
        } else {
-               for (i = 0; i < rec.extra_u32; i++)
-                       rec.u.nocycle.extra_u32[i] = va_arg(*args, u32);
+               for (i = 0; i < extra; i++)
+                       rec.u.notimestamp.extra_u32[i] = va_arg(*args, u32);
        }
 
-       size = calc_rec_size(rec.cycle_in, rec.extra_u32 * sizeof(u32));
+       size = calc_rec_size(p->timestamp_in, extra * sizeof(u32));
        relay_write(kt->rchan, &rec, size);
 }
 
diff --git a/virt/kvm/vtd.c b/virt/kvm/vtd.c
new file mode 100644 (file)
index 0000000..a770874
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) 2006-2008 Intel Corporation
+ * Copyright IBM Corporation, 2008
+ * Author: Allen M. Kay <allen.m.kay@intel.com>
+ * Author: Weidong Han <weidong.han@intel.com>
+ * Author: Ben-Ami Yassour <benami@il.ibm.com>
+ */
+
+#include <linux/list.h>
+#include <linux/kvm_host.h>
+#include <linux/pci.h>
+#include <linux/dmar.h>
+#include <linux/intel-iommu.h>
+
+static int kvm_iommu_unmap_memslots(struct kvm *kvm);
+static void kvm_iommu_put_pages(struct kvm *kvm,
+                               gfn_t base_gfn, unsigned long npages);
+
+int kvm_iommu_map_pages(struct kvm *kvm,
+                       gfn_t base_gfn, unsigned long npages)
+{
+       gfn_t gfn = base_gfn;
+       pfn_t pfn;
+       int i, r = 0;
+       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
+
+       /* check if iommu exists and in use */
+       if (!domain)
+               return 0;
+
+       for (i = 0; i < npages; i++) {
+               /* check if already mapped */
+               pfn = (pfn_t)intel_iommu_iova_to_pfn(domain,
+                                                    gfn_to_gpa(gfn));
+               if (pfn)
+                       continue;
+
+               pfn = gfn_to_pfn(kvm, gfn);
+               r = intel_iommu_page_mapping(domain,
+                                            gfn_to_gpa(gfn),
+                                            pfn_to_hpa(pfn),
+                                            PAGE_SIZE,
+                                            DMA_PTE_READ |
+                                            DMA_PTE_WRITE);
+               if (r) {
+                       printk(KERN_ERR "kvm_iommu_map_pages:"
+                              "iommu failed to map pfn=%lx\n", pfn);
+                       goto unmap_pages;
+               }
+               gfn++;
+       }
+       return 0;
+
+unmap_pages:
+       kvm_iommu_put_pages(kvm, base_gfn, i);
+       return r;
+}
+
+static int kvm_iommu_map_memslots(struct kvm *kvm)
+{
+       int i, r;
+
+       down_read(&kvm->slots_lock);
+       for (i = 0; i < kvm->nmemslots; i++) {
+               r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn,
+                                       kvm->memslots[i].npages);
+               if (r)
+                       break;
+       }
+       up_read(&kvm->slots_lock);
+       return r;
+}
+
+int kvm_iommu_map_guest(struct kvm *kvm,
+                       struct kvm_assigned_dev_kernel *assigned_dev)
+{
+       struct pci_dev *pdev = NULL;
+       int r;
+
+       if (!intel_iommu_found()) {
+               printk(KERN_ERR "%s: intel iommu not found\n", __func__);
+               return -ENODEV;
+       }
+
+       printk(KERN_DEBUG "VT-d direct map: host bdf = %x:%x:%x\n",
+              assigned_dev->host_busnr,
+              PCI_SLOT(assigned_dev->host_devfn),
+              PCI_FUNC(assigned_dev->host_devfn));
+
+       pdev = assigned_dev->dev;
+
+       if (pdev == NULL) {
+               if (kvm->arch.intel_iommu_domain) {
+                       intel_iommu_domain_exit(kvm->arch.intel_iommu_domain);
+                       kvm->arch.intel_iommu_domain = NULL;
+               }
+               return -ENODEV;
+       }
+
+       kvm->arch.intel_iommu_domain = intel_iommu_domain_alloc(pdev);
+       if (!kvm->arch.intel_iommu_domain)
+               return -ENODEV;
+
+       r = kvm_iommu_map_memslots(kvm);
+       if (r)
+               goto out_unmap;
+
+       intel_iommu_detach_dev(kvm->arch.intel_iommu_domain,
+                              pdev->bus->number, pdev->devfn);
+
+       r = intel_iommu_context_mapping(kvm->arch.intel_iommu_domain,
+                                       pdev);
+       if (r) {
+               printk(KERN_ERR "Domain context map for %s failed",
+                      pci_name(pdev));
+               goto out_unmap;
+       }
+       return 0;
+
+out_unmap:
+       kvm_iommu_unmap_memslots(kvm);
+       return r;
+}
+
+static void kvm_iommu_put_pages(struct kvm *kvm,
+                              gfn_t base_gfn, unsigned long npages)
+{
+       gfn_t gfn = base_gfn;
+       pfn_t pfn;
+       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
+       int i;
+
+       for (i = 0; i < npages; i++) {
+               pfn = (pfn_t)intel_iommu_iova_to_pfn(domain,
+                                                    gfn_to_gpa(gfn));
+               kvm_release_pfn_clean(pfn);
+               gfn++;
+       }
+}
+
+static int kvm_iommu_unmap_memslots(struct kvm *kvm)
+{
+       int i;
+       down_read(&kvm->slots_lock);
+       for (i = 0; i < kvm->nmemslots; i++) {
+               kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn,
+                                   kvm->memslots[i].npages);
+       }
+       up_read(&kvm->slots_lock);
+
+       return 0;
+}
+
+int kvm_iommu_unmap_guest(struct kvm *kvm)
+{
+       struct kvm_assigned_dev_kernel *entry;
+       struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
+
+       /* check if iommu exists and in use */
+       if (!domain)
+               return 0;
+
+       list_for_each_entry(entry, &kvm->arch.assigned_dev_head, list) {
+               printk(KERN_DEBUG "VT-d unmap: host bdf = %x:%x:%x\n",
+                      entry->host_busnr,
+                      PCI_SLOT(entry->host_devfn),
+                      PCI_FUNC(entry->host_devfn));
+
+               /* detach kvm dmar domain */
+               intel_iommu_detach_dev(domain, entry->host_busnr,
+                                      entry->host_devfn);
+       }
+       kvm_iommu_unmap_memslots(kvm);
+       intel_iommu_domain_exit(domain);
+       return 0;
+}